📄 xc_ia64_linux_save.c
字号:
/****************************************************************************** * xc_ia64_linux_save.c * * Save the state of a running Linux session. * * Copyright (c) 2003, K A Fraser. * Rewritten for ia64 by Tristan Gingold <tristan.gingold@bull.net> * * Copyright (c) 2007 Isaku Yamahata <yamahata@valinux.co.jp> * Use foreign p2m exposure. * VTi domain support. */#include <inttypes.h>#include <time.h>#include <stdlib.h>#include <unistd.h>#include <sys/time.h>#include "xg_private.h"#include "xc_ia64.h"#include "xc_ia64_save_restore.h"#include "xc_efi.h"#include "xen/hvm/params.h"/*** Default values for important tuning parameters. Can override by passing** non-zero replacement values to xc_linux_save().**** XXX SMH: should consider if want to be able to override MAX_MBIT_RATE too.***/#define DEF_MAX_ITERS (4 - 1) /* limit us to 4 times round loop */#define DEF_MAX_FACTOR 3 /* never send more than 3x nr_pfns *//*** During (live) save/migrate, we maintain a number of bitmaps to track** which pages we have to send, and to skip.*/static inline int test_bit(int nr, volatile void * addr){ return (BITMAP_ENTRY(nr, addr) >> BITMAP_SHIFT(nr)) & 1;}static inline void clear_bit(int nr, volatile void * addr){ BITMAP_ENTRY(nr, addr) &= ~(1UL << BITMAP_SHIFT(nr));}static inline void set_bit(int nr, volatile void * addr){ BITMAP_ENTRY(nr, addr) |= (1UL << BITMAP_SHIFT(nr));}static intsuspend_and_state(int (*suspend)(int), int xc_handle, int io_fd, int dom, xc_dominfo_t *info){ int i = 0; if (!(*suspend)(dom)) { ERROR("Suspend request failed"); return -1; }retry: if (xc_domain_getinfo(xc_handle, dom, 1, info) != 1) { ERROR("Could not get domain info"); return -1; } if (info->shutdown && info->shutdown_reason == SHUTDOWN_suspend) return 0; // success if (info->paused) { // try unpausing domain, wait, and retest xc_domain_unpause(xc_handle, dom); ERROR("Domain was paused. Wait and re-test."); usleep(10000); // 10ms goto retry; } if(++i < 100) { ERROR("Retry suspend domain."); usleep(10000); // 10ms goto retry; } ERROR("Unable to suspend domain."); return -1;}static inline intmd_is_not_ram(const efi_memory_desc_t *md){ return ((md->type != EFI_CONVENTIONAL_MEMORY) || (md->attribute != EFI_MEMORY_WB) || (md->num_pages == 0));}/* * Send through a list of all the PFNs that were not in map at the close. * We send pages which was allocated. However balloon driver may * decreased after sending page. So we have to check the freed * page after pausing the domain. */static intxc_ia64_send_unallocated_list(int xc_handle, int io_fd, struct xen_ia64_p2m_table *p2m_table, xen_ia64_memmap_info_t *memmap_info, void *memmap_desc_start, void *memmap_desc_end){ void *p; efi_memory_desc_t *md; unsigned long N; unsigned long pfntab[1024]; unsigned int j; j = 0; 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)) j++; } } if (write_exact(io_fd, &j, sizeof(unsigned int))) { ERROR("Error when writing to state file (6a)"); return -1; } j = 0; 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)) pfntab[j++] = N; if (j == sizeof(pfntab)/sizeof(pfntab[0])) { if (write_exact(io_fd, &pfntab, sizeof(pfntab[0]) * j)) { ERROR("Error when writing to state file (6b)"); return -1; } j = 0; } } } if (j > 0) { if (write_exact(io_fd, &pfntab, sizeof(pfntab[0]) * j)) { ERROR("Error when writing to state file (6c)"); return -1; } } return 0;}static intxc_ia64_send_vcpu_context(int xc_handle, int io_fd, uint32_t dom, uint32_t vcpu, vcpu_guest_context_any_t *ctxt_any){ vcpu_guest_context_t *ctxt = &ctxt_any->c; if (xc_vcpu_getcontext(xc_handle, dom, vcpu, ctxt_any)) { ERROR("Could not get vcpu context"); return -1; } if (write_exact(io_fd, ctxt, sizeof(*ctxt))) { ERROR("Error when writing to state file (1)"); return -1; } fprintf(stderr, "ip=%016lx, b0=%016lx\n", ctxt->regs.ip, ctxt->regs.b[0]); return 0;}static intxc_ia64_send_shared_info(int xc_handle, int io_fd, shared_info_t *live_shinfo){ if (write_exact(io_fd, live_shinfo, PAGE_SIZE)) { ERROR("Error when writing to state file (1)"); return -1; } return 0;}static intxc_ia64_send_vcpumap(int xc_handle, int io_fd, uint32_t dom, const xc_dominfo_t *info, uint64_t max_virt_cpus, uint64_t **vcpumapp){ int rc = -1; unsigned int i; unsigned long vcpumap_size; uint64_t *vcpumap = NULL; vcpumap_size = (max_virt_cpus + 1 + sizeof(vcpumap[0]) - 1) / sizeof(vcpumap[0]); vcpumap = malloc(vcpumap_size); if (vcpumap == NULL) { ERROR("memory alloc for vcpumap"); goto out; } memset(vcpumap, 0, vcpumap_size); for (i = 0; i <= info->max_vcpu_id; i++) { xc_vcpuinfo_t vinfo; if ((xc_vcpu_getinfo(xc_handle, dom, i, &vinfo) == 0) && vinfo.online) __set_bit(i, vcpumap); } if (write_exact(io_fd, &max_virt_cpus, sizeof(max_virt_cpus))) { ERROR("write max_virt_cpus"); goto out; } if (write_exact(io_fd, vcpumap, vcpumap_size)) { ERROR("write vcpumap"); goto out; } rc = 0; out: if (rc != 0 && vcpumap != NULL) { free(vcpumap); vcpumap = NULL; } *vcpumapp = vcpumap; return rc;}static intxc_ia64_pv_send_context(int xc_handle, int io_fd, uint32_t dom, const xc_dominfo_t *info, shared_info_t *live_shinfo){ int rc = -1; unsigned int i; /* vcpu map */ uint64_t *vcpumap = NULL; if (xc_ia64_send_vcpumap(xc_handle, io_fd, dom, info, MAX_VIRT_CPUS, &vcpumap)) goto out; /* vcpu context */ for (i = 0; i <= info->max_vcpu_id; i++) { /* A copy of the CPU context of the guest. */ vcpu_guest_context_any_t ctxt_any; vcpu_guest_context_t *ctxt = &ctxt_any.c; char *mem; if (!__test_bit(i, vcpumap)) continue; if (xc_ia64_send_vcpu_context(xc_handle, io_fd, dom, i, &ctxt_any)) goto out; mem = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, ctxt->privregs_pfn); if (mem == NULL) { ERROR("cannot map privreg page"); goto out; } if (write_exact(io_fd, mem, PAGE_SIZE)) { ERROR("Error when writing privreg to state file (5)"); munmap(mem, PAGE_SIZE); goto out; } munmap(mem, PAGE_SIZE); } rc = xc_ia64_send_shared_info(xc_handle, io_fd, live_shinfo); out: if (vcpumap != NULL) free(vcpumap); return rc;}static intxc_ia64_hvm_send_context(int xc_handle, int io_fd, uint32_t dom, const xc_dominfo_t *info, shared_info_t *live_shinfo){ int rc = -1; unsigned int i; /* vcpu map */ uint64_t *vcpumap = NULL; /* HVM: magic frames for ioreqs and xenstore comms */ const int hvm_params[] = { HVM_PARAM_STORE_PFN, HVM_PARAM_IOREQ_PFN, HVM_PARAM_BUFIOREQ_PFN, HVM_PARAM_BUFPIOREQ_PFN, }; const int NR_PARAMS = sizeof(hvm_params) / sizeof(hvm_params[0]); /* ioreq_pfn, bufioreq_pfn, store_pfn */ uint64_t magic_pfns[NR_PARAMS]; /* HVM: a buffer for holding HVM contxt */ uint64_t rec_size; uint64_t hvm_buf_size = 0; uint8_t *hvm_buf = NULL; if (xc_ia64_send_shared_info(xc_handle, io_fd, live_shinfo)) return -1; /* vcpu map */ if (xc_ia64_send_vcpumap(xc_handle, io_fd, dom, info, MAX_VIRT_CPUS, &vcpumap)) goto out; /* vcpu context */ for (i = 0; i <= info->max_vcpu_id; i++) { /* A copy of the CPU context of the guest. */ vcpu_guest_context_any_t ctxt_any; if (!__test_bit(i, vcpumap)) continue; if (xc_ia64_send_vcpu_context(xc_handle, io_fd, dom, i, &ctxt_any)) goto out; /* system context of vcpu is sent as hvm context. */ } /* Save magic-page locations. */ memset(magic_pfns, 0, sizeof(magic_pfns)); for (i = 0; i < NR_PARAMS; i++) { if (xc_get_hvm_param(xc_handle, dom, hvm_params[i], &magic_pfns[i])) { PERROR("Error when xc_get_hvm_param"); goto out; } } if (write_exact(io_fd, magic_pfns, sizeof(magic_pfns))) { ERROR("Error when writing to state file (7)"); goto out; } /* Need another buffer for HVM context */ hvm_buf_size = xc_domain_hvm_getcontext(xc_handle, dom, 0, 0); if (hvm_buf_size == -1) { ERROR("Couldn't get HVM context size from Xen"); goto out; } hvm_buf = malloc(hvm_buf_size); if (!hvm_buf) { ERROR("Couldn't allocate memory"); goto out; } /* Get HVM context from Xen and save it too */ rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf, hvm_buf_size); if (rec_size == -1) { ERROR("HVM:Could not get hvm buffer"); goto out; } if (write_exact(io_fd, &rec_size, sizeof(rec_size))) { ERROR("error write hvm buffer size"); goto out; } if (write_exact(io_fd, hvm_buf, rec_size)) { ERROR("write HVM info failed!\n"); goto out; } rc = 0;out: if (hvm_buf != NULL) free(hvm_buf); if (vcpumap != NULL) free(vcpumap); return rc;}intxc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, uint32_t max_factor, uint32_t flags, int (*suspend)(int), int hvm, void *(*init_qemu_maps)(int, unsigned), void (*qemu_flip_buffer)(int, int)){ DECLARE_DOMCTL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -