--- a/xen/include/xen/sched.h 2006-12-12 16:59:57.000000000 -0700 +++ b/xen/include/xen/sched.h 2006-12-12 17:00:59.000000000 -0700 @@ -188,6 +188,7 @@ #define PAEKERN_no 0 #define PAEKERN_yes 1 #define PAEKERN_extended_cr3 2 +#define PAEKERN_bimodal 3 unsigned int pae_kernel; /* Initialised by loader: Private. */ unsigned long elf_paddr_offset; --- a/xen/common/elf.c 2006-12-12 16:43:43.000000000 -0700 +++ b/xen/common/elf.c 2006-12-12 16:58:10.000000000 -0700 @@ -286,6 +286,8 @@ } /* + * A "bimodal" ELF note indicates the kernel will adjust to the + * current paging mode, including handling extended cr3 syntax. * 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. @@ -294,9 +296,10 @@ if ( dsi->__elfnote_section ) { p = xen_elfnote_string(dsi, XEN_ELFNOTE_PAE_MODE); - if ( p != NULL && strncmp(p, "yes", 3) == 0 ) + if ( p != NULL && strncmp(p, "bimodal", 7) == 0 ) + dsi->pae_kernel = PAEKERN_bimodal; + else if ( p != NULL && strncmp(p, "yes", 3) == 0 ) dsi->pae_kernel = PAEKERN_extended_cr3; - } else { --- a/xen/arch/x86/domain_build.c 2006-12-12 17:02:08.000000000 -0700 +++ b/xen/arch/x86/domain_build.c 2006-12-12 17:43:35.000000000 -0700 @@ -321,8 +321,11 @@ if ( (rc = parseelfimage(&dsi)) != 0 ) return rc; - dom0_pae = (dsi.pae_kernel != PAEKERN_no); xen_pae = (CONFIG_PAGING_LEVELS == 3); + if (dsi.pae_kernel == PAEKERN_bimodal) + dom0_pae = xen_pae; + else + dom0_pae = (dsi.pae_kernel != PAEKERN_no); if ( dom0_pae != xen_pae ) { printk("PAE mode mismatch between Xen and DOM0 (xen=%s, dom0=%s)\n", @@ -330,7 +333,8 @@ return -EINVAL; } - if ( xen_pae && dsi.pae_kernel == PAEKERN_extended_cr3 ) + if ( xen_pae && (dsi.pae_kernel == PAEKERN_extended_cr3 || + dsi.pae_kernel == PAEKERN_bimodal) ) set_bit(VMASST_TYPE_pae_extended_cr3, &d->vm_assist); if ( (p = xen_elfnote_string(&dsi, XEN_ELFNOTE_FEATURES)) != NULL ) --- a/tools/libxc/xg_private.h 2006-12-12 17:14:48.000000000 -0700 +++ b/tools/libxc/xg_private.h 2006-12-12 17:15:48.000000000 -0700 @@ -132,6 +132,7 @@ #define PAEKERN_no 0 #define PAEKERN_yes 1 #define PAEKERN_extended_cr3 2 +#define PAEKERN_bimodal 3 unsigned int pae_kernel; unsigned int load_symtab; --- a/tools/libxc/xc_load_elf.c 2006-12-13 07:37:37.000000000 -0700 +++ b/tools/libxc/xc_load_elf.c 2006-12-13 07:37:26.000000000 -0700 @@ -325,17 +325,6 @@ return -EINVAL; } - /* Find the section-header strings table. */ - if ( ehdr->e_shstrndx == SHN_UNDEF ) - { - xc_set_error(XC_INVALID_KERNEL, - "ELF image has no section-header strings table (shstrtab)."); - return -EINVAL; - } - shdr = (Elf_Shdr *)(image + ehdr->e_shoff + - (ehdr->e_shstrndx*ehdr->e_shentsize)); - shstrtab = image + shdr->sh_offset; - dsi->__elfnote_section = NULL; dsi->__xen_guest_string = NULL; @@ -354,6 +343,17 @@ /* Fall back to looking for the special '__xen_guest' section. */ if ( dsi->__elfnote_section == NULL ) { + /* Find the section-header strings table. */ + if ( ehdr->e_shstrndx == SHN_UNDEF ) + { + xc_set_error(XC_INVALID_KERNEL, + "ELF image has no section-header strings table (shstrtab)."); + return -EINVAL; + } + shdr = (Elf_Shdr *)(image + ehdr->e_shoff + + (ehdr->e_shstrndx*ehdr->e_shentsize)); + shstrtab = image + shdr->sh_offset; + for ( h = 0; h < ehdr->e_shnum; h++ ) { shdr = (Elf_Shdr *)(image + ehdr->e_shoff + (h*ehdr->e_shentsize)); @@ -400,6 +400,8 @@ } /* + * A "bimodal" ELF note indicates the kernel will adjust to the + * current paging mode, including handling extended cr3 syntax. * 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. @@ -408,7 +410,9 @@ if ( dsi->__elfnote_section ) { p = xen_elfnote_string(dsi, XEN_ELFNOTE_PAE_MODE); - if ( p != NULL && strncmp(p, "yes", 3) == 0 ) + if ( p != NULL && strncmp(p, "bimodal", 7) == 0 ) + dsi->pae_kernel = PAEKERN_bimodal; + else if ( p != NULL && strncmp(p, "yes", 3) == 0 ) dsi->pae_kernel = PAEKERN_extended_cr3; } --- a/tools/libxc/xc_linux_build.c 2006-12-12 17:31:16.000000000 -0700 +++ b/tools/libxc/xc_linux_build.c 2006-12-12 17:34:19.000000000 -0700 @@ -596,15 +596,21 @@ } if (strstr(xen_caps, "xen-3.0-x86_32p")) { + if (dsi->pae_kernel == PAEKERN_bimodal) + dsi->pae_kernel = PAEKERN_extended_cr3; if (dsi->pae_kernel == PAEKERN_no) { xc_set_error(XC_INVALID_KERNEL, "Non PAE-kernel on PAE host."); return 0; } - } else if (dsi->pae_kernel != PAEKERN_no) { - xc_set_error(XC_INVALID_KERNEL, - "PAE-kernel on non-PAE host."); - return 0; + } else { + if (dsi->pae_kernel == PAEKERN_bimodal) + dsi->pae_kernel = PAEKERN_no; + else if (dsi->pae_kernel != PAEKERN_no) { + xc_set_error(XC_INVALID_KERNEL, + "PAE-kernel on non-PAE host."); + return 0; + } } return 1;