WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] merge

# HG changeset patch
# User Ian Campbell <ian.campbell@xxxxxxxxxxxxx>
# Node ID 551495fa7b3e24823cce62d8cfe257f3fe8a2b7c
# Parent  51a98a6c2c054bfc37c90a5a3f29929f2347bda8
# Parent  2eb8efcc70d1744198d729e1caf2a59b046b178b
merge
---
 tools/libxc/xc_load_bin.c   |    2 
 tools/libxc/xc_load_elf.c   |   26 ++-----
 tools/libxc/xg_private.h    |    2 
 xen/arch/x86/domain_build.c |   13 ---
 xen/common/elf.c            |  163 ++++++++++++++++++++++++++++++++++++++++----
 xen/include/xen/sched.h     |   13 +++
 6 files changed, 178 insertions(+), 41 deletions(-)

diff -r 51a98a6c2c05 -r 551495fa7b3e tools/libxc/xc_load_bin.c
--- a/tools/libxc/xc_load_bin.c Wed Aug 23 18:38:08 2006 +0100
+++ b/tools/libxc/xc_load_bin.c Wed Aug 23 18:39:17 2006 +0100
@@ -227,7 +227,7 @@ static int parsebinimage(const char *ima
     dsi->v_kernstart = dsi->v_start;
     dsi->v_kernend = dsi->v_end;
     dsi->v_kernentry = image_info->entry_addr;
-    dsi->__xen_guest_string = "";
+    dsi->__xen_guest_string = NULL;
 
     return 0;
 }
diff -r 51a98a6c2c05 -r 551495fa7b3e tools/libxc/xc_load_elf.c
--- a/tools/libxc/xc_load_elf.c Wed Aug 23 18:38:08 2006 +0100
+++ b/tools/libxc/xc_load_elf.c Wed Aug 23 18:39:17 2006 +0100
@@ -109,15 +109,13 @@ static const char *xen_guest_string(stru
 {
     const char *p = xen_guest_lookup(dsi, type);
 
-    DPRINTF("found __xen_guest entry for type %#x = \"%s\"\n",
-            type, p);
-
     /*
      * We special case this since the __xen_guest_section treats the
      * mere precense of the BSD_SYMTAB string as true or false.
      */
     if ( type == XEN_ELFNOTE_BSD_SYMTAB )
         return p ? "yes" : "no";
+
     return p;
 }
 
@@ -140,9 +138,6 @@ static unsigned long long xen_guest_nume
      */
     if (type == XEN_ELFNOTE_HYPERCALL_PAGE)
         value = dsi->v_start + (value<<PAGE_SHIFT);
-
-    DPRINTF("found __xen_guest entry for type %#x = %#llx\n",
-            type, value);
 
     *defined = 1;
     return value;
@@ -177,6 +172,9 @@ static Elf_Note *xen_elfnote_lookup(stru
 {
     Elf_Note *note;
 
+    if ( !dsi->__elfnote_section )
+        return NULL;
+
     for ( note = (Elf_Note *)dsi->__elfnote_section;
           note < (Elf_Note *)dsi->__elfnote_section_end;
           note = ELFNOTE_NEXT(note) )
@@ -188,7 +186,6 @@ static Elf_Note *xen_elfnote_lookup(stru
             return note;
     }
 
-    DPRINTF("unable to find Xen ELF note with type %#x\n", type);
     return NULL;
 }
 
@@ -202,9 +199,6 @@ const char *xen_elfnote_string(struct do
     note = xen_elfnote_lookup(dsi, type);
     if ( note == NULL )
         return NULL;
-
-    DPRINTF("found Xen ELF note type %#x = \"%s\"\n",
-            type, (char *)ELFNOTE_DESC(note));
 
     return (const char *)ELFNOTE_DESC(note);
 }
@@ -297,7 +291,6 @@ static int parseelfimage(const char *ima
         shdr = (Elf_Shdr *)(image + ehdr->e_shoff + (h*ehdr->e_shentsize));
         if ( !is_xen_elfnote_section(image, shdr) )
             continue;
-        DPRINTF("found note section containing Xen entries\n");
         dsi->__elfnote_section = (void *)image + shdr->sh_offset;
         dsi->__elfnote_section_end =
             (void *)image + shdr->sh_offset + shdr->sh_size;
@@ -312,7 +305,6 @@ static int parseelfimage(const char *ima
             shdr = (Elf_Shdr *)(image + ehdr->e_shoff + (h*ehdr->e_shentsize));
             if ( is_xen_guest_section(shdr, shstrtab) )
             {
-                DPRINTF("found a legacy __xen_guest section\n");
                 dsi->__xen_guest_string = (char *)image + shdr->sh_offset;
                 break;
             }
@@ -343,16 +335,18 @@ static int parseelfimage(const char *ima
     }
     else
     {
-#ifdef __ia64__
-        dsi->__elfnote_section = NULL;
-        dsi->__xen_guest_string = "";
-#else
+#if defined(__x86_64__) || defined(__i386__)
         ERROR("Not a Xen-ELF image: "
               "No ELF notes or '__xen_guest' section found.");
         return -EINVAL;
 #endif
     }
 
+    /*
+     * If we have ELF notes then PAE=yes implies that we must support
+     * the extended cr3 syntax. Otherwise we need to find the
+     * [extended-cr3] syntax in the __xen_guest string.
+     */
     dsi->pae_kernel = PAEKERN_no;
     if ( dsi->__elfnote_section )
     {
diff -r 51a98a6c2c05 -r 551495fa7b3e tools/libxc/xg_private.h
--- a/tools/libxc/xg_private.h  Wed Aug 23 18:38:08 2006 +0100
+++ b/tools/libxc/xg_private.h  Wed Aug 23 18:39:17 2006 +0100
@@ -159,7 +159,7 @@ struct domain_setup_info
      * pickup the correct one and retain backwards compatibility.
      */
     void *__elfnote_section, *__elfnote_section_end;
-    char *__xen_guest_string;
+    const char *__xen_guest_string;
 };
 
 typedef int (*parseimagefunc)(const char *image, unsigned long image_size,
diff -r 51a98a6c2c05 -r 551495fa7b3e xen/arch/x86/domain_build.c
--- a/xen/arch/x86/domain_build.c       Wed Aug 23 18:38:08 2006 +0100
+++ b/xen/arch/x86/domain_build.c       Wed Aug 23 18:39:17 2006 +0100
@@ -290,14 +290,7 @@ int construct_dom0(struct domain *d,
     if ( (rc = parseelfimage(&dsi)) != 0 )
         return rc;
 
-    if ( dsi.__elfnote_section == NULL )
-    {
-        printk("Not a Xen-ELF image: no Xen ELF notes were found.\n");
-        return -EINVAL;
-    }
-
-    p = xen_elfnote_string(&dsi, XEN_ELFNOTE_PAE_MODE);
-    dom0_pae = !!(p != NULL && strcmp(p, "yes") == 0);
+    dom0_pae = (dsi.pae_kernel != PAEKERN_no);
     xen_pae  = (CONFIG_PAGING_LEVELS == 3);
     if ( dom0_pae != xen_pae )
     {
@@ -306,8 +299,8 @@ int construct_dom0(struct domain *d,
         return -EINVAL;
     }
 
-    if ( xen_pae )
-        set_bit(VMASST_TYPE_pae_extended_cr3, &d->vm_assist);
+    if ( xen_pae && dsi.pae_kernel == PAEKERN_extended_cr3 )
+            set_bit(VMASST_TYPE_pae_extended_cr3, &d->vm_assist);
 
     if ( (p = xen_elfnote_string(&dsi, XEN_ELFNOTE_FEATURES)) != NULL )
     {
diff -r 51a98a6c2c05 -r 551495fa7b3e xen/common/elf.c
--- a/xen/common/elf.c  Wed Aug 23 18:38:08 2006 +0100
+++ b/xen/common/elf.c  Wed Aug 23 18:39:17 2006 +0100
@@ -23,6 +23,80 @@ static inline int is_loadable_phdr(Elf_P
 }
 
 /*
+ * Fallback for kernels containing only the legacy __xen_guest string
+ * and no ELF notes.
+ */
+static int is_xen_guest_section(Elf_Shdr *shdr, const char *shstrtab)
+{
+    return strcmp(&shstrtab[shdr->sh_name], "__xen_guest") == 0;
+}
+
+static const char *xen_guest_lookup(struct domain_setup_info *dsi, int type)
+{
+    const char *xenguest_fallbacks[] = {
+        [XEN_ELFNOTE_ENTRY] = "VIRT_ENTRY=",
+        [XEN_ELFNOTE_HYPERCALL_PAGE] = "HYPERCALL_PAGE=",
+        [XEN_ELFNOTE_VIRT_BASE] = "VIRT_BASE=",
+        [XEN_ELFNOTE_PADDR_OFFSET] = "ELF_PADDR_OFFSET=",
+        [XEN_ELFNOTE_XEN_VERSION] = "XEN_VER=",
+        [XEN_ELFNOTE_GUEST_OS] = "GUEST_OS=",
+        [XEN_ELFNOTE_GUEST_VERSION] = "GUEST_VER=",
+        [XEN_ELFNOTE_LOADER] = "LOADER=",
+        [XEN_ELFNOTE_PAE_MODE] = "PAE=",
+        [XEN_ELFNOTE_FEATURES] = "FEATURES=",
+        [XEN_ELFNOTE_BSD_SYMTAB] = "BSD_SYMTAB=",
+    };
+    const char *fallback;
+    const char *p;
+
+    if ( type > sizeof(xenguest_fallbacks) )
+        return NULL;
+
+    if ( (fallback = xenguest_fallbacks[type]) == NULL )
+        return NULL;
+
+    if ( (p = strstr(dsi->__xen_guest_string,fallback)) == NULL )
+        return NULL;
+
+    return p + strlen(fallback);
+}
+
+static const char *xen_guest_string(struct domain_setup_info *dsi, int type)
+{
+    const char *p = xen_guest_lookup(dsi, type);
+
+    /*
+     * We special case this since the __xen_guest_section treats the
+     * mere precense of the BSD_SYMTAB string as true or false.
+     */
+    if ( type == XEN_ELFNOTE_BSD_SYMTAB )
+        return p ? "yes" : "no";
+
+    return p;
+}
+
+static unsigned long long xen_guest_numeric(struct domain_setup_info *dsi,
+                                                   int type, int *defined)
+{
+    const char *p = xen_guest_lookup(dsi, type);
+    unsigned long long value;
+
+    if ( p == NULL )
+        return 0;
+
+    value = simple_strtoull(p, NULL, 0);
+
+    /* We special case this since __xen_guest_section contains a PFN
+     * for this field not a virtual address.
+     */
+    if (type == XEN_ELFNOTE_HYPERCALL_PAGE)
+        value = dsi->v_start + (value<<PAGE_SHIFT);
+
+    *defined = 1;
+    return value;
+}
+
+/*
  * Interface to the Xen ELF notes.
  */
 #define ELFNOTE_NAME(_n_)   ((void*)(_n_) + sizeof(*(_n_)))
@@ -65,21 +139,20 @@ static Elf_Note *xen_elfnote_lookup(stru
             return note;
     }
 
-    DPRINTK("unable to find Xen ELF note with type %#x\n", type);
     return NULL;
 }
 
 const char *xen_elfnote_string(struct domain_setup_info *dsi, int type)
 {
     Elf_Note *note;
+
+    if ( !dsi->__elfnote_section )
+        return xen_guest_string(dsi, type);
 
     note = xen_elfnote_lookup(dsi, type);
     if ( note == NULL )
         return NULL;
 
-    DPRINTK("found Xen ELF note type %#x = \"%s\"\n",
-            type, (char *)ELFNOTE_DESC(note));
-
     return (const char *)ELFNOTE_DESC(note);
 }
 
@@ -89,6 +162,9 @@ unsigned long long xen_elfnote_numeric(s
     Elf_Note *note;
 
     *defined = 0;
+
+    if ( !dsi->__elfnote_section )
+        return xen_guest_numeric(dsi, type, defined);
 
     note = xen_elfnote_lookup(dsi, type);
     if ( note == NULL )
@@ -105,6 +181,8 @@ unsigned long long xen_elfnote_numeric(s
         *defined = 1;
         return *(uint64_t*)ELFNOTE_DESC(note);
     default:
+        printk("ERROR: unknown data size %#x for numeric type note %#x\n",
+               note->descsz, type);
         return 0;
     }
 }
@@ -146,6 +224,7 @@ int parseelfimage(struct domain_setup_in
     shstrtab = image + shdr->sh_offset;
 
     dsi->__elfnote_section = NULL;
+    dsi->__xen_guest_string = NULL;
 
     /* Look for .notes segment containing at least one Xen note */
     for ( h = 0; h < ehdr->e_shnum; h++ )
@@ -159,25 +238,71 @@ int parseelfimage(struct domain_setup_in
         break;
     }
 
-    /* Check the contents of the Xen notes. */
-    if ( dsi->__elfnote_section )
+    /* Fall back to looking for the special '__xen_guest' section. */
+    if ( dsi->__elfnote_section == NULL )
+    {
+        for ( h = 0; h < ehdr->e_shnum; h++ )
+        {
+            shdr = (Elf_Shdr *)(image + ehdr->e_shoff + (h*ehdr->e_shentsize));
+            if ( is_xen_guest_section(shdr, shstrtab) )
+            {
+                dsi->__xen_guest_string = (char *)image + shdr->sh_offset;
+                break;
+            }
+        }
+    }
+
+    /* Check the contents of the Xen notes or guest string. */
+    if ( dsi->__elfnote_section || dsi->__xen_guest_string )
     {
         const char *loader = xen_elfnote_string(dsi, XEN_ELFNOTE_LOADER);
         const char *guest_os = xen_elfnote_string(dsi, XEN_ELFNOTE_GUEST_OS);
         const char *xen_version =
             xen_elfnote_string(dsi, XEN_ELFNOTE_XEN_VERSION);
 
-        if ( ( loader == NULL || strcmp(loader, "generic") ) &&
-             ( guest_os == NULL || strcmp(guest_os, "linux") ) )
+        if ( ( loader == NULL || strncmp(loader, "generic", 7) ) &&
+             ( guest_os == NULL || strncmp(guest_os, "linux", 5) ) )
         {
             printk("ERROR: Will only load images built for the generic "
                    "loader or Linux images");
             return -EINVAL;
         }
 
-        if ( xen_version == NULL || strcmp(xen_version, "xen-3.0") )
+        if ( xen_version == NULL || strncmp(xen_version, "xen-3.0", 7) )
         {
             printk("ERROR: Xen will only load images built for Xen v3.0\n");
+        }
+    }
+    else
+    {
+#if defined(__x86_64__) || defined(__i386__)
+        printk("ERROR: Not a Xen-ELF image: "
+               "No ELF notes or '__xen_guest' section found.\n");
+        return -EINVAL;
+#endif
+    }
+
+    /*
+     * If we have ELF notes then PAE=yes implies that we must support
+     * the extended cr3 syntax. Otherwise we need to find the
+     * [extended-cr3] syntax in the __xen_guest string.
+     */
+    dsi->pae_kernel = PAEKERN_no;
+    if ( dsi->__elfnote_section )
+    {
+        p = xen_elfnote_string(dsi, XEN_ELFNOTE_PAE_MODE);
+        if ( p != NULL && strncmp(p, "yes", 3) == 0 )
+            dsi->pae_kernel = PAEKERN_extended_cr3;
+
+    }
+    else
+    {
+        p = xen_guest_lookup(dsi, XEN_ELFNOTE_PAE_MODE);
+        if ( p != NULL && strncmp(p, "yes", 3) == 0 )
+        {
+            dsi->pae_kernel = PAEKERN_yes;
+            if ( !strncmp(p+4, "[extended-cr3]", 14) )
+                dsi->pae_kernel = PAEKERN_extended_cr3;
         }
     }
 
@@ -187,11 +312,24 @@ int parseelfimage(struct domain_setup_in
     if ( !virt_base_defined )
         dsi->v_start = 0;
 
-    /* We are using the ELF notes interface so the default is 0. */
+    /*
+     * If we are using the legacy __xen_guest section then elf_pa_off
+     * defaults to v_start in order to maintain compatibility with
+     * older hypervisors which set padd in the ELF header to
+     * virt_base.
+     *
+     * If we are using the modern ELF notes interface then the default
+     * is 0.
+     */
     dsi->elf_paddr_offset =
         xen_elfnote_numeric(dsi, XEN_ELFNOTE_PADDR_OFFSET, 
&elf_pa_off_defined);
     if ( !elf_pa_off_defined )
-        dsi->elf_paddr_offset = 0;
+    {
+        if ( dsi->__elfnote_section )
+            dsi->elf_paddr_offset = 0;
+        else
+            dsi->elf_paddr_offset = dsi->v_start;
+    }
 
     if ( elf_pa_off_defined && !virt_base_defined )
     {
@@ -219,6 +357,7 @@ int parseelfimage(struct domain_setup_in
     }
 
     dsi->v_kernentry = ehdr->e_entry;
+
     virt_entry =
         xen_elfnote_numeric(dsi, XEN_ELFNOTE_ENTRY, &virt_entry_defined);
     if ( virt_entry_defined )
@@ -234,7 +373,7 @@ int parseelfimage(struct domain_setup_in
     }
 
     p = xen_elfnote_string(dsi, XEN_ELFNOTE_BSD_SYMTAB);
-    if ( p != NULL && strcmp(p, "yes") == 0 )
+    if ( p != NULL && strncmp(p, "yes", 3) == 0 )
         dsi->load_symtab = 1;
 
     dsi->v_kernstart = kernstart;
diff -r 51a98a6c2c05 -r 551495fa7b3e xen/include/xen/sched.h
--- a/xen/include/xen/sched.h   Wed Aug 23 18:38:08 2006 +0100
+++ b/xen/include/xen/sched.h   Wed Aug 23 18:39:17 2006 +0100
@@ -179,13 +179,24 @@ struct domain_setup_info
     unsigned long v_kernstart;
     unsigned long v_kernend;
     unsigned long v_kernentry;
+#define PAEKERN_no           0
+#define PAEKERN_yes          1
+#define PAEKERN_extended_cr3 2
+    unsigned int  pae_kernel;
     /* Initialised by loader: Private. */
     unsigned long elf_paddr_offset;
     unsigned int  load_symtab;
     unsigned long symtab_addr;
     unsigned long symtab_len;
-    /* Indicate whether it's xen specific image */
+    /*
+     * Only one of __elfnote_* or __xen_guest_string will be
+     * non-NULL.
+     *
+     * You should use the xen_elfnote_* accessors below in order to
+     * pickup the correct one and retain backwards compatibility.
+     */
     void *__elfnote_section, *__elfnote_section_end;
+    char *__xen_guest_string;
 };
 
 extern struct vcpu *idle_vcpu[NR_CPUS];

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>