Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions Documentation/arch/riscv/vector.rst
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,30 @@ processes in form of sysctl knob:
3. Vector Register State Across System Calls
---------------------------------------------

As indicated by version 1.0 of the V extension [1], vector registers are
clobbered by system calls.
Linux adopts the syscall ABI proposed by version 1.0 of the V extension [1],
where vector registers are clobbered by system calls. Specifically:

Executing a system call causes all caller-saved vector registers
(v0-v31, vl, vtype) and vstart to become unspecified.

Linux clobbers the vector registers (e.g. discards vector state) on the syscall
entry path. This is done to identify userspace programs that mistakenly expect
vector registers to be preserved across syscalls. This can be helpful for
debugging and testing. However, clobbering vector state can negatively impact
performance on some RISC-V implementations, and is not strictly necessary.

To mitigate this performance impact, a sysctl knob is provided that controls
whether vector state is always clobbered on syscall entry:

* /proc/sys/abi/riscv_v_vstate_discard

Valid values are:

* 0: Vector state is not always clobbered in all syscalls
* 1: Mandatory clobbering of vector state in all syscalls

Reading this file returns the current discard behavior. Write to '0' or '1'
to file to change the current behavior. The initial state is controlled by
CONFIG_RISCV_ISA_V_VSTATE_DISCARD.

1: https://github.com/riscv/riscv-v-spec/blob/master/calling-convention.adoc
20 changes: 20 additions & 0 deletions arch/riscv/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,26 @@ config RISCV_ISA_V_DEFAULT_ENABLE

If you don't know what to do here, say Y.

config RISCV_ISA_V_VSTATE_DISCARD
bool "Enable Vector state discard by default"
depends on RISCV_ISA_V
default n
help
Discarding vector state (also known as clobbering) on syscall entry
can help identify userspace programs that are mistakenly relying on
vector registers being preserved across syscalls. This can be useful
for debugging and testing. However, this behavior can negatively
impact performance on some RISC-V implementations and is not strictly
necessary.

Select Y here if you want mandatory clobbering of vector state even
though it can increase the duration of syscalls on some RISC-V cores.
If you don't know what to do, then select N.

This choice sets the initial value of the abi.riscv_v_vstate_discard
sysctl. Regardless of whether you choose Y or N, the sysctl can still
be changed by the user while the system is running.

config RISCV_ISA_V_UCOPY_THRESHOLD
int "Threshold size for vectorized user copies"
depends on RISCV_ISA_V
Expand Down
4 changes: 4 additions & 0 deletions arch/riscv/include/asm/vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
_res; \
})

extern bool riscv_v_vstate_discard_ctl;
extern unsigned long riscv_v_vsize;
int riscv_v_setup_vsize(void);
bool insn_is_vector(u32 insn_buf);
Expand Down Expand Up @@ -270,6 +271,9 @@ static inline void __riscv_v_vstate_discard(void)
{
unsigned long vl, vtype_inval = 1UL << (BITS_PER_LONG - 1);

if (READ_ONCE(riscv_v_vstate_discard_ctl) == 0)
return;

riscv_v_enable();
if (has_xtheadvector())
asm volatile (THEAD_VSETVLI_T4X0E8M8D1 : : : "t4");
Expand Down
16 changes: 15 additions & 1 deletion arch/riscv/kernel/vector.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ static struct kmem_cache *riscv_v_user_cachep;
static struct kmem_cache *riscv_v_kernel_cachep;
#endif

bool riscv_v_vstate_discard_ctl = IS_ENABLED(CONFIG_RISCV_ISA_V_VSTATE_DISCARD);
unsigned long riscv_v_vsize __read_mostly;
EXPORT_SYMBOL_GPL(riscv_v_vsize);

Expand Down Expand Up @@ -307,11 +308,24 @@ static const struct ctl_table riscv_v_default_vstate_table[] = {
},
};

static const struct ctl_table riscv_v_vstate_discard_table[] = {
{
.procname = "riscv_v_vstate_discard",
.data = &riscv_v_vstate_discard_ctl,
.maxlen = sizeof(riscv_v_vstate_discard_ctl),
.mode = 0644,
.proc_handler = proc_dobool,
},
};

static int __init riscv_v_sysctl_init(void)
{
if (has_vector() || has_xtheadvector())
if (has_vector() || has_xtheadvector()) {
if (!register_sysctl("abi", riscv_v_default_vstate_table))
return -EINVAL;
if (!register_sysctl("abi", riscv_v_vstate_discard_table))
return -EINVAL;
}
return 0;
}

Expand Down