ia64/xen-unstable

view tools/libxc/ia64/xc_ia64_linux_save.c @ 10692:306d7857928c

[IA64] Save & restore.

xc_ia64_linux_save.c and xc_ia64_linux_restore.c added.
vcpu context has more registers and states (eg: tr registers).
Per cpu irqs are deallocated when cpu is switched off.
#if/#endif added in reboot.c for ia64.

Signed-off-by: Tristan Gingold <tristan.gingold@bull.net>
author awilliam@xenbuild.aw
date Tue Jul 11 12:51:18 2006 -0600 (2006-07-11)
parents
children 86e5d8458c08
line source
1 /******************************************************************************
2 * xc_ia64_linux_save.c
3 *
4 * Save the state of a running Linux session.
5 *
6 * Copyright (c) 2003, K A Fraser.
7 * Rewritten for ia64 by Tristan Gingold <tristan.gingold@bull.net>
8 */
10 #include <inttypes.h>
11 #include <time.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <sys/time.h>
16 #include "xg_private.h"
18 /* total number of pages used by the current guest */
19 static unsigned long max_pfn;
21 static inline ssize_t
22 write_exact(int fd, void *buf, size_t count)
23 {
24 if (write(fd, buf, count) != count)
25 return 0;
26 return 1;
27 }
29 static int
30 suspend_and_state(int (*suspend)(int), int xc_handle, int io_fd,
31 int dom, xc_dominfo_t *info)
32 {
33 int i = 0;
35 if (!(*suspend)(dom)) {
36 ERR("Suspend request failed");
37 return -1;
38 }
40 retry:
42 if (xc_domain_getinfo(xc_handle, dom, 1, info) != 1) {
43 ERR("Could not get domain info");
44 return -1;
45 }
47 if (info->shutdown && info->shutdown_reason == SHUTDOWN_suspend)
48 return 0; // success
50 if (info->paused) {
51 // try unpausing domain, wait, and retest
52 xc_domain_unpause(xc_handle, dom);
54 ERR("Domain was paused. Wait and re-test.");
55 usleep(10000); // 10ms
57 goto retry;
58 }
61 if(++i < 100) {
62 ERR("Retry suspend domain.");
63 usleep(10000); // 10ms
64 goto retry;
65 }
67 ERR("Unable to suspend domain.");
69 return -1;
70 }
72 int
73 xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
74 uint32_t max_factor, uint32_t flags, int (*suspend)(int))
75 {
76 DECLARE_DOM0_OP;
77 xc_dominfo_t info;
79 int rc = 1;
80 unsigned long N;
82 //int live = (flags & XCFLAGS_LIVE);
83 int debug = (flags & XCFLAGS_DEBUG);
85 /* The new domain's shared-info frame number. */
86 unsigned long shared_info_frame;
88 /* A copy of the CPU context of the guest. */
89 vcpu_guest_context_t ctxt;
91 unsigned long *page_array = NULL;
93 /* Live mapping of shared info structure */
94 shared_info_t *live_shinfo = NULL;
96 char *mem;
98 if (debug)
99 fprintf (stderr, "xc_linux_save (ia64): started dom=%d\n", dom);
101 if (xc_domain_getinfo(xc_handle, dom, 1, &info) != 1) {
102 ERR("Could not get domain info");
103 return 1;
104 }
106 shared_info_frame = info.shared_info_frame;
108 #if 0
109 /* cheesy sanity check */
110 if ((info.max_memkb >> (PAGE_SHIFT - 10)) > max_mfn) {
111 ERR("Invalid state record -- pfn count out of range: %lu",
112 (info.max_memkb >> (PAGE_SHIFT - 10)));
113 goto out;
114 }
115 #endif
117 /* Map the shared info frame */
118 live_shinfo = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
119 PROT_READ, shared_info_frame);
120 if (!live_shinfo) {
121 ERR("Couldn't map live_shinfo");
122 goto out;
123 }
125 max_pfn = info.max_memkb >> (PAGE_SHIFT - 10);
128 /* This is a non-live suspend. Issue the call back to get the
129 domain suspended */
131 if (suspend_and_state(suspend, xc_handle, io_fd, dom, &info)) {
132 ERR("Domain appears not to have suspended");
133 goto out;
134 }
136 page_array = malloc(max_pfn * sizeof(unsigned long));
137 if (page_array == NULL) {
138 ERR("Could not allocate memory");
139 goto out;
140 }
142 if (xc_ia64_get_pfn_list(xc_handle, dom, page_array,
143 0, max_pfn) != max_pfn) {
144 ERR("Could not get the page frame list");
145 goto out;
146 }
148 /* This is expected by xm restore. */
149 if (!write_exact(io_fd, &max_pfn, sizeof(unsigned long))) {
150 ERR("write: max_pfn");
151 goto out;
152 }
154 /* xc_linux_restore starts to read here. */
155 /* Write a version number. This can avoid searching for a stupid bug
156 if the format change.
157 The version is hard-coded, don't forget to change the restore code
158 too! */
159 N = 1;
160 if (!write_exact(io_fd, &N, sizeof(unsigned long))) {
161 ERR("write: version");
162 goto out;
163 }
165 op.cmd = DOM0_DOMAIN_SETUP;
166 op.u.domain_setup.domain = (domid_t)dom;
167 op.u.domain_setup.flags = XEN_DOMAINSETUP_query;
168 if (xc_dom0_op(xc_handle, &op) < 0) {
169 ERR("Could not get domain setup");
170 goto out;
171 }
172 op.u.domain_setup.domain = 0;
173 if (!write_exact(io_fd, &op.u.domain_setup, sizeof(op.u.domain_setup))) {
174 ERR("write: domain setup");
175 goto out;
176 }
178 /* Start writing out the saved-domain record. */
179 for (N = 0; N < max_pfn; N++) {
180 if (page_array[N] == INVALID_MFN)
181 continue;
182 if (debug)
183 fprintf (stderr, "xc_linux_save: page %lx (%lu/%lu)\n",
184 page_array[N], N, max_pfn);
186 if (!write_exact(io_fd, &N, sizeof(N))) {
187 ERR("write: max_pfn");
188 goto out;
189 }
191 mem = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
192 PROT_READ|PROT_WRITE, page_array[N]);
193 if (mem == NULL) {
194 ERR("cannot map page");
195 goto out;
196 }
197 if (write(io_fd, mem, PAGE_SIZE) != PAGE_SIZE) {
198 ERR("Error when writing to state file (5)");
199 goto out;
200 }
201 munmap(mem, PAGE_SIZE);
202 }
204 fprintf (stderr, "All memory is saved\n");
206 /* terminate */
207 N = INVALID_MFN;
208 if (!write_exact(io_fd, &N, sizeof(N))) {
209 ERR("Error when writing to state file (6)");
210 goto out;
211 }
213 /* Send through a list of all the PFNs that were not in map at the close */
214 {
215 unsigned int i,j;
216 unsigned long pfntab[1024];
218 for (i = 0, j = 0; i < max_pfn; i++) {
219 if (page_array[i] == INVALID_MFN)
220 j++;
221 }
223 if (!write_exact(io_fd, &j, sizeof(unsigned int))) {
224 ERR("Error when writing to state file (6a)");
225 goto out;
226 }
228 for (i = 0, j = 0; i < max_pfn; ) {
230 if (page_array[i] == INVALID_MFN)
231 pfntab[j++] = i;
233 i++;
234 if (j == 1024 || i == max_pfn) {
235 if (!write_exact(io_fd, &pfntab, sizeof(unsigned long)*j)) {
236 ERR("Error when writing to state file (6b)");
237 goto out;
238 }
239 j = 0;
240 }
241 }
243 }
245 if (xc_vcpu_getcontext(xc_handle, dom, 0, &ctxt)) {
246 ERR("Could not get vcpu context");
247 goto out;
248 }
250 if (!write_exact(io_fd, &ctxt, sizeof(ctxt))) {
251 ERR("Error when writing to state file (1)");
252 goto out;
253 }
255 mem = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
256 PROT_READ|PROT_WRITE, ctxt.privregs_pfn);
257 if (mem == NULL) {
258 ERR("cannot map privreg page");
259 goto out;
260 }
261 if (write(io_fd, mem, PAGE_SIZE) != PAGE_SIZE) {
262 ERR("Error when writing privreg to state file (5)");
263 goto out;
264 }
265 munmap(mem, PAGE_SIZE);
267 if (!write_exact(io_fd, live_shinfo, PAGE_SIZE)) {
268 ERR("Error when writing to state file (1)");
269 goto out;
270 }
272 /* Success! */
273 rc = 0;
275 out:
277 free (page_array);
279 if (live_shinfo)
280 munmap(live_shinfo, PAGE_SIZE);
282 fprintf(stderr,"Save exit rc=%d\n",rc);
284 return !!rc;
285 }
287 /*
288 * Local variables:
289 * mode: C
290 * c-set-style: "BSD"
291 * c-basic-offset: 4
292 * tab-width: 4
293 * indent-tabs-mode: nil
294 * End:
295 */