aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-02-07 02:14:48 -0800
committerDavid S. Miller <davem@davemloft.net>2008-02-07 02:58:40 -0800
commitce22e1d39429c7de9f054ce8d03278dd2010b642 (patch)
treeaf47d57927d7b8595d1b252f9bad2535a3c50d5d
parentMerge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs (diff)
downloadlinux-dev-ce22e1d39429c7de9f054ce8d03278dd2010b642.tar.xz
linux-dev-ce22e1d39429c7de9f054ce8d03278dd2010b642.zip
[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.S25
-rw-r--r--arch/sparc64/prom/init.c3
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);
}