ia64/xen-unstable

view xen/arch/ia64/xen/xensetup.c @ 10664:3041cac985d6

[IA64] build warning fix

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