direct-io.hg

view xen/arch/powerpc/setup.c @ 11379:215d5eae720c

[XEN][POWERPC] restructure RMA code to allow dom0 tools to allocate in the future
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
author Hollis Blanchard <hollisb@us.ibm.com>
date Fri Aug 25 14:48:07 2006 -0500 (2006-08-25)
parents 20c988c92bee
children 18ce855ff594
line source
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * Copyright (C) IBM Corp. 2005, 2006
17 *
18 * Authors: Jimi Xenidis <jimix@watson.ibm.com>
19 */
21 #include <xen/config.h>
22 #include <xen/init.h>
23 #include <xen/lib.h>
24 #include <xen/cpumask.h>
25 #include <xen/sched.h>
26 #include <xen/multiboot.h>
27 #include <xen/serial.h>
28 #include <xen/softirq.h>
29 #include <xen/console.h>
30 #include <xen/trace.h>
31 #include <xen/mm.h>
32 #include <xen/domain.h>
33 #include <xen/gdbstub.h>
34 #include <xen/symbols.h>
35 #include <xen/keyhandler.h>
36 #include <acm/acm_hooks.h>
37 #include <public/version.h>
38 #include <asm/processor.h>
39 #include <asm/desc.h>
40 #include <asm/cache.h>
41 #include <asm/debugger.h>
42 #include <asm/delay.h>
43 #include <asm/percpu.h>
44 #include "exceptions.h"
45 #include "of-devtree.h"
46 #include "oftree.h"
48 #define DEBUG
50 /* opt_noht: If true, Hyperthreading is ignored. */
51 int opt_noht = 0;
52 boolean_param("noht", opt_noht);
54 int opt_earlygdb = 0;
55 boolean_param("earlygdb", opt_earlygdb);
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 u32 tlbflush_clock = 1U;
66 DEFINE_PER_CPU(u32, tlbflush_time);
68 unsigned int watchdog_on;
69 unsigned long wait_init_idle;
70 ulong oftree;
71 ulong oftree_len;
72 ulong oftree_end;
74 cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
75 cpumask_t cpu_online_map; /* missing ifdef in schedule.c */
76 cpumask_t cpu_present_map;
78 /* XXX get this from ISA node in device tree */
79 ulong isa_io_base;
80 struct ns16550_defaults ns16550;
82 extern char __per_cpu_start[], __per_cpu_data_end[], __per_cpu_end[];
83 extern void idle_loop(void);
85 /* move us to a header file */
86 extern void initialize_keytable(void);
88 volatile struct processor_area * volatile global_cpu_table[NR_CPUS];
90 int is_kernel_text(unsigned long addr)
91 {
92 if (addr >= (unsigned long) &_start &&
93 addr <= (unsigned long) &_etext)
94 return 1;
95 return 0;
96 }
98 unsigned long kernel_text_end(void)
99 {
100 return (unsigned long) &_etext;
101 }
103 void idle_loop(void)
104 {
105 int cpu = smp_processor_id();
107 for ( ; ; )
108 {
109 while (!softirq_pending(cpu)) {
110 void sleep(void);
111 page_scrub_schedule_work();
112 sleep();
113 }
114 do_softirq();
115 }
116 }
118 static void __init do_initcalls(void)
119 {
120 initcall_t *call;
121 for (call = &__initcall_start; call < &__initcall_end; call++) {
122 (*call)();
123 }
124 }
126 static void hw_probe_attn(unsigned char key, struct cpu_user_regs *regs)
127 {
128 /* To continue the probe will step over the ATTN instruction. The
129 * NOP is there to make sure there is something sane to "step
130 * over" to. */
131 asm volatile(".long 0x00000200; nop");
132 }
134 static void percpu_init_areas(void)
135 {
136 unsigned int i, data_size = __per_cpu_data_end - __per_cpu_start;
138 BUG_ON(data_size > PERCPU_SIZE);
140 for ( i = 1; i < NR_CPUS; i++ )
141 memcpy(__per_cpu_start + (i << PERCPU_SHIFT),
142 __per_cpu_start,
143 data_size);
144 }
146 static void percpu_free_unused_areas(void)
147 {
148 unsigned int i, first_unused;
150 /* Find first unused CPU number. */
151 for ( i = 0; i < NR_CPUS; i++ )
152 if ( !cpu_online(i) )
153 break;
154 first_unused = i;
156 /* Check that there are no holes in cpu_online_map. */
157 for ( ; i < NR_CPUS; i++ )
158 BUG_ON(cpu_online(i));
160 init_xenheap_pages((ulong)__per_cpu_start + (first_unused << PERCPU_SHIFT),
161 (ulong)__per_cpu_end);
162 }
164 static void __init start_of_day(void)
165 {
166 struct domain *idle_domain;
168 init_IRQ();
170 scheduler_init();
172 /* create idle domain */
173 idle_domain = domain_create(IDLE_DOMAIN_ID);
174 if ((idle_domain == NULL) || (alloc_vcpu(idle_domain, 0, 0) == NULL))
175 BUG();
176 set_current(idle_domain->vcpu[0]);
177 idle_vcpu[0] = current;
179 /* for some reason we need to set our own bit in the thread map */
180 cpu_set(0, cpu_sibling_map[0]);
182 percpu_free_unused_areas();
184 {
185 /* FIXME: Xen assumes that an online CPU is a schedualable
186 * CPU, but we just are not there yet. Remove this fragment when
187 * scheduling processors actually works. */
188 int cpuid;
190 printk("WARNING!: Taking all secondary CPUs offline\n");
192 for_each_online_cpu(cpuid) {
193 if (cpuid == 0)
194 continue;
195 cpu_clear(cpuid, cpu_online_map);
196 }
197 }
199 initialize_keytable();
200 /* Register another key that will allow for the the Harware Probe
201 * to be contacted, this works with RiscWatch probes and should
202 * work with Chronos and FSPs */
203 register_irq_keyhandler('^', hw_probe_attn, "Trap to Hardware Probe");
205 timer_init();
206 serial_init_postirq();
207 do_initcalls();
208 schedulers_start();
209 }
211 void startup_cpu_idle_loop(void)
212 {
213 struct vcpu *v = current;
215 ASSERT(is_idle_vcpu(v));
216 cpu_set(smp_processor_id(), v->domain->domain_dirty_cpumask);
217 cpu_set(smp_processor_id(), v->vcpu_dirty_cpumask);
219 /* Finally get off the boot stack. */
220 reset_stack_and_jump(idle_loop);
221 }
223 static void init_parea(int cpuid)
224 {
225 /* Be careful not to shadow the global variable. */
226 volatile struct processor_area *pa;
227 void *stack;
229 pa = xmalloc(struct processor_area);
230 if (pa == NULL)
231 panic("%s: failed to allocate parea for cpu #%d\n", __func__, cpuid);
233 stack = alloc_xenheap_pages(STACK_ORDER);
234 if (stack == NULL)
235 panic("%s: failed to allocate stack (order %d) for cpu #%d\n",
236 __func__, STACK_ORDER, cpuid);
238 pa->whoami = cpuid;
239 pa->hyp_stack_base = (void *)((ulong)stack + STACK_SIZE);
241 /* This store has the effect of invoking secondary_cpu_init. */
242 global_cpu_table[cpuid] = pa;
243 mb();
244 }
246 static int kick_secondary_cpus(int maxcpus)
247 {
248 int cpuid;
250 for_each_present_cpu(cpuid) {
251 if (cpuid == 0)
252 continue;
253 if (cpuid >= maxcpus)
254 break;
255 init_parea(cpuid);
256 cpu_set(cpuid, cpu_online_map);
257 }
259 return 0;
260 }
262 /* This is the first C code that secondary processors invoke. */
263 int secondary_cpu_init(int cpuid, unsigned long r4);
264 int secondary_cpu_init(int cpuid, unsigned long r4)
265 {
266 cpu_initialize(cpuid);
267 while(1);
268 }
270 static void __init __start_xen(multiboot_info_t *mbi)
271 {
272 char *cmdline;
273 module_t *mod = (module_t *)((ulong)mbi->mods_addr);
274 ulong dom0_start, dom0_len;
275 ulong initrd_start, initrd_len;
277 memcpy(0, exception_vectors, exception_vectors_end - exception_vectors);
278 synchronize_caches(0, exception_vectors_end - exception_vectors);
280 ticks_per_usec = timebase_freq / 1000000ULL;
282 /* Parse the command-line options. */
283 if ((mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0))
284 cmdline_parse(__va((ulong)mbi->cmdline));
286 /* We initialise the serial devices very early so we can get debugging. */
287 ns16550.io_base = 0x3f8;
288 ns16550_init(0, &ns16550);
289 ns16550.io_base = 0x2f8;
290 ns16550_init(1, &ns16550);
291 serial_init_preirq();
293 init_console();
294 #ifdef CONSOLE_SYNC
295 console_start_sync();
296 #endif
298 /* we give the first RMA to the hypervisor */
299 xenheap_phys_end = rma_size(cpu_default_rma_order_pages());
301 /* Check that we have at least one Multiboot module. */
302 if (!(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0)) {
303 panic("FATAL ERROR: Require at least one Multiboot module.\n");
304 }
306 if (!(mbi->flags & MBI_MEMMAP)) {
307 panic("FATAL ERROR: Bootloader provided no memory information.\n");
308 }
310 /* OF dev tree is the last module */
311 oftree = mod[mbi->mods_count-1].mod_start;
312 oftree_end = mod[mbi->mods_count-1].mod_end;
313 oftree_len = oftree_end - oftree;
315 /* remove it from consideration */
316 mod[mbi->mods_count-1].mod_start = 0;
317 mod[mbi->mods_count-1].mod_end = 0;
318 --mbi->mods_count;
320 memory_init(mod, mbi->mods_count);
322 #ifdef OF_DEBUG
323 printk("ofdump:\n");
324 /* make sure the OF devtree is good */
325 ofd_walk((void *)oftree, OFD_ROOT, ofd_dump_props, OFD_DUMP_ALL);
326 #endif
328 percpu_init_areas();
330 init_parea(0);
331 cpu_initialize(0);
333 #ifdef CONFIG_GDB
334 initialise_gdb();
335 if (opt_earlygdb)
336 debugger_trap_immediate();
337 #endif
339 /* Deal with secondary processors. */
340 if (opt_nosmp) {
341 printk("nosmp: leaving secondary processors spinning forever\n");
342 } else {
343 printk("spinning up at most %d total processors ...\n", max_cpus);
344 kick_secondary_cpus(max_cpus);
345 }
347 start_of_day();
349 /* Create initial domain 0. */
350 dom0 = domain_create(0);
351 if ((dom0 == NULL) || (alloc_vcpu(dom0, 0, 0) == NULL))
352 panic("Error creating domain 0\n");
354 set_bit(_DOMF_privileged, &dom0->domain_flags);
355 /* post-create hooks sets security label */
356 acm_post_domain0_create(dom0->domain_id);
358 cmdline = (char *)(mod[0].string ? __va((ulong)mod[0].string) : NULL);
360 /* scrub_heap_pages() requires IRQs enabled, and we're post IRQ setup... */
361 local_irq_enable();
362 /* Scrub RAM that is still free and so may go to an unprivileged domain. */
363 scrub_heap_pages();
365 dom0_start = mod[0].mod_start;
366 dom0_len = mod[0].mod_end - mod[0].mod_start;
367 if (mbi->mods_count > 1) {
368 initrd_start = mod[1].mod_start;
369 initrd_len = mod[1].mod_end - mod[1].mod_start;
370 } else {
371 initrd_start = 0;
372 initrd_len = 0;
373 }
374 if (construct_dom0(dom0, dom0_start, dom0_len,
375 initrd_start, initrd_len,
376 cmdline) != 0) {
377 panic("Could not set up DOM0 guest OS\n");
378 }
380 init_xenheap_pages(ALIGN_UP(dom0_start, PAGE_SIZE),
381 ALIGN_DOWN(dom0_start + dom0_len, PAGE_SIZE));
382 if (initrd_start)
383 init_xenheap_pages(ALIGN_UP(initrd_start, PAGE_SIZE),
384 ALIGN_DOWN(initrd_start + initrd_len, PAGE_SIZE));
386 init_trace_bufs();
388 console_endboot();
390 /* Hide UART from DOM0 if we're using it */
391 serial_endboot();
393 domain_unpause_by_systemcontroller(dom0);
395 startup_cpu_idle_loop();
396 }
398 void __init __start_xen_ppc(
399 ulong r3, ulong r4, ulong r5, ulong r6, ulong r7, ulong orig_msr)
400 {
401 multiboot_info_t *mbi = NULL;
403 /* clear bss */
404 memset(__bss_start, 0, (ulong)_end - (ulong)__bss_start);
406 if (r5 > 0) {
407 /* we were booted by OpenFirmware */
408 mbi = boot_of_init(r3, r4, r5, r6, r7, orig_msr);
410 } else {
411 /* booted by someone else that hopefully has a trap handler */
412 trap();
413 }
415 __start_xen(mbi);
417 }
419 extern void arch_get_xen_caps(xen_capabilities_info_t info);
420 void arch_get_xen_caps(xen_capabilities_info_t info)
421 {
422 }
426 /*
427 * Local variables:
428 * mode: C
429 * c-set-style: "BSD"
430 * c-basic-offset: 4
431 * tab-width: 4
432 * indent-tabs-mode: nil
433 * End:
434 */