1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include <linux/sched.h>
17#include <linux/mm.h>
18#include <linux/smp.h>
19#include <linux/kernel.h>
20#include <linux/signal.h>
21#include <linux/errno.h>
22#include <linux/wait.h>
23#include <linux/ptrace.h>
24#include <linux/tracehook.h>
25#include <linux/unistd.h>
26#include <linux/stddef.h>
27#include <linux/compat.h>
28#include <linux/elf.h>
29#include <asm/ucontext.h>
30#include <asm/rt_sigframe.h>
31#include <asm/uaccess.h>
32#include <asm/pgalloc.h>
33#include <asm/cacheflush.h>
34#include <asm/asm-offsets.h>
35
36#ifdef CONFIG_COMPAT
37#include "signal32.h"
38#endif
39
40#define DEBUG_SIG 0
41#define DEBUG_SIG_LEVEL 2
42
43#if DEBUG_SIG
44#define DBG(LEVEL, ...) \
45 ((DEBUG_SIG_LEVEL >= LEVEL) \
46 ? printk(__VA_ARGS__) : (void) 0)
47#else
48#define DBG(LEVEL, ...)
49#endif
50
51
52
53
54
55
56#define A(__x) ((unsigned long)(__x))
57
58
59
60
61
62
63#define INSN_LDI_R25_0 0x34190000
64#define INSN_LDI_R25_1 0x34190002
65#define INSN_LDI_R20 0x3414015a
66#define INSN_BLE_SR2_R0 0xe4008200
67#define INSN_NOP 0x08000240
68
69#define INSN_DIE_HORRIBLY 0x68000ccc
70
71static long
72restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
73{
74 long err = 0;
75
76 err |= __copy_from_user(regs->gr, sc->sc_gr, sizeof(regs->gr));
77 err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
78 err |= __copy_from_user(regs->iaoq, sc->sc_iaoq, sizeof(regs->iaoq));
79 err |= __copy_from_user(regs->iasq, sc->sc_iasq, sizeof(regs->iasq));
80 err |= __get_user(regs->sar, &sc->sc_sar);
81 DBG(2,"restore_sigcontext: iaoq is %#lx / %#lx\n",
82 regs->iaoq[0],regs->iaoq[1]);
83 DBG(2,"restore_sigcontext: r28 is %ld\n", regs->gr[28]);
84 return err;
85}
86
87void
88sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
89{
90 struct rt_sigframe __user *frame;
91 sigset_t set;
92 unsigned long usp = (regs->gr[30] & ~(0x01UL));
93 unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE;
94#ifdef CONFIG_64BIT
95 compat_sigset_t compat_set;
96 struct compat_rt_sigframe __user * compat_frame;
97
98 if (is_compat_task())
99 sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
100#endif
101
102 current_thread_info()->restart_block.fn = do_no_restart_syscall;
103
104
105 frame = (struct rt_sigframe __user *)
106 (usp - sigframe_size);
107 DBG(2,"sys_rt_sigreturn: frame is %p\n", frame);
108
109 regs->orig_r28 = 1;
110
111#ifdef CONFIG_64BIT
112 compat_frame = (struct compat_rt_sigframe __user *)frame;
113
114 if (is_compat_task()) {
115 DBG(2,"sys_rt_sigreturn: ELF32 process.\n");
116 if (__copy_from_user(&compat_set, &compat_frame->uc.uc_sigmask, sizeof(compat_set)))
117 goto give_sigsegv;
118 sigset_32to64(&set,&compat_set);
119 } else
120#endif
121 {
122 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
123 goto give_sigsegv;
124 }
125
126 set_current_blocked(&set);
127
128
129#ifdef CONFIG_64BIT
130 if (is_compat_task()) {
131 DBG(1,"sys_rt_sigreturn: compat_frame->uc.uc_mcontext 0x%p\n",
132 &compat_frame->uc.uc_mcontext);
133
134 if (restore_sigcontext32(&compat_frame->uc.uc_mcontext,
135 &compat_frame->regs, regs))
136 goto give_sigsegv;
137 DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n",
138 usp, &compat_frame->uc.uc_stack);
139 if (compat_restore_altstack(&compat_frame->uc.uc_stack))
140 goto give_sigsegv;
141 } else
142#endif
143 {
144 DBG(1,"sys_rt_sigreturn: frame->uc.uc_mcontext 0x%p\n",
145 &frame->uc.uc_mcontext);
146 if (restore_sigcontext(&frame->uc.uc_mcontext, regs))
147 goto give_sigsegv;
148 DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n",
149 usp, &frame->uc.uc_stack);
150 if (restore_altstack(&frame->uc.uc_stack))
151 goto give_sigsegv;
152 }
153
154
155
156
157
158
159 if (in_syscall)
160 regs->gr[31] = regs->iaoq[0];
161#if DEBUG_SIG
162 DBG(1,"sys_rt_sigreturn: returning to %#lx, DUMPING REGS:\n", regs->iaoq[0]);
163 show_regs(regs);
164#endif
165 return;
166
167give_sigsegv:
168 DBG(1,"sys_rt_sigreturn: Sending SIGSEGV\n");
169 force_sig(SIGSEGV, current);
170 return;
171}
172
173
174
175
176
177static inline void __user *
178get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
179{
180
181
182
183 DBG(1,"get_sigframe: ka = %#lx, sp = %#lx, frame_size = %#lx\n",
184 (unsigned long)ka, sp, frame_size);
185
186
187
188 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
189 sp = (current->sas_ss_sp + 0x7f) & ~0x3f;
190
191 DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp);
192 return (void __user *) sp;
193}
194
195static long
196setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, int in_syscall)
197
198{
199 unsigned long flags = 0;
200 long err = 0;
201
202 if (on_sig_stack((unsigned long) sc))
203 flags |= PARISC_SC_FLAG_ONSTACK;
204 if (in_syscall) {
205 flags |= PARISC_SC_FLAG_IN_SYSCALL;
206
207 err |= __put_user(regs->gr[31], &sc->sc_iaoq[0]);
208 err |= __put_user(regs->gr[31]+4, &sc->sc_iaoq[1]);
209 err |= __put_user(regs->sr[3], &sc->sc_iasq[0]);
210 err |= __put_user(regs->sr[3], &sc->sc_iasq[1]);
211 DBG(1,"setup_sigcontext: iaoq %#lx / %#lx (in syscall)\n",
212 regs->gr[31], regs->gr[31]+4);
213 } else {
214 err |= __copy_to_user(sc->sc_iaoq, regs->iaoq, sizeof(regs->iaoq));
215 err |= __copy_to_user(sc->sc_iasq, regs->iasq, sizeof(regs->iasq));
216 DBG(1,"setup_sigcontext: iaoq %#lx / %#lx (not in syscall)\n",
217 regs->iaoq[0], regs->iaoq[1]);
218 }
219
220 err |= __put_user(flags, &sc->sc_flags);
221 err |= __copy_to_user(sc->sc_gr, regs->gr, sizeof(regs->gr));
222 err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
223 err |= __put_user(regs->sar, &sc->sc_sar);
224 DBG(1,"setup_sigcontext: r28 is %ld\n", regs->gr[28]);
225
226 return err;
227}
228
229static long
230setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
231 int in_syscall)
232{
233 struct rt_sigframe __user *frame;
234 unsigned long rp, usp;
235 unsigned long haddr, sigframe_size;
236 int err = 0;
237#ifdef CONFIG_64BIT
238 struct compat_rt_sigframe __user * compat_frame;
239 compat_sigset_t compat_set;
240#endif
241
242 usp = (regs->gr[30] & ~(0x01UL));
243
244 frame = get_sigframe(&ksig->ka, usp, sizeof(*frame));
245
246 DBG(1,"SETUP_RT_FRAME: START\n");
247 DBG(1,"setup_rt_frame: frame %p info %p\n", frame, ksig->info);
248
249
250#ifdef CONFIG_64BIT
251
252 compat_frame = (struct compat_rt_sigframe __user *)frame;
253
254 if (is_compat_task()) {
255 DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info);
256 err |= copy_siginfo_to_user32(&compat_frame->info, &ksig->info);
257 err |= __compat_save_altstack( &compat_frame->uc.uc_stack, regs->gr[30]);
258 DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &compat_frame->uc);
259 DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &compat_frame->uc.uc_mcontext);
260 err |= setup_sigcontext32(&compat_frame->uc.uc_mcontext,
261 &compat_frame->regs, regs, in_syscall);
262 sigset_64to32(&compat_set,set);
263 err |= __copy_to_user(&compat_frame->uc.uc_sigmask, &compat_set, sizeof(compat_set));
264 } else
265#endif
266 {
267 DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &frame->info);
268 err |= copy_siginfo_to_user(&frame->info, &ksig->info);
269 err |= __save_altstack(&frame->uc.uc_stack, regs->gr[30]);
270 DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &frame->uc);
271 DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &frame->uc.uc_mcontext);
272 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, in_syscall);
273
274 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
275 }
276
277 if (err)
278 return -EFAULT;
279
280
281
282
283
284
285 err |= __put_user(in_syscall ? INSN_LDI_R25_1 : INSN_LDI_R25_0,
286 &frame->tramp[SIGRESTARTBLOCK_TRAMP+0]);
287 err |= __put_user(INSN_LDI_R20,
288 &frame->tramp[SIGRESTARTBLOCK_TRAMP+1]);
289 err |= __put_user(INSN_BLE_SR2_R0,
290 &frame->tramp[SIGRESTARTBLOCK_TRAMP+2]);
291 err |= __put_user(INSN_NOP, &frame->tramp[SIGRESTARTBLOCK_TRAMP+3]);
292
293#if DEBUG_SIG
294
295 {
296 unsigned long sid;
297 asm ("mfsp %%sr3,%0" : "=r" (sid));
298 DBG(1,"setup_rt_frame: Flushing 64 bytes at space %#x offset %p\n",
299 sid, frame->tramp);
300 }
301#endif
302
303 flush_user_dcache_range((unsigned long) &frame->tramp[0],
304 (unsigned long) &frame->tramp[TRAMP_SIZE]);
305 flush_user_icache_range((unsigned long) &frame->tramp[0],
306 (unsigned long) &frame->tramp[TRAMP_SIZE]);
307
308
309
310
311
312 rp = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP];
313
314 if (err)
315 return -EFAULT;
316
317 haddr = A(ksig->ka.sa.sa_handler);
318
319#ifdef CONFIG_64BIT
320 if (is_compat_task()) {
321#endif
322 if (haddr & PA_PLABEL_FDESC) {
323 Elf32_Fdesc fdesc;
324 Elf32_Fdesc __user *ufdesc = (Elf32_Fdesc __user *)A(haddr & ~3);
325
326 err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
327
328 if (err)
329 return -EFAULT;
330
331 haddr = fdesc.addr;
332 regs->gr[19] = fdesc.gp;
333 }
334#ifdef CONFIG_64BIT
335 } else {
336 Elf64_Fdesc fdesc;
337 Elf64_Fdesc __user *ufdesc = (Elf64_Fdesc __user *)A(haddr & ~3);
338
339 err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
340
341 if (err)
342 return -EFAULT;
343
344 haddr = fdesc.addr;
345 regs->gr[19] = fdesc.gp;
346 DBG(1,"setup_rt_frame: 64 bit signal, exe=%#lx, r19=%#lx, in_syscall=%d\n",
347 haddr, regs->gr[19], in_syscall);
348 }
349#endif
350
351
352
353 sigframe_size = PARISC_RT_SIGFRAME_SIZE;
354#ifdef CONFIG_64BIT
355 if (is_compat_task())
356 sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
357#endif
358 if (in_syscall) {
359 regs->gr[31] = haddr;
360#ifdef CONFIG_64BIT
361 if (!test_thread_flag(TIF_32BIT))
362 sigframe_size |= 1;
363#endif
364 } else {
365 unsigned long psw = USER_PSW;
366#ifdef CONFIG_64BIT
367 if (!test_thread_flag(TIF_32BIT))
368 psw |= PSW_W;
369#endif
370
371
372
373
374
375
376
377 if (pa_psw(current)->r) {
378 pa_psw(current)->r = 0;
379 psw |= PSW_R;
380 mtctl(-1, 0);
381 }
382
383 regs->gr[0] = psw;
384 regs->iaoq[0] = haddr | 3;
385 regs->iaoq[1] = regs->iaoq[0] + 4;
386 }
387
388 regs->gr[2] = rp;
389 regs->gr[26] = ksig->sig;
390
391#ifdef CONFIG_64BIT
392 if (is_compat_task()) {
393 regs->gr[25] = A(&compat_frame->info);
394 regs->gr[24] = A(&compat_frame->uc);
395 } else
396#endif
397 {
398 regs->gr[25] = A(&frame->info);
399 regs->gr[24] = A(&frame->uc);
400 }
401
402 DBG(1,"setup_rt_frame: making sigreturn frame: %#lx + %#lx = %#lx\n",
403 regs->gr[30], sigframe_size,
404 regs->gr[30] + sigframe_size);
405
406 regs->gr[30] = (A(frame) + sigframe_size);
407
408
409 DBG(1,"setup_rt_frame: sig deliver (%s,%d) frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",
410 current->comm, current->pid, frame, regs->gr[30],
411 regs->iaoq[0], regs->iaoq[1], rp);
412
413 return 0;
414}
415
416
417
418
419
420static void
421handle_signal(struct ksignal *ksig, struct pt_regs *regs, int in_syscall)
422{
423 int ret;
424 sigset_t *oldset = sigmask_to_save();
425
426 DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n",
427 ksig->sig, ksig->ka, ksig->info, oldset, regs);
428
429
430 ret = setup_rt_frame(ksig, oldset, regs, in_syscall);
431
432 signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP) ||
433 test_thread_flag(TIF_BLOCKSTEP));
434
435 DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
436 regs->gr[28]);
437}
438
439static inline void
440syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
441{
442 if (regs->orig_r28)
443 return;
444 regs->orig_r28 = 1;
445
446 switch (regs->gr[28]) {
447 case -ERESTART_RESTARTBLOCK:
448 case -ERESTARTNOHAND:
449 DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
450 regs->gr[28] = -EINTR;
451 break;
452
453 case -ERESTARTSYS:
454 if (!(ka->sa.sa_flags & SA_RESTART)) {
455 DBG(1,"ERESTARTSYS: putting -EINTR\n");
456 regs->gr[28] = -EINTR;
457 break;
458 }
459
460 case -ERESTARTNOINTR:
461
462
463
464 regs->gr[31] -= 8;
465 break;
466 }
467}
468
469static inline void
470insert_restart_trampoline(struct pt_regs *regs)
471{
472 if (regs->orig_r28)
473 return;
474 regs->orig_r28 = 1;
475 switch(regs->gr[28]) {
476 case -ERESTART_RESTARTBLOCK: {
477
478 unsigned int *usp = (unsigned int *)regs->gr[30];
479
480
481
482
483
484
485
486
487
488
489#ifdef CONFIG_64BIT
490 put_user(regs->gr[31] >> 32, &usp[0]);
491 put_user(regs->gr[31] & 0xffffffff, &usp[1]);
492 put_user(0x0fc010df, &usp[2]);
493#else
494 put_user(regs->gr[31], &usp[0]);
495 put_user(0x0fc0109f, &usp[2]);
496#endif
497 put_user(0xe0008200, &usp[3]);
498 put_user(0x34140000, &usp[4]);
499
500
501
502
503
504
505 flush_user_dcache_range(regs->gr[30], regs->gr[30] + 4);
506 flush_user_icache_range(regs->gr[30], regs->gr[30] + 4);
507
508 regs->gr[31] = regs->gr[30] + 8;
509 return;
510 }
511 case -ERESTARTNOHAND:
512 case -ERESTARTSYS:
513 case -ERESTARTNOINTR: {
514
515
516
517
518
519 regs->gr[31] -= 8;
520 return;
521 }
522 default:
523 break;
524 }
525}
526
527
528
529
530
531
532
533
534
535
536
537
538asmlinkage void
539do_signal(struct pt_regs *regs, long in_syscall)
540{
541 struct ksignal ksig;
542
543 DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n",
544 regs, regs->sr[7], in_syscall);
545
546 if (get_signal(&ksig)) {
547 DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
548
549 if (in_syscall)
550 syscall_restart(regs, &ksig.ka);
551
552 handle_signal(&ksig, regs, in_syscall);
553 return;
554 }
555
556
557 if (in_syscall)
558 insert_restart_trampoline(regs);
559
560 DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n",
561 regs->gr[28]);
562
563 restore_saved_sigmask();
564}
565
566void do_notify_resume(struct pt_regs *regs, long in_syscall)
567{
568 if (test_thread_flag(TIF_SIGPENDING))
569 do_signal(regs, in_syscall);
570
571 if (test_thread_flag(TIF_NOTIFY_RESUME)) {
572 clear_thread_flag(TIF_NOTIFY_RESUME);
573 tracehook_notify_resume(regs);
574 }
575}
576