hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
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>
....@@ -30,52 +17,81 @@
3017 #include <asm/switch_to.h>
3118 #include <asm/csr.h>
3219
20
+extern u32 __user_rt_sigreturn[2];
21
+
3322 #define DEBUG_SIG 0
3423
3524 struct rt_sigframe {
3625 struct siginfo info;
3726 struct ucontext uc;
27
+#ifndef CONFIG_MMU
28
+ u32 sigreturn_code[2];
29
+#endif
3830 };
3931
40
-static long restore_d_state(struct pt_regs *regs,
41
- struct __riscv_d_ext_state __user *state)
32
+#ifdef CONFIG_FPU
33
+static long restore_fp_state(struct pt_regs *regs,
34
+ union __riscv_fp_state __user *sc_fpregs)
4235 {
4336 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;
37
+ struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
6138 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));
39
+
40
+ err = __copy_from_user(&current->thread.fstate, state, sizeof(*state));
6441 if (unlikely(err))
6542 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;
43
+
44
+ fstate_restore(current, regs);
45
+
7046 /* We support no other extension state at this time. */
71
- for (i = 0; i < ARRAY_SIZE(sc->sc_fpregs.q.reserved); i++) {
47
+ for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
7248 u32 value;
73
- err = __get_user(value, &sc->sc_fpregs.q.reserved[i]);
49
+
50
+ err = __get_user(value, &sc_fpregs->q.reserved[i]);
7451 if (unlikely(err))
7552 break;
7653 if (value != 0)
7754 return -EINVAL;
7855 }
56
+
57
+ return err;
58
+}
59
+
60
+static long save_fp_state(struct pt_regs *regs,
61
+ union __riscv_fp_state __user *sc_fpregs)
62
+{
63
+ long err;
64
+ struct __riscv_d_ext_state __user *state = &sc_fpregs->d;
65
+ size_t i;
66
+
67
+ fstate_save(current, regs);
68
+ err = __copy_to_user(state, &current->thread.fstate, sizeof(*state));
69
+ if (unlikely(err))
70
+ return err;
71
+
72
+ /* We support no other extension state at this time. */
73
+ for (i = 0; i < ARRAY_SIZE(sc_fpregs->q.reserved); i++) {
74
+ err = __put_user(0, &sc_fpregs->q.reserved[i]);
75
+ if (unlikely(err))
76
+ break;
77
+ }
78
+
79
+ return err;
80
+}
81
+#else
82
+#define save_fp_state(task, regs) (0)
83
+#define restore_fp_state(task, regs) (0)
84
+#endif
85
+
86
+static long restore_sigcontext(struct pt_regs *regs,
87
+ struct sigcontext __user *sc)
88
+{
89
+ long err;
90
+ /* sc_regs is structured the same as the start of pt_regs */
91
+ err = __copy_from_user(regs, &sc->sc_regs, sizeof(sc->sc_regs));
92
+ /* Restore the floating-point state. */
93
+ if (has_fpu)
94
+ err |= restore_fp_state(regs, &sc->sc_fpregs);
7995 return err;
8096 }
8197
....@@ -91,7 +107,7 @@
91107
92108 frame = (struct rt_sigframe __user *)regs->sp;
93109
94
- if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
110
+ if (!access_ok(frame, sizeof(*frame)))
95111 goto badframe;
96112
97113 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
....@@ -105,6 +121,8 @@
105121 if (restore_altstack(&frame->uc.uc_stack))
106122 goto badframe;
107123
124
+ regs->cause = -1UL;
125
+
108126 return regs->a0;
109127
110128 badframe:
....@@ -113,9 +131,9 @@
113131 pr_info_ratelimited(
114132 "%s[%d]: bad frame in %s: frame=%p pc=%p sp=%p\n",
115133 task->comm, task_pid_nr(task), __func__,
116
- frame, (void *)regs->sepc, (void *)regs->sp);
134
+ frame, (void *)regs->epc, (void *)regs->sp);
117135 }
118
- force_sig(SIGSEGV, task);
136
+ force_sig(SIGSEGV);
119137 return 0;
120138 }
121139
....@@ -124,14 +142,11 @@
124142 {
125143 struct sigcontext __user *sc = &frame->uc.uc_mcontext;
126144 long err;
127
- size_t i;
128145 /* sc_regs is structured the same as the start of pt_regs */
129146 err = __copy_to_user(&sc->sc_regs, regs, sizeof(sc->sc_regs));
130147 /* 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]);
148
+ if (has_fpu)
149
+ err |= save_fp_state(regs, &sc->sc_fpregs);
135150 return err;
136151 }
137152
....@@ -158,7 +173,6 @@
158173 return (void __user *)sp;
159174 }
160175
161
-
162176 static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
163177 struct pt_regs *regs)
164178 {
....@@ -166,7 +180,7 @@
166180 long err = 0;
167181
168182 frame = get_sigframe(ksig, regs, sizeof(*frame));
169
- if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
183
+ if (!access_ok(frame, sizeof(*frame)))
170184 return -EFAULT;
171185
172186 err |= copy_siginfo_to_user(&frame->info, &ksig->info);
....@@ -181,8 +195,19 @@
181195 return -EFAULT;
182196
183197 /* Set up to return from userspace. */
198
+#ifdef CONFIG_MMU
184199 regs->ra = (unsigned long)VDSO_SYMBOL(
185200 current->mm->context.vdso, rt_sigreturn);
201
+#else
202
+ /*
203
+ * For the nommu case we don't have a VDSO. Instead we push two
204
+ * instructions to call the rt_sigreturn syscall onto the user stack.
205
+ */
206
+ if (copy_to_user(&frame->sigreturn_code, __user_rt_sigreturn,
207
+ sizeof(frame->sigreturn_code)))
208
+ return -EFAULT;
209
+ regs->ra = (unsigned long)&frame->sigreturn_code;
210
+#endif /* CONFIG_MMU */
186211
187212 /*
188213 * Set up registers for signal handler.
....@@ -191,7 +216,7 @@
191216 * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
192217 * since some things rely on this (e.g. glibc's debug/segfault.c).
193218 */
194
- regs->sepc = (unsigned long)ksig->ka.sa.sa_handler;
219
+ regs->epc = (unsigned long)ksig->ka.sa.sa_handler;
195220 regs->sp = (unsigned long)frame;
196221 regs->a0 = ksig->sig; /* a0: signal number */
197222 regs->a1 = (unsigned long)(&frame->info); /* a1: siginfo pointer */
....@@ -200,7 +225,7 @@
200225 #if DEBUG_SIG
201226 pr_info("SIG deliver (%s:%d): sig=%d pc=%p ra=%p sp=%p\n",
202227 current->comm, task_pid_nr(current), ksig->sig,
203
- (void *)regs->sepc, (void *)regs->ra, frame);
228
+ (void *)regs->epc, (void *)regs->ra, frame);
204229 #endif
205230
206231 return 0;
....@@ -212,7 +237,9 @@
212237 int ret;
213238
214239 /* Are we from a system call? */
215
- if (regs->scause == EXC_SYSCALL) {
240
+ if (regs->cause == EXC_SYSCALL) {
241
+ /* Avoid additional syscall restarting via ret_from_exception */
242
+ regs->cause = -1UL;
216243 /* If so, check system call restarting.. */
217244 switch (regs->a0) {
218245 case -ERESTART_RESTARTBLOCK:
....@@ -225,10 +252,10 @@
225252 regs->a0 = -EINTR;
226253 break;
227254 }
228
- /* fallthrough */
255
+ fallthrough;
229256 case -ERESTARTNOINTR:
230257 regs->a0 = regs->orig_a0;
231
- regs->sepc -= 0x4;
258
+ regs->epc -= 0x4;
232259 break;
233260 }
234261 }
....@@ -250,19 +277,22 @@
250277 }
251278
252279 /* Did we come from a system call? */
253
- if (regs->scause == EXC_SYSCALL) {
280
+ if (regs->cause == EXC_SYSCALL) {
281
+ /* Avoid additional syscall restarting via ret_from_exception */
282
+ regs->cause = -1UL;
283
+
254284 /* Restart the system call - no handlers present */
255285 switch (regs->a0) {
256286 case -ERESTARTNOHAND:
257287 case -ERESTARTSYS:
258288 case -ERESTARTNOINTR:
259289 regs->a0 = regs->orig_a0;
260
- regs->sepc -= 0x4;
290
+ regs->epc -= 0x4;
261291 break;
262292 case -ERESTART_RESTARTBLOCK:
263293 regs->a0 = regs->orig_a0;
264294 regs->a7 = __NR_restart_syscall;
265
- regs->sepc -= 0x4;
295
+ regs->epc -= 0x4;
266296 break;
267297 }
268298 }
....@@ -278,15 +308,13 @@
278308 * notification of userspace execution resumption
279309 * - triggered by the _TIF_WORK_MASK flags
280310 */
281
-asmlinkage void do_notify_resume(struct pt_regs *regs,
282
- unsigned long thread_info_flags)
311
+asmlinkage __visible void do_notify_resume(struct pt_regs *regs,
312
+ unsigned long thread_info_flags)
283313 {
284314 /* Handle pending signal delivery */
285
- if (thread_info_flags & _TIF_SIGPENDING)
315
+ if (thread_info_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
286316 do_signal(regs);
287317
288
- if (thread_info_flags & _TIF_NOTIFY_RESUME) {
289
- clear_thread_flag(TIF_NOTIFY_RESUME);
318
+ if (thread_info_flags & _TIF_NOTIFY_RESUME)
290319 tracehook_notify_resume(regs);
291
- }
292320 }