This adds vmm support to kexec-tool for ia64. This is annalogous
to the same feature that is present in the latest version of elilo.
It is a method of booting a vmm (hypervisor) such as Xen.
Essentially it works as follows.

* If the --vmm argument is not provided, then the kernel is booted as normal,
  no changes
* Else, the image specified by --vmm is placed loaded into the elf
  segments, where the Linux kernel image would otherwise have gone.
  And the Linux kernel image, allong with its length is loaded into a
  seprate segment, and passed as new entry at the end of the boot parameters.
  This is somewhat similar to how initramfs/initramd images are passed
  to a booting kernel, and can work in conjunction with that feature.
  On boot (or in this case on kexec) the vmm (hypervisor) will be
  loaded instead of a Linux kernel, and the hypervisor will then load up
  the Linux kernel as it sees fit.
  
This is needed in order for kexec from Xen to Xen, using the
port of kexec to Xen that I am working on, to work.

I am not entirely fond of this design, and i think that developing
an ia64 variant of multiboot would be much nicer. However it is
an existing method that is currently in widespread use through
its incarntation in elilo. And if multiboot is added in future,
it can be done as a separate boot method, and thus orthogonal to this
patch.

In order to use this code a number of other changes are needed,
in particular:

  1. Xen and the corresponding Linux Kernel needs to be patched with
     the port of kexec to ia64-xen that I have been working on.
     I will post the latest version of these patches to xen-devel
     shortly.

  2. The currently hardcoded PAGE_OFFSET value in purgatory needs
     to be changed from the Linux value to the Xen value. I will
     post a very hackish, definately not to be released, patch
     after this patch which includes a comment that explains this problem
     more clearly.

Also, xen->linux and linux->xen is still very much work in progress due
to the problem described at the following link
http://permalink.gmane.org/gmane.linux.ports.ia64/14995

However, from an infastructure point of view I think it would be good to
apply this code, so that kexec-tool is one step closer to being able to
support vmms (hypervisors). The patch does not alter any existing
behaviour, it just adds a new feature. Bugs asside, the only real danger
seems to be confusion for end-users, perhaps we could comment out the help
text to hide the feature from the lay user, or attach a big fat warning to it.

Signed-Off-By: Simon Horman <[EMAIL PROTECTED]>

Index: kexec-tools-vmm/kexec/arch/ia64/kexec-elf-ia64.c
===================================================================
--- kexec-tools-vmm.orig/kexec/arch/ia64/kexec-elf-ia64.c       2006-09-21 
12:08:20.000000000 +0900
+++ kexec-tools-vmm/kexec/arch/ia64/kexec-elf-ia64.c    2006-09-21 
12:09:10.000000000 +0900
@@ -79,7 +79,8 @@
        printf(
                "    --command-line=STRING Set the kernel command line to 
STRING.\n"
                "    --append=STRING       Set the kernel command line to 
STRING.\n"
-               "    --initrd=FILE       Use FILE as the kernel's initial 
ramdisk.\n");
+               "    --initrd=FILE         Use FILE as the kernel's initial 
ramdisk.\n"
+               "    --vmm=FILE            Use FILE as the kernel image for a 
virtual machine monitor (aka hypervisor)\n");
 }
 
 /* Move the crash kerenl physical offset to reserved region
@@ -108,12 +109,12 @@
        struct kexec_info *info)
 {
        struct mem_ehdr ehdr;
-       const char *command_line, *ramdisk=0;
+       const char *command_line, *ramdisk=0, *vmm=0, *kernel_buf;
        char *ramdisk_buf = NULL;
-       off_t ramdisk_size = 0;
+       off_t ramdisk_size = 0, kernel_size;
        unsigned long command_line_len;
        unsigned long entry, max_addr, gp_value;
-       unsigned long command_line_base, ramdisk_base;
+       unsigned long command_line_base, ramdisk_base, image_base;
        unsigned long efi_memmap_base, efi_memmap_size;
        unsigned long boot_param_base;
        int result;
@@ -121,11 +122,13 @@
        char *efi_memmap_buf, *boot_param;
 #define OPT_APPEND     (OPT_ARCH_MAX+0)
 #define OPT_RAMDISK    (OPT_ARCH_MAX+1)
+#define OPT_VMM                (OPT_ARCH_MAX+2)
        static const struct option options[] = {
                KEXEC_ARCH_OPTIONS
                {"command-line", 1, 0, OPT_APPEND},
                {"append",       1, 0, OPT_APPEND},
                {"initrd",       1, 0, OPT_RAMDISK},
+               {"vmm",          1, 0, OPT_VMM},
                {0, 0, 0, 0},
        };
 
@@ -148,6 +151,9 @@
                case OPT_RAMDISK:
                        ramdisk = optarg;
                        break;
+               case OPT_VMM:
+                       vmm = optarg;
+                       break;
                }
        }
        command_line_len = 0;
@@ -155,8 +161,15 @@
                command_line_len = strlen(command_line) + 16;
        }
 
+       if (vmm)
+               kernel_buf = slurp_decompress_file(vmm, &kernel_size);
+       else {
+               kernel_buf = buf;
+               kernel_size = len;
+       }
+
        /* Parse the Elf file */
-       result = build_elf_exec_info(buf, len, &ehdr);
+       result = build_elf_exec_info(kernel_buf, kernel_size, &ehdr);
        if (result < 0) {
                fprintf(stderr, "ELF parse failed\n");
                free_elf_info(&ehdr);
@@ -166,7 +179,8 @@
        if (info->kexec_flags & KEXEC_ON_CRASH ) {
                if ((mem_min == 0x00) && (mem_max = ULONG_MAX)) {
                        fprintf(stderr, "Failed to find crash kernel region in 
/proc/iomem\n");
-               return -1;
+                       free_elf_info(&ehdr);
+                       return -1;
                }
                move_loaded_segments(info, &ehdr);
        }
@@ -218,7 +232,7 @@
                char *cmdline = xmalloc(command_line_len);
                strcpy(cmdline, command_line);
 
-       if (info->kexec_flags & KEXEC_ON_CRASH) {
+               if (info->kexec_flags & KEXEC_ON_CRASH) {
                        char buf[128];
                        sprintf(buf," max_addr=%lluM min_addr=%lluM",
                                        mem_max>>20, mem_min>>20);
@@ -249,6 +263,15 @@
                                &ramdisk_size, sizeof(long));
        }
 
+       if (vmm) {
+               image_base = add_buffer(info, buf, len, len,
+                               getpagesize(), 0, max_addr, -1);
+               elf_rel_set_symbol(&info->rhdr, "__vmcode_base",
+                               &image_base, sizeof(long));
+               elf_rel_set_symbol(&info->rhdr, "__vmcode_size",
+                               &len, sizeof(long));
+       }
+
        gp_value = info->rhdr.rel_addr + 0x200000;
         elf_rel_set_symbol(&info->rhdr, "__gp_value", &gp_value,
                         sizeof(gp_value));
Index: kexec-tools-vmm/purgatory/arch/ia64/entry.S
===================================================================
--- kexec-tools-vmm.orig/purgatory/arch/ia64/entry.S    2006-09-21 
12:08:20.000000000 +0900
+++ kexec-tools-vmm/purgatory/arch/ia64/entry.S 2006-09-21 12:08:40.000000000 
+0900
@@ -42,7 +42,7 @@
        alloc r2 = ar.pfs, 0, 0, 2, 0
        ;;
        mov out0=r28
-       movl out1=__ramdisk_base;;
+       movl out1=__vmcode_base;
        br.call.sptk.many b0=ia64_env_setup
        movl r10=__kernel_entry;;
        ld8 r14=[r10];;
@@ -57,6 +57,8 @@
 .endp   purgatory_start
 
 DECLARE_DATA8(__kernel_entry)
+DECLARE_DATA8(__vmcode_base)
+DECLARE_DATA8(__vmcode_size)
 DECLARE_DATA8(__ramdisk_base)
 DECLARE_DATA8(__ramdisk_size)
 DECLARE_DATA8(__command_line)
Index: kexec-tools-vmm/purgatory/arch/ia64/purgatory-ia64.c
===================================================================
--- kexec-tools-vmm.orig/purgatory/arch/ia64/purgatory-ia64.c   2006-09-21 
12:08:36.000000000 +0900
+++ kexec-tools-vmm/purgatory/arch/ia64/purgatory-ia64.c        2006-09-21 
12:08:40.000000000 +0900
@@ -104,6 +104,9 @@
         uint64_t fpswa;            /* physical address of the fpswa interface 
*/
         uint64_t initrd_start;
         uint64_t initrd_size;
+
+        uint64_t vmcode_start;
+        uint64_t vmcode_size;
 };
 
 typedef struct {
@@ -122,6 +125,8 @@
 };
 
 struct kexec_boot_params {
+       uint64_t vmcode_base;
+       uint64_t vmcode_size;
        uint64_t ramdisk_base;
        uint64_t ramdisk_size;
        uint64_t command_line;
@@ -273,6 +278,8 @@
        new_boot_param->console_info.orig_y = 0;
        new_boot_param->initrd_start = params->ramdisk_base;
        new_boot_param->initrd_size =  params->ramdisk_size;
+       new_boot_param->vmcode_start = params->vmcode_base;
+       new_boot_param->vmcode_size =  params->vmcode_size;
 }
 
 /* This function can be used to execute after the SHA256 verification. */

--

-- 
Horms
  H: http://www.vergenet.net/~horms/
  W: http://www.valinux.co.jp/en/

_______________________________________________
fastboot mailing list
[email protected]
https://lists.osdl.org/mailman/listinfo/fastboot

Reply via email to