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 */
82struct 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 */
94int
95sendsig(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 */
176int
177sys_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
228void
229signotify(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