* [PATCH 0/1] riscv: Optimize signal handling with sum enabled accesses
@ 2025-12-02 7:43 maohan4761
2025-12-02 7:43 ` [PATCH 1/1] " maohan4761
0 siblings, 1 reply; 3+ messages in thread
From: maohan4761 @ 2025-12-02 7:43 UTC (permalink / raw)
To: pjw, palmer; +Cc: guoren, linux-riscv, linux-kernel, Mao Han
From: Mao Han <han_mao@linux.alibaba.com>
Currently, the signal function frequently toggles the SUM bit to control
user-space access within __get_user/__put_user.
void __user *sc_ext_ptr = &sc->sc_extdesc.hdr;
ffffffff80005904: 44898a13 addi s4,s3,1096
err |= __get_user(magic, &head->magic);
ffffffff80005908: 8752 mv a4,s4
ffffffff8000590a: 00000013 nop
ffffffff8000590e: 1004a073 csrs sstatus,s1
ffffffff80005912: 4781 li a5,0
ffffffff80005914: 4310 lw a2,0(a4)
ffffffff80005916: 2601 sext.w a2,a2
ffffffff80005918: 1004b073 csrc sstatus,s1
err |= __get_user(size, &head->size);
ffffffff8000591c: 004a0693 addi a3,s4,4
ffffffff80005920: 00000013 nop
ffffffff80005924: 1004a073 csrs sstatus,s1
ffffffff80005928: 4701 li a4,0
ffffffff8000592a: 428c lw a1,0(a3)
ffffffff8000592c: 86ae mv a3,a1
ffffffff8000592e: 2581 sext.w a1,a1
ffffffff80005930: 1004b073 csrc sstatus,s1
ffffffff80005934: 8fd9 or a5,a5,a4
On modern out-of-order processors, frequent CSR (Control and Status Register)
operations introduce pipeline stalls, significantly degrading performance.
This patch attempts to enable the SUM bit only once at the beginning of
rt_sigreturn and setup_rt_frame, keep it enabled throughout frame handling,
and directly access user-space memory without repeatedly toggling the SUM bit.
This reduces the overhead caused by frequent CSR state changes.
Lmbench signal-related benchmarks show approximately a 20% performance improvement.
Mao Han (1):
riscv: Optimize signal handling with sum enabled accesses
arch/riscv/include/asm/uaccess.h | 75 ++++++++++++++++++++++++++++++++
arch/riscv/kernel/signal.c | 74 +++++++++++++++++++------------
2 files changed, 121 insertions(+), 28 deletions(-)
--
2.25.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH 1/1] riscv: Optimize signal handling with sum enabled accesses
2025-12-02 7:43 [PATCH 0/1] riscv: Optimize signal handling with sum enabled accesses maohan4761
@ 2025-12-02 7:43 ` maohan4761
2025-12-03 20:10 ` kernel test robot
0 siblings, 1 reply; 3+ messages in thread
From: maohan4761 @ 2025-12-02 7:43 UTC (permalink / raw)
To: pjw, palmer; +Cc: guoren, linux-riscv, linux-kernel, Mao Han
From: Mao Han <han_mao@linux.alibaba.com>
Introduce new __get_user_sum_enabled() and __put_user_sum_enabled() macros
in uaccess.h that perform user-space accesses assuming the SUM bit is
already enabled.
Explicitly manage SUM state around bulk user copies in rt_sigreturn() and
setup_rt_frame() by bracketing sequences of SUM-enabled operations with
a single pair of __enable_user_access() / __disable_user_access(), reducing
the number of CSR writes and improving performance. All callers ensure
access_ok() checks are performed for the signal frame.
Signed-off-by: Mao Han <han_mao@linux.alibaba.com>
---
arch/riscv/include/asm/uaccess.h | 75 ++++++++++++++++++++++++++++++++
arch/riscv/kernel/signal.c | 74 +++++++++++++++++++------------
2 files changed, 121 insertions(+), 28 deletions(-)
diff --git a/arch/riscv/include/asm/uaccess.h b/arch/riscv/include/asm/uaccess.h
index f5f4f7f..78f8a21 100644
--- a/arch/riscv/include/asm/uaccess.h
+++ b/arch/riscv/include/asm/uaccess.h
@@ -213,6 +213,43 @@ __gu_failed: \
err = -EFAULT; \
} while (0)
+/**
+ * __get_user_sum_enabled - Get a simple variable from user space,
+ * assuming user access is already enabled (SUM bit enabled).
+ * @x: Variable to store result.
+ * @ptr: Source address, in user space.
+ *
+ * Context: User context only. This macro does NOT sleep.
+ *
+ * This variant of __get_user assumes that the CPU is already in a state
+ * where user-space addresses can be accessed directly from kernel mode.
+ * Therefore, it omits the __enable_user_access() / __disable_user_access()
+ * calls.
+ *
+ * @ptr must have pointer-to-simple-variable type, and the result of
+ * dereferencing @ptr must be assignable to @x without a cast.
+ *
+ * Caller MUST ensure:
+ * - access_ok(ptr, sizeof(*ptr)) has been verified.
+ * - The execution context permits direct user-space reads.
+ *
+ * Returns zero on success, or -EFAULT on error.
+ * On error, the variable @x is set to zero.
+ */
+#define __get_user_sum_enabled(x, ptr) \
+({ \
+ const __typeof__(*(ptr)) __user *__gu_ptr = untagged_addr(ptr); \
+ long __gu_err = 0; \
+ __typeof__(x) __gu_val = (__typeof__(x))0; \
+ \
+ __chk_user_ptr(__gu_ptr); \
+ \
+ __get_user_error(__gu_val, __gu_ptr, __gu_err); \
+ \
+ (x) = __gu_val; \
+ __gu_err; \
+})
+
/**
* __get_user: - Get a simple variable from user space, with less checking.
* @x: Variable to store result.
@@ -343,6 +380,44 @@ err_label: \
(err) = -EFAULT; \
} while (0)
+
+/**
+ * __put_user_sum_enabled - Write a simple value into user space,
+ * assuming user access is already enabled (SUM bit enabled).
+ * @x: Value to copy to user space.
+ * @ptr: Destination address, in user space.
+ *
+ * Context: User context only. This macro does NOT sleep.
+ *
+ * This variant of __put_user_sum_enabled assumes that the CPU is already
+ * in a state where user-space addresses can be accessed directly from
+ * kernel mode. Therefore, it omits the
+ * __enable_user_access() / __disable_user_access() calls.
+ *
+ * @ptr must have pointer-to-simple-variable type, and @x must be assignable
+ * to the result of dereferencing @ptr. The value of @x is copied to avoid
+ * re-ordering where @x is evaluated inside the block that enables user-space
+ * access (thus bypassing user space protection if @x is a function).
+ *
+ * Caller MUST ensure:
+ * - access_ok(ptr, sizeof(*ptr)) has been verified.
+ * - The execution context permits direct user-space writes.
+ *
+ * Returns zero on success, or -EFAULT on error.
+ */
+#define __put_user_sum_enabled(x, ptr) \
+({ \
+ __typeof__(*(ptr)) __user *__gu_ptr = untagged_addr(ptr); \
+ __typeof__(*__gu_ptr) __val = (x); \
+ long __pu_err = 0; \
+ \
+ __chk_user_ptr(__gu_ptr); \
+ \
+ __put_user_error(__val, __gu_ptr, __pu_err); \
+ \
+ __pu_err; \
+})
+
/**
* __put_user: - Write a simple value into user space, with less checking.
* @x: Value to copy to user space.
diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c
index 08378fe..a4a9395 100644
--- a/arch/riscv/kernel/signal.c
+++ b/arch/riscv/kernel/signal.c
@@ -45,7 +45,7 @@ static long restore_fp_state(struct pt_regs *regs,
long err;
struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
- err = __copy_from_user(¤t->thread.fstate, state, sizeof(*state));
+ err = __asm_copy_from_user_sum_enabled(¤t->thread.fstate, state, sizeof(*state));
if (unlikely(err))
return err;
@@ -60,7 +60,7 @@ static long save_fp_state(struct pt_regs *regs,
struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
fstate_save(current, regs);
- err = __copy_to_user(state, ¤t->thread.fstate, sizeof(*state));
+ err = __asm_copy_to_user_sum_enabled(state, ¤t->thread.fstate, sizeof(*state));
return err;
}
#else
@@ -91,15 +91,15 @@ static long save_v_state(struct pt_regs *regs, void __user **sc_vec)
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));
+ err = __asm_copy_to_user_sum_enabled(&state->v_state, ¤t->thread.vstate,
+ offsetof(struct __riscv_v_ext_state, datap));
/* Copy the pointer datap itself. */
- err |= __put_user((__force void *)datap, &state->v_state.datap);
+ err |= __put_user_sum_enabled((__force void *)datap, &state->v_state.datap);
/* Copy the whole vector content to user space datap. */
- err |= __copy_to_user(datap, current->thread.vstate.datap, riscv_v_vsize);
+ err |= __asm_copy_to_user_sum_enabled(datap, current->thread.vstate.datap, riscv_v_vsize);
/* Copy magic to the user space after saving all vector conetext */
- err |= __put_user(RISCV_V_MAGIC, &hdr->magic);
- err |= __put_user(riscv_v_sc_size, &hdr->size);
+ err |= __put_user_sum_enabled(RISCV_V_MAGIC, &hdr->magic);
+ err |= __put_user_sum_enabled(riscv_v_sc_size, &hdr->size);
if (unlikely(err))
return err;
@@ -127,20 +127,20 @@ static long __restore_v_state(struct pt_regs *regs, void __user *sc_vec)
riscv_v_vstate_set_restore(current, regs);
/* Copy everything of __sc_riscv_v_state except datap. */
- err = __copy_from_user(¤t->thread.vstate, &state->v_state,
- offsetof(struct __riscv_v_ext_state, datap));
+ err = __asm_copy_from_user_sum_enabled(¤t->thread.vstate, &state->v_state,
+ offsetof(struct __riscv_v_ext_state, datap));
if (unlikely(err))
return err;
/* Copy the pointer datap itself. */
- err = __get_user(datap, &state->v_state.datap);
+ err = __get_user_sum_enabled(datap, &state->v_state.datap);
if (unlikely(err))
return err;
/*
* Copy the whole vector content from user space datap. Use
* copy_from_user to prevent information leak.
*/
- return copy_from_user(current->thread.vstate.datap, datap, riscv_v_vsize);
+ return __asm_copy_from_user_sum_enabled(current->thread.vstate.datap, datap, riscv_v_vsize);
}
#else
#define save_v_state(task, regs) (0)
@@ -154,7 +154,7 @@ static long restore_sigcontext(struct pt_regs *regs,
__u32 rsvd;
long err;
/* sc_regs is structured the same as the start of pt_regs */
- err = __copy_from_user(regs, &sc->sc_regs, sizeof(sc->sc_regs));
+ err = __asm_copy_from_user_sum_enabled(regs, &sc->sc_regs, sizeof(sc->sc_regs));
if (unlikely(err))
return err;
@@ -166,7 +166,7 @@ static long restore_sigcontext(struct pt_regs *regs,
}
/* Check the reserved word before extensions parsing */
- err = __get_user(rsvd, &sc->sc_extdesc.reserved);
+ err = __get_user_sum_enabled(rsvd, &sc->sc_extdesc.reserved);
if (unlikely(err))
return err;
if (unlikely(rsvd))
@@ -176,8 +176,8 @@ static long restore_sigcontext(struct pt_regs *regs,
__u32 magic, size;
struct __riscv_ctx_hdr __user *head = sc_ext_ptr;
- err |= __get_user(magic, &head->magic);
- err |= __get_user(size, &head->size);
+ err |= __get_user_sum_enabled(magic, &head->magic);
+ err |= __get_user_sum_enabled(size, &head->size);
if (unlikely(err))
return err;
@@ -238,7 +238,8 @@ SYSCALL_DEFINE0(rt_sigreturn)
if (!access_ok(frame, frame_size))
goto badframe;
- if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+ __enable_user_access();
+ if (__asm_copy_from_user_sum_enabled(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe;
set_current_blocked(&set);
@@ -248,12 +249,14 @@ SYSCALL_DEFINE0(rt_sigreturn)
if (restore_altstack(&frame->uc.uc_stack))
goto badframe;
+ __disable_user_access();
regs->cause = -1UL;
return regs->a0;
badframe:
+ __disable_user_access();
task = current;
if (show_unhandled_signals) {
pr_info_ratelimited(
@@ -273,7 +276,7 @@ static long setup_sigcontext(struct rt_sigframe __user *frame,
long err;
/* sc_regs is structured the same as the start of pt_regs */
- err = __copy_to_user(&sc->sc_regs, regs, sizeof(sc->sc_regs));
+ err = __asm_copy_to_user_sum_enabled(&sc->sc_regs, regs, sizeof(sc->sc_regs));
/* Save the floating-point state. */
if (has_fpu())
err |= save_fp_state(regs, &sc->sc_fpregs);
@@ -281,10 +284,10 @@ static long setup_sigcontext(struct rt_sigframe __user *frame,
if ((has_vector() || has_xtheadvector()) && riscv_v_vstate_query(regs))
err |= save_v_state(regs, (void __user **)&sc_ext_ptr);
/* Write zero to fp-reserved space and check it on restore_sigcontext */
- err |= __put_user(0, &sc->sc_extdesc.reserved);
+ err |= __put_user_sum_enabled(0, &sc->sc_extdesc.reserved);
/* And put END __riscv_ctx_hdr at the end. */
- err |= __put_user(END_MAGIC, &sc_ext_ptr->magic);
- err |= __put_user(END_HDR_SIZE, &sc_ext_ptr->size);
+ err |= __put_user_sum_enabled(END_MAGIC, &sc_ext_ptr->magic);
+ err |= __put_user_sum_enabled(END_HDR_SIZE, &sc_ext_ptr->size);
return err;
}
@@ -312,6 +315,15 @@ static inline void __user *get_sigframe(struct ksignal *ksig,
return (void __user *)sp;
}
+static int __save_altstack_sum_enabled(stack_t __user *uss, unsigned long sp)
+{
+ struct task_struct *t = current;
+ int err = __put_user_sum_enabled((void __user *)t->sas_ss_sp, &uss->ss_sp) |
+ __put_user_sum_enabled(t->sas_ss_flags, &uss->ss_flags) |
+ __put_user_sum_enabled(t->sas_ss_size, &uss->ss_size);
+ return err;
+}
+
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
struct pt_regs *regs)
{
@@ -327,13 +339,16 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
/* Create the ucontext. */
- err |= __put_user(0, &frame->uc.uc_flags);
- err |= __put_user(NULL, &frame->uc.uc_link);
- err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
+ __enable_user_access();
+ err |= __put_user_sum_enabled(0, &frame->uc.uc_flags);
+ err |= __put_user_sum_enabled(NULL, &frame->uc.uc_link);
+ err |= __save_altstack_sum_enabled(&frame->uc.uc_stack, regs->sp);
err |= setup_sigcontext(frame, regs);
- err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
- if (err)
+ err |= __asm_copy_to_user_sum_enabled(&frame->uc.uc_sigmask, set, sizeof(*set));
+ if (err) {
+ __disable_user_access();
return -EFAULT;
+ }
/* Set up to return from userspace. */
#ifdef CONFIG_MMU
@@ -344,9 +359,12 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
* For the nommu case we don't have a VDSO. Instead we push two
* instructions to call the rt_sigreturn syscall onto the user stack.
*/
- if (copy_to_user(&frame->sigreturn_code, __user_rt_sigreturn,
- sizeof(frame->sigreturn_code)))
+ if (__asm_copy_to_user_sum_enabled(&frame->sigreturn_code, __user_rt_sigreturn,
+ sizeof(frame->sigreturn_code))) {
+ __disable_user_access();
return -EFAULT;
+ }
+ __disable_user_access();
addr = (unsigned long)&frame->sigreturn_code;
/* Make sure the two instructions are pushed to icache. */
--
2.25.1
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 1/1] riscv: Optimize signal handling with sum enabled accesses
2025-12-02 7:43 ` [PATCH 1/1] " maohan4761
@ 2025-12-03 20:10 ` kernel test robot
0 siblings, 0 replies; 3+ messages in thread
From: kernel test robot @ 2025-12-03 20:10 UTC (permalink / raw)
To: maohan4761, pjw, palmer
Cc: oe-kbuild-all, guoren, linux-riscv, linux-kernel, Mao Han
Hi,
kernel test robot noticed the following build errors:
[auto build test ERROR on linus/master]
[also build test ERROR on v6.18]
[cannot apply to next-20251203]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/maohan4761-gmail-com/riscv-Optimize-signal-handling-with-sum-enabled-accesses/20251202-154643
base: linus/master
patch link: https://lore.kernel.org/r/20251202074303.81485-2-maohan4761%40gmail.com
patch subject: [PATCH 1/1] riscv: Optimize signal handling with sum enabled accesses
config: riscv-nommu_k210_sdcard_defconfig (https://download.01.org/0day-ci/archive/20251204/202512040335.j2VwCIKL-lkp@intel.com/config)
compiler: riscv64-linux-gcc (GCC) 15.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251204/202512040335.j2VwCIKL-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512040335.j2VwCIKL-lkp@intel.com/
All errors (new ones prefixed by >>):
arch/riscv/kernel/signal.c: In function 'restore_fp_state':
>> arch/riscv/kernel/signal.c:48:15: error: implicit declaration of function '__asm_copy_from_user_sum_enabled' [-Wimplicit-function-declaration]
48 | err = __asm_copy_from_user_sum_enabled(¤t->thread.fstate, state, sizeof(*state));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
arch/riscv/kernel/signal.c: In function 'save_fp_state':
>> arch/riscv/kernel/signal.c:63:15: error: implicit declaration of function '__asm_copy_to_user_sum_enabled' [-Wimplicit-function-declaration]
63 | err = __asm_copy_to_user_sum_enabled(state, ¤t->thread.fstate, sizeof(*state));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
arch/riscv/kernel/signal.c: In function 'save_v_state':
>> arch/riscv/kernel/signal.c:97:16: error: implicit declaration of function '__put_user_sum_enabled' [-Wimplicit-function-declaration]
97 | err |= __put_user_sum_enabled((__force void *)datap, &state->v_state.datap);
| ^~~~~~~~~~~~~~~~~~~~~~
arch/riscv/kernel/signal.c: In function '__restore_v_state':
>> arch/riscv/kernel/signal.c:136:15: error: implicit declaration of function '__get_user_sum_enabled' [-Wimplicit-function-declaration]
136 | err = __get_user_sum_enabled(datap, &state->v_state.datap);
| ^~~~~~~~~~~~~~~~~~~~~~
arch/riscv/kernel/signal.c: In function '__riscv_sys_rt_sigreturn':
>> arch/riscv/kernel/signal.c:241:9: error: implicit declaration of function '__enable_user_access' [-Wimplicit-function-declaration]
241 | __enable_user_access();
| ^~~~~~~~~~~~~~~~~~~~
>> arch/riscv/kernel/signal.c:252:9: error: implicit declaration of function '__disable_user_access' [-Wimplicit-function-declaration]
252 | __disable_user_access();
| ^~~~~~~~~~~~~~~~~~~~~
vim +/__asm_copy_from_user_sum_enabled +48 arch/riscv/kernel/signal.c
40
41 #ifdef CONFIG_FPU
42 static long restore_fp_state(struct pt_regs *regs,
43 union __riscv_fp_state __user *sc_fpregs)
44 {
45 long err;
46 struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
47
> 48 err = __asm_copy_from_user_sum_enabled(¤t->thread.fstate, state, sizeof(*state));
49 if (unlikely(err))
50 return err;
51
52 fstate_restore(current, regs);
53 return 0;
54 }
55
56 static long save_fp_state(struct pt_regs *regs,
57 union __riscv_fp_state __user *sc_fpregs)
58 {
59 long err;
60 struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
61
62 fstate_save(current, regs);
> 63 err = __asm_copy_to_user_sum_enabled(state, ¤t->thread.fstate, sizeof(*state));
64 return err;
65 }
66 #else
67 #define save_fp_state(task, regs) (0)
68 #define restore_fp_state(task, regs) (0)
69 #endif
70
71 #ifdef CONFIG_RISCV_ISA_V
72
73 static long save_v_state(struct pt_regs *regs, void __user **sc_vec)
74 {
75 struct __riscv_ctx_hdr __user *hdr;
76 struct __sc_riscv_v_state __user *state;
77 void __user *datap;
78 long err;
79
80 hdr = *sc_vec;
81 /* Place state to the user's signal context space after the hdr */
82 state = (struct __sc_riscv_v_state __user *)(hdr + 1);
83 /* Point datap right after the end of __sc_riscv_v_state */
84 datap = state + 1;
85
86 /* datap is designed to be 16 byte aligned for better performance */
87 WARN_ON(!IS_ALIGNED((unsigned long)datap, 16));
88
89 get_cpu_vector_context();
90 riscv_v_vstate_save(¤t->thread.vstate, regs);
91 put_cpu_vector_context();
92
93 /* Copy everything of vstate but datap. */
94 err = __asm_copy_to_user_sum_enabled(&state->v_state, ¤t->thread.vstate,
95 offsetof(struct __riscv_v_ext_state, datap));
96 /* Copy the pointer datap itself. */
> 97 err |= __put_user_sum_enabled((__force void *)datap, &state->v_state.datap);
98 /* Copy the whole vector content to user space datap. */
99 err |= __asm_copy_to_user_sum_enabled(datap, current->thread.vstate.datap, riscv_v_vsize);
100 /* Copy magic to the user space after saving all vector conetext */
101 err |= __put_user_sum_enabled(RISCV_V_MAGIC, &hdr->magic);
102 err |= __put_user_sum_enabled(riscv_v_sc_size, &hdr->size);
103 if (unlikely(err))
104 return err;
105
106 /* Only progress the sv_vec if everything has done successfully */
107 *sc_vec += riscv_v_sc_size;
108 return 0;
109 }
110
111 /*
112 * Restore Vector extension context from the user's signal frame. This function
113 * assumes a valid extension header. So magic and size checking must be done by
114 * the caller.
115 */
116 static long __restore_v_state(struct pt_regs *regs, void __user *sc_vec)
117 {
118 long err;
119 struct __sc_riscv_v_state __user *state = sc_vec;
120 void __user *datap;
121
122 /*
123 * Mark the vstate as clean prior performing the actual copy,
124 * to avoid getting the vstate incorrectly clobbered by the
125 * discarded vector state.
126 */
127 riscv_v_vstate_set_restore(current, regs);
128
129 /* Copy everything of __sc_riscv_v_state except datap. */
130 err = __asm_copy_from_user_sum_enabled(¤t->thread.vstate, &state->v_state,
131 offsetof(struct __riscv_v_ext_state, datap));
132 if (unlikely(err))
133 return err;
134
135 /* Copy the pointer datap itself. */
> 136 err = __get_user_sum_enabled(datap, &state->v_state.datap);
137 if (unlikely(err))
138 return err;
139 /*
140 * Copy the whole vector content from user space datap. Use
141 * copy_from_user to prevent information leak.
142 */
143 return __asm_copy_from_user_sum_enabled(current->thread.vstate.datap, datap, riscv_v_vsize);
144 }
145 #else
146 #define save_v_state(task, regs) (0)
147 #define __restore_v_state(task, regs) (0)
148 #endif
149
150 static long restore_sigcontext(struct pt_regs *regs,
151 struct sigcontext __user *sc)
152 {
153 void __user *sc_ext_ptr = &sc->sc_extdesc.hdr;
154 __u32 rsvd;
155 long err;
156 /* sc_regs is structured the same as the start of pt_regs */
157 err = __asm_copy_from_user_sum_enabled(regs, &sc->sc_regs, sizeof(sc->sc_regs));
158 if (unlikely(err))
159 return err;
160
161 /* Restore the floating-point state. */
162 if (has_fpu()) {
163 err = restore_fp_state(regs, &sc->sc_fpregs);
164 if (unlikely(err))
165 return err;
166 }
167
168 /* Check the reserved word before extensions parsing */
169 err = __get_user_sum_enabled(rsvd, &sc->sc_extdesc.reserved);
170 if (unlikely(err))
171 return err;
172 if (unlikely(rsvd))
173 return -EINVAL;
174
175 while (!err) {
176 __u32 magic, size;
177 struct __riscv_ctx_hdr __user *head = sc_ext_ptr;
178
179 err |= __get_user_sum_enabled(magic, &head->magic);
180 err |= __get_user_sum_enabled(size, &head->size);
181 if (unlikely(err))
182 return err;
183
184 sc_ext_ptr += sizeof(*head);
185 switch (magic) {
186 case END_MAGIC:
187 if (size != END_HDR_SIZE)
188 return -EINVAL;
189
190 return 0;
191 case RISCV_V_MAGIC:
192 if (!(has_vector() || has_xtheadvector()) || !riscv_v_vstate_query(regs) ||
193 size != riscv_v_sc_size)
194 return -EINVAL;
195
196 err = __restore_v_state(regs, sc_ext_ptr);
197 break;
198 default:
199 return -EINVAL;
200 }
201 sc_ext_ptr = (void __user *)head + size;
202 }
203 return err;
204 }
205
206 static size_t get_rt_frame_size(bool cal_all)
207 {
208 struct rt_sigframe __user *frame;
209 size_t frame_size;
210 size_t total_context_size = 0;
211
212 frame_size = sizeof(*frame);
213
214 if (has_vector() || has_xtheadvector()) {
215 if (cal_all || riscv_v_vstate_query(task_pt_regs(current)))
216 total_context_size += riscv_v_sc_size;
217 }
218
219 frame_size += total_context_size;
220
221 frame_size = round_up(frame_size, 16);
222 return frame_size;
223 }
224
225 SYSCALL_DEFINE0(rt_sigreturn)
226 {
227 struct pt_regs *regs = current_pt_regs();
228 struct rt_sigframe __user *frame;
229 struct task_struct *task;
230 sigset_t set;
231 size_t frame_size = get_rt_frame_size(false);
232
233 /* Always make any pending restarted system calls return -EINTR */
234 current->restart_block.fn = do_no_restart_syscall;
235
236 frame = (struct rt_sigframe __user *)regs->sp;
237
238 if (!access_ok(frame, frame_size))
239 goto badframe;
240
> 241 __enable_user_access();
242 if (__asm_copy_from_user_sum_enabled(&set, &frame->uc.uc_sigmask, sizeof(set)))
243 goto badframe;
244
245 set_current_blocked(&set);
246
247 if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
248 goto badframe;
249
250 if (restore_altstack(&frame->uc.uc_stack))
251 goto badframe;
252 __disable_user_access();
253
254 regs->cause = -1UL;
255
256 return regs->a0;
257
258 badframe:
259 __disable_user_access();
260 task = current;
261 if (show_unhandled_signals) {
262 pr_info_ratelimited(
263 "%s[%d]: bad frame in %s: frame=%p pc=%p sp=%p\n",
264 task->comm, task_pid_nr(task), __func__,
265 frame, (void *)regs->epc, (void *)regs->sp);
266 }
267 force_sig(SIGSEGV);
268 return 0;
269 }
270
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-12-03 20:11 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-02 7:43 [PATCH 0/1] riscv: Optimize signal handling with sum enabled accesses maohan4761
2025-12-02 7:43 ` [PATCH 1/1] " maohan4761
2025-12-03 20:10 ` kernel test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox