Esempio n. 1
0
int arch_setup_meminit(struct xc_dom_image *dom)
{
    int rc;
    xen_pfn_t pfn, allocsz, i;

    dom->shadow_enabled = 1;

    dom->p2m_host = xc_dom_malloc(dom, sizeof(xen_pfn_t) * dom->total_pages);
    if ( dom->p2m_host == NULL )
        return -EINVAL;

    /* setup initial p2m */
    for ( pfn = 0; pfn < dom->total_pages; pfn++ )
        dom->p2m_host[pfn] = pfn + dom->rambase_pfn;

    /* allocate guest memory */
    for ( i = rc = allocsz = 0;
          (i < dom->total_pages) && !rc;
          i += allocsz )
    {
        allocsz = dom->total_pages - i;
        if ( allocsz > 1024*1024 )
            allocsz = 1024*1024;

        rc = xc_domain_populate_physmap_exact(
            dom->xch, dom->guest_domid, allocsz,
            0, 0, &dom->p2m_host[i]);
    }

    return 0;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
void *xc_vm_event_enable(xc_interface *xch, domid_t domain_id, int param,
                         uint32_t *port)
{
    void *ring_page = NULL;
    uint64_t pfn;
    xen_pfn_t ring_pfn, mmap_pfn;
    unsigned int op, mode;
    int rc1, rc2, saved_errno;

    if ( !port )
    {
        errno = EINVAL;
        return NULL;
    }

    /* Pause the domain for ring page setup */
    rc1 = xc_domain_pause(xch, domain_id);
    if ( rc1 != 0 )
    {
        PERROR("Unable to pause domain\n");
        return NULL;
    }

    /* Get the pfn of the ring page */
    rc1 = xc_hvm_param_get(xch, domain_id, param, &pfn);
    if ( rc1 != 0 )
    {
        PERROR("Failed to get pfn of ring page\n");
        goto out;
    }

    ring_pfn = pfn;
    mmap_pfn = pfn;
    rc1 = xc_get_pfn_type_batch(xch, domain_id, 1, &mmap_pfn);
    if ( rc1 || mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
    {
        /* Page not in the physmap, try to populate it */
        rc1 = xc_domain_populate_physmap_exact(xch, domain_id, 1, 0, 0,
                                              &ring_pfn);
        if ( rc1 != 0 )
        {
            PERROR("Failed to populate ring pfn\n");
            goto out;
        }
    }

    mmap_pfn = ring_pfn;
    ring_page = xc_map_foreign_pages(xch, domain_id, PROT_READ | PROT_WRITE,
                                         &mmap_pfn, 1);
    if ( !ring_page )
    {
        PERROR("Could not map the ring page\n");
        goto out;
    }

    switch ( param )
    {
    case HVM_PARAM_PAGING_RING_PFN:
        op = XEN_VM_EVENT_ENABLE;
        mode = XEN_DOMCTL_VM_EVENT_OP_PAGING;
        break;

    case HVM_PARAM_MONITOR_RING_PFN:
        op = XEN_VM_EVENT_ENABLE;
        mode = XEN_DOMCTL_VM_EVENT_OP_MONITOR;
        break;

    case HVM_PARAM_SHARING_RING_PFN:
        op = XEN_VM_EVENT_ENABLE;
        mode = XEN_DOMCTL_VM_EVENT_OP_SHARING;
        break;

    /*
     * This is for the outside chance that the HVM_PARAM is valid but is invalid
     * as far as vm_event goes.
     */
    default:
        errno = EINVAL;
        rc1 = -1;
        goto out;
    }

    rc1 = xc_vm_event_control(xch, domain_id, op, mode, port);
    if ( rc1 != 0 )
    {
        PERROR("Failed to enable vm_event\n");
        goto out;
    }

    /* Remove the ring_pfn from the guest's physmap */
    rc1 = xc_domain_decrease_reservation_exact(xch, domain_id, 1, 0, &ring_pfn);
    if ( rc1 != 0 )
        PERROR("Failed to remove ring page from guest physmap");

 out:
    saved_errno = errno;

    rc2 = xc_domain_unpause(xch, domain_id);
    if ( rc1 != 0 || rc2 != 0 )
    {
        if ( rc2 != 0 )
        {
            if ( rc1 == 0 )
                saved_errno = errno;
            PERROR("Unable to unpause domain");
        }

        if ( ring_page )
            xenforeignmemory_unmap(xch->fmem, ring_page, 1);
        ring_page = NULL;

        errno = saved_errno;
    }

    return ring_page;
}
Esempio n. 4
0
int arch_setup_meminit(struct xc_dom_image *dom)
{
    int rc;
    xen_pfn_t pfn, allocsz, i;
    uint64_t modbase;

    /* Convenient */
    const uint64_t rambase = dom->rambase_pfn << XC_PAGE_SHIFT;
    const uint64_t ramsize = dom->total_pages << XC_PAGE_SHIFT;
    const uint64_t ramend = rambase + ramsize;
    const uint64_t kernbase = dom->kernel_seg.vstart;
    const uint64_t kernend = ROUNDUP(dom->kernel_seg.vend, 21/*2MB*/);
    const uint64_t kernsize = kernend - kernbase;
    const uint64_t dtb_size = dom->devicetree_blob ?
        ROUNDUP(dom->devicetree_size, XC_PAGE_SHIFT) : 0;
    const uint64_t ramdisk_size = dom->ramdisk_blob ?
        ROUNDUP(dom->ramdisk_size, XC_PAGE_SHIFT) : 0;
    const uint64_t modsize = dtb_size + ramdisk_size;
    const uint64_t ram128mb = rambase + (128<<20);

    if ( modsize + kernsize > ramsize )
    {
        DOMPRINTF("%s: Not enough memory for the kernel+dtb+initrd",
                  __FUNCTION__);
        return -1;
    }

    if ( ramsize > GUEST_RAM_SIZE - NR_MAGIC_PAGES*XC_PAGE_SIZE )
    {
        DOMPRINTF("%s: ram size is too large for guest address space: "
                  "%"PRIx64" > %llx",
                  __FUNCTION__, ramsize,
                  GUEST_RAM_SIZE - NR_MAGIC_PAGES*XC_PAGE_SIZE);
        return -1;
    }

    rc = set_mode(dom->xch, dom->guest_domid, dom->guest_type);
    if ( rc )
        return rc;

    dom->shadow_enabled = 1;

    dom->p2m_host = xc_dom_malloc(dom, sizeof(xen_pfn_t) * dom->total_pages);
    if ( dom->p2m_host == NULL )
        return -EINVAL;

    /* setup initial p2m */
    for ( pfn = 0; pfn < dom->total_pages; pfn++ )
        dom->p2m_host[pfn] = pfn + dom->rambase_pfn;

    /* allocate guest memory */
    for ( i = rc = allocsz = 0;
          (i < dom->total_pages) && !rc;
          i += allocsz )
    {
        allocsz = dom->total_pages - i;
        if ( allocsz > 1024*1024 )
            allocsz = 1024*1024;

        rc = xc_domain_populate_physmap_exact(
            dom->xch, dom->guest_domid, allocsz,
            0, 0, &dom->p2m_host[i]);
    }

    /*
     * We try to place dtb+initrd at 128MB or if we have less RAM
     * as high as possible. If there is no space then fallback to
     * just before the kernel.
     *
     * If changing this then consider
     * xen/arch/arm/kernel.c:place_modules as well.
     */
    if ( ramend >= ram128mb + modsize && kernend < ram128mb )
        modbase = ram128mb;
    else if ( ramend - modsize > kernend )
        modbase = ramend - modsize;
    else if (kernbase - rambase > modsize )
        modbase = kernbase - modsize;
    else
        return -1;

    DOMPRINTF("%s: placing boot modules at 0x%" PRIx64, __FUNCTION__, modbase);

    /*
     * Must map DTB *after* initrd, to satisfy order of calls to
     * xc_dom_alloc_segment in xc_dom_build_image, which must map
     * things at monotonolically increasing addresses.
     */
    if ( ramdisk_size )
    {
        dom->ramdisk_seg.vstart = modbase;
        dom->ramdisk_seg.vend = modbase + ramdisk_size;

        DOMPRINTF("%s: ramdisk: 0x%" PRIx64 " -> 0x%" PRIx64 "",
                  __FUNCTION__,
                  dom->ramdisk_seg.vstart, dom->ramdisk_seg.vend);

        modbase += ramdisk_size;
    }

    if ( dtb_size )
    {
        dom->devicetree_seg.vstart = modbase;
        dom->devicetree_seg.vend = modbase + dtb_size;

        DOMPRINTF("%s: devicetree: 0x%" PRIx64 " -> 0x%" PRIx64 "",
                  __FUNCTION__,
                  dom->devicetree_seg.vstart, dom->devicetree_seg.vend);

        modbase += dtb_size;
    }

    return 0;
}