Пример #1
0
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;
}
Пример #2
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);
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
0
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;
}
Пример #6
0
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;
}