1 1.5 riastrad /* $NetBSD: freebsd_machdep.c,v 1.5 2021/09/07 11:43:03 riastradh Exp $ */ 2 1.1 maxv 3 1.1 maxv /*- 4 1.1 maxv * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. 5 1.1 maxv * All rights reserved. 6 1.1 maxv * 7 1.1 maxv * This code is derived from software contributed to The NetBSD Foundation 8 1.1 maxv * by Charles M. Hannum. 9 1.1 maxv * 10 1.1 maxv * Redistribution and use in source and binary forms, with or without 11 1.1 maxv * modification, are permitted provided that the following conditions 12 1.1 maxv * are met: 13 1.1 maxv * 1. Redistributions of source code must retain the above copyright 14 1.1 maxv * notice, this list of conditions and the following disclaimer. 15 1.1 maxv * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 maxv * notice, this list of conditions and the following disclaimer in the 17 1.1 maxv * documentation and/or other materials provided with the distribution. 18 1.1 maxv * 19 1.1 maxv * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 maxv * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 maxv * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 maxv * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 maxv * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 maxv * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 maxv * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 maxv * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 maxv * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 maxv * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 maxv * POSSIBILITY OF SUCH DAMAGE. 30 1.1 maxv */ 31 1.1 maxv 32 1.1 maxv #include <sys/cdefs.h> 33 1.5 riastrad __KERNEL_RCSID(0, "$NetBSD: freebsd_machdep.c,v 1.5 2021/09/07 11:43:03 riastradh Exp $"); 34 1.1 maxv 35 1.1 maxv #include <sys/param.h> 36 1.1 maxv #include <sys/systm.h> 37 1.1 maxv #include <sys/signalvar.h> 38 1.1 maxv #include <sys/proc.h> 39 1.1 maxv #include <sys/exec.h> 40 1.1 maxv #include <sys/mount.h> 41 1.1 maxv 42 1.1 maxv #include <compat/sys/signal.h> 43 1.1 maxv 44 1.1 maxv #include <machine/cpufunc.h> 45 1.1 maxv #include <x86/fpu.h> 46 1.1 maxv #include <machine/reg.h> 47 1.1 maxv #include <machine/vmparam.h> 48 1.2 maxv #include <compat/freebsd/freebsd_machdep.h> 49 1.1 maxv 50 1.1 maxv 51 1.1 maxv #include <compat/freebsd/freebsd_syscallargs.h> 52 1.1 maxv #include <compat/freebsd/freebsd_exec.h> 53 1.1 maxv #include <compat/freebsd/freebsd_signal.h> 54 1.1 maxv 55 1.1 maxv void 56 1.1 maxv freebsd_setregs(struct lwp *l, struct exec_package *epp, vaddr_t stack) 57 1.1 maxv { 58 1.1 maxv 59 1.1 maxv setregs(l, epp, stack); 60 1.1 maxv fpu_set_default_cw(l, __FreeBSD_NPXCW__); 61 1.1 maxv } 62 1.1 maxv 63 1.1 maxv /* 64 1.1 maxv * signal support 65 1.1 maxv */ 66 1.1 maxv 67 1.1 maxv /* 68 1.1 maxv * Send an interrupt to process. 69 1.1 maxv * 70 1.1 maxv * Stack is set up to allow sigcode stored 71 1.1 maxv * in u. to call routine, followed by kcall 72 1.1 maxv * to sigreturn routine below. After sigreturn 73 1.1 maxv * resets the signal mask, the stack, and the 74 1.1 maxv * frame pointer, it returns to the user 75 1.1 maxv * specified pc, psl. 76 1.1 maxv */ 77 1.1 maxv void 78 1.1 maxv freebsd_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) 79 1.1 maxv { 80 1.1 maxv int sig = ksi->ksi_signo; 81 1.1 maxv u_long code = KSI_TRAPCODE(ksi); 82 1.1 maxv struct lwp *l = curlwp; 83 1.1 maxv struct proc *p = l->l_proc; 84 1.1 maxv int onstack, error; 85 1.1 maxv struct freebsd_sigframe *fp = getframe(l, sig, &onstack), frame; 86 1.1 maxv sig_t catcher = SIGACTION(p, sig).sa_handler; 87 1.1 maxv struct trapframe *tf = l->l_md.md_regs; 88 1.1 maxv 89 1.1 maxv fp--; 90 1.1 maxv 91 1.5 riastrad memset(&frame, 0, sizeof(frame)); 92 1.5 riastrad 93 1.1 maxv /* Build stack frame for signal trampoline. */ 94 1.1 maxv frame.sf_signum = sig; 95 1.1 maxv frame.sf_code = code; 96 1.1 maxv frame.sf_scp = &fp->sf_sc; 97 1.1 maxv frame.sf_addr = (char *)rcr2(); 98 1.1 maxv frame.sf_handler = catcher; 99 1.1 maxv 100 1.1 maxv /* Save context. */ 101 1.3 maxv frame.sf_sc.sc_gs = tf->tf_gs; 102 1.3 maxv frame.sf_sc.sc_fs = tf->tf_fs; 103 1.3 maxv frame.sf_sc.sc_es = tf->tf_es; 104 1.3 maxv frame.sf_sc.sc_ds = tf->tf_ds; 105 1.3 maxv frame.sf_sc.sc_efl = tf->tf_eflags; 106 1.3 maxv 107 1.1 maxv frame.sf_sc.sc_edi = tf->tf_edi; 108 1.1 maxv frame.sf_sc.sc_esi = tf->tf_esi; 109 1.1 maxv frame.sf_sc.sc_ebp = tf->tf_ebp; 110 1.1 maxv frame.sf_sc.sc_isp = 0; /* don't have to pass kernel sp to user. */ 111 1.1 maxv frame.sf_sc.sc_ebx = tf->tf_ebx; 112 1.1 maxv frame.sf_sc.sc_edx = tf->tf_edx; 113 1.1 maxv frame.sf_sc.sc_ecx = tf->tf_ecx; 114 1.1 maxv frame.sf_sc.sc_eax = tf->tf_eax; 115 1.1 maxv frame.sf_sc.sc_eip = tf->tf_eip; 116 1.1 maxv frame.sf_sc.sc_cs = tf->tf_cs; 117 1.1 maxv frame.sf_sc.sc_esp = tf->tf_esp; 118 1.1 maxv frame.sf_sc.sc_ss = tf->tf_ss; 119 1.1 maxv 120 1.1 maxv /* Save signal stack. */ 121 1.1 maxv frame.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK; 122 1.1 maxv 123 1.1 maxv /* Save signal mask. */ 124 1.1 maxv /* XXX freebsd_osigcontext compat? */ 125 1.1 maxv frame.sf_sc.sc_mask = *mask; 126 1.1 maxv 127 1.1 maxv sendsig_reset(l, sig); 128 1.1 maxv 129 1.1 maxv mutex_exit(p->p_lock); 130 1.1 maxv error = copyout(&frame, fp, sizeof(frame)); 131 1.1 maxv mutex_enter(p->p_lock); 132 1.1 maxv 133 1.1 maxv if (error != 0) { 134 1.1 maxv /* 135 1.1 maxv * Process has trashed its stack; give it an illegal 136 1.1 maxv * instruction to halt it in its tracks. 137 1.1 maxv */ 138 1.1 maxv sigexit(l, SIGILL); 139 1.1 maxv /* NOTREACHED */ 140 1.1 maxv } 141 1.1 maxv 142 1.1 maxv buildcontext(l, GUCODEBIG_SEL, p->p_sigctx.ps_sigcode, fp); 143 1.1 maxv 144 1.1 maxv /* Remember that we're now on the signal stack. */ 145 1.1 maxv if (onstack) 146 1.1 maxv l->l_sigstk.ss_flags |= SS_ONSTACK; 147 1.1 maxv } 148 1.1 maxv 149 1.1 maxv /* 150 1.1 maxv * System call to cleanup state after a signal 151 1.1 maxv * has been taken. Reset signal mask and 152 1.1 maxv * stack state from context left by sendsig (above). 153 1.1 maxv * Return to previous pc and psl as specified by 154 1.1 maxv * context left by sendsig. Check carefully to 155 1.1 maxv * make sure that the user has not modified the 156 1.1 maxv * psl to gain improper privileges or to cause 157 1.1 maxv * a machine fault. 158 1.1 maxv */ 159 1.1 maxv int 160 1.1 maxv freebsd_sys_sigreturn(struct lwp *l, const struct freebsd_sys_sigreturn_args *uap, register_t *retval) 161 1.1 maxv { 162 1.1 maxv /* { 163 1.1 maxv syscallarg(struct freebsd_sigcontext *) scp; 164 1.1 maxv } */ 165 1.1 maxv struct proc *p = l->l_proc; 166 1.1 maxv struct freebsd_sigcontext *scp, context; 167 1.1 maxv struct trapframe *tf; 168 1.1 maxv sigset_t mask; 169 1.1 maxv 170 1.1 maxv /* 171 1.1 maxv * The trampoline code hands us the context. 172 1.1 maxv * It is unsafe to keep track of it ourselves, in the event that a 173 1.1 maxv * program jumps out of a signal handler. 174 1.1 maxv */ 175 1.1 maxv scp = SCARG(uap, scp); 176 1.1 maxv if (copyin((void *)scp, &context, sizeof(*scp)) != 0) 177 1.1 maxv return (EFAULT); 178 1.1 maxv 179 1.1 maxv /* Restore register context. */ 180 1.1 maxv tf = l->l_md.md_regs; 181 1.3 maxv 182 1.3 maxv /* 183 1.3 maxv * Check for security violations. If we're returning to 184 1.3 maxv * protected mode, the CPU will validate the segment registers 185 1.3 maxv * automatically and generate a trap on violations. We handle 186 1.3 maxv * the trap, rather than doing all of the checking here. 187 1.3 maxv */ 188 1.3 maxv if (((context.sc_efl ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 || 189 1.4 maxv !USERMODE(context.sc_cs)) 190 1.3 maxv return (EINVAL); 191 1.3 maxv 192 1.3 maxv tf->tf_gs = context.sc_gs; 193 1.3 maxv tf->tf_fs = context.sc_fs; 194 1.3 maxv tf->tf_es = context.sc_es; 195 1.3 maxv tf->tf_ds = context.sc_ds; 196 1.3 maxv tf->tf_eflags &= ~PSL_USER; 197 1.3 maxv tf->tf_eflags |= context.sc_efl & PSL_USER; 198 1.3 maxv 199 1.1 maxv tf->tf_edi = context.sc_edi; 200 1.1 maxv tf->tf_esi = context.sc_esi; 201 1.1 maxv tf->tf_ebp = context.sc_ebp; 202 1.1 maxv /* FreeBSD's context.sc_isp is useless. (`popal' ignores it.) */ 203 1.1 maxv tf->tf_ebx = context.sc_ebx; 204 1.1 maxv tf->tf_edx = context.sc_edx; 205 1.1 maxv tf->tf_ecx = context.sc_ecx; 206 1.1 maxv tf->tf_eax = context.sc_eax; 207 1.1 maxv tf->tf_eip = context.sc_eip; 208 1.1 maxv tf->tf_cs = context.sc_cs; 209 1.1 maxv tf->tf_esp = context.sc_esp; 210 1.1 maxv tf->tf_ss = context.sc_ss; 211 1.1 maxv 212 1.1 maxv mutex_enter(p->p_lock); 213 1.1 maxv /* Restore signal stack. */ 214 1.1 maxv if (context.sc_onstack & SS_ONSTACK) 215 1.1 maxv l->l_sigstk.ss_flags |= SS_ONSTACK; 216 1.1 maxv else 217 1.1 maxv l->l_sigstk.ss_flags &= ~SS_ONSTACK; 218 1.1 maxv /* Restore signal mask. */ 219 1.1 maxv /* XXX freebsd_osigcontext compat? */ 220 1.1 maxv mask = context.sc_mask; 221 1.1 maxv (void) sigprocmask1(l, SIG_SETMASK, &mask, 0); 222 1.1 maxv mutex_exit(p->p_lock); 223 1.1 maxv 224 1.1 maxv return (EJUSTRETURN); 225 1.1 maxv } 226