]>
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" |
04b0de0e WL |
12 | #include "hw/xen/xen_backend.h" |
13 | #include "qmp-commands.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) { | |
99 | fprintf(stderr, "xenstore connection not initialized\n"); | |
100 | exit(1); | |
101 | } | |
102 | ||
103 | snprintf(path, sizeof (path), "device-model/%u/state", xen_domid); | |
104 | if (!xs_write(xs, XBT_NULL, path, state, strlen(state))) { | |
105 | fprintf(stderr, "error recording dm state\n"); | |
106 | exit(1); | |
107 | } | |
108 | } | |
109 | ||
110 | ||
111 | static void xen_change_state_handler(void *opaque, int running, | |
112 | RunState state) | |
113 | { | |
114 | if (running) { | |
115 | /* record state running */ | |
116 | xenstore_record_dm_state(xenstore, "running"); | |
117 | } | |
118 | } | |
119 | ||
f6a1ef64 | 120 | static int xen_init(MachineState *ms) |
04b0de0e | 121 | { |
81daba58 IC |
122 | xen_xc = xc_interface_open(0, 0, 0); |
123 | if (xen_xc == NULL) { | |
96c77dba | 124 | xen_pv_printf(NULL, 0, "can't open xen interface\n"); |
04b0de0e WL |
125 | return -1; |
126 | } | |
e0cb42ae IC |
127 | xen_fmem = xenforeignmemory_open(0, 0); |
128 | if (xen_fmem == NULL) { | |
96c77dba | 129 | xen_pv_printf(NULL, 0, "can't open xen fmem interface\n"); |
e0cb42ae IC |
130 | xc_interface_close(xen_xc); |
131 | return -1; | |
132 | } | |
d655f34e PD |
133 | xen_dmod = xendevicemodel_open(0, 0); |
134 | if (xen_dmod == NULL) { | |
135 | xen_pv_printf(NULL, 0, "can't open xen devicemodel interface\n"); | |
136 | xenforeignmemory_close(xen_fmem); | |
137 | xc_interface_close(xen_xc); | |
138 | return -1; | |
139 | } | |
04b0de0e | 140 | qemu_add_vm_change_state_handler(xen_change_state_handler, NULL); |
04b0de0e WL |
141 | return 0; |
142 | } | |
143 | ||
5272298c PX |
144 | static GlobalProperty xen_compat_props[] = { |
145 | { | |
146 | .driver = "migration", | |
147 | .property = "store-global-state", | |
148 | .value = "off", | |
149 | }, | |
71dd4c1a PX |
150 | { |
151 | .driver = "migration", | |
152 | .property = "send-configuration", | |
153 | .value = "off", | |
154 | }, | |
15c38503 PX |
155 | { |
156 | .driver = "migration", | |
157 | .property = "send-section-footer", | |
158 | .value = "off", | |
159 | }, | |
5272298c PX |
160 | { /* end of list */ }, |
161 | }; | |
162 | ||
b152b05a EH |
163 | static void xen_accel_class_init(ObjectClass *oc, void *data) |
164 | { | |
165 | AccelClass *ac = ACCEL_CLASS(oc); | |
166 | ac->name = "Xen"; | |
0d15da8e | 167 | ac->init_machine = xen_init; |
b152b05a | 168 | ac->allowed = &xen_allowed; |
5272298c | 169 | ac->global_props = xen_compat_props; |
b152b05a EH |
170 | } |
171 | ||
172 | #define TYPE_XEN_ACCEL ACCEL_CLASS_NAME("xen") | |
173 | ||
174 | static const TypeInfo xen_accel_type = { | |
175 | .name = TYPE_XEN_ACCEL, | |
176 | .parent = TYPE_ACCEL, | |
177 | .class_init = xen_accel_class_init, | |
178 | }; | |
179 | ||
180 | static void xen_type_init(void) | |
181 | { | |
182 | type_register_static(&xen_accel_type); | |
183 | } | |
184 | ||
185 | type_init(xen_type_init); |