#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: compat_13_machdep.c,v 1.24 2017/08/22 09:12:49 maxv Exp $");
#ifdef _KERNEL_OPT
#include "opt_ddb.h"
#endif
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/kernel.h>
#include <sys/mount.h>
#include <sys/signal.h>
#include <sys/signalvar.h>
#include <sys/syscallargs.h>
#include <sparc64/sparc64/sigdebug.h>
#include <compat/sys/signal.h>
#include <compat/sys/signalvar.h>
int
compat_13_sys_sigreturn(struct lwp *l, const struct compat_13_sys_sigreturn_args *uap, register_t *retval)
{
struct sigcontext13 sc, *scp;
struct trapframe64 *tf;
struct proc *p = l->l_proc;
sigset_t mask;
write_user_windows();
if (rwindow_save(l)) {
#ifdef DEBUG
printf("compat_13_sys_sigreturn: rwindow_save(%p) failed, sending SIGILL\n", l);
#ifdef DDB
Debugger();
#endif
#endif
mutex_enter(p->p_lock);
sigexit(l, SIGILL);
}
#ifdef DEBUG
if (sigdebug & SDB_FOLLOW) {
printf("compat_13_sys_sigreturn: %s[%d], sigcntxp %p\n",
p->p_comm, p->p_pid, SCARG(uap, sigcntxp));
#ifdef DDB
if (sigdebug & SDB_DDB) Debugger();
#endif
}
#endif
scp = SCARG(uap, sigcntxp);
if ((vaddr_t)scp & 3 || (copyin((void *)scp, &sc, sizeof sc) != 0))
#ifdef DEBUG
{
printf("compat_13_sys_sigreturn: copyin failed: scp=%p\n", scp);
#ifdef DDB
Debugger();
#endif
return (EFAULT);
}
#else
return (EFAULT);
#endif
scp = ≻
tf = l->l_md.md_tf;
if (((scp->sc_pc | scp->sc_npc) & 3) != 0 || scp->sc_pc == 0 || scp->sc_npc == 0)
#ifdef DEBUG
{
printf("compat_13_sys_sigreturn: pc %p or npc %p invalid\n",
(void *)scp->sc_pc, (void *)scp->sc_npc);
#ifdef DDB
Debugger();
#endif
return (EINVAL);
}
#endif
return (EINVAL);
#ifdef __arch64__
tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | (scp->sc_tstate & TSTATE_CCR);
#else
tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | PSRCC_TO_TSTATE(scp->sc_psr);
#endif
tf->tf_pc = scp->sc_pc;
tf->tf_npc = scp->sc_npc;
tf->tf_global[1] = scp->sc_g1;
tf->tf_out[0] = scp->sc_o0;
tf->tf_out[6] = scp->sc_sp;
#ifdef DEBUG
if (sigdebug & SDB_FOLLOW) {
printf("compat_13_sys_sigreturn: return trapframe pc=%llx sp=%llx tstate=%llx\n",
(long long)tf->tf_pc, (long long)tf->tf_out[6],
(long long)tf->tf_tstate);
#ifdef DDB
if (sigdebug & SDB_DDB) Debugger();
#endif
}
#endif
mutex_enter(p->p_lock);
if (scp->sc_onstack & SS_ONSTACK)
l->l_sigstk.ss_flags |= SS_ONSTACK;
else
l->l_sigstk.ss_flags &= ~SS_ONSTACK;
native_sigset13_to_sigset(&scp->sc_mask, &mask);
(void) sigprocmask1(l, SIG_SETMASK, &mask, 0);
mutex_exit(p->p_lock);
return (EJUSTRETURN);
}