hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/arch/riscv/kernel/signal.c
....@@ -1,22 +1,9 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright (C) 2009 Sunplus Core Technology Co., Ltd.
34 * Chen Liqin <liqin.chen@sunplusct.com>
45 * Lennox Wu <lennox.wu@sunplusct.com>
56 * Copyright (C) 2012 Regents of the University of California
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by
9
- * the Free Software Foundation; either version 2 of the License, or
10
- * (at your option) any later version.
11
- *
12
- * This program is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- * GNU General Public License for more details.
16
- *
17
- * You should have received a copy of the GNU General Public License
18
- * along with this program; if not, see the file COPYING, or write
19
- * to the Free Software Foundation, Inc.,
207 */
218
229 #include <linux/signal.h>
....@@ -29,53 +16,83 @@
2916 #include <asm/vdso.h>
3017 #include <asm/switch_to.h>
3118 #include <asm/csr.h>
19
+#include <asm/cacheflush.h>
20
+
21
+extern u32 __user_rt_sigreturn[2];
3222
3323 #define DEBUG_SIG 0
3424
3525 struct rt_sigframe {
3626 struct siginfo info;
3727 struct ucontext uc;
28
+#ifndef CONFIG_MMU
29
+ u32 sigreturn_code[2];
30
+#endif
3831 };
3932
40
-static long restore_d_state(struct pt_regs *regs,
41
- struct __riscv_d_ext_state __user *state)
33
+#ifdef CONFIG_FPU
34
+static long restore_fp_state(struct pt_regs *regs,
35
+ union __riscv_fp_state __user *sc_fpregs)
4236 {
4337 long err;
44
- err = __copy_from_user(&current->thread.fstate, state, sizeof(*state));
45
- if (likely(!err))
46
- fstate_restore(current, regs);
47
- return err;
48
-}
49
-
50
-static long save_d_state(struct pt_regs *regs,
51
- struct __riscv_d_ext_state __user *state)
52
-{
53
- fstate_save(current, regs);
54
- return __copy_to_user(state, &current->thread.fstate, sizeof(*state));
55
-}
56
-
57
-static long restore_sigcontext(struct pt_regs *regs,
58
- struct sigcontext __user *sc)
59
-{
60
- long err;
38
+ struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
6139 size_t i;
62
- /* sc_regs is structured the same as the start of pt_regs */
63
- err = __copy_from_user(regs, &sc->sc_regs, sizeof(sc->sc_regs));
40
+
41
+ err = __copy_from_user(&current->thread.fstate, state, sizeof(*state));
6442 if (unlikely(err))
6543 return err;
66
- /* Restore the floating-point state. */
67
- err = restore_d_state(regs, &sc->sc_fpregs.d);
68
- if (unlikely(err))
69
- return err;
44
+
45
+ fstate_restore(current, regs);
46
+
7047 /* We support no other extension state at this time. */
71
- for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++) {
48
+ for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
7249 u32 value;
73
- err = __get_user(value, &sc->sc_fpregs.q.reserved[i]);
50
+
51
+ err = __get_user(value, &sc_fpregs->q.reserved[i]);
7452 if (unlikely(err))
7553 break;
7654 if (value != 0)
7755 return -EINVAL;
7856 }
57
+
58
+ return err;
59
+}
60
+
61
+static long save_fp_state(struct pt_regs *regs,
62
+ union __riscv_fp_state __user *sc_fpregs)
63
+{
64
+ long err;
65
+ struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
66
+ size_t i;
67
+
68
+ fstate_save(current, regs);
69
+ err = __copy_to_user(state, &current->thread.fstate, sizeof(*state));
70
+ if (unlikely(err))
71
+ return err;
72
+
73
+ /* We support no other extension state at this time. */
74
+ for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
75
+ err = __put_user(0, &sc_fpregs->q.reserved[i]);
76
+ if (unlikely(err))
77
+ break;
78
+ }
79
+
80
+ return err;
81
+}
82
+#else
83
+#define save_fp_state(task, regs) (0)
84
+#define restore_fp_state(task, regs) (0)
85
+#endif
86
+
87
+static long restore_sigcontext(struct pt_regs *regs,
88
+ struct sigcontext __user *sc)
89
+{
90
+ long err;
91
+ /* sc_regs is structured the same as the start of pt_regs */
92
+ err = __copy_from_user(regs, &sc->sc_regs, sizeof(sc->sc_regs));
93
+ /* Restore the floating-point state. */
94
+ if (has_fpu)
95
+ err |= restore_fp_state(regs, &sc->sc_fpregs);
7996 return err;
8097 }
8198
....@@ -91,7 +108,7 @@
91108
92109 frame = (struct rt_sigframe __user *)regs->sp;
93110
94
- if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
111
+ if (!access_ok(frame, sizeof(*frame)))
95112 goto badframe;
96113
97114 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
....@@ -105,6 +122,8 @@
105122 if (restore_altstack(&frame->uc.uc_stack))
106123 goto badframe;
107124
125
+ regs->cause = -1UL;
126
+
108127 return regs->a0;
109128
110129 badframe:
....@@ -113,9 +132,9 @@
113132 pr_info_ratelimited(
114133 "%s[%d]: bad frame in %s: frame=%p pc=%p sp=%p\n",
115134 task->comm, task_pid_nr(task), __func__,
116
- frame, (void *)regs->sepc, (void *)regs->sp);
135
+ frame, (void *)regs->epc, (void *)regs->sp);
117136 }
118
- force_sig(SIGSEGV, task);
137
+ force_sig(SIGSEGV);
119138 return 0;
120139 }
121140
....@@ -124,14 +143,11 @@
124143 {
125144 struct sigcontext __user *sc = &frame->uc.uc_mcontext;
126145 long err;
127
- size_t i;
128146 /* sc_regs is structured the same as the start of pt_regs */
129147 err = __copy_to_user(&sc->sc_regs, regs, sizeof(sc->sc_regs));
130148 /* Save the floating-point state. */
131
- err |= save_d_state(regs, &sc->sc_fpregs.d);
132
- /* We support no other extension state at this time. */
133
- for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++)
134
- err |= __put_user(0, &sc->sc_fpregs.q.reserved[i]);
149
+ if (has_fpu)
150
+ err |= save_fp_state(regs, &sc->sc_fpregs);
135151 return err;
136152 }
137153
....@@ -158,15 +174,15 @@
158174 return (void __user *)sp;
159175 }
160176
161
-
162177 static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
163178 struct pt_regs *regs)
164179 {
165180 struct rt_sigframe __user *frame;
166181 long err = 0;
182
+ unsigned long __maybe_unused addr;
167183
168184 frame = get_sigframe(ksig, regs, sizeof(*frame));
169
- if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
185
+ if (!access_ok(frame, sizeof(*frame)))
170186 return -EFAULT;
171187
172188 err |= copy_siginfo_to_user(&frame->info, &ksig->info);
....@@ -181,8 +197,24 @@
181197 return -EFAULT;
182198
183199 /* Set up to return from userspace. */
200
+#ifdef CONFIG_MMU
184201 regs->ra = (unsigned long)VDSO_SYMBOL(
185202 current->mm->context.vdso, rt_sigreturn);
203
+#else
204
+ /*
205
+ * For the nommu case we don't have a VDSO. Instead we push two
206
+ * instructions to call the rt_sigreturn syscall onto the user stack.
207
+ */
208
+ if (copy_to_user(&frame->sigreturn_code, __user_rt_sigreturn,
209
+ sizeof(frame->sigreturn_code)))
210
+ return -EFAULT;
211
+
212
+ addr = (unsigned long)&frame->sigreturn_code;
213
+ /* Make sure the two instructions are pushed to icache. */
214
+ flush_icache_range(addr, addr + sizeof(frame->sigreturn_code));
215
+
216
+ regs->ra = addr;
217
+#endif /* CONFIG_MMU */
186218
187219 /*
188220 * Set up registers for signal handler.
....@@ -191,7 +223,7 @@
191223 * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
192224 * since some things rely on this (e.g. glibc's debug/segfault.c).
193225 */
194
- regs->sepc = (unsigned long)ksig->ka.sa.sa_handler;
226
+ regs->epc = (unsigned long)ksig->ka.sa.sa_handler;
195227 regs->sp = (unsigned long)frame;
196228 regs->a0 = ksig->sig; /* a0: signal number */
197229 regs->a1 = (unsigned long)(&frame->info); /* a1: siginfo pointer */
....@@ -200,7 +232,7 @@
200232 #if DEBUG_SIG
201233 pr_info("SIG deliver (%s:%d): sig=%d pc=%p ra=%p sp=%p\n",
202234 current->comm, task_pid_nr(current), ksig->sig,
203
- (void *)regs->sepc, (void *)regs->ra, frame);
235
+ (void *)regs->epc, (void *)regs->ra, frame);
204236 #endif
205237
206238 return 0;
....@@ -212,7 +244,9 @@
212244 int ret;
213245
214246 /* Are we from a system call? */
215
- if (regs->scause == EXC_SYSCALL) {
247
+ if (regs->cause == EXC_SYSCALL) {
248
+ /* Avoid additional syscall restarting via ret_from_exception */
249
+ regs->cause = -1UL;
216250 /* If so, check system call restarting.. */
217251 switch (regs->a0) {
218252 case -ERESTART_RESTARTBLOCK:
....@@ -225,10 +259,10 @@
225259 regs->a0 = -EINTR;
226260 break;
227261 }
228
- /* fallthrough */
262
+ fallthrough;
229263 case -ERESTARTNOINTR:
230264 regs->a0 = regs->orig_a0;
231
- regs->sepc -= 0x4;
265
+ regs->epc -= 0x4;
232266 break;
233267 }
234268 }
....@@ -250,19 +284,22 @@
250284 }
251285
252286 /* Did we come from a system call? */
253
- if (regs->scause == EXC_SYSCALL) {
287
+ if (regs->cause == EXC_SYSCALL) {
288
+ /* Avoid additional syscall restarting via ret_from_exception */
289
+ regs->cause = -1UL;
290
+
254291 /* Restart the system call - no handlers present */
255292 switch (regs->a0) {
256293 case -ERESTARTNOHAND:
257294 case -ERESTARTSYS:
258295 case -ERESTARTNOINTR:
259296 regs->a0 = regs->orig_a0;
260
- regs->sepc -= 0x4;
297
+ regs->epc -= 0x4;
261298 break;
262299 case -ERESTART_RESTARTBLOCK:
263300 regs->a0 = regs->orig_a0;
264301 regs->a7 = __NR_restart_syscall;
265
- regs->sepc -= 0x4;
302
+ regs->epc -= 0x4;
266303 break;
267304 }
268305 }
....@@ -278,15 +315,13 @@
278315 * notification of userspace execution resumption
279316 * - triggered by the _TIF_WORK_MASK flags
280317 */
281
-asmlinkage void do_notify_resume(struct pt_regs *regs,
282
- unsigned long thread_info_flags)
318
+asmlinkage __visible void do_notify_resume(struct pt_regs *regs,
319
+ unsigned long thread_info_flags)
283320 {
284321 /* Handle pending signal delivery */
285
- if (thread_info_flags & _TIF_SIGPENDING)
322
+ if (thread_info_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
286323 do_signal(regs);
287324
288
- if (thread_info_flags & _TIF_NOTIFY_RESUME) {
289
- clear_thread_flag(TIF_NOTIFY_RESUME);
325
+ if (thread_info_flags & _TIF_NOTIFY_RESUME)
290326 tracehook_notify_resume(regs);
291
- }
292327 }