* [PATCH 1/4] powerpc/pseries: Limit PVR list to 16 entries for CAS negotiation
2026-07-29 14:54 [PATCH 0/4] Base support for Power12 Mahesh Salgaonkar
@ 2026-07-29 14:54 ` Mahesh Salgaonkar
2026-07-29 14:54 ` [PATCH 2/4] powerpc: Add Power12 raw mode Mahesh Salgaonkar
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Mahesh Salgaonkar @ 2026-07-29 14:54 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Madhavan Srinivasan
Current Power system firmware caps the PVR list array size at 16 entries
during CAS (Client Architecture Support) negotiation. Passing more than
capped size to older firmware could cause an undefined behaviour and
breaks compatibility.
Future Power system firmware releases will lift this restriction and
support greater than 16 array entries.
Ensure that when running on Power11 or below hardware, the number
of PVR entries passed during CAS negotiation does not exceed the
firmware-imposed limit of 16.
In prom_send_capabilities(), compute start_index to skip the oldest
leading pvrs[] entries when running on Power11 or below hardware, so
that the pointer passed to ibm,client-architecture-support points to
ibm_architecture_vec.pvrs[start_index], presenting exactly 16 entries to
firmware.
Signed-off-by: Mahesh Salgaonkar <mahesh@linux.ibm.com>
---
arch/powerpc/kernel/prom_init.c | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 53503937de0e..f4f92cdaaa6b 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -979,6 +979,10 @@ static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
.mask = cpu_to_be32(0xfffe0000), /* POWER5/POWER5+ */
.val = cpu_to_be32(0x003a0000),
},
+ {
+ .mask = cpu_to_be32(0xffffffff), /* all 2.04-compliant and earlier */
+ .val = cpu_to_be32(0x0f000001),
+ },
{
.mask = cpu_to_be32(0xffff0000), /* POWER6 */
.val = cpu_to_be32(0x003e0000),
@@ -1032,13 +1036,9 @@ static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
.val = cpu_to_be32(0x0f000003),
},
{
- .mask = cpu_to_be32(0xffffffff), /* all 2.05-compliant */
+ .mask = cpu_to_be32(0xfffffffd), /* all 2.05-compliant */
.val = cpu_to_be32(0x0f000002),
},
- {
- .mask = cpu_to_be32(0xfffffffe), /* all 2.04-compliant and earlier */
- .val = cpu_to_be32(0x0f000001),
- },
},
.num_vectors = NUM_VECTORS(6),
@@ -1347,7 +1347,6 @@ static void __init prom_check_platform_support(void)
};
int prop_len = prom_getproplen(prom.chosen,
"ibm,arch-vec-5-platform-support");
-
/*
* First copy the architecture vec template
*
@@ -1403,6 +1402,11 @@ static void __init prom_send_capabilities(void)
ihandle root;
prom_arg_t ret;
u32 cores;
+ int start_index = 0;
+
+ if ((ARRAY_SIZE(ibm_architecture_vec_template.pvrs) > 16) &&
+ (PVR_VER(mfspr(SPRN_PVR)) <= PVR_POWER11))
+ start_index = ARRAY_SIZE(ibm_architecture_vec_template.pvrs) - 16;
/* Check ibm,arch-vec-5-platform-support and fixup vec5 if required */
prom_check_platform_support();
@@ -1427,7 +1431,7 @@ static void __init prom_send_capabilities(void)
if (call_prom_ret("call-method", 3, 2, &ret,
ADDR("ibm,client-architecture-support"),
root,
- ADDR(&ibm_architecture_vec)) == 0) {
+ ADDR(&ibm_architecture_vec.pvrs[start_index])) == 0) {
/* the call exists... */
if (ret)
prom_printf("\nWARNING: ibm,client-architecture"
--
2.55.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 2/4] powerpc: Add Power12 raw mode
2026-07-29 14:54 [PATCH 0/4] Base support for Power12 Mahesh Salgaonkar
2026-07-29 14:54 ` [PATCH 1/4] powerpc/pseries: Limit PVR list to 16 entries for CAS negotiation Mahesh Salgaonkar
@ 2026-07-29 14:54 ` Mahesh Salgaonkar
2026-07-29 14:54 ` [PATCH 3/4] powerpc: Add Power12 architected mode Mahesh Salgaonkar
2026-07-29 14:54 ` [PATCH 4/4] powerpc/perf: Add power12 Base Performance Monitoring support Mahesh Salgaonkar
3 siblings, 0 replies; 5+ messages in thread
From: Mahesh Salgaonkar @ 2026-07-29 14:54 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Nicholas Piggin, Madhavan Srinivasan, Ritesh Harjani (IBM)
From: Nicholas Piggin <npiggin@gmail.com>
Add CPU table entries for raw mode.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
Signed-off-by: Mahesh Salgaonkar <mahesh@linux.ibm.com>
---
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
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 3/4] powerpc: Add Power12 architected mode
2026-07-29 14:54 [PATCH 0/4] Base support for Power12 Mahesh Salgaonkar
2026-07-29 14:54 ` [PATCH 1/4] powerpc/pseries: Limit PVR list to 16 entries for CAS negotiation Mahesh Salgaonkar
2026-07-29 14:54 ` [PATCH 2/4] powerpc: Add Power12 raw mode Mahesh Salgaonkar
@ 2026-07-29 14:54 ` Mahesh Salgaonkar
2026-07-29 14:54 ` [PATCH 4/4] powerpc/perf: Add power12 Base Performance Monitoring support Mahesh Salgaonkar
3 siblings, 0 replies; 5+ messages in thread
From: Mahesh Salgaonkar @ 2026-07-29 14:54 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Ritesh Harjani (IBM), Madhavan Srinivasan, Nicholas Piggin
From: "Ritesh Harjani (IBM)" <ritesh.list@gmail.com>
PVR value of 0x0f000008 means we are arch v3.2 compliant (i.e.
Power12). This is used by phyp and kvm when booting as a pseries guest
to detect the presence of new Power12 features and to enable the
appropriate hwcap and facility bits.
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
Signed-off-by: Mahesh Salgaonkar <mahesh@linux.ibm.com>
---
arch/powerpc/include/asm/prom.h | 1 +
arch/powerpc/include/uapi/asm/cputable.h | 1 +
arch/powerpc/kernel/cpu_specs_book3s_64.h | 14 ++++++++++++++
arch/powerpc/kernel/prom_init.c | 12 ++++++++++--
4 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
index f4991d10d89e..cd025c7225ee 100644
--- a/arch/powerpc/include/asm/prom.h
+++ b/arch/powerpc/include/asm/prom.h
@@ -118,6 +118,7 @@ extern unsigned int boot_cpu_node_count;
#define OV1_PPC_3_00 0x80 /* set if we support PowerPC 3.00 */
#define OV1_PPC_3_1 0x40 /* set if we support PowerPC 3.1 */
+#define OV1_PPC_3_2 0x20 /* set if we support PowerPC 3.2 */
/* Option vector 2: Open Firmware options supported */
#define OV2_REAL_MODE 0x20 /* set if we want OF in real mode */
diff --git a/arch/powerpc/include/uapi/asm/cputable.h b/arch/powerpc/include/uapi/asm/cputable.h
index bc9bd225f587..68215b7ce67e 100644
--- a/arch/powerpc/include/uapi/asm/cputable.h
+++ b/arch/powerpc/include/uapi/asm/cputable.h
@@ -53,6 +53,7 @@
#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 */
+#define PPC_FEATURE2_DMF 0x00008000 /* Dense Math Facility */
/*
* IMPORTANT!
diff --git a/arch/powerpc/kernel/cpu_specs_book3s_64.h b/arch/powerpc/kernel/cpu_specs_book3s_64.h
index 7619dd157646..26fa40aa34db 100644
--- a/arch/powerpc/kernel/cpu_specs_book3s_64.h
+++ b/arch/powerpc/kernel/cpu_specs_book3s_64.h
@@ -303,6 +303,20 @@ static struct cpu_spec cpu_specs[] __initdata = {
.cpu_restore = __restore_cpu_power10,
.platform = "power11",
},
+ { /* 3.2-compliant processor, i.e. Power12 "architected" mode */
+ .pvr_mask = 0xffffffff,
+ .pvr_value = 0x0f000008,
+ .cpu_name = "Power12 (architected)",
+ .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,
+ .cpu_setup = __setup_cpu_power12,
+ .cpu_restore = __restore_cpu_power12,
+ .platform = "power12",
+ },
{ /* Power7 */
.pvr_mask = 0xffff0000,
.pvr_value = 0x003f0000,
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index f4f92cdaaa6b..0d54718b0929 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -947,7 +947,7 @@ struct option_vector7 {
} __packed;
struct ibm_arch_vec {
- struct { __be32 mask, val; } pvrs[16];
+ struct { __be32 mask, val; } pvrs[18];
u8 num_vectors;
@@ -1015,6 +1015,14 @@ static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
.mask = cpu_to_be32(0xffff0000), /* POWER11 */
.val = cpu_to_be32(0x00820000),
},
+ {
+ .mask = cpu_to_be32(0xffff0000), /* POWER12 */
+ .val = cpu_to_be32(0x00830000),
+ },
+ {
+ .mask = cpu_to_be32(0xffffffff), /* all 3.2-compliant */
+ .val = cpu_to_be32(0x0f000008),
+ },
{
.mask = cpu_to_be32(0xffffffff), /* P11 compliant */
.val = cpu_to_be32(0x0f000007),
@@ -1048,7 +1056,7 @@ static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
.byte1 = 0,
.arch_versions = OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
- .arch_versions3 = OV1_PPC_3_00 | OV1_PPC_3_1,
+ .arch_versions3 = OV1_PPC_3_00 | OV1_PPC_3_1 | OV1_PPC_3_2,
},
.vec2_len = VECTOR_LENGTH(sizeof(struct option_vector2)),
--
2.55.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 4/4] powerpc/perf: Add power12 Base Performance Monitoring support
2026-07-29 14:54 [PATCH 0/4] Base support for Power12 Mahesh Salgaonkar
` (2 preceding siblings ...)
2026-07-29 14:54 ` [PATCH 3/4] powerpc: Add Power12 architected mode Mahesh Salgaonkar
@ 2026-07-29 14:54 ` Mahesh Salgaonkar
3 siblings, 0 replies; 5+ messages in thread
From: Mahesh Salgaonkar @ 2026-07-29 14:54 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Athira Rajeev, Madhavan Srinivasan
From: Athira Rajeev <atrajeev@linux.ibm.com>
Base enablement patch to register performance monitoring hardware
support for power12. Patch introduce the raw event encoding format,
defines the supported list of events, config fields for the event
attributes and their corresponding bit values which are exported via
sysfs.
Signed-off-by: Athira Rajeev <atrajeev@linux.ibm.com>
Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
---
arch/powerpc/perf/Makefile | 2 +-
arch/powerpc/perf/core-book3s.c | 2 +
arch/powerpc/perf/internal.h | 1 +
arch/powerpc/perf/power12-events-list.h | 78 ++++
arch/powerpc/perf/power12-pmu.c | 466 ++++++++++++++++++++++++
5 files changed, 548 insertions(+), 1 deletion(-)
create mode 100644 arch/powerpc/perf/power12-events-list.h
create mode 100644 arch/powerpc/perf/power12-pmu.c
diff --git a/arch/powerpc/perf/Makefile b/arch/powerpc/perf/Makefile
index 78dd7e25219e..bcc804c41338 100644
--- a/arch/powerpc/perf/Makefile
+++ b/arch/powerpc/perf/Makefile
@@ -7,7 +7,7 @@ obj-$(CONFIG_PPC_PERF_CTRS) += core-book3s.o
obj64-$(CONFIG_PPC_PERF_CTRS) += ppc970-pmu.o power5-pmu.o \
power5+-pmu.o power6-pmu.o power7-pmu.o \
isa207-common.o power8-pmu.o power9-pmu.o \
- generic-compat-pmu.o power10-pmu.o bhrb.o
+ generic-compat-pmu.o power10-pmu.o bhrb.o power12-pmu.o
obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450-pmu.o
obj-$(CONFIG_PPC_POWERNV) += imc-pmu.o
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 720b1a500922..10ded865583c 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -2613,6 +2613,8 @@ static int __init init_ppc64_pmu(void)
return 0;
else if (!init_power11_pmu())
return 0;
+ else if (!init_power12_pmu())
+ return 0;
else if (!init_ppc970_pmu())
return 0;
else
diff --git a/arch/powerpc/perf/internal.h b/arch/powerpc/perf/internal.h
index a70ac471a5a5..84d6ca209c49 100644
--- a/arch/powerpc/perf/internal.h
+++ b/arch/powerpc/perf/internal.h
@@ -11,4 +11,5 @@ int __init init_power8_pmu(void);
int __init init_power9_pmu(void);
int __init init_power10_pmu(void);
int __init init_power11_pmu(void);
+int __init init_power12_pmu(void);
int __init init_generic_compat_pmu(void);
diff --git a/arch/powerpc/perf/power12-events-list.h b/arch/powerpc/perf/power12-events-list.h
new file mode 100644
index 000000000000..6c043e42cb00
--- /dev/null
+++ b/arch/powerpc/perf/power12-events-list.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Performance counter support for POWER12 processors.
+ *
+ * Copyright 2026 Athira Rajeev, IBM Corporation.
+ */
+
+/*
+ * Power12 event codes.
+ */
+EVENT(PM_CYC, 0x600f4);
+EVENT(PM_DISP_STALL_CYC, 0x100f8);
+EVENT(PM_EXEC_STALL, 0x30008);
+EVENT(PM_INST_CMPL, 0x500fa);
+EVENT(PM_BR_CMPL, 0x4d05e);
+EVENT(PM_BR_MPRED_CMPL, 0x400f6);
+EVENT(PM_BR_FIN, 0x10068);
+EVENT(PM_MPRED_BR_FIN, 0x27098);
+EVENT(PM_LD_DEMAND_MISS_L1_FIN, 0x400f0);
+
+/* All L1 D cache load references counted at finish, gated by reject */
+EVENT(PM_LD_REF_L1, 0x100fc);
+/* Load Missed L1 */
+EVENT(PM_LD_MISS_L1, 0x3e054);
+/* Store Missed L1 */
+EVENT(PM_ST_MISS_L1, 0x300f0);
+/* L1 cache data prefetches */
+EVENT(PM_LD_PREFETCH_CACHE_LINE_MISS, 0x1002c);
+/* Demand iCache Miss */
+EVENT(PM_L1_ICACHE_MISS, 0x200fc);
+/* Instruction fetches from L1 */
+EVENT(PM_INST_FROM_L1, 0x04080);
+/* Instruction Demand sectors wriittent into IL1 */
+EVENT(PM_INST_FROM_L1MISS, 0x03F00000001C040);
+/* Instruction prefetch written into IL1 */
+EVENT(PM_IC_PREF_REQ, 0x040a0);
+/* The data cache was reloaded from local core's L3 due to a demand load */
+EVENT(PM_DATA_FROM_L3, 0x10340000003C040);
+/* Demand LD - L3 Miss (not L2 hit and not L3 hit) */
+EVENT(PM_DATA_FROM_L3MISS, 0x300fe);
+/* All successful D-side store dispatches for this thread */
+EVENT(PM_L2_ST, 0x010000046080);
+/* All successful D-side store dispatches for this thread that were L2 Miss */
+EVENT(PM_L2_ST_MISS, 0x26880);
+/* Total HW L3 prefetches(Load+store) */
+EVENT(PM_L3_PF_MISS_L3, 0x100000016080);
+/* Data PTEG reload */
+EVENT(PM_DTLB_MISS, 0x300fc);
+/* ITLB Reloaded */
+EVENT(PM_ITLB_MISS, 0x400fc);
+
+EVENT(PM_CYC_ALT, 0x0001e);
+EVENT(PM_INST_CMPL_ALT, 0x00002);
+
+/*
+ * Memory Access Events
+ *
+ * Primary PMU event used here is PM_MRK_INST_CMPL (0x401e0)
+ * To enable capturing of memory profiling, these MMCRA bits
+ * needs to be programmed and corresponding raw event format
+ * encoding.
+ *
+ * MMCRA bits encoding needed are
+ * SM (Sampling Mode)
+ * EM (Eligibility for Random Sampling)
+ * TECE (Threshold Event Counter Event)
+ * TS (Threshold Start Event)
+ * TE (Threshold End Event)
+ *
+ * Corresponding Raw Encoding bits:
+ * sample [EM,SM]
+ * thresh_sel (TECE)
+ * thresh start (TS)
+ * thresh end (TE)
+ */
+
+EVENT(MEM_LOADS, 0x35340401e0);
+EVENT(MEM_STORES, 0x353c0401e0);
diff --git a/arch/powerpc/perf/power12-pmu.c b/arch/powerpc/perf/power12-pmu.c
new file mode 100644
index 000000000000..89cc704b8324
--- /dev/null
+++ b/arch/powerpc/perf/power12-pmu.c
@@ -0,0 +1,466 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Performance counter support for Power12 processors.
+ *
+ * Copyright 2026 Athira Rajeev, IBM Corporation.
+ */
+
+#define pr_fmt(fmt) "power12-pmu: " fmt
+
+#include "isa207-common.h"
+
+/*
+ * Raw event encoding for Power12:
+ *
+ * 60 56 52 48 44 40 36 32
+ * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
+ * | | [ ] [ src_match ] [ src_mask ] | [ ] [ l2l3_sel ] [ thresh_ctl ]
+ * | | | | | |
+ * | | *- IFM (Linux) | | thresh start/stop -*
+ * | *- BHRB (Linux) | src_sel
+ * *- EBB (Linux) *invert_bit
+ *
+ * 28 24 20 16 12 8 4 0
+ * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
+ * [ ] [ sample ] [ ] [ ] [ pmc ] [unit ] [ ] | m [ pmcxsel ]
+ * | | | | | | |
+ * | | | | | | *- mark
+ * | | | *- L1/L2/L3 cache_sel | |*-radix_scope_qual
+ * | | sdar_mode |
+ * | *- sampling mode for marked events *- combine
+ * |
+ * *- thresh_sel
+ *
+ * Below uses IBM bit numbering.
+ *
+ * MMCR1[x:y] = unit (PMCxUNIT)
+ * MMCR1[24] = pmc1combine[0]
+ * MMCR1[25] = pmc1combine[1]
+ * MMCR1[26] = pmc2combine[0]
+ * MMCR1[27] = pmc2combine[1]
+ * MMCR1[28] = pmc3combine[0]
+ * MMCR1[29] = pmc3combine[1]
+ * MMCR1[30] = pmc4combine[0]
+ * MMCR1[31] = pmc4combine[1]
+ *
+ * if pmc == 3 and unit == 0 and pmcxsel[0:6] == 0b0101011
+ * MMCR1[20:27] = thresh_ctl
+ * else if pmc == 4 and unit == 0xf and pmcxsel[0:6] == 0b0101001
+ * MMCR1[20:27] = thresh_ctl
+ * else
+ * MMCRA[48:55] = thresh_ctl (THRESH START/END)
+ *
+ * if thresh_sel:
+ * MMCRA[45:47] = thresh_sel
+ *
+ * if l2l3_sel:
+ * MMCR2[56:60] = l2l3_sel[0:4]
+ *
+ * MMCR1[16] = cache_sel[0]
+ * MMCR1[17] = cache_sel[1]
+ * MMCR1[18] = radix_scope_qual
+ *
+ * if mark:
+ * MMCRA[63] = 1 (SAMPLE_ENABLE)
+ * MMCRA[57:59] = sample[0:2] (RAND_SAMP_ELIG)
+ * MMCRA[61:62] = sample[3:4] (RAND_SAMP_MODE)
+ *
+ * if EBB and BHRB:
+ * MMCRA[32:33] = IFM
+ *
+ * MMCRA[SDAR_MODE] = sdar_mode[0:1]
+ */
+
+/*
+ * Some power12 event codes.
+ */
+#define EVENT(_name, _code) enum{_name = _code}
+
+#include "power12-events-list.h"
+
+#undef EVENT
+
+/* MMCRA IFM bits - POWER12 */
+#define POWER12_MMCRA_IFM1 0x0000000040000000UL
+#define POWER12_MMCRA_IFM2 0x0000000080000000UL
+#define POWER12_MMCRA_IFM3 0x00000000C0000000UL
+#define POWER12_MMCRA_BHRB_MASK 0x00000000C0000000UL
+
+extern u64 PERF_REG_EXTENDED_MASK;
+
+/* Table of alternatives, sorted by column 0 */
+static const unsigned int power12_event_alternatives[][MAX_ALT] = {
+ { PM_INST_CMPL_ALT, PM_INST_CMPL },
+ { PM_CYC_ALT, PM_CYC },
+};
+
+static int power12_get_alternatives(u64 event, unsigned int flags, u64 alt[])
+{
+ int num_alt = 0;
+
+ num_alt = isa207_get_alternatives(event, alt,
+ ARRAY_SIZE(power12_event_alternatives), flags,
+ power12_event_alternatives);
+
+ return num_alt;
+}
+
+static int power12_check_attr_config(struct perf_event *ev)
+{
+ u64 val;
+ u64 event = ev->attr.config;
+
+ val = (event >> EVENT_SAMPLE_SHIFT) & EVENT_SAMPLE_MASK;
+ if (val == 0x10 || isa3XX_check_attr_config(ev))
+ return -EINVAL;
+
+ return 0;
+}
+
+GENERIC_EVENT_ATTR(cpu-cycles, PM_CYC);
+GENERIC_EVENT_ATTR(instructions, PM_INST_CMPL);
+GENERIC_EVENT_ATTR(branch-instructions, PM_BR_FIN);
+GENERIC_EVENT_ATTR(branch-misses, PM_MPRED_BR_FIN);
+GENERIC_EVENT_ATTR(cache-references, PM_LD_REF_L1);
+GENERIC_EVENT_ATTR(cache-misses, PM_LD_DEMAND_MISS_L1_FIN);
+GENERIC_EVENT_ATTR(mem-loads, MEM_LOADS);
+GENERIC_EVENT_ATTR(mem-stores, MEM_STORES);
+
+CACHE_EVENT_ATTR(L1-dcache-load-misses, PM_LD_MISS_L1);
+CACHE_EVENT_ATTR(L1-dcache-loads, PM_LD_REF_L1);
+CACHE_EVENT_ATTR(L1-dcache-prefetches, PM_LD_PREFETCH_CACHE_LINE_MISS);
+CACHE_EVENT_ATTR(L1-dcache-store-misses, PM_ST_MISS_L1);
+CACHE_EVENT_ATTR(L1-icache-load-misses, PM_L1_ICACHE_MISS);
+CACHE_EVENT_ATTR(L1-icache-loads, PM_INST_FROM_L1);
+CACHE_EVENT_ATTR(L1-icache-prefetches, PM_IC_PREF_REQ);
+CACHE_EVENT_ATTR(LLC-load-misses, PM_DATA_FROM_L3MISS);
+CACHE_EVENT_ATTR(LLC-loads, PM_DATA_FROM_L3);
+CACHE_EVENT_ATTR(LLC-prefetches, PM_L3_PF_MISS_L3);
+CACHE_EVENT_ATTR(LLC-store-misses, PM_L2_ST_MISS);
+CACHE_EVENT_ATTR(LLC-stores, PM_L2_ST);
+CACHE_EVENT_ATTR(branch-load-misses, PM_BR_MPRED_CMPL);
+CACHE_EVENT_ATTR(branch-loads, PM_BR_CMPL);
+CACHE_EVENT_ATTR(dTLB-load-misses, PM_DTLB_MISS);
+CACHE_EVENT_ATTR(iTLB-load-misses, PM_ITLB_MISS);
+
+static struct attribute *power12_events_attr[] = {
+ GENERIC_EVENT_PTR(PM_CYC),
+ GENERIC_EVENT_PTR(PM_INST_CMPL),
+ GENERIC_EVENT_PTR(PM_BR_FIN),
+ GENERIC_EVENT_PTR(PM_MPRED_BR_FIN),
+ GENERIC_EVENT_PTR(PM_LD_REF_L1),
+ GENERIC_EVENT_PTR(PM_LD_DEMAND_MISS_L1_FIN),
+ GENERIC_EVENT_PTR(MEM_LOADS),
+ GENERIC_EVENT_PTR(MEM_STORES),
+ CACHE_EVENT_PTR(PM_LD_MISS_L1),
+ CACHE_EVENT_PTR(PM_LD_REF_L1),
+ CACHE_EVENT_PTR(PM_LD_PREFETCH_CACHE_LINE_MISS),
+ CACHE_EVENT_PTR(PM_ST_MISS_L1),
+ CACHE_EVENT_PTR(PM_L1_ICACHE_MISS),
+ CACHE_EVENT_PTR(PM_INST_FROM_L1),
+ CACHE_EVENT_PTR(PM_IC_PREF_REQ),
+ CACHE_EVENT_PTR(PM_DATA_FROM_L3MISS),
+ CACHE_EVENT_PTR(PM_DATA_FROM_L3),
+ CACHE_EVENT_PTR(PM_L3_PF_MISS_L3),
+ CACHE_EVENT_PTR(PM_L2_ST_MISS),
+ CACHE_EVENT_PTR(PM_L2_ST),
+ CACHE_EVENT_PTR(PM_BR_MPRED_CMPL),
+ CACHE_EVENT_PTR(PM_BR_CMPL),
+ CACHE_EVENT_PTR(PM_DTLB_MISS),
+ CACHE_EVENT_PTR(PM_ITLB_MISS),
+ NULL
+};
+
+static const struct attribute_group power12_pmu_events_group = {
+ .name = "events",
+ .attrs = power12_events_attr,
+};
+
+PMU_FORMAT_ATTR(event, "config:0-59");
+PMU_FORMAT_ATTR(pmcxsel, "config:0-7");
+PMU_FORMAT_ATTR(mark, "config:8");
+PMU_FORMAT_ATTR(combine, "config:10-11");
+PMU_FORMAT_ATTR(unit, "config:12-15");
+PMU_FORMAT_ATTR(pmc, "config:16-19");
+PMU_FORMAT_ATTR(cache_sel, "config:20-21");
+PMU_FORMAT_ATTR(sdar_mode, "config:22-23");
+PMU_FORMAT_ATTR(sample_mode, "config:24-28");
+PMU_FORMAT_ATTR(thresh_sel, "config:29-31");
+PMU_FORMAT_ATTR(thresh_stop, "config:32-35");
+PMU_FORMAT_ATTR(thresh_start, "config:36-39");
+PMU_FORMAT_ATTR(l2l3_sel, "config:40-44");
+PMU_FORMAT_ATTR(src_sel, "config:45-46");
+PMU_FORMAT_ATTR(invert_bit, "config:47");
+PMU_FORMAT_ATTR(src_mask, "config:48-53");
+PMU_FORMAT_ATTR(src_match, "config:54-59");
+PMU_FORMAT_ATTR(radix_scope, "config:9");
+PMU_FORMAT_ATTR(thresh_cmp, "config1:0-17");
+
+static struct attribute *power12_pmu_format_attr[] = {
+ &format_attr_event.attr,
+ &format_attr_pmcxsel.attr,
+ &format_attr_mark.attr,
+ &format_attr_combine.attr,
+ &format_attr_unit.attr,
+ &format_attr_pmc.attr,
+ &format_attr_cache_sel.attr,
+ &format_attr_sdar_mode.attr,
+ &format_attr_sample_mode.attr,
+ &format_attr_thresh_sel.attr,
+ &format_attr_thresh_stop.attr,
+ &format_attr_thresh_start.attr,
+ &format_attr_l2l3_sel.attr,
+ &format_attr_src_sel.attr,
+ &format_attr_invert_bit.attr,
+ &format_attr_src_mask.attr,
+ &format_attr_src_match.attr,
+ &format_attr_radix_scope.attr,
+ &format_attr_thresh_cmp.attr,
+ NULL,
+};
+
+static const struct attribute_group power12_pmu_format_group = {
+ .name = "format",
+ .attrs = power12_pmu_format_attr,
+};
+
+static const struct attribute_group *power12_pmu_attr_groups[] = {
+ &power12_pmu_format_group,
+ &power12_pmu_events_group,
+ NULL,
+};
+
+static int power12_generic_events[] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = PM_CYC,
+ [PERF_COUNT_HW_INSTRUCTIONS] = PM_INST_CMPL,
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = PM_BR_FIN,
+ [PERF_COUNT_HW_BRANCH_MISSES] = PM_MPRED_BR_FIN,
+ [PERF_COUNT_HW_CACHE_REFERENCES] = PM_LD_REF_L1,
+ [PERF_COUNT_HW_CACHE_MISSES] = PM_LD_DEMAND_MISS_L1_FIN,
+};
+
+static u64 power12_bhrb_filter_map(u64 branch_sample_type)
+{
+ u64 pmu_bhrb_filter = 0;
+
+ /* BHRB and regular PMU events share the same privilege state
+ * filter configuration. BHRB is always recorded along with a
+ * regular PMU event. As the privilege state filter is handled
+ * in the basic PMC configuration of the accompanying regular
+ * PMU event, we ignore any separate BHRB specific request.
+ */
+
+ /* No branch filter requested */
+ if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY)
+ return pmu_bhrb_filter;
+
+ /* Invalid branch filter options - HW does not support */
+ if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY_RETURN)
+ return -1;
+
+ if (branch_sample_type & PERF_SAMPLE_BRANCH_IND_CALL) {
+ pmu_bhrb_filter |= POWER12_MMCRA_IFM2;
+ return pmu_bhrb_filter;
+ }
+
+ if (branch_sample_type & PERF_SAMPLE_BRANCH_COND) {
+ pmu_bhrb_filter |= POWER12_MMCRA_IFM3;
+ return pmu_bhrb_filter;
+ }
+
+ if (branch_sample_type & PERF_SAMPLE_BRANCH_CALL)
+ return -1;
+
+ if (branch_sample_type & PERF_SAMPLE_BRANCH_ANY_CALL) {
+ pmu_bhrb_filter |= POWER12_MMCRA_IFM1;
+ return pmu_bhrb_filter;
+ }
+
+ /* Every thing else is unsupported */
+ return -1;
+}
+
+static void power12_config_bhrb(u64 pmu_bhrb_filter)
+{
+ pmu_bhrb_filter &= POWER12_MMCRA_BHRB_MASK;
+
+ /* Enable BHRB filter in PMU */
+ mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter));
+}
+
+#define C(x) PERF_COUNT_HW_CACHE_##x
+
+/*
+ * Table of generalized cache-related events.
+ * 0 means not supported, -1 means nonsensical, other values
+ * are event codes.
+ */
+static u64 power12_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
+ [C(L1D)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = PM_LD_REF_L1,
+ [C(RESULT_MISS)] = PM_LD_MISS_L1,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = 0,
+ [C(RESULT_MISS)] = PM_ST_MISS_L1,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = PM_LD_PREFETCH_CACHE_LINE_MISS,
+ [C(RESULT_MISS)] = 0,
+ },
+ },
+ [C(L1I)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = PM_INST_FROM_L1,
+ [C(RESULT_MISS)] = PM_L1_ICACHE_MISS,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = PM_INST_FROM_L1MISS,
+ [C(RESULT_MISS)] = -1,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = PM_IC_PREF_REQ,
+ [C(RESULT_MISS)] = 0,
+ },
+ },
+ [C(LL)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = PM_DATA_FROM_L3,
+ [C(RESULT_MISS)] = PM_DATA_FROM_L3MISS,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = PM_L2_ST,
+ [C(RESULT_MISS)] = PM_L2_ST_MISS,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = PM_L3_PF_MISS_L3,
+ [C(RESULT_MISS)] = 0,
+ },
+ },
+ [C(DTLB)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = 0,
+ [C(RESULT_MISS)] = PM_DTLB_MISS,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = -1,
+ [C(RESULT_MISS)] = -1,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = -1,
+ [C(RESULT_MISS)] = -1,
+ },
+ },
+ [C(ITLB)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = 0,
+ [C(RESULT_MISS)] = PM_ITLB_MISS,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = -1,
+ [C(RESULT_MISS)] = -1,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = -1,
+ [C(RESULT_MISS)] = -1,
+ },
+ },
+ [C(BPU)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = PM_BR_CMPL,
+ [C(RESULT_MISS)] = PM_BR_MPRED_CMPL,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = -1,
+ [C(RESULT_MISS)] = -1,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = -1,
+ [C(RESULT_MISS)] = -1,
+ },
+ },
+ [C(NODE)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = -1,
+ [C(RESULT_MISS)] = -1,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = -1,
+ [C(RESULT_MISS)] = -1,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = -1,
+ [C(RESULT_MISS)] = -1,
+ },
+ },
+};
+
+#undef C
+
+/*
+ * Set the MMCR0[CC56RUN] bit to enable counting for
+ * PMC5 and PMC6 regardless of the state of CTRL[RUN],
+ * so that we can use counters 5 and 6 as PM_INST_CMPL and
+ * PM_CYC.
+ */
+static int power12_compute_mmcr(u64 event[], int n_ev,
+ unsigned int hwc[], struct mmcr_regs *mmcr,
+ struct perf_event *pevents[], u32 flags)
+{
+ int ret;
+
+ ret = isa207_compute_mmcr(event, n_ev, hwc, mmcr, pevents, flags);
+ if (!ret)
+ mmcr->mmcr0 |= MMCR0_C56RUN;
+ return ret;
+}
+
+static struct power_pmu power12_pmu = {
+ .name = "Power12",
+ .n_counter = MAX_PMU_COUNTERS,
+ .add_fields = ISA207_ADD_FIELDS,
+ .test_adder = ISA207_TEST_ADDER,
+ .group_constraint_mask = CNST_CACHE_PMC4_MASK,
+ .group_constraint_val = CNST_CACHE_PMC4_VAL,
+ .compute_mmcr = power12_compute_mmcr,
+ .config_bhrb = power12_config_bhrb,
+ .bhrb_filter_map = power12_bhrb_filter_map,
+ .get_constraint = isa207_get_constraint,
+ .get_alternatives = power12_get_alternatives,
+ .get_mem_data_src = isa207_get_mem_data_src,
+ .get_mem_weight = isa207_get_mem_weight,
+ .disable_pmc = isa207_disable_pmc,
+ .flags = PPMU_HAS_SIER | PPMU_ARCH_207S |
+ PPMU_ARCH_31 | PPMU_HAS_ATTR_CONFIG1 |
+ PPMU_P10,
+ .n_generic = ARRAY_SIZE(power12_generic_events),
+ .generic_events = power12_generic_events,
+ .cache_events = &power12_cache_events,
+ .attr_groups = power12_pmu_attr_groups,
+ .bhrb_nr = 32,
+ .capabilities = PERF_PMU_CAP_EXTENDED_REGS,
+ .check_attr_config = power12_check_attr_config,
+};
+
+int __init init_power12_pmu(void)
+{
+ unsigned int pvr;
+ int rc;
+
+ pvr = mfspr(SPRN_PVR);
+ if (PVR_VER(pvr) != PVR_POWER12)
+ return -ENODEV;
+
+ /* Set the PERF_REG_EXTENDED_MASK here */
+ PERF_REG_EXTENDED_MASK = PERF_REG_PMU_MASK_31;
+
+ rc = register_power_pmu(&power12_pmu);
+ if (rc)
+ return rc;
+
+ /* Tell userspace that EBB is supported */
+ cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_EBB;
+
+ return 0;
+}
--
2.55.0
^ permalink raw reply related [flat|nested] 5+ messages in thread