[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH2] multiboot module support



Samuel Thibault, le Fri 11 Dec 2009 11:29:23 +0100, a écrit :
> 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 them
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 added to
libxc to load such list of modules, used by PV-GRUB.

Signed-Off-By: Samuel Thibault <samuel.thibault@xxxxxxxxxxxx>

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 @@
  
  /* 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 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_size, 
char *cmdline);
+void kexec(void *kernel, long kernel_size, char *cmdline, void *module, long 
module_size, int multiboot_number, void **multiboot_blobs, size_t 
*multiboot_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;
 }
 
-void kexec(void *kernel, long kernel_size, void *module, long module_size, 
char *cmdline)
+void kexec(void *kernel, long kernel_size, char *cmdline, void *module, long 
module_size, int multiboot_number, void **multiboot_blobs, size_t 
*multiboot_sizes, char **multiboot_cmdlines)
 {
     struct xc_dom_image *dom;
     int rc;
@@ -123,11 +123,11 @@
     dom = xc_dom_allocate(cmdline, features);
     dom->allocate = kexec_allocate;
 
-    dom->kernel_blob = kernel;
-    dom->kernel_size = kernel_size;
-
-    dom->ramdisk_blob = module;
-    dom->ramdisk_size = 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, 
multiboot_sizes, multiboot_cmdlines);
 
     dom->flags = 0;
     dom->console_evtchn = 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 @@
 
 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;
 
 kernel_t
 load_image (char *kernel, char *arg, kernel_t suggested_type,
@@ -196,6 +200,13 @@
     if (module_image)
         free(module_image);
     module_image = NULL;
+    multiboot_number = 0;
+    free(multiboot_blobs);
+    multiboot_blobs = NULL;
+    free(multiboot_sizes);
+    multiboot_sizes = NULL;
+    free(multiboot_cmdlines);
+    multiboot_cmdlines = 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 = NULL;
-    load_file (module, &module_image, &module_size);
-    if (module_arg)
-        free(module_arg);
-    module_arg = strdup(arg);
-    return ! errnum;
+    void *module_blob;
+    long module_size;
+
+    if (load_file (module, &module_blob, &module_size))
+        return 0;
+
+    multiboot_number++;
+    multiboot_blobs = realloc(multiboot_blobs, multiboot_number * 
sizeof(*multiboot_blobs));
+    multiboot_sizes = realloc(multiboot_sizes, multiboot_number * 
sizeof(*multiboot_sizes));
+    multiboot_cmdlines = realloc(multiboot_cmdlines, multiboot_number * 
sizeof(*multiboot_cmdlines));
+
+    multiboot_blobs[multiboot_number-1] = module_blob;
+    multiboot_sizes[multiboot_number-1] = module_size;
+    multiboot_cmdlines[multiboot_number-1] = arg;
+
+    return 1;
 }
 
 void
 pv_boot (void)
 {
-    kexec(kernel_image, kernel_size, module_image, module_size, kernel_arg);
+    kexec(kernel_image, kernel_size, kernel_arg, module_image, module_size, 
multiboot_number, multiboot_blobs, multiboot_sizes, multiboot_cmdlines);
 }
 
 /*
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;
 
     /* 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);
 
 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;
 }
 
+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 = number;
+    dom->multiboot_blobs = mems;
+    dom->multiboot_sizes = memsizes;
+    dom->multiboot_cmdlines = 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);
     }
 
+    /* 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 = 0;
+        size_t headers_size = 0;
+        size_t cmdlines_size = 0;
+
+        for (i = 0; i < dom->multiboot_number; i++) {
+            totsize += ROUNDUP(dom->multiboot_sizes[i], page_size);
+            headers_size += sizeof(*module);
+            cmdlines_size += strlen(dom->multiboot_cmdlines[i]) + 1;
+        }
+        headers_size += sizeof(*module);
+
+        totsize += ROUNDUP(headers_size + cmdlines_size, page_size);
+
+        if (xc_dom_alloc_segment(dom, &dom->multiboot_seg, "multiboot", 0, 
totsize))
+            goto err;
+        multibootmap = xc_dom_seg_to_ptr(dom, &dom->multiboot_seg);
+
+        module = multibootmap;
+        module_cmdline = multibootmap + headers_size;
+        module_blob = multibootmap + headers_size + cmdlines_size;
+
+        for (i = 0; i < dom->multiboot_number; i++) {
+            int len = strlen(dom->multiboot_cmdlines[i]) + 1;
+            memcpy(module_cmdline, dom->multiboot_cmdlines[i], len);
+            module->cmdline = (void*) module_cmdline - multibootmap
+                            + dom->multiboot_seg.vstart - dom->parms.virt_base;
+            module_cmdline += len;
+
+            memcpy(module_blob, dom->multiboot_blobs[i],
+                   dom->multiboot_sizes[i]);
+            module->mod_start = (void*) module_blob - multibootmap
+                            + dom->multiboot_seg.vstart - dom->parms.virt_base;
+            module->mod_end = module->mod_start + dom->multiboot_sizes[i] - 1;
+            module_blob += ROUNDUP(dom->multiboot_sizes[i], page_size);
+
+            module->pad = 0;
+
+            module++;
+        }
+        module->mod_start = 0;
+    }
+
     /* allocate other pages */
     if ( dom->arch_hooks->alloc_magic_pages(dom) != 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 = start_info->mod_start;
         bp->initrd_size = start_info->mod_len;
     }
+
+    if ( dom->multiboot_blobs )
+    {
+        start_info->mod_start = dom->multiboot_seg.vstart;
+        start_info->mod_len = dom->multiboot_seg.vend - 
dom->multiboot_seg.vstart;
+        bp->initrd_start = start_info->mod_start;
+        bp->initrd_size = start_info->mod_len;
+        dom->flags |= SIF_MULTIBOOT_MOD;
+    }
+
     bp->command_line = (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 = dom->ramdisk_seg.vend - dom->ramdisk_seg.vstart;
     }
 
+    if ( dom->multiboot_blobs )
+    {
+        start_info->mod_start = dom->multiboot_seg.vstart;
+        start_info->mod_len = dom->multiboot_seg.vend - 
dom->multiboot_seg.vstart;
+        dom->flags |= SIF_MULTIBOOT_MOD;
+    }
+
     if ( dom->cmdline )
     {
         strncpy((char *)start_info->cmd_line, dom->cmdline, MAX_GUEST_CMDLINE);
@@ -481,6 +488,13 @@
         start_info->mod_len = dom->ramdisk_seg.vend - dom->ramdisk_seg.vstart;
     }
 
+    if ( dom->multiboot_blobs )
+    {
+        start_info->mod_start = dom->multiboot_seg.vstart;
+        start_info->mod_len = dom->multiboot_seg.vend - 
dom->multiboot_seg.vstart;
+        dom->flags |= SIF_MULTIBOOT_MOD;
+    }
+
     if ( dom->cmdline )
     {
         strncpy((char *)start_info->cmd_line, dom->cmdline, MAX_GUEST_CMDLINE);
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 */
 
+/*
+ * A multiboot module is a package containing modules like a multiboot module
+ * array. The only difference is that the module list always ends with an entry
+ * with mod_start set to zero, to let the guest know how many modules are
+ * 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

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.