direct-io.hg

view xen/arch/ia64/xen/xensetup.c @ 10470:411a3c01bb40

[XEN] Xen always relinquishes VGA console to domain0 when domain0
starts to boot (previous behaviour looked for console=tty0 on
dom0's command line). To prevent this 'console=vga[keep]' must
be specified.
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Tue Jun 20 18:51:46 2006 +0100 (2006-06-20)
parents 11f228aa783a
children fdf25330e4a6
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/compile.h>
17 #include <xen/console.h>
18 #include <xen/serial.h>
19 #include <xen/trace.h>
20 #include <asm/meminit.h>
21 #include <asm/page.h>
22 #include <asm/setup.h>
23 #include <xen/string.h>
24 #include <asm/vmx.h>
25 #include <linux/efi.h>
27 /* Be sure the struct shared_info fits on a page because it is mapped in
28 domain. */
29 #if SHARED_INFO_SIZE > PAGE_SIZE
30 #error "struct shared_info does not not fit in PAGE_SIZE"
31 #endif
33 unsigned long xenheap_phys_end, total_pages;
35 char saved_command_line[COMMAND_LINE_SIZE];
36 char dom0_command_line[COMMAND_LINE_SIZE];
38 cpumask_t cpu_present_map;
40 extern unsigned long domain0_ready;
42 int find_max_pfn (unsigned long, unsigned long, void *);
43 void start_of_day(void);
45 /* FIXME: which header these declarations should be there ? */
46 extern long is_platform_hp_ski(void);
47 extern void early_setup_arch(char **);
48 extern void late_setup_arch(char **);
49 extern void hpsim_serial_init(void);
50 extern void alloc_dom0(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);
56 /* opt_nosmp: If true, secondary processors are ignored. */
57 static int opt_nosmp = 0;
58 boolean_param("nosmp", opt_nosmp);
60 /* maxcpus: maximum number of CPUs to activate. */
61 static unsigned int max_cpus = NR_CPUS;
62 integer_param("maxcpus", max_cpus);
64 /*
65 * opt_xenheap_megabytes: Size of Xen heap in megabytes, including:
66 * xen image
67 * bootmap bits
68 * xen heap
69 * Note: To allow xenheap size configurable, the prerequisite is
70 * to configure elilo allowing relocation defaultly. Then since
71 * elilo chooses 256M as alignment when relocating, alignment issue
72 * on IPF can be addressed.
73 */
74 unsigned int opt_xenheap_megabytes = XENHEAP_DEFAULT_MB;
75 unsigned long xenheap_size = XENHEAP_DEFAULT_SIZE;
76 extern long running_on_sim;
77 unsigned long xen_pstart;
79 static int
80 xen_count_pages(u64 start, u64 end, void *arg)
81 {
82 unsigned long *count = arg;
84 /* FIXME: do we need consider difference between DMA-usable memory and
85 * normal memory? Seems that HV has no requirement to operate DMA which
86 * is owned by Dom0? */
87 *count += (end - start) >> PAGE_SHIFT;
88 return 0;
89 }
91 static void __init do_initcalls(void)
92 {
93 initcall_t *call;
94 for ( call = &__initcall_start; call < &__initcall_end; call++ )
95 (*call)();
96 }
98 /*
99 * IPF loader only supports one commaind line currently, for
100 * both xen and guest kernel. This function provides pre-parse
101 * to mixed command line, to split it into two parts.
102 *
103 * User should split the parameters by "--", with strings after
104 * spliter for guest kernel. Missing "--" means whole line belongs
105 * to guest. Example:
106 * "com2=57600,8n1 console=com2 -- console=ttyS1 console=tty
107 * root=/dev/sda3 ro"
108 */
109 static char null[4] = { 0 };
111 void early_cmdline_parse(char **cmdline_p)
112 {
113 char *guest_cmd;
114 static const char * const split = "--";
116 if (*cmdline_p == NULL) {
117 *cmdline_p = &null[0];
118 saved_command_line[0] = '\0';
119 dom0_command_line[0] = '\0';
120 return;
121 }
123 guest_cmd = strstr(*cmdline_p, split);
124 /* If no spliter, whole line is for guest */
125 if (guest_cmd == NULL) {
126 guest_cmd = *cmdline_p;
127 *cmdline_p = &null[0];
128 } else {
129 *guest_cmd = '\0'; /* Split boot parameters for xen and guest */
130 guest_cmd += strlen(split);
131 while (*guest_cmd == ' ') guest_cmd++;
132 }
134 strlcpy(saved_command_line, *cmdline_p, COMMAND_LINE_SIZE);
135 strlcpy(dom0_command_line, guest_cmd, COMMAND_LINE_SIZE);
136 return;
137 }
139 struct ns16550_defaults ns16550_com1 = {
140 .baud = BAUD_AUTO,
141 .data_bits = 8,
142 .parity = 'n',
143 .stop_bits = 1
144 };
146 struct ns16550_defaults ns16550_com2 = {
147 .baud = BAUD_AUTO,
148 .data_bits = 8,
149 .parity = 'n',
150 .stop_bits = 1
151 };
153 /* efi_print: print efi table at boot */
154 static int opt_efi_print = 0;
155 boolean_param("efi_print", opt_efi_print);
157 /* print EFI memory map: */
158 static void
159 efi_print(void)
160 {
161 void *efi_map_start, *efi_map_end;
162 u64 efi_desc_size;
164 efi_memory_desc_t *md;
165 void *p;
166 int i;
168 if (!opt_efi_print)
169 return;
171 efi_map_start = __va(ia64_boot_param->efi_memmap);
172 efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
173 efi_desc_size = ia64_boot_param->efi_memdesc_size;
175 for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) {
176 md = p;
177 printk("mem%02u: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)\n",
178 i, md->type, md->attribute, md->phys_addr,
179 md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
180 md->num_pages >> (20 - EFI_PAGE_SHIFT));
181 }
182 }
184 /*
185 * These functions are utility functions for getting and
186 * testing memory descriptors for allocating the xenheap area.
187 */
188 static efi_memory_desc_t *
189 efi_get_md (unsigned long phys_addr)
190 {
191 void *efi_map_start, *efi_map_end, *p;
192 efi_memory_desc_t *md;
193 u64 efi_desc_size;
195 efi_map_start = __va(ia64_boot_param->efi_memmap);
196 efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
197 efi_desc_size = ia64_boot_param->efi_memdesc_size;
199 for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
200 md = p;
201 if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT))
202 return md;
203 }
204 return 0;
205 }
207 static int
208 is_xenheap_usable_memory(efi_memory_desc_t *md)
209 {
210 if (!(md->attribute & EFI_MEMORY_WB))
211 return 0;
213 switch (md->type) {
214 case EFI_LOADER_CODE:
215 case EFI_LOADER_DATA:
216 case EFI_BOOT_SERVICES_CODE:
217 case EFI_BOOT_SERVICES_DATA:
218 case EFI_CONVENTIONAL_MEMORY:
219 return 1;
220 }
221 return 0;
222 }
224 static inline int
225 md_overlaps(efi_memory_desc_t *md, unsigned long phys_addr)
226 {
227 return (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT));
228 }
230 #define MD_SIZE(md) (md->num_pages << EFI_PAGE_SHIFT)
232 void start_kernel(void)
233 {
234 unsigned char *cmdline;
235 void *heap_start;
236 unsigned long nr_pages;
237 unsigned long dom0_memory_start, dom0_memory_size;
238 unsigned long dom0_initrd_start, dom0_initrd_size;
239 unsigned long md_end, relo_start, relo_end, relo_size = 0;
240 struct domain *idle_domain;
241 efi_memory_desc_t *kern_md, *last_md, *md;
242 #ifdef CONFIG_SMP
243 int i;
244 #endif
246 running_on_sim = is_platform_hp_ski();
247 /* Kernel may be relocated by EFI loader */
248 xen_pstart = ia64_tpa(KERNEL_START);
250 early_setup_arch((char **) &cmdline);
252 /* We initialise the serial devices very early so we can get debugging. */
253 if (running_on_sim) hpsim_serial_init();
254 else {
255 ns16550_init(0, &ns16550_com1);
256 /* Also init com2 for Tiger4. */
257 ns16550_com2.io_base = 0x2f8;
258 ns16550_com2.irq = 3;
259 ns16550_init(1, &ns16550_com2);
260 }
261 serial_init_preirq();
263 init_console();
264 set_printk_prefix("(XEN) ");
266 if (running_on_sim || ia64_boot_param->domain_start == 0 ||
267 ia64_boot_param->domain_size == 0) {
268 /* This is possible only with the old elilo, which does not support
269 a vmm. Fix now, and continue without initrd. */
270 printk ("Your elilo is not Xen-aware. Bootparams fixed\n");
271 ia64_boot_param->domain_start = ia64_boot_param->initrd_start;
272 ia64_boot_param->domain_size = ia64_boot_param->initrd_size;
273 ia64_boot_param->initrd_start = 0;
274 ia64_boot_param->initrd_size = 0;
275 }
277 /* xenheap should be in same TR-covered range with xen image */
278 xenheap_phys_end = xen_pstart + xenheap_size;
279 printk("xen image pstart: 0x%lx, xenheap pend: 0x%lx\n",
280 xen_pstart, xenheap_phys_end);
282 kern_md = md = efi_get_md(xen_pstart);
283 md_end = __pa(ia64_imva(&_end));
284 relo_start = xenheap_phys_end;
286 /*
287 * Scan through the memory descriptors after the kernel
288 * image to make sure we have enough room for the xenheap
289 * area, pushing out whatever may already be there.
290 */
291 while (relo_start + relo_size >= md_end) {
292 md = efi_get_md(md_end);
294 BUG_ON(!md);
295 BUG_ON(!is_xenheap_usable_memory(md));
297 md_end = md->phys_addr + MD_SIZE(md);
298 /*
299 * The dom0 kernel or initrd could overlap, reserve space
300 * at the end to relocate them later.
301 */
302 if (md->type == EFI_LOADER_DATA) {
303 /* Test for ranges we're not prepared to move */
304 BUG_ON(md_overlaps(md, __pa(ia64_boot_param)) ||
305 md_overlaps(md, ia64_boot_param->efi_memmap) ||
306 md_overlaps(md, ia64_boot_param->command_line));
308 relo_size += MD_SIZE(md);
309 /* If range overlaps the end, push out the relocation start */
310 if (md_end > relo_start)
311 relo_start = md_end;
312 }
313 }
314 last_md = md;
315 relo_end = relo_start + relo_size;
317 md_end = __pa(ia64_imva(&_end));
319 /*
320 * Move any relocated data out into the previously found relocation
321 * area. Any extra memory descriptrs are moved out to the end
322 * and set to zero pages.
323 */
324 for (md = efi_get_md(md_end) ;; md = efi_get_md(md_end)) {
325 md_end = md->phys_addr + MD_SIZE(md);
327 if (md->type == EFI_LOADER_DATA) {
328 unsigned long relo_offset;
330 if (md_overlaps(md, ia64_boot_param->domain_start)) {
331 relo_offset = ia64_boot_param->domain_start - md->phys_addr;
332 printk("Moving Dom0 kernel image: 0x%lx -> 0x%lx (%ld KiB)\n",
333 ia64_boot_param->domain_start, relo_start + relo_offset,
334 ia64_boot_param->domain_size >> 10);
335 ia64_boot_param->domain_start = relo_start + relo_offset;
336 }
337 if (ia64_boot_param->initrd_size &&
338 md_overlaps(md, ia64_boot_param->initrd_start)) {
339 relo_offset = ia64_boot_param->initrd_start - md->phys_addr;
340 printk("Moving Dom0 initrd image: 0x%lx -> 0x%lx (%ld KiB)\n",
341 ia64_boot_param->initrd_start, relo_start + relo_offset,
342 ia64_boot_param->initrd_size >> 10);
343 ia64_boot_param->initrd_start = relo_start + relo_offset;
344 }
345 memcpy(__va(relo_start), __va(md->phys_addr), MD_SIZE(md));
346 relo_start += MD_SIZE(md);
347 }
349 if (md == kern_md)
350 continue;
351 if (md == last_md)
352 break;
354 md->phys_addr = relo_end;
355 md->num_pages = 0;
356 }
358 /* Trim the last entry */
359 md->phys_addr = relo_end;
360 md->num_pages = (md_end - relo_end) >> EFI_PAGE_SHIFT;
362 /*
363 * Expand the new kernel/xenheap (and maybe dom0/initrd) out to
364 * the full size. This range will already be type EFI_LOADER_DATA,
365 * therefore the xenheap area is now protected being allocated for
366 * use by find_memmap_space() in efi.c
367 */
368 kern_md->num_pages = (relo_end - kern_md->phys_addr) >> EFI_PAGE_SHIFT;
370 reserve_memory();
372 /* first find highest page frame number */
373 max_page = 0;
374 efi_memmap_walk(find_max_pfn, &max_page);
375 printf("find_memory: efi_memmap_walk returns max_page=%lx\n",max_page);
376 #ifndef CONFIG_XEN_IA64_DOM0_VP
377 /* this is a bad hack. see dom_fw.c creation of EFI map for dom0 */
378 max_page = (GRANULEROUNDDOWN(max_page << PAGE_SHIFT)
379 - IA64_GRANULE_SIZE) >> PAGE_SHIFT;
380 printf("find_memory: last granule reserved for dom0; xen max_page=%lx\n",
381 max_page);
382 #endif
383 efi_print();
385 heap_start = memguard_init(ia64_imva(&_end));
386 printf("Before heap_start: %p\n", heap_start);
387 heap_start = __va(init_boot_allocator(__pa(heap_start)));
388 printf("After heap_start: %p\n", heap_start);
390 efi_memmap_walk(filter_rsvd_memory, init_boot_pages);
391 efi_memmap_walk(xen_count_pages, &nr_pages);
393 printk("System RAM: %luMB (%lukB)\n",
394 nr_pages >> (20 - PAGE_SHIFT),
395 nr_pages << (PAGE_SHIFT - 10));
396 total_pages = nr_pages;
398 init_frametable();
400 trap_init();
402 alloc_dom0();
404 end_boot_allocator();
406 init_xenheap_pages(__pa(heap_start), xenheap_phys_end);
407 printk("Xen heap: %luMB (%lukB)\n",
408 (xenheap_phys_end-__pa(heap_start)) >> 20,
409 (xenheap_phys_end-__pa(heap_start)) >> 10);
411 printk("About to call scheduler_init()\n");
412 scheduler_init();
413 idle_vcpu[0] = (struct vcpu*) ia64_r13;
414 idle_domain = domain_create(IDLE_DOMAIN_ID, 0);
415 BUG_ON(idle_domain == NULL);
417 late_setup_arch((char **) &cmdline);
418 alloc_dom_xen_and_dom_io();
419 setup_per_cpu_areas();
420 mem_init();
422 local_irq_disable();
423 init_IRQ ();
424 printk("About to call init_xen_time()\n");
425 init_xen_time(); /* initialise the time */
426 printk("About to call timer_init()\n");
427 timer_init();
429 #ifdef CONFIG_XEN_CONSOLE_INPUT /* CONFIG_SERIAL_8250_CONSOLE=n in dom0! */
430 initialize_keytable();
431 serial_init_postirq();
432 #endif
434 #ifdef CONFIG_SMP
435 if ( opt_nosmp )
436 {
437 max_cpus = 0;
438 smp_num_siblings = 1;
439 //boot_cpu_data.x86_num_cores = 1;
440 }
442 /* A vcpu is created for the idle domain on every physical cpu.
443 Limit the number of cpus to the maximum number of vcpus. */
444 if (max_cpus > MAX_VIRT_CPUS)
445 max_cpus = MAX_VIRT_CPUS;
447 smp_prepare_cpus(max_cpus);
449 /* We aren't hotplug-capable yet. */
450 for_each_cpu ( i )
451 cpu_set(i, cpu_present_map);
453 /* Enable IRQ to receive IPI (needed for ITC sync). */
454 local_irq_enable();
456 printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus);
457 for_each_present_cpu ( i )
458 {
459 if ( num_online_cpus() >= max_cpus )
460 break;
461 if ( !cpu_online(i) ) {
462 __cpu_up(i);
463 }
464 }
466 local_irq_disable();
468 printk("Brought up %ld CPUs\n", (long)num_online_cpus());
469 smp_cpus_done(max_cpus);
470 #endif
472 initialise_gdb(); /* could be moved earlier */
474 do_initcalls();
475 printk("About to call sort_main_extable()\n");
476 sort_main_extable();
479 init_rid_allocator ();
481 /* Create initial domain 0. */
482 printk("About to call domain_create()\n");
483 dom0 = domain_create(0, 0);
485 if ( dom0 == NULL )
486 panic("Error creating domain 0\n");
488 set_bit(_DOMF_privileged, &dom0->domain_flags);
490 /*
491 * We're going to setup domain0 using the module(s) that we stashed safely
492 * above our heap. The second module, if present, is an initrd ramdisk.
493 */
494 printk("About to call construct_dom0()\n");
495 dom0_memory_start = (unsigned long) __va(ia64_boot_param->domain_start);
496 dom0_memory_size = ia64_boot_param->domain_size;
497 dom0_initrd_start = (unsigned long) __va(ia64_boot_param->initrd_start);
498 dom0_initrd_size = ia64_boot_param->initrd_size;
500 if ( construct_dom0(dom0, dom0_memory_start, dom0_memory_size,
501 dom0_initrd_start,dom0_initrd_size,
502 0) != 0)
503 panic("Could not set up DOM0 guest OS\n");
505 /* PIN domain0 on CPU 0. */
506 dom0->vcpu[0]->cpu_affinity = cpumask_of_cpu(0);
508 if (!running_on_sim) // slow on ski and pages are pre-initialized to zero
509 scrub_heap_pages();
511 printk("About to call init_trace_bufs()\n");
512 init_trace_bufs();
514 #ifdef CONFIG_XEN_CONSOLE_INPUT /* CONFIG_SERIAL_8250_CONSOLE=n in dom0! */
515 console_endboot();
516 #endif
518 domain0_ready = 1;
520 local_irq_enable();
522 printf("About to call schedulers_start dom0=%p, idle_dom=%p\n",
523 dom0, idle_domain);
524 schedulers_start();
526 domain_unpause_by_systemcontroller(dom0);
528 printk("About to call startup_cpu_idle_loop()\n");
529 startup_cpu_idle_loop();
530 }
532 void arch_get_xen_caps(xen_capabilities_info_t info)
533 {
534 char *p=info;
536 p += sprintf(p,"xen-%d.%d-ia64 ", XEN_VERSION, XEN_SUBVERSION);
538 if (vmx_enabled)
539 p += sprintf(p,"hvm-%d.%d-ia64 ", XEN_VERSION, XEN_SUBVERSION);
541 *(p-1) = 0;
543 BUG_ON((p-info)>sizeof(xen_capabilities_info_t));
545 }