* [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