* [RFC PATCH 1/6] powerpc/dexcr: Make all aspects CPU features
2023-10-09 5:54 [RFC PATCH 0/6] Add dynamic DEXCR support Benjamin Gray
@ 2023-10-09 5:54 ` Benjamin Gray
2023-10-09 5:54 ` [RFC PATCH 2/6] powerpc/dexcr: Add thread specific DEXCR configuration Benjamin Gray
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Benjamin Gray @ 2023-10-09 5:54 UTC (permalink / raw)
To: linuxppc-dev; +Cc: ajd, npiggin, Benjamin Gray
The CPU_FEATURE_* mechanism is the only way right now to get
configuration from the "ibm,pa-features" devicetree node. Add a
CPU_FEATURE_* entry for each other DEXCR aspect that will be
exposed to userspace.
The NPHIE feature value is changed for consistency; the actual value is
never accessed or exposed to userspace, so there is no breakage.
Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
arch/powerpc/include/asm/cputable.h | 6 +++++-
arch/powerpc/kernel/prom.c | 3 +++
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 8765d5158324..bd087d0cb5fa 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -192,7 +192,10 @@ 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)
+#define CPU_FTR_DEXCR_SBHE LONG_ASM_CONST(0x0010000000000000)
+#define CPU_FTR_DEXCR_IBRTPD LONG_ASM_CONST(0x0020000000000000)
+#define CPU_FTR_DEXCR_SRAPD LONG_ASM_CONST(0x0040000000000000)
+#define CPU_FTR_DEXCR_NPHIE LONG_ASM_CONST(0x0080000000000000)
#ifndef __ASSEMBLY__
@@ -453,6 +456,7 @@ static inline void cpu_feature_keys_init(void) { }
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_DEXCR_SBHE | CPU_FTR_DEXCR_IBRTPD | CPU_FTR_DEXCR_SRAPD | \
CPU_FTR_DEXCR_NPHIE)
#define CPU_FTRS_CELL (CPU_FTR_LWSYNC | \
CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 0b5878c3125b..ea081a5d2023 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -182,6 +182,9 @@ 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 = 0, .cpu_features = CPU_FTR_DEXCR_SBHE },
+ { .pabyte = 68, .pabit = 3, .cpu_features = CPU_FTR_DEXCR_IBRTPD },
+ { .pabyte = 68, .pabit = 4, .cpu_features = CPU_FTR_DEXCR_SRAPD },
{ .pabyte = 68, .pabit = 5, .cpu_features = CPU_FTR_DEXCR_NPHIE },
};
--
2.41.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [RFC PATCH 2/6] powerpc/dexcr: Add thread specific DEXCR configuration
2023-10-09 5:54 [RFC PATCH 0/6] Add dynamic DEXCR support Benjamin Gray
2023-10-09 5:54 ` [RFC PATCH 1/6] powerpc/dexcr: Make all aspects CPU features Benjamin Gray
@ 2023-10-09 5:54 ` Benjamin Gray
2023-10-09 5:54 ` [RFC PATCH 3/6] prctl: Define PowerPC DEXCR interface Benjamin Gray
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Benjamin Gray @ 2023-10-09 5:54 UTC (permalink / raw)
To: linuxppc-dev; +Cc: ajd, npiggin, Benjamin Gray
Add capability to track a DEXCR value per thread.
Nothing actually changes these values yet, but they are correctly
tracked, propagated, and used to set the hardware register.
Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
arch/powerpc/include/asm/processor.h | 12 ++++++++++++
arch/powerpc/kernel/process.c | 24 ++++++++++++++++++++++++
2 files changed, 36 insertions(+)
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index b2c51d337e60..28a72023f9bd 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -260,6 +260,9 @@ struct thread_struct {
unsigned long sier2;
unsigned long sier3;
unsigned long hashkeyr;
+ unsigned int dexcr; /* Temporary value saved during thread switch */
+ unsigned int dexcr_enabled; /* Bitmask of aspects enabled by this thread */
+ unsigned int dexcr_inherit; /* Bitmask of aspects to inherit across exec */
#endif
};
@@ -448,6 +451,15 @@ int exit_vmx_usercopy(void);
int enter_vmx_ops(void);
void *exit_vmx_ops(void *dest);
+static inline unsigned long get_thread_dexcr(struct thread_struct const *thread)
+{
+#ifdef CONFIG_PPC_BOOK3S_64
+ return thread->dexcr_enabled;
+#else
+ return 0;
+#endif
+}
+
#endif /* __KERNEL__ */
#endif /* __ASSEMBLY__ */
#endif /* _ASM_POWERPC_PROCESSOR_H */
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index b68898ac07e1..c05d58b7c6b3 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1185,6 +1185,9 @@ static inline void save_sprs(struct thread_struct *t)
if (cpu_has_feature(CPU_FTR_DEXCR_NPHIE))
t->hashkeyr = mfspr(SPRN_HASHKEYR);
+
+ if (cpu_has_feature(CPU_FTR_ARCH_31))
+ t->dexcr = mfspr(SPRN_DEXCR);
#endif
}
@@ -1267,6 +1270,10 @@ static inline void restore_sprs(struct thread_struct *old_thread,
if (cpu_has_feature(CPU_FTR_DEXCR_NPHIE) &&
old_thread->hashkeyr != new_thread->hashkeyr)
mtspr(SPRN_HASHKEYR, new_thread->hashkeyr);
+
+ if (cpu_has_feature(CPU_FTR_ARCH_31) &&
+ old_thread->dexcr != get_thread_dexcr(new_thread))
+ mtspr(SPRN_DEXCR, get_thread_dexcr(new_thread));
#endif
}
@@ -1634,6 +1641,11 @@ void arch_setup_new_exec(void)
current->thread.regs->amr = default_amr;
current->thread.regs->iamr = default_iamr;
#endif
+
+#ifdef CONFIG_PPC_BOOK3S_64
+ current->thread.dexcr_enabled &= current->thread.dexcr_inherit;
+ current->thread.dexcr_enabled |= ~current->thread.dexcr_inherit & DEXCR_INIT;
+#endif
}
#ifdef CONFIG_PPC64
@@ -1878,6 +1890,11 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
#ifdef CONFIG_PPC_BOOK3S_64
if (cpu_has_feature(CPU_FTR_DEXCR_NPHIE))
p->thread.hashkeyr = current->thread.hashkeyr;
+
+ if (cpu_has_feature(CPU_FTR_ARCH_31)) {
+ p->thread.dexcr_enabled = current->thread.dexcr_enabled;
+ p->thread.dexcr_inherit = current->thread.dexcr_inherit;
+ }
#endif
return 0;
}
@@ -2000,6 +2017,13 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
current->thread.hashkeyr = get_random_long();
mtspr(SPRN_HASHKEYR, current->thread.hashkeyr);
}
+
+ if (cpu_has_feature(CPU_FTR_ARCH_31)) {
+ current->thread.dexcr = 0;
+ current->thread.dexcr_enabled = DEXCR_INIT;
+ current->thread.dexcr_inherit = 0;
+ mtspr(SPRN_DEXCR, get_thread_dexcr(¤t->thread));
+ }
#endif /* CONFIG_PPC_BOOK3S_64 */
}
EXPORT_SYMBOL(start_thread);
--
2.41.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [RFC PATCH 3/6] prctl: Define PowerPC DEXCR interface
2023-10-09 5:54 [RFC PATCH 0/6] Add dynamic DEXCR support Benjamin Gray
2023-10-09 5:54 ` [RFC PATCH 1/6] powerpc/dexcr: Make all aspects CPU features Benjamin Gray
2023-10-09 5:54 ` [RFC PATCH 2/6] powerpc/dexcr: Add thread specific DEXCR configuration Benjamin Gray
@ 2023-10-09 5:54 ` Benjamin Gray
2023-10-09 5:54 ` [RFC PATCH 4/6] powerpc/dexcr: Add prctl implementation Benjamin Gray
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Benjamin Gray @ 2023-10-09 5:54 UTC (permalink / raw)
To: linuxppc-dev; +Cc: ajd, npiggin, Benjamin Gray
Adds the definitions and generic handler for prctl control of the
PowerPC Dynamic Execution Control Register (DEXCR).
Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
include/uapi/linux/prctl.h | 13 +++++++++++++
kernel/sys.c | 16 ++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index 3c36aeade991..85d66ad134b1 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -305,4 +305,17 @@ struct prctl_mm_map {
# define PR_RISCV_V_VSTATE_CTRL_NEXT_MASK 0xc
# define PR_RISCV_V_VSTATE_CTRL_MASK 0x1f
+/* PowerPC Dynamic Execution Control Register (DEXCR) controls */
+#define PR_PPC_GET_DEXCR 71
+#define PR_PPC_SET_DEXCR 72
+/* DEXCR aspect to act on */
+# define PR_PPC_DEXCR_SBHE 0 /* Speculative branch hint enable */
+# define PR_PPC_DEXCR_IBRTPD 1 /* Indirect branch recurrent target prediction disable */
+# define PR_PPC_DEXCR_SRAPD 2 /* Subroutine return address prediction disable */
+# define PR_PPC_DEXCR_NPHIE 3 /* Non-privileged hash instruction enable */
+/* Action to apply / return */
+# define PR_PPC_DEXCR_CTRL_OFF (1UL << 0)
+# define PR_PPC_DEXCR_CTRL_ON (1UL << 1)
+# define PR_PPC_DEXCR_CTRL_INHERIT (1UL << 2)
+
#endif /* _LINUX_PRCTL_H */
diff --git a/kernel/sys.c b/kernel/sys.c
index 2410e3999ebe..0c1b8e9c3d16 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -146,6 +146,12 @@
#ifndef RISCV_V_GET_CONTROL
# define RISCV_V_GET_CONTROL() (-EINVAL)
#endif
+#ifndef PPC_GET_DEXCR_ASPECT
+# define PPC_GET_DEXCR_ASPECT(a, b) (-EINVAL)
+#endif
+#ifndef PPC_SET_DEXCR_ASPECT
+# define PPC_SET_DEXCR_ASPECT(a, b, c) (-EINVAL)
+#endif
/*
* this is where the system-wide overflow UID and GID are defined, for
@@ -2686,6 +2692,16 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
case PR_GET_MDWE:
error = prctl_get_mdwe(arg2, arg3, arg4, arg5);
break;
+ case PR_PPC_GET_DEXCR:
+ if (arg3 || arg4 || arg5)
+ return -EINVAL;
+ error = PPC_GET_DEXCR_ASPECT(me, arg2);
+ break;
+ case PR_PPC_SET_DEXCR:
+ if (arg4 || arg5)
+ return -EINVAL;
+ error = PPC_SET_DEXCR_ASPECT(me, arg2, arg3);
+ break;
case PR_SET_VMA:
error = prctl_set_vma(arg2, arg3, arg4, arg5);
break;
--
2.41.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [RFC PATCH 4/6] powerpc/dexcr: Add prctl implementation
2023-10-09 5:54 [RFC PATCH 0/6] Add dynamic DEXCR support Benjamin Gray
` (2 preceding siblings ...)
2023-10-09 5:54 ` [RFC PATCH 3/6] prctl: Define PowerPC DEXCR interface Benjamin Gray
@ 2023-10-09 5:54 ` Benjamin Gray
2023-10-09 5:54 ` [RFC PATCH 5/6] powerpc/dexcr: Add sysctl entry for SBHE system override Benjamin Gray
2023-10-09 5:54 ` [RFC PATCH 6/6] powerpc/dexcr: Add enforced userspace ROP protection config Benjamin Gray
5 siblings, 0 replies; 7+ messages in thread
From: Benjamin Gray @ 2023-10-09 5:54 UTC (permalink / raw)
To: linuxppc-dev; +Cc: ajd, npiggin, Benjamin Gray
Adds an initial prctl interface implementation. Unprivileged processes
can query the current prctl setting, including whether an aspect is
implemented by the hardware or is permitted to be modified by a setter
prctl. Editable aspects can be changed by a CAP_SYS_ADMIN privileged
process.
The prctl setting represents what the process itself has requested, and
does not account for any overrides. Either the kernel or a hypervisor
may enforce a different setting for an aspect.
Userspace can access a readonly view of the current DEXCR via SPR 812,
and a readonly view of the aspects enforced by the hypervisor via
SPR 455. A bitwise OR of these two SPRs will give the effective
DEXCR aspect state of the process.
Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
arch/powerpc/include/asm/processor.h | 10 +++
arch/powerpc/kernel/Makefile | 1 +
arch/powerpc/kernel/dexcr.c | 128 +++++++++++++++++++++++++++
3 files changed, 139 insertions(+)
create mode 100644 arch/powerpc/kernel/dexcr.c
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index 28a72023f9bd..a9d83621dfad 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -336,6 +336,16 @@ extern int set_endian(struct task_struct *tsk, unsigned int val);
extern int get_unalign_ctl(struct task_struct *tsk, unsigned long adr);
extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val);
+#ifdef CONFIG_PPC_BOOK3S_64
+
+#define PPC_GET_DEXCR_ASPECT(tsk, asp) get_dexcr_prctl((tsk), (asp))
+#define PPC_SET_DEXCR_ASPECT(tsk, asp, val) set_dexcr_prctl((tsk), (asp), (val))
+
+int get_dexcr_prctl(struct task_struct *tsk, unsigned long asp);
+int set_dexcr_prctl(struct task_struct *tsk, unsigned long asp, unsigned long val);
+
+#endif
+
extern void load_fp_state(struct thread_fp_state *fp);
extern void store_fp_state(struct thread_fp_state *fp);
extern void load_vr_state(struct thread_vr_state *vr);
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 2919433be355..24f82b09246c 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -88,6 +88,7 @@ obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
obj-$(CONFIG_PPC_DAWR) += dawr.o
obj-$(CONFIG_PPC_BOOK3S_64) += cpu_setup_ppc970.o cpu_setup_pa6t.o
obj-$(CONFIG_PPC_BOOK3S_64) += cpu_setup_power.o
+obj-$(CONFIG_PPC_BOOK3S_64) += dexcr.o
obj-$(CONFIG_PPC_BOOK3S_64) += mce.o mce_power.o
obj-$(CONFIG_PPC_BOOK3E_64) += exceptions-64e.o idle_64e.o
obj-$(CONFIG_PPC_BARRIER_NOSPEC) += security.o
diff --git a/arch/powerpc/kernel/dexcr.c b/arch/powerpc/kernel/dexcr.c
new file mode 100644
index 000000000000..db663ce7b3ce
--- /dev/null
+++ b/arch/powerpc/kernel/dexcr.c
@@ -0,0 +1,128 @@
+#include <linux/capability.h>
+#include <linux/init.h>
+#include <linux/prctl.h>
+#include <linux/sched.h>
+
+#include <asm/cpu_has_feature.h>
+#include <asm/cputable.h>
+#include <asm/processor.h>
+#include <asm/reg.h>
+
+/* Allow thread local configuration of these by default */
+#define DEXCR_PRCTL_EDITABLE ( \
+ DEXCR_PR_IBRTPD | \
+ DEXCR_PR_SRAPD | \
+ DEXCR_PR_NPHIE)
+
+static unsigned long dexcr_supported __ro_after_init = 0;
+
+static int __init dexcr_init(void)
+{
+ if (!early_cpu_has_feature(CPU_FTR_ARCH_31))
+ return 0;
+
+ if (early_cpu_has_feature(CPU_FTR_DEXCR_SBHE))
+ dexcr_supported |= DEXCR_PR_SBHE;
+
+ if (early_cpu_has_feature(CPU_FTR_DEXCR_IBRTPD))
+ dexcr_supported |= DEXCR_PR_IBRTPD;
+
+ if (early_cpu_has_feature(CPU_FTR_DEXCR_SRAPD))
+ dexcr_supported |= DEXCR_PR_SRAPD;
+
+ if (early_cpu_has_feature(CPU_FTR_DEXCR_NPHIE))
+ dexcr_supported |= DEXCR_PR_NPHIE;
+
+ return 0;
+}
+early_initcall(dexcr_init);
+
+static int prctl_to_aspect(unsigned long which, unsigned int *aspect)
+{
+ switch (which) {
+ case PR_PPC_DEXCR_SBHE:
+ *aspect = DEXCR_PR_SBHE;
+ break;
+ case PR_PPC_DEXCR_IBRTPD:
+ *aspect = DEXCR_PR_IBRTPD;
+ break;
+ case PR_PPC_DEXCR_SRAPD:
+ *aspect = DEXCR_PR_SRAPD;
+ break;
+ case PR_PPC_DEXCR_NPHIE:
+ *aspect = DEXCR_PR_NPHIE;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+int get_dexcr_prctl(struct task_struct *task, unsigned long which)
+{
+ unsigned int aspect;
+ int ret;
+
+ ret = prctl_to_aspect(which, &aspect);
+ if (ret)
+ return ret;
+
+ if (!(aspect & dexcr_supported))
+ return -ENODEV;
+
+ if (aspect & task->thread.dexcr_enabled)
+ ret |= PR_PPC_DEXCR_CTRL_ON;
+ else
+ ret |= PR_PPC_DEXCR_CTRL_OFF;
+
+ if (aspect & task->thread.dexcr_inherit)
+ ret |= PR_PPC_DEXCR_CTRL_INHERIT;
+
+ return ret;
+}
+
+int set_dexcr_prctl(struct task_struct *task, unsigned long which, unsigned long ctrl)
+{
+ unsigned int aspect;
+ unsigned long enable;
+ unsigned long disable;
+ unsigned long inherit;
+ int err = 0;
+
+ /* We do not want an unprivileged process being able to set a value that a setuid process may inherit (particularly for NPHIE) */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ err = prctl_to_aspect(which, &aspect);
+ if (err)
+ return err;
+
+ if (!(aspect & dexcr_supported))
+ return -ENODEV;
+
+ enable = ctrl & PR_PPC_DEXCR_CTRL_ON;
+ disable = ctrl & PR_PPC_DEXCR_CTRL_OFF;
+ inherit = ctrl & PR_PPC_DEXCR_CTRL_INHERIT;
+ ctrl &= ~(PR_PPC_DEXCR_CTRL_ON | PR_PPC_DEXCR_CTRL_OFF | PR_PPC_DEXCR_CTRL_INHERIT);
+
+ if (ctrl)
+ return -EINVAL;
+
+ if ((enable && disable) || !(enable || disable))
+ return -EINVAL;
+
+ if (enable)
+ task->thread.dexcr_enabled |= aspect;
+ else
+ task->thread.dexcr_enabled &= ~aspect;
+
+ if (inherit)
+ task->thread.dexcr_inherit |= aspect;
+ else
+ task->thread.dexcr_inherit &= ~aspect;
+
+ mtspr(SPRN_DEXCR, get_thread_dexcr(¤t->thread));
+
+ return 0;
+}
--
2.41.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [RFC PATCH 5/6] powerpc/dexcr: Add sysctl entry for SBHE system override
2023-10-09 5:54 [RFC PATCH 0/6] Add dynamic DEXCR support Benjamin Gray
` (3 preceding siblings ...)
2023-10-09 5:54 ` [RFC PATCH 4/6] powerpc/dexcr: Add prctl implementation Benjamin Gray
@ 2023-10-09 5:54 ` Benjamin Gray
2023-10-09 5:54 ` [RFC PATCH 6/6] powerpc/dexcr: Add enforced userspace ROP protection config Benjamin Gray
5 siblings, 0 replies; 7+ messages in thread
From: Benjamin Gray @ 2023-10-09 5:54 UTC (permalink / raw)
To: linuxppc-dev; +Cc: ajd, npiggin, Benjamin Gray
The DEXCR Speculative Branch Hint Enable (SBHE) aspect controls whether
the hints provided by BO field of Branch instructions are obeyed during
speculative execution.
SBHE behaviour per ISA 3.1B:
0: The hints provided by BO field of Branch instructions may be
ignored during speculative execution
1: The hints provided by BO field of Branch instructions are obeyed
during speculative execution
Add a sysctl entry to allow changing this aspect globally in the system
at runtime:
/proc/sys/kernel/speculative_branch_hint_enable
Three values are supported:
-1: Disable DEXCR SBHE sysctl override
0: Override and set DEXCR[SBHE] aspect to 0
1: Override and set DEXCR[SBHE] aspect to 1
Internally, introduces a mechanism to apply arbitrary system wide
overrides on top of the prctl() config.
Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
arch/powerpc/include/asm/processor.h | 8 +--
arch/powerpc/kernel/dexcr.c | 85 ++++++++++++++++++++++++++++
2 files changed, 89 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
index a9d83621dfad..e7b732efb968 100644
--- a/arch/powerpc/include/asm/processor.h
+++ b/arch/powerpc/include/asm/processor.h
@@ -461,14 +461,14 @@ int exit_vmx_usercopy(void);
int enter_vmx_ops(void);
void *exit_vmx_ops(void *dest);
-static inline unsigned long get_thread_dexcr(struct thread_struct const *thread)
-{
#ifdef CONFIG_PPC_BOOK3S_64
- return thread->dexcr_enabled;
+unsigned long get_thread_dexcr(struct thread_struct const *thread);
#else
+static inline unsigned long get_thread_dexcr(struct thread_struct const *thread)
+{
return 0;
-#endif
}
+#endif
#endif /* __KERNEL__ */
#endif /* __ASSEMBLY__ */
diff --git a/arch/powerpc/kernel/dexcr.c b/arch/powerpc/kernel/dexcr.c
index db663ce7b3ce..e790f76787db 100644
--- a/arch/powerpc/kernel/dexcr.c
+++ b/arch/powerpc/kernel/dexcr.c
@@ -1,7 +1,9 @@
#include <linux/capability.h>
+#include <linux/cpu.h>
#include <linux/init.h>
#include <linux/prctl.h>
#include <linux/sched.h>
+#include <linux/sysctl.h>
#include <asm/cpu_has_feature.h>
#include <asm/cputable.h>
@@ -16,6 +18,8 @@
static unsigned long dexcr_supported __ro_after_init = 0;
+static int spec_branch_hint_enable = -1;
+
static int __init dexcr_init(void)
{
if (!early_cpu_has_feature(CPU_FTR_ARCH_31))
@@ -37,6 +41,35 @@ static int __init dexcr_init(void)
}
early_initcall(dexcr_init);
+unsigned long get_thread_dexcr(struct thread_struct const *thread)
+{
+ unsigned long dexcr = thread->dexcr_enabled;
+
+ /*
+ * spec_branch_hint_enable may be written to concurrently via sysctl.
+ * The sysctl handler is careful to use WRITE_ONCE, so we avoid
+ * tearing/different values with READ_ONCE
+ */
+ switch (READ_ONCE(spec_branch_hint_enable)) {
+ case 0:
+ dexcr &= ~DEXCR_PR_SBHE;
+ break;
+ case 1:
+ dexcr |= DEXCR_PR_SBHE;
+ break;
+ }
+
+ return dexcr;
+}
+
+static void update_dexcr_on_cpu(void *_info)
+{
+ /* ensure the spec_branch_hint_enable write propagated to this CPU */
+ smp_mb();
+
+ mtspr(SPRN_DEXCR, get_thread_dexcr(¤t->thread));
+}
+
static int prctl_to_aspect(unsigned long which, unsigned int *aspect)
{
switch (which) {
@@ -126,3 +159,55 @@ int set_dexcr_prctl(struct task_struct *task, unsigned long which, unsigned long
return 0;
}
+
+#ifdef CONFIG_SYSCTL
+
+static const int min_sysctl_val = -1;
+
+static int sysctl_dexcr_sbhe_handler(struct ctl_table *table, int write,
+ void *buf, size_t *lenp, loff_t *ppos)
+{
+ int err = 0;
+ int prev;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ if (!cpu_has_feature(CPU_FTR_DEXCR_SBHE))
+ return -ENODEV;
+
+ prev = READ_ONCE(spec_branch_hint_enable);
+
+ err = proc_dointvec_minmax(table, write, buf, lenp, ppos);
+ if (err)
+ return err;
+
+ if (spec_branch_hint_enable != prev && write)
+ on_each_cpu(update_dexcr_on_cpu, NULL, 1);
+
+ return 0;
+}
+
+static struct ctl_table dexcr_sbhe_ctl_table[] = {
+ {
+ .procname = "speculative_branch_hint_enable",
+ .data = &spec_branch_hint_enable,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = sysctl_dexcr_sbhe_handler,
+ .extra1 = (void *)&min_sysctl_val,
+ .extra2 = SYSCTL_ONE,
+ }
+};
+
+static int __init register_dexcr_aspects_sysctl(void)
+{
+ if (!early_cpu_has_feature(CPU_FTR_DEXCR_SBHE))
+ return -ENODEV;
+
+ register_sysctl("kernel", dexcr_sbhe_ctl_table);
+ return 0;
+}
+device_initcall(register_dexcr_aspects_sysctl);
+
+#endif /* CONFIG_SYSCTL */
--
2.41.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* [RFC PATCH 6/6] powerpc/dexcr: Add enforced userspace ROP protection config
2023-10-09 5:54 [RFC PATCH 0/6] Add dynamic DEXCR support Benjamin Gray
` (4 preceding siblings ...)
2023-10-09 5:54 ` [RFC PATCH 5/6] powerpc/dexcr: Add sysctl entry for SBHE system override Benjamin Gray
@ 2023-10-09 5:54 ` Benjamin Gray
5 siblings, 0 replies; 7+ messages in thread
From: Benjamin Gray @ 2023-10-09 5:54 UTC (permalink / raw)
To: linuxppc-dev; +Cc: ajd, npiggin, Benjamin Gray
The DEXCR Non-Privileged Hash Instruction Enable (NPHIE) aspect controls
whether the hashst and hashchk instructions are treated as no-ops by the
CPU.
NPHIE behaviour per ISA 3.1B:
0: hashst and hashchk instructions are executed as no-ops
(even when allowed by PCR)
1: hashst and hashchk instructions are executed normally
(if allowed by PCR)
Currently this aspect may be set per-process by prctl() or enforced
globally by the hypervisor.
Add a kernel config option PPC_USER_ENFORCE_ROP_PROTECT to enforce
DEXCR[NPHIE] globally regardless of prctl() or hypervisor. If set, don't
report NPHIE as editable via prctl(), as the prctl() value can never
take effect.
Signed-off-by: Benjamin Gray <bgray@linux.ibm.com>
---
arch/powerpc/Kconfig | 5 +++++
arch/powerpc/kernel/dexcr.c | 7 ++++++-
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 3aaadfd2c8eb..4851cb463dc0 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -473,6 +473,11 @@ config PGTABLE_LEVELS
default 2 if !PPC64
default 4
+config PPC_USER_ENFORCE_ROP_PROTECT
+ bool
+ depends on PPC_BOOK3S_64
+ default y
+
source "arch/powerpc/sysdev/Kconfig"
source "arch/powerpc/platforms/Kconfig"
diff --git a/arch/powerpc/kernel/dexcr.c b/arch/powerpc/kernel/dexcr.c
index e790f76787db..01d8fa28ca17 100644
--- a/arch/powerpc/kernel/dexcr.c
+++ b/arch/powerpc/kernel/dexcr.c
@@ -1,6 +1,8 @@
+#include <linux/cache.h>
#include <linux/capability.h>
#include <linux/cpu.h>
#include <linux/init.h>
+#include <linux/kconfig.h>
#include <linux/prctl.h>
#include <linux/sched.h>
#include <linux/sysctl.h>
@@ -14,7 +16,7 @@
#define DEXCR_PRCTL_EDITABLE ( \
DEXCR_PR_IBRTPD | \
DEXCR_PR_SRAPD | \
- DEXCR_PR_NPHIE)
+ (!IS_ENABLED(CONFIG_PPC_USER_ENFORCE_ROP_PROTECT) ? DEXCR_PR_NPHIE : 0))
static unsigned long dexcr_supported __ro_after_init = 0;
@@ -45,6 +47,9 @@ unsigned long get_thread_dexcr(struct thread_struct const *thread)
{
unsigned long dexcr = thread->dexcr_enabled;
+ if (IS_ENABLED(CONFIG_PPC_USER_ENFORCE_ROP_PROTECT))
+ dexcr |= DEXCR_PR_NPHIE;
+
/*
* spec_branch_hint_enable may be written to concurrently via sysctl.
* The sysctl handler is careful to use WRITE_ONCE, so we avoid
--
2.41.0
^ permalink raw reply related [flat|nested] 7+ messages in thread