int xc_dom_mem_init(struct xc_dom_image *dom, unsigned int mem_mb) { unsigned int page_shift; xen_pfn_t nr_pages; dom->arch_hooks = xc_dom_find_arch_hooks(dom->guest_type); if ( dom->arch_hooks == NULL ) { xc_dom_panic(XC_INTERNAL_ERROR, "%s: arch hooks not set\n", __FUNCTION__); return -1; } page_shift = XC_DOM_PAGE_SHIFT(dom); nr_pages = mem_mb << (20 - page_shift); xc_dom_printf("%s: mem %d MB, pages 0x%" PRIpfn " pages, %dk each\n", __FUNCTION__, mem_mb, nr_pages, 1 << (page_shift-10)); dom->total_pages = nr_pages; xc_dom_printf("%s: 0x%" PRIpfn " pages\n", __FUNCTION__, dom->total_pages); return 0; }
void xc_dom_unmap_one(struct xc_dom_image *dom, xen_pfn_t pfn) { unsigned int page_shift = XC_DOM_PAGE_SHIFT(dom); struct xc_dom_phys *phys, *prev = NULL; for ( phys = dom->phys_pages; phys != NULL; phys = phys->next ) { if ( (pfn >= phys->first) && (pfn < (phys->first + phys->count)) ) break; prev = phys; } if ( !phys ) { DOMPRINTF("%s: Huh? no mapping with pfn 0x%" PRIpfn "", __FUNCTION__, pfn); return; } munmap(phys->ptr, phys->count << page_shift); if ( prev ) prev->next = phys->next; else dom->phys_pages = phys->next; xc_domain_cacheflush(dom->xch, dom->guest_domid, phys->first, phys->count); }
void *xc_dom_boot_domU_map(struct xc_dom_image *dom, xen_pfn_t pfn, xen_pfn_t count) { int page_shift = XC_DOM_PAGE_SHIFT(dom); privcmd_mmap_entry_t *entries; void *ptr; int i, rc; int err; entries = xc_dom_malloc(dom, count * sizeof(privcmd_mmap_entry_t)); if ( entries == NULL ) { xc_dom_panic(XC_INTERNAL_ERROR, "%s: failed to mmap domU pages 0x%" PRIpfn "+0x%" PRIpfn " [malloc]\n", __FUNCTION__, pfn, count); return NULL; } ptr = mmap(NULL, count << page_shift, PROT_READ | PROT_WRITE, MAP_SHARED, dom->guest_xc, 0); if ( ptr == MAP_FAILED ) { err = errno; xc_dom_panic(XC_INTERNAL_ERROR, "%s: failed to mmap domU pages 0x%" PRIpfn "+0x%" PRIpfn " [mmap, errno=%i (%s)]\n", __FUNCTION__, pfn, count, err, strerror(err)); return NULL; } for ( i = 0; i < count; i++ ) { entries[i].va = (uintptr_t) ptr + (i << page_shift); entries[i].mfn = xc_dom_p2m_host(dom, pfn + i); entries[i].npages = 1; } rc = xc_map_foreign_ranges(dom->guest_xc, dom->guest_domid, entries, count); if ( rc < 0 ) { xc_dom_panic(XC_INTERNAL_ERROR, "%s: failed to mmap domU pages 0x%" PRIpfn "+0x%" PRIpfn " [xenctl, rc=%d]\n", __FUNCTION__, pfn, count, rc); return NULL; } return ptr; }
static int setup_hypercall_page(struct xc_dom_image *dom) { DECLARE_DOMCTL; xen_pfn_t pfn; int rc; if ( dom->parms.virt_hypercall == -1 ) return 0; pfn = (dom->parms.virt_hypercall - dom->parms.virt_base) >> XC_DOM_PAGE_SHIFT(dom); xc_dom_printf("%s: vaddr=0x%" PRIx64 " pfn=0x%" PRIpfn "\n", __FUNCTION__, dom->parms.virt_hypercall, pfn); domctl.cmd = XEN_DOMCTL_hypercall_init; domctl.domain = dom->guest_domid; domctl.u.hypercall_init.gmfn = xc_dom_p2m_guest(dom, pfn); rc = do_domctl(dom->guest_xc, &domctl); if ( rc != 0 ) xc_dom_panic(XC_INTERNAL_ERROR, "%s: HYPERCALL_INIT failed (rc=%d)\n", __FUNCTION__, rc); return rc; }
void *xc_dom_boot_domU_map(struct xc_dom_image *dom, xen_pfn_t pfn, xen_pfn_t count) { int page_shift = XC_DOM_PAGE_SHIFT(dom); privcmd_mmap_entry_t *entries; void *ptr; int i; int err; entries = xc_dom_malloc(dom, count * sizeof(privcmd_mmap_entry_t)); if ( entries == NULL ) { xc_dom_panic(dom->xch, XC_INTERNAL_ERROR, "%s: failed to mmap domU pages 0x%" PRIpfn "+0x%" PRIpfn " [malloc]", __FUNCTION__, pfn, count); return NULL; } for ( i = 0; i < count; i++ ) entries[i].mfn = xc_dom_p2m_host(dom, pfn + i); ptr = xc_map_foreign_ranges(dom->xch, dom->guest_domid, count << page_shift, PROT_READ | PROT_WRITE, 1 << page_shift, entries, count); if ( ptr == NULL ) { err = errno; xc_dom_panic(dom->xch, XC_INTERNAL_ERROR, "%s: failed to mmap domU pages 0x%" PRIpfn "+0x%" PRIpfn " [mmap, errno=%i (%s)]", __FUNCTION__, pfn, count, err, strerror(err)); return NULL; } return ptr; }
void *xc_dom_pfn_to_ptr(struct xc_dom_image *dom, xen_pfn_t pfn, xen_pfn_t count) { struct xc_dom_phys *phys; unsigned int page_shift = XC_DOM_PAGE_SHIFT(dom); char *mode = "unset"; if ( pfn > dom->total_pages ) { xc_dom_printf("%s: pfn out of range (0x%" PRIpfn " > 0x%" PRIpfn ")\n", __FUNCTION__, pfn, dom->total_pages); return NULL; } /* already allocated? */ for ( phys = dom->phys_pages; phys != NULL; phys = phys->next ) { if ( pfn >= (phys->first + phys->count) ) continue; if ( count ) { /* size given: must be completely within the already allocated block */ if ( (pfn + count) <= phys->first ) continue; if ( (pfn < phys->first) || ((pfn + count) > (phys->first + phys->count)) ) { xc_dom_printf("%s: request overlaps allocated block" " (req 0x%" PRIpfn "+0x%" PRIpfn "," " blk 0x%" PRIpfn "+0x%" PRIpfn ")\n", __FUNCTION__, pfn, count, phys->first, phys->count); return NULL; } } else { /* no size given: block must be allocated already, just hand out a pointer to it */ if ( pfn < phys->first ) continue; } return phys->ptr + ((pfn - phys->first) << page_shift); } /* allocating is allowed with size specified only */ if ( count == 0 ) { xc_dom_printf("%s: no block found, no size given," " can't malloc (pfn 0x%" PRIpfn ")\n", __FUNCTION__, pfn); return NULL; } /* not found, no overlap => allocate */ phys = xc_dom_malloc(dom, sizeof(*phys)); if ( phys == NULL ) return NULL; memset(phys, 0, sizeof(*phys)); phys->first = pfn; phys->count = count; if ( dom->guest_domid ) { mode = "domU mapping"; phys->ptr = xc_dom_boot_domU_map(dom, phys->first, phys->count); if ( phys->ptr == NULL ) return NULL; dom->alloc_domU_map += phys->count << page_shift; } else { int err; mode = "anonymous memory"; phys->ptr = mmap(NULL, phys->count << page_shift, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); if ( phys->ptr == MAP_FAILED ) { err = errno; xc_dom_panic(XC_OUT_OF_MEMORY, "%s: oom: can't allocate 0x%" PRIpfn " pages" " [mmap, errno=%i (%s)]\n", __FUNCTION__, count, err, strerror(err)); return NULL; } dom->alloc_mem_map += phys->count << page_shift; } #if 1 xc_dom_printf("%s: %s: pfn 0x%" PRIpfn "+0x%" PRIpfn " at %p\n", __FUNCTION__, mode, phys->first, phys->count, phys->ptr); #endif phys->next = dom->phys_pages; dom->phys_pages = phys; return phys->ptr; }