ia64/xen-unstable

view tools/libxc/xc_linux_build.c @ 6422:e24fd7012ffb

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