ia64/xen-unstable

view tools/libxc/xc_linux_build.c @ 9167:cb5abeaabd1a

[IA64] fix print out in ia64 setup_guest()

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author awilliam@xenbuild.aw
date Fri Mar 10 09:19:54 2006 -0700 (2006-03-10)
parents b470657718fe
children 0ed4a312765b
line source
1 /******************************************************************************
2 * xc_linux_build.c
3 */
5 #include "xg_private.h"
6 #include "xc_private.h"
7 #include <xenctrl.h>
9 #if defined(__i386__)
10 #define ELFSIZE 32
11 #endif
13 #if defined(__x86_64__) || defined(__ia64__)
14 #define ELFSIZE 64
15 #endif
17 #include "xc_elf.h"
18 #include "xc_aout9.h"
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <zlib.h>
23 #if defined(__i386__)
24 #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
25 #define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
26 #define L3_PROT (_PAGE_PRESENT)
27 #endif
29 #if defined(__x86_64__)
30 #define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER)
31 #define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
32 #define L3_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
33 #define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
34 #endif
36 #ifdef __ia64__
37 #define get_tot_pages xc_get_max_pages
38 #else
39 #define get_tot_pages xc_get_tot_pages
40 #endif
42 #define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
43 #define round_pgdown(_p) ((_p)&PAGE_MASK)
45 #ifdef __ia64__
46 #define probe_aout9(image,image_size,load_funcs) 1
47 #endif
49 static const char *feature_names[XENFEAT_NR_SUBMAPS*32] = {
50 [XENFEAT_writable_page_tables] = "writable_page_tables",
51 [XENFEAT_writable_descriptor_tables] = "writable_descriptor_tables",
52 [XENFEAT_auto_translated_physmap] = "auto_translated_physmap",
53 [XENFEAT_supervisor_mode_kernel] = "supervisor_mode_kernel",
54 [XENFEAT_pae_pgdir_above_4gb] = "pae_pgdir_above_4gb"
55 };
57 static inline void set_feature_bit (int nr, uint32_t *addr)
58 {
59 addr[nr>>5] |= (1<<(nr&31));
60 }
62 static inline int test_feature_bit(int nr, uint32_t *addr)
63 {
64 return !!(addr[nr>>5] & (1<<(nr&31)));
65 }
67 static int parse_features(
68 const char *feats,
69 uint32_t supported[XENFEAT_NR_SUBMAPS],
70 uint32_t required[XENFEAT_NR_SUBMAPS])
71 {
72 const char *end, *p;
73 int i, req;
75 if ( (end = strchr(feats, ',')) == NULL )
76 end = feats + strlen(feats);
78 while ( feats < end )
79 {
80 p = strchr(feats, '|');
81 if ( (p == NULL) || (p > end) )
82 p = end;
84 req = (*feats == '!');
85 if ( req )
86 feats++;
88 for ( i = 0; i < XENFEAT_NR_SUBMAPS*32; i++ )
89 {
90 if ( feature_names[i] == NULL )
91 continue;
93 if ( strncmp(feature_names[i], feats, p-feats) == 0 )
94 {
95 set_feature_bit(i, supported);
96 if ( required && req )
97 set_feature_bit(i, required);
98 break;
99 }
100 }
102 if ( i == XENFEAT_NR_SUBMAPS*32 )
103 {
104 ERROR("Unknown feature \"%.*s\".\n", (int)(p-feats), feats);
105 if ( req )
106 {
107 ERROR("Kernel requires an unknown hypervisor feature.\n");
108 return -EINVAL;
109 }
110 }
112 feats = p;
113 if ( *feats == '|' )
114 feats++;
115 }
117 return -EINVAL;
118 }
120 static int probeimageformat(char *image,
121 unsigned long image_size,
122 struct load_funcs *load_funcs)
123 {
124 if ( probe_elf(image, image_size, load_funcs) &&
125 probe_bin(image, image_size, load_funcs) &&
126 probe_aout9(image, image_size, load_funcs) )
127 {
128 ERROR( "Unrecognized image format" );
129 return -EINVAL;
130 }
132 return 0;
133 }
135 #define alloc_pt(ltab, vltab, pltab) \
136 do { \
137 pltab = ppt_alloc++; \
138 ltab = (uint64_t)page_array[pltab] << PAGE_SHIFT; \
139 pltab <<= PAGE_SHIFT; \
140 if ( vltab != NULL ) \
141 munmap(vltab, PAGE_SIZE); \
142 if ( (vltab = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, \
143 PROT_READ|PROT_WRITE, \
144 ltab >> PAGE_SHIFT)) == NULL ) \
145 goto error_out; \
146 memset(vltab, 0x0, PAGE_SIZE); \
147 } while ( 0 )
149 #if defined(__i386__)
151 static int setup_pg_tables(int xc_handle, uint32_t dom,
152 vcpu_guest_context_t *ctxt,
153 unsigned long dsi_v_start,
154 unsigned long v_end,
155 unsigned long *page_array,
156 unsigned long vpt_start,
157 unsigned long vpt_end,
158 unsigned shadow_mode_enabled)
159 {
160 l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
161 l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
162 unsigned long l1tab = 0, pl1tab;
163 unsigned long l2tab = 0, pl2tab;
164 unsigned long ppt_alloc;
165 unsigned long count;
167 ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT;
168 alloc_pt(l2tab, vl2tab, pl2tab);
169 vl2e = &vl2tab[l2_table_offset(dsi_v_start)];
170 if (shadow_mode_enabled)
171 ctxt->ctrlreg[3] = pl2tab;
172 else
173 ctxt->ctrlreg[3] = l2tab;
175 for ( count = 0; count < ((v_end - dsi_v_start) >> PAGE_SHIFT); count++ )
176 {
177 if ( ((unsigned long)vl1e & (PAGE_SIZE-1)) == 0 )
178 {
179 alloc_pt(l1tab, vl1tab, pl1tab);
180 vl1e = &vl1tab[l1_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
181 if (shadow_mode_enabled)
182 *vl2e = pl1tab | L2_PROT;
183 else
184 *vl2e = l1tab | L2_PROT;
185 vl2e++;
186 }
188 if ( shadow_mode_enabled )
189 {
190 *vl1e = (count << PAGE_SHIFT) | L1_PROT;
191 }
192 else
193 {
194 *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
195 if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
196 (count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
197 *vl1e &= ~_PAGE_RW;
198 }
199 vl1e++;
200 }
201 munmap(vl1tab, PAGE_SIZE);
202 munmap(vl2tab, PAGE_SIZE);
203 return 0;
205 error_out:
206 if (vl1tab)
207 munmap(vl1tab, PAGE_SIZE);
208 if (vl2tab)
209 munmap(vl2tab, PAGE_SIZE);
210 return -1;
211 }
213 static int setup_pg_tables_pae(int xc_handle, uint32_t dom,
214 vcpu_guest_context_t *ctxt,
215 unsigned long dsi_v_start,
216 unsigned long v_end,
217 unsigned long *page_array,
218 unsigned long vpt_start,
219 unsigned long vpt_end,
220 unsigned shadow_mode_enabled)
221 {
222 l1_pgentry_64_t *vl1tab = NULL, *vl1e = NULL;
223 l2_pgentry_64_t *vl2tab = NULL, *vl2e = NULL;
224 l3_pgentry_64_t *vl3tab = NULL, *vl3e = NULL;
225 uint64_t l1tab, l2tab, l3tab, pl1tab, pl2tab, pl3tab;
226 unsigned long ppt_alloc, count, nmfn;
228 /* First allocate page for page dir. */
229 ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT;
231 if ( page_array[ppt_alloc] > 0xfffff )
232 {
233 nmfn = xc_make_page_below_4G(xc_handle, dom, page_array[ppt_alloc]);
234 if ( nmfn == 0 )
235 {
236 fprintf(stderr, "Couldn't get a page below 4GB :-(\n");
237 goto error_out;
238 }
239 page_array[ppt_alloc] = nmfn;
240 }
242 alloc_pt(l3tab, vl3tab, pl3tab);
243 vl3e = &vl3tab[l3_table_offset_pae(dsi_v_start)];
244 if (shadow_mode_enabled)
245 ctxt->ctrlreg[3] = pl3tab;
246 else
247 ctxt->ctrlreg[3] = l3tab;
249 for ( count = 0; count < ((v_end - dsi_v_start) >> PAGE_SHIFT); count++)
250 {
251 if ( !((unsigned long)vl1e & (PAGE_SIZE-1)) )
252 {
253 if ( !((unsigned long)vl2e & (PAGE_SIZE-1)) )
254 {
255 alloc_pt(l2tab, vl2tab, pl2tab);
256 vl2e = &vl2tab[l2_table_offset_pae(
257 dsi_v_start + (count << PAGE_SHIFT))];
258 if (shadow_mode_enabled)
259 *vl3e = pl2tab | L3_PROT;
260 else
261 *vl3e++ = l2tab | L3_PROT;
262 }
264 alloc_pt(l1tab, vl1tab, pl1tab);
265 vl1e = &vl1tab[l1_table_offset_pae(
266 dsi_v_start + (count << PAGE_SHIFT))];
267 if (shadow_mode_enabled)
268 *vl2e = pl1tab | L2_PROT;
269 else
270 *vl2e++ = l1tab | L2_PROT;
271 }
273 if ( shadow_mode_enabled )
274 {
275 *vl1e = (count << PAGE_SHIFT) | L1_PROT;
276 }
277 else
278 {
279 *vl1e = ((uint64_t)page_array[count] << PAGE_SHIFT) | L1_PROT;
280 if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
281 (count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
282 *vl1e &= ~_PAGE_RW;
283 }
284 vl1e++;
285 }
287 munmap(vl1tab, PAGE_SIZE);
288 munmap(vl2tab, PAGE_SIZE);
289 munmap(vl3tab, PAGE_SIZE);
290 return 0;
292 error_out:
293 if (vl1tab)
294 munmap(vl1tab, PAGE_SIZE);
295 if (vl2tab)
296 munmap(vl2tab, PAGE_SIZE);
297 if (vl3tab)
298 munmap(vl3tab, PAGE_SIZE);
299 return -1;
300 }
302 #endif
304 #if defined(__x86_64__)
306 static int setup_pg_tables_64(int xc_handle, uint32_t dom,
307 vcpu_guest_context_t *ctxt,
308 unsigned long dsi_v_start,
309 unsigned long v_end,
310 unsigned long *page_array,
311 unsigned long vpt_start,
312 unsigned long vpt_end,
313 int shadow_mode_enabled)
314 {
315 l1_pgentry_t *vl1tab=NULL, *vl1e=NULL;
316 l2_pgentry_t *vl2tab=NULL, *vl2e=NULL;
317 l3_pgentry_t *vl3tab=NULL, *vl3e=NULL;
318 l4_pgentry_t *vl4tab=NULL, *vl4e=NULL;
319 unsigned long l2tab = 0, pl2tab;
320 unsigned long l1tab = 0, pl1tab;
321 unsigned long l3tab = 0, pl3tab;
322 unsigned long l4tab = 0, pl4tab;
323 unsigned long ppt_alloc;
324 unsigned long count;
326 /* First allocate page for page dir. */
327 ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT;
328 alloc_pt(l4tab, vl4tab, pl4tab);
329 vl4e = &vl4tab[l4_table_offset(dsi_v_start)];
330 if (shadow_mode_enabled)
331 ctxt->ctrlreg[3] = pl4tab;
332 else
333 ctxt->ctrlreg[3] = l4tab;
335 for ( count = 0; count < ((v_end-dsi_v_start)>>PAGE_SHIFT); count++)
336 {
337 if ( !((unsigned long)vl1e & (PAGE_SIZE-1)) )
338 {
339 alloc_pt(l1tab, vl1tab, pl1tab);
341 if ( !((unsigned long)vl2e & (PAGE_SIZE-1)) )
342 {
343 alloc_pt(l2tab, vl2tab, pl2tab);
344 if ( !((unsigned long)vl3e & (PAGE_SIZE-1)) )
345 {
346 alloc_pt(l3tab, vl3tab, pl3tab);
347 vl3e = &vl3tab[l3_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
348 if (shadow_mode_enabled)
349 *vl4e = pl3tab | L4_PROT;
350 else
351 *vl4e = l3tab | L4_PROT;
352 vl4e++;
353 }
354 vl2e = &vl2tab[l2_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
355 if (shadow_mode_enabled)
356 *vl3e = pl2tab | L3_PROT;
357 else
358 *vl3e = l2tab | L3_PROT;
359 vl3e++;
360 }
361 vl1e = &vl1tab[l1_table_offset(dsi_v_start + (count<<PAGE_SHIFT))];
362 if (shadow_mode_enabled)
363 *vl2e = pl1tab | L2_PROT;
364 else
365 *vl2e = l1tab | L2_PROT;
366 vl2e++;
367 }
369 if ( shadow_mode_enabled )
370 {
371 *vl1e = (count << PAGE_SHIFT) | L1_PROT;
372 }
373 else
374 {
375 *vl1e = (page_array[count] << PAGE_SHIFT) | L1_PROT;
376 if ( (count >= ((vpt_start-dsi_v_start)>>PAGE_SHIFT)) &&
377 (count < ((vpt_end -dsi_v_start)>>PAGE_SHIFT)) )
378 {
379 *vl1e &= ~_PAGE_RW;
380 }
381 }
382 vl1e++;
383 }
385 munmap(vl1tab, PAGE_SIZE);
386 munmap(vl2tab, PAGE_SIZE);
387 munmap(vl3tab, PAGE_SIZE);
388 munmap(vl4tab, PAGE_SIZE);
389 return 0;
391 error_out:
392 if (vl1tab)
393 munmap(vl1tab, PAGE_SIZE);
394 if (vl2tab)
395 munmap(vl2tab, PAGE_SIZE);
396 if (vl3tab)
397 munmap(vl3tab, PAGE_SIZE);
398 if (vl4tab)
399 munmap(vl4tab, PAGE_SIZE);
400 return -1;
401 }
402 #endif
404 #ifdef __ia64__
405 extern unsigned long xc_ia64_fpsr_default(void);
407 static int setup_guest(int xc_handle,
408 uint32_t dom,
409 char *image, unsigned long image_size,
410 gzFile initrd_gfd, unsigned long initrd_len,
411 unsigned long nr_pages,
412 unsigned long *pvsi, unsigned long *pvke,
413 unsigned long *pvss, vcpu_guest_context_t *ctxt,
414 const char *cmdline,
415 unsigned long shared_info_frame,
416 unsigned long flags,
417 unsigned int store_evtchn, unsigned long *store_mfn,
418 unsigned int console_evtchn, unsigned long *console_mfn,
419 uint32_t required_features[XENFEAT_NR_SUBMAPS])
420 {
421 unsigned long *page_array = NULL;
422 struct load_funcs load_funcs;
423 struct domain_setup_info dsi;
424 unsigned long vinitrd_start;
425 unsigned long vinitrd_end;
426 unsigned long v_end;
427 unsigned long start_page, pgnr;
428 start_info_t *start_info;
429 int rc;
430 unsigned long i;
432 rc = probeimageformat(image, image_size, &load_funcs);
433 if ( rc != 0 )
434 goto error_out;
436 memset(&dsi, 0, sizeof(struct domain_setup_info));
438 rc = (load_funcs.parseimage)(image, image_size, &dsi);
439 if ( rc != 0 )
440 goto error_out;
442 dsi.v_start = round_pgdown(dsi.v_start);
443 vinitrd_start = round_pgup(dsi.v_end);
444 vinitrd_end = vinitrd_start + initrd_len;
445 v_end = round_pgup(vinitrd_end);
447 start_page = dsi.v_start >> PAGE_SHIFT;
448 pgnr = (v_end - dsi.v_start) >> PAGE_SHIFT;
449 if ( (page_array = malloc(pgnr * sizeof(unsigned long))) == NULL )
450 {
451 PERROR("Could not allocate memory");
452 goto error_out;
453 }
455 if ( xc_ia64_get_pfn_list(xc_handle, dom, page_array, start_page, pgnr) != pgnr )
456 {
457 PERROR("Could not get the page frame list");
458 goto error_out;
459 }
461 #define _p(a) ((void *) (a))
463 printf("VIRTUAL MEMORY ARRANGEMENT:\n"
464 " Loaded kernel: %p->%p\n"
465 " Init. ramdisk: %p->%p\n"
466 " TOTAL: %p->%p\n",
467 _p(dsi.v_kernstart), _p(dsi.v_kernend),
468 _p(vinitrd_start), _p(vinitrd_end),
469 _p(dsi.v_start), _p(v_end));
470 printf(" ENTRY ADDRESS: %p\n", _p(dsi.v_kernentry));
472 (load_funcs.loadimage)(image, image_size, xc_handle, dom, page_array,
473 &dsi);
475 /* Load the initial ramdisk image. */
476 if ( initrd_len != 0 )
477 {
478 for ( i = (vinitrd_start - dsi.v_start);
479 i < (vinitrd_end - dsi.v_start); i += PAGE_SIZE )
480 {
481 char page[PAGE_SIZE];
482 if ( gzread(initrd_gfd, page, PAGE_SIZE) == -1 )
483 {
484 PERROR("Error reading initrd image, could not");
485 goto error_out;
486 }
487 xc_copy_to_domain_page(xc_handle, dom,
488 page_array[i>>PAGE_SHIFT], page);
489 }
490 }
493 *pvke = dsi.v_kernentry;
495 /* Now need to retrieve machine pfn for system pages:
496 * start_info/store/console
497 */
498 pgnr = 3;
499 if ( xc_ia64_get_pfn_list(xc_handle, dom, page_array,
500 nr_pages - 3, pgnr) != pgnr )
501 {
502 PERROR("Could not get page frame for xenstore");
503 goto error_out;
504 }
506 *store_mfn = page_array[1];
507 *console_mfn = page_array[2];
508 printf("start_info: 0x%lx at 0x%lx, "
509 "store_mfn: 0x%lx at 0x%lx, "
510 "console_mfn: 0x%lx at 0x%lx\n",
511 page_array[0], nr_pages,
512 *store_mfn, nr_pages - 2,
513 *console_mfn, nr_pages - 1);
515 start_info = xc_map_foreign_range(
516 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, page_array[0]);
517 memset(start_info, 0, sizeof(*start_info));
518 rc = xc_version(xc_handle, XENVER_version, NULL);
519 sprintf(start_info->magic, "xen-%i.%i-ia64", rc >> 16, rc & (0xFFFF));
520 start_info->flags = flags;
521 start_info->store_mfn = nr_pages - 2;
522 start_info->store_evtchn = store_evtchn;
523 start_info->console_mfn = nr_pages - 1;
524 start_info->console_evtchn = console_evtchn;
525 start_info->nr_pages = nr_pages; // FIXME?: nr_pages - 2 ????
526 if ( initrd_len != 0 )
527 {
528 ctxt->initrd.start = vinitrd_start;
529 ctxt->initrd.size = initrd_len;
530 }
531 else
532 {
533 ctxt->initrd.start = 0;
534 ctxt->initrd.size = 0;
535 }
536 if ( cmdline != NULL )
537 {
538 strncpy((char *)ctxt->cmdline, cmdline, IA64_COMMAND_LINE_SIZE);
539 ctxt->cmdline[IA64_COMMAND_LINE_SIZE-1] = '\0';
540 }
541 munmap(start_info, PAGE_SIZE);
543 free(page_array);
544 return 0;
546 error_out:
547 free(page_array);
548 return -1;
549 }
550 #else /* x86 */
551 static int setup_guest(int xc_handle,
552 uint32_t dom,
553 char *image, unsigned long image_size,
554 gzFile initrd_gfd, unsigned long initrd_len,
555 unsigned long nr_pages,
556 unsigned long *pvsi, unsigned long *pvke,
557 unsigned long *pvss, vcpu_guest_context_t *ctxt,
558 const char *cmdline,
559 unsigned long shared_info_frame,
560 unsigned long flags,
561 unsigned int store_evtchn, unsigned long *store_mfn,
562 unsigned int console_evtchn, unsigned long *console_mfn,
563 uint32_t required_features[XENFEAT_NR_SUBMAPS])
564 {
565 unsigned long *page_array = NULL;
566 unsigned long count, i, hypercall_pfn;
567 start_info_t *start_info;
568 shared_info_t *shared_info;
569 xc_mmu_t *mmu = NULL;
570 char *p;
571 DECLARE_DOM0_OP;
572 int rc;
574 unsigned long nr_pt_pages;
575 unsigned long physmap_pfn;
576 unsigned long *physmap, *physmap_e;
578 struct load_funcs load_funcs;
579 struct domain_setup_info dsi;
580 unsigned long vinitrd_start;
581 unsigned long vinitrd_end;
582 unsigned long vphysmap_start;
583 unsigned long vphysmap_end;
584 unsigned long vstartinfo_start;
585 unsigned long vstartinfo_end;
586 unsigned long vstoreinfo_start;
587 unsigned long vstoreinfo_end;
588 unsigned long vconsole_start;
589 unsigned long vconsole_end;
590 unsigned long vstack_start;
591 unsigned long vstack_end;
592 unsigned long vpt_start;
593 unsigned long vpt_end;
594 unsigned long v_end;
595 unsigned long guest_store_mfn, guest_console_mfn, guest_shared_info_mfn;
596 unsigned long shadow_mode_enabled;
597 uint32_t supported_features[XENFEAT_NR_SUBMAPS] = { 0, };
599 rc = probeimageformat(image, image_size, &load_funcs);
600 if ( rc != 0 )
601 goto error_out;
603 memset(&dsi, 0, sizeof(struct domain_setup_info));
605 rc = (load_funcs.parseimage)(image, image_size, &dsi);
606 if ( rc != 0 )
607 goto error_out;
609 if ( (dsi.v_start & (PAGE_SIZE-1)) != 0 )
610 {
611 PERROR("Guest OS must load to a page boundary.\n");
612 goto error_out;
613 }
615 /*
616 * Why do we need this? The number of page-table frames depends on the
617 * size of the bootstrap address space. But the size of the address space
618 * depends on the number of page-table frames (since each one is mapped
619 * read-only). We have a pair of simultaneous equations in two unknowns,
620 * which we solve by exhaustive search.
621 */
622 vinitrd_start = round_pgup(dsi.v_end);
623 vinitrd_end = vinitrd_start + initrd_len;
624 vphysmap_start = round_pgup(vinitrd_end);
625 vphysmap_end = vphysmap_start + (nr_pages * sizeof(unsigned long));
626 vstartinfo_start = round_pgup(vphysmap_end);
627 vstartinfo_end = vstartinfo_start + PAGE_SIZE;
628 vstoreinfo_start = vstartinfo_end;
629 vstoreinfo_end = vstoreinfo_start + PAGE_SIZE;
630 vconsole_start = vstoreinfo_end;
631 vconsole_end = vconsole_start + PAGE_SIZE;
632 vpt_start = vconsole_end;
634 for ( nr_pt_pages = 2; ; nr_pt_pages++ )
635 {
636 vpt_end = vpt_start + (nr_pt_pages * PAGE_SIZE);
637 vstack_start = vpt_end;
638 vstack_end = vstack_start + PAGE_SIZE;
639 v_end = (vstack_end + (1UL<<22)-1) & ~((1UL<<22)-1);
640 if ( (v_end - vstack_end) < (512UL << 10) )
641 v_end += 1UL << 22; /* Add extra 4MB to get >= 512kB padding. */
642 #if defined(__i386__)
643 if ( dsi.pae_kernel )
644 {
645 /* FIXME: assumes one L2 pgtable @ 0xc0000000 */
646 if ( (((v_end - dsi.v_start + ((1<<L2_PAGETABLE_SHIFT_PAE)-1)) >>
647 L2_PAGETABLE_SHIFT_PAE) + 2) <= nr_pt_pages )
648 break;
649 }
650 else
651 {
652 if ( (((v_end - dsi.v_start + ((1<<L2_PAGETABLE_SHIFT)-1)) >>
653 L2_PAGETABLE_SHIFT) + 1) <= nr_pt_pages )
654 break;
655 }
656 #endif
657 #if defined(__x86_64__)
658 #define NR(_l,_h,_s) \
659 (((((_h) + ((1UL<<(_s))-1)) & ~((1UL<<(_s))-1)) - \
660 ((_l) & ~((1UL<<(_s))-1))) >> (_s))
661 if ( (1 + /* # L4 */
662 NR(dsi.v_start, v_end, L4_PAGETABLE_SHIFT) + /* # L3 */
663 NR(dsi.v_start, v_end, L3_PAGETABLE_SHIFT) + /* # L2 */
664 NR(dsi.v_start, v_end, L2_PAGETABLE_SHIFT)) /* # L1 */
665 <= nr_pt_pages )
666 break;
667 #endif
668 }
670 #define _p(a) ((void *) (a))
672 printf("VIRTUAL MEMORY ARRANGEMENT:\n"
673 " Loaded kernel: %p->%p\n"
674 " Init. ramdisk: %p->%p\n"
675 " Phys-Mach map: %p->%p\n"
676 " Start info: %p->%p\n"
677 " Store page: %p->%p\n"
678 " Console page: %p->%p\n"
679 " Page tables: %p->%p\n"
680 " Boot stack: %p->%p\n"
681 " TOTAL: %p->%p\n",
682 _p(dsi.v_kernstart), _p(dsi.v_kernend),
683 _p(vinitrd_start), _p(vinitrd_end),
684 _p(vphysmap_start), _p(vphysmap_end),
685 _p(vstartinfo_start), _p(vstartinfo_end),
686 _p(vstoreinfo_start), _p(vstoreinfo_end),
687 _p(vconsole_start), _p(vconsole_end),
688 _p(vpt_start), _p(vpt_end),
689 _p(vstack_start), _p(vstack_end),
690 _p(dsi.v_start), _p(v_end));
691 printf(" ENTRY ADDRESS: %p\n", _p(dsi.v_kernentry));
693 if ( ((v_end - dsi.v_start)>>PAGE_SHIFT) > nr_pages )
694 {
695 PERROR("Initial guest OS requires too much space\n"
696 "(%luMB is greater than %luMB limit)\n",
697 (v_end-dsi.v_start)>>20, nr_pages>>(20-PAGE_SHIFT));
698 goto error_out;
699 }
701 if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL )
702 {
703 PERROR("Could not allocate memory");
704 goto error_out;
705 }
707 if ( xc_get_pfn_list(xc_handle, dom, page_array, nr_pages) != nr_pages )
708 {
709 PERROR("Could not get the page frame list");
710 goto error_out;
711 }
713 (load_funcs.loadimage)(image, image_size, xc_handle, dom, page_array,
714 &dsi);
716 /* Parse and validate kernel features. */
717 p = strstr(dsi.xen_guest_string, "FEATURES=");
718 if ( p != NULL )
719 {
720 if ( !parse_features(p + strlen("FEATURES="),
721 supported_features,
722 required_features) )
723 {
724 ERROR("Failed to parse guest kernel features.\n");
725 goto error_out;
726 }
728 fprintf(stderr, "Supported features = { %08x }.\n",
729 supported_features[0]);
730 fprintf(stderr, "Required features = { %08x }.\n",
731 required_features[0]);
732 }
734 for ( i = 0; i < XENFEAT_NR_SUBMAPS; i++ )
735 {
736 if ( (supported_features[i]&required_features[i]) != required_features[i] )
737 {
738 ERROR("Guest kernel does not support a required feature.\n");
739 goto error_out;
740 }
741 }
743 shadow_mode_enabled = test_feature_bit(XENFEAT_auto_translated_physmap, required_features);
745 /* Load the initial ramdisk image. */
746 if ( initrd_len != 0 )
747 {
748 for ( i = (vinitrd_start - dsi.v_start);
749 i < (vinitrd_end - dsi.v_start); i += PAGE_SIZE )
750 {
751 char page[PAGE_SIZE];
752 if ( gzread(initrd_gfd, page, PAGE_SIZE) == -1 )
753 {
754 PERROR("Error reading initrd image, could not");
755 goto error_out;
756 }
757 xc_copy_to_domain_page(xc_handle, dom,
758 page_array[i>>PAGE_SHIFT], page);
759 }
760 }
762 /* setup page tables */
763 #if defined(__i386__)
764 if (dsi.pae_kernel)
765 rc = setup_pg_tables_pae(xc_handle, dom, ctxt,
766 dsi.v_start, v_end,
767 page_array, vpt_start, vpt_end,
768 shadow_mode_enabled);
769 else
770 rc = setup_pg_tables(xc_handle, dom, ctxt,
771 dsi.v_start, v_end,
772 page_array, vpt_start, vpt_end,
773 shadow_mode_enabled);
774 #endif
775 #if defined(__x86_64__)
776 rc = setup_pg_tables_64(xc_handle, dom, ctxt,
777 dsi.v_start, v_end,
778 page_array, vpt_start, vpt_end,
779 shadow_mode_enabled);
780 #endif
781 if (0 != rc)
782 goto error_out;
784 #if defined(__i386__)
785 /*
786 * Pin down l2tab addr as page dir page - causes hypervisor to provide
787 * correct protection for the page
788 */
789 if ( !shadow_mode_enabled )
790 {
791 if ( dsi.pae_kernel )
792 {
793 if ( pin_table(xc_handle, MMUEXT_PIN_L3_TABLE,
794 ctxt->ctrlreg[3] >> PAGE_SHIFT, dom) )
795 goto error_out;
796 }
797 else
798 {
799 if ( pin_table(xc_handle, MMUEXT_PIN_L2_TABLE,
800 ctxt->ctrlreg[3] >> PAGE_SHIFT, dom) )
801 goto error_out;
802 }
803 }
804 #endif
806 #if defined(__x86_64__)
807 /*
808 * Pin down l4tab addr as page dir page - causes hypervisor to provide
809 * correct protection for the page
810 */
811 if ( pin_table(xc_handle, MMUEXT_PIN_L4_TABLE,
812 ctxt->ctrlreg[3] >> PAGE_SHIFT, dom) )
813 goto error_out;
814 #endif
816 if ( (mmu = xc_init_mmu_updates(xc_handle, dom)) == NULL )
817 goto error_out;
819 /* Write the phys->machine and machine->phys table entries. */
820 physmap_pfn = (vphysmap_start - dsi.v_start) >> PAGE_SHIFT;
821 physmap = physmap_e = xc_map_foreign_range(
822 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
823 page_array[physmap_pfn++]);
825 for ( count = 0; count < nr_pages; count++ )
826 {
827 if ( xc_add_mmu_update(
828 xc_handle, mmu,
829 ((uint64_t)page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE,
830 count) )
831 {
832 fprintf(stderr,"m2p update failure p=%lx m=%lx\n",
833 count, page_array[count]);
834 munmap(physmap, PAGE_SIZE);
835 goto error_out;
836 }
837 *physmap_e++ = page_array[count];
838 if ( ((unsigned long)physmap_e & (PAGE_SIZE-1)) == 0 )
839 {
840 munmap(physmap, PAGE_SIZE);
841 physmap = physmap_e = xc_map_foreign_range(
842 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
843 page_array[physmap_pfn++]);
844 }
845 }
846 munmap(physmap, PAGE_SIZE);
848 /* Send the page update requests down to the hypervisor. */
849 if ( xc_finish_mmu_updates(xc_handle, mmu) )
850 goto error_out;
852 if ( shadow_mode_enabled )
853 {
854 struct xen_reserved_phys_area xrpa;
856 /* Enable shadow translate mode */
857 if ( xc_shadow_control(xc_handle, dom,
858 DOM0_SHADOW_CONTROL_OP_ENABLE_TRANSLATE,
859 NULL, 0, NULL) < 0 )
860 {
861 PERROR("Could not enable translation mode");
862 goto error_out;
863 }
865 /* Find the shared info frame. It's guaranteed to be at the
866 start of the PFN hole. */
867 xrpa.domid = dom;
868 xrpa.idx = 0;
869 rc = xc_memory_op(xc_handle, XENMEM_reserved_phys_area, &xrpa);
870 if ( rc != 0 )
871 {
872 PERROR("Cannot find shared info pfn");
873 goto error_out;
874 }
875 guest_shared_info_mfn = xrpa.first_gpfn;
876 }
877 else
878 {
879 guest_shared_info_mfn = shared_info_frame;
880 }
882 *store_mfn = page_array[(vstoreinfo_start-dsi.v_start) >> PAGE_SHIFT];
883 *console_mfn = page_array[(vconsole_start-dsi.v_start) >> PAGE_SHIFT];
884 if ( xc_clear_domain_page(xc_handle, dom, *store_mfn) ||
885 xc_clear_domain_page(xc_handle, dom, *console_mfn) )
886 goto error_out;
887 if ( shadow_mode_enabled )
888 {
889 guest_store_mfn = (vstoreinfo_start-dsi.v_start) >> PAGE_SHIFT;
890 guest_console_mfn = (vconsole_start-dsi.v_start) >> PAGE_SHIFT;
891 }
892 else
893 {
894 guest_store_mfn = *store_mfn;
895 guest_console_mfn = *console_mfn;
896 }
898 start_info = xc_map_foreign_range(
899 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
900 page_array[(vstartinfo_start-dsi.v_start)>>PAGE_SHIFT]);
901 /*shared_info, start_info */
902 memset(start_info, 0, sizeof(*start_info));
903 rc = xc_version(xc_handle, XENVER_version, NULL);
904 sprintf(start_info->magic, "xen-%i.%i-x86_%d%s",
905 rc >> 16, rc & (0xFFFF), (unsigned int)sizeof(long)*8,
906 dsi.pae_kernel ? "p" : "");
907 start_info->nr_pages = nr_pages;
908 start_info->shared_info = guest_shared_info_mfn << PAGE_SHIFT;
909 start_info->flags = flags;
910 start_info->pt_base = vpt_start;
911 start_info->nr_pt_frames = nr_pt_pages;
912 start_info->mfn_list = vphysmap_start;
913 start_info->store_mfn = guest_store_mfn;
914 start_info->store_evtchn = store_evtchn;
915 start_info->console_mfn = guest_console_mfn;
916 start_info->console_evtchn = console_evtchn;
917 if ( initrd_len != 0 )
918 {
919 start_info->mod_start = vinitrd_start;
920 start_info->mod_len = initrd_len;
921 }
922 if ( cmdline != NULL )
923 {
924 strncpy((char *)start_info->cmd_line, cmdline, MAX_GUEST_CMDLINE);
925 start_info->cmd_line[MAX_GUEST_CMDLINE-1] = '\0';
926 }
927 munmap(start_info, PAGE_SIZE);
929 /* shared_info page starts its life empty. */
930 shared_info = xc_map_foreign_range(
931 xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, shared_info_frame);
932 memset(shared_info, 0, sizeof(shared_info_t));
933 /* Mask all upcalls... */
934 for ( i = 0; i < MAX_VIRT_CPUS; i++ )
935 shared_info->vcpu_info[i].evtchn_upcall_mask = 1;
937 munmap(shared_info, PAGE_SIZE);
939 /* Send the page update requests down to the hypervisor. */
940 if ( xc_finish_mmu_updates(xc_handle, mmu) )
941 goto error_out;
943 p = strstr(dsi.xen_guest_string, "HYPERCALL_PAGE=");
944 if ( p != NULL )
945 {
946 p += strlen("HYPERCALL_PAGE=");
947 hypercall_pfn = strtoul(p, NULL, 16);
948 if ( hypercall_pfn >= nr_pages )
949 goto error_out;
950 op.u.hypercall_init.domain = (domid_t)dom;
951 op.u.hypercall_init.mfn = page_array[hypercall_pfn];
952 op.cmd = DOM0_HYPERCALL_INIT;
953 if ( xc_dom0_op(xc_handle, &op) )
954 goto error_out;
955 }
957 free(mmu);
958 free(page_array);
960 *pvsi = vstartinfo_start;
961 *pvss = vstack_start;
962 *pvke = dsi.v_kernentry;
964 return 0;
966 error_out:
967 free(mmu);
968 free(page_array);
969 return -1;
970 }
971 #endif
973 int xc_linux_build(int xc_handle,
974 uint32_t domid,
975 const char *image_name,
976 const char *ramdisk_name,
977 const char *cmdline,
978 const char *features,
979 unsigned long flags,
980 unsigned int store_evtchn,
981 unsigned long *store_mfn,
982 unsigned int console_evtchn,
983 unsigned long *console_mfn)
984 {
985 dom0_op_t launch_op;
986 DECLARE_DOM0_OP;
987 int initrd_fd = -1;
988 gzFile initrd_gfd = NULL;
989 int rc, i;
990 vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt;
991 unsigned long nr_pages;
992 char *image = NULL;
993 unsigned long image_size, initrd_size=0;
994 unsigned long vstartinfo_start, vkern_entry, vstack_start;
995 uint32_t features_bitmap[XENFEAT_NR_SUBMAPS] = { 0, };
997 if ( features != NULL )
998 {
999 if ( !parse_features(features, features_bitmap, NULL) )
1001 PERROR("Failed to parse configured features\n");
1002 goto error_out;
1006 if ( (nr_pages = get_tot_pages(xc_handle, domid)) < 0 )
1008 PERROR("Could not find total pages for domain");
1009 goto error_out;
1012 if ( (image = xc_read_kernel_image(image_name, &image_size)) == NULL )
1013 goto error_out;
1015 if ( (ramdisk_name != NULL) && (strlen(ramdisk_name) != 0) )
1017 if ( (initrd_fd = open(ramdisk_name, O_RDONLY)) < 0 )
1019 PERROR("Could not open the initial ramdisk image");
1020 goto error_out;
1023 initrd_size = xc_get_filesz(initrd_fd);
1025 if ( (initrd_gfd = gzdopen(initrd_fd, "rb")) == NULL )
1027 PERROR("Could not allocate decompression state for initrd");
1028 goto error_out;
1032 #ifdef VALGRIND
1033 memset(&st_ctxt, 0, sizeof(st_ctxt));
1034 #endif
1036 if ( mlock(&st_ctxt, sizeof(st_ctxt) ) )
1038 PERROR("%s: ctxt mlock failed", __func__);
1039 return 1;
1042 op.cmd = DOM0_GETDOMAININFO;
1043 op.u.getdomaininfo.domain = (domid_t)domid;
1044 if ( (xc_dom0_op(xc_handle, &op) < 0) ||
1045 ((uint16_t)op.u.getdomaininfo.domain != domid) )
1047 PERROR("Could not get info on domain");
1048 goto error_out;
1051 memset(ctxt, 0, sizeof(*ctxt));
1053 if ( setup_guest(xc_handle, domid, image, image_size,
1054 initrd_gfd, initrd_size, nr_pages,
1055 &vstartinfo_start, &vkern_entry,
1056 &vstack_start, ctxt, cmdline,
1057 op.u.getdomaininfo.shared_info_frame,
1058 flags, store_evtchn, store_mfn,
1059 console_evtchn, console_mfn,
1060 features_bitmap) < 0 )
1062 ERROR("Error constructing guest OS");
1063 goto error_out;
1066 if ( initrd_fd >= 0 )
1067 close(initrd_fd);
1068 if ( initrd_gfd )
1069 gzclose(initrd_gfd);
1070 free(image);
1072 #ifdef __ia64__
1073 /* based on new_thread in xen/arch/ia64/domain.c */
1074 ctxt->flags = 0;
1075 ctxt->shared.flags = flags;
1076 ctxt->shared.start_info_pfn = nr_pages - 3; /* metaphysical */
1077 ctxt->regs.cr_ipsr = 0; /* all necessary bits filled by hypervisor */
1078 ctxt->regs.cr_iip = vkern_entry;
1079 ctxt->regs.cr_ifs = 1UL << 63;
1080 ctxt->regs.ar_fpsr = xc_ia64_fpsr_default();
1081 /* currently done by hypervisor, should move here */
1082 /* ctxt->regs.r28 = dom_fw_setup(); */
1083 ctxt->vcpu.privregs = 0;
1084 ctxt->sys_pgnr = 3;
1085 i = 0; /* silence unused variable warning */
1086 #else /* x86 */
1087 /*
1088 * Initial register values:
1089 * DS,ES,FS,GS = FLAT_KERNEL_DS
1090 * CS:EIP = FLAT_KERNEL_CS:start_pc
1091 * SS:ESP = FLAT_KERNEL_DS:start_stack
1092 * ESI = start_info
1093 * [EAX,EBX,ECX,EDX,EDI,EBP are zero]
1094 * EFLAGS = IF | 2 (bit 1 is reserved and should always be 1)
1095 */
1096 ctxt->user_regs.ds = FLAT_KERNEL_DS;
1097 ctxt->user_regs.es = FLAT_KERNEL_DS;
1098 ctxt->user_regs.fs = FLAT_KERNEL_DS;
1099 ctxt->user_regs.gs = FLAT_KERNEL_DS;
1100 ctxt->user_regs.ss = FLAT_KERNEL_SS;
1101 ctxt->user_regs.cs = FLAT_KERNEL_CS;
1102 ctxt->user_regs.eip = vkern_entry;
1103 ctxt->user_regs.esp = vstack_start + PAGE_SIZE;
1104 ctxt->user_regs.esi = vstartinfo_start;
1105 ctxt->user_regs.eflags = 1 << 9; /* Interrupt Enable */
1107 ctxt->flags = VGCF_IN_KERNEL;
1109 /* FPU is set up to default initial state. */
1110 memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
1112 /* Virtual IDT is empty at start-of-day. */
1113 for ( i = 0; i < 256; i++ )
1115 ctxt->trap_ctxt[i].vector = i;
1116 ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS;
1119 /* No LDT. */
1120 ctxt->ldt_ents = 0;
1122 /* Use the default Xen-provided GDT. */
1123 ctxt->gdt_ents = 0;
1125 /* Ring 1 stack is the initial stack. */
1126 ctxt->kernel_ss = FLAT_KERNEL_SS;
1127 ctxt->kernel_sp = vstack_start + PAGE_SIZE;
1129 /* No debugging. */
1130 memset(ctxt->debugreg, 0, sizeof(ctxt->debugreg));
1132 /* No callback handlers. */
1133 #if defined(__i386__)
1134 ctxt->event_callback_cs = FLAT_KERNEL_CS;
1135 ctxt->event_callback_eip = 0;
1136 ctxt->failsafe_callback_cs = FLAT_KERNEL_CS;
1137 ctxt->failsafe_callback_eip = 0;
1138 #elif defined(__x86_64__)
1139 ctxt->event_callback_eip = 0;
1140 ctxt->failsafe_callback_eip = 0;
1141 ctxt->syscall_callback_eip = 0;
1142 #endif
1143 #endif /* x86 */
1145 memset( &launch_op, 0, sizeof(launch_op) );
1147 launch_op.u.setvcpucontext.domain = (domid_t)domid;
1148 launch_op.u.setvcpucontext.vcpu = 0;
1149 launch_op.u.setvcpucontext.ctxt = ctxt;
1151 launch_op.cmd = DOM0_SETVCPUCONTEXT;
1152 rc = xc_dom0_op(xc_handle, &launch_op);
1154 return rc;
1156 error_out:
1157 if ( initrd_gfd != NULL )
1158 gzclose(initrd_gfd);
1159 else if ( initrd_fd >= 0 )
1160 close(initrd_fd);
1161 free(image);
1162 return -1;
1165 /*
1166 * Local variables:
1167 * mode: C
1168 * c-set-style: "BSD"
1169 * c-basic-offset: 4
1170 * tab-width: 4
1171 * indent-tabs-mode: nil
1172 * End:
1173 */