ia64/xen-unstable

view xen/arch/ia64/xen/xensetup.c @ 9772:ddcd9c267612

[IA64] Reseve memory of domain0 (fix dom0 boot panic)

Our patch fix domain0 boot panic on large memory system.
(e.g. amount of installed memory is 16GB)

Memory of domain0 is not reserved now.
Our patch can make this memory reserved.
And we clean up initrd_start of domain0.

Signed-off-by: Kouya Shimura <kouya@jp.fujitsu.com>
Signed-off-by: Akio Takebe <takebe_akio@jp.fujitsu.com>
author awilliam@xenbuild.aw
date Tue Apr 25 22:52:49 2006 -0600 (2006-04-25)
parents ced37bea0647
children 9a915e2828f3
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;
35 char saved_command_line[COMMAND_LINE_SIZE];
36 char dom0_command_line[COMMAND_LINE_SIZE];
38 struct vcpu *idle_vcpu[NR_CPUS];
40 cpumask_t cpu_present_map;
42 extern unsigned long domain0_ready;
44 int find_max_pfn (unsigned long, unsigned long, void *);
45 void start_of_day(void);
47 /* FIXME: which header these declarations should be there ? */
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);
57 /* opt_nosmp: If true, secondary processors are ignored. */
58 static int opt_nosmp = 0;
59 boolean_param("nosmp", opt_nosmp);
61 /* maxcpus: maximum number of CPUs to activate. */
62 static unsigned int max_cpus = NR_CPUS;
63 integer_param("maxcpus", max_cpus);
65 /*
66 * opt_xenheap_megabytes: Size of Xen heap in megabytes, including:
67 * xen image
68 * bootmap bits
69 * xen heap
70 * Note: To allow xenheap size configurable, the prerequisite is
71 * to configure elilo allowing relocation defaultly. Then since
72 * elilo chooses 256M as alignment when relocating, alignment issue
73 * on IPF can be addressed.
74 */
75 unsigned int opt_xenheap_megabytes = XENHEAP_DEFAULT_MB;
76 unsigned long xenheap_size = XENHEAP_DEFAULT_SIZE;
77 extern long running_on_sim;
78 unsigned long xen_pstart;
80 static int
81 xen_count_pages(u64 start, u64 end, void *arg)
82 {
83 unsigned long *count = arg;
85 /* FIXME: do we need consider difference between DMA-usable memory and
86 * normal memory? Seems that HV has no requirement to operate DMA which
87 * is owned by Dom0? */
88 *count += (end - start) >> PAGE_SHIFT;
89 return 0;
90 }
92 /* Find first hole after trunk for xen image */
93 static int
94 xen_find_first_hole(u64 start, u64 end, void *arg)
95 {
96 unsigned long *first_hole = arg;
98 if ((*first_hole) == 0) {
99 if ((start <= KERNEL_START) && (KERNEL_START < end))
100 *first_hole = __pa(end);
101 }
103 return 0;
104 }
106 static void __init do_initcalls(void)
107 {
108 initcall_t *call;
109 for ( call = &__initcall_start; call < &__initcall_end; call++ )
110 (*call)();
111 }
113 /*
114 * IPF loader only supports one commaind line currently, for
115 * both xen and guest kernel. This function provides pre-parse
116 * to mixed command line, to split it into two parts.
117 *
118 * User should split the parameters by "--", with strings after
119 * spliter for guest kernel. Missing "--" means whole line belongs
120 * to guest. Example:
121 * "com2=57600,8n1 console=com2 -- console=ttyS1 console=tty
122 * root=/dev/sda3 ro"
123 */
124 static char null[4] = { 0 };
126 void early_cmdline_parse(char **cmdline_p)
127 {
128 char *guest_cmd;
129 static const char * const split = "--";
131 if (*cmdline_p == NULL) {
132 *cmdline_p = &null[0];
133 saved_command_line[0] = '\0';
134 dom0_command_line[0] = '\0';
135 return;
136 }
138 guest_cmd = strstr(*cmdline_p, split);
139 /* If no spliter, whole line is for guest */
140 if (guest_cmd == NULL) {
141 guest_cmd = *cmdline_p;
142 *cmdline_p = &null[0];
143 } else {
144 *guest_cmd = '\0'; /* Split boot parameters for xen and guest */
145 guest_cmd += strlen(split);
146 while (*guest_cmd == ' ') guest_cmd++;
147 }
149 strlcpy(saved_command_line, *cmdline_p, COMMAND_LINE_SIZE);
150 strlcpy(dom0_command_line, guest_cmd, COMMAND_LINE_SIZE);
151 return;
152 }
154 struct ns16550_defaults ns16550_com1 = {
155 .baud = BAUD_AUTO,
156 .data_bits = 8,
157 .parity = 'n',
158 .stop_bits = 1
159 };
161 struct ns16550_defaults ns16550_com2 = {
162 .baud = BAUD_AUTO,
163 .data_bits = 8,
164 .parity = 'n',
165 .stop_bits = 1
166 };
168 /* efi_print: print efi table at boot */
169 static int opt_efi_print = 0;
170 boolean_param("efi_print", opt_efi_print);
172 /* print EFI memory map: */
173 static void
174 efi_print(void)
175 {
176 void *efi_map_start, *efi_map_end;
177 u64 efi_desc_size;
179 efi_memory_desc_t *md;
180 void *p;
181 int i;
183 if (!opt_efi_print)
184 return;
186 efi_map_start = __va(ia64_boot_param->efi_memmap);
187 efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
188 efi_desc_size = ia64_boot_param->efi_memdesc_size;
190 for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) {
191 md = p;
192 printk("mem%02u: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)\n",
193 i, md->type, md->attribute, md->phys_addr,
194 md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
195 md->num_pages >> (20 - EFI_PAGE_SHIFT));
196 }
197 }
199 void start_kernel(void)
200 {
201 unsigned char *cmdline;
202 void *heap_start;
203 unsigned long nr_pages, firsthole_start;
204 unsigned long dom0_memory_start, dom0_memory_size;
205 unsigned long dom0_initrd_start, dom0_initrd_size;
206 unsigned long initial_images_start, initial_images_end;
207 struct domain *idle_domain;
208 #ifdef CONFIG_SMP
209 int i;
210 #endif
212 running_on_sim = is_platform_hp_ski();
213 /* Kernel may be relocated by EFI loader */
214 xen_pstart = ia64_tpa(KERNEL_START);
216 early_setup_arch((char **) &cmdline);
218 /* We initialise the serial devices very early so we can get debugging. */
219 if (running_on_sim) hpsim_serial_init();
220 else {
221 ns16550_init(0, &ns16550_com1);
222 /* Also init com2 for Tiger4. */
223 ns16550_com2.io_base = 0x2f8;
224 ns16550_com2.irq = 3;
225 ns16550_init(1, &ns16550_com2);
226 }
227 serial_init_preirq();
229 init_console();
230 set_printk_prefix("(XEN) ");
232 /* xenheap should be in same TR-covered range with xen image */
233 xenheap_phys_end = xen_pstart + xenheap_size;
234 printk("xen image pstart: 0x%lx, xenheap pend: 0x%lx\n",
235 xen_pstart, xenheap_phys_end);
237 /* Find next hole */
238 firsthole_start = 0;
239 efi_memmap_walk(xen_find_first_hole, &firsthole_start);
241 if (running_on_sim || ia64_boot_param->domain_start == 0
242 || ia64_boot_param->domain_size == 0) {
243 /* This is possible only with the old elilo, which does not support
244 a vmm. Fix now, and continue without initrd. */
245 printk ("Your elilo is not Xen-aware. Bootparams fixed\n");
246 ia64_boot_param->domain_start = ia64_boot_param->initrd_start;
247 ia64_boot_param->domain_size = ia64_boot_param->initrd_size;
248 ia64_boot_param->initrd_start = 0;
249 ia64_boot_param->initrd_size = 0;
250 }
252 initial_images_start = xenheap_phys_end;
253 initial_images_end = initial_images_start +
254 PAGE_ALIGN(ia64_boot_param->domain_size);
256 /* also reserve space for initrd */
257 if (ia64_boot_param->initrd_start && ia64_boot_param->initrd_size)
258 initial_images_end += PAGE_ALIGN(ia64_boot_param->initrd_size);
259 else {
260 /* sanity cleanup */
261 ia64_boot_param->initrd_size = 0;
262 ia64_boot_param->initrd_start = 0;
263 }
266 /* Later may find another memory trunk, even away from xen image... */
267 if (initial_images_end > firsthole_start) {
268 printk("Not enough memory to stash the DOM0 kernel image.\n");
269 printk("First hole:0x%lx, relocation end: 0x%lx\n",
270 firsthole_start, initial_images_end);
271 for ( ; ; );
272 }
274 /* This copy is time consuming, but elilo may load Dom0 image
275 * within xenheap range */
276 printk("ready to move Dom0 to 0x%lx with len %lx...", initial_images_start,
277 ia64_boot_param->domain_size);
279 memmove(__va(initial_images_start),
280 __va(ia64_boot_param->domain_start),
281 ia64_boot_param->domain_size);
282 ia64_boot_param->domain_start = initial_images_start;
284 printk("ready to move initrd to 0x%lx with len %lx...",
285 initial_images_start+PAGE_ALIGN(ia64_boot_param->domain_size),
286 ia64_boot_param->initrd_size);
287 memmove(__va(initial_images_start+PAGE_ALIGN(ia64_boot_param->domain_size)),
288 __va(ia64_boot_param->initrd_start),
289 ia64_boot_param->initrd_size);
290 printk("Done\n");
291 ia64_boot_param->initrd_start = initial_images_start +
292 PAGE_ALIGN(ia64_boot_param->domain_size);
294 /* first find highest page frame number */
295 max_page = 0;
296 efi_memmap_walk(find_max_pfn, &max_page);
297 printf("find_memory: efi_memmap_walk returns max_page=%lx\n",max_page);
298 #ifndef CONFIG_XEN_IA64_DOM0_VP
299 /* this is a bad hack. see dom_fw.c creation of EFI map for dom0 */
300 max_page = (GRANULEROUNDDOWN(max_page << PAGE_SHIFT)
301 - IA64_GRANULE_SIZE) >> PAGE_SHIFT;
302 printf("find_memory: last granule reserved for dom0; xen max_page=%lx\n",
303 max_page);
304 #endif
305 efi_print();
307 heap_start = memguard_init(ia64_imva(&_end));
308 printf("Before heap_start: %p\n", heap_start);
309 heap_start = __va(init_boot_allocator(__pa(heap_start)));
310 printf("After heap_start: %p\n", heap_start);
312 reserve_memory();
314 efi_memmap_walk(filter_rsvd_memory, init_boot_pages);
315 efi_memmap_walk(xen_count_pages, &nr_pages);
317 printk("System RAM: %luMB (%lukB)\n",
318 nr_pages >> (20 - PAGE_SHIFT),
319 nr_pages << (PAGE_SHIFT - 10));
321 init_frametable();
323 alloc_dom0();
325 end_boot_allocator();
327 init_xenheap_pages(__pa(heap_start), xenheap_phys_end);
328 printk("Xen heap: %luMB (%lukB)\n",
329 (xenheap_phys_end-__pa(heap_start)) >> 20,
330 (xenheap_phys_end-__pa(heap_start)) >> 10);
332 printk("About to call scheduler_init()\n");
333 scheduler_init();
334 idle_vcpu[0] = (struct vcpu*) ia64_r13;
335 idle_domain = domain_create(IDLE_DOMAIN_ID, 0);
336 BUG_ON(idle_domain == NULL);
338 late_setup_arch((char **) &cmdline);
339 setup_per_cpu_areas();
340 mem_init();
342 local_irq_disable();
343 init_IRQ ();
344 printk("About to call init_xen_time()\n");
345 init_xen_time(); /* initialise the time */
346 printk("About to call timer_init()\n");
347 timer_init();
349 #ifdef CONFIG_XEN_CONSOLE_INPUT /* CONFIG_SERIAL_8250_CONSOLE=n in dom0! */
350 initialize_keytable();
351 serial_init_postirq();
352 #endif
354 #ifdef CONFIG_SMP
355 if ( opt_nosmp )
356 {
357 max_cpus = 0;
358 smp_num_siblings = 1;
359 //boot_cpu_data.x86_num_cores = 1;
360 }
362 /* A vcpu is created for the idle domain on every physical cpu.
363 Limit the number of cpus to the maximum number of vcpus. */
364 if (max_cpus > MAX_VIRT_CPUS)
365 max_cpus = MAX_VIRT_CPUS;
367 smp_prepare_cpus(max_cpus);
369 /* We aren't hotplug-capable yet. */
370 for_each_cpu ( i )
371 cpu_set(i, cpu_present_map);
373 /* Enable IRQ to receive IPI (needed for ITC sync). */
374 local_irq_enable();
376 printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus);
377 for_each_present_cpu ( i )
378 {
379 if ( num_online_cpus() >= max_cpus )
380 break;
381 if ( !cpu_online(i) ) {
382 __cpu_up(i);
383 }
384 }
386 local_irq_disable();
388 printk("Brought up %ld CPUs\n", (long)num_online_cpus());
389 smp_cpus_done(max_cpus);
390 #endif
392 initialise_gdb(); /* could be moved earlier */
394 do_initcalls();
395 printk("About to call sort_main_extable()\n");
396 sort_main_extable();
399 init_rid_allocator ();
401 /* Create initial domain 0. */
402 printk("About to call domain_create()\n");
403 dom0 = domain_create(0, 0);
405 if ( dom0 == NULL )
406 panic("Error creating domain 0\n");
408 set_bit(_DOMF_privileged, &dom0->domain_flags);
410 /*
411 * We're going to setup domain0 using the module(s) that we stashed safely
412 * above our heap. The second module, if present, is an initrd ramdisk.
413 */
414 printk("About to call construct_dom0()\n");
415 dom0_memory_start = (unsigned long) __va(initial_images_start);
416 dom0_memory_size = ia64_boot_param->domain_size;
417 dom0_initrd_start = (unsigned long) __va(initial_images_start +
418 PAGE_ALIGN(ia64_boot_param->domain_size));
419 dom0_initrd_size = ia64_boot_param->initrd_size;
421 if ( construct_dom0(dom0, dom0_memory_start, dom0_memory_size,
422 dom0_initrd_start,dom0_initrd_size,
423 0) != 0)
424 panic("Could not set up DOM0 guest OS\n");
426 /* PIN domain0 on CPU 0. */
427 dom0->vcpu[0]->cpu_affinity = cpumask_of_cpu(0);
429 if (!running_on_sim) // slow on ski and pages are pre-initialized to zero
430 scrub_heap_pages();
432 printk("About to call init_trace_bufs()\n");
433 init_trace_bufs();
435 /* Give up the VGA console if DOM0 is configured to grab it. */
436 #ifdef CONFIG_XEN_CONSOLE_INPUT /* CONFIG_SERIAL_8250_CONSOLE=n in dom0! */
437 console_endboot(cmdline && strstr(cmdline, "tty0"));
438 #endif
440 domain0_ready = 1;
442 local_irq_enable();
444 printf("About to call schedulers_start dom0=%p, idle_dom=%p\n",
445 dom0, &idle_domain);
446 schedulers_start();
448 domain_unpause_by_systemcontroller(dom0);
450 printk("About to call startup_cpu_idle_loop()\n");
451 startup_cpu_idle_loop();
452 }
454 void arch_get_xen_caps(xen_capabilities_info_t info)
455 {
456 char *p=info;
458 p += sprintf(p,"xen-%d.%d-ia64 ", XEN_VERSION, XEN_SUBVERSION);
460 if (vmx_enabled)
461 p += sprintf(p,"hvm-%d.%d-ia64 ", XEN_VERSION, XEN_SUBVERSION);
463 *(p-1) = 0;
465 BUG_ON((p-info)>sizeof(xen_capabilities_info_t));
467 }