/* * restore_ops function. Sets extra hvm parameters and seeds the grant table. */ static int x86_hvm_stream_complete(struct xc_sr_context *ctx) { xc_interface *xch = ctx->xch; int rc; rc = xc_hvm_param_set(xch, ctx->domid, HVM_PARAM_STORE_EVTCHN, ctx->restore.xenstore_evtchn); if ( rc ) { PERROR("Failed to set HVM_PARAM_STORE_EVTCHN"); return rc; } rc = xc_hvm_param_set(xch, ctx->domid, HVM_PARAM_CONSOLE_EVTCHN, ctx->restore.console_evtchn); if ( rc ) { PERROR("Failed to set HVM_PARAM_CONSOLE_EVTCHN"); return rc; } rc = xc_domain_hvm_setcontext(xch, ctx->domid, ctx->x86_hvm.restore.context, ctx->x86_hvm.restore.contextsz); if ( rc < 0 ) { PERROR("Unable to restore HVM context"); return rc; } rc = xc_dom_gnttab_hvm_seed(xch, ctx->domid, ctx->restore.console_gfn, ctx->restore.xenstore_gfn, ctx->restore.console_domid, ctx->restore.xenstore_domid); if ( rc ) { PERROR("Failed to seed grant table"); return rc; } #ifdef XG_LIBXL_HVM_COMPAT rc = handle_qemu(ctx); if ( rc ) { ERROR("Failed to dump qemu"); return rc; } #endif return rc; }
int stub_xc_hvm_build_with_mem(uint64_t max_mem_mib, uint64_t max_start_mib, const char *image) { uint64_t lowmem_end, highmem_start, highmem_end, mmio_start; struct xc_hvm_build_args args = { .mem_size = max_mem_mib << 20, .mem_target = max_start_mib << 20, .mmio_size = HVM_BELOW_4G_MMIO_LENGTH, .image_file_name = image, }; unsigned int i, j, nr = 0; struct e820entry *e820; int rc; unsigned int nr_rdm_entries[MAX_RMRR_DEVICES] = {0}; unsigned int nr_rmrr_devs = 0; struct xen_reserved_device_memory *xrdm[MAX_RMRR_DEVICES] = {0}; unsigned long rmrr_overlapped_ram = 0; char *s; if ( pci_passthrough_sbdf_list ) { s = strtok(pci_passthrough_sbdf_list,","); while ( s != NULL ) { unsigned int seg, bus, device, func; xg_info("Getting RMRRs for device '%s'\n",s); if ( parse_pci_sbdf(s, &seg, &bus, &device, &func) ) { if ( !get_rdm(seg, bus, (device << 3) + func, &nr_rdm_entries[nr_rmrr_devs], &xrdm[nr_rmrr_devs]) ) nr_rmrr_devs++; } if ( nr_rmrr_devs == MAX_RMRR_DEVICES ) { xg_err("Error: hit limit of %d RMRR devices for domain\n", MAX_RMRR_DEVICES); exit(1); } s = strtok (NULL, ","); } } e820 = malloc(sizeof(*e820) * E820MAX); if (!e820) return -ENOMEM; lowmem_end = args.mem_size; highmem_end = highmem_start = 1ull << 32; mmio_start = highmem_start - args.mmio_size; if ( lowmem_end > mmio_start ) { highmem_end = (1ull << 32) + (lowmem_end - mmio_start); lowmem_end = mmio_start; } args.lowmem_end = lowmem_end; args.highmem_end = highmem_end; args.mmio_start = mmio_start; /* Leave low 1MB to HVMLoader... */ e820[nr].addr = 0x100000u; e820[nr].size = args.lowmem_end - 0x100000u; e820[nr].type = E820_RAM; nr++; /* RDM mapping */ for (i = 0; i < nr_rmrr_devs; i++) { for (j = 0; j < nr_rdm_entries[i]; j++) { e820[nr].addr = xrdm[i][j].start_pfn << XC_PAGE_SHIFT; e820[nr].size = xrdm[i][j].nr_pages << XC_PAGE_SHIFT; e820[nr].type = E820_RESERVED; xg_info("Adding RMRR 0x%lx size 0x%lx\n", e820[nr].addr, e820[nr].size); if ( e820[nr].addr < args.lowmem_end ) { rmrr_overlapped_ram += ( args.lowmem_end - e820[nr].addr ); args.lowmem_end = e820[nr].addr; } nr++; } } e820[0].size -= rmrr_overlapped_ram; args.highmem_end += rmrr_overlapped_ram; args.mmio_size += rmrr_overlapped_ram; args.mmio_start -= rmrr_overlapped_ram; for (i = 0; i < nr_rmrr_devs; i++) { free(xrdm[i]); } if ( args.highmem_end > highmem_start ) { e820[nr].addr = highmem_start; e820[nr].size = args.highmem_end - e820[nr].addr; e820[nr].type = E820_RAM; nr++; } rc = xc_hvm_build(xch, domid, &args); if (!rc) rc = xc_domain_set_memory_map(xch, domid, e820, nr); free(e820); return rc; } int stub_xc_hvm_build(int mem_max_mib, int mem_start_mib, const char *image_name, int store_evtchn, int store_domid, int console_evtchn, int console_domid, unsigned long *store_mfn, unsigned long *console_mfn) { int r; struct flags f; get_flags(&f); configure_vcpus(f); configure_tsc(f); r = stub_xc_hvm_build_with_mem(mem_max_mib, mem_start_mib, image_name); if ( r ) failwith_oss_xc("hvm_build"); r = hvm_build_set_params(store_evtchn, store_mfn, console_evtchn, console_mfn, f); if ( r ) failwith_oss_xc("hvm_build_params"); r = construct_cpuid_policy(&f, true); if ( r ) failwith_oss_xc("construct_cpuid_policy"); r = xc_dom_gnttab_hvm_seed(xch, domid, *console_mfn, *store_mfn, console_domid, store_domid); if ( r ) failwith_oss_xc("xc_dom_gnttab_hvm_seed"); free_flags(&f); return 0; }
int xc_dom_gnttab_hvm_seed(xc_interface *xch, domid_t domid, xen_pfn_t console_gpfn, xen_pfn_t xenstore_gpfn, domid_t console_domid, domid_t xenstore_domid) { int rc; xen_pfn_t scratch_gpfn; struct xen_add_to_physmap xatp = { .domid = domid, .space = XENMAPSPACE_grant_table, .idx = 0, }; struct xen_remove_from_physmap xrfp = { .domid = domid, }; rc = xc_core_arch_get_scratch_gpfn(xch, domid, &scratch_gpfn); if ( rc < 0 ) { xc_dom_panic(xch, XC_INTERNAL_ERROR, "%s: failed to get a scratch gfn " "[errno=%d]\n", __FUNCTION__, errno); return -1; } xatp.gpfn = scratch_gpfn; xrfp.gpfn = scratch_gpfn; xc_dom_printf(xch, "%s: called, pfn=0x%"PRI_xen_pfn, __FUNCTION__, scratch_gpfn); rc = do_memory_op(xch, XENMEM_add_to_physmap, &xatp, sizeof(xatp)); if ( rc != 0 ) { xc_dom_panic(xch, XC_INTERNAL_ERROR, "%s: failed to add gnttab to physmap " "[errno=%d]\n", __FUNCTION__, errno); return -1; } rc = xc_dom_gnttab_seed(xch, domid, console_gpfn, xenstore_gpfn, console_domid, xenstore_domid); if (rc != 0) { xc_dom_panic(xch, XC_INTERNAL_ERROR, "%s: failed to seed gnttab entries\n", __FUNCTION__); (void) do_memory_op(xch, XENMEM_remove_from_physmap, &xrfp, sizeof(xrfp)); return -1; } rc = do_memory_op(xch, XENMEM_remove_from_physmap, &xrfp, sizeof(xrfp)); if (rc != 0) { xc_dom_panic(xch, XC_INTERNAL_ERROR, "%s: failed to remove gnttab from physmap " "[errno=%d]\n", __FUNCTION__, errno); return -1; } return 0; } int xc_dom_gnttab_init(struct xc_dom_image *dom) { if ( xc_dom_feature_translated(dom) ) { return xc_dom_gnttab_hvm_seed(dom->xch, dom->guest_domid, dom->console_pfn, dom->xenstore_pfn, dom->console_domid, dom->xenstore_domid); } else { return xc_dom_gnttab_seed(dom->xch, dom->guest_domid, xc_dom_p2m_host(dom, dom->console_pfn), xc_dom_p2m_host(dom, dom->xenstore_pfn), dom->console_domid, dom->xenstore_domid); } }
CAMLprim value stub_xc_hvm_build_native(value xc_handle, value domid, value mem_max_mib, value mem_start_mib, value image_name, value store_evtchn, value store_domid, value console_evtchn, value console_domid) { CAMLparam5(xc_handle, domid, mem_max_mib, mem_start_mib, image_name); CAMLxparam2(store_evtchn, console_evtchn); CAMLlocal1(result); char *image_name_c = strdup(String_val(image_name)); xc_interface *xch; unsigned long store_mfn=0; unsigned long console_mfn=0; int r; struct flags f; /* The xenguest interface changed and was backported to XCP: */ #if defined(XENGUEST_HAS_HVM_BUILD_ARGS) || (__XEN_LATEST_INTERFACE_VERSION__ >= 0x00040200) struct xc_hvm_build_args args; memset(&args, 0, sizeof(struct xc_hvm_build_args)); #endif get_flags(&f, _D(domid)); xch = _H(xc_handle); configure_vcpus(xch, _D(domid), f); configure_tsc(xch, _D(domid), f); #if defined(XENGUEST_HAS_HVM_BUILD_ARGS) || (__XEN_LATEST_INTERFACE_VERSION__ >= 0x00040200) args.mem_size = (uint64_t)Int_val(mem_max_mib) << 20; args.mem_target = (uint64_t)Int_val(mem_start_mib) << 20; args.mmio_size = f.mmio_size_mib << 20; args.image_file_name = image_name_c; #endif caml_enter_blocking_section (); #if defined(XENGUEST_HAS_HVM_BUILD_ARGS) || (__XEN_LATEST_INTERFACE_VERSION__ >= 0x00040200) r = xc_hvm_build(xch, _D(domid), &args); #else r = xc_hvm_build_target_mem(xch, _D(domid), Int_val(mem_max_mib), Int_val(mem_start_mib), image_name_c); #endif caml_leave_blocking_section (); free(image_name_c); if (r) failwith_oss_xc(xch, "hvm_build"); r = hvm_build_set_params(xch, _D(domid), Int_val(store_evtchn), &store_mfn, Int_val(console_evtchn), &console_mfn, f); if (r) failwith_oss_xc(xch, "hvm_build_params"); #ifdef XENGUEST_4_2 xc_dom_gnttab_hvm_seed(xch, _D(domid), console_mfn, store_mfn, Int_val(console_domid), Int_val(store_domid)); #endif result = caml_alloc_tuple(2); Store_field(result, 0, caml_copy_nativeint(store_mfn)); Store_field(result, 1, caml_copy_nativeint(console_mfn)); CAMLreturn(result); }