Home | History | Annotate | Line # | Download | only in arm
      1 /*	$NetBSD: compat_16_machdep.c,v 1.21 2023/03/04 08:52:19 skrll Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1994-1998 Mark Brinicombe.
      5  * Copyright (c) 1994 Brini.
      6  * All rights reserved.
      7  *
      8  * This code is derived from software written for Brini by Mark Brinicombe
      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 Mark Brinicombe
     21  *	for the NetBSD Project.
     22  * 4. The name of the company nor the name of the author may be used to
     23  *    endorse or promote products derived from this software without specific
     24  *    prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
     27  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     28  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     29  * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     30  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     31  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     32  * 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  * Machine dependent functions for kernel setup
     39  *
     40  * Created      : 17/09/94
     41  */
     42 
     43 
     44 #include <sys/cdefs.h>
     45 __KERNEL_RCSID(0, "$NetBSD: compat_16_machdep.c,v 1.21 2023/03/04 08:52:19 skrll Exp $");
     46 
     47 #ifdef _KERNEL_OPT
     48 #include "opt_compat_netbsd.h"
     49 #include "opt_armfpe.h"
     50 #endif
     51 
     52 #include <sys/param.h>
     53 #include <sys/mount.h>		/* XXX only needed by syscallargs.h */
     54 #include <sys/proc.h>
     55 #include <sys/signal.h>
     56 #include <sys/syscallargs.h>
     57 #include <sys/systm.h>
     58 #include <sys/ras.h>
     59 #include <sys/ucontext.h>
     60 
     61 #include <arm/armreg.h>
     62 #include <arm/locore.h>
     63 
     64 #include <machine/cpu.h>
     65 #include <machine/frame.h>
     66 #include <arm/cpufunc.h>
     67 
     68 /*
     69  * Send an interrupt to process.
     70  *
     71  * Stack is set up to allow sigcode stored
     72  * in u. to call routine, followed by kcall
     73  * to sigreturn routine below.  After sigreturn
     74  * resets the signal mask, the stack, and the
     75  * frame pointer, it returns to the user specified pc.
     76  */
     77 #if defined(COMPAT_16) || defined(COMPAT_13)
     78 
     79 #include <compat/sys/signal.h>
     80 #include <compat/sys/signalvar.h>
     81 
     82 void
     83 sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask)
     84 {
     85 	struct lwp * const l = curlwp;
     86 	struct proc * const p = l->l_proc;
     87 	struct sigacts * const ps = p->p_sigacts;
     88 	struct trapframe * const tf = lwp_trapframe(l);
     89 	struct sigframe_sigcontext *fp, frame;
     90 	int onstack, error;
     91 	int sig = ksi->ksi_signo;
     92 	u_long code = KSI_TRAPCODE(ksi);
     93 	sig_t catcher = SIGACTION(p, sig).sa_handler;
     94 
     95 	fp = getframe(l, sig, &onstack);
     96 
     97 	/* make room on the stack */
     98 	fp--;
     99 
    100 	/* make the stack aligned */
    101 	fp = (void *)STACK_ALIGN(fp, STACK_ALIGNBYTES);
    102 
    103 	/* Save register context. */
    104 	frame.sf_sc.sc_r0     = tf->tf_r0;
    105 	frame.sf_sc.sc_r1     = tf->tf_r1;
    106 	frame.sf_sc.sc_r2     = tf->tf_r2;
    107 	frame.sf_sc.sc_r3     = tf->tf_r3;
    108 	frame.sf_sc.sc_r4     = tf->tf_r4;
    109 	frame.sf_sc.sc_r5     = tf->tf_r5;
    110 	frame.sf_sc.sc_r6     = tf->tf_r6;
    111 	frame.sf_sc.sc_r7     = tf->tf_r7;
    112 	frame.sf_sc.sc_r8     = tf->tf_r8;
    113 	frame.sf_sc.sc_r9     = tf->tf_r9;
    114 	frame.sf_sc.sc_r10    = tf->tf_r10;
    115 	frame.sf_sc.sc_r11    = tf->tf_r11;
    116 	frame.sf_sc.sc_r12    = tf->tf_r12;
    117 	frame.sf_sc.sc_usr_sp = tf->tf_usr_sp;
    118 	frame.sf_sc.sc_usr_lr = tf->tf_usr_lr;
    119 	frame.sf_sc.sc_svc_lr = tf->tf_svc_lr;
    120 	frame.sf_sc.sc_pc     = tf->tf_pc;
    121 	frame.sf_sc.sc_spsr   = tf->tf_spsr;
    122 
    123 	/* Save signal stack. */
    124 	frame.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK;
    125 
    126 	/* Save signal mask. */
    127 	frame.sf_sc.sc_mask = *mask;
    128 
    129 #ifdef COMPAT_13
    130 	/*
    131 	 * XXX We always have to save an old style signal mask because
    132 	 * XXX we might be delivering a signal to a process which will
    133 	 * XXX escape from the signal in a non-standard way and invoke
    134 	 * XXX sigreturn() directly.
    135 	 */
    136 	native_sigset_to_sigset13(mask, &frame.sf_sc.__sc_mask13);
    137 #endif
    138 
    139 	sendsig_reset(l, sig);
    140 	mutex_exit(p->p_lock);
    141 	error = copyout(&frame, fp, sizeof(frame));
    142 	mutex_enter(p->p_lock);
    143 
    144 	if (error != 0) {
    145 		/*
    146 		 * Process has trashed its stack; give it an illegal
    147 		 * instruction to halt it in its tracks.
    148 		 */
    149 		sigexit(l, SIGILL);
    150 		/* NOTREACHED */
    151 	}
    152 
    153 	/*
    154 	 * Build context to run handler in.  We invoke the handler
    155 	 * directly, only returning via the trampoline.  Note the
    156 	 * trampoline version numbers are coordinated with machine-
    157 	 * dependent code in libc.
    158 	 */
    159 
    160 	/*
    161 	 * this was all in the switch below, seemed daft to duplicate it, if
    162 	 * we do a new trampoline version it might change then
    163 	 */
    164 	tf->tf_r0 = sig;
    165 	tf->tf_r1 = code;
    166 	tf->tf_r2 = (int)&fp->sf_sc;
    167 	tf->tf_pc = (int)catcher;
    168 #ifdef THUMB_CODE
    169 	if (((int) catcher) & 1)
    170 		tf->tf_spsr |= PSR_T_bit;
    171 	else
    172 		tf->tf_spsr &= ~PSR_T_bit;
    173 #endif
    174 	tf->tf_usr_sp = (int)fp;
    175 
    176 	switch (ps->sa_sigdesc[sig].sd_vers) {
    177 	case __SIGTRAMP_SIGCODE_VERSION:	/* legacy on-stack sigtramp */
    178 		tf->tf_usr_lr = (int)p->p_sigctx.ps_sigcode;
    179 		/* XXX This should not be needed. */
    180 		cpu_icache_sync_all();
    181 		break;
    182 	case __SIGTRAMP_SIGCONTEXT_VERSION:
    183 		tf->tf_usr_lr = (int)ps->sa_sigdesc[sig].sd_tramp;
    184 		break;
    185 
    186 	default:
    187 		/* Don't know what trampoline version; kill it. */
    188 		sigexit(l, SIGILL);
    189 	}
    190 
    191 	/* Remember that we're now on the signal stack. */
    192 	if (onstack)
    193 		l->l_sigstk.ss_flags |= SS_ONSTACK;
    194 }
    195 
    196 /*
    197  * System call to cleanup state after a signal
    198  * has been taken.  Reset signal mask and
    199  * stack state from context left by sendsig (above).
    200  * Return to previous pc and psl as specified by
    201  * context left by sendsig. Check carefully to
    202  * make sure that the user has not modified the
    203  * psr to gain improper privileges or to cause
    204  * a machine fault.
    205  */
    206 
    207 int
    208 compat_16_sys___sigreturn14(struct lwp *l, const struct compat_16_sys___sigreturn14_args *uap, register_t *retval)
    209 {
    210 	/* {
    211 		syscallarg(struct sigcontext *) sigcntxp;
    212 	} */
    213 	struct trapframe * const tf = lwp_trapframe(l);
    214 	struct proc * const p = l->l_proc;
    215 	struct sigcontext *scp, context;
    216 
    217 	/*
    218 	 * we do a rather scary test in userland
    219 	 */
    220 	if (uap == NULL)
    221 		return (EFAULT);
    222 
    223 	/*
    224 	 * The trampoline code hands us the context.
    225 	 * It is unsafe to keep track of it ourselves, in the event that a
    226 	 * program jumps out of a signal handler.
    227 	 */
    228 	scp = SCARG(uap, sigcntxp);
    229 	if (copyin((void *)scp, &context, sizeof(*scp)) != 0)
    230 		return (EFAULT);
    231 
    232 	/*
    233 	 * Make sure the processor mode has not been tampered with and
    234 	 * interrupts have not been disabled.
    235 	 */
    236 	if (!VALID_PSR(context.sc_spsr))
    237 		return EINVAL;
    238 
    239 	/* Restore register context. */
    240 	tf->tf_r0    = context.sc_r0;
    241 	tf->tf_r1    = context.sc_r1;
    242 	tf->tf_r2    = context.sc_r2;
    243 	tf->tf_r3    = context.sc_r3;
    244 	tf->tf_r4    = context.sc_r4;
    245 	tf->tf_r5    = context.sc_r5;
    246 	tf->tf_r6    = context.sc_r6;
    247 	tf->tf_r7    = context.sc_r7;
    248 	tf->tf_r8    = context.sc_r8;
    249 	tf->tf_r9    = context.sc_r9;
    250 	tf->tf_r10   = context.sc_r10;
    251 	tf->tf_r11   = context.sc_r11;
    252 	tf->tf_r12   = context.sc_r12;
    253 	tf->tf_usr_sp = context.sc_usr_sp;
    254 	tf->tf_usr_lr = context.sc_usr_lr;
    255 	tf->tf_svc_lr = context.sc_svc_lr;
    256 	tf->tf_pc    = context.sc_pc;
    257 	tf->tf_spsr  = context.sc_spsr;
    258 
    259 	mutex_enter(p->p_lock);
    260 
    261 	/* Restore signal stack. */
    262 	if (context.sc_onstack & SS_ONSTACK)
    263 		l->l_sigstk.ss_flags |= SS_ONSTACK;
    264 	else
    265 		l->l_sigstk.ss_flags &= ~SS_ONSTACK;
    266 
    267 	/* Restore signal mask. */
    268 	(void) sigprocmask1(l, SIG_SETMASK, &context.sc_mask, 0);
    269 
    270 	mutex_exit(p->p_lock);
    271 
    272 	return (EJUSTRETURN);
    273 }
    274 #endif
    275