[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |