ia64/xen-unstable

view tools/libxc/xc_load_elf.c @ 9488:0a6f5527ca4b

[IA64] set itv handoff as masked and enable reading irr[0-3]

Set initial vcpu itv handoff state to mask the timer vector.
This seems to match hardware and makes logical sense from a
spurious interrupt perspective. Enable vcpu_get_irr[0-3]
functions as they seem to work and have the proper backing.
This enables the check_sal_cache_flush() in arch/ia64/kernel.sal.c
to work unmodified, allowing us to remove the Xen changes from
the file (and thus the file from the sparse tree).

Signed-off-by: Alex Williamson <alex.williamson@hp.com>
author awilliam@xenbuild.aw
date Tue Apr 04 09:39:45 2006 -0600 (2006-04-04)
parents a1fcee3b2abe
children 86db4688d514
line source
1 /******************************************************************************
2 * xc_elf_load.c
3 */
5 #include "xg_private.h"
7 #if defined(__i386__)
8 #define ELFSIZE 32
9 #endif
10 #if defined(__x86_64__) || defined(__ia64__)
11 #define ELFSIZE 64
12 #endif
14 #include "xc_elf.h"
15 #include <stdlib.h>
17 #define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
18 #define round_pgdown(_p) ((_p)&PAGE_MASK)
20 static int
21 parseelfimage(
22 const char *image, unsigned long image_size,
23 struct domain_setup_info *dsi);
24 static int
25 loadelfimage(
26 const char *image, unsigned long image_size, int xch, uint32_t dom,
27 unsigned long *parray, struct domain_setup_info *dsi);
28 static int
29 loadelfsymtab(
30 const char *image, int xch, uint32_t dom, unsigned long *parray,
31 struct domain_setup_info *dsi);
33 int probe_elf(const char *image,
34 unsigned long image_size,
35 struct load_funcs *load_funcs)
36 {
37 Elf_Ehdr *ehdr = (Elf_Ehdr *)image;
39 if ( !IS_ELF(*ehdr) )
40 return -EINVAL;
42 load_funcs->parseimage = parseelfimage;
43 load_funcs->loadimage = loadelfimage;
45 return 0;
46 }
48 static inline int is_loadable_phdr(Elf_Phdr *phdr)
49 {
50 return ((phdr->p_type == PT_LOAD) &&
51 ((phdr->p_flags & (PF_W|PF_X)) != 0));
52 }
54 static int parseelfimage(const char *image,
55 unsigned long elfsize,
56 struct domain_setup_info *dsi)
57 {
58 Elf_Ehdr *ehdr = (Elf_Ehdr *)image;
59 Elf_Phdr *phdr;
60 Elf_Shdr *shdr;
61 unsigned long kernstart = ~0UL, kernend=0UL;
62 const char *shstrtab;
63 char *guestinfo=NULL, *p;
64 int h;
66 if ( !IS_ELF(*ehdr) )
67 {
68 ERROR("Kernel image does not have an ELF header.");
69 return -EINVAL;
70 }
72 if ( (ehdr->e_phoff + (ehdr->e_phnum * ehdr->e_phentsize)) > elfsize )
73 {
74 ERROR("ELF program headers extend beyond end of image.");
75 return -EINVAL;
76 }
78 if ( (ehdr->e_shoff + (ehdr->e_shnum * ehdr->e_shentsize)) > elfsize )
79 {
80 ERROR("ELF section headers extend beyond end of image.");
81 return -EINVAL;
82 }
84 /* Find the section-header strings table. */
85 if ( ehdr->e_shstrndx == SHN_UNDEF )
86 {
87 ERROR("ELF image has no section-header strings table (shstrtab).");
88 return -EINVAL;
89 }
90 shdr = (Elf_Shdr *)(image + ehdr->e_shoff +
91 (ehdr->e_shstrndx*ehdr->e_shentsize));
92 shstrtab = image + shdr->sh_offset;
94 /* Find the special '__xen_guest' section and check its contents. */
95 for ( h = 0; h < ehdr->e_shnum; h++ )
96 {
97 shdr = (Elf_Shdr *)(image + ehdr->e_shoff + (h*ehdr->e_shentsize));
98 if ( strcmp(&shstrtab[shdr->sh_name], "__xen_guest") != 0 )
99 continue;
101 guestinfo = (char *)image + shdr->sh_offset;
103 if ( (strstr(guestinfo, "LOADER=generic") == NULL) &&
104 (strstr(guestinfo, "GUEST_OS=linux") == NULL) )
105 {
106 ERROR("Will only load images built for the generic loader "
107 "or Linux images");
108 ERROR("Actually saw: '%s'", guestinfo);
109 return -EINVAL;
110 }
112 if ( (strstr(guestinfo, "XEN_VER=xen-3.0") == NULL) )
113 {
114 ERROR("Will only load images built for Xen v3.0");
115 ERROR("Actually saw: '%s'", guestinfo);
116 return -EINVAL;
117 }
118 if ( (strstr(guestinfo, "PAE=yes") != NULL) )
119 dsi->pae_kernel = 1;
121 break;
122 }
124 if ( guestinfo == NULL )
125 {
126 #ifdef __ia64__
127 guestinfo = "";
128 #else
129 ERROR("Not a Xen-ELF image: '__xen_guest' section not found.");
130 return -EINVAL;
131 #endif
132 }
134 dsi->xen_guest_string = guestinfo;
136 for ( h = 0; h < ehdr->e_phnum; h++ )
137 {
138 phdr = (Elf_Phdr *)(image + ehdr->e_phoff + (h*ehdr->e_phentsize));
139 if ( !is_loadable_phdr(phdr) )
140 continue;
141 if ( phdr->p_paddr < kernstart )
142 kernstart = phdr->p_paddr;
143 if ( (phdr->p_paddr + phdr->p_memsz) > kernend )
144 kernend = phdr->p_paddr + phdr->p_memsz;
145 }
147 if ( (kernstart > kernend) ||
148 (ehdr->e_entry < kernstart) ||
149 (ehdr->e_entry > kernend) )
150 {
151 ERROR("Malformed ELF image.");
152 return -EINVAL;
153 }
155 dsi->v_start = kernstart;
156 if ( (p = strstr(guestinfo, "VIRT_BASE=")) != NULL )
157 dsi->v_start = strtoul(p+10, &p, 0);
159 if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL )
160 dsi->load_symtab = 1;
162 dsi->v_kernstart = kernstart;
163 dsi->v_kernend = kernend;
164 dsi->v_kernentry = ehdr->e_entry;
165 dsi->v_end = dsi->v_kernend;
167 loadelfsymtab(image, 0, 0, NULL, dsi);
169 return 0;
170 }
172 static int
173 loadelfimage(
174 const char *image, unsigned long elfsize, int xch, uint32_t dom,
175 unsigned long *parray, struct domain_setup_info *dsi)
176 {
177 Elf_Ehdr *ehdr = (Elf_Ehdr *)image;
178 Elf_Phdr *phdr;
179 int h;
181 char *va;
182 unsigned long pa, done, chunksz;
184 for ( h = 0; h < ehdr->e_phnum; h++ )
185 {
186 phdr = (Elf_Phdr *)(image + ehdr->e_phoff + (h*ehdr->e_phentsize));
187 if ( !is_loadable_phdr(phdr) )
188 continue;
190 for ( done = 0; done < phdr->p_filesz; done += chunksz )
191 {
192 pa = (phdr->p_paddr + done) - dsi->v_start;
193 va = xc_map_foreign_range(
194 xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
195 chunksz = phdr->p_filesz - done;
196 if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
197 chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
198 memcpy(va + (pa & (PAGE_SIZE-1)),
199 image + phdr->p_offset + done, chunksz);
200 munmap(va, PAGE_SIZE);
201 }
203 for ( ; done < phdr->p_memsz; done += chunksz )
204 {
205 pa = (phdr->p_paddr + done) - dsi->v_start;
206 va = xc_map_foreign_range(
207 xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
208 chunksz = phdr->p_memsz - done;
209 if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
210 chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
211 memset(va + (pa & (PAGE_SIZE-1)), 0, chunksz);
212 munmap(va, PAGE_SIZE);
213 }
214 }
216 loadelfsymtab(image, xch, dom, parray, dsi);
218 return 0;
219 }
221 #define ELFROUND (ELFSIZE / 8)
223 static int
224 loadelfsymtab(
225 const char *image, int xch, uint32_t dom, unsigned long *parray,
226 struct domain_setup_info *dsi)
227 {
228 Elf_Ehdr *ehdr = (Elf_Ehdr *)image, *sym_ehdr;
229 Elf_Shdr *shdr;
230 unsigned long maxva, symva;
231 char *p;
232 int h, i;
234 if ( !dsi->load_symtab )
235 return 0;
237 p = malloc(sizeof(int) + sizeof(Elf_Ehdr) +
238 ehdr->e_shnum * sizeof(Elf_Shdr));
239 if (p == NULL)
240 return 0;
242 maxva = (dsi->v_kernend + ELFROUND - 1) & ~(ELFROUND - 1);
243 symva = maxva;
244 maxva += sizeof(int);
245 dsi->symtab_addr = maxva;
246 dsi->symtab_len = 0;
247 maxva += sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr);
248 maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
250 shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
251 memcpy(shdr, image + ehdr->e_shoff, ehdr->e_shnum * sizeof(Elf_Shdr));
253 for ( h = 0; h < ehdr->e_shnum; h++ )
254 {
255 if ( shdr[h].sh_type == SHT_STRTAB )
256 {
257 /* Look for a strtab @i linked to symtab @h. */
258 for ( i = 0; i < ehdr->e_shnum; i++ )
259 if ( (shdr[i].sh_type == SHT_SYMTAB) &&
260 (shdr[i].sh_link == h) )
261 break;
262 /* Skip symtab @h if we found no corresponding strtab @i. */
263 if ( i == ehdr->e_shnum )
264 {
265 shdr[h].sh_offset = 0;
266 continue;
267 }
268 }
270 if ( (shdr[h].sh_type == SHT_STRTAB) ||
271 (shdr[h].sh_type == SHT_SYMTAB) )
272 {
273 if ( parray != NULL )
274 xc_map_memcpy(maxva, image + shdr[h].sh_offset,
275 shdr[h].sh_size,
276 xch, dom, parray, dsi->v_start);
278 /* Mangled to be based on ELF header location. */
279 shdr[h].sh_offset = maxva - dsi->symtab_addr;
281 dsi->symtab_len += shdr[h].sh_size;
282 maxva += shdr[h].sh_size;
283 maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
284 }
286 shdr[h].sh_name = 0; /* Name is NULL. */
287 }
289 if ( dsi->symtab_len == 0 )
290 {
291 dsi->symtab_addr = 0;
292 goto out;
293 }
295 if ( parray != NULL )
296 {
297 *(int *)p = maxva - dsi->symtab_addr;
298 sym_ehdr = (Elf_Ehdr *)(p + sizeof(int));
299 memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr));
300 sym_ehdr->e_phoff = 0;
301 sym_ehdr->e_shoff = sizeof(Elf_Ehdr);
302 sym_ehdr->e_phentsize = 0;
303 sym_ehdr->e_phnum = 0;
304 sym_ehdr->e_shstrndx = SHN_UNDEF;
306 /* Copy total length, crafted ELF header and section header table */
307 xc_map_memcpy(symva, p, sizeof(int) + sizeof(Elf_Ehdr) +
308 ehdr->e_shnum * sizeof(Elf_Shdr), xch, dom, parray,
309 dsi->v_start);
310 }
312 dsi->symtab_len = maxva - dsi->symtab_addr;
313 dsi->v_end = round_pgup(maxva);
315 out:
316 free(p);
318 return 0;
319 }
321 /*
322 * Local variables:
323 * mode: C
324 * c-set-style: "BSD"
325 * c-basic-offset: 4
326 * tab-width: 4
327 * indent-tabs-mode: nil
328 * End:
329 */