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
|