hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/arch/nds32/kernel/signal.c
....@@ -12,6 +12,7 @@
1212 #include <asm/cacheflush.h>
1313 #include <asm/ucontext.h>
1414 #include <asm/unistd.h>
15
+#include <asm/fpu.h>
1516
1617 #include <asm/ptrace.h>
1718 #include <asm/vdso.h>
....@@ -20,6 +21,60 @@
2021 struct siginfo info;
2122 struct ucontext uc;
2223 };
24
+#if IS_ENABLED(CONFIG_FPU)
25
+static inline int restore_sigcontext_fpu(struct pt_regs *regs,
26
+ struct sigcontext __user *sc)
27
+{
28
+ struct task_struct *tsk = current;
29
+ unsigned long used_math_flag;
30
+ int ret = 0;
31
+
32
+ clear_used_math();
33
+ __get_user_error(used_math_flag, &sc->used_math_flag, ret);
34
+
35
+ if (!used_math_flag)
36
+ return 0;
37
+ set_used_math();
38
+
39
+#if IS_ENABLED(CONFIG_LAZY_FPU)
40
+ preempt_disable();
41
+ if (current == last_task_used_math) {
42
+ last_task_used_math = NULL;
43
+ disable_ptreg_fpu(regs);
44
+ }
45
+ preempt_enable();
46
+#else
47
+ clear_fpu(regs);
48
+#endif
49
+
50
+ return __copy_from_user(&tsk->thread.fpu, &sc->fpu,
51
+ sizeof(struct fpu_struct));
52
+}
53
+
54
+static inline int setup_sigcontext_fpu(struct pt_regs *regs,
55
+ struct sigcontext __user *sc)
56
+{
57
+ struct task_struct *tsk = current;
58
+ int ret = 0;
59
+
60
+ __put_user_error(used_math(), &sc->used_math_flag, ret);
61
+
62
+ if (!used_math())
63
+ return ret;
64
+
65
+ preempt_disable();
66
+#if IS_ENABLED(CONFIG_LAZY_FPU)
67
+ if (last_task_used_math == tsk)
68
+ save_fpu(last_task_used_math);
69
+#else
70
+ unlazy_fpu(tsk);
71
+#endif
72
+ ret = __copy_to_user(&sc->fpu, &tsk->thread.fpu,
73
+ sizeof(struct fpu_struct));
74
+ preempt_enable();
75
+ return ret;
76
+}
77
+#endif
2378
2479 static int restore_sigframe(struct pt_regs *regs,
2580 struct rt_sigframe __user * sf)
....@@ -69,7 +124,9 @@
69124 __get_user_error(regs->le, &sf->uc.uc_mcontext.zol.nds32_le, err);
70125 __get_user_error(regs->lb, &sf->uc.uc_mcontext.zol.nds32_lb, err);
71126 #endif
72
-
127
+#if IS_ENABLED(CONFIG_FPU)
128
+ err |= restore_sigcontext_fpu(regs, &sf->uc.uc_mcontext);
129
+#endif
73130 /*
74131 * Avoid sys_rt_sigreturn() restarting.
75132 */
....@@ -94,7 +151,7 @@
94151
95152 frame = (struct rt_sigframe __user *)regs->sp;
96153
97
- if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
154
+ if (!access_ok(frame, sizeof(*frame)))
98155 goto badframe;
99156
100157 if (restore_sigframe(regs, frame))
....@@ -106,7 +163,7 @@
106163 return regs->uregs[0];
107164
108165 badframe:
109
- force_sig(SIGSEGV, current);
166
+ force_sig(SIGSEGV);
110167 return 0;
111168 }
112169
....@@ -152,6 +209,9 @@
152209 __put_user_error(regs->lc, &sf->uc.uc_mcontext.zol.nds32_lc, err);
153210 __put_user_error(regs->le, &sf->uc.uc_mcontext.zol.nds32_le, err);
154211 __put_user_error(regs->lb, &sf->uc.uc_mcontext.zol.nds32_lb, err);
212
+#endif
213
+#if IS_ENABLED(CONFIG_FPU)
214
+ err |= setup_sigcontext_fpu(regs, &sf->uc.uc_mcontext);
155215 #endif
156216
157217 __put_user_error(current->thread.trap_no, &sf->uc.uc_mcontext.trap_no,
....@@ -215,7 +275,7 @@
215275 get_sigframe(ksig, regs, sizeof(*frame));
216276 int err = 0;
217277
218
- if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
278
+ if (!access_ok(frame, sizeof(*frame)))
219279 return -EFAULT;
220280
221281 __put_user_error(0, &frame->uc.uc_flags, err);
....@@ -256,6 +316,7 @@
256316 regs->uregs[0] = -EINTR;
257317 break;
258318 }
319
+ fallthrough;
259320 case -ERESTARTNOINTR:
260321 regs->uregs[0] = regs->orig_r0;
261322 regs->ipc -= 4;
....@@ -300,6 +361,7 @@
300361 switch (regs->uregs[0]) {
301362 case -ERESTART_RESTARTBLOCK:
302363 regs->uregs[15] = __NR_restart_syscall;
364
+ fallthrough;
303365 case -ERESTARTNOHAND:
304366 case -ERESTARTSYS:
305367 case -ERESTARTNOINTR:
....@@ -314,11 +376,9 @@
314376 asmlinkage void
315377 do_notify_resume(struct pt_regs *regs, unsigned int thread_flags)
316378 {
317
- if (thread_flags & _TIF_SIGPENDING)
379
+ if (thread_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL))
318380 do_signal(regs);
319381
320
- if (thread_flags & _TIF_NOTIFY_RESUME) {
321
- clear_thread_flag(TIF_NOTIFY_RESUME);
382
+ if (thread_flags & _TIF_NOTIFY_RESUME)
322383 tracehook_notify_resume(regs);
323
- }
324384 }