ia64/xen-unstable

view xen/arch/ia64/xen/xensetup.c @ 15131:26492c6476f0

[IA64] free initmem and add __init and __initdata.

ia64 counter part of xen-unstable.hg 15043:759d924af6d8.
By freeing init area, un/pickle_domain() is broken because
__init_begin < xen_heap_start. This is fixed by introducing xen_pickle_offset.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Alex Williamson <alex.williamson@hp.com>
date Wed May 23 08:51:42 2007 -0600 (2007-05-23)
parents aeac9a7d97e0
children 90f19b7667f7
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>
29 #include <xen/softirq.h>
30 #include <xen/rcupdate.h>
31 #include <acm/acm_hooks.h>
33 unsigned long xenheap_phys_end, total_pages;
35 char saved_command_line[COMMAND_LINE_SIZE];
36 char __initdata 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 *);
44 /* FIXME: which header these declarations should be there ? */
45 extern long is_platform_hp_ski(void);
46 extern void early_setup_arch(char **);
47 extern void late_setup_arch(char **);
48 extern void hpsim_serial_init(void);
49 extern void alloc_dom0(void);
50 extern void setup_per_cpu_areas(void);
51 extern void mem_init(void);
52 extern void init_IRQ(void);
53 extern void trap_init(void);
54 extern void xen_patch_kernel(void);
56 /* opt_nosmp: If true, secondary processors are ignored. */
57 static int opt_nosmp;
58 boolean_param("nosmp", opt_nosmp);
60 /* maxcpus: maximum number of CPUs to activate. */
61 static unsigned int __initdata max_cpus = NR_CPUS;
62 integer_param("maxcpus", max_cpus);
64 /* xencons: if true enable xenconsole input (and irq).
65 Note: you have to disable 8250 serials in domains (to avoid use of the
66 same resource). */
67 static int __initdata opt_xencons = 1;
68 integer_param("xencons", opt_xencons);
70 /* Toggle to allow non-legacy xencons UARTs to run in polling mode */
71 static int __initdata opt_xencons_poll;
72 boolean_param("xencons_poll", opt_xencons_poll);
74 /*
75 * opt_xenheap_megabytes: Size of Xen heap in megabytes, including:
76 * xen image
77 * bootmap bits
78 * xen heap
79 * Note: To allow xenheap size configurable, the prerequisite is
80 * to configure elilo allowing relocation defaultly. Then since
81 * elilo chooses 256M as alignment when relocating, alignment issue
82 * on IPF can be addressed.
83 */
84 unsigned int opt_xenheap_megabytes = XENHEAP_DEFAULT_MB;
85 unsigned long xenheap_size = XENHEAP_DEFAULT_SIZE;
86 extern long running_on_sim;
87 unsigned long xen_pstart;
88 void *xen_pickle_offset __read_mostly;
90 static int __init
91 xen_count_pages(u64 start, u64 end, void *arg)
92 {
93 unsigned long *count = arg;
95 /* FIXME: do we need consider difference between DMA-usable memory and
96 * normal memory? Seems that HV has no requirement to operate DMA which
97 * is owned by Dom0? */
98 *count += (end - start) >> PAGE_SHIFT;
99 return 0;
100 }
102 static void __init do_initcalls(void)
103 {
104 initcall_t *call;
105 for ( call = &__initcall_start; call < &__initcall_end; call++ )
106 (*call)();
107 }
109 /*
110 * IPF loader only supports one commaind line currently, for
111 * both xen and guest kernel. This function provides pre-parse
112 * to mixed command line, to split it into two parts.
113 *
114 * User should split the parameters by "--", with strings after
115 * spliter for guest kernel. Missing "--" means whole line belongs
116 * to guest. Example:
117 * "com2=57600,8n1 console=com2 -- console=ttyS1 console=tty
118 * root=/dev/sda3 ro"
119 */
120 static char null[4] = { 0 };
122 void __init early_cmdline_parse(char **cmdline_p)
123 {
124 char *guest_cmd;
125 static const char * const split = "--";
127 if (*cmdline_p == NULL) {
128 *cmdline_p = &null[0];
129 saved_command_line[0] = '\0';
130 dom0_command_line[0] = '\0';
131 return;
132 }
134 guest_cmd = strstr(*cmdline_p, split);
135 /* If no spliter, whole line is for guest */
136 if (guest_cmd == NULL) {
137 guest_cmd = *cmdline_p;
138 *cmdline_p = &null[0];
139 } else {
140 *guest_cmd = '\0'; /* Split boot parameters for xen and guest */
141 guest_cmd += strlen(split);
142 while (*guest_cmd == ' ') guest_cmd++;
143 }
145 strlcpy(saved_command_line, *cmdline_p, COMMAND_LINE_SIZE);
146 strlcpy(dom0_command_line, guest_cmd, COMMAND_LINE_SIZE);
147 return;
148 }
150 struct ns16550_defaults ns16550_com1 = {
151 .data_bits = 8,
152 .parity = 'n',
153 .stop_bits = 1
154 };
156 unsigned int ns16550_com1_gsi;
157 unsigned int ns16550_com1_polarity;
158 unsigned int ns16550_com1_trigger;
160 struct ns16550_defaults ns16550_com2 = {
161 .data_bits = 8,
162 .parity = 'n',
163 .stop_bits = 1
164 };
166 /* efi_print: print efi table at boot */
167 static int __initdata opt_efi_print;
168 boolean_param("efi_print", opt_efi_print);
170 /* print EFI memory map: */
171 static void __init
172 efi_print(void)
173 {
174 void *efi_map_start, *efi_map_end;
175 u64 efi_desc_size;
177 efi_memory_desc_t *md;
178 void *p;
179 int i;
181 if (!opt_efi_print)
182 return;
184 efi_map_start = __va(ia64_boot_param->efi_memmap);
185 efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
186 efi_desc_size = ia64_boot_param->efi_memdesc_size;
188 for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) {
189 md = p;
190 printk("mem%02u: type=%2u, attr=0x%016lx, range=[0x%016lx-0x%016lx) "
191 "(%luMB)\n", i, md->type, md->attribute, md->phys_addr,
192 md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
193 md->num_pages >> (20 - EFI_PAGE_SHIFT));
194 }
195 }
197 /*
198 * These functions are utility functions for getting and
199 * testing memory descriptors for allocating the xenheap area.
200 */
201 static efi_memory_desc_t *
202 efi_get_md (unsigned long phys_addr)
203 {
204 void *efi_map_start, *efi_map_end, *p;
205 efi_memory_desc_t *md;
206 u64 efi_desc_size;
208 efi_map_start = __va(ia64_boot_param->efi_memmap);
209 efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
210 efi_desc_size = ia64_boot_param->efi_memdesc_size;
212 for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
213 md = p;
214 if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT))
215 return md;
216 }
217 return 0;
218 }
220 static int
221 is_xenheap_usable_memory(efi_memory_desc_t *md)
222 {
223 if (!(md->attribute & EFI_MEMORY_WB))
224 return 0;
226 switch (md->type) {
227 case EFI_LOADER_CODE:
228 case EFI_LOADER_DATA:
229 case EFI_BOOT_SERVICES_CODE:
230 case EFI_BOOT_SERVICES_DATA:
231 case EFI_CONVENTIONAL_MEMORY:
232 return 1;
233 }
234 return 0;
235 }
237 static inline int
238 md_overlaps(efi_memory_desc_t *md, unsigned long phys_addr)
239 {
240 return (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT));
241 }
243 #define MD_SIZE(md) (md->num_pages << EFI_PAGE_SHIFT)
245 extern char __init_begin[], __init_end[];
246 static void noinline init_done(void)
247 {
248 memset(__init_begin, 0, __init_end - __init_begin);
249 flush_icache_range((unsigned long)__init_begin, (unsigned long)__init_end);
250 init_xenheap_pages(__pa(__init_begin), __pa(__init_end));
251 printk("Freed %ldkB init memory.\n",
252 (long)(__init_end-__init_begin)>>10);
254 startup_cpu_idle_loop();
255 }
257 void __init start_kernel(void)
258 {
259 char *cmdline;
260 unsigned long nr_pages;
261 unsigned long dom0_memory_start, dom0_memory_size;
262 unsigned long dom0_initrd_start, dom0_initrd_size;
263 unsigned long md_end, relo_start, relo_end, relo_size = 0;
264 struct domain *idle_domain;
265 struct vcpu *dom0_vcpu0;
266 efi_memory_desc_t *kern_md, *last_md, *md;
267 void *xen_heap_start;
268 #ifdef CONFIG_SMP
269 int i;
270 #endif
272 /* Be sure the struct shared_info size is <= XSI_SIZE. */
273 BUILD_BUG_ON(sizeof(struct shared_info) > XSI_SIZE);
275 running_on_sim = is_platform_hp_ski();
276 /* Kernel may be relocated by EFI loader */
277 xen_pstart = ia64_tpa(KERNEL_START);
279 early_setup_arch(&cmdline);
281 /* We initialise the serial devices very early so we can get debugging. */
282 if (running_on_sim)
283 hpsim_serial_init();
284 else {
285 ns16550_init(0, &ns16550_com1);
286 ns16550_init(1, &ns16550_com2);
287 }
288 serial_init_preirq();
290 init_console();
291 set_printk_prefix("(XEN) ");
293 if (running_on_sim || ia64_boot_param->domain_start == 0 ||
294 ia64_boot_param->domain_size == 0) {
295 /* This is possible only with the old elilo, which does not support
296 a vmm. Fix now, and continue without initrd. */
297 printk ("Your elilo is not Xen-aware. Bootparams fixed\n");
298 ia64_boot_param->domain_start = ia64_boot_param->initrd_start;
299 ia64_boot_param->domain_size = ia64_boot_param->initrd_size;
300 ia64_boot_param->initrd_start = 0;
301 ia64_boot_param->initrd_size = 0;
302 }
304 printk("Xen command line: %s\n", saved_command_line);
305 /* xenheap should be in same TR-covered range with xen image */
306 xenheap_phys_end = xen_pstart + xenheap_size;
307 printk("xen image pstart: 0x%lx, xenheap pend: 0x%lx\n",
308 xen_pstart, xenheap_phys_end);
310 xen_patch_kernel();
312 kern_md = md = efi_get_md(xen_pstart);
313 md_end = __pa(ia64_imva(&_end));
314 relo_start = xenheap_phys_end;
316 /*
317 * Scan through the memory descriptors after the kernel
318 * image to make sure we have enough room for the xenheap
319 * area, pushing out whatever may already be there.
320 */
321 while (relo_start + relo_size >= md_end) {
322 md = efi_get_md(md_end);
324 BUG_ON(!md);
325 BUG_ON(!is_xenheap_usable_memory(md));
327 md_end = md->phys_addr + MD_SIZE(md);
328 /*
329 * The dom0 kernel or initrd could overlap, reserve space
330 * at the end to relocate them later.
331 */
332 if (md->type == EFI_LOADER_DATA) {
333 /* Test for ranges we're not prepared to move */
334 BUG_ON(md_overlaps(md, __pa(ia64_boot_param)) ||
335 md_overlaps(md, ia64_boot_param->efi_memmap) ||
336 md_overlaps(md, ia64_boot_param->command_line));
338 relo_size += MD_SIZE(md);
339 /* If range overlaps the end, push out the relocation start */
340 if (md_end > relo_start)
341 relo_start = md_end;
342 }
343 }
344 last_md = md;
345 relo_end = relo_start + relo_size;
347 md_end = __pa(ia64_imva(&_end));
349 /*
350 * Move any relocated data out into the previously found relocation
351 * area. Any extra memory descriptrs are moved out to the end
352 * and set to zero pages.
353 */
354 for (md = efi_get_md(md_end) ;; md = efi_get_md(md_end)) {
355 md_end = md->phys_addr + MD_SIZE(md);
357 if (md->type == EFI_LOADER_DATA) {
358 unsigned long relo_offset;
360 if (md_overlaps(md, ia64_boot_param->domain_start)) {
361 relo_offset = ia64_boot_param->domain_start - md->phys_addr;
362 printk("Moving Dom0 kernel image: 0x%lx -> 0x%lx (%ld KiB)\n",
363 ia64_boot_param->domain_start, relo_start + relo_offset,
364 ia64_boot_param->domain_size >> 10);
365 ia64_boot_param->domain_start = relo_start + relo_offset;
366 }
367 if (ia64_boot_param->initrd_size &&
368 md_overlaps(md, ia64_boot_param->initrd_start)) {
369 relo_offset = ia64_boot_param->initrd_start - md->phys_addr;
370 printk("Moving Dom0 initrd image: 0x%lx -> 0x%lx (%ld KiB)\n",
371 ia64_boot_param->initrd_start, relo_start + relo_offset,
372 ia64_boot_param->initrd_size >> 10);
373 ia64_boot_param->initrd_start = relo_start + relo_offset;
374 }
375 memcpy(__va(relo_start), __va(md->phys_addr), MD_SIZE(md));
376 relo_start += MD_SIZE(md);
377 }
379 if (md == kern_md)
380 continue;
381 if (md == last_md)
382 break;
384 md->phys_addr = relo_end;
385 md->num_pages = 0;
386 }
388 /* Trim the last entry */
389 md->phys_addr = relo_end;
390 md->num_pages = (md_end - relo_end) >> EFI_PAGE_SHIFT;
392 /*
393 * Expand the new kernel/xenheap (and maybe dom0/initrd) out to
394 * the full size. This range will already be type EFI_LOADER_DATA,
395 * therefore the xenheap area is now protected being allocated for
396 * use by find_memmap_space() in efi.c
397 */
398 kern_md->num_pages = (relo_end - kern_md->phys_addr) >> EFI_PAGE_SHIFT;
400 reserve_memory();
402 /* first find highest page frame number */
403 max_page = 0;
404 efi_memmap_walk(find_max_pfn, &max_page);
405 printk("find_memory: efi_memmap_walk returns max_page=%lx\n",max_page);
406 efi_print();
408 /*
409 * later [__init_begin, __init_end) will be freed up as xen heap
410 * so that struct domain might be allocated from the init area
411 * which is < xen_heap_start. so we can't simply set
412 * xen_pickle_offset = xen_heap_start.
413 */
414 xen_pickle_offset = ia64_imva(__init_begin);
416 xen_heap_start = memguard_init(ia64_imva(&_end));
417 printk("Before xen_heap_start: %p\n", xen_heap_start);
418 xen_heap_start = __va(init_boot_allocator(__pa(xen_heap_start)));
419 printk("After xen_heap_start: %p\n", xen_heap_start);
421 efi_memmap_walk(filter_rsvd_memory, init_boot_pages);
422 efi_memmap_walk(xen_count_pages, &nr_pages);
424 printk("System RAM: %luMB (%lukB)\n",
425 nr_pages >> (20 - PAGE_SHIFT),
426 nr_pages << (PAGE_SHIFT - 10));
427 total_pages = nr_pages;
429 init_frametable();
431 trap_init();
433 alloc_dom0();
435 end_boot_allocator();
437 init_xenheap_pages(__pa(xen_heap_start), xenheap_phys_end);
438 printk("Xen heap: %luMB (%lukB)\n",
439 (xenheap_phys_end-__pa(xen_heap_start)) >> 20,
440 (xenheap_phys_end-__pa(xen_heap_start)) >> 10);
442 late_setup_arch(&cmdline);
444 scheduler_init();
445 idle_vcpu[0] = (struct vcpu*) ia64_r13;
446 idle_domain = domain_create(IDLE_DOMAIN_ID, 0, 0);
447 if ( (idle_domain == NULL) || (alloc_vcpu(idle_domain, 0, 0) == NULL) )
448 BUG();
450 alloc_dom_xen_and_dom_io();
451 setup_per_cpu_areas();
452 mem_init();
454 local_irq_disable();
455 init_IRQ ();
456 init_xen_time(); /* initialise the time */
457 timer_init();
459 rcu_init();
461 #ifdef CONFIG_XEN_IA64_TLBFLUSH_CLOCK
462 open_softirq(NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ, new_tlbflush_clock_period);
463 #endif
465 #ifdef CONFIG_SMP
466 if ( opt_nosmp )
467 {
468 max_cpus = 0;
469 smp_num_siblings = 1;
470 //boot_cpu_data.x86_num_cores = 1;
471 }
473 /* A vcpu is created for the idle domain on every physical cpu.
474 Limit the number of cpus to the maximum number of vcpus. */
475 if (max_cpus > MAX_VIRT_CPUS)
476 max_cpus = MAX_VIRT_CPUS;
478 smp_prepare_cpus(max_cpus);
480 /* We aren't hotplug-capable yet. */
481 for_each_cpu ( i )
482 cpu_set(i, cpu_present_map);
484 /* Enable IRQ to receive IPI (needed for ITC sync). */
485 local_irq_enable();
487 printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus);
488 for_each_present_cpu ( i )
489 {
490 if ( num_online_cpus() >= max_cpus )
491 break;
492 if ( !cpu_online(i) ) {
493 rcu_online_cpu(i);
494 __cpu_up(i);
495 }
496 }
498 local_irq_disable();
500 printk("Brought up %ld CPUs\n", (long)num_online_cpus());
501 smp_cpus_done(max_cpus);
502 #endif
504 initialise_gdb(); /* could be moved earlier */
506 do_initcalls();
507 sort_main_extable();
509 init_rid_allocator ();
511 local_irq_enable();
513 if (opt_xencons) {
514 initialize_keytable();
515 if (ns16550_com1_gsi) {
516 if (opt_xencons_poll ||
517 iosapic_register_intr(ns16550_com1_gsi,
518 ns16550_com1_polarity,
519 ns16550_com1_trigger) < 0) {
520 ns16550_com1.irq = 0;
521 ns16550_init(0, &ns16550_com1);
522 }
523 }
524 serial_init_postirq();
526 /* Hide the HCDP table from dom0 */
527 efi.hcdp = NULL;
528 }
530 expose_p2m_init();
532 /* Create initial domain 0. */
533 dom0 = domain_create(0, 0, DOM0_SSIDREF);
534 if (dom0 == NULL)
535 panic("Error creating domain 0\n");
536 dom0_vcpu0 = alloc_vcpu(dom0, 0, 0);
537 if (dom0_vcpu0 == NULL || vcpu_late_initialise(dom0_vcpu0) != 0)
538 panic("Cannot allocate dom0 vcpu 0\n");
540 dom0->is_privileged = 1;
542 /*
543 * We're going to setup domain0 using the module(s) that we stashed safely
544 * above our heap. The second module, if present, is an initrd ramdisk.
545 */
546 dom0_memory_start = (unsigned long) __va(ia64_boot_param->domain_start);
547 dom0_memory_size = ia64_boot_param->domain_size;
548 dom0_initrd_start = (unsigned long) __va(ia64_boot_param->initrd_start);
549 dom0_initrd_size = ia64_boot_param->initrd_size;
551 if ( construct_dom0(dom0, dom0_memory_start, dom0_memory_size,
552 dom0_initrd_start,dom0_initrd_size,
553 0) != 0)
554 panic("Could not set up DOM0 guest OS\n");
556 if (!running_on_sim) // slow on ski and pages are pre-initialized to zero
557 scrub_heap_pages();
559 init_trace_bufs();
561 if (opt_xencons) {
562 console_endboot();
563 serial_endboot();
564 }
566 domain0_ready = 1;
568 domain_unpause_by_systemcontroller(dom0);
570 init_done();
571 }
573 void arch_get_xen_caps(xen_capabilities_info_t *info)
574 {
575 /* Interface name is always xen-3.0-* for Xen-3.x. */
576 int major = 3, minor = 0;
577 char s[32];
579 (*info)[0] = '\0';
581 snprintf(s, sizeof(s), "xen-%d.%d-ia64 ", major, minor);
582 safe_strcat(*info, s);
584 snprintf(s, sizeof(s), "xen-%d.%d-ia64be ", major, minor);
585 safe_strcat(*info, s);
587 if (vmx_enabled)
588 {
589 snprintf(s, sizeof(s), "hvm-%d.%d-ia64 ", major, minor);
590 safe_strcat(*info, s);
591 }
592 }