Example #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;
}
Example #2
0
char *xc_dom_strdup(struct xc_dom_image *dom, const char *str)
{
    size_t len = strlen(str) + 1;
    char *nstr = xc_dom_malloc(dom, len);

    if ( nstr == NULL )
        return NULL;
    memcpy(nstr, str, len);
    return nstr;
}
Example #3
0
static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
{
    struct elf_binary *elf;
    int rc;

    rc = check_elf_kernel(dom, 1);
    if ( rc != 0 )
        return rc;

    elf = xc_dom_malloc(dom, sizeof(*elf));
    dom->private_loader = elf;
    rc = elf_init(elf, dom->kernel_blob, dom->kernel_size);
    xc_elf_set_logfile(dom->xch, elf, 1);
    if ( rc != 0 )
    {
        xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: corrupted ELF image",
                     __FUNCTION__);
        return rc;
    }

    /* Find the section-header strings table. */
    if ( elf->sec_strtab == NULL )
    {
        xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: ELF image"
                     " has no shstrtab", __FUNCTION__);
        return -EINVAL;
    }

    /* parse binary and get xen meta info */
    elf_parse_binary(elf);
    if ( (rc = elf_xen_parse(elf, &dom->parms)) != 0 )
        return rc;

    if ( elf_xen_feature_get(XENFEAT_dom0, dom->parms.f_required) )
    {
        xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: Kernel does not"
                     " support unprivileged (DomU) operation", __FUNCTION__);
        return -EINVAL;
    }

    /* find kernel segment */
    dom->kernel_seg.vstart = dom->parms.virt_kstart;
    dom->kernel_seg.vend   = dom->parms.virt_kend;

    if ( dom->parms.bsd_symtab )
        xc_dom_load_elf_symtab(dom, elf, 0);

    dom->guest_type = xc_dom_guest_type(dom, elf);
    DOMPRINTF("%s: %s: 0x%" PRIx64 " -> 0x%" PRIx64 "",
              __FUNCTION__, dom->guest_type,
              dom->kernel_seg.vstart, dom->kernel_seg.vend);
    return 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;
}
int arch_setup_meminit(struct xc_dom_image *dom)
{
    xen_pfn_t pfn;
    int rc;

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

    /* allocate guest memory */
    rc = xc_domain_memory_populate_physmap(dom->guest_xc, dom->guest_domid,
                                           dom->total_pages, 0, 0,
                                           dom->p2m_host);
    return rc;
}
static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom)
{
    struct elf_binary *elf;
    int rc;

    rc = check_elf_kernel(dom, 1);
    if ( rc != 0 )
        return rc;

    elf = xc_dom_malloc(dom, sizeof(*elf));
    dom->private_loader = elf;
    rc = elf_init(elf, dom->kernel_blob, dom->kernel_size);
    if ( xc_dom_logfile )
        elf_set_logfile(elf, xc_dom_logfile, 1);
    if ( rc != 0 )
    {
        xc_dom_panic(XC_INVALID_KERNEL, "%s: corrupted ELF image\n",
                     __FUNCTION__);
        return rc;
    }

    /* Find the section-header strings table. */
    if ( elf->sec_strtab == NULL )
    {
        xc_dom_panic(XC_INVALID_KERNEL, "%s: ELF image has no shstrtab\n",
                     __FUNCTION__);
        return -EINVAL;
    }

    /* parse binary and get xen meta info */
    elf_parse_binary(elf);
    if ( (rc = elf_xen_parse(elf, &dom->parms)) != 0 )
        return rc;

    /* find kernel segment */
    dom->kernel_seg.vstart = dom->parms.virt_kstart;
    dom->kernel_seg.vend   = dom->parms.virt_kend;

    if ( dom->parms.bsd_symtab )
        xc_dom_load_elf_symtab(dom, elf, 0);

    dom->guest_type = xc_dom_guest_type(dom, elf);
    xc_dom_printf("%s: %s: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
                  __FUNCTION__, dom->guest_type,
                  dom->kernel_seg.vstart, dom->kernel_seg.vend);
    return 0;
}
Example #7
0
int xc_dom_try_gunzip(struct xc_dom_image *dom, void **blob, size_t * size)
{
    void *unzip;
    size_t unziplen;

    unziplen = xc_dom_check_gzip(*blob, *size);
    if ( unziplen == 0 )
        return 0;

    unzip = xc_dom_malloc(dom, unziplen);
    if ( unzip == NULL )
        return -1;

    if ( xc_dom_do_gunzip(*blob, *size, unzip, unziplen) == -1 )
        return -1;

    *blob = unzip;
    *size = unziplen;
    return 0;
}
Example #8
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;
}
Example #9
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;
}
static int xc_dom_load_elf_symtab(struct xc_dom_image *dom,
                                  struct elf_binary *elf, int load)
{
    struct elf_binary syms;
    const elf_shdr *shdr, *shdr2;
    xen_vaddr_t symtab, maxaddr;
    char *hdr;
    size_t size;
    int h, count, type, i, tables = 0;

    if ( elf_swap(elf) )
    {
        xc_dom_printf("%s: non-native byte order, bsd symtab not supported\n",
                      __FUNCTION__);
        return 0;
    }

    if ( load )
    {
        if ( !dom->bsd_symtab_start )
            return 0;
        size = dom->kernel_seg.vend - dom->bsd_symtab_start;
        hdr  = xc_dom_vaddr_to_ptr(dom, dom->bsd_symtab_start);
        *(int *)hdr = size - sizeof(int);
    }
    else
    {
        size = sizeof(int) + elf_size(elf, elf->ehdr) +
            elf_shdr_count(elf) * elf_size(elf, shdr);
        hdr = xc_dom_malloc(dom, size);
        if ( hdr == NULL )
            return 0;
        dom->bsd_symtab_start = elf_round_up(&syms, dom->kernel_seg.vend);
    }

    memcpy(hdr + sizeof(int),
           elf->image,
           elf_size(elf, elf->ehdr));
    memcpy(hdr + sizeof(int) + elf_size(elf, elf->ehdr),
           elf->image + elf_uval(elf, elf->ehdr, e_shoff),
           elf_shdr_count(elf) * elf_size(elf, shdr));
    if ( elf_64bit(elf) )
    {
        Elf64_Ehdr *ehdr = (Elf64_Ehdr *)(hdr + sizeof(int));
        ehdr->e_phoff = 0;
        ehdr->e_phentsize = 0;
        ehdr->e_phnum = 0;
        ehdr->e_shoff = elf_size(elf, elf->ehdr);
        ehdr->e_shstrndx = SHN_UNDEF;
    }
    else
    {
        Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(hdr + sizeof(int));
        ehdr->e_phoff = 0;
        ehdr->e_phentsize = 0;
        ehdr->e_phnum = 0;
        ehdr->e_shoff = elf_size(elf, elf->ehdr);
        ehdr->e_shstrndx = SHN_UNDEF;
    }
    if ( elf_init(&syms, hdr + sizeof(int), size - sizeof(int)) )
        return -1;
    if ( xc_dom_logfile )
        elf_set_logfile(&syms, xc_dom_logfile, 1);

    symtab = dom->bsd_symtab_start + sizeof(int);
    maxaddr = elf_round_up(&syms, symtab + elf_size(&syms, syms.ehdr) +
                           elf_shdr_count(&syms) * elf_size(&syms, shdr));

    xc_dom_printf("%s/%s: bsd_symtab_start=%" PRIx64 ", kernel.end=0x%" PRIx64
                  " -- symtab=0x%" PRIx64 ", maxaddr=0x%" PRIx64 "\n",
                  __FUNCTION__, load ? "load" : "parse",
                  dom->bsd_symtab_start, dom->kernel_seg.vend,
                  symtab, maxaddr);

    count = elf_shdr_count(&syms);
    for ( h = 0; h < count; h++ )
    {
        shdr = elf_shdr_by_index(&syms, h);
        type = elf_uval(&syms, shdr, sh_type);
        if ( type == SHT_STRTAB )
        {
            /* Look for a strtab @i linked to symtab @h. */
            for ( i = 0; i < count; i++ )
            {
                shdr2 = elf_shdr_by_index(&syms, i);
                if ( (elf_uval(&syms, shdr2, sh_type) == SHT_SYMTAB) &&
                     (elf_uval(&syms, shdr2, sh_link) == h) )
                    break;
            }
            /* Skip symtab @h if we found no corresponding strtab @i. */
            if ( i == count )
            {
                if ( elf_64bit(&syms) )
                    *(Elf64_Off*)(&shdr->e64.sh_offset) = 0;
                else
                    *(Elf32_Off*)(&shdr->e32.sh_offset) = 0;
                continue;
            }
        }

        if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) )
        {
            /* Mangled to be based on ELF header location. */
            if ( elf_64bit(&syms) )
                *(Elf64_Off*)(&shdr->e64.sh_offset) = maxaddr - symtab;
            else
                *(Elf32_Off*)(&shdr->e32.sh_offset) = maxaddr - symtab;
            size = elf_uval(&syms, shdr, sh_size);
            maxaddr = elf_round_up(&syms, maxaddr + size);
            tables++;
            xc_dom_printf("%s: h=%d %s, size=0x%zx, maxaddr=0x%" PRIx64 "\n",
                          __FUNCTION__, h,
                          type == SHT_SYMTAB ? "symtab" : "strtab",
                          size, maxaddr);

            if ( load )
            {
                shdr2 = elf_shdr_by_index(elf, h);
                memcpy((void*)elf_section_start(&syms, shdr),
                       elf_section_start(elf, shdr2),
                       size);
            }
        }

        /* Name is NULL. */
        if ( elf_64bit(&syms) )
            *(Elf64_Half*)(&shdr->e64.sh_name) = 0;
        else
            *(Elf32_Word*)(&shdr->e32.sh_name) = 0;
    }

    if ( tables == 0 )
    {
        xc_dom_printf("%s: no symbol table present\n", __FUNCTION__);
        dom->bsd_symtab_start = 0;
        return 0;
    }
    if ( !load )
        dom->kernel_seg.vend = maxaddr;
    return 0;
}
Example #11
0
        if ( hdr_ptr == NULL )
        {
            DOMPRINTF("%s: xc_dom_vaddr_to_ptr(dom,dom->bsd_symtab_start"
                      " => NULL", __FUNCTION__);
            return -1;
        }
        elf->caller_xdest_base = hdr_ptr;
        elf->caller_xdest_size = allow_size;
        hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
        elf_store_val(elf, unsigned, hdr, size - sizeof(unsigned));
    }
    else
    {
        char *hdr_ptr;

        hdr_ptr = xc_dom_malloc(dom, size);
        if ( hdr_ptr == NULL )
            return 0;
        elf->caller_xdest_base = hdr_ptr;
        elf->caller_xdest_size = size;
        hdr = ELF_REALPTR2PTRVAL(hdr_ptr);
        dom->bsd_symtab_start = elf_round_up(elf, dom->kernel_seg.vend);
        dom->kernel_seg.vend = elf_round_up(elf, dom->bsd_symtab_start + size);
        return 0;
    }

    elf_memcpy_safe(elf, hdr + sizeof(unsigned),
           ELF_IMAGE_BASE(elf),
           elf_size(elf, elf->ehdr));
    elf_memcpy_safe(elf, hdr + sizeof(unsigned) + elf_size(elf, elf->ehdr),
           ELF_IMAGE_BASE(elf) + elf_uval(elf, elf->ehdr, e_shoff),
int xc_dom_boot_image(struct xc_dom_image *dom)
{
    DECLARE_DOMCTL;
    void *ctxt;
    int rc;

    xc_dom_printf("%s: called\n", __FUNCTION__);

    /* misc ia64 stuff*/
    if ( (rc = arch_setup_bootearly(dom)) != 0 )
        return rc;

    /* collect some info */
    domctl.cmd = XEN_DOMCTL_getdomaininfo;
    domctl.domain = dom->guest_domid;
    rc = do_domctl(dom->guest_xc, &domctl);
    if ( rc != 0 )
    {
        xc_dom_panic(XC_INTERNAL_ERROR,
                     "%s: getdomaininfo failed (rc=%d)\n", __FUNCTION__, rc);
        return rc;
    }
    if ( domctl.domain != dom->guest_domid )
    {
        xc_dom_panic(XC_INTERNAL_ERROR,
                     "%s: Huh? domid mismatch (%d != %d)\n", __FUNCTION__,
                     domctl.domain, dom->guest_domid);
        return -1;
    }
    dom->shared_info_mfn = domctl.u.getdomaininfo.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 */
    ctxt = xc_dom_malloc(dom, PAGE_SIZE * 2 /* FIXME */ );
    memset(ctxt, 0, PAGE_SIZE * 2);
    if ( (rc = dom->arch_hooks->vcpu(dom, ctxt)) != 0 )
        return rc;
    xc_dom_unmap_all(dom);
    rc = launch_vm(dom->guest_xc, dom->guest_domid, ctxt);

    return rc;
}
Example #13
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;
}