static int alloc_magic_pages(struct xc_dom_image *dom) { int rc, i; xen_pfn_t p2m[NR_MAGIC_PAGES]; DOMPRINTF_CALLED(dom->xch); for (i = 0; i < NR_MAGIC_PAGES; i++) p2m[i] = dom->rambase_pfn + dom->total_pages + i; rc = xc_domain_populate_physmap_exact( dom->xch, dom->guest_domid, NR_MAGIC_PAGES, 0, 0, p2m); if ( rc < 0 ) return rc; dom->console_pfn = dom->rambase_pfn + dom->total_pages + CONSOLE_PFN_OFFSET; dom->xenstore_pfn = dom->rambase_pfn + dom->total_pages + XENSTORE_PFN_OFFSET; xc_clear_domain_page(dom->xch, dom->guest_domid, dom->console_pfn); xc_clear_domain_page(dom->xch, dom->guest_domid, dom->xenstore_pfn); xc_set_hvm_param(dom->xch, dom->guest_domid, HVM_PARAM_CONSOLE_PFN, dom->console_pfn); xc_set_hvm_param(dom->xch, dom->guest_domid, HVM_PARAM_STORE_PFN, dom->xenstore_pfn); /* allocated by toolstack */ xc_set_hvm_param(dom->xch, dom->guest_domid, HVM_PARAM_CONSOLE_EVTCHN, dom->console_evtchn); xc_set_hvm_param(dom->xch, dom->guest_domid, HVM_PARAM_STORE_EVTCHN, dom->xenstore_evtchn); return 0; }
static int vcpu_arm64(struct xc_dom_image *dom, void *ptr) { vcpu_guest_context_t *ctxt = ptr; DOMPRINTF_CALLED(dom->xch); /* clear everything */ memset(ctxt, 0, sizeof(*ctxt)); ctxt->user_regs.pc64 = dom->parms.virt_entry; /* Linux boot protocol. See linux.Documentation/arm64/booting.txt. */ ctxt->user_regs.x0 = dom->devicetree_blob ? dom->devicetree_seg.vstart : 0xffffffff; ctxt->user_regs.x1 = 0; ctxt->user_regs.x2 = 0; ctxt->user_regs.x3 = 0; DOMPRINTF("DTB %"PRIx64, ctxt->user_regs.x0); ctxt->sctlr = SCTLR_GUEST_INIT; ctxt->ttbr0 = 0; ctxt->ttbr1 = 0; ctxt->ttbcr = 0; /* Defined Reset Value */ ctxt->user_regs.cpsr = PSR_GUEST64_INIT; ctxt->flags = VGCF_online; DOMPRINTF("Initial state CPSR %#"PRIx32" PC %#"PRIx64, ctxt->user_regs.cpsr, ctxt->user_regs.pc64); return 0; }
int xc_dom_kernel_mem(struct xc_dom_image *dom, const void *mem, size_t memsize) { DOMPRINTF_CALLED(dom->xch); dom->kernel_blob = (void *)mem; dom->kernel_size = memsize; return xc_dom_try_gunzip(dom, &dom->kernel_blob, &dom->kernel_size); }
int xc_dom_devicetree_mem(struct xc_dom_image *dom, const void *mem, size_t memsize) { DOMPRINTF_CALLED(dom->xch); dom->devicetree_blob = (void *)mem; dom->devicetree_size = memsize; return 0; }
void xc_dom_release(struct xc_dom_image *dom) { DOMPRINTF_CALLED(dom->xch); if ( dom->phys_pages ) xc_dom_unmap_all(dom); xc_dom_free_all(dom); free(dom); }
int xc_dom_ramdisk_mem(struct xc_dom_image *dom, const void *mem, size_t memsize) { DOMPRINTF_CALLED(dom->xch); dom->ramdisk_blob = (void *)mem; dom->ramdisk_size = memsize; // return xc_dom_try_gunzip(dom, &dom->ramdisk_blob, &dom->ramdisk_size); return 0; }
static int xc_dom_parse_zimage32_kernel(struct xc_dom_image *dom) { uint32_t *zimage; uint32_t start, entry_addr; uint64_t v_start, v_end; uint64_t rambase = dom->rambase_pfn << XC_PAGE_SHIFT; DOMPRINTF_CALLED(dom->xch); zimage = (uint32_t *)dom->kernel_blob; /* Do not load kernel at the very first RAM address */ v_start = rambase + 0x8000; if ( dom->kernel_size > UINT64_MAX - v_start ) { DOMPRINTF("%s: kernel is too large\n", __FUNCTION__); return -EINVAL; } v_end = v_start + dom->kernel_size; /* * If start is invalid then the guest will start at some invalid * address and crash, but this happens in guest context so doesn't * concern us here. */ start = zimage[ZIMAGE32_START_OFFSET/4]; if (start == 0) entry_addr = v_start; else entry_addr = start; /* find kernel segment */ dom->kernel_seg.vstart = v_start; dom->kernel_seg.vend = v_end; dom->parms.virt_entry = entry_addr; dom->parms.virt_base = rambase; dom->guest_type = "xen-3.0-armv7l"; DOMPRINTF("%s: %s: 0x%" PRIx64 " -> 0x%" PRIx64 "", __FUNCTION__, dom->guest_type, dom->kernel_seg.vstart, dom->kernel_seg.vend); return 0; }
int xc_dom_boot_mem_init(struct xc_dom_image *dom) { long rc; DOMPRINTF_CALLED(dom->xch); rc = arch_setup_meminit(dom); if ( rc != 0 ) { xc_dom_panic(dom->xch, XC_OUT_OF_MEMORY, "%s: can't allocate low memory for domain", __FUNCTION__); return rc; } return 0; }
int xc_dom_parse_image(struct xc_dom_image *dom) { int i; DOMPRINTF_CALLED(dom->xch); /* parse kernel image */ dom->kernel_loader = xc_dom_find_loader(dom); if ( dom->kernel_loader == NULL ) goto err; if ( dom->kernel_loader->parser(dom) != 0 ) goto err; if ( dom->guest_type == NULL ) { xc_dom_panic(dom->xch, XC_INTERNAL_ERROR, "%s: guest_type not set", __FUNCTION__); goto err; } if ( dom->pvh_enabled ) { const char *pvh_features = "writable_descriptor_tables|" "auto_translated_physmap|" "supervisor_mode_kernel|" "hvm_callback_vector"; elf_xen_parse_features(pvh_features, dom->f_requested, NULL); } /* check features */ for ( i = 0; i < XENFEAT_NR_SUBMAPS; i++ ) { dom->f_active[i] |= dom->f_requested[i]; /* cmd line */ dom->f_active[i] |= dom->parms.f_required[i]; /* kernel */ if ( (dom->f_active[i] & dom->parms.f_supported[i]) != dom->f_active[i] ) { xc_dom_panic(dom->xch, XC_INVALID_PARAM, "%s: unsupported feature requested", __FUNCTION__); goto err; } } return 0; err: return -1; }
static int xc_dom_parse_zimage64_kernel(struct xc_dom_image *dom) { struct zimage64_hdr *zimage; uint64_t v_start, v_end; uint64_t rambase = dom->rambase_pfn << XC_PAGE_SHIFT; DOMPRINTF_CALLED(dom->xch); zimage = dom->kernel_blob; if ( zimage->text_offset > UINT64_MAX - rambase ) { DOMPRINTF("%s: kernel text offset is too large\n", __FUNCTION__); return -EINVAL; } v_start = rambase + zimage->text_offset; if ( dom->kernel_size > UINT64_MAX - v_start ) { DOMPRINTF("%s: kernel is too large\n", __FUNCTION__); return -EINVAL; } v_end = v_start + dom->kernel_size; dom->kernel_seg.vstart = v_start; dom->kernel_seg.vend = v_end; /* Call the kernel at offset 0 */ dom->parms.virt_entry = v_start; dom->parms.virt_base = rambase; dom->guest_type = "xen-3.0-aarch64"; DOMPRINTF("%s: %s: 0x%" PRIx64 " -> 0x%" PRIx64 "", __FUNCTION__, dom->guest_type, dom->kernel_seg.vstart, dom->kernel_seg.vend); return 0; }
static int xc_dom_parse_zimage_kernel(struct xc_dom_image *dom) { uint32_t *zimage; uint32_t start, entry_addr; uint64_t v_start, v_end; uint64_t rambase = GUEST_RAM_BASE; DOMPRINTF_CALLED(dom->xch); zimage = (uint32_t *)dom->kernel_blob; dom->rambase_pfn = rambase >> XC_PAGE_SHIFT; /* Do not load kernel at the very first RAM address */ v_start = rambase + 0x8000; v_end = v_start + dom->kernel_size; start = zimage[ZIMAGE_START_OFFSET/4]; if (start == 0) entry_addr = v_start; else entry_addr = start; /* find kernel segment */ dom->kernel_seg.vstart = v_start; dom->kernel_seg.vend = v_end; dom->parms.virt_entry = entry_addr; dom->parms.virt_base = rambase; dom->guest_type = "xen-3.0-armv7l"; DOMPRINTF("%s: %s: RAM starts at %"PRI_xen_pfn, __FUNCTION__, dom->guest_type, dom->rambase_pfn); DOMPRINTF("%s: %s: 0x%" PRIx64 " -> 0x%" PRIx64 "", __FUNCTION__, dom->guest_type, dom->kernel_seg.vstart, dom->kernel_seg.vend); return 0; }
static int xc_dom_load_zimage_kernel(struct xc_dom_image *dom) { void *dst; DOMPRINTF_CALLED(dom->xch); dst = xc_dom_seg_to_ptr(dom, &dom->kernel_seg); if ( dst == NULL ) { DOMPRINTF("%s: xc_dom_seg_to_ptr(dom, &dom->kernel_seg) => NULL", __func__); return -1; } DOMPRINTF("%s: kernel sed %#"PRIx64"-%#"PRIx64, __func__, dom->kernel_seg.vstart, dom->kernel_seg.vend); DOMPRINTF("%s: copy %zd bytes from blob %p to dst %p", __func__, dom->kernel_size, dom->kernel_blob, dst); memcpy(dst, dom->kernel_blob, dom->kernel_size); return 0; }
static int vcpu_arm32(struct xc_dom_image *dom, void *ptr) { vcpu_guest_context_t *ctxt = ptr; DOMPRINTF_CALLED(dom->xch); /* clear everything */ memset(ctxt, 0, sizeof(*ctxt)); ctxt->user_regs.pc32 = dom->parms.virt_entry; /* Linux boot protocol. See linux.Documentation/arm/Booting. */ ctxt->user_regs.r0_usr = 0; /* SBZ */ /* Machine ID: We use DTB therefore no machine id */ ctxt->user_regs.r1_usr = 0xffffffff; /* ATAGS/DTB: We currently require that the guest kernel to be * using CONFIG_ARM_APPENDED_DTB. Ensure that r2 does not look * like a valid pointer to a set of ATAGS or a DTB. */ ctxt->user_regs.r2_usr = dom->devicetree_blob ? dom->devicetree_seg.vstart : 0xffffffff; ctxt->sctlr = SCTLR_GUEST_INIT; ctxt->ttbr0 = 0; ctxt->ttbr1 = 0; ctxt->ttbcr = 0; /* Defined Reset Value */ ctxt->user_regs.cpsr = PSR_GUEST32_INIT; ctxt->flags = VGCF_online; DOMPRINTF("Initial state CPSR %#"PRIx32" PC %#"PRIx32, ctxt->user_regs.cpsr, ctxt->user_regs.pc32); return 0; }
static int start_info_arm(struct xc_dom_image *dom) { DOMPRINTF_CALLED(dom->xch); return 0; }
int xc_dom_boot_image(struct xc_dom_image *dom) { DECLARE_HYPERCALL_BUFFER(vcpu_guest_context_any_t, ctxt); xc_dominfo_t info; int rc; ctxt = xc_hypercall_buffer_alloc(dom->xch, ctxt, sizeof(*ctxt)); if ( ctxt == NULL ) return -1; DOMPRINTF_CALLED(dom->xch); /* misc stuff*/ if ( (rc = arch_setup_bootearly(dom)) != 0 ) return rc; /* collect some info */ rc = xc_domain_getinfo(dom->xch, dom->guest_domid, 1, &info); if ( rc < 0 ) { xc_dom_panic(dom->xch, XC_INTERNAL_ERROR, "%s: getdomaininfo failed (rc=%d)", __FUNCTION__, rc); return rc; } if ( rc == 0 || info.domid != dom->guest_domid ) { xc_dom_panic(dom->xch, XC_INTERNAL_ERROR, "%s: Huh? No domains found (nr_domains=%d) " "or domid mismatch (%d != %d)", __FUNCTION__, rc, info.domid, dom->guest_domid); return -1; } dom->shared_info_mfn = info.shared_info_frame; /* sanity checks */ if ( !xc_dom_compat_check(dom) ) return -1; /* initial mm setup */ if ( (rc = xc_dom_update_guest_p2m(dom)) != 0 ) return rc; if ( dom->arch_hooks->setup_pgtables ) if ( (rc = dom->arch_hooks->setup_pgtables(dom)) != 0 ) return rc; if ( (rc = clear_page(dom, dom->console_pfn)) != 0 ) return rc; if ( (rc = clear_page(dom, dom->xenstore_pfn)) != 0 ) return rc; /* start info page */ if ( dom->arch_hooks->start_info ) dom->arch_hooks->start_info(dom); /* hypercall page */ if ( (rc = setup_hypercall_page(dom)) != 0 ) return rc; xc_dom_log_memory_footprint(dom); /* misc x86 stuff */ if ( (rc = arch_setup_bootlate(dom)) != 0 ) return rc; /* let the vm run */ memset(ctxt, 0, sizeof(*ctxt)); if ( (rc = dom->arch_hooks->vcpu(dom, ctxt)) != 0 ) return rc; xc_dom_unmap_all(dom); rc = launch_vm(dom->xch, dom->guest_domid, ctxt); xc_hypercall_buffer_free(dom->xch, ctxt); return rc; }
static int setup_pgtables_arm(struct xc_dom_image *dom) { DOMPRINTF_CALLED(dom->xch); return 0; }
static int shared_info_arm(struct xc_dom_image *dom, void *ptr) { DOMPRINTF_CALLED(dom->xch); return 0; }