From: Nicholas Piggin <[email protected]> Add CPU table entries for raw mode.
Signed-off-by: Nicholas Piggin <[email protected]> Signed-off-by: Ritesh Harjani (IBM) <[email protected]> Signed-off-by: Mahesh Salgaonkar <[email protected]> --- arch/powerpc/include/asm/cpu_setup.h | 2 ++ arch/powerpc/include/asm/cputable.h | 17 +++++++-- arch/powerpc/include/asm/mmu.h | 1 + arch/powerpc/include/asm/reg.h | 5 ++- arch/powerpc/include/asm/synch.h | 6 +++- arch/powerpc/include/uapi/asm/cputable.h | 1 + arch/powerpc/kernel/cpu_setup_power.c | 43 +++++++++++++++++++++++ arch/powerpc/kernel/cpu_specs_book3s_64.h | 22 ++++++++++++ arch/powerpc/kernel/dt_cpu_ftrs.c | 37 +++++++++++++++++++ arch/powerpc/kernel/setup-common.c | 1 + arch/powerpc/kvm/book3s_hv.c | 9 +++-- arch/powerpc/mm/book3s64/hash_native.c | 22 ++++++++---- arch/powerpc/mm/init_64.c | 4 ++- 13 files changed, 157 insertions(+), 13 deletions(-) diff --git a/arch/powerpc/include/asm/cpu_setup.h b/arch/powerpc/include/asm/cpu_setup.h index 30e2fe389502..26d2c0e2c99c 100644 --- a/arch/powerpc/include/asm/cpu_setup.h +++ b/arch/powerpc/include/asm/cpu_setup.h @@ -9,10 +9,12 @@ void __setup_cpu_power7(unsigned long offset, struct cpu_spec *spec); void __setup_cpu_power8(unsigned long offset, struct cpu_spec *spec); void __setup_cpu_power9(unsigned long offset, struct cpu_spec *spec); void __setup_cpu_power10(unsigned long offset, struct cpu_spec *spec); +void __setup_cpu_power12(unsigned long offset, struct cpu_spec *spec); void __restore_cpu_power7(void); void __restore_cpu_power8(void); void __restore_cpu_power9(void); void __restore_cpu_power10(void); +void __restore_cpu_power12(void); void __setup_cpu_e500v1(unsigned long offset, struct cpu_spec *spec); void __setup_cpu_e500v2(unsigned long offset, struct cpu_spec *spec); diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index ec16c12296da..a3be81c47df3 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h @@ -194,6 +194,7 @@ static inline void cpu_feature_keys_init(void) { } #define CPU_FTR_DAWR1 LONG_ASM_CONST(0x0008000000000000) #define CPU_FTR_DEXCR_NPHIE LONG_ASM_CONST(0x0010000000000000) #define CPU_FTR_P11_PVR LONG_ASM_CONST(0x0020000000000000) +#define CPU_FTR_ARCH_32 LONG_ASM_CONST(0x0040000000000000) #ifndef __ASSEMBLER__ @@ -457,6 +458,18 @@ static inline void cpu_feature_keys_init(void) { } #define CPU_FTRS_POWER11 (CPU_FTRS_POWER10 | CPU_FTR_P11_PVR) +#define CPU_FTRS_POWER12 (CPU_FTR_LWSYNC | \ + CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | CPU_FTR_ARCH_206 |\ + CPU_FTR_MMCRA | CPU_FTR_SMT | \ + CPU_FTR_COHERENT_ICACHE | \ + CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \ + CPU_FTR_DSCR | \ + CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ + CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \ + CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_ARCH_207S | \ + CPU_FTR_ARCH_300 | CPU_FTR_ARCH_31 | CPU_FTR_ARCH_32 | \ + CPU_FTR_DAWR | CPU_FTR_DAWR1) + #define CPU_FTRS_CELL (CPU_FTR_LWSYNC | \ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ @@ -476,7 +489,7 @@ static inline void cpu_feature_keys_init(void) { } (CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | CPU_FTRS_POWER8 | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_VSX_COMP | CPU_FTRS_POWER9 | \ CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | \ - CPU_FTRS_POWER9_DD2_3 | CPU_FTRS_POWER10 | CPU_FTRS_POWER11) + CPU_FTRS_POWER9_DD2_3 | CPU_FTRS_POWER10 | CPU_FTRS_POWER11 | CPU_FTRS_POWER12) #else #define CPU_FTRS_POSSIBLE \ (CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | \ @@ -484,7 +497,7 @@ static inline void cpu_feature_keys_init(void) { } CPU_FTRS_POWER8 | CPU_FTRS_CELL | CPU_FTRS_PA6T | \ CPU_FTR_VSX_COMP | CPU_FTR_ALTIVEC_COMP | CPU_FTRS_POWER9 | \ CPU_FTRS_POWER9_DD2_1 | CPU_FTRS_POWER9_DD2_2 | \ - CPU_FTRS_POWER9_DD2_3 | CPU_FTRS_POWER10 | CPU_FTRS_POWER11) + CPU_FTRS_POWER9_DD2_3 | CPU_FTRS_POWER10 | CPU_FTRS_POWER11 | CPU_FTRS_POWER12) #endif /* CONFIG_CPU_LITTLE_ENDIAN */ #endif #else diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h index 5f9c5d436e17..4fd7f81a2930 100644 --- a/arch/powerpc/include/asm/mmu.h +++ b/arch/powerpc/include/asm/mmu.h @@ -133,6 +133,7 @@ #define MMU_FTRS_POWER9 MMU_FTRS_POWER6 #define MMU_FTRS_POWER10 MMU_FTRS_POWER6 #define MMU_FTRS_POWER11 MMU_FTRS_POWER6 +#define MMU_FTRS_POWER12 MMU_FTRS_POWER6 #define MMU_FTRS_CELL MMU_FTRS_DEFAULT_HPTE_ARCH_V2 | \ MMU_FTR_CI_LARGE_PAGE #define MMU_FTRS_PA6T MMU_FTRS_DEFAULT_HPTE_ARCH_V2 | \ diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 3449dd2b577d..4460b666c603 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -492,11 +492,12 @@ * determine both the compatibility level which we want to emulate and the * compatibility level which the host is capable of emulating. */ +#define PCR_ARCH_31 0x20 /* Architecture 3.1 */ #define PCR_ARCH_300 0x10 /* Architecture 3.00 */ #define PCR_ARCH_207 0x8 /* Architecture 2.07 */ #define PCR_ARCH_206 0x4 /* Architecture 2.06 */ #define PCR_ARCH_205 0x2 /* Architecture 2.05 */ -#define PCR_LOW_BITS (PCR_ARCH_207 | PCR_ARCH_206 | PCR_ARCH_205 | PCR_ARCH_300) +#define PCR_LOW_BITS (PCR_ARCH_207 | PCR_ARCH_206 | PCR_ARCH_205 | PCR_ARCH_300 | PCR_ARCH_31) #define PCR_MASK ~(PCR_HIGH_BITS | PCR_LOW_BITS) /* PCR Reserved Bits */ #define SPRN_HEIR 0x153 /* Hypervisor Emulated Instruction Register */ #define SPRN_TLBINDEXR 0x154 /* P7 TLB control register */ @@ -1344,6 +1345,7 @@ #define PVR_POWER9 0x004E #define PVR_POWER10 0x0080 #define PVR_POWER11 0x0082 +#define PVR_POWER12 0x0083 #define PVR_BE 0x0070 #define PVR_PA6T 0x0090 @@ -1356,6 +1358,7 @@ #define PVR_ARCH_300 0x0f000005 #define PVR_ARCH_31 0x0f000006 #define PVR_ARCH_31_P11 0x0f000007 +#define PVR_ARCH_32 0x0f000008 /* Macros for setting and retrieving special purpose registers */ #ifndef __ASSEMBLER__ diff --git a/arch/powerpc/include/asm/synch.h b/arch/powerpc/include/asm/synch.h index 0d3ccb34adfb..d0e9765dee28 100644 --- a/arch/powerpc/include/asm/synch.h +++ b/arch/powerpc/include/asm/synch.h @@ -37,8 +37,12 @@ static inline void ppc_after_tlbiel_barrier(void) * accelerators mapped will use tlbie (which does invalidate the copy) * to invalidate translations. It's not possible to limit POWER10 this * way due to local copy-paste. + * + * POWER12 does not need it. */ - asm volatile(ASM_FTR_IFSET(PPC_CP_ABORT, "", %0) : : "i" (CPU_FTR_ARCH_31) : "memory"); + asm volatile(ASM_FTR_IF(PPC_CP_ABORT, "", %0, %1) : + : "i" (CPU_FTR_ARCH_31|CPU_FTR_ARCH_32), "i" (CPU_FTR_ARCH_31) + : "memory"); } #endif /* __ASSEMBLER__ */ diff --git a/arch/powerpc/include/uapi/asm/cputable.h b/arch/powerpc/include/uapi/asm/cputable.h index 731b97dc2d15..bc9bd225f587 100644 --- a/arch/powerpc/include/uapi/asm/cputable.h +++ b/arch/powerpc/include/uapi/asm/cputable.h @@ -52,6 +52,7 @@ #define PPC_FEATURE2_HTM_NO_SUSPEND 0x00080000 /* TM w/out suspended state */ #define PPC_FEATURE2_ARCH_3_1 0x00040000 /* ISA 3.1 */ #define PPC_FEATURE2_MMA 0x00020000 /* Matrix Multiply Assist */ +#define PPC_FEATURE2_ARCH_3_2 0x00010000 /* ISA 3.2 */ /* * IMPORTANT! diff --git a/arch/powerpc/kernel/cpu_setup_power.c b/arch/powerpc/kernel/cpu_setup_power.c index 98bd4e6c1770..5de704ac031d 100644 --- a/arch/powerpc/kernel/cpu_setup_power.c +++ b/arch/powerpc/kernel/cpu_setup_power.c @@ -286,3 +286,46 @@ void __restore_cpu_power10(void) init_HFSCR(); init_PMU_HV(); } + +void __setup_cpu_power12(unsigned long offset, struct cpu_spec *t) +{ + init_FSCR_power10(); + init_PMU(); + init_PMU_ISA31(); + + if (!init_hvmode_206(t)) + return; + + mtspr(SPRN_PSSCR, 0); + mtspr(SPRN_LPID, 0); + mtspr(SPRN_PID, 0); + mtspr(SPRN_AMOR, ~0); + mtspr(SPRN_PCR, PCR_MASK); + init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\ + LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0); + init_HFSCR(); + init_PMU_HV(); +} + +void __restore_cpu_power12(void) +{ + u64 msr; + + init_FSCR_power10(); + init_PMU(); + init_PMU_ISA31(); + + msr = mfmsr(); + if (!(msr & MSR_HV)) + return; + + mtspr(SPRN_PSSCR, 0); + mtspr(SPRN_LPID, 0); + mtspr(SPRN_PID, 0); + mtspr(SPRN_AMOR, ~0); + mtspr(SPRN_PCR, PCR_MASK); + init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\ + LPCR_HVICE | LPCR_HEIC) & ~(LPCR_UPRT | LPCR_HR), 0); + init_HFSCR(); + init_PMU_HV(); +} diff --git a/arch/powerpc/kernel/cpu_specs_book3s_64.h b/arch/powerpc/kernel/cpu_specs_book3s_64.h index 98d4274a1b6b..7619dd157646 100644 --- a/arch/powerpc/kernel/cpu_specs_book3s_64.h +++ b/arch/powerpc/kernel/cpu_specs_book3s_64.h @@ -63,6 +63,11 @@ #define COMMON_USER_POWER11 COMMON_USER_POWER10 #define COMMON_USER2_POWER11 COMMON_USER2_POWER10 +#define COMMON_USER_POWER12 COMMON_USER_POWER10 +#define COMMON_USER2_POWER12 (COMMON_USER2_POWER10 | \ + PPC_FEATURE2_ARCH_3_2) + + static struct cpu_spec cpu_specs[] __initdata = { { /* PPC970 */ .pvr_mask = 0xffff0000, @@ -485,6 +490,23 @@ static struct cpu_spec cpu_specs[] __initdata = { .machine_check_early = __machine_check_early_realmode_p10, .platform = "power11", }, + { /* Power12 */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x00830000, + .cpu_name = "Power12 (raw)", + .cpu_features = CPU_FTRS_POWER12, + .cpu_user_features = COMMON_USER_POWER12, + .cpu_user_features2 = COMMON_USER2_POWER12, + .mmu_features = MMU_FTRS_POWER12, + .icache_bsize = 128, + .dcache_bsize = 128, + .num_pmcs = 6, + .pmc_type = PPC_PMC_IBM, + .cpu_setup = __setup_cpu_power12, + .cpu_restore = __restore_cpu_power12, + .machine_check_early = __machine_check_early_realmode_p10, + .platform = "power12", + }, { /* Cell Broadband Engine */ .pvr_mask = 0xffff0000, .pvr_value = 0x00700000, diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c index e5853daa6a48..b369e8cda12e 100644 --- a/arch/powerpc/kernel/dt_cpu_ftrs.c +++ b/arch/powerpc/kernel/dt_cpu_ftrs.c @@ -26,6 +26,7 @@ /* Device-tree visible constants follow */ #define ISA_V3_0B 3000 #define ISA_V3_1 3100 +#define ISA_V3_2 3200 #define USABLE_PR (1U << 0) #define USABLE_OS (1U << 1) @@ -466,6 +467,35 @@ static int __init feat_enable_mce_power11(struct dt_cpu_feature *f) return 1; } +static void init_pmu_power12(void) +{ + init_pmu_power10(); +} + +static int __init feat_enable_pmu_power12(struct dt_cpu_feature *f) +{ + hfscr_pmu_enable(); + + init_pmu_power12(); + init_pmu_registers = init_pmu_power12; + + cur_cpu_spec->cpu_features |= CPU_FTR_MMCRA; + cur_cpu_spec->cpu_user_features |= PPC_FEATURE_PSERIES_PERFMON_COMPAT; + + cur_cpu_spec->num_pmcs = 6; + cur_cpu_spec->pmc_type = PPC_PMC_IBM; + + return 1; +} + +static int __init feat_enable_mce_power12(struct dt_cpu_feature *f) +{ + cur_cpu_spec->platform = "power12"; + cur_cpu_spec->machine_check_early = __machine_check_early_realmode_p10; + + return 1; +} + static int __init feat_enable_tm(struct dt_cpu_feature *f) { #ifdef CONFIG_PPC_TRANSACTIONAL_MEM @@ -657,9 +687,11 @@ static struct dt_cpu_feature_match __initdata {"machine-check-power9", feat_enable_mce_power9, 0}, {"machine-check-power10", feat_enable_mce_power10, 0}, {"machine-check-power11", feat_enable_mce_power11, 0}, + {"machine-check-power12", feat_enable_mce_power12, 0}, {"performance-monitor-power9", feat_enable_pmu_power9, 0}, {"performance-monitor-power10", feat_enable_pmu_power10, 0}, {"performance-monitor-power11", feat_enable_pmu_power10, 0}, + {"performance-monitor-power12", feat_enable_pmu_power12, 0}, {"event-based-branch-v3", feat_enable, 0}, {"random-number-generator", feat_enable, 0}, {"system-call-vectored", feat_disable, 0}, @@ -714,6 +746,11 @@ static void __init cpufeatures_setup_start(u32 isa) if (PVR_VER(mfspr(SPRN_PVR)) >= PVR_POWER11) cur_cpu_spec->cpu_features |= CPU_FTR_P11_PVR; } + + if (isa >= ISA_V3_2) { + cur_cpu_spec->cpu_features |= CPU_FTR_ARCH_32; + cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_ARCH_3_2; + } } static bool __init cpufeatures_process_feature(struct dt_cpu_feature *f) diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 67c545f61f0d..4afaba19b586 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -304,6 +304,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) break; case 0x004e: /* POWER9 bits 12-15 give chip type */ case 0x0080: /* POWER10 bit 12 gives SMT8/4 */ + case 0x0083: /* POWER12 bit 12 gives SMT8/4 */ maj = (pvr >> 8) & 0x0F; min = pvr & 0xFF; break; diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 61dbeea317f3..6ad4e3d0b5a0 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -388,7 +388,7 @@ static void kvmppc_set_pvr_hv(struct kvm_vcpu *vcpu, u32 pvr) } /* Dummy value used in computing PCR value below */ -#define PCR_ARCH_31 (PCR_ARCH_300 << 1) +#define PCR_ARCH_32 (PCR_ARCH_31 << 1) static inline unsigned long map_pcr_to_cap(unsigned long pcr) { @@ -417,7 +417,9 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat) struct kvmppc_vcore *vc = vcpu->arch.vcore; /* We can (emulate) our own architecture version and anything older */ - if (cpu_has_feature(CPU_FTR_P11_PVR) || cpu_has_feature(CPU_FTR_ARCH_31)) + if (cpu_has_feature(CPU_FTR_ARCH_32)) + host_pcr_bit = PCR_ARCH_32; + else if (cpu_has_feature(CPU_FTR_P11_PVR) || cpu_has_feature(CPU_FTR_ARCH_31)) host_pcr_bit = PCR_ARCH_31; else if (cpu_has_feature(CPU_FTR_ARCH_300)) host_pcr_bit = PCR_ARCH_300; @@ -449,6 +451,9 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat) case PVR_ARCH_31_P11: guest_pcr_bit = PCR_ARCH_31; break; + case PVR_ARCH_32: + guest_pcr_bit = PCR_ARCH_32; + break; default: return -EINVAL; } diff --git a/arch/powerpc/mm/book3s64/hash_native.c b/arch/powerpc/mm/book3s64/hash_native.c index e9e2dd70c060..ab2a80e59011 100644 --- a/arch/powerpc/mm/book3s64/hash_native.c +++ b/arch/powerpc/mm/book3s64/hash_native.c @@ -184,9 +184,14 @@ static inline void __tlbiel(unsigned long vpn, int psize, int apsize, int ssize) va |= ssize << 8; sllp = get_sllp_encoding(apsize); va |= sllp << 5; - asm volatile(ASM_FTR_IFSET("tlbiel %0", PPC_TLBIEL_v205(%0, 0), %1) - : : "r" (va), "i" (CPU_FTR_ARCH_206) - : "memory"); + + if (cpu_has_feature(CPU_FTR_ARCH_32)) { + asm volatile(PPC_TLBIEL(%0, %1, 0, 0, 0) : : "r"(va), "r"(0) : "memory"); + } else { + asm volatile(ASM_FTR_IFSET("tlbiel %0", PPC_TLBIEL_v205(%0, 0), %1) + : : "r" (va), "i" (CPU_FTR_ARCH_206) + : "memory"); + } break; default: /* We need 14 to 14 + i bits of va */ @@ -203,9 +208,14 @@ static inline void __tlbiel(unsigned long vpn, int psize, int apsize, int ssize) */ va |= (vpn & 0xfe); va |= 1; /* L */ - asm volatile(ASM_FTR_IFSET("tlbiel %0", PPC_TLBIEL_v205(%0, 1), %1) - : : "r" (va), "i" (CPU_FTR_ARCH_206) - : "memory"); + + if (cpu_has_feature(CPU_FTR_ARCH_32)) { + asm volatile(PPC_TLBIEL(%0, %1, 0, 0, 0) : : "r"(va), "r"(0) : "memory"); + } else { + asm volatile(ASM_FTR_IFSET("tlbiel %0", PPC_TLBIEL_v205(%0, 1), %1) + : : "r" (va), "i" (CPU_FTR_ARCH_206) + : "memory"); + } break; } trace_tlbie(0, 1, va, 0, 0, 0, 0); diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 64f0df5bb5cd..0e777d7dc332 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -628,7 +628,9 @@ void __init mmu_early_init_devtree(void) of_scan_flat_dt(dt_scan_mmu_pid_width, NULL); if (hvmode && !mmu_lpid_bits) { - if (early_cpu_has_feature(CPU_FTR_ARCH_207S)) + if (early_cpu_has_feature(CPU_FTR_ARCH_32)) + mmu_lpid_bits = 16; /* POWER12 */ + else if (early_cpu_has_feature(CPU_FTR_ARCH_207S)) mmu_lpid_bits = 12; /* POWER8-10 */ else mmu_lpid_bits = 10; /* POWER7 */ -- 2.55.0
