Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * This file is subject to the terms and conditions of the GNU General Public | |
3 | * License. See the file "COPYING" in the main directory of this archive | |
4 | * for more details. | |
5 | * | |
6 | * Copyright (C) 1991, 1992 Linus Torvalds | |
7 | * Copyright (C) 1994 - 2000 Ralf Baechle | |
8 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | |
ca750649 | 9 | * Copyright (C) 2014, Imagination Technologies Ltd. |
1da177e4 | 10 | */ |
02416dcf | 11 | #include <linux/cache.h> |
c3fc5cd5 | 12 | #include <linux/context_tracking.h> |
1f717929 | 13 | #include <linux/irqflags.h> |
1da177e4 LT |
14 | #include <linux/sched.h> |
15 | #include <linux/mm.h> | |
16 | #include <linux/personality.h> | |
17 | #include <linux/smp.h> | |
1da177e4 LT |
18 | #include <linux/kernel.h> |
19 | #include <linux/signal.h> | |
20 | #include <linux/errno.h> | |
21 | #include <linux/wait.h> | |
22 | #include <linux/ptrace.h> | |
23 | #include <linux/unistd.h> | |
40e084a5 | 24 | #include <linux/uprobes.h> |
1da177e4 | 25 | #include <linux/compiler.h> |
dbda6ac0 | 26 | #include <linux/syscalls.h> |
faea6234 | 27 | #include <linux/uaccess.h> |
733e5e4b | 28 | #include <linux/tracehook.h> |
1da177e4 | 29 | |
e50c0a8f | 30 | #include <asm/abi.h> |
1da177e4 LT |
31 | #include <asm/asm.h> |
32 | #include <linux/bitops.h> | |
33 | #include <asm/cacheflush.h> | |
34 | #include <asm/fpu.h> | |
35 | #include <asm/sim.h> | |
1da177e4 LT |
36 | #include <asm/ucontext.h> |
37 | #include <asm/cpu-features.h> | |
02416dcf | 38 | #include <asm/war.h> |
b81947c6 | 39 | #include <asm/dsp.h> |
01be057b | 40 | #include <asm/inst.h> |
bf82cb30 | 41 | #include <asm/msa.h> |
1da177e4 LT |
42 | |
43 | #include "signal-common.h" | |
44 | ||
2db9ca0a PB |
45 | static int (*save_fp_context)(void __user *sc); |
46 | static int (*restore_fp_context)(void __user *sc); | |
137f6f3e | 47 | |
66680583 RB |
48 | struct sigframe { |
49 | u32 sf_ass[4]; /* argument save space for o32 */ | |
d814c28c | 50 | u32 sf_pad[2]; /* Was: signal trampoline */ |
f1fe2d21 PB |
51 | |
52 | /* Matches struct ucontext from its uc_mcontext field onwards */ | |
66680583 RB |
53 | struct sigcontext sf_sc; |
54 | sigset_t sf_mask; | |
f1fe2d21 | 55 | unsigned long long sf_extcontext[0]; |
66680583 RB |
56 | }; |
57 | ||
c0b9bae9 FBH |
58 | struct rt_sigframe { |
59 | u32 rs_ass[4]; /* argument save space for o32 */ | |
d814c28c | 60 | u32 rs_pad[2]; /* Was: signal trampoline */ |
c0b9bae9 FBH |
61 | struct siginfo rs_info; |
62 | struct ucontext rs_uc; | |
63 | }; | |
64 | ||
b2ead528 PB |
65 | /* |
66 | * Thread saved context copy to/from a signal context presumed to be on the | |
67 | * user stack, and therefore accessed with appropriate macros from uaccess.h. | |
68 | */ | |
2db9ca0a | 69 | static int copy_fp_to_sigcontext(void __user *sc) |
b2ead528 | 70 | { |
2db9ca0a PB |
71 | struct mips_abi *abi = current->thread.abi; |
72 | uint64_t __user *fpregs = sc + abi->off_sc_fpregs; | |
73 | uint32_t __user *csr = sc + abi->off_sc_fpc_csr; | |
b2ead528 PB |
74 | int i; |
75 | int err = 0; | |
6f0aba63 | 76 | int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1; |
b2ead528 | 77 | |
6f0aba63 | 78 | for (i = 0; i < NUM_FPU_REGS; i += inc) { |
b2ead528 PB |
79 | err |= |
80 | __put_user(get_fpr64(¤t->thread.fpu.fpr[i], 0), | |
2db9ca0a | 81 | &fpregs[i]); |
b2ead528 | 82 | } |
2db9ca0a | 83 | err |= __put_user(current->thread.fpu.fcr31, csr); |
b2ead528 PB |
84 | |
85 | return err; | |
86 | } | |
87 | ||
2db9ca0a | 88 | static int copy_fp_from_sigcontext(void __user *sc) |
b2ead528 | 89 | { |
2db9ca0a PB |
90 | struct mips_abi *abi = current->thread.abi; |
91 | uint64_t __user *fpregs = sc + abi->off_sc_fpregs; | |
92 | uint32_t __user *csr = sc + abi->off_sc_fpc_csr; | |
b2ead528 PB |
93 | int i; |
94 | int err = 0; | |
6f0aba63 | 95 | int inc = test_thread_flag(TIF_32BIT_FPREGS) ? 2 : 1; |
b2ead528 PB |
96 | u64 fpr_val; |
97 | ||
6f0aba63 | 98 | for (i = 0; i < NUM_FPU_REGS; i += inc) { |
2db9ca0a | 99 | err |= __get_user(fpr_val, &fpregs[i]); |
b2ead528 PB |
100 | set_fpr64(¤t->thread.fpu.fpr[i], 0, fpr_val); |
101 | } | |
2db9ca0a | 102 | err |= __get_user(current->thread.fpu.fcr31, csr); |
b2ead528 PB |
103 | |
104 | return err; | |
105 | } | |
106 | ||
2db9ca0a PB |
107 | /* |
108 | * Wrappers for the assembly _{save,restore}_fp_context functions. | |
109 | */ | |
110 | static int save_hw_fp_context(void __user *sc) | |
111 | { | |
112 | struct mips_abi *abi = current->thread.abi; | |
113 | uint64_t __user *fpregs = sc + abi->off_sc_fpregs; | |
114 | uint32_t __user *csr = sc + abi->off_sc_fpc_csr; | |
115 | ||
116 | return _save_fp_context(fpregs, csr); | |
117 | } | |
118 | ||
119 | static int restore_hw_fp_context(void __user *sc) | |
120 | { | |
121 | struct mips_abi *abi = current->thread.abi; | |
122 | uint64_t __user *fpregs = sc + abi->off_sc_fpregs; | |
123 | uint32_t __user *csr = sc + abi->off_sc_fpc_csr; | |
124 | ||
125 | return _restore_fp_context(fpregs, csr); | |
126 | } | |
127 | ||
bf82cb30 PB |
128 | /* |
129 | * Extended context handling. | |
130 | */ | |
131 | ||
132 | static inline void __user *sc_to_extcontext(void __user *sc) | |
133 | { | |
134 | struct ucontext __user *uc; | |
135 | ||
136 | /* | |
137 | * We can just pretend the sigcontext is always embedded in a struct | |
138 | * ucontext here, because the offset from sigcontext to extended | |
139 | * context is the same in the struct sigframe case. | |
140 | */ | |
141 | uc = container_of(sc, struct ucontext, uc_mcontext); | |
142 | return &uc->uc_extcontext; | |
143 | } | |
144 | ||
145 | static int save_msa_extcontext(void __user *buf) | |
146 | { | |
147 | struct msa_extcontext __user *msa = buf; | |
148 | uint64_t val; | |
149 | int i, err; | |
150 | ||
151 | if (!thread_msa_context_live()) | |
152 | return 0; | |
153 | ||
154 | /* | |
155 | * Ensure that we can't lose the live MSA context between checking | |
156 | * for it & writing it to memory. | |
157 | */ | |
158 | preempt_disable(); | |
159 | ||
160 | if (is_msa_enabled()) { | |
161 | /* | |
162 | * There are no EVA versions of the vector register load/store | |
163 | * instructions, so MSA context has to be saved to kernel memory | |
164 | * and then copied to user memory. The save to kernel memory | |
165 | * should already have been done when handling scalar FP | |
166 | * context. | |
167 | */ | |
168 | BUG_ON(config_enabled(CONFIG_EVA)); | |
169 | ||
170 | err = __put_user(read_msa_csr(), &msa->csr); | |
171 | err |= _save_msa_all_upper(&msa->wr); | |
172 | ||
173 | preempt_enable(); | |
174 | } else { | |
175 | preempt_enable(); | |
176 | ||
177 | err = __put_user(current->thread.fpu.msacsr, &msa->csr); | |
178 | ||
179 | for (i = 0; i < NUM_FPU_REGS; i++) { | |
180 | val = get_fpr64(¤t->thread.fpu.fpr[i], 1); | |
181 | err |= __put_user(val, &msa->wr[i]); | |
182 | } | |
183 | } | |
184 | ||
185 | err |= __put_user(MSA_EXTCONTEXT_MAGIC, &msa->ext.magic); | |
186 | err |= __put_user(sizeof(*msa), &msa->ext.size); | |
187 | ||
188 | return err ? -EFAULT : sizeof(*msa); | |
189 | } | |
190 | ||
191 | static int restore_msa_extcontext(void __user *buf, unsigned int size) | |
192 | { | |
193 | struct msa_extcontext __user *msa = buf; | |
194 | unsigned long long val; | |
195 | unsigned int csr; | |
196 | int i, err; | |
197 | ||
198 | if (size != sizeof(*msa)) | |
199 | return -EINVAL; | |
200 | ||
201 | err = get_user(csr, &msa->csr); | |
202 | if (err) | |
203 | return err; | |
204 | ||
205 | preempt_disable(); | |
206 | ||
207 | if (is_msa_enabled()) { | |
208 | /* | |
209 | * There are no EVA versions of the vector register load/store | |
210 | * instructions, so MSA context has to be copied to kernel | |
211 | * memory and later loaded to registers. The same is true of | |
212 | * scalar FP context, so FPU & MSA should have already been | |
213 | * disabled whilst handling scalar FP context. | |
214 | */ | |
215 | BUG_ON(config_enabled(CONFIG_EVA)); | |
216 | ||
217 | write_msa_csr(csr); | |
218 | err |= _restore_msa_all_upper(&msa->wr); | |
219 | preempt_enable(); | |
220 | } else { | |
221 | preempt_enable(); | |
222 | ||
223 | current->thread.fpu.msacsr = csr; | |
224 | ||
225 | for (i = 0; i < NUM_FPU_REGS; i++) { | |
226 | err |= __get_user(val, &msa->wr[i]); | |
227 | set_fpr64(¤t->thread.fpu.fpr[i], 1, val); | |
228 | } | |
229 | } | |
230 | ||
231 | return err; | |
232 | } | |
233 | ||
234 | static int save_extcontext(void __user *buf) | |
235 | { | |
236 | int sz; | |
237 | ||
238 | sz = save_msa_extcontext(buf); | |
239 | if (sz < 0) | |
240 | return sz; | |
241 | buf += sz; | |
242 | ||
243 | /* If no context was saved then trivially return */ | |
244 | if (!sz) | |
245 | return 0; | |
246 | ||
247 | /* Write the end marker */ | |
248 | if (__put_user(END_EXTCONTEXT_MAGIC, (u32 *)buf)) | |
249 | return -EFAULT; | |
250 | ||
251 | sz += sizeof(((struct extcontext *)NULL)->magic); | |
252 | return sz; | |
253 | } | |
254 | ||
255 | static int restore_extcontext(void __user *buf) | |
256 | { | |
257 | struct extcontext ext; | |
258 | int err; | |
259 | ||
260 | while (1) { | |
261 | err = __get_user(ext.magic, (unsigned int *)buf); | |
262 | if (err) | |
263 | return err; | |
264 | ||
265 | if (ext.magic == END_EXTCONTEXT_MAGIC) | |
266 | return 0; | |
267 | ||
268 | err = __get_user(ext.size, (unsigned int *)(buf | |
269 | + offsetof(struct extcontext, size))); | |
270 | if (err) | |
271 | return err; | |
272 | ||
273 | switch (ext.magic) { | |
274 | case MSA_EXTCONTEXT_MAGIC: | |
275 | err = restore_msa_extcontext(buf, ext.size); | |
276 | break; | |
277 | ||
278 | default: | |
279 | err = -EINVAL; | |
280 | break; | |
281 | } | |
282 | ||
283 | if (err) | |
284 | return err; | |
285 | ||
286 | buf += ext.size; | |
287 | } | |
288 | } | |
289 | ||
c3fc4ab3 FBH |
290 | /* |
291 | * Helper routines | |
292 | */ | |
d02a40af | 293 | int protected_save_fp_context(void __user *sc) |
faea6234 | 294 | { |
2db9ca0a PB |
295 | struct mips_abi *abi = current->thread.abi; |
296 | uint64_t __user *fpregs = sc + abi->off_sc_fpregs; | |
297 | uint32_t __user *csr = sc + abi->off_sc_fpc_csr; | |
64243c2a | 298 | uint32_t __user *used_math = sc + abi->off_sc_used_math; |
bf82cb30 | 299 | unsigned int used, ext_sz; |
faea6234 | 300 | int err; |
689ee856 | 301 | |
0d071fa3 | 302 | used = used_math() ? USED_FP : 0; |
bf82cb30 PB |
303 | if (!used) |
304 | goto fp_done; | |
0d071fa3 | 305 | |
bf82cb30 PB |
306 | if (!test_thread_flag(TIF_32BIT_FPREGS)) |
307 | used |= USED_FR1; | |
308 | if (test_thread_flag(TIF_HYBRID_FPREGS)) | |
309 | used |= USED_HYBRID_FPRS; | |
64243c2a | 310 | |
689ee856 PB |
311 | /* |
312 | * EVA does not have userland equivalents of ldc1 or sdc1, so | |
313 | * save to the kernel FP context & copy that to userland below. | |
314 | */ | |
315 | if (config_enabled(CONFIG_EVA)) | |
316 | lose_fpu(1); | |
317 | ||
faea6234 AN |
318 | while (1) { |
319 | lock_fpu_owner(); | |
ff3aa5f2 PB |
320 | if (is_fpu_owner()) { |
321 | err = save_fp_context(sc); | |
322 | unlock_fpu_owner(); | |
323 | } else { | |
324 | unlock_fpu_owner(); | |
325 | err = copy_fp_to_sigcontext(sc); | |
326 | } | |
faea6234 AN |
327 | if (likely(!err)) |
328 | break; | |
329 | /* touch the sigcontext and try again */ | |
2db9ca0a PB |
330 | err = __put_user(0, &fpregs[0]) | |
331 | __put_user(0, &fpregs[31]) | | |
332 | __put_user(0, csr); | |
faea6234 | 333 | if (err) |
bf82cb30 | 334 | return err; /* really bad sigcontext */ |
faea6234 | 335 | } |
689ee856 | 336 | |
bf82cb30 PB |
337 | fp_done: |
338 | ext_sz = err = save_extcontext(sc_to_extcontext(sc)); | |
339 | if (err < 0) | |
340 | return err; | |
341 | used |= ext_sz ? USED_EXTCONTEXT : 0; | |
342 | ||
343 | return __put_user(used, used_math); | |
faea6234 AN |
344 | } |
345 | ||
d02a40af | 346 | int protected_restore_fp_context(void __user *sc) |
faea6234 | 347 | { |
2db9ca0a PB |
348 | struct mips_abi *abi = current->thread.abi; |
349 | uint64_t __user *fpregs = sc + abi->off_sc_fpregs; | |
350 | uint32_t __user *csr = sc + abi->off_sc_fpc_csr; | |
64243c2a PB |
351 | uint32_t __user *used_math = sc + abi->off_sc_used_math; |
352 | unsigned int used; | |
bf82cb30 | 353 | int err, sig = 0, tmp __maybe_unused; |
64243c2a PB |
354 | |
355 | err = __get_user(used, used_math); | |
0d071fa3 | 356 | conditional_used_math(used & USED_FP); |
64243c2a PB |
357 | |
358 | /* | |
359 | * The signal handler may have used FPU; give it up if the program | |
360 | * doesn't want it following sigreturn. | |
361 | */ | |
bf82cb30 | 362 | if (err || !(used & USED_FP)) |
64243c2a | 363 | lose_fpu(0); |
bf82cb30 | 364 | if (err) |
64243c2a | 365 | return err; |
bf82cb30 PB |
366 | if (!(used & USED_FP)) |
367 | goto fp_done; | |
64243c2a PB |
368 | |
369 | err = sig = fpcsr_pending(csr); | |
370 | if (err < 0) | |
371 | return err; | |
689ee856 PB |
372 | |
373 | /* | |
374 | * EVA does not have userland equivalents of ldc1 or sdc1, so we | |
375 | * disable the FPU here such that the code below simply copies to | |
376 | * the kernel FP context. | |
377 | */ | |
378 | if (config_enabled(CONFIG_EVA)) | |
379 | lose_fpu(0); | |
380 | ||
faea6234 AN |
381 | while (1) { |
382 | lock_fpu_owner(); | |
ff3aa5f2 PB |
383 | if (is_fpu_owner()) { |
384 | err = restore_fp_context(sc); | |
385 | unlock_fpu_owner(); | |
386 | } else { | |
387 | unlock_fpu_owner(); | |
388 | err = copy_fp_from_sigcontext(sc); | |
389 | } | |
faea6234 AN |
390 | if (likely(!err)) |
391 | break; | |
392 | /* touch the sigcontext and try again */ | |
2db9ca0a PB |
393 | err = __get_user(tmp, &fpregs[0]) | |
394 | __get_user(tmp, &fpregs[31]) | | |
395 | __get_user(tmp, csr); | |
faea6234 AN |
396 | if (err) |
397 | break; /* really bad sigcontext */ | |
398 | } | |
689ee856 | 399 | |
bf82cb30 PB |
400 | fp_done: |
401 | if (used & USED_EXTCONTEXT) | |
402 | err |= restore_extcontext(sc_to_extcontext(sc)); | |
403 | ||
64243c2a | 404 | return err ?: sig; |
faea6234 AN |
405 | } |
406 | ||
c3fc4ab3 FBH |
407 | int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) |
408 | { | |
409 | int err = 0; | |
410 | int i; | |
411 | ||
412 | err |= __put_user(regs->cp0_epc, &sc->sc_pc); | |
413 | ||
414 | err |= __put_user(0, &sc->sc_regs[0]); | |
415 | for (i = 1; i < 32; i++) | |
416 | err |= __put_user(regs->regs[i], &sc->sc_regs[i]); | |
417 | ||
9693a853 FBH |
418 | #ifdef CONFIG_CPU_HAS_SMARTMIPS |
419 | err |= __put_user(regs->acx, &sc->sc_acx); | |
420 | #endif | |
c3fc4ab3 FBH |
421 | err |= __put_user(regs->hi, &sc->sc_mdhi); |
422 | err |= __put_user(regs->lo, &sc->sc_mdlo); | |
423 | if (cpu_has_dsp) { | |
424 | err |= __put_user(mfhi1(), &sc->sc_hi1); | |
425 | err |= __put_user(mflo1(), &sc->sc_lo1); | |
426 | err |= __put_user(mfhi2(), &sc->sc_hi2); | |
427 | err |= __put_user(mflo2(), &sc->sc_lo2); | |
428 | err |= __put_user(mfhi3(), &sc->sc_hi3); | |
429 | err |= __put_user(mflo3(), &sc->sc_lo3); | |
430 | err |= __put_user(rddsp(DSP_MASK), &sc->sc_dsp); | |
431 | } | |
432 | ||
c3fc4ab3 | 433 | |
64243c2a PB |
434 | /* |
435 | * Save FPU state to signal context. Signal handler | |
436 | * will "inherit" current FPU state. | |
437 | */ | |
438 | err |= protected_save_fp_context(sc); | |
439 | ||
c3fc4ab3 FBH |
440 | return err; |
441 | } | |
442 | ||
bf82cb30 PB |
443 | static size_t extcontext_max_size(void) |
444 | { | |
445 | size_t sz = 0; | |
446 | ||
447 | /* | |
448 | * The assumption here is that between this point & the point at which | |
449 | * the extended context is saved the size of the context should only | |
450 | * ever be able to shrink (if the task is preempted), but never grow. | |
451 | * That is, what this function returns is an upper bound on the size of | |
452 | * the extended context for the current task at the current time. | |
453 | */ | |
454 | ||
455 | if (thread_msa_context_live()) | |
456 | sz += sizeof(struct msa_extcontext); | |
457 | ||
458 | /* If any context is saved then we'll append the end marker */ | |
459 | if (sz) | |
460 | sz += sizeof(((struct extcontext *)NULL)->magic); | |
461 | ||
462 | return sz; | |
463 | } | |
464 | ||
c6a2f467 AN |
465 | int fpcsr_pending(unsigned int __user *fpcsr) |
466 | { | |
467 | int err, sig = 0; | |
468 | unsigned int csr, enabled; | |
469 | ||
470 | err = __get_user(csr, fpcsr); | |
471 | enabled = FPU_CSR_UNI_X | ((csr & FPU_CSR_ALL_E) << 5); | |
472 | /* | |
473 | * If the signal handler set some FPU exceptions, clear it and | |
474 | * send SIGFPE. | |
475 | */ | |
476 | if (csr & enabled) { | |
477 | csr &= ~enabled; | |
478 | err |= __put_user(csr, fpcsr); | |
479 | sig = SIGFPE; | |
480 | } | |
481 | return err ?: sig; | |
482 | } | |
483 | ||
c3fc4ab3 FBH |
484 | int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) |
485 | { | |
c3fc4ab3 FBH |
486 | unsigned long treg; |
487 | int err = 0; | |
488 | int i; | |
489 | ||
490 | /* Always make any pending restarted system calls return -EINTR */ | |
f56141e3 | 491 | current->restart_block.fn = do_no_restart_syscall; |
c3fc4ab3 FBH |
492 | |
493 | err |= __get_user(regs->cp0_epc, &sc->sc_pc); | |
9693a853 FBH |
494 | |
495 | #ifdef CONFIG_CPU_HAS_SMARTMIPS | |
496 | err |= __get_user(regs->acx, &sc->sc_acx); | |
497 | #endif | |
c3fc4ab3 FBH |
498 | err |= __get_user(regs->hi, &sc->sc_mdhi); |
499 | err |= __get_user(regs->lo, &sc->sc_mdlo); | |
500 | if (cpu_has_dsp) { | |
501 | err |= __get_user(treg, &sc->sc_hi1); mthi1(treg); | |
502 | err |= __get_user(treg, &sc->sc_lo1); mtlo1(treg); | |
503 | err |= __get_user(treg, &sc->sc_hi2); mthi2(treg); | |
504 | err |= __get_user(treg, &sc->sc_lo2); mtlo2(treg); | |
505 | err |= __get_user(treg, &sc->sc_hi3); mthi3(treg); | |
506 | err |= __get_user(treg, &sc->sc_lo3); mtlo3(treg); | |
507 | err |= __get_user(treg, &sc->sc_dsp); wrdsp(treg, DSP_MASK); | |
508 | } | |
509 | ||
510 | for (i = 1; i < 32; i++) | |
511 | err |= __get_user(regs->regs[i], &sc->sc_regs[i]); | |
512 | ||
64243c2a | 513 | return err ?: protected_restore_fp_context(sc); |
c3fc4ab3 FBH |
514 | } |
515 | ||
7c4f5635 | 516 | void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, |
c3fc4ab3 FBH |
517 | size_t frame_size) |
518 | { | |
519 | unsigned long sp; | |
520 | ||
bf82cb30 PB |
521 | /* Leave space for potential extended context */ |
522 | frame_size += extcontext_max_size(); | |
523 | ||
c3fc4ab3 FBH |
524 | /* Default to using normal stack */ |
525 | sp = regs->regs[29]; | |
526 | ||
527 | /* | |
528 | * FPU emulator may have it's own trampoline active just | |
529 | * above the user stack, 16-bytes before the next lowest | |
530 | * 16 byte boundary. Try to avoid trashing it. | |
531 | */ | |
532 | sp -= 32; | |
533 | ||
7c4f5635 | 534 | sp = sigsp(sp, ksig); |
c3fc4ab3 FBH |
535 | |
536 | return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK)); | |
537 | } | |
538 | ||
1da177e4 LT |
539 | /* |
540 | * Atomically swap in the new signal mask, and wait for a signal. | |
541 | */ | |
542 | ||
543 | #ifdef CONFIG_TRAD_SIGNALS | |
1910f4ab | 544 | SYSCALL_DEFINE1(sigsuspend, sigset_t __user *, uset) |
1da177e4 | 545 | { |
1910f4ab | 546 | return sys_rt_sigsuspend(uset, sizeof(sigset_t)); |
1da177e4 LT |
547 | } |
548 | #endif | |
549 | ||
1da177e4 | 550 | #ifdef CONFIG_TRAD_SIGNALS |
dbda6ac0 RB |
551 | SYSCALL_DEFINE3(sigaction, int, sig, const struct sigaction __user *, act, |
552 | struct sigaction __user *, oact) | |
1da177e4 LT |
553 | { |
554 | struct k_sigaction new_ka, old_ka; | |
555 | int ret; | |
556 | int err = 0; | |
557 | ||
558 | if (act) { | |
559 | old_sigset_t mask; | |
560 | ||
561 | if (!access_ok(VERIFY_READ, act, sizeof(*act))) | |
562 | return -EFAULT; | |
563 | err |= __get_user(new_ka.sa.sa_handler, &act->sa_handler); | |
564 | err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); | |
565 | err |= __get_user(mask, &act->sa_mask.sig[0]); | |
566 | if (err) | |
567 | return -EFAULT; | |
568 | ||
569 | siginitset(&new_ka.sa.sa_mask, mask); | |
570 | } | |
571 | ||
572 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); | |
573 | ||
574 | if (!ret && oact) { | |
575 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact))) | |
e0daad44 | 576 | return -EFAULT; |
1da177e4 LT |
577 | err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); |
578 | err |= __put_user(old_ka.sa.sa_handler, &oact->sa_handler); | |
579 | err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig); | |
580 | err |= __put_user(0, &oact->sa_mask.sig[1]); | |
581 | err |= __put_user(0, &oact->sa_mask.sig[2]); | |
582 | err |= __put_user(0, &oact->sa_mask.sig[3]); | |
583 | if (err) | |
584 | return -EFAULT; | |
585 | } | |
586 | ||
587 | return ret; | |
588 | } | |
589 | #endif | |
590 | ||
1da177e4 | 591 | #ifdef CONFIG_TRAD_SIGNALS |
f90080a0 | 592 | asmlinkage void sys_sigreturn(nabi_no_regargs struct pt_regs regs) |
1da177e4 | 593 | { |
9bbf28a3 | 594 | struct sigframe __user *frame; |
1da177e4 | 595 | sigset_t blocked; |
c6a2f467 | 596 | int sig; |
1da177e4 | 597 | |
9bbf28a3 | 598 | frame = (struct sigframe __user *) regs.regs[29]; |
1da177e4 LT |
599 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
600 | goto badframe; | |
601 | if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked))) | |
602 | goto badframe; | |
603 | ||
8598f3cd | 604 | set_current_blocked(&blocked); |
1da177e4 | 605 | |
c6a2f467 AN |
606 | sig = restore_sigcontext(®s, &frame->sf_sc); |
607 | if (sig < 0) | |
1da177e4 | 608 | goto badframe; |
c6a2f467 AN |
609 | else if (sig) |
610 | force_sig(sig, current); | |
1da177e4 LT |
611 | |
612 | /* | |
613 | * Don't let your children do this ... | |
614 | */ | |
1da177e4 LT |
615 | __asm__ __volatile__( |
616 | "move\t$29, %0\n\t" | |
617 | "j\tsyscall_exit" | |
618 | :/* no outputs */ | |
619 | :"r" (®s)); | |
620 | /* Unreached */ | |
621 | ||
622 | badframe: | |
623 | force_sig(SIGSEGV, current); | |
624 | } | |
e50c0a8f | 625 | #endif /* CONFIG_TRAD_SIGNALS */ |
1da177e4 | 626 | |
f90080a0 | 627 | asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) |
1da177e4 | 628 | { |
9bbf28a3 | 629 | struct rt_sigframe __user *frame; |
1da177e4 | 630 | sigset_t set; |
c6a2f467 | 631 | int sig; |
1da177e4 | 632 | |
9bbf28a3 | 633 | frame = (struct rt_sigframe __user *) regs.regs[29]; |
1da177e4 LT |
634 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
635 | goto badframe; | |
636 | if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set))) | |
637 | goto badframe; | |
638 | ||
8598f3cd | 639 | set_current_blocked(&set); |
1da177e4 | 640 | |
c6a2f467 AN |
641 | sig = restore_sigcontext(®s, &frame->rs_uc.uc_mcontext); |
642 | if (sig < 0) | |
1da177e4 | 643 | goto badframe; |
c6a2f467 AN |
644 | else if (sig) |
645 | force_sig(sig, current); | |
1da177e4 | 646 | |
ea536ad4 AV |
647 | if (restore_altstack(&frame->rs_uc.uc_stack)) |
648 | goto badframe; | |
1da177e4 LT |
649 | |
650 | /* | |
651 | * Don't let your children do this ... | |
652 | */ | |
653 | __asm__ __volatile__( | |
654 | "move\t$29, %0\n\t" | |
655 | "j\tsyscall_exit" | |
656 | :/* no outputs */ | |
657 | :"r" (®s)); | |
658 | /* Unreached */ | |
659 | ||
660 | badframe: | |
661 | force_sig(SIGSEGV, current); | |
662 | } | |
663 | ||
664 | #ifdef CONFIG_TRAD_SIGNALS | |
81d103bf RW |
665 | static int setup_frame(void *sig_return, struct ksignal *ksig, |
666 | struct pt_regs *regs, sigset_t *set) | |
1da177e4 | 667 | { |
9bbf28a3 | 668 | struct sigframe __user *frame; |
1da177e4 LT |
669 | int err = 0; |
670 | ||
7c4f5635 | 671 | frame = get_sigframe(ksig, regs, sizeof(*frame)); |
1da177e4 | 672 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) |
81d103bf | 673 | return -EFAULT; |
1da177e4 | 674 | |
1da177e4 LT |
675 | err |= setup_sigcontext(regs, &frame->sf_sc); |
676 | err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set)); | |
677 | if (err) | |
81d103bf | 678 | return -EFAULT; |
1da177e4 LT |
679 | |
680 | /* | |
681 | * Arguments to signal handler: | |
682 | * | |
683 | * a0 = signal number | |
684 | * a1 = 0 (should be cause) | |
685 | * a2 = pointer to struct sigcontext | |
686 | * | |
687 | * $25 and c0_epc point to the signal handler, $29 points to the | |
688 | * struct sigframe. | |
689 | */ | |
81d103bf | 690 | regs->regs[ 4] = ksig->sig; |
1da177e4 LT |
691 | regs->regs[ 5] = 0; |
692 | regs->regs[ 6] = (unsigned long) &frame->sf_sc; | |
693 | regs->regs[29] = (unsigned long) frame; | |
d814c28c | 694 | regs->regs[31] = (unsigned long) sig_return; |
81d103bf | 695 | regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler; |
1da177e4 | 696 | |
722bb63d | 697 | DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", |
1da177e4 | 698 | current->comm, current->pid, |
722bb63d | 699 | frame, regs->cp0_epc, regs->regs[31]); |
e0daad44 | 700 | return 0; |
1da177e4 LT |
701 | } |
702 | #endif | |
703 | ||
81d103bf RW |
704 | static int setup_rt_frame(void *sig_return, struct ksignal *ksig, |
705 | struct pt_regs *regs, sigset_t *set) | |
1da177e4 | 706 | { |
9bbf28a3 | 707 | struct rt_sigframe __user *frame; |
1da177e4 LT |
708 | int err = 0; |
709 | ||
7c4f5635 | 710 | frame = get_sigframe(ksig, regs, sizeof(*frame)); |
1da177e4 | 711 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) |
81d103bf | 712 | return -EFAULT; |
1da177e4 | 713 | |
1da177e4 | 714 | /* Create siginfo. */ |
81d103bf | 715 | err |= copy_siginfo_to_user(&frame->rs_info, &ksig->info); |
1da177e4 | 716 | |
70342287 | 717 | /* Create the ucontext. */ |
1da177e4 | 718 | err |= __put_user(0, &frame->rs_uc.uc_flags); |
5665a0ac | 719 | err |= __put_user(NULL, &frame->rs_uc.uc_link); |
ea536ad4 | 720 | err |= __save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]); |
1da177e4 LT |
721 | err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext); |
722 | err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set)); | |
723 | ||
724 | if (err) | |
81d103bf | 725 | return -EFAULT; |
1da177e4 LT |
726 | |
727 | /* | |
728 | * Arguments to signal handler: | |
729 | * | |
730 | * a0 = signal number | |
731 | * a1 = 0 (should be cause) | |
732 | * a2 = pointer to ucontext | |
733 | * | |
734 | * $25 and c0_epc point to the signal handler, $29 points to | |
735 | * the struct rt_sigframe. | |
736 | */ | |
81d103bf | 737 | regs->regs[ 4] = ksig->sig; |
1da177e4 LT |
738 | regs->regs[ 5] = (unsigned long) &frame->rs_info; |
739 | regs->regs[ 6] = (unsigned long) &frame->rs_uc; | |
740 | regs->regs[29] = (unsigned long) frame; | |
d814c28c | 741 | regs->regs[31] = (unsigned long) sig_return; |
81d103bf | 742 | regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler; |
1da177e4 | 743 | |
722bb63d | 744 | DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", |
1da177e4 LT |
745 | current->comm, current->pid, |
746 | frame, regs->cp0_epc, regs->regs[31]); | |
722bb63d | 747 | |
7b3e2fc8 | 748 | return 0; |
1da177e4 LT |
749 | } |
750 | ||
151fd6ac RB |
751 | struct mips_abi mips_abi = { |
752 | #ifdef CONFIG_TRAD_SIGNALS | |
753 | .setup_frame = setup_frame, | |
754 | #endif | |
70342287 | 755 | .setup_rt_frame = setup_rt_frame, |
77856100 PB |
756 | .restart = __NR_restart_syscall, |
757 | ||
758 | .off_sc_fpregs = offsetof(struct sigcontext, sc_fpregs), | |
759 | .off_sc_fpc_csr = offsetof(struct sigcontext, sc_fpc_csr), | |
760 | .off_sc_used_math = offsetof(struct sigcontext, sc_used_math), | |
ebb5e78c AS |
761 | |
762 | .vdso = &vdso_image, | |
151fd6ac RB |
763 | }; |
764 | ||
81d103bf | 765 | static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) |
1da177e4 | 766 | { |
b7f9a11a | 767 | sigset_t *oldset = sigmask_to_save(); |
129bc8f7 | 768 | int ret; |
d814c28c | 769 | struct mips_abi *abi = current->thread.abi; |
01be057b DL |
770 | #ifdef CONFIG_CPU_MICROMIPS |
771 | void *vdso; | |
2fabc7d2 | 772 | unsigned long tmp = (unsigned long)current->mm->context.vdso; |
01be057b DL |
773 | |
774 | set_isa16_mode(tmp); | |
775 | vdso = (void *)tmp; | |
776 | #else | |
d814c28c | 777 | void *vdso = current->mm->context.vdso; |
01be057b | 778 | #endif |
129bc8f7 | 779 | |
8f5a00eb AV |
780 | if (regs->regs[0]) { |
781 | switch(regs->regs[2]) { | |
782 | case ERESTART_RESTARTBLOCK: | |
783 | case ERESTARTNOHAND: | |
1da177e4 LT |
784 | regs->regs[2] = EINTR; |
785 | break; | |
8f5a00eb | 786 | case ERESTARTSYS: |
81d103bf | 787 | if (!(ksig->ka.sa.sa_flags & SA_RESTART)) { |
8f5a00eb AV |
788 | regs->regs[2] = EINTR; |
789 | break; | |
790 | } | |
791 | /* fallthrough */ | |
792 | case ERESTARTNOINTR: | |
793 | regs->regs[7] = regs->regs[26]; | |
794 | regs->regs[2] = regs->regs[0]; | |
795 | regs->cp0_epc -= 4; | |
1da177e4 | 796 | } |
1da177e4 | 797 | |
70342287 | 798 | regs->regs[0] = 0; /* Don't deal with this again. */ |
8f5a00eb | 799 | } |
1da177e4 | 800 | |
81d103bf | 801 | if (sig_uses_siginfo(&ksig->ka)) |
ebb5e78c | 802 | ret = abi->setup_rt_frame(vdso + abi->vdso->off_rt_sigreturn, |
81d103bf | 803 | ksig, regs, oldset); |
1da177e4 | 804 | else |
ebb5e78c AS |
805 | ret = abi->setup_frame(vdso + abi->vdso->off_sigreturn, |
806 | ksig, regs, oldset); | |
062ab57b | 807 | |
81d103bf | 808 | signal_setup_done(ret, ksig, 0); |
1da177e4 LT |
809 | } |
810 | ||
151fd6ac | 811 | static void do_signal(struct pt_regs *regs) |
1da177e4 | 812 | { |
81d103bf | 813 | struct ksignal ksig; |
1da177e4 | 814 | |
81d103bf | 815 | if (get_signal(&ksig)) { |
70342287 | 816 | /* Whee! Actually deliver the signal. */ |
81d103bf | 817 | handle_signal(&ksig, regs); |
45887e12 | 818 | return; |
7b3e2fc8 | 819 | } |
1da177e4 | 820 | |
1da177e4 | 821 | if (regs->regs[0]) { |
9ec9b5ac RB |
822 | switch (regs->regs[2]) { |
823 | case ERESTARTNOHAND: | |
824 | case ERESTARTSYS: | |
825 | case ERESTARTNOINTR: | |
8f5a00eb | 826 | regs->regs[2] = regs->regs[0]; |
1da177e4 | 827 | regs->regs[7] = regs->regs[26]; |
8f5a00eb | 828 | regs->cp0_epc -= 4; |
9ec9b5ac RB |
829 | break; |
830 | ||
831 | case ERESTART_RESTARTBLOCK: | |
151fd6ac | 832 | regs->regs[2] = current->thread.abi->restart; |
1da177e4 LT |
833 | regs->regs[7] = regs->regs[26]; |
834 | regs->cp0_epc -= 4; | |
9ec9b5ac | 835 | break; |
1da177e4 | 836 | } |
70342287 | 837 | regs->regs[0] = 0; /* Don't deal with this again. */ |
1da177e4 | 838 | } |
7b3e2fc8 RB |
839 | |
840 | /* | |
841 | * If there's no signal to deliver, we just put the saved sigmask | |
842 | * back | |
843 | */ | |
51a7b448 | 844 | restore_saved_sigmask(); |
1da177e4 LT |
845 | } |
846 | ||
847 | /* | |
848 | * notification of userspace execution resumption | |
7b3e2fc8 | 849 | * - triggered by the TIF_WORK_MASK flags |
1da177e4 | 850 | */ |
7b3e2fc8 | 851 | asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, |
1da177e4 LT |
852 | __u32 thread_info_flags) |
853 | { | |
1f717929 RB |
854 | local_irq_enable(); |
855 | ||
c3fc5cd5 RB |
856 | user_exit(); |
857 | ||
40e084a5 RB |
858 | if (thread_info_flags & _TIF_UPROBE) |
859 | uprobe_notify_resume(regs); | |
860 | ||
1da177e4 | 861 | /* deal with pending signal delivery */ |
6fd84c08 | 862 | if (thread_info_flags & _TIF_SIGPENDING) |
151fd6ac | 863 | do_signal(regs); |
d0420c83 DH |
864 | |
865 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | |
866 | clear_thread_flag(TIF_NOTIFY_RESUME); | |
867 | tracehook_notify_resume(regs); | |
868 | } | |
c3fc5cd5 RB |
869 | |
870 | user_enter(); | |
1da177e4 | 871 | } |
137f6f3e RB |
872 | |
873 | #ifdef CONFIG_SMP | |
2db9ca0a | 874 | static int smp_save_fp_context(void __user *sc) |
137f6f3e RB |
875 | { |
876 | return raw_cpu_has_fpu | |
2db9ca0a | 877 | ? save_hw_fp_context(sc) |
b2ead528 | 878 | : copy_fp_to_sigcontext(sc); |
137f6f3e RB |
879 | } |
880 | ||
2db9ca0a | 881 | static int smp_restore_fp_context(void __user *sc) |
137f6f3e RB |
882 | { |
883 | return raw_cpu_has_fpu | |
2db9ca0a | 884 | ? restore_hw_fp_context(sc) |
b2ead528 | 885 | : copy_fp_from_sigcontext(sc); |
137f6f3e RB |
886 | } |
887 | #endif | |
888 | ||
889 | static int signal_setup(void) | |
890 | { | |
f1fe2d21 PB |
891 | /* |
892 | * The offset from sigcontext to extended context should be the same | |
893 | * regardless of the type of signal, such that userland can always know | |
894 | * where to look if it wishes to find the extended context structures. | |
895 | */ | |
896 | BUILD_BUG_ON((offsetof(struct sigframe, sf_extcontext) - | |
897 | offsetof(struct sigframe, sf_sc)) != | |
898 | (offsetof(struct rt_sigframe, rs_uc.uc_extcontext) - | |
899 | offsetof(struct rt_sigframe, rs_uc.uc_mcontext))); | |
900 | ||
137f6f3e RB |
901 | #ifdef CONFIG_SMP |
902 | /* For now just do the cpu_has_fpu check when the functions are invoked */ | |
903 | save_fp_context = smp_save_fp_context; | |
904 | restore_fp_context = smp_restore_fp_context; | |
905 | #else | |
906 | if (cpu_has_fpu) { | |
2db9ca0a PB |
907 | save_fp_context = save_hw_fp_context; |
908 | restore_fp_context = restore_hw_fp_context; | |
137f6f3e | 909 | } else { |
14fa12df PB |
910 | save_fp_context = copy_fp_to_sigcontext; |
911 | restore_fp_context = copy_fp_from_sigcontext; | |
137f6f3e | 912 | } |
ca750649 | 913 | #endif /* CONFIG_SMP */ |
137f6f3e RB |
914 | |
915 | return 0; | |
916 | } | |
917 | ||
918 | arch_initcall(signal_setup); |