ia64/xen-unstable

view xen/arch/ia64/xen/xensetup.c @ 16817:564fa97594a6

[IA64] Introduce dom0_vhpt_size_log2 boot option to change dom0 vhpt size

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Alex Williamson <alex.williamson@hp.com>
date Tue Jan 22 08:26:20 2008 -0700 (2008-01-22)
parents 8977f087351a
children cff4c8a1aa28
line source
1 /******************************************************************************
2 * xensetup.c
3 * Copyright (c) 2004-2005 Hewlett-Packard Co
4 * Dan Magenheimer <dan.magenheimer@hp.com>
5 */
7 #include <xen/config.h>
8 #include <xen/lib.h>
9 #include <xen/errno.h>
10 #include <xen/multiboot.h>
11 #include <xen/sched.h>
12 #include <xen/mm.h>
13 #include <public/version.h>
14 #include <xen/gdbstub.h>
15 #include <xen/version.h>
16 #include <xen/console.h>
17 #include <xen/domain.h>
18 #include <xen/serial.h>
19 #include <xen/trace.h>
20 #include <xen/keyhandler.h>
21 #include <xen/vga.h>
22 #include <asm/meminit.h>
23 #include <asm/page.h>
24 #include <asm/setup.h>
25 #include <asm/vhpt.h>
26 #include <xen/string.h>
27 #include <asm/vmx.h>
28 #include <linux/efi.h>
29 #include <asm/iosapic.h>
30 #include <xen/softirq.h>
31 #include <xen/rcupdate.h>
32 #include <xsm/acm/acm_hooks.h>
33 #include <asm/sn/simulator.h>
34 #include <linux/asm/sal.h>
36 unsigned long xenheap_phys_end, total_pages;
38 char saved_command_line[COMMAND_LINE_SIZE];
39 char __initdata dom0_command_line[COMMAND_LINE_SIZE];
41 cpumask_t cpu_present_map;
43 extern unsigned long domain0_ready;
45 int find_max_pfn (unsigned long, unsigned long, void *);
47 /* FIXME: which header these declarations should be there ? */
48 extern void early_setup_arch(char **);
49 extern void late_setup_arch(char **);
50 extern void hpsim_serial_init(void);
51 extern void setup_per_cpu_areas(void);
52 extern void mem_init(void);
53 extern void init_IRQ(void);
54 extern void trap_init(void);
55 extern void xen_patch_kernel(void);
57 /* nosmp: ignore secondary processors */
58 static int __initdata opt_nosmp;
59 boolean_param("nosmp", opt_nosmp);
61 /* maxcpus: maximum number of CPUs to activate */
62 static unsigned int __initdata max_cpus = NR_CPUS;
63 integer_param("maxcpus", max_cpus);
65 /* xencons: toggle xenconsole input (and irq).
66 Note: you have to disable 8250 serials in domains (to avoid use of the
67 same resource). */
68 static int __initdata opt_xencons = 1;
69 integer_param("xencons", opt_xencons);
71 /* xencons_poll: toggle non-legacy xencons UARTs to run in polling mode */
72 static int __initdata opt_xencons_poll;
73 boolean_param("xencons_poll", opt_xencons_poll);
75 unsigned long xenheap_size = XENHEAP_DEFAULT_SIZE;
76 unsigned long xen_pstart;
77 void *xen_pickle_offset __read_mostly;
79 static void __init parse_xenheap_megabytes(char *s)
80 {
81 unsigned long megabytes = simple_strtoll(s, NULL, 0);
83 #define XENHEAP_MEGABYTES_MIN 16
84 if (megabytes < XENHEAP_MEGABYTES_MIN)
85 megabytes = XENHEAP_MEGABYTES_MIN;
87 #define XENHEAP_MEGABYTES_MAX 4096 /* need more? If so,
88 __pickle()/__unpickle() must be
89 revised. */
90 if (megabytes > XENHEAP_MEGABYTES_MAX)
91 megabytes = XENHEAP_MEGABYTES_MAX;
93 xenheap_size = megabytes * 1024 * 1024;
94 }
95 custom_param("xenheap_megabytes", parse_xenheap_megabytes);
97 static int __init
98 xen_count_pages(u64 start, u64 end, void *arg)
99 {
100 unsigned long *count = arg;
102 /* FIXME: do we need consider difference between DMA-usable memory and
103 * normal memory? Seems that HV has no requirement to operate DMA which
104 * is owned by Dom0? */
105 *count += (end - start) >> PAGE_SHIFT;
106 return 0;
107 }
109 static void __init do_initcalls(void)
110 {
111 initcall_t *call;
112 for ( call = &__initcall_start; call < &__initcall_end; call++ )
113 (*call)();
114 }
116 /*
117 * IPF loader only supports one command line currently, for
118 * both xen and guest kernel. This function provides pre-parse
119 * to mixed command line, to split it into two parts.
120 *
121 * User should split the parameters by "--", with strings after
122 * spliter for guest kernel. Missing "--" means whole line belongs
123 * to guest. Example:
124 * "com2=57600,8n1 console=com2 -- console=ttyS1 console=tty
125 * root=/dev/sda3 ro"
126 */
127 static char null[4] = { 0 };
129 void __init early_cmdline_parse(char **cmdline_p)
130 {
131 char *guest_cmd;
132 static const char * const split = "--";
134 if (*cmdline_p == NULL) {
135 *cmdline_p = &null[0];
136 saved_command_line[0] = '\0';
137 dom0_command_line[0] = '\0';
138 return;
139 }
141 guest_cmd = strstr(*cmdline_p, split);
142 /* If no spliter, whole line is for guest */
143 if (guest_cmd == NULL) {
144 guest_cmd = *cmdline_p;
145 *cmdline_p = &null[0];
146 } else {
147 *guest_cmd = '\0'; /* Split boot parameters for xen and guest */
148 guest_cmd += strlen(split);
149 while (*guest_cmd == ' ') guest_cmd++;
150 }
152 strlcpy(saved_command_line, *cmdline_p, COMMAND_LINE_SIZE);
153 strlcpy(dom0_command_line, guest_cmd, COMMAND_LINE_SIZE);
154 return;
155 }
157 struct ns16550_defaults ns16550_com1 = {
158 .data_bits = 8,
159 .parity = 'n',
160 .stop_bits = 1
161 };
163 unsigned int ns16550_com1_gsi;
164 unsigned int ns16550_com1_polarity;
165 unsigned int ns16550_com1_trigger;
167 struct ns16550_defaults ns16550_com2 = {
168 .data_bits = 8,
169 .parity = 'n',
170 .stop_bits = 1
171 };
173 /* efi_print: print efi table at boot */
174 static int __initdata opt_efi_print;
175 boolean_param("efi_print", opt_efi_print);
177 /* print EFI memory map: */
178 static void __init
179 efi_print(void)
180 {
181 void *efi_map_start, *efi_map_end;
182 u64 efi_desc_size;
184 efi_memory_desc_t *md;
185 void *p;
186 int i;
188 if (!opt_efi_print)
189 return;
191 efi_map_start = __va(ia64_boot_param->efi_memmap);
192 efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
193 efi_desc_size = ia64_boot_param->efi_memdesc_size;
195 for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) {
196 md = p;
197 printk("mem%02u: type=%2u, attr=0x%016lx, range=[0x%016lx-0x%016lx) "
198 "(%luMB)\n", i, md->type, md->attribute, md->phys_addr,
199 md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
200 md->num_pages >> (20 - EFI_PAGE_SHIFT));
201 }
202 }
204 /*
205 * These functions are utility functions for getting and
206 * testing memory descriptors for allocating the xenheap area.
207 */
208 static efi_memory_desc_t * __init
209 efi_get_md (unsigned long phys_addr)
210 {
211 void *efi_map_start, *efi_map_end, *p;
212 efi_memory_desc_t *md;
213 u64 efi_desc_size;
215 efi_map_start = __va(ia64_boot_param->efi_memmap);
216 efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
217 efi_desc_size = ia64_boot_param->efi_memdesc_size;
219 for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
220 md = p;
221 if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT))
222 return md;
223 }
224 return 0;
225 }
227 static int __init
228 is_xenheap_usable_memory(efi_memory_desc_t *md)
229 {
230 if (!(md->attribute & EFI_MEMORY_WB))
231 return 0;
233 switch (md->type) {
234 case EFI_LOADER_CODE:
235 case EFI_LOADER_DATA:
236 case EFI_BOOT_SERVICES_CODE:
237 case EFI_BOOT_SERVICES_DATA:
238 case EFI_CONVENTIONAL_MEMORY:
239 return 1;
240 }
241 return 0;
242 }
244 static inline int __init
245 md_overlaps(const efi_memory_desc_t *md, unsigned long phys_addr)
246 {
247 return (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT));
248 }
250 static inline int __init
251 md_overlap_with_boot_param(const efi_memory_desc_t *md)
252 {
253 return md_overlaps(md, __pa(ia64_boot_param)) ||
254 md_overlaps(md, ia64_boot_param->efi_memmap) ||
255 md_overlaps(md, ia64_boot_param->command_line);
256 }
258 #define MD_SIZE(md) (md->num_pages << EFI_PAGE_SHIFT)
259 #define MD_END(md) ((md)->phys_addr + MD_SIZE(md))
261 extern char __init_begin[], __init_end[];
262 static void noinline init_done(void)
263 {
264 memset(__init_begin, 0, __init_end - __init_begin);
265 flush_icache_range((unsigned long)__init_begin, (unsigned long)__init_end);
266 init_xenheap_pages(__pa(__init_begin), __pa(__init_end));
267 printk("Freed %ldkB init memory.\n",
268 (long)(__init_end-__init_begin)>>10);
270 startup_cpu_idle_loop();
271 }
273 struct xen_heap_desc {
274 void* xen_heap_start;
275 unsigned long xenheap_phys_end;
276 efi_memory_desc_t* kern_md;
277 };
279 static int __init
280 init_xenheap_mds(unsigned long start, unsigned long end, void *arg)
281 {
282 struct xen_heap_desc *desc = (struct xen_heap_desc*)arg;
283 unsigned long md_end = __pa(desc->xen_heap_start);
284 efi_memory_desc_t* md;
286 start = __pa(start);
287 end = __pa(end);
289 for (md = efi_get_md(md_end);
290 md != NULL && md->phys_addr < desc->xenheap_phys_end;
291 md = efi_get_md(md_end)) {
292 md_end = MD_END(md);
294 if (md == desc->kern_md ||
295 (md->type == EFI_LOADER_DATA && !md_overlap_with_boot_param(md)) ||
296 ((md->attribute & EFI_MEMORY_WB) &&
297 is_xenheap_usable_memory(md))) {
298 unsigned long s = max(start, max(__pa(desc->xen_heap_start),
299 md->phys_addr));
300 unsigned long e = min(end, min(md_end, desc->xenheap_phys_end));
301 init_xenheap_pages(s, e);
302 }
303 }
305 return 0;
306 }
308 int running_on_sim;
310 static int __init
311 is_platform_hp_ski(void)
312 {
313 int i;
314 long cpuid[6];
316 for (i = 0; i < 5; ++i)
317 cpuid[i] = ia64_get_cpuid(i);
319 if ((cpuid[0] & 0xff) != 'H')
320 return 0;
321 if ((cpuid[3] & 0xff) != 0x4)
322 return 0;
323 if (((cpuid[3] >> 8) & 0xff) != 0x0)
324 return 0;
325 if (((cpuid[3] >> 16) & 0xff) != 0x0)
326 return 0;
327 if (((cpuid[3] >> 24) & 0x7) != 0x7)
328 return 0;
330 return 1;
331 }
333 #ifdef CONFIG_XEN_IA64_PERVCPU_VHPT
334 static int __initdata dom0_vhpt_size_log2;
335 integer_param("dom0_vhpt_size_log2", dom0_vhpt_size_log2);
336 #endif
338 void __init start_kernel(void)
339 {
340 char *cmdline;
341 unsigned long nr_pages;
342 unsigned long dom0_memory_start, dom0_memory_size;
343 unsigned long dom0_initrd_start, dom0_initrd_size;
344 unsigned long md_end, relo_start, relo_end, relo_size = 0;
345 struct domain *idle_domain;
346 struct vcpu *dom0_vcpu0;
347 efi_memory_desc_t *kern_md, *last_md, *md;
348 void *xen_heap_start;
349 struct xen_heap_desc heap_desc;
350 #ifdef CONFIG_SMP
351 int i;
352 #endif
354 /* Be sure the struct shared_info size is <= XSI_SIZE. */
355 BUILD_BUG_ON(sizeof(struct shared_info) > XSI_SIZE);
357 /* Kernel may be relocated by EFI loader */
358 xen_pstart = ia64_tpa(KERNEL_START);
360 running_on_sim = is_platform_hp_ski();
362 early_setup_arch(&cmdline);
364 /* We initialise the serial devices very early so we can get debugging. */
365 if (running_on_sim)
366 hpsim_serial_init();
367 else {
368 ns16550_init(0, &ns16550_com1);
369 ns16550_init(1, &ns16550_com2);
370 }
371 serial_init_preirq();
373 #ifdef CONFIG_VGA
374 /* Plug in a default VGA mode */
375 vga_console_info.video_type = XEN_VGATYPE_TEXT_MODE_3;
376 vga_console_info.u.text_mode_3.font_height = 16; /* generic VGA? */
377 vga_console_info.u.text_mode_3.cursor_x =
378 ia64_boot_param->console_info.orig_x;
379 vga_console_info.u.text_mode_3.cursor_y =
380 ia64_boot_param->console_info.orig_y;
381 vga_console_info.u.text_mode_3.rows =
382 ia64_boot_param->console_info.num_rows;
383 vga_console_info.u.text_mode_3.columns =
384 ia64_boot_param->console_info.num_cols;
385 #endif
387 init_console();
389 if (running_on_sim || ia64_boot_param->domain_start == 0 ||
390 ia64_boot_param->domain_size == 0) {
391 /* This is possible only with the old elilo, which does not support
392 a vmm. Fix now, and continue without initrd. */
393 printk ("Your elilo is not Xen-aware. Bootparams fixed\n");
394 ia64_boot_param->domain_start = ia64_boot_param->initrd_start;
395 ia64_boot_param->domain_size = ia64_boot_param->initrd_size;
396 ia64_boot_param->initrd_start = 0;
397 ia64_boot_param->initrd_size = 0;
398 }
400 printk("Xen command line: %s\n", saved_command_line);
402 xenheap_phys_end = xen_pstart + xenheap_size;
403 printk("xen image pstart: 0x%lx, xenheap pend: 0x%lx\n",
404 xen_pstart, xenheap_phys_end);
406 xen_patch_kernel();
408 kern_md = md = efi_get_md(xen_pstart);
409 md_end = __pa(ia64_imva(&_end));
410 relo_start = xenheap_phys_end;
412 /*
413 * Scan through the memory descriptors after the kernel
414 * image to make sure we have enough room for the xenheap
415 * area, pushing out whatever may already be there.
416 */
417 while (relo_start + relo_size >= md_end) {
418 md = efi_get_md(md_end);
420 if (md == NULL) {
421 printk("no room to move loader data. skip moving loader data\n");
422 goto skip_move;
423 }
425 md_end = MD_END(md);
426 if (relo_start < md->phys_addr)
427 relo_start = md->phys_addr;
429 if (!is_xenheap_usable_memory(md)) {
430 /* Skip this area */
431 if (md_end > relo_start)
432 relo_start = md_end;
433 continue;
434 }
436 /*
437 * The dom0 kernel or initrd could overlap, reserve space
438 * at the end to relocate them later.
439 */
440 if (md->type == EFI_LOADER_DATA) {
441 /* Test for ranges we're not prepared to move */
442 if (!md_overlap_with_boot_param(md))
443 relo_size += MD_SIZE(md);
445 /* If range overlaps the end, push out the relocation start */
446 if (md_end > relo_start)
447 relo_start = md_end;
448 }
449 }
450 last_md = md;
451 relo_start = md_end - relo_size;
452 relo_end = relo_start + relo_size;
454 md_end = __pa(ia64_imva(&_end));
456 /*
457 * Move any relocated data out into the previously found relocation
458 * area. Any extra memory descriptrs are moved out to the end
459 * and set to zero pages.
460 */
461 for (md = efi_get_md(md_end) ;; md = efi_get_md(md_end)) {
462 md_end = MD_END(md);
464 if (md->type == EFI_LOADER_DATA && !md_overlap_with_boot_param(md)) {
465 unsigned long relo_offset;
467 if (md_overlaps(md, ia64_boot_param->domain_start)) {
468 relo_offset = ia64_boot_param->domain_start - md->phys_addr;
469 printk("Moving Dom0 kernel image: 0x%lx -> 0x%lx (%ld KiB)\n",
470 ia64_boot_param->domain_start, relo_start + relo_offset,
471 ia64_boot_param->domain_size >> 10);
472 ia64_boot_param->domain_start = relo_start + relo_offset;
473 }
474 if (ia64_boot_param->initrd_size &&
475 md_overlaps(md, ia64_boot_param->initrd_start)) {
476 relo_offset = ia64_boot_param->initrd_start - md->phys_addr;
477 printk("Moving Dom0 initrd image: 0x%lx -> 0x%lx (%ld KiB)\n",
478 ia64_boot_param->initrd_start, relo_start + relo_offset,
479 ia64_boot_param->initrd_size >> 10);
480 ia64_boot_param->initrd_start = relo_start + relo_offset;
481 }
482 memcpy(__va(relo_start), __va(md->phys_addr), MD_SIZE(md));
483 relo_start += MD_SIZE(md);
484 }
486 if (md == last_md)
487 break;
488 }
490 /* Trim the last entry */
491 md->num_pages -= (relo_size >> EFI_PAGE_SHIFT);
493 skip_move:
494 reserve_memory();
496 /* first find highest page frame number */
497 max_page = 0;
498 efi_memmap_walk(find_max_pfn, &max_page);
499 printk("find_memory: efi_memmap_walk returns max_page=%lx\n",max_page);
500 efi_print();
502 /*
503 * later [__init_begin, __init_end) will be freed up as xen heap
504 * so that struct domain might be allocated from the init area
505 * which is < xen_heap_start. so we can't simply set
506 * xen_pickle_offset = xen_heap_start.
507 */
508 xen_pickle_offset = ia64_imva(__init_begin);
510 xen_heap_start = memguard_init(ia64_imva(&_end));
511 printk("Before xen_heap_start: %p\n", xen_heap_start);
512 xen_heap_start = __va(init_boot_allocator(__pa(xen_heap_start)));
513 printk("After xen_heap_start: %p\n", xen_heap_start);
515 efi_memmap_walk(filter_rsvd_memory, init_boot_pages);
516 efi_memmap_walk(xen_count_pages, &nr_pages);
518 printk("System RAM: %luMB (%lukB)\n",
519 nr_pages >> (20 - PAGE_SHIFT),
520 nr_pages << (PAGE_SHIFT - 10));
521 total_pages = nr_pages;
523 init_frametable();
525 trap_init();
527 /* process SAL system table */
528 /* must be before any pal/sal call */
529 ia64_sal_init(efi.sal_systab);
531 /* early_setup_arch() maps PAL code. */
532 identify_vmx_feature();
533 /* If vmx feature is on, do necessary initialization for vmx */
534 if (vmx_enabled)
535 xen_heap_start = vmx_init_env(xen_heap_start, xenheap_phys_end);
537 heap_desc.xen_heap_start = xen_heap_start;
538 heap_desc.xenheap_phys_end = xenheap_phys_end;
539 heap_desc.kern_md = kern_md;
540 efi_memmap_walk(&init_xenheap_mds, &heap_desc);
542 printk("Xen heap: %luMB (%lukB)\n",
543 (xenheap_phys_end-__pa(xen_heap_start)) >> 20,
544 (xenheap_phys_end-__pa(xen_heap_start)) >> 10);
546 end_boot_allocator();
548 late_setup_arch(&cmdline);
550 scheduler_init();
551 idle_vcpu[0] = (struct vcpu*) ia64_r13;
552 idle_domain = domain_create(IDLE_DOMAIN_ID, 0, 0);
553 if ( (idle_domain == NULL) || (alloc_vcpu(idle_domain, 0, 0) == NULL) )
554 BUG();
556 alloc_dom_xen_and_dom_io();
557 setup_per_cpu_areas();
558 mem_init();
560 local_irq_disable();
561 init_IRQ ();
562 init_xen_time(); /* initialise the time */
563 timer_init();
565 rcu_init();
567 #ifdef CONFIG_XEN_IA64_TLBFLUSH_CLOCK
568 open_softirq(NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ, new_tlbflush_clock_period);
569 #endif
571 #ifdef CONFIG_SMP
572 if ( opt_nosmp )
573 {
574 max_cpus = 0;
575 smp_num_siblings = 1;
576 //boot_cpu_data.x86_num_cores = 1;
577 }
579 /* A vcpu is created for the idle domain on every physical cpu.
580 Limit the number of cpus to the maximum number of vcpus. */
581 if (max_cpus > MAX_VIRT_CPUS)
582 max_cpus = MAX_VIRT_CPUS;
584 smp_prepare_cpus(max_cpus);
586 /* We aren't hotplug-capable yet. */
587 for_each_cpu ( i )
588 cpu_set(i, cpu_present_map);
590 /* Enable IRQ to receive IPI (needed for ITC sync). */
591 local_irq_enable();
593 printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus);
594 for_each_present_cpu ( i )
595 {
596 if ( num_online_cpus() >= max_cpus )
597 break;
598 if ( !cpu_online(i) ) {
599 rcu_online_cpu(i);
600 __cpu_up(i);
601 }
602 }
604 local_irq_disable();
606 printk("Brought up %ld CPUs\n", (long)num_online_cpus());
607 smp_cpus_done(max_cpus);
608 #endif
610 initialise_gdb(); /* could be moved earlier */
612 do_initcalls();
613 sort_main_extable();
615 init_rid_allocator ();
617 local_irq_enable();
619 if (opt_xencons) {
620 initialize_keytable();
621 if (ns16550_com1_gsi) {
622 if (opt_xencons_poll ||
623 iosapic_register_intr(ns16550_com1_gsi,
624 ns16550_com1_polarity,
625 ns16550_com1_trigger) < 0) {
626 ns16550_com1.irq = 0;
627 ns16550_init(0, &ns16550_com1);
628 }
629 }
630 serial_init_postirq();
631 }
633 expose_p2m_init();
635 /* Create initial domain 0. */
636 dom0 = domain_create(0, 0, DOM0_SSIDREF);
637 if (dom0 == NULL)
638 panic("Error creating domain 0\n");
639 domain_set_vhpt_size(dom0, dom0_vhpt_size_log2);
640 dom0_vcpu0 = alloc_vcpu(dom0, 0, 0);
641 if (dom0_vcpu0 == NULL || vcpu_late_initialise(dom0_vcpu0) != 0)
642 panic("Cannot allocate dom0 vcpu 0\n");
644 dom0->is_privileged = 1;
646 /*
647 * We're going to setup domain0 using the module(s) that we stashed safely
648 * above our heap. The second module, if present, is an initrd ramdisk.
649 */
650 dom0_memory_start = (unsigned long) __va(ia64_boot_param->domain_start);
651 dom0_memory_size = ia64_boot_param->domain_size;
652 dom0_initrd_start = (unsigned long) __va(ia64_boot_param->initrd_start);
653 dom0_initrd_size = ia64_boot_param->initrd_size;
655 if ( construct_dom0(dom0, dom0_memory_start, dom0_memory_size,
656 dom0_initrd_start,dom0_initrd_size,
657 0) != 0)
658 panic("Could not set up DOM0 guest OS\n");
660 if (!running_on_sim && !IS_MEDUSA()) // slow on ski and pages are pre-initialized to zero
661 scrub_heap_pages();
663 init_trace_bufs();
665 if (opt_xencons) {
666 console_endboot();
667 serial_endboot();
668 }
670 domain0_ready = 1;
672 domain_unpause_by_systemcontroller(dom0);
674 init_done();
675 }
677 void arch_get_xen_caps(xen_capabilities_info_t *info)
678 {
679 /* Interface name is always xen-3.0-* for Xen-3.x. */
680 int major = 3, minor = 0;
681 char s[32];
683 (*info)[0] = '\0';
685 snprintf(s, sizeof(s), "xen-%d.%d-ia64 ", major, minor);
686 safe_strcat(*info, s);
688 snprintf(s, sizeof(s), "xen-%d.%d-ia64be ", major, minor);
689 safe_strcat(*info, s);
691 if (vmx_enabled)
692 {
693 snprintf(s, sizeof(s), "hvm-%d.%d-ia64 ", major, minor);
694 safe_strcat(*info, s);
695 }
696 }