ia64/xen-unstable

view xen/arch/ia64/xensetup.c @ 5987:5f1ed597f107

Ensure percpu data area not used before the TR is set.
author fred@xuni-t01.sc.intel.com
date Tue Aug 23 18:43:18 2005 -0800 (2005-08-23)
parents 1ec2225aa8c6
children 8799d14bef77
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 #ifdef CLONE_DOMAIN0
31 struct domain *clones[CLONE_DOMAIN0];
32 #endif
33 extern unsigned long domain0_ready;
35 int find_max_pfn (unsigned long, unsigned long, void *);
36 void start_of_day(void);
38 /* opt_nosmp: If true, secondary processors are ignored. */
39 static int opt_nosmp = 0;
40 boolean_param("nosmp", opt_nosmp);
42 /* maxcpus: maximum number of CPUs to activate. */
43 static unsigned int max_cpus = NR_CPUS;
44 integer_param("maxcpus", max_cpus);
46 /*
47 * opt_xenheap_megabytes: Size of Xen heap in megabytes, including:
48 * xen image
49 * bootmap bits
50 * xen heap
51 * Note: To allow xenheap size configurable, the prerequisite is
52 * to configure elilo allowing relocation defaultly. Then since
53 * elilo chooses 256M as alignment when relocating, alignment issue
54 * on IPF can be addressed.
55 */
56 unsigned int opt_xenheap_megabytes = XENHEAP_DEFAULT_MB;
57 unsigned long xenheap_size = XENHEAP_DEFAULT_SIZE;
58 extern long running_on_sim;
59 unsigned long xen_pstart;
61 static int
62 xen_count_pages(u64 start, u64 end, void *arg)
63 {
64 unsigned long *count = arg;
66 /* FIXME: do we need consider difference between DMA-usable memory and
67 * normal memory? Seems that HV has no requirement to operate DMA which
68 * is owned by Dom0? */
69 *count += (end - start) >> PAGE_SHIFT;
70 return 0;
71 }
73 /* Find first hole after trunk for xen image */
74 static int
75 xen_find_first_hole(u64 start, u64 end, void *arg)
76 {
77 unsigned long *first_hole = arg;
79 if ((*first_hole) == 0) {
80 if ((start <= KERNEL_START) && (KERNEL_START < end))
81 *first_hole = __pa(end);
82 }
84 return 0;
85 }
87 static void __init do_initcalls(void)
88 {
89 initcall_t *call;
90 for ( call = &__initcall_start; call < &__initcall_end; call++ )
91 (*call)();
92 }
94 /*
95 * IPF loader only supports one commaind line currently, for
96 * both xen and guest kernel. This function provides pre-parse
97 * to mixed command line, to split it into two parts.
98 *
99 * User should split the parameters by "--", with strings after
100 * spliter for guest kernel. Missing "--" means whole line belongs
101 * to guest. Example:
102 * "com2=57600,8n1 console=com2 -- console=ttyS1 console=tty
103 * root=/dev/sda3 ro"
104 */
105 static char null[4] = { 0 };
107 void early_cmdline_parse(char **cmdline_p)
108 {
109 char *guest_cmd;
110 char *split = "--";
112 if (*cmdline_p == NULL) {
113 *cmdline_p = &null[0];
114 saved_command_line[0] = '\0';
115 return;
116 }
118 guest_cmd = strstr(*cmdline_p, split);
119 /* If no spliter, whole line is for guest */
120 if (guest_cmd == NULL) {
121 guest_cmd = *cmdline_p;
122 *cmdline_p = &null[0];
123 } else {
124 *guest_cmd = '\0'; /* Split boot parameters for xen and guest */
125 guest_cmd += strlen(split);
126 while (*guest_cmd == ' ') guest_cmd++;
127 }
129 strlcpy(saved_command_line, guest_cmd, COMMAND_LINE_SIZE);
130 return;
131 }
133 struct ns16550_defaults ns16550_com1 = {
134 .data_bits = 8,
135 .parity = 'n',
136 .stop_bits = 1
137 };
139 struct ns16550_defaults ns16550_com2 = {
140 .data_bits = 8,
141 .parity = 'n',
142 .stop_bits = 1
143 };
145 void start_kernel(void)
146 {
147 unsigned char *cmdline;
148 void *heap_start;
149 int i;
150 unsigned long max_mem, nr_pages, firsthole_start;
151 unsigned long dom0_memory_start, dom0_memory_end;
152 unsigned long initial_images_start, initial_images_end;
154 running_on_sim = is_platform_hp_ski();
155 /* Kernel may be relocated by EFI loader */
156 xen_pstart = ia64_tpa(KERNEL_START);
158 /* Must do this early -- e.g., spinlocks rely on get_current(). */
159 //set_current(&idle0_vcpu);
160 ia64_r13 = (void *)&idle0_vcpu;
161 idle0_vcpu.domain = &idle0_domain;
163 early_setup_arch(&cmdline);
165 /* We initialise the serial devices very early so we can get debugging. */
166 if (running_on_sim) hpsim_serial_init();
167 else {
168 ns16550_init(0, &ns16550_com1);
169 /* Also init com2 for Tiger4. */
170 ns16550_com2.io_base = 0x2f8;
171 ns16550_com2.irq = 3;
172 ns16550_init(1, &ns16550_com2);
173 }
174 serial_init_preirq();
176 init_console();
177 set_printk_prefix("(XEN) ");
179 /* xenheap should be in same TR-covered range with xen image */
180 xenheap_phys_end = xen_pstart + xenheap_size;
181 printk("xen image pstart: 0x%lx, xenheap pend: 0x%lx\n",
182 xen_pstart, xenheap_phys_end);
184 /* Find next hole */
185 firsthole_start = 0;
186 efi_memmap_walk(xen_find_first_hole, &firsthole_start);
188 initial_images_start = xenheap_phys_end;
189 initial_images_end = initial_images_start + ia64_boot_param->initrd_size;
191 /* Later may find another memory trunk, even away from xen image... */
192 if (initial_images_end > firsthole_start) {
193 printk("Not enough memory to stash the DOM0 kernel image.\n");
194 printk("First hole:0x%lx, relocation end: 0x%lx\n",
195 firsthole_start, initial_images_end);
196 for ( ; ; );
197 }
199 /* This copy is time consuming, but elilo may load Dom0 image
200 * within xenheap range */
201 printk("ready to move Dom0 to 0x%lx...", initial_images_start);
202 memmove(__va(initial_images_start),
203 __va(ia64_boot_param->initrd_start),
204 ia64_boot_param->initrd_size);
205 ia64_boot_param->initrd_start = initial_images_start;
206 printk("Done\n");
208 /* first find highest page frame number */
209 max_page = 0;
210 efi_memmap_walk(find_max_pfn, &max_page);
211 printf("find_memory: efi_memmap_walk returns max_page=%lx\n",max_page);
213 heap_start = memguard_init(ia64_imva(&_end));
214 printf("Before heap_start: 0x%lx\n", heap_start);
215 heap_start = __va(init_boot_allocator(__pa(heap_start)));
216 printf("After heap_start: 0x%lx\n", heap_start);
218 reserve_memory();
220 efi_memmap_walk(filter_rsvd_memory, init_boot_pages);
221 efi_memmap_walk(xen_count_pages, &nr_pages);
223 printk("System RAM: %luMB (%lukB)\n",
224 nr_pages >> (20 - PAGE_SHIFT),
225 nr_pages << (PAGE_SHIFT - 10));
227 init_frametable();
229 ia64_fph_enable();
230 __ia64_init_fpu();
232 alloc_dom0();
233 #ifdef DOMU_BUILD_STAGING
234 alloc_domU_staging();
235 #endif
237 end_boot_allocator();
239 init_xenheap_pages(__pa(heap_start), xenheap_phys_end);
240 printk("Xen heap: %luMB (%lukB)\n",
241 (xenheap_phys_end-__pa(heap_start)) >> 20,
242 (xenheap_phys_end-__pa(heap_start)) >> 10);
244 late_setup_arch(&cmdline);
245 setup_per_cpu_areas();
246 mem_init();
248 printk("About to call scheduler_init()\n");
249 scheduler_init();
250 local_irq_disable();
251 printk("About to call xen_time_init()\n");
252 xen_time_init();
253 #ifdef CONFIG_VTI
254 init_xen_time(); /* initialise the time */
255 #endif // CONFIG_VTI
256 printk("About to call ac_timer_init()\n");
257 ac_timer_init();
258 // init_xen_time(); ???
259 schedulers_start();
260 do_initcalls();
261 printk("About to call sort_main_extable()\n");
262 sort_main_extable();
264 /* surrender usage of kernel registers to domain, use percpu area instead */
265 __get_cpu_var(cpu_kr)._kr[IA64_KR_IO_BASE] = ia64_get_kr(IA64_KR_IO_BASE);
266 __get_cpu_var(cpu_kr)._kr[IA64_KR_PER_CPU_DATA] = ia64_get_kr(IA64_KR_PER_CPU_DATA);
267 __get_cpu_var(cpu_kr)._kr[IA64_KR_CURRENT_STACK] = ia64_get_kr(IA64_KR_CURRENT_STACK);
268 __get_cpu_var(cpu_kr)._kr[IA64_KR_FPU_OWNER] = ia64_get_kr(IA64_KR_FPU_OWNER);
269 __get_cpu_var(cpu_kr)._kr[IA64_KR_CURRENT] = ia64_get_kr(IA64_KR_CURRENT);
270 __get_cpu_var(cpu_kr)._kr[IA64_KR_PT_BASE] = ia64_get_kr(IA64_KR_PT_BASE);
272 /* Create initial domain 0. */
273 printk("About to call do_createdomain()\n");
274 dom0 = do_createdomain(0, 0);
275 init_task.domain = &idle0_domain;
276 init_task.processor = 0;
277 // init_task.mm = &init_mm;
278 init_task.domain->arch.mm = &init_mm;
279 // init_task.thread = INIT_THREAD;
280 //arch_do_createdomain(current);
281 #ifdef CLONE_DOMAIN0
282 {
283 int i;
284 for (i = 0; i < CLONE_DOMAIN0; i++) {
285 clones[i] = do_createdomain(i+1, 0);
286 if ( clones[i] == NULL )
287 panic("Error creating domain0 clone %d\n",i);
288 }
289 }
290 #endif
291 if ( dom0 == NULL )
292 panic("Error creating domain 0\n");
294 set_bit(_DOMF_privileged, &dom0->domain_flags);
296 /*
297 * We're going to setup domain0 using the module(s) that we stashed safely
298 * above our heap. The second module, if present, is an initrd ramdisk.
299 */
300 printk("About to call construct_dom0()\n");
301 dom0_memory_start = __va(ia64_boot_param->initrd_start);
302 dom0_memory_end = ia64_boot_param->initrd_size;
303 if ( construct_dom0(dom0, dom0_memory_start, dom0_memory_end,
304 0,
305 0,
306 0) != 0)
307 panic("Could not set up DOM0 guest OS\n");
308 #ifdef CLONE_DOMAIN0
309 {
310 int i;
311 dom0_memory_start = __va(ia64_boot_param->initrd_start);
312 dom0_memory_end = ia64_boot_param->initrd_size;
313 for (i = 0; i < CLONE_DOMAIN0; i++) {
314 printk("CONSTRUCTING DOMAIN0 CLONE #%d\n",i+1);
315 if ( construct_domU(clones[i], dom0_memory_start, dom0_memory_end,
316 0,
317 0,
318 0) != 0)
319 panic("Could not set up DOM0 clone %d\n",i);
320 }
321 }
322 #endif
324 /* The stash space for the initial kernel image can now be freed up. */
325 init_domheap_pages(ia64_boot_param->initrd_start,
326 ia64_boot_param->initrd_start + ia64_boot_param->initrd_size);
327 if (!running_on_sim) // slow on ski and pages are pre-initialized to zero
328 scrub_heap_pages();
330 printk("About to call init_trace_bufs()\n");
331 init_trace_bufs();
333 /* Give up the VGA console if DOM0 is configured to grab it. */
334 #ifndef IA64
335 console_endboot(cmdline && strstr(cmdline, "tty0"));
336 #endif
338 #ifdef CLONE_DOMAIN0
339 {
340 int i;
341 for (i = 0; i < CLONE_DOMAIN0; i++)
342 domain_unpause_by_systemcontroller(clones[i]);
343 }
344 #endif
345 domain_unpause_by_systemcontroller(dom0);
346 domain0_ready = 1;
347 local_irq_enable();
348 printk("About to call startup_cpu_idle_loop()\n");
349 startup_cpu_idle_loop();
350 }