1/*	$OpenBSD: sig_machdep.c,v 1.9 2023/04/16 10:14:59 kettenis 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
67#include <sys/mount.h>		/* XXX only needed by syscallargs.h */
68#include <sys/proc.h>
69#include <sys/signal.h>
70#include <sys/signalvar.h>
71#include <sys/syscallargs.h>
72#include <sys/systm.h>
73#include <sys/user.h>
74
75#include <arm64/armreg.h>
76
77#include <machine/cpu.h>
78#include <machine/frame.h>
79#include <machine/pcb.h>
80
81#include <uvm/uvm_extern.h>
82
83static __inline struct trapframe *
84process_frame(struct proc *p)
85{
86	return p->p_addr->u_pcb.pcb_tf;
87}
88
89/*
90 * Send an interrupt to process.
91 *
92 * Stack is set up to allow sigcode to call routine, followed by
93 * syscall to sigreturn routine below.  After sigreturn resets the
94 * signal mask, the stack, and the frame pointer, it returns to the
95 * user specified pc.
96 */
97int
98sendsig(sig_t catcher, int sig, sigset_t mask, const siginfo_t *ksip,
99    int info, int onstack)
100{
101	struct proc *p = curproc;
102	struct trapframe *tf;
103	struct sigframe *fp, frame;
104	siginfo_t *sip = NULL;
105	int i;
106
107	tf = process_frame(p);
108
109	/* Allocate space for the signal handler context. */
110	if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 &&
111	    !sigonstack(tf->tf_sp) && onstack)
112		fp = (struct sigframe *)
113		    trunc_page((vaddr_t)p->p_sigstk.ss_sp + p->p_sigstk.ss_size);
114	else
115		fp = (struct sigframe *)tf->tf_sp;
116
117	/* make room on the stack */
118	fp--;
119
120	/* make the stack aligned */
121	fp = (struct sigframe *)STACKALIGN(fp);
122
123	/* Build stack frame for signal trampoline. */
124	bzero(&frame, sizeof(frame));
125	frame.sf_signum = sig;
126
127	/* Save register context. */
128	for (i=0; i < 30; i++)
129		frame.sf_sc.sc_x[i] = tf->tf_x[i];
130	frame.sf_sc.sc_sp = tf->tf_sp;
131	frame.sf_sc.sc_lr = tf->tf_lr;
132	frame.sf_sc.sc_elr = tf->tf_elr;
133	frame.sf_sc.sc_spsr = tf->tf_spsr;
134
135	/* Save signal mask. */
136	frame.sf_sc.sc_mask = mask;
137
138	/* XXX Save floating point context */
139
140	if (info) {
141		sip = &fp->sf_si;
142		frame.sf_si = *ksip;
143	}
144
145	frame.sf_sc.sc_cookie = (long)&fp->sf_sc ^ p->p_p->ps_sigcookie;
146	if (copyout(&frame, fp, sizeof(frame)) != 0)
147		return 1;
148
149	/*
150	 * Build context to run handler in.  We invoke the handler
151	 * directly, only returning via the trampoline.
152         */
153	tf->tf_x[0] = sig;
154	tf->tf_x[1] = (register_t)sip;
155	tf->tf_x[2] = (register_t)&fp->sf_sc;
156	tf->tf_lr = (register_t)catcher;
157	tf->tf_sp = (register_t)fp;
158
159	tf->tf_elr = p->p_p->ps_sigcode;
160	tf->tf_spsr &= ~PSR_BTYPE;
161
162	return 0;
163}
164
165/*
166 * System call to cleanup state after a signal
167 * has been taken.  Reset signal mask and
168 * stack state from context left by sendsig (above).
169 * Return to previous pc and psl as specified by
170 * context left by sendsig. Check carefully to
171 * make sure that the user has not modified the
172 * psr to gain improper privileges or to cause
173 * a machine fault.
174 */
175
176int
177sys_sigreturn(struct proc *p, void *v, register_t *retval)
178{
179	struct sys_sigreturn_args /* {
180		syscallarg(struct sigcontext *) sigcntxp;
181	} */ *uap = v;
182	struct sigcontext ksc, *scp = SCARG(uap, sigcntxp);
183	struct trapframe *tf;
184	int i;
185
186	if (PROC_PC(p) != p->p_p->ps_sigcoderet) {
187		sigexit(p, SIGILL);
188		return (EPERM);
189	}
190
191	if (copyin(scp, &ksc, sizeof(*scp)) != 0)
192		return (EFAULT);
193
194	if (ksc.sc_cookie != ((long)scp ^ p->p_p->ps_sigcookie)) {
195		sigexit(p, SIGILL);
196		return (EFAULT);
197	}
198
199	/* Prevent reuse of the sigcontext cookie */
200	ksc.sc_cookie = 0;
201	(void)copyout(&ksc.sc_cookie, (caddr_t)scp +
202	    offsetof(struct sigcontext, sc_cookie), sizeof (ksc.sc_cookie));
203
204	/*
205	 * Make sure the processor mode has not been tampered with and
206	 * interrupts have not been disabled.
207	 */
208	if ((ksc.sc_spsr & PSR_M_MASK) != PSR_M_EL0t ||
209	    (ksc.sc_spsr & (PSR_I | PSR_F)) != 0)
210		return (EINVAL);
211
212	/* XXX Restore floating point context */
213
214	/* Restore register context. */
215	tf = process_frame(p);
216	for (i=0; i < 30; i++)
217		tf->tf_x[i] = ksc.sc_x[i];
218	tf->tf_sp = ksc.sc_sp;
219	tf->tf_lr = ksc.sc_lr;
220	tf->tf_elr = ksc.sc_elr;
221	tf->tf_spsr = ksc.sc_spsr;
222
223	/* Restore signal mask. */
224	p->p_sigmask = ksc.sc_mask & ~sigcantmask;
225
226	return (EJUSTRETURN);
227}
228