direct-io.hg

view tools/libxc/xc_linux_build.c @ 3452:707455ee2ff6

bitkeeper revision 1.1159.217.20 (41ebdda5ZO9YBU_VHuSh0IwgcQe0Ng)

Merge arcadians.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-unstable.bk
into arcadians.cl.cam.ac.uk:/local/scratch-2/cl349/xen-unstable.bk-merge
author cl349@arcadians.cl.cam.ac.uk
date Mon Jan 17 15:45:41 2005 +0000 (2005-01-17)
parents 6096356005ba 90f0ae7be1de
children 3c69b6ca4021
line source
1 /******************************************************************************
2 * xc_linux_build.c
3 */
5 #include "xc_private.h"
6 #define ELFSIZE 32
7 #include "xc_elf.h"
8 #include <stdlib.h>
9 #include <zlib.h>
11 #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
12 #define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
14 #define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
15 #define round_pgdown(_p) ((_p)&PAGE_MASK)
17 struct domain_setup_info
18 {
19 unsigned long v_start;
20 unsigned long v_end;
21 unsigned long v_kernstart;
22 unsigned long v_kernend;
23 unsigned long v_kernentry;
25 unsigned int use_writable_pagetables;
26 unsigned int load_bsd_symtab;
28 unsigned long symtab_addr;
29 unsigned long symtab_len;
30 };
32 static int
33 parseelfimage(
34 char *elfbase, unsigned long elfsize, struct domain_setup_info *dsi);
35 static int
36 loadelfimage(
37 char *elfbase, int xch, u32 dom, unsigned long *parray,
38 unsigned long vstart);
39 static int
40 loadelfsymtab(
41 char *elfbase, int xch, u32 dom, unsigned long *parray,
42 struct domain_setup_info *dsi);
44 static int setup_guestos(int xc_handle,
45 u32 dom,
46 char *image, unsigned long image_size,
47 gzFile initrd_gfd, unsigned long initrd_len,
48 unsigned long nr_pages,
49 unsigned long *pvsi, unsigned long *pvke,
50 full_execution_context_t *ctxt,
51 const char *cmdline,
52 unsigned long shared_info_frame,
53 unsigned int control_evtchn,
54 unsigned long flags,
55 unsigned int vcpus)
56 {
57 l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
58 l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
59 unsigned long *page_array = NULL;
60 unsigned long l2tab;
61 unsigned long l1tab;
62 unsigned long count, i;
63 start_info_t *start_info;
64 shared_info_t *shared_info;
65 mmu_t *mmu = NULL;
66 int rc;
68 unsigned long nr_pt_pages;
69 unsigned long ppt_alloc;
70 unsigned long *physmap, *physmap_e, physmap_pfn;
72 struct domain_setup_info dsi;
73 unsigned long vinitrd_start;
74 unsigned long vinitrd_end;
75 unsigned long vphysmap_start;
76 unsigned long vphysmap_end;
77 unsigned long vstartinfo_start;
78 unsigned long vstartinfo_end;
79 unsigned long vstack_start;
80 unsigned long vstack_end;
81 unsigned long vpt_start;
82 unsigned long vpt_end;
83 unsigned long v_end;
85 memset(&dsi, 0, sizeof(struct domain_setup_info));
87 rc = parseelfimage(image, image_size, &dsi);
88 if ( rc != 0 )
89 goto error_out;
91 if (dsi.use_writable_pagetables)
92 xc_domain_setvmassist(xc_handle, dom, VMASST_CMD_enable,
93 VMASST_TYPE_writable_pagetables);
95 if (dsi.load_bsd_symtab)
96 loadelfsymtab(image, xc_handle, dom, NULL, &dsi);
98 if ( (dsi.v_start & (PAGE_SIZE-1)) != 0 )
99 {
100 PERROR("Guest OS must load to a page boundary.\n");
101 goto error_out;
102 }
104 /*
105 * Why do we need this? The number of page-table frames depends on the
106 * size of the bootstrap address space. But the size of the address space
107 * depends on the number of page-table frames (since each one is mapped
108 * read-only). We have a pair of simultaneous equations in two unknowns,
109 * which we solve by exhaustive search.
110 */
111 vinitrd_start = round_pgup(dsi.v_end);
112 vinitrd_end = vinitrd_start + initrd_len;
113 vphysmap_start = round_pgup(vinitrd_end);
114 vphysmap_end = vphysmap_start + (nr_pages * sizeof(unsigned long));
115 vpt_start = round_pgup(vphysmap_end);
116 for ( nr_pt_pages = 2; ; nr_pt_pages++ )
117 {
118 vpt_end = vpt_start + (nr_pt_pages * PAGE_SIZE);
119 vstartinfo_start = vpt_end;
120 vstartinfo_end = vstartinfo_start + PAGE_SIZE;
121 vstack_start = vstartinfo_end;
122 vstack_end = vstack_start + PAGE_SIZE;
123 v_end = (vstack_end + (1<<22)-1) & ~((1<<22)-1);
124 if ( (v_end - vstack_end) < (512 << 10) )
125 v_end += 1 << 22; /* Add extra 4MB to get >= 512kB padding. */
126 if ( (((v_end - dsi.v_start + ((1<<L2_PAGETABLE_SHIFT)-1)) >>
127 L2_PAGETABLE_SHIFT) + 1) <= nr_pt_pages )
128 break;
129 }
131 printf("VIRTUAL MEMORY ARRANGEMENT:\n"
132 " Loaded kernel: %08lx->%08lx\n"
133 " Init. ramdisk: %08lx->%08lx\n"
134 " Phys-Mach map: %08lx->%08lx\n"
135 " Page tables: %08lx->%08lx\n"
136 " Start info: %08lx->%08lx\n"
137 " Boot stack: %08lx->%08lx\n"
138 " TOTAL: %08lx->%08lx\n",
139 dsi.v_kernstart, dsi.v_kernend,
140 vinitrd_start, vinitrd_end,
141 vphysmap_start, vphysmap_end,
142 vpt_start, vpt_end,
143 vstartinfo_start, vstartinfo_end,
144 vstack_start, vstack_end,
145 dsi.v_start, v_end);
146 printf(" ENTRY ADDRESS: %08lx\n", dsi.v_kernentry);
148 if ( (v_end - dsi.v_start) > (nr_pages * PAGE_SIZE) )
149 {
150 printf("Initial guest OS requires too much space\n"
151 "(%luMB is greater than %luMB limit)\n",
152 (v_end-dsi.v_start)>>20, (nr_pages<<PAGE_SHIFT)>>20);
153 goto error_out;
154 }
156 if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL )
157 {
158 PERROR("Could not allocate memory");
159 goto error_out;
160 }
162 if ( xc_get_pfn_list(xc_handle, dom, page_array, nr_pages) != nr_pages )
163 {
164 PERROR("Could not get the page frame list");
165 goto error_out;
166 }
168 loadelfimage(image, xc_handle, dom, page_array, dsi.v_start);
170 if (dsi.load_bsd_symtab)
171 loadelfsymtab(image, xc_handle, dom, page_array, &dsi);
173 /* Load the initial ramdisk image. */
174 if ( initrd_len != 0 )
175 {
176 for ( i = (vinitrd_start - dsi.v_start);
177 i < (vinitrd_end - dsi.v_start); i += PAGE_SIZE )
178 {
179 char page[PAGE_SIZE];
180 if ( gzread(initrd_gfd, page, PAGE_SIZE) == -1 )
181 {
182 PERROR("Error reading initrd image, could not");
183 goto error_out;
184 }
185 xc_copy_to_domain_page(xc_handle, dom,
186 page_array[i>>PAGE_SHIFT], page);
187 }
188 }
190 if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL )
191 goto error_out;
193 /* First allocate page for page dir. */
194 ppt_alloc = (vpt_start - dsi.v_start) >> PAGE_SHIFT;
195 l2tab = page_array[ppt_alloc++] << PAGE_SHIFT;
196 ctxt->pt_base = l2tab;
198 /* Initialise the page tables. */
199 if ( (vl2tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
200 PROT_READ|PROT_WRITE,
201 l2tab >> PAGE_SHIFT)) == NULL )
202 goto error_out;
203 memset(vl2tab, 0, PAGE_SIZE);
204 vl2e = &vl2tab[l2_table_offset(dsi.v_start)];
205 for ( count = 0; count < ((v_end-dsi.v_start)>>PAGE_SHIFT); count++ )
206 {
207 if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 )
208 {
209 l1tab = page_array[ppt_alloc++] << PAGE_SHIFT;
210 if ( vl1tab != NULL )
211 munmap(vl1tab, PAGE_SIZE);
212 if ( (vl1tab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
213 PROT_READ|PROT_WRITE,
214 l1tab >> PAGE_SHIFT)) == NULL )
215 {
216 munmap(vl2tab, PAGE_SIZE);
217 goto error_out;
218 }
219 memset(vl1tab, 0, PAGE_SIZE);
220 vl1e = &vl1tab[l1_table_offset(dsi.v_start + (count<<PAGE_SHIFT))];
221 *vl2e++ = l1tab | L2_PROT;
222 }
224 *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
225 if ( (count >= ((vpt_start-dsi.v_start)>>PAGE_SHIFT)) &&
226 (count < ((vpt_end -dsi.v_start)>>PAGE_SHIFT)) )
227 *vl1e &= ~_PAGE_RW;
228 vl1e++;
229 }
230 munmap(vl1tab, PAGE_SIZE);
231 munmap(vl2tab, PAGE_SIZE);
233 /* Write the phys->machine and machine->phys table entries. */
234 physmap_pfn = (vphysmap_start - dsi.v_start) >> PAGE_SHIFT;
235 physmap = physmap_e = xc_map_foreign_range(
236 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
237 page_array[physmap_pfn++]);
238 for ( count = 0; count < nr_pages; count++ )
239 {
240 if ( add_mmu_update(xc_handle, mmu,
241 (page_array[count] << PAGE_SHIFT) |
242 MMU_MACHPHYS_UPDATE, count) )
243 {
244 munmap(physmap, PAGE_SIZE);
245 goto error_out;
246 }
247 *physmap_e++ = page_array[count];
248 if ( ((unsigned long)physmap_e & (PAGE_SIZE-1)) == 0 )
249 {
250 munmap(physmap, PAGE_SIZE);
251 physmap = physmap_e = xc_map_foreign_range(
252 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
253 page_array[physmap_pfn++]);
254 }
255 }
256 munmap(physmap, PAGE_SIZE);
258 /*
259 * Pin down l2tab addr as page dir page - causes hypervisor to provide
260 * correct protection for the page
261 */
262 if ( add_mmu_update(xc_handle, mmu,
263 l2tab | MMU_EXTENDED_COMMAND, MMUEXT_PIN_L2_TABLE) )
264 goto error_out;
266 start_info = xc_map_foreign_range(
267 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
268 page_array[(vstartinfo_start-dsi.v_start)>>PAGE_SHIFT]);
269 memset(start_info, 0, sizeof(*start_info));
270 start_info->nr_pages = nr_pages;
271 start_info->shared_info = shared_info_frame << PAGE_SHIFT;
272 start_info->flags = flags;
273 start_info->pt_base = vpt_start;
274 start_info->nr_pt_frames = nr_pt_pages;
275 start_info->mfn_list = vphysmap_start;
276 start_info->domain_controller_evtchn = control_evtchn;
277 if ( initrd_len != 0 )
278 {
279 start_info->mod_start = vinitrd_start;
280 start_info->mod_len = initrd_len;
281 }
282 strncpy(start_info->cmd_line, cmdline, MAX_CMDLINE);
283 start_info->cmd_line[MAX_CMDLINE-1] = '\0';
284 munmap(start_info, PAGE_SIZE);
286 /* shared_info page starts its life empty. */
287 shared_info = xc_map_foreign_range(
288 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, shared_info_frame);
289 memset(shared_info, 0, sizeof(shared_info_t));
290 /* Mask all upcalls... */
291 for ( i = 0; i < MAX_VIRT_CPUS; i++ )
292 shared_info->vcpu_data[i].evtchn_upcall_mask = 1;
294 shared_info->n_vcpu = vcpus;
295 printf(" VCPUS: %d\n", shared_info->n_vcpu);
297 munmap(shared_info, PAGE_SIZE);
299 /* Send the page update requests down to the hypervisor. */
300 if ( finish_mmu_updates(xc_handle, mmu) )
301 goto error_out;
303 free(mmu);
304 free(page_array);
306 *pvsi = vstartinfo_start;
307 *pvke = dsi.v_kernentry;
309 return 0;
311 error_out:
312 if ( mmu != NULL )
313 free(mmu);
314 if ( page_array != NULL )
315 free(page_array);
316 return -1;
317 }
319 int xc_linux_build(int xc_handle,
320 u32 domid,
321 const char *image_name,
322 const char *ramdisk_name,
323 const char *cmdline,
324 unsigned int control_evtchn,
325 unsigned long flags,
326 unsigned int vcpus)
327 {
328 dom0_op_t launch_op, op;
329 int initrd_fd = -1;
330 gzFile initrd_gfd = NULL;
331 int rc, i;
332 full_execution_context_t st_ctxt, *ctxt = &st_ctxt;
333 unsigned long nr_pages;
334 char *image = NULL;
335 unsigned long image_size, initrd_size=0;
336 unsigned long vstartinfo_start, vkern_entry;
338 if ( (nr_pages = xc_get_tot_pages(xc_handle, domid)) < 0 )
339 {
340 PERROR("Could not find total pages for domain");
341 goto error_out;
342 }
344 if ( (image = xc_read_kernel_image(image_name, &image_size)) == NULL )
345 goto error_out;
347 if ( (ramdisk_name != NULL) && (strlen(ramdisk_name) != 0) )
348 {
349 if ( (initrd_fd = open(ramdisk_name, O_RDONLY)) < 0 )
350 {
351 PERROR("Could not open the initial ramdisk image");
352 goto error_out;
353 }
355 initrd_size = xc_get_filesz(initrd_fd);
357 if ( (initrd_gfd = gzdopen(initrd_fd, "rb")) == NULL )
358 {
359 PERROR("Could not allocate decompression state for initrd");
360 goto error_out;
361 }
362 }
364 if ( mlock(&st_ctxt, sizeof(st_ctxt) ) )
365 {
366 PERROR("Unable to mlock ctxt");
367 return 1;
368 }
370 op.cmd = DOM0_GETDOMAININFO;
371 op.u.getdomaininfo.domain = (domid_t)domid;
372 op.u.getdomaininfo.exec_domain = 0;
373 op.u.getdomaininfo.ctxt = ctxt;
374 if ( (do_dom0_op(xc_handle, &op) < 0) ||
375 ((u16)op.u.getdomaininfo.domain != domid) )
376 {
377 PERROR("Could not get info on domain");
378 goto error_out;
379 }
380 if ( !(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) ||
381 (ctxt->pt_base != 0) )
382 {
383 ERROR("Domain is already constructed");
384 goto error_out;
385 }
387 if ( setup_guestos(xc_handle, domid, image, image_size,
388 initrd_gfd, initrd_size, nr_pages,
389 &vstartinfo_start, &vkern_entry,
390 ctxt, cmdline,
391 op.u.getdomaininfo.shared_info_frame,
392 control_evtchn, flags, vcpus) < 0 )
393 {
394 ERROR("Error constructing guest OS");
395 goto error_out;
396 }
398 if ( initrd_fd >= 0 )
399 close(initrd_fd);
400 if ( initrd_gfd )
401 gzclose(initrd_gfd);
402 if ( image != NULL )
403 free(image);
405 ctxt->flags = 0;
407 /*
408 * Initial register values:
409 * DS,ES,FS,GS = FLAT_GUESTOS_DS
410 * CS:EIP = FLAT_GUESTOS_CS:start_pc
411 * SS:ESP = FLAT_GUESTOS_DS:start_stack
412 * ESI = start_info
413 * [EAX,EBX,ECX,EDX,EDI,EBP are zero]
414 * EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
415 */
416 ctxt->cpu_ctxt.ds = FLAT_GUESTOS_DS;
417 ctxt->cpu_ctxt.es = FLAT_GUESTOS_DS;
418 ctxt->cpu_ctxt.fs = FLAT_GUESTOS_DS;
419 ctxt->cpu_ctxt.gs = FLAT_GUESTOS_DS;
420 ctxt->cpu_ctxt.ss = FLAT_GUESTOS_DS;
421 ctxt->cpu_ctxt.cs = FLAT_GUESTOS_CS;
422 ctxt->cpu_ctxt.eip = vkern_entry;
423 ctxt->cpu_ctxt.esp = vstartinfo_start + 2*PAGE_SIZE;
424 ctxt->cpu_ctxt.esi = vstartinfo_start;
425 ctxt->cpu_ctxt.eflags = (1<<9) | (1<<2);
427 /* FPU is set up to default initial state. */
428 memset(ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
430 /* Virtual IDT is empty at start-of-day. */
431 for ( i = 0; i < 256; i++ )
432 {
433 ctxt->trap_ctxt[i].vector = i;
434 ctxt->trap_ctxt[i].cs = FLAT_GUESTOS_CS;
435 }
436 ctxt->fast_trap_idx = 0;
438 /* No LDT. */
439 ctxt->ldt_ents = 0;
441 /* Use the default Xen-provided GDT. */
442 ctxt->gdt_ents = 0;
444 /* Ring 1 stack is the initial stack. */
445 ctxt->guestos_ss = FLAT_GUESTOS_DS;
446 ctxt->guestos_esp = vstartinfo_start + 2*PAGE_SIZE;
448 /* No debugging. */
449 memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
451 /* No callback handlers. */
452 ctxt->event_callback_cs = FLAT_GUESTOS_CS;
453 ctxt->event_callback_eip = 0;
454 ctxt->failsafe_callback_cs = FLAT_GUESTOS_CS;
455 ctxt->failsafe_callback_eip = 0;
457 memset( &launch_op, 0, sizeof(launch_op) );
459 launch_op.u.builddomain.domain = (domid_t)domid;
460 launch_op.u.builddomain.ctxt = ctxt;
462 launch_op.cmd = DOM0_BUILDDOMAIN;
463 rc = do_dom0_op(xc_handle, &launch_op);
465 return rc;
467 error_out:
468 if ( initrd_gfd != NULL )
469 gzclose(initrd_gfd);
470 else if ( initrd_fd >= 0 )
471 close(initrd_fd);
472 if ( image != NULL )
473 free(image);
475 return -1;
476 }
478 static inline int is_loadable_phdr(Elf_Phdr *phdr)
479 {
480 return ((phdr->p_type == PT_LOAD) &&
481 ((phdr->p_flags & (PF_W|PF_X)) != 0));
482 }
484 static int parseelfimage(char *elfbase,
485 unsigned long elfsize,
486 struct domain_setup_info *dsi)
487 {
488 Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase;
489 Elf_Phdr *phdr;
490 Elf_Shdr *shdr;
491 unsigned long kernstart = ~0UL, kernend=0UL;
492 char *shstrtab, *guestinfo=NULL, *p;
493 int h;
495 if ( !IS_ELF(*ehdr) )
496 {
497 ERROR("Kernel image does not have an ELF header.");
498 return -EINVAL;
499 }
501 if ( (ehdr->e_phoff + (ehdr->e_phnum * ehdr->e_phentsize)) > elfsize )
502 {
503 ERROR("ELF program headers extend beyond end of image.");
504 return -EINVAL;
505 }
507 if ( (ehdr->e_shoff + (ehdr->e_shnum * ehdr->e_shentsize)) > elfsize )
508 {
509 ERROR("ELF section headers extend beyond end of image.");
510 return -EINVAL;
511 }
513 /* Find the section-header strings table. */
514 if ( ehdr->e_shstrndx == SHN_UNDEF )
515 {
516 ERROR("ELF image has no section-header strings table (shstrtab).");
517 return -EINVAL;
518 }
519 shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff +
520 (ehdr->e_shstrndx*ehdr->e_shentsize));
521 shstrtab = elfbase + shdr->sh_offset;
523 /* Find the special '__xen_guest' section and check its contents. */
524 for ( h = 0; h < ehdr->e_shnum; h++ )
525 {
526 shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff + (h*ehdr->e_shentsize));
527 if ( strcmp(&shstrtab[shdr->sh_name], "__xen_guest") != 0 )
528 continue;
530 guestinfo = elfbase + shdr->sh_offset;
532 if ( (strstr(guestinfo, "LOADER=generic") == NULL) &&
533 (strstr(guestinfo, "GUEST_OS=linux") == NULL) )
534 {
535 ERROR("Will only load images built for the generic loader "
536 "or Linux images");
537 ERROR("Actually saw: '%s'", guestinfo);
538 return -EINVAL;
539 }
541 if ( (strstr(guestinfo, "XEN_VER=2.0") == NULL) )
542 {
543 ERROR("Will only load images built for Xen v2.0");
544 ERROR("Actually saw: '%s'", guestinfo);
545 return -EINVAL;
546 }
548 break;
549 }
550 if ( guestinfo == NULL )
551 {
552 ERROR("Not a Xen-ELF image: '__xen_guest' section not found.");
553 return -EINVAL;
554 }
556 for ( h = 0; h < ehdr->e_phnum; h++ )
557 {
558 phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
559 if ( !is_loadable_phdr(phdr) )
560 continue;
561 if ( phdr->p_vaddr < kernstart )
562 kernstart = phdr->p_vaddr;
563 if ( (phdr->p_vaddr + phdr->p_memsz) > kernend )
564 kernend = phdr->p_vaddr + phdr->p_memsz;
565 }
567 if ( (kernstart > kernend) ||
568 (ehdr->e_entry < kernstart) ||
569 (ehdr->e_entry > kernend) )
570 {
571 ERROR("Malformed ELF image.");
572 return -EINVAL;
573 }
575 dsi->v_start = kernstart;
576 if ( (p = strstr(guestinfo, "VIRT_BASE=")) != NULL )
577 dsi->v_start = strtoul(p+10, &p, 0);
579 if ( (p = strstr(guestinfo, "PT_MODE_WRITABLE")) != NULL )
580 dsi->use_writable_pagetables = 1;
582 if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL )
583 dsi->load_bsd_symtab = 1;
585 dsi->v_kernstart = kernstart;
586 dsi->v_kernend = kernend;
587 dsi->v_kernentry = ehdr->e_entry;
589 dsi->v_end = dsi->v_kernend;
591 return 0;
592 }
594 static int
595 loadelfimage(
596 char *elfbase, int xch, u32 dom, unsigned long *parray,
597 unsigned long vstart)
598 {
599 Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase;
600 Elf_Phdr *phdr;
601 int h;
603 char *va;
604 unsigned long pa, done, chunksz;
606 for ( h = 0; h < ehdr->e_phnum; h++ )
607 {
608 phdr = (Elf_Phdr *)(elfbase + ehdr->e_phoff + (h*ehdr->e_phentsize));
609 if ( !is_loadable_phdr(phdr) )
610 continue;
612 for ( done = 0; done < phdr->p_filesz; done += chunksz )
613 {
614 pa = (phdr->p_vaddr + done) - vstart;
615 va = xc_map_foreign_range(
616 xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
617 chunksz = phdr->p_filesz - done;
618 if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
619 chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
620 memcpy(va + (pa & (PAGE_SIZE-1)),
621 elfbase + phdr->p_offset + done, chunksz);
622 munmap(va, PAGE_SIZE);
623 }
625 for ( ; done < phdr->p_memsz; done += chunksz )
626 {
627 pa = (phdr->p_vaddr + done) - vstart;
628 va = xc_map_foreign_range(
629 xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]);
630 chunksz = phdr->p_memsz - done;
631 if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
632 chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
633 memset(va + (pa & (PAGE_SIZE-1)), 0, chunksz);
634 munmap(va, PAGE_SIZE);
635 }
636 }
638 return 0;
639 }
641 #define ELFROUND (ELFSIZE / 8)
643 static int
644 loadelfsymtab(
645 char *elfbase, int xch, u32 dom, unsigned long *parray,
646 struct domain_setup_info *dsi)
647 {
648 Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase, *sym_ehdr;
649 Elf_Shdr *shdr;
650 unsigned long maxva, symva;
651 char *p;
652 int h, i;
654 p = malloc(sizeof(int) + sizeof(Elf_Ehdr) +
655 ehdr->e_shnum * sizeof(Elf_Shdr));
656 if (p == NULL)
657 return 0;
659 maxva = (dsi->v_kernend + ELFROUND - 1) & ~(ELFROUND - 1);
660 symva = maxva;
661 maxva += sizeof(int);
662 dsi->symtab_addr = maxva;
663 dsi->symtab_len = 0;
664 maxva += sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr);
665 maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
667 shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
668 memcpy(shdr, elfbase + ehdr->e_shoff, ehdr->e_shnum * sizeof(Elf_Shdr));
670 for ( h = 0; h < ehdr->e_shnum; h++ )
671 {
672 if ( shdr[h].sh_type == SHT_STRTAB )
673 {
674 /* Look for a strtab @i linked to symtab @h. */
675 for ( i = 0; i < ehdr->e_shnum; i++ )
676 if ( (shdr[i].sh_type == SHT_SYMTAB) &&
677 (shdr[i].sh_link == h) )
678 break;
679 /* Skip symtab @h if we found no corresponding strtab @i. */
680 if ( i == ehdr->e_shnum )
681 {
682 shdr[h].sh_offset = 0;
683 continue;
684 }
685 }
687 if ( (shdr[h].sh_type == SHT_STRTAB) ||
688 (shdr[h].sh_type == SHT_SYMTAB) )
689 {
690 if ( parray != NULL )
691 xc_map_memcpy(maxva, elfbase + shdr[h].sh_offset, shdr[h].sh_size,
692 xch, dom, parray, dsi->v_start);
694 /* Mangled to be based on ELF header location. */
695 shdr[h].sh_offset = maxva - dsi->symtab_addr;
697 dsi->symtab_len += shdr[h].sh_size;
698 maxva += shdr[h].sh_size;
699 maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
700 }
702 shdr[h].sh_name = 0; /* Name is NULL. */
703 }
705 if ( dsi->symtab_len == 0 )
706 {
707 dsi->symtab_addr = 0;
708 goto out;
709 }
711 if ( parray != NULL )
712 {
713 *(int *)p = maxva - dsi->symtab_addr;
714 sym_ehdr = (Elf_Ehdr *)(p + sizeof(int));
715 memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr));
716 sym_ehdr->e_phoff = 0;
717 sym_ehdr->e_shoff = sizeof(Elf_Ehdr);
718 sym_ehdr->e_phentsize = 0;
719 sym_ehdr->e_phnum = 0;
720 sym_ehdr->e_shstrndx = SHN_UNDEF;
722 /* Copy total length, crafted ELF header and section header table */
723 xc_map_memcpy(symva, p, sizeof(int) + sizeof(Elf_Ehdr) +
724 ehdr->e_shnum * sizeof(Elf_Shdr), xch, dom, parray,
725 dsi->v_start);
726 }
728 dsi->symtab_len = maxva - dsi->symtab_addr;
729 dsi->v_end = round_pgup(maxva);
731 out:
732 if ( p != NULL )
733 free(p);
735 return 0;
736 }