direct-io.hg

view xen/arch/ia64/xen/xensetup.c @ 11967:e9c7f965e70a

[IA64] make efi_print()'s output more readable

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author awilliam@xenbuild.aw
date Sun Oct 08 18:21:32 2006 -0600 (2006-10-08)
parents 0bb486157ff5
children 6fae3a36f50b
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/spinlock.h>
11 #include <xen/multiboot.h>
12 #include <xen/sched.h>
13 #include <xen/mm.h>
14 #include <public/version.h>
15 #include <xen/gdbstub.h>
16 #include <xen/version.h>
17 #include <xen/console.h>
18 #include <xen/domain.h>
19 #include <xen/serial.h>
20 #include <xen/trace.h>
21 #include <xen/keyhandler.h>
22 #include <asm/meminit.h>
23 #include <asm/page.h>
24 #include <asm/setup.h>
25 #include <xen/string.h>
26 #include <asm/vmx.h>
27 #include <linux/efi.h>
28 #include <asm/iosapic.h>
30 unsigned long xenheap_phys_end, total_pages;
32 char saved_command_line[COMMAND_LINE_SIZE];
33 char dom0_command_line[COMMAND_LINE_SIZE];
35 cpumask_t cpu_present_map;
37 extern unsigned long domain0_ready;
39 int find_max_pfn (unsigned long, unsigned long, void *);
41 /* FIXME: which header these declarations should be there ? */
42 extern long is_platform_hp_ski(void);
43 extern void early_setup_arch(char **);
44 extern void late_setup_arch(char **);
45 extern void hpsim_serial_init(void);
46 extern void alloc_dom0(void);
47 extern void setup_per_cpu_areas(void);
48 extern void mem_init(void);
49 extern void init_IRQ(void);
50 extern void trap_init(void);
51 extern void xen_patch_kernel(void);
53 /* opt_nosmp: If true, secondary processors are ignored. */
54 static int opt_nosmp = 0;
55 boolean_param("nosmp", opt_nosmp);
57 /* maxcpus: maximum number of CPUs to activate. */
58 static unsigned int max_cpus = NR_CPUS;
59 integer_param("maxcpus", max_cpus);
61 /* xencons: if true enable xenconsole input (and irq).
62 Note: you have to disable 8250 serials in domains (to avoid use of the
63 same resource). */
64 static int opt_xencons = 1;
65 integer_param("xencons", opt_xencons);
67 /* Toggle to allow non-legacy xencons UARTs to run in polling mode */
68 static int opt_xencons_poll = 0;
69 boolean_param("xencons_poll", opt_xencons_poll);
71 /*
72 * opt_xenheap_megabytes: Size of Xen heap in megabytes, including:
73 * xen image
74 * bootmap bits
75 * xen heap
76 * Note: To allow xenheap size configurable, the prerequisite is
77 * to configure elilo allowing relocation defaultly. Then since
78 * elilo chooses 256M as alignment when relocating, alignment issue
79 * on IPF can be addressed.
80 */
81 unsigned int opt_xenheap_megabytes = XENHEAP_DEFAULT_MB;
82 unsigned long xenheap_size = XENHEAP_DEFAULT_SIZE;
83 extern long running_on_sim;
84 unsigned long xen_pstart;
85 void *xen_heap_start;
87 static int
88 xen_count_pages(u64 start, u64 end, void *arg)
89 {
90 unsigned long *count = arg;
92 /* FIXME: do we need consider difference between DMA-usable memory and
93 * normal memory? Seems that HV has no requirement to operate DMA which
94 * is owned by Dom0? */
95 *count += (end - start) >> PAGE_SHIFT;
96 return 0;
97 }
99 static void __init do_initcalls(void)
100 {
101 initcall_t *call;
102 for ( call = &__initcall_start; call < &__initcall_end; call++ )
103 (*call)();
104 }
106 /*
107 * IPF loader only supports one commaind line currently, for
108 * both xen and guest kernel. This function provides pre-parse
109 * to mixed command line, to split it into two parts.
110 *
111 * User should split the parameters by "--", with strings after
112 * spliter for guest kernel. Missing "--" means whole line belongs
113 * to guest. Example:
114 * "com2=57600,8n1 console=com2 -- console=ttyS1 console=tty
115 * root=/dev/sda3 ro"
116 */
117 static char null[4] = { 0 };
119 void early_cmdline_parse(char **cmdline_p)
120 {
121 char *guest_cmd;
122 static const char * const split = "--";
124 if (*cmdline_p == NULL) {
125 *cmdline_p = &null[0];
126 saved_command_line[0] = '\0';
127 dom0_command_line[0] = '\0';
128 return;
129 }
131 guest_cmd = strstr(*cmdline_p, split);
132 /* If no spliter, whole line is for guest */
133 if (guest_cmd == NULL) {
134 guest_cmd = *cmdline_p;
135 *cmdline_p = &null[0];
136 } else {
137 *guest_cmd = '\0'; /* Split boot parameters for xen and guest */
138 guest_cmd += strlen(split);
139 while (*guest_cmd == ' ') guest_cmd++;
140 }
142 strlcpy(saved_command_line, *cmdline_p, COMMAND_LINE_SIZE);
143 strlcpy(dom0_command_line, guest_cmd, COMMAND_LINE_SIZE);
144 return;
145 }
147 struct ns16550_defaults ns16550_com1 = {
148 .baud = BAUD_AUTO,
149 .data_bits = 8,
150 .parity = 'n',
151 .stop_bits = 1
152 };
154 unsigned int ns16550_com1_gsi;
155 unsigned int ns16550_com1_polarity;
156 unsigned int ns16550_com1_trigger;
158 struct ns16550_defaults ns16550_com2 = {
159 .baud = BAUD_AUTO,
160 .data_bits = 8,
161 .parity = 'n',
162 .stop_bits = 1
163 };
165 /* efi_print: print efi table at boot */
166 static int opt_efi_print = 0;
167 boolean_param("efi_print", opt_efi_print);
169 /* print EFI memory map: */
170 static void
171 efi_print(void)
172 {
173 void *efi_map_start, *efi_map_end;
174 u64 efi_desc_size;
176 efi_memory_desc_t *md;
177 void *p;
178 int i;
180 if (!opt_efi_print)
181 return;
183 efi_map_start = __va(ia64_boot_param->efi_memmap);
184 efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
185 efi_desc_size = ia64_boot_param->efi_memdesc_size;
187 for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) {
188 md = p;
189 printk("mem%02u: type=%2u, attr=0x%016lx, range=[0x%016lx-0x%016lx) "
190 "(%luMB)\n", i, md->type, md->attribute, md->phys_addr,
191 md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
192 md->num_pages >> (20 - EFI_PAGE_SHIFT));
193 }
194 }
196 /*
197 * These functions are utility functions for getting and
198 * testing memory descriptors for allocating the xenheap area.
199 */
200 static efi_memory_desc_t *
201 efi_get_md (unsigned long phys_addr)
202 {
203 void *efi_map_start, *efi_map_end, *p;
204 efi_memory_desc_t *md;
205 u64 efi_desc_size;
207 efi_map_start = __va(ia64_boot_param->efi_memmap);
208 efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
209 efi_desc_size = ia64_boot_param->efi_memdesc_size;
211 for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
212 md = p;
213 if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT))
214 return md;
215 }
216 return 0;
217 }
219 static int
220 is_xenheap_usable_memory(efi_memory_desc_t *md)
221 {
222 if (!(md->attribute & EFI_MEMORY_WB))
223 return 0;
225 switch (md->type) {
226 case EFI_LOADER_CODE:
227 case EFI_LOADER_DATA:
228 case EFI_BOOT_SERVICES_CODE:
229 case EFI_BOOT_SERVICES_DATA:
230 case EFI_CONVENTIONAL_MEMORY:
231 return 1;
232 }
233 return 0;
234 }
236 static inline int
237 md_overlaps(efi_memory_desc_t *md, unsigned long phys_addr)
238 {
239 return (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT));
240 }
242 #define MD_SIZE(md) (md->num_pages << EFI_PAGE_SHIFT)
244 void start_kernel(void)
245 {
246 char *cmdline;
247 unsigned long nr_pages;
248 unsigned long dom0_memory_start, dom0_memory_size;
249 unsigned long dom0_initrd_start, dom0_initrd_size;
250 unsigned long md_end, relo_start, relo_end, relo_size = 0;
251 struct domain *idle_domain;
252 efi_memory_desc_t *kern_md, *last_md, *md;
253 #ifdef CONFIG_SMP
254 int i;
255 #endif
257 /* Be sure the struct shared_info size is <= XSI_SIZE. */
258 BUILD_BUG_ON(sizeof(struct shared_info) > XSI_SIZE);
260 running_on_sim = is_platform_hp_ski();
261 /* Kernel may be relocated by EFI loader */
262 xen_pstart = ia64_tpa(KERNEL_START);
264 early_setup_arch(&cmdline);
266 /* We initialise the serial devices very early so we can get debugging. */
267 if (running_on_sim) hpsim_serial_init();
268 else {
269 ns16550_init(0, &ns16550_com1);
270 /* Also init com2 for Tiger4. */
271 ns16550_com2.io_base = 0x2f8;
272 ns16550_com2.irq = 3;
273 ns16550_init(1, &ns16550_com2);
274 }
275 serial_init_preirq();
277 init_console();
278 set_printk_prefix("(XEN) ");
280 if (running_on_sim || ia64_boot_param->domain_start == 0 ||
281 ia64_boot_param->domain_size == 0) {
282 /* This is possible only with the old elilo, which does not support
283 a vmm. Fix now, and continue without initrd. */
284 printk ("Your elilo is not Xen-aware. Bootparams fixed\n");
285 ia64_boot_param->domain_start = ia64_boot_param->initrd_start;
286 ia64_boot_param->domain_size = ia64_boot_param->initrd_size;
287 ia64_boot_param->initrd_start = 0;
288 ia64_boot_param->initrd_size = 0;
289 }
291 printk("Xen command line: %s\n", saved_command_line);
292 /* xenheap should be in same TR-covered range with xen image */
293 xenheap_phys_end = xen_pstart + xenheap_size;
294 printk("xen image pstart: 0x%lx, xenheap pend: 0x%lx\n",
295 xen_pstart, xenheap_phys_end);
297 xen_patch_kernel();
299 kern_md = md = efi_get_md(xen_pstart);
300 md_end = __pa(ia64_imva(&_end));
301 relo_start = xenheap_phys_end;
303 /*
304 * Scan through the memory descriptors after the kernel
305 * image to make sure we have enough room for the xenheap
306 * area, pushing out whatever may already be there.
307 */
308 while (relo_start + relo_size >= md_end) {
309 md = efi_get_md(md_end);
311 BUG_ON(!md);
312 BUG_ON(!is_xenheap_usable_memory(md));
314 md_end = md->phys_addr + MD_SIZE(md);
315 /*
316 * The dom0 kernel or initrd could overlap, reserve space
317 * at the end to relocate them later.
318 */
319 if (md->type == EFI_LOADER_DATA) {
320 /* Test for ranges we're not prepared to move */
321 BUG_ON(md_overlaps(md, __pa(ia64_boot_param)) ||
322 md_overlaps(md, ia64_boot_param->efi_memmap) ||
323 md_overlaps(md, ia64_boot_param->command_line));
325 relo_size += MD_SIZE(md);
326 /* If range overlaps the end, push out the relocation start */
327 if (md_end > relo_start)
328 relo_start = md_end;
329 }
330 }
331 last_md = md;
332 relo_end = relo_start + relo_size;
334 md_end = __pa(ia64_imva(&_end));
336 /*
337 * Move any relocated data out into the previously found relocation
338 * area. Any extra memory descriptrs are moved out to the end
339 * and set to zero pages.
340 */
341 for (md = efi_get_md(md_end) ;; md = efi_get_md(md_end)) {
342 md_end = md->phys_addr + MD_SIZE(md);
344 if (md->type == EFI_LOADER_DATA) {
345 unsigned long relo_offset;
347 if (md_overlaps(md, ia64_boot_param->domain_start)) {
348 relo_offset = ia64_boot_param->domain_start - md->phys_addr;
349 printk("Moving Dom0 kernel image: 0x%lx -> 0x%lx (%ld KiB)\n",
350 ia64_boot_param->domain_start, relo_start + relo_offset,
351 ia64_boot_param->domain_size >> 10);
352 ia64_boot_param->domain_start = relo_start + relo_offset;
353 }
354 if (ia64_boot_param->initrd_size &&
355 md_overlaps(md, ia64_boot_param->initrd_start)) {
356 relo_offset = ia64_boot_param->initrd_start - md->phys_addr;
357 printk("Moving Dom0 initrd image: 0x%lx -> 0x%lx (%ld KiB)\n",
358 ia64_boot_param->initrd_start, relo_start + relo_offset,
359 ia64_boot_param->initrd_size >> 10);
360 ia64_boot_param->initrd_start = relo_start + relo_offset;
361 }
362 memcpy(__va(relo_start), __va(md->phys_addr), MD_SIZE(md));
363 relo_start += MD_SIZE(md);
364 }
366 if (md == kern_md)
367 continue;
368 if (md == last_md)
369 break;
371 md->phys_addr = relo_end;
372 md->num_pages = 0;
373 }
375 /* Trim the last entry */
376 md->phys_addr = relo_end;
377 md->num_pages = (md_end - relo_end) >> EFI_PAGE_SHIFT;
379 /*
380 * Expand the new kernel/xenheap (and maybe dom0/initrd) out to
381 * the full size. This range will already be type EFI_LOADER_DATA,
382 * therefore the xenheap area is now protected being allocated for
383 * use by find_memmap_space() in efi.c
384 */
385 kern_md->num_pages = (relo_end - kern_md->phys_addr) >> EFI_PAGE_SHIFT;
387 reserve_memory();
389 /* first find highest page frame number */
390 max_page = 0;
391 efi_memmap_walk(find_max_pfn, &max_page);
392 printf("find_memory: efi_memmap_walk returns max_page=%lx\n",max_page);
393 efi_print();
395 xen_heap_start = memguard_init(ia64_imva(&_end));
396 printf("Before xen_heap_start: %p\n", xen_heap_start);
397 xen_heap_start = __va(init_boot_allocator(__pa(xen_heap_start)));
398 printf("After xen_heap_start: %p\n", xen_heap_start);
400 efi_memmap_walk(filter_rsvd_memory, init_boot_pages);
401 efi_memmap_walk(xen_count_pages, &nr_pages);
403 printk("System RAM: %luMB (%lukB)\n",
404 nr_pages >> (20 - PAGE_SHIFT),
405 nr_pages << (PAGE_SHIFT - 10));
406 total_pages = nr_pages;
408 init_frametable();
410 trap_init();
412 alloc_dom0();
414 end_boot_allocator();
416 init_xenheap_pages(__pa(xen_heap_start), xenheap_phys_end);
417 printk("Xen heap: %luMB (%lukB)\n",
418 (xenheap_phys_end-__pa(xen_heap_start)) >> 20,
419 (xenheap_phys_end-__pa(xen_heap_start)) >> 10);
421 late_setup_arch(&cmdline);
423 scheduler_init();
424 idle_vcpu[0] = (struct vcpu*) ia64_r13;
425 idle_domain = domain_create(IDLE_DOMAIN_ID);
426 if ( (idle_domain == NULL) || (alloc_vcpu(idle_domain, 0, 0) == NULL) )
427 BUG();
429 alloc_dom_xen_and_dom_io();
430 setup_per_cpu_areas();
431 mem_init();
433 local_irq_disable();
434 init_IRQ ();
435 init_xen_time(); /* initialise the time */
436 timer_init();
438 #ifdef CONFIG_SMP
439 if ( opt_nosmp )
440 {
441 max_cpus = 0;
442 smp_num_siblings = 1;
443 //boot_cpu_data.x86_num_cores = 1;
444 }
446 /* A vcpu is created for the idle domain on every physical cpu.
447 Limit the number of cpus to the maximum number of vcpus. */
448 if (max_cpus > MAX_VIRT_CPUS)
449 max_cpus = MAX_VIRT_CPUS;
451 smp_prepare_cpus(max_cpus);
453 /* We aren't hotplug-capable yet. */
454 for_each_cpu ( i )
455 cpu_set(i, cpu_present_map);
457 /* Enable IRQ to receive IPI (needed for ITC sync). */
458 local_irq_enable();
460 printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus);
461 for_each_present_cpu ( i )
462 {
463 if ( num_online_cpus() >= max_cpus )
464 break;
465 if ( !cpu_online(i) ) {
466 __cpu_up(i);
467 }
468 }
470 local_irq_disable();
472 printk("Brought up %ld CPUs\n", (long)num_online_cpus());
473 smp_cpus_done(max_cpus);
474 #endif
476 initialise_gdb(); /* could be moved earlier */
478 do_initcalls();
479 sort_main_extable();
481 init_rid_allocator ();
483 local_irq_enable();
485 if (opt_xencons) {
486 initialize_keytable();
487 if (ns16550_com1_gsi) {
488 if (opt_xencons_poll ||
489 iosapic_register_intr(ns16550_com1_gsi,
490 ns16550_com1_polarity,
491 ns16550_com1_trigger) < 0) {
492 ns16550_com1.irq = 0;
493 ns16550_init(0, &ns16550_com1);
494 }
495 }
496 serial_init_postirq();
498 /* Hide the HCDP table from dom0 */
499 efi.hcdp = NULL;
500 }
502 expose_p2m_init();
504 /* Create initial domain 0. */
505 dom0 = domain_create(0);
506 if ( (dom0 == NULL) || (alloc_vcpu(dom0, 0, 0) == NULL) )
507 panic("Error creating domain 0\n");
509 set_bit(_DOMF_privileged, &dom0->domain_flags);
511 /*
512 * We're going to setup domain0 using the module(s) that we stashed safely
513 * above our heap. The second module, if present, is an initrd ramdisk.
514 */
515 dom0_memory_start = (unsigned long) __va(ia64_boot_param->domain_start);
516 dom0_memory_size = ia64_boot_param->domain_size;
517 dom0_initrd_start = (unsigned long) __va(ia64_boot_param->initrd_start);
518 dom0_initrd_size = ia64_boot_param->initrd_size;
520 if ( construct_dom0(dom0, dom0_memory_start, dom0_memory_size,
521 dom0_initrd_start,dom0_initrd_size,
522 0) != 0)
523 panic("Could not set up DOM0 guest OS\n");
525 if (!running_on_sim) // slow on ski and pages are pre-initialized to zero
526 scrub_heap_pages();
528 init_trace_bufs();
530 if (opt_xencons) {
531 console_endboot();
532 serial_endboot();
533 }
535 domain0_ready = 1;
537 schedulers_start();
539 domain_unpause_by_systemcontroller(dom0);
541 startup_cpu_idle_loop();
542 }
544 void arch_get_xen_caps(xen_capabilities_info_t info)
545 {
546 char *p=info;
547 int major = xen_major_version();
548 int minor = xen_minor_version();
550 p += sprintf(p,"xen-%d.%d-ia64 ", major, minor);
552 if (vmx_enabled)
553 p += sprintf(p,"hvm-%d.%d-ia64 ", major, minor);
555 *(p-1) = 0;
557 BUG_ON((p-info)>sizeof(xen_capabilities_info_t));
559 }