ia64/xen-unstable

view xen/arch/ia64/xen/xensetup.c @ 6458:3ca4ca7a9cc2

Final changes for linux 2.6.13 rebasing and some directory reorgs
author djm@kirby.fc.hp.com
date Thu Sep 01 12:46:28 2005 -0600 (2005-09-01)
parents
children 89fc07f85b01
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 <xen/delay.h>
15 #include <xen/compile.h>
16 //#include <xen/console.h>
17 #include <xen/serial.h>
18 #include <xen/trace.h>
19 #include <asm/meminit.h>
20 #include <asm/page.h>
21 #include <asm/setup.h>
22 #include <xen/string.h>
24 unsigned long xenheap_phys_end;
26 char saved_command_line[COMMAND_LINE_SIZE];
28 struct vcpu *idle_task[NR_CPUS] = { &idle0_vcpu };
30 cpumask_t cpu_present_map;
32 #ifdef CLONE_DOMAIN0
33 struct domain *clones[CLONE_DOMAIN0];
34 #endif
35 extern unsigned long domain0_ready;
37 int find_max_pfn (unsigned long, unsigned long, void *);
38 void start_of_day(void);
40 /* opt_nosmp: If true, secondary processors are ignored. */
41 static int opt_nosmp = 0;
42 boolean_param("nosmp", opt_nosmp);
44 /* maxcpus: maximum number of CPUs to activate. */
45 static unsigned int max_cpus = NR_CPUS;
46 integer_param("maxcpus", max_cpus);
48 /*
49 * opt_xenheap_megabytes: Size of Xen heap in megabytes, including:
50 * xen image
51 * bootmap bits
52 * xen heap
53 * Note: To allow xenheap size configurable, the prerequisite is
54 * to configure elilo allowing relocation defaultly. Then since
55 * elilo chooses 256M as alignment when relocating, alignment issue
56 * on IPF can be addressed.
57 */
58 unsigned int opt_xenheap_megabytes = XENHEAP_DEFAULT_MB;
59 unsigned long xenheap_size = XENHEAP_DEFAULT_SIZE;
60 extern long running_on_sim;
61 unsigned long xen_pstart;
63 static int
64 xen_count_pages(u64 start, u64 end, void *arg)
65 {
66 unsigned long *count = arg;
68 /* FIXME: do we need consider difference between DMA-usable memory and
69 * normal memory? Seems that HV has no requirement to operate DMA which
70 * is owned by Dom0? */
71 *count += (end - start) >> PAGE_SHIFT;
72 return 0;
73 }
75 /* Find first hole after trunk for xen image */
76 static int
77 xen_find_first_hole(u64 start, u64 end, void *arg)
78 {
79 unsigned long *first_hole = arg;
81 if ((*first_hole) == 0) {
82 if ((start <= KERNEL_START) && (KERNEL_START < end))
83 *first_hole = __pa(end);
84 }
86 return 0;
87 }
89 static void __init do_initcalls(void)
90 {
91 initcall_t *call;
92 for ( call = &__initcall_start; call < &__initcall_end; call++ )
93 (*call)();
94 }
96 /*
97 * IPF loader only supports one commaind line currently, for
98 * both xen and guest kernel. This function provides pre-parse
99 * to mixed command line, to split it into two parts.
100 *
101 * User should split the parameters by "--", with strings after
102 * spliter for guest kernel. Missing "--" means whole line belongs
103 * to guest. Example:
104 * "com2=57600,8n1 console=com2 -- console=ttyS1 console=tty
105 * root=/dev/sda3 ro"
106 */
107 static char null[4] = { 0 };
109 void early_cmdline_parse(char **cmdline_p)
110 {
111 char *guest_cmd;
112 char *split = "--";
114 if (*cmdline_p == NULL) {
115 *cmdline_p = &null[0];
116 saved_command_line[0] = '\0';
117 return;
118 }
120 guest_cmd = strstr(*cmdline_p, split);
121 /* If no spliter, whole line is for guest */
122 if (guest_cmd == NULL) {
123 guest_cmd = *cmdline_p;
124 *cmdline_p = &null[0];
125 } else {
126 *guest_cmd = '\0'; /* Split boot parameters for xen and guest */
127 guest_cmd += strlen(split);
128 while (*guest_cmd == ' ') guest_cmd++;
129 }
131 strlcpy(saved_command_line, guest_cmd, COMMAND_LINE_SIZE);
132 return;
133 }
135 struct ns16550_defaults ns16550_com1 = {
136 .baud = BAUD_AUTO,
137 .data_bits = 8,
138 .parity = 'n',
139 .stop_bits = 1
140 };
142 struct ns16550_defaults ns16550_com2 = {
143 .baud = BAUD_AUTO,
144 .data_bits = 8,
145 .parity = 'n',
146 .stop_bits = 1
147 };
149 void start_kernel(void)
150 {
151 unsigned char *cmdline;
152 void *heap_start;
153 int i;
154 unsigned long max_mem, nr_pages, firsthole_start;
155 unsigned long dom0_memory_start, dom0_memory_end;
156 unsigned long initial_images_start, initial_images_end;
158 running_on_sim = is_platform_hp_ski();
159 /* Kernel may be relocated by EFI loader */
160 xen_pstart = ia64_tpa(KERNEL_START);
162 /* Must do this early -- e.g., spinlocks rely on get_current(). */
163 //set_current(&idle0_vcpu);
164 ia64_r13 = (void *)&idle0_vcpu;
165 idle0_vcpu.domain = &idle0_domain;
167 early_setup_arch(&cmdline);
169 /* We initialise the serial devices very early so we can get debugging. */
170 if (running_on_sim) hpsim_serial_init();
171 else {
172 ns16550_init(0, &ns16550_com1);
173 /* Also init com2 for Tiger4. */
174 ns16550_com2.io_base = 0x2f8;
175 ns16550_com2.irq = 3;
176 ns16550_init(1, &ns16550_com2);
177 }
178 serial_init_preirq();
180 init_console();
181 set_printk_prefix("(XEN) ");
183 /* xenheap should be in same TR-covered range with xen image */
184 xenheap_phys_end = xen_pstart + xenheap_size;
185 printk("xen image pstart: 0x%lx, xenheap pend: 0x%lx\n",
186 xen_pstart, xenheap_phys_end);
188 /* Find next hole */
189 firsthole_start = 0;
190 efi_memmap_walk(xen_find_first_hole, &firsthole_start);
192 initial_images_start = xenheap_phys_end;
193 initial_images_end = initial_images_start + ia64_boot_param->initrd_size;
195 /* Later may find another memory trunk, even away from xen image... */
196 if (initial_images_end > firsthole_start) {
197 printk("Not enough memory to stash the DOM0 kernel image.\n");
198 printk("First hole:0x%lx, relocation end: 0x%lx\n",
199 firsthole_start, initial_images_end);
200 for ( ; ; );
201 }
203 /* This copy is time consuming, but elilo may load Dom0 image
204 * within xenheap range */
205 printk("ready to move Dom0 to 0x%lx...", initial_images_start);
206 memmove(__va(initial_images_start),
207 __va(ia64_boot_param->initrd_start),
208 ia64_boot_param->initrd_size);
209 ia64_boot_param->initrd_start = initial_images_start;
210 printk("Done\n");
212 /* first find highest page frame number */
213 max_page = 0;
214 efi_memmap_walk(find_max_pfn, &max_page);
215 printf("find_memory: efi_memmap_walk returns max_page=%lx\n",max_page);
217 heap_start = memguard_init(ia64_imva(&_end));
218 printf("Before heap_start: 0x%lx\n", heap_start);
219 heap_start = __va(init_boot_allocator(__pa(heap_start)));
220 printf("After heap_start: 0x%lx\n", heap_start);
222 reserve_memory();
224 efi_memmap_walk(filter_rsvd_memory, init_boot_pages);
225 efi_memmap_walk(xen_count_pages, &nr_pages);
227 printk("System RAM: %luMB (%lukB)\n",
228 nr_pages >> (20 - PAGE_SHIFT),
229 nr_pages << (PAGE_SHIFT - 10));
231 init_frametable();
233 ia64_fph_enable();
234 __ia64_init_fpu();
236 alloc_dom0();
237 #ifdef DOMU_BUILD_STAGING
238 alloc_domU_staging();
239 #endif
241 end_boot_allocator();
243 init_xenheap_pages(__pa(heap_start), xenheap_phys_end);
244 printk("Xen heap: %luMB (%lukB)\n",
245 (xenheap_phys_end-__pa(heap_start)) >> 20,
246 (xenheap_phys_end-__pa(heap_start)) >> 10);
248 late_setup_arch(&cmdline);
249 setup_per_cpu_areas();
250 mem_init();
252 printk("About to call scheduler_init()\n");
253 scheduler_init();
254 local_irq_disable();
255 printk("About to call xen_time_init()\n");
256 xen_time_init();
257 #ifdef CONFIG_VTI
258 init_xen_time(); /* initialise the time */
259 #endif // CONFIG_VTI
260 printk("About to call ac_timer_init()\n");
261 ac_timer_init();
262 // init_xen_time(); ???
264 #ifdef CONFIG_SMP
265 if ( opt_nosmp )
266 {
267 max_cpus = 0;
268 smp_num_siblings = 1;
269 //boot_cpu_data.x86_num_cores = 1;
270 }
272 smp_prepare_cpus(max_cpus);
274 /* We aren't hotplug-capable yet. */
275 //BUG_ON(!cpus_empty(cpu_present_map));
276 for_each_cpu ( i )
277 cpu_set(i, cpu_present_map);
279 //BUG_ON(!local_irq_is_enabled());
281 printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus);
282 for_each_present_cpu ( i )
283 {
284 if ( num_online_cpus() >= max_cpus )
285 break;
286 if ( !cpu_online(i) ) {
287 printk("About to call __cpu_up(%d)\n",i);
288 __cpu_up(i);
289 }
290 }
292 printk("Brought up %ld CPUs\n", (long)num_online_cpus());
293 smp_cpus_done(max_cpus);
294 #endif
297 // FIXME: Should the following be swapped and moved later?
298 schedulers_start();
299 do_initcalls();
300 printk("About to call sort_main_extable()\n");
301 sort_main_extable();
303 /* surrender usage of kernel registers to domain, use percpu area instead */
304 __get_cpu_var(cpu_kr)._kr[IA64_KR_IO_BASE] = ia64_get_kr(IA64_KR_IO_BASE);
305 __get_cpu_var(cpu_kr)._kr[IA64_KR_PER_CPU_DATA] = ia64_get_kr(IA64_KR_PER_CPU_DATA);
306 __get_cpu_var(cpu_kr)._kr[IA64_KR_CURRENT_STACK] = ia64_get_kr(IA64_KR_CURRENT_STACK);
307 __get_cpu_var(cpu_kr)._kr[IA64_KR_FPU_OWNER] = ia64_get_kr(IA64_KR_FPU_OWNER);
308 __get_cpu_var(cpu_kr)._kr[IA64_KR_CURRENT] = ia64_get_kr(IA64_KR_CURRENT);
309 __get_cpu_var(cpu_kr)._kr[IA64_KR_PT_BASE] = ia64_get_kr(IA64_KR_PT_BASE);
311 /* Create initial domain 0. */
312 printk("About to call do_createdomain()\n");
313 dom0 = do_createdomain(0, 0);
314 init_task.domain = &idle0_domain;
315 init_task.processor = 0;
316 // init_task.mm = &init_mm;
317 init_task.domain->arch.mm = &init_mm;
318 // init_task.thread = INIT_THREAD;
319 //arch_do_createdomain(current);
320 #ifdef CLONE_DOMAIN0
321 {
322 int i;
323 for (i = 0; i < CLONE_DOMAIN0; i++) {
324 clones[i] = do_createdomain(i+1, 0);
325 if ( clones[i] == NULL )
326 panic("Error creating domain0 clone %d\n",i);
327 }
328 }
329 #endif
330 if ( dom0 == NULL )
331 panic("Error creating domain 0\n");
333 set_bit(_DOMF_privileged, &dom0->domain_flags);
335 /*
336 * We're going to setup domain0 using the module(s) that we stashed safely
337 * above our heap. The second module, if present, is an initrd ramdisk.
338 */
339 printk("About to call construct_dom0()\n");
340 dom0_memory_start = __va(ia64_boot_param->initrd_start);
341 dom0_memory_end = ia64_boot_param->initrd_size;
342 if ( construct_dom0(dom0, dom0_memory_start, dom0_memory_end,
343 0,
344 0,
345 0) != 0)
346 panic("Could not set up DOM0 guest OS\n");
347 #ifdef CLONE_DOMAIN0
348 {
349 int i;
350 dom0_memory_start = __va(ia64_boot_param->initrd_start);
351 dom0_memory_end = ia64_boot_param->initrd_size;
352 for (i = 0; i < CLONE_DOMAIN0; i++) {
353 printk("CONSTRUCTING DOMAIN0 CLONE #%d\n",i+1);
354 if ( construct_domU(clones[i], dom0_memory_start, dom0_memory_end,
355 0,
356 0,
357 0) != 0)
358 panic("Could not set up DOM0 clone %d\n",i);
359 }
360 }
361 #endif
363 /* The stash space for the initial kernel image can now be freed up. */
364 init_domheap_pages(ia64_boot_param->initrd_start,
365 ia64_boot_param->initrd_start + ia64_boot_param->initrd_size);
366 if (!running_on_sim) // slow on ski and pages are pre-initialized to zero
367 scrub_heap_pages();
369 printk("About to call init_trace_bufs()\n");
370 init_trace_bufs();
372 /* Give up the VGA console if DOM0 is configured to grab it. */
373 #ifndef IA64
374 console_endboot(cmdline && strstr(cmdline, "tty0"));
375 #endif
377 #ifdef CLONE_DOMAIN0
378 {
379 int i;
380 for (i = 0; i < CLONE_DOMAIN0; i++)
381 domain_unpause_by_systemcontroller(clones[i]);
382 }
383 #endif
384 domain_unpause_by_systemcontroller(dom0);
385 domain0_ready = 1;
386 local_irq_enable();
387 printk("About to call startup_cpu_idle_loop()\n");
388 startup_cpu_idle_loop();
389 }