compat_16_machdep.c revision 1.1
1/* $NetBSD: compat_16_machdep.c,v 1.1 2003/10/06 22:53:47 fvdl Exp $ */ 2 3/*- 4 * Copyright (c) 1996, 1997, 1998, 2000 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Charles M. Hannum. 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 NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39#include <sys/cdefs.h> 40__KERNEL_RCSID(0, "$NetBSD: compat_16_machdep.c,v 1.1 2003/10/06 22:53:47 fvdl Exp $"); 41 42#include "opt_vm86.h" 43#include "opt_compat_netbsd.h" 44#include "opt_compat_ibcs2.h" 45 46#include <sys/param.h> 47#include <sys/systm.h> 48#include <sys/signal.h> 49#include <sys/signalvar.h> 50#include <sys/kernel.h> 51#include <sys/proc.h> 52#include <sys/user.h> 53#include <sys/mount.h> 54#include <sys/sa.h> 55#include <sys/syscallargs.h> 56 57#include <uvm/uvm_extern.h> 58#include <uvm/uvm_page.h> 59 60#include <machine/pmap.h> 61#include <machine/vmparam.h> 62 63/* 64 * System call to cleanup state after a signal 65 * has been taken. Reset signal mask and 66 * stack state from context left by sendsig (above). 67 * Return to previous pc and psl as specified by 68 * context left by sendsig. Check carefully to 69 * make sure that the user has not modified the 70 * psl to gain improper privileges or to cause 71 * a machine fault. 72 */ 73 74int compat_16_sys___sigreturn14(struct lwp *, void *, register_t *); 75 76int 77compat_16_sys___sigreturn14(l, v, retval) 78 struct lwp *l; 79 void *v; 80 register_t *retval; 81{ 82 struct compat_16_sys___sigreturn14_args /* { 83 syscallarg(struct sigcontext *) sigcntxp; 84 } */ *uap = v; 85 struct proc *p = l->l_proc; 86 struct sigcontext *scp, context; 87 struct trapframe *tf; 88 uint64_t rflags; 89 90 /* 91 * The trampoline code hands us the context. 92 * It is unsafe to keep track of it ourselves, in the event that a 93 * program jumps out of a signal handler. 94 */ 95 scp = SCARG(uap, sigcntxp); 96 if (copyin((caddr_t)scp, &context, 97 sizeof(struct sigcontext) - sizeof(struct fxsave64)) != 0) 98 return EFAULT; 99 100 /* Restore register context. */ 101 tf = l->l_md.md_regs; 102 /* 103 * Check for security violations. If we're returning to 104 * protected mode, the CPU will validate the segment registers 105 * automatically and generate a trap on violations. We handle 106 * the trap, rather than doing all of the checking here. 107 */ 108 rflags = context.sc_mcontext.__gregs[_REG_RFL]; 109 if (((rflags ^ tf->tf_rflags) & PSL_USERSTATIC) != 0 || 110 !USERMODE(context.sc_mcontext.__gregs[_REG_CS], rflags)) 111 return EINVAL; 112 113 memcpy(tf, &context.sc_mcontext.__gregs, sizeof (*tf)); 114 115 /* Restore (possibly fixed up) FP state and force it to be reloaded */ 116 if (l->l_md.md_flags & MDP_USEDFPU) { 117 fpusave_lwp(l, 0); 118 if (context.sc_fpstate != NULL && copyin(context.sc_fpstate, 119 &l->l_addr->u_pcb.pcb_savefpu.fp_fxsave, 120 sizeof (struct fxsave64)) != 0) 121 return EFAULT; 122 } 123 124 /* Restore signal stack. */ 125 if (context.sc_onstack & SS_ONSTACK) 126 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 127 else 128 p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK; 129 130 /* Restore signal mask. */ 131 (void) sigprocmask1(p, SIG_SETMASK, &context.sc_mask, 0); 132 133 return EJUSTRETURN; 134} 135 136/* 137 * Send an interrupt to process. 138 * 139 * Stack is set up to allow sigcode stored 140 * in u. to call routine, followed by kcall 141 * to sigreturn routine below. After sigreturn 142 * resets the signal mask, the stack, and the 143 * frame pointer, it returns to the user 144 * specified pc, psl. 145 */ 146void 147sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask) 148{ 149 struct lwp *l = curlwp; 150 struct proc *p = l->l_proc; 151 struct sigacts *ps = p->p_sigacts; 152 struct trapframe *tf; 153 struct sigframe_sigcontext *fp, frame; 154 int onstack; 155 size_t tocopy; 156 int sig = ksi->ksi_signo; 157 sig_t catcher = SIGACTION(p, sig).sa_handler; 158 159 tf = l->l_md.md_regs; 160 161 fp = getframe(l, sig, &onstack); 162 fp--; 163 164 if (l->l_md.md_flags & MDP_USEDFPU) { 165 fpusave_lwp(l, 1); 166 frame.sf_sc.sc_fpstate = 167 (struct fxsave64 *)&fp->sf_sc.sc_mcontext.__fpregs; 168 memcpy(&frame.sf_sc.sc_mcontext.__fpregs, 169 &l->l_addr->u_pcb.pcb_savefpu.fp_fxsave, 170 sizeof (struct fxsave64)); 171 tocopy = sizeof (struct sigframe_sigcontext); 172 } else { 173 frame.sf_sc.sc_fpstate = NULL; 174 tocopy = sizeof (struct sigframe_sigcontext) - 175 sizeof (fp->sf_sc.sc_mcontext.__fpregs); 176 } 177 178 /* Build stack frame for signal trampoline. */ 179 switch (ps->sa_sigdesc[sig].sd_vers) { 180 case 0: /* legacy on-stack sigtramp */ 181 frame.sf_ra = (uint64_t) p->p_sigctx.ps_sigcode; 182 break; 183 184 case 1: 185 frame.sf_ra = (uint64_t) ps->sa_sigdesc[sig].sd_tramp; 186 break; 187 188 default: 189 printf("osendsig: bad version %d\n", 190 ps->sa_sigdesc[sig].sd_vers); 191 sigexit(l, SIGILL); 192 } 193 194 /* Save register context. */ 195 memcpy(&frame.sf_sc.sc_mcontext.__gregs, tf, sizeof (*tf)); 196 197 /* Save signal stack. */ 198 frame.sf_sc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK; 199 200 /* Save signal mask. */ 201 frame.sf_sc.sc_mask = *mask; 202 203 if (copyout(&frame, fp, tocopy) != 0) { 204 /* 205 * Process has trashed its stack; give it an illegal 206 * instruction to halt it in its tracks. 207 */ 208 sigexit(l, SIGILL); 209 /* NOTREACHED */ 210 } 211 212 buildcontext(l, catcher, fp); 213 214 tf->tf_rdi = sig; 215 tf->tf_rsi = ksi->ksi_trap; 216 tf->tf_rdx = (int64_t) &fp->sf_sc; 217 218 219 /* Remember that we're now on the signal stack. */ 220 if (onstack) 221 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 222} 223