162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Architecture-specific signal handling support. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 1999-2004 Hewlett-Packard Co 662306a36Sopenharmony_ci * David Mosberger-Tang <davidm@hpl.hp.com> 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Derived from i386 and Alpha versions. 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/errno.h> 1262306a36Sopenharmony_ci#include <linux/kernel.h> 1362306a36Sopenharmony_ci#include <linux/mm.h> 1462306a36Sopenharmony_ci#include <linux/ptrace.h> 1562306a36Sopenharmony_ci#include <linux/sched.h> 1662306a36Sopenharmony_ci#include <linux/signal.h> 1762306a36Sopenharmony_ci#include <linux/smp.h> 1862306a36Sopenharmony_ci#include <linux/stddef.h> 1962306a36Sopenharmony_ci#include <linux/tty.h> 2062306a36Sopenharmony_ci#include <linux/binfmts.h> 2162306a36Sopenharmony_ci#include <linux/unistd.h> 2262306a36Sopenharmony_ci#include <linux/wait.h> 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include <asm/intrinsics.h> 2562306a36Sopenharmony_ci#include <linux/uaccess.h> 2662306a36Sopenharmony_ci#include <asm/rse.h> 2762306a36Sopenharmony_ci#include <asm/sigcontext.h> 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#include "sigframe.h" 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define DEBUG_SIG 0 3262306a36Sopenharmony_ci#define STACK_ALIGN 16 /* minimal alignment for stack pointer */ 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#if _NSIG_WORDS > 1 3562306a36Sopenharmony_ci# define PUT_SIGSET(k,u) __copy_to_user((u)->sig, (k)->sig, sizeof(sigset_t)) 3662306a36Sopenharmony_ci# define GET_SIGSET(k,u) __copy_from_user((k)->sig, (u)->sig, sizeof(sigset_t)) 3762306a36Sopenharmony_ci#else 3862306a36Sopenharmony_ci# define PUT_SIGSET(k,u) __put_user((k)->sig[0], &(u)->sig[0]) 3962306a36Sopenharmony_ci# define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0]) 4062306a36Sopenharmony_ci#endif 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic long 4362306a36Sopenharmony_cirestore_sigcontext (struct sigcontext __user *sc, struct sigscratch *scr) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci unsigned long ip, flags, nat, um, cfm, rsc; 4662306a36Sopenharmony_ci long err; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci /* Always make any pending restarted system calls return -EINTR */ 4962306a36Sopenharmony_ci current->restart_block.fn = do_no_restart_syscall; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci /* restore scratch that always needs gets updated during signal delivery: */ 5262306a36Sopenharmony_ci err = __get_user(flags, &sc->sc_flags); 5362306a36Sopenharmony_ci err |= __get_user(nat, &sc->sc_nat); 5462306a36Sopenharmony_ci err |= __get_user(ip, &sc->sc_ip); /* instruction pointer */ 5562306a36Sopenharmony_ci err |= __get_user(cfm, &sc->sc_cfm); 5662306a36Sopenharmony_ci err |= __get_user(um, &sc->sc_um); /* user mask */ 5762306a36Sopenharmony_ci err |= __get_user(rsc, &sc->sc_ar_rsc); 5862306a36Sopenharmony_ci err |= __get_user(scr->pt.ar_unat, &sc->sc_ar_unat); 5962306a36Sopenharmony_ci err |= __get_user(scr->pt.ar_fpsr, &sc->sc_ar_fpsr); 6062306a36Sopenharmony_ci err |= __get_user(scr->pt.ar_pfs, &sc->sc_ar_pfs); 6162306a36Sopenharmony_ci err |= __get_user(scr->pt.pr, &sc->sc_pr); /* predicates */ 6262306a36Sopenharmony_ci err |= __get_user(scr->pt.b0, &sc->sc_br[0]); /* b0 (rp) */ 6362306a36Sopenharmony_ci err |= __get_user(scr->pt.b6, &sc->sc_br[6]); /* b6 */ 6462306a36Sopenharmony_ci err |= __copy_from_user(&scr->pt.r1, &sc->sc_gr[1], 8); /* r1 */ 6562306a36Sopenharmony_ci err |= __copy_from_user(&scr->pt.r8, &sc->sc_gr[8], 4*8); /* r8-r11 */ 6662306a36Sopenharmony_ci err |= __copy_from_user(&scr->pt.r12, &sc->sc_gr[12], 2*8); /* r12-r13 */ 6762306a36Sopenharmony_ci err |= __copy_from_user(&scr->pt.r15, &sc->sc_gr[15], 8); /* r15 */ 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci scr->pt.cr_ifs = cfm | (1UL << 63); 7062306a36Sopenharmony_ci scr->pt.ar_rsc = rsc | (3 << 2); /* force PL3 */ 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci /* establish new instruction pointer: */ 7362306a36Sopenharmony_ci scr->pt.cr_iip = ip & ~0x3UL; 7462306a36Sopenharmony_ci ia64_psr(&scr->pt)->ri = ip & 0x3; 7562306a36Sopenharmony_ci scr->pt.cr_ipsr = (scr->pt.cr_ipsr & ~IA64_PSR_UM) | (um & IA64_PSR_UM); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci scr->scratch_unat = ia64_put_scratch_nat_bits(&scr->pt, nat); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci if (!(flags & IA64_SC_FLAG_IN_SYSCALL)) { 8062306a36Sopenharmony_ci /* Restore most scratch-state only when not in syscall. */ 8162306a36Sopenharmony_ci err |= __get_user(scr->pt.ar_ccv, &sc->sc_ar_ccv); /* ar.ccv */ 8262306a36Sopenharmony_ci err |= __get_user(scr->pt.b7, &sc->sc_br[7]); /* b7 */ 8362306a36Sopenharmony_ci err |= __get_user(scr->pt.r14, &sc->sc_gr[14]); /* r14 */ 8462306a36Sopenharmony_ci err |= __copy_from_user(&scr->pt.ar_csd, &sc->sc_ar25, 2*8); /* ar.csd & ar.ssd */ 8562306a36Sopenharmony_ci err |= __copy_from_user(&scr->pt.r2, &sc->sc_gr[2], 2*8); /* r2-r3 */ 8662306a36Sopenharmony_ci err |= __copy_from_user(&scr->pt.r16, &sc->sc_gr[16], 16*8); /* r16-r31 */ 8762306a36Sopenharmony_ci } 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci if ((flags & IA64_SC_FLAG_FPH_VALID) != 0) { 9062306a36Sopenharmony_ci struct ia64_psr *psr = ia64_psr(&scr->pt); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci err |= __copy_from_user(current->thread.fph, &sc->sc_fr[32], 96*16); 9362306a36Sopenharmony_ci psr->mfh = 0; /* drop signal handler's fph contents... */ 9462306a36Sopenharmony_ci preempt_disable(); 9562306a36Sopenharmony_ci if (psr->dfh) 9662306a36Sopenharmony_ci ia64_drop_fpu(current); 9762306a36Sopenharmony_ci else { 9862306a36Sopenharmony_ci /* We already own the local fph, otherwise psr->dfh wouldn't be 0. */ 9962306a36Sopenharmony_ci __ia64_load_fpu(current->thread.fph); 10062306a36Sopenharmony_ci ia64_set_local_fpu_owner(current); 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci preempt_enable(); 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci return err; 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cilong 10862306a36Sopenharmony_ciia64_rt_sigreturn (struct sigscratch *scr) 10962306a36Sopenharmony_ci{ 11062306a36Sopenharmony_ci extern char ia64_strace_leave_kernel, ia64_leave_kernel; 11162306a36Sopenharmony_ci struct sigcontext __user *sc; 11262306a36Sopenharmony_ci sigset_t set; 11362306a36Sopenharmony_ci long retval; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci sc = &((struct sigframe __user *) (scr->pt.r12 + 16))->sc; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci /* 11862306a36Sopenharmony_ci * When we return to the previously executing context, r8 and r10 have already 11962306a36Sopenharmony_ci * been setup the way we want them. Indeed, if the signal wasn't delivered while 12062306a36Sopenharmony_ci * in a system call, we must not touch r8 or r10 as otherwise user-level state 12162306a36Sopenharmony_ci * could be corrupted. 12262306a36Sopenharmony_ci */ 12362306a36Sopenharmony_ci retval = (long) &ia64_leave_kernel; 12462306a36Sopenharmony_ci if (test_thread_flag(TIF_SYSCALL_TRACE) 12562306a36Sopenharmony_ci || test_thread_flag(TIF_SYSCALL_AUDIT)) 12662306a36Sopenharmony_ci /* 12762306a36Sopenharmony_ci * strace expects to be notified after sigreturn returns even though the 12862306a36Sopenharmony_ci * context to which we return may not be in the middle of a syscall. 12962306a36Sopenharmony_ci * Thus, the return-value that strace displays for sigreturn is 13062306a36Sopenharmony_ci * meaningless. 13162306a36Sopenharmony_ci */ 13262306a36Sopenharmony_ci retval = (long) &ia64_strace_leave_kernel; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci if (!access_ok(sc, sizeof(*sc))) 13562306a36Sopenharmony_ci goto give_sigsegv; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci if (GET_SIGSET(&set, &sc->sc_mask)) 13862306a36Sopenharmony_ci goto give_sigsegv; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci set_current_blocked(&set); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci if (restore_sigcontext(sc, scr)) 14362306a36Sopenharmony_ci goto give_sigsegv; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci#if DEBUG_SIG 14662306a36Sopenharmony_ci printk("SIG return (%s:%d): sp=%lx ip=%lx\n", 14762306a36Sopenharmony_ci current->comm, current->pid, scr->pt.r12, scr->pt.cr_iip); 14862306a36Sopenharmony_ci#endif 14962306a36Sopenharmony_ci if (restore_altstack(&sc->sc_stack)) 15062306a36Sopenharmony_ci goto give_sigsegv; 15162306a36Sopenharmony_ci return retval; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci give_sigsegv: 15462306a36Sopenharmony_ci force_sig(SIGSEGV); 15562306a36Sopenharmony_ci return retval; 15662306a36Sopenharmony_ci} 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci/* 15962306a36Sopenharmony_ci * This does just the minimum required setup of sigcontext. 16062306a36Sopenharmony_ci * Specifically, it only installs data that is either not knowable at 16162306a36Sopenharmony_ci * the user-level or that gets modified before execution in the 16262306a36Sopenharmony_ci * trampoline starts. Everything else is done at the user-level. 16362306a36Sopenharmony_ci */ 16462306a36Sopenharmony_cistatic long 16562306a36Sopenharmony_cisetup_sigcontext (struct sigcontext __user *sc, sigset_t *mask, struct sigscratch *scr) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci unsigned long flags = 0, ifs, cfm, nat; 16862306a36Sopenharmony_ci long err = 0; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci ifs = scr->pt.cr_ifs; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci if (on_sig_stack((unsigned long) sc)) 17362306a36Sopenharmony_ci flags |= IA64_SC_FLAG_ONSTACK; 17462306a36Sopenharmony_ci if ((ifs & (1UL << 63)) == 0) 17562306a36Sopenharmony_ci /* if cr_ifs doesn't have the valid bit set, we got here through a syscall */ 17662306a36Sopenharmony_ci flags |= IA64_SC_FLAG_IN_SYSCALL; 17762306a36Sopenharmony_ci cfm = ifs & ((1UL << 38) - 1); 17862306a36Sopenharmony_ci ia64_flush_fph(current); 17962306a36Sopenharmony_ci if ((current->thread.flags & IA64_THREAD_FPH_VALID)) { 18062306a36Sopenharmony_ci flags |= IA64_SC_FLAG_FPH_VALID; 18162306a36Sopenharmony_ci err = __copy_to_user(&sc->sc_fr[32], current->thread.fph, 96*16); 18262306a36Sopenharmony_ci } 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci nat = ia64_get_scratch_nat_bits(&scr->pt, scr->scratch_unat); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci err |= __put_user(flags, &sc->sc_flags); 18762306a36Sopenharmony_ci err |= __put_user(nat, &sc->sc_nat); 18862306a36Sopenharmony_ci err |= PUT_SIGSET(mask, &sc->sc_mask); 18962306a36Sopenharmony_ci err |= __put_user(cfm, &sc->sc_cfm); 19062306a36Sopenharmony_ci err |= __put_user(scr->pt.cr_ipsr & IA64_PSR_UM, &sc->sc_um); 19162306a36Sopenharmony_ci err |= __put_user(scr->pt.ar_rsc, &sc->sc_ar_rsc); 19262306a36Sopenharmony_ci err |= __put_user(scr->pt.ar_unat, &sc->sc_ar_unat); /* ar.unat */ 19362306a36Sopenharmony_ci err |= __put_user(scr->pt.ar_fpsr, &sc->sc_ar_fpsr); /* ar.fpsr */ 19462306a36Sopenharmony_ci err |= __put_user(scr->pt.ar_pfs, &sc->sc_ar_pfs); 19562306a36Sopenharmony_ci err |= __put_user(scr->pt.pr, &sc->sc_pr); /* predicates */ 19662306a36Sopenharmony_ci err |= __put_user(scr->pt.b0, &sc->sc_br[0]); /* b0 (rp) */ 19762306a36Sopenharmony_ci err |= __put_user(scr->pt.b6, &sc->sc_br[6]); /* b6 */ 19862306a36Sopenharmony_ci err |= __copy_to_user(&sc->sc_gr[1], &scr->pt.r1, 8); /* r1 */ 19962306a36Sopenharmony_ci err |= __copy_to_user(&sc->sc_gr[8], &scr->pt.r8, 4*8); /* r8-r11 */ 20062306a36Sopenharmony_ci err |= __copy_to_user(&sc->sc_gr[12], &scr->pt.r12, 2*8); /* r12-r13 */ 20162306a36Sopenharmony_ci err |= __copy_to_user(&sc->sc_gr[15], &scr->pt.r15, 8); /* r15 */ 20262306a36Sopenharmony_ci err |= __put_user(scr->pt.cr_iip + ia64_psr(&scr->pt)->ri, &sc->sc_ip); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci if (!(flags & IA64_SC_FLAG_IN_SYSCALL)) { 20562306a36Sopenharmony_ci /* Copy scratch regs to sigcontext if the signal didn't interrupt a syscall. */ 20662306a36Sopenharmony_ci err |= __put_user(scr->pt.ar_ccv, &sc->sc_ar_ccv); /* ar.ccv */ 20762306a36Sopenharmony_ci err |= __put_user(scr->pt.b7, &sc->sc_br[7]); /* b7 */ 20862306a36Sopenharmony_ci err |= __put_user(scr->pt.r14, &sc->sc_gr[14]); /* r14 */ 20962306a36Sopenharmony_ci err |= __copy_to_user(&sc->sc_ar25, &scr->pt.ar_csd, 2*8); /* ar.csd & ar.ssd */ 21062306a36Sopenharmony_ci err |= __copy_to_user(&sc->sc_gr[2], &scr->pt.r2, 2*8); /* r2-r3 */ 21162306a36Sopenharmony_ci err |= __copy_to_user(&sc->sc_gr[16], &scr->pt.r16, 16*8); /* r16-r31 */ 21262306a36Sopenharmony_ci } 21362306a36Sopenharmony_ci return err; 21462306a36Sopenharmony_ci} 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci/* 21762306a36Sopenharmony_ci * Check whether the register-backing store is already on the signal stack. 21862306a36Sopenharmony_ci */ 21962306a36Sopenharmony_cistatic inline int 22062306a36Sopenharmony_cirbs_on_sig_stack (unsigned long bsp) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci return (bsp - current->sas_ss_sp < current->sas_ss_size); 22362306a36Sopenharmony_ci} 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_cistatic long 22662306a36Sopenharmony_cisetup_frame(struct ksignal *ksig, sigset_t *set, struct sigscratch *scr) 22762306a36Sopenharmony_ci{ 22862306a36Sopenharmony_ci extern char __kernel_sigtramp[]; 22962306a36Sopenharmony_ci unsigned long tramp_addr, new_rbs = 0, new_sp; 23062306a36Sopenharmony_ci struct sigframe __user *frame; 23162306a36Sopenharmony_ci long err; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci new_sp = scr->pt.r12; 23462306a36Sopenharmony_ci tramp_addr = (unsigned long) __kernel_sigtramp; 23562306a36Sopenharmony_ci if (ksig->ka.sa.sa_flags & SA_ONSTACK) { 23662306a36Sopenharmony_ci int onstack = sas_ss_flags(new_sp); 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci if (onstack == 0) { 23962306a36Sopenharmony_ci new_sp = current->sas_ss_sp + current->sas_ss_size; 24062306a36Sopenharmony_ci /* 24162306a36Sopenharmony_ci * We need to check for the register stack being on the 24262306a36Sopenharmony_ci * signal stack separately, because it's switched 24362306a36Sopenharmony_ci * separately (memory stack is switched in the kernel, 24462306a36Sopenharmony_ci * register stack is switched in the signal trampoline). 24562306a36Sopenharmony_ci */ 24662306a36Sopenharmony_ci if (!rbs_on_sig_stack(scr->pt.ar_bspstore)) 24762306a36Sopenharmony_ci new_rbs = ALIGN(current->sas_ss_sp, 24862306a36Sopenharmony_ci sizeof(long)); 24962306a36Sopenharmony_ci } else if (onstack == SS_ONSTACK) { 25062306a36Sopenharmony_ci unsigned long check_sp; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci /* 25362306a36Sopenharmony_ci * If we are on the alternate signal stack and would 25462306a36Sopenharmony_ci * overflow it, don't. Return an always-bogus address 25562306a36Sopenharmony_ci * instead so we will die with SIGSEGV. 25662306a36Sopenharmony_ci */ 25762306a36Sopenharmony_ci check_sp = (new_sp - sizeof(*frame)) & -STACK_ALIGN; 25862306a36Sopenharmony_ci if (!likely(on_sig_stack(check_sp))) { 25962306a36Sopenharmony_ci force_sigsegv(ksig->sig); 26062306a36Sopenharmony_ci return 1; 26162306a36Sopenharmony_ci } 26262306a36Sopenharmony_ci } 26362306a36Sopenharmony_ci } 26462306a36Sopenharmony_ci frame = (void __user *) ((new_sp - sizeof(*frame)) & -STACK_ALIGN); 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci if (!access_ok(frame, sizeof(*frame))) { 26762306a36Sopenharmony_ci force_sigsegv(ksig->sig); 26862306a36Sopenharmony_ci return 1; 26962306a36Sopenharmony_ci } 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci err = __put_user(ksig->sig, &frame->arg0); 27262306a36Sopenharmony_ci err |= __put_user(&frame->info, &frame->arg1); 27362306a36Sopenharmony_ci err |= __put_user(&frame->sc, &frame->arg2); 27462306a36Sopenharmony_ci err |= __put_user(new_rbs, &frame->sc.sc_rbs_base); 27562306a36Sopenharmony_ci err |= __put_user(0, &frame->sc.sc_loadrs); /* initialize to zero */ 27662306a36Sopenharmony_ci err |= __put_user(ksig->ka.sa.sa_handler, &frame->handler); 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci err |= copy_siginfo_to_user(&frame->info, &ksig->info); 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci err |= __save_altstack(&frame->sc.sc_stack, scr->pt.r12); 28162306a36Sopenharmony_ci err |= setup_sigcontext(&frame->sc, set, scr); 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci if (unlikely(err)) { 28462306a36Sopenharmony_ci force_sigsegv(ksig->sig); 28562306a36Sopenharmony_ci return 1; 28662306a36Sopenharmony_ci } 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci scr->pt.r12 = (unsigned long) frame - 16; /* new stack pointer */ 28962306a36Sopenharmony_ci scr->pt.ar_fpsr = FPSR_DEFAULT; /* reset fpsr for signal handler */ 29062306a36Sopenharmony_ci scr->pt.cr_iip = tramp_addr; 29162306a36Sopenharmony_ci ia64_psr(&scr->pt)->ri = 0; /* start executing in first slot */ 29262306a36Sopenharmony_ci ia64_psr(&scr->pt)->be = 0; /* force little-endian byte-order */ 29362306a36Sopenharmony_ci /* 29462306a36Sopenharmony_ci * Force the interruption function mask to zero. This has no effect when a 29562306a36Sopenharmony_ci * system-call got interrupted by a signal (since, in that case, scr->pt_cr_ifs is 29662306a36Sopenharmony_ci * ignored), but it has the desirable effect of making it possible to deliver a 29762306a36Sopenharmony_ci * signal with an incomplete register frame (which happens when a mandatory RSE 29862306a36Sopenharmony_ci * load faults). Furthermore, it has no negative effect on the getting the user's 29962306a36Sopenharmony_ci * dirty partition preserved, because that's governed by scr->pt.loadrs. 30062306a36Sopenharmony_ci */ 30162306a36Sopenharmony_ci scr->pt.cr_ifs = (1UL << 63); 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci /* 30462306a36Sopenharmony_ci * Note: this affects only the NaT bits of the scratch regs (the ones saved in 30562306a36Sopenharmony_ci * pt_regs), which is exactly what we want. 30662306a36Sopenharmony_ci */ 30762306a36Sopenharmony_ci scr->scratch_unat = 0; /* ensure NaT bits of r12 is clear */ 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci#if DEBUG_SIG 31062306a36Sopenharmony_ci printk("SIG deliver (%s:%d): sig=%d sp=%lx ip=%lx handler=%p\n", 31162306a36Sopenharmony_ci current->comm, current->pid, ksig->sig, scr->pt.r12, frame->sc.sc_ip, frame->handler); 31262306a36Sopenharmony_ci#endif 31362306a36Sopenharmony_ci return 0; 31462306a36Sopenharmony_ci} 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_cistatic long 31762306a36Sopenharmony_cihandle_signal (struct ksignal *ksig, struct sigscratch *scr) 31862306a36Sopenharmony_ci{ 31962306a36Sopenharmony_ci int ret = setup_frame(ksig, sigmask_to_save(), scr); 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci if (!ret) 32262306a36Sopenharmony_ci signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP)); 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci return ret; 32562306a36Sopenharmony_ci} 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci/* 32862306a36Sopenharmony_ci * Note that `init' is a special process: it doesn't get signals it doesn't want to 32962306a36Sopenharmony_ci * handle. Thus you cannot kill init even with a SIGKILL even by mistake. 33062306a36Sopenharmony_ci */ 33162306a36Sopenharmony_civoid 33262306a36Sopenharmony_ciia64_do_signal (struct sigscratch *scr, long in_syscall) 33362306a36Sopenharmony_ci{ 33462306a36Sopenharmony_ci long restart = in_syscall; 33562306a36Sopenharmony_ci long errno = scr->pt.r8; 33662306a36Sopenharmony_ci struct ksignal ksig; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci /* 33962306a36Sopenharmony_ci * This only loops in the rare cases of handle_signal() failing, in which case we 34062306a36Sopenharmony_ci * need to push through a forced SIGSEGV. 34162306a36Sopenharmony_ci */ 34262306a36Sopenharmony_ci while (1) { 34362306a36Sopenharmony_ci if (!get_signal(&ksig)) 34462306a36Sopenharmony_ci break; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci /* 34762306a36Sopenharmony_ci * get_signal() may have run a debugger (via notify_parent()) 34862306a36Sopenharmony_ci * and the debugger may have modified the state (e.g., to arrange for an 34962306a36Sopenharmony_ci * inferior call), thus it's important to check for restarting _after_ 35062306a36Sopenharmony_ci * get_signal(). 35162306a36Sopenharmony_ci */ 35262306a36Sopenharmony_ci if ((long) scr->pt.r10 != -1) 35362306a36Sopenharmony_ci /* 35462306a36Sopenharmony_ci * A system calls has to be restarted only if one of the error codes 35562306a36Sopenharmony_ci * ERESTARTNOHAND, ERESTARTSYS, or ERESTARTNOINTR is returned. If r10 35662306a36Sopenharmony_ci * isn't -1 then r8 doesn't hold an error code and we don't need to 35762306a36Sopenharmony_ci * restart the syscall, so we can clear the "restart" flag here. 35862306a36Sopenharmony_ci */ 35962306a36Sopenharmony_ci restart = 0; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci if (ksig.sig <= 0) 36262306a36Sopenharmony_ci break; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci if (unlikely(restart)) { 36562306a36Sopenharmony_ci switch (errno) { 36662306a36Sopenharmony_ci case ERESTART_RESTARTBLOCK: 36762306a36Sopenharmony_ci case ERESTARTNOHAND: 36862306a36Sopenharmony_ci scr->pt.r8 = EINTR; 36962306a36Sopenharmony_ci /* note: scr->pt.r10 is already -1 */ 37062306a36Sopenharmony_ci break; 37162306a36Sopenharmony_ci case ERESTARTSYS: 37262306a36Sopenharmony_ci if ((ksig.ka.sa.sa_flags & SA_RESTART) == 0) { 37362306a36Sopenharmony_ci scr->pt.r8 = EINTR; 37462306a36Sopenharmony_ci /* note: scr->pt.r10 is already -1 */ 37562306a36Sopenharmony_ci break; 37662306a36Sopenharmony_ci } 37762306a36Sopenharmony_ci fallthrough; 37862306a36Sopenharmony_ci case ERESTARTNOINTR: 37962306a36Sopenharmony_ci ia64_decrement_ip(&scr->pt); 38062306a36Sopenharmony_ci restart = 0; /* don't restart twice if handle_signal() fails... */ 38162306a36Sopenharmony_ci } 38262306a36Sopenharmony_ci } 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci /* 38562306a36Sopenharmony_ci * Whee! Actually deliver the signal. If the delivery failed, we need to 38662306a36Sopenharmony_ci * continue to iterate in this loop so we can deliver the SIGSEGV... 38762306a36Sopenharmony_ci */ 38862306a36Sopenharmony_ci if (handle_signal(&ksig, scr)) 38962306a36Sopenharmony_ci return; 39062306a36Sopenharmony_ci } 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci /* Did we come from a system call? */ 39362306a36Sopenharmony_ci if (restart) { 39462306a36Sopenharmony_ci /* Restart the system call - no handlers present */ 39562306a36Sopenharmony_ci if (errno == ERESTARTNOHAND || errno == ERESTARTSYS || errno == ERESTARTNOINTR 39662306a36Sopenharmony_ci || errno == ERESTART_RESTARTBLOCK) 39762306a36Sopenharmony_ci { 39862306a36Sopenharmony_ci /* 39962306a36Sopenharmony_ci * Note: the syscall number is in r15 which is saved in 40062306a36Sopenharmony_ci * pt_regs so all we need to do here is adjust ip so that 40162306a36Sopenharmony_ci * the "break" instruction gets re-executed. 40262306a36Sopenharmony_ci */ 40362306a36Sopenharmony_ci ia64_decrement_ip(&scr->pt); 40462306a36Sopenharmony_ci if (errno == ERESTART_RESTARTBLOCK) 40562306a36Sopenharmony_ci scr->pt.r15 = __NR_restart_syscall; 40662306a36Sopenharmony_ci } 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci /* if there's no signal to deliver, we just put the saved sigmask 41062306a36Sopenharmony_ci * back */ 41162306a36Sopenharmony_ci restore_saved_sigmask(); 41262306a36Sopenharmony_ci} 413