ia64/xen-unstable

view tools/libxc/xc_linux_build.c @ 10692:306d7857928c

[IA64] Save & restore.

xc_ia64_linux_save.c and xc_ia64_linux_restore.c added.
vcpu context has more registers and states (eg: tr registers).
Per cpu irqs are deallocated when cpu is switched off.
#if/#endif added in reboot.c for ia64.

Signed-off-by: Tristan Gingold <tristan.gingold@bull.net>
author awilliam@xenbuild.aw
date Tue Jul 11 12:51:18 2006 -0600 (2006-07-11)
parents 2b815d9acdea
children 46df563bf1b8
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 #if defined(__i386__)
20 #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
21 #define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
22 #define L3_PROT (_PAGE_PRESENT)
23 #endif
25 #if defined(__x86_64__)
26 #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER)
27 #define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
28 #define L3_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
29 #define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
30 #endif
32 #ifdef __ia64__
33 #define get_tot_pages xc_get_max_pages
34 #else
35 #define get_tot_pages xc_get_tot_pages
36 #endif
38 #define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
39 #define round_pgdown(_p) ((_p)&PAGE_MASK)
41 struct initrd_info {
42 enum { INITRD_none, INITRD_file, INITRD_mem } type;
43 unsigned long len;
44 union {
45 gzFile file_handle;
46 char *mem_addr;
47 } u;
48 };
50 static const char *feature_names[XENFEAT_NR_SUBMAPS*32] = {
51 [XENFEAT_writable_page_tables] = "writable_page_tables",
52 [XENFEAT_writable_descriptor_tables] = "writable_descriptor_tables",
53 [XENFEAT_auto_translated_physmap] = "auto_translated_physmap",
54 [XENFEAT_supervisor_mode_kernel] = "supervisor_mode_kernel",
55 [XENFEAT_pae_pgdir_above_4gb] = "pae_pgdir_above_4gb"
56 };
58 static inline void set_feature_bit (int nr, uint32_t *addr)
59 {
60 addr[nr>>5] |= (1<<(nr&31));
61 }
63 static inline int test_feature_bit(int nr, uint32_t *addr)
64 {
65 return !!(addr[nr>>5] & (1<<(nr&31)));
66 }
68 static int parse_features(
69 const char *feats,
70 uint32_t supported[XENFEAT_NR_SUBMAPS],
71 uint32_t required[XENFEAT_NR_SUBMAPS])
72 {
73 const char *end, *p;
74 int i, req;
76 if ( (end = strchr(feats, ',')) == NULL )
77 end = feats + strlen(feats);
79 while ( feats < end )
80 {
81 p = strchr(feats, '|');
82 if ( (p == NULL) || (p > end) )
83 p = end;
85 req = (*feats == '!');
86 if ( req )
87 feats++;
89 for ( i = 0; i < XENFEAT_NR_SUBMAPS*32; i++ )
90 {
91 if ( feature_names[i] == NULL )
92 continue;
94 if ( strncmp(feature_names[i], feats, p-feats) == 0 )
95 {
96 set_feature_bit(i, supported);
97 if ( required && req )
98 set_feature_bit(i, required);
99 break;
100 }
101 }
103 if ( i == XENFEAT_NR_SUBMAPS*32 )
104 {
105 ERROR("Unknown feature \"%.*s\".", (int)(p-feats), feats);
106 if ( req )
107 {
108 ERROR("Kernel requires an unknown hypervisor feature.");
109 return -EINVAL;
110 }
111 }
113 feats = p;
114 if ( *feats == '|' )
115 feats++;
116 }
118 return -EINVAL;
119 }
121 static int probeimageformat(const char *image,
122 unsigned long image_size,
123 struct load_funcs *load_funcs)
124 {
125 if ( probe_elf(image, image_size, load_funcs) &&
126 probe_bin(image, image_size, load_funcs) )
127 {
128 ERROR( "Unrecognized image format" );
129 return -EINVAL;
130 }
132 return 0;
133 }
135 int load_initrd(int xc_handle, domid_t dom,
136 struct initrd_info *initrd,
137 unsigned long physbase,
138 xen_pfn_t *phys_to_mach)
139 {
140 char page[PAGE_SIZE];
141 unsigned long pfn_start, pfn, nr_pages;
143 if ( initrd->type == INITRD_none )
144 return 0;
146 pfn_start = physbase >> PAGE_SHIFT;
147 nr_pages = (initrd->len + PAGE_SIZE - 1) >> PAGE_SHIFT;
149 for ( pfn = pfn_start; pfn < (pfn_start + nr_pages); pfn++ )
150 {
151 if ( initrd->type == INITRD_mem )
152 {
153 xc_copy_to_domain_page(
154 xc_handle, dom, phys_to_mach[pfn],
155 &initrd->u.mem_addr[(pfn - pfn_start) << PAGE_SHIFT]);
156 }
157 else
158 {
159 if ( gzread(initrd->u.file_handle, page, PAGE_SIZE) == -1 )
160 {
161 PERROR("Error reading initrd image, could not");
162 return -EINVAL;
163 }
164 xc_copy_to_domain_page(xc_handle, dom, phys_to_mach[pfn], page);
165 }
166 }
168 return 0;
169 }
171 #define alloc_pt(ltab, vltab, pltab) \
172 do { \
173 pltab = ppt_alloc++; \
174 ltab = (uint64_t)page_array[pltab] << PAGE_SHIFT; \
175 pltab <<= PAGE_SHIFT; \
176 if ( vltab != NULL ) \
177 munmap(vltab, PAGE_SIZE); \
178 if ( (vltab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, \
179 PROT_READ|PROT_WRITE, \
180 ltab >> PAGE_SHIFT)) == NULL ) \
181 goto error_out; \
182 memset(vltab, 0x0, PAGE_SIZE); \
183 } while ( 0 )
185 #if defined(__i386__)
187 static int setup_pg_tables(int xc_handle, uint32_t dom,
188 vcpu_guest_context_t *ctxt,
189 unsigned long dsi_v_start,
190 unsigned long v_end,
191 xen_pfn_t *page_array,
192 unsigned long vpt_start,
193 unsigned long vpt_end,
194 unsigned shadow_mode_enabled)
195 {
196 l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
197 l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
198 unsigned long l1tab = 0, pl1tab;
199 unsigned long l2tab = 0, pl2tab;
200 unsigned long ppt_alloc;
201 unsigned long count;
203 ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT;
204 alloc_pt(l2tab, vl2tab, pl2tab);
205 vl2e = &vl2tab[l2_table_offset(dsi_v_start)];
206 if (shadow_mode_enabled)
207 ctxt->ctrlreg[3] = xen_pfn_to_cr3(pl2tab >> PAGE_SHIFT);
208 else
209 ctxt->ctrlreg[3] = xen_pfn_to_cr3(l2tab >> PAGE_SHIFT);
211 for ( count = 0; count < ((v_end - dsi_v_start) >> PAGE_SHIFT); count++ )
212 {
213 if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 )
214 {
215 alloc_pt(l1tab, vl1tab, pl1tab);
216 vl1e = &vl1tab[l1_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
217 if (shadow_mode_enabled)
218 *vl2e = pl1tab | L2_PROT;
219 else
220 *vl2e = l1tab | L2_PROT;
221 vl2e++;
222 }
224 if ( shadow_mode_enabled )
225 {
226 *vl1e = (count << PAGE_SHIFT) | L1_PROT;
227 }
228 else
229 {
230 *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
231 if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
232 (count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
233 *vl1e &= ~_PAGE_RW;
234 }
235 vl1e++;
236 }
237 munmap(vl1tab, PAGE_SIZE);
238 munmap(vl2tab, PAGE_SIZE);
239 return 0;
241 error_out:
242 if (vl1tab)
243 munmap(vl1tab, PAGE_SIZE);
244 if (vl2tab)
245 munmap(vl2tab, PAGE_SIZE);
246 return -1;
247 }
249 static int setup_pg_tables_pae(int xc_handle, uint32_t dom,
250 vcpu_guest_context_t *ctxt,
251 unsigned long dsi_v_start,
252 unsigned long v_end,
253 xen_pfn_t *page_array,
254 unsigned long vpt_start,
255 unsigned long vpt_end,
256 unsigned shadow_mode_enabled,
257 unsigned pae_mode)
258 {
259 l1_pgentry_64_t *vl1tab = NULL, *vl1e = NULL;
260 l2_pgentry_64_t *vl2tab = NULL, *vl2e = NULL;
261 l3_pgentry_64_t *vl3tab = NULL, *vl3e = NULL;
262 uint64_t l1tab, l2tab, l3tab, pl1tab, pl2tab, pl3tab;
263 unsigned long ppt_alloc, count, nmfn;
265 /* First allocate page for page dir. */
266 ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT;
268 if ( pae_mode == PAEKERN_extended_cr3 )
269 {
270 ctxt->vm_assist |= (1UL << VMASST_TYPE_pae_extended_cr3);
271 }
272 else if ( page_array[ppt_alloc] > 0xfffff )
273 {
274 nmfn = xc_make_page_below_4G(xc_handle, dom, page_array[ppt_alloc]);
275 if ( nmfn == 0 )
276 {
277 DPRINTF("Couldn't get a page below 4GB :-(\n");
278 goto error_out;
279 }
280 page_array[ppt_alloc] = nmfn;
281 }
283 alloc_pt(l3tab, vl3tab, pl3tab);
284 vl3e = &vl3tab[l3_table_offset_pae(dsi_v_start)];
285 if (shadow_mode_enabled)
286 ctxt->ctrlreg[3] = xen_pfn_to_cr3(pl3tab >> PAGE_SHIFT);
287 else
288 ctxt->ctrlreg[3] = xen_pfn_to_cr3(l3tab >> PAGE_SHIFT);
290 for ( count = 0; count < ((v_end - dsi_v_start) >> PAGE_SHIFT); count++)
291 {
292 if ( !((unsigned long)vl1e & (PAGE_SIZE-1)) )
293 {
294 if ( !((unsigned long)vl2e & (PAGE_SIZE-1)) )
295 {
296 alloc_pt(l2tab, vl2tab, pl2tab);
297 vl2e = &vl2tab[l2_table_offset_pae(
298 dsi_v_start + (count << PAGE_SHIFT))];
299 if (shadow_mode_enabled)
300 *vl3e = pl2tab | L3_PROT;
301 else
302 *vl3e++ = l2tab | L3_PROT;
303 }
305 alloc_pt(l1tab, vl1tab, pl1tab);
306 vl1e = &vl1tab[l1_table_offset_pae(
307 dsi_v_start + (count << PAGE_SHIFT))];
308 if (shadow_mode_enabled)
309 *vl2e = pl1tab | L2_PROT;
310 else
311 *vl2e++ = l1tab | L2_PROT;
312 }
314 if ( shadow_mode_enabled )
315 {
316 *vl1e = (count << PAGE_SHIFT) | L1_PROT;
317 }
318 else
319 {
320 *vl1e = ((uint64_t)page_array[count] << PAGE_SHIFT) | L1_PROT;
321 if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
322 (count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
323 *vl1e &= ~_PAGE_RW;
324 }
325 vl1e++;
326 }
328 /* Xen requires a mid-level pgdir mapping 0xC0000000 region. */
329 if ( (vl3tab[3] & _PAGE_PRESENT) == 0 )
330 {
331 alloc_pt(l2tab, vl2tab, pl2tab);
332 vl3tab[3] = l2tab | L3_PROT;
333 }
335 munmap(vl1tab, PAGE_SIZE);
336 munmap(vl2tab, PAGE_SIZE);
337 munmap(vl3tab, PAGE_SIZE);
338 return 0;
340 error_out:
341 if (vl1tab)
342 munmap(vl1tab, PAGE_SIZE);
343 if (vl2tab)
344 munmap(vl2tab, PAGE_SIZE);
345 if (vl3tab)
346 munmap(vl3tab, PAGE_SIZE);
347 return -1;
348 }
350 #endif
352 #if defined(__x86_64__)
354 static int setup_pg_tables_64(int xc_handle, uint32_t dom,
355 vcpu_guest_context_t *ctxt,
356 unsigned long dsi_v_start,
357 unsigned long v_end,
358 xen_pfn_t *page_array,
359 unsigned long vpt_start,
360 unsigned long vpt_end,
361 int shadow_mode_enabled)
362 {
363 l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
364 l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
365 l3_pgentry_t *vl3tab=NULL, *vl3e=NULL;
366 l4_pgentry_t *vl4tab=NULL, *vl4e=NULL;
367 unsigned long l2tab = 0, pl2tab;
368 unsigned long l1tab = 0, pl1tab;
369 unsigned long l3tab = 0, pl3tab;
370 unsigned long l4tab = 0, pl4tab;
371 unsigned long ppt_alloc;
372 unsigned long count;
374 /* First allocate page for page dir. */
375 ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT;
376 alloc_pt(l4tab, vl4tab, pl4tab);
377 vl4e = &vl4tab[l4_table_offset(dsi_v_start)];
378 if (shadow_mode_enabled)
379 ctxt->ctrlreg[3] = xen_pfn_to_cr3(pl4tab >> PAGE_SHIFT);
380 else
381 ctxt->ctrlreg[3] = xen_pfn_to_cr3(l4tab >> PAGE_SHIFT);
383 for ( count = 0; count < ((v_end-dsi_v_start)>>PAGE_SHIFT); count++)
384 {
385 if ( !((unsigned long)vl1e & (PAGE_SIZE-1)) )
386 {
387 alloc_pt(l1tab, vl1tab, pl1tab);
389 if ( !((unsigned long)vl2e & (PAGE_SIZE-1)) )
390 {
391 alloc_pt(l2tab, vl2tab, pl2tab);
392 if ( !((unsigned long)vl3e & (PAGE_SIZE-1)) )
393 {
394 alloc_pt(l3tab, vl3tab, pl3tab);
395 vl3e = &vl3tab[l3_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
396 if (shadow_mode_enabled)
397 *vl4e = pl3tab | L4_PROT;
398 else
399 *vl4e = l3tab | L4_PROT;
400 vl4e++;
401 }
402 vl2e = &vl2tab[l2_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
403 if (shadow_mode_enabled)
404 *vl3e = pl2tab | L3_PROT;
405 else
406 *vl3e = l2tab | L3_PROT;
407 vl3e++;
408 }
409 vl1e = &vl1tab[l1_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
410 if (shadow_mode_enabled)
411 *vl2e = pl1tab | L2_PROT;
412 else
413 *vl2e = l1tab | L2_PROT;
414 vl2e++;
415 }
417 if ( shadow_mode_enabled )
418 {
419 *vl1e = (count << PAGE_SHIFT) | L1_PROT;
420 }
421 else
422 {
423 *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
424 if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
425 (count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
426 {
427 *vl1e &= ~_PAGE_RW;
428 }
429 }
430 vl1e++;
431 }
433 munmap(vl1tab, PAGE_SIZE);
434 munmap(vl2tab, PAGE_SIZE);
435 munmap(vl3tab, PAGE_SIZE);
436 munmap(vl4tab, PAGE_SIZE);
437 return 0;
439 error_out:
440 if (vl1tab)
441 munmap(vl1tab, PAGE_SIZE);
442 if (vl2tab)
443 munmap(vl2tab, PAGE_SIZE);
444 if (vl3tab)
445 munmap(vl3tab, PAGE_SIZE);
446 if (vl4tab)
447 munmap(vl4tab, PAGE_SIZE);
448 return -1;
449 }
450 #endif
452 #ifdef __ia64__
453 extern unsigned long xc_ia64_fpsr_default(void);
455 static int setup_guest(int xc_handle,
456 uint32_t dom,
457 const char *image, unsigned long image_size,
458 struct initrd_info *initrd,
459 unsigned long nr_pages,
460 unsigned long *pvsi, unsigned long *pvke,
461 unsigned long *pvss, vcpu_guest_context_t *ctxt,
462 const char *cmdline,
463 unsigned long shared_info_frame,
464 unsigned long flags,
465 unsigned int store_evtchn, unsigned long *store_mfn,
466 unsigned int console_evtchn, unsigned long *console_mfn,
467 uint32_t required_features[XENFEAT_NR_SUBMAPS])
468 {
469 xen_pfn_t *page_array = NULL;
470 struct load_funcs load_funcs;
471 struct domain_setup_info dsi;
472 unsigned long vinitrd_start;
473 unsigned long vinitrd_end;
474 unsigned long v_end;
475 unsigned long start_page, pgnr;
476 start_info_t *start_info;
477 unsigned long start_info_mpa;
478 struct xen_ia64_boot_param *bp;
479 shared_info_t *shared_info;
480 int i;
481 DECLARE_DOM0_OP;
482 int rc;
484 rc = probeimageformat(image, image_size, &load_funcs);
485 if ( rc != 0 )
486 goto error_out;
488 memset(&dsi, 0, sizeof(struct domain_setup_info));
490 rc = (load_funcs.parseimage)(image, image_size, &dsi);
491 if ( rc != 0 )
492 goto error_out;
494 dsi.v_start = round_pgdown(dsi.v_start);
495 vinitrd_start = round_pgup(dsi.v_end);
496 vinitrd_end = vinitrd_start + initrd->len;
497 v_end = round_pgup(vinitrd_end);
498 start_info_mpa = (nr_pages - 3) << PAGE_SHIFT;
500 /* Build firmware. */
501 memset(&op.u.domain_setup, 0, sizeof(op.u.domain_setup));
502 op.u.domain_setup.flags = 0;
503 op.u.domain_setup.domain = (domid_t)dom;
504 op.u.domain_setup.bp = start_info_mpa + sizeof (start_info_t);
505 op.u.domain_setup.maxmem = (nr_pages - 3) << PAGE_SHIFT;
507 op.cmd = DOM0_DOMAIN_SETUP;
508 if ( xc_dom0_op(xc_handle, &op) )
509 goto error_out;
511 start_page = dsi.v_start >> PAGE_SHIFT;
512 pgnr = (v_end - dsi.v_start) >> PAGE_SHIFT;
513 if ( (page_array = malloc(pgnr * sizeof(xen_pfn_t))) == NULL )
514 {
515 PERROR("Could not allocate memory");
516 goto error_out;
517 }
519 if ( xc_ia64_get_pfn_list(xc_handle, dom, page_array,
520 start_page, pgnr) != pgnr )
521 {
522 PERROR("Could not get the page frame list");
523 goto error_out;
524 }
526 IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n"
527 " Loaded kernel: %p->%p\n"
528 " Init. ramdisk: %p->%p\n"
529 " TOTAL: %p->%p\n",
530 _p(dsi.v_kernstart), _p(dsi.v_kernend),
531 _p(vinitrd_start), _p(vinitrd_end),
532 _p(dsi.v_start), _p(v_end));
533 IPRINTF(" ENTRY ADDRESS: %p\n", _p(dsi.v_kernentry));
535 (load_funcs.loadimage)(image, image_size, xc_handle, dom, page_array,
536 &dsi);
538 if ( load_initrd(xc_handle, dom, initrd,
539 vinitrd_start - dsi.v_start, page_array) )
540 goto error_out;
542 *pvke = dsi.v_kernentry;
544 /* Now need to retrieve machine pfn for system pages:
545 * start_info/store/console
546 */
547 pgnr = 3;
548 if ( xc_ia64_get_pfn_list(xc_handle, dom, page_array,
549 nr_pages - 3, pgnr) != pgnr )
550 {
551 PERROR("Could not get page frame for xenstore");
552 goto error_out;
553 }
555 *store_mfn = page_array[1];
556 *console_mfn = page_array[2];
557 IPRINTF("start_info: 0x%lx at 0x%lx, "
558 "store_mfn: 0x%lx at 0x%lx, "
559 "console_mfn: 0x%lx at 0x%lx\n",
560 page_array[0], nr_pages - 3,
561 *store_mfn, nr_pages - 2,
562 *console_mfn, nr_pages - 1);
564 start_info = xc_map_foreign_range(
565 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, page_array[0]);
566 memset(start_info, 0, sizeof(*start_info));
567 rc = xc_version(xc_handle, XENVER_version, NULL);
568 sprintf(start_info->magic, "xen-%i.%i-ia64", rc >> 16, rc & (0xFFFF));
569 start_info->flags = flags;
570 start_info->store_mfn = nr_pages - 2;
571 start_info->store_evtchn = store_evtchn;
572 start_info->console_mfn = nr_pages - 1;
573 start_info->console_evtchn = console_evtchn;
574 start_info->nr_pages = nr_pages; // FIXME?: nr_pages - 2 ????
576 bp = (struct xen_ia64_boot_param *)(start_info + 1);
577 bp->command_line = start_info_mpa + offsetof(start_info_t, cmd_line);
578 if ( cmdline != NULL )
579 {
580 strncpy((char *)start_info->cmd_line, cmdline, MAX_GUEST_CMDLINE);
581 start_info->cmd_line[MAX_GUEST_CMDLINE - 1] = 0;
582 }
583 if ( initrd->len != 0 )
584 {
585 bp->initrd_start = vinitrd_start;
586 bp->initrd_size = initrd->len;
587 }
588 ctxt->user_regs.r28 = start_info_mpa + sizeof (start_info_t);
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 printf("shared_info = %p, err=%s frame=%lx\n",
595 shared_info, strerror (errno), shared_info_frame);
596 //memset(shared_info, 0, sizeof(shared_info_t));
597 /* Mask all upcalls... */
598 for ( i = 0; i < MAX_VIRT_CPUS; i++ )
599 shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
600 shared_info->arch.start_info_pfn = nr_pages - 3;
602 munmap(shared_info, PAGE_SIZE);
604 free(page_array);
605 return 0;
607 error_out:
608 free(page_array);
609 return -1;
610 }
611 #else /* x86 */
613 /* Check if the platform supports the guest kernel format */
614 static int compat_check(int xc_handle, struct domain_setup_info *dsi)
615 {
616 xen_capabilities_info_t xen_caps = "";
618 if (xc_version(xc_handle, XENVER_capabilities, &xen_caps) != 0) {
619 ERROR("Cannot determine host capabilities.");
620 return 0;
621 }
623 if (strstr(xen_caps, "xen-3.0-x86_32p")) {
624 if (dsi->pae_kernel == PAEKERN_no) {
625 ERROR("Non PAE-kernel on PAE host.");
626 return 0;
627 }
628 } else if (dsi->pae_kernel != PAEKERN_no) {
629 ERROR("PAE-kernel on non-PAE host.");
630 return 0;
631 }
633 return 1;
634 }
636 static inline int increment_ulong(unsigned long *pval, unsigned long inc)
637 {
638 if ( inc >= -*pval )
639 {
640 ERROR("Value wrapped to zero: image too large?");
641 return 0;
642 }
643 *pval += inc;
644 return 1;
645 }
647 static int setup_guest(int xc_handle,
648 uint32_t dom,
649 const char *image, unsigned long image_size,
650 struct initrd_info *initrd,
651 unsigned long nr_pages,
652 unsigned long *pvsi, unsigned long *pvke,
653 unsigned long *pvss, vcpu_guest_context_t *ctxt,
654 const char *cmdline,
655 unsigned long shared_info_frame,
656 unsigned long flags,
657 unsigned int store_evtchn, unsigned long *store_mfn,
658 unsigned int console_evtchn, unsigned long *console_mfn,
659 uint32_t required_features[XENFEAT_NR_SUBMAPS])
660 {
661 xen_pfn_t *page_array = NULL;
662 unsigned long count, i, hypercall_pfn;
663 start_info_t *start_info;
664 shared_info_t *shared_info;
665 xc_mmu_t *mmu = NULL;
666 char *p;
667 DECLARE_DOM0_OP;
668 int rc;
670 unsigned long nr_pt_pages;
671 unsigned long physmap_pfn;
672 xen_pfn_t *physmap, *physmap_e;
674 struct load_funcs load_funcs;
675 struct domain_setup_info dsi;
676 unsigned long vinitrd_start;
677 unsigned long vphysmap_start;
678 unsigned long vstartinfo_start;
679 unsigned long vstoreinfo_start;
680 unsigned long vconsole_start;
681 unsigned long vsharedinfo_start = 0; /* XXX gcc */
682 unsigned long vstack_start;
683 unsigned long vstack_end;
684 unsigned long vpt_start;
685 unsigned long vpt_end;
686 unsigned long v_end;
687 unsigned long guest_store_mfn, guest_console_mfn, guest_shared_info_mfn;
688 unsigned long shadow_mode_enabled;
689 uint32_t supported_features[XENFEAT_NR_SUBMAPS] = { 0, };
691 rc = probeimageformat(image, image_size, &load_funcs);
692 if ( rc != 0 )
693 goto error_out;
695 memset(&dsi, 0, sizeof(struct domain_setup_info));
697 rc = (load_funcs.parseimage)(image, image_size, &dsi);
698 if ( rc != 0 )
699 goto error_out;
701 if ( (dsi.v_start & (PAGE_SIZE-1)) != 0 )
702 {
703 PERROR("Guest OS must load to a page boundary.");
704 goto error_out;
705 }
707 if (!compat_check(xc_handle, &dsi))
708 goto error_out;
710 /* Parse and validate kernel features. */
711 p = strstr(dsi.xen_guest_string, "FEATURES=");
712 if ( p != NULL )
713 {
714 if ( !parse_features(p + strlen("FEATURES="),
715 supported_features,
716 required_features) )
717 {
718 ERROR("Failed to parse guest kernel features.");
719 goto error_out;
720 }
722 IPRINTF("Supported features = { %08x }.\n", supported_features[0]);
723 IPRINTF("Required features = { %08x }.\n", required_features[0]);
724 }
726 for ( i = 0; i < XENFEAT_NR_SUBMAPS; i++ )
727 {
728 if ( (supported_features[i] & required_features[i]) !=
729 required_features[i] )
730 {
731 ERROR("Guest kernel does not support a required feature.");
732 goto error_out;
733 }
734 }
736 shadow_mode_enabled = test_feature_bit(XENFEAT_auto_translated_physmap,
737 required_features);
739 /*
740 * Why do we need this? The number of page-table frames depends on the
741 * size of the bootstrap address space. But the size of the address space
742 * depends on the number of page-table frames (since each one is mapped
743 * read-only). We have a pair of simultaneous equations in two unknowns,
744 * which we solve by exhaustive search.
745 */
746 v_end = round_pgup(dsi.v_end);
747 if ( v_end == 0 )
748 {
749 ERROR("End of mapped kernel image too close to end of memory");
750 goto error_out;
751 }
752 vinitrd_start = v_end;
753 if ( !increment_ulong(&v_end, round_pgup(initrd->len)) )
754 goto error_out;
755 vphysmap_start = v_end;
756 if ( !increment_ulong(&v_end, round_pgup(nr_pages * sizeof(long))) )
757 goto error_out;
758 vstartinfo_start = v_end;
759 if ( !increment_ulong(&v_end, PAGE_SIZE) )
760 goto error_out;
761 vstoreinfo_start = v_end;
762 if ( !increment_ulong(&v_end, PAGE_SIZE) )
763 goto error_out;
764 vconsole_start = v_end;
765 if ( !increment_ulong(&v_end, PAGE_SIZE) )
766 goto error_out;
767 if ( shadow_mode_enabled ) {
768 vsharedinfo_start = v_end;
769 if ( !increment_ulong(&v_end, PAGE_SIZE) )
770 goto error_out;
771 }
772 vpt_start = v_end;
774 for ( nr_pt_pages = 2; ; nr_pt_pages++ )
775 {
776 /* vpt_end = vpt_staret + (nr_pt_pages * PAGE_SIZE); */
777 vpt_end = vpt_start;
778 if ( !increment_ulong(&vpt_end, nr_pt_pages * PAGE_SIZE) )
779 goto error_out;
781 vstack_start = vpt_end;
782 /* vstack_end = vstack_start + PAGE_SIZE; */
783 vstack_end = vstack_start;
784 if ( !increment_ulong(&vstack_end, PAGE_SIZE) )
785 goto error_out;
787 /* v_end = (vstack_end + (1UL<<22)-1) & ~((1UL<<22)-1); */
788 v_end = vstack_end;
789 if ( !increment_ulong(&v_end, (1UL<<22)-1) )
790 goto error_out;
791 v_end &= ~((1UL<<22)-1);
793 if ( (v_end - vstack_end) < (512UL << 10) )
794 {
795 /* Add extra 4MB to get >= 512kB padding. */
796 if ( !increment_ulong(&v_end, 1UL << 22) )
797 goto error_out;
798 }
800 #define NR(_l,_h,_s) \
801 (((((unsigned long)(_h) + ((1UL<<(_s))-1)) & ~((1UL<<(_s))-1)) - \
802 ((unsigned long)(_l) & ~((1UL<<(_s))-1))) >> (_s))
803 #if defined(__i386__)
804 if ( dsi.pae_kernel != PAEKERN_no )
805 {
806 if ( (1 + /* # L3 */
807 NR(dsi.v_start, v_end, L3_PAGETABLE_SHIFT_PAE) + /* # L2 */
808 NR(dsi.v_start, v_end, L2_PAGETABLE_SHIFT_PAE) + /* # L1 */
809 /* Include a fourth mid-level page directory for Xen. */
810 (v_end <= (3 << L3_PAGETABLE_SHIFT_PAE)))
811 <= nr_pt_pages )
812 break;
813 }
814 else
815 {
816 if ( (1 + /* # L2 */
817 NR(dsi.v_start, v_end, L2_PAGETABLE_SHIFT)) /* # L1 */
818 <= nr_pt_pages )
819 break;
820 }
821 #elif defined(__x86_64__)
822 if ( (1 + /* # L4 */
823 NR(dsi.v_start, v_end, L4_PAGETABLE_SHIFT) + /* # L3 */
824 NR(dsi.v_start, v_end, L3_PAGETABLE_SHIFT) + /* # L2 */
825 NR(dsi.v_start, v_end, L2_PAGETABLE_SHIFT)) /* # L1 */
826 <= nr_pt_pages )
827 break;
828 #endif
829 }
831 IPRINTF("VIRTUAL MEMORY ARRANGEMENT:\n");
832 IPRINTF(" Loaded kernel: %p->%p\n", _p(dsi.v_kernstart),
833 _p(dsi.v_kernend));
834 if ( initrd->len )
835 IPRINTF(" Initial ramdisk: %p->%p\n", _p(vinitrd_start),
836 _p(vinitrd_start + initrd->len));
837 IPRINTF(" Phys-Mach map: %p\n", _p(vphysmap_start));
838 IPRINTF(" Start info: %p\n", _p(vstartinfo_start));
839 IPRINTF(" Store page: %p\n", _p(vstoreinfo_start));
840 IPRINTF(" Console page: %p\n", _p(vconsole_start));
841 if ( shadow_mode_enabled )
842 IPRINTF(" Shared Info page: %p\n", _p(vsharedinfo_start));
843 IPRINTF(" Page tables: %p\n", _p(vpt_start));
844 IPRINTF(" Boot stack: %p\n", _p(vstack_start));
845 IPRINTF(" TOTAL: %p->%p\n", _p(dsi.v_start), _p(v_end));
846 IPRINTF(" ENTRY ADDRESS: %p\n", _p(dsi.v_kernentry));
848 if ( ((v_end - dsi.v_start)>>PAGE_SHIFT) > nr_pages )
849 {
850 PERROR("Initial guest OS requires too much space\n"
851 "(%pMB is greater than %luMB limit)\n",
852 _p((v_end-dsi.v_start)>>20), nr_pages>>(20-PAGE_SHIFT));
853 goto error_out;
854 }
856 if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL )
857 {
858 PERROR("Could not allocate memory");
859 goto error_out;
860 }
862 if ( xc_get_pfn_list(xc_handle, dom, page_array, nr_pages) != nr_pages )
863 {
864 PERROR("Could not get the page frame list");
865 goto error_out;
866 }
868 rc = (load_funcs.loadimage)(image, image_size,
869 xc_handle, dom, page_array,
870 &dsi);
871 if ( rc != 0 )
872 goto error_out;
874 if ( load_initrd(xc_handle, dom, initrd,
875 vinitrd_start - dsi.v_start, page_array) )
876 goto error_out;
878 /* setup page tables */
879 #if defined(__i386__)
880 if (dsi.pae_kernel != PAEKERN_no)
881 rc = setup_pg_tables_pae(xc_handle, dom, ctxt,
882 dsi.v_start, v_end,
883 page_array, vpt_start, vpt_end,
884 shadow_mode_enabled, dsi.pae_kernel);
885 else
886 rc = setup_pg_tables(xc_handle, dom, ctxt,
887 dsi.v_start, v_end,
888 page_array, vpt_start, vpt_end,
889 shadow_mode_enabled);
890 #endif
891 #if defined(__x86_64__)
892 rc = setup_pg_tables_64(xc_handle, dom, ctxt,
893 dsi.v_start, v_end,
894 page_array, vpt_start, vpt_end,
895 shadow_mode_enabled);
896 #endif
897 if (0 != rc)
898 goto error_out;
900 #if defined(__i386__)
901 /*
902 * Pin down l2tab addr as page dir page - causes hypervisor to provide
903 * correct protection for the page
904 */
905 if ( !shadow_mode_enabled )
906 {
907 if ( dsi.pae_kernel != PAEKERN_no )
908 {
909 if ( pin_table(xc_handle, MMUEXT_PIN_L3_TABLE,
910 xen_cr3_to_pfn(ctxt->ctrlreg[3]), dom) )
911 goto error_out;
912 }
913 else
914 {
915 if ( pin_table(xc_handle, MMUEXT_PIN_L2_TABLE,
916 xen_cr3_to_pfn(ctxt->ctrlreg[3]), dom) )
917 goto error_out;
918 }
919 }
920 #endif
922 #if defined(__x86_64__)
923 /*
924 * Pin down l4tab addr as page dir page - causes hypervisor to provide
925 * correct protection for the page
926 */
927 if ( pin_table(xc_handle, MMUEXT_PIN_L4_TABLE,
928 xen_cr3_to_pfn(ctxt->ctrlreg[3]), dom) )
929 goto error_out;
930 #endif
932 if ( (mmu = xc_init_mmu_updates(xc_handle, dom)) == NULL )
933 goto error_out;
935 /* Write the phys->machine and machine->phys table entries. */
936 physmap_pfn = (vphysmap_start - dsi.v_start) >> PAGE_SHIFT;
937 physmap = physmap_e = xc_map_foreign_range(
938 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
939 page_array[physmap_pfn++]);
941 for ( count = 0; count < nr_pages; count++ )
942 {
943 if ( xc_add_mmu_update(
944 xc_handle, mmu,
945 ((uint64_t)page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE,
946 count) )
947 {
948 DPRINTF("m2p update failure p=%lx m=%"PRIx64"\n",
949 count, (uint64_t)page_array[count]);
950 munmap(physmap, PAGE_SIZE);
951 goto error_out;
952 }
953 *physmap_e++ = page_array[count];
954 if ( ((unsigned long)physmap_e & (PAGE_SIZE-1)) == 0 )
955 {
956 munmap(physmap, PAGE_SIZE);
957 physmap = physmap_e = xc_map_foreign_range(
958 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
959 page_array[physmap_pfn++]);
960 }
961 }
962 munmap(physmap, PAGE_SIZE);
964 /* Send the page update requests down to the hypervisor. */
965 if ( xc_finish_mmu_updates(xc_handle, mmu) )
966 goto error_out;
968 if ( shadow_mode_enabled )
969 {
970 struct xen_add_to_physmap xatp;
972 /* Enable shadow translate mode */
973 if ( xc_shadow_control(xc_handle, dom,
974 DOM0_SHADOW_CONTROL_OP_ENABLE_TRANSLATE,
975 NULL, 0, NULL) < 0 )
976 {
977 PERROR("Could not enable translation mode");
978 goto error_out;
979 }
981 guest_shared_info_mfn = (vsharedinfo_start-dsi.v_start) >> PAGE_SHIFT;
983 /* Map shared info frame into guest physmap. */
984 xatp.domid = dom;
985 xatp.space = XENMAPSPACE_shared_info;
986 xatp.idx = 0;
987 xatp.gpfn = guest_shared_info_mfn;
988 rc = xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp);
989 if ( rc != 0 )
990 {
991 PERROR("Cannot map shared info pfn");
992 goto error_out;
993 }
995 /* Map grant table frames into guest physmap. */
996 for ( i = 0; ; i++ )
997 {
998 xatp.domid = dom;
999 xatp.space = XENMAPSPACE_grant_table;
1000 xatp.idx = i;
1001 xatp.gpfn = nr_pages + i;
1002 rc = xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp);
1003 if ( rc != 0 )
1005 if ( errno == EINVAL )
1006 break; /* done all grant tables */
1007 PERROR("Cannot map grant table pfn");
1008 goto error_out;
1012 else
1014 guest_shared_info_mfn = shared_info_frame;
1017 *store_mfn = page_array[(vstoreinfo_start-dsi.v_start) >> PAGE_SHIFT];
1018 *console_mfn = page_array[(vconsole_start-dsi.v_start) >> PAGE_SHIFT];
1019 if ( xc_clear_domain_page(xc_handle, dom, *store_mfn) ||
1020 xc_clear_domain_page(xc_handle, dom, *console_mfn) )
1021 goto error_out;
1022 if ( shadow_mode_enabled )
1024 guest_store_mfn = (vstoreinfo_start-dsi.v_start) >> PAGE_SHIFT;
1025 guest_console_mfn = (vconsole_start-dsi.v_start) >> PAGE_SHIFT;
1027 else
1029 guest_store_mfn = *store_mfn;
1030 guest_console_mfn = *console_mfn;
1033 start_info = xc_map_foreign_range(
1034 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
1035 page_array[(vstartinfo_start-dsi.v_start)>>PAGE_SHIFT]);
1036 /*shared_info, start_info */
1037 memset(start_info, 0, sizeof(*start_info));
1038 rc = xc_version(xc_handle, XENVER_version, NULL);
1039 sprintf(start_info->magic, "xen-%i.%i-x86_%d%s",
1040 rc >> 16, rc & (0xFFFF), (unsigned int)sizeof(long)*8,
1041 (dsi.pae_kernel != PAEKERN_no) ? "p" : "");
1042 start_info->nr_pages = nr_pages;
1043 start_info->shared_info = guest_shared_info_mfn << PAGE_SHIFT;
1044 start_info->flags = flags;
1045 start_info->pt_base = vpt_start;
1046 start_info->nr_pt_frames = nr_pt_pages;
1047 start_info->mfn_list = vphysmap_start;
1048 start_info->store_mfn = guest_store_mfn;
1049 start_info->store_evtchn = store_evtchn;
1050 start_info->console_mfn = guest_console_mfn;
1051 start_info->console_evtchn = console_evtchn;
1052 if ( initrd->len != 0 )
1054 start_info->mod_start = vinitrd_start;
1055 start_info->mod_len = initrd->len;
1057 if ( cmdline != NULL )
1059 strncpy((char *)start_info->cmd_line, cmdline, MAX_GUEST_CMDLINE);
1060 start_info->cmd_line[MAX_GUEST_CMDLINE-1] = '\0';
1062 munmap(start_info, PAGE_SIZE);
1064 /* shared_info page starts its life empty. */
1065 shared_info = xc_map_foreign_range(
1066 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, shared_info_frame);
1067 memset(shared_info, 0, sizeof(shared_info_t));
1068 /* Mask all upcalls... */
1069 for ( i = 0; i < MAX_VIRT_CPUS; i++ )
1070 shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
1072 munmap(shared_info, PAGE_SIZE);
1074 /* Send the page update requests down to the hypervisor. */
1075 if ( xc_finish_mmu_updates(xc_handle, mmu) )
1076 goto error_out;
1078 p = strstr(dsi.xen_guest_string, "HYPERCALL_PAGE=");
1079 if ( p != NULL )
1081 p += strlen("HYPERCALL_PAGE=");
1082 hypercall_pfn = strtoul(p, NULL, 16);
1083 if ( hypercall_pfn >= nr_pages )
1084 goto error_out;
1085 op.u.hypercall_init.domain = (domid_t)dom;
1086 op.u.hypercall_init.gmfn = shadow_mode_enabled ?
1087 hypercall_pfn : page_array[hypercall_pfn];
1088 op.cmd = DOM0_HYPERCALL_INIT;
1089 if ( xc_dom0_op(xc_handle, &op) )
1090 goto error_out;
1093 free(mmu);
1094 free(page_array);
1096 *pvsi = vstartinfo_start;
1097 *pvss = vstack_start;
1098 *pvke = dsi.v_kernentry;
1100 return 0;
1102 error_out:
1103 free(mmu);
1104 free(page_array);
1105 return -1;
1107 #endif
1109 static int xc_linux_build_internal(int xc_handle,
1110 uint32_t domid,
1111 char *image,
1112 unsigned long image_size,
1113 struct initrd_info *initrd,
1114 const char *cmdline,
1115 const char *features,
1116 unsigned long flags,
1117 unsigned int store_evtchn,
1118 unsigned long *store_mfn,
1119 unsigned int console_evtchn,
1120 unsigned long *console_mfn)
1122 dom0_op_t launch_op;
1123 DECLARE_DOM0_OP;
1124 int rc, i;
1125 vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt;
1126 unsigned long nr_pages;
1127 unsigned long vstartinfo_start, vkern_entry, vstack_start;
1128 uint32_t features_bitmap[XENFEAT_NR_SUBMAPS] = { 0, };
1130 if ( features != NULL )
1132 if ( !parse_features(features, features_bitmap, NULL) )
1134 PERROR("Failed to parse configured features\n");
1135 goto error_out;
1139 if ( (nr_pages = get_tot_pages(xc_handle, domid)) < 0 )
1141 PERROR("Could not find total pages for domain");
1142 goto error_out;
1145 #ifdef VALGRIND
1146 memset(&st_ctxt, 0, sizeof(st_ctxt));
1147 #endif
1149 if ( mlock(&st_ctxt, sizeof(st_ctxt) ) )
1151 PERROR("%s: ctxt mlock failed", __func__);
1152 return 1;
1155 op.cmd = DOM0_GETDOMAININFO;
1156 op.u.getdomaininfo.domain = (domid_t)domid;
1157 if ( (xc_dom0_op(xc_handle, &op) < 0) ||
1158 ((uint16_t)op.u.getdomaininfo.domain != domid) )
1160 PERROR("Could not get info on domain");
1161 goto error_out;
1164 memset(ctxt, 0, sizeof(*ctxt));
1166 if ( setup_guest(xc_handle, domid, image, image_size,
1167 initrd,
1168 nr_pages,
1169 &vstartinfo_start, &vkern_entry,
1170 &vstack_start, ctxt, cmdline,
1171 op.u.getdomaininfo.shared_info_frame,
1172 flags, store_evtchn, store_mfn,
1173 console_evtchn, console_mfn,
1174 features_bitmap) < 0 )
1176 ERROR("Error constructing guest OS");
1177 goto error_out;
1180 #ifdef __ia64__
1181 /* based on new_thread in xen/arch/ia64/domain.c */
1182 ctxt->flags = 0;
1183 ctxt->user_regs.cr_ipsr = 0; /* all necessary bits filled by hypervisor */
1184 ctxt->user_regs.cr_iip = vkern_entry;
1185 ctxt->user_regs.cr_ifs = 1UL << 63;
1186 ctxt->user_regs.ar_fpsr = xc_ia64_fpsr_default();
1187 i = 0; /* silence unused variable warning */
1188 #else /* x86 */
1189 /*
1190 * Initial register values:
1191 * DS,ES,FS,GS = FLAT_KERNEL_DS
1192 * CS:EIP = FLAT_KERNEL_CS:start_pc
1193 * SS:ESP = FLAT_KERNEL_DS:start_stack
1194 * ESI = start_info
1195 * [EAX,EBX,ECX,EDX,EDI,EBP are zero]
1196 * EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
1197 */
1198 ctxt->user_regs.ds = FLAT_KERNEL_DS;
1199 ctxt->user_regs.es = FLAT_KERNEL_DS;
1200 ctxt->user_regs.fs = FLAT_KERNEL_DS;
1201 ctxt->user_regs.gs = FLAT_KERNEL_DS;
1202 ctxt->user_regs.ss = FLAT_KERNEL_SS;
1203 ctxt->user_regs.cs = FLAT_KERNEL_CS;
1204 ctxt->user_regs.eip = vkern_entry;
1205 ctxt->user_regs.esp = vstack_start + PAGE_SIZE;
1206 ctxt->user_regs.esi = vstartinfo_start;
1207 ctxt->user_regs.eflags = 1 << 9; /* Interrupt Enable */
1209 ctxt->flags = VGCF_IN_KERNEL;
1211 /* FPU is set up to default initial state. */
1212 memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
1214 /* Virtual IDT is empty at start-of-day. */
1215 for ( i = 0; i < 256; i++ )
1217 ctxt->trap_ctxt[i].vector = i;
1218 ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS;
1221 /* No LDT. */
1222 ctxt->ldt_ents = 0;
1224 /* Use the default Xen-provided GDT. */
1225 ctxt->gdt_ents = 0;
1227 /* Ring 1 stack is the initial stack. */
1228 ctxt->kernel_ss = FLAT_KERNEL_SS;
1229 ctxt->kernel_sp = vstack_start + PAGE_SIZE;
1231 /* No debugging. */
1232 memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
1234 /* No callback handlers. */
1235 #if defined(__i386__)
1236 ctxt->event_callback_cs = FLAT_KERNEL_CS;
1237 ctxt->event_callback_eip = 0;
1238 ctxt->failsafe_callback_cs = FLAT_KERNEL_CS;
1239 ctxt->failsafe_callback_eip = 0;
1240 #elif defined(__x86_64__)
1241 ctxt->event_callback_eip = 0;
1242 ctxt->failsafe_callback_eip = 0;
1243 ctxt->syscall_callback_eip = 0;
1244 #endif
1245 #endif /* x86 */
1247 memset( &launch_op, 0, sizeof(launch_op) );
1249 launch_op.u.setvcpucontext.domain = (domid_t)domid;
1250 launch_op.u.setvcpucontext.vcpu = 0;
1251 set_xen_guest_handle(launch_op.u.setvcpucontext.ctxt, ctxt);
1253 launch_op.cmd = DOM0_SETVCPUCONTEXT;
1254 rc = xc_dom0_op(xc_handle, &launch_op);
1256 return rc;
1258 error_out:
1259 return -1;
1262 int xc_linux_build_mem(int xc_handle,
1263 uint32_t domid,
1264 const char *image_buffer,
1265 unsigned long image_size,
1266 const char *initrd,
1267 unsigned long initrd_len,
1268 const char *cmdline,
1269 const char *features,
1270 unsigned long flags,
1271 unsigned int store_evtchn,
1272 unsigned long *store_mfn,
1273 unsigned int console_evtchn,
1274 unsigned long *console_mfn)
1276 int sts;
1277 char *img_buf;
1278 unsigned long img_len;
1279 struct initrd_info initrd_info = { .type = INITRD_none };
1281 /* A kernel buffer is required */
1282 if ( (image_buffer == NULL) || (image_size == 0) )
1284 ERROR("kernel image buffer not present");
1285 return -1;
1288 /* If it's gzipped, inflate it; otherwise, use as is */
1289 /* xc_inflate_buffer may return the same buffer pointer if */
1290 /* the buffer is already inflated */
1291 img_buf = xc_inflate_buffer(image_buffer, image_size, &img_len);
1292 if ( img_buf == NULL )
1294 ERROR("unable to inflate kernel image buffer");
1295 return -1;
1298 /* RAM disks are optional; if we get one, inflate it */
1299 if ( initrd != NULL )
1301 initrd_info.type = INITRD_mem;
1302 initrd_info.u.mem_addr = xc_inflate_buffer(
1303 initrd, initrd_len, &initrd_info.len);
1304 if ( initrd_info.u.mem_addr == NULL )
1306 ERROR("unable to inflate ram disk buffer");
1307 sts = -1;
1308 goto out;
1312 sts = xc_linux_build_internal(xc_handle, domid, img_buf, img_len,
1313 &initrd_info, cmdline, features, flags,
1314 store_evtchn, store_mfn,
1315 console_evtchn, console_mfn);
1317 out:
1318 /* The inflation routines may pass back the same buffer so be */
1319 /* sure that we have a buffer and that it's not the one passed in. */
1320 /* Don't unnecessarily annoy/surprise/confound the caller */
1321 if ( (img_buf != NULL) && (img_buf != image_buffer) )
1322 free(img_buf);
1323 if ( (initrd_info.u.mem_addr != NULL) &&
1324 (initrd_info.u.mem_addr != initrd) )
1325 free(initrd_info.u.mem_addr);
1327 return sts;
1330 int xc_linux_build(int xc_handle,
1331 uint32_t domid,
1332 const char *image_name,
1333 const char *initrd_name,
1334 const char *cmdline,
1335 const char *features,
1336 unsigned long flags,
1337 unsigned int store_evtchn,
1338 unsigned long *store_mfn,
1339 unsigned int console_evtchn,
1340 unsigned long *console_mfn)
1342 char *image = NULL;
1343 unsigned long image_size;
1344 struct initrd_info initrd_info = { .type = INITRD_none };
1345 int fd = -1, sts = -1;
1347 if ( (image_name == NULL) ||
1348 ((image = xc_read_image(image_name, &image_size)) == NULL ))
1349 return -1;
1351 if ( (initrd_name != NULL) && (strlen(initrd_name) != 0) )
1353 initrd_info.type = INITRD_file;
1355 if ( (fd = open(initrd_name, O_RDONLY)) < 0 )
1357 PERROR("Could not open the initial ramdisk image");
1358 goto error_out;
1361 initrd_info.len = xc_get_filesz(fd);
1362 if ( (initrd_info.u.file_handle = gzdopen(fd, "rb")) == NULL )
1364 PERROR("Could not allocate decompression state for initrd");
1365 goto error_out;
1369 sts = xc_linux_build_internal(xc_handle, domid, image, image_size,
1370 &initrd_info, cmdline, features, flags,
1371 store_evtchn, store_mfn,
1372 console_evtchn, console_mfn);
1374 error_out:
1375 free(image);
1376 if ( fd >= 0 )
1377 close(fd);
1378 if ( initrd_info.u.file_handle )
1379 gzclose(initrd_info.u.file_handle);
1381 return sts;
1384 /*
1385 * Local variables:
1386 * mode: C
1387 * c-set-style: "BSD"
1388 * c-basic-offset: 4
1389 * tab-width: 4
1390 * indent-tabs-mode: nil
1391 * End:
1392 */