ia64/xen-unstable

view xen/arch/powerpc/setup.c @ 15265:da3185b03113

Enable ACM on PPC
Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
author kfraser@localhost.localdomain
date Mon Jun 04 14:40:12 2007 +0100 (2007-06-04)
parents aeac9a7d97e0
children 553f64e4f6ef
line source
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License as
4 * published by the Free Software Foundation; either version 2 of the
5 * License, or (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 IBM Corp. 2005, 2006, 2007
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 <xen/numa.h>
39 #include <xen/rcupdate.h>
40 #include <xen/version.h>
41 #include <acm/acm_hooks.h>
42 #include <public/version.h>
43 #include <asm/mpic.h>
44 #include <asm/processor.h>
45 #include <asm/desc.h>
46 #include <asm/cache.h>
47 #include <asm/debugger.h>
48 #include <asm/delay.h>
49 #include <asm/percpu.h>
50 #include <asm/io.h>
51 #include "exceptions.h"
52 #include "of-devtree.h"
53 #include "oftree.h"
54 #include "rtas.h"
56 #define DEBUG
58 /* opt_noht: If true, Hyperthreading is ignored. */
59 int opt_noht = 0;
60 boolean_param("noht", opt_noht);
62 int opt_earlygdb = 0;
63 boolean_param("earlygdb", opt_earlygdb);
65 /* opt_nosmp: If true, secondary processors are ignored. */
66 static int opt_nosmp = 0;
67 boolean_param("nosmp", opt_nosmp);
69 /* maxcpus: maximum number of CPUs to activate. */
70 static unsigned int max_cpus = NR_CPUS;
71 integer_param("maxcpus", max_cpus);
73 u32 tlbflush_clock = 1U;
74 DEFINE_PER_CPU(u32, tlbflush_time);
76 unsigned int watchdog_on;
77 unsigned long wait_init_idle;
78 ulong oftree;
79 ulong oftree_len;
80 ulong oftree_end;
82 uint cpu_hard_id[NR_CPUS] __initdata;
83 cpumask_t cpu_present_map;
85 /* XXX get this from ISA node in device tree */
86 char *vgabase;
87 ulong isa_io_base;
88 struct ns16550_defaults ns16550;
90 extern char __per_cpu_start[], __per_cpu_data_end[], __per_cpu_end[];
92 static struct domain *idle_domain;
94 volatile struct processor_area * volatile global_cpu_table[NR_CPUS];
96 static void __init do_initcalls(void)
97 {
98 initcall_t *call;
99 for (call = &__initcall_start; call < &__initcall_end; call++) {
100 (*call)();
101 }
102 }
105 void noinline __attn(void)
106 {
107 /* To continue the probe will step over the ATTN instruction. The
108 * NOP is there to make sure there is something sane to "step
109 * over" to. */
110 console_start_sync();
111 asm volatile(".long 0x200;nop");
112 console_end_sync();
113 }
115 static void key_hw_probe_attn(unsigned char key)
116 {
117 __attn();
118 }
120 static void key_ofdump(unsigned char key)
121 {
122 printk("ofdump:\n");
123 /* make sure the OF devtree is good */
124 ofd_walk((void *)oftree, "devtree", OFD_ROOT,
125 ofd_dump_props, OFD_DUMP_ALL);
126 }
128 static void percpu_init_areas(void)
129 {
130 unsigned int i, data_size = __per_cpu_data_end - __per_cpu_start;
132 BUG_ON(data_size > PERCPU_SIZE);
134 for ( i = 1; i < NR_CPUS; i++ )
135 memcpy(__per_cpu_start + (i << PERCPU_SHIFT),
136 __per_cpu_start,
137 data_size);
138 }
140 static void percpu_free_unused_areas(void)
141 {
142 unsigned int i, first_unused;
144 /* Find first unused CPU number. */
145 for ( i = 0; i < NR_CPUS; i++ )
146 if ( !cpu_online(i) )
147 break;
148 first_unused = i;
150 /* Check that there are no holes in cpu_online_map. */
151 for ( ; i < NR_CPUS; i++ )
152 BUG_ON(cpu_online(i));
154 init_xenheap_pages((ulong)__per_cpu_start + (first_unused << PERCPU_SHIFT),
155 (ulong)__per_cpu_end);
156 }
158 static void __init start_of_day(void)
159 {
160 init_IRQ();
162 scheduler_init();
164 /* create idle domain */
165 idle_domain = domain_create(IDLE_DOMAIN_ID, 0, 0);
166 if ((idle_domain == NULL) || (alloc_vcpu(idle_domain, 0, 0) == NULL))
167 BUG();
168 set_current(idle_domain->vcpu[0]);
169 idle_vcpu[0] = current;
171 initialize_keytable();
172 /* Register another key that will allow for the the Harware Probe
173 * to be contacted, this works with RiscWatch probes and should
174 * work with Chronos and FSPs */
175 register_keyhandler('^', key_hw_probe_attn, "Trap to Hardware Probe");
177 /* allow the dumping of the devtree */
178 register_keyhandler('D', key_ofdump , "Dump OF Devtree");
180 timer_init();
181 rcu_init();
182 serial_init_postirq();
183 do_initcalls();
184 }
186 void startup_cpu_idle_loop(void)
187 {
188 struct vcpu *v = current;
190 ASSERT(is_idle_vcpu(v));
191 cpu_set(smp_processor_id(), v->domain->domain_dirty_cpumask);
192 cpu_set(smp_processor_id(), v->vcpu_dirty_cpumask);
194 /* Finally get off the boot stack. */
195 reset_stack_and_jump(idle_loop);
196 }
198 /* The boot_pa is enough "parea" for the boot CPU to get thru
199 * initialization, it will ultimately get replaced later */
200 static __init void init_boot_cpu(void)
201 {
202 static struct processor_area boot_pa;
203 boot_pa.whoami = 0;
204 parea = &boot_pa;
205 }
207 static void init_parea(int cpuid)
208 {
209 /* Be careful not to shadow the global variable. */
210 volatile struct processor_area *pa;
211 void *stack;
213 pa = xmalloc(struct processor_area);
214 if (pa == NULL)
215 panic("%s: failed to allocate parea for cpu #%d\n", __func__, cpuid);
217 stack = alloc_xenheap_pages(STACK_ORDER);
218 if (stack == NULL)
219 panic("%s: failed to allocate stack (order %d) for cpu #%d\n",
220 __func__, STACK_ORDER, cpuid);
222 pa->whoami = cpuid;
223 pa->hard_id = cpu_hard_id[cpuid];
224 pa->hyp_stack_base = (void *)((ulong)stack + STACK_SIZE);
225 mb();
227 /* This store has the effect of invoking secondary_cpu_init. */
228 global_cpu_table[cpuid] = pa;
229 mb();
230 }
232 static int kick_secondary_cpus(int maxcpus)
233 {
234 int cpuid;
236 for_each_present_cpu(cpuid) {
237 int threads;
238 int i;
240 threads = cpu_threads(cpuid);
241 for (i = 0; i < threads; i++)
242 cpu_set(i, cpu_sibling_map[cpuid]);
244 /* For now everything is single core */
245 cpu_set(cpuid, cpu_core_map[cpuid]);
247 rcu_online_cpu(cpuid);
249 numa_set_node(cpuid, 0);
250 numa_add_cpu(cpuid);
252 if (cpuid == 0)
253 continue;
254 if (cpuid >= maxcpus)
255 break;
256 init_parea(cpuid);
257 smp_generic_give_timebase();
259 /* wait for it */
260 while (!cpu_online(cpuid))
261 cpu_relax();
262 }
264 return 0;
265 }
267 /* This is the first C code that secondary processors invoke. */
268 void secondary_cpu_init(int cpuid, unsigned long r4)
269 {
270 struct vcpu *vcpu;
272 cpu_initialize(cpuid);
273 smp_generic_take_timebase();
275 /* If we are online, we must be able to ACK IPIs. */
276 mpic_setup_this_cpu();
277 cpu_set(cpuid, cpu_online_map);
279 vcpu = alloc_vcpu(idle_domain, cpuid, cpuid);
280 BUG_ON(vcpu == NULL);
282 set_current(idle_domain->vcpu[cpuid]);
283 idle_vcpu[cpuid] = current;
284 startup_cpu_idle_loop();
286 panic("should never get here\n");
287 }
289 static void __init __start_xen(multiboot_info_t *mbi)
290 {
291 char *cmdline;
292 module_t *mod = (module_t *)((ulong)mbi->mods_addr);
293 ulong dom0_start, dom0_len;
294 ulong initrd_start, initrd_len;
296 memcpy(0, exception_vectors, exception_vectors_end - exception_vectors);
297 synchronize_caches(0, exception_vectors_end - exception_vectors);
299 ticks_per_usec = timebase_freq / 1000000ULL;
301 /* Parse the command-line options. */
302 if ((mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0))
303 cmdline_parse(__va((ulong)mbi->cmdline));
305 /* we need to be able to identify this CPU early on */
306 init_boot_cpu();
308 /* We initialise the serial devices very early so we can get debugging. */
309 ns16550.io_base = 0x3f8;
310 ns16550_init(0, &ns16550);
311 ns16550.io_base = 0x2f8;
312 ns16550_init(1, &ns16550);
313 serial_init_preirq();
315 init_console();
316 /* let synchronize until we really get going */
317 console_start_sync();
319 /* Check that we have at least one Multiboot module. */
320 if (!(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0)) {
321 panic("FATAL ERROR: Require at least one Multiboot module.\n");
322 }
324 /* OF dev tree is the last module */
325 oftree = mod[mbi->mods_count-1].mod_start;
326 oftree_end = mod[mbi->mods_count-1].mod_end;
327 oftree_len = oftree_end - oftree;
329 /* remove it from consideration */
330 mod[mbi->mods_count-1].mod_start = 0;
331 mod[mbi->mods_count-1].mod_end = 0;
332 --mbi->mods_count;
334 if (rtas_entry) {
335 rtas_init((void *)oftree);
336 /* remove rtas module from consideration */
337 mod[mbi->mods_count-1].mod_start = 0;
338 mod[mbi->mods_count-1].mod_end = 0;
339 --mbi->mods_count;
340 }
341 memory_init(mod, mbi->mods_count);
343 #ifdef OF_DEBUG
344 key_ofdump(0);
345 #endif
346 percpu_init_areas();
348 init_parea(0);
349 cpu_initialize(0);
351 #ifdef CONFIG_GDB
352 initialise_gdb();
353 if (opt_earlygdb)
354 debugger_trap_immediate();
355 #endif
357 start_of_day();
359 acm_init(NULL, 0);
361 mpic_setup_this_cpu();
363 /* Deal with secondary processors. */
364 if (opt_nosmp || ofd_boot_cpu == -1) {
365 printk("nosmp: leaving secondary processors spinning forever\n");
366 } else {
367 printk("spinning up at most %d total processors ...\n", max_cpus);
368 kick_secondary_cpus(max_cpus);
369 }
371 /* This cannot be called before secondary cpus are marked online. */
372 percpu_free_unused_areas();
374 /* Create initial domain 0. */
375 dom0 = domain_create(0, 0, DOM0_SSIDREF);
376 if (dom0 == NULL)
377 panic("Error creating domain 0\n");
379 /* The Interrupt Controller will route everything to CPU 0 so we
380 * need to make sure Dom0's vVCPU 0 is pinned to the CPU */
381 dom0->vcpu[0]->cpu_affinity = cpumask_of_cpu(0);
383 dom0->is_privileged = 1;
385 cmdline = (char *)(mod[0].string ? __va((ulong)mod[0].string) : NULL);
387 /* scrub_heap_pages() requires IRQs enabled, and we're post IRQ setup... */
388 local_irq_enable();
389 /* Scrub RAM that is still free and so may go to an unprivileged domain. */
390 scrub_heap_pages();
392 dom0_start = mod[0].mod_start;
393 dom0_len = mod[0].mod_end - mod[0].mod_start;
394 if (mbi->mods_count > 1) {
395 initrd_start = mod[1].mod_start;
396 initrd_len = mod[1].mod_end - mod[1].mod_start;
397 } else {
398 initrd_start = 0;
399 initrd_len = 0;
400 }
401 if (construct_dom0(dom0, dom0_start, dom0_len,
402 initrd_start, initrd_len,
403 cmdline) != 0) {
404 panic("Could not set up DOM0 guest OS\n");
405 }
407 init_xenheap_pages(ALIGN_UP(dom0_start, PAGE_SIZE),
408 ALIGN_DOWN(dom0_start + dom0_len, PAGE_SIZE));
409 if (initrd_start)
410 init_xenheap_pages(ALIGN_UP(initrd_start, PAGE_SIZE),
411 ALIGN_DOWN(initrd_start + initrd_len, PAGE_SIZE));
413 init_trace_bufs();
415 console_endboot();
417 /* Hide UART from DOM0 if we're using it */
418 serial_endboot();
420 console_end_sync();
422 domain_unpause_by_systemcontroller(dom0);
423 #ifdef DEBUG_IPI
424 ipi_torture_test();
425 #endif
426 startup_cpu_idle_loop();
427 }
429 void __init __start_xen_ppc(
430 ulong r3, ulong r4, ulong r5, ulong r6, ulong r7, ulong orig_msr)
431 {
432 multiboot_info_t *mbi = NULL;
434 /* clear bss */
435 memset(__bss_start, 0, (ulong)_end - (ulong)__bss_start);
437 if (r5 > 0) {
438 /* we were booted by OpenFirmware */
439 mbi = boot_of_init(r3, r4, r5, r6, r7, orig_msr);
441 } else {
442 /* booted by someone else that hopefully has a trap handler */
443 __builtin_trap();
444 }
446 __start_xen(mbi);
448 }
450 extern void arch_get_xen_caps(xen_capabilities_info_t *info);
451 void arch_get_xen_caps(xen_capabilities_info_t *info)
452 {
453 /* Interface name is always xen-3.0-* for Xen-3.x. */
454 int major = 3, minor = 0;
455 char s[32];
457 (*info)[0] = '\0';
459 snprintf(s, sizeof(s), "xen-%d.%d-powerpc64 ", major, minor);
460 safe_strcat(*info, s);
461 }
465 /*
466 * Local variables:
467 * mode: C
468 * c-set-style: "BSD"
469 * c-basic-offset: 4
470 * tab-width: 4
471 * indent-tabs-mode: nil
472 * End:
473 */