aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2004-07-14 14:26:03 +0000
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2004-07-14 14:26:03 +0000
commit49f78c77c25611a41c26766e6bf32739b39d7f25 (patch)
tree2df219c4fbfea91acd7d057f24aebf3b9d119f69
parenta5af4e1ea589d8ad1c7485b12d756297cd12d536 (diff)
downloadxen-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.S2
-rw-r--r--linux-2.4.26-xen-sparse/arch/xen/kernel/setup.c6
-rw-r--r--linux-2.4.26-xen-sparse/arch/xen/vmlinux.lds2
-rw-r--r--tools/libxc/xc_linux_build.c62
-rw-r--r--xen/arch/x86/domain.c30
-rw-r--r--xen/common/elf.c20
-rw-r--r--xen/include/xen/elf.h5
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__ */