powerpc/dexcr: Add initial Dynamic Execution Control Register (DEXCR) support
authorBenjamin Gray <bgray@linux.ibm.com>
Mon, 19 Jun 2023 07:36:25 +0000 (17:36 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Mon, 19 Jun 2023 07:36:25 +0000 (17:36 +1000)
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: Benjamin Gray <bgray@linux.ibm.com>
[mpe: Use simple values for DEXCR constants]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20230616034846.311705-4-bgray@linux.ibm.com
arch/powerpc/include/asm/book3s/64/kexec.h
arch/powerpc/include/asm/cputable.h
arch/powerpc/include/asm/reg.h
arch/powerpc/kernel/cpu_setup_power.c
arch/powerpc/kernel/prom.c

index d4b9d476ecba272eafbd9e94edcdb4e24ede18d0..df37a76c1e9f3286f6468fc4dc44ed3fa1f17e17 100644 (file)
@@ -21,6 +21,11 @@ static inline void reset_sprs(void)
                        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 */
        isync();
 }
index 757dbded11dcfa3c9de381cb10ee49821091f5ba..443a9d482b1524f6b9ee815284e5a76d41b95b96 100644 (file)
@@ -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_ARCH_31                        LONG_ASM_CONST(0x0004000000000000)
 #define CPU_FTR_DAWR1                  LONG_ASM_CONST(0x0008000000000000)
+#define CPU_FTR_DEXCR_NPHIE            LONG_ASM_CONST(0x0010000000000000)
 
 #ifndef __ASSEMBLY__
 
@@ -451,7 +452,8 @@ static inline void cpu_feature_keys_init(void) { }
            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_DAWR | CPU_FTR_DAWR1)
+           CPU_FTR_DAWR | CPU_FTR_DAWR1 | \
+           CPU_FTR_DEXCR_NPHIE)
 #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 | \
index 6372e5f55ef02bffabfc3a31f35c074ac9961dc0..bb0121222ee3c4ef4939c64e977cc80a8a77cb3d 100644 (file)
 #define SPRN_HIOR      0x137   /* 970 Hypervisor interrupt offset */
 #define SPRN_RMOR      0x138   /* 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_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_VTB       0x351   /* Virtual Time Base */
 #define SPRN_LDBAR     0x352   /* LD Base Address Register */
index 097c033668f0faee68f3a9d3410137142a778e53..98bd4e6c1770523c4062ff436fb8f90c620ad739 100644 (file)
@@ -126,6 +126,12 @@ static void init_PMU_ISA31(void)
        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.
  * The parameter offset is not used.
@@ -241,6 +247,7 @@ void __setup_cpu_power10(unsigned long offset, struct cpu_spec *t)
        init_FSCR_power10();
        init_PMU();
        init_PMU_ISA31();
+       init_DEXCR();
 
        if (!init_hvmode_206(t))
                return;
@@ -263,6 +270,7 @@ void __restore_cpu_power10(void)
        init_FSCR_power10();
        init_PMU();
        init_PMU_ISA31();
+       init_DEXCR();
 
        msr = mfmsr();
        if (!(msr & MSR_HV))
index 9d9ee4e9e1a1bd79599f20d09a31e0f69046cdc5..0b5878c3125b1cd67ff3f44cedf83d514478c262 100644 (file)
@@ -182,6 +182,7 @@ static struct ibm_feature ibm_pa_features[] __initdata = {
          .cpu_user_ftrs2 = PPC_FEATURE2_HTM_COMP | PPC_FEATURE2_HTM_NOSC_COMP },
 
        { .pabyte = 64, .pabit = 0, .cpu_features = CPU_FTR_DAWR1 },
+       { .pabyte = 68, .pabit = 5, .cpu_features = CPU_FTR_DEXCR_NPHIE },
 };
 
 /*