[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [XEN] Restore backwards compatibility by supporting __xen_guest
# HG changeset patch # User Ian Campbell <ian.campbell@xxxxxxxxxxxxx> # Node ID 2eb8efcc70d1744198d729e1caf2a59b046b178b # Parent cc006f78cbe20d0b84f7e80c2b1fac6c9eb7dc29 [XEN] Restore backwards compatibility by supporting __xen_guest section in dom0 loader. Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxxxxx> --- xen/arch/x86/domain_build.c | 13 --- xen/common/elf.c | 163 ++++++++++++++++++++++++++++++++++++++++---- xen/include/xen/sched.h | 13 +++ 3 files changed, 166 insertions(+), 23 deletions(-) diff -r cc006f78cbe2 -r 2eb8efcc70d1 xen/arch/x86/domain_build.c --- a/xen/arch/x86/domain_build.c Wed Aug 23 18:35:21 2006 +0100 +++ b/xen/arch/x86/domain_build.c Wed Aug 23 18:38:49 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 cc006f78cbe2 -r 2eb8efcc70d1 xen/common/elf.c --- a/xen/common/elf.c Wed Aug 23 18:35:21 2006 +0100 +++ b/xen/common/elf.c Wed Aug 23 18:38:49 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 cc006f78cbe2 -r 2eb8efcc70d1 xen/include/xen/sched.h --- a/xen/include/xen/sched.h Wed Aug 23 18:35:21 2006 +0100 +++ b/xen/include/xen/sched.h Wed Aug 23 18:38:49 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |