ia64/xen-unstable

changeset 11284:2eb8efcc70d1

[XEN] Restore backwards compatibility by supporting __xen_guest
section in dom0 loader.

Signed-off-by: Ian Campbell <ian.campbell@xensource.com>
author Ian Campbell <ian.campbell@xensource.com>
date Wed Aug 23 18:38:49 2006 +0100 (2006-08-23)
parents cc006f78cbe2
children 551495fa7b3e
files xen/arch/x86/domain_build.c xen/common/elf.c xen/include/xen/sched.h
line diff
     1.1 --- a/xen/arch/x86/domain_build.c	Wed Aug 23 18:35:21 2006 +0100
     1.2 +++ b/xen/arch/x86/domain_build.c	Wed Aug 23 18:38:49 2006 +0100
     1.3 @@ -290,14 +290,7 @@ int construct_dom0(struct domain *d,
     1.4      if ( (rc = parseelfimage(&dsi)) != 0 )
     1.5          return rc;
     1.6  
     1.7 -    if ( dsi.__elfnote_section == NULL )
     1.8 -    {
     1.9 -        printk("Not a Xen-ELF image: no Xen ELF notes were found.\n");
    1.10 -        return -EINVAL;
    1.11 -    }
    1.12 -
    1.13 -    p = xen_elfnote_string(&dsi, XEN_ELFNOTE_PAE_MODE);
    1.14 -    dom0_pae = !!(p != NULL && strcmp(p, "yes") == 0);
    1.15 +    dom0_pae = (dsi.pae_kernel != PAEKERN_no);
    1.16      xen_pae  = (CONFIG_PAGING_LEVELS == 3);
    1.17      if ( dom0_pae != xen_pae )
    1.18      {
    1.19 @@ -306,8 +299,8 @@ int construct_dom0(struct domain *d,
    1.20          return -EINVAL;
    1.21      }
    1.22  
    1.23 -    if ( xen_pae )
    1.24 -        set_bit(VMASST_TYPE_pae_extended_cr3, &d->vm_assist);
    1.25 +    if ( xen_pae && dsi.pae_kernel == PAEKERN_extended_cr3 )
    1.26 +            set_bit(VMASST_TYPE_pae_extended_cr3, &d->vm_assist);
    1.27  
    1.28      if ( (p = xen_elfnote_string(&dsi, XEN_ELFNOTE_FEATURES)) != NULL )
    1.29      {
     2.1 --- a/xen/common/elf.c	Wed Aug 23 18:35:21 2006 +0100
     2.2 +++ b/xen/common/elf.c	Wed Aug 23 18:38:49 2006 +0100
     2.3 @@ -23,6 +23,80 @@ static inline int is_loadable_phdr(Elf_P
     2.4  }
     2.5  
     2.6  /*
     2.7 + * Fallback for kernels containing only the legacy __xen_guest string
     2.8 + * and no ELF notes.
     2.9 + */
    2.10 +static int is_xen_guest_section(Elf_Shdr *shdr, const char *shstrtab)
    2.11 +{
    2.12 +    return strcmp(&shstrtab[shdr->sh_name], "__xen_guest") == 0;
    2.13 +}
    2.14 +
    2.15 +static const char *xen_guest_lookup(struct domain_setup_info *dsi, int type)
    2.16 +{
    2.17 +    const char *xenguest_fallbacks[] = {
    2.18 +        [XEN_ELFNOTE_ENTRY] = "VIRT_ENTRY=",
    2.19 +        [XEN_ELFNOTE_HYPERCALL_PAGE] = "HYPERCALL_PAGE=",
    2.20 +        [XEN_ELFNOTE_VIRT_BASE] = "VIRT_BASE=",
    2.21 +        [XEN_ELFNOTE_PADDR_OFFSET] = "ELF_PADDR_OFFSET=",
    2.22 +        [XEN_ELFNOTE_XEN_VERSION] = "XEN_VER=",
    2.23 +        [XEN_ELFNOTE_GUEST_OS] = "GUEST_OS=",
    2.24 +        [XEN_ELFNOTE_GUEST_VERSION] = "GUEST_VER=",
    2.25 +        [XEN_ELFNOTE_LOADER] = "LOADER=",
    2.26 +        [XEN_ELFNOTE_PAE_MODE] = "PAE=",
    2.27 +        [XEN_ELFNOTE_FEATURES] = "FEATURES=",
    2.28 +        [XEN_ELFNOTE_BSD_SYMTAB] = "BSD_SYMTAB=",
    2.29 +    };
    2.30 +    const char *fallback;
    2.31 +    const char *p;
    2.32 +
    2.33 +    if ( type > sizeof(xenguest_fallbacks) )
    2.34 +        return NULL;
    2.35 +
    2.36 +    if ( (fallback = xenguest_fallbacks[type]) == NULL )
    2.37 +        return NULL;
    2.38 +
    2.39 +    if ( (p = strstr(dsi->__xen_guest_string,fallback)) == NULL )
    2.40 +        return NULL;
    2.41 +
    2.42 +    return p + strlen(fallback);
    2.43 +}
    2.44 +
    2.45 +static const char *xen_guest_string(struct domain_setup_info *dsi, int type)
    2.46 +{
    2.47 +    const char *p = xen_guest_lookup(dsi, type);
    2.48 +
    2.49 +    /*
    2.50 +     * We special case this since the __xen_guest_section treats the
    2.51 +     * mere precense of the BSD_SYMTAB string as true or false.
    2.52 +     */
    2.53 +    if ( type == XEN_ELFNOTE_BSD_SYMTAB )
    2.54 +        return p ? "yes" : "no";
    2.55 +
    2.56 +    return p;
    2.57 +}
    2.58 +
    2.59 +static unsigned long long xen_guest_numeric(struct domain_setup_info *dsi,
    2.60 +                                                   int type, int *defined)
    2.61 +{
    2.62 +    const char *p = xen_guest_lookup(dsi, type);
    2.63 +    unsigned long long value;
    2.64 +
    2.65 +    if ( p == NULL )
    2.66 +        return 0;
    2.67 +
    2.68 +    value = simple_strtoull(p, NULL, 0);
    2.69 +
    2.70 +    /* We special case this since __xen_guest_section contains a PFN
    2.71 +     * for this field not a virtual address.
    2.72 +     */
    2.73 +    if (type == XEN_ELFNOTE_HYPERCALL_PAGE)
    2.74 +        value = dsi->v_start + (value<<PAGE_SHIFT);
    2.75 +
    2.76 +    *defined = 1;
    2.77 +    return value;
    2.78 +}
    2.79 +
    2.80 +/*
    2.81   * Interface to the Xen ELF notes.
    2.82   */
    2.83  #define ELFNOTE_NAME(_n_)   ((void*)(_n_) + sizeof(*(_n_)))
    2.84 @@ -65,7 +139,6 @@ static Elf_Note *xen_elfnote_lookup(stru
    2.85              return note;
    2.86      }
    2.87  
    2.88 -    DPRINTK("unable to find Xen ELF note with type %#x\n", type);
    2.89      return NULL;
    2.90  }
    2.91  
    2.92 @@ -73,13 +146,13 @@ const char *xen_elfnote_string(struct do
    2.93  {
    2.94      Elf_Note *note;
    2.95  
    2.96 +    if ( !dsi->__elfnote_section )
    2.97 +        return xen_guest_string(dsi, type);
    2.98 +
    2.99      note = xen_elfnote_lookup(dsi, type);
   2.100      if ( note == NULL )
   2.101          return NULL;
   2.102  
   2.103 -    DPRINTK("found Xen ELF note type %#x = \"%s\"\n",
   2.104 -            type, (char *)ELFNOTE_DESC(note));
   2.105 -
   2.106      return (const char *)ELFNOTE_DESC(note);
   2.107  }
   2.108  
   2.109 @@ -90,6 +163,9 @@ unsigned long long xen_elfnote_numeric(s
   2.110  
   2.111      *defined = 0;
   2.112  
   2.113 +    if ( !dsi->__elfnote_section )
   2.114 +        return xen_guest_numeric(dsi, type, defined);
   2.115 +
   2.116      note = xen_elfnote_lookup(dsi, type);
   2.117      if ( note == NULL )
   2.118      {
   2.119 @@ -105,6 +181,8 @@ unsigned long long xen_elfnote_numeric(s
   2.120          *defined = 1;
   2.121          return *(uint64_t*)ELFNOTE_DESC(note);
   2.122      default:
   2.123 +        printk("ERROR: unknown data size %#x for numeric type note %#x\n",
   2.124 +               note->descsz, type);
   2.125          return 0;
   2.126      }
   2.127  }
   2.128 @@ -146,6 +224,7 @@ int parseelfimage(struct domain_setup_in
   2.129      shstrtab = image + shdr->sh_offset;
   2.130  
   2.131      dsi->__elfnote_section = NULL;
   2.132 +    dsi->__xen_guest_string = NULL;
   2.133  
   2.134      /* Look for .notes segment containing at least one Xen note */
   2.135      for ( h = 0; h < ehdr->e_shnum; h++ )
   2.136 @@ -159,27 +238,73 @@ int parseelfimage(struct domain_setup_in
   2.137          break;
   2.138      }
   2.139  
   2.140 -    /* Check the contents of the Xen notes. */
   2.141 -    if ( dsi->__elfnote_section )
   2.142 +    /* Fall back to looking for the special '__xen_guest' section. */
   2.143 +    if ( dsi->__elfnote_section == NULL )
   2.144 +    {
   2.145 +        for ( h = 0; h < ehdr->e_shnum; h++ )
   2.146 +        {
   2.147 +            shdr = (Elf_Shdr *)(image + ehdr->e_shoff + (h*ehdr->e_shentsize));
   2.148 +            if ( is_xen_guest_section(shdr, shstrtab) )
   2.149 +            {
   2.150 +                dsi->__xen_guest_string = (char *)image + shdr->sh_offset;
   2.151 +                break;
   2.152 +            }
   2.153 +        }
   2.154 +    }
   2.155 +
   2.156 +    /* Check the contents of the Xen notes or guest string. */
   2.157 +    if ( dsi->__elfnote_section || dsi->__xen_guest_string )
   2.158      {
   2.159          const char *loader = xen_elfnote_string(dsi, XEN_ELFNOTE_LOADER);
   2.160          const char *guest_os = xen_elfnote_string(dsi, XEN_ELFNOTE_GUEST_OS);
   2.161          const char *xen_version =
   2.162              xen_elfnote_string(dsi, XEN_ELFNOTE_XEN_VERSION);
   2.163  
   2.164 -        if ( ( loader == NULL || strcmp(loader, "generic") ) &&
   2.165 -             ( guest_os == NULL || strcmp(guest_os, "linux") ) )
   2.166 +        if ( ( loader == NULL || strncmp(loader, "generic", 7) ) &&
   2.167 +             ( guest_os == NULL || strncmp(guest_os, "linux", 5) ) )
   2.168          {
   2.169              printk("ERROR: Will only load images built for the generic "
   2.170                     "loader or Linux images");
   2.171              return -EINVAL;
   2.172          }
   2.173  
   2.174 -        if ( xen_version == NULL || strcmp(xen_version, "xen-3.0") )
   2.175 +        if ( xen_version == NULL || strncmp(xen_version, "xen-3.0", 7) )
   2.176          {
   2.177              printk("ERROR: Xen will only load images built for Xen v3.0\n");
   2.178          }
   2.179      }
   2.180 +    else
   2.181 +    {
   2.182 +#if defined(__x86_64__) || defined(__i386__)
   2.183 +        printk("ERROR: Not a Xen-ELF image: "
   2.184 +               "No ELF notes or '__xen_guest' section found.\n");
   2.185 +        return -EINVAL;
   2.186 +#endif
   2.187 +    }
   2.188 +
   2.189 +    /*
   2.190 +     * If we have ELF notes then PAE=yes implies that we must support
   2.191 +     * the extended cr3 syntax. Otherwise we need to find the
   2.192 +     * [extended-cr3] syntax in the __xen_guest string.
   2.193 +     */
   2.194 +    dsi->pae_kernel = PAEKERN_no;
   2.195 +    if ( dsi->__elfnote_section )
   2.196 +    {
   2.197 +        p = xen_elfnote_string(dsi, XEN_ELFNOTE_PAE_MODE);
   2.198 +        if ( p != NULL && strncmp(p, "yes", 3) == 0 )
   2.199 +            dsi->pae_kernel = PAEKERN_extended_cr3;
   2.200 +
   2.201 +    }
   2.202 +    else
   2.203 +    {
   2.204 +        p = xen_guest_lookup(dsi, XEN_ELFNOTE_PAE_MODE);
   2.205 +        if ( p != NULL && strncmp(p, "yes", 3) == 0 )
   2.206 +        {
   2.207 +            dsi->pae_kernel = PAEKERN_yes;
   2.208 +            if ( !strncmp(p+4, "[extended-cr3]", 14) )
   2.209 +                dsi->pae_kernel = PAEKERN_extended_cr3;
   2.210 +        }
   2.211 +    }
   2.212  
   2.213      /* Initial guess for v_start is 0 if it is not explicitly defined. */
   2.214      dsi->v_start =
   2.215 @@ -187,11 +312,24 @@ int parseelfimage(struct domain_setup_in
   2.216      if ( !virt_base_defined )
   2.217          dsi->v_start = 0;
   2.218  
   2.219 -    /* We are using the ELF notes interface so the default is 0. */
   2.220 +    /*
   2.221 +     * If we are using the legacy __xen_guest section then elf_pa_off
   2.222 +     * defaults to v_start in order to maintain compatibility with
   2.223 +     * older hypervisors which set padd in the ELF header to
   2.224 +     * virt_base.
   2.225 +     *
   2.226 +     * If we are using the modern ELF notes interface then the default
   2.227 +     * is 0.
   2.228 +     */
   2.229      dsi->elf_paddr_offset =
   2.230          xen_elfnote_numeric(dsi, XEN_ELFNOTE_PADDR_OFFSET, &elf_pa_off_defined);
   2.231      if ( !elf_pa_off_defined )
   2.232 -        dsi->elf_paddr_offset = 0;
   2.233 +    {
   2.234 +        if ( dsi->__elfnote_section )
   2.235 +            dsi->elf_paddr_offset = 0;
   2.236 +        else
   2.237 +            dsi->elf_paddr_offset = dsi->v_start;
   2.238 +    }
   2.239  
   2.240      if ( elf_pa_off_defined && !virt_base_defined )
   2.241      {
   2.242 @@ -219,6 +357,7 @@ int parseelfimage(struct domain_setup_in
   2.243      }
   2.244  
   2.245      dsi->v_kernentry = ehdr->e_entry;
   2.246 +
   2.247      virt_entry =
   2.248          xen_elfnote_numeric(dsi, XEN_ELFNOTE_ENTRY, &virt_entry_defined);
   2.249      if ( virt_entry_defined )
   2.250 @@ -234,7 +373,7 @@ int parseelfimage(struct domain_setup_in
   2.251      }
   2.252  
   2.253      p = xen_elfnote_string(dsi, XEN_ELFNOTE_BSD_SYMTAB);
   2.254 -    if ( p != NULL && strcmp(p, "yes") == 0 )
   2.255 +    if ( p != NULL && strncmp(p, "yes", 3) == 0 )
   2.256          dsi->load_symtab = 1;
   2.257  
   2.258      dsi->v_kernstart = kernstart;
     3.1 --- a/xen/include/xen/sched.h	Wed Aug 23 18:35:21 2006 +0100
     3.2 +++ b/xen/include/xen/sched.h	Wed Aug 23 18:38:49 2006 +0100
     3.3 @@ -179,13 +179,24 @@ struct domain_setup_info
     3.4      unsigned long v_kernstart;
     3.5      unsigned long v_kernend;
     3.6      unsigned long v_kernentry;
     3.7 +#define PAEKERN_no           0
     3.8 +#define PAEKERN_yes          1
     3.9 +#define PAEKERN_extended_cr3 2
    3.10 +    unsigned int  pae_kernel;
    3.11      /* Initialised by loader: Private. */
    3.12      unsigned long elf_paddr_offset;
    3.13      unsigned int  load_symtab;
    3.14      unsigned long symtab_addr;
    3.15      unsigned long symtab_len;
    3.16 -    /* Indicate whether it's xen specific image */
    3.17 +    /*
    3.18 +     * Only one of __elfnote_* or __xen_guest_string will be
    3.19 +     * non-NULL.
    3.20 +     *
    3.21 +     * You should use the xen_elfnote_* accessors below in order to
    3.22 +     * pickup the correct one and retain backwards compatibility.
    3.23 +     */
    3.24      void *__elfnote_section, *__elfnote_section_end;
    3.25 +    char *__xen_guest_string;
    3.26  };
    3.27  
    3.28  extern struct vcpu *idle_vcpu[NR_CPUS];