Home | History | Annotate | Line # | Download | only in sparc64
      1 /*	$NetBSD: compat_13_machdep.c,v 1.24 2017/08/22 09:12:49 maxv Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
      9  * NASA Ames Research Center.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30  * POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include <sys/cdefs.h>
     34 __KERNEL_RCSID(0, "$NetBSD: compat_13_machdep.c,v 1.24 2017/08/22 09:12:49 maxv Exp $");
     35 
     36 #ifdef _KERNEL_OPT
     37 #include "opt_ddb.h"
     38 #endif
     39 
     40 #include <sys/param.h>
     41 #include <sys/systm.h>
     42 #include <sys/proc.h>
     43 #include <sys/kernel.h>
     44 #include <sys/mount.h>
     45 #include <sys/signal.h>
     46 #include <sys/signalvar.h>
     47 
     48 #include <sys/syscallargs.h>
     49 #include <sparc64/sparc64/sigdebug.h>
     50 
     51 #include <compat/sys/signal.h>
     52 #include <compat/sys/signalvar.h>
     53 /*
     54  * System call to cleanup state after a signal
     55  * has been taken.  Reset signal mask and
     56  * stack state from context left by sendsig (above),
     57  * and return to the given trap frame (if there is one).
     58  * Check carefully to make sure that the user has not
     59  * modified the state to gain improper privileges or to cause
     60  * a machine fault.
     61  */
     62 /* ARGSUSED */
     63 int
     64 compat_13_sys_sigreturn(struct lwp *l, const struct compat_13_sys_sigreturn_args *uap, register_t *retval)
     65 {
     66 	/* {
     67 		syscallarg(struct sigcontext13 *) sigcntxp;
     68 	} */
     69 	struct sigcontext13 sc, *scp;
     70 	struct trapframe64 *tf;
     71 	struct proc *p = l->l_proc;
     72 	sigset_t mask;
     73 
     74 	/* First ensure consistent stack state (see sendsig). */
     75 	write_user_windows();
     76 	if (rwindow_save(l)) {
     77 #ifdef DEBUG
     78 		printf("compat_13_sys_sigreturn: rwindow_save(%p) failed, sending SIGILL\n", l);
     79 #ifdef DDB
     80 		Debugger();
     81 #endif
     82 #endif
     83 		mutex_enter(p->p_lock);
     84 		sigexit(l, SIGILL);
     85 	}
     86 #ifdef DEBUG
     87 	if (sigdebug & SDB_FOLLOW) {
     88 		printf("compat_13_sys_sigreturn: %s[%d], sigcntxp %p\n",
     89 		    p->p_comm, p->p_pid, SCARG(uap, sigcntxp));
     90 #ifdef DDB
     91 		if (sigdebug & SDB_DDB) Debugger();
     92 #endif
     93 	}
     94 #endif
     95 
     96 	scp = SCARG(uap, sigcntxp);
     97 	if ((vaddr_t)scp & 3 || (copyin((void *)scp, &sc, sizeof sc) != 0))
     98 #ifdef DEBUG
     99 	{
    100 		printf("compat_13_sys_sigreturn: copyin failed: scp=%p\n", scp);
    101 #ifdef DDB
    102 		Debugger();
    103 #endif
    104 		return (EFAULT);
    105 	}
    106 #else
    107 		return (EFAULT);
    108 #endif
    109 
    110 	scp = &sc;
    111 
    112 	tf = l->l_md.md_tf;
    113 	/*
    114 	 * Only the icc bits in the psr are used, so it need not be
    115 	 * verified.  pc and npc must be multiples of 4.  This is all
    116 	 * that is required; if it holds, just do it.
    117 	 */
    118 	if (((scp->sc_pc | scp->sc_npc) & 3) != 0 || scp->sc_pc == 0 || scp->sc_npc == 0)
    119 #ifdef DEBUG
    120 	{
    121 		printf("compat_13_sys_sigreturn: pc %p or npc %p invalid\n",
    122 			(void *)scp->sc_pc, (void *)scp->sc_npc);
    123 #ifdef DDB
    124 		Debugger();
    125 #endif
    126 		return (EINVAL);
    127 	}
    128 #endif
    129 		return (EINVAL);
    130 	/* take only psr ICC field */
    131 #ifdef __arch64__
    132 	tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | (scp->sc_tstate & TSTATE_CCR);
    133 #else
    134 	tf->tf_tstate = (int64_t)(tf->tf_tstate & ~TSTATE_CCR) | PSRCC_TO_TSTATE(scp->sc_psr);
    135 #endif
    136 	tf->tf_pc = scp->sc_pc;
    137 	tf->tf_npc = scp->sc_npc;
    138 	tf->tf_global[1] = scp->sc_g1;
    139 	tf->tf_out[0] = scp->sc_o0;
    140 	tf->tf_out[6] = scp->sc_sp;
    141 #ifdef DEBUG
    142 	if (sigdebug & SDB_FOLLOW) {
    143 		printf("compat_13_sys_sigreturn: return trapframe pc=%llx sp=%llx tstate=%llx\n",
    144 			(long long)tf->tf_pc, (long long)tf->tf_out[6],
    145 			(long long)tf->tf_tstate);
    146 #ifdef DDB
    147 		if (sigdebug & SDB_DDB) Debugger();
    148 #endif
    149 	}
    150 #endif
    151 
    152 	mutex_enter(p->p_lock);
    153 	if (scp->sc_onstack & SS_ONSTACK)
    154 		l->l_sigstk.ss_flags |= SS_ONSTACK;
    155 	else
    156 		l->l_sigstk.ss_flags &= ~SS_ONSTACK;
    157 
    158 	/* Restore signal mask */
    159 	native_sigset13_to_sigset(&scp->sc_mask, &mask);
    160 	(void) sigprocmask1(l, SIG_SETMASK, &mask, 0);
    161 	mutex_exit(p->p_lock);
    162 
    163 	return (EJUSTRETURN);
    164 }
    165