1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
3df24e178SHelge Deller * PA-RISC architecture-specific signal handling support.
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Copyright (C) 2000 David Huggins-Daines <dhd@debian.org>
61da177e4SLinus Torvalds * Copyright (C) 2000 Linuxcare, Inc.
7df24e178SHelge Deller * Copyright (C) 2000-2022 Helge Deller <deller@gmx.de>
8df24e178SHelge Deller * Copyright (C) 2022 John David Anglin <dave.anglin@bell.net>
91da177e4SLinus Torvalds *
101da177e4SLinus Torvalds * Based on the ia64, i386, and alpha versions.
111da177e4SLinus Torvalds */
121da177e4SLinus Torvalds
131da177e4SLinus Torvalds #include <linux/sched.h>
14b17b0153SIngo Molnar #include <linux/sched/debug.h>
151da177e4SLinus Torvalds #include <linux/mm.h>
161da177e4SLinus Torvalds #include <linux/smp.h>
171da177e4SLinus Torvalds #include <linux/kernel.h>
181da177e4SLinus Torvalds #include <linux/signal.h>
191da177e4SLinus Torvalds #include <linux/errno.h>
201da177e4SLinus Torvalds #include <linux/wait.h>
211da177e4SLinus Torvalds #include <linux/ptrace.h>
2203248addSEric W. Biederman #include <linux/resume_user_mode.h>
231da177e4SLinus Torvalds #include <linux/unistd.h>
241da177e4SLinus Torvalds #include <linux/stddef.h>
251da177e4SLinus Torvalds #include <linux/compat.h>
261da177e4SLinus Torvalds #include <linux/elf.h>
271da177e4SLinus Torvalds #include <asm/ucontext.h>
281da177e4SLinus Torvalds #include <asm/rt_sigframe.h>
297c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
301da177e4SLinus Torvalds #include <asm/cacheflush.h>
310013a854SSam Ravnborg #include <asm/asm-offsets.h>
32df24e178SHelge Deller #include <asm/vdso.h>
331da177e4SLinus Torvalds
341da177e4SLinus Torvalds #ifdef CONFIG_COMPAT
351da177e4SLinus Torvalds #include "signal32.h"
361da177e4SLinus Torvalds #endif
371da177e4SLinus Torvalds
381da177e4SLinus Torvalds #define DEBUG_SIG 0
391da177e4SLinus Torvalds #define DEBUG_SIG_LEVEL 2
401da177e4SLinus Torvalds
411da177e4SLinus Torvalds #if DEBUG_SIG
421da177e4SLinus Torvalds #define DBG(LEVEL, ...) \
431da177e4SLinus Torvalds ((DEBUG_SIG_LEVEL >= LEVEL) \
441da177e4SLinus Torvalds ? printk(__VA_ARGS__) : (void) 0)
451da177e4SLinus Torvalds #else
461da177e4SLinus Torvalds #define DBG(LEVEL, ...)
471da177e4SLinus Torvalds #endif
481da177e4SLinus Torvalds
491da177e4SLinus Torvalds /* gcc will complain if a pointer is cast to an integer of different
501da177e4SLinus Torvalds * size. If you really need to do this (and we do for an ELF32 user
511da177e4SLinus Torvalds * application in an ELF64 kernel) then you have to do a cast to an
521da177e4SLinus Torvalds * integer of the same size first. The A() macro accomplishes
531da177e4SLinus Torvalds * this. */
541da177e4SLinus Torvalds #define A(__x) ((unsigned long)(__x))
551da177e4SLinus Torvalds
561da177e4SLinus Torvalds /*
571da177e4SLinus Torvalds * Do a signal return - restore sigcontext.
581da177e4SLinus Torvalds */
591da177e4SLinus Torvalds
601da177e4SLinus Torvalds static long
restore_sigcontext(struct sigcontext __user * sc,struct pt_regs * regs)611da177e4SLinus Torvalds restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
621da177e4SLinus Torvalds {
631da177e4SLinus Torvalds long err = 0;
641da177e4SLinus Torvalds
651da177e4SLinus Torvalds err |= __copy_from_user(regs->gr, sc->sc_gr, sizeof(regs->gr));
661da177e4SLinus Torvalds err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
671da177e4SLinus Torvalds err |= __copy_from_user(regs->iaoq, sc->sc_iaoq, sizeof(regs->iaoq));
681da177e4SLinus Torvalds err |= __copy_from_user(regs->iasq, sc->sc_iasq, sizeof(regs->iasq));
691da177e4SLinus Torvalds err |= __get_user(regs->sar, &sc->sc_sar);
70df24e178SHelge Deller DBG(2, "%s: iaoq is %#lx / %#lx\n",
71df24e178SHelge Deller __func__, regs->iaoq[0], regs->iaoq[1]);
72df24e178SHelge Deller DBG(2, "%s: r28 is %ld\n", __func__, regs->gr[28]);
731da177e4SLinus Torvalds return err;
741da177e4SLinus Torvalds }
751da177e4SLinus Torvalds
76cfb25b82SHelge Deller asmlinkage void
sys_rt_sigreturn(struct pt_regs * regs,int in_syscall)771da177e4SLinus Torvalds sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
781da177e4SLinus Torvalds {
791da177e4SLinus Torvalds struct rt_sigframe __user *frame;
801da177e4SLinus Torvalds sigset_t set;
811da177e4SLinus Torvalds unsigned long usp = (regs->gr[30] & ~(0x01UL));
821da177e4SLinus Torvalds unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE;
83a8f44e38SHelge Deller #ifdef CONFIG_64BIT
841da177e4SLinus Torvalds struct compat_rt_sigframe __user * compat_frame;
851da177e4SLinus Torvalds
86a3ea84faSKyle McMartin if (is_compat_task())
871da177e4SLinus Torvalds sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
881da177e4SLinus Torvalds #endif
891da177e4SLinus Torvalds
90f56141e3SAndy Lutomirski current->restart_block.fn = do_no_restart_syscall;
911da177e4SLinus Torvalds
921da177e4SLinus Torvalds /* Unwind the user stack to get the rt_sigframe structure. */
931da177e4SLinus Torvalds frame = (struct rt_sigframe __user *)
941da177e4SLinus Torvalds (usp - sigframe_size);
95df24e178SHelge Deller DBG(2, "%s: frame is %p pid %d\n", __func__, frame, task_pid_nr(current));
961da177e4SLinus Torvalds
9700df111eSAl Viro regs->orig_r28 = 1; /* no restarts for sigreturn */
9800df111eSAl Viro
99a8f44e38SHelge Deller #ifdef CONFIG_64BIT
1001da177e4SLinus Torvalds compat_frame = (struct compat_rt_sigframe __user *)frame;
1011da177e4SLinus Torvalds
102a3ea84faSKyle McMartin if (is_compat_task()) {
103d74f0f47SAl Viro if (get_compat_sigset(&set, &compat_frame->uc.uc_sigmask))
1041da177e4SLinus Torvalds goto give_sigsegv;
1051da177e4SLinus Torvalds } else
1061da177e4SLinus Torvalds #endif
1071da177e4SLinus Torvalds {
1081da177e4SLinus Torvalds if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
1091da177e4SLinus Torvalds goto give_sigsegv;
1101da177e4SLinus Torvalds }
1111da177e4SLinus Torvalds
112ade7728bSMatt Fleming set_current_blocked(&set);
1131da177e4SLinus Torvalds
1141da177e4SLinus Torvalds /* Good thing we saved the old gr[30], eh? */
115a8f44e38SHelge Deller #ifdef CONFIG_64BIT
116a3ea84faSKyle McMartin if (is_compat_task()) {
117df24e178SHelge Deller DBG(1, "%s: compat_frame->uc.uc_mcontext 0x%p\n",
118df24e178SHelge Deller __func__, &compat_frame->uc.uc_mcontext);
1191da177e4SLinus Torvalds // FIXME: Load upper half from register file
1201da177e4SLinus Torvalds if (restore_sigcontext32(&compat_frame->uc.uc_mcontext,
1211da177e4SLinus Torvalds &compat_frame->regs, regs))
1221da177e4SLinus Torvalds goto give_sigsegv;
123df24e178SHelge Deller DBG(1, "%s: usp %#08lx stack 0x%p\n",
124df24e178SHelge Deller __func__, usp, &compat_frame->uc.uc_stack);
1256e26aab9SAl Viro if (compat_restore_altstack(&compat_frame->uc.uc_stack))
1261da177e4SLinus Torvalds goto give_sigsegv;
1271da177e4SLinus Torvalds } else
1281da177e4SLinus Torvalds #endif
1291da177e4SLinus Torvalds {
130df24e178SHelge Deller DBG(1, "%s: frame->uc.uc_mcontext 0x%p\n",
131df24e178SHelge Deller __func__, &frame->uc.uc_mcontext);
1321da177e4SLinus Torvalds if (restore_sigcontext(&frame->uc.uc_mcontext, regs))
1331da177e4SLinus Torvalds goto give_sigsegv;
134df24e178SHelge Deller DBG(1, "%s: usp %#08lx stack 0x%p\n",
135df24e178SHelge Deller __func__, usp, &frame->uc.uc_stack);
1366e26aab9SAl Viro if (restore_altstack(&frame->uc.uc_stack))
1371da177e4SLinus Torvalds goto give_sigsegv;
1381da177e4SLinus Torvalds }
1391da177e4SLinus Torvalds
1401da177e4SLinus Torvalds
1411da177e4SLinus Torvalds
1421da177e4SLinus Torvalds /* If we are on the syscall path IAOQ will not be restored, and
1431da177e4SLinus Torvalds * if we are on the interrupt path we must not corrupt gr31.
1441da177e4SLinus Torvalds */
1451da177e4SLinus Torvalds if (in_syscall)
1461da177e4SLinus Torvalds regs->gr[31] = regs->iaoq[0];
147df24e178SHelge Deller
1481da177e4SLinus Torvalds return;
1491da177e4SLinus Torvalds
1501da177e4SLinus Torvalds give_sigsegv:
151df24e178SHelge Deller DBG(1, "%s: Sending SIGSEGV\n", __func__);
1523cf5d076SEric W. Biederman force_sig(SIGSEGV);
1531da177e4SLinus Torvalds return;
1541da177e4SLinus Torvalds }
1551da177e4SLinus Torvalds
1561da177e4SLinus Torvalds /*
1571da177e4SLinus Torvalds * Set up a signal frame.
1581da177e4SLinus Torvalds */
1591da177e4SLinus Torvalds
1601da177e4SLinus Torvalds static inline void __user *
get_sigframe(struct k_sigaction * ka,unsigned long sp,size_t frame_size)1611da177e4SLinus Torvalds get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
1621da177e4SLinus Torvalds {
1631da177e4SLinus Torvalds /*FIXME: ELF32 vs. ELF64 has different frame_size, but since we
1641da177e4SLinus Torvalds don't use the parameter it doesn't matter */
1651da177e4SLinus Torvalds
166df24e178SHelge Deller DBG(1, "%s: ka = %#lx, sp = %#lx, frame_size = %zu\n",
167df24e178SHelge Deller __func__, (unsigned long)ka, sp, frame_size);
1681da177e4SLinus Torvalds
169ad30f3ffSJohn David Anglin /* Align alternate stack and reserve 64 bytes for the signal
170ad30f3ffSJohn David Anglin handler's frame marker. */
171d09042daSLaurent MEYER if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
172ad30f3ffSJohn David Anglin sp = (current->sas_ss_sp + 0x7f) & ~0x3f; /* Stacks grow up! */
1731da177e4SLinus Torvalds
174df24e178SHelge Deller DBG(1, "%s: Returning sp = %#lx\n", __func__, (unsigned long)sp);
1751da177e4SLinus Torvalds return (void __user *) sp; /* Stacks grow up. Fun. */
1761da177e4SLinus Torvalds }
1771da177e4SLinus Torvalds
1781da177e4SLinus Torvalds static long
setup_sigcontext(struct sigcontext __user * sc,struct pt_regs * regs,long in_syscall)179cfb25b82SHelge Deller setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, long in_syscall)
1801da177e4SLinus Torvalds
1811da177e4SLinus Torvalds {
1821da177e4SLinus Torvalds unsigned long flags = 0;
1831da177e4SLinus Torvalds long err = 0;
1841da177e4SLinus Torvalds
1851da177e4SLinus Torvalds if (on_sig_stack((unsigned long) sc))
1861da177e4SLinus Torvalds flags |= PARISC_SC_FLAG_ONSTACK;
1871da177e4SLinus Torvalds if (in_syscall) {
1881da177e4SLinus Torvalds flags |= PARISC_SC_FLAG_IN_SYSCALL;
1891da177e4SLinus Torvalds /* regs->iaoq is undefined in the syscall return path */
1901da177e4SLinus Torvalds err |= __put_user(regs->gr[31], &sc->sc_iaoq[0]);
1911da177e4SLinus Torvalds err |= __put_user(regs->gr[31]+4, &sc->sc_iaoq[1]);
1921da177e4SLinus Torvalds err |= __put_user(regs->sr[3], &sc->sc_iasq[0]);
1931da177e4SLinus Torvalds err |= __put_user(regs->sr[3], &sc->sc_iasq[1]);
194df24e178SHelge Deller DBG(1, "%s: iaoq %#lx / %#lx (in syscall)\n",
195df24e178SHelge Deller __func__, regs->gr[31], regs->gr[31]+4);
1961da177e4SLinus Torvalds } else {
1971da177e4SLinus Torvalds err |= __copy_to_user(sc->sc_iaoq, regs->iaoq, sizeof(regs->iaoq));
1981da177e4SLinus Torvalds err |= __copy_to_user(sc->sc_iasq, regs->iasq, sizeof(regs->iasq));
199df24e178SHelge Deller DBG(1, "%s: iaoq %#lx / %#lx (not in syscall)\n",
200df24e178SHelge Deller __func__, regs->iaoq[0], regs->iaoq[1]);
2011da177e4SLinus Torvalds }
2021da177e4SLinus Torvalds
2031da177e4SLinus Torvalds err |= __put_user(flags, &sc->sc_flags);
2041da177e4SLinus Torvalds err |= __copy_to_user(sc->sc_gr, regs->gr, sizeof(regs->gr));
2051da177e4SLinus Torvalds err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
2061da177e4SLinus Torvalds err |= __put_user(regs->sar, &sc->sc_sar);
207df24e178SHelge Deller DBG(1, "%s: r28 is %ld\n", __func__, regs->gr[28]);
2081da177e4SLinus Torvalds
2091da177e4SLinus Torvalds return err;
2101da177e4SLinus Torvalds }
2111da177e4SLinus Torvalds
2121da177e4SLinus Torvalds static long
setup_rt_frame(struct ksignal * ksig,sigset_t * set,struct pt_regs * regs,long in_syscall)213e4dc894bSRichard Weinberger setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
214cfb25b82SHelge Deller long in_syscall)
2151da177e4SLinus Torvalds {
2161da177e4SLinus Torvalds struct rt_sigframe __user *frame;
2171da177e4SLinus Torvalds unsigned long rp, usp;
2181da177e4SLinus Torvalds unsigned long haddr, sigframe_size;
219df24e178SHelge Deller unsigned long start;
2201da177e4SLinus Torvalds int err = 0;
221a8f44e38SHelge Deller #ifdef CONFIG_64BIT
2221da177e4SLinus Torvalds struct compat_rt_sigframe __user * compat_frame;
2231da177e4SLinus Torvalds #endif
2241da177e4SLinus Torvalds
2251da177e4SLinus Torvalds usp = (regs->gr[30] & ~(0x01UL));
2263e4a1affSHelge Deller sigframe_size = PARISC_RT_SIGFRAME_SIZE;
227030f6530SMikulas Patocka #ifdef CONFIG_64BIT
228030f6530SMikulas Patocka if (is_compat_task()) {
229030f6530SMikulas Patocka /* The gcc alloca implementation leaves garbage in the upper 32 bits of sp */
230030f6530SMikulas Patocka usp = (compat_uint_t)usp;
2313e4a1affSHelge Deller sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
232030f6530SMikulas Patocka }
233030f6530SMikulas Patocka #endif
2343e4a1affSHelge Deller frame = get_sigframe(&ksig->ka, usp, sigframe_size);
2351da177e4SLinus Torvalds
236df24e178SHelge Deller DBG(1, "%s: frame %p info %p\n", __func__, frame, &ksig->info);
2371da177e4SLinus Torvalds
2383e4a1affSHelge Deller start = (unsigned long) frame;
239967747bbSArnd Bergmann if (start >= TASK_SIZE_MAX - sigframe_size)
2403e4a1affSHelge Deller return -EFAULT;
2411da177e4SLinus Torvalds
242a8f44e38SHelge Deller #ifdef CONFIG_64BIT
2431da177e4SLinus Torvalds
2441da177e4SLinus Torvalds compat_frame = (struct compat_rt_sigframe __user *)frame;
2451da177e4SLinus Torvalds
246a3ea84faSKyle McMartin if (is_compat_task()) {
247df24e178SHelge Deller DBG(1, "%s: frame->info = 0x%p\n", __func__, &compat_frame->info);
248e4dc894bSRichard Weinberger err |= copy_siginfo_to_user32(&compat_frame->info, &ksig->info);
2496e26aab9SAl Viro err |= __compat_save_altstack( &compat_frame->uc.uc_stack, regs->gr[30]);
250df24e178SHelge Deller DBG(1, "%s: frame->uc = 0x%p\n", __func__, &compat_frame->uc);
251df24e178SHelge Deller DBG(1, "%s: frame->uc.uc_mcontext = 0x%p\n",
252df24e178SHelge Deller __func__, &compat_frame->uc.uc_mcontext);
2531da177e4SLinus Torvalds err |= setup_sigcontext32(&compat_frame->uc.uc_mcontext,
2541da177e4SLinus Torvalds &compat_frame->regs, regs, in_syscall);
255d74f0f47SAl Viro err |= put_compat_sigset(&compat_frame->uc.uc_sigmask, set,
256d74f0f47SAl Viro sizeof(compat_sigset_t));
2571da177e4SLinus Torvalds } else
2581da177e4SLinus Torvalds #endif
2591da177e4SLinus Torvalds {
260df24e178SHelge Deller DBG(1, "%s: frame->info = 0x%p\n", __func__, &frame->info);
261e4dc894bSRichard Weinberger err |= copy_siginfo_to_user(&frame->info, &ksig->info);
2626e26aab9SAl Viro err |= __save_altstack(&frame->uc.uc_stack, regs->gr[30]);
263df24e178SHelge Deller DBG(1, "%s: frame->uc = 0x%p\n", __func__, &frame->uc);
264df24e178SHelge Deller DBG(1, "%s: frame->uc.uc_mcontext = 0x%p\n",
265df24e178SHelge Deller __func__, &frame->uc.uc_mcontext);
2661da177e4SLinus Torvalds err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, in_syscall);
2671da177e4SLinus Torvalds /* FIXME: Should probably be converted as well for the compat case */
2681da177e4SLinus Torvalds err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
2691da177e4SLinus Torvalds }
2701da177e4SLinus Torvalds
2711da177e4SLinus Torvalds if (err)
272e4dc894bSRichard Weinberger return -EFAULT;
2731da177e4SLinus Torvalds
274df24e178SHelge Deller #ifdef CONFIG_64BIT
275df24e178SHelge Deller if (!is_compat_task())
276df24e178SHelge Deller rp = VDSO64_SYMBOL(current, sigtramp_rt);
277df24e178SHelge Deller else
278df24e178SHelge Deller #endif
279df24e178SHelge Deller rp = VDSO32_SYMBOL(current, sigtramp_rt);
2801da177e4SLinus Torvalds
281df24e178SHelge Deller if (in_syscall)
282df24e178SHelge Deller rp += 4*4; /* skip 4 instructions and start at ldi 1,%r25 */
2831da177e4SLinus Torvalds
284e4dc894bSRichard Weinberger haddr = A(ksig->ka.sa.sa_handler);
2851da177e4SLinus Torvalds /* The sa_handler may be a pointer to a function descriptor */
286a8f44e38SHelge Deller #ifdef CONFIG_64BIT
287a3ea84faSKyle McMartin if (is_compat_task()) {
2881da177e4SLinus Torvalds #endif
2891da177e4SLinus Torvalds if (haddr & PA_PLABEL_FDESC) {
2901da177e4SLinus Torvalds Elf32_Fdesc fdesc;
2911da177e4SLinus Torvalds Elf32_Fdesc __user *ufdesc = (Elf32_Fdesc __user *)A(haddr & ~3);
2921da177e4SLinus Torvalds
2931da177e4SLinus Torvalds err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
2941da177e4SLinus Torvalds
2951da177e4SLinus Torvalds if (err)
296e4dc894bSRichard Weinberger return -EFAULT;
2971da177e4SLinus Torvalds
2981da177e4SLinus Torvalds haddr = fdesc.addr;
2991da177e4SLinus Torvalds regs->gr[19] = fdesc.gp;
3001da177e4SLinus Torvalds }
301a8f44e38SHelge Deller #ifdef CONFIG_64BIT
3021da177e4SLinus Torvalds } else {
3031da177e4SLinus Torvalds Elf64_Fdesc fdesc;
3041da177e4SLinus Torvalds Elf64_Fdesc __user *ufdesc = (Elf64_Fdesc __user *)A(haddr & ~3);
3051da177e4SLinus Torvalds
3061da177e4SLinus Torvalds err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
3071da177e4SLinus Torvalds
3081da177e4SLinus Torvalds if (err)
309e4dc894bSRichard Weinberger return -EFAULT;
3101da177e4SLinus Torvalds
3111da177e4SLinus Torvalds haddr = fdesc.addr;
3121da177e4SLinus Torvalds regs->gr[19] = fdesc.gp;
313df24e178SHelge Deller DBG(1, "%s: 64 bit signal, exe=%#lx, r19=%#lx, in_syscall=%d\n",
314df24e178SHelge Deller __func__, haddr, regs->gr[19], in_syscall);
3151da177e4SLinus Torvalds }
3161da177e4SLinus Torvalds #endif
3171da177e4SLinus Torvalds
3181da177e4SLinus Torvalds /* The syscall return path will create IAOQ values from r31.
3191da177e4SLinus Torvalds */
3201da177e4SLinus Torvalds if (in_syscall) {
3211da177e4SLinus Torvalds regs->gr[31] = haddr;
322a8f44e38SHelge Deller #ifdef CONFIG_64BIT
323df570b9cSKyle McMartin if (!test_thread_flag(TIF_32BIT))
324df24e178SHelge Deller sigframe_size |= 1; /* XXX ???? */
3251da177e4SLinus Torvalds #endif
3261da177e4SLinus Torvalds } else {
3271da177e4SLinus Torvalds unsigned long psw = USER_PSW;
328a8f44e38SHelge Deller #ifdef CONFIG_64BIT
329df570b9cSKyle McMartin if (!test_thread_flag(TIF_32BIT))
3301da177e4SLinus Torvalds psw |= PSW_W;
3311da177e4SLinus Torvalds #endif
3321da177e4SLinus Torvalds
3331da177e4SLinus Torvalds /* If we are singlestepping, arrange a trap to be delivered
3341da177e4SLinus Torvalds when we return to userspace. Note the semantics -- we
3351da177e4SLinus Torvalds should trap before the first insn in the handler is
3361da177e4SLinus Torvalds executed. Ref:
3371da177e4SLinus Torvalds http://sources.redhat.com/ml/gdb/2004-11/msg00245.html
3381da177e4SLinus Torvalds */
3391da177e4SLinus Torvalds if (pa_psw(current)->r) {
3401da177e4SLinus Torvalds pa_psw(current)->r = 0;
3411da177e4SLinus Torvalds psw |= PSW_R;
3421da177e4SLinus Torvalds mtctl(-1, 0);
3431da177e4SLinus Torvalds }
3441da177e4SLinus Torvalds
3451da177e4SLinus Torvalds regs->gr[0] = psw;
346df24e178SHelge Deller regs->iaoq[0] = haddr | PRIV_USER;
3471da177e4SLinus Torvalds regs->iaoq[1] = regs->iaoq[0] + 4;
3481da177e4SLinus Torvalds }
3491da177e4SLinus Torvalds
3501da177e4SLinus Torvalds regs->gr[2] = rp; /* userland return pointer */
351e4dc894bSRichard Weinberger regs->gr[26] = ksig->sig; /* signal number */
3521da177e4SLinus Torvalds
353a8f44e38SHelge Deller #ifdef CONFIG_64BIT
354a3ea84faSKyle McMartin if (is_compat_task()) {
3551da177e4SLinus Torvalds regs->gr[25] = A(&compat_frame->info); /* siginfo pointer */
3561da177e4SLinus Torvalds regs->gr[24] = A(&compat_frame->uc); /* ucontext pointer */
3571da177e4SLinus Torvalds } else
3581da177e4SLinus Torvalds #endif
3591da177e4SLinus Torvalds {
3601da177e4SLinus Torvalds regs->gr[25] = A(&frame->info); /* siginfo pointer */
3611da177e4SLinus Torvalds regs->gr[24] = A(&frame->uc); /* ucontext pointer */
3621da177e4SLinus Torvalds }
3631da177e4SLinus Torvalds
364df24e178SHelge Deller DBG(1, "%s: making sigreturn frame: %#lx + %#lx = %#lx\n", __func__,
3651da177e4SLinus Torvalds regs->gr[30], sigframe_size,
3661da177e4SLinus Torvalds regs->gr[30] + sigframe_size);
3671da177e4SLinus Torvalds /* Raise the user stack pointer to make a proper call frame. */
3681da177e4SLinus Torvalds regs->gr[30] = (A(frame) + sigframe_size);
3691da177e4SLinus Torvalds
3701da177e4SLinus Torvalds
371df24e178SHelge Deller DBG(1, "%s: sig deliver (%s,%d) frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",
372df24e178SHelge Deller __func__, current->comm, current->pid, frame, regs->gr[30],
3731da177e4SLinus Torvalds regs->iaoq[0], regs->iaoq[1], rp);
3741da177e4SLinus Torvalds
3751da177e4SLinus Torvalds return 0;
3761da177e4SLinus Torvalds }
3771da177e4SLinus Torvalds
3781da177e4SLinus Torvalds /*
3791da177e4SLinus Torvalds * OK, we're invoking a handler.
3801da177e4SLinus Torvalds */
3811da177e4SLinus Torvalds
382e3b880c6SAl Viro static void
handle_signal(struct ksignal * ksig,struct pt_regs * regs,long in_syscall)383cfb25b82SHelge Deller handle_signal(struct ksignal *ksig, struct pt_regs *regs, long in_syscall)
3841da177e4SLinus Torvalds {
385e4dc894bSRichard Weinberger int ret;
386b7f9a11aSAl Viro sigset_t *oldset = sigmask_to_save();
387e4dc894bSRichard Weinberger
388df24e178SHelge Deller DBG(1, "%s: sig=%d, ka=%p, info=%p, oldset=%p, regs=%p\n",
389df24e178SHelge Deller __func__, ksig->sig, &ksig->ka, &ksig->info, oldset, regs);
3901da177e4SLinus Torvalds
3911da177e4SLinus Torvalds /* Set up the stack frame */
392e4dc894bSRichard Weinberger ret = setup_rt_frame(ksig, oldset, regs, in_syscall);
3931da177e4SLinus Torvalds
394e4dc894bSRichard Weinberger signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP) ||
39522a8cdd6SKyle McMartin test_thread_flag(TIF_BLOCKSTEP));
396ecf02de5SKyle McMartin
397df24e178SHelge Deller DBG(1, "%s: Exit (success), regs->gr[28] = %ld\n",
398df24e178SHelge Deller __func__, regs->gr[28]);
3991da177e4SLinus Torvalds }
4001da177e4SLinus Torvalds
40171a71fb5SHelge Deller /*
40271a71fb5SHelge Deller * Check how the syscall number gets loaded into %r20 within
40371a71fb5SHelge Deller * the delay branch in userspace and adjust as needed.
40471a71fb5SHelge Deller */
40571a71fb5SHelge Deller
check_syscallno_in_delay_branch(struct pt_regs * regs)40671a71fb5SHelge Deller static void check_syscallno_in_delay_branch(struct pt_regs *regs)
40771a71fb5SHelge Deller {
40871a71fb5SHelge Deller u32 opcode, source_reg;
40971a71fb5SHelge Deller u32 __user *uaddr;
41071a71fb5SHelge Deller int err;
41171a71fb5SHelge Deller
41271a71fb5SHelge Deller /* Usually we don't have to restore %r20 (the system call number)
41371a71fb5SHelge Deller * because it gets loaded in the delay slot of the branch external
41471a71fb5SHelge Deller * instruction via the ldi instruction.
41571a71fb5SHelge Deller * In some cases a register-to-register copy instruction might have
41671a71fb5SHelge Deller * been used instead, in which case we need to copy the syscall
41771a71fb5SHelge Deller * number into the source register before returning to userspace.
41871a71fb5SHelge Deller */
41971a71fb5SHelge Deller
42071a71fb5SHelge Deller /* A syscall is just a branch, so all we have to do is fiddle the
42171a71fb5SHelge Deller * return pointer so that the ble instruction gets executed again.
42271a71fb5SHelge Deller */
42371a71fb5SHelge Deller regs->gr[31] -= 8; /* delayed branching */
42471a71fb5SHelge Deller
42571a71fb5SHelge Deller /* Get assembler opcode of code in delay branch */
426*dc54a52aSHelge Deller uaddr = (u32 __user *) ((regs->gr[31] & ~3) + 4);
42771a71fb5SHelge Deller err = get_user(opcode, uaddr);
42871a71fb5SHelge Deller if (err)
42971a71fb5SHelge Deller return;
43071a71fb5SHelge Deller
43171a71fb5SHelge Deller /* Check if delay branch uses "ldi int,%r20" */
43271a71fb5SHelge Deller if ((opcode & 0xffff0000) == 0x34140000)
43371a71fb5SHelge Deller return; /* everything ok, just return */
43471a71fb5SHelge Deller
43571a71fb5SHelge Deller /* Check if delay branch uses "nop" */
43671a71fb5SHelge Deller if (opcode == INSN_NOP)
43771a71fb5SHelge Deller return;
43871a71fb5SHelge Deller
43971a71fb5SHelge Deller /* Check if delay branch uses "copy %rX,%r20" */
44071a71fb5SHelge Deller if ((opcode & 0xffe0ffff) == 0x08000254) {
44171a71fb5SHelge Deller source_reg = (opcode >> 16) & 31;
44271a71fb5SHelge Deller regs->gr[source_reg] = regs->gr[20];
44371a71fb5SHelge Deller return;
44471a71fb5SHelge Deller }
44571a71fb5SHelge Deller
44671a71fb5SHelge Deller pr_warn("syscall restart: %s (pid %d): unexpected opcode 0x%08x\n",
44771a71fb5SHelge Deller current->comm, task_pid_nr(current), opcode);
44871a71fb5SHelge Deller }
44971a71fb5SHelge Deller
4502b163b71SKyle McMartin static inline void
syscall_restart(struct pt_regs * regs,struct k_sigaction * ka)4512b163b71SKyle McMartin syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
4522b163b71SKyle McMartin {
45300df111eSAl Viro if (regs->orig_r28)
45400df111eSAl Viro return;
45500df111eSAl Viro regs->orig_r28 = 1; /* no more restarts */
456df24e178SHelge Deller
457df24e178SHelge Deller DBG(1, "%s: orig_r28 = %ld pid %d r20 %ld\n",
458df24e178SHelge Deller __func__, regs->orig_r28, task_pid_nr(current), regs->gr[20]);
459df24e178SHelge Deller
4602b163b71SKyle McMartin /* Check the return code */
4612b163b71SKyle McMartin switch (regs->gr[28]) {
4622b163b71SKyle McMartin case -ERESTART_RESTARTBLOCK:
4632b163b71SKyle McMartin case -ERESTARTNOHAND:
464df24e178SHelge Deller DBG(1, "%s: ERESTARTNOHAND: returning -EINTR\n", __func__);
4652b163b71SKyle McMartin regs->gr[28] = -EINTR;
4662b163b71SKyle McMartin break;
4672b163b71SKyle McMartin case -ERESTARTSYS:
4682b163b71SKyle McMartin if (!(ka->sa.sa_flags & SA_RESTART)) {
469df24e178SHelge Deller DBG(1, "%s: ERESTARTSYS: putting -EINTR pid %d\n",
470df24e178SHelge Deller __func__, task_pid_nr(current));
4712b163b71SKyle McMartin regs->gr[28] = -EINTR;
4722b163b71SKyle McMartin break;
4732b163b71SKyle McMartin }
474df561f66SGustavo A. R. Silva fallthrough;
4752b163b71SKyle McMartin case -ERESTARTNOINTR:
476df24e178SHelge Deller DBG(1, "%s: %ld\n", __func__, regs->gr[28]);
47771a71fb5SHelge Deller check_syscallno_in_delay_branch(regs);
4782b163b71SKyle McMartin break;
4792b163b71SKyle McMartin }
4802b163b71SKyle McMartin }
4812b163b71SKyle McMartin
4822b163b71SKyle McMartin static inline void
insert_restart_trampoline(struct pt_regs * regs)4832b163b71SKyle McMartin insert_restart_trampoline(struct pt_regs *regs)
4842b163b71SKyle McMartin {
48500df111eSAl Viro if (regs->orig_r28)
48600df111eSAl Viro return;
48700df111eSAl Viro regs->orig_r28 = 1; /* no more restarts */
488df24e178SHelge Deller
489df24e178SHelge Deller DBG(2, "%s: gr28 = %ld pid %d\n",
490df24e178SHelge Deller __func__, regs->gr[28], task_pid_nr(current));
491df24e178SHelge Deller
4922b163b71SKyle McMartin switch (regs->gr[28]) {
4932b163b71SKyle McMartin case -ERESTART_RESTARTBLOCK: {
4942b163b71SKyle McMartin /* Restart the system call - no handlers present */
4952b163b71SKyle McMartin unsigned int *usp = (unsigned int *)regs->gr[30];
496df24e178SHelge Deller unsigned long rp;
4970bd1e94bSHelge Deller long err = 0;
4982b163b71SKyle McMartin
4993e4a1affSHelge Deller /* check that we don't exceed the stack */
500967747bbSArnd Bergmann if (A(&usp[0]) >= TASK_SIZE_MAX - 5 * sizeof(int))
5013e4a1affSHelge Deller return;
5023e4a1affSHelge Deller
503df24e178SHelge Deller /* Call trampoline in vdso to restart the syscall
504df24e178SHelge Deller * with __NR_restart_syscall.
505df24e178SHelge Deller * Original return addresses are on stack like this:
5062b163b71SKyle McMartin *
5072b163b71SKyle McMartin * 0: <return address (orig r31)>
5082b163b71SKyle McMartin * 4: <2nd half for 64-bit>
5092b163b71SKyle McMartin */
5102b163b71SKyle McMartin #ifdef CONFIG_64BIT
511df24e178SHelge Deller if (!is_compat_task()) {
5120bd1e94bSHelge Deller err |= put_user(regs->gr[31] >> 32, &usp[0]);
5130bd1e94bSHelge Deller err |= put_user(regs->gr[31] & 0xffffffff, &usp[1]);
514df24e178SHelge Deller rp = VDSO64_SYMBOL(current, restart_syscall);
515df24e178SHelge Deller } else
5162b163b71SKyle McMartin #endif
517df24e178SHelge Deller {
518df24e178SHelge Deller err |= put_user(regs->gr[31], &usp[0]);
519df24e178SHelge Deller rp = VDSO32_SYMBOL(current, restart_syscall);
520df24e178SHelge Deller }
5210bd1e94bSHelge Deller WARN_ON(err);
5220bd1e94bSHelge Deller
523df24e178SHelge Deller regs->gr[31] = rp;
524df24e178SHelge Deller DBG(1, "%s: ERESTART_RESTARTBLOCK\n", __func__);
5252b163b71SKyle McMartin return;
5262b163b71SKyle McMartin }
527df24e178SHelge Deller case -EINTR:
528df24e178SHelge Deller /* ok, was handled before and should be returned. */
529df24e178SHelge Deller break;
5302b163b71SKyle McMartin case -ERESTARTNOHAND:
5312b163b71SKyle McMartin case -ERESTARTSYS:
53271a71fb5SHelge Deller case -ERESTARTNOINTR:
533df24e178SHelge Deller DBG(1, "%s: Type %ld\n", __func__, regs->gr[28]);
53471a71fb5SHelge Deller check_syscallno_in_delay_branch(regs);
5352b163b71SKyle McMartin return;
5362b163b71SKyle McMartin default:
5372b163b71SKyle McMartin break;
5382b163b71SKyle McMartin }
5392b163b71SKyle McMartin }
5402b163b71SKyle McMartin
5411da177e4SLinus Torvalds /*
5421da177e4SLinus Torvalds * We need to be able to restore the syscall arguments (r21-r26) to
5431da177e4SLinus Torvalds * restart syscalls. Thus, the syscall path should save them in the
5441da177e4SLinus Torvalds * pt_regs structure (it's okay to do so since they are caller-save
5451da177e4SLinus Torvalds * registers). As noted below, the syscall number gets restored for
5461da177e4SLinus Torvalds * us due to the magic of delayed branching.
5471da177e4SLinus Torvalds */
do_signal(struct pt_regs * regs,long in_syscall)548df24e178SHelge Deller static void do_signal(struct pt_regs *regs, long in_syscall)
5491da177e4SLinus Torvalds {
550e4dc894bSRichard Weinberger struct ksignal ksig;
551df24e178SHelge Deller int restart_syscall;
552df24e178SHelge Deller bool has_handler;
5531da177e4SLinus Torvalds
554df24e178SHelge Deller has_handler = get_signal(&ksig);
5551da177e4SLinus Torvalds
556df24e178SHelge Deller restart_syscall = 0;
5572b163b71SKyle McMartin if (in_syscall)
558df24e178SHelge Deller restart_syscall = 1;
559df24e178SHelge Deller
560df24e178SHelge Deller if (has_handler) {
561df24e178SHelge Deller /* Restart a system call if necessary. */
562df24e178SHelge Deller if (restart_syscall)
563e4dc894bSRichard Weinberger syscall_restart(regs, &ksig.ka);
5641da177e4SLinus Torvalds
565e4dc894bSRichard Weinberger handle_signal(&ksig, regs, in_syscall);
566df24e178SHelge Deller DBG(1, "%s: Handled signal pid %d\n",
567df24e178SHelge Deller __func__, task_pid_nr(current));
5684650f0a5SKyle McMartin return;
5691da177e4SLinus Torvalds }
5701da177e4SLinus Torvalds
571df24e178SHelge Deller /* Do we need to restart the system call? */
572df24e178SHelge Deller if (restart_syscall)
5732b163b71SKyle McMartin insert_restart_trampoline(regs);
5741da177e4SLinus Torvalds
575df24e178SHelge Deller DBG(1, "%s: Exit (not delivered), regs->gr[28] = %ld orig_r28 = %ld pid %d\n",
576df24e178SHelge Deller __func__, regs->gr[28], regs->orig_r28, task_pid_nr(current));
5771da177e4SLinus Torvalds
57851a7b448SAl Viro restore_saved_sigmask();
5794650f0a5SKyle McMartin }
5804650f0a5SKyle McMartin
do_notify_resume(struct pt_regs * regs,long in_syscall)581cfb25b82SHelge Deller asmlinkage void do_notify_resume(struct pt_regs *regs, long in_syscall)
5824650f0a5SKyle McMartin {
58318cb3281SJens Axboe if (test_thread_flag(TIF_SIGPENDING) ||
58418cb3281SJens Axboe test_thread_flag(TIF_NOTIFY_SIGNAL))
5854650f0a5SKyle McMartin do_signal(regs, in_syscall);
586d0420c83SDavid Howells
5873c532798SJens Axboe if (test_thread_flag(TIF_NOTIFY_RESUME))
58803248addSEric W. Biederman resume_user_mode_work(regs);
589d0420c83SDavid Howells }
590