ia64/xen-unstable

changeset 1780:3bca70370d6e

bitkeeper revision 1.1082 (40f5427bJQEFqTSPn7NWKEkiQ-CC9g)

Allow loading of kernel images with virtual-memory base different
from kernel-image load base.
author kaf24@scramble.cl.cam.ac.uk
date Wed Jul 14 14:26:03 2004 +0000 (2004-07-14)
parents f48283c49033
children 8f75eee1c448
files linux-2.4.26-xen-sparse/arch/xen/kernel/head.S linux-2.4.26-xen-sparse/arch/xen/kernel/setup.c linux-2.4.26-xen-sparse/arch/xen/vmlinux.lds tools/libxc/xc_linux_build.c xen/arch/x86/domain.c xen/common/elf.c xen/include/xen/elf.h
line diff
     1.1 --- a/linux-2.4.26-xen-sparse/arch/xen/kernel/head.S	Wed Jul 14 11:46:25 2004 +0000
     1.2 +++ b/linux-2.4.26-xen-sparse/arch/xen/kernel/head.S	Wed Jul 14 14:26:03 2004 +0000
     1.3 @@ -1,6 +1,6 @@
     1.4  
     1.5  .section __xen_guest
     1.6 -    .asciz "GUEST_OS=linux,GUEST_VER=2.4,XEN_VER=1.3"
     1.7 +    .asciz "GUEST_OS=linux,GUEST_VER=2.4,XEN_VER=1.3,VIRT_BASE=0xC0000000"
     1.8  
     1.9  .text
    1.10  #include <linux/config.h>
     2.1 --- a/linux-2.4.26-xen-sparse/arch/xen/kernel/setup.c	Wed Jul 14 11:46:25 2004 +0000
     2.2 +++ b/linux-2.4.26-xen-sparse/arch/xen/kernel/setup.c	Wed Jul 14 14:26:03 2004 +0000
     2.3 @@ -205,6 +205,8 @@ void __init setup_arch(char **cmdline_p)
     2.4      extern const struct exception_table_entry __start___ex_table[];
     2.5      extern const struct exception_table_entry __stop___ex_table[];
     2.6  
     2.7 +    extern char _stext;
     2.8 +
     2.9      /* Force a quick death if the kernel panics. */
    2.10      extern int panic_timeout;
    2.11      if ( panic_timeout == 0 )
    2.12 @@ -314,7 +316,9 @@ void __init setup_arch(char **cmdline_p)
    2.13       */
    2.14      bootmap_size = init_bootmem(start_pfn, max_low_pfn);
    2.15      free_bootmem(0, PFN_PHYS(max_low_pfn));
    2.16 -    reserve_bootmem(0, PFN_PHYS(start_pfn) + bootmap_size + PAGE_SIZE-1);
    2.17 +    reserve_bootmem(__pa(&_stext), 
    2.18 +                    PFN_PHYS(start_pfn) + bootmap_size + PAGE_SIZE-1 - 
    2.19 +                    __pa(&_stext));
    2.20  
    2.21  #ifdef CONFIG_BLK_DEV_INITRD
    2.22      if ( start_info.mod_start != 0 )
     3.1 --- a/linux-2.4.26-xen-sparse/arch/xen/vmlinux.lds	Wed Jul 14 11:46:25 2004 +0000
     3.2 +++ b/linux-2.4.26-xen-sparse/arch/xen/vmlinux.lds	Wed Jul 14 14:26:03 2004 +0000
     3.3 @@ -6,7 +6,7 @@ OUTPUT_ARCH(i386)
     3.4  ENTRY(_start)
     3.5  SECTIONS
     3.6  {
     3.7 -  . = 0xC0000000 + 0x000000;
     3.8 +  . = 0xC0000000 + 0x100000;
     3.9    _text = .;			/* Text and read-only data */
    3.10    .text : {
    3.11  	*(.text)
     4.1 --- a/tools/libxc/xc_linux_build.c	Wed Jul 14 11:46:25 2004 +0000
     4.2 +++ b/tools/libxc/xc_linux_build.c	Wed Jul 14 14:26:03 2004 +0000
     4.3 @@ -5,6 +5,7 @@
     4.4  #include "xc_private.h"
     4.5  #define ELFSIZE 32
     4.6  #include "xc_elf.h"
     4.7 +#include <stdlib.h>
     4.8  #include <zlib.h>
     4.9  
    4.10  #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
    4.11 @@ -13,11 +14,12 @@
    4.12  #define round_pgup(_p)    (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
    4.13  #define round_pgdown(_p)  ((_p)&PAGE_MASK)
    4.14  
    4.15 -static int readelfimage_base_and_size(char *elfbase, 
    4.16 -                                      unsigned long elfsize,
    4.17 -                                      unsigned long *pkernstart,
    4.18 -                                      unsigned long *pkernend,
    4.19 -                                      unsigned long *pkernentry);
    4.20 +static int parseelfimage(char *elfbase, 
    4.21 +                         unsigned long elfsize,
    4.22 +                         unsigned long *pvirtstart,
    4.23 +                         unsigned long *pkernstart,
    4.24 +                         unsigned long *pkernend,
    4.25 +                         unsigned long *pkernentry);
    4.26  static int loadelfimage(char *elfbase, void *pmh, unsigned long *parray,
    4.27                          unsigned long vstart);
    4.28  
    4.29 @@ -109,11 +111,17 @@ static int setup_guestos(int xc_handle,
    4.30      unsigned long vpt_end;
    4.31      unsigned long v_end;
    4.32  
    4.33 -    rc = readelfimage_base_and_size(image, image_size, 
    4.34 -                                    &vkern_start, &vkern_end, &vkern_entry);
    4.35 +    rc = parseelfimage(image, image_size, &v_start,
    4.36 +                       &vkern_start, &vkern_end, &vkern_entry);
    4.37      if ( rc != 0 )
    4.38          goto error_out;
    4.39      
    4.40 +    if ( (v_start & (PAGE_SIZE-1)) != 0 )
    4.41 +    {
    4.42 +        PERROR("Guest OS must load to a page boundary.\n");
    4.43 +        goto error_out;
    4.44 +    }
    4.45 +
    4.46      /*
    4.47       * Why do we need this? The number of page-table frames depends on the 
    4.48       * size of the bootstrap address space. But the size of the address space 
    4.49 @@ -123,7 +131,6 @@ static int setup_guestos(int xc_handle,
    4.50       */
    4.51      for ( nr_pt_pages = 2; ; nr_pt_pages++ )
    4.52      {
    4.53 -        v_start          = vkern_start & ~((1<<22)-1);
    4.54          vinitrd_start    = round_pgup(vkern_end);
    4.55          vinitrd_end      = vinitrd_start + initrd_len;
    4.56          vphysmap_start   = round_pgup(vinitrd_end);
    4.57 @@ -137,18 +144,11 @@ static int setup_guestos(int xc_handle,
    4.58          v_end            = (vstack_end + (1<<22)-1) & ~((1<<22)-1);
    4.59          if ( (v_end - vstack_end) < (512 << 10) )
    4.60              v_end += 1 << 22; /* Add extra 4MB to get >= 512kB padding. */
    4.61 -        if ( (((v_end - v_start) >> L2_PAGETABLE_SHIFT) + 1) <= nr_pt_pages )
    4.62 +        if ( (((v_end - v_start + ((1<<L2_PAGETABLE_SHIFT)-1)) >> 
    4.63 +               L2_PAGETABLE_SHIFT) + 1) <= nr_pt_pages )
    4.64              break;
    4.65      }
    4.66  
    4.67 -    if ( (v_end - v_start) > (nr_pages * PAGE_SIZE) )
    4.68 -    {
    4.69 -        printf("Initial guest OS requires too much space\n"
    4.70 -               "(%luMB is greater than %luMB limit)\n",
    4.71 -               (v_end-v_start)>>20, (nr_pages<<PAGE_SHIFT)>>20);
    4.72 -        goto error_out;
    4.73 -    }
    4.74 -
    4.75      printf("VIRTUAL MEMORY ARRANGEMENT:\n"
    4.76             " Loaded kernel: %08lx->%08lx\n"
    4.77             " Init. ramdisk: %08lx->%08lx\n"
    4.78 @@ -166,6 +166,14 @@ static int setup_guestos(int xc_handle,
    4.79             v_start, v_end);
    4.80      printf(" ENTRY ADDRESS: %08lx\n", vkern_entry);
    4.81  
    4.82 +    if ( (v_end - v_start) > (nr_pages * PAGE_SIZE) )
    4.83 +    {
    4.84 +        printf("Initial guest OS requires too much space\n"
    4.85 +               "(%luMB is greater than %luMB limit)\n",
    4.86 +               (v_end-v_start)>>20, (nr_pages<<PAGE_SHIFT)>>20);
    4.87 +        goto error_out;
    4.88 +    }
    4.89 +
    4.90      if ( (pm_handle = init_pfn_mapper((domid_t)dom)) == NULL )
    4.91          goto error_out;
    4.92  
    4.93 @@ -541,17 +549,18 @@ static inline int is_loadable_phdr(Elf_P
    4.94              ((phdr->p_flags & (PF_W|PF_X)) != 0));
    4.95  }
    4.96  
    4.97 -static int readelfimage_base_and_size(char *elfbase, 
    4.98 -                                      unsigned long elfsize,
    4.99 -                                      unsigned long *pkernstart,
   4.100 -                                      unsigned long *pkernend,
   4.101 -                                      unsigned long *pkernentry)
   4.102 +static int parseelfimage(char *elfbase, 
   4.103 +                         unsigned long elfsize,
   4.104 +                         unsigned long *pvirtstart,
   4.105 +                         unsigned long *pkernstart,
   4.106 +                         unsigned long *pkernend,
   4.107 +                         unsigned long *pkernentry)
   4.108  {
   4.109      Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase;
   4.110      Elf_Phdr *phdr;
   4.111      Elf_Shdr *shdr;
   4.112      unsigned long kernstart = ~0UL, kernend=0UL;
   4.113 -    char *shstrtab, *guestinfo;
   4.114 +    char *shstrtab, *guestinfo, *p;
   4.115      int h;
   4.116  
   4.117      if ( !IS_ELF(*ehdr) )
   4.118 @@ -588,7 +597,9 @@ static int readelfimage_base_and_size(ch
   4.119          shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff + (h*ehdr->e_shentsize));
   4.120          if ( strcmp(&shstrtab[shdr->sh_name], "__xen_guest") != 0 )
   4.121              continue;
   4.122 +
   4.123          guestinfo = elfbase + shdr->sh_offset;
   4.124 +
   4.125          if ( (strstr(guestinfo, "GUEST_OS=linux") == NULL) ||
   4.126               (strstr(guestinfo, "XEN_VER=1.3") == NULL) )
   4.127          {
   4.128 @@ -596,6 +607,11 @@ static int readelfimage_base_and_size(ch
   4.129              ERROR("Actually saw: '%s'", guestinfo);
   4.130              return -EINVAL;
   4.131          }
   4.132 +
   4.133 +        *pvirtstart = kernstart;
   4.134 +        if ( (p = strstr(guestinfo, "VIRT_BASE=")) != NULL )
   4.135 +            *pvirtstart = strtoul(p+10, &p, 0);
   4.136 +
   4.137          break;
   4.138      }
   4.139      if ( h == ehdr->e_shnum )
     5.1 --- a/xen/arch/x86/domain.c	Wed Jul 14 11:46:25 2004 +0000
     5.2 +++ b/xen/arch/x86/domain.c	Wed Jul 14 14:26:03 2004 +0000
     5.3 @@ -565,11 +565,17 @@ int construct_dom0(struct domain *p,
     5.4       * We'll have to revisit this if we ever support PAE (64GB).
     5.5       */
     5.6  
     5.7 -    rc = readelfimage_base_and_size(image_start, image_len,
     5.8 -                                    &vkern_start, &vkern_end, &vkern_entry);
     5.9 +    rc = parseelfimage(image_start, image_len, &v_start,
    5.10 +                       &vkern_start, &vkern_end, &vkern_entry);
    5.11      if ( rc != 0 )
    5.12          return rc;
    5.13  
    5.14 +    if ( (v_start & (PAGE_SIZE-1)) != 0 )
    5.15 +    {
    5.16 +        printk("Initial guest OS must load to a page boundary.\n");
    5.17 +        return -EINVAL;
    5.18 +    }
    5.19 +
    5.20      /*
    5.21       * Why do we need this? The number of page-table frames depends on the 
    5.22       * size of the bootstrap address space. But the size of the address space 
    5.23 @@ -579,7 +585,6 @@ int construct_dom0(struct domain *p,
    5.24       */
    5.25      for ( nr_pt_pages = 2; ; nr_pt_pages++ )
    5.26      {
    5.27 -        v_start          = vkern_start & ~((1<<22)-1);
    5.28          vinitrd_start    = round_pgup(vkern_end);
    5.29          vinitrd_end      = vinitrd_start + initrd_len;
    5.30          vphysmap_start   = round_pgup(vinitrd_end);
    5.31 @@ -593,18 +598,11 @@ int construct_dom0(struct domain *p,
    5.32          v_end            = (vstack_end + (1<<22)-1) & ~((1<<22)-1);
    5.33          if ( (v_end - vstack_end) < (512 << 10) )
    5.34              v_end += 1 << 22; /* Add extra 4MB to get >= 512kB padding. */
    5.35 -        if ( (((v_end - v_start) >> L2_PAGETABLE_SHIFT) + 1) <= nr_pt_pages )
    5.36 +        if ( (((v_end - v_start + ((1<<L2_PAGETABLE_SHIFT)-1)) >> 
    5.37 +               L2_PAGETABLE_SHIFT) + 1) <= nr_pt_pages )
    5.38              break;
    5.39      }
    5.40  
    5.41 -    if ( (v_end - v_start) > (nr_pages * PAGE_SIZE) )
    5.42 -    {
    5.43 -        printk("Initial guest OS requires too much space\n"
    5.44 -               "(%luMB is greater than %luMB limit)\n",
    5.45 -               (v_end-v_start)>>20, (nr_pages<<PAGE_SHIFT)>>20);
    5.46 -        return -ENOMEM;
    5.47 -    }
    5.48 -
    5.49      printk("PHYSICAL MEMORY ARRANGEMENT:\n"
    5.50             " Kernel image:  %p->%p\n"
    5.51             " Initrd image:  %p->%p\n"
    5.52 @@ -629,6 +627,14 @@ int construct_dom0(struct domain *p,
    5.53             v_start, v_end);
    5.54      printk(" ENTRY ADDRESS: %08lx\n", vkern_entry);
    5.55  
    5.56 +    if ( (v_end - v_start) > (nr_pages * PAGE_SIZE) )
    5.57 +    {
    5.58 +        printk("Initial guest OS requires too much space\n"
    5.59 +               "(%luMB is greater than %luMB limit)\n",
    5.60 +               (v_end-v_start)>>20, (nr_pages<<PAGE_SHIFT)>>20);
    5.61 +        return -ENOMEM;
    5.62 +    }
    5.63 +
    5.64      /*
    5.65       * Protect the lowest 1GB of memory. We use a temporary mapping there
    5.66       * from which we copy the kernel and ramdisk images.
     6.1 --- a/xen/common/elf.c	Wed Jul 14 11:46:25 2004 +0000
     6.2 +++ b/xen/common/elf.c	Wed Jul 14 14:26:03 2004 +0000
     6.3 @@ -16,17 +16,18 @@ static inline int is_loadable_phdr(Elf_P
     6.4              ((phdr->p_flags & (PF_W|PF_X)) != 0));
     6.5  }
     6.6  
     6.7 -int readelfimage_base_and_size(char *elfbase, 
     6.8 -                                      unsigned long elfsize,
     6.9 -                                      unsigned long *pkernstart,
    6.10 -                                      unsigned long *pkernend,
    6.11 -                                      unsigned long *pkernentry)
    6.12 +int parseelfimage(char *elfbase, 
    6.13 +                  unsigned long elfsize,
    6.14 +                  unsigned long *pvirtstart,
    6.15 +                  unsigned long *pkernstart,
    6.16 +                  unsigned long *pkernend,
    6.17 +                  unsigned long *pkernentry)
    6.18  {
    6.19      Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase;
    6.20      Elf_Phdr *phdr;
    6.21      Elf_Shdr *shdr;
    6.22      unsigned long kernstart = ~0UL, kernend=0UL;
    6.23 -    char *shstrtab, *guestinfo;
    6.24 +    char *shstrtab, *guestinfo, *p;
    6.25      int h;
    6.26  
    6.27      if ( !IS_ELF(*ehdr) )
    6.28 @@ -63,14 +64,21 @@ int readelfimage_base_and_size(char *elf
    6.29          shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff + (h*ehdr->e_shentsize));
    6.30          if ( strcmp(&shstrtab[shdr->sh_name], "__xen_guest") != 0 )
    6.31              continue;
    6.32 +
    6.33          guestinfo = elfbase + shdr->sh_offset;
    6.34          printk("Xen-ELF header found: '%s'\n", guestinfo);
    6.35 +
    6.36          if ( (strstr(guestinfo, "GUEST_OS=linux") == NULL) ||
    6.37               (strstr(guestinfo, "XEN_VER=1.3") == NULL) )
    6.38          {
    6.39              printk("ERROR: Xen will only load Linux built for Xen v1.3\n");
    6.40              return -EINVAL;
    6.41          }
    6.42 +
    6.43 +        *pvirtstart = kernstart;
    6.44 +        if ( (p = strstr(guestinfo, "VIRT_BASE=")) != NULL )
    6.45 +            *pvirtstart = simple_strtoul(p+10, &p, 0);
    6.46 +
    6.47          break;
    6.48      }
    6.49      if ( h == ehdr->e_shnum )
     7.1 --- a/xen/include/xen/elf.h	Wed Jul 14 11:46:25 2004 +0000
     7.2 +++ b/xen/include/xen/elf.h	Wed Jul 14 14:26:03 2004 +0000
     7.3 @@ -525,7 +525,8 @@ typedef struct {
     7.4  #endif
     7.5  
     7.6  extern int loadelfimage(char *);
     7.7 -extern int readelfimage_base_and_size(
     7.8 -    char *, unsigned long, unsigned long *, unsigned long *, unsigned long *);
     7.9 +extern int parseelfimage(
    7.10 +    char *, unsigned long, unsigned long *,
    7.11 +    unsigned long *, unsigned long *, unsigned long *);
    7.12  
    7.13  #endif /* __XEN_ELF_H__ */