ia64/xen-unstable

view tools/libxc/xc_linux_build.c @ 6385:f34e732ed4bf

Xenstore testsuite robustness: save output rather than rerun on failure.
"make check" reruns a test which fails with more verbosity. If the test
fails intermittently, that doesn't work well: save the output and simply
dump it if the test fails.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Tue Aug 23 19:58:59 2005 +0000 (2005-08-23)
parents 522bc50588ed
children fdfd511768a3 2f20c2fce2c5 cc5f88b719d0 fa0754a9f64f
line source
1 /******************************************************************************
2 * xc_linux_build.c
3 */
5 #include "xc_private.h"
7 #if defined(__i386__)
8 #define ELFSIZE 32
9 #endif
11 #if defined(__x86_64__) || defined(__ia64__)
12 #define ELFSIZE 64
13 #endif
16 #include "xc_elf.h"
17 #include "xc_aout9.h"
18 #include <stdlib.h>
19 #include <zlib.h>
21 #if defined(__i386__)
22 #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
23 #define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
24 #define L3_PROT (_PAGE_PRESENT)
25 #endif
27 #if defined(__x86_64__)
28 #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER)
29 #define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
30 #define L3_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
31 #define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
32 #endif
35 #define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
36 #define round_pgdown(_p) ((_p)&PAGE_MASK)
38 #ifdef __ia64__
39 #define probe_aout9(image,image_size,load_funcs) 1
40 #endif
42 static int probeimageformat(char *image,
43 unsigned long image_size,
44 struct load_funcs *load_funcs)
45 {
46 if ( probe_elf(image, image_size, load_funcs) &&
47 probe_bin(image, image_size, load_funcs) &&
48 probe_aout9(image, image_size, load_funcs) )
49 {
50 ERROR( "Unrecognized image format" );
51 return -EINVAL;
52 }
54 return 0;
55 }
57 #define alloc_pt(ltab, vltab) \
58 ltab = page_array[ppt_alloc++] << PAGE_SHIFT; \
59 if (vltab != NULL) { \
60 munmap(vltab, PAGE_SIZE); \
61 } \
62 if ((vltab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, \
63 PROT_READ|PROT_WRITE, \
64 ltab >> PAGE_SHIFT)) == NULL) { \
65 goto error_out; \
66 } \
67 memset(vltab, 0, PAGE_SIZE);
69 #if defined(__i386__)
71 static int setup_pg_tables(int xc_handle, u32 dom,
72 vcpu_guest_context_t *ctxt,
73 unsigned long dsi_v_start,
74 unsigned long v_end,
75 unsigned long *page_array,
76 unsigned long vpt_start,
77 unsigned long vpt_end)
78 {
79 l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
80 l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
81 unsigned long l1tab = 0;
82 unsigned long l2tab = 0;
83 unsigned long ppt_alloc;
84 unsigned long count;
86 ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT;
87 alloc_pt(l2tab, vl2tab);
88 vl2e = &vl2tab[l2_table_offset(dsi_v_start)];
89 ctxt->ctrlreg[3] = l2tab;
91 for ( count = 0; count < ((v_end-dsi_v_start)>>PAGE_SHIFT); count++ )
92 {
93 if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 )
94 {
95 alloc_pt(l1tab, vl1tab);
96 vl1e = &vl1tab[l1_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
97 *vl2e++ = l1tab | L2_PROT;
98 }
100 *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
101 if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
102 (count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
103 *vl1e &= ~_PAGE_RW;
104 vl1e++;
105 }
106 munmap(vl1tab, PAGE_SIZE);
107 munmap(vl2tab, PAGE_SIZE);
108 return 0;
110 error_out:
111 if (vl1tab)
112 munmap(vl1tab, PAGE_SIZE);
113 if (vl2tab)
114 munmap(vl2tab, PAGE_SIZE);
115 return -1;
116 }
118 static int setup_pg_tables_pae(int xc_handle, u32 dom,
119 vcpu_guest_context_t *ctxt,
120 unsigned long dsi_v_start,
121 unsigned long v_end,
122 unsigned long *page_array,
123 unsigned long vpt_start,
124 unsigned long vpt_end)
125 {
126 l1_pgentry_64_t *vl1tab=NULL, *vl1e=NULL;
127 l2_pgentry_64_t *vl2tab=NULL, *vl2e=NULL;
128 l3_pgentry_64_t *vl3tab=NULL, *vl3e=NULL;
129 unsigned long l1tab = 0;
130 unsigned long l2tab = 0;
131 unsigned long l3tab = 0;
132 unsigned long ppt_alloc;
133 unsigned long count;
135 /* First allocate page for page dir. */
136 ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT;
137 alloc_pt(l3tab, vl3tab);
138 vl3e = &vl3tab[l3_table_offset_pae(dsi_v_start)];
139 ctxt->ctrlreg[3] = l3tab;
141 for ( count = 0; count < ((v_end-dsi_v_start)>>PAGE_SHIFT); count++)
142 {
143 if ( !((unsigned long)vl1e & (PAGE_SIZE-1)) )
144 {
145 alloc_pt(l1tab, vl1tab);
147 if ( !((unsigned long)vl2e & (PAGE_SIZE-1)) )
148 {
149 alloc_pt(l2tab, vl2tab);
150 vl2e = &vl2tab[l2_table_offset_pae(dsi_v_start + (count<<PAGE_SHIFT))];
151 *vl3e = l2tab | L3_PROT;
152 vl3e++;
153 }
154 vl1e = &vl1tab[l1_table_offset_pae(dsi_v_start + (count<<PAGE_SHIFT))];
155 *vl2e = l1tab | L2_PROT;
156 vl2e++;
157 }
159 *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
160 if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
161 (count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
162 {
163 *vl1e &= ~_PAGE_RW;
164 }
165 vl1e++;
166 }
168 munmap(vl1tab, PAGE_SIZE);
169 munmap(vl2tab, PAGE_SIZE);
170 munmap(vl3tab, PAGE_SIZE);
171 return 0;
173 error_out:
174 if (vl1tab)
175 munmap(vl1tab, PAGE_SIZE);
176 if (vl2tab)
177 munmap(vl2tab, PAGE_SIZE);
178 if (vl3tab)
179 munmap(vl3tab, PAGE_SIZE);
180 return -1;
181 }
183 #endif
185 #if defined(__x86_64__)
187 static int setup_pg_tables_64(int xc_handle, u32 dom,
188 vcpu_guest_context_t *ctxt,
189 unsigned long dsi_v_start,
190 unsigned long v_end,
191 unsigned long *page_array,
192 unsigned long vpt_start,
193 unsigned long vpt_end)
194 {
195 l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
196 l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
197 l3_pgentry_t *vl3tab=NULL, *vl3e=NULL;
198 l4_pgentry_t *vl4tab=NULL, *vl4e=NULL;
199 unsigned long l2tab = 0;
200 unsigned long l1tab = 0;
201 unsigned long l3tab = 0;
202 unsigned long l4tab = 0;
203 unsigned long ppt_alloc;
204 unsigned long count;
206 /* First allocate page for page dir. */
207 ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT;
208 alloc_pt(l4tab, vl4tab);
209 vl4e = &vl4tab[l4_table_offset(dsi_v_start)];
210 ctxt->ctrlreg[3] = l4tab;
212 for ( count = 0; count < ((v_end-dsi_v_start)>>PAGE_SHIFT); count++)
213 {
214 if ( !((unsigned long)vl1e & (PAGE_SIZE-1)) )
215 {
216 alloc_pt(l1tab, vl1tab);
218 if ( !((unsigned long)vl2e & (PAGE_SIZE-1)) )
219 {
220 alloc_pt(l2tab, vl2tab);
221 if ( !((unsigned long)vl3e & (PAGE_SIZE-1)) )
222 {
223 alloc_pt(l3tab, vl3tab);
224 vl3e = &vl3tab[l3_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
225 *vl4e = l3tab | L4_PROT;
226 vl4e++;
227 }
228 vl2e = &vl2tab[l2_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
229 *vl3e = l2tab | L3_PROT;
230 vl3e++;
231 }
232 vl1e = &vl1tab[l1_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
233 *vl2e = l1tab | L2_PROT;
234 vl2e++;
235 }
237 *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
238 if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
239 (count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
240 {
241 *vl1e &= ~_PAGE_RW;
242 }
243 vl1e++;
244 }
246 munmap(vl1tab, PAGE_SIZE);
247 munmap(vl2tab, PAGE_SIZE);
248 munmap(vl3tab, PAGE_SIZE);
249 munmap(vl4tab, PAGE_SIZE);
250 return 0;
252 error_out:
253 if (vl1tab)
254 munmap(vl1tab, PAGE_SIZE);
255 if (vl2tab)
256 munmap(vl2tab, PAGE_SIZE);
257 if (vl3tab)
258 munmap(vl3tab, PAGE_SIZE);
259 if (vl4tab)
260 munmap(vl4tab, PAGE_SIZE);
261 return -1;
262 }
263 #endif
265 #ifdef __ia64__
266 #include <asm/fpu.h> /* for FPSR_DEFAULT */
267 static int setup_guest(int xc_handle,
268 u32 dom,
269 char *image, unsigned long image_size,
270 gzFile initrd_gfd, unsigned long initrd_len,
271 unsigned long nr_pages,
272 unsigned long *pvsi, unsigned long *pvke,
273 unsigned long *pvss, vcpu_guest_context_t *ctxt,
274 const char *cmdline,
275 unsigned long shared_info_frame,
276 unsigned int control_evtchn,
277 unsigned long flags,
278 unsigned int vcpus,
279 unsigned int store_evtchn, unsigned long *store_mfn)
280 {
281 unsigned long *page_array = NULL;
282 struct load_funcs load_funcs;
283 struct domain_setup_info dsi;
284 unsigned long start_page;
285 int rc;
287 rc = probeimageformat(image, image_size, &load_funcs);
288 if ( rc != 0 )
289 goto error_out;
291 memset(&dsi, 0, sizeof(struct domain_setup_info));
293 rc = (load_funcs.parseimage)(image, image_size, &dsi);
294 if ( rc != 0 )
295 goto error_out;
297 dsi.v_start = round_pgdown(dsi.v_start);
298 dsi.v_end = round_pgup(dsi.v_end);
300 start_page = dsi.v_start >> PAGE_SHIFT;
301 nr_pages = (dsi.v_end - dsi.v_start) >> PAGE_SHIFT;
302 if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL )
303 {
304 PERROR("Could not allocate memory");
305 goto error_out;
306 }
308 if ( xc_ia64_get_pfn_list(xc_handle, dom, page_array, start_page, nr_pages) != nr_pages )
309 {
310 PERROR("Could not get the page frame list");
311 goto error_out;
312 }
314 (load_funcs.loadimage)(image, image_size, xc_handle, dom, page_array,
315 &dsi);
317 *pvke = dsi.v_kernentry;
318 return 0;
320 error_out:
321 free(page_array);
322 return -1;
323 }
324 #else /* x86 */
325 static int setup_guest(int xc_handle,
326 u32 dom,
327 char *image, unsigned long image_size,
328 gzFile initrd_gfd, unsigned long initrd_len,
329 unsigned long nr_pages,
330 unsigned long *pvsi, unsigned long *pvke,
331 unsigned long *pvss, vcpu_guest_context_t *ctxt,
332 const char *cmdline,
333 unsigned long shared_info_frame,
334 unsigned int control_evtchn,
335 unsigned long flags,
336 unsigned int vcpus,
337 unsigned int store_evtchn, unsigned long *store_mfn)
338 {
339 unsigned long *page_array = NULL;
340 unsigned long count, i;
341 start_info_t *start_info;
342 shared_info_t *shared_info;
343 mmu_t *mmu = NULL;
344 int rc;
346 unsigned long nr_pt_pages;
347 unsigned long physmap_pfn;
348 u32 *physmap, *physmap_e;
350 struct load_funcs load_funcs;
351 struct domain_setup_info dsi;
352 unsigned long vinitrd_start;
353 unsigned long vinitrd_end;
354 unsigned long vphysmap_start;
355 unsigned long vphysmap_end;
356 unsigned long vstartinfo_start;
357 unsigned long vstartinfo_end;
358 unsigned long vstoreinfo_start;
359 unsigned long vstoreinfo_end;
360 unsigned long vstack_start;
361 unsigned long vstack_end;
362 unsigned long vpt_start;
363 unsigned long vpt_end;
364 unsigned long v_end;
366 rc = probeimageformat(image, image_size, &load_funcs);
367 if ( rc != 0 )
368 goto error_out;
370 memset(&dsi, 0, sizeof(struct domain_setup_info));
372 rc = (load_funcs.parseimage)(image, image_size, &dsi);
373 if ( rc != 0 )
374 goto error_out;
376 if ( (dsi.v_start & (PAGE_SIZE-1)) != 0 )
377 {
378 PERROR("Guest OS must load to a page boundary.\n");
379 goto error_out;
380 }
382 /*
383 * Why do we need this? The number of page-table frames depends on the
384 * size of the bootstrap address space. But the size of the address space
385 * depends on the number of page-table frames (since each one is mapped
386 * read-only). We have a pair of simultaneous equations in two unknowns,
387 * which we solve by exhaustive search.
388 */
389 vinitrd_start = round_pgup(dsi.v_end);
390 vinitrd_end = vinitrd_start + initrd_len;
391 vphysmap_start = round_pgup(vinitrd_end);
392 vphysmap_end = vphysmap_start + (nr_pages * sizeof(unsigned long));
393 vstoreinfo_start = round_pgup(vphysmap_end);
394 vstoreinfo_end = vstoreinfo_start + PAGE_SIZE;
395 vpt_start = vstoreinfo_end;
397 for ( nr_pt_pages = 2; ; nr_pt_pages++ )
398 {
399 vpt_end = vpt_start + (nr_pt_pages * PAGE_SIZE);
400 vstartinfo_start = vpt_end;
401 vstartinfo_end = vstartinfo_start + PAGE_SIZE;
402 vstack_start = vstartinfo_end;
403 vstack_end = vstack_start + PAGE_SIZE;
404 v_end = (vstack_end + (1UL<<22)-1) & ~((1UL<<22)-1);
405 if ( (v_end - vstack_end) < (512UL << 10) )
406 v_end += 1UL << 22; /* Add extra 4MB to get >= 512kB padding. */
407 #if defined(__i386__)
408 if (dsi.pae_kernel) {
409 /* FIXME: assumes one L2 pgtable @ 0xc0000000 */
410 if ( (((v_end - dsi.v_start + ((1<<L2_PAGETABLE_SHIFT_PAE)-1)) >>
411 L2_PAGETABLE_SHIFT_PAE) + 2) <= nr_pt_pages )
412 break;
413 } else {
414 if ( (((v_end - dsi.v_start + ((1<<L2_PAGETABLE_SHIFT)-1)) >>
415 L2_PAGETABLE_SHIFT) + 1) <= nr_pt_pages )
416 break;
417 }
418 #endif
419 #if defined(__x86_64__)
420 #define NR(_l,_h,_s) \
421 (((((_h) + ((1UL<<(_s))-1)) & ~((1UL<<(_s))-1)) - \
422 ((_l) & ~((1UL<<(_s))-1))) >> (_s))
423 if ( (1 + /* # L4 */
424 NR(dsi.v_start, v_end, L4_PAGETABLE_SHIFT) + /* # L3 */
425 NR(dsi.v_start, v_end, L3_PAGETABLE_SHIFT) + /* # L2 */
426 NR(dsi.v_start, v_end, L2_PAGETABLE_SHIFT)) /* # L1 */
427 <= nr_pt_pages )
428 break;
429 #endif
430 }
432 #define _p(a) ((void *) (a))
434 printf("VIRTUAL MEMORY ARRANGEMENT:\n"
435 " Loaded kernel: %p->%p\n"
436 " Init. ramdisk: %p->%p\n"
437 " Phys-Mach map: %p->%p\n"
438 " Store page: %p->%p\n"
439 " Page tables: %p->%p\n"
440 " Start info: %p->%p\n"
441 " Boot stack: %p->%p\n"
442 " TOTAL: %p->%p\n",
443 _p(dsi.v_kernstart), _p(dsi.v_kernend),
444 _p(vinitrd_start), _p(vinitrd_end),
445 _p(vphysmap_start), _p(vphysmap_end),
446 _p(vstoreinfo_start), _p(vstoreinfo_end),
447 _p(vpt_start), _p(vpt_end),
448 _p(vstartinfo_start), _p(vstartinfo_end),
449 _p(vstack_start), _p(vstack_end),
450 _p(dsi.v_start), _p(v_end));
451 printf(" ENTRY ADDRESS: %p\n", _p(dsi.v_kernentry));
453 if ( (v_end - dsi.v_start) > (nr_pages * PAGE_SIZE) )
454 {
455 printf("Initial guest OS requires too much space\n"
456 "(%luMB is greater than %luMB limit)\n",
457 (v_end-dsi.v_start)>>20, (nr_pages<<PAGE_SHIFT)>>20);
458 goto error_out;
459 }
461 if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL )
462 {
463 PERROR("Could not allocate memory");
464 goto error_out;
465 }
467 if ( xc_get_pfn_list(xc_handle, dom, page_array, nr_pages) != nr_pages )
468 {
469 PERROR("Could not get the page frame list");
470 goto error_out;
471 }
473 (load_funcs.loadimage)(image, image_size, xc_handle, dom, page_array,
474 &dsi);
476 /* Load the initial ramdisk image. */
477 if ( initrd_len != 0 )
478 {
479 for ( i = (vinitrd_start - dsi.v_start);
480 i < (vinitrd_end - dsi.v_start); i += PAGE_SIZE )
481 {
482 char page[PAGE_SIZE];
483 if ( gzread(initrd_gfd, page, PAGE_SIZE) == -1 )
484 {
485 PERROR("Error reading initrd image, could not");
486 goto error_out;
487 }
488 xc_copy_to_domain_page(xc_handle, dom,
489 page_array[i>>PAGE_SHIFT], page);
490 }
491 }
493 if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL )
494 goto error_out;
496 /* setup page tables */
497 #if defined(__i386__)
498 if (dsi.pae_kernel)
499 rc = setup_pg_tables_pae(xc_handle, dom, ctxt,
500 dsi.v_start, v_end,
501 page_array, vpt_start, vpt_end);
502 else {
503 rc = setup_pg_tables(xc_handle, dom, ctxt,
504 dsi.v_start, v_end,
505 page_array, vpt_start, vpt_end);
506 }
507 #endif
508 #if defined(__x86_64__)
509 rc = setup_pg_tables_64(xc_handle, dom, ctxt,
510 dsi.v_start, v_end,
511 page_array, vpt_start, vpt_end);
512 #endif
513 if (0 != rc)
514 goto error_out;
516 /* Write the phys->machine and machine->phys table entries. */
517 physmap_pfn = (vphysmap_start - dsi.v_start) >> PAGE_SHIFT;
518 physmap = physmap_e = xc_map_foreign_range(
519 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
520 page_array[physmap_pfn++]);
521 for ( count = 0; count < nr_pages; count++ )
522 {
523 if ( add_mmu_update(xc_handle, mmu,
524 (page_array[count] << PAGE_SHIFT) |
525 MMU_MACHPHYS_UPDATE, count) )
526 {
527 munmap(physmap, PAGE_SIZE);
528 goto error_out;
529 }
530 *physmap_e++ = page_array[count];
531 if ( ((unsigned long)physmap_e & (PAGE_SIZE-1)) == 0 )
532 {
533 munmap(physmap, PAGE_SIZE);
534 physmap = physmap_e = xc_map_foreign_range(
535 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
536 page_array[physmap_pfn++]);
537 }
538 }
539 munmap(physmap, PAGE_SIZE);
541 #if defined(__i386__)
542 /*
543 * Pin down l2tab addr as page dir page - causes hypervisor to provide
544 * correct protection for the page
545 */
546 if (dsi.pae_kernel) {
547 if ( pin_table(xc_handle, MMUEXT_PIN_L3_TABLE,
548 ctxt->ctrlreg[3] >> PAGE_SHIFT, dom) )
549 goto error_out;
550 } else {
551 if ( pin_table(xc_handle, MMUEXT_PIN_L2_TABLE,
552 ctxt->ctrlreg[3] >> PAGE_SHIFT, dom) )
553 goto error_out;
554 }
555 #endif
557 #if defined(__x86_64__)
558 /*
559 * Pin down l4tab addr as page dir page - causes hypervisor to provide
560 * correct protection for the page
561 */
562 if ( pin_table(xc_handle, MMUEXT_PIN_L4_TABLE,
563 ctxt->ctrlreg[3] >> PAGE_SHIFT, dom) )
564 goto error_out;
565 #endif
567 *store_mfn = page_array[(vstoreinfo_start-dsi.v_start) >> PAGE_SHIFT];
569 start_info = xc_map_foreign_range(
570 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
571 page_array[(vstartinfo_start-dsi.v_start)>>PAGE_SHIFT]);
572 memset(start_info, 0, sizeof(*start_info));
573 start_info->nr_pages = nr_pages;
574 start_info->shared_info = shared_info_frame << PAGE_SHIFT;
575 start_info->flags = flags;
576 start_info->pt_base = vpt_start;
577 start_info->nr_pt_frames = nr_pt_pages;
578 start_info->mfn_list = vphysmap_start;
579 start_info->domain_controller_evtchn = control_evtchn;
580 start_info->store_mfn = *store_mfn;
581 start_info->store_evtchn = store_evtchn;
582 if ( initrd_len != 0 )
583 {
584 start_info->mod_start = vinitrd_start;
585 start_info->mod_len = initrd_len;
586 }
587 strncpy((char *)start_info->cmd_line, cmdline, MAX_GUEST_CMDLINE);
588 start_info->cmd_line[MAX_GUEST_CMDLINE-1] = '\0';
589 munmap(start_info, PAGE_SIZE);
591 /* shared_info page starts its life empty. */
592 shared_info = xc_map_foreign_range(
593 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, shared_info_frame);
594 memset(shared_info, 0, sizeof(shared_info_t));
595 /* Mask all upcalls... */
596 for ( i = 0; i < MAX_VIRT_CPUS; i++ )
597 shared_info->vcpu_data[i].evtchn_upcall_mask = 1;
599 shared_info->n_vcpu = vcpus;
600 printf(" VCPUS: %d\n", shared_info->n_vcpu);
602 munmap(shared_info, PAGE_SIZE);
604 /* Send the page update requests down to the hypervisor. */
605 if ( finish_mmu_updates(xc_handle, mmu) )
606 goto error_out;
608 free(mmu);
609 free(page_array);
611 *pvsi = vstartinfo_start;
612 *pvss = vstack_start;
613 *pvke = dsi.v_kernentry;
615 return 0;
617 error_out:
618 free(mmu);
619 free(page_array);
620 return -1;
621 }
622 #endif
624 int xc_linux_build(int xc_handle,
625 u32 domid,
626 const char *image_name,
627 const char *ramdisk_name,
628 const char *cmdline,
629 unsigned int control_evtchn,
630 unsigned long flags,
631 unsigned int vcpus,
632 unsigned int store_evtchn,
633 unsigned long *store_mfn)
634 {
635 dom0_op_t launch_op, op;
636 int initrd_fd = -1;
637 gzFile initrd_gfd = NULL;
638 int rc, i;
639 vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt;
640 unsigned long nr_pages;
641 char *image = NULL;
642 unsigned long image_size, initrd_size=0;
643 unsigned long vstartinfo_start, vkern_entry, vstack_start;
645 if ( (nr_pages = xc_get_tot_pages(xc_handle, domid)) < 0 )
646 {
647 PERROR("Could not find total pages for domain");
648 goto error_out;
649 }
651 if ( (image = xc_read_kernel_image(image_name, &image_size)) == NULL )
652 goto error_out;
654 if ( (ramdisk_name != NULL) && (strlen(ramdisk_name) != 0) )
655 {
656 if ( (initrd_fd = open(ramdisk_name, O_RDONLY)) < 0 )
657 {
658 PERROR("Could not open the initial ramdisk image");
659 goto error_out;
660 }
662 initrd_size = xc_get_filesz(initrd_fd);
664 if ( (initrd_gfd = gzdopen(initrd_fd, "rb")) == NULL )
665 {
666 PERROR("Could not allocate decompression state for initrd");
667 goto error_out;
668 }
669 }
671 if ( mlock(&st_ctxt, sizeof(st_ctxt) ) )
672 {
673 PERROR("xc_linux_build: ctxt mlock failed");
674 return 1;
675 }
677 op.cmd = DOM0_GETDOMAININFO;
678 op.u.getdomaininfo.domain = (domid_t)domid;
679 if ( (do_dom0_op(xc_handle, &op) < 0) ||
680 ((u16)op.u.getdomaininfo.domain != domid) )
681 {
682 PERROR("Could not get info on domain");
683 goto error_out;
684 }
686 if ( xc_domain_get_vcpu_context(xc_handle, domid, 0, ctxt) )
687 {
688 PERROR("Could not get vcpu context");
689 goto error_out;
690 }
692 if ( !(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) ||
693 #ifdef __ia64__
694 0 )
695 #else
696 (ctxt->ctrlreg[3] != 0) )
697 #endif
698 {
699 ERROR("Domain is already constructed");
700 goto error_out;
701 }
703 if ( setup_guest(xc_handle, domid, image, image_size,
704 initrd_gfd, initrd_size, nr_pages,
705 &vstartinfo_start, &vkern_entry,
706 &vstack_start, ctxt, cmdline,
707 op.u.getdomaininfo.shared_info_frame,
708 control_evtchn, flags, vcpus,
709 store_evtchn, store_mfn) < 0 )
710 {
711 ERROR("Error constructing guest OS");
712 goto error_out;
713 }
715 if ( initrd_fd >= 0 )
716 close(initrd_fd);
717 if ( initrd_gfd )
718 gzclose(initrd_gfd);
719 free(image);
721 #ifdef __ia64__
722 /* based on new_thread in xen/arch/ia64/domain.c */
723 ctxt->regs.cr_ipsr = 0; /* all necessary bits filled by hypervisor */
724 ctxt->regs.cr_iip = vkern_entry;
725 ctxt->regs.cr_ifs = 1UL << 63;
726 ctxt->regs.ar_fpsr = FPSR_DEFAULT;
727 /* ctxt->regs.r28 = dom_fw_setup(); currently done by hypervisor, should move here */
728 ctxt->vcpu.privregs = 0;
729 ctxt->shared.domain_controller_evtchn = control_evtchn;
730 ctxt->shared.flags = flags;
731 i = 0; /* silence unused variable warning */
732 #else /* x86 */
733 /*
734 * Initial register values:
735 * DS,ES,FS,GS = FLAT_KERNEL_DS
736 * CS:EIP = FLAT_KERNEL_CS:start_pc
737 * SS:ESP = FLAT_KERNEL_DS:start_stack
738 * ESI = start_info
739 * [EAX,EBX,ECX,EDX,EDI,EBP are zero]
740 * EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
741 */
742 ctxt->user_regs.ds = FLAT_KERNEL_DS;
743 ctxt->user_regs.es = FLAT_KERNEL_DS;
744 ctxt->user_regs.fs = FLAT_KERNEL_DS;
745 ctxt->user_regs.gs = FLAT_KERNEL_DS;
746 ctxt->user_regs.ss = FLAT_KERNEL_SS;
747 ctxt->user_regs.cs = FLAT_KERNEL_CS;
748 ctxt->user_regs.eip = vkern_entry;
749 ctxt->user_regs.esp = vstack_start + PAGE_SIZE;
750 ctxt->user_regs.esi = vstartinfo_start;
751 ctxt->user_regs.eflags = 1 << 9; /* Interrupt Enable */
753 /* FPU is set up to default initial state. */
754 memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
756 /* Virtual IDT is empty at start-of-day. */
757 for ( i = 0; i < 256; i++ )
758 {
759 ctxt->trap_ctxt[i].vector = i;
760 ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS;
761 }
763 /* No LDT. */
764 ctxt->ldt_ents = 0;
766 /* Use the default Xen-provided GDT. */
767 ctxt->gdt_ents = 0;
769 /* Ring 1 stack is the initial stack. */
770 ctxt->kernel_ss = FLAT_KERNEL_SS;
771 ctxt->kernel_sp = vstack_start + PAGE_SIZE;
773 /* No debugging. */
774 memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
776 /* No callback handlers. */
777 #if defined(__i386__)
778 ctxt->event_callback_cs = FLAT_KERNEL_CS;
779 ctxt->event_callback_eip = 0;
780 ctxt->failsafe_callback_cs = FLAT_KERNEL_CS;
781 ctxt->failsafe_callback_eip = 0;
782 #elif defined(__x86_64__)
783 ctxt->event_callback_eip = 0;
784 ctxt->failsafe_callback_eip = 0;
785 ctxt->syscall_callback_eip = 0;
786 #endif
787 #endif /* x86 */
789 memset( &launch_op, 0, sizeof(launch_op) );
791 launch_op.u.setdomaininfo.domain = (domid_t)domid;
792 launch_op.u.setdomaininfo.vcpu = 0;
793 launch_op.u.setdomaininfo.ctxt = ctxt;
795 launch_op.cmd = DOM0_SETDOMAININFO;
796 rc = do_dom0_op(xc_handle, &launch_op);
798 return rc;
800 error_out:
801 if ( initrd_gfd != NULL )
802 gzclose(initrd_gfd);
803 else if ( initrd_fd >= 0 )
804 close(initrd_fd);
805 free(image);
807 return -1;
808 }