xref: /openbmc/qemu/accel/xen/xen-all.c (revision 7a8a749da7d30b420291fa0b11e3eda7f72d9b83)
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