diff options
author | Emmanuel Ackaouy <ack@xensource.com> | 2007-01-25 22:16:52 +0000 |
---|---|---|
committer | Emmanuel Ackaouy <ack@xensource.com> | 2007-01-25 22:16:52 +0000 |
commit | b4feb14b3dd705b59ce7a2d66fe0879d54e408e8 (patch) | |
tree | d2786344b21060b576e5d9bc484652a1e14b16de /tools/libxc/xc_dom_core.c | |
parent | a62512128bdc7632982ddc0b3285703e5ab66c98 (diff) | |
download | xen-b4feb14b3dd705b59ce7a2d66fe0879d54e408e8.tar.gz xen-b4feb14b3dd705b59ce7a2d66fe0879d54e408e8.tar.bz2 xen-b4feb14b3dd705b59ce7a2d66fe0879d54e408e8.zip |
libxc domain builder rewrite, core bits.
Signed-off-by: Gerd Hoffmann <kraxel@suse.de>
---
tools/libxc/Makefile | 14
tools/libxc/xc_dom.h | 261 +++++++++++++
tools/libxc/xc_dom_binloader.c | 294 +++++++++++++++
tools/libxc/xc_dom_boot.c | 515 +++++++++++++++++++++++++++
tools/libxc/xc_dom_core.c | 773 +++++++++++++++++++++++++++++++++++++++++
tools/libxc/xc_dom_elfloader.c | 283 +++++++++++++++
tools/libxc/xc_dom_ia64.c | 118 ++++++
tools/libxc/xc_dom_powerpc64.c | 100 +++++
tools/libxc/xc_dom_x86.c | 559 +++++++++++++++++++++++++++++
9 files changed, 2917 insertions(+)
Diffstat (limited to 'tools/libxc/xc_dom_core.c')
-rw-r--r-- | tools/libxc/xc_dom_core.c | 773 |
1 files changed, 773 insertions, 0 deletions
diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c new file mode 100644 index 0000000000..8d329ae74f --- /dev/null +++ b/tools/libxc/xc_dom_core.c @@ -0,0 +1,773 @@ +/* + * Xen domain builder -- core bits. + * + * The core code goes here: + * - allocate and release domain structs. + * - memory management functions. + * - misc helper functions. + * + * This code is licenced under the GPL. + * written 2006 by Gerd Hoffmann <kraxel@suse.de>. + * + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include <inttypes.h> +#include <zlib.h> + +#include "xg_private.h" +#include "xc_dom.h" + +/* ------------------------------------------------------------------------ */ +/* debugging */ + +FILE *xc_dom_logfile = NULL; + +void xc_dom_loginit(void) +{ + if (xc_dom_logfile) + return; + xc_dom_logfile = fopen("/var/log/xen/domain-builder-ng.log", "a"); + setvbuf(xc_dom_logfile, NULL, _IONBF, 0); + xc_dom_printf("### ----- xc domain builder logfile opened -----\n"); +} + +int xc_dom_printf(const char *fmt, ...) +{ + va_list args; + char buf[1024]; + int rc; + + if (!xc_dom_logfile) + return 0; + + va_start(args, fmt); + rc = vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + rc = fwrite(buf, rc, 1, xc_dom_logfile); + + return rc; +} + +int xc_dom_panic_func(const char *file, int line, xc_error_code err, + const char *fmt, ...) +{ + va_list args; + FILE *fp = stderr; + int rc = 0; + char pos[256]; + char msg[XC_MAX_ERROR_MSG_LEN]; + + if (xc_dom_logfile) + fp = xc_dom_logfile; + + snprintf(pos, sizeof(pos), "%s:%d: panic: ", file, line); + va_start(args, fmt); + vsnprintf(msg, sizeof(msg), fmt, args); + va_end(args); + xc_set_error(err, "%s", msg); + rc = fprintf(fp, "%s%s", pos, msg); + return rc; +} + +static void print_mem(const char *name, size_t mem) +{ + if (mem > 32 * 1024 * 1024) + xc_dom_printf("%-24s : %zd MB\n", name, mem / (1024 * 1024)); + else if (mem > 32 * 1024) + xc_dom_printf("%-24s : %zd kB\n", name, mem / 1024); + else + xc_dom_printf("%-24s : %zd bytes\n", name, mem); +} + +void xc_dom_log_memory_footprint(struct xc_dom_image *dom) +{ + xc_dom_printf("domain builder memory footprint\n"); + xc_dom_printf(" allocated\n"); + print_mem(" malloc", dom->alloc_malloc); + print_mem(" anon mmap", dom->alloc_mem_map); + xc_dom_printf(" mapped\n"); + print_mem(" file mmap", dom->alloc_file_map); + print_mem(" domU mmap", dom->alloc_domU_map); +} + +/* ------------------------------------------------------------------------ */ +/* simple memory pool */ + +void *xc_dom_malloc(struct xc_dom_image *dom, size_t size) +{ + struct xc_dom_mem *block; + + block = malloc(sizeof(*block) + size); + if (NULL == block) + return NULL; + memset(block, 0, sizeof(*block) + size); + block->next = dom->memblocks; + dom->memblocks = block; + dom->alloc_malloc += sizeof(*block) + size; + if (size > 100 * 1024) + print_mem(__FUNCTION__, size); + return block->memory; +} + +void *xc_dom_malloc_page_aligned(struct xc_dom_image *dom, size_t size) +{ + struct xc_dom_mem *block; + + block = malloc(sizeof(*block)); + if (NULL == block) + return NULL; + memset(block, 0, sizeof(*block)); + block->mmap_len = size; + block->mmap_ptr = mmap(NULL, block->mmap_len, + PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + if (MAP_FAILED == block->mmap_ptr) + { + free(block); + return NULL; + } + block->next = dom->memblocks; + dom->memblocks = block; + dom->alloc_malloc += sizeof(*block); + dom->alloc_mem_map += block->mmap_len; + if (size > 100 * 1024) + print_mem(__FUNCTION__, size); + return block->mmap_ptr; +} + +void *xc_dom_malloc_filemap(struct xc_dom_image *dom, + const char *filename, size_t * size) +{ + struct xc_dom_mem *block = NULL; + int fd = -1; + + fd = open(filename, O_RDONLY); + if (-1 == fd) + goto err; + + lseek(fd, 0, SEEK_SET); + *size = lseek(fd, 0, SEEK_END); + + block = malloc(sizeof(*block)); + if (NULL == block) + goto err; + memset(block, 0, sizeof(*block)); + block->mmap_len = *size; + block->mmap_ptr = mmap(NULL, block->mmap_len, PROT_READ, MAP_SHARED, fd, 0); + if (MAP_FAILED == block->mmap_ptr) + goto err; + block->next = dom->memblocks; + dom->memblocks = block; + dom->alloc_malloc += sizeof(*block); + dom->alloc_file_map += block->mmap_len; + close(fd); + if (*size > 100 * 1024) + print_mem(__FUNCTION__, *size); + return block->mmap_ptr; + + err: + if (-1 != fd) + close(fd); + if (block) + free(block); + return NULL; +} + +static void xc_dom_free_all(struct xc_dom_image *dom) +{ + struct xc_dom_mem *block; + + while (NULL != (block = dom->memblocks)) + { + dom->memblocks = block->next; + if (block->mmap_ptr) + munmap(block->mmap_ptr, block->mmap_len); + free(block); + } +} + +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 (NULL == nstr) + return NULL; + memcpy(nstr, str, len); + return nstr; +} + +/* ------------------------------------------------------------------------ */ +/* read files, copy memory blocks, with transparent gunzip */ + +size_t xc_dom_check_gzip(void *blob, size_t ziplen) +{ + unsigned char *gzlen; + size_t unziplen; + + if (0 != strncmp(blob, "\037\213", 2)) + /* not gzipped */ + return 0; + + gzlen = blob + ziplen - 4; + unziplen = gzlen[3] << 24 | gzlen[2] << 16 | gzlen[1] << 8 | gzlen[0]; + if (unziplen < ziplen || unziplen > ziplen * 8) + { + xc_dom_printf + ("%s: size (zip %zd, unzip %zd) looks insane, skip gunzip\n", + __FUNCTION__, ziplen, unziplen); + return 0; + } + + return unziplen + 16; +} + +int xc_dom_do_gunzip(void *src, size_t srclen, void *dst, size_t dstlen) +{ + z_stream zStream; + int rc; + + memset(&zStream, 0, sizeof(zStream)); + zStream.next_in = src; + zStream.avail_in = srclen; + zStream.next_out = dst; + zStream.avail_out = dstlen; + rc = inflateInit2(&zStream, (MAX_WBITS + 32)); /* +32 means "handle gzip" */ + if (rc != Z_OK) + { + xc_dom_panic(XC_INTERNAL_ERROR, + "%s: inflateInit2 failed (rc=%d)\n", __FUNCTION__, rc); + return -1; + } + rc = inflate(&zStream, Z_FINISH); + if (rc != Z_STREAM_END) + { + xc_dom_panic(XC_INTERNAL_ERROR, + "%s: inflate failed (rc=%d)\n", __FUNCTION__, rc); + return -1; + } + + xc_dom_printf("%s: unzip ok, 0x%zx -> 0x%zx\n", + __FUNCTION__, srclen, dstlen); + return 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 (0 == unziplen) + return 0; + + unzip = xc_dom_malloc(dom, unziplen); + if (NULL == unzip) + return -1; + + if (-1 == xc_dom_do_gunzip(*blob, *size, unzip, unziplen)) + return -1; + + *blob = unzip; + *size = unziplen; + return 0; +} + +/* ------------------------------------------------------------------------ */ +/* domain memory */ + +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; NULL != phys; 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 (0 == count) + { + 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 (NULL == phys) + 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 (NULL == phys->ptr) + return NULL; + dom->alloc_domU_map += phys->count << page_shift; + } + else + { + mode = "anonymous memory"; + phys->ptr = mmap(NULL, phys->count << page_shift, + PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); + if (MAP_FAILED == phys->ptr) + { + xc_dom_panic(XC_OUT_OF_MEMORY, + "%s: oom: can't allocate 0x%" PRIpfn " pages\n", + __FUNCTION__, count); + 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; +} + +int xc_dom_alloc_segment(struct xc_dom_image *dom, + struct xc_dom_seg *seg, char *name, + xen_vaddr_t start, xen_vaddr_t size) +{ + unsigned int page_size = XC_DOM_PAGE_SIZE(dom); + xen_pfn_t pages = (size + page_size - 1) / page_size; + void *ptr; + + if (0 == start) + start = dom->virt_alloc_end; + + if (start & (page_size - 1)) + { + xc_dom_panic(XC_INTERNAL_ERROR, + "%s: segment start isn't page aligned (0x%" PRIx64 ")\n", + __FUNCTION__, start); + return -1; + } + if (start < dom->virt_alloc_end) + { + xc_dom_panic(XC_INTERNAL_ERROR, + "%s: segment start too low (0x%" PRIx64 " < 0x%" PRIx64 + ")\n", __FUNCTION__, start, dom->virt_alloc_end); + return -1; + } + + seg->vstart = start; + seg->vend = start + pages * page_size; + seg->pfn = (seg->vstart - dom->parms.virt_base) / page_size; + dom->virt_alloc_end = seg->vend; + + xc_dom_printf("%-20s: %-12s : 0x%" PRIx64 " -> 0x%" PRIx64 + " (pfn 0x%" PRIpfn " + 0x%" PRIpfn " pages)\n", + __FUNCTION__, name, seg->vstart, seg->vend, seg->pfn, pages); + + /* map and clear pages */ + ptr = xc_dom_seg_to_ptr(dom, seg); + if (NULL == ptr) + return -1; + memset(ptr, 0, pages * page_size); + + return 0; +} + +int xc_dom_alloc_page(struct xc_dom_image *dom, char *name) +{ + unsigned int page_size = XC_DOM_PAGE_SIZE(dom); + xen_vaddr_t start; + xen_pfn_t pfn; + + start = dom->virt_alloc_end; + dom->virt_alloc_end += page_size; + pfn = (start - dom->parms.virt_base) / page_size; + + xc_dom_printf("%-20s: %-12s : 0x%" PRIx64 " (pfn 0x%" PRIpfn ")\n", + __FUNCTION__, name, start, pfn); + return pfn; +} + +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; NULL != phys; phys = phys->next) + { + if (pfn >= phys->first && pfn < phys->first + phys->count) + break; + prev = phys; + } + if (!phys) + { + xc_dom_printf("%s: Huh? no mapping with pfn 0x%" PRIpfn "\n", + __FUNCTION__, pfn); + return; + } + + munmap(phys->ptr, phys->count << page_shift); + if (prev) + prev->next = phys->next; + else + dom->phys_pages = phys->next; +} + +void xc_dom_unmap_all(struct xc_dom_image *dom) +{ + while (dom->phys_pages) + xc_dom_unmap_one(dom, dom->phys_pages->first); +} + +/* ------------------------------------------------------------------------ */ +/* pluggable kernel loaders */ + +static struct xc_dom_loader *first_loader = NULL; +static struct xc_dom_arch *first_hook = NULL; + +void xc_dom_register_loader(struct xc_dom_loader *loader) +{ + loader->next = first_loader; + first_loader = loader; +} + +static struct xc_dom_loader *xc_dom_find_loader(struct xc_dom_image *dom) +{ + struct xc_dom_loader *loader = first_loader; + + while (NULL != loader) + { + xc_dom_printf("%s: trying %s loader ... ", __FUNCTION__, loader->name); + if (0 == loader->probe(dom)) + { + xc_dom_printf("OK\n"); + return loader; + } + xc_dom_printf("failed\n"); + loader = loader->next; + } + xc_dom_panic(XC_INVALID_KERNEL, "%s: no loader found\n", __FUNCTION__); + return NULL; +} + +void xc_dom_register_arch_hooks(struct xc_dom_arch *hooks) +{ + hooks->next = first_hook; + first_hook = hooks; +} + +static struct xc_dom_arch *xc_dom_find_arch_hooks(char *guest_type) +{ + struct xc_dom_arch *hooks = first_hook; + + while (NULL != hooks) + { + if (0 == strcmp(hooks->guest_type, guest_type)) + return hooks; + hooks = hooks->next; + } + xc_dom_panic(XC_INVALID_KERNEL, + "%s: not found (type %s)\n", __FUNCTION__, guest_type); + return NULL; +} + +/* ------------------------------------------------------------------------ */ +/* public interface */ + +void xc_dom_release(struct xc_dom_image *dom) +{ + xc_dom_printf("%s: called\n", __FUNCTION__); + if (dom->phys_pages) + xc_dom_unmap_all(dom); + xc_dom_free_all(dom); + free(dom); +} + +struct xc_dom_image *xc_dom_allocate(const char *cmdline, const char *features) +{ + struct xc_dom_image *dom; + + xc_dom_printf("%s: cmdline=\"%s\", features=\"%s\"\n", + __FUNCTION__, cmdline, features); + dom = malloc(sizeof(*dom)); + if (!dom) + goto err; + + memset(dom, 0, sizeof(*dom)); + if (cmdline) + dom->cmdline = xc_dom_strdup(dom, cmdline); + if (features) + elf_xen_parse_features(features, dom->f_requested, NULL); + + dom->parms.virt_base = UNSET_ADDR; + dom->parms.virt_entry = UNSET_ADDR; + dom->parms.virt_hypercall = UNSET_ADDR; + dom->parms.virt_hv_start_low = UNSET_ADDR; + dom->parms.elf_paddr_offset = UNSET_ADDR; + + dom->alloc_malloc += sizeof(*dom); + return dom; + + err: + if (dom) + xc_dom_release(dom); + return NULL; +} + +int xc_dom_kernel_file(struct xc_dom_image *dom, const char *filename) +{ + xc_dom_printf("%s: filename=\"%s\"\n", __FUNCTION__, filename); + dom->kernel_blob = xc_dom_malloc_filemap(dom, filename, &dom->kernel_size); + if (NULL == dom->kernel_blob) + return -1; + return xc_dom_try_gunzip(dom, &dom->kernel_blob, &dom->kernel_size); +} + +int xc_dom_ramdisk_file(struct xc_dom_image *dom, const char *filename) +{ + xc_dom_printf("%s: filename=\"%s\"\n", __FUNCTION__, filename); + dom->ramdisk_blob = + xc_dom_malloc_filemap(dom, filename, &dom->ramdisk_size); + if (NULL == dom->ramdisk_blob) + return -1; +// return xc_dom_try_gunzip(dom, &dom->ramdisk_blob, &dom->ramdisk_size); + return 0; +} + +int xc_dom_kernel_mem(struct xc_dom_image *dom, const void *mem, size_t memsize) +{ + xc_dom_printf("%s: called\n", __FUNCTION__); + dom->kernel_blob = (void *)mem; + dom->kernel_size = memsize; + return xc_dom_try_gunzip(dom, &dom->kernel_blob, &dom->kernel_size); +} + +int xc_dom_ramdisk_mem(struct xc_dom_image *dom, const void *mem, + size_t memsize) +{ + xc_dom_printf("%s: called\n", __FUNCTION__); + dom->ramdisk_blob = (void *)mem; + dom->ramdisk_size = memsize; +// return xc_dom_try_gunzip(dom, &dom->ramdisk_blob, &dom->ramdisk_size); + return 0; +} + +int xc_dom_parse_image(struct xc_dom_image *dom) +{ + int i; + + xc_dom_printf("%s: called\n", __FUNCTION__); + + /* parse kernel image */ + dom->kernel_loader = xc_dom_find_loader(dom); + if (NULL == dom->kernel_loader) + goto err; + if (0 != dom->kernel_loader->parser(dom)) + goto err; + if (NULL == dom->guest_type) + { + xc_dom_panic(XC_INTERNAL_ERROR, + "%s: guest_type not set\n", __FUNCTION__); + goto err; + } + + /* 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(XC_INVALID_PARAM, + "%s: unsupported feature requested\n", __FUNCTION__); + goto err; + } + } + return 0; + + err: + return -1; +} + +int xc_dom_mem_init(struct xc_dom_image *dom, unsigned int mem_mb) +{ + unsigned int page_shift; + xen_pfn_t nr_pages, pfn; + + dom->arch_hooks = xc_dom_find_arch_hooks(dom->guest_type); + if (NULL == dom->arch_hooks) + { + 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); + + /* 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; + return 0; +} + +int xc_dom_update_guest_p2m(struct xc_dom_image *dom) +{ + uint32_t *p2m_32; + uint64_t *p2m_64; + xen_pfn_t i; + + if (!dom->p2m_guest) + return 0; + + switch (dom->arch_hooks->sizeof_pfn) + { + case 4: + xc_dom_printf("%s: dst 32bit, pages 0x%" PRIpfn " \n", + __FUNCTION__, dom->total_pages); + p2m_32 = dom->p2m_guest; + for (i = 0; i < dom->total_pages; i++) + if (INVALID_P2M_ENTRY != dom->p2m_host[i]) + p2m_32[i] = dom->p2m_host[i]; + else + p2m_32[i] = (uint32_t) - 1; + break; + case 8: + xc_dom_printf("%s: dst 64bit, pages 0x%" PRIpfn " \n", + __FUNCTION__, dom->total_pages); + p2m_64 = dom->p2m_guest; + for (i = 0; i < dom->total_pages; i++) + if (INVALID_P2M_ENTRY != dom->p2m_host[i]) + p2m_64[i] = dom->p2m_host[i]; + else + p2m_64[i] = (uint64_t) - 1; + break; + default: + xc_dom_panic(XC_INTERNAL_ERROR, + "sizeof_pfn is invalid (is %d, can be 4 or 8)", + dom->arch_hooks->sizeof_pfn); + return -1; + } + return 0; +} + +int xc_dom_build_image(struct xc_dom_image *dom) +{ + unsigned int page_size; + + xc_dom_printf("%s: called\n", __FUNCTION__); + + /* check for arch hooks */ + if (NULL == dom->arch_hooks) + { + xc_dom_panic(XC_INTERNAL_ERROR, "%s: arch hooks not set\n", + __FUNCTION__); + goto err; + } + page_size = XC_DOM_PAGE_SIZE(dom); + + /* load kernel */ + if (0 != xc_dom_alloc_segment(dom, &dom->kernel_seg, "kernel", + dom->kernel_seg.vstart, + dom->kernel_seg.vend - + dom->kernel_seg.vstart)) + goto err; + if (0 != dom->kernel_loader->loader(dom)) + goto err; + + /* load ramdisk */ + if (dom->ramdisk_blob) + { + size_t unziplen, ramdisklen; + void *ramdiskmap; + + unziplen = xc_dom_check_gzip(dom->ramdisk_blob, dom->ramdisk_size); + ramdisklen = unziplen ? unziplen : dom->ramdisk_size; + if (0 != xc_dom_alloc_segment(dom, &dom->ramdisk_seg, "ramdisk", 0, + ramdisklen)) + goto err; + ramdiskmap = xc_dom_seg_to_ptr(dom, &dom->ramdisk_seg); + if (unziplen) + { + if (-1 == xc_dom_do_gunzip(dom->ramdisk_blob, dom->ramdisk_size, + ramdiskmap, ramdisklen)) + goto err; + } + else + memcpy(ramdiskmap, dom->ramdisk_blob, dom->ramdisk_size); + } + + /* allocate other pages */ + if (0 != dom->arch_hooks->alloc_magic_pages(dom)) + goto err; + if (dom->arch_hooks->count_pgtables) + { + dom->arch_hooks->count_pgtables(dom); + if (dom->pgtables > 0) + if (0 != + xc_dom_alloc_segment(dom, &dom->pgtables_seg, "page tables", 0, + dom->pgtables * page_size)) + goto err; + } + if (dom->alloc_bootstack) + dom->bootstack_pfn = xc_dom_alloc_page(dom, "boot stack"); + xc_dom_printf("%-20s: virt_alloc_end : 0x%" PRIx64 "\n", + __FUNCTION__, dom->virt_alloc_end); + xc_dom_printf("%-20s: virt_pgtab_end : 0x%" PRIx64 "\n", + __FUNCTION__, dom->virt_pgtab_end); + return 0; + + err: + return -1; +} |