diff options
author | David S. Miller <davem@davemloft.net> | 2008-02-07 05:14:48 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-02-07 05:58:40 -0500 |
commit | ce22e1d39429c7de9f054ce8d03278dd2010b642 (patch) | |
tree | af47d57927d7b8595d1b252f9bad2535a3c50d5d /arch/sparc64 | |
parent | 488b5ec871191359b9b79262a3d48456dae7ea5f (diff) |
[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>
Diffstat (limited to 'arch/sparc64')
-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: | |||
632 | /* Not reached... */ | 632 | /* Not reached... */ |
633 | 633 | ||
634 | 1: | 634 | 1: |
635 | /* If we boot on a non-zero cpu, all of the per-cpu | ||
636 | * variable references we make before setting up the | ||
637 | * per-cpu areas will use a bogus offset. Put a | ||
638 | * compensating factor into __per_cpu_base to handle | ||
639 | * this cleanly. | ||
640 | * | ||
641 | * What the per-cpu code calculates is: | ||
642 | * | ||
643 | * __per_cpu_base + (cpu << __per_cpu_shift) | ||
644 | * | ||
645 | * These two variables are zero initially, so to | ||
646 | * make it all cancel out to zero we need to put | ||
647 | * "0 - (cpu << 0)" into __per_cpu_base so that the | ||
648 | * above formula evaluates to zero. | ||
649 | * | ||
650 | * We cannot even perform a printk() until this stuff | ||
651 | * is setup as that calls cpu_clock() which uses | ||
652 | * per-cpu variables. | ||
653 | */ | ||
654 | sub %g0, %o0, %o1 | ||
655 | sethi %hi(__per_cpu_base), %o2 | ||
656 | stx %o1, [%o2 + %lo(__per_cpu_base)] | ||
635 | #else | 657 | #else |
636 | mov 0, %o0 | 658 | mov 0, %o0 |
637 | #endif | 659 | #endif |
638 | sth %o0, [%g6 + TI_CPU] | 660 | sth %o0, [%g6 + TI_CPU] |
639 | 661 | ||
662 | call prom_init_report | ||
663 | nop | ||
664 | |||
640 | /* Off we go.... */ | 665 | /* Off we go.... */ |
641 | call start_kernel | 666 | call start_kernel |
642 | nop | 667 | 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) | |||
48 | prom_getstring(node, "version", prom_version, sizeof(prom_version)); | 48 | prom_getstring(node, "version", prom_version, sizeof(prom_version)); |
49 | 49 | ||
50 | prom_printf("\n"); | 50 | prom_printf("\n"); |
51 | } | ||
51 | 52 | ||
53 | void __init prom_init_report(void) | ||
54 | { | ||
52 | printk("PROMLIB: Sun IEEE Boot Prom '%s'\n", prom_version); | 55 | printk("PROMLIB: Sun IEEE Boot Prom '%s'\n", prom_version); |
53 | printk("PROMLIB: Root node compatible: %s\n", prom_root_compatible); | 56 | printk("PROMLIB: Root node compatible: %s\n", prom_root_compatible); |
54 | } | 57 | } |