diff options
author | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-07-14 14:26:03 +0000 |
---|---|---|
committer | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-07-14 14:26:03 +0000 |
commit | 49f78c77c25611a41c26766e6bf32739b39d7f25 (patch) | |
tree | 2df219c4fbfea91acd7d057f24aebf3b9d119f69 | |
parent | a5af4e1ea589d8ad1c7485b12d756297cd12d536 (diff) | |
download | xen-49f78c77c25611a41c26766e6bf32739b39d7f25.tar.gz xen-49f78c77c25611a41c26766e6bf32739b39d7f25.tar.bz2 xen-49f78c77c25611a41c26766e6bf32739b39d7f25.zip |
bitkeeper revision 1.1082 (40f5427bJQEFqTSPn7NWKEkiQ-CC9g)
Allow loading of kernel images with virtual-memory base different
from kernel-image load base.
-rw-r--r-- | linux-2.4.26-xen-sparse/arch/xen/kernel/head.S | 2 | ||||
-rw-r--r-- | linux-2.4.26-xen-sparse/arch/xen/kernel/setup.c | 6 | ||||
-rw-r--r-- | linux-2.4.26-xen-sparse/arch/xen/vmlinux.lds | 2 | ||||
-rw-r--r-- | tools/libxc/xc_linux_build.c | 62 | ||||
-rw-r--r-- | xen/arch/x86/domain.c | 30 | ||||
-rw-r--r-- | xen/common/elf.c | 20 | ||||
-rw-r--r-- | xen/include/xen/elf.h | 5 |
7 files changed, 81 insertions, 46 deletions
diff --git a/linux-2.4.26-xen-sparse/arch/xen/kernel/head.S b/linux-2.4.26-xen-sparse/arch/xen/kernel/head.S index 2d9379a15b..cf5aa93fce 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/kernel/head.S +++ b/linux-2.4.26-xen-sparse/arch/xen/kernel/head.S @@ -1,6 +1,6 @@ .section __xen_guest - .asciz "GUEST_OS=linux,GUEST_VER=2.4,XEN_VER=1.3" + .asciz "GUEST_OS=linux,GUEST_VER=2.4,XEN_VER=1.3,VIRT_BASE=0xC0000000" .text #include <linux/config.h> diff --git a/linux-2.4.26-xen-sparse/arch/xen/kernel/setup.c b/linux-2.4.26-xen-sparse/arch/xen/kernel/setup.c index 42ef543546..039fdaf162 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/kernel/setup.c +++ b/linux-2.4.26-xen-sparse/arch/xen/kernel/setup.c @@ -205,6 +205,8 @@ void __init setup_arch(char **cmdline_p) extern const struct exception_table_entry __start___ex_table[]; extern const struct exception_table_entry __stop___ex_table[]; + extern char _stext; + /* Force a quick death if the kernel panics. */ extern int panic_timeout; if ( panic_timeout == 0 ) @@ -314,7 +316,9 @@ void __init setup_arch(char **cmdline_p) */ bootmap_size = init_bootmem(start_pfn, max_low_pfn); free_bootmem(0, PFN_PHYS(max_low_pfn)); - reserve_bootmem(0, PFN_PHYS(start_pfn) + bootmap_size + PAGE_SIZE-1); + reserve_bootmem(__pa(&_stext), + PFN_PHYS(start_pfn) + bootmap_size + PAGE_SIZE-1 - + __pa(&_stext)); #ifdef CONFIG_BLK_DEV_INITRD if ( start_info.mod_start != 0 ) diff --git a/linux-2.4.26-xen-sparse/arch/xen/vmlinux.lds b/linux-2.4.26-xen-sparse/arch/xen/vmlinux.lds index 6bd3ec3c04..258de1a67f 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/vmlinux.lds +++ b/linux-2.4.26-xen-sparse/arch/xen/vmlinux.lds @@ -6,7 +6,7 @@ OUTPUT_ARCH(i386) ENTRY(_start) SECTIONS { - . = 0xC0000000 + 0x000000; + . = 0xC0000000 + 0x100000; _text = .; /* Text and read-only data */ .text : { *(.text) diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index c2228b5e9e..e2edd81e17 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -5,6 +5,7 @@ #include "xc_private.h" #define ELFSIZE 32 #include "xc_elf.h" +#include <stdlib.h> #include <zlib.h> #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED) @@ -13,11 +14,12 @@ #define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK) #define round_pgdown(_p) ((_p)&PAGE_MASK) -static int readelfimage_base_and_size(char *elfbase, - unsigned long elfsize, - unsigned long *pkernstart, - unsigned long *pkernend, - unsigned long *pkernentry); +static int parseelfimage(char *elfbase, + unsigned long elfsize, + unsigned long *pvirtstart, + unsigned long *pkernstart, + unsigned long *pkernend, + unsigned long *pkernentry); static int loadelfimage(char *elfbase, void *pmh, unsigned long *parray, unsigned long vstart); @@ -109,11 +111,17 @@ static int setup_guestos(int xc_handle, unsigned long vpt_end; unsigned long v_end; - rc = readelfimage_base_and_size(image, image_size, - &vkern_start, &vkern_end, &vkern_entry); + rc = parseelfimage(image, image_size, &v_start, + &vkern_start, &vkern_end, &vkern_entry); if ( rc != 0 ) goto error_out; + if ( (v_start & (PAGE_SIZE-1)) != 0 ) + { + PERROR("Guest OS must load to a page boundary.\n"); + goto error_out; + } + /* * Why do we need this? The number of page-table frames depends on the * size of the bootstrap address space. But the size of the address space @@ -123,7 +131,6 @@ static int setup_guestos(int xc_handle, */ for ( nr_pt_pages = 2; ; nr_pt_pages++ ) { - v_start = vkern_start & ~((1<<22)-1); vinitrd_start = round_pgup(vkern_end); vinitrd_end = vinitrd_start + initrd_len; vphysmap_start = round_pgup(vinitrd_end); @@ -137,18 +144,11 @@ static int setup_guestos(int xc_handle, v_end = (vstack_end + (1<<22)-1) & ~((1<<22)-1); if ( (v_end - vstack_end) < (512 << 10) ) v_end += 1 << 22; /* Add extra 4MB to get >= 512kB padding. */ - if ( (((v_end - v_start) >> L2_PAGETABLE_SHIFT) + 1) <= nr_pt_pages ) + if ( (((v_end - v_start + ((1<<L2_PAGETABLE_SHIFT)-1)) >> + L2_PAGETABLE_SHIFT) + 1) <= nr_pt_pages ) break; } - if ( (v_end - v_start) > (nr_pages * PAGE_SIZE) ) - { - printf("Initial guest OS requires too much space\n" - "(%luMB is greater than %luMB limit)\n", - (v_end-v_start)>>20, (nr_pages<<PAGE_SHIFT)>>20); - goto error_out; - } - printf("VIRTUAL MEMORY ARRANGEMENT:\n" " Loaded kernel: %08lx->%08lx\n" " Init. ramdisk: %08lx->%08lx\n" @@ -166,6 +166,14 @@ static int setup_guestos(int xc_handle, v_start, v_end); printf(" ENTRY ADDRESS: %08lx\n", vkern_entry); + if ( (v_end - v_start) > (nr_pages * PAGE_SIZE) ) + { + printf("Initial guest OS requires too much space\n" + "(%luMB is greater than %luMB limit)\n", + (v_end-v_start)>>20, (nr_pages<<PAGE_SHIFT)>>20); + goto error_out; + } + if ( (pm_handle = init_pfn_mapper((domid_t)dom)) == NULL ) goto error_out; @@ -541,17 +549,18 @@ static inline int is_loadable_phdr(Elf_Phdr *phdr) ((phdr->p_flags & (PF_W|PF_X)) != 0)); } -static int readelfimage_base_and_size(char *elfbase, - unsigned long elfsize, - unsigned long *pkernstart, - unsigned long *pkernend, - unsigned long *pkernentry) +static int parseelfimage(char *elfbase, + unsigned long elfsize, + unsigned long *pvirtstart, + unsigned long *pkernstart, + unsigned long *pkernend, + unsigned long *pkernentry) { Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase; Elf_Phdr *phdr; Elf_Shdr *shdr; unsigned long kernstart = ~0UL, kernend=0UL; - char *shstrtab, *guestinfo; + char *shstrtab, *guestinfo, *p; int h; if ( !IS_ELF(*ehdr) ) @@ -588,7 +597,9 @@ static int readelfimage_base_and_size(char *elfbase, shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff + (h*ehdr->e_shentsize)); if ( strcmp(&shstrtab[shdr->sh_name], "__xen_guest") != 0 ) continue; + guestinfo = elfbase + shdr->sh_offset; + if ( (strstr(guestinfo, "GUEST_OS=linux") == NULL) || (strstr(guestinfo, "XEN_VER=1.3") == NULL) ) { @@ -596,6 +607,11 @@ static int readelfimage_base_and_size(char *elfbase, ERROR("Actually saw: '%s'", guestinfo); return -EINVAL; } + + *pvirtstart = kernstart; + if ( (p = strstr(guestinfo, "VIRT_BASE=")) != NULL ) + *pvirtstart = strtoul(p+10, &p, 0); + break; } if ( h == ehdr->e_shnum ) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 83eea289aa..866b4d0016 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -565,11 +565,17 @@ int construct_dom0(struct domain *p, * We'll have to revisit this if we ever support PAE (64GB). */ - rc = readelfimage_base_and_size(image_start, image_len, - &vkern_start, &vkern_end, &vkern_entry); + rc = parseelfimage(image_start, image_len, &v_start, + &vkern_start, &vkern_end, &vkern_entry); if ( rc != 0 ) return rc; + if ( (v_start & (PAGE_SIZE-1)) != 0 ) + { + printk("Initial guest OS must load to a page boundary.\n"); + return -EINVAL; + } + /* * Why do we need this? The number of page-table frames depends on the * size of the bootstrap address space. But the size of the address space @@ -579,7 +585,6 @@ int construct_dom0(struct domain *p, */ for ( nr_pt_pages = 2; ; nr_pt_pages++ ) { - v_start = vkern_start & ~((1<<22)-1); vinitrd_start = round_pgup(vkern_end); vinitrd_end = vinitrd_start + initrd_len; vphysmap_start = round_pgup(vinitrd_end); @@ -593,18 +598,11 @@ int construct_dom0(struct domain *p, v_end = (vstack_end + (1<<22)-1) & ~((1<<22)-1); if ( (v_end - vstack_end) < (512 << 10) ) v_end += 1 << 22; /* Add extra 4MB to get >= 512kB padding. */ - if ( (((v_end - v_start) >> L2_PAGETABLE_SHIFT) + 1) <= nr_pt_pages ) + if ( (((v_end - v_start + ((1<<L2_PAGETABLE_SHIFT)-1)) >> + L2_PAGETABLE_SHIFT) + 1) <= nr_pt_pages ) break; } - if ( (v_end - v_start) > (nr_pages * PAGE_SIZE) ) - { - printk("Initial guest OS requires too much space\n" - "(%luMB is greater than %luMB limit)\n", - (v_end-v_start)>>20, (nr_pages<<PAGE_SHIFT)>>20); - return -ENOMEM; - } - printk("PHYSICAL MEMORY ARRANGEMENT:\n" " Kernel image: %p->%p\n" " Initrd image: %p->%p\n" @@ -629,6 +627,14 @@ int construct_dom0(struct domain *p, v_start, v_end); printk(" ENTRY ADDRESS: %08lx\n", vkern_entry); + if ( (v_end - v_start) > (nr_pages * PAGE_SIZE) ) + { + printk("Initial guest OS requires too much space\n" + "(%luMB is greater than %luMB limit)\n", + (v_end-v_start)>>20, (nr_pages<<PAGE_SHIFT)>>20); + return -ENOMEM; + } + /* * Protect the lowest 1GB of memory. We use a temporary mapping there * from which we copy the kernel and ramdisk images. diff --git a/xen/common/elf.c b/xen/common/elf.c index 72f1617a32..b59171b5d9 100644 --- a/xen/common/elf.c +++ b/xen/common/elf.c @@ -16,17 +16,18 @@ static inline int is_loadable_phdr(Elf_Phdr *phdr) ((phdr->p_flags & (PF_W|PF_X)) != 0)); } -int readelfimage_base_and_size(char *elfbase, - unsigned long elfsize, - unsigned long *pkernstart, - unsigned long *pkernend, - unsigned long *pkernentry) +int parseelfimage(char *elfbase, + unsigned long elfsize, + unsigned long *pvirtstart, + unsigned long *pkernstart, + unsigned long *pkernend, + unsigned long *pkernentry) { Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase; Elf_Phdr *phdr; Elf_Shdr *shdr; unsigned long kernstart = ~0UL, kernend=0UL; - char *shstrtab, *guestinfo; + char *shstrtab, *guestinfo, *p; int h; if ( !IS_ELF(*ehdr) ) @@ -63,14 +64,21 @@ int readelfimage_base_and_size(char *elfbase, shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff + (h*ehdr->e_shentsize)); if ( strcmp(&shstrtab[shdr->sh_name], "__xen_guest") != 0 ) continue; + guestinfo = elfbase + shdr->sh_offset; printk("Xen-ELF header found: '%s'\n", guestinfo); + if ( (strstr(guestinfo, "GUEST_OS=linux") == NULL) || (strstr(guestinfo, "XEN_VER=1.3") == NULL) ) { printk("ERROR: Xen will only load Linux built for Xen v1.3\n"); return -EINVAL; } + + *pvirtstart = kernstart; + if ( (p = strstr(guestinfo, "VIRT_BASE=")) != NULL ) + *pvirtstart = simple_strtoul(p+10, &p, 0); + break; } if ( h == ehdr->e_shnum ) diff --git a/xen/include/xen/elf.h b/xen/include/xen/elf.h index c66aeb0d3d..2abd8a2206 100644 --- a/xen/include/xen/elf.h +++ b/xen/include/xen/elf.h @@ -525,7 +525,8 @@ typedef struct { #endif extern int loadelfimage(char *); -extern int readelfimage_base_and_size( - char *, unsigned long, unsigned long *, unsigned long *, unsigned long *); +extern int parseelfimage( + char *, unsigned long, unsigned long *, + unsigned long *, unsigned long *, unsigned long *); #endif /* __XEN_ELF_H__ */ |