summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/paca.c45
-rw-r--r--arch/powerpc/kernel/setup_64.c4
2 files changed, 43 insertions, 6 deletions
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index a186911791c7..0f7e2be23fa2 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -20,6 +20,41 @@
#include "setup.h"
+#ifndef CONFIG_SMP
+#define boot_cpuid 0
+#endif
+
+static void *__init alloc_paca_data(unsigned long size, unsigned long align,
+ unsigned long limit, int cpu)
+{
+ unsigned long pa;
+ int nid;
+
+ /*
+ * boot_cpuid paca is allocated very early before cpu_to_node is up.
+ * Set bottom-up mode, because the boot CPU should be on node-0,
+ * which will put its paca in the right place.
+ */
+ if (cpu == boot_cpuid) {
+ nid = -1;
+ memblock_set_bottom_up(true);
+ } else {
+ nid = early_cpu_to_node(cpu);
+ }
+
+ pa = memblock_alloc_base_nid(size, align, limit, nid, MEMBLOCK_NONE);
+ if (!pa) {
+ pa = memblock_alloc_base(size, align, limit);
+ if (!pa)
+ panic("cannot allocate paca data");
+ }
+
+ if (cpu == boot_cpuid)
+ memblock_set_bottom_up(false);
+
+ return __va(pa);
+}
+
#ifdef CONFIG_PPC_PSERIES
/*
@@ -52,7 +87,7 @@ static struct lppaca * __init new_lppaca(int cpu, unsigned long limit)
if (early_cpu_has_feature(CPU_FTR_HVMODE))
return NULL;
- lp = __va(memblock_alloc_base(size, 0x400, limit));
+ lp = alloc_paca_data(size, 0x400, limit, cpu);
init_lppaca(lp);
return lp;
@@ -82,7 +117,7 @@ static struct slb_shadow * __init new_slb_shadow(int cpu, unsigned long limit)
return NULL;
}
- s = __va(memblock_alloc_base(sizeof(*s), L1_CACHE_BYTES, limit));
+ s = alloc_paca_data(sizeof(*s), L1_CACHE_BYTES, limit, cpu);
memset(s, 0, sizeof(*s));
s->persistent = cpu_to_be32(SLB_NUM_BOLTED);
@@ -170,7 +205,6 @@ void __init allocate_paca_ptrs(void)
void __init allocate_paca(int cpu)
{
u64 limit;
- unsigned long pa;
struct paca_struct *paca;
BUG_ON(cpu >= paca_nr_cpu_ids);
@@ -185,9 +219,8 @@ void __init allocate_paca(int cpu)
limit = ppc64_rma_size;
#endif
- pa = memblock_alloc_base(sizeof(struct paca_struct),
- L1_CACHE_BYTES, limit);
- paca = __va(pa);
+ paca = alloc_paca_data(sizeof(struct paca_struct), L1_CACHE_BYTES,
+ limit, cpu);
paca_ptrs[cpu] = paca;
memset(paca, 0, sizeof(struct paca_struct));
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index dde34d35d1e7..02fa358982e6 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -312,6 +312,10 @@ void __init early_setup(unsigned long dt_ptr)
early_init_devtree(__va(dt_ptr));
/* Now we know the logical id of our boot cpu, setup the paca. */
+ if (boot_cpuid != 0) {
+ /* Poison paca_ptrs[0] again if it's not the boot cpu */
+ memset(&paca_ptrs[0], 0x88, sizeof(paca_ptrs[0]));
+ }
setup_paca(paca_ptrs[boot_cpuid]);
fixup_boot_paca();