direct-io.hg

view tools/libxc/xc_linux_build.c @ 12425:5c5af79e7272

[IA64] IA64 counter part of the change 12204:e6fdb32b786c of xen-unstable.hg

Remove xc_ia64_get_pfn_list() from setup_guest() in xc_linux_build.c,
use xc_domain_populate_physmap() and xc_domain_translate_gpfn_list().

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author awilliam@xenbuild.aw
date Fri Nov 10 11:14:32 2006 -0700 (2006-11-10)
parents 93d7d0025408
children a9d2106313fa
line source
1 /******************************************************************************
2 * xc_linux_build.c
3 */
5 #include <stddef.h>
6 #include "xg_private.h"
7 #include "xc_private.h"
8 #include <xenctrl.h>
10 #include "xc_elf.h"
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <inttypes.h>
14 #include <zlib.h>
16 /* Handy for printing out '0' prepended values at native pointer size */
17 #define _p(a) ((void *) ((ulong)a))
19 #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
20 #define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
21 #if defined(__i386__)
22 #define L3_PROT (_PAGE_PRESENT)
23 #elif defined(__x86_64__)
24 #define L3_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
25 #define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
26 #endif
28 #define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
29 #define round_pgdown(_p) ((_p)&PAGE_MASK)
31 struct initrd_info {
32 enum { INITRD_none, INITRD_file, INITRD_mem } type;
33 /*
34 * .len must be filled in by the user for type==INITRD_mem. It is
35 * filled in by load_initrd() for INITRD_file and unused for
36 * INITRD_none.
37 */
38 unsigned long len;
39 union {
40 gzFile file_handle;
41 char *mem_addr;
42 } u;
43 };
45 static const char *feature_names[XENFEAT_NR_SUBMAPS*32] = {
46 [XENFEAT_writable_page_tables] = "writable_page_tables",
47 [XENFEAT_writable_descriptor_tables] = "writable_descriptor_tables",
48 [XENFEAT_auto_translated_physmap] = "auto_translated_physmap",
49 [XENFEAT_supervisor_mode_kernel] = "supervisor_mode_kernel",
50 [XENFEAT_pae_pgdir_above_4gb] = "pae_pgdir_above_4gb"
51 };
53 static inline void set_feature_bit (int nr, uint32_t *addr)
54 {
55 addr[nr>>5] |= (1<<(nr&31));
56 }
58 static inline int test_feature_bit(int nr, uint32_t *addr)
59 {
60 return !!(addr[nr>>5] & (1<<(nr&31)));
61 }
63 static int parse_features(
64 const char *feats,
65 uint32_t supported[XENFEAT_NR_SUBMAPS],
66 uint32_t required[XENFEAT_NR_SUBMAPS])
67 {
68 const char *end, *p;
69 int i, req;
71 if ( (end = strchr(feats, ',')) == NULL )
72 end = feats + strlen(feats);
74 while ( feats < end )
75 {
76 p = strchr(feats, '|');
77 if ( (p == NULL) || (p > end) )
78 p = end;
80 req = (*feats == '!');
81 if ( req )
82 feats++;
84 for ( i = 0; i < XENFEAT_NR_SUBMAPS*32; i++ )
85 {
86 if ( feature_names[i] == NULL )
87 continue;
89 if ( strncmp(feature_names[i], feats, p-feats) == 0 )
90 {
91 set_feature_bit(i, supported);
92 if ( required && req )
93 set_feature_bit(i, required);
94 break;
95 }
96 }
98 if ( i == XENFEAT_NR_SUBMAPS*32 )
99 {
100 ERROR("Unknown feature \"%.*s\".", (int)(p-feats), feats);
101 if ( req )
102 {
103 ERROR("Kernel requires an unknown hypervisor feature.");
104 return -EINVAL;
105 }
106 }
108 feats = p;
109 if ( *feats == '|' )
110 feats++;
111 }
113 return -EINVAL;
114 }
116 static int probeimageformat(const char *image,
117 unsigned long image_size,
118 struct load_funcs *load_funcs)
119 {
120 if ( probe_elf(image, image_size, load_funcs) &&
121 probe_bin(image, image_size, load_funcs) )
122 {
123 ERROR( "Unrecognized image format" );
124 return -EINVAL;
125 }
127 return 0;
128 }
130 static int load_initrd(int xc_handle, domid_t dom,
131 struct initrd_info *initrd,
132 unsigned long physbase,
133 xen_pfn_t *phys_to_mach)
134 {
135 char page[PAGE_SIZE];
136 unsigned long pfn_start, pfn;
138 if ( initrd->type == INITRD_none )
139 return 0;
141 pfn_start = physbase >> PAGE_SHIFT;
143 if ( initrd->type == INITRD_mem )
144 {
145 unsigned long nr_pages = (initrd->len + PAGE_SIZE - 1) >> PAGE_SHIFT;
147 for ( pfn = pfn_start; pfn < (pfn_start + nr_pages); pfn++ )
148 {
149 xc_copy_to_domain_page(
150 xc_handle, dom, phys_to_mach[pfn],
151 &initrd->u.mem_addr[(pfn - pfn_start) << PAGE_SHIFT]);
152 }
153 }
154 else
155 {
156 int readlen;
158 pfn = pfn_start;
159 initrd->len = 0;
161 /* gzread returns 0 on EOF */
162 while ( (readlen = gzread(initrd->u.file_handle, page, PAGE_SIZE)) )
163 {
164 if ( readlen < 0 )
165 {
166 PERROR("Error reading initrd image, could not");
167 return -EINVAL;
168 }
170 initrd->len += readlen;
171 xc_copy_to_domain_page(xc_handle, dom, phys_to_mach[pfn++], page);
172 }
173 }
175 return 0;
176 }
178 #define alloc_pt(ltab, vltab, pltab) \
179 do { \
180 pltab = ppt_alloc++; \
181 ltab = (uint64_t)page_array[pltab] << PAGE_SHIFT; \
182 pltab <<= PAGE_SHIFT; \
183 if ( vltab != NULL ) \
184 munmap(vltab, PAGE_SIZE); \
185 if ( (vltab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, \
186 PROT_READ|PROT_WRITE, \
187 ltab >> PAGE_SHIFT)) == NULL ) \
188 goto error_out; \
189 memset(vltab, 0x0, PAGE_SIZE); \
190 } while ( 0 )
192 #if defined(__i386__)
194 static int setup_pg_tables(int xc_handle, uint32_t dom,
195 vcpu_guest_context_t *ctxt,
196 unsigned long dsi_v_start,
197 unsigned long v_end,
198 xen_pfn_t *page_array,
199 unsigned long vpt_start,
200 unsigned long vpt_end,
201 unsigned shadow_mode_enabled)
202 {
203 l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
204 l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
205 unsigned long l1tab = 0, pl1tab;
206 unsigned long l2tab = 0, pl2tab;
207 unsigned long ppt_alloc;
208 unsigned long count;
210 ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT;
211 alloc_pt(l2tab, vl2tab, pl2tab);
212 vl2e = &vl2tab[l2_table_offset(dsi_v_start)];
213 if (shadow_mode_enabled)
214 ctxt->ctrlreg[3] = xen_pfn_to_cr3(pl2tab >> PAGE_SHIFT);
215 else
216 ctxt->ctrlreg[3] = xen_pfn_to_cr3(l2tab >> PAGE_SHIFT);
218 for ( count = 0; count < ((v_end - dsi_v_start) >> PAGE_SHIFT); count++ )
219 {
220 if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 )
221 {
222 alloc_pt(l1tab, vl1tab, pl1tab);
223 vl1e = &vl1tab[l1_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
224 if (shadow_mode_enabled)
225 *vl2e = pl1tab | L2_PROT;
226 else
227 *vl2e = l1tab | L2_PROT;
228 vl2e++;
229 }
231 if ( shadow_mode_enabled )
232 {
233 *vl1e = (count << PAGE_SHIFT) | L1_PROT;
234 }
235 else
236 {
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 *vl1e &= ~_PAGE_RW;
241 }
242 vl1e++;
243 }
244 munmap(vl1tab, PAGE_SIZE);
245 munmap(vl2tab, PAGE_SIZE);
246 return 0;
248 error_out:
249 if (vl1tab)
250 munmap(vl1tab, PAGE_SIZE);
251 if (vl2tab)
252 munmap(vl2tab, PAGE_SIZE);
253 return -1;
254 }
256 static int setup_pg_tables_pae(int xc_handle, uint32_t dom,
257 vcpu_guest_context_t *ctxt,
258 unsigned long dsi_v_start,
259 unsigned long v_end,
260 xen_pfn_t *page_array,
261 unsigned long vpt_start,
262 unsigned long vpt_end,
263 unsigned shadow_mode_enabled,
264 unsigned pae_mode)
265 {
266 l1_pgentry_64_t *vl1tab = NULL, *vl1e = NULL;
267 l2_pgentry_64_t *vl2tab = NULL, *vl2e = NULL;
268 l3_pgentry_64_t *vl3tab = NULL, *vl3e = NULL;
269 uint64_t l1tab, l2tab, l3tab, pl1tab, pl2tab, pl3tab;
270 unsigned long ppt_alloc, count, nmfn;
272 /* First allocate page for page dir. */
273 ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT;
275 if ( pae_mode == PAEKERN_extended_cr3 )
276 {
277 ctxt->vm_assist |= (1UL << VMASST_TYPE_pae_extended_cr3);
278 }
279 else if ( page_array[ppt_alloc] > 0xfffff )
280 {
281 nmfn = xc_make_page_below_4G(xc_handle, dom, page_array[ppt_alloc]);
282 if ( nmfn == 0 )
283 {
284 DPRINTF("Couldn't get a page below 4GB :-(\n");
285 goto error_out;
286 }
287 page_array[ppt_alloc] = nmfn;
288 }
290 alloc_pt(l3tab, vl3tab, pl3tab);
291 vl3e = &vl3tab[l3_table_offset_pae(dsi_v_start)];
292 if (shadow_mode_enabled)
293 ctxt->ctrlreg[3] = xen_pfn_to_cr3(pl3tab >> PAGE_SHIFT);
294 else
295 ctxt->ctrlreg[3] = xen_pfn_to_cr3(l3tab >> PAGE_SHIFT);
297 for ( count = 0; count < ((v_end - dsi_v_start) >> PAGE_SHIFT); count++)
298 {
299 if ( !((unsigned long)vl1e & (PAGE_SIZE-1)) )
300 {
301 if ( !((unsigned long)vl2e & (PAGE_SIZE-1)) )
302 {
303 alloc_pt(l2tab, vl2tab, pl2tab);
304 vl2e = &vl2tab[l2_table_offset_pae(
305 dsi_v_start + (count << PAGE_SHIFT))];
306 if (shadow_mode_enabled)
307 *vl3e = pl2tab | L3_PROT;
308 else
309 *vl3e++ = l2tab | L3_PROT;
310 }
312 alloc_pt(l1tab, vl1tab, pl1tab);
313 vl1e = &vl1tab[l1_table_offset_pae(
314 dsi_v_start + (count << PAGE_SHIFT))];
315 if (shadow_mode_enabled)
316 *vl2e = pl1tab | L2_PROT;
317 else
318 *vl2e++ = l1tab | L2_PROT;
319 }
321 if ( shadow_mode_enabled )
322 {
323 *vl1e = (count << PAGE_SHIFT) | L1_PROT;
324 }
325 else
326 {
327 *vl1e = ((uint64_t)page_array[count] << PAGE_SHIFT) | L1_PROT;
328 if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
329 (count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
330 *vl1e &= ~_PAGE_RW;
331 }
332 vl1e++;
333 }
335 /* Xen requires a mid-level pgdir mapping 0xC0000000 region. */
336 if ( (vl3tab[3] & _PAGE_PRESENT) == 0 )
337 {
338 alloc_pt(l2tab, vl2tab, pl2tab);
339 vl3tab[3] = l2tab | L3_PROT;
340 }
342 munmap(vl1tab, PAGE_SIZE);
343 munmap(vl2tab, PAGE_SIZE);
344 munmap(vl3tab, PAGE_SIZE);
345 return 0;
347 error_out:
348 if (vl1tab)
349 munmap(vl1tab, PAGE_SIZE);
350 if (vl2tab)
351 munmap(vl2tab, PAGE_SIZE);
352 if (vl3tab)
353 munmap(vl3tab, PAGE_SIZE);
354 return -1;
355 }
357 #endif
359 #if defined(__x86_64__)
361 static int setup_pg_tables_64(int xc_handle, uint32_t dom,
362 vcpu_guest_context_t *ctxt,
363 unsigned long dsi_v_start,
364 unsigned long v_end,
365 xen_pfn_t *page_array,
366 unsigned long vpt_start,
367 unsigned long vpt_end,
368 int shadow_mode_enabled)
369 {
370 l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
371 l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
372 l3_pgentry_t *vl3tab=NULL, *vl3e=NULL;
373 l4_pgentry_t *vl4tab=NULL, *vl4e=NULL;
374 unsigned long l2tab = 0, pl2tab;
375 unsigned long l1tab = 0, pl1tab;
376 unsigned long l3tab = 0, pl3tab;
377 unsigned long l4tab = 0, pl4tab;
378 unsigned long ppt_alloc;
379 unsigned long count;
381 /* First allocate page for page dir. */
382 ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT;
383 alloc_pt(l4tab, vl4tab, pl4tab);
384 vl4e = &vl4tab[l4_table_offset(dsi_v_start)];
385 if (shadow_mode_enabled)
386 ctxt->ctrlreg[3] = xen_pfn_to_cr3(pl4tab >> PAGE_SHIFT);
387 else
388 ctxt->ctrlreg[3] = xen_pfn_to_cr3(l4tab >> PAGE_SHIFT);
390 for ( count = 0; count < ((v_end-dsi_v_start)>>PAGE_SHIFT); count++)
391 {
392 if ( !((unsigned long)vl1e & (PAGE_SIZE-1)) )
393 {
394 alloc_pt(l1tab, vl1tab, pl1tab);
396 if ( !((unsigned long)vl2e & (PAGE_SIZE-1)) )
397 {
398 alloc_pt(l2tab, vl2tab, pl2tab);
399 if ( !((unsigned long)vl3e & (PAGE_SIZE-1)) )
400 {
401 alloc_pt(l3tab, vl3tab, pl3tab);
402 vl3e = &vl3tab[l3_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
403 if (shadow_mode_enabled)
404 *vl4e = pl3tab | L4_PROT;
405 else
406 *vl4e = l3tab | L4_PROT;
407 vl4e++;
408 }
409 vl2e = &vl2tab[l2_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
410 if (shadow_mode_enabled)
411 *vl3e = pl2tab | L3_PROT;
412 else
413 *vl3e = l2tab | L3_PROT;
414 vl3e++;
415 }
416 vl1e = &vl1tab[l1_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
417 if (shadow_mode_enabled)
418 *vl2e = pl1tab | L2_PROT;
419 else
420 *vl2e = l1tab | L2_PROT;
421 vl2e++;
422 }
424 if ( shadow_mode_enabled )
425 {
426 *vl1e = (count << PAGE_SHIFT) | L1_PROT;
427 }
428 else
429 {
430 *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
431 if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
432 (count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
433 {
434 *vl1e &= ~_PAGE_RW;
435 }
436 }
437 vl1e++;
438 }
440 munmap(vl1tab, PAGE_SIZE);
441 munmap(vl2tab, PAGE_SIZE);
442 munmap(vl3tab, PAGE_SIZE);
443 munmap(vl4tab, PAGE_SIZE);
444 return 0;
446 error_out:
447 if (vl1tab)
448 munmap(vl1tab, PAGE_SIZE);
449 if (vl2tab)
450 munmap(vl2tab, PAGE_SIZE);
451 if (vl3tab)
452 munmap(vl3tab, PAGE_SIZE);
453 if (vl4tab)
454 munmap(vl4tab, PAGE_SIZE);
455 return -1;
456 }
457 #endif
459 #ifdef __ia64__
460 static int setup_guest(int xc_handle,
461 uint32_t dom,
462 const char *image, unsigned long image_size,
463 struct initrd_info *initrd,
464 unsigned long nr_pages,
465 unsigned long *pvsi, unsigned long *pvke,
466 unsigned long *pvss, vcpu_guest_context_t *ctxt,
467 const char *cmdline,
468 unsigned long shared_info_frame,
469 unsigned long flags,
470 unsigned int store_evtchn, unsigned long *store_mfn,
471 unsigned int console_evtchn, unsigned long *console_mfn,
472 uint32_t required_features[XENFEAT_NR_SUBMAPS])
473 {
474 xen_pfn_t *page_array = NULL;
475 struct load_funcs load_funcs;
476 struct domain_setup_info dsi;
477 unsigned long vinitrd_start;
478 unsigned long vinitrd_end;
479 unsigned long v_end;
480 unsigned long start_page, pgnr;
481 start_info_t *start_info;
482 unsigned long start_info_mpa;
483 struct xen_ia64_boot_param *bp;
484 shared_info_t *shared_info;
485 int i;
486 DECLARE_DOMCTL;
487 int rc;
489 rc = probeimageformat(image, image_size, &load_funcs);
490 if ( rc != 0 )
491 goto error_out;
493 memset(&dsi, 0, sizeof(struct domain_setup_info));
495 rc = (load_funcs.parseimage)(image, image_size, &dsi);
496 if ( rc != 0 )
497 goto error_out;
499 if ( (page_array = malloc(nr_pages * sizeof(xen_pfn_t))) == NULL )
500 {
501 PERROR("Could not allocate memory");
502 goto error_out;
503 }
504 for ( i = 0; i < nr_pages; i++ )
505 page_array[i] = i;
506 if ( xc_domain_memory_populate_physmap(xc_handle, dom, nr_pages,
507 0, 0, page_array) )
508 {
509 PERROR("Could not allocate memory for PV guest.\n");
510 goto error_out;
511 }
512 if ( xc_domain_translate_gpfn_list(xc_handle, dom, nr_pages,
513 page_array, page_array) )
514 {
515 PERROR("Could not translate addresses of PV guest.\n");
516 goto error_out;
517 }
519 dsi.v_start = round_pgdown(dsi.v_start);
520 vinitrd_start = round_pgup(dsi.v_end);
521 start_info_mpa = (nr_pages - 3) << PAGE_SHIFT;
522 *pvke = dsi.v_kernentry;
524 /* Build firmware. */
525 memset(&domctl.u.arch_setup, 0, sizeof(domctl.u.arch_setup));
526 domctl.u.arch_setup.flags = 0;
527 domctl.u.arch_setup.bp = start_info_mpa + sizeof (start_info_t);
528 domctl.u.arch_setup.maxmem = (nr_pages - 3) << PAGE_SHIFT;
529 domctl.cmd = XEN_DOMCTL_arch_setup;
530 domctl.domain = (domid_t)dom;
531 if ( xc_domctl(xc_handle, &domctl) )
532 goto error_out;
534 start_page = dsi.v_start >> PAGE_SHIFT;
535 /* in order to get initrd->len, we need to load initrd image at first */
536 if ( load_initrd(xc_handle, dom, initrd,
537 vinitrd_start - dsi.v_start, page_array + start_page) )
538 goto error_out;
540 vinitrd_end = vinitrd_start + initrd->len;
541 v_end = round_pgup(vinitrd_end);
542 pgnr = (v_end - dsi.v_start) >> PAGE_SHIFT;
543 if ( pgnr > nr_pages )
544 {
545 PERROR("too small memory is specified. "
546 "At least %ld kb is necessary.\n",
547 pgnr << (PAGE_SHIFT - 10));
548 }
550 IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n"
551 " Loaded kernel: %p->%p\n"
552 " Init. ramdisk: %p->%p\n"
553 " TOTAL: %p->%p\n",
554 _p(dsi.v_kernstart), _p(dsi.v_kernend),
555 _p(vinitrd_start), _p(vinitrd_end),
556 _p(dsi.v_start), _p(v_end));
557 IPRINTF(" ENTRY ADDRESS: %p\n", _p(dsi.v_kernentry));
559 (load_funcs.loadimage)(image, image_size, xc_handle, dom,
560 page_array + start_page, &dsi);
562 *store_mfn = page_array[nr_pages - 2];
563 *console_mfn = page_array[nr_pages - 1];
564 IPRINTF("start_info: 0x%lx at 0x%lx, "
565 "store_mfn: 0x%lx at 0x%lx, "
566 "console_mfn: 0x%lx at 0x%lx\n",
567 page_array[nr_pages - 3], nr_pages - 3,
568 *store_mfn, nr_pages - 2,
569 *console_mfn, nr_pages - 1);
571 start_info = xc_map_foreign_range(
572 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
573 page_array[nr_pages - 3]);
574 memset(start_info, 0, sizeof(*start_info));
575 rc = xc_version(xc_handle, XENVER_version, NULL);
576 sprintf(start_info->magic, "xen-%i.%i-ia64", rc >> 16, rc & (0xFFFF));
577 start_info->flags = flags;
578 start_info->store_mfn = nr_pages - 2;
579 start_info->store_evtchn = store_evtchn;
580 start_info->console.domU.mfn = nr_pages - 1;
581 start_info->console.domU.evtchn = console_evtchn;
582 start_info->nr_pages = nr_pages; // FIXME?: nr_pages - 2 ????
584 bp = (struct xen_ia64_boot_param *)(start_info + 1);
585 bp->command_line = start_info_mpa + offsetof(start_info_t, cmd_line);
586 if ( cmdline != NULL )
587 {
588 strncpy((char *)start_info->cmd_line, cmdline, MAX_GUEST_CMDLINE);
589 start_info->cmd_line[MAX_GUEST_CMDLINE - 1] = 0;
590 }
591 if ( initrd->len != 0 )
592 {
593 bp->initrd_start = vinitrd_start;
594 bp->initrd_size = initrd->len;
595 }
596 ctxt->user_regs.r28 = start_info_mpa + sizeof (start_info_t);
597 munmap(start_info, PAGE_SIZE);
599 /* shared_info page starts its life empty. */
600 shared_info = xc_map_foreign_range(
601 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, shared_info_frame);
602 printf("shared_info = %p, err=%s frame=%lx\n",
603 shared_info, strerror (errno), shared_info_frame);
604 //memset(shared_info, 0, PAGE_SIZE);
605 /* Mask all upcalls... */
606 for ( i = 0; i < MAX_VIRT_CPUS; i++ )
607 shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
608 shared_info->arch.start_info_pfn = nr_pages - 3;
610 munmap(shared_info, PAGE_SIZE);
612 free(page_array);
613 return 0;
615 error_out:
616 free(page_array);
617 return -1;
618 }
619 #else /* x86 */
621 /* Check if the platform supports the guest kernel format */
622 static int compat_check(int xc_handle, struct domain_setup_info *dsi)
623 {
624 xen_capabilities_info_t xen_caps = "";
626 if (xc_version(xc_handle, XENVER_capabilities, &xen_caps) != 0) {
627 ERROR("Cannot determine host capabilities.");
628 return 0;
629 }
631 if (strstr(xen_caps, "xen-3.0-x86_32p")) {
632 if (dsi->pae_kernel == PAEKERN_no) {
633 ERROR("Non PAE-kernel on PAE host.");
634 return 0;
635 }
636 } else if (dsi->pae_kernel != PAEKERN_no) {
637 ERROR("PAE-kernel on non-PAE host.");
638 return 0;
639 }
641 return 1;
642 }
644 static inline int increment_ulong(unsigned long *pval, unsigned long inc)
645 {
646 if ( inc >= -*pval )
647 {
648 ERROR("Value wrapped to zero: image too large?");
649 return 0;
650 }
651 *pval += inc;
652 return 1;
653 }
655 static int setup_guest(int xc_handle,
656 uint32_t dom,
657 const char *image, unsigned long image_size,
658 struct initrd_info *initrd,
659 unsigned long nr_pages,
660 unsigned long *pvsi, unsigned long *pvke,
661 unsigned long *pvss, vcpu_guest_context_t *ctxt,
662 const char *cmdline,
663 unsigned long shared_info_frame,
664 unsigned long flags,
665 unsigned int store_evtchn, unsigned long *store_mfn,
666 unsigned int console_evtchn, unsigned long *console_mfn,
667 uint32_t required_features[XENFEAT_NR_SUBMAPS])
668 {
669 xen_pfn_t *page_array = NULL;
670 unsigned long count, i;
671 unsigned long long hypercall_page;
672 int hypercall_page_defined;
673 start_info_t *start_info;
674 shared_info_t *shared_info;
675 const char *p;
676 DECLARE_DOMCTL;
677 int rc;
679 unsigned long nr_pt_pages;
680 unsigned long physmap_pfn;
681 xen_pfn_t *physmap, *physmap_e;
683 struct load_funcs load_funcs;
684 struct domain_setup_info dsi;
685 unsigned long vinitrd_start;
686 unsigned long vphysmap_start;
687 unsigned long vstartinfo_start;
688 unsigned long vstoreinfo_start;
689 unsigned long vconsole_start;
690 unsigned long vsharedinfo_start = 0; /* XXX gcc */
691 unsigned long vstack_start;
692 unsigned long vstack_end;
693 unsigned long vpt_start;
694 unsigned long vpt_end;
695 unsigned long v_end;
696 unsigned long guest_store_mfn, guest_console_mfn, guest_shared_info_mfn;
697 unsigned long shadow_mode_enabled;
698 uint32_t supported_features[XENFEAT_NR_SUBMAPS] = { 0, };
700 rc = probeimageformat(image, image_size, &load_funcs);
701 if ( rc != 0 )
702 goto error_out;
704 memset(&dsi, 0, sizeof(struct domain_setup_info));
706 rc = (load_funcs.parseimage)(image, image_size, &dsi);
707 if ( rc != 0 )
708 goto error_out;
710 if ( (dsi.v_start & (PAGE_SIZE-1)) != 0 )
711 {
712 PERROR("Guest OS must load to a page boundary.");
713 goto error_out;
714 }
716 if ( !compat_check(xc_handle, &dsi) )
717 goto error_out;
719 /* Parse and validate kernel features. */
720 if ( (p = xen_elfnote_string(&dsi, XEN_ELFNOTE_FEATURES)) != NULL )
721 {
722 if ( !parse_features(p, supported_features, required_features) )
723 {
724 ERROR("Failed to parse guest kernel features.");
725 goto error_out;
726 }
728 IPRINTF("Supported features = { %08x }.\n", supported_features[0]);
729 IPRINTF("Required features = { %08x }.\n", required_features[0]);
730 }
732 for ( i = 0; i < XENFEAT_NR_SUBMAPS; i++ )
733 {
734 if ( (supported_features[i] & required_features[i]) !=
735 required_features[i] )
736 {
737 ERROR("Guest kernel does not support a required feature.");
738 goto error_out;
739 }
740 }
742 shadow_mode_enabled = test_feature_bit(XENFEAT_auto_translated_physmap,
743 required_features);
745 if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL )
746 {
747 PERROR("Could not allocate memory");
748 goto error_out;
749 }
751 for ( i = 0; i < nr_pages; i++ )
752 page_array[i] = i;
754 if ( xc_domain_memory_populate_physmap(xc_handle, dom, nr_pages,
755 0, 0, page_array) )
756 {
757 PERROR("Could not allocate memory for PV guest.\n");
758 goto error_out;
759 }
761 rc = (load_funcs.loadimage)(image, image_size,
762 xc_handle, dom, page_array,
763 &dsi);
764 if ( rc != 0 )
765 goto error_out;
767 /*
768 * Why do we need this? The number of page-table frames depends on the
769 * size of the bootstrap address space. But the size of the address space
770 * depends on the number of page-table frames (since each one is mapped
771 * read-only). We have a pair of simultaneous equations in two unknowns,
772 * which we solve by exhaustive search.
773 */
774 v_end = round_pgup(dsi.v_end);
775 if ( v_end == 0 )
776 {
777 ERROR("End of mapped kernel image too close to end of memory");
778 goto error_out;
779 }
781 vinitrd_start = v_end;
782 if ( load_initrd(xc_handle, dom, initrd,
783 vinitrd_start - dsi.v_start, page_array) )
784 goto error_out;
785 if ( !increment_ulong(&v_end, round_pgup(initrd->len)) )
786 goto error_out;
788 vphysmap_start = v_end;
789 if ( !increment_ulong(&v_end, round_pgup(nr_pages * sizeof(long))) )
790 goto error_out;
791 vstartinfo_start = v_end;
792 if ( !increment_ulong(&v_end, PAGE_SIZE) )
793 goto error_out;
794 vstoreinfo_start = v_end;
795 if ( !increment_ulong(&v_end, PAGE_SIZE) )
796 goto error_out;
797 vconsole_start = v_end;
798 if ( !increment_ulong(&v_end, PAGE_SIZE) )
799 goto error_out;
800 if ( shadow_mode_enabled ) {
801 vsharedinfo_start = v_end;
802 if ( !increment_ulong(&v_end, PAGE_SIZE) )
803 goto error_out;
804 }
805 vpt_start = v_end;
807 for ( nr_pt_pages = 2; ; nr_pt_pages++ )
808 {
809 /* vpt_end = vpt_staret + (nr_pt_pages * PAGE_SIZE); */
810 vpt_end = vpt_start;
811 if ( !increment_ulong(&vpt_end, nr_pt_pages * PAGE_SIZE) )
812 goto error_out;
814 vstack_start = vpt_end;
815 /* vstack_end = vstack_start + PAGE_SIZE; */
816 vstack_end = vstack_start;
817 if ( !increment_ulong(&vstack_end, PAGE_SIZE) )
818 goto error_out;
820 /* v_end = (vstack_end + (1UL<<22)-1) & ~((1UL<<22)-1); */
821 v_end = vstack_end;
822 if ( !increment_ulong(&v_end, (1UL<<22)-1) )
823 goto error_out;
824 v_end &= ~((1UL<<22)-1);
826 if ( (v_end - vstack_end) < (512UL << 10) )
827 {
828 /* Add extra 4MB to get >= 512kB padding. */
829 if ( !increment_ulong(&v_end, 1UL << 22) )
830 goto error_out;
831 }
833 #define NR(_l,_h,_s) \
834 (((((unsigned long)(_h) + ((1UL<<(_s))-1)) & ~((1UL<<(_s))-1)) - \
835 ((unsigned long)(_l) & ~((1UL<<(_s))-1))) >> (_s))
836 #if defined(__i386__)
837 if ( dsi.pae_kernel != PAEKERN_no )
838 {
839 if ( (1 + /* # L3 */
840 NR(dsi.v_start, v_end, L3_PAGETABLE_SHIFT_PAE) + /* # L2 */
841 NR(dsi.v_start, v_end, L2_PAGETABLE_SHIFT_PAE) + /* # L1 */
842 /* Include a fourth mid-level page directory for Xen. */
843 (v_end <= (3 << L3_PAGETABLE_SHIFT_PAE)))
844 <= nr_pt_pages )
845 break;
846 }
847 else
848 {
849 if ( (1 + /* # L2 */
850 NR(dsi.v_start, v_end, L2_PAGETABLE_SHIFT)) /* # L1 */
851 <= nr_pt_pages )
852 break;
853 }
854 #elif defined(__x86_64__)
855 if ( (1 + /* # L4 */
856 NR(dsi.v_start, v_end, L4_PAGETABLE_SHIFT) + /* # L3 */
857 NR(dsi.v_start, v_end, L3_PAGETABLE_SHIFT) + /* # L2 */
858 NR(dsi.v_start, v_end, L2_PAGETABLE_SHIFT)) /* # L1 */
859 <= nr_pt_pages )
860 break;
861 #endif
862 }
864 IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n");
865 IPRINTF(" Loaded kernel: %p->%p\n", _p(dsi.v_kernstart),
866 _p(dsi.v_kernend));
867 if ( initrd->len )
868 IPRINTF(" Initial ramdisk: %p->%p\n", _p(vinitrd_start),
869 _p(vinitrd_start + initrd->len));
870 IPRINTF(" Phys-Mach map: %p\n", _p(vphysmap_start));
871 IPRINTF(" Start info: %p\n", _p(vstartinfo_start));
872 IPRINTF(" Store page: %p\n", _p(vstoreinfo_start));
873 IPRINTF(" Console page: %p\n", _p(vconsole_start));
874 if ( shadow_mode_enabled )
875 IPRINTF(" Shared Info page: %p\n", _p(vsharedinfo_start));
876 IPRINTF(" Page tables: %p\n", _p(vpt_start));
877 IPRINTF(" Boot stack: %p\n", _p(vstack_start));
878 IPRINTF(" TOTAL: %p->%p\n", _p(dsi.v_start), _p(v_end));
879 IPRINTF(" ENTRY ADDRESS: %p\n", _p(dsi.v_kernentry));
881 if ( ((v_end - dsi.v_start)>>PAGE_SHIFT) > nr_pages )
882 {
883 PERROR("Initial guest OS requires too much space\n"
884 "(%pMB is greater than %luMB limit)\n",
885 _p((v_end-dsi.v_start)>>20), nr_pages>>(20-PAGE_SHIFT));
886 goto error_out;
887 }
889 #if defined(__i386__)
890 if ( dsi.pae_kernel != PAEKERN_no )
891 rc = setup_pg_tables_pae(xc_handle, dom, ctxt,
892 dsi.v_start, v_end,
893 page_array, vpt_start, vpt_end,
894 shadow_mode_enabled, dsi.pae_kernel);
895 else
896 rc = setup_pg_tables(xc_handle, dom, ctxt,
897 dsi.v_start, v_end,
898 page_array, vpt_start, vpt_end,
899 shadow_mode_enabled);
900 #endif
901 #if defined(__x86_64__)
902 rc = setup_pg_tables_64(xc_handle, dom, ctxt,
903 dsi.v_start, v_end,
904 page_array, vpt_start, vpt_end,
905 shadow_mode_enabled);
906 #endif
907 if ( rc != 0 )
908 goto error_out;
910 /*
911 * Pin down l2tab addr as page dir page - causes hypervisor to provide
912 * correct protection for the page
913 */
914 if ( !shadow_mode_enabled )
915 {
916 #if defined(__i386__)
917 if ( dsi.pae_kernel != PAEKERN_no )
918 {
919 if ( pin_table(xc_handle, MMUEXT_PIN_L3_TABLE,
920 xen_cr3_to_pfn(ctxt->ctrlreg[3]), dom) )
921 goto error_out;
922 }
923 else
924 {
925 if ( pin_table(xc_handle, MMUEXT_PIN_L2_TABLE,
926 xen_cr3_to_pfn(ctxt->ctrlreg[3]), dom) )
927 goto error_out;
928 }
929 #elif defined(__x86_64__)
930 /*
931 * Pin down l4tab addr as page dir page - causes hypervisor to provide
932 * correct protection for the page
933 */
934 if ( pin_table(xc_handle, MMUEXT_PIN_L4_TABLE,
935 xen_cr3_to_pfn(ctxt->ctrlreg[3]), dom) )
936 goto error_out;
937 #endif
938 }
940 /* Write the phys->machine table entries (machine->phys already done). */
941 physmap_pfn = (vphysmap_start - dsi.v_start) >> PAGE_SHIFT;
942 physmap = physmap_e = xc_map_foreign_range(
943 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
944 page_array[physmap_pfn++]);
945 for ( count = 0; count < nr_pages; count++ )
946 {
947 *physmap_e++ = page_array[count];
948 if ( ((unsigned long)physmap_e & (PAGE_SIZE-1)) == 0 )
949 {
950 munmap(physmap, PAGE_SIZE);
951 physmap = physmap_e = xc_map_foreign_range(
952 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
953 page_array[physmap_pfn++]);
954 }
955 }
956 munmap(physmap, PAGE_SIZE);
958 if ( shadow_mode_enabled )
959 {
960 struct xen_add_to_physmap xatp;
962 /* Enable shadow translate mode */
963 if ( xc_shadow_control(xc_handle, dom,
964 XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE,
965 NULL, 0, NULL, 0, NULL) < 0 )
966 {
967 PERROR("Could not enable translation mode");
968 goto error_out;
969 }
971 guest_shared_info_mfn = (vsharedinfo_start-dsi.v_start) >> PAGE_SHIFT;
973 /* Map shared info frame into guest physmap. */
974 xatp.domid = dom;
975 xatp.space = XENMAPSPACE_shared_info;
976 xatp.idx = 0;
977 xatp.gpfn = guest_shared_info_mfn;
978 rc = xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp);
979 if ( rc != 0 )
980 {
981 PERROR("Cannot map shared info pfn");
982 goto error_out;
983 }
985 /* Map grant table frames into guest physmap. */
986 for ( i = 0; ; i++ )
987 {
988 xatp.domid = dom;
989 xatp.space = XENMAPSPACE_grant_table;
990 xatp.idx = i;
991 xatp.gpfn = nr_pages + i;
992 rc = xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp);
993 if ( rc != 0 )
994 {
995 if ( errno == EINVAL )
996 break; /* done all grant tables */
997 PERROR("Cannot map grant table pfn");
998 goto error_out;
999 }
1002 else
1004 guest_shared_info_mfn = shared_info_frame;
1007 *store_mfn = page_array[(vstoreinfo_start-dsi.v_start) >> PAGE_SHIFT];
1008 *console_mfn = page_array[(vconsole_start-dsi.v_start) >> PAGE_SHIFT];
1009 if ( xc_clear_domain_page(xc_handle, dom, *store_mfn) ||
1010 xc_clear_domain_page(xc_handle, dom, *console_mfn) )
1011 goto error_out;
1012 if ( shadow_mode_enabled )
1014 guest_store_mfn = (vstoreinfo_start-dsi.v_start) >> PAGE_SHIFT;
1015 guest_console_mfn = (vconsole_start-dsi.v_start) >> PAGE_SHIFT;
1017 else
1019 guest_store_mfn = *store_mfn;
1020 guest_console_mfn = *console_mfn;
1023 start_info = xc_map_foreign_range(
1024 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
1025 page_array[(vstartinfo_start-dsi.v_start)>>PAGE_SHIFT]);
1026 /*shared_info, start_info */
1027 memset(start_info, 0, sizeof(*start_info));
1028 rc = xc_version(xc_handle, XENVER_version, NULL);
1029 sprintf(start_info->magic, "xen-%i.%i-x86_%d%s",
1030 rc >> 16, rc & (0xFFFF), (unsigned int)sizeof(long)*8,
1031 (dsi.pae_kernel != PAEKERN_no) ? "p" : "");
1032 start_info->nr_pages = nr_pages;
1033 start_info->shared_info = guest_shared_info_mfn << PAGE_SHIFT;
1034 start_info->flags = flags;
1035 start_info->pt_base = vpt_start;
1036 start_info->nr_pt_frames = nr_pt_pages;
1037 start_info->mfn_list = vphysmap_start;
1038 start_info->store_mfn = guest_store_mfn;
1039 start_info->store_evtchn = store_evtchn;
1040 start_info->console.domU.mfn = guest_console_mfn;
1041 start_info->console.domU.evtchn = console_evtchn;
1042 if ( initrd->len != 0 )
1044 start_info->mod_start = vinitrd_start;
1045 start_info->mod_len = initrd->len;
1047 if ( cmdline != NULL )
1049 strncpy((char *)start_info->cmd_line, cmdline, MAX_GUEST_CMDLINE);
1050 start_info->cmd_line[MAX_GUEST_CMDLINE-1] = '\0';
1052 munmap(start_info, PAGE_SIZE);
1054 /* shared_info page starts its life empty. */
1055 shared_info = xc_map_foreign_range(
1056 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, shared_info_frame);
1057 memset(shared_info, 0, PAGE_SIZE);
1058 /* Mask all upcalls... */
1059 for ( i = 0; i < MAX_VIRT_CPUS; i++ )
1060 shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
1062 munmap(shared_info, PAGE_SIZE);
1064 hypercall_page = xen_elfnote_numeric(&dsi, XEN_ELFNOTE_HYPERCALL_PAGE,
1065 &hypercall_page_defined);
1066 if ( hypercall_page_defined )
1068 unsigned long long pfn = (hypercall_page - dsi.v_start) >> PAGE_SHIFT;
1069 if ( pfn >= nr_pages )
1070 goto error_out;
1071 domctl.domain = (domid_t)dom;
1072 domctl.u.hypercall_init.gmfn = shadow_mode_enabled ?
1073 pfn : page_array[pfn];
1074 domctl.cmd = XEN_DOMCTL_hypercall_init;
1075 if ( xc_domctl(xc_handle, &domctl) )
1076 goto error_out;
1079 free(page_array);
1081 *pvsi = vstartinfo_start;
1082 *pvss = vstack_start;
1083 *pvke = dsi.v_kernentry;
1085 return 0;
1087 error_out:
1088 free(page_array);
1089 return -1;
1091 #endif
1093 static int xc_linux_build_internal(int xc_handle,
1094 uint32_t domid,
1095 unsigned int mem_mb,
1096 char *image,
1097 unsigned long image_size,
1098 struct initrd_info *initrd,
1099 const char *cmdline,
1100 const char *features,
1101 unsigned long flags,
1102 unsigned int store_evtchn,
1103 unsigned long *store_mfn,
1104 unsigned int console_evtchn,
1105 unsigned long *console_mfn)
1107 struct xen_domctl launch_domctl;
1108 DECLARE_DOMCTL;
1109 int rc, i;
1110 struct vcpu_guest_context st_ctxt, *ctxt = &st_ctxt;
1111 unsigned long vstartinfo_start, vkern_entry, vstack_start;
1112 uint32_t features_bitmap[XENFEAT_NR_SUBMAPS] = { 0, };
1114 if ( features != NULL )
1116 if ( !parse_features(features, features_bitmap, NULL) )
1118 PERROR("Failed to parse configured features\n");
1119 goto error_out;
1123 #ifdef VALGRIND
1124 memset(&st_ctxt, 0, sizeof(st_ctxt));
1125 #endif
1127 if ( lock_pages(&st_ctxt, sizeof(st_ctxt) ) )
1129 PERROR("%s: ctxt lock failed", __func__);
1130 return 1;
1133 domctl.cmd = XEN_DOMCTL_getdomaininfo;
1134 domctl.domain = (domid_t)domid;
1135 if ( (xc_domctl(xc_handle, &domctl) < 0) ||
1136 ((uint16_t)domctl.domain != domid) )
1138 PERROR("Could not get info on domain");
1139 goto error_out;
1142 memset(ctxt, 0, sizeof(*ctxt));
1144 if ( setup_guest(xc_handle, domid, image, image_size,
1145 initrd,
1146 mem_mb << (20 - PAGE_SHIFT),
1147 &vstartinfo_start, &vkern_entry,
1148 &vstack_start, ctxt, cmdline,
1149 domctl.u.getdomaininfo.shared_info_frame,
1150 flags, store_evtchn, store_mfn,
1151 console_evtchn, console_mfn,
1152 features_bitmap) < 0 )
1154 ERROR("Error constructing guest OS");
1155 goto error_out;
1158 #ifdef __ia64__
1159 /* based on new_thread in xen/arch/ia64/domain.c */
1160 ctxt->flags = 0;
1161 ctxt->user_regs.cr_ipsr = 0; /* all necessary bits filled by hypervisor */
1162 ctxt->user_regs.cr_iip = vkern_entry;
1163 ctxt->user_regs.cr_ifs = 1UL << 63;
1164 ctxt->user_regs.ar_fpsr = xc_ia64_fpsr_default();
1165 i = 0; /* silence unused variable warning */
1166 #else /* x86 */
1167 /*
1168 * Initial register values:
1169 * DS,ES,FS,GS = FLAT_KERNEL_DS
1170 * CS:EIP = FLAT_KERNEL_CS:start_pc
1171 * SS:ESP = FLAT_KERNEL_DS:start_stack
1172 * ESI = start_info
1173 * [EAX,EBX,ECX,EDX,EDI,EBP are zero]
1174 * EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
1175 */
1176 ctxt->user_regs.ds = FLAT_KERNEL_DS;
1177 ctxt->user_regs.es = FLAT_KERNEL_DS;
1178 ctxt->user_regs.fs = FLAT_KERNEL_DS;
1179 ctxt->user_regs.gs = FLAT_KERNEL_DS;
1180 ctxt->user_regs.ss = FLAT_KERNEL_SS;
1181 ctxt->user_regs.cs = FLAT_KERNEL_CS;
1182 ctxt->user_regs.eip = vkern_entry;
1183 ctxt->user_regs.esp = vstack_start + PAGE_SIZE;
1184 ctxt->user_regs.esi = vstartinfo_start;
1185 ctxt->user_regs.eflags = 1 << 9; /* Interrupt Enable */
1187 ctxt->flags = VGCF_IN_KERNEL;
1189 /* FPU is set up to default initial state. */
1190 memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
1192 /* Virtual IDT is empty at start-of-day. */
1193 for ( i = 0; i < 256; i++ )
1195 ctxt->trap_ctxt[i].vector = i;
1196 ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS;
1199 /* No LDT. */
1200 ctxt->ldt_ents = 0;
1202 /* Use the default Xen-provided GDT. */
1203 ctxt->gdt_ents = 0;
1205 /* Ring 1 stack is the initial stack. */
1206 ctxt->kernel_ss = FLAT_KERNEL_SS;
1207 ctxt->kernel_sp = vstack_start + PAGE_SIZE;
1209 /* No debugging. */
1210 memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
1212 /* No callback handlers. */
1213 #if defined(__i386__)
1214 ctxt->event_callback_cs = FLAT_KERNEL_CS;
1215 ctxt->event_callback_eip = 0;
1216 ctxt->failsafe_callback_cs = FLAT_KERNEL_CS;
1217 ctxt->failsafe_callback_eip = 0;
1218 #elif defined(__x86_64__)
1219 ctxt->event_callback_eip = 0;
1220 ctxt->failsafe_callback_eip = 0;
1221 ctxt->syscall_callback_eip = 0;
1222 #endif
1223 #endif /* x86 */
1225 memset( &launch_domctl, 0, sizeof(launch_domctl) );
1227 launch_domctl.domain = (domid_t)domid;
1228 launch_domctl.u.vcpucontext.vcpu = 0;
1229 set_xen_guest_handle(launch_domctl.u.vcpucontext.ctxt, ctxt);
1231 launch_domctl.cmd = XEN_DOMCTL_setvcpucontext;
1232 rc = xc_domctl(xc_handle, &launch_domctl);
1234 return rc;
1236 error_out:
1237 return -1;
1240 int xc_linux_build_mem(int xc_handle,
1241 uint32_t domid,
1242 unsigned int mem_mb,
1243 const char *image_buffer,
1244 unsigned long image_size,
1245 const char *initrd,
1246 unsigned long initrd_len,
1247 const char *cmdline,
1248 const char *features,
1249 unsigned long flags,
1250 unsigned int store_evtchn,
1251 unsigned long *store_mfn,
1252 unsigned int console_evtchn,
1253 unsigned long *console_mfn)
1255 int sts;
1256 char *img_buf;
1257 unsigned long img_len;
1258 struct initrd_info initrd_info = { .type = INITRD_none };
1260 /* A kernel buffer is required */
1261 if ( (image_buffer == NULL) || (image_size == 0) )
1263 ERROR("kernel image buffer not present");
1264 return -1;
1267 /* If it's gzipped, inflate it; otherwise, use as is */
1268 /* xc_inflate_buffer may return the same buffer pointer if */
1269 /* the buffer is already inflated */
1270 img_buf = xc_inflate_buffer(image_buffer, image_size, &img_len);
1271 if ( img_buf == NULL )
1273 ERROR("unable to inflate kernel image buffer");
1274 return -1;
1277 /* RAM disks are optional; if we get one, inflate it */
1278 if ( initrd != NULL )
1280 initrd_info.type = INITRD_mem;
1281 initrd_info.u.mem_addr = xc_inflate_buffer(
1282 initrd, initrd_len, &initrd_info.len);
1283 if ( initrd_info.u.mem_addr == NULL )
1285 ERROR("unable to inflate ram disk buffer");
1286 sts = -1;
1287 goto out;
1291 sts = xc_linux_build_internal(xc_handle, domid, mem_mb, img_buf, img_len,
1292 &initrd_info, cmdline, features, flags,
1293 store_evtchn, store_mfn,
1294 console_evtchn, console_mfn);
1296 out:
1297 /* The inflation routines may pass back the same buffer so be */
1298 /* sure that we have a buffer and that it's not the one passed in. */
1299 /* Don't unnecessarily annoy/surprise/confound the caller */
1300 if ( (img_buf != NULL) && (img_buf != image_buffer) )
1301 free(img_buf);
1302 if ( (initrd_info.u.mem_addr != NULL) &&
1303 (initrd_info.u.mem_addr != initrd) )
1304 free(initrd_info.u.mem_addr);
1306 return sts;
1309 int xc_linux_build(int xc_handle,
1310 uint32_t domid,
1311 unsigned int mem_mb,
1312 const char *image_name,
1313 const char *initrd_name,
1314 const char *cmdline,
1315 const char *features,
1316 unsigned long flags,
1317 unsigned int store_evtchn,
1318 unsigned long *store_mfn,
1319 unsigned int console_evtchn,
1320 unsigned long *console_mfn)
1322 char *image = NULL;
1323 unsigned long image_size;
1324 struct initrd_info initrd_info = { .type = INITRD_none };
1325 int fd = -1, sts = -1;
1327 if ( (image_name == NULL) ||
1328 ((image = xc_read_image(image_name, &image_size)) == NULL ))
1329 return -1;
1331 if ( (initrd_name != NULL) && (strlen(initrd_name) != 0) )
1333 initrd_info.type = INITRD_file;
1335 if ( (fd = open(initrd_name, O_RDONLY)) < 0 )
1337 PERROR("Could not open the initial ramdisk image");
1338 goto error_out;
1341 if ( (initrd_info.u.file_handle = gzdopen(fd, "rb")) == NULL )
1343 PERROR("Could not allocate decompression state for initrd");
1344 goto error_out;
1348 sts = xc_linux_build_internal(xc_handle, domid, mem_mb, image, image_size,
1349 &initrd_info, cmdline, features, flags,
1350 store_evtchn, store_mfn,
1351 console_evtchn, console_mfn);
1353 error_out:
1354 free(image);
1355 if ( initrd_info.type == INITRD_file && initrd_info.u.file_handle )
1356 gzclose(initrd_info.u.file_handle);
1357 else if ( fd >= 0 )
1358 close(fd);
1360 return sts;
1363 /*
1364 * Local variables:
1365 * mode: C
1366 * c-set-style: "BSD"
1367 * c-basic-offset: 4
1368 * tab-width: 4
1369 * indent-tabs-mode: nil
1370 * End:
1371 */