[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH] multiboot-like module support
This defines how multiple modules can be passed to a domain by packing them together into a "multiboot module" in a way very similar to the multiboot standard. An SIF_ flag is added to announce such package. This also adds a packing implementation to PV-GRUB. Signed-Off-By: Samuel Thibault <samuel.thibault@xxxxxxxxxxxx> diff -r d0b030008814 xen/include/public/xen.h --- a/xen/include/public/xen.h Fri Nov 27 08:09:26 2009 +0000 +++ b/xen/include/public/xen.h Sun Nov 29 13:17:38 2009 +0100 @@ -584,8 +584,35 @@ typedef struct start_info start_info_t; /* These flags are passed in the 'flags' field of start_info_t. */ #define SIF_PRIVILEGED (1<<0) /* Is the domain privileged? */ #define SIF_INITDOMAIN (1<<1) /* Is this the initial control domain? */ +#define SIF_MULTIBOOT_MOD (1<<2) /* Is mod_start a multiboot module? */ #define SIF_PM_MASK (0xFF<<8) /* reserve 1 byte for xen-pm options */ +/* + * A multiboot module is a package containing modules very similar to a + * multiboot module array. The only differences are: + * - the array of module descriptors is by convention simply at the beginning + * of the multiboot module, + * - addresses in the module descriptors are based on the beginning of the + * multiboot module, + * - the number of modules is determined by a termination descriptor that has + * mod_start == 0. + * + * This permits to both build it statically and reference it in a configuration + * file, and let the PV guest easily rebase the addresses to virtual addresses + * and at the same time count the number of modules. + */ +struct xen_multiboot_mod_list +{ + /* Address of first byte of the module */ + uint32_t mod_start; + /* Address of last byte of the module (inclusive) */ + uint32_t mod_end; + /* Address of zero-terminated command line */ + uint32_t cmdline; + /* Unused, must be zero */ + uint32_t pad; +}; + typedef struct dom0_vga_console_info { uint8_t video_type; /* DOM0_VGA_CONSOLE_??? */ #define XEN_VGATYPE_TEXT_MODE_3 0x03 diff -r d0b030008814 stubdom/grub.patches/99minios --- a/stubdom/grub.patches/99minios Fri Nov 27 08:09:26 2009 +0000 +++ b/stubdom/grub.patches/99minios Sun Nov 29 13:17:38 2009 +0100 @@ -151,6 +151,14 @@ Index: grub/stage2/builtins.c /* print */ static int +@@ -2910,6 +2910,7 @@ + switch (kernel_type) + { + case KERNEL_TYPE_MULTIBOOT: ++ case KERNEL_TYPE_PV: + if (mb_cmdline + len + 1 > (char *) MB_CMDLINE_BUF + MB_CMDLINE_BUFLEN) + { + errnum = ERR_WONT_FIT; @@ -3776,6 +3802,7 @@ }; diff -r d0b030008814 stubdom/grub/config.h --- a/stubdom/grub/config.h Fri Nov 27 08:09:26 2009 +0000 +++ b/stubdom/grub/config.h Sun Nov 29 13:17:38 2009 +0100 @@ -5,7 +5,7 @@ #define debug _debug #define grub_halt(a) do_exit() #define printf grub_printf -void kexec(void *kernel, long kernel_size, void *module, long module_size, char *cmdline); +void kexec(void *kernel, long kernel_size, void *module, long module_size, char *cmdline, unsigned long flags); struct fbfront_dev *fb_open(void *fb, int width, int height, int depth); void fb_close(void); void pv_boot (void); diff -r d0b030008814 stubdom/grub/kexec.c --- a/stubdom/grub/kexec.c Fri Nov 27 08:09:26 2009 +0000 +++ b/stubdom/grub/kexec.c Sun Nov 29 13:17:38 2009 +0100 @@ -103,7 +103,7 @@ int kexec_allocate(struct xc_dom_image * return 0; } -void kexec(void *kernel, long kernel_size, void *module, long module_size, char *cmdline) +void kexec(void *kernel, long kernel_size, void *module, long module_size, char *cmdline, unsigned long flags) { struct xc_dom_image *dom; int rc; @@ -129,7 +129,7 @@ void kexec(void *kernel, long kernel_siz dom->ramdisk_blob = module; dom->ramdisk_size = module_size; - dom->flags = 0; + dom->flags = flags; dom->console_evtchn = start_info.console.domU.evtchn; dom->xenstore_evtchn = start_info.store_evtchn; diff -r d0b030008814 stubdom/grub/mini-os.c --- a/stubdom/grub/mini-os.c Fri Nov 27 08:09:26 2009 +0000 +++ b/stubdom/grub/mini-os.c Sun Nov 29 13:17:38 2009 +0100 @@ -173,6 +173,8 @@ load_file(char *name, void **ptr, long * void *kernel_image, *module_image; long kernel_size, module_size; char *kernel_arg, *module_arg; +void *multiboot_next_module; +struct xen_multiboot_mod_list *multiboot_next_module_header; kernel_t load_image (char *kernel, char *arg, kernel_t suggested_type, @@ -196,6 +198,8 @@ load_initrd (char *initrd) if (module_image) free(module_image); module_image = NULL; + multiboot_next_module = NULL; + multiboot_next_module_header = NULL; load_file (initrd, &module_image, &module_size); return ! errnum; } @@ -203,20 +207,76 @@ load_initrd (char *initrd) int load_module (char *module, char *arg) { - if (module_image) + void *new_module, *new_module_image; + long new_module_size, rounded_new_module_size; + + if (load_file (module, &new_module, &new_module_size)) + return 0; + if (strlen(arg) >= PAGE_SIZE) { + /* Too big module command line */ + errnum = ERR_WONT_FIT; + return 0; + } + rounded_new_module_size = (new_module_size + PAGE_SIZE - 1) & PAGE_MASK; + + if (module_image && !multiboot_next_module_header) { + /* Initrd already loaded, drop it */ free(module_image); - module_image = NULL; - load_file (module, &module_image, &module_size); - if (module_arg) - free(module_arg); - module_arg = strdup(arg); - return ! errnum; + if (module_arg) + free(module_arg); + module_image = NULL; + } + if (!module_image) + /* Reserve one page for the header */ + multiboot_next_module = (void*) PAGE_SIZE; + + /* Allocate more room for the new module plus its arg */ + new_module_image = realloc(module_image, + (multiboot_next_module - module_image) + rounded_new_module_size + PAGE_SIZE); + + /* Update pointers */ + multiboot_next_module += new_module_image - module_image; + multiboot_next_module_header = (void*) multiboot_next_module_header + (new_module_image - module_image); + module_image = new_module_image; + + if ((void*) (multiboot_next_module_header+1) - module_image > PAGE_SIZE) { + /* Too many modules */ + ERR_WONT_FIT; + return 0; + } + + /* Copy module */ + memcpy(multiboot_next_module, new_module, new_module_size); + multiboot_next_module_header->mod_start = multiboot_next_module - module_image; + multiboot_next_module_header->mod_end = multiboot_next_module_header->mod_start + new_module_size - 1; + multiboot_next_module += rounded_new_module_size; + + /* Copy cmdline */ + strcpy(multiboot_next_module, arg); + multiboot_next_module_header->cmdline = multiboot_next_module - module_image; + multiboot_next_module += PAGE_SIZE; + + /* Pad */ + multiboot_next_module_header->pad = 0; + + multiboot_next_module_header++; + + return 1; } void pv_boot (void) { - kexec(kernel_image, kernel_size, module_image, module_size, kernel_arg); + unsigned long flags = 0; + if (multiboot_next_module_header) { + /* Termination entry */ + multiboot_next_module_header->mod_start = 0; + /* Total size */ + module_size = multiboot_next_module - module_image; + /* It's a multiboot module */ + flags |= SIF_MULTIBOOT_MOD; + } + kexec(kernel_image, kernel_size, module_image, module_size, kernel_arg, flags); } /* _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |