powerpc/64s: dt_cpu_ftrs use tlbiel-sets mmu property
Subsystems (2)
Nicholas Piggin
reviewerPATCH 1/1 powerpc/64s: dt_cpu_ftrs use tlbiel-sets mmu property
Remove the open-coding of radix set sizes for loops. Populate the cputable with the correct values for old firmware, but dt_cpu_ftrs will use a property under its mmu feature nodes.
---
Hi,
This is a proposal for a different approach here, by using specific properties under dt_cpu_ftrs feature nodes to provide more data.
This was some question about whether we should allow these kind of custom properties in general. Code-wise, it turns out simpler to do it this way mainly because a dependency between the init-time TLB flushing in the dt_cpu_ftrs init case, and the parsing of the tlbiel-sets value.
So it would be pretty trivial *not* to do it this way (and the boot time tlb flushing needs to be reworked and moved later in boot anyway), but it kind of turns out pretty nicely this way.
arch/powerpc/include/asm/cputable.h | 14 +++++------ arch/powerpc/include/asm/mce.h | 5 ++++ arch/powerpc/kernel/cputable.c | 26 ++++++++++---------- arch/powerpc/kernel/dt_cpu_ftrs.c | 48 +++++++++++++++++++++---------------- arch/powerpc/kernel/mce_power.c | 46 ++++++++--------------------------- arch/powerpc/kernel/prom.c | 1 + arch/powerpc/kvm/book3s_hv.c | 13 +++++----- arch/powerpc/kvm/book3s_hv_ras.c | 6 ++--- arch/powerpc/mm/init_64.c | 7 ++++-- arch/powerpc/mm/tlb-radix.c | 2 +- 10 files changed, 77 insertions(+), 91 deletions(-)
arch/powerpc/include/asm/cputable.h +7 -7
@@ -62,6 +62,12 @@ struct cpu_spec {unsigned int cpu_user_features2;/* Userland features v2 */ unsigned int mmu_features;/* MMU features */ +/* Number of sets/congruence classes for tlbiel IS!=0 invalidation */ +/* For POWER7 and later Book3s 64-bit CPUs */ +unsigned int tlbiel_sets;/* set to current MMU mode */ +unsigned int tlbiel_sets_hash; +unsigned int tlbiel_sets_radix; +/* cache line sizes */ unsigned int icache_bsize;unsigned int dcache_bsize;
@@ -106,12 +112,6 @@ struct cpu_spec {* called in real mode to handle SLB and TLB errors. */ long (*machine_check_early)(struct pt_regs *regs); - -/* -* Processor specific routine to flush tlbs. -*/ -void (*flush_tlb)(unsigned int action); - };extern struct cpu_spec *cur_cpu_spec;
@@ -132,7 +132,7 @@ extern void cpu_feature_keys_init(void);static inline void cpu_feature_keys_init (void ) { }#endif -/* TLB flush actions. Used as argument to cpu_spec.flush_tlb() hook */ +/* TLB flush actions. Used as argument to machine_check_flush_tlb() */ enum {TLB_INVAL_SCOPE_GLOBAL =0 ,/* invalidate all TLBs */ TLB_INVAL_SCOPE_LPID =1 ,/* invalidate TLBs for current LPID */
arch/powerpc/include/asm/mce.h +5 -0
@@ -211,4 +211,9 @@ extern void machine_check_print_event_info(struct machine_check_event *evt, bool user_mode);extern uint64_t get_mce_fault_addr (struct machine_check_event *evt); +/* +* TLB flush for POWER7 and later +*/ +extern void machine_check_flush_tlb (unsigned int action); +#endif /* __ASM_PPC64_MCE_H__ */
arch/powerpc/kernel/cputable.c +12 -14
@@ -74,9 +74,6 @@ extern void __setup_cpu_power8(unsigned long offset, struct cpu_spec* spec);extern void __restore_cpu_power8 (void );extern void __setup_cpu_power9 (unsigned long offset,struct cpu_spec * spec);extern void __restore_cpu_power9 (void ); -extern void __flush_tlb_power7 (unsigned int action); -extern void __flush_tlb_power8 (unsigned int action); -extern void __flush_tlb_power9 (unsigned int action);extern long __machine_check_early_realmode_p7 (struct pt_regs *regs);extern long __machine_check_early_realmode_p8 (struct pt_regs *regs);extern long __machine_check_early_realmode_p9 (struct pt_regs *regs);
@@ -361,13 +358,13 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_user_features = COMMON_USER_POWER7, .cpu_user_features2 = COMMON_USER2_POWER7, .mmu_features = MMU_FTRS_POWER7, + .tlbiel_sets_hash = POWER7_TLB_SETS, .icache_bsize = 128, .dcache_bsize = 128, .oprofile_type = PPC_OPROFILE_POWER4, .oprofile_cpu_type = "ppc64/ibm-compat-v1", .cpu_setup = __setup_cpu_power7, .cpu_restore = __restore_cpu_power7, - .flush_tlb = __flush_tlb_power7, .machine_check_early = __machine_check_early_realmode_p7, .platform = "power7", },
@@ -379,13 +376,13 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_user_features = COMMON_USER_POWER8, .cpu_user_features2 = COMMON_USER2_POWER8, .mmu_features = MMU_FTRS_POWER8, + .tlbiel_sets_hash = POWER8_TLB_SETS, .icache_bsize = 128, .dcache_bsize = 128, .oprofile_type = PPC_OPROFILE_INVALID, .oprofile_cpu_type = "ppc64/ibm-compat-v1", .cpu_setup = __setup_cpu_power8, .cpu_restore = __restore_cpu_power8, - .flush_tlb = __flush_tlb_power8, .machine_check_early = __machine_check_early_realmode_p8, .platform = "power8", },
@@ -403,7 +400,6 @@ static struct cpu_spec __initdata cpu_specs[] = { .oprofile_cpu_type = "ppc64/ibm-compat-v1", .cpu_setup = __setup_cpu_power9, .cpu_restore = __restore_cpu_power9, - .flush_tlb = __flush_tlb_power9, .platform = "power9", }, {/* Power7 */
@@ -414,6 +410,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_user_features = COMMON_USER_POWER7, .cpu_user_features2 = COMMON_USER2_POWER7, .mmu_features = MMU_FTRS_POWER7, + .tlbiel_sets_hash = POWER7_TLB_SETS, .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 6,
@@ -422,7 +419,6 @@ static struct cpu_spec __initdata cpu_specs[] = { .oprofile_type = PPC_OPROFILE_POWER4, .cpu_setup = __setup_cpu_power7, .cpu_restore = __restore_cpu_power7, - .flush_tlb = __flush_tlb_power7, .machine_check_early = __machine_check_early_realmode_p7, .platform = "power7", },
@@ -434,6 +430,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_user_features = COMMON_USER_POWER7, .cpu_user_features2 = COMMON_USER2_POWER7, .mmu_features = MMU_FTRS_POWER7, + .tlbiel_sets_hash = POWER7_TLB_SETS, .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 6,
@@ -442,7 +439,6 @@ static struct cpu_spec __initdata cpu_specs[] = { .oprofile_type = PPC_OPROFILE_POWER4, .cpu_setup = __setup_cpu_power7, .cpu_restore = __restore_cpu_power7, - .flush_tlb = __flush_tlb_power7, .machine_check_early = __machine_check_early_realmode_p7, .platform = "power7+", },
@@ -454,6 +450,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_user_features = COMMON_USER_POWER8, .cpu_user_features2 = COMMON_USER2_POWER8, .mmu_features = MMU_FTRS_POWER8, + .tlbiel_sets_hash = POWER8_TLB_SETS, .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 6,
@@ -462,7 +459,6 @@ static struct cpu_spec __initdata cpu_specs[] = { .oprofile_type = PPC_OPROFILE_INVALID, .cpu_setup = __setup_cpu_power8, .cpu_restore = __restore_cpu_power8, - .flush_tlb = __flush_tlb_power8, .machine_check_early = __machine_check_early_realmode_p8, .platform = "power8", },
@@ -474,6 +470,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_user_features = COMMON_USER_POWER8, .cpu_user_features2 = COMMON_USER2_POWER8, .mmu_features = MMU_FTRS_POWER8, + .tlbiel_sets_hash = POWER8_TLB_SETS, .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 6,
@@ -482,7 +479,6 @@ static struct cpu_spec __initdata cpu_specs[] = { .oprofile_type = PPC_OPROFILE_INVALID, .cpu_setup = __setup_cpu_power8, .cpu_restore = __restore_cpu_power8, - .flush_tlb = __flush_tlb_power8, .machine_check_early = __machine_check_early_realmode_p8, .platform = "power8", },
@@ -494,6 +490,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_user_features = COMMON_USER_POWER8, .cpu_user_features2 = COMMON_USER2_POWER8, .mmu_features = MMU_FTRS_POWER8, + .tlbiel_sets_hash = POWER8_TLB_SETS, .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 6,
@@ -502,7 +499,6 @@ static struct cpu_spec __initdata cpu_specs[] = { .oprofile_type = PPC_OPROFILE_INVALID, .cpu_setup = __setup_cpu_power8, .cpu_restore = __restore_cpu_power8, - .flush_tlb = __flush_tlb_power8, .machine_check_early = __machine_check_early_realmode_p8, .platform = "power8", },
@@ -514,6 +510,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_user_features = COMMON_USER_POWER8, .cpu_user_features2 = COMMON_USER2_POWER8, .mmu_features = MMU_FTRS_POWER8, + .tlbiel_sets_hash = POWER8_TLB_SETS, .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 6,
@@ -522,7 +519,6 @@ static struct cpu_spec __initdata cpu_specs[] = { .oprofile_type = PPC_OPROFILE_INVALID, .cpu_setup = __setup_cpu_power8, .cpu_restore = __restore_cpu_power8, - .flush_tlb = __flush_tlb_power8, .machine_check_early = __machine_check_early_realmode_p8, .platform = "power8", },
@@ -534,6 +530,8 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_user_features = COMMON_USER_POWER9, .cpu_user_features2 = COMMON_USER2_POWER9, .mmu_features = MMU_FTRS_POWER9, + .tlbiel_sets_hash = POWER9_TLB_SETS_HASH, + .tlbiel_sets_radix = POWER9_TLB_SETS_RADIX, .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 6,
@@ -542,7 +540,6 @@ static struct cpu_spec __initdata cpu_specs[] = { .oprofile_type = PPC_OPROFILE_INVALID, .cpu_setup = __setup_cpu_power9, .cpu_restore = __restore_cpu_power9, - .flush_tlb = __flush_tlb_power9, .machine_check_early = __machine_check_early_realmode_p9, .platform = "power9", },
@@ -554,6 +551,8 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_user_features = COMMON_USER_POWER9, .cpu_user_features2 = COMMON_USER2_POWER9, .mmu_features = MMU_FTRS_POWER9, + .tlbiel_sets_hash = POWER9_TLB_SETS_HASH, + .tlbiel_sets_radix = POWER9_TLB_SETS_RADIX, .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 6,
@@ -562,7 +561,6 @@ static struct cpu_spec __initdata cpu_specs[] = { .oprofile_type = PPC_OPROFILE_INVALID, .cpu_setup = __setup_cpu_power9, .cpu_restore = __restore_cpu_power9, - .flush_tlb = __flush_tlb_power9, .machine_check_early = __machine_check_early_realmode_p9, .platform = "power9", },
arch/powerpc/kernel/dt_cpu_ftrs.c +27 -21
126 lines not on this page · raw message
arch/powerpc/kernel/mce_power.c +10 -36
70 lines not on this page · raw message
arch/powerpc/kernel/prom.c +1 -0
@@ -237,6 +237,7 @@ static void __init init_mmu_slb_size(unsigned long node)if (slb_size_ptr) mmu_slb_size = be32_to_cpup(slb_size_ptr); } +#else #define init_mmu_slb_size (node) do { } while(0)#endif
arch/powerpc/kvm/book3s_hv.c +7 -6
@@ -3429,15 +3429,16 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm)/* * Work out how many sets the TLB has, for the use of * the TLB invalidation loop in book3s_hv_rmhandlers.S. +* +* Note that depending on implementation of future architecture that +* allows mixed radix/hash mode, this may not be the right thing to +* do for flushing guest TLB. The dt property is valid for the host +* tlbiel (and guest when radix mode matches host). */ if (kvm_is_radix (kvm)) - kvm->arch.tlb_sets =POWER9_TLB_SETS_RADIX ;/* 128 */ -else if (cpu_has_feature (CPU_FTR_ARCH_300 )) - kvm->arch.tlb_sets =POWER9_TLB_SETS_HASH ;/* 256 */ -else if (cpu_has_feature (CPU_FTR_ARCH_207S )) - kvm->arch.tlb_sets =POWER8_TLB_SETS ;/* 512 */ + kvm->arch.tlb_sets = cur_cpu_spec->tlbiel_sets_radix;else - kvm->arch.tlb_sets =POWER7_TLB_SETS ;/* 128 */ + kvm->arch.tlb_sets = cur_cpu_spec->tlbiel_sets_hash;/* * Track that we now have a HV mode VM active. This blocks secondary
arch/powerpc/kvm/book3s_hv_ras.c +2 -4
@@ -87,8 +87,7 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu) DSISR_MC_SLB_PARITY | DSISR_MC_DERAT_MULTI); }if (dsisr &DSISR_MC_TLB_MULTI ) { -if (cur_cpu_spec && cur_cpu_spec->flush_tlb) - cur_cpu_spec->flush_tlb (TLB_INVAL_SCOPE_LPID ); +machine_check_flush_tlb (TLB_INVAL_SCOPE_LPID ); dsisr &= ~DSISR_MC_TLB_MULTI ; }/* Any other errors we don't understand? */
@@ -105,8 +104,7 @@ static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)reload_slb (vcpu);break ;case SRR1_MC_IFETCH_TLBMULTI : -if (cur_cpu_spec && cur_cpu_spec->flush_tlb) - cur_cpu_spec->flush_tlb (TLB_INVAL_SCOPE_LPID ); +machine_check_flush_tlb (TLB_INVAL_SCOPE_LPID );break ;default : handled =0 ;
arch/powerpc/mm/init_64.c +5 -2
@@ -405,9 +405,12 @@ void __init mmu_early_init_devtree(void)if (!(mfmsr () &MSR_HV ))early_check_vec5 (); -if (early_radix_enabled ()) +if (early_radix_enabled ()) { + cur_cpu_spec->tlbiel_sets = cur_cpu_spec->tlbiel_sets_radix;radix__early_init_devtree (); -else + }else { + cur_cpu_spec->tlbiel_sets = cur_cpu_spec->tlbiel_sets_hash;hash__early_init_devtree (); + } }#endif /* CONFIG_PPC_STD_MMU_64 */
arch/powerpc/mm/tlb-radix.c +1 -1
@@ -56,7 +56,7 @@ static inline void _tlbiel_pid(unsigned long pid, unsigned long ric)/* For the remaining sets, just flush the TLB */ ric =RIC_FLUSH_TLB ; -for (set =1 ; set <POWER9_TLB_SETS_RADIX ; set++) +for (set =1 ; set < cur_cpu_spec->tlbiel_sets; set++)__tlbiel_pid (pid, set, ric); asmvolatile ("ptesync" : : :"memory" );
Signature · 1 line
2.11.0