debuggers.hg
changeset 11283:2eb8efcc70d1
[XEN] Restore backwards compatibility by supporting __xen_guest
section in dom0 loader.
Signed-off-by: Ian Campbell <ian.campbell@xensource.com>
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];