[v8, 04/10] riscv: sched: defer restoring Vector context for user
Song Shuai
suagrfillet at gmail.com
Wed Dec 27 04:07:14 PST 2023
在 2023/12/23 12:29, Andy Chiu 写道:
> User will use its Vector registers only after the kernel really returns
> to the userspace. So we can delay restoring Vector registers as long as
> we are still running in kernel mode. So, add a thread flag to indicates
> the need of restoring Vector and do the restore at the last
> arch-specific exit-to-user hook. This save the context restoring cost
> when we switch over multiple processes that run V in kernel mode. For
> example, if the kernel performs a context swicth from A->B->C, and
> returns to C's userspace, then there is no need to restore B's
> V-register.
>
> Besides, this also prevents us from repeatedly restoring V context when
> executing kernel-mode Vector multiple times.
>
> The cost of this is that we must disable preemption and mark vector as
> busy during vstate_{save,restore}. Because then the V context will not
> get restored back immediately when a trap-causing context switch happens
> in the middle of vstate_{save,restore}.
>
> Signed-off-by: Andy Chiu <andy.chiu at sifive.com>
> Acked-by: Conor Dooley <conor.dooley at microchip.com>
> ---
> Changelog v4:
> - fix typos and re-add Conor's A-b.
> Changelog v3:
> - Guard {get,put}_cpu_vector_context between vstate_* operation and
> explain it in the commit msg.
> - Drop R-b from Björn and A-b from Conor.
> Changelog v2:
> - rename and add comment for the new thread flag (Conor)
> ---
> arch/riscv/include/asm/entry-common.h | 17 +++++++++++++++++
> arch/riscv/include/asm/thread_info.h | 2 ++
> arch/riscv/include/asm/vector.h | 11 ++++++++++-
> arch/riscv/kernel/kernel_mode_vector.c | 2 +-
> arch/riscv/kernel/process.c | 2 ++
> arch/riscv/kernel/ptrace.c | 5 ++++-
> arch/riscv/kernel/signal.c | 5 ++++-
> arch/riscv/kernel/vector.c | 2 +-
> 8 files changed, 41 insertions(+), 5 deletions(-)
>
> diff --git a/arch/riscv/include/asm/entry-common.h b/arch/riscv/include/asm/entry-common.h
> index 7ab5e34318c8..6361a8488642 100644
> --- a/arch/riscv/include/asm/entry-common.h
> +++ b/arch/riscv/include/asm/entry-common.h
> @@ -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 vector_context_busy.
"vector_context_busy" here should mean the flag used to track in-kernel
Vector context -- riscv_v_flags in this version, please update it.
> + */
> + riscv_v_vstate_restore(current, 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);
> diff --git a/arch/riscv/include/asm/thread_info.h b/arch/riscv/include/asm/thread_info.h
> index 574779900bfb..1047a97ddbc8 100644
> --- a/arch/riscv/include/asm/thread_info.h
> +++ b/arch/riscv/include/asm/thread_info.h
> @@ -103,12 +103,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 | \
> diff --git a/arch/riscv/include/asm/vector.h b/arch/riscv/include/asm/vector.h
> index 6254830c0668..e706613aae2c 100644
> --- a/arch/riscv/include/asm/vector.h
> +++ b/arch/riscv/include/asm/vector.h
> @@ -205,6 +205,15 @@ static inline void riscv_v_vstate_restore(struct task_struct *task,
> }
> }
>
> +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);
> + }
> +}
> +
> static inline void __switch_to_vector(struct task_struct *prev,
> struct task_struct *next)
> {
> @@ -212,7 +221,7 @@ static inline void __switch_to_vector(struct task_struct *prev,
>
> regs = task_pt_regs(prev);
> riscv_v_vstate_save(prev, regs);
> - riscv_v_vstate_restore(next, task_pt_regs(next));
> + riscv_v_vstate_set_restore(next, task_pt_regs(next));
> }
>
> void riscv_v_vstate_ctrl_init(struct task_struct *tsk);
> diff --git a/arch/riscv/kernel/kernel_mode_vector.c b/arch/riscv/kernel/kernel_mode_vector.c
> index 385d9b4d8cc6..63814e780c28 100644
> --- a/arch/riscv/kernel/kernel_mode_vector.c
> +++ b/arch/riscv/kernel/kernel_mode_vector.c
> @@ -96,7 +96,7 @@ void kernel_vector_end(void)
> if (WARN_ON(!has_vector()))
> return;
>
> - riscv_v_vstate_restore(current, task_pt_regs(current));
> + riscv_v_vstate_set_restore(current, task_pt_regs(current));
>
> riscv_v_disable();
>
> diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
> index 4a1275db1146..36993f408de4 100644
> --- a/arch/riscv/kernel/process.c
> +++ b/arch/riscv/kernel/process.c
> @@ -171,6 +171,7 @@ void flush_thread(void)
> riscv_v_vstate_off(task_pt_regs(current));
> kfree(current->thread.vstate.datap);
> memset(¤t->thread.vstate, 0, sizeof(struct __riscv_v_ext_state));
> + clear_tsk_thread_flag(current, TIF_RISCV_V_DEFER_RESTORE);
> #endif
> }
>
> @@ -187,6 +188,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
> *dst = *src;
> /* clear entire V context, including datap for a new task */
> memset(&dst->thread.vstate, 0, sizeof(struct __riscv_v_ext_state));
> + clear_tsk_thread_flag(dst, TIF_RISCV_V_DEFER_RESTORE);
>
> return 0;
> }
> diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c
> index 2afe460de16a..7b93bcbdf9fa 100644
> --- a/arch/riscv/kernel/ptrace.c
> +++ b/arch/riscv/kernel/ptrace.c
> @@ -99,8 +99,11 @@ static int riscv_vr_get(struct task_struct *target,
> * Ensure the vector registers have been saved to the memory before
> * copying them to membuf.
> */
> - if (target == current)
> + if (target == current) {
> + get_cpu_vector_context();
> riscv_v_vstate_save(current, task_pt_regs(current));
> + put_cpu_vector_context();
> + }
>
> ptrace_vstate.vstart = vstate->vstart;
> ptrace_vstate.vl = vstate->vl;
> diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
> index 88b6220b2608..aca4a12c8416 100644
> --- a/arch/riscv/kernel/signal.c
> +++ b/arch/riscv/kernel/signal.c
> @@ -86,7 +86,10 @@ static long save_v_state(struct pt_regs *regs, void __user **sc_vec)
> /* datap is designed to be 16 byte aligned for better performance */
> WARN_ON(unlikely(!IS_ALIGNED((unsigned long)datap, 16)));
>
> + get_cpu_vector_context();
> riscv_v_vstate_save(current, regs);
> + put_cpu_vector_context();
> +
> /* Copy everything of vstate but datap. */
> err = __copy_to_user(&state->v_state, ¤t->thread.vstate,
> offsetof(struct __riscv_v_ext_state, datap));
> @@ -134,7 +137,7 @@ static long __restore_v_state(struct pt_regs *regs, void __user *sc_vec)
> if (unlikely(err))
> return err;
>
> - riscv_v_vstate_restore(current, regs);
> + riscv_v_vstate_set_restore(current, regs);
>
> return err;
> }
> diff --git a/arch/riscv/kernel/vector.c b/arch/riscv/kernel/vector.c
> index 578b6292487e..66e8c6ab09d2 100644
> --- a/arch/riscv/kernel/vector.c
> +++ b/arch/riscv/kernel/vector.c
> @@ -167,7 +167,7 @@ bool riscv_v_first_use_handler(struct pt_regs *regs)
> return true;
> }
> riscv_v_vstate_on(regs);
> - riscv_v_vstate_restore(current, regs);
> + riscv_v_vstate_set_restore(current, regs);
> return true;
> }
>
--
Thanks
Song Shuai
More information about the linux-riscv
mailing list