Commit 0ffd60b7 authored by Benjamin Gray's avatar Benjamin Gray Committed by Michael Ellerman

powerpc/dexcr: Add initial Dynamic Execution Control Register (DEXCR) support

ISA 3.1B introduces the Dynamic Execution Control Register (DEXCR). It
is a per-cpu register that allows control over various CPU behaviours
including branch hint usage, indirect branch speculation, and
hashst/hashchk support.

Add some definitions and basic support for the DEXCR in the kernel.
Right now it just

  * Initialises the DEXCR and HASHKEYR to a fixed value when a CPU
    onlines.
  * Clears them in reset_sprs().
  * Detects when the NPHIE aspect is supported (the others don't get
    looked at in this series, so there's no need to waste a CPU_FTR
    on them).

We initialise the HASHKEYR to ensure that all cores have the same key,
so an HV enforced NPHIE + swapping cores doesn't randomly crash a
process using hash instructions. The stores to HASHKEYR are
unconditional because the ISA makes no mention of the SPR being missing
if support for doing the hashes isn't present. So all that would happen
is the HASHKEYR value gets ignored. This helps slightly if NPHIE
detection fails; e.g., we currently only detect it on pseries.
Signed-off-by: default avatarBenjamin Gray <bgray@linux.ibm.com>
[mpe: Use simple values for DEXCR constants]
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20230616034846.311705-4-bgray@linux.ibm.com
parent 81e30a54
...@@ -21,6 +21,11 @@ static inline void reset_sprs(void) ...@@ -21,6 +21,11 @@ static inline void reset_sprs(void)
plpar_set_ciabr(0); plpar_set_ciabr(0);
} }
if (cpu_has_feature(CPU_FTR_ARCH_31)) {
mtspr(SPRN_DEXCR, 0);
mtspr(SPRN_HASHKEYR, 0);
}
/* Do we need isync()? We are going via a kexec reset */ /* Do we need isync()? We are going via a kexec reset */
isync(); isync();
} }
......
...@@ -192,6 +192,7 @@ static inline void cpu_feature_keys_init(void) { } ...@@ -192,6 +192,7 @@ static inline void cpu_feature_keys_init(void) { }
#define CPU_FTR_P9_RADIX_PREFETCH_BUG LONG_ASM_CONST(0x0002000000000000) #define CPU_FTR_P9_RADIX_PREFETCH_BUG LONG_ASM_CONST(0x0002000000000000)
#define CPU_FTR_ARCH_31 LONG_ASM_CONST(0x0004000000000000) #define CPU_FTR_ARCH_31 LONG_ASM_CONST(0x0004000000000000)
#define CPU_FTR_DAWR1 LONG_ASM_CONST(0x0008000000000000) #define CPU_FTR_DAWR1 LONG_ASM_CONST(0x0008000000000000)
#define CPU_FTR_DEXCR_NPHIE LONG_ASM_CONST(0x0010000000000000)
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
...@@ -451,7 +452,8 @@ static inline void cpu_feature_keys_init(void) { } ...@@ -451,7 +452,8 @@ static inline void cpu_feature_keys_init(void) { }
CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \ CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \
CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_ARCH_207S | \ CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_ARCH_207S | \
CPU_FTR_ARCH_300 | CPU_FTR_ARCH_31 | \ CPU_FTR_ARCH_300 | CPU_FTR_ARCH_31 | \
CPU_FTR_DAWR | CPU_FTR_DAWR1) CPU_FTR_DAWR | CPU_FTR_DAWR1 | \
CPU_FTR_DEXCR_NPHIE)
#define CPU_FTRS_CELL (CPU_FTR_LWSYNC | \ #define CPU_FTRS_CELL (CPU_FTR_LWSYNC | \
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
......
...@@ -382,7 +382,17 @@ ...@@ -382,7 +382,17 @@
#define SPRN_HIOR 0x137 /* 970 Hypervisor interrupt offset */ #define SPRN_HIOR 0x137 /* 970 Hypervisor interrupt offset */
#define SPRN_RMOR 0x138 /* Real mode offset register */ #define SPRN_RMOR 0x138 /* Real mode offset register */
#define SPRN_HRMOR 0x139 /* Real mode offset register */ #define SPRN_HRMOR 0x139 /* Real mode offset register */
#define SPRN_HDEXCR_RO 0x1C7 /* Hypervisor DEXCR (non-privileged, readonly) */
#define SPRN_HASHKEYR 0x1D4 /* Non-privileged hashst/hashchk key register */
#define SPRN_HDEXCR 0x1D7 /* Hypervisor dynamic execution control register */
#define SPRN_DEXCR_RO 0x32C /* DEXCR (non-privileged, readonly) */
#define SPRN_ASDR 0x330 /* Access segment descriptor register */ #define SPRN_ASDR 0x330 /* Access segment descriptor register */
#define SPRN_DEXCR 0x33C /* Dynamic execution control register */
#define DEXCR_PR_SBHE 0x80000000UL /* 0: Speculative Branch Hint Enable */
#define DEXCR_PR_IBRTPD 0x10000000UL /* 3: Indirect Branch Recurrent Target Prediction Disable */
#define DEXCR_PR_SRAPD 0x08000000UL /* 4: Subroutine Return Address Prediction Disable */
#define DEXCR_PR_NPHIE 0x04000000UL /* 5: Non-Privileged Hash Instruction Enable */
#define DEXCR_INIT DEXCR_PR_NPHIE /* Fixed DEXCR value to initialise all CPUs with */
#define SPRN_IC 0x350 /* Virtual Instruction Count */ #define SPRN_IC 0x350 /* Virtual Instruction Count */
#define SPRN_VTB 0x351 /* Virtual Time Base */ #define SPRN_VTB 0x351 /* Virtual Time Base */
#define SPRN_LDBAR 0x352 /* LD Base Address Register */ #define SPRN_LDBAR 0x352 /* LD Base Address Register */
......
...@@ -126,6 +126,12 @@ static void init_PMU_ISA31(void) ...@@ -126,6 +126,12 @@ static void init_PMU_ISA31(void)
mtspr(SPRN_MMCR0, MMCR0_FC | MMCR0_PMCCEXT); mtspr(SPRN_MMCR0, MMCR0_FC | MMCR0_PMCCEXT);
} }
static void init_DEXCR(void)
{
mtspr(SPRN_DEXCR, DEXCR_INIT);
mtspr(SPRN_HASHKEYR, 0);
}
/* /*
* Note that we can be called twice of pseudo-PVRs. * Note that we can be called twice of pseudo-PVRs.
* The parameter offset is not used. * The parameter offset is not used.
...@@ -241,6 +247,7 @@ void __setup_cpu_power10(unsigned long offset, struct cpu_spec *t) ...@@ -241,6 +247,7 @@ void __setup_cpu_power10(unsigned long offset, struct cpu_spec *t)
init_FSCR_power10(); init_FSCR_power10();
init_PMU(); init_PMU();
init_PMU_ISA31(); init_PMU_ISA31();
init_DEXCR();
if (!init_hvmode_206(t)) if (!init_hvmode_206(t))
return; return;
...@@ -263,6 +270,7 @@ void __restore_cpu_power10(void) ...@@ -263,6 +270,7 @@ void __restore_cpu_power10(void)
init_FSCR_power10(); init_FSCR_power10();
init_PMU(); init_PMU();
init_PMU_ISA31(); init_PMU_ISA31();
init_DEXCR();
msr = mfmsr(); msr = mfmsr();
if (!(msr & MSR_HV)) if (!(msr & MSR_HV))
......
...@@ -182,6 +182,7 @@ static struct ibm_feature ibm_pa_features[] __initdata = { ...@@ -182,6 +182,7 @@ static struct ibm_feature ibm_pa_features[] __initdata = {
.cpu_user_ftrs2 = PPC_FEATURE2_HTM_COMP | PPC_FEATURE2_HTM_NOSC_COMP }, .cpu_user_ftrs2 = PPC_FEATURE2_HTM_COMP | PPC_FEATURE2_HTM_NOSC_COMP },
{ .pabyte = 64, .pabit = 0, .cpu_features = CPU_FTR_DAWR1 }, { .pabyte = 64, .pabit = 0, .cpu_features = CPU_FTR_DAWR1 },
{ .pabyte = 68, .pabit = 5, .cpu_features = CPU_FTR_DEXCR_NPHIE },
}; };
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment