xref: /openbsd-src/sys/arch/mips64/mips64/sendsig.c (revision 5b133f3f277e80f096764111e64f3a1284acb179)
1 /*	$OpenBSD: sendsig.c,v 1.36 2023/03/08 04:43:07 guenther Exp $ */
2 
3 /*
4  * Copyright (c) 1990 The Regents of the University of California.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * William Jolitz and Don Ahn.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *      This product includes software developed by the University of
21  *      California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  */
39 /*
40  * Copyright (c) 2001 Opsycon AB  (www.opsycon.se)
41  *
42  * Redistribution and use in source and binary forms, with or without
43  * modification, are permitted provided that the following conditions
44  * are met:
45  * 1. Redistributions of source code must retain the above copyright
46  *    notice, this list of conditions and the following disclaimer.
47  * 2. Redistributions in binary form must reproduce the above copyright
48  *    notice, this list of conditions and the following disclaimer in the
49  *    documentation and/or other materials provided with the distribution.
50  *
51  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
52  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
53  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
55  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61  * SUCH DAMAGE.
62  *
63  */
64 
65 #include <sys/param.h>
66 #include <sys/systm.h>
67 #include <sys/signalvar.h>
68 #include <sys/proc.h>
69 #include <sys/exec.h>
70 #include <sys/mount.h>
71 #include <sys/syscallargs.h>
72 
73 #include <uvm/uvm_extern.h>
74 
75 #include <machine/regnum.h>
76 #include <mips64/mips_cpu.h>
77 
78 /*
79  * WARNING: code in locore.s assumes the layout shown for sf_signum
80  * thru sf_handler so... don't screw with them!
81  */
82 struct sigframe {
83 	int	sf_signum;		/* signo for handler */
84 	siginfo_t *sf_sip;		/* pointer to siginfo_t */
85 	struct	sigcontext *sf_scp;	/* context ptr for handler */
86 	sig_t	sf_handler;		/* handler addr for u_sigc */
87 	struct	sigcontext sf_sc;	/* actual context */
88 	siginfo_t sf_si;
89 };
90 
91 /*
92  * Send an interrupt to process.
93  */
94 int
sendsig(sig_t catcher,int sig,sigset_t mask,const siginfo_t * ksip,int info,int onstack)95 sendsig(sig_t catcher, int sig, sigset_t mask, const siginfo_t *ksip,
96     int info, int onstack)
97 {
98 	struct cpu_info *ci = curcpu();
99 	struct proc *p = ci->ci_curproc;
100 	struct sigframe *fp;
101 	struct trapframe *regs;
102 	int fsize;
103 	struct sigcontext ksc;
104 
105 	regs = p->p_md.md_regs;
106 
107 	/*
108 	 * Allocate space for the signal handler context.
109 	 */
110 	fsize = sizeof(struct sigframe);
111 	if (!info)
112 		fsize -= sizeof(siginfo_t);
113 	if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 &&
114 	    !sigonstack(regs->sp) && onstack)
115 		fp = (struct sigframe *)
116 		    (trunc_page((vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size)
117 		    - fsize);
118 	else
119 		fp = (struct sigframe *)(regs->sp - fsize);
120 	/*
121 	 * Build the signal context to be used by sigreturn.
122 	 */
123 	bzero(&ksc, sizeof(ksc));
124 	ksc.sc_mask = mask;
125 	ksc.sc_pc = regs->pc;
126 	ksc.mullo = regs->mullo;
127 	ksc.mulhi = regs->mulhi;
128 	bcopy((caddr_t)&regs->ast, (caddr_t)&ksc.sc_regs[1],
129 		sizeof(ksc.sc_regs) - sizeof(register_t));
130 	ksc.sc_fpused = p->p_md.md_flags & MDP_FPUSED;
131 	if (ksc.sc_fpused) {
132 		/* if FPU has current state, save it first */
133 		if (p == ci->ci_fpuproc)
134 			save_fpu();
135 
136 		bcopy((caddr_t)&p->p_md.md_regs->f0, (caddr_t)ksc.sc_fpregs,
137 			sizeof(ksc.sc_fpregs));
138 	}
139 
140 	if (info) {
141 		if (copyout(ksip, (caddr_t)&fp->sf_si, sizeof *ksip))
142 			return 1;
143 	}
144 
145 	ksc.sc_cookie = (long)&fp->sf_sc ^ p->p_p->ps_sigcookie;
146 	if (copyout((caddr_t)&ksc, (caddr_t)&fp->sf_sc, sizeof(ksc)))
147 		return 1;
148 
149 	/*
150 	 * Build the argument list for the signal handler.
151 	 */
152 	regs->a0 = sig;
153 	regs->a1 = info ? (register_t)&fp->sf_si : 0;
154 	regs->a2 = (register_t)&fp->sf_sc;
155 	regs->a3 = (register_t)catcher;
156 
157 	regs->pc = (register_t)catcher;
158 	regs->t9 = (register_t)catcher;
159 	regs->sp = (register_t)fp;
160 
161 	regs->ra = p->p_p->ps_sigcode;
162 
163 	return 0;
164 }
165 
166 /*
167  * System call to cleanup state after a signal
168  * has been taken.  Reset signal mask and
169  * stack state from context left by sendsig (above).
170  * Return to previous pc and psl as specified by
171  * context left by sendsig. Check carefully to
172  * make sure that the user has not modified the
173  * psl to gain improper privileges or to cause
174  * a machine fault.
175  */
176 int
sys_sigreturn(struct proc * p,void * v,register_t * retval)177 sys_sigreturn(struct proc *p, void *v, register_t *retval)
178 {
179 	struct cpu_info *ci = curcpu();
180 	struct sys_sigreturn_args /* {
181 		syscallarg(struct sigcontext *) sigcntxp;
182 	} */ *uap = v;
183 	struct sigcontext ksc, *scp = SCARG(uap, sigcntxp);
184 	struct trapframe *regs = p->p_md.md_regs;
185 	int error;
186 
187 	if (PROC_PC(p) != p->p_p->ps_sigcoderet) {
188 		sigexit(p, SIGILL);
189 		return (EPERM);
190 	}
191 
192 	/*
193 	 * Test and fetch the context structure.
194 	 * We grab it all at once for speed.
195 	 */
196 	error = copyin((caddr_t)scp, (caddr_t)&ksc, sizeof(ksc));
197 	if (error)
198 		return (error);
199 
200 	if (ksc.sc_cookie != ((long)scp ^ p->p_p->ps_sigcookie)) {
201 		sigexit(p, SIGILL);
202 		return (EFAULT);
203 	}
204 
205 	/* Prevent reuse of the sigcontext cookie */
206 	ksc.sc_cookie = 0;
207 	(void)copyout(&ksc.sc_cookie, (caddr_t)scp +
208 	    offsetof(struct sigcontext, sc_cookie), sizeof (ksc.sc_cookie));
209 
210 	/*
211 	 * Restore the user supplied information
212 	 */
213 	p->p_sigmask = ksc.sc_mask &~ sigcantmask;
214 	regs->pc = ksc.sc_pc;
215 	regs->mullo = ksc.mullo;
216 	regs->mulhi = ksc.mulhi;
217 	regs->sr &= ~SR_COP_1_BIT;	/* Zap current FP state */
218 	if (p == ci->ci_fpuproc)
219 		ci->ci_fpuproc = NULL;
220 	bcopy((caddr_t)&ksc.sc_regs[1], (caddr_t)&regs->ast,
221 		sizeof(ksc.sc_regs) - sizeof(register_t));
222 	if (ksc.sc_fpused)
223 		bcopy((caddr_t)ksc.sc_fpregs, (caddr_t)&p->p_md.md_regs->f0,
224 			sizeof(ksc.sc_fpregs));
225 	return (EJUSTRETURN);
226 }
227 
228 void
signotify(struct proc * p)229 signotify(struct proc *p)
230 {
231 	/*
232 	 * Ensure that preceding stores are visible to other CPUs
233 	 * before setting the AST flag.
234 	 */
235 	membar_producer();
236 
237 	aston(p);
238 	cpu_unidle(p->p_cpu);
239 }
240