1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <linux/sched.h>
16#include <linux/sched/debug.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 <linux/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->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 unsigned long start, end;
237 int err = 0;
238#ifdef CONFIG_64BIT
239 struct compat_rt_sigframe __user * compat_frame;
240 compat_sigset_t compat_set;
241#endif
242
243 usp = (regs->gr[30] & ~(0x01UL));
244
245 frame = get_sigframe(&ksig->ka, usp, sizeof(*frame));
246
247 DBG(1,"SETUP_RT_FRAME: START\n");
248 DBG(1,"setup_rt_frame: frame %p info %p\n", frame, ksig->info);
249
250
251#ifdef CONFIG_64BIT
252
253 compat_frame = (struct compat_rt_sigframe __user *)frame;
254
255 if (is_compat_task()) {
256 DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info);
257 err |= copy_siginfo_to_user32(&compat_frame->info, &ksig->info);
258 err |= __compat_save_altstack( &compat_frame->uc.uc_stack, regs->gr[30]);
259 DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &compat_frame->uc);
260 DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &compat_frame->uc.uc_mcontext);
261 err |= setup_sigcontext32(&compat_frame->uc.uc_mcontext,
262 &compat_frame->regs, regs, in_syscall);
263 sigset_64to32(&compat_set,set);
264 err |= __copy_to_user(&compat_frame->uc.uc_sigmask, &compat_set, sizeof(compat_set));
265 } else
266#endif
267 {
268 DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &frame->info);
269 err |= copy_siginfo_to_user(&frame->info, &ksig->info);
270 err |= __save_altstack(&frame->uc.uc_stack, regs->gr[30]);
271 DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &frame->uc);
272 DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &frame->uc.uc_mcontext);
273 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, in_syscall);
274
275 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
276 }
277
278 if (err)
279 return -EFAULT;
280
281
282
283
284
285
286 err |= __put_user(in_syscall ? INSN_LDI_R25_1 : INSN_LDI_R25_0,
287 &frame->tramp[SIGRESTARTBLOCK_TRAMP+0]);
288 err |= __put_user(INSN_LDI_R20,
289 &frame->tramp[SIGRESTARTBLOCK_TRAMP+1]);
290 err |= __put_user(INSN_BLE_SR2_R0,
291 &frame->tramp[SIGRESTARTBLOCK_TRAMP+2]);
292 err |= __put_user(INSN_NOP, &frame->tramp[SIGRESTARTBLOCK_TRAMP+3]);
293
294#if DEBUG_SIG
295
296 {
297 unsigned long sid;
298 asm ("mfsp %%sr3,%0" : "=r" (sid));
299 DBG(1,"setup_rt_frame: Flushing 64 bytes at space %#x offset %p\n",
300 sid, frame->tramp);
301 }
302#endif
303
304 start = (unsigned long) &frame->tramp[0];
305 end = (unsigned long) &frame->tramp[TRAMP_SIZE];
306 flush_user_dcache_range_asm(start, end);
307 flush_user_icache_range_asm(start, end);
308
309
310
311
312
313 rp = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP];
314
315 if (err)
316 return -EFAULT;
317
318 haddr = A(ksig->ka.sa.sa_handler);
319
320#ifdef CONFIG_64BIT
321 if (is_compat_task()) {
322#endif
323 if (haddr & PA_PLABEL_FDESC) {
324 Elf32_Fdesc fdesc;
325 Elf32_Fdesc __user *ufdesc = (Elf32_Fdesc __user *)A(haddr & ~3);
326
327 err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
328
329 if (err)
330 return -EFAULT;
331
332 haddr = fdesc.addr;
333 regs->gr[19] = fdesc.gp;
334 }
335#ifdef CONFIG_64BIT
336 } else {
337 Elf64_Fdesc fdesc;
338 Elf64_Fdesc __user *ufdesc = (Elf64_Fdesc __user *)A(haddr & ~3);
339
340 err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
341
342 if (err)
343 return -EFAULT;
344
345 haddr = fdesc.addr;
346 regs->gr[19] = fdesc.gp;
347 DBG(1,"setup_rt_frame: 64 bit signal, exe=%#lx, r19=%#lx, in_syscall=%d\n",
348 haddr, regs->gr[19], in_syscall);
349 }
350#endif
351
352
353
354 sigframe_size = PARISC_RT_SIGFRAME_SIZE;
355#ifdef CONFIG_64BIT
356 if (is_compat_task())
357 sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
358#endif
359 if (in_syscall) {
360 regs->gr[31] = haddr;
361#ifdef CONFIG_64BIT
362 if (!test_thread_flag(TIF_32BIT))
363 sigframe_size |= 1;
364#endif
365 } else {
366 unsigned long psw = USER_PSW;
367#ifdef CONFIG_64BIT
368 if (!test_thread_flag(TIF_32BIT))
369 psw |= PSW_W;
370#endif
371
372
373
374
375
376
377
378 if (pa_psw(current)->r) {
379 pa_psw(current)->r = 0;
380 psw |= PSW_R;
381 mtctl(-1, 0);
382 }
383
384 regs->gr[0] = psw;
385 regs->iaoq[0] = haddr | 3;
386 regs->iaoq[1] = regs->iaoq[0] + 4;
387 }
388
389 regs->gr[2] = rp;
390 regs->gr[26] = ksig->sig;
391
392#ifdef CONFIG_64BIT
393 if (is_compat_task()) {
394 regs->gr[25] = A(&compat_frame->info);
395 regs->gr[24] = A(&compat_frame->uc);
396 } else
397#endif
398 {
399 regs->gr[25] = A(&frame->info);
400 regs->gr[24] = A(&frame->uc);
401 }
402
403 DBG(1,"setup_rt_frame: making sigreturn frame: %#lx + %#lx = %#lx\n",
404 regs->gr[30], sigframe_size,
405 regs->gr[30] + sigframe_size);
406
407 regs->gr[30] = (A(frame) + sigframe_size);
408
409
410 DBG(1,"setup_rt_frame: sig deliver (%s,%d) frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",
411 current->comm, current->pid, frame, regs->gr[30],
412 regs->iaoq[0], regs->iaoq[1], rp);
413
414 return 0;
415}
416
417
418
419
420
421static void
422handle_signal(struct ksignal *ksig, struct pt_regs *regs, int in_syscall)
423{
424 int ret;
425 sigset_t *oldset = sigmask_to_save();
426
427 DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n",
428 ksig->sig, ksig->ka, ksig->info, oldset, regs);
429
430
431 ret = setup_rt_frame(ksig, oldset, regs, in_syscall);
432
433 signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP) ||
434 test_thread_flag(TIF_BLOCKSTEP));
435
436 DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
437 regs->gr[28]);
438}
439
440
441
442
443
444
445static void check_syscallno_in_delay_branch(struct pt_regs *regs)
446{
447 u32 opcode, source_reg;
448 u32 __user *uaddr;
449 int err;
450
451
452
453
454
455
456
457
458
459
460
461
462 regs->gr[31] -= 8;
463
464
465 uaddr = (unsigned int *) ((regs->gr[31] & ~3) + 4);
466 err = get_user(opcode, uaddr);
467 if (err)
468 return;
469
470
471 if ((opcode & 0xffff0000) == 0x34140000)
472 return;
473
474
475 if (opcode == INSN_NOP)
476 return;
477
478
479 if ((opcode & 0xffe0ffff) == 0x08000254) {
480 source_reg = (opcode >> 16) & 31;
481 regs->gr[source_reg] = regs->gr[20];
482 return;
483 }
484
485 pr_warn("syscall restart: %s (pid %d): unexpected opcode 0x%08x\n",
486 current->comm, task_pid_nr(current), opcode);
487}
488
489static inline void
490syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
491{
492 if (regs->orig_r28)
493 return;
494 regs->orig_r28 = 1;
495
496 switch (regs->gr[28]) {
497 case -ERESTART_RESTARTBLOCK:
498 case -ERESTARTNOHAND:
499 DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
500 regs->gr[28] = -EINTR;
501 break;
502
503 case -ERESTARTSYS:
504 if (!(ka->sa.sa_flags & SA_RESTART)) {
505 DBG(1,"ERESTARTSYS: putting -EINTR\n");
506 regs->gr[28] = -EINTR;
507 break;
508 }
509
510 case -ERESTARTNOINTR:
511 check_syscallno_in_delay_branch(regs);
512 break;
513 }
514}
515
516static inline void
517insert_restart_trampoline(struct pt_regs *regs)
518{
519 if (regs->orig_r28)
520 return;
521 regs->orig_r28 = 1;
522 switch(regs->gr[28]) {
523 case -ERESTART_RESTARTBLOCK: {
524
525 unsigned int *usp = (unsigned int *)regs->gr[30];
526 unsigned long start = (unsigned long) &usp[2];
527 unsigned long end = (unsigned long) &usp[5];
528 long err = 0;
529
530
531
532
533
534
535
536
537
538
539#ifdef CONFIG_64BIT
540 err |= put_user(regs->gr[31] >> 32, &usp[0]);
541 err |= put_user(regs->gr[31] & 0xffffffff, &usp[1]);
542 err |= put_user(0x0fc010df, &usp[2]);
543#else
544 err |= put_user(regs->gr[31], &usp[0]);
545 err |= put_user(0x0fc0109f, &usp[2]);
546#endif
547 err |= put_user(0xe0008200, &usp[3]);
548 err |= put_user(0x34140000, &usp[4]);
549
550 WARN_ON(err);
551
552
553 flush_user_dcache_range_asm(start, end);
554 flush_user_icache_range_asm(start, end);
555
556 regs->gr[31] = regs->gr[30] + 8;
557 return;
558 }
559 case -ERESTARTNOHAND:
560 case -ERESTARTSYS:
561 case -ERESTARTNOINTR:
562 check_syscallno_in_delay_branch(regs);
563 return;
564 default:
565 break;
566 }
567}
568
569
570
571
572
573
574
575
576
577
578
579
580asmlinkage void
581do_signal(struct pt_regs *regs, long in_syscall)
582{
583 struct ksignal ksig;
584
585 DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n",
586 regs, regs->sr[7], in_syscall);
587
588 if (get_signal(&ksig)) {
589 DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
590
591 if (in_syscall)
592 syscall_restart(regs, &ksig.ka);
593
594 handle_signal(&ksig, regs, in_syscall);
595 return;
596 }
597
598
599 if (in_syscall)
600 insert_restart_trampoline(regs);
601
602 DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n",
603 regs->gr[28]);
604
605 restore_saved_sigmask();
606}
607
608void do_notify_resume(struct pt_regs *regs, long in_syscall)
609{
610 if (test_thread_flag(TIF_SIGPENDING))
611 do_signal(regs, in_syscall);
612
613 if (test_thread_flag(TIF_NOTIFY_RESUME)) {
614 clear_thread_flag(TIF_NOTIFY_RESUME);
615 tracehook_notify_resume(regs);
616 }
617}
618