1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * PA-RISC architecture-specific signal handling support. |
4 | * |
5 | * Copyright (C) 2000 David Huggins-Daines <dhd@debian.org> |
6 | * Copyright (C) 2000 Linuxcare, Inc. |
7 | * Copyright (C) 2000-2022 Helge Deller <deller@gmx.de> |
8 | * Copyright (C) 2022 John David Anglin <dave.anglin@bell.net> |
9 | * |
10 | * Based on the ia64, i386, and alpha versions. |
11 | */ |
12 | |
13 | #include <linux/sched.h> |
14 | #include <linux/sched/debug.h> |
15 | #include <linux/mm.h> |
16 | #include <linux/smp.h> |
17 | #include <linux/kernel.h> |
18 | #include <linux/signal.h> |
19 | #include <linux/errno.h> |
20 | #include <linux/wait.h> |
21 | #include <linux/ptrace.h> |
22 | #include <linux/resume_user_mode.h> |
23 | #include <linux/unistd.h> |
24 | #include <linux/stddef.h> |
25 | #include <linux/compat.h> |
26 | #include <linux/elf.h> |
27 | #include <asm/ucontext.h> |
28 | #include <asm/rt_sigframe.h> |
29 | #include <linux/uaccess.h> |
30 | #include <asm/cacheflush.h> |
31 | #include <asm/asm-offsets.h> |
32 | #include <asm/vdso.h> |
33 | |
34 | #ifdef CONFIG_COMPAT |
35 | #include "signal32.h" |
36 | #endif |
37 | |
38 | #define DEBUG_SIG 0 |
39 | #define DEBUG_SIG_LEVEL 2 |
40 | |
41 | #if DEBUG_SIG |
42 | #define DBG(LEVEL, ...) \ |
43 | ((DEBUG_SIG_LEVEL >= LEVEL) \ |
44 | ? printk(__VA_ARGS__) : (void) 0) |
45 | #else |
46 | #define DBG(LEVEL, ...) |
47 | #endif |
48 | |
49 | /* gcc will complain if a pointer is cast to an integer of different |
50 | * size. If you really need to do this (and we do for an ELF32 user |
51 | * application in an ELF64 kernel) then you have to do a cast to an |
52 | * integer of the same size first. The A() macro accomplishes |
53 | * this. */ |
54 | #define A(__x) ((unsigned long)(__x)) |
55 | |
56 | /* |
57 | * Do a signal return - restore sigcontext. |
58 | */ |
59 | |
60 | static long |
61 | restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) |
62 | { |
63 | long err = 0; |
64 | |
65 | err |= __copy_from_user(to: regs->gr, from: sc->sc_gr, n: sizeof(regs->gr)); |
66 | err |= __copy_from_user(to: regs->fr, from: sc->sc_fr, n: sizeof(regs->fr)); |
67 | err |= __copy_from_user(to: regs->iaoq, from: sc->sc_iaoq, n: sizeof(regs->iaoq)); |
68 | err |= __copy_from_user(to: regs->iasq, from: sc->sc_iasq, n: sizeof(regs->iasq)); |
69 | err |= __get_user(regs->sar, &sc->sc_sar); |
70 | DBG(2, "%s: iaoq is %#lx / %#lx\n" , |
71 | __func__, regs->iaoq[0], regs->iaoq[1]); |
72 | DBG(2, "%s: r28 is %ld\n" , __func__, regs->gr[28]); |
73 | return err; |
74 | } |
75 | |
76 | asmlinkage void |
77 | sys_rt_sigreturn(struct pt_regs *regs, int in_syscall) |
78 | { |
79 | struct rt_sigframe __user *frame; |
80 | sigset_t set; |
81 | unsigned long usp = (regs->gr[30] & ~(0x01UL)); |
82 | unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE; |
83 | #ifdef CONFIG_64BIT |
84 | struct compat_rt_sigframe __user * compat_frame; |
85 | |
86 | if (is_compat_task()) |
87 | sigframe_size = PARISC_RT_SIGFRAME_SIZE32; |
88 | #endif |
89 | |
90 | current->restart_block.fn = do_no_restart_syscall; |
91 | |
92 | /* Unwind the user stack to get the rt_sigframe structure. */ |
93 | frame = (struct rt_sigframe __user *) |
94 | (usp - sigframe_size); |
95 | DBG(2, "%s: frame is %p pid %d\n" , __func__, frame, task_pid_nr(current)); |
96 | |
97 | regs->orig_r28 = 1; /* no restarts for sigreturn */ |
98 | |
99 | #ifdef CONFIG_64BIT |
100 | compat_frame = (struct compat_rt_sigframe __user *)frame; |
101 | |
102 | if (is_compat_task()) { |
103 | if (get_compat_sigset(set: &set, compat: &compat_frame->uc.uc_sigmask)) |
104 | goto give_sigsegv; |
105 | } else |
106 | #endif |
107 | { |
108 | if (__copy_from_user(to: &set, from: &frame->uc.uc_sigmask, n: sizeof(set))) |
109 | goto give_sigsegv; |
110 | } |
111 | |
112 | set_current_blocked(&set); |
113 | |
114 | /* Good thing we saved the old gr[30], eh? */ |
115 | #ifdef CONFIG_64BIT |
116 | if (is_compat_task()) { |
117 | DBG(1, "%s: compat_frame->uc.uc_mcontext 0x%p\n" , |
118 | __func__, &compat_frame->uc.uc_mcontext); |
119 | // FIXME: Load upper half from register file |
120 | if (restore_sigcontext32(sc: &compat_frame->uc.uc_mcontext, |
121 | rf: &compat_frame->regs, regs)) |
122 | goto give_sigsegv; |
123 | DBG(1, "%s: usp %#08lx stack 0x%p\n" , |
124 | __func__, usp, &compat_frame->uc.uc_stack); |
125 | if (compat_restore_altstack(uss: &compat_frame->uc.uc_stack)) |
126 | goto give_sigsegv; |
127 | } else |
128 | #endif |
129 | { |
130 | DBG(1, "%s: frame->uc.uc_mcontext 0x%p\n" , |
131 | __func__, &frame->uc.uc_mcontext); |
132 | if (restore_sigcontext(sc: &frame->uc.uc_mcontext, regs)) |
133 | goto give_sigsegv; |
134 | DBG(1, "%s: usp %#08lx stack 0x%p\n" , |
135 | __func__, usp, &frame->uc.uc_stack); |
136 | if (restore_altstack(&frame->uc.uc_stack)) |
137 | goto give_sigsegv; |
138 | } |
139 | |
140 | |
141 | |
142 | /* If we are on the syscall path IAOQ will not be restored, and |
143 | * if we are on the interrupt path we must not corrupt gr31. |
144 | */ |
145 | if (in_syscall) |
146 | regs->gr[31] = regs->iaoq[0]; |
147 | |
148 | return; |
149 | |
150 | give_sigsegv: |
151 | DBG(1, "%s: Sending SIGSEGV\n" , __func__); |
152 | force_sig(SIGSEGV); |
153 | return; |
154 | } |
155 | |
156 | /* |
157 | * Set up a signal frame. |
158 | */ |
159 | |
160 | static inline void __user * |
161 | get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) |
162 | { |
163 | /*FIXME: ELF32 vs. ELF64 has different frame_size, but since we |
164 | don't use the parameter it doesn't matter */ |
165 | |
166 | DBG(1, "%s: ka = %#lx, sp = %#lx, frame_size = %zu\n" , |
167 | __func__, (unsigned long)ka, sp, frame_size); |
168 | |
169 | /* Align alternate stack and reserve 64 bytes for the signal |
170 | handler's frame marker. */ |
171 | if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp)) |
172 | sp = (current->sas_ss_sp + 0x7f) & ~0x3f; /* Stacks grow up! */ |
173 | |
174 | DBG(1, "%s: Returning sp = %#lx\n" , __func__, (unsigned long)sp); |
175 | return (void __user *) sp; /* Stacks grow up. Fun. */ |
176 | } |
177 | |
178 | static long |
179 | setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, long in_syscall) |
180 | |
181 | { |
182 | unsigned long flags = 0; |
183 | long err = 0; |
184 | |
185 | if (on_sig_stack(sp: (unsigned long) sc)) |
186 | flags |= PARISC_SC_FLAG_ONSTACK; |
187 | if (in_syscall) { |
188 | flags |= PARISC_SC_FLAG_IN_SYSCALL; |
189 | /* regs->iaoq is undefined in the syscall return path */ |
190 | err |= __put_user(regs->gr[31], &sc->sc_iaoq[0]); |
191 | err |= __put_user(regs->gr[31]+4, &sc->sc_iaoq[1]); |
192 | err |= __put_user(regs->sr[3], &sc->sc_iasq[0]); |
193 | err |= __put_user(regs->sr[3], &sc->sc_iasq[1]); |
194 | DBG(1, "%s: iaoq %#lx / %#lx (in syscall)\n" , |
195 | __func__, regs->gr[31], regs->gr[31]+4); |
196 | } else { |
197 | err |= __copy_to_user(to: sc->sc_iaoq, from: regs->iaoq, n: sizeof(regs->iaoq)); |
198 | err |= __copy_to_user(to: sc->sc_iasq, from: regs->iasq, n: sizeof(regs->iasq)); |
199 | DBG(1, "%s: iaoq %#lx / %#lx (not in syscall)\n" , |
200 | __func__, regs->iaoq[0], regs->iaoq[1]); |
201 | } |
202 | |
203 | err |= __put_user(flags, &sc->sc_flags); |
204 | err |= __copy_to_user(to: sc->sc_gr, from: regs->gr, n: sizeof(regs->gr)); |
205 | err |= __copy_to_user(to: sc->sc_fr, from: regs->fr, n: sizeof(regs->fr)); |
206 | err |= __put_user(regs->sar, &sc->sc_sar); |
207 | DBG(1, "%s: r28 is %ld\n" , __func__, regs->gr[28]); |
208 | |
209 | return err; |
210 | } |
211 | |
212 | static long |
213 | setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs, |
214 | long in_syscall) |
215 | { |
216 | struct rt_sigframe __user *frame; |
217 | unsigned long rp, usp; |
218 | unsigned long haddr, sigframe_size; |
219 | unsigned long start; |
220 | int err = 0; |
221 | #ifdef CONFIG_64BIT |
222 | struct compat_rt_sigframe __user * compat_frame; |
223 | #endif |
224 | |
225 | usp = (regs->gr[30] & ~(0x01UL)); |
226 | sigframe_size = PARISC_RT_SIGFRAME_SIZE; |
227 | #ifdef CONFIG_64BIT |
228 | if (is_compat_task()) { |
229 | /* The gcc alloca implementation leaves garbage in the upper 32 bits of sp */ |
230 | usp = (compat_uint_t)usp; |
231 | sigframe_size = PARISC_RT_SIGFRAME_SIZE32; |
232 | } |
233 | #endif |
234 | frame = get_sigframe(ka: &ksig->ka, sp: usp, frame_size: sigframe_size); |
235 | |
236 | DBG(1, "%s: frame %p info %p\n" , __func__, frame, &ksig->info); |
237 | |
238 | start = (unsigned long) frame; |
239 | if (start >= TASK_SIZE_MAX - sigframe_size) |
240 | return -EFAULT; |
241 | |
242 | #ifdef CONFIG_64BIT |
243 | |
244 | compat_frame = (struct compat_rt_sigframe __user *)frame; |
245 | |
246 | if (is_compat_task()) { |
247 | DBG(1, "%s: frame->info = 0x%p\n" , __func__, &compat_frame->info); |
248 | err |= copy_siginfo_to_user32(to: &compat_frame->info, from: &ksig->info); |
249 | err |= __compat_save_altstack( &compat_frame->uc.uc_stack, regs->gr[30]); |
250 | DBG(1, "%s: frame->uc = 0x%p\n" , __func__, &compat_frame->uc); |
251 | DBG(1, "%s: frame->uc.uc_mcontext = 0x%p\n" , |
252 | __func__, &compat_frame->uc.uc_mcontext); |
253 | err |= setup_sigcontext32(sc: &compat_frame->uc.uc_mcontext, |
254 | rf: &compat_frame->regs, regs, in_syscall); |
255 | err |= put_compat_sigset(compat: &compat_frame->uc.uc_sigmask, set, |
256 | size: sizeof(compat_sigset_t)); |
257 | } else |
258 | #endif |
259 | { |
260 | DBG(1, "%s: frame->info = 0x%p\n" , __func__, &frame->info); |
261 | err |= copy_siginfo_to_user(to: &frame->info, from: &ksig->info); |
262 | err |= __save_altstack(&frame->uc.uc_stack, regs->gr[30]); |
263 | DBG(1, "%s: frame->uc = 0x%p\n" , __func__, &frame->uc); |
264 | DBG(1, "%s: frame->uc.uc_mcontext = 0x%p\n" , |
265 | __func__, &frame->uc.uc_mcontext); |
266 | err |= setup_sigcontext(sc: &frame->uc.uc_mcontext, regs, in_syscall); |
267 | /* FIXME: Should probably be converted as well for the compat case */ |
268 | err |= __copy_to_user(to: &frame->uc.uc_sigmask, from: set, n: sizeof(*set)); |
269 | } |
270 | |
271 | if (err) |
272 | return -EFAULT; |
273 | |
274 | #ifdef CONFIG_64BIT |
275 | if (!is_compat_task()) |
276 | rp = VDSO64_SYMBOL(current, sigtramp_rt); |
277 | else |
278 | #endif |
279 | rp = VDSO32_SYMBOL(current, sigtramp_rt); |
280 | |
281 | if (in_syscall) |
282 | rp += 4*4; /* skip 4 instructions and start at ldi 1,%r25 */ |
283 | |
284 | haddr = A(ksig->ka.sa.sa_handler); |
285 | /* The sa_handler may be a pointer to a function descriptor */ |
286 | #ifdef CONFIG_64BIT |
287 | if (is_compat_task()) { |
288 | #endif |
289 | if (haddr & PA_PLABEL_FDESC) { |
290 | Elf32_Fdesc fdesc; |
291 | Elf32_Fdesc __user *ufdesc = (Elf32_Fdesc __user *)A(haddr & ~3); |
292 | |
293 | err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc)); |
294 | |
295 | if (err) |
296 | return -EFAULT; |
297 | |
298 | haddr = fdesc.addr; |
299 | regs->gr[19] = fdesc.gp; |
300 | } |
301 | #ifdef CONFIG_64BIT |
302 | } else { |
303 | Elf64_Fdesc fdesc; |
304 | Elf64_Fdesc __user *ufdesc = (Elf64_Fdesc __user *)A(haddr & ~3); |
305 | |
306 | err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc)); |
307 | |
308 | if (err) |
309 | return -EFAULT; |
310 | |
311 | haddr = fdesc.addr; |
312 | regs->gr[19] = fdesc.gp; |
313 | DBG(1, "%s: 64 bit signal, exe=%#lx, r19=%#lx, in_syscall=%d\n" , |
314 | __func__, haddr, regs->gr[19], in_syscall); |
315 | } |
316 | #endif |
317 | |
318 | /* The syscall return path will create IAOQ values from r31. |
319 | */ |
320 | if (in_syscall) { |
321 | regs->gr[31] = haddr; |
322 | #ifdef CONFIG_64BIT |
323 | if (!test_thread_flag(TIF_32BIT)) |
324 | sigframe_size |= 1; /* XXX ???? */ |
325 | #endif |
326 | } else { |
327 | unsigned long psw = USER_PSW; |
328 | #ifdef CONFIG_64BIT |
329 | if (!test_thread_flag(TIF_32BIT)) |
330 | psw |= PSW_W; |
331 | #endif |
332 | |
333 | /* If we are singlestepping, arrange a trap to be delivered |
334 | when we return to userspace. Note the semantics -- we |
335 | should trap before the first insn in the handler is |
336 | executed. Ref: |
337 | http://sources.redhat.com/ml/gdb/2004-11/msg00245.html |
338 | */ |
339 | if (pa_psw(current)->r) { |
340 | pa_psw(current)->r = 0; |
341 | psw |= PSW_R; |
342 | mtctl(-1, 0); |
343 | } |
344 | |
345 | regs->gr[0] = psw; |
346 | regs->iaoq[0] = haddr | PRIV_USER; |
347 | regs->iaoq[1] = regs->iaoq[0] + 4; |
348 | } |
349 | |
350 | regs->gr[2] = rp; /* userland return pointer */ |
351 | regs->gr[26] = ksig->sig; /* signal number */ |
352 | |
353 | #ifdef CONFIG_64BIT |
354 | if (is_compat_task()) { |
355 | regs->gr[25] = A(&compat_frame->info); /* siginfo pointer */ |
356 | regs->gr[24] = A(&compat_frame->uc); /* ucontext pointer */ |
357 | } else |
358 | #endif |
359 | { |
360 | regs->gr[25] = A(&frame->info); /* siginfo pointer */ |
361 | regs->gr[24] = A(&frame->uc); /* ucontext pointer */ |
362 | } |
363 | |
364 | DBG(1, "%s: making sigreturn frame: %#lx + %#lx = %#lx\n" , __func__, |
365 | regs->gr[30], sigframe_size, |
366 | regs->gr[30] + sigframe_size); |
367 | /* Raise the user stack pointer to make a proper call frame. */ |
368 | regs->gr[30] = (A(frame) + sigframe_size); |
369 | |
370 | |
371 | DBG(1, "%s: sig deliver (%s,%d) frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n" , |
372 | __func__, current->comm, current->pid, frame, regs->gr[30], |
373 | regs->iaoq[0], regs->iaoq[1], rp); |
374 | |
375 | return 0; |
376 | } |
377 | |
378 | /* |
379 | * OK, we're invoking a handler. |
380 | */ |
381 | |
382 | static void |
383 | handle_signal(struct ksignal *ksig, struct pt_regs *regs, long in_syscall) |
384 | { |
385 | int ret; |
386 | sigset_t *oldset = sigmask_to_save(); |
387 | |
388 | DBG(1, "%s: sig=%d, ka=%p, info=%p, oldset=%p, regs=%p\n" , |
389 | __func__, ksig->sig, &ksig->ka, &ksig->info, oldset, regs); |
390 | |
391 | /* Set up the stack frame */ |
392 | ret = setup_rt_frame(ksig, set: oldset, regs, in_syscall); |
393 | |
394 | signal_setup_done(failed: ret, ksig, test_thread_flag(TIF_SINGLESTEP) || |
395 | test_thread_flag(TIF_BLOCKSTEP)); |
396 | |
397 | DBG(1, "%s: Exit (success), regs->gr[28] = %ld\n" , |
398 | __func__, regs->gr[28]); |
399 | } |
400 | |
401 | /* |
402 | * Check how the syscall number gets loaded into %r20 within |
403 | * the delay branch in userspace and adjust as needed. |
404 | */ |
405 | |
406 | static void check_syscallno_in_delay_branch(struct pt_regs *regs) |
407 | { |
408 | u32 opcode, source_reg; |
409 | u32 __user *uaddr; |
410 | int err; |
411 | |
412 | /* Usually we don't have to restore %r20 (the system call number) |
413 | * because it gets loaded in the delay slot of the branch external |
414 | * instruction via the ldi instruction. |
415 | * In some cases a register-to-register copy instruction might have |
416 | * been used instead, in which case we need to copy the syscall |
417 | * number into the source register before returning to userspace. |
418 | */ |
419 | |
420 | /* A syscall is just a branch, so all we have to do is fiddle the |
421 | * return pointer so that the ble instruction gets executed again. |
422 | */ |
423 | regs->gr[31] -= 8; /* delayed branching */ |
424 | |
425 | /* Get assembler opcode of code in delay branch */ |
426 | uaddr = (u32 __user *) ((regs->gr[31] & ~3) + 4); |
427 | err = get_user(opcode, uaddr); |
428 | if (err) |
429 | return; |
430 | |
431 | /* Check if delay branch uses "ldi int,%r20" */ |
432 | if ((opcode & 0xffff0000) == 0x34140000) |
433 | return; /* everything ok, just return */ |
434 | |
435 | /* Check if delay branch uses "nop" */ |
436 | if (opcode == INSN_NOP) |
437 | return; |
438 | |
439 | /* Check if delay branch uses "copy %rX,%r20" */ |
440 | if ((opcode & 0xffe0ffff) == 0x08000254) { |
441 | source_reg = (opcode >> 16) & 31; |
442 | regs->gr[source_reg] = regs->gr[20]; |
443 | return; |
444 | } |
445 | |
446 | pr_warn("syscall restart: %s (pid %d): unexpected opcode 0x%08x\n" , |
447 | current->comm, task_pid_nr(current), opcode); |
448 | } |
449 | |
450 | static inline void |
451 | syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) |
452 | { |
453 | if (regs->orig_r28) |
454 | return; |
455 | regs->orig_r28 = 1; /* no more restarts */ |
456 | |
457 | DBG(1, "%s: orig_r28 = %ld pid %d r20 %ld\n" , |
458 | __func__, regs->orig_r28, task_pid_nr(current), regs->gr[20]); |
459 | |
460 | /* Check the return code */ |
461 | switch (regs->gr[28]) { |
462 | case -ERESTART_RESTARTBLOCK: |
463 | case -ERESTARTNOHAND: |
464 | DBG(1, "%s: ERESTARTNOHAND: returning -EINTR\n" , __func__); |
465 | regs->gr[28] = -EINTR; |
466 | break; |
467 | case -ERESTARTSYS: |
468 | if (!(ka->sa.sa_flags & SA_RESTART)) { |
469 | DBG(1, "%s: ERESTARTSYS: putting -EINTR pid %d\n" , |
470 | __func__, task_pid_nr(current)); |
471 | regs->gr[28] = -EINTR; |
472 | break; |
473 | } |
474 | fallthrough; |
475 | case -ERESTARTNOINTR: |
476 | DBG(1, "%s: %ld\n" , __func__, regs->gr[28]); |
477 | check_syscallno_in_delay_branch(regs); |
478 | break; |
479 | } |
480 | } |
481 | |
482 | static inline void |
483 | insert_restart_trampoline(struct pt_regs *regs) |
484 | { |
485 | if (regs->orig_r28) |
486 | return; |
487 | regs->orig_r28 = 1; /* no more restarts */ |
488 | |
489 | DBG(2, "%s: gr28 = %ld pid %d\n" , |
490 | __func__, regs->gr[28], task_pid_nr(current)); |
491 | |
492 | switch (regs->gr[28]) { |
493 | case -ERESTART_RESTARTBLOCK: { |
494 | /* Restart the system call - no handlers present */ |
495 | unsigned int *usp = (unsigned int *)regs->gr[30]; |
496 | unsigned long rp; |
497 | long err = 0; |
498 | |
499 | /* check that we don't exceed the stack */ |
500 | if (A(&usp[0]) >= TASK_SIZE_MAX - 5 * sizeof(int)) |
501 | return; |
502 | |
503 | /* Call trampoline in vdso to restart the syscall |
504 | * with __NR_restart_syscall. |
505 | * Original return addresses are on stack like this: |
506 | * |
507 | * 0: <return address (orig r31)> |
508 | * 4: <2nd half for 64-bit> |
509 | */ |
510 | #ifdef CONFIG_64BIT |
511 | if (!is_compat_task()) { |
512 | err |= put_user(regs->gr[31] >> 32, &usp[0]); |
513 | err |= put_user(regs->gr[31] & 0xffffffff, &usp[1]); |
514 | rp = VDSO64_SYMBOL(current, restart_syscall); |
515 | } else |
516 | #endif |
517 | { |
518 | err |= put_user(regs->gr[31], &usp[0]); |
519 | rp = VDSO32_SYMBOL(current, restart_syscall); |
520 | } |
521 | WARN_ON(err); |
522 | |
523 | regs->gr[31] = rp; |
524 | DBG(1, "%s: ERESTART_RESTARTBLOCK\n" , __func__); |
525 | return; |
526 | } |
527 | case -EINTR: |
528 | /* ok, was handled before and should be returned. */ |
529 | break; |
530 | case -ERESTARTNOHAND: |
531 | case -ERESTARTSYS: |
532 | case -ERESTARTNOINTR: |
533 | DBG(1, "%s: Type %ld\n" , __func__, regs->gr[28]); |
534 | check_syscallno_in_delay_branch(regs); |
535 | return; |
536 | default: |
537 | break; |
538 | } |
539 | } |
540 | |
541 | /* |
542 | * We need to be able to restore the syscall arguments (r21-r26) to |
543 | * restart syscalls. Thus, the syscall path should save them in the |
544 | * pt_regs structure (it's okay to do so since they are caller-save |
545 | * registers). As noted below, the syscall number gets restored for |
546 | * us due to the magic of delayed branching. |
547 | */ |
548 | static void do_signal(struct pt_regs *regs, long in_syscall) |
549 | { |
550 | struct ksignal ksig; |
551 | int restart_syscall; |
552 | bool has_handler; |
553 | |
554 | has_handler = get_signal(ksig: &ksig); |
555 | |
556 | restart_syscall = 0; |
557 | if (in_syscall) |
558 | restart_syscall = 1; |
559 | |
560 | if (has_handler) { |
561 | /* Restart a system call if necessary. */ |
562 | if (restart_syscall) |
563 | syscall_restart(regs, ka: &ksig.ka); |
564 | |
565 | handle_signal(ksig: &ksig, regs, in_syscall); |
566 | DBG(1, "%s: Handled signal pid %d\n" , |
567 | __func__, task_pid_nr(current)); |
568 | return; |
569 | } |
570 | |
571 | /* Do we need to restart the system call? */ |
572 | if (restart_syscall) |
573 | insert_restart_trampoline(regs); |
574 | |
575 | DBG(1, "%s: Exit (not delivered), regs->gr[28] = %ld orig_r28 = %ld pid %d\n" , |
576 | __func__, regs->gr[28], regs->orig_r28, task_pid_nr(current)); |
577 | |
578 | restore_saved_sigmask(); |
579 | } |
580 | |
581 | asmlinkage void do_notify_resume(struct pt_regs *regs, long in_syscall) |
582 | { |
583 | if (test_thread_flag(TIF_SIGPENDING) || |
584 | test_thread_flag(TIF_NOTIFY_SIGNAL)) |
585 | do_signal(regs, in_syscall); |
586 | |
587 | if (test_thread_flag(TIF_NOTIFY_RESUME)) |
588 | resume_user_mode_work(regs); |
589 | } |
590 | |