[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] Add a parallel set of APIs to the domain builders to allow images and
# HG changeset patch # User kaf24@xxxxxxxxxxxxxxxxxxxx # Node ID 899532500ada24763c01ad27f781701d8240be3a # Parent 5ea87acc07dc748ad7aaa60e32bfd2f3a1fccfea Add a parallel set of APIs to the domain builders to allow images and ramdisks to be passed via buffer, rather than via file. This allows usage of the underlying domain building routines in "file-challenged" enviroments. Specifically, xc_linux_build_mem is the buffer oriented version of the file-oriented xc_linux_build. Likewise, xc_hvm_build_mem is the buffer oriented analog of the file based xc_hvm_build. Signed-off-by: Ben Thomas (bthomas@xxxxxxxxxxxxxxx) diff -r 5ea87acc07dc -r 899532500ada tools/libxc/xc_hvm_build.c --- a/tools/libxc/xc_hvm_build.c Thu Mar 9 10:20:31 2006 +++ b/tools/libxc/xc_hvm_build.c Thu Mar 9 12:00:38 2006 @@ -338,24 +338,29 @@ return -1; } -int xc_hvm_build(int xc_handle, - uint32_t domid, - int memsize, - const char *image_name, - unsigned int vcpus, - unsigned int pae, - unsigned int acpi, - unsigned int apic, - unsigned int store_evtchn, - unsigned long *store_mfn) +static int xc_hvm_build_internal(int xc_handle, + uint32_t domid, + int memsize, + char *image, + unsigned long image_size, + unsigned int vcpus, + unsigned int pae, + unsigned int acpi, + unsigned int apic, + unsigned int store_evtchn, + unsigned long *store_mfn) { dom0_op_t launch_op, op; int rc, i; vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt; unsigned long nr_pages; - char *image = NULL; - unsigned long image_size; xen_capabilities_info_t xen_caps; + + if ( (image == NULL) || (image_size == 0) ) + { + ERROR("Image required"); + goto error_out; + } if ( (rc = xc_version(xc_handle, XENVER_capabilities, &xen_caps)) != 0 ) { @@ -375,9 +380,6 @@ PERROR("Could not find total pages for domain"); goto error_out; } - - if ( (image = xc_read_kernel_image(image_name, &image_size)) == NULL ) - goto error_out; if ( mlock(&st_ctxt, sizeof(st_ctxt) ) ) { @@ -404,8 +406,6 @@ ERROR("Error constructing guest OS"); goto error_out; } - - free(image); /* FPU is set up to default initial state. */ memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt)); @@ -450,7 +450,6 @@ return rc; error_out: - free(image); return -1; } @@ -580,6 +579,92 @@ return 0; } +/* xc_hvm_build + * + * Create a domain for a virtualized Linux, using files/filenames + * + */ + +int xc_hvm_build(int xc_handle, + uint32_t domid, + int memsize, + const char *image_name, + unsigned int vcpus, + unsigned int pae, + unsigned int acpi, + unsigned int apic, + unsigned int store_evtchn, + unsigned long *store_mfn) +{ + char *image; + int sts; + unsigned long image_size; + + if ( (image_name == NULL) || + ((image = xc_read_image(image_name, &image_size)) == NULL) ) + return -1; + + sts = xc_hvm_build_internal(xc_handle, domid, memsize, + image, image_size, + vcpus, pae, acpi, apic, + store_evtchn, store_mfn); + + free(image); + + return sts; +} + +/* xc_hvm_build_mem + * + * Create a domain for a virtualized Linux, using buffers + * + */ + +int xc_hvm_build_mem(int xc_handle, + uint32_t domid, + int memsize, + char *image_buffer, + unsigned long image_size, + unsigned int vcpus, + unsigned int pae, + unsigned int acpi, + unsigned int apic, + unsigned int store_evtchn, + unsigned long *store_mfn) +{ + int sts; + unsigned long img_len; + char *img; + + /* Validate that there is a kernel buffer */ + + if ( (image_buffer == NULL) || (image_size == 0) ) + { + ERROR("kernel image buffer not present"); + return -EINVAL; + } + + img = xc_inflate_buffer(image_buffer, image_size, &img_len); + if (img == NULL) + { + ERROR("unable to inflate ram disk buffer"); + return -1; + } + + sts = xc_hvm_build_internal(xc_handle, domid, memsize, + img, img_len, + vcpus, pae, acpi, apic, + store_evtchn, store_mfn); + + /* xc_inflate_buffer may return the original buffer pointer (for + for already inflated buffers), so exercise some care in freeing */ + + if ( (img != NULL) && (img != image_buffer) ) + free(img); + + return sts; +} + /* * Local variables: * mode: C diff -r 5ea87acc07dc -r 899532500ada tools/libxc/xc_ia64_stubs.c --- a/tools/libxc/xc_ia64_stubs.c Thu Mar 9 10:20:31 2006 +++ b/tools/libxc/xc_ia64_stubs.c Thu Mar 9 12:00:38 2006 @@ -658,7 +658,7 @@ goto error_out; } - if ( (image = xc_read_kernel_image(image_name, &image_size)) == NULL ){ + if ( (image = xc_read_image(image_name, &image_size)) == NULL ){ PERROR("Could not read guest firmware image %s",image_name); goto error_out; } diff -r 5ea87acc07dc -r 899532500ada tools/libxc/xc_linux_build.c --- a/tools/libxc/xc_linux_build.c Thu Mar 9 10:20:31 2006 +++ b/tools/libxc/xc_linux_build.c Thu Mar 9 12:00:38 2006 @@ -406,8 +406,8 @@ static int setup_guest(int xc_handle, uint32_t dom, - char *image, unsigned long image_size, - gzFile initrd_gfd, unsigned long initrd_len, + const char *image, unsigned long image_size, + char *initrd, unsigned long initrd_len, unsigned long nr_pages, unsigned long *pvsi, unsigned long *pvke, unsigned long *pvss, vcpu_guest_context_t *ctxt, @@ -472,23 +472,17 @@ (load_funcs.loadimage)(image, image_size, xc_handle, dom, page_array, &dsi); - /* Load the initial ramdisk image. */ + /* Load the initial ramdisk image, if present */ if ( initrd_len != 0 ) { - for ( i = (vinitrd_start - dsi.v_start); - i < (vinitrd_end - dsi.v_start); i += PAGE_SIZE ) - { - char page[PAGE_SIZE]; - if ( gzread(initrd_gfd, page, PAGE_SIZE) == -1 ) - { - PERROR("Error reading initrd image, could not"); - goto error_out; - } + /* Pages are not contiguous, so do the copy one page at a time */ + for ( i = (vinitrd_start - dsi.v_start), offset = 0; + i < (vinitrd_end - dsi.v_start); + i += PAGE_SIZE, offset += PAGE_SIZE ) xc_copy_to_domain_page(xc_handle, dom, - page_array[i>>PAGE_SHIFT], page); - } - } - + page_array[i>>PAGE_SHIFT], + &initrd[offset]); + } *pvke = dsi.v_kernentry; @@ -518,7 +512,7 @@ start_info->store_evtchn = store_evtchn; start_info->console_mfn = nr_pages - 1; start_info->console_evtchn = console_evtchn; - start_info->nr_pages = nr_pages; // FIXME?: nr_pages - 2 ???? + start_info->nr_pages = nr_pages; // FIXME?: nr_pages - 2 ???? if ( initrd_len != 0 ) { ctxt->initrd.start = vinitrd_start; @@ -546,8 +540,8 @@ #else /* x86 */ static int setup_guest(int xc_handle, uint32_t dom, - char *image, unsigned long image_size, - gzFile initrd_gfd, unsigned long initrd_len, + const char *image, unsigned long image_size, + char *initrd, unsigned long initrd_len, unsigned long nr_pages, unsigned long *pvsi, unsigned long *pvke, unsigned long *pvss, vcpu_guest_context_t *ctxt, @@ -592,13 +586,13 @@ unsigned long shadow_mode_enabled; uint32_t supported_features[XENFEAT_NR_SUBMAPS] = { 0, }; - rc = probeimageformat(image, image_size, &load_funcs); + rc = probeimageformat((char *)image, (unsigned long)image_size, &load_funcs); if ( rc != 0 ) goto error_out; memset(&dsi, 0, sizeof(struct domain_setup_info)); - rc = (load_funcs.parseimage)(image, image_size, &dsi); + rc = (load_funcs.parseimage)((char *)image, (unsigned long)image_size, &dsi); if ( rc != 0 ) goto error_out; @@ -706,7 +700,8 @@ goto error_out; } - (load_funcs.loadimage)(image, image_size, xc_handle, dom, page_array, + (load_funcs.loadimage)((char *)image, image_size, + xc_handle, dom, page_array, &dsi); /* Parse and validate kernel features. */ @@ -738,21 +733,17 @@ shadow_mode_enabled = test_feature_bit(XENFEAT_auto_translated_physmap, required_features); - /* Load the initial ramdisk image. */ + /* Load the initial ramdisk image, if present. */ if ( initrd_len != 0 ) { - for ( i = (vinitrd_start - dsi.v_start); - i < (vinitrd_end - dsi.v_start); i += PAGE_SIZE ) - { - char page[PAGE_SIZE]; - if ( gzread(initrd_gfd, page, PAGE_SIZE) == -1 ) - { - PERROR("Error reading initrd image, could not"); - goto error_out; - } + int offset; + /* Pages are not contiguous, so do the inflation a page at a time. */ + for ( i = (vinitrd_start - dsi.v_start), offset = 0; + i < (vinitrd_end - dsi.v_start); + i += PAGE_SIZE, offset += PAGE_SIZE ) xc_copy_to_domain_page(xc_handle, dom, - page_array[i>>PAGE_SHIFT], page); - } + page_array[i>>PAGE_SHIFT], + &initrd[offset]); } /* setup page tables */ @@ -966,27 +957,25 @@ } #endif -int xc_linux_build(int xc_handle, - uint32_t domid, - const char *image_name, - const char *ramdisk_name, - const char *cmdline, - const char *features, - unsigned long flags, - unsigned int store_evtchn, - unsigned long *store_mfn, - unsigned int console_evtchn, - unsigned long *console_mfn) +static int xc_linux_build_internal(int xc_handle, + uint32_t domid, + const char *image, + unsigned long image_size, + char *initrd, + unsigned long initrd_len, + const char *cmdline, + const char *features, + unsigned long flags, + unsigned int store_evtchn, + unsigned long *store_mfn, + unsigned int console_evtchn, + unsigned long *console_mfn) { dom0_op_t launch_op; DECLARE_DOM0_OP; - int initrd_fd = -1; - gzFile initrd_gfd = NULL; int rc, i; vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt; unsigned long nr_pages; - char *image = NULL; - unsigned long image_size, initrd_size=0; unsigned long vstartinfo_start, vkern_entry, vstack_start; uint32_t features_bitmap[XENFEAT_NR_SUBMAPS] = { 0, }; @@ -1003,26 +992,6 @@ { PERROR("Could not find total pages for domain"); goto error_out; - } - - if ( (image = xc_read_kernel_image(image_name, &image_size)) == NULL ) - goto error_out; - - if ( (ramdisk_name != NULL) && (strlen(ramdisk_name) != 0) ) - { - if ( (initrd_fd = open(ramdisk_name, O_RDONLY)) < 0 ) - { - PERROR("Could not open the initial ramdisk image"); - goto error_out; - } - - initrd_size = xc_get_filesz(initrd_fd); - - if ( (initrd_gfd = gzdopen(initrd_fd, "rb")) == NULL ) - { - PERROR("Could not allocate decompression state for initrd"); - goto error_out; - } } #ifdef VALGRIND @@ -1047,7 +1016,8 @@ memset(ctxt, 0, sizeof(*ctxt)); if ( setup_guest(xc_handle, domid, image, image_size, - initrd_gfd, initrd_size, nr_pages, + initrd, initrd_len, + nr_pages, &vstartinfo_start, &vkern_entry, &vstack_start, ctxt, cmdline, op.u.getdomaininfo.shared_info_frame, @@ -1058,12 +1028,6 @@ ERROR("Error constructing guest OS"); goto error_out; } - - if ( initrd_fd >= 0 ) - close(initrd_fd); - if ( initrd_gfd ) - gzclose(initrd_gfd); - free(image); #ifdef __ia64__ /* based on new_thread in xen/arch/ia64/domain.c */ @@ -1150,12 +1114,114 @@ return rc; error_out: - if ( initrd_gfd != NULL ) - gzclose(initrd_gfd); - else if ( initrd_fd >= 0 ) - close(initrd_fd); + return -1; +} + +int xc_linux_build_mem(int xc_handle, + uint32_t domid, + char *image_buffer, + unsigned long image_size, + char *initrd, + unsigned long initrd_len, + const char *cmdline, + const char *features, + unsigned long flags, + unsigned int store_evtchn, + unsigned long *store_mfn, + unsigned int console_evtchn, + unsigned long *console_mfn) +{ + int sts; + char *img_buf, *ram_buf; + unsigned long img_len, ram_len; + + /* A kernel buffer is required */ + if ( (image_buffer == NULL) || (image_size == 0) ) + { + ERROR("kernel image buffer not present"); + return EINVAL; + } + + /* If it's gzipped, inflate it; otherwise, use as is */ + /* xc_inflate_buffer may return the same buffer pointer if */ + /* the buffer is already inflated */ + img_buf = xc_inflate_buffer(image_buffer, image_size, &img_len); + if ( img_buf == NULL ) + { + ERROR("unable to inflate kernel image buffer"); + return EFAULT; + } + + /* RAM disks are optional; if we get one, inflate it */ + if ( initrd != NULL ) + { + ram_buf = xc_inflate_buffer(initrd, initrd_len, &ram_len); + if ( ram_buf == NULL ) + { + ERROR("unable to inflate ram disk buffer"); + sts = -1; + goto out; + } + } + else + { + ram_buf = initrd; + ram_len = initrd_len; + } + + sts = xc_linux_build_internal(xc_handle, domid, img_buf, img_len, + ram_buf, ram_len, cmdline, features, flags, + store_evtchn, store_mfn, + console_evtchn, console_mfn); + + out: + /* The inflation routines may pass back the same buffer so be */ + /* sure that we have a buffer and that it's not the one passed in. */ + /* Don't unnecessarily annoy/surprise/confound the caller */ + if ( (img_buf != NULL) && (img_buf != image_buffer) ) + free(img_buf); + if ( (ram_buf != NULL) && (ram_buf != initrd) ) + free(ram_buf); + + return sts; +} + +int xc_linux_build(int xc_handle, + uint32_t domid, + const char *image_name, + const char *initrd_name, + const char *cmdline, + const char *features, + unsigned long flags, + unsigned int store_evtchn, + unsigned long *store_mfn, + unsigned int console_evtchn, + unsigned long *console_mfn) +{ + char *image, *ram = NULL; + unsigned long image_size, ram_size = 0; + int sts; + + if ( (image_name == NULL) || + ((image = xc_read_image(image_name, &image_size)) == NULL )) + return -1; + + if ( (initrd_name != NULL) && (strlen(initrd_name) != 0) && + ((ram = xc_read_image(initrd_name, &ram_size)) == NULL) ) + { + free(image); + return -1; + } + + sts = xc_linux_build_internal(xc_handle, domid, image, image_size, + ram, ram_size, cmdline, features, flags, + store_evtchn, store_mfn, + console_evtchn, console_mfn); + free(image); - return -1; + free(ram); + + return sts; } /* diff -r 5ea87acc07dc -r 899532500ada tools/libxc/xenguest.h --- a/tools/libxc/xenguest.h Thu Mar 9 10:20:31 2006 +++ b/tools/libxc/xenguest.h Thu Mar 9 12:00:38 2006 @@ -42,6 +42,22 @@ unsigned long *store_mfn, unsigned int console_evtchn, unsigned long *console_mfn); +/** + * This function will create a domain for a paravirtualized Linux + * using file names pointing to kernel and ramdisk + * + * @parm xc_handle a handle to an open hypervisor interface + * @parm domid the id of the domain + * @param image_name name of the kernel image file + * @param ramdisk_name name of the ramdisk image file + * @parm cmdline command line string + * @parm flags domain creation flags + * @parm store_evtchn the store event channel for this domain to use + * @parm store_mfn returned with the mfn of the store page + * @parm console_evtchn the console event channel for this domain to use + * @parm conole_mfn returned with the mfn of the console page + * @return 0 on success, -1 on failure + */ int xc_linux_build(int xc_handle, uint32_t domid, const char *image_name, @@ -54,6 +70,38 @@ unsigned int console_evtchn, unsigned long *console_mfn); +/** + * This function will create a domain for a paravirtualized Linux + * using buffers for kernel and initrd + * + * @param xc_handle a handle to an open hypervisor interface + * @param domid the id of the domain + * @param image_buffer buffer containing kernel image + * @param image_size size of the kernel image buffer + * @param initrd_buffer name of the ramdisk image file + * @param initrd_size size of the ramdisk buffer + * @param cmdline command line string + * @param flags domain creation flags + * @param store_evtchn the store event channel for this domain to use + * @param store_mfn returned with the mfn of the store page + * @param console_evtchn the console event channel for this domain to use + * @param conole_mfn returned with the mfn of the console page + * @return 0 on success, -1 on failure + */ +int xc_linux_build_mem(int xc_handle, + uint32_t domid, + char *image_buffer, + unsigned long image_size, + char *initrd_buffer, + unsigned long initrd_size, + const char *cmdline, + const char *features, + unsigned long flags, + unsigned int store_evtchn, + unsigned long *store_mfn, + unsigned int console_evtchn, + unsigned long *console_mfn); + int xc_hvm_build(int xc_handle, uint32_t domid, int memsize, @@ -65,4 +113,16 @@ unsigned int store_evtchn, unsigned long *store_mfn); -#endif // XENGUEST_H +int xc_hvm_build_mem(int xc_handle, + uint32_t domid, + int memsize, + char *image_buffer, + unsigned long image_size, + unsigned int vcpus, + unsigned int pae, + unsigned int acpi, + unsigned int apic, + unsigned int store_evtchn, + unsigned long *store_mfn); + +#endif /* XENGUEST_H */ diff -r 5ea87acc07dc -r 899532500ada tools/libxc/xg_private.c --- a/tools/libxc/xg_private.c Thu Mar 9 10:20:31 2006 +++ b/tools/libxc/xg_private.c Thu Mar 9 12:00:38 2006 @@ -10,15 +10,15 @@ #include "xg_private.h" -char *xc_read_kernel_image(const char *filename, unsigned long *size) +char *xc_read_image(const char *filename, unsigned long *size) { int kernel_fd = -1; gzFile kernel_gfd = NULL; char *image = NULL; unsigned int bytes; - if ( filename == NULL ) - goto out; + if ( (filename == NULL) || (size == NULL) ) + return NULL; if ( (kernel_fd = open(filename, O_RDONLY)) < 0 ) { @@ -60,6 +60,62 @@ return image; } +char *xc_inflate_buffer(char *in_buf, unsigned long in_size, + unsigned long *out_size) +{ + int sts; + z_stream zStream; + unsigned long out_len; + char *out_buf; + + /* Not compressed? Then return the original buffer. */ + if ( ((unsigned char)in_buf[0] != 0x1F) || + ((unsigned char)in_buf[1] != 0x8B) ) + { + if ( out_size != NULL ) + *out_size = in_size; + return in_buf; + } + + out_len = in_buf[in_size-4] + + (256 * (in_buf[in_size-3] + + (256 * (in_buf[in_size-2] + + (256 * in_buf[in_size-1]))))); + bzero(&zStream, sizeof(zStream)); + out_buf = malloc(out_len + 16); /* Leave a little extra space */ + if ( out_buf == NULL ) + { + ERROR("Error mallocing buffer\n"); + return NULL; + } + + zStream.next_in = (unsigned char *)in_buf; + zStream.avail_in = in_size; + zStream.next_out = (unsigned char *)out_buf; + zStream.avail_out = out_len+16; + sts = inflateInit2(&zStream, (MAX_WBITS+32)); /* +32 means "handle gzip" */ + if ( sts != Z_OK ) + { + ERROR("inflateInit failed, sts %d\n", sts); + free(out_buf); + return NULL; + } + + /* Inflate in one pass/call */ + sts = inflate(&zStream, Z_FINISH); + if ( sts != Z_STREAM_END ) + { + ERROR("inflate failed, sts %d\n", sts); + free(out_buf); + return NULL; + } + + if ( out_size != NULL ) + *out_size = out_len; + + return out_buf; +} + /*******************/ int pin_table( @@ -77,7 +133,7 @@ } /* This is shared between save and restore, and may generally be useful. */ -unsigned long csum_page (void * page) +unsigned long csum_page(void *page) { int i; unsigned long *p = page; diff -r 5ea87acc07dc -r 899532500ada tools/libxc/xg_private.h --- a/tools/libxc/xg_private.h Thu Mar 9 10:20:31 2006 +++ b/tools/libxc/xg_private.h Thu Mar 9 12:00:38 2006 @@ -26,7 +26,11 @@ #endif -char *xc_read_kernel_image(const char *filename, unsigned long *size); +char *xc_read_image(const char *filename, unsigned long *size); +char *xc_inflate_buffer(char *in_buf, + unsigned long in_size, + unsigned long *out_size); + unsigned long csum_page (void * page); #define _PAGE_PRESENT 0x001 @@ -89,7 +93,7 @@ #define l2_table_offset_pae(_a) \ (((_a) >> L2_PAGETABLE_SHIFT_PAE) & (L2_PAGETABLE_ENTRIES_PAE - 1)) #define l3_table_offset_pae(_a) \ - (((_a) >> L3_PAGETABLE_SHIFT_PAE) & (L3_PAGETABLE_ENTRIES_PAE - 1)) + (((_a) >> L3_PAGETABLE_SHIFT_PAE) & (L3_PAGETABLE_ENTRIES_PAE - 1)) #if defined(__i386__) #define l1_table_offset(_a) \ @@ -102,9 +106,9 @@ #define l2_table_offset(_a) \ (((_a) >> L2_PAGETABLE_SHIFT) & (L2_PAGETABLE_ENTRIES - 1)) #define l3_table_offset(_a) \ - (((_a) >> L3_PAGETABLE_SHIFT) & (L3_PAGETABLE_ENTRIES - 1)) + (((_a) >> L3_PAGETABLE_SHIFT) & (L3_PAGETABLE_ENTRIES - 1)) #define l4_table_offset(_a) \ - (((_a) >> L4_PAGETABLE_SHIFT) & (L4_PAGETABLE_ENTRIES - 1)) + (((_a) >> L4_PAGETABLE_SHIFT) & (L4_PAGETABLE_ENTRIES - 1)) #endif #define ERROR(_m, _a...) \ @@ -142,10 +146,10 @@ }; typedef int (*parseimagefunc)(char *image, unsigned long image_size, - struct domain_setup_info *dsi); + struct domain_setup_info *dsi); typedef int (*loadimagefunc)(char *image, unsigned long image_size, int xch, - uint32_t dom, unsigned long *parray, - struct domain_setup_info *dsi); + uint32_t dom, unsigned long *parray, + struct domain_setup_info *dsi); struct load_funcs { @@ -176,7 +180,7 @@ unsigned long vstart); int pin_table(int xc_handle, unsigned int type, unsigned long mfn, - domid_t dom); + domid_t dom); /* image loading */ int probe_elf(char *image, unsigned long image_size, struct load_funcs *funcs); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |