ia64/xen-unstable

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