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