modernize early memory allocation limits and
Subsystems (4)
Nicholas Piggin
reviewercover modernize early memory allocation limits and
This series improves (mostly relaxes) limits on early memory allocations for stacks, pacas, etc. on 64s.
It also avoids allocating lppacas for bare metal, and it changes allocation of paca and lppaca from single big arrays to inividual allocations.
The main goal of this is toward allocating these basic structures per-node. We're not there yet, but closer.
Thanks,
Nick
Nicholas Piggin (9):
powerpc/powernv: Remove real mode access limit for early allocations powerpc/pseries: radix is not subject to RMA limit, remove it powerpc/64: rtas avoid accessing paca in 32-bit mode powerpc/pseries: lift RTAS limit for radix powerpc/pseries: lift RTAS limit for hash
powerpc/64s: Relax PACA address limitations
powerpc/64s: do not allocate lppaca if we are not virtualized powerpc/64: Use array of paca pointers and allocate pacas individually powerpc/64s: Use array of lppaca pointers and allocate lppacas
individually
arch/powerpc/include/asm/kvm_ppc.h | 8 +- arch/powerpc/include/asm/lppaca.h | 26 ++-- arch/powerpc/include/asm/paca.h | 12 +- arch/powerpc/include/asm/pmc.h | 13 +- arch/powerpc/include/asm/smp.h | 4 +- arch/powerpc/kernel/asm-offsets.c | 5 + arch/powerpc/kernel/crash.c | 2 +- arch/powerpc/kernel/entry_64.S | 17 ++- arch/powerpc/kernel/head_64.S | 19 +-- arch/powerpc/kernel/machine_kexec_64.c | 37 +++--- arch/powerpc/kernel/paca.c | 174 ++++++++++++++------------- arch/powerpc/kernel/setup.h | 4 + arch/powerpc/kernel/setup_64.c | 40 +++--- arch/powerpc/kernel/smp.c | 10 +- arch/powerpc/kernel/sysfs.c | 2 +- arch/powerpc/kvm/book3s_hv.c | 34 +++--- arch/powerpc/kvm/book3s_hv_builtin.c | 2 +- arch/powerpc/kvm/book3s_hv_interrupts.S | 3 +- arch/powerpc/kvm/book3s_hv_rmhandlers.S | 3 +- arch/powerpc/mm/hash_utils_64.c | 24 ++-- arch/powerpc/mm/numa.c | 4 +- arch/powerpc/mm/pgtable-radix.c | 17 +-- arch/powerpc/mm/tlb-radix.c | 2 +- arch/powerpc/platforms/85xx/smp.c | 8 +- arch/powerpc/platforms/cell/smp.c | 4 +- arch/powerpc/platforms/powernv/idle.c | 13 +- arch/powerpc/platforms/powernv/setup.c | 4 +- arch/powerpc/platforms/powernv/smp.c | 2 +- arch/powerpc/platforms/powernv/subcore.c | 2 +- arch/powerpc/platforms/pseries/hotplug-cpu.c | 2 +- arch/powerpc/platforms/pseries/kexec.c | 7 +- arch/powerpc/platforms/pseries/lpar.c | 4 +- arch/powerpc/platforms/pseries/setup.c | 2 +- arch/powerpc/platforms/pseries/smp.c | 4 +- arch/powerpc/sysdev/xics/icp-native.c | 2 +- arch/powerpc/xmon/xmon.c | 2 +- 36 files changed, 289 insertions(+), 229 deletions(-)
Signature · 1 line
2.15.0
Nicholas Piggin
reviewerPATCH 1/9 powerpc/powernv: Remove real mode access limit for early allocations
This removes the RMA limit on powernv platform, which constrains early allocations such as PACAs and stacks. There are still other restrictions that must be followed, such as bolted SLB limits, but real mode addressing has no constraints.
--- arch/powerpc/mm/hash_utils_64.c | 20 +++++++++++++------- arch/powerpc/mm/pgtable-radix.c | 37 +++++++++++++++++++++---------------- 2 files changed, 34 insertions(+), 23 deletions(-)
arch/powerpc/mm/hash_utils_64.c +13 -7
@@ -1825,16 +1825,22 @@ void hash__setup_initial_memory_limit(phys_addr_t first_memblock_base,*/ BUG_ON (first_memblock_base !=0 ); -/* On LPAR systems, the first entry is our RMA region, -* non-LPAR 64-bit hash MMU systems don't have a limitation -* on real mode access, but using the first entry works well -* enough. We also clamp it to 1G to avoid some funky things +/* +* On virtualized systems the first entry is our RMA region aka VRMA, +* non-virtualized 64-bit hash MMU systems don't have a limitation +* on real mode access. +* +* We also clamp it to 1G to avoid some funky things * such as RTAS bugs etc... */ - ppc64_rma_size =min_t (u64, first_memblock_size,0x40000000 ); +if (!early_cpu_has_feature (CPU_FTR_HVMODE )) { + ppc64_rma_size =min_t (u64, first_memblock_size,0x40000000 ); -/* Finally limit subsequent allocations */ -memblock_set_current_limit (ppc64_rma_size); +/* Finally limit subsequent allocations */ +memblock_set_current_limit (ppc64_rma_size); + }else { + ppc64_rma_size =ULONG_MAX ; + } }#ifdef CONFIG_DEBUG_FS
arch/powerpc/mm/pgtable-radix.c +21 -16
@@ -622,22 +622,27 @@ void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base,* physical on those processors */ BUG_ON (first_memblock_base !=0 ); -/* -* We limit the allocation that depend on ppc64_rma_size -* to first_memblock_size. We also clamp it to 1GB to -* avoid some funky things such as RTAS bugs. -* -* On radix config we really don't have a limitation -* on real mode access. But keeping it as above works -* well enough. -*/ - ppc64_rma_size =min_t (u64, first_memblock_size,0x40000000 ); -/* -* Finally limit subsequent allocations. We really don't want -* to limit the memblock allocations to rma_size. FIXME!! should -* we even limit at all ? -*/ -memblock_set_current_limit (first_memblock_base + first_memblock_size); + +if (!early_cpu_has_feature (CPU_FTR_HVMODE )) { +/* +* We limit the allocation that depend on ppc64_rma_size +* to first_memblock_size. We also clamp it to 1GB to +* avoid some funky things such as RTAS bugs. +* +* On radix config we really don't have a limitation +* on real mode access. But keeping it as above works +* well enough. +*/ + ppc64_rma_size =min_t (u64, first_memblock_size,0x40000000 ); +/* +* Finally limit subsequent allocations. We really don't want +* to limit the memblock allocations to rma_size. FIXME!! should +* we even limit at all ? +*/ +memblock_set_current_limit (first_memblock_base + first_memblock_size); + }else { + ppc64_rma_size =ULONG_MAX ; + } }#ifdef CONFIG_MEMORY_HOTPLUG
Signature · 1 line
2.15.0
Re: [1/9] powerpc/powernv: Remove real mode access limit for early allocations
Quoted 6 lines · Nicholas Piggin
This removes the RMA limit on powernv platform, which constrains early allocations such as PACAs and stacks. There are still other restrictions that must be followed, such as bolted SLB limits, but real mode addressing has no constraints.
Signed-off-by Nicholas Piggin <[email protected]>
Patches 1-6 applied to powerpc next, thanks.
https://git.kernel.org/powerpc/c/1513c33d7174e87a079cfa2666cb9a
cheers
Nicholas Piggin
reviewerPATCH 2/9 powerpc/pseries: radix is not subject to RMA limit, remove it
In reply to Nicholas PigginThe radix guest is not subject to the paravirtualized HPT VRMA limit, so remove that from ppc64_rma_size calculation for that platform.
--- arch/powerpc/mm/pgtable-radix.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)
arch/powerpc/mm/pgtable-radix.c +4 -7
@@ -625,15 +625,12 @@ void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base,if (!early_cpu_has_feature (CPU_FTR_HVMODE )) {/* -* We limit the allocation that depend on ppc64_rma_size -* to first_memblock_size. We also clamp it to 1GB to -* avoid some funky things such as RTAS bugs. +* Radix mode guests are not limited by RMA / VRMA addressing. * -* On radix config we really don't have a limitation -* on real mode access. But keeping it as above works -* well enough. +* We do clamp addresses to 1GB to avoid some funky things +* such as RTAS bugs. */ - ppc64_rma_size =min_t (u64, first_memblock_size,0x40000000 ); + ppc64_rma_size =0x40000000 ;/* * Finally limit subsequent allocations. We really don't want * to limit the memblock allocations to rma_size. FIXME!! should
Signature · 1 line
2.15.0
Nicholas Piggin
reviewerPATCH 3/9 powerpc/64: rtas avoid accessing paca in 32-bit mode
In reply to Nicholas PigginCommit 177ba7c647f3 ("powerpc/mm/radix: Limit paca allocation in radix") limited the paca allocation address to 1G on pSeries because RTAS return accesses the paca in 32-bit mode:
On return from RTAS we access the paca variables and we have 64 bit disabled. This requires us to limit paca in 32 bit range.
Fix this by setting ppc64_rma_size to first_memblock_size/1G range.
Avoid this limit by switching to 64-bit mode before accessing any memory.
--- arch/powerpc/kernel/entry_64.S | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-)
arch/powerpc/kernel/entry_64.S +11 -6
@@ -1083,6 +1083,17 @@ __enter_rtas: rtas_return_loc: FIXUP_ENDIAN + /* + * Clear RI and set SF before anything. + */ + mfmsr r6 + li r0,MSR_RI + andc r6,r6,r0 + sldi r0,r0,(MSR_SF_LG - MSR_RI_LG) + or r6,r6,r0 + sync + mtmsrd r6 + /* relocation is off at this point */ GET_PACA(r4) clrldi r4,r4,2 /* convert to realmode address */
@@ -1091,12 +1102,6 @@ rtas_return_loc: 0: mflr r3 ld r3,(1f-0b)(r3) /* get &rtas_restore_regs */ - mfmsr r6 - li r0,MSR_RI - andc r6,r6,r0 - sync - mtmsrd r6 - ld r1,PACAR1(r4) /* Restore our SP */ ld r4,PACASAVEDMSR(r4) /* Restore our MSR */
Signature · 1 line
2.15.0
Nicholas Piggin
reviewerPATCH 4/9 powerpc/pseries: lift RTAS limit for radix
In reply to Nicholas PigginWith the previous patch to switch to 64-bit mode after returning from RTAS and before doing any memory accesses, the RMA limit need not be clamped to 1GB to avoid RTAS bugs.
Keep the 1GB limit for older firmware (although this is more of a kernel concern than RTAS), and remove it starting with POWER9.
--- arch/powerpc/mm/pgtable-radix.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-)
arch/powerpc/mm/pgtable-radix.c +4 -17
@@ -623,23 +623,10 @@ void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base,*/ BUG_ON (first_memblock_base !=0 ); -if (!early_cpu_has_feature (CPU_FTR_HVMODE )) { -/* -* Radix mode guests are not limited by RMA / VRMA addressing. -* -* We do clamp addresses to 1GB to avoid some funky things -* such as RTAS bugs. -*/ - ppc64_rma_size =0x40000000 ; -/* -* Finally limit subsequent allocations. We really don't want -* to limit the memblock allocations to rma_size. FIXME!! should -* we even limit at all ? -*/ -memblock_set_current_limit (first_memblock_base + first_memblock_size); - }else { - ppc64_rma_size =ULONG_MAX ; - } +/* +* Radix mode is not limited by RMA / VRMA addressing. +*/ + ppc64_rma_size =ULONG_MAX ; }#ifdef CONFIG_MEMORY_HOTPLUG
Signature · 1 line
2.15.0
Nicholas Piggin
reviewerPATCH 5/9 powerpc/pseries: lift RTAS limit for hash
In reply to Nicholas PigginWith the previous patch to switch to 64-bit mode after returning from RTAS and before doing any memory accesses, the RMA limit need not be clamped to 1GB to avoid RTAS bugs.
Keep the 1GB limit for older firmware (although this is more of a kernel concern than RTAS), and remove it starting with POWER9.
--- arch/powerpc/mm/hash_utils_64.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
arch/powerpc/mm/hash_utils_64.c +5 -3
@@ -1830,11 +1830,13 @@ void hash__setup_initial_memory_limit(phys_addr_t first_memblock_base,* non-virtualized 64-bit hash MMU systems don't have a limitation * on real mode access. * -* We also clamp it to 1G to avoid some funky things -* such as RTAS bugs etc... +* For guests on platforms before POWER9, we clamp the it limit to 1G +* to avoid some funky things such as RTAS bugs etc... */ if (!early_cpu_has_feature (CPU_FTR_HVMODE )) { - ppc64_rma_size =min_t (u64, first_memblock_size,0x40000000 ); + ppc64_rma_size = first_memblock_size; +if (!early_cpu_has_feature (CPU_FTR_ARCH_300 )) + ppc64_rma_size =min_t (u64, ppc64_rma_size,0x40000000 );/* Finally limit subsequent allocations */ memblock_set_current_limit (ppc64_rma_size);
Signature · 1 line
2.15.0
Nicholas Piggin
reviewerPATCH 6/9 powerpc/64s: Relax PACA address limitations
In reply to Nicholas PigginBook3S PACA memory allocation is restricted by the RMA limit and also must not take SLB faults when accessed in virtual mode. Currently a fixed 256MB limit is used for this, which is imprecise and sub-optimal.
Update the paca allocation limits to use use the ppc64_rma_size for RMA limit, and share the safe_stack_limit() that is currently used for stack allocations that must not take virtual mode faults.
The safe_stack_limit() name is changed to ppc64_bolted_size() to match ppc64_rma_size and some comments are updated, but code unchanged.
--- arch/powerpc/kernel/paca.c | 13 +++++++------ arch/powerpc/kernel/setup.h | 4 ++++ arch/powerpc/kernel/setup_64.c | 22 ++++++++++++++-------- 3 files changed, 25 insertions(+), 14 deletions(-)
arch/powerpc/kernel/paca.c +7 -6
@@ -18,6 +18,8 @@#include <asm/pgtable.h> #include <asm/kexec.h> +#include "setup.h" +#ifdef CONFIG_PPC_BOOK3S /*
@@ -208,15 +210,14 @@ void __init allocate_pacas(void)u64 limit;int cpu; - limit = ppc64_rma_size; -#ifdef CONFIG_PPC_BOOK3S_64 /* -* We can't take SLB misses on the paca, and we want to access them -* in real mode, so allocate them within the RMA and also within -* the first segment. +* We access pacas in real mode, and cannot take SLB faults +* on them when in virtual mode, so allocate them accordingly. */ - limit =min (0x10000000ULL , limit); + limit =min (ppc64_bolted_size (), ppc64_rma_size); +#else + limit = ppc64_rma_size;#endif paca_size =PAGE_ALIGN (sizeof (struct paca_struct ) * nr_cpu_ids);
arch/powerpc/kernel/setup.h +4 -0
@@ -51,6 +51,10 @@ void record_spr_defaults(void);static inline void record_spr_defaults (void ) { };#endif +#ifdef CONFIG_PPC64 +u64 ppc64_bolted_size (void ); +#endif +/* * Having this in kvm_ppc.h makes include dependencies too * tricky to solve for setup-common.c so have it here.
arch/powerpc/kernel/setup_64.c +14 -8
@@ -565,24 +565,30 @@ void __init initialize_cache_info(void)DBG (" <- initialize_cache_info()\n" ); } -/* This returns the limit below which memory accesses to the linear -* mapping are guarnateed not to cause a TLB or SLB miss. This is -* used to allocate interrupt or emergency stacks for which our -* exception entry path doesn't deal with being interrupted. +/* +* This returns the limit below which memory accesses to the linear +* mapping are guarnateed not to cause an architectural exception (e.g., +* TLB or SLB miss fault). +* +* This is used to allocate PACAs and various interrupt stacks that +* that are accessed early in interrupt handlers that must not cause +* re-entrant interrupts. */ -static __init u64 safe_stack_limit (void ) +__init u64 ppc64_bolted_size (void ) {#ifdef CONFIG_PPC_BOOK3E /* Freescale BookE bolts the entire linear mapping */ +/* XXX: BookE ppc64_rma_limit setup seems to disagree? */ if (mmu_has_feature (MMU_FTR_TYPE_FSL_E ))return linear_map_top;/* Other BookE, we assume the first GB is bolted */ return 1ul <<30 ;#else +/* BookS radix, does not take faults on linear mapping */ if (early_radix_enabled ())return ULONG_MAX ; -/* BookS, the first segment is bolted */ +/* BookS hash, the first segment is bolted */ if (mmu_has_feature (MMU_FTR_1T_SEGMENT ))return 1UL <<SID_SHIFT_1T ;return 1UL <<SID_SHIFT ;
@@ -591,7 +597,7 @@ static __init u64 safe_stack_limit(void)void __init irqstack_early_init (void ) { -u64 limit =safe_stack_limit (); +u64 limit =ppc64_bolted_size ();unsigned int i;/*
@@ -676,7 +682,7 @@ void __init emergency_stack_init(void)* initialized in kernel/irq.c. These are initialized here in order * to have emergency stacks available as early as possible. */ - limit =min (safe_stack_limit (), ppc64_rma_size); + limit =min (ppc64_bolted_size (), ppc64_rma_size);for_each_possible_cpu (i) {struct thread_info *ti;
Signature · 1 line
2.15.0
Nicholas Piggin
reviewerPATCH 7/9 powerpc/64s: do not allocate lppaca if we are not virtualized
In reply to Nicholas PigginThe "lppaca" is a structure registered with the hypervisor. This is unnecessary when running on non-virtualised platforms. One field from the lppaca (pmcregs_in_use) is also used by the host, so move the host part out into the paca (lppaca field is still updated in guest mode).
--- arch/powerpc/include/asm/paca.h | 8 ++++++-- arch/powerpc/include/asm/pmc.h | 13 ++++++++++++- arch/powerpc/kernel/asm-offsets.c | 5 +++++ arch/powerpc/kernel/paca.c | 16 +++++++++++++--- arch/powerpc/kvm/book3s_hv_interrupts.S | 3 +-- arch/powerpc/kvm/book3s_hv_rmhandlers.S | 3 +-- 6 files changed, 38 insertions(+), 10 deletions(-)
arch/powerpc/include/asm/paca.h +6 -2
@@ -58,7 +58,7 @@ struct task_struct;* processor. */ struct paca_struct { -#ifdef CONFIG_PPC_BOOK3S +#ifdef CONFIG_PPC_PSERIES /* * Because hw_cpu_id, unlike other paca fields, is accessed * routinely from other CPUs (from the IRQ code), we stick to
@@ -67,7 +67,8 @@ struct paca_struct {*/ struct lppaca *lppaca_ptr;/* Pointer to LpPaca for PLIC */ -#endif /* CONFIG_PPC_BOOK3S */ +#endif /* CONFIG_PPC_PSERIES */ +/* * MAGIC: the spinlock functions in arch/powerpc/lib/locks.c * load lock_token and paca_index with a single lwz
@@ -159,6 +160,9 @@ struct paca_struct {u64 saved_r1;/* r1 save for RTAS calls or PM */ u64 saved_msr;/* MSR saved here by enter_rtas */ u16 trap_save;/* Used when bad stack is encountered */ +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE +u8 pmcregs_in_use;/* pseries puts this in lppaca */ +#endif u8 soft_enabled;/* irq soft-enable flag */ u8 irq_happened;/* irq happened while soft-disabled */ u8 io_sync;/* writel() needs spin_unlock sync */
arch/powerpc/include/asm/pmc.h +12 -1
@@ -31,10 +31,21 @@ void ppc_enable_pmcs(void);#ifdef CONFIG_PPC_BOOK3S_64 #include <asm/lppaca.h> +#include <asm/firmware.h> static inline void ppc_set_pmu_inuse (int inuse) { -get_lppaca ()->pmcregs_in_use = inuse; +#if defined(CONFIG_PPC_PSERIES ) || defined(CONFIG_KVM_BOOK3S_HV_POSSIBLE ) +if (firmware_has_feature (FW_FEATURE_LPAR )) { +#ifdef CONFIG_PPC_PSERIES +get_lppaca ()->pmcregs_in_use = inuse; +#endif + }else { +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE +get_paca ()->pmcregs_in_use = inuse; +#endif + } +#endif }extern void power4_enable_pmcs (void );
arch/powerpc/kernel/asm-offsets.c +5 -0
@@ -221,12 +221,17 @@ int main(void)OFFSET (PACA_EXMC , paca_struct, exmc);OFFSET (PACA_EXSLB , paca_struct, exslb);OFFSET (PACA_EXNMI , paca_struct, exnmi); +#ifdef CONFIG_PPC_PSERIES OFFSET (PACALPPACAPTR , paca_struct, lppaca_ptr); +#endif OFFSET (PACA_SLBSHADOWPTR , paca_struct, slb_shadow_ptr);OFFSET (SLBSHADOW_STACKVSID , slb_shadow, save_area[SLB_NUM_BOLTED -1 ].vsid);OFFSET (SLBSHADOW_STACKESID , slb_shadow, save_area[SLB_NUM_BOLTED -1 ].esid);OFFSET (SLBSHADOW_SAVEAREA , slb_shadow, save_area);OFFSET (LPPACA_PMCINUSE , lppaca, pmcregs_in_use); +#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE +OFFSET (PACA_PMCINUSE , paca_struct, pmcregs_in_use); +#endif OFFSET (LPPACA_DTLIDX , lppaca, dtl_idx);OFFSET (LPPACA_YIELDCOUNT , lppaca, yield_count);OFFSET (PACA_DTL_RIDX , paca_struct, dtl_ridx);
arch/powerpc/kernel/paca.c +13 -3
@@ -20,7 +20,7 @@#include "setup.h" -#ifdef CONFIG_PPC_BOOK3S +#ifdef CONFIG_PPC_PSERIES /* * The structure which the hypervisor knows about - this structure
@@ -47,6 +47,9 @@ static long __initdata lppaca_size;static void __init allocate_lppacas (int nr_cpus,unsigned long limit) { +if (early_cpu_has_feature (CPU_FTR_HVMODE )) +return ; +if (nr_cpus <=NR_LPPACAS )return ;
@@ -60,6 +63,9 @@ static struct lppaca * __init new_lppaca(int cpu) {struct lppaca *lp; +if (early_cpu_has_feature (CPU_FTR_HVMODE )) +return NULL ; +if (cpu <NR_LPPACAS )return &lppaca[cpu];
@@ -73,6 +79,9 @@ static void __init free_lppacas(void) {long new_size =0 , nr; +if (early_cpu_has_feature (CPU_FTR_HVMODE )) +return ; +if (!lppaca_size)return ; nr =num_possible_cpus () -NR_LPPACAS ;
@@ -157,9 +166,10 @@ EXPORT_SYMBOL(paca);void __init initialise_paca (struct paca_struct *new_paca,int cpu) { -#ifdef CONFIG_PPC_BOOK3S +#ifdef CONFIG_PPC_PSERIES new_paca->lppaca_ptr =new_lppaca (cpu); -#else +#endif +#ifdef CONFIG_PPC_BOOK3E new_paca->kernel_pgd = swapper_pg_dir;#endif new_paca->lock_token =0x8000 ;
arch/powerpc/kvm/book3s_hv_interrupts.S +1 -2
@@ -79,8 +79,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) li r5, 0 mtspr SPRN_MMCRA, r5 isync - ld r3, PACALPPACAPTR(r13) /* is the host using the PMU? */ - lbz r5, LPPACA_PMCINUSE(r3) + lbz r5, PACA_PMCINUSE(r13) /* is the host using the PMU? */ cmpwi r5, 0 beq 31f /* skip if not */ mfspr r5, SPRN_MMCR1
arch/powerpc/kvm/book3s_hv_rmhandlers.S +1 -2
@@ -113,8 +113,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S) mtspr SPRN_SPRG_VDSO_WRITE,r3 /* Reload the host's PMU registers */ - ld r3, PACALPPACAPTR(r13) /* is the host using the PMU? */ - lbz r4, LPPACA_PMCINUSE(r3) + lbz r4, PACA_PMCINUSE(r13) /* is the host using the PMU? */ cmpwi r4, 0 beq 23f /* skip if not */ BEGIN_FTR_SECTION
Signature · 1 line
2.15.0
Nicholas Piggin
reviewerPATCH 8/9 powerpc/64: Use array of paca pointers and allocate pacas individually
In reply to Nicholas PigginChange the paca array into an array of pointers to pacas. Allocate pacas individually.
This allows flexibility in where the PACAs are allocated. Future work will allocate them node-local. Platforms that don't have address limits on PACAs would be able to defer PACA allocations until later in boot rather than allocate all possible ones up-front then freeing unused.
This is slightly more overhead (one additional indirection) for cross CPU paca references, but those aren't too common.
--- arch/powerpc/include/asm/kvm_ppc.h | 8 ++-- arch/powerpc/include/asm/lppaca.h | 2 +- arch/powerpc/include/asm/paca.h | 4 +- arch/powerpc/include/asm/smp.h | 4 +- arch/powerpc/kernel/crash.c | 2 +- arch/powerpc/kernel/head_64.S | 19 ++++---- arch/powerpc/kernel/machine_kexec_64.c | 22 ++++----- arch/powerpc/kernel/paca.c | 70 +++++++++++++++++++--------- arch/powerpc/kernel/setup_64.c | 18 +++---- arch/powerpc/kernel/smp.c | 10 ++-- arch/powerpc/kernel/sysfs.c | 2 +- arch/powerpc/kvm/book3s_hv.c | 31 ++++++------ arch/powerpc/kvm/book3s_hv_builtin.c | 2 +- arch/powerpc/mm/tlb-radix.c | 2 +- arch/powerpc/platforms/85xx/smp.c | 8 ++-- arch/powerpc/platforms/cell/smp.c | 4 +- arch/powerpc/platforms/powernv/idle.c | 13 +++--- arch/powerpc/platforms/powernv/setup.c | 4 +- arch/powerpc/platforms/powernv/smp.c | 2 +- arch/powerpc/platforms/powernv/subcore.c | 2 +- arch/powerpc/platforms/pseries/hotplug-cpu.c | 2 +- arch/powerpc/platforms/pseries/lpar.c | 4 +- arch/powerpc/platforms/pseries/setup.c | 2 +- arch/powerpc/platforms/pseries/smp.c | 4 +- arch/powerpc/sysdev/xics/icp-native.c | 2 +- arch/powerpc/xmon/xmon.c | 2 +- 26 files changed, 140 insertions(+), 105 deletions(-)
arch/powerpc/include/asm/kvm_ppc.h +4 -4
@@ -432,15 +432,15 @@ struct openpic;extern void kvm_cma_reserve (void )__init ;static inline void kvmppc_set_xics_phys (int cpu,unsigned long addr) { - paca[cpu].kvm_hstate.xics_phys = (void __iomem *)addr; + paca_ptrs[cpu]->kvm_hstate.xics_phys = (void __iomem *)addr; }static inline void kvmppc_set_xive_tima (int cpu,unsigned long phys_addr,void __iomem *virt_addr) { - paca[cpu].kvm_hstate.xive_tima_phys = (void __iomem *)phys_addr; - paca[cpu].kvm_hstate.xive_tima_virt = virt_addr; + paca_ptrs[cpu]->kvm_hstate.xive_tima_phys = (void __iomem *)phys_addr; + paca_ptrs[cpu]->kvm_hstate.xive_tima_virt = virt_addr; }static inline u32 kvmppc_get_xics_latch (void )
@@ -454,7 +454,7 @@ static inline u32 kvmppc_get_xics_latch(void)static inline void kvmppc_set_host_ipi (int cpu,u8 host_ipi) { - paca[cpu].kvm_hstate.host_ipi = host_ipi; + paca_ptrs[cpu]->kvm_hstate.host_ipi = host_ipi; }static inline void kvmppc_fast_vcpu_kick (struct kvm_vcpu *vcpu)
arch/powerpc/include/asm/lppaca.h +1 -1
@@ -103,7 +103,7 @@ struct lppaca {extern struct lppaca lppaca[]; -#define lppaca_of (cpu) (*paca[cpu].lppaca_ptr) +#define lppaca_of (cpu) (*paca_ptrs[cpu]->lppaca_ptr)/* * We are using a non architected field to determine if a partition is
arch/powerpc/include/asm/paca.h +2 -2
@@ -236,10 +236,10 @@ struct paca_struct {struct sibling_subcore_state *sibling_subcore_state;#endif #endif -}; +}____cacheline_aligned ;extern void copy_mm_to_paca (struct mm_struct *mm); -extern struct paca_struct *paca; +extern struct paca_struct **paca_ptrs;extern void initialise_paca (struct paca_struct *new_paca,int cpu);extern void setup_paca (struct paca_struct *new_paca);extern void allocate_pacas (void );
arch/powerpc/include/asm/smp.h +2 -2
@@ -170,12 +170,12 @@ static inline const struct cpumask *cpu_sibling_mask(int cpu)#ifdef CONFIG_PPC64 static inline int get_hard_smp_processor_id (int cpu) { -return paca[cpu].hw_cpu_id; +return paca_ptrs[cpu]->hw_cpu_id; }static inline void set_hard_smp_processor_id (int cpu,int phys) { - paca[cpu].hw_cpu_id = phys; + paca_ptrs[cpu]->hw_cpu_id = phys; }#else /* 32-bit */
arch/powerpc/kernel/crash.c +1 -1
@@ -230,7 +230,7 @@ static void __maybe_unused crash_kexec_wait_realmode(int cpu)if (i == cpu)continue ; -while (paca[i].kexec_state <KEXEC_STATE_REAL_MODE ) { +while (paca_ptrs[i]->kexec_state <KEXEC_STATE_REAL_MODE ) {barrier ();if (!cpu_possible (i) || !cpu_online (i) || (msecs <=0 ))break ;
arch/powerpc/kernel/head_64.S +10 -9
@@ -392,19 +392,20 @@ generic_secondary_common_init: * physical cpu id in r24, we need to search the pacas to find * which logical id maps to our physical one. */ - LOAD_REG_ADDR(r13, paca) /* Load paca pointer */ - ld r13,0(r13) /* Get base vaddr of paca array */ #ifndef CONFIG_SMP - addi r13,r13,PACA_SIZE /* know r13 if used accidentally */ b kexec_wait /* wait for next kernel if !SMP */ #else + LOAD_REG_ADDR(r8, paca_ptrs) /* Load paca_ptrs pointe */ + ld r8,0(r8) /* Get base vaddr of array */ LOAD_REG_ADDR(r7, nr_cpu_ids) /* Load nr_cpu_ids address */ lwz r7,0(r7) /* also the max paca allocated */ li r5,0 /* logical cpu id */ -1: lhz r6,PACAHWCPUID(r13) /* Load HW procid from paca */ +1: + sldi r9,r5,3 /* get paca_ptrs[] index from cpu id */ + ldx r13,r9,r8 /* r13 = paca_ptrs[cpu id] */ + lhz r6,PACAHWCPUID(r13) /* Load HW procid from paca */ cmpw r6,r24 /* Compare to our id */ beq 2f - addi r13,r13,PACA_SIZE /* Loop to next PACA on miss */ addi r5,r5,1 cmpw r5,r7 /* Check if more pacas exist */ blt 1b
@@ -756,10 +757,10 @@ _GLOBAL(pmac_secondary_start) mtmsrd r3 /* RI on */ /* Set up a paca value for this processor. */ - LOAD_REG_ADDR(r4,paca) /* Load paca pointer */ - ld r4,0(r4) /* Get base vaddr of paca array */ - mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */ - add r13,r13,r4 /* for this processor. */ + LOAD_REG_ADDR(r4,paca_ptrs) /* Load paca pointer */ + ld r4,0(r4) /* Get base vaddr of paca_ptrs array */ + sldi r5,r24,3 /* get paca_ptrs[] index from cpu id */ + ldx r13,r5,r4 /* r13 = paca_ptrs[cpu id] */ SET_PACA(r13) /* Save vaddr of paca in an SPRG*/ /* Mark interrupts soft and hard disabled (they might be enabled
arch/powerpc/kernel/machine_kexec_64.c +11 -11
@@ -168,24 +168,25 @@ static void kexec_prepare_cpus_wait(int wait_state)* are correctly onlined. If somehow we start a CPU on boot with RTAS * start-cpu, but somehow that CPU doesn't write callin_cpu_map[] in * time, the boot CPU will timeout. If it does eventually execute -* stuff, the secondary will start up (paca[].cpu_start was written) and -* get into a peculiar state. If the platform supports -* smp_ops->take_timebase(), the secondary CPU will probably be spinning -* in there. If not (i.e. pseries), the secondary will continue on and -* try to online itself/idle/etc. If it survives that, we need to find -* these possible-but-not-online-but-should-be CPUs and chaperone them -* into kexec_smp_wait(). +* stuff, the secondary will start up (paca_ptrs[]->cpu_start was +* written) and get into a peculiar state. +* If the platform supports smp_ops->take_timebase(), the secondary CPU +* will probably be spinning in there. If not (i.e. pseries), the +* secondary will continue on and try to online itself/idle/etc. If it +* survives that, we need to find these +* possible-but-not-online-but-should-be CPUs and chaperone them into +* kexec_smp_wait(). */ for_each_online_cpu (i) {if (i == my_cpu)continue ; -while (paca[i].kexec_state < wait_state) { +while (paca_ptrs[i]->kexec_state < wait_state) {barrier ();if (i != notified) {printk (KERN_INFO "kexec: waiting for cpu %d " "(physical %d) to enter %i state\n" , - i, paca[i].hw_cpu_id, wait_state); + i, paca_ptrs[i]->hw_cpu_id, wait_state); notified = i; } }
@@ -327,8 +328,7 @@ void default_machine_kexec(struct kimage *image)*/ memcpy (&kexec_paca,get_paca (),sizeof (struct paca_struct )); kexec_paca.data_offset =0xedeaddeadeeeeeeeUL ; - paca = (struct paca_struct *)RELOC_HIDE (&kexec_paca,0 ) - - kexec_paca.paca_index; + paca_ptrs[kexec_paca.paca_index] = &kexec_paca;setup_paca (&kexec_paca);/* XXX: If anyone does 'dynamic lppacas' this will also need to be
arch/powerpc/kernel/paca.c +49 -21
107 lines not on this page · raw message
arch/powerpc/kernel/setup_64.c +9 -9
@@ -108,7 +108,7 @@ void __init setup_tlb_core_data(void)if (cpu_first_thread_sibling (boot_cpuid) == first) first = boot_cpuid; - paca[cpu].tcd_ptr = &paca[first].tcd; + paca_ptrs[cpu]->tcd_ptr = &paca_ptrs[first]->tcd;/* * If we have threads, we need either tlbsrx.
@@ -300,7 +300,7 @@ 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. */ -setup_paca (&paca[boot_cpuid]); +setup_paca (paca_ptrs[boot_cpuid]);fixup_boot_paca ();/*
@@ -624,15 +624,15 @@ void __init exc_lvl_early_init(void)for_each_possible_cpu (i) { sp =memblock_alloc (THREAD_SIZE ,THREAD_SIZE ); critirq_ctx[i] = (struct thread_info *)__va (sp); - paca[i].crit_kstack =__va (sp +THREAD_SIZE ); + paca_ptrs[i]->crit_kstack =__va (sp +THREAD_SIZE ); sp =memblock_alloc (THREAD_SIZE ,THREAD_SIZE ); dbgirq_ctx[i] = (struct thread_info *)__va (sp); - paca[i].dbg_kstack =__va (sp +THREAD_SIZE ); + paca_ptrs[i]->dbg_kstack =__va (sp +THREAD_SIZE ); sp =memblock_alloc (THREAD_SIZE ,THREAD_SIZE ); mcheckirq_ctx[i] = (struct thread_info *)__va (sp); - paca[i].mc_kstack =__va (sp +THREAD_SIZE ); + paca_ptrs[i]->mc_kstack =__va (sp +THREAD_SIZE ); }if (cpu_has_feature (CPU_FTR_DEBUG_LVL_EXC ))
@@ -689,20 +689,20 @@ void __init emergency_stack_init(void) ti =__va (memblock_alloc_base (THREAD_SIZE ,THREAD_SIZE , limit));memset (ti,0 ,THREAD_SIZE );emerg_stack_init_thread_info (ti, i); - paca[i].emergency_sp = (void *)ti +THREAD_SIZE ; + paca_ptrs[i]->emergency_sp = (void *)ti +THREAD_SIZE ;#ifdef CONFIG_PPC_BOOK3S_64 /* emergency stack for NMI exception handling. */ ti =__va (memblock_alloc_base (THREAD_SIZE ,THREAD_SIZE , limit));memset (ti,0 ,THREAD_SIZE );emerg_stack_init_thread_info (ti, i); - paca[i].nmi_emergency_sp = (void *)ti +THREAD_SIZE ; + paca_ptrs[i]->nmi_emergency_sp = (void *)ti +THREAD_SIZE ;/* emergency stack for machine check exception handling. */ ti =__va (memblock_alloc_base (THREAD_SIZE ,THREAD_SIZE , limit));memset (ti,0 ,THREAD_SIZE );emerg_stack_init_thread_info (ti, i); - paca[i].mc_emergency_sp = (void *)ti +THREAD_SIZE ; + paca_ptrs[i]->mc_emergency_sp = (void *)ti +THREAD_SIZE ;#endif } }
@@ -758,7 +758,7 @@ void __init setup_per_cpu_areas(void) delta = (unsigned long )pcpu_base_addr - (unsigned long )__per_cpu_start;for_each_possible_cpu (cpu) { __per_cpu_offset[cpu] = delta + pcpu_unit_offsets[cpu]; - paca[cpu].data_offset = __per_cpu_offset[cpu]; + paca_ptrs[cpu]->data_offset = __per_cpu_offset[cpu]; } }#endif
arch/powerpc/kernel/smp.c +5 -5
@@ -123,8 +123,8 @@ int smp_generic_kick_cpu(int nr)* cpu_start field to become non-zero After we set cpu_start, * the processor will continue on to secondary_start */ -if (!paca[nr].cpu_start) { - paca[nr].cpu_start =1 ; +if (!paca_ptrs[nr]->cpu_start) { + paca_ptrs[nr]->cpu_start =1 ;smp_mb ();return 0 ; }
@@ -639,7 +639,7 @@ void smp_prepare_boot_cpu(void) {BUG_ON (smp_processor_id () != boot_cpuid);#ifdef CONFIG_PPC64 - paca[boot_cpuid].__current = current; + paca_ptrs[boot_cpuid]->__current = current;#endif set_numa_node (numa_cpu_lookup_table[boot_cpuid]); current_set[boot_cpuid] =task_thread_info (current);
@@ -730,8 +730,8 @@ static void cpu_idle_thread_init(unsigned int cpu, struct task_struct *idle)struct thread_info *ti =task_thread_info (idle);#ifdef CONFIG_PPC64 - paca[cpu].__current = idle; - paca[cpu].kstack = (unsigned long )ti +THREAD_SIZE -STACK_FRAME_OVERHEAD ; + paca_ptrs[cpu]->__current = idle; + paca_ptrs[cpu]->kstack = (unsigned long )ti +THREAD_SIZE -STACK_FRAME_OVERHEAD ;#endif ti->cpu = cpu; secondary_ti = current_set[cpu] = ti;
arch/powerpc/kernel/sysfs.c +1 -1
@@ -598,7 +598,7 @@ void __init record_spr_defaults(void)if (cpu_has_feature (CPU_FTR_DSCR )) { dscr_default =mfspr (SPRN_DSCR );for (cpu =0 ; cpu < nr_cpu_ids; cpu++) - paca[cpu].dscr_default = dscr_default; + paca_ptrs[cpu]->dscr_default = dscr_default; } }#endif /* CONFIG_PPC64 */
arch/powerpc/kvm/book3s_hv.c +18 -13
@@ -169,7 +169,7 @@ static bool kvmppc_ipi_thread(int cpu)#if defined(CONFIG_PPC_ICP_NATIVE ) && defined(CONFIG_SMP )if (cpu >=0 && cpu < nr_cpu_ids) { -if (paca[cpu].kvm_hstate.xics_phys) { +if (paca_ptrs[cpu]->kvm_hstate.xics_phys) {xics_wake_cpu (cpu);return true; }
@@ -2124,7 +2124,7 @@ static int kvmppc_grab_hwthread(int cpu)struct paca_struct *tpaca;long timeout =10000 ; - tpaca = &paca[cpu]; + tpaca = paca_ptrs[cpu];/* Ensure the thread won't go into the kernel if it wakes */ tpaca->kvm_hstate.kvm_vcpu =NULL ;
@@ -2157,7 +2157,7 @@ static void kvmppc_release_hwthread(int cpu) {struct paca_struct *tpaca; - tpaca = &paca[cpu]; + tpaca = paca_ptrs[cpu]; tpaca->kvm_hstate.hwthread_req =0 ; tpaca->kvm_hstate.kvm_vcpu =NULL ; tpaca->kvm_hstate.kvm_vcore =NULL ;
@@ -2223,7 +2223,7 @@ static void kvmppc_start_thread(struct kvm_vcpu *vcpu, struct kvmppc_vcore *vc) vcpu->arch.thread_cpu = cpu;cpumask_set_cpu (cpu, &kvm->arch.cpu_in_guest); } - tpaca = &paca[cpu]; + tpaca = paca_ptrs[cpu]; tpaca->kvm_hstate.kvm_vcpu = vcpu; tpaca->kvm_hstate.ptid = cpu - vc->pcpu;/* Order stores to hstate.kvm_vcpu etc. before store to kvm_vcore */
@@ -2248,7 +2248,7 @@ static void kvmppc_wait_for_nap(int n_threads)* for any threads that still have a non-NULL vcore ptr. */ for (i =1 ; i < n_threads; ++i) -if (paca[cpu + i].kvm_hstate.kvm_vcore) +if (paca_ptrs[cpu + i]->kvm_hstate.kvm_vcore)break ;if (i == n_threads) {HMT_medium ();
@@ -2258,7 +2258,7 @@ static void kvmppc_wait_for_nap(int n_threads) }HMT_medium ();for (i =1 ; i < n_threads; ++i) -if (paca[cpu + i].kvm_hstate.kvm_vcore) +if (paca_ptrs[cpu + i]->kvm_hstate.kvm_vcore)pr_err ("KVM: CPU %d seems to be stuck\n" , cpu + i); }
@@ -2788,9 +2788,11 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc) }for (thr =0 ; thr < controlled_threads; ++thr) { - paca[pcpu + thr].kvm_hstate.tid = thr; - paca[pcpu + thr].kvm_hstate.napping =0 ; - paca[pcpu + thr].kvm_hstate.kvm_split_mode = sip; +struct paca_struct *paca = paca_ptrs[pcpu + thr]; + + paca->kvm_hstate.tid = thr; + paca->kvm_hstate.napping =0 ; + paca->kvm_hstate.kvm_split_mode = sip; }/* Initiate micro-threading (split-core) on POWER8 if required */
@@ -2908,7 +2910,9 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc) }else if (hpt_on_radix) {/* Wait for all threads to have seen final sync */ for (thr =1 ; thr < controlled_threads; ++thr) { -while (paca[pcpu + thr].kvm_hstate.kvm_split_mode) { +struct paca_struct *paca = paca_ptrs[pcpu + thr]; + +while (paca->kvm_hstate.kvm_split_mode) {HMT_low ();barrier (); }
@@ -4378,7 +4382,7 @@ static int kvm_init_subcore_bitmap(void)int node =cpu_to_node (first_cpu);/* Ignore if it is already allocated. */ -if (paca[first_cpu].sibling_subcore_state) +if (paca_ptrs[first_cpu]->sibling_subcore_state)continue ; sibling_subcore_state =
@@ -4393,7 +4397,8 @@ static int kvm_init_subcore_bitmap(void)for (j =0 ; j < threads_per_core; j++) {int cpu = first_cpu + j; - paca[cpu].sibling_subcore_state = sibling_subcore_state; + paca_ptrs[cpu]->sibling_subcore_state = + sibling_subcore_state; } }return 0 ;
@@ -4420,7 +4425,7 @@ static int kvmppc_book3s_init_hv(void)/* * We need a way of accessing the XICS interrupt controller, -* either directly, via paca[cpu].kvm_hstate.xics_phys, or +* either directly, via paca_ptrs[cpu]->kvm_hstate.xics_phys, or * indirectly, via OPAL. */ #ifdef CONFIG_SMP
arch/powerpc/kvm/book3s_hv_builtin.c +1 -1
@@ -251,7 +251,7 @@ void kvmhv_rm_send_ipi(int cpu)return ;/* Else poke the target with an IPI */ - xics_phys = paca[cpu].kvm_hstate.xics_phys; + xics_phys = paca_ptrs[cpu]->kvm_hstate.xics_phys;if (xics_phys)__raw_rm_writeb (IPI_PRIORITY , xics_phys +XICS_MFRR );else
arch/powerpc/mm/tlb-radix.c +1 -1
@@ -659,7 +659,7 @@ extern void radix_kvm_prefetch_workaround(struct mm_struct *mm)for (; sib <=cpu_last_thread_sibling (cpu) && !flush; sib++) {if (sib == cpu)continue ; -if (paca[sib].kvm_hstate.kvm_vcpu) +if (paca_ptrs[sib]->kvm_hstate.kvm_vcpu) flush = true; }if (flush)
arch/powerpc/platforms/85xx/smp.c +4 -4
@@ -147,7 +147,7 @@ static void qoriq_cpu_kill(unsigned int cpu)for (i =0 ; i <500 ; i++) {if (is_cpu_dead (cpu)) {#ifdef CONFIG_PPC64 - paca[cpu].cpu_start =0 ; + paca_ptrs[cpu]->cpu_start =0 ;#endif return ; }
@@ -328,7 +328,7 @@ static int smp_85xx_kick_cpu(int nr)return ret; done: - paca[nr].cpu_start =1 ; + paca_ptrs[nr]->cpu_start =1 ;generic_set_cpu_up (nr);return ret;
@@ -409,14 +409,14 @@ void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary) }if (disable_threadbit) { -while (paca[disable_cpu].kexec_state <KEXEC_STATE_REAL_MODE ) { +while (paca_ptrs[disable_cpu]->kexec_state <KEXEC_STATE_REAL_MODE ) {barrier (); now =mftb ();if (!notified && now - start >1000000 ) {pr_info ("%s/%d: waiting for cpu %d to enter KEXEC_STATE_REAL_MODE (%d)\n" , __func__,smp_processor_id (), disable_cpu, - paca[disable_cpu].kexec_state); + paca_ptrs[disable_cpu]->kexec_state); notified = true; } }
arch/powerpc/platforms/cell/smp.c +2 -2
@@ -83,7 +83,7 @@ static inline int smp_startup_cpu(unsigned int lcpu) pcpu =get_hard_smp_processor_id (lcpu);/* Fixup atomic count: it exited inside IRQ handler. */ -task_thread_info (paca[lcpu].__current)->preempt_count =0 ; +task_thread_info (paca_ptrs[lcpu]->__current)->preempt_count =0 ;/* * If the RTAS start-cpu token does not exist then presume the
@@ -126,7 +126,7 @@ static int smp_cell_kick_cpu(int nr)* cpu_start field to become non-zero After we set cpu_start, * the processor will continue on to secondary_start */ - paca[nr].cpu_start =1 ; + paca_ptrs[nr]->cpu_start =1 ;return 0 ; }
arch/powerpc/platforms/powernv/idle.c +7 -6
@@ -80,7 +80,7 @@ static int pnv_save_sprs_for_deep_states(void)for_each_possible_cpu (cpu) {uint64_t pir =get_hard_smp_processor_id (cpu); -uint64_t hsprg0_val = (uint64_t )&paca[cpu]; +uint64_t hsprg0_val = (uint64_t )paca_ptrs[cpu]; rc =opal_slw_set_reg (pir,SPRN_HSPRG0 , hsprg0_val);if (rc !=0 )
@@ -173,12 +173,12 @@ static void pnv_alloc_idle_core_states(void)for (j =0 ; j < threads_per_core; j++) {int cpu = first_cpu + j; - paca[cpu].core_idle_state_ptr = core_idle_state; - paca[cpu].thread_idle_state =PNV_THREAD_RUNNING ; - paca[cpu].thread_mask =1 << j; + paca_ptrs[cpu]->core_idle_state_ptr = core_idle_state; + paca_ptrs[cpu]->thread_idle_state =PNV_THREAD_RUNNING ; + paca_ptrs[cpu]->thread_mask =1 << j;if (!cpu_has_feature (CPU_FTR_POWER9_DD1 ))continue ; - paca[cpu].thread_sibling_pacas = + paca_ptrs[cpu]->thread_sibling_pacas =kmalloc_node (paca_ptr_array_size,GFP_KERNEL , node); }
@@ -749,7 +749,8 @@ static int __init pnv_init_idle_states(void)for (i =0 ; i < threads_per_core; i++) {int j = base_cpu + i; - paca[j].thread_sibling_pacas[idx] = &paca[cpu]; + paca_ptrs[j]->thread_sibling_pacas[idx] = + paca_ptrs[cpu]; } } }
arch/powerpc/platforms/powernv/setup.c +2 -2
@@ -205,7 +205,7 @@ static void pnv_kexec_wait_secondaries_down(void)if (i != notified) {printk (KERN_INFO "kexec: waiting for cpu %d " "(physical %d) to enter OPAL\n" , - i, paca[i].hw_cpu_id); + i, paca_ptrs[i]->hw_cpu_id); notified = i; }
@@ -217,7 +217,7 @@ static void pnv_kexec_wait_secondaries_down(void)if (timeout-- ==0 ) {printk (KERN_ERR "kexec: timed out waiting for " "cpu %d (physical %d) to enter OPAL\n" , - i, paca[i].hw_cpu_id); + i, paca_ptrs[i]->hw_cpu_id);break ; } }
arch/powerpc/platforms/powernv/smp.c +1 -1
@@ -78,7 +78,7 @@ static int pnv_smp_kick_cpu(int nr)* If we already started or OPAL is not supported, we just * kick the CPU via the PACA */ -if (paca[nr].cpu_start || !firmware_has_feature (FW_FEATURE_OPAL )) +if (paca_ptrs[nr]->cpu_start || !firmware_has_feature (FW_FEATURE_OPAL )) goto kick;/*
arch/powerpc/platforms/powernv/subcore.c +1 -1
@@ -280,7 +280,7 @@ void update_subcore_sibling_mask(void)int offset = (tid / threads_per_subcore) * threads_per_subcore;int mask = sibling_mask_first_cpu << offset; - paca[cpu].subcore_sibling_mask = mask; + paca_ptrs[cpu]->subcore_sibling_mask = mask; } }
arch/powerpc/platforms/pseries/hotplug-cpu.c +1 -1
@@ -233,7 +233,7 @@ static void pseries_cpu_die(unsigned int cpu)* done here. Change isolate state to Isolate and * change allocation-state to Unusable. */ - paca[cpu].cpu_start =0 ; + paca_ptrs[cpu]->cpu_start =0 ; }/*
arch/powerpc/platforms/pseries/lpar.c +2 -2
@@ -99,7 +99,7 @@ void vpa_init(int cpu)* reports that. All SPLPAR support SLB shadow buffer. */ if (!radix_enabled () &&firmware_has_feature (FW_FEATURE_SPLPAR )) { - addr =__pa (paca[cpu].slb_shadow_ptr); + addr =__pa (paca_ptrs[cpu]->slb_shadow_ptr); ret =register_slb_shadow (hwcpu, addr);if (ret) pr_err("WARNING: SLB shadow buffer registration for "
@@ -111,7 +111,7 @@ void vpa_init(int cpu)/* * Register dispatch trace log, if one has been allocated. */ - pp = &paca[cpu]; + pp = paca_ptrs[cpu]; dtl = pp->dispatch_log;if (dtl) { pp->dtl_ridx =0 ;
arch/powerpc/platforms/pseries/setup.c +1 -1
@@ -246,7 +246,7 @@ static int alloc_dispatch_logs(void)return 0 ;for_each_possible_cpu (cpu) { - pp = &paca[cpu]; + pp = paca_ptrs[cpu]; dtl =kmem_cache_alloc (dtl_cache,GFP_KERNEL );if (!dtl) { pr_warn("Failed to allocate dispatch trace log for cpu %d\n",
arch/powerpc/platforms/pseries/smp.c +2 -2
@@ -110,7 +110,7 @@ static inline int smp_startup_cpu(unsigned int lcpu) }/* Fixup atomic count: it exited inside IRQ handler. */ -task_thread_info (paca[lcpu].__current)->preempt_count =0 ; +task_thread_info (paca_ptrs[lcpu]->__current)->preempt_count =0 ;#ifdef CONFIG_HOTPLUG_CPU if (get_cpu_current_state (lcpu) ==CPU_STATE_INACTIVE ) goto out;
@@ -165,7 +165,7 @@ static int smp_pSeries_kick_cpu(int nr)* cpu_start field to become non-zero After we set cpu_start, * the processor will continue on to secondary_start */ - paca[nr].cpu_start =1 ; + paca_ptrs[nr]->cpu_start =1 ;#ifdef CONFIG_HOTPLUG_CPU set_preferred_offline_state (nr,CPU_STATE_ONLINE );
arch/powerpc/sysdev/xics/icp-native.c +1 -1
@@ -164,7 +164,7 @@ void icp_native_cause_ipi_rm(int cpu)* Just like the cause_ipi functions, it is required to * include a full barrier before causing the IPI. */ - xics_phys = paca[cpu].kvm_hstate.xics_phys; + xics_phys = paca_ptrs[cpu]->kvm_hstate.xics_phys;mb ();__raw_rm_writeb (IPI_PRIORITY , xics_phys +XICS_MFRR ); }
arch/powerpc/xmon/xmon.c +1 -1
@@ -2327,7 +2327,7 @@ static void dump_one_paca(int cpu) catch_memory_errors =1 ;sync (); - p = &paca[cpu]; + p = paca_ptrs[cpu];printf ("paca for cpu 0x%x @ %px:\n" , cpu, p);
Signature · 1 line
2.15.0
Nicholas Piggin
reviewerPATCH 9/9 powerpc/64s: Use array of lppaca pointers and allocate lppacas individually
In reply to Nicholas PigginSimilary to the previous patch, allocate LPPACAs individually.
We no longer allocate lppacas in an array, so this patch removes the 1kB static alignment for the structure, and enforce the PAPR alignment requirements at allocation time. We can not reduce the 1kB allocation size however, due to existing KVM hypervisors.
--- arch/powerpc/include/asm/lppaca.h | 24 ++++----- arch/powerpc/kernel/machine_kexec_64.c | 15 ++++-- arch/powerpc/kernel/paca.c | 89 ++++++++++++---------------------- arch/powerpc/kvm/book3s_hv.c | 3 +- arch/powerpc/mm/numa.c | 4 +- arch/powerpc/platforms/pseries/kexec.c | 7 ++- 6 files changed, 63 insertions(+), 79 deletions(-)
arch/powerpc/include/asm/lppaca.h +12 -12
@@ -36,14 +36,16 @@#include <asm/mmu.h> /* -* We only have to have statically allocated lppaca structs on -* legacy iSeries, which supports at most 64 cpus. -*/ -#define NR_LPPACAS 1 - -/* -* The Hypervisor barfs if the lppaca crosses a page boundary. A 1k -* alignment is sufficient to prevent this +* The lppaca is the "virtual processor area" registered with the hypervisor, +* H_REGISTER_VPA etc. +* +* According to PAPR, the structure is 640 bytes long, must be L1 cache line +* aligned, and must not cross a 4kB boundary. Its size field must be at +* least 640 bytes (but may be more). +* +* Pre-v4.14 KVM hypervisors reject the VPA if its size field is smaller than +* 1kB, so we dynamically allocate 1kB and advertise size as 1kB, but keep +* this structure as the canonical 640 byte size. */ struct lppaca {/* cacheline 1 contains read-only data */
@@ -97,11 +99,9 @@ struct lppaca {__be32 page_ins;/* CMO Hint - # page ins by OS */ u8 reserved11[148 ]; -volatile __be64 dtl_idx;/* Dispatch Trace Log head index */ +volatile __be64 dtl_idx;/* Dispatch Trace Log head index */ u8 reserved12[96 ]; -} __attribute__((__aligned__(0x400))); - -extern struct lppaca lppaca[]; +}____cacheline_aligned ;#define lppaca_of (cpu) (*paca_ptrs[cpu]->lppaca_ptr)
arch/powerpc/kernel/machine_kexec_64.c +11 -4
@@ -323,17 +323,24 @@ void default_machine_kexec(struct kimage *image) kexec_stack.thread_info.cpu =current_thread_info ()->cpu;/* We need a static PACA, too; copy this CPU's PACA over and switch to -* it. Also poison per_cpu_offset to catch anyone using non-static -* data. +* it. Also poison per_cpu_offset and NULL lppaca to catch anyone using +* non-static data. */ memcpy (&kexec_paca,get_paca (),sizeof (struct paca_struct )); kexec_paca.data_offset =0xedeaddeadeeeeeeeUL ; +#ifdef CONFIG_PPC_PSERIES + kexec_paca.lppaca_ptr =NULL ; +#endif paca_ptrs[kexec_paca.paca_index] = &kexec_paca; +setup_paca (&kexec_paca); -/* XXX: If anyone does 'dynamic lppacas' this will also need to be -* switched to a static version! +/* +* The lppaca should be unregistered at this point so the HV won't +* touch it. In the case of a crash, none of the lppacas are +* unregistered so there is not much we can do about it here. */ +/* * On Book3S, the copy must happen with the MMU off if we are either * using Radix page tables or we are not in an LPAR since we can
arch/powerpc/kernel/paca.c +30 -59
146 lines not on this page · raw message
arch/powerpc/kvm/book3s_hv.c +2 -1
@@ -497,7 +497,8 @@ static unsigned long do_h_register_vpa(struct kvm_vcpu *vcpu,* use 640 bytes of the structure though, so we should accept * clients that set a size of 640. */ -if (len <640 ) +BUILD_BUG_ON (sizeof (struct lppaca ) !=640 ); +if (len <sizeof (struct lppaca ))break ; vpap = &tvcpu->arch.vpa; err =0 ;
arch/powerpc/mm/numa.c +2 -2
@@ -1190,7 +1190,7 @@ static void setup_cpu_associativity_change_counters(void)for_each_possible_cpu (cpu) {int i;u8 *counts = vphn_cpu_change_counts[cpu]; -volatile u8 *hypervisor_counts = lppaca[cpu].vphn_assoc_counts; +volatile u8 *hypervisor_counts =lppaca_of (cpu).vphn_assoc_counts;for (i =0 ; i < distance_ref_points_depth; i++) counts[i] = hypervisor_counts[i];
@@ -1216,7 +1216,7 @@ static int update_cpu_associativity_changes_mask(void)for_each_possible_cpu (cpu) {int i, changed =0 ;u8 *counts = vphn_cpu_change_counts[cpu]; -volatile u8 *hypervisor_counts = lppaca[cpu].vphn_assoc_counts; +volatile u8 *hypervisor_counts =lppaca_of (cpu).vphn_assoc_counts;for (i =0 ; i < distance_ref_points_depth; i++) {if (hypervisor_counts[i] != counts[i]) {
arch/powerpc/platforms/pseries/kexec.c +6 -1
@@ -23,7 +23,12 @@void pseries_kexec_cpu_down (int crash_shutdown,int secondary) { -/* Don't risk a hypervisor call if we're crashing */ +/* +* Don't risk a hypervisor call if we're crashing +* XXX: Why? The hypervisor is not crashing. It might be better +* to at least attempt unregister to avoid the hypervisor stepping +* on our memory. +*/ if (firmware_has_feature (FW_FEATURE_SPLPAR ) && !crash_shutdown) {int ret;int cpu =smp_processor_id ();
Signature · 1 line
2.15.0