xref: /linux/arch/parisc/kernel/signal.c (revision a1c613ae4c322ddd58d5a8539dbfba2a0380a8c0)
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