* [PATCH v2 1/4] powerpc/pseries: Limit PVR list to 16 entries for CAS negotiation
2026-08-03 15:57 [PATCH v2 0/4] Base support for Power12 Mahesh Salgaonkar
@ 2026-08-03 15:57 ` Mahesh Salgaonkar
2026-08-03 18:32 ` Amit Machhiwal
2026-08-03 15:57 ` [PATCH v2 2/4] powerpc: Add Power12 raw mode Mahesh Salgaonkar
` (2 subsequent siblings)
3 siblings, 1 reply; 16+ messages in thread
From: Mahesh Salgaonkar @ 2026-08-03 15:57 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Madhavan Srinivasan, Praveen K Pandey
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>
Tested-by: Praveen K Pandey <praveen@linux.ibm.com>
---
Change in v2:
- Define a named macro CAS_MAX_PVR_ENTRIES
---
arch/powerpc/kernel/prom_init.c | 35 ++++++++++++++++++++++++++-------
1 file changed, 28 insertions(+), 7 deletions(-)
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 53503937de0ee..6b50870759fd9 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -86,6 +86,12 @@
*/
#define ADDR(x) (u32)(unsigned long)(x)
+/*
+ * Current Power system firmware caps the PVR list array size at 16 entries
+ * during CAS (Client Architecture Support) negotiation.
+ */
+#define CAS_MAX_PVR_ENTRIES 16
+
#ifdef CONFIG_PPC64
#define OF_WORKAROUNDS 0
#else
@@ -979,6 +985,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 +1042,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 +1353,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 +1408,22 @@ static void __init prom_send_capabilities(void)
ihandle root;
prom_arg_t ret;
u32 cores;
+ int start_index = 0;
+
+ /*
+ * 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.
+ *
+ * Compute the 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.
+ */
+ if ((ARRAY_SIZE(ibm_architecture_vec_template.pvrs) > CAS_MAX_PVR_ENTRIES) &&
+ (PVR_VER(mfspr(SPRN_PVR)) <= PVR_POWER11))
+ start_index = ARRAY_SIZE(ibm_architecture_vec_template.pvrs) - CAS_MAX_PVR_ENTRIES;
/* Check ibm,arch-vec-5-platform-support and fixup vec5 if required */
prom_check_platform_support();
@@ -1427,7 +1448,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] 16+ messages in thread* Re: [PATCH v2 1/4] powerpc/pseries: Limit PVR list to 16 entries for CAS negotiation
2026-08-03 15:57 ` [PATCH v2 1/4] powerpc/pseries: Limit PVR list to 16 entries for CAS negotiation Mahesh Salgaonkar
@ 2026-08-03 18:32 ` Amit Machhiwal
2026-08-04 6:42 ` Mahesh J Salgaonkar
0 siblings, 1 reply; 16+ messages in thread
From: Amit Machhiwal @ 2026-08-03 18:32 UTC (permalink / raw)
To: Mahesh Salgaonkar; +Cc: linuxppc-dev, Madhavan Srinivasan, Praveen K Pandey
On 2026/08/03 09:27 PM, Mahesh Salgaonkar wrote:
> 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>
> Tested-by: Praveen K Pandey <praveen@linux.ibm.com>
> ---
> Change in v2:
> - Define a named macro CAS_MAX_PVR_ENTRIES
> ---
> arch/powerpc/kernel/prom_init.c | 35 ++++++++++++++++++++++++++-------
> 1 file changed, 28 insertions(+), 7 deletions(-)
>
> diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
> index 53503937de0ee..6b50870759fd9 100644
> --- a/arch/powerpc/kernel/prom_init.c
> +++ b/arch/powerpc/kernel/prom_init.c
> @@ -86,6 +86,12 @@
> */
> #define ADDR(x) (u32)(unsigned long)(x)
>
> +/*
> + * Current Power system firmware caps the PVR list array size at 16 entries
> + * during CAS (Client Architecture Support) negotiation.
> + */
> +#define CAS_MAX_PVR_ENTRIES 16
> +
> #ifdef CONFIG_PPC64
> #define OF_WORKAROUNDS 0
> #else
> @@ -979,6 +985,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),
> + },
It may be a good idea to add a comment (like below) above .pvrs = {
explaining why the oldest entries are at the front, otherwise the intent
of start_index trimming from the front is not obvious to future
contributors:
/*
* The oldest/least-capable entries are placed at the FRONT so that
* start_index trims them first when running on older firmware (Power11
* and below) that caps the array at CAS_MAX_PVR_ENTRIES entries. As
* newer processors are added, more old front entries will naturally
* fall outside the firmware window. New entries must be inserted in
* newest-first order AFTER these oldest front entries.
*/
> {
> .mask = cpu_to_be32(0xffff0000), /* POWER6 */
> .val = cpu_to_be32(0x003e0000),
> @@ -1032,13 +1042,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 +1353,6 @@ static void __init prom_check_platform_support(void)
> };
> int prop_len = prom_getproplen(prom.chosen,
> "ibm,arch-vec-5-platform-support");
> -
Nit: Looks unintentional whitespace change, please drop.
> /*
> * First copy the architecture vec template
> *
> @@ -1403,6 +1408,22 @@ static void __init prom_send_capabilities(void)
> ihandle root;
> prom_arg_t ret;
> u32 cores;
> + int start_index = 0;
> +
> + /*
> + * 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.
> + *
> + * Compute the 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.
> + */
> + if ((ARRAY_SIZE(ibm_architecture_vec_template.pvrs) > CAS_MAX_PVR_ENTRIES) &&
> + (PVR_VER(mfspr(SPRN_PVR)) <= PVR_POWER11))
> + start_index = ARRAY_SIZE(ibm_architecture_vec_template.pvrs) - CAS_MAX_PVR_ENTRIES;
>
> /* Check ibm,arch-vec-5-platform-support and fixup vec5 if required */
> prom_check_platform_support();
> @@ -1427,7 +1448,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 [flat|nested] 16+ messages in thread* Re: [PATCH v2 1/4] powerpc/pseries: Limit PVR list to 16 entries for CAS negotiation
2026-08-03 18:32 ` Amit Machhiwal
@ 2026-08-04 6:42 ` Mahesh J Salgaonkar
0 siblings, 0 replies; 16+ messages in thread
From: Mahesh J Salgaonkar @ 2026-08-04 6:42 UTC (permalink / raw)
To: linuxppc-dev, Madhavan Srinivasan, Praveen K Pandey
On 2026-08-04 00:02:08 Tue, Amit Machhiwal wrote:
> On 2026/08/03 09:27 PM, Mahesh Salgaonkar wrote:
> > 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>
> > Tested-by: Praveen K Pandey <praveen@linux.ibm.com>
> > ---
> > Change in v2:
> > - Define a named macro CAS_MAX_PVR_ENTRIES
> > ---
[...]
> > @@ -1032,13 +1042,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 +1353,6 @@ static void __init prom_check_platform_support(void)
> > };
> > int prop_len = prom_getproplen(prom.chosen,
> > "ibm,arch-vec-5-platform-support");
> > -
>
> Nit: Looks unintentional whitespace change, please drop.
Hi Maddy,
Let me know if you want ime to send out v3 to handle this unintentional
whitespace change Or do you think you handle this while merging ?
Thanks,
-Mahesh.
>
> > /*
> > * First copy the architecture vec template
> > *
> > @@ -1403,6 +1408,22 @@ static void __init prom_send_capabilities(void)
> > ihandle root;
> > prom_arg_t ret;
> > u32 cores;
> > + int start_index = 0;
> > +
> > + /*
> > + * 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.
> > + *
> > + * Compute the 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.
> > + */
> > + if ((ARRAY_SIZE(ibm_architecture_vec_template.pvrs) > CAS_MAX_PVR_ENTRIES) &&
> > + (PVR_VER(mfspr(SPRN_PVR)) <= PVR_POWER11))
> > + start_index = ARRAY_SIZE(ibm_architecture_vec_template.pvrs) - CAS_MAX_PVR_ENTRIES;
> >
> > /* Check ibm,arch-vec-5-platform-support and fixup vec5 if required */
> > prom_check_platform_support();
> > @@ -1427,7 +1448,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
> >
> >
>
--
Mahesh J Salgaonkar
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v2 2/4] powerpc: Add Power12 raw mode
2026-08-03 15:57 [PATCH v2 0/4] Base support for Power12 Mahesh Salgaonkar
2026-08-03 15:57 ` [PATCH v2 1/4] powerpc/pseries: Limit PVR list to 16 entries for CAS negotiation Mahesh Salgaonkar
@ 2026-08-03 15:57 ` Mahesh Salgaonkar
2026-08-03 19:10 ` Amit Machhiwal
2026-08-03 15:57 ` [PATCH v2 3/4] powerpc: Add Power12 architected mode Mahesh Salgaonkar
2026-08-03 15:57 ` [PATCH v2 4/4] powerpc/perf: Add power12 Base Performance Monitoring support Mahesh Salgaonkar
3 siblings, 1 reply; 16+ messages in thread
From: Mahesh Salgaonkar @ 2026-08-03 15:57 UTC (permalink / raw)
To: linuxppc-dev
Cc: Nicholas Piggin, Madhavan Srinivasan, Ritesh Harjani (IBM),
Praveen K Pandey, Nikhil Kumar Singh
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>
Tested-by: Praveen K Pandey <praveen@linux.ibm.com>
Reviewed-by: Nikhil Kumar Singh <nikhilks@linux.ibm.com>
---
Change in v2:
- Added Reviewed-by from Nikhil
---
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 30e2fe3895024..26d2c0e2c99c6 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 ec16c12296da8..a3be81c47df3a 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 5f9c5d436e171..4fd7f81a29304 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 3449dd2b577d4..4460b666c603e 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 0d3ccb34adfb2..d0e9765dee287 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 731b97dc2d150..bc9bd225f5876 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 98bd4e6c17705..5de704ac031d8 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 98d4274a1b6bf..7619dd157646f 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 e5853daa6a486..b369e8cda12ee 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 67c545f61f0d7..4afaba19b5867 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 61dbeea317f3b..6ad4e3d0b5a08 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 e9e2dd70c0605..ab2a80e59011c 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 64f0df5bb5cdc..0e777d7dc3326 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] 16+ messages in thread* Re: [PATCH v2 2/4] powerpc: Add Power12 raw mode
2026-08-03 15:57 ` [PATCH v2 2/4] powerpc: Add Power12 raw mode Mahesh Salgaonkar
@ 2026-08-03 19:10 ` Amit Machhiwal
2026-08-04 5:52 ` Mahesh J Salgaonkar
0 siblings, 1 reply; 16+ messages in thread
From: Amit Machhiwal @ 2026-08-03 19:10 UTC (permalink / raw)
To: Mahesh Salgaonkar
Cc: linuxppc-dev, Nicholas Piggin, Madhavan Srinivasan,
Ritesh Harjani (IBM), Praveen K Pandey, Nikhil Kumar Singh
On 2026/08/03 09:27 PM, Mahesh Salgaonkar wrote:
> 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>
> Tested-by: Praveen K Pandey <praveen@linux.ibm.com>
> Reviewed-by: Nikhil Kumar Singh <nikhilks@linux.ibm.com>
> ---
> Change in v2:
> - Added Reviewed-by from Nikhil
> ---
> 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 30e2fe3895024..26d2c0e2c99c6 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 ec16c12296da8..a3be81c47df3a 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)
Line exceeds 80 columns. Please wrap CPU_FTRS_POWER12 onto its own line.
Same applies to the #else variant below.
> #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 5f9c5d436e171..4fd7f81a29304 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 3449dd2b577d4..4460b666c603e 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 0d3ccb34adfb2..d0e9765dee287 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 731b97dc2d150..bc9bd225f5876 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 98bd4e6c17705..5de704ac031d8 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 |\
The '\' continuation is unnecessary inside a function body — the
enclosing parentheses are sufficient for the compiler. While this
pattern exists in the upstream __setup_cpu_power10 and
__restore_cpu_power10 functions, please consider not perpetuating it in
the new Power12 functions. Simply drop the '\'.
checkpatch.pl does report this:
WARNING: Avoid unnecessary line continuations
#201: FILE: arch/powerpc/kernel/cpu_setup_power.c:304:
+ init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
WARNING: Avoid unnecessary line continuations
#224: FILE: arch/powerpc/kernel/cpu_setup_power.c:327:
+ init_LPCR_ISA300((mfspr(SPRN_LPCR) | LPCR_PECEDH | LPCR_PECE_HVEE |\
Thanks,
Amit
> + 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 |\
Ditto.
> + 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 98d4274a1b6bf..7619dd157646f 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 e5853daa6a486..b369e8cda12ee 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 67c545f61f0d7..4afaba19b5867 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 61dbeea317f3b..6ad4e3d0b5a08 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 e9e2dd70c0605..ab2a80e59011c 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 64f0df5bb5cdc..0e777d7dc3326 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 [flat|nested] 16+ messages in thread* Re: [PATCH v2 2/4] powerpc: Add Power12 raw mode
2026-08-03 19:10 ` Amit Machhiwal
@ 2026-08-04 5:52 ` Mahesh J Salgaonkar
2026-08-04 6:13 ` Amit Machhiwal
0 siblings, 1 reply; 16+ messages in thread
From: Mahesh J Salgaonkar @ 2026-08-04 5:52 UTC (permalink / raw)
To: linuxppc-dev, Nicholas Piggin, Madhavan Srinivasan,
Ritesh Harjani (IBM), Praveen K Pandey, Nikhil Kumar Singh
On 2026-08-04 00:40:10 Tue, Amit Machhiwal wrote:
> On 2026/08/03 09:27 PM, Mahesh Salgaonkar wrote:
> > 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>
> > Tested-by: Praveen K Pandey <praveen@linux.ibm.com>
> > Reviewed-by: Nikhil Kumar Singh <nikhilks@linux.ibm.com>
> > ---
> > Change in v2:
> > - Added Reviewed-by from Nikhil
> > ---
> > 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 30e2fe3895024..26d2c0e2c99c6 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 ec16c12296da8..a3be81c47df3a 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)
>
> Line exceeds 80 columns. Please wrap CPU_FTRS_POWER12 onto its own line.
> Same applies to the #else variant below.
Linux has long lifted the 80 column restriction and increased the
default limit to 100 chars.
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bdc48fa11e46f867ea4d75fa59ee87a7f48be144
Thanks,
-Mahesh.
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [PATCH v2 2/4] powerpc: Add Power12 raw mode
2026-08-04 5:52 ` Mahesh J Salgaonkar
@ 2026-08-04 6:13 ` Amit Machhiwal
0 siblings, 0 replies; 16+ messages in thread
From: Amit Machhiwal @ 2026-08-04 6:13 UTC (permalink / raw)
To: Mahesh J Salgaonkar
Cc: linuxppc-dev, Nicholas Piggin, Madhavan Srinivasan,
Ritesh Harjani (IBM), Praveen K Pandey, Nikhil Kumar Singh
On 2026/08/04 11:22 AM, Mahesh J Salgaonkar wrote:
> On 2026-08-04 00:40:10 Tue, Amit Machhiwal wrote:
> > On 2026/08/03 09:27 PM, Mahesh Salgaonkar wrote:
> > > 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>
> > > Tested-by: Praveen K Pandey <praveen@linux.ibm.com>
> > > Reviewed-by: Nikhil Kumar Singh <nikhilks@linux.ibm.com>
> > > ---
> > > Change in v2:
> > > - Added Reviewed-by from Nikhil
> > > ---
> > > 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 30e2fe3895024..26d2c0e2c99c6 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 ec16c12296da8..a3be81c47df3a 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)
> >
> > Line exceeds 80 columns. Please wrap CPU_FTRS_POWER12 onto its own line.
> > Same applies to the #else variant below.
>
> Linux has long lifted the 80 column restriction and increased the
> default limit to 100 chars.
>
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bdc48fa11e46f867ea4d75fa59ee87a7f48be144
The commit log itself mentions:
staying withing 80 columns is certainly still _preferred_
But I'll leave it upto you. Either way:
Reviewed-by: Amit Machhiwal <amachhiw@linux.ibm.com>
Thanks,
Amit
>
> Thanks,
> -Mahesh.
>
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v2 3/4] powerpc: Add Power12 architected mode
2026-08-03 15:57 [PATCH v2 0/4] Base support for Power12 Mahesh Salgaonkar
2026-08-03 15:57 ` [PATCH v2 1/4] powerpc/pseries: Limit PVR list to 16 entries for CAS negotiation Mahesh Salgaonkar
2026-08-03 15:57 ` [PATCH v2 2/4] powerpc: Add Power12 raw mode Mahesh Salgaonkar
@ 2026-08-03 15:57 ` Mahesh Salgaonkar
2026-08-03 19:17 ` Amit Machhiwal
2026-08-03 15:57 ` [PATCH v2 4/4] powerpc/perf: Add power12 Base Performance Monitoring support Mahesh Salgaonkar
3 siblings, 1 reply; 16+ messages in thread
From: Mahesh Salgaonkar @ 2026-08-03 15:57 UTC (permalink / raw)
To: linuxppc-dev
Cc: Ritesh Harjani (IBM), Madhavan Srinivasan, Nicholas Piggin,
Praveen K Pandey, Nikhil Kumar Singh
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>
Tested-by: Praveen K Pandey <praveen@linux.ibm.com>
Reviewed-by: Nikhil Kumar Singh <nikhilks@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 f4991d10d89ec..cd025c7225ee7 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 bc9bd225f5876..68215b7ce67e6 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 7619dd157646f..26fa40aa34db2 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 6b50870759fd9..7ebfe048f97a2 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -953,7 +953,7 @@ struct option_vector7 {
} __packed;
struct ibm_arch_vec {
- struct { __be32 mask, val; } pvrs[16];
+ struct { __be32 mask, val; } pvrs[18];
u8 num_vectors;
@@ -1021,6 +1021,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),
@@ -1054,7 +1062,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] 16+ messages in thread* Re: [PATCH v2 3/4] powerpc: Add Power12 architected mode
2026-08-03 15:57 ` [PATCH v2 3/4] powerpc: Add Power12 architected mode Mahesh Salgaonkar
@ 2026-08-03 19:17 ` Amit Machhiwal
2026-08-04 6:00 ` Mahesh J Salgaonkar
0 siblings, 1 reply; 16+ messages in thread
From: Amit Machhiwal @ 2026-08-03 19:17 UTC (permalink / raw)
To: Mahesh Salgaonkar
Cc: linuxppc-dev, Ritesh Harjani (IBM), Madhavan Srinivasan,
Nicholas Piggin, Praveen K Pandey, Nikhil Kumar Singh
On 2026/08/03 09:27 PM, Mahesh Salgaonkar wrote:
> 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>
> Tested-by: Praveen K Pandey <praveen@linux.ibm.com>
> Reviewed-by: Nikhil Kumar Singh <nikhilks@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 f4991d10d89ec..cd025c7225ee7 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 */
Minor: OV1_PPC_3_1 and OV1_PPC_3_2 use extra tabs relative to OV1_PPC_3_00.
This is pre-existing style inconsistency in the file (not introduced by
this patch) but new additions should match the surrounding code. Please
consider aligning them.
Thanks,
Amit
>
> /* 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 bc9bd225f5876..68215b7ce67e6 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 7619dd157646f..26fa40aa34db2 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 6b50870759fd9..7ebfe048f97a2 100644
> --- a/arch/powerpc/kernel/prom_init.c
> +++ b/arch/powerpc/kernel/prom_init.c
> @@ -953,7 +953,7 @@ struct option_vector7 {
> } __packed;
>
> struct ibm_arch_vec {
> - struct { __be32 mask, val; } pvrs[16];
> + struct { __be32 mask, val; } pvrs[18];
>
> u8 num_vectors;
>
> @@ -1021,6 +1021,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),
> @@ -1054,7 +1062,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 [flat|nested] 16+ messages in thread* Re: [PATCH v2 3/4] powerpc: Add Power12 architected mode
2026-08-03 19:17 ` Amit Machhiwal
@ 2026-08-04 6:00 ` Mahesh J Salgaonkar
2026-08-04 6:20 ` Amit Machhiwal
0 siblings, 1 reply; 16+ messages in thread
From: Mahesh J Salgaonkar @ 2026-08-04 6:00 UTC (permalink / raw)
To: linuxppc-dev, Ritesh Harjani (IBM), Madhavan Srinivasan,
Nicholas Piggin, Praveen K Pandey, Nikhil Kumar Singh
On 2026-08-04 00:47:49 Tue, Amit Machhiwal wrote:
> On 2026/08/03 09:27 PM, Mahesh Salgaonkar wrote:
> > 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>
> > Tested-by: Praveen K Pandey <praveen@linux.ibm.com>
> > Reviewed-by: Nikhil Kumar Singh <nikhilks@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 f4991d10d89ec..cd025c7225ee7 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 */
>
> Minor: OV1_PPC_3_1 and OV1_PPC_3_2 use extra tabs relative to OV1_PPC_3_00.
> This is pre-existing style inconsistency in the file (not introduced by
> this patch) but new additions should match the surrounding code. Please
> consider aligning them.
This is bit tricky. Prior to 3.0 the ISA versions were 2.05, 2.06, 2.07
and so on and pre-existing style did make sense. But it looks like from
3.1 the style changed may be for a reason because it can not be written
as 3.10 which may create more confusiton. Hence, I plan to stick with
the new style which is introduced from 3.1.
Thanks,
-Mahesh.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 3/4] powerpc: Add Power12 architected mode
2026-08-04 6:00 ` Mahesh J Salgaonkar
@ 2026-08-04 6:20 ` Amit Machhiwal
2026-08-05 9:32 ` Mahesh J Salgaonkar
0 siblings, 1 reply; 16+ messages in thread
From: Amit Machhiwal @ 2026-08-04 6:20 UTC (permalink / raw)
To: Mahesh J Salgaonkar
Cc: linuxppc-dev, Ritesh Harjani (IBM), Madhavan Srinivasan,
Nicholas Piggin, Praveen K Pandey, Nikhil Kumar Singh
On 2026/08/04 11:30 AM, Mahesh J Salgaonkar wrote:
> On 2026-08-04 00:47:49 Tue, Amit Machhiwal wrote:
> > On 2026/08/03 09:27 PM, Mahesh Salgaonkar wrote:
> > > 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>
> > > Tested-by: Praveen K Pandey <praveen@linux.ibm.com>
> > > Reviewed-by: Nikhil Kumar Singh <nikhilks@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 f4991d10d89ec..cd025c7225ee7 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 */
> >
> > Minor: OV1_PPC_3_1 and OV1_PPC_3_2 use extra tabs relative to OV1_PPC_3_00.
> > This is pre-existing style inconsistency in the file (not introduced by
> > this patch) but new additions should match the surrounding code. Please
> > consider aligning them.
>
> This is bit tricky. Prior to 3.0 the ISA versions were 2.05, 2.06, 2.07
> and so on and pre-existing style did make sense. But it looks like from
> 3.1 the style changed may be for a reason because it can not be written
> as 3.10 which may create more confusiton. Hence, I plan to stick with
> the new style which is introduced from 3.1.
If the extra tab is intentional to maintain visual alignment for the 3.x
series names, then it make sense. Please feel free to add:
Reviewed-by: Amit Machhiwal <amachhiw@linux.ibm.com>
Thanks,
Amit
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 3/4] powerpc: Add Power12 architected mode
2026-08-04 6:20 ` Amit Machhiwal
@ 2026-08-05 9:32 ` Mahesh J Salgaonkar
0 siblings, 0 replies; 16+ messages in thread
From: Mahesh J Salgaonkar @ 2026-08-05 9:32 UTC (permalink / raw)
To: linuxppc-dev, Ritesh Harjani (IBM), Madhavan Srinivasan,
Nicholas Piggin, Praveen K Pandey, Nikhil Kumar Singh
On 2026-08-04 11:50:45 Tue, Amit Machhiwal wrote:
> On 2026/08/04 11:30 AM, Mahesh J Salgaonkar wrote:
> > On 2026-08-04 00:47:49 Tue, Amit Machhiwal wrote:
> > > On 2026/08/03 09:27 PM, Mahesh Salgaonkar wrote:
> > > > 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>
> > > > Tested-by: Praveen K Pandey <praveen@linux.ibm.com>
> > > > Reviewed-by: Nikhil Kumar Singh <nikhilks@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 f4991d10d89ec..cd025c7225ee7 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 */
> > >
> > > Minor: OV1_PPC_3_1 and OV1_PPC_3_2 use extra tabs relative to OV1_PPC_3_00.
> > > This is pre-existing style inconsistency in the file (not introduced by
> > > this patch) but new additions should match the surrounding code. Please
> > > consider aligning them.
> >
> > This is bit tricky. Prior to 3.0 the ISA versions were 2.05, 2.06, 2.07
> > and so on and pre-existing style did make sense. But it looks like from
> > 3.1 the style changed may be for a reason because it can not be written
> > as 3.10 which may create more confusiton. Hence, I plan to stick with
> > the new style which is introduced from 3.1.
>
> If the extra tab is intentional to maintain visual alignment for the 3.x
> series names, then it make sense. Please feel free to add:
Ouch I missed that. thanks for the catch. Fixing it in v3
>
> Reviewed-by: Amit Machhiwal <amachhiw@linux.ibm.com>
Thanks for your review.
-Mahesh.
>
> Thanks,
> Amit
>
>
--
Mahesh J Salgaonkar
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v2 4/4] powerpc/perf: Add power12 Base Performance Monitoring support
2026-08-03 15:57 [PATCH v2 0/4] Base support for Power12 Mahesh Salgaonkar
` (2 preceding siblings ...)
2026-08-03 15:57 ` [PATCH v2 3/4] powerpc: Add Power12 architected mode Mahesh Salgaonkar
@ 2026-08-03 15:57 ` Mahesh Salgaonkar
2026-08-03 19:32 ` Amit Machhiwal
3 siblings, 1 reply; 16+ messages in thread
From: Mahesh Salgaonkar @ 2026-08-03 15:57 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Athira Rajeev, Madhavan Srinivasan, Praveen K Pandey
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>
Signed-off-by: Mahesh Salgaonkar <mahesh@linux.ibm.com>
Tested-by: Praveen K Pandey <praveen@linux.ibm.com>
---
Change in v2:
- Fix typo reported by Nikhil
---
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 78dd7e25219ee..bcc804c413381 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 720b1a5009226..10ded865583c3 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 a70ac471a5a5d..84d6ca209c492 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 0000000000000..cc26796d418b3
--- /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 writtent 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 0000000000000..89cc704b8324c
--- /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] 16+ messages in thread* Re: [PATCH v2 4/4] powerpc/perf: Add power12 Base Performance Monitoring support
2026-08-03 15:57 ` [PATCH v2 4/4] powerpc/perf: Add power12 Base Performance Monitoring support Mahesh Salgaonkar
@ 2026-08-03 19:32 ` Amit Machhiwal
2026-08-04 6:34 ` Mahesh J Salgaonkar
0 siblings, 1 reply; 16+ messages in thread
From: Amit Machhiwal @ 2026-08-03 19:32 UTC (permalink / raw)
To: Mahesh Salgaonkar
Cc: linuxppc-dev, Athira Rajeev, Madhavan Srinivasan,
Praveen K Pandey
On 2026/08/03 09:27 PM, Mahesh Salgaonkar wrote:
> 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>
> Signed-off-by: Mahesh Salgaonkar <mahesh@linux.ibm.com>
> Tested-by: Praveen K Pandey <praveen@linux.ibm.com>
> ---
> Change in v2:
> - Fix typo reported by Nikhil
> ---
> 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 78dd7e25219ee..bcc804c413381 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
Minor: Line exceeds 80 columns (with tabs expanded). Please wrap
power12-pmu.o onto its own continuation line aligned with the entries
above it.
Thanks,
Amit
> 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 720b1a5009226..10ded865583c3 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 a70ac471a5a5d..84d6ca209c492 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 0000000000000..cc26796d418b3
> --- /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 writtent 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 0000000000000..89cc704b8324c
> --- /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 [flat|nested] 16+ messages in thread* Re: [PATCH v2 4/4] powerpc/perf: Add power12 Base Performance Monitoring support
2026-08-03 19:32 ` Amit Machhiwal
@ 2026-08-04 6:34 ` Mahesh J Salgaonkar
0 siblings, 0 replies; 16+ messages in thread
From: Mahesh J Salgaonkar @ 2026-08-04 6:34 UTC (permalink / raw)
To: linuxppc-dev, Athira Rajeev, Madhavan Srinivasan,
Praveen K Pandey
On 2026-08-04 01:02:49 Tue, Amit Machhiwal wrote:
> On 2026/08/03 09:27 PM, Mahesh Salgaonkar wrote:
> > 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>
> > Signed-off-by: Mahesh Salgaonkar <mahesh@linux.ibm.com>
> > Tested-by: Praveen K Pandey <praveen@linux.ibm.com>
> > ---
> > Change in v2:
> > - Fix typo reported by Nikhil
> > ---
> > 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 78dd7e25219ee..bcc804c413381 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
>
> Minor: Line exceeds 80 columns (with tabs expanded). Please wrap
> power12-pmu.o onto its own continuation line aligned with the entries
> above it.
As I mentioned in my response to previous patch, 80 column is no more
hard limit.
Thanks,
-Mahesh.
^ permalink raw reply [flat|nested] 16+ messages in thread