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

[XenPPC] [rfc][patch] dom0 elf32 loading to load a zImage



WANRNING: This is a total insomnia hack!

It has concerned me for quite some time that we will need to boot dom0
with a a ramdisk, and our current boot loading mechanisms do not
easily support it.  One solution could be a zImage.

I think someone outside of IBM was making noises about a generic elf
loader but I figured until that happens the following patch will do.

It loads and runs a 64 vmlinux or a 32 bit zImage and runs it.

BTW: uncompressing kernel under mambo is way faster

It requires a single line change in common code.
xen/arch/ppc/elf32.c is dubious but easier then the necessary
makefile majik.

Comments welcome.

-JX


diff -r d6a49aaee312 xen/arch/ppc/Makefile
--- a/xen/arch/ppc/Makefile     Mon Jun 26 16:08:27 2006 -0500
+++ b/xen/arch/ppc/Makefile     Tue Jun 27 15:19:09 2006 -0400
@@ -41,6 +41,8 @@ obj-$(builtin_dom0) += dom0.o
 obj-$(builtin_dom0) += dom0.o
 
 obj-y += firmware_image.o
+
+obj-y += elf32.o
 
 CFLAGS += -Wundef -Wpointer-arith
 CFLAGS += -Wmissing-prototypes -Wmissing-declarations -Wpacked
diff -r d6a49aaee312 xen/arch/ppc/domain_build.c
--- a/xen/arch/ppc/domain_build.c       Mon Jun 26 16:08:27 2006 -0500
+++ b/xen/arch/ppc/domain_build.c       Tue Jun 27 15:19:09 2006 -0400
@@ -30,8 +30,10 @@
 #include <asm/papr.h>
 #include "oftree.h"
 
+extern int parseelfimage_32(struct domain_setup_info *dsi);
+extern int loadelfimage_32(struct domain_setup_info *dsi);
+
 /* opt_dom0_mem: memory allocated to domain 0. */
-
 static unsigned int opt_dom0_mem;
 static void parse_dom0_mem(char *s)
 {
@@ -46,23 +48,16 @@ custom_param("dom0_mem", parse_dom0_mem)
 
 int elf_sanity_check(Elf_Ehdr *ehdr)
 {
-#if !defined(ELFSIZE)
-#error "Must pick a default ELFSIZE"
-#endif
-
     if (IS_ELF(*ehdr))
-#if ELFSIZE == 32
-        if (ehdr->e_ident[EI_CLASS] == ELFCLASS32
-            && ehdr->e_machine == EM_PPC)
-#elif ELFSIZE == 64
-        if (ehdr->e_ident[EI_CLASS] == ELFCLASS64
-             && ehdr->e_machine == EM_PPC64)
-#else
-#error "unknown ELFSIZE"
-#endif
+        /* we are happy with either */
+        if ((ehdr->e_ident[EI_CLASS] == ELFCLASS32
+             && ehdr->e_machine == EM_PPC)
+            || (ehdr->e_ident[EI_CLASS] == ELFCLASS64
+                && ehdr->e_machine == EM_PPC64)) {
             if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB
-                 && ehdr->e_type == ET_EXEC)
+                && ehdr->e_type == ET_EXEC)
                 return 1;
+        }
     printk("DOM0 image is not a Xen-compatible Elf image.\n");
     return 0;
 }
@@ -70,24 +65,20 @@ int elf_sanity_check(Elf_Ehdr *ehdr)
 /* adapted from common/elf.c */
 #define RM_MASK(a,l) ((a) & ((1UL << (l)) - 1))
 
-static inline int is_loadable_phdr(Elf_Phdr *phdr)
-{
-    return ((phdr->p_type == PT_LOAD) &&
-            ((phdr->p_flags & (PF_W|PF_X)) != 0));
-}
-
-static int rm_loadelfimage(struct domain_setup_info *dsi, ulong rma)
+static int rm_loadelfimage_64(struct domain_setup_info *dsi, ulong rma)
 {
     char *elfbase = (char *)dsi->image_addr;
-    Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr;
-    Elf_Phdr *phdr;
+    Elf64_Ehdr *ehdr = (Elf64_Ehdr *)dsi->image_addr;
+    Elf64_Phdr *phdr;
     int h;
   
     for (h = 0; h < ehdr->e_phnum; h++ ) 
     {
-        phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
-        if (!is_loadable_phdr(phdr))
+        phdr = (Elf64_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
+        if (!((phdr->p_type == PT_LOAD) &&
+             ((phdr->p_flags & (PF_W|PF_X)) != 0)))
             continue;
+
         if (phdr->p_filesz != 0)
             memcpy((char *)(rma + RM_MASK(phdr->p_paddr, 42)),
                    elfbase + phdr->p_offset, 
@@ -118,6 +109,10 @@ int construct_dom0(struct domain *d,
     ulong rma = d->arch.rma_base;
     start_info_t *si;
     ulong eomem;
+    int am64 = 1;
+    ulong msr;
+    ulong pc;
+    ulong r2;
 
     /* Sanity! */
     BUG_ON(d->domain_id != 0);
@@ -129,8 +124,11 @@ int construct_dom0(struct domain *d,
     dsi.image_addr = image_start;
     dsi.image_len  = image_len;
 
-    if ((rc = parseelfimage(&dsi)) != 0)
-        return rc;
+    if ((rc = parseelfimage(&dsi)) != 0) {
+        if ((rc = parseelfimage_32(&dsi)) != 0)
+            return rc;
+        am64 = 0;
+    }
 
     /* elf contains virtual addresses that can have the upper bits
      * masked while running in real mode, so we do the masking as well
@@ -186,10 +184,6 @@ int construct_dom0(struct domain *d,
     /* copy relative to Xen */
     dst += rma;
 
-
-    extern int firmware_image_start[0];
-    extern int firmware_image_size[0];
-
     ASSERT((dst - rma) + (ulong)firmware_image_size < eomem);
     printk("loading OFH: 0x%lx, RMA: 0x%lx\n", dst, dst - rma);
     memcpy((void *)dst, firmware_image_start, (ulong)firmware_image_size);
@@ -208,27 +202,58 @@ int construct_dom0(struct domain *d,
     memcpy((void *)dst, (void *)oftree, oftree_len);
 
     dst = ALIGN_UP(dst + oftree_len, PAGE_SIZE);
-    printk("loading Dom0: 0x%lx, in RMA:0x%lx\n", dst, dst - rma);
-    rm_loadelfimage(&dsi, dst);
-
-    ulong kbase = dst;
-
-    /* move dst to end of bss */
-    dst = ALIGN_UP(dsi.v_kernend + dst, PAGE_SIZE);
-    if ( initrd_len > 0 ) {
-        ASSERT( (dst - rma) + image_len < eomem );
-
-        printk("loading initrd: 0x%lx, 0x%lx\n", dst, initrd_len);
-        memcpy((void *)dst, (void *)initrd_start, initrd_len);
-
-        si->mod_start = dst - rma;
-        si->mod_len = image_len;
-
-        dst = ALIGN_UP(dst + initrd_len, PAGE_SIZE);
+
+    if (am64) {
+        ulong kbase;
+        ulong *fdesc;
+
+        printk("loading 64-bit Dom0: 0x%lx, in RMA:0x%lx\n", dst, dst - rma);
+        rm_loadelfimage_64(&dsi, dst);
+
+        kbase = dst;
+        /* move dst to end of bss */
+        dst = ALIGN_UP(dsi.v_kernend + dst, PAGE_SIZE);
+
+        if ( initrd_len > 0 ) {
+            ASSERT( (dst - rma) + image_len < eomem );
+
+            printk("loading initrd: 0x%lx, 0x%lx\n", dst, initrd_len);
+            memcpy((void *)dst, (void *)initrd_start, initrd_len);
+
+            si->mod_start = dst - rma;
+            si->mod_len = image_len;
+
+            dst = ALIGN_UP(dst + initrd_len, PAGE_SIZE);
+        } else {
+            printk("no initrd\n");
+            si->mod_start = 0;
+            si->mod_len = 0;
+        }
+        /* it may be a function descriptor */
+        fdesc = (ulong *)(dsi.v_kernstart + dsi.v_kernentry + kbase);
+
+        if (fdesc[2] == 0
+            && ((fdesc[0] >= dsi.v_kernstart)
+                && (fdesc[0] < dsi.v_kernend)) /* text entry is in range */
+            && ((fdesc[1] >= dsi.v_kernstart)  /* toc can be > image */
+                && (fdesc[1] < (dsi.v_kernend + (0x7fff * sizeof (ulong)))))) {
+            /* it is almost certainly a function descriptor */
+            pc = RM_MASK(fdesc[0], 42) + kbase - rma;
+            r2 = RM_MASK(fdesc[1], 42) + kbase - rma;
+        } else {
+            pc = ((ulong)fdesc) - rma;
+            r2 = 0;
+        }
+        msr = MSR_SF;
     } else {
-        printk("no initrd\n");
-        si->mod_start = 0;
-        si->mod_len = 0;
+        printk("loading 32-bit Dom0: 0x%lx, in RMA:0x%lx\n",
+               dsi.v_kernstart + rma, dsi.v_kernstart);
+        dsi.v_start = rma;
+        loadelfimage_32(&dsi);
+
+        pc = dsi.v_kernentry;
+        r2 = 0;
+        msr = 0;
     }
 
     v->arch.ctxt.gprs[3] = si->mod_start;
@@ -238,26 +263,7 @@ int construct_dom0(struct domain *d,
     if ( cmdline != NULL )
         strncpy((char *)si->cmd_line, cmdline, sizeof(si->cmd_line)-1);
 
-    /* set up the MSR how we like it */
-    v->arch.ctxt.msr = MSR_SF;
-
-    ulong *fdesc = (ulong *)(dsi.v_kernstart + dsi.v_kernentry + kbase);
-    ulong pc;
-    ulong r2;
-
-    if (fdesc[2] == 0  /* could be a true function descriptor */
-        && ((fdesc[0] >= dsi.v_kernstart)
-            && (fdesc[0] < dsi.v_kernend)) /* text entry is in range */
-        && ((fdesc[1] >= dsi.v_kernstart)  /* toc can be greater than image */
-            && (fdesc[1] < (dsi.v_kernend + (0x7fff * sizeof (ulong)))))) {
-        /* it is almost certainly a function descriptor */
-        pc = RM_MASK(fdesc[0], 42) + kbase - rma;
-        r2 = RM_MASK(fdesc[1], 42) + kbase - rma;
-    } else {
-        pc = ((ulong)fdesc) - rma;
-        r2 = 0;
-    }
-
+    v->arch.ctxt.msr = msr;
     v->arch.ctxt.pc = pc;
     v->arch.ctxt.gprs[2] = r2;
 
diff -r d6a49aaee312 xen/arch/ppc/oftree.h
--- a/xen/arch/ppc/oftree.h     Mon Jun 26 16:08:27 2006 -0500
+++ b/xen/arch/ppc/oftree.h     Tue Jun 27 15:19:09 2006 -0400
@@ -27,4 +27,7 @@ extern int ofd_dom0_fixup(
 extern int ofd_dom0_fixup(
     struct domain *d, ulong oftree, start_info_t *si, ulong dst);
 
+extern int firmware_image_start[0];
+extern int firmware_image_size[0];
+
 #endif  /* #ifndef _OFTREE_H */
diff -r d6a49aaee312 xen/common/elf.c
--- a/xen/common/elf.c  Mon Jun 26 16:08:27 2006 -0500
+++ b/xen/common/elf.c  Tue Jun 27 15:19:09 2006 -0400
@@ -23,7 +23,7 @@ int parseelfimage(struct domain_setup_in
     Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr;
     Elf_Phdr *phdr;
     Elf_Shdr *shdr;
-    unsigned long kernstart = ~0UL, kernend=0UL, vaddr, virt_base, elf_pa_off;
+    Elf_Addr kernstart = -1, kernend = 0, vaddr, virt_base, elf_pa_off;
     char *shstrtab, *guestinfo=NULL, *p;
     char *elfbase = (char *)dsi->image_addr;
     int h, virt_base_defined, elf_pa_off_defined;
diff -r d6a49aaee312 xen/include/asm-ppc/config.h
--- a/xen/include/asm-ppc/config.h      Mon Jun 26 16:08:27 2006 -0500
+++ b/xen/include/asm-ppc/config.h      Tue Jun 27 15:19:09 2006 -0400
@@ -52,7 +52,9 @@ extern char __bss_start[];
 #define CONFIG_PCI 1
 #define NR_CPUS 1
 
+#ifndef ELFSIZE
 #define ELFSIZE 64
+#endif
 
 #define asmlinkage
 
diff -r d6a49aaee312 xen/arch/ppc/elf32.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/ppc/elf32.c      Tue Jun 27 15:19:09 2006 -0400
@@ -0,0 +1,5 @@
+#define parseelfimage parseelfimage_32
+#define loadelfimage loadelfimage_32
+#define ELFSIZE 32
+#include "../../common/elf.c"
+

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


 


Rackspace

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