Skip to content

Commit d1049fc

Browse files
AndybnACTpalmer-dabbelt
authored andcommitted
riscv: vector: Support calling schedule() for preemptible Vector
Each function entry implies a call to ftrace infrastructure. And it may call into schedule in some cases. So, it is possible for preemptible kernel-mode Vector to implicitly call into schedule. Since all V-regs are caller-saved, it is possible to drop all V context when a thread voluntarily call schedule(). Besides, we currently don't pass argument through vector register, so we don't have to save/restore V-regs in ftrace trampoline. Signed-off-by: Andy Chiu <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexandre Ghiti <[email protected]> Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 5aa4ef9 commit d1049fc

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

arch/riscv/include/asm/processor.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ struct pt_regs;
7979
* Thus, the task does not own preempt_v. Any use of Vector will have to
8080
* save preempt_v, if dirty, and fallback to non-preemptible kernel-mode
8181
* Vector.
82+
* - bit 29: The thread voluntarily calls schedule() while holding an active
83+
* preempt_v. All preempt_v context should be dropped in such case because
84+
* V-regs are caller-saved. Only sstatus.VS=ON is persisted across a
85+
* schedule() call.
8286
* - bit 30: The in-kernel preempt_v context is saved, and requries to be
8387
* restored when returning to the context that owns the preempt_v.
8488
* - bit 31: The in-kernel preempt_v context is dirty, as signaled by the
@@ -93,6 +97,7 @@ struct pt_regs;
9397
#define RISCV_PREEMPT_V 0x00000100
9498
#define RISCV_PREEMPT_V_DIRTY 0x80000000
9599
#define RISCV_PREEMPT_V_NEED_RESTORE 0x40000000
100+
#define RISCV_PREEMPT_V_IN_SCHEDULE 0x20000000
96101

97102
/* CPU-specific state of a task */
98103
struct thread_struct {

arch/riscv/include/asm/vector.h

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ static __always_inline void riscv_v_disable(void)
120120
csr_clear(CSR_SSTATUS, SR_VS);
121121
}
122122

123+
static __always_inline bool riscv_v_is_on(void)
124+
{
125+
return !!(csr_read(CSR_SSTATUS) & SR_VS);
126+
}
127+
123128
static __always_inline void __vstate_csr_save(struct __riscv_v_ext_state *dest)
124129
{
125130
asm volatile (
@@ -366,6 +371,11 @@ static inline void __switch_to_vector(struct task_struct *prev,
366371
struct pt_regs *regs;
367372

368373
if (riscv_preempt_v_started(prev)) {
374+
if (riscv_v_is_on()) {
375+
WARN_ON(prev->thread.riscv_v_flags & RISCV_V_CTX_DEPTH_MASK);
376+
riscv_v_disable();
377+
prev->thread.riscv_v_flags |= RISCV_PREEMPT_V_IN_SCHEDULE;
378+
}
369379
if (riscv_preempt_v_dirty(prev)) {
370380
__riscv_v_vstate_save(&prev->thread.kernel_vstate,
371381
prev->thread.kernel_vstate.datap);
@@ -376,10 +386,16 @@ static inline void __switch_to_vector(struct task_struct *prev,
376386
riscv_v_vstate_save(&prev->thread.vstate, regs);
377387
}
378388

379-
if (riscv_preempt_v_started(next))
380-
riscv_preempt_v_set_restore(next);
381-
else
389+
if (riscv_preempt_v_started(next)) {
390+
if (next->thread.riscv_v_flags & RISCV_PREEMPT_V_IN_SCHEDULE) {
391+
next->thread.riscv_v_flags &= ~RISCV_PREEMPT_V_IN_SCHEDULE;
392+
riscv_v_enable();
393+
} else {
394+
riscv_preempt_v_set_restore(next);
395+
}
396+
} else {
382397
riscv_v_vstate_set_restore(next, task_pt_regs(next));
398+
}
383399
}
384400

385401
void riscv_v_vstate_ctrl_init(struct task_struct *tsk);

0 commit comments

Comments
 (0)