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(int sig, struct k_sigaction *ka, siginfo_t *info,
231 sigset_t *set, struct pt_regs *regs, 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(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, 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, 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, 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 goto give_sigsegv;
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 goto give_sigsegv;
316
317 haddr = A(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 goto give_sigsegv;
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 goto give_sigsegv;
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] = 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 1;
414
415give_sigsegv:
416 DBG(1,"setup_rt_frame: sending SIGSEGV\n");
417 force_sigsegv(sig, current);
418 return 0;
419}
420
421
422
423
424
425static void
426handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
427 struct pt_regs *regs, int in_syscall)
428{
429 sigset_t *oldset = sigmask_to_save();
430 DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n",
431 sig, ka, info, oldset, regs);
432
433
434 if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
435 return;
436
437 signal_delivered(sig, info, ka, regs,
438 test_thread_flag(TIF_SINGLESTEP) ||
439 test_thread_flag(TIF_BLOCKSTEP));
440
441 DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
442 regs->gr[28]);
443}
444
445static inline void
446syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
447{
448 if (regs->orig_r28)
449 return;
450 regs->orig_r28 = 1;
451
452 switch (regs->gr[28]) {
453 case -ERESTART_RESTARTBLOCK:
454 case -ERESTARTNOHAND:
455 DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
456 regs->gr[28] = -EINTR;
457 break;
458
459 case -ERESTARTSYS:
460 if (!(ka->sa.sa_flags & SA_RESTART)) {
461 DBG(1,"ERESTARTSYS: putting -EINTR\n");
462 regs->gr[28] = -EINTR;
463 break;
464 }
465
466 case -ERESTARTNOINTR:
467
468
469
470 regs->gr[31] -= 8;
471 break;
472 }
473}
474
475static inline void
476insert_restart_trampoline(struct pt_regs *regs)
477{
478 if (regs->orig_r28)
479 return;
480 regs->orig_r28 = 1;
481 switch(regs->gr[28]) {
482 case -ERESTART_RESTARTBLOCK: {
483
484 unsigned int *usp = (unsigned int *)regs->gr[30];
485
486
487
488
489
490
491
492
493
494
495#ifdef CONFIG_64BIT
496 put_user(regs->gr[31] >> 32, &usp[0]);
497 put_user(regs->gr[31] & 0xffffffff, &usp[1]);
498 put_user(0x0fc010df, &usp[2]);
499#else
500 put_user(regs->gr[31], &usp[0]);
501 put_user(0x0fc0109f, &usp[2]);
502#endif
503 put_user(0xe0008200, &usp[3]);
504 put_user(0x34140000, &usp[4]);
505
506
507
508
509
510
511 flush_user_dcache_range(regs->gr[30], regs->gr[30] + 4);
512 flush_user_icache_range(regs->gr[30], regs->gr[30] + 4);
513
514 regs->gr[31] = regs->gr[30] + 8;
515 return;
516 }
517 case -ERESTARTNOHAND:
518 case -ERESTARTSYS:
519 case -ERESTARTNOINTR: {
520
521
522
523
524
525 regs->gr[31] -= 8;
526 return;
527 }
528 default:
529 break;
530 }
531}
532
533
534
535
536
537
538
539
540
541
542
543
544asmlinkage void
545do_signal(struct pt_regs *regs, long in_syscall)
546{
547 siginfo_t info;
548 struct k_sigaction ka;
549 int signr;
550
551 DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n",
552 regs, regs->sr[7], in_syscall);
553
554 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
555 DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
556
557 if (signr > 0) {
558
559 if (in_syscall)
560 syscall_restart(regs, &ka);
561
562 handle_signal(signr, &info, &ka, regs, in_syscall);
563 return;
564 }
565
566
567 if (in_syscall)
568 insert_restart_trampoline(regs);
569
570 DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n",
571 regs->gr[28]);
572
573 restore_saved_sigmask();
574}
575
576void do_notify_resume(struct pt_regs *regs, long in_syscall)
577{
578 if (test_thread_flag(TIF_SIGPENDING))
579 do_signal(regs, in_syscall);
580
581 if (test_thread_flag(TIF_NOTIFY_RESUME)) {
582 clear_thread_flag(TIF_NOTIFY_RESUME);
583 tracehook_notify_resume(regs);
584 }
585}
586