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