1 /* 2 * Copyright (C) 2014 Citrix Systems UK Ltd. 3 * 4 * This work is licensed under the terms of the GNU GPL, version 2. See 5 * the COPYING file in the top-level directory. 6 * 7 * Contributions after 2012-01-13 are licensed under the terms of the 8 * GNU GPL, version 2 or (at your option) any later version. 9 */ 10 11 #include "hw/xen/xen_backend.h" 12 #include "qmp-commands.h" 13 #include "sysemu/char.h" 14 #include "sysemu/accel.h" 15 #include "migration/migration.h" 16 17 //#define DEBUG_XEN 18 19 #ifdef DEBUG_XEN 20 #define DPRINTF(fmt, ...) \ 21 do { fprintf(stderr, "xen: " fmt, ## __VA_ARGS__); } while (0) 22 #else 23 #define DPRINTF(fmt, ...) \ 24 do { } while (0) 25 #endif 26 27 static int store_dev_info(int domid, CharDriverState *cs, const char *string) 28 { 29 struct xs_handle *xs = NULL; 30 char *path = NULL; 31 char *newpath = NULL; 32 char *pts = NULL; 33 int ret = -1; 34 35 /* Only continue if we're talking to a pty. */ 36 if (strncmp(cs->filename, "pty:", 4)) { 37 return 0; 38 } 39 pts = cs->filename + 4; 40 41 /* We now have everything we need to set the xenstore entry. */ 42 xs = xs_open(0); 43 if (xs == NULL) { 44 fprintf(stderr, "Could not contact XenStore\n"); 45 goto out; 46 } 47 48 path = xs_get_domain_path(xs, domid); 49 if (path == NULL) { 50 fprintf(stderr, "xs_get_domain_path() error\n"); 51 goto out; 52 } 53 newpath = realloc(path, (strlen(path) + strlen(string) + 54 strlen("/tty") + 1)); 55 if (newpath == NULL) { 56 fprintf(stderr, "realloc error\n"); 57 goto out; 58 } 59 path = newpath; 60 61 strcat(path, string); 62 strcat(path, "/tty"); 63 if (!xs_write(xs, XBT_NULL, path, pts, strlen(pts))) { 64 fprintf(stderr, "xs_write for '%s' fail", string); 65 goto out; 66 } 67 ret = 0; 68 69 out: 70 free(path); 71 xs_close(xs); 72 73 return ret; 74 } 75 76 void xenstore_store_pv_console_info(int i, CharDriverState *chr) 77 { 78 if (i == 0) { 79 store_dev_info(xen_domid, chr, "/console"); 80 } else { 81 char buf[32]; 82 snprintf(buf, sizeof(buf), "/device/console/%d", i); 83 store_dev_info(xen_domid, chr, buf); 84 } 85 } 86 87 88 static void xenstore_record_dm_state(struct xs_handle *xs, const char *state) 89 { 90 char path[50]; 91 92 if (xs == NULL) { 93 fprintf(stderr, "xenstore connection not initialized\n"); 94 exit(1); 95 } 96 97 snprintf(path, sizeof (path), "device-model/%u/state", xen_domid); 98 if (!xs_write(xs, XBT_NULL, path, state, strlen(state))) { 99 fprintf(stderr, "error recording dm state\n"); 100 exit(1); 101 } 102 } 103 104 105 static void xen_change_state_handler(void *opaque, int running, 106 RunState state) 107 { 108 if (running) { 109 /* record state running */ 110 xenstore_record_dm_state(xenstore, "running"); 111 } 112 } 113 114 static int xen_init(MachineState *ms) 115 { 116 xen_xc = xen_xc_interface_open(0, 0, 0); 117 if (xen_xc == XC_HANDLER_INITIAL_VALUE) { 118 xen_be_printf(NULL, 0, "can't open xen interface\n"); 119 return -1; 120 } 121 qemu_add_vm_change_state_handler(xen_change_state_handler, NULL); 122 123 global_state_set_optional(); 124 savevm_skip_configuration(); 125 savevm_skip_section_footers(); 126 127 return 0; 128 } 129 130 static void xen_accel_class_init(ObjectClass *oc, void *data) 131 { 132 AccelClass *ac = ACCEL_CLASS(oc); 133 ac->name = "Xen"; 134 ac->init_machine = xen_init; 135 ac->allowed = &xen_allowed; 136 } 137 138 #define TYPE_XEN_ACCEL ACCEL_CLASS_NAME("xen") 139 140 static const TypeInfo xen_accel_type = { 141 .name = TYPE_XEN_ACCEL, 142 .parent = TYPE_ACCEL, 143 .class_init = xen_accel_class_init, 144 }; 145 146 static void xen_type_init(void) 147 { 148 type_register_static(&xen_accel_type); 149 } 150 151 type_init(xen_type_init); 152