1 /*	$NetBSD: compat_13_machdep.c,v 1.23 2009/11/21 04:16:52 rmind 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.23 2009/11/21 04:16:52 rmind 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;
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