.. | .. |
---|
12 | 12 | #include <asm/cacheflush.h> |
---|
13 | 13 | #include <asm/ucontext.h> |
---|
14 | 14 | #include <asm/unistd.h> |
---|
| 15 | +#include <asm/fpu.h> |
---|
15 | 16 | |
---|
16 | 17 | #include <asm/ptrace.h> |
---|
17 | 18 | #include <asm/vdso.h> |
---|
.. | .. |
---|
20 | 21 | struct siginfo info; |
---|
21 | 22 | struct ucontext uc; |
---|
22 | 23 | }; |
---|
| 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 |
---|
23 | 78 | |
---|
24 | 79 | static int restore_sigframe(struct pt_regs *regs, |
---|
25 | 80 | struct rt_sigframe __user * sf) |
---|
.. | .. |
---|
69 | 124 | __get_user_error(regs->le, &sf->uc.uc_mcontext.zol.nds32_le, err); |
---|
70 | 125 | __get_user_error(regs->lb, &sf->uc.uc_mcontext.zol.nds32_lb, err); |
---|
71 | 126 | #endif |
---|
72 | | - |
---|
| 127 | +#if IS_ENABLED(CONFIG_FPU) |
---|
| 128 | + err |= restore_sigcontext_fpu(regs, &sf->uc.uc_mcontext); |
---|
| 129 | +#endif |
---|
73 | 130 | /* |
---|
74 | 131 | * Avoid sys_rt_sigreturn() restarting. |
---|
75 | 132 | */ |
---|
.. | .. |
---|
94 | 151 | |
---|
95 | 152 | frame = (struct rt_sigframe __user *)regs->sp; |
---|
96 | 153 | |
---|
97 | | - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
---|
| 154 | + if (!access_ok(frame, sizeof(*frame))) |
---|
98 | 155 | goto badframe; |
---|
99 | 156 | |
---|
100 | 157 | if (restore_sigframe(regs, frame)) |
---|
.. | .. |
---|
106 | 163 | return regs->uregs[0]; |
---|
107 | 164 | |
---|
108 | 165 | badframe: |
---|
109 | | - force_sig(SIGSEGV, current); |
---|
| 166 | + force_sig(SIGSEGV); |
---|
110 | 167 | return 0; |
---|
111 | 168 | } |
---|
112 | 169 | |
---|
.. | .. |
---|
152 | 209 | __put_user_error(regs->lc, &sf->uc.uc_mcontext.zol.nds32_lc, err); |
---|
153 | 210 | __put_user_error(regs->le, &sf->uc.uc_mcontext.zol.nds32_le, err); |
---|
154 | 211 | __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); |
---|
155 | 215 | #endif |
---|
156 | 216 | |
---|
157 | 217 | __put_user_error(current->thread.trap_no, &sf->uc.uc_mcontext.trap_no, |
---|
.. | .. |
---|
215 | 275 | get_sigframe(ksig, regs, sizeof(*frame)); |
---|
216 | 276 | int err = 0; |
---|
217 | 277 | |
---|
218 | | - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
---|
| 278 | + if (!access_ok(frame, sizeof(*frame))) |
---|
219 | 279 | return -EFAULT; |
---|
220 | 280 | |
---|
221 | 281 | __put_user_error(0, &frame->uc.uc_flags, err); |
---|
.. | .. |
---|
256 | 316 | regs->uregs[0] = -EINTR; |
---|
257 | 317 | break; |
---|
258 | 318 | } |
---|
| 319 | + fallthrough; |
---|
259 | 320 | case -ERESTARTNOINTR: |
---|
260 | 321 | regs->uregs[0] = regs->orig_r0; |
---|
261 | 322 | regs->ipc -= 4; |
---|
.. | .. |
---|
300 | 361 | switch (regs->uregs[0]) { |
---|
301 | 362 | case -ERESTART_RESTARTBLOCK: |
---|
302 | 363 | regs->uregs[15] = __NR_restart_syscall; |
---|
| 364 | + fallthrough; |
---|
303 | 365 | case -ERESTARTNOHAND: |
---|
304 | 366 | case -ERESTARTSYS: |
---|
305 | 367 | case -ERESTARTNOINTR: |
---|
.. | .. |
---|
314 | 376 | asmlinkage void |
---|
315 | 377 | do_notify_resume(struct pt_regs *regs, unsigned int thread_flags) |
---|
316 | 378 | { |
---|
317 | | - if (thread_flags & _TIF_SIGPENDING) |
---|
| 379 | + if (thread_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) |
---|
318 | 380 | do_signal(regs); |
---|
319 | 381 | |
---|
320 | | - if (thread_flags & _TIF_NOTIFY_RESUME) { |
---|
321 | | - clear_thread_flag(TIF_NOTIFY_RESUME); |
---|
| 382 | + if (thread_flags & _TIF_NOTIFY_RESUME) |
---|
322 | 383 | tracehook_notify_resume(regs); |
---|
323 | | - } |
---|
324 | 384 | } |
---|