ia64/xen-unstable

view tools/libxc/xc_plan9_build.c @ 3981:b40911fea95b

bitkeeper revision 1.1236.1.55 (42277df7j-1VW2xTCyrLOtTW1Z8OVg)

Merge arcadians.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xeno.bk
into arcadians.cl.cam.ac.uk:/auto/anfs/nos1/akw27/xeno-clone/xeno.bk
author akw27@arcadians.cl.cam.ac.uk
date Thu Mar 03 21:13:27 2005 +0000 (2005-03-03)
parents df7ae5341e20 dadc3f1e1507
children 0914061e11ca
line source
1 /******************************************************************************
2 * xc_plan9_build.c
3 * derived from xc_linux_build.c
4 */
6 #include "xc_private.h"
8 #include <zlib.h>
10 #define DEBUG 1
11 #ifdef DEBUG
12 #define DPRINTF(x) printf x; fflush(stdout);
13 #else
14 #define DPRINTF(x)
15 #endif
17 #include "plan9a.out.h"
19 /* really TOS which means stack starts at 0x2000, and uses page 1*/
20 #define STACKPAGE 2
21 struct Exec header, origheader;
23 typedef struct page {
24 char data[PAGE_SIZE];
25 } PAGE;
28 int
29 memcpy_toguest(int xc_handle, u32 dom, void *v, int size,
30 unsigned long *page_array, unsigned int to_page)
31 {
32 int ret;
33 unsigned char *cp = v;
34 unsigned int whichpage;
35 unsigned char *vaddr;
37 // DPRINTF(("memcpy_to_guest: to_page 0x%x, count %d\n", to_page, size));
38 for (ret = 0, whichpage = to_page; size > 0;
39 whichpage++, size -= PAGE_SIZE, cp += PAGE_SIZE) {
41 // DPRINTF (("map_pfn_writeable(%p, 0x%lx)\n", pm_handle,
42 // page_array[whichpage]));
43 vaddr = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE,
44 PROT_READ | PROT_WRITE,
45 page_array[whichpage]);
46 // DPRINTF (("vaddr is %p\n", vaddr));
47 if (vaddr == NULL) {
48 ret = -1;
49 ERROR("Couldn't map guest memory");
50 goto out;
51 }
52 // DPRINTF (("copy %p to %p, count 0x%x\n", cp, vaddr, 4096));
53 memcpy(vaddr, cp, 4096);
54 munmap(vaddr, PAGE_SIZE);
55 // DPRINTF (("Did %ud'th pages\n", whichpage));
56 }
57 out:
58 return ret;
59 }
61 int
62 blah(char *b)
63 {
64 fprintf(stderr, "Error in xc_plan9_build!\n");
65 perror(b);
66 return errno;
67 }
69 /* swap bytes. For plan 9 headers */
70 void
71 swabby(unsigned long *s, char *name)
72 {
73 unsigned long it;
74 it = ((*s & 0xff000000) >> 24) | ((*s & 0xff0000) >> 8) |
75 ((*s & 0xff00) << 8) | ((*s & 0xff) << 24);
76 DPRINTF(("Item %s is 0x%lx\n", name, it));
77 *s = it;
78 }
80 void
81 plan9header(Exec * header)
82 {
83 /* header is big-endian */
84 swabby(&header->magic, "magic");
85 swabby(&header->text, "text");
86 swabby(&header->data, "data");
87 swabby(&header->bss, "bss");
88 swabby(&header->syms, "syms");
89 swabby(&header->entry, "entry");
90 swabby(&header->spsz, "spsz");
91 swabby(&header->pcsz, "pcsz");
93 }
95 static int
96 loadp9image(gzFile kernel_gfd, int xc_handle, u32 dom,
97 unsigned long *page_array,
98 unsigned long tot_pages, unsigned long *virt_load_addr,
99 unsigned long *ksize, unsigned long *symtab_addr,
100 unsigned long *symtab_len,
101 unsigned long *first_data_page, unsigned long *pdb_page,
102 const char *cmdline);
104 #define P9ROUND (P9SIZE / 8)
106 #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
107 #define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
109 static int
110 setup_guest(int xc_handle,
111 u32 dom,
112 gzFile kernel_gfd,
113 unsigned long tot_pages,
114 unsigned long *virt_startinfo_addr,
115 unsigned long *virt_load_addr,
116 full_execution_context_t * ctxt,
117 const char *cmdline,
118 unsigned long shared_info_frame,
119 unsigned int control_evtchn,
120 int flags)
121 {
122 l1_pgentry_t *vl1e = NULL;
123 l2_pgentry_t *vl2tab = NULL, *vl2e = NULL;
124 unsigned long *cpage_array = NULL;
125 unsigned long *pte_array = NULL;
126 unsigned long l2tab;
127 unsigned long l1tab;
128 unsigned long count;
129 unsigned long symtab_addr = 0, symtab_len = 0;
130 start_info_t *start_info;
131 shared_info_t *shared_info;
132 unsigned long ksize;
133 mmu_t *mmu = NULL;
134 int i;
135 unsigned long first_page_after_kernel,
136 first_data_page,
137 page_array_page;
138 unsigned long cpu0pdb, cpu0pte, cpu0ptelast;
139 unsigned long /*last_pfn, */ tot_pte_pages;
141 DPRINTF(("tot pages is %ld\n", tot_pages));
142 if ((cpage_array = malloc(tot_pages * sizeof (unsigned long))) == NULL) {
143 PERROR("Could not allocate cpage array");
144 goto error_out;
145 }
147 if (xc_get_pfn_list(xc_handle, dom, cpage_array, tot_pages) != tot_pages) {
148 PERROR("Could not get the page frame list");
149 goto error_out;
150 }
152 for (i = 0; i < 64; i++)
153 DPRINTF(("First %d page is 0x%lx\n", i, cpage_array[i]));
155 tot_pte_pages = tot_pages >> 10;
156 DPRINTF(("Page range is 0 to 0x%lx, which requires 0x%lx pte pages\n",
157 tot_pte_pages, tot_pte_pages));
159 if (loadp9image(kernel_gfd, xc_handle, dom, cpage_array, tot_pages,
160 virt_load_addr, &ksize, &symtab_addr, &symtab_len,
161 &first_data_page, &first_page_after_kernel, cmdline))
162 goto error_out;
163 DPRINTF(("First data page is 0x%lx\n", first_data_page));
164 DPRINTF(("First page after kernel is 0x%lx\n",
165 first_page_after_kernel));
167 /*
168 NEED TO INCREMENT first page after kernel by:
169 + 1 (pdb)
170 + tot_pte_pages (pte)
171 + tot_pte_pages (page_array)
172 */
173 /* SO, have to copy the first kernel pages pfns right into the
174 * page_array, then do identity maps for the rest.
175 */
176 DPRINTF(("mapped kernel pages\n"));
178 /* now loop over all ptes and store into the page_array, so as
179 * to get the identity map.
180 */
181 if ((pte_array =
182 malloc(tot_pte_pages * 1024 * sizeof (unsigned long))) == NULL) {
183 PERROR("Could not allocate pte array");
184 goto error_out;
185 }
187 /* plan 9 on startup expects a "l2" (xen parlance) at 0x2000,
188 * this "l2" should have one PTE pointer for a va of 0x80000000.
189 * and an l1 (PTEs to you) at 0x3000. (physical).
190 * the PTEs should map the first 4M of memory.
191 */
192 /* get a physical address for the L2. This means take the PFN and
193 * shift left.
194 */
195 /* this terminology is plan 9 terminology.
196 * pdb is essentially the Xen L2. 'Page Directory Block'?
197 * I need to ask JMK.
198 * cpupte is the pte array.
199 * Plan 9 counts on these being set up for cpu0.
200 * SO: cpu0pdb (Xen L2)
201 * and cpupte (Xen L1)
202 */
203 /* cpu0pdb is right after kernel */
204 cpu0pdb = first_page_after_kernel;
205 /* cpu0pte comes right after cpu0pdb */
206 cpu0pte = cpu0pdb + 1;
207 /* number of the past cpu0pte page */
208 cpu0ptelast = cpu0pte + tot_pte_pages - 1;
209 /* first page of the page array (mfn) */
210 page_array_page = cpu0ptelast + 1;
212 DPRINTF(("cpu0pdb 0x%lx, cpu0pte 0x%lx cpu0ptelast 0x%lx\n", cpu0pdb,
213 cpu0pte, cpu0ptelast));
214 l2tab = cpage_array[cpu0pdb] << PAGE_SHIFT;
215 DPRINTF(("l2tab 0x%lx\n", l2tab));
216 ctxt->pt_base = l2tab;
218 /* get a physical address for the L1. This means take the PFN and
219 * shift left.
220 */
221 l1tab = cpage_array[cpu0pte] << PAGE_SHIFT;
222 DPRINTF(("l1tab 0x%lx\n", l1tab));
223 if ((mmu = init_mmu_updates(xc_handle, dom)) == NULL)
224 goto error_out;
225 DPRINTF(("now map in l2tab\n"));
227 /* Initialise the page tables. */
228 /* mmap in the l2tab */
229 if ((vl2tab = xc_map_foreign_range(xc_handle, dom,
230 PAGE_SIZE, PROT_READ | PROT_WRITE,
231 l2tab >> PAGE_SHIFT)) == NULL)
232 goto error_out;
233 DPRINTF(("vl2tab 0x%p\n", vl2tab));
234 /* now we have the cpu0pdb for the kernel, starting at 0x2000,
235 * so we can plug in the physical pointer to the 0x3000 pte
236 */
237 /* zero it */
238 memset(vl2tab, 0, PAGE_SIZE);
239 /* get a pointer in the l2tab for the virt_load_addr */
240 DPRINTF(("&vl2tab[l2_table_offset(*virt_load_addr)] is 0x%p[0x%lx]\n",
241 &vl2tab[l2_table_offset(*virt_load_addr)],
242 l2_table_offset(*virt_load_addr)));
244 vl2e = &vl2tab[l2_table_offset(*virt_load_addr)];
246 /* OK, for all the available PTE, set the PTE pointer up */
247 DPRINTF(("For i = %ld to %ld ...\n", cpu0pte, cpu0ptelast));
248 for (i = cpu0pte; i <= cpu0ptelast; i++) {
249 DPRINTF(("Index %d Set %p to 0x%lx\n", i, vl2e,
250 (cpage_array[i] << PAGE_SHIFT) | L2_PROT));
251 *vl2e++ = (cpage_array[i] << PAGE_SHIFT) | L2_PROT;
252 }
254 /* unmap it ... */
255 munmap(vl2tab, PAGE_SIZE);
257 /* for the pages from virt_load_pointer to the end of this
258 * set of PTEs, map in the PFN for that VA
259 */
260 for (vl1e = (l1_pgentry_t *) pte_array, count = 0;
261 count < tot_pte_pages * 1024; count++, vl1e++) {
263 *vl1e = cpage_array[count];
264 if (!cpage_array[count])
265 continue;
266 /* set in the PFN for this entry */
267 *vl1e = (cpage_array[count] << PAGE_SHIFT) | L1_PROT;
268 /*
269 DPRINTF (("vl1e # %d 0x%lx gets 0x%lx\n",
270 count, vl1e, *vl1e));
271 */
272 if ((count >= cpu0pdb) && (count <= cpu0ptelast)) {
273 //DPRINTF((" Fix up page %d as it is in pte ville: ", count));
274 *vl1e &= ~_PAGE_RW;
275 DPRINTF(("0x%lx\n", *vl1e));
276 }
277 if ((count >= (0x100000 >> 12))
278 && (count < (first_data_page >> 12))) {
279 //DPRINTF((" Fix up page %d as it is in text ", count));
280 *vl1e &= ~_PAGE_RW;
281 //DPRINTF (("0x%lx\n", *vl1e));
282 }
283 }
284 /* special thing. Pre-map the shared info page */
285 vl1e = &pte_array[2];
286 *vl1e = (shared_info_frame << PAGE_SHIFT) | L1_PROT;
287 DPRINTF(("v1l1 %p, has value 0x%lx\n", vl1e, *(unsigned long *) vl1e));
288 /* another special thing. VA 80005000 has to point to 80006000 */
289 /* this is a Plan 9 thing -- the 'mach' pointer */
290 /* 80005000 is the mach pointer per-cpu, and the actual
291 * mach pointers are 80006000, 80007000 etc.
292 */
293 vl1e = &pte_array[5];
294 *vl1e = (cpage_array[6] << PAGE_SHIFT) | L1_PROT;
296 /* OK, it's all set up, copy it in */
297 memcpy_toguest(xc_handle, dom, pte_array,
298 (tot_pte_pages * 1024 * sizeof (unsigned long) /**/),
299 cpage_array, cpu0pte);
301 /* We really need to have the vl1tab unmapped or the add_mmu_update
302 * below will fail bigtime.
303 */
304 /* Xen guys: remember my errors on domain exit? Something I'm doing
305 * wrong in here? We never did find out ...
306 */
307 /* get rid of the entries we can not use ... */
308 memcpy_toguest(xc_handle, dom, cpage_array,
309 (tot_pte_pages * 1024 * sizeof (unsigned long) /**/),
310 cpage_array, page_array_page);
311 /* last chance to dump all of memory */
312 // dumpit(xc_handle, dom, 0 /*0x100000>>12*/, tot_pages, cpage_array) ;
313 /*
314 * Pin down l2tab addr as page dir page - causes hypervisor to provide
315 * correct protection for the page
316 */
317 if (add_mmu_update(xc_handle, mmu,
318 l2tab | MMU_EXTENDED_COMMAND, MMUEXT_PIN_L2_TABLE))
319 goto error_out;
321 for (count = 0; count < tot_pages; count++) {
322 /*
323 DPRINTF (("add_mmu_update(0x%x, 0x%x, 0x%x, %d)\n", xc_handle, mmu,
324 (cpage_array[count]
325 << PAGE_SHIFT) |
326 MMU_MACHPHYS_UPDATE,
327 count));
328 */
329 if (add_mmu_update(xc_handle, mmu,
330 (cpage_array[count] << PAGE_SHIFT) |
331 MMU_MACHPHYS_UPDATE, count))
332 goto error_out;
333 //DPRINTF(("Do the next one\n"));
334 }
335 /*
336 */
338 //dumpit(pm_handle, 3, 4, page_array);
339 /* put the virt_startinfo_addr at KZERO */
340 /* just hard-code for now */
341 *virt_startinfo_addr = 0x80000000;
343 DPRINTF(("virt_startinfo_addr = 0x%lx\n", *virt_startinfo_addr));
344 start_info = xc_map_foreign_range(xc_handle, dom,
345 PAGE_SIZE, PROT_READ | PROT_WRITE,
346 cpage_array[0]);
347 DPRINTF(("startinfo = 0x%p\n", start_info));
348 DPRINTF(("shared_info_frame is %lx\n", shared_info_frame));
349 memset(start_info, 0, sizeof (*start_info));
350 start_info->pt_base = 0x80000000 | cpu0pdb << PAGE_SHIFT;
351 start_info->mfn_list = 0x80000000 | (page_array_page) << PAGE_SHIFT;
352 DPRINTF(("mfn_list 0x%lx\n", start_info->mfn_list));
353 start_info->mod_start = 0;
354 start_info->mod_len = 0;
355 start_info->nr_pages = tot_pte_pages * 1024;
356 start_info->nr_pt_frames = tot_pte_pages + 1;
357 start_info->shared_info = shared_info_frame;
358 start_info->flags = 0;
359 DPRINTF((" control event channel is %d\n", control_evtchn));
360 start_info->domain_controller_evtchn = control_evtchn;
361 strncpy(start_info->cmd_line, cmdline, MAX_CMDLINE);
362 start_info->cmd_line[MAX_CMDLINE - 1] = '\0';
363 munmap(start_info, PAGE_SIZE);
365 DPRINTF(("done setting up start_info\n"));
366 DPRINTF(("shared_info_frame = 0x%lx\n", shared_info_frame));
367 /* shared_info page starts its life empty. */
369 shared_info = xc_map_foreign_range(xc_handle, dom,
370 PAGE_SIZE, PROT_READ | PROT_WRITE,
371 shared_info_frame);
372 memset(shared_info, 0, PAGE_SIZE);
373 /* Mask all upcalls... */
374 DPRINTF(("mask all upcalls\n"));
375 for (i = 0; i < MAX_VIRT_CPUS; i++)
376 shared_info->vcpu_data[i].evtchn_upcall_mask = 1;
377 munmap(shared_info, PAGE_SIZE);
379 /* Send the page update requests down to the hypervisor. */
380 DPRINTF(("send page update reqs down.\n"));
381 if (finish_mmu_updates(xc_handle, mmu))
382 goto error_out;
384 //DPRINTF (("call dumpit.\n"));
385 //dumpit(pm_handle, 0x100000>>12, tot_pages, page_array) ;
386 //dumpit (pm_handle, 2, 0x100, page_array);
387 free(mmu);
389 /* we don't bother freeing anything at this point --
390 * we're exiting and it is pointless
391 */
392 return 0;
394 error_out:
395 /* oh well we still free some things -- I oughtta nuke this */
396 if (mmu != NULL)
397 free(mmu);
398 ;
399 return -1;
400 }
402 int
403 xc_plan9_build(int xc_handle,
404 u32 domid,
405 const char *image_name,
406 const char *cmdline,
407 unsigned int control_evtchn, unsigned long flags)
408 {
409 dom0_op_t launch_op, op;
410 unsigned long load_addr;
411 long tot_pages;
412 int kernel_fd = -1;
413 gzFile kernel_gfd = NULL;
414 int rc, i;
415 full_execution_context_t st_ctxt, *ctxt = &st_ctxt;
416 unsigned long virt_startinfo_addr;
418 if ((tot_pages = xc_get_tot_pages(xc_handle, domid)) < 0) {
419 PERROR("Could not find total pages for domain");
420 return 1;
421 }
422 DPRINTF(("xc_get_tot_pages returns %ld pages\n", tot_pages));
424 kernel_fd = open(image_name, O_RDONLY);
425 if (kernel_fd < 0) {
426 PERROR("Could not open kernel image");
427 return 1;
428 }
430 if ((kernel_gfd = gzdopen(kernel_fd, "rb")) == NULL) {
431 PERROR("Could not allocate decompression state for state file");
432 close(kernel_fd);
433 return 1;
434 }
436 DPRINTF(("xc_get_tot_pages returns %ld pages\n", tot_pages));
437 if (mlock(&st_ctxt, sizeof (st_ctxt))) {
438 PERROR("Unable to mlock ctxt");
439 return 1;
440 }
442 op.cmd = DOM0_GETDOMAININFO;
443 op.u.getdomaininfo.domain = (domid_t) domid;
444 op.u.getdomaininfo.exec_domain = 0;
445 op.u.getdomaininfo.ctxt = ctxt;
446 if ((do_dom0_op(xc_handle, &op) < 0) ||
447 ((u32) op.u.getdomaininfo.domain != domid)) {
448 PERROR("Could not get info on domain");
449 goto error_out;
450 }
451 DPRINTF(("xc_get_tot_pages returns %ld pages\n", tot_pages));
453 if (!(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED)
454 || (op.u.getdomaininfo.ctxt->pt_base != 0)) {
455 ERROR("Domain is already constructed");
456 goto error_out;
457 }
459 DPRINTF(("xc_get_tot_pages returns %ld pages\n", tot_pages));
460 if (setup_guest(xc_handle, domid, kernel_gfd, tot_pages,
461 &virt_startinfo_addr,
462 &load_addr, &st_ctxt, cmdline,
463 op.u.getdomaininfo.shared_info_frame,
464 control_evtchn, flags) < 0) {
465 ERROR("Error constructing guest OS");
466 goto error_out;
467 }
469 /* leave the leak in here for now
470 if ( kernel_fd >= 0 )
471 close(kernel_fd);
472 if( kernel_gfd )
473 gzclose(kernel_gfd);
474 */
475 ctxt->flags = 0;
477 /*
478 * Initial register values:
479 * DS,ES,FS,GS = FLAT_KERNEL_DS
480 * CS:EIP = FLAT_KERNEL_CS:start_pc
481 * SS:ESP = FLAT_KERNEL_DS:start_stack
482 * ESI = start_info
483 * [EAX,EBX,ECX,EDX,EDI,EBP are zero]
484 * EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
485 */
486 ctxt->cpu_ctxt.ds = FLAT_KERNEL_DS;
487 ctxt->cpu_ctxt.es = FLAT_KERNEL_DS;
488 ctxt->cpu_ctxt.fs = FLAT_KERNEL_DS;
489 ctxt->cpu_ctxt.gs = FLAT_KERNEL_DS;
490 ctxt->cpu_ctxt.ss = FLAT_KERNEL_DS;
491 ctxt->cpu_ctxt.cs = FLAT_KERNEL_CS;
492 ctxt->cpu_ctxt.eip = load_addr;
493 ctxt->cpu_ctxt.eip = 0x80100020;
494 /* put stack at top of second page */
495 ctxt->cpu_ctxt.esp = 0x80000000 + (STACKPAGE << PAGE_SHIFT);
497 /* why is this set? */
498 ctxt->cpu_ctxt.esi = ctxt->cpu_ctxt.esp;
499 ctxt->cpu_ctxt.eflags = (1 << 9) | (1 << 2);
501 /* FPU is set up to default initial state. */
502 memset(ctxt->fpu_ctxt, 0, sizeof (ctxt->fpu_ctxt));
504 /* Virtual IDT is empty at start-of-day. */
505 for (i = 0; i < 256; i++) {
506 ctxt->trap_ctxt[i].vector = i;
507 ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS;
508 }
510 #if defined(__i386__)
511 ctxt->fast_trap_idx = 0;
512 #endif
514 /* No LDT. */
515 ctxt->ldt_ents = 0;
517 /* Use the default Xen-provided GDT. */
518 ctxt->gdt_ents = 0;
520 /* Ring 1 stack is the initial stack. */
521 /* put stack at top of second page */
522 ctxt->kernel_ss = FLAT_KERNEL_DS;
523 ctxt->kernel_esp = ctxt->cpu_ctxt.esp;
525 /* No debugging. */
526 memset(ctxt->debugreg, 0, sizeof (ctxt->debugreg));
528 /* No callback handlers. */
529 ctxt->event_callback_cs = FLAT_KERNEL_CS;
530 ctxt->event_callback_eip = 0;
531 ctxt->failsafe_callback_cs = FLAT_KERNEL_CS;
532 ctxt->failsafe_callback_eip = 0;
534 memset(&launch_op, 0, sizeof (launch_op));
536 launch_op.u.builddomain.domain = (domid_t) domid;
537 // launch_op.u.builddomain.num_vifs = 1;
538 launch_op.u.builddomain.ctxt = ctxt;
539 launch_op.cmd = DOM0_BUILDDOMAIN;
540 rc = do_dom0_op(xc_handle, &launch_op);
542 fprintf(stderr, "RC is %d\n", rc);
543 return rc;
545 error_out:
546 if (kernel_fd >= 0)
547 close(kernel_fd);
548 if (kernel_gfd)
549 gzclose(kernel_gfd);
551 return -1;
552 }
554 /*
555 * Plan 9 memory layout (initial)
556 * ----------------
557 * | info from xen| @0
558 * ---------------|<--- boot args (start at 0x1200 + 64)
559 * | stack |
560 * ----------------<--- page 2
561 * | empty |
562 * ---------------<---- page 5 MACHADDR (always points to machp[cpuno]
563 * | aliased |
564 * ---------------<----- page 6 CPU0MACH
565 * | CPU0MACH |
566 * ----------------
567 * | empty |
568 * ---------------- *virt_load_addr = ehdr.e_entry (0x80100000)
569 * | kernel |
570 * | |
571 * ---------------- <----- page aligned boundary.
572 * | data |
573 * | |
574 * ----------------
575 * | bss |
576 * ----------------<--- end of kernel (page aligned)
577 * | PMD cpu0pdb |
578 * ----------------<--- page +1
579 * | PTE cpu0pte |
580 * ----------------<--- page (tot_pte_pages)/1024
581 * | page_array |
582 * ---------------- <--- page (tot_pte_pages)/1024
583 * | empty to TOM |
584 * ----------------
585 */
587 static int
588 loadp9image(gzFile kernel_gfd, int xc_handle, u32 dom,
589 unsigned long *page_array,
590 unsigned long tot_pages, unsigned long *virt_load_addr,
591 unsigned long *ksize, unsigned long *symtab_addr,
592 unsigned long *symtab_len,
593 unsigned long *first_data_page, unsigned long *pdb_page,
594 const char *cmdline)
595 {
596 unsigned long datapage;
597 Exec ehdr;
599 char *p;
600 unsigned long maxva;
601 int curpos, ret;
602 PAGE *image = 0;
603 unsigned long image_tot_pages = 0;
604 unsigned long textround;
605 static PAGE args;
607 ret = -1;
609 p = NULL;
610 maxva = 0;
612 if (gzread(kernel_gfd, &ehdr, sizeof (Exec)) != sizeof (Exec)) {
613 PERROR("Error reading kernel image P9 header.");
614 goto out;
615 }
617 plan9header(&ehdr);
618 curpos = sizeof (Exec);
620 if (ehdr.magic != I_MAGIC) {
621 PERROR("Image does not have an P9 header.");
622 goto out;
623 }
625 textround = ((ehdr.text + 0x20 + 4095) >> 12) << 12;
626 *first_data_page = 0x100000 + textround;
627 DPRINTF(("ehrd.text is 0x%lx, textround is 0x%lx\n",
628 ehdr.text, textround));
630 image_tot_pages =
631 (textround + ehdr.data + ehdr.bss + PAGE_SIZE - 1) >> PAGE_SHIFT;
632 DPRINTF(("tot pages is %ld\n", image_tot_pages));
634 *virt_load_addr = 0x80100000;
636 if ((*virt_load_addr & (PAGE_SIZE - 1)) != 0) {
637 ERROR("We can only deal with page-aligned load addresses");
638 goto out;
639 }
641 if ((*virt_load_addr + (image_tot_pages << PAGE_SHIFT)) >
642 HYPERVISOR_VIRT_START) {
643 ERROR("Cannot map all domain memory without hitting Xen space");
644 goto out;
645 }
647 /* just malloc an image that is image_tot_pages in size. Then read in
648 * the image -- text, data, -- to page-rounded alignments.
649 * then copy into xen .
650 * this gets BSS zeroed for free
651 */
652 DPRINTF(("Allocate %ld bytes\n", image_tot_pages * sizeof (*image)));
653 image = calloc(image_tot_pages, sizeof (*image));
654 if (!image)
655 return blah("alloc data");
656 /* text starts at 0x20, after the header, just like Unix long ago */
657 if (gzread(kernel_gfd, &image[0].data[sizeof (Exec)], ehdr.text) <
658 ehdr.text)
659 return blah("read text");
660 DPRINTF(("READ TEXT %ld bytes\n", ehdr.text));
661 datapage = ((ehdr.text + sizeof (Exec)) / PAGE_SIZE) + 1;
662 if (gzread(kernel_gfd, image[datapage].data, ehdr.data) < ehdr.data)
663 return blah("read data");
664 DPRINTF(("READ DATA %ld bytes\n", ehdr.data));
666 /* nice contig stuff */
667 /* oops need to start at 0x100000 */
669 ret = memcpy_toguest(xc_handle, dom,
670 image, image_tot_pages * 4096, page_array, 0x100);
671 DPRINTF(("done copying kernel to guest memory\n"));
673 /* now do the bootargs */
674 /* in plan 9, the x=y bootargs start at 0x1200 + 64 in real memory */
675 /* we'll copy to page 1, so we offset into the page struct at
676 * 0x200 + 64
677 */
678 memset(&args, 0, sizeof(args));
679 memcpy(&args.data[0x200 + 64], cmdline, strlen(cmdline));
680 printf("Copied :%s: to page for args\n", cmdline);
681 ret = memcpy_toguest(xc_handle, dom, &args, sizeof(args), page_array,1);
682 //dumpit(xc_handle, dom, 0 /*0x100000>>12*/, 4, page_array) ;
683 out:
684 if (image)
685 free(image);
686 *pdb_page = image_tot_pages + (0x100000 >> PAGE_SHIFT);
687 return ret;
688 }