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