Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
ed82ad6
riscv: use ".L" local labels in assembly when applicable
uestc-gr Aug 4, 2025
d031b42
riscv: Use SYM_*() assembly macros instead of deprecated ones
uestc-gr Aug 4, 2025
15a4470
riscv: kernel: Use correct SYM_DATA_*() macro for data
uestc-gr Aug 4, 2025
309720e
riscv: Add support for kernel mode vector
uestc-gr Aug 5, 2025
03d73f2
riscv: vector: make Vector always available for softirq context
uestc-gr Aug 5, 2025
5f43b56
riscv: Add vector extension XOR implementation
uestc-gr Aug 5, 2025
19788c6
riscv: sched: defer restoring Vector context for user
uestc-gr Aug 5, 2025
fce75af
riscv: lib: vectorize copy_to_user/copy_from_user
uestc-gr Aug 5, 2025
e3b4083
riscv: fpu: drop SR_SD bit checking
uestc-gr Aug 5, 2025
e52ab30
riscv: vector: do not pass task_struct into riscv_v_vstate_{save,rest…
uestc-gr Aug 5, 2025
de34628
riscv: vector: use a mask to write vstate_ctrl
uestc-gr Aug 5, 2025
47fdb28
riscv: vector: use kmem_cache to manage vector context
uestc-gr Aug 5, 2025
8737ea8
riscv: vector: allow kernel-mode Vector with preemption
uestc-gr Aug 5, 2025
a6c7c54
riscv: Fix vector state restore in rt_sigreturn()
uestc-gr Aug 5, 2025
a64e6ce
Revert "iommu: Handle race with default domain setup"
uestc-gr Jul 29, 2025
6fbad84
iommu: Add iommu_ops->identity_domain
uestc-gr Jul 28, 2025
473d4b5
iommu: Add IOMMU_DOMAIN_PLATFORM
uestc-gr Jul 28, 2025
edf7845
iommu: Add IOMMU_DOMAIN_PLATFORM for S390
uestc-gr Apr 22, 2025
15f49d6
iommu/fsl_pamu: Implement a PLATFORM domain
uestc-gr Apr 22, 2025
b5d3d26
iommu/mtk_iommu_v1: Implement an IDENTITY domain
uestc-gr Apr 22, 2025
d1fbae6
iommu: Reorganize iommu_get_default_domain_type() to respect def_doma…
uestc-gr Apr 22, 2025
0e95881
iommu: Allow an IDENTITY domain as the default_domain in ARM32
uestc-gr Apr 22, 2025
ebc96f0
iommu/exynos: Implement an IDENTITY domain
uestc-gr Apr 22, 2025
6ba9ccf
iommu/tegra-smmu: Implement an IDENTITY domain
uestc-gr Apr 22, 2025
5e98c25
iommu/tegra-smmu: Support DMA domains in tegra
uestc-gr Apr 22, 2025
9fde0bc
iommu/omap: Implement an IDENTITY domain
uestc-gr Apr 22, 2025
3b3a831
iommu/msm: Implement an IDENTITY domain
uestc-gr Apr 22, 2025
d058ec9
iommu: Remove ops->set_platform_dma_ops()
uestc-gr Apr 22, 2025
2413d9d
iommu/qcom_iommu: Add an IOMMU_IDENTITIY_DOMAIN
uestc-gr Apr 22, 2025
f7c775e
iommu/ipmmu: Add an IOMMU_IDENTITIY_DOMAIN
uestc-gr Apr 22, 2025
845098d
iommu/mtk_iommu: Add an IOMMU_IDENTITIY_DOMAIN
uestc-gr Apr 22, 2025
1064cd3
iommu/sun50i: Add an IOMMU_IDENTITIY_DOMAIN
uestc-gr Apr 22, 2025
c9071a4
iommu: Require a default_domain for all iommu drivers
uestc-gr Apr 22, 2025
78db90d
iommu: Add __iommu_group_domain_alloc()
uestc-gr Apr 22, 2025
78c3a76
iommu: Add ops->domain_alloc_paging()
uestc-gr Apr 22, 2025
b92f9e7
iommu: Convert simple drivers with DOMAIN_DMA to domain_alloc_paging()
uestc-gr Apr 22, 2025
46127ca
iommu: Convert remaining simple drivers to domain_alloc_paging()
uestc-gr Apr 22, 2025
3fa05bf
iommu: Do not use IOMMU_DOMAIN_DMA if CONFIG_IOMMU_DMA is not enabled
uestc-gr Jul 31, 2025
ceb2003
iommu: Handle race with default domain setup
uestc-gr Jul 31, 2025
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
22 changes: 22 additions & 0 deletions arch/riscv/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,28 @@ config RISCV_ISA_ZACAS

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

config RISCV_ISA_V_UCOPY_THRESHOLD
int "Threshold size for vectorized user copies"
depends on RISCV_ISA_V
default 768
help
Prefer using vectorized copy_to_user()/copy_from_user() when the
workload size exceeds this value.

config RISCV_ISA_V_PREEMPTIVE
bool "Run kernel-mode Vector with kernel preemption"
depends on PREEMPTION
depends on RISCV_ISA_V
default y
help
Usually, in-kernel SIMD routines are run with preemption disabled.
Functions which envoke long running SIMD thus must yield core's
vector unit to prevent blocking other tasks for too long.

This config allows kernel to run SIMD without explicitly disable
preemption. Enabling this config will result in higher memory
consumption due to the allocation of per-task's kernel Vector context.

config TOOLCHAIN_HAS_ZBB
bool
default y
Expand Down
27 changes: 27 additions & 0 deletions arch/riscv/include/asm/asm-prototypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,33 @@ long long __lshrti3(long long a, int b);
long long __ashrti3(long long a, int b);
long long __ashlti3(long long a, int b);

#ifdef CONFIG_RISCV_ISA_V

#ifdef CONFIG_MMU
asmlinkage int enter_vector_usercopy(void *dst, void *src, size_t n);
#endif /* CONFIG_MMU */

void xor_regs_2_(unsigned long bytes, unsigned long *__restrict p1,
const unsigned long *__restrict p2);
void xor_regs_3_(unsigned long bytes, unsigned long *__restrict p1,
const unsigned long *__restrict p2,
const unsigned long *__restrict p3);
void xor_regs_4_(unsigned long bytes, unsigned long *__restrict p1,
const unsigned long *__restrict p2,
const unsigned long *__restrict p3,
const unsigned long *__restrict p4);
void xor_regs_5_(unsigned long bytes, unsigned long *__restrict p1,
const unsigned long *__restrict p2,
const unsigned long *__restrict p3,
const unsigned long *__restrict p4,
const unsigned long *__restrict p5);

#ifdef CONFIG_RISCV_ISA_V_PREEMPTIVE
asmlinkage void riscv_v_context_nesting_start(struct pt_regs *regs);
asmlinkage void riscv_v_context_nesting_end(struct pt_regs *regs);
#endif /* CONFIG_RISCV_ISA_V_PREEMPTIVE */

#endif /* CONFIG_RISCV_ISA_V */

#define DECLARE_DO_ERROR_INFO(name) asmlinkage void name(struct pt_regs *regs)

Expand Down
17 changes: 17 additions & 0 deletions arch/riscv/include/asm/entry-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,23 @@
#define _ASM_RISCV_ENTRY_COMMON_H

#include <asm/stacktrace.h>
#include <asm/thread_info.h>
#include <asm/vector.h>

static inline void arch_exit_to_user_mode_prepare(struct pt_regs *regs,
unsigned long ti_work)
{
if (ti_work & _TIF_RISCV_V_DEFER_RESTORE) {
clear_thread_flag(TIF_RISCV_V_DEFER_RESTORE);
/*
* We are already called with irq disabled, so go without
* keeping track of riscv_v_flags.
*/
riscv_v_vstate_restore(&current->thread.vstate, regs);
}
}

#define arch_exit_to_user_mode_prepare arch_exit_to_user_mode_prepare

void handle_page_fault(struct pt_regs *regs);
void handle_break(struct pt_regs *regs);
Expand Down
41 changes: 40 additions & 1 deletion arch/riscv/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,43 @@
struct task_struct;
struct pt_regs;

/*
* We use a flag to track in-kernel Vector context. Currently the flag has the
* following meaning:
*
* - bit 0: indicates whether the in-kernel Vector context is active. The
* activation of this state disables the preemption. On a non-RT kernel, it
* also disable bh.
* - bits 8: is used for tracking preemptible kernel-mode Vector, when
* RISCV_ISA_V_PREEMPTIVE is enabled. Calling kernel_vector_begin() does not
* disable the preemption if the thread's kernel_vstate.datap is allocated.
* Instead, the kernel set this bit field. Then the trap entry/exit code
* knows if we are entering/exiting the context that owns preempt_v.
* - 0: the task is not using preempt_v
* - 1: the task is actively using preempt_v. But whether does the task own
* the preempt_v context is decided by bits in RISCV_V_CTX_DEPTH_MASK.
* - bit 16-23 are RISCV_V_CTX_DEPTH_MASK, used by context tracking routine
* when preempt_v starts:
* - 0: the task is actively using, and own preempt_v context.
* - non-zero: the task was using preempt_v, but then took a trap within.
* Thus, the task does not own preempt_v. Any use of Vector will have to
* save preempt_v, if dirty, and fallback to non-preemptible kernel-mode
* Vector.
* - bit 30: The in-kernel preempt_v context is saved, and requries to be
* restored when returning to the context that owns the preempt_v.
* - bit 31: The in-kernel preempt_v context is dirty, as signaled by the
* trap entry code. Any context switches out-of current task need to save
* it to the task's in-kernel V context. Also, any traps nesting on-top-of
* preempt_v requesting to use V needs a save.
*/
#define RISCV_V_CTX_DEPTH_MASK 0x00ff0000

#define RISCV_V_CTX_UNIT_DEPTH 0x00010000
#define RISCV_KERNEL_MODE_V 0x00000001
#define RISCV_PREEMPT_V 0x00000100
#define RISCV_PREEMPT_V_DIRTY 0x80000000
#define RISCV_PREEMPT_V_NEED_RESTORE 0x40000000

/* CPU-specific state of a task */
struct thread_struct {
/* Callee-saved registers */
Expand All @@ -86,8 +123,10 @@ struct thread_struct {
unsigned long s[12]; /* s[0]: frame pointer */
struct __riscv_d_ext_state fstate;
unsigned long bad_cause;
unsigned long vstate_ctrl;
u32 riscv_v_flags;
u32 vstate_ctrl;
struct __riscv_v_ext_state vstate;
struct __riscv_v_ext_state kernel_vstate;
};

/* Whitelist the fstate from the task_struct for hardened usercopy */
Expand Down
64 changes: 64 additions & 0 deletions arch/riscv/include/asm/simd.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2017 Linaro Ltd. <ard.biesheuvel@linaro.org>
* Copyright (C) 2023 SiFive
*/

#ifndef __ASM_SIMD_H
#define __ASM_SIMD_H

#include <linux/compiler.h>
#include <linux/irqflags.h>
#include <linux/percpu.h>
#include <linux/preempt.h>
#include <linux/types.h>
#include <linux/thread_info.h>

#include <asm/vector.h>

#ifdef CONFIG_RISCV_ISA_V
/*
* may_use_simd - whether it is allowable at this time to issue vector
* instructions or access the vector register file
*
* Callers must not assume that the result remains true beyond the next
* preempt_enable() or return from softirq context.
*/
static __must_check inline bool may_use_simd(void)
{
/*
* RISCV_KERNEL_MODE_V is only set while preemption is disabled,
* and is clear whenever preemption is enabled.
*/
if (in_hardirq() || in_nmi())
return false;

/*
* Nesting is acheived in preempt_v by spreading the control for
* preemptible and non-preemptible kernel-mode Vector into two fields.
* Always try to match with prempt_v if kernel V-context exists. Then,
* fallback to check non preempt_v if nesting happens, or if the config
* is not set.
*/
if (IS_ENABLED(CONFIG_RISCV_ISA_V_PREEMPTIVE) && current->thread.kernel_vstate.datap) {
if (!riscv_preempt_v_started(current))
return true;
}
/*
* Non-preemptible kernel-mode Vector temporarily disables bh. So we
* must not return true on irq_disabled(). Otherwise we would fail the
* lockdep check calling local_bh_enable()
*/
return !irqs_disabled() && !(riscv_v_flags() & RISCV_KERNEL_MODE_V);
}

#else /* ! CONFIG_RISCV_ISA_V */

static __must_check inline bool may_use_simd(void)
{
return false;
}

#endif /* ! CONFIG_RISCV_ISA_V */

#endif
3 changes: 1 addition & 2 deletions arch/riscv/include/asm/switch_to.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ static inline void __switch_to_fpu(struct task_struct *prev,
struct pt_regs *regs;

regs = task_pt_regs(prev);
if (unlikely(regs->status & SR_SD))
fstate_save(prev, regs);
fstate_save(prev, regs);
fstate_restore(next, task_pt_regs(next));
}

Expand Down
2 changes: 2 additions & 0 deletions arch/riscv/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,14 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
#define TIF_NOTIFY_SIGNAL 9 /* signal notifications exist */
#define TIF_UPROBE 10 /* uprobe breakpoint or singlestep */
#define TIF_32BIT 11 /* compat-mode 32bit process */
#define TIF_RISCV_V_DEFER_RESTORE 12 /* restore Vector before returing to user */

#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
#define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL)
#define _TIF_UPROBE (1 << TIF_UPROBE)
#define _TIF_RISCV_V_DEFER_RESTORE (1 << TIF_RISCV_V_DEFER_RESTORE)

#define _TIF_WORK_MASK \
(_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NEED_RESCHED | \
Expand Down
88 changes: 79 additions & 9 deletions arch/riscv/include/asm/vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@
extern unsigned long riscv_v_vsize;
int riscv_v_setup_vsize(void);
bool riscv_v_first_use_handler(struct pt_regs *regs);
void kernel_vector_begin(void);
void kernel_vector_end(void);
void get_cpu_vector_context(void);
void put_cpu_vector_context(void);
void riscv_v_thread_free(struct task_struct *tsk);
void __init riscv_v_setup_ctx_cache(void);
void riscv_v_thread_alloc(struct task_struct *tsk);

static inline u32 riscv_v_flags(void)
{
return READ_ONCE(current->thread.riscv_v_flags);
}

static __always_inline bool has_vector(void)
{
Expand Down Expand Up @@ -253,7 +265,7 @@ static inline void riscv_v_vstate_discard(struct pt_regs *regs)
__riscv_v_vstate_dirty(regs);
}

static inline void riscv_v_vstate_save(struct task_struct *task,
static inline void riscv_v_vstate_save(struct __riscv_v_ext_state *vstate,
struct pt_regs *regs)
{
unsigned long sr_vs, sr_vs_dirty;
Expand All @@ -262,36 +274,91 @@ static inline void riscv_v_vstate_save(struct task_struct *task,
ALT_SR_VS(sr_vs_dirty, SR_VS_DIRTY);

if ((regs->status & sr_vs) == sr_vs_dirty) {
struct __riscv_v_ext_state *vstate = &task->thread.vstate;
if (vstate->datap)
__riscv_v_vstate_save(vstate, vstate->datap);
__riscv_v_vstate_clean(regs);
}
}

static inline void riscv_v_vstate_restore(struct task_struct *task,
static inline void riscv_v_vstate_restore(struct __riscv_v_ext_state *vstate,
struct pt_regs *regs)
{
unsigned long sr_vs;

ALT_SR_VS(sr_vs, SR_VS);

if ((regs->status & sr_vs) != SR_VS_OFF) {
struct __riscv_v_ext_state *vstate = &task->thread.vstate;
if (vstate->datap)
__riscv_v_vstate_restore(vstate, vstate->datap);
__riscv_v_vstate_clean(regs);
}
}

static inline void riscv_v_vstate_set_restore(struct task_struct *task,
struct pt_regs *regs)
{
if ((regs->status & SR_VS) != SR_VS_OFF) {
set_tsk_thread_flag(task, TIF_RISCV_V_DEFER_RESTORE);
riscv_v_vstate_on(regs);
}
}

#ifdef CONFIG_RISCV_ISA_V_PREEMPTIVE
static inline bool riscv_preempt_v_dirty(struct task_struct *task)
{
return !!(task->thread.riscv_v_flags & RISCV_PREEMPT_V_DIRTY);
}

static inline bool riscv_preempt_v_restore(struct task_struct *task)
{
return !!(task->thread.riscv_v_flags & RISCV_PREEMPT_V_NEED_RESTORE);
}

static inline void riscv_preempt_v_clear_dirty(struct task_struct *task)
{
barrier();
task->thread.riscv_v_flags &= ~RISCV_PREEMPT_V_DIRTY;
}

static inline void riscv_preempt_v_set_restore(struct task_struct *task)
{
barrier();
task->thread.riscv_v_flags |= RISCV_PREEMPT_V_NEED_RESTORE;
}

static inline bool riscv_preempt_v_started(struct task_struct *task)
{
return !!(task->thread.riscv_v_flags & RISCV_PREEMPT_V);
}

#else /* !CONFIG_RISCV_ISA_V_PREEMPTIVE */
static inline bool riscv_preempt_v_dirty(struct task_struct *task) { return false; }
static inline bool riscv_preempt_v_restore(struct task_struct *task) { return false; }
static inline bool riscv_preempt_v_started(struct task_struct *task) { return false; }
#define riscv_preempt_v_clear_dirty(tsk) do {} while (0)
#define riscv_preempt_v_set_restore(tsk) do {} while (0)
#endif /* CONFIG_RISCV_ISA_V_PREEMPTIVE */

static inline void __switch_to_vector(struct task_struct *prev,
struct task_struct *next)
{
struct pt_regs *regs;

regs = task_pt_regs(prev);
riscv_v_vstate_save(prev, regs);
riscv_v_vstate_restore(next, task_pt_regs(next));
if (riscv_preempt_v_started(prev)) {
if (riscv_preempt_v_dirty(prev)) {
__riscv_v_vstate_save(&prev->thread.kernel_vstate,
prev->thread.kernel_vstate.datap);
riscv_preempt_v_clear_dirty(prev);
}
} else {
regs = task_pt_regs(prev);
riscv_v_vstate_save(&prev->thread.vstate, regs);
}

if (riscv_preempt_v_started(next))
riscv_preempt_v_set_restore(next);
else
riscv_v_vstate_set_restore(next, task_pt_regs(next));
}

void riscv_v_vstate_ctrl_init(struct task_struct *tsk);
Expand All @@ -309,11 +376,14 @@ static inline bool riscv_v_vstate_query(struct pt_regs *regs) { return false; }
static inline bool riscv_v_vstate_ctrl_user_allowed(void) { return false; }
#define riscv_v_vsize (0)
#define riscv_v_vstate_discard(regs) do {} while (0)
#define riscv_v_vstate_save(task, regs) do {} while (0)
#define riscv_v_vstate_restore(task, regs) do {} while (0)
#define riscv_v_vstate_save(vstate, regs) do {} while (0)
#define riscv_v_vstate_restore(vstate, regs) do {} while (0)
#define __switch_to_vector(__prev, __next) do {} while (0)
#define riscv_v_vstate_off(regs) do {} while (0)
#define riscv_v_vstate_on(regs) do {} while (0)
#define riscv_v_thread_free(tsk) do {} while (0)
#define riscv_v_setup_ctx_cache() do {} while (0)
#define riscv_v_thread_alloc(tsk) do {} while (0)

#endif /* CONFIG_RISCV_ISA_V */

Expand Down
Loading
Loading