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
|