📄 xc_ia64_linux_save.c
字号:
xc_dominfo_t info; int rc = 1; int debug = (flags & XCFLAGS_DEBUG); int live = (flags & XCFLAGS_LIVE); /* The new domain's shared-info frame number. */ unsigned long shared_info_frame; /* Live mapping of shared info structure */ shared_info_t *live_shinfo = NULL; /* Iteration number. */ int iter; /* Number of pages sent in the last iteration (live only). */ unsigned int sent_last_iter; /* Number of pages sent (live only). */ unsigned int total_sent; /* total number of pages used by the current guest */ unsigned long p2m_size; /* Size of the shadow bitmap (live only). */ unsigned int bitmap_size = 0; /* True if last iteration. */ int last_iter; /* Bitmap of pages to be sent. */ unsigned long *to_send = NULL; /* Bitmap of pages not to be sent (because dirtied). */ unsigned long *to_skip = NULL; char *mem; /* HVM: shared-memory bitmaps for getting log-dirty bits from qemu-dm */ unsigned long *qemu_bitmaps[2]; int qemu_active = 0; int qemu_non_active = 1; /* for foreign p2m exposure */ unsigned int memmap_info_num_pages; unsigned long memmap_size = 0; xen_ia64_memmap_info_t *memmap_info_live = NULL; xen_ia64_memmap_info_t *memmap_info = NULL; void *memmap_desc_start; void *memmap_desc_end; void *p; efi_memory_desc_t *md; struct xen_ia64_p2m_table p2m_table; xc_ia64_p2m_init(&p2m_table); if (debug) fprintf(stderr, "xc_linux_save (ia64): started dom=%d\n", dom); /* If no explicit control parameters given, use defaults */ if (!max_iters) max_iters = DEF_MAX_ITERS; if (!max_factor) max_factor = DEF_MAX_FACTOR; //initialize_mbit_rate(); if (xc_domain_getinfo(xc_handle, dom, 1, &info) != 1) { ERROR("Could not get domain info"); return 1; } shared_info_frame = info.shared_info_frame;#if 0 /* cheesy sanity check */ if ((info.max_memkb >> (PAGE_SHIFT - 10)) > max_mfn) { ERROR("Invalid state record -- pfn count out of range: %lu", (info.max_memkb >> (PAGE_SHIFT - 10))); goto out; }#endif /* Map the shared info frame */ live_shinfo = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ, shared_info_frame); if (!live_shinfo) { ERROR("Couldn't map live_shinfo"); goto out; } p2m_size = xc_memory_op(xc_handle, XENMEM_maximum_gpfn, &dom) + 1; /* This is expected by xm restore. */ if (write_exact(io_fd, &p2m_size, sizeof(unsigned long))) { ERROR("write: p2m_size"); goto out; } /* xc_linux_restore starts to read here. */ /* Write a version number. This can avoid searching for a stupid bug if the format change. The version is hard-coded, don't forget to change the restore code too! */ { unsigned long version = XC_IA64_SR_FORMAT_VER_CURRENT; if (write_exact(io_fd, &version, sizeof(unsigned long))) { ERROR("write: version"); goto out; } } domctl.cmd = XEN_DOMCTL_arch_setup; domctl.domain = (domid_t)dom; domctl.u.arch_setup.flags = XEN_DOMAINSETUP_query; if (xc_domctl(xc_handle, &domctl) < 0) { ERROR("Could not get domain setup"); goto out; } if (write_exact(io_fd, &domctl.u.arch_setup, sizeof(domctl.u.arch_setup))) { ERROR("write: domain setup"); goto out; } /* Domain is still running at this point */ if (live) { if (xc_shadow_control(xc_handle, dom, XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY, NULL, 0, NULL, 0, NULL ) < 0) { ERROR("Couldn't enable shadow mode"); goto out; } last_iter = 0; bitmap_size = ((p2m_size + BITS_PER_LONG-1) & ~(BITS_PER_LONG-1)) / 8; to_send = malloc(bitmap_size); to_skip = malloc(bitmap_size); if (!to_send || !to_skip) { ERROR("Couldn't allocate bitmap array"); goto out; } /* Initially all the pages must be sent. */ memset(to_send, 0xff, bitmap_size); if (lock_pages(to_send, bitmap_size)) { ERROR("Unable to lock_pages to_send"); goto out; } if (lock_pages(to_skip, bitmap_size)) { ERROR("Unable to lock_pages to_skip"); goto out; } if (hvm) { /* Get qemu-dm logging dirty pages too */ void *seg = init_qemu_maps(dom, bitmap_size); qemu_bitmaps[0] = seg; qemu_bitmaps[1] = seg + bitmap_size; qemu_active = 0; qemu_non_active = 1; } } else { /* This is a non-live suspend. Issue the call back to get the domain suspended */ last_iter = 1; if (suspend_and_state(suspend, xc_handle, io_fd, dom, &info)) { ERROR("Domain appears not to have suspended"); goto out; } } memmap_info_num_pages = live_shinfo->arch.memmap_info_num_pages; memmap_size = PAGE_SIZE * memmap_info_num_pages; memmap_info_live = xc_map_foreign_range(xc_handle, info.domid, memmap_size, PROT_READ, live_shinfo->arch.memmap_info_pfn); if (memmap_info_live == NULL) { PERROR("Could not map memmap info."); goto out; } memmap_info = malloc(memmap_size); if (memmap_info == NULL) { PERROR("Could not allocate memmap info memory"); goto out; } memcpy(memmap_info, memmap_info_live, memmap_size); munmap(memmap_info_live, memmap_size); memmap_info_live = NULL; if (xc_ia64_p2m_map(&p2m_table, xc_handle, dom, memmap_info, 0) < 0) { PERROR("xc_ia64_p2m_map"); goto out; } if (write_exact(io_fd, &memmap_info_num_pages, sizeof(memmap_info_num_pages))) { PERROR("write: arch.memmap_info_num_pages"); goto out; } if (write_exact(io_fd, memmap_info, memmap_size)) { PERROR("write: memmap_info"); goto out; } sent_last_iter = p2m_size; total_sent = 0; for (iter = 1; ; iter++) { unsigned int sent_this_iter, skip_this_iter; unsigned long N; sent_this_iter = 0; skip_this_iter = 0; /* Dirtied pages won't be saved. slightly wasteful to peek the whole array evey time, but this is fast enough for the moment. */ if (!last_iter) { if (xc_shadow_control(xc_handle, dom, XEN_DOMCTL_SHADOW_OP_PEEK, to_skip, p2m_size, NULL, 0, NULL) != p2m_size) { ERROR("Error peeking shadow bitmap"); goto out; } } /* Start writing out the saved-domain record. */ memmap_desc_start = &memmap_info->memdesc; memmap_desc_end = memmap_desc_start + memmap_info->efi_memmap_size; for (p = memmap_desc_start; p < memmap_desc_end; p += memmap_info->efi_memdesc_size) { md = p; if (md_is_not_ram(md)) continue; for (N = md->phys_addr >> PAGE_SHIFT; N < (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >> PAGE_SHIFT; N++) { if (!xc_ia64_p2m_allocated(&p2m_table, N)) continue; if (!last_iter) { if (test_bit(N, to_skip) && test_bit(N, to_send)) skip_this_iter++; if (test_bit(N, to_skip) || !test_bit(N, to_send)) continue; } else if (live) { if (!test_bit(N, to_send)) continue; } if (debug) fprintf(stderr, "xc_linux_save: page %lx (%lu/%lu)\n", xc_ia64_p2m_mfn(&p2m_table, N), N, p2m_size); mem = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, N); if (mem == NULL) { /* The page may have move. It will be remarked dirty. FIXME: to be tracked. */ fprintf(stderr, "cannot map mfn page %lx gpfn %lx: %s\n", xc_ia64_p2m_mfn(&p2m_table, N), N, safe_strerror(errno)); continue; } if (write_exact(io_fd, &N, sizeof(N))) { ERROR("write: p2m_size"); munmap(mem, PAGE_SIZE); goto out; } if (write(io_fd, mem, PAGE_SIZE) != PAGE_SIZE) { ERROR("Error when writing to state file (5)"); munmap(mem, PAGE_SIZE); goto out; } munmap(mem, PAGE_SIZE); sent_this_iter++; total_sent++; } } if (last_iter) break; DPRINTF(" %d: sent %d, skipped %d\n", iter, sent_this_iter, skip_this_iter ); if (live) { if ( /* ((sent_this_iter > sent_last_iter) && RATE_IS_MAX()) || */ (iter >= max_iters) || (sent_this_iter+skip_this_iter < 50) || (total_sent > p2m_size*max_factor)) { DPRINTF("Start last iteration\n"); last_iter = 1; if (suspend_and_state(suspend, xc_handle, io_fd, dom, &info)) { ERROR("Domain appears not to have suspended"); goto out; } } /* Pages to be sent are pages which were dirty. */ if (xc_shadow_control(xc_handle, dom, XEN_DOMCTL_SHADOW_OP_CLEAN, to_send, p2m_size, NULL, 0, NULL ) != p2m_size) { ERROR("Error flushing shadow PT"); goto out; } if (hvm) { unsigned int j; /* Pull in the dirty bits from qemu-dm too */ if (!last_iter) { qemu_active = qemu_non_active; qemu_non_active = qemu_active ? 0 : 1; qemu_flip_buffer(dom, qemu_active); for (j = 0; j < bitmap_size / sizeof(unsigned long); j++) { to_send[j] |= qemu_bitmaps[qemu_non_active][j]; qemu_bitmaps[qemu_non_active][j] = 0; } } else { for (j = 0; j < bitmap_size / sizeof(unsigned long); j++) to_send[j] |= qemu_bitmaps[qemu_active][j]; } } sent_last_iter = sent_this_iter; //print_stats(xc_handle, dom, sent_this_iter, &stats, 1); } } fprintf(stderr, "All memory is saved\n"); /* terminate */ { unsigned long pfn = INVALID_MFN; if (write_exact(io_fd, &pfn, sizeof(pfn))) { ERROR("Error when writing to state file (6)"); goto out; } } if (xc_ia64_send_unallocated_list(xc_handle, io_fd, &p2m_table, memmap_info, memmap_desc_start, memmap_desc_end)) goto out; if (!hvm) rc = xc_ia64_pv_send_context(xc_handle, io_fd, dom, &info, live_shinfo); else rc = xc_ia64_hvm_send_context(xc_handle, io_fd, dom, &info, live_shinfo); if (rc) goto out; /* Success! */ rc = 0; out: if (live) { if (xc_shadow_control(xc_handle, dom, XEN_DOMCTL_SHADOW_OP_OFF, NULL, 0, NULL, 0, NULL ) < 0) { DPRINTF("Warning - couldn't disable shadow mode"); } } unlock_pages(to_send, bitmap_size); free(to_send); unlock_pages(to_skip, bitmap_size); free(to_skip); if (live_shinfo) munmap(live_shinfo, PAGE_SIZE); if (memmap_info_live) munmap(memmap_info_live, memmap_size); if (memmap_info) free(memmap_info); xc_ia64_p2m_unmap(&p2m_table); fprintf(stderr,"Save exit rc=%d\n",rc); return !!rc;}/* * Local variables: * mode: C * c-set-style: "BSD" * c-basic-offset: 4 * tab-width: 4 * indent-tabs-mode: nil * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -