xref: /qemu/accel/xen/xen-all.c (revision 47d17c0ac310f3274489c74d29dce4656376be8c)
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 "hw/xen/xen_backend.h"
14 #include "qmp-commands.h"
15 #include "chardev/char.h"
16 #include "sysemu/accel.h"
17 #include "migration/misc.h"
18 #include "migration/global_state.h"
19 
20 //#define DEBUG_XEN
21 
22 #ifdef DEBUG_XEN
23 #define DPRINTF(fmt, ...) \
24     do { fprintf(stderr, "xen: " fmt, ## __VA_ARGS__); } while (0)
25 #else
26 #define DPRINTF(fmt, ...) \
27     do { } while (0)
28 #endif
29 
30 xc_interface *xen_xc;
31 xenforeignmemory_handle *xen_fmem;
32 xendevicemodel_handle *xen_dmod;
33 
34 static int store_dev_info(int domid, Chardev *cs, const char *string)
35 {
36     struct xs_handle *xs = NULL;
37     char *path = NULL;
38     char *newpath = NULL;
39     char *pts = NULL;
40     int ret = -1;
41 
42     /* Only continue if we're talking to a pty. */
43     if (!CHARDEV_IS_PTY(cs)) {
44         return 0;
45     }
46     pts = cs->filename + 4;
47 
48     /* We now have everything we need to set the xenstore entry. */
49     xs = xs_open(0);
50     if (xs == NULL) {
51         fprintf(stderr, "Could not contact XenStore\n");
52         goto out;
53     }
54 
55     path = xs_get_domain_path(xs, domid);
56     if (path == NULL) {
57         fprintf(stderr, "xs_get_domain_path() error\n");
58         goto out;
59     }
60     newpath = realloc(path, (strlen(path) + strlen(string) +
61                 strlen("/tty") + 1));
62     if (newpath == NULL) {
63         fprintf(stderr, "realloc error\n");
64         goto out;
65     }
66     path = newpath;
67 
68     strcat(path, string);
69     strcat(path, "/tty");
70     if (!xs_write(xs, XBT_NULL, path, pts, strlen(pts))) {
71         fprintf(stderr, "xs_write for '%s' fail", string);
72         goto out;
73     }
74     ret = 0;
75 
76 out:
77     free(path);
78     xs_close(xs);
79 
80     return ret;
81 }
82 
83 void xenstore_store_pv_console_info(int i, Chardev *chr)
84 {
85     if (i == 0) {
86         store_dev_info(xen_domid, chr, "/console");
87     } else {
88         char buf[32];
89         snprintf(buf, sizeof(buf), "/device/console/%d", i);
90         store_dev_info(xen_domid, chr, buf);
91     }
92 }
93 
94 
95 static void xenstore_record_dm_state(struct xs_handle *xs, const char *state)
96 {
97     char path[50];
98 
99     if (xs == NULL) {
100         error_report("xenstore connection not initialized");
101         exit(1);
102     }
103 
104     snprintf(path, sizeof (path), "device-model/%u/state", xen_domid);
105     if (!xs_write(xs, XBT_NULL, path, state, strlen(state))) {
106         error_report("error recording dm state");
107         exit(1);
108     }
109 }
110 
111 
112 static void xen_change_state_handler(void *opaque, int running,
113                                      RunState state)
114 {
115     if (running) {
116         /* record state running */
117         xenstore_record_dm_state(xenstore, "running");
118     }
119 }
120 
121 static int xen_init(MachineState *ms)
122 {
123     xen_xc = xc_interface_open(0, 0, 0);
124     if (xen_xc == NULL) {
125         xen_pv_printf(NULL, 0, "can't open xen interface\n");
126         return -1;
127     }
128     xen_fmem = xenforeignmemory_open(0, 0);
129     if (xen_fmem == NULL) {
130         xen_pv_printf(NULL, 0, "can't open xen fmem interface\n");
131         xc_interface_close(xen_xc);
132         return -1;
133     }
134     xen_dmod = xendevicemodel_open(0, 0);
135     if (xen_dmod == NULL) {
136         xen_pv_printf(NULL, 0, "can't open xen devicemodel interface\n");
137         xenforeignmemory_close(xen_fmem);
138         xc_interface_close(xen_xc);
139         return -1;
140     }
141     qemu_add_vm_change_state_handler(xen_change_state_handler, NULL);
142     return 0;
143 }
144 
145 static GlobalProperty xen_compat_props[] = {
146     {
147         .driver = "migration",
148         .property = "store-global-state",
149         .value = "off",
150     },
151     {
152         .driver = "migration",
153         .property = "send-configuration",
154         .value = "off",
155     },
156     {
157         .driver = "migration",
158         .property = "send-section-footer",
159         .value = "off",
160     },
161     { /* end of list */ },
162 };
163 
164 static void xen_accel_class_init(ObjectClass *oc, void *data)
165 {
166     AccelClass *ac = ACCEL_CLASS(oc);
167     ac->name = "Xen";
168     ac->init_machine = xen_init;
169     ac->allowed = &xen_allowed;
170     ac->global_props = xen_compat_props;
171 }
172 
173 #define TYPE_XEN_ACCEL ACCEL_CLASS_NAME("xen")
174 
175 static const TypeInfo xen_accel_type = {
176     .name = TYPE_XEN_ACCEL,
177     .parent = TYPE_ACCEL,
178     .class_init = xen_accel_class_init,
179 };
180 
181 static void xen_type_init(void)
182 {
183     type_register_static(&xen_accel_type);
184 }
185 
186 type_init(xen_type_init);
187