powerpc: Add Power12 raw mode

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>
Reviewed-by: Amit Machhiwal <amachhiw@linux.ibm.com>
Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
Link: https://patch.msgid.link/20260806051120.3703698-3-mahesh@linux.ibm.com
This commit is contained in:
Nicholas Piggin
2026-08-06 10:41:18 +05:30
committed by Madhavan Srinivasan
parent 972a7b7872
commit e671e147ea
13 changed files with 157 additions and 13 deletions

View File

@@ -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);

View File

@@ -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

View File

@@ -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 | \

View File

@@ -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
/*
* Kernel-internal sentinel for invalid processor compatibility modes.

View File

@@ -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__ */

View File

@@ -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!

View File

@@ -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();
}

View File

@@ -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,

View File

@@ -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)
@@ -464,6 +465,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
@@ -655,9 +685,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},
@@ -712,6 +744,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)

View File

@@ -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;

View File

@@ -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;
@@ -461,6 +463,9 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
}
guest_pcr_bit = PCR_ARCH_31;
break;
case PVR_ARCH_32:
guest_pcr_bit = PCR_ARCH_32;
break;
default:
return -EINVAL;
}

View File

@@ -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);

View File

@@ -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 */