direct-io.hg

view xen/arch/powerpc/setup.c @ 11526:ce9c34c049c5

[POWERPC][XEN] Track the Hard CPUID as configured by the FW

This patch correctly implements and supports hard_smp_processor_id().

Signed-off-by: Jimi Xenidis <jimix@watson.ibm.com>
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
author Jimi Xenidis <jimix@watson.ibm.com>
date Mon Sep 18 09:23:51 2006 -0400 (2006-09-18)
parents 3bd92176890c
children 828c0c89d830
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"
51 #define DEBUG
53 /* opt_noht: If true, Hyperthreading is ignored. */
54 int opt_noht = 0;
55 boolean_param("noht", opt_noht);
57 int opt_earlygdb = 0;
58 boolean_param("earlygdb", opt_earlygdb);
60 /* opt_nosmp: If true, secondary processors are ignored. */
61 static int opt_nosmp = 0;
62 boolean_param("nosmp", opt_nosmp);
64 /* maxcpus: maximum number of CPUs to activate. */
65 static unsigned int max_cpus = NR_CPUS;
66 integer_param("maxcpus", max_cpus);
68 u32 tlbflush_clock = 1U;
69 DEFINE_PER_CPU(u32, tlbflush_time);
71 unsigned int watchdog_on;
72 unsigned long wait_init_idle;
73 ulong oftree;
74 ulong oftree_len;
75 ulong oftree_end;
77 uint cpu_hard_id[NR_CPUS] __initdata;
78 cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly;
79 cpumask_t cpu_online_map; /* missing ifdef in schedule.c */
80 cpumask_t cpu_present_map;
81 cpumask_t cpu_possible_map;
83 /* XXX get this from ISA node in device tree */
84 char *vgabase;
85 ulong isa_io_base;
86 struct ns16550_defaults ns16550;
88 extern char __per_cpu_start[], __per_cpu_data_end[], __per_cpu_end[];
90 /* move us to a header file */
91 extern void initialize_keytable(void);
93 volatile struct processor_area * volatile global_cpu_table[NR_CPUS];
95 int is_kernel_text(unsigned long addr)
96 {
97 if (addr >= (unsigned long) &_start &&
98 addr <= (unsigned long) &_etext)
99 return 1;
100 return 0;
101 }
103 unsigned long kernel_text_end(void)
104 {
105 return (unsigned long) &_etext;
106 }
108 static void __init do_initcalls(void)
109 {
110 initcall_t *call;
111 for (call = &__initcall_start; call < &__initcall_end; call++) {
112 (*call)();
113 }
114 }
116 static void hw_probe_attn(unsigned char key, struct cpu_user_regs *regs)
117 {
118 /* To continue the probe will step over the ATTN instruction. The
119 * NOP is there to make sure there is something sane to "step
120 * over" to. */
121 asm volatile(".long 0x00000200; nop");
122 }
124 static void percpu_init_areas(void)
125 {
126 unsigned int i, data_size = __per_cpu_data_end - __per_cpu_start;
128 BUG_ON(data_size > PERCPU_SIZE);
130 for ( i = 1; i < NR_CPUS; i++ )
131 memcpy(__per_cpu_start + (i << PERCPU_SHIFT),
132 __per_cpu_start,
133 data_size);
134 }
136 static void percpu_free_unused_areas(void)
137 {
138 unsigned int i, first_unused;
140 /* Find first unused CPU number. */
141 for ( i = 0; i < NR_CPUS; i++ )
142 if ( !cpu_online(i) )
143 break;
144 first_unused = i;
146 /* Check that there are no holes in cpu_online_map. */
147 for ( ; i < NR_CPUS; i++ )
148 BUG_ON(cpu_online(i));
150 init_xenheap_pages((ulong)__per_cpu_start + (first_unused << PERCPU_SHIFT),
151 (ulong)__per_cpu_end);
152 }
154 static void __init start_of_day(void)
155 {
156 struct domain *idle_domain;
158 init_IRQ();
160 scheduler_init();
162 /* create idle domain */
163 idle_domain = domain_create(IDLE_DOMAIN_ID);
164 if ((idle_domain == NULL) || (alloc_vcpu(idle_domain, 0, 0) == NULL))
165 BUG();
166 set_current(idle_domain->vcpu[0]);
167 idle_vcpu[0] = current;
169 /* for some reason we need to set our own bit in the thread map */
170 cpu_set(0, cpu_sibling_map[0]);
172 percpu_free_unused_areas();
174 {
175 /* FIXME: Xen assumes that an online CPU is a schedualable
176 * CPU, but we just are not there yet. Remove this fragment when
177 * scheduling processors actually works. */
178 int cpuid;
180 printk("WARNING!: Taking all secondary CPUs offline\n");
182 for_each_online_cpu(cpuid) {
183 if (cpuid == 0)
184 continue;
185 cpu_clear(cpuid, cpu_online_map);
186 }
187 }
189 initialize_keytable();
190 /* Register another key that will allow for the the Harware Probe
191 * to be contacted, this works with RiscWatch probes and should
192 * work with Chronos and FSPs */
193 register_irq_keyhandler('^', hw_probe_attn, "Trap to Hardware Probe");
195 timer_init();
196 serial_init_postirq();
197 do_initcalls();
198 schedulers_start();
199 }
201 extern void idle_loop(void);
203 void startup_cpu_idle_loop(void)
204 {
205 struct vcpu *v = current;
207 ASSERT(is_idle_vcpu(v));
208 cpu_set(smp_processor_id(), v->domain->domain_dirty_cpumask);
209 cpu_set(smp_processor_id(), v->vcpu_dirty_cpumask);
211 /* Finally get off the boot stack. */
212 reset_stack_and_jump(idle_loop);
213 }
215 static void init_parea(int cpuid)
216 {
217 /* Be careful not to shadow the global variable. */
218 volatile struct processor_area *pa;
219 void *stack;
221 pa = xmalloc(struct processor_area);
222 if (pa == NULL)
223 panic("%s: failed to allocate parea for cpu #%d\n", __func__, cpuid);
225 stack = alloc_xenheap_pages(STACK_ORDER);
226 if (stack == NULL)
227 panic("%s: failed to allocate stack (order %d) for cpu #%d\n",
228 __func__, STACK_ORDER, cpuid);
230 pa->whoami = cpuid;
231 pa->hard_id = cpu_hard_id[cpuid];
232 pa->hyp_stack_base = (void *)((ulong)stack + STACK_SIZE);
234 /* This store has the effect of invoking secondary_cpu_init. */
235 global_cpu_table[cpuid] = pa;
236 mb();
237 }
239 static int kick_secondary_cpus(int maxcpus)
240 {
241 int cpuid;
243 for_each_present_cpu(cpuid) {
244 if (cpuid == 0)
245 continue;
246 if (cpuid >= maxcpus)
247 break;
248 init_parea(cpuid);
249 smp_generic_give_timebase();
251 /* wait for it */
252 while (!cpu_online(cpuid))
253 cpu_relax();
254 }
256 return 0;
257 }
259 /* This is the first C code that secondary processors invoke. */
260 int secondary_cpu_init(int cpuid, unsigned long r4)
261 {
262 cpu_initialize(cpuid);
263 smp_generic_take_timebase();
264 cpu_set(cpuid, cpu_online_map);
265 while(1);
266 }
268 static void __init __start_xen(multiboot_info_t *mbi)
269 {
270 char *cmdline;
271 module_t *mod = (module_t *)((ulong)mbi->mods_addr);
272 ulong dom0_start, dom0_len;
273 ulong initrd_start, initrd_len;
275 memcpy(0, exception_vectors, exception_vectors_end - exception_vectors);
276 synchronize_caches(0, exception_vectors_end - exception_vectors);
278 ticks_per_usec = timebase_freq / 1000000ULL;
280 /* Parse the command-line options. */
281 if ((mbi->flags & MBI_CMDLINE) && (mbi->cmdline != 0))
282 cmdline_parse(__va((ulong)mbi->cmdline));
284 /* We initialise the serial devices very early so we can get debugging. */
285 ns16550.io_base = 0x3f8;
286 ns16550_init(0, &ns16550);
287 ns16550.io_base = 0x2f8;
288 ns16550_init(1, &ns16550);
289 serial_init_preirq();
291 init_console();
292 #ifdef CONSOLE_SYNC
293 console_start_sync();
294 #endif
296 /* we give the first RMA to the hypervisor */
297 xenheap_phys_end = rma_size(cpu_default_rma_order_pages());
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 memory_init(mod, mbi->mods_count);
320 #ifdef OF_DEBUG
321 printk("ofdump:\n");
322 /* make sure the OF devtree is good */
323 ofd_walk((void *)oftree, OFD_ROOT, ofd_dump_props, OFD_DUMP_ALL);
324 #endif
326 percpu_init_areas();
328 init_parea(0);
329 cpu_initialize(0);
331 #ifdef CONFIG_GDB
332 initialise_gdb();
333 if (opt_earlygdb)
334 debugger_trap_immediate();
335 #endif
337 /* Deal with secondary processors. */
338 if (opt_nosmp || ofd_boot_cpu == -1) {
339 printk("nosmp: leaving secondary processors spinning forever\n");
340 } else {
341 printk("spinning up at most %d total processors ...\n", max_cpus);
342 kick_secondary_cpus(max_cpus);
343 }
345 start_of_day();
347 /* Create initial domain 0. */
348 dom0 = domain_create(0);
349 if (dom0 == NULL)
350 panic("Error creating domain 0\n");
351 dom0->max_pages = ~0U;
352 if (0 > allocate_rma(dom0, cpu_default_rma_order_pages()))
353 panic("Error allocating domain 0 RMA\n");
354 if (NULL == alloc_vcpu(dom0, 0, 0))
355 panic("Error creating domain 0 vcpu 0\n");
357 /* The Interrupt Controller will route everything to CPU 0 so we
358 * need to make sure Dom0's vVCPU 0 is pinned to the CPU */
359 dom0->vcpu[0]->cpu_affinity = cpumask_of_cpu(0);
361 set_bit(_DOMF_privileged, &dom0->domain_flags);
362 /* post-create hooks sets security label */
363 acm_post_domain0_create(dom0->domain_id);
365 cmdline = (char *)(mod[0].string ? __va((ulong)mod[0].string) : NULL);
367 /* scrub_heap_pages() requires IRQs enabled, and we're post IRQ setup... */
368 local_irq_enable();
369 /* Scrub RAM that is still free and so may go to an unprivileged domain. */
370 scrub_heap_pages();
372 dom0_start = mod[0].mod_start;
373 dom0_len = mod[0].mod_end - mod[0].mod_start;
374 if (mbi->mods_count > 1) {
375 initrd_start = mod[1].mod_start;
376 initrd_len = mod[1].mod_end - mod[1].mod_start;
377 } else {
378 initrd_start = 0;
379 initrd_len = 0;
380 }
381 if (construct_dom0(dom0, dom0_start, dom0_len,
382 initrd_start, initrd_len,
383 cmdline) != 0) {
384 panic("Could not set up DOM0 guest OS\n");
385 }
387 init_xenheap_pages(ALIGN_UP(dom0_start, PAGE_SIZE),
388 ALIGN_DOWN(dom0_start + dom0_len, PAGE_SIZE));
389 if (initrd_start)
390 init_xenheap_pages(ALIGN_UP(initrd_start, PAGE_SIZE),
391 ALIGN_DOWN(initrd_start + initrd_len, PAGE_SIZE));
393 init_trace_bufs();
395 console_endboot();
397 /* Hide UART from DOM0 if we're using it */
398 serial_endboot();
400 domain_unpause_by_systemcontroller(dom0);
402 startup_cpu_idle_loop();
403 }
405 void __init __start_xen_ppc(
406 ulong r3, ulong r4, ulong r5, ulong r6, ulong r7, ulong orig_msr)
407 {
408 multiboot_info_t *mbi = NULL;
410 /* clear bss */
411 memset(__bss_start, 0, (ulong)_end - (ulong)__bss_start);
413 if (r5 > 0) {
414 /* we were booted by OpenFirmware */
415 mbi = boot_of_init(r3, r4, r5, r6, r7, orig_msr);
417 } else {
418 /* booted by someone else that hopefully has a trap handler */
419 trap();
420 }
422 __start_xen(mbi);
424 }
426 extern void arch_get_xen_caps(xen_capabilities_info_t info);
427 void arch_get_xen_caps(xen_capabilities_info_t info)
428 {
429 }
433 /*
434 * Local variables:
435 * mode: C
436 * c-set-style: "BSD"
437 * c-basic-offset: 4
438 * tab-width: 4
439 * indent-tabs-mode: nil
440 * End:
441 */