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 "qemu/osdep.h" 12 #include "qemu/error-report.h" 13 #include "qemu/module.h" 14 #include "qapi/error.h" 15 #include "hw/xen/xen-legacy-backend.h" 16 #include "hw/xen/xen_pt.h" 17 #include "chardev/char.h" 18 #include "qemu/accel.h" 19 #include "sysemu/cpus.h" 20 #include "sysemu/xen.h" 21 #include "sysemu/runstate.h" 22 #include "migration/misc.h" 23 #include "migration/global_state.h" 24 #include "hw/boards.h" 25 26 bool xen_allowed; 27 28 xc_interface *xen_xc; 29 xenforeignmemory_handle *xen_fmem; 30 xendevicemodel_handle *xen_dmod; 31 32 static void xenstore_record_dm_state(const char *state) 33 { 34 struct xs_handle *xs; 35 char path[50]; 36 37 /* We now have everything we need to set the xenstore entry. */ 38 xs = xs_open(0); 39 if (xs == NULL) { 40 fprintf(stderr, "Could not contact XenStore\n"); 41 exit(1); 42 } 43 44 snprintf(path, sizeof (path), "device-model/%u/state", xen_domid); 45 /* 46 * This call may fail when running restricted so don't make it fatal in 47 * that case. Toolstacks should instead use QMP to listen for state changes. 48 */ 49 if (!xs_write(xs, XBT_NULL, path, state, strlen(state)) && 50 !xen_domid_restrict) { 51 error_report("error recording dm state"); 52 exit(1); 53 } 54 55 xs_close(xs); 56 } 57 58 59 static void xen_change_state_handler(void *opaque, bool running, 60 RunState state) 61 { 62 if (running) { 63 /* record state running */ 64 xenstore_record_dm_state("running"); 65 } 66 } 67 68 static bool xen_get_igd_gfx_passthru(Object *obj, Error **errp) 69 { 70 return xen_igd_gfx_pt_enabled(); 71 } 72 73 static void xen_set_igd_gfx_passthru(Object *obj, bool value, Error **errp) 74 { 75 xen_igd_gfx_pt_set(value, errp); 76 } 77 78 static void xen_setup_post(MachineState *ms, AccelState *accel) 79 { 80 int rc; 81 82 if (xen_domid_restrict) { 83 rc = xen_restrict(xen_domid); 84 if (rc < 0) { 85 perror("xen: failed to restrict"); 86 exit(1); 87 } 88 } 89 } 90 91 static int xen_init(MachineState *ms) 92 { 93 MachineClass *mc = MACHINE_GET_CLASS(ms); 94 95 xen_xc = xc_interface_open(0, 0, 0); 96 if (xen_xc == NULL) { 97 xen_pv_printf(NULL, 0, "can't open xen interface\n"); 98 return -1; 99 } 100 xen_fmem = xenforeignmemory_open(0, 0); 101 if (xen_fmem == NULL) { 102 xen_pv_printf(NULL, 0, "can't open xen fmem interface\n"); 103 xc_interface_close(xen_xc); 104 return -1; 105 } 106 xen_dmod = xendevicemodel_open(0, 0); 107 if (xen_dmod == NULL) { 108 xen_pv_printf(NULL, 0, "can't open xen devicemodel interface\n"); 109 xenforeignmemory_close(xen_fmem); 110 xc_interface_close(xen_xc); 111 return -1; 112 } 113 qemu_add_vm_change_state_handler(xen_change_state_handler, NULL); 114 /* 115 * opt out of system RAM being allocated by generic code 116 */ 117 mc->default_ram_id = NULL; 118 119 xen_mode = XEN_ATTACH; 120 return 0; 121 } 122 123 static void xen_accel_class_init(ObjectClass *oc, void *data) 124 { 125 AccelClass *ac = ACCEL_CLASS(oc); 126 static GlobalProperty compat[] = { 127 { "migration", "store-global-state", "off" }, 128 { "migration", "send-configuration", "off" }, 129 { "migration", "send-section-footer", "off" }, 130 }; 131 132 ac->name = "Xen"; 133 ac->init_machine = xen_init; 134 ac->setup_post = xen_setup_post; 135 ac->allowed = &xen_allowed; 136 ac->compat_props = g_ptr_array_new(); 137 138 compat_props_add(ac->compat_props, compat, G_N_ELEMENTS(compat)); 139 140 object_class_property_add_bool(oc, "igd-passthru", 141 xen_get_igd_gfx_passthru, xen_set_igd_gfx_passthru); 142 object_class_property_set_description(oc, "igd-passthru", 143 "Set on/off to enable/disable igd passthrou"); 144 } 145 146 #define TYPE_XEN_ACCEL ACCEL_CLASS_NAME("xen") 147 148 static const TypeInfo xen_accel_type = { 149 .name = TYPE_XEN_ACCEL, 150 .parent = TYPE_ACCEL, 151 .class_init = xen_accel_class_init, 152 }; 153 154 static void xen_accel_ops_class_init(ObjectClass *oc, void *data) 155 { 156 AccelOpsClass *ops = ACCEL_OPS_CLASS(oc); 157 158 ops->create_vcpu_thread = dummy_start_vcpu_thread; 159 } 160 161 static const TypeInfo xen_accel_ops_type = { 162 .name = ACCEL_OPS_NAME("xen"), 163 164 .parent = TYPE_ACCEL_OPS, 165 .class_init = xen_accel_ops_class_init, 166 .abstract = true, 167 }; 168 169 static void xen_type_init(void) 170 { 171 type_register_static(&xen_accel_type); 172 type_register_static(&xen_accel_ops_type); 173 } 174 type_init(xen_type_init); 175