debuggers.hg

changeset 20653:5f076dbdab6c

domain builder: 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@ens-lyon.org>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Dec 11 08:44:33 2009 +0000 (2009-12-11)
parents 295e77eed8c9
children 9575425fdebd
files stubdom/grub.patches/99minios stubdom/grub/config.h stubdom/grub/kexec.c stubdom/grub/mini-os.c xen/include/public/xen.h
line diff
     1.1 --- a/stubdom/grub.patches/99minios	Fri Dec 11 08:42:28 2009 +0000
     1.2 +++ b/stubdom/grub.patches/99minios	Fri Dec 11 08:44:33 2009 +0000
     1.3 @@ -151,6 +151,14 @@ Index: grub/stage2/builtins.c
     1.4   
     1.5   /* print */
     1.6   static int
     1.7 +@@ -2910,6 +2910,7 @@
     1.8 +   switch (kernel_type)
     1.9 +     {
    1.10 +     case KERNEL_TYPE_MULTIBOOT:
    1.11 ++    case KERNEL_TYPE_PV:
    1.12 +       if (mb_cmdline + len + 1 > (char *) MB_CMDLINE_BUF + MB_CMDLINE_BUFLEN)
    1.13 + 	{
    1.14 + 	  errnum = ERR_WONT_FIT;
    1.15  @@ -3776,6 +3802,7 @@
    1.16   };
    1.17   
     2.1 --- a/stubdom/grub/config.h	Fri Dec 11 08:42:28 2009 +0000
     2.2 +++ b/stubdom/grub/config.h	Fri Dec 11 08:44:33 2009 +0000
     2.3 @@ -5,7 +5,7 @@
     2.4  #define debug _debug
     2.5  #define grub_halt(a) do_exit()
     2.6  #define printf grub_printf
     2.7 -void kexec(void *kernel, long kernel_size, void *module, long module_size, char *cmdline);
     2.8 +void kexec(void *kernel, long kernel_size, void *module, long module_size, char *cmdline, unsigned long flags);
     2.9  struct fbfront_dev *fb_open(void *fb, int width, int height, int depth);
    2.10  void fb_close(void);
    2.11  void pv_boot (void);
     3.1 --- a/stubdom/grub/kexec.c	Fri Dec 11 08:42:28 2009 +0000
     3.2 +++ b/stubdom/grub/kexec.c	Fri Dec 11 08:44:33 2009 +0000
     3.3 @@ -103,7 +103,7 @@ int kexec_allocate(struct xc_dom_image *
     3.4      return 0;
     3.5  }
     3.6  
     3.7 -void kexec(void *kernel, long kernel_size, void *module, long module_size, char *cmdline)
     3.8 +void kexec(void *kernel, long kernel_size, void *module, long module_size, char *cmdline, unsigned long flags)
     3.9  {
    3.10      struct xc_dom_image *dom;
    3.11      int rc;
    3.12 @@ -129,7 +129,7 @@ void kexec(void *kernel, long kernel_siz
    3.13      dom->ramdisk_blob = module;
    3.14      dom->ramdisk_size = module_size;
    3.15  
    3.16 -    dom->flags = 0;
    3.17 +    dom->flags = flags;
    3.18      dom->console_evtchn = start_info.console.domU.evtchn;
    3.19      dom->xenstore_evtchn = start_info.store_evtchn;
    3.20  
     4.1 --- a/stubdom/grub/mini-os.c	Fri Dec 11 08:42:28 2009 +0000
     4.2 +++ b/stubdom/grub/mini-os.c	Fri Dec 11 08:44:33 2009 +0000
     4.3 @@ -173,6 +173,8 @@ load_file(char *name, void **ptr, long *
     4.4  void *kernel_image, *module_image;
     4.5  long  kernel_size, module_size;
     4.6  char *kernel_arg, *module_arg;
     4.7 +void *multiboot_next_module;
     4.8 +struct xen_multiboot_mod_list *multiboot_next_module_header;
     4.9  
    4.10  kernel_t
    4.11  load_image (char *kernel, char *arg, kernel_t suggested_type,
    4.12 @@ -196,6 +198,8 @@ load_initrd (char *initrd)
    4.13      if (module_image)
    4.14          free(module_image);
    4.15      module_image = NULL;
    4.16 +    multiboot_next_module = NULL;
    4.17 +    multiboot_next_module_header = NULL;
    4.18      load_file (initrd, &module_image, &module_size);
    4.19      return ! errnum;
    4.20  }
    4.21 @@ -203,20 +207,76 @@ load_initrd (char *initrd)
    4.22  int
    4.23  load_module (char *module, char *arg)
    4.24  {
    4.25 -    if (module_image)
    4.26 +    void *new_module, *new_module_image;
    4.27 +    long new_module_size, rounded_new_module_size;
    4.28 +
    4.29 +    if (load_file (module, &new_module, &new_module_size))
    4.30 +        return 0;
    4.31 +    if (strlen(arg) >= PAGE_SIZE) {
    4.32 +        /* Too big module command line */
    4.33 +        errnum = ERR_WONT_FIT;
    4.34 +        return 0;
    4.35 +    }
    4.36 +    rounded_new_module_size = (new_module_size + PAGE_SIZE - 1) & PAGE_MASK;
    4.37 +
    4.38 +    if (module_image && !multiboot_next_module_header) {
    4.39 +        /* Initrd already loaded, drop it */
    4.40          free(module_image);
    4.41 -    module_image = NULL;
    4.42 -    load_file (module, &module_image, &module_size);
    4.43 -    if (module_arg)
    4.44 -        free(module_arg);
    4.45 -    module_arg = strdup(arg);
    4.46 -    return ! errnum;
    4.47 +        if (module_arg)
    4.48 +            free(module_arg);
    4.49 +        module_image = NULL;
    4.50 +    }
    4.51 +    if (!module_image)
    4.52 +        /* Reserve one page for the header */
    4.53 +        multiboot_next_module = (void*) PAGE_SIZE;
    4.54 +
    4.55 +    /* Allocate more room for the new module plus its arg */
    4.56 +    new_module_image = realloc(module_image,
    4.57 +            (multiboot_next_module - module_image) + rounded_new_module_size + PAGE_SIZE);
    4.58 +
    4.59 +    /* Update pointers */
    4.60 +    multiboot_next_module += new_module_image - module_image;
    4.61 +    multiboot_next_module_header = (void*) multiboot_next_module_header + (new_module_image - module_image);
    4.62 +    module_image = new_module_image;
    4.63 +
    4.64 +    if ((void*) (multiboot_next_module_header+1) - module_image > PAGE_SIZE) {
    4.65 +        /* Too many modules */
    4.66 +        ERR_WONT_FIT;
    4.67 +        return 0;
    4.68 +    }
    4.69 +
    4.70 +    /* Copy module */
    4.71 +    memcpy(multiboot_next_module, new_module, new_module_size);
    4.72 +    multiboot_next_module_header->mod_start = multiboot_next_module - module_image;
    4.73 +    multiboot_next_module_header->mod_end = multiboot_next_module_header->mod_start + new_module_size - 1;
    4.74 +    multiboot_next_module += rounded_new_module_size;
    4.75 +
    4.76 +    /* Copy cmdline */
    4.77 +    strcpy(multiboot_next_module, arg);
    4.78 +    multiboot_next_module_header->cmdline = multiboot_next_module - module_image;
    4.79 +    multiboot_next_module += PAGE_SIZE;
    4.80 +
    4.81 +    /* Pad */
    4.82 +    multiboot_next_module_header->pad = 0;
    4.83 +
    4.84 +    multiboot_next_module_header++;
    4.85 +
    4.86 +    return 1;
    4.87  }
    4.88  
    4.89  void
    4.90  pv_boot (void)
    4.91  {
    4.92 -    kexec(kernel_image, kernel_size, module_image, module_size, kernel_arg);
    4.93 +    unsigned long flags = 0;
    4.94 +    if (multiboot_next_module_header) {
    4.95 +        /* Termination entry */
    4.96 +        multiboot_next_module_header->mod_start = 0;
    4.97 +        /* Total size */
    4.98 +        module_size = multiboot_next_module - module_image;
    4.99 +        /* It's a multiboot module */
   4.100 +        flags |= SIF_MULTIBOOT_MOD;
   4.101 +    }
   4.102 +    kexec(kernel_image, kernel_size, module_image, module_size, kernel_arg, flags);
   4.103  }
   4.104  
   4.105  /*
     5.1 --- a/xen/include/public/xen.h	Fri Dec 11 08:42:28 2009 +0000
     5.2 +++ b/xen/include/public/xen.h	Fri Dec 11 08:44:33 2009 +0000
     5.3 @@ -584,8 +584,35 @@ typedef struct start_info start_info_t;
     5.4  /* These flags are passed in the 'flags' field of start_info_t. */
     5.5  #define SIF_PRIVILEGED    (1<<0)  /* Is the domain privileged? */
     5.6  #define SIF_INITDOMAIN    (1<<1)  /* Is this the initial control domain? */
     5.7 +#define SIF_MULTIBOOT_MOD (1<<2)  /* Is mod_start a multiboot module? */
     5.8  #define SIF_PM_MASK       (0xFF<<8) /* reserve 1 byte for xen-pm options */
     5.9  
    5.10 +/*
    5.11 + * A multiboot module is a package containing modules very similar to a
    5.12 + * multiboot module array. The only differences are:
    5.13 + * - the array of module descriptors is by convention simply at the beginning
    5.14 + *   of the multiboot module,
    5.15 + * - addresses in the module descriptors are based on the beginning of the
    5.16 + *   multiboot module,
    5.17 + * - the number of modules is determined by a termination descriptor that has
    5.18 + *   mod_start == 0.
    5.19 + *
    5.20 + * This permits to both build it statically and reference it in a configuration
    5.21 + * file, and let the PV guest easily rebase the addresses to virtual addresses
    5.22 + * and at the same time count the number of modules.
    5.23 + */
    5.24 +struct xen_multiboot_mod_list
    5.25 +{
    5.26 +    /* Address of first byte of the module */
    5.27 +    uint32_t mod_start;
    5.28 +    /* Address of last byte of the module (inclusive) */
    5.29 +    uint32_t mod_end;
    5.30 +    /* Address of zero-terminated command line */
    5.31 +    uint32_t cmdline;
    5.32 +    /* Unused, must be zero */
    5.33 +    uint32_t pad;
    5.34 +};
    5.35 +
    5.36  typedef struct dom0_vga_console_info {
    5.37      uint8_t video_type; /* DOM0_VGA_CONSOLE_??? */
    5.38  #define XEN_VGATYPE_TEXT_MODE_3 0x03