From mboxrd@z Thu Jan 1 00:00:00 1970 From: Samuel Thibault Subject: Re: [PATCH2] multiboot module support Date: Sat, 12 Dec 2009 00:18:54 +0100 Message-ID: <20091211231854.GD6590@const> References: <1260525584.10348.5030.camel@zakaz.uk.xensource.com> <20091211102923.GF5096@const.bordeaux.inria.fr> Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: quoted-printable Return-path: Content-Disposition: inline In-Reply-To: <20091211102923.GF5096@const.bordeaux.inria.fr> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: Ian Campbell , Keir Fraser , "xen-devel@lists.xensource.com" List-Id: xen-devel@lists.xenproject.org Samuel Thibault, le Fri 11 Dec 2009 11:29:23 +0100, a =E9crit : > Yes, it didn't go as badly as I thought. The addition of mods_count > could perhaps be avoided by saying that the multiboot module table > always ends with a NULL entry. That is still compliant with multiboot, > it just makes the PV guest have to count the modules itself (but not > have to rebase all the pointers). i.e. the patch below Samuel This defines how multiple modules can be passed to a domain by packing th= em together into a "multiboot module" the same way as the multiboot standard= . An SIF_ flag is added to announce such package. xc_dom_multiboot_mem is adde= d to libxc to load such list of modules, used by PV-GRUB. Signed-Off-By: Samuel Thibault diff -r 8f304c003af4 stubdom/grub.patches/99minios --- a/stubdom/grub.patches/99minios Wed Dec 09 10:59:31 2009 +0000 +++ b/stubdom/grub.patches/99minios Sat Dec 12 00:18:05 2009 +0100 @@ -151,6 +151,14 @@ =20 /* 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_B= UFLEN) + { + errnum =3D ERR_WONT_FIT; @@ -3776,6 +3802,7 @@ }; =20 diff -r 8f304c003af4 stubdom/grub/config.h --- a/stubdom/grub/config.h Wed Dec 09 10:59:31 2009 +0000 +++ b/stubdom/grub/config.h Sat Dec 12 00:18:05 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_siz= e, char *cmdline); +void kexec(void *kernel, long kernel_size, char *cmdline, void *module, = long module_size, int multiboot_number, void **multiboot_blobs, size_t *m= ultiboot_sizes, char **multiboot_cmdlines); struct fbfront_dev *fb_open(void *fb, int width, int height, int depth); void fb_close(void); void pv_boot (void); diff -r 8f304c003af4 stubdom/grub/kexec.c --- a/stubdom/grub/kexec.c Wed Dec 09 10:59:31 2009 +0000 +++ b/stubdom/grub/kexec.c Sat Dec 12 00:18:05 2009 +0100 @@ -103,7 +103,7 @@ return 0; } =20 -void kexec(void *kernel, long kernel_size, void *module, long module_siz= e, char *cmdline) +void kexec(void *kernel, long kernel_size, char *cmdline, void *module, = long module_size, int multiboot_number, void **multiboot_blobs, size_t *m= ultiboot_sizes, char **multiboot_cmdlines) { struct xc_dom_image *dom; int rc; @@ -123,11 +123,11 @@ dom =3D xc_dom_allocate(cmdline, features); dom->allocate =3D kexec_allocate; =20 - dom->kernel_blob =3D kernel; - dom->kernel_size =3D kernel_size; - - dom->ramdisk_blob =3D module; - dom->ramdisk_size =3D module_size; + xc_dom_kernel_mem(dom, kernel, kernel_size); + if (module) + xc_dom_ramdisk_mem(dom, module, module_size); + else if (multiboot_blobs) + xc_dom_multiboot_mem(dom, multiboot_number, multiboot_blobs, multi= boot_sizes, multiboot_cmdlines); =20 dom->flags =3D 0; dom->console_evtchn =3D start_info.console.domU.evtchn; diff -r 8f304c003af4 stubdom/grub/mini-os.c --- a/stubdom/grub/mini-os.c Wed Dec 09 10:59:31 2009 +0000 +++ b/stubdom/grub/mini-os.c Sat Dec 12 00:18:05 2009 +0100 @@ -172,7 +172,11 @@ =20 void *kernel_image, *module_image; long kernel_size, module_size; -char *kernel_arg, *module_arg; +char *kernel_arg; +void **multiboot_blobs; +size_t *multiboot_sizes; +char **multiboot_cmdlines; +int multiboot_number; =20 kernel_t load_image (char *kernel, char *arg, kernel_t suggested_type, @@ -196,6 +200,13 @@ if (module_image) free(module_image); module_image =3D NULL; + multiboot_number =3D 0; + free(multiboot_blobs); + multiboot_blobs =3D NULL; + free(multiboot_sizes); + multiboot_sizes =3D NULL; + free(multiboot_cmdlines); + multiboot_cmdlines =3D NULL; load_file (initrd, &module_image, &module_size); return ! errnum; } @@ -203,20 +214,28 @@ int load_module (char *module, char *arg) { - if (module_image) - free(module_image); - module_image =3D NULL; - load_file (module, &module_image, &module_size); - if (module_arg) - free(module_arg); - module_arg =3D strdup(arg); - return ! errnum; + void *module_blob; + long module_size; + + if (load_file (module, &module_blob, &module_size)) + return 0; + + multiboot_number++; + multiboot_blobs =3D realloc(multiboot_blobs, multiboot_number * size= of(*multiboot_blobs)); + multiboot_sizes =3D realloc(multiboot_sizes, multiboot_number * size= of(*multiboot_sizes)); + multiboot_cmdlines =3D realloc(multiboot_cmdlines, multiboot_number = * sizeof(*multiboot_cmdlines)); + + multiboot_blobs[multiboot_number-1] =3D module_blob; + multiboot_sizes[multiboot_number-1] =3D module_size; + multiboot_cmdlines[multiboot_number-1] =3D arg; + + return 1; } =20 void pv_boot (void) { - kexec(kernel_image, kernel_size, module_image, module_size, kernel_a= rg); + kexec(kernel_image, kernel_size, kernel_arg, module_image, module_si= ze, multiboot_number, multiboot_blobs, multiboot_sizes, multiboot_cmdline= s); } =20 /* diff -r 8f304c003af4 tools/libxc/xc_dom.h --- a/tools/libxc/xc_dom.h Wed Dec 09 10:59:31 2009 +0000 +++ b/tools/libxc/xc_dom.h Sat Dec 12 00:18:05 2009 +0100 @@ -35,6 +35,10 @@ size_t kernel_size; void *ramdisk_blob; size_t ramdisk_size; + int multiboot_number; + void **multiboot_blobs; + char **multiboot_cmdlines; + size_t *multiboot_sizes; =20 /* arguments and parameters */ char *cmdline; @@ -47,6 +51,7 @@ /* memory layout */ struct xc_dom_seg kernel_seg; struct xc_dom_seg ramdisk_seg; + struct xc_dom_seg multiboot_seg; struct xc_dom_seg p2m_seg; struct xc_dom_seg pgtables_seg; struct xc_dom_seg devicetree_seg; @@ -168,6 +173,10 @@ size_t memsize); int xc_dom_ramdisk_mem(struct xc_dom_image *dom, const void *mem, size_t memsize); +int xc_dom_multiboot_mem(struct xc_dom_image *dom, int multiboot_number, + void **multiboot_blobs, + size_t *multiboot_sizes, + char **multiboot_cmdlines); =20 int xc_dom_parse_image(struct xc_dom_image *dom); struct xc_dom_arch *xc_dom_find_arch_hooks(char *guest_type); diff -r 8f304c003af4 tools/libxc/xc_dom_core.c --- a/tools/libxc/xc_dom_core.c Wed Dec 09 10:59:31 2009 +0000 +++ b/tools/libxc/xc_dom_core.c Sat Dec 12 00:18:05 2009 +0100 @@ -607,6 +607,17 @@ return 0; } =20 +int xc_dom_multiboot_mem(struct xc_dom_image *dom, int number, + void **mems, size_t *memsizes, char **cmdlines) +{ + xc_dom_printf("%s: called\n", __FUNCTION__); + dom->multiboot_number =3D number; + dom->multiboot_blobs =3D mems; + dom->multiboot_sizes =3D memsizes; + dom->multiboot_cmdlines =3D cmdlines; + return 0; +} + int xc_dom_parse_image(struct xc_dom_image *dom) { int i; @@ -757,6 +768,56 @@ memcpy(ramdiskmap, dom->ramdisk_blob, dom->ramdisk_size); } =20 + /* load multiboot modules */ + if ( dom->multiboot_blobs ) + { + void *multibootmap; + int i; + struct xen_multiboot_mod_list *module; + char *module_cmdline; + void *module_blob; + size_t totsize =3D 0; + size_t headers_size =3D 0; + size_t cmdlines_size =3D 0; + + for (i =3D 0; i < dom->multiboot_number; i++) { + totsize +=3D ROUNDUP(dom->multiboot_sizes[i], page_size); + headers_size +=3D sizeof(*module); + cmdlines_size +=3D strlen(dom->multiboot_cmdlines[i]) + 1; + } + headers_size +=3D sizeof(*module); + + totsize +=3D ROUNDUP(headers_size + cmdlines_size, page_size); + + if (xc_dom_alloc_segment(dom, &dom->multiboot_seg, "multiboot", = 0, totsize)) + goto err; + multibootmap =3D xc_dom_seg_to_ptr(dom, &dom->multiboot_seg); + + module =3D multibootmap; + module_cmdline =3D multibootmap + headers_size; + module_blob =3D multibootmap + headers_size + cmdlines_size; + + for (i =3D 0; i < dom->multiboot_number; i++) { + int len =3D strlen(dom->multiboot_cmdlines[i]) + 1; + memcpy(module_cmdline, dom->multiboot_cmdlines[i], len); + module->cmdline =3D (void*) module_cmdline - multibootmap + + dom->multiboot_seg.vstart - dom->parms.vir= t_base; + module_cmdline +=3D len; + + memcpy(module_blob, dom->multiboot_blobs[i], + dom->multiboot_sizes[i]); + module->mod_start =3D (void*) module_blob - multibootmap + + dom->multiboot_seg.vstart - dom->parms.vir= t_base; + module->mod_end =3D module->mod_start + dom->multiboot_sizes= [i] - 1; + module_blob +=3D ROUNDUP(dom->multiboot_sizes[i], page_size)= ; + + module->pad =3D 0; + + module++; + } + module->mod_start =3D 0; + } + /* allocate other pages */ if ( dom->arch_hooks->alloc_magic_pages(dom) !=3D 0 ) goto err; diff -r 8f304c003af4 tools/libxc/xc_dom_ia64.c --- a/tools/libxc/xc_dom_ia64.c Wed Dec 09 10:59:31 2009 +0000 +++ b/tools/libxc/xc_dom_ia64.c Sat Dec 12 00:18:05 2009 +0100 @@ -69,6 +69,16 @@ bp->initrd_start =3D start_info->mod_start; bp->initrd_size =3D start_info->mod_len; } + + if ( dom->multiboot_blobs ) + { + start_info->mod_start =3D dom->multiboot_seg.vstart; + start_info->mod_len =3D dom->multiboot_seg.vend - dom->multiboot= _seg.vstart; + bp->initrd_start =3D start_info->mod_start; + bp->initrd_size =3D start_info->mod_len; + dom->flags |=3D SIF_MULTIBOOT_MOD; + } + bp->command_line =3D (dom->start_info_pfn << PAGE_SHIFT_IA64) + offsetof(start_info_t, cmd_line); if ( dom->cmdline ) diff -r 8f304c003af4 tools/libxc/xc_dom_x86.c --- a/tools/libxc/xc_dom_x86.c Wed Dec 09 10:59:31 2009 +0000 +++ b/tools/libxc/xc_dom_x86.c Sat Dec 12 00:18:05 2009 +0100 @@ -441,6 +441,13 @@ start_info->mod_len =3D dom->ramdisk_seg.vend - dom->ramdisk_seg= .vstart; } =20 + if ( dom->multiboot_blobs ) + { + start_info->mod_start =3D dom->multiboot_seg.vstart; + start_info->mod_len =3D dom->multiboot_seg.vend - dom->multiboot= _seg.vstart; + dom->flags |=3D SIF_MULTIBOOT_MOD; + } + if ( dom->cmdline ) { strncpy((char *)start_info->cmd_line, dom->cmdline, MAX_GUEST_CM= DLINE); @@ -481,6 +488,13 @@ start_info->mod_len =3D dom->ramdisk_seg.vend - dom->ramdisk_seg= .vstart; } =20 + if ( dom->multiboot_blobs ) + { + start_info->mod_start =3D dom->multiboot_seg.vstart; + start_info->mod_len =3D dom->multiboot_seg.vend - dom->multiboot= _seg.vstart; + dom->flags |=3D SIF_MULTIBOOT_MOD; + } + if ( dom->cmdline ) { strncpy((char *)start_info->cmd_line, dom->cmdline, MAX_GUEST_CM= DLINE); diff -r 8f304c003af4 xen/include/public/xen.h --- a/xen/include/public/xen.h Wed Dec 09 10:59:31 2009 +0000 +++ b/xen/include/public/xen.h Sat Dec 12 00:18:05 2009 +0100 @@ -584,8 +584,27 @@ /* 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= */ =20 +/* + * A multiboot module is a package containing modules like a multiboot m= odule + * array. The only difference is that the module list always ends with a= n entry + * with mod_start set to zero, to let the guest know how many modules ar= e + * provided. + */ +struct xen_multiboot_mod_list +{ + /* PHYSICAL address of first byte of the module */ + unsigned long mod_start; + /* PHYSICAL address of last byte of the module (inclusive) */ + unsigned long mod_end; + /* PHYSICAL address of zero-terminated command line */ + unsigned long cmdline; + /* Unused, must be zero */ + unsigned long pad; +}; + typedef struct dom0_vga_console_info { uint8_t video_type; /* DOM0_VGA_CONSOLE_??? */ #define XEN_VGATYPE_TEXT_MODE_3 0x03