direct-io.hg

view xen/arch/powerpc/setup.c @ 12945:0ff8b14fb530

[XEN][POWERPC] Support your older compilers

gcc 3.3.x doesn't like some instructions we are using so lets dum them
down a bit.

Signed-off-by: Jimi Xenidis <jimix@watson.ibm.com>
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
author jimix@localhost.localdomain
date Thu Oct 12 17:09:19 2006 -0400 (2006-10-12)
parents d6ec02744592
children 5909f57c8c39
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 * Amos Waterland <apw@us.ibm.com>
20 * Hollis Blanchard <hollisb@us.ibm.com>
21 */
23 #include <xen/config.h>
24 #include <xen/init.h>
25 #include <xen/lib.h>
26 #include <xen/cpumask.h>
27 #include <xen/sched.h>
28 #include <xen/multiboot.h>
29 #include <xen/serial.h>
30 #include <xen/softirq.h>
31 #include <xen/console.h>
32 #include <xen/trace.h>
33 #include <xen/mm.h>
34 #include <xen/domain.h>
35 #include <xen/gdbstub.h>
36 #include <xen/symbols.h>
37 #include <xen/keyhandler.h>
38 #include <acm/acm_hooks.h>
39 #include <public/version.h>
40 #include <asm/processor.h>
41 #include <asm/desc.h>
42 #include <asm/cache.h>
43 #include <asm/debugger.h>
44 #include <asm/delay.h>
45 #include <asm/percpu.h>
46 #include <asm/io.h>
47 #include "exceptions.h"
48 #include "of-devtree.h"
49 #include "oftree.h"
50 #include "rtas.h"
52 #define DEBUG
54 /* opt_noht: If true, Hyperthreading is ignored. */
55 int opt_noht = 0;
56 boolean_param("noht", opt_noht);
58 int opt_earlygdb = 0;
59 boolean_param("earlygdb", opt_earlygdb);
61 /* opt_nosmp: If true, secondary processors are ignored. */
62 static int opt_nosmp = 0;
63 boolean_param("nosmp", opt_nosmp);
65 /* maxcpus: maximum number of CPUs to activate. */
66 static unsigned int max_cpus = NR_CPUS;
67 integer_param("maxcpus", max_cpus);
69 u32 tlbflush_clock = 1U;
70 DEFINE_PER_CPU(u32, tlbflush_time);
72 unsigned int watchdog_on;
73 unsigned long wait_init_idle;
74 ulong oftree;
75 ulong oftree_len;
76 ulong oftree_end;
78 uint cpu_hard_id[NR_CPUS] __initdata;
79 cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
80 cpumask_t cpu_online_map; /* missing ifdef in schedule.c */
81 cpumask_t cpu_present_map;
82 cpumask_t cpu_possible_map;
84 /* XXX get this from ISA node in device tree */
85 char *vgabase;
86 ulong isa_io_base;
87 struct ns16550_defaults ns16550;
89 extern char __per_cpu_start[], __per_cpu_data_end[], __per_cpu_end[];
91 volatile struct processor_area * volatile global_cpu_table[NR_CPUS];
93 int is_kernel_text(unsigned long addr)
94 {
95 if (addr >= (unsigned long) &_start &&
96 addr <= (unsigned long) &_etext)
97 return 1;
98 return 0;
99 }
101 unsigned long kernel_text_end(void)
102 {
103 return (unsigned long) &_etext;
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 }
112 }
115 void noinline __attn(void)
116 {
117 /* To continue the probe will step over the ATTN instruction. The
118 * NOP is there to make sure there is something sane to "step
119 * over" to. */
120 console_start_sync();
121 asm volatile(".long 0x200;nop");
122 console_end_sync();
123 }
125 static void hw_probe_attn(unsigned char key, struct cpu_user_regs *regs)
126 {
127 __attn();
128 }
130 static void percpu_init_areas(void)
131 {
132 unsigned int i, data_size = __per_cpu_data_end - __per_cpu_start;
134 BUG_ON(data_size > PERCPU_SIZE);
136 for ( i = 1; i < NR_CPUS; i++ )
137 memcpy(__per_cpu_start + (i << PERCPU_SHIFT),
138 __per_cpu_start,
139 data_size);
140 }
142 static void percpu_free_unused_areas(void)
143 {
144 unsigned int i, first_unused;
146 /* Find first unused CPU number. */
147 for ( i = 0; i < NR_CPUS; i++ )
148 if ( !cpu_online(i) )
149 break;
150 first_unused = i;
152 /* Check that there are no holes in cpu_online_map. */
153 for ( ; i < NR_CPUS; i++ )
154 BUG_ON(cpu_online(i));
156 init_xenheap_pages((ulong)__per_cpu_start + (first_unused << PERCPU_SHIFT),
157 (ulong)__per_cpu_end);
158 }
160 static void __init start_of_day(void)
161 {
162 struct domain *idle_domain;
164 init_IRQ();
166 scheduler_init();
168 /* create idle domain */
169 idle_domain = domain_create(IDLE_DOMAIN_ID, 0);
170 if ((idle_domain == NULL) || (alloc_vcpu(idle_domain, 0, 0) == NULL))
171 BUG();
172 set_current(idle_domain->vcpu[0]);
173 idle_vcpu[0] = current;
175 /* for some reason we need to set our own bit in the thread map */
176 cpu_set(0, cpu_sibling_map[0]);
178 percpu_free_unused_areas();
180 {
181 /* FIXME: Xen assumes that an online CPU is a schedualable
182 * CPU, but we just are not there yet. Remove this fragment when
183 * scheduling processors actually works. */
184 int cpuid;
186 printk("WARNING!: Taking all secondary CPUs offline\n");
188 for_each_online_cpu(cpuid) {
189 if (cpuid == 0)
190 continue;
191 cpu_clear(cpuid, cpu_online_map);
192 }
193 }
195 initialize_keytable();
196 /* Register another key that will allow for the the Harware Probe
197 * to be contacted, this works with RiscWatch probes and should
198 * work with Chronos and FSPs */
199 register_irq_keyhandler('^', hw_probe_attn, "Trap to Hardware Probe");
201 timer_init();
202 serial_init_postirq();
203 do_initcalls();
204 schedulers_start();
205 }
207 void startup_cpu_idle_loop(void)
208 {
209 struct vcpu *v = current;
211 ASSERT(is_idle_vcpu(v));
212 cpu_set(smp_processor_id(), v->domain->domain_dirty_cpumask);
213 cpu_set(smp_processor_id(), v->vcpu_dirty_cpumask);
215 /* Finally get off the boot stack. */
216 reset_stack_and_jump(idle_loop);
217 }
219 static void init_parea(int cpuid)
220 {
221 /* Be careful not to shadow the global variable. */
222 volatile struct processor_area *pa;
223 void *stack;
225 pa = xmalloc(struct processor_area);
226 if (pa == NULL)
227 panic("%s: failed to allocate parea for cpu #%d\n", __func__, cpuid);
229 stack = alloc_xenheap_pages(STACK_ORDER);
230 if (stack == NULL)
231 panic("%s: failed to allocate stack (order %d) for cpu #%d\n",
232 __func__, STACK_ORDER, cpuid);
234 pa->whoami = cpuid;
235 pa->hard_id = cpu_hard_id[cpuid];
236 pa->hyp_stack_base = (void *)((ulong)stack + STACK_SIZE);
238 /* This store has the effect of invoking secondary_cpu_init. */
239 global_cpu_table[cpuid] = pa;
240 mb();
241 }
243 static int kick_secondary_cpus(int maxcpus)
244 {
245 int cpuid;
247 for_each_present_cpu(cpuid) {
248 if (cpuid == 0)
249 continue;
250 if (cpuid >= maxcpus)
251 break;
252 init_parea(cpuid);
253 smp_generic_give_timebase();
255 /* wait for it */
256 while (!cpu_online(cpuid))
257 cpu_relax();
258 }
260 return 0;
261 }
263 /* This is the first C code that secondary processors invoke. */
264 int secondary_cpu_init(int cpuid, unsigned long r4)
265 {
266 cpu_initialize(cpuid);
267 smp_generic_take_timebase();
268 cpu_set(cpuid, cpu_online_map);
269 while(1);
270 }
272 static void __init __start_xen(multiboot_info_t *mbi)
273 {
274 char *cmdline;
275 module_t *mod = (module_t *)((ulong)mbi->mods_addr);
276 ulong dom0_start, dom0_len;
277 ulong initrd_start, initrd_len;
279 memcpy(0, exception_vectors, exception_vectors_end - exception_vectors);
280 synchronize_caches(0, exception_vectors_end - exception_vectors);
282 ticks_per_usec = timebase_freq / 1000000ULL;
284 /* Parse the command-line options. */
285 if ((mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0))
286 cmdline_parse(__va((ulong)mbi->cmdline));
288 /* We initialise the serial devices very early so we can get debugging. */
289 ns16550.io_base = 0x3f8;
290 ns16550_init(0, &ns16550);
291 ns16550.io_base = 0x2f8;
292 ns16550_init(1, &ns16550);
293 serial_init_preirq();
295 init_console();
296 /* let synchronize until we really get going */
297 console_start_sync();
299 /* Check that we have at least one Multiboot module. */
300 if (!(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0)) {
301 panic("FATAL ERROR: Require at least one Multiboot module.\n");
302 }
304 if (!(mbi->flags & MBI_MEMMAP)) {
305 panic("FATAL ERROR: Bootloader provided no memory information.\n");
306 }
308 /* OF dev tree is the last module */
309 oftree = mod[mbi->mods_count-1].mod_start;
310 oftree_end = mod[mbi->mods_count-1].mod_end;
311 oftree_len = oftree_end - oftree;
313 /* remove it from consideration */
314 mod[mbi->mods_count-1].mod_start = 0;
315 mod[mbi->mods_count-1].mod_end = 0;
316 --mbi->mods_count;
318 if (rtas_entry) {
319 rtas_init((void *)oftree);
320 /* remove rtas module from consideration */
321 mod[mbi->mods_count-1].mod_start = 0;
322 mod[mbi->mods_count-1].mod_end = 0;
323 --mbi->mods_count;
324 }
325 memory_init(mod, mbi->mods_count);
327 #ifdef OF_DEBUG
328 printk("ofdump:\n");
329 /* make sure the OF devtree is good */
330 ofd_walk((void *)oftree, OFD_ROOT, ofd_dump_props, OFD_DUMP_ALL);
331 #endif
332 percpu_init_areas();
334 init_parea(0);
335 cpu_initialize(0);
337 #ifdef CONFIG_GDB
338 initialise_gdb();
339 if (opt_earlygdb)
340 debugger_trap_immediate();
341 #endif
343 /* Deal with secondary processors. */
344 if (opt_nosmp || ofd_boot_cpu == -1) {
345 printk("nosmp: leaving secondary processors spinning forever\n");
346 } else {
347 printk("spinning up at most %d total processors ...\n", max_cpus);
348 kick_secondary_cpus(max_cpus);
349 }
351 start_of_day();
353 /* Create initial domain 0. */
354 dom0 = domain_create(0, 0);
355 if (dom0 == NULL)
356 panic("Error creating domain 0\n");
357 dom0->max_pages = ~0U;
358 if (0 > allocate_rma(dom0, cpu_default_rma_order_pages()))
359 panic("Error allocating domain 0 RMA\n");
360 if (NULL == alloc_vcpu(dom0, 0, 0))
361 panic("Error creating domain 0 vcpu 0\n");
363 /* The Interrupt Controller will route everything to CPU 0 so we
364 * need to make sure Dom0's vVCPU 0 is pinned to the CPU */
365 dom0->vcpu[0]->cpu_affinity = cpumask_of_cpu(0);
367 dom0->is_privileged = 1;
369 /* Post-create hook sets security label. */
370 acm_post_domain0_create(dom0->domain_id);
372 cmdline = (char *)(mod[0].string ? __va((ulong)mod[0].string) : NULL);
374 /* scrub_heap_pages() requires IRQs enabled, and we're post IRQ setup... */
375 local_irq_enable();
376 /* Scrub RAM that is still free and so may go to an unprivileged domain. */
377 scrub_heap_pages();
379 dom0_start = mod[0].mod_start;
380 dom0_len = mod[0].mod_end - mod[0].mod_start;
381 if (mbi->mods_count > 1) {
382 initrd_start = mod[1].mod_start;
383 initrd_len = mod[1].mod_end - mod[1].mod_start;
384 } else {
385 initrd_start = 0;
386 initrd_len = 0;
387 }
388 if (construct_dom0(dom0, dom0_start, dom0_len,
389 initrd_start, initrd_len,
390 cmdline) != 0) {
391 panic("Could not set up DOM0 guest OS\n");
392 }
394 init_xenheap_pages(ALIGN_UP(dom0_start, PAGE_SIZE),
395 ALIGN_DOWN(dom0_start + dom0_len, PAGE_SIZE));
396 if (initrd_start)
397 init_xenheap_pages(ALIGN_UP(initrd_start, PAGE_SIZE),
398 ALIGN_DOWN(initrd_start + initrd_len, PAGE_SIZE));
400 init_trace_bufs();
402 console_endboot();
404 /* Hide UART from DOM0 if we're using it */
405 serial_endboot();
407 console_end_sync();
409 domain_unpause_by_systemcontroller(dom0);
410 startup_cpu_idle_loop();
411 }
413 void __init __start_xen_ppc(
414 ulong r3, ulong r4, ulong r5, ulong r6, ulong r7, ulong orig_msr)
415 {
416 multiboot_info_t *mbi = NULL;
418 /* clear bss */
419 memset(__bss_start, 0, (ulong)_end - (ulong)__bss_start);
421 if (r5 > 0) {
422 /* we were booted by OpenFirmware */
423 mbi = boot_of_init(r3, r4, r5, r6, r7, orig_msr);
425 } else {
426 /* booted by someone else that hopefully has a trap handler */
427 __builtin_trap();
428 }
430 __start_xen(mbi);
432 }
434 extern void arch_get_xen_caps(xen_capabilities_info_t info);
435 void arch_get_xen_caps(xen_capabilities_info_t info)
436 {
437 }
441 /*
442 * Local variables:
443 * mode: C
444 * c-set-style: "BSD"
445 * c-basic-offset: 4
446 * tab-width: 4
447 * indent-tabs-mode: nil
448 * End:
449 */