diff options
author | David S. Miller <davem@davemloft.net> | 2008-02-07 02:14:48 -0800 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-02-07 02:58:40 -0800 |
commit | ce22e1d39429c7de9f054ce8d03278dd2010b642 (patch) | |
tree | af47d57927d7b8595d1b252f9bad2535a3c50d5d | |
parent | 488b5ec871191359b9b79262a3d48456dae7ea5f (diff) | |
download | linux-ce22e1d39429c7de9f054ce8d03278dd2010b642.tar.bz2 |
[SPARC64]: Fix booting on non-zero cpu.
The early per-cpu handling needs a slight tweak to work when booting
on a non-zero cpu.
We got away with this for a long time, but can't any longer as now
even printk() calls functions (cpu_clock() for example) that thus make
early references to per-cpu variables.
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | arch/sparc64/kernel/head.S | 25 | ||||
-rw-r--r-- | arch/sparc64/prom/init.c | 3 |
2 files changed, 28 insertions, 0 deletions
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index c4147ad8677b..44b105c04dd3 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S @@ -632,11 +632,36 @@ tlb_fixup_done: /* Not reached... */ 1: + /* If we boot on a non-zero cpu, all of the per-cpu + * variable references we make before setting up the + * per-cpu areas will use a bogus offset. Put a + * compensating factor into __per_cpu_base to handle + * this cleanly. + * + * What the per-cpu code calculates is: + * + * __per_cpu_base + (cpu << __per_cpu_shift) + * + * These two variables are zero initially, so to + * make it all cancel out to zero we need to put + * "0 - (cpu << 0)" into __per_cpu_base so that the + * above formula evaluates to zero. + * + * We cannot even perform a printk() until this stuff + * is setup as that calls cpu_clock() which uses + * per-cpu variables. + */ + sub %g0, %o0, %o1 + sethi %hi(__per_cpu_base), %o2 + stx %o1, [%o2 + %lo(__per_cpu_base)] #else mov 0, %o0 #endif sth %o0, [%g6 + TI_CPU] + call prom_init_report + nop + /* Off we go.... */ call start_kernel nop diff --git a/arch/sparc64/prom/init.c b/arch/sparc64/prom/init.c index 1c0db842a6f4..87e7c7ea0ee6 100644 --- a/arch/sparc64/prom/init.c +++ b/arch/sparc64/prom/init.c @@ -48,7 +48,10 @@ void __init prom_init(void *cif_handler, void *cif_stack) prom_getstring(node, "version", prom_version, sizeof(prom_version)); prom_printf("\n"); +} +void __init prom_init_report(void) +{ printk("PROMLIB: Sun IEEE Boot Prom '%s'\n", prom_version); printk("PROMLIB: Root node compatible: %s\n", prom_root_compatible); } |