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