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