11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  linux/arch/parisc/kernel/signal.c: Architecture-specific signal
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  handling support.
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 2000 David Huggins-Daines <dhd@debian.org>
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 2000 Linuxcare, Inc.
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Based on the ia64, i386, and alpha versions.
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Like the IA-64, we are a recent enough port (we are *starting*
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  with glibc2.2) that we do not need to support the old non-realtime
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Linux signals.  Therefore we don't.  HP/UX signals will go in
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  arch/parisc/hpux/signal.c when we figure out how to do them.
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h>
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/smp.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/signal.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/wait.h>
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ptrace.h>
24ecf02de5a1491592d1b68d8095ff62ea3aaee67eKyle McMartin#include <linux/tracehook.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/unistd.h>
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/stddef.h>
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/compat.h>
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/elf.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/ucontext.h>
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/rt_sigframe.h>
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h>
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pgalloc.h>
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/cacheflush.h>
340013a85454c281faaf064ccb576e373a2881aac8Sam Ravnborg#include <asm/asm-offsets.h>
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_COMPAT
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "signal32.h"
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DEBUG_SIG 0
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DEBUG_SIG_LEVEL 2
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG_SIG
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG(LEVEL, ...) \
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        ((DEBUG_SIG_LEVEL >= LEVEL) \
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	? printk(__VA_ARGS__) : (void) 0)
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DBG(LEVEL, ...)
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* gcc will complain if a pointer is cast to an integer of different
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * size.  If you really need to do this (and we do for an ELF32 user
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * application in an ELF64 kernel) then you have to do a cast to an
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * integer of the same size first.  The A() macro accomplishes
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this. */
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define A(__x)	((unsigned long)(__x))
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Do a signal return - restore sigcontext.
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Trampoline for calling rt_sigreturn() */
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INSN_LDI_R25_0	 0x34190000 /* ldi  0,%r25 (in_syscall=0) */
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INSN_LDI_R25_1	 0x34190002 /* ldi  1,%r25 (in_syscall=1) */
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INSN_LDI_R20	 0x3414015a /* ldi  __NR_rt_sigreturn,%r20 */
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INSN_BLE_SR2_R0  0xe4008200 /* be,l 0x100(%sr2,%r0),%sr0,%r31 */
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INSN_NOP	 0x08000240 /* nop */
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* For debugging */
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INSN_DIE_HORRIBLY 0x68000ccc /* stw %r0,0x666(%sr0,%r0) */
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic long
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsrestore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long err = 0;
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err |= __copy_from_user(regs->gr, sc->sc_gr, sizeof(regs->gr));
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err |= __copy_from_user(regs->iaoq, sc->sc_iaoq, sizeof(regs->iaoq));
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err |= __copy_from_user(regs->iasq, sc->sc_iasq, sizeof(regs->iasq));
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err |= __get_user(regs->sar, &sc->sc_sar);
818e33a52fadddcfc9f85594a7ab4802c60ee0046aJoe Perches	DBG(2,"restore_sigcontext: iaoq is %#lx / %#lx\n",
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			regs->iaoq[0],regs->iaoq[1]);
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DBG(2,"restore_sigcontext: r28 is %ld\n", regs->gr[28]);
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct rt_sigframe __user *frame;
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sigset_t set;
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long usp = (regs->gr[30] & ~(0x01UL));
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE;
94a8f44e3889b686813926b288bd4e51a0cf17d2c7Helge Deller#ifdef CONFIG_64BIT
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	compat_sigset_t compat_set;
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct compat_rt_sigframe __user * compat_frame;
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
98a3ea84fabacd9cc5bcc3fda67c35e692ca10dc8cKyle McMartin	if (is_compat_task())
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10285a847ffad1d4ee94590db25bad444d18a8db263Al Viro	current_thread_info()->restart_block.fn = do_no_restart_syscall;
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Unwind the user stack to get the rt_sigframe structure. */
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	frame = (struct rt_sigframe __user *)
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(usp - sigframe_size);
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DBG(2,"sys_rt_sigreturn: frame is %p\n", frame);
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10900df111e7eb505558c54f23861e9341e56dd5fb0Al Viro	regs->orig_r28 = 1; /* no restarts for sigreturn */
11000df111e7eb505558c54f23861e9341e56dd5fb0Al Viro
111a8f44e3889b686813926b288bd4e51a0cf17d2c7Helge Deller#ifdef CONFIG_64BIT
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	compat_frame = (struct compat_rt_sigframe __user *)frame;
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
114a3ea84fabacd9cc5bcc3fda67c35e692ca10dc8cKyle McMartin	if (is_compat_task()) {
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG(2,"sys_rt_sigreturn: ELF32 process.\n");
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (__copy_from_user(&compat_set, &compat_frame->uc.uc_sigmask, sizeof(compat_set)))
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto give_sigsegv;
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sigset_32to64(&set,&compat_set);
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto give_sigsegv;
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
126ade7728b4e9aac4cc82117e3e35c5745b7d16037Matt Fleming	set_current_blocked(&set);
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Good thing we saved the old gr[30], eh? */
129a8f44e3889b686813926b288bd4e51a0cf17d2c7Helge Deller#ifdef CONFIG_64BIT
130a3ea84fabacd9cc5bcc3fda67c35e692ca10dc8cKyle McMartin	if (is_compat_task()) {
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG(1,"sys_rt_sigreturn: compat_frame->uc.uc_mcontext 0x%p\n",
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				&compat_frame->uc.uc_mcontext);
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// FIXME: Load upper half from register file
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (restore_sigcontext32(&compat_frame->uc.uc_mcontext,
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					&compat_frame->regs, regs))
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto give_sigsegv;
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n",
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				usp, &compat_frame->uc.uc_stack);
1396e26aab98ce8a818fb1ec47f8f727a8480a9011bAl Viro		if (compat_restore_altstack(&compat_frame->uc.uc_stack))
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto give_sigsegv;
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG(1,"sys_rt_sigreturn: frame->uc.uc_mcontext 0x%p\n",
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				&frame->uc.uc_mcontext);
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (restore_sigcontext(&frame->uc.uc_mcontext, regs))
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto give_sigsegv;
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n",
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				usp, &frame->uc.uc_stack);
1506e26aab98ce8a818fb1ec47f8f727a8480a9011bAl Viro		if (restore_altstack(&frame->uc.uc_stack))
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto give_sigsegv;
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* If we are on the syscall path IAOQ will not be restored, and
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * if we are on the interrupt path we must not corrupt gr31.
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (in_syscall)
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->gr[31] = regs->iaoq[0];
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG_SIG
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DBG(1,"sys_rt_sigreturn: returning to %#lx, DUMPING REGS:\n", regs->iaoq[0]);
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	show_regs(regs);
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsgive_sigsegv:
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DBG(1,"sys_rt_sigreturn: Sending SIGSEGV\n");
16967bace72ee64f6a11cfb914b91d9d6bd47e80ed8Kyle McMartin	force_sig(SIGSEGV, current);
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set up a signal frame.
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void __user *
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsget_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*FIXME: ELF32 vs. ELF64 has different frame_size, but since we
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  don't use the parameter it doesn't matter */
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DBG(1,"get_sigframe: ka = %#lx, sp = %#lx, frame_size = %#lx\n",
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			(unsigned long)ka, sp, frame_size);
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
186ad30f3ff3deb4037f2beea15812d01d795f8b3ccJohn David Anglin	/* Align alternate stack and reserve 64 bytes for the signal
187ad30f3ff3deb4037f2beea15812d01d795f8b3ccJohn David Anglin	   handler's frame marker.  */
188d09042da7284a86ffbdd18695f517a71514ed598Laurent MEYER	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
189ad30f3ff3deb4037f2beea15812d01d795f8b3ccJohn David Anglin		sp = (current->sas_ss_sp + 0x7f) & ~0x3f; /* Stacks grow up! */
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp);
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (void __user *) sp; /* Stacks grow up.  Fun. */
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic long
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssetup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, int in_syscall)
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags = 0;
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	long err = 0;
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (on_sig_stack((unsigned long) sc))
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		flags |= PARISC_SC_FLAG_ONSTACK;
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (in_syscall) {
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		flags |= PARISC_SC_FLAG_IN_SYSCALL;
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* regs->iaoq is undefined in the syscall return path */
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err |= __put_user(regs->gr[31], &sc->sc_iaoq[0]);
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err |= __put_user(regs->gr[31]+4, &sc->sc_iaoq[1]);
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err |= __put_user(regs->sr[3], &sc->sc_iasq[0]);
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err |= __put_user(regs->sr[3], &sc->sc_iasq[1]);
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG(1,"setup_sigcontext: iaoq %#lx / %#lx (in syscall)\n",
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			regs->gr[31], regs->gr[31]+4);
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err |= __copy_to_user(sc->sc_iaoq, regs->iaoq, sizeof(regs->iaoq));
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err |= __copy_to_user(sc->sc_iasq, regs->iasq, sizeof(regs->iasq));
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG(1,"setup_sigcontext: iaoq %#lx / %#lx (not in syscall)\n",
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			regs->iaoq[0], regs->iaoq[1]);
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err |= __put_user(flags, &sc->sc_flags);
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err |= __copy_to_user(sc->sc_gr, regs->gr, sizeof(regs->gr));
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err |= __put_user(regs->sar, &sc->sc_sar);
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DBG(1,"setup_sigcontext: r28 is %ld\n", regs->gr[28]);
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic long
230e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinbergersetup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
231e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinberger	       int in_syscall)
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct rt_sigframe __user *frame;
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long rp, usp;
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long haddr, sigframe_size;
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err = 0;
237a8f44e3889b686813926b288bd4e51a0cf17d2c7Helge Deller#ifdef CONFIG_64BIT
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct compat_rt_sigframe __user * compat_frame;
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	compat_sigset_t compat_set;
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	usp = (regs->gr[30] & ~(0x01UL));
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*FIXME: frame_size parameter is unused, remove it. */
244e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinberger	frame = get_sigframe(&ksig->ka, usp, sizeof(*frame));
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DBG(1,"SETUP_RT_FRAME: START\n");
247e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinberger	DBG(1,"setup_rt_frame: frame %p info %p\n", frame, ksig->info);
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
250a8f44e3889b686813926b288bd4e51a0cf17d2c7Helge Deller#ifdef CONFIG_64BIT
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	compat_frame = (struct compat_rt_sigframe __user *)frame;
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
254a3ea84fabacd9cc5bcc3fda67c35e692ca10dc8cKyle McMartin	if (is_compat_task()) {
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info);
256e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinberger		err |= copy_siginfo_to_user32(&compat_frame->info, &ksig->info);
2576e26aab98ce8a818fb1ec47f8f727a8480a9011bAl Viro		err |= __compat_save_altstack( &compat_frame->uc.uc_stack, regs->gr[30]);
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &compat_frame->uc);
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &compat_frame->uc.uc_mcontext);
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err |= setup_sigcontext32(&compat_frame->uc.uc_mcontext,
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					&compat_frame->regs, regs, in_syscall);
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sigset_64to32(&compat_set,set);
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err |= __copy_to_user(&compat_frame->uc.uc_sigmask, &compat_set, sizeof(compat_set));
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &frame->info);
268e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinberger		err |= copy_siginfo_to_user(&frame->info, &ksig->info);
2696e26aab98ce8a818fb1ec47f8f727a8480a9011bAl Viro		err |= __save_altstack(&frame->uc.uc_stack, regs->gr[30]);
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &frame->uc);
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &frame->uc.uc_mcontext);
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, in_syscall);
27325985edcedea6396277003854657b5f3cb31a628Lucas De Marchi		/* FIXME: Should probably be converted as well for the compat case */
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
278e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinberger		return -EFAULT;
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set up to return from userspace.  If provided, use a stub
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   already in userspace. The first words of tramp are used to
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   save the previous sigrestartblock trampoline that might be
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   on the stack. We start the sigreturn trampoline at
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   SIGRESTARTBLOCK_TRAMP+X. */
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err |= __put_user(in_syscall ? INSN_LDI_R25_1 : INSN_LDI_R25_0,
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			&frame->tramp[SIGRESTARTBLOCK_TRAMP+0]);
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err |= __put_user(INSN_LDI_R20,
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			&frame->tramp[SIGRESTARTBLOCK_TRAMP+1]);
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err |= __put_user(INSN_BLE_SR2_R0,
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			&frame->tramp[SIGRESTARTBLOCK_TRAMP+2]);
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err |= __put_user(INSN_NOP, &frame->tramp[SIGRESTARTBLOCK_TRAMP+3]);
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if DEBUG_SIG
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Assert that we're flushing in the correct space... */
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
29645b6eff2a60c8bec1254412dfdb36acb0afe04a2John David Anglin		unsigned long sid;
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		asm ("mfsp %%sr3,%0" : "=r" (sid));
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG(1,"setup_rt_frame: Flushing 64 bytes at space %#x offset %p\n",
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       sid, frame->tramp);
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flush_user_dcache_range((unsigned long) &frame->tramp[0],
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   (unsigned long) &frame->tramp[TRAMP_SIZE]);
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	flush_user_icache_range((unsigned long) &frame->tramp[0],
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   (unsigned long) &frame->tramp[TRAMP_SIZE]);
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
308efad798b9f01300565f65058b153250cc49d58f2Paulius Zaleckas	/* TRAMP Words 0-4, Length 5 = SIGRESTARTBLOCK_TRAMP
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * TRAMP Words 5-9, Length 4 = SIGRETURN_TRAMP
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * So the SIGRETURN_TRAMP is at the end of SIGRESTARTBLOCK_TRAMP
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rp = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP];
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
315e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinberger		return -EFAULT;
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
317e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinberger	haddr = A(ksig->ka.sa.sa_handler);
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* The sa_handler may be a pointer to a function descriptor */
319a8f44e3889b686813926b288bd4e51a0cf17d2c7Helge Deller#ifdef CONFIG_64BIT
320a3ea84fabacd9cc5bcc3fda67c35e692ca10dc8cKyle McMartin	if (is_compat_task()) {
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (haddr & PA_PLABEL_FDESC) {
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			Elf32_Fdesc fdesc;
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			Elf32_Fdesc __user *ufdesc = (Elf32_Fdesc __user *)A(haddr & ~3);
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (err)
329e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinberger				return -EFAULT;
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			haddr = fdesc.addr;
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			regs->gr[19] = fdesc.gp;
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
334a8f44e3889b686813926b288bd4e51a0cf17d2c7Helge Deller#ifdef CONFIG_64BIT
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		Elf64_Fdesc fdesc;
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		Elf64_Fdesc __user *ufdesc = (Elf64_Fdesc __user *)A(haddr & ~3);
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (err)
342e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinberger			return -EFAULT;
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		haddr = fdesc.addr;
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->gr[19] = fdesc.gp;
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DBG(1,"setup_rt_frame: 64 bit signal, exe=%#lx, r19=%#lx, in_syscall=%d\n",
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		     haddr, regs->gr[19], in_syscall);
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* The syscall return path will create IAOQ values from r31.
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sigframe_size = PARISC_RT_SIGFRAME_SIZE;
354a8f44e3889b686813926b288bd4e51a0cf17d2c7Helge Deller#ifdef CONFIG_64BIT
355a3ea84fabacd9cc5bcc3fda67c35e692ca10dc8cKyle McMartin	if (is_compat_task())
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (in_syscall) {
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->gr[31] = haddr;
360a8f44e3889b686813926b288bd4e51a0cf17d2c7Helge Deller#ifdef CONFIG_64BIT
361df570b9c284701d08b22aa00cbfcf870b7f1b7c1Kyle McMartin		if (!test_thread_flag(TIF_32BIT))
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			sigframe_size |= 1;
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned long psw = USER_PSW;
366a8f44e3889b686813926b288bd4e51a0cf17d2c7Helge Deller#ifdef CONFIG_64BIT
367df570b9c284701d08b22aa00cbfcf870b7f1b7c1Kyle McMartin		if (!test_thread_flag(TIF_32BIT))
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			psw |= PSW_W;
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* If we are singlestepping, arrange a trap to be delivered
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   when we return to userspace. Note the semantics -- we
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   should trap before the first insn in the handler is
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   executed. Ref:
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			http://sources.redhat.com/ml/gdb/2004-11/msg00245.html
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (pa_psw(current)->r) {
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			pa_psw(current)->r = 0;
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			psw |= PSW_R;
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mtctl(-1, 0);
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->gr[0] = psw;
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->iaoq[0] = haddr | 3;
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->iaoq[1] = regs->iaoq[0] + 4;
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->gr[2]  = rp;                /* userland return pointer */
389e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinberger	regs->gr[26] = ksig->sig;               /* signal number */
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
391a8f44e3889b686813926b288bd4e51a0cf17d2c7Helge Deller#ifdef CONFIG_64BIT
392a3ea84fabacd9cc5bcc3fda67c35e692ca10dc8cKyle McMartin	if (is_compat_task()) {
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->gr[25] = A(&compat_frame->info); /* siginfo pointer */
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->gr[24] = A(&compat_frame->uc);   /* ucontext pointer */
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->gr[25] = A(&frame->info); /* siginfo pointer */
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->gr[24] = A(&frame->uc);   /* ucontext pointer */
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DBG(1,"setup_rt_frame: making sigreturn frame: %#lx + %#lx = %#lx\n",
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       regs->gr[30], sigframe_size,
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       regs->gr[30] + sigframe_size);
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Raise the user stack pointer to make a proper call frame. */
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	regs->gr[30] = (A(frame) + sigframe_size);
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DBG(1,"setup_rt_frame: sig deliver (%s,%d) frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       current->comm, current->pid, frame, regs->gr[30],
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	       regs->iaoq[0], regs->iaoq[1], rp);
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * OK, we're invoking a handler.
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
420e3b880c6ee55e8858a75e3dcf6c3dda04d5e3605Al Virostatic void
421e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinbergerhandle_signal(struct ksignal *ksig, struct pt_regs *regs, int in_syscall)
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
423e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinberger	int ret;
424b7f9a11a6cf1ea9ee6be3eb2b90d91327a09ad14Al Viro	sigset_t *oldset = sigmask_to_save();
425e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinberger
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n",
427e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinberger	       ksig->sig, ksig->ka, ksig->info, oldset, regs);
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set up the stack frame */
430e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinberger	ret = setup_rt_frame(ksig, oldset, regs, in_syscall);
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
432e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinberger	signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP) ||
433e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinberger			  test_thread_flag(TIF_BLOCKSTEP));
434ecf02de5a1491592d1b68d8095ff62ea3aaee67eKyle McMartin
435a610d6e672d6d3723e8da257ad4a8a288a8f2f89Al Viro	DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
436a610d6e672d6d3723e8da257ad4a8a288a8f2f89Al Viro		regs->gr[28]);
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4392b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartinstatic inline void
4402b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartinsyscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
4412b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin{
44200df111e7eb505558c54f23861e9341e56dd5fb0Al Viro	if (regs->orig_r28)
44300df111e7eb505558c54f23861e9341e56dd5fb0Al Viro		return;
44400df111e7eb505558c54f23861e9341e56dd5fb0Al Viro	regs->orig_r28 = 1; /* no more restarts */
4452b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin	/* Check the return code */
4462b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin	switch (regs->gr[28]) {
4472b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin	case -ERESTART_RESTARTBLOCK:
4482b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin	case -ERESTARTNOHAND:
4492b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
4502b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		regs->gr[28] = -EINTR;
4512b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		break;
4522b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin
4532b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin	case -ERESTARTSYS:
4542b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		if (!(ka->sa.sa_flags & SA_RESTART)) {
4552b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin			DBG(1,"ERESTARTSYS: putting -EINTR\n");
4562b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin			regs->gr[28] = -EINTR;
4572b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin			break;
4582b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		}
4592b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		/* fallthrough */
4602b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin	case -ERESTARTNOINTR:
4612b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		/* A syscall is just a branch, so all
4622b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		 * we have to do is fiddle the return pointer.
4632b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		 */
4642b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		regs->gr[31] -= 8; /* delayed branching */
4652b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		break;
4662b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin	}
4672b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin}
4682b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin
4692b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartinstatic inline void
4702b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartininsert_restart_trampoline(struct pt_regs *regs)
4712b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin{
47200df111e7eb505558c54f23861e9341e56dd5fb0Al Viro	if (regs->orig_r28)
47300df111e7eb505558c54f23861e9341e56dd5fb0Al Viro		return;
47400df111e7eb505558c54f23861e9341e56dd5fb0Al Viro	regs->orig_r28 = 1; /* no more restarts */
4752b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin	switch(regs->gr[28]) {
4762b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin	case -ERESTART_RESTARTBLOCK: {
4772b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		/* Restart the system call - no handlers present */
4782b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		unsigned int *usp = (unsigned int *)regs->gr[30];
4792b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin
4802b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		/* Setup a trampoline to restart the syscall
4812b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		 * with __NR_restart_syscall
4822b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		 *
4832b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		 *  0: <return address (orig r31)>
4842b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		 *  4: <2nd half for 64-bit>
4852b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		 *  8: ldw 0(%sp), %r31
4862b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		 * 12: be 0x100(%sr2, %r0)
4872b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		 * 16: ldi __NR_restart_syscall, %r20
4882b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		 */
4892b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin#ifdef CONFIG_64BIT
4902b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		put_user(regs->gr[31] >> 32, &usp[0]);
4912b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		put_user(regs->gr[31] & 0xffffffff, &usp[1]);
4922b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		put_user(0x0fc010df, &usp[2]);
4932b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin#else
4942b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		put_user(regs->gr[31], &usp[0]);
4952b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		put_user(0x0fc0109f, &usp[2]);
4962b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin#endif
4972b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		put_user(0xe0008200, &usp[3]);
4982b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		put_user(0x34140000, &usp[4]);
4992b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin
5002b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		/* Stack is 64-byte aligned, and we only need
5012b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		 * to flush 1 cache line.
5022b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		 * Flushing one cacheline is cheap.
5032b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		 * "sync" on bigger (> 4 way) boxes is not.
5042b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		 */
505cf39cc3b56bc4a562db6242d3069f65034ec7549Kyle McMartin		flush_user_dcache_range(regs->gr[30], regs->gr[30] + 4);
506cf39cc3b56bc4a562db6242d3069f65034ec7549Kyle McMartin		flush_user_icache_range(regs->gr[30], regs->gr[30] + 4);
5072b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin
5082b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		regs->gr[31] = regs->gr[30] + 8;
5092b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		return;
5102b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin	}
5112b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin	case -ERESTARTNOHAND:
5122b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin	case -ERESTARTSYS:
5132b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin	case -ERESTARTNOINTR: {
5142b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		/* Hooray for delayed branching.  We don't
5152b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		 * have to restore %r20 (the system call
5162b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		 * number) because it gets loaded in the delay
5172b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		 * slot of the branch external instruction.
5182b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		 */
5192b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		regs->gr[31] -= 8;
5202b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		return;
5212b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin	}
5222b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin	default:
5232b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		break;
5242b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin	}
5252b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin}
5262b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note that 'init' is a special process: it doesn't get signals it doesn't
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * want to handle. Thus you cannot kill init even with a SIGKILL even by
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mistake.
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We need to be able to restore the syscall arguments (r21-r26) to
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * restart syscalls.  Thus, the syscall path should save them in the
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * pt_regs structure (it's okay to do so since they are caller-save
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * registers).  As noted below, the syscall number gets restored for
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * us due to the magic of delayed branching.
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
5384650f0a5832033c78690811aa9b171764c11fc0fKyle McMartinasmlinkage void
5394650f0a5832033c78690811aa9b171764c11fc0fKyle McMartindo_signal(struct pt_regs *regs, long in_syscall)
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
541e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinberger	struct ksignal ksig;
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
543b7f9a11a6cf1ea9ee6be3eb2b90d91327a09ad14Al Viro	DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n",
544b7f9a11a6cf1ea9ee6be3eb2b90d91327a09ad14Al Viro	       regs, regs->sr[7], in_syscall);
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
546e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinberger	if (get_signal(&ksig)) {
547e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinberger		DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Restart a system call if necessary. */
5492b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		if (in_syscall)
550e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinberger			syscall_restart(regs, &ksig.ka);
5512b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin
552e4dc894b61776733629b24507031dd46f5ba5efcRichard Weinberger		handle_signal(&ksig, regs, in_syscall);
553e3b880c6ee55e8858a75e3dcf6c3dda04d5e3605Al Viro		return;
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Did we come from a system call? */
5572b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin	if (in_syscall)
5582b163b71e6d4471cae74037cb680e885eafc8d64Kyle McMartin		insert_restart_trampoline(regs);
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n",
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		regs->gr[28]);
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56351a7b448d4134e3e8eec633435e3e8faee14a828Al Viro	restore_saved_sigmask();
5644650f0a5832033c78690811aa9b171764c11fc0fKyle McMartin}
5654650f0a5832033c78690811aa9b171764c11fc0fKyle McMartin
5664650f0a5832033c78690811aa9b171764c11fc0fKyle McMartinvoid do_notify_resume(struct pt_regs *regs, long in_syscall)
5674650f0a5832033c78690811aa9b171764c11fc0fKyle McMartin{
5686fd84c0831ec78d98736b76dc5e9b849f1dbfc9eAl Viro	if (test_thread_flag(TIF_SIGPENDING))
5694650f0a5832033c78690811aa9b171764c11fc0fKyle McMartin		do_signal(regs, in_syscall);
570d0420c83f39f79afb82010c2d2cafd150eef651bDavid Howells
571d0420c83f39f79afb82010c2d2cafd150eef651bDavid Howells	if (test_thread_flag(TIF_NOTIFY_RESUME)) {
572d0420c83f39f79afb82010c2d2cafd150eef651bDavid Howells		clear_thread_flag(TIF_NOTIFY_RESUME);
573d0420c83f39f79afb82010c2d2cafd150eef651bDavid Howells		tracehook_notify_resume(regs);
574d0420c83f39f79afb82010c2d2cafd150eef651bDavid Howells	}
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
576