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