compat_16_machdep.c revision 1.1
11.1Sfvdl/*	$NetBSD: compat_16_machdep.c,v 1.1 2003/10/06 22:53:47 fvdl Exp $	*/
21.1Sfvdl
31.1Sfvdl/*-
41.1Sfvdl * Copyright (c) 1996, 1997, 1998, 2000 The NetBSD Foundation, Inc.
51.1Sfvdl * All rights reserved.
61.1Sfvdl *
71.1Sfvdl * This code is derived from software contributed to The NetBSD Foundation
81.1Sfvdl * by Charles M. Hannum.
91.1Sfvdl *
101.1Sfvdl * Redistribution and use in source and binary forms, with or without
111.1Sfvdl * modification, are permitted provided that the following conditions
121.1Sfvdl * are met:
131.1Sfvdl * 1. Redistributions of source code must retain the above copyright
141.1Sfvdl *    notice, this list of conditions and the following disclaimer.
151.1Sfvdl * 2. Redistributions in binary form must reproduce the above copyright
161.1Sfvdl *    notice, this list of conditions and the following disclaimer in the
171.1Sfvdl *    documentation and/or other materials provided with the distribution.
181.1Sfvdl * 3. All advertising materials mentioning features or use of this software
191.1Sfvdl *    must display the following acknowledgement:
201.1Sfvdl *	This product includes software developed by the NetBSD
211.1Sfvdl *	Foundation, Inc. and its contributors.
221.1Sfvdl * 4. Neither the name of The NetBSD Foundation nor the names of its
231.1Sfvdl *    contributors may be used to endorse or promote products derived
241.1Sfvdl *    from this software without specific prior written permission.
251.1Sfvdl *
261.1Sfvdl * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
271.1Sfvdl * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
281.1Sfvdl * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
291.1Sfvdl * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
301.1Sfvdl * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
311.1Sfvdl * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
321.1Sfvdl * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
331.1Sfvdl * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
341.1Sfvdl * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
351.1Sfvdl * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
361.1Sfvdl * POSSIBILITY OF SUCH DAMAGE.
371.1Sfvdl */
381.1Sfvdl
391.1Sfvdl#include <sys/cdefs.h>
401.1Sfvdl__KERNEL_RCSID(0, "$NetBSD: compat_16_machdep.c,v 1.1 2003/10/06 22:53:47 fvdl Exp $");
411.1Sfvdl
421.1Sfvdl#include "opt_vm86.h"
431.1Sfvdl#include "opt_compat_netbsd.h"
441.1Sfvdl#include "opt_compat_ibcs2.h"
451.1Sfvdl
461.1Sfvdl#include <sys/param.h>
471.1Sfvdl#include <sys/systm.h>
481.1Sfvdl#include <sys/signal.h>
491.1Sfvdl#include <sys/signalvar.h>
501.1Sfvdl#include <sys/kernel.h>
511.1Sfvdl#include <sys/proc.h>
521.1Sfvdl#include <sys/user.h>
531.1Sfvdl#include <sys/mount.h>
541.1Sfvdl#include <sys/sa.h>
551.1Sfvdl#include <sys/syscallargs.h>
561.1Sfvdl
571.1Sfvdl#include <uvm/uvm_extern.h>
581.1Sfvdl#include <uvm/uvm_page.h>
591.1Sfvdl
601.1Sfvdl#include <machine/pmap.h>
611.1Sfvdl#include <machine/vmparam.h>
621.1Sfvdl
631.1Sfvdl/*
641.1Sfvdl * System call to cleanup state after a signal
651.1Sfvdl * has been taken.  Reset signal mask and
661.1Sfvdl * stack state from context left by sendsig (above).
671.1Sfvdl * Return to previous pc and psl as specified by
681.1Sfvdl * context left by sendsig. Check carefully to
691.1Sfvdl * make sure that the user has not modified the
701.1Sfvdl * psl to gain improper privileges or to cause
711.1Sfvdl * a machine fault.
721.1Sfvdl */
731.1Sfvdl
741.1Sfvdlint compat_16_sys___sigreturn14(struct lwp *, void *, register_t *);
751.1Sfvdl
761.1Sfvdlint
771.1Sfvdlcompat_16_sys___sigreturn14(l, v, retval)
781.1Sfvdl	struct lwp *l;
791.1Sfvdl	void *v;
801.1Sfvdl	register_t *retval;
811.1Sfvdl{
821.1Sfvdl	struct compat_16_sys___sigreturn14_args /* {
831.1Sfvdl		syscallarg(struct sigcontext *) sigcntxp;
841.1Sfvdl	} */ *uap = v;
851.1Sfvdl	struct proc *p = l->l_proc;
861.1Sfvdl	struct sigcontext *scp, context;
871.1Sfvdl	struct trapframe *tf;
881.1Sfvdl	uint64_t rflags;
891.1Sfvdl
901.1Sfvdl	/*
911.1Sfvdl	 * The trampoline code hands us the context.
921.1Sfvdl	 * It is unsafe to keep track of it ourselves, in the event that a
931.1Sfvdl	 * program jumps out of a signal handler.
941.1Sfvdl	 */
951.1Sfvdl	scp = SCARG(uap, sigcntxp);
961.1Sfvdl	if (copyin((caddr_t)scp, &context,
971.1Sfvdl	    sizeof(struct sigcontext) - sizeof(struct fxsave64)) != 0)
981.1Sfvdl		return EFAULT;
991.1Sfvdl
1001.1Sfvdl	/* Restore register context. */
1011.1Sfvdl	tf = l->l_md.md_regs;
1021.1Sfvdl	/*
1031.1Sfvdl	 * Check for security violations.  If we're returning to
1041.1Sfvdl	 * protected mode, the CPU will validate the segment registers
1051.1Sfvdl	 * automatically and generate a trap on violations.  We handle
1061.1Sfvdl	 * the trap, rather than doing all of the checking here.
1071.1Sfvdl	 */
1081.1Sfvdl	rflags = context.sc_mcontext.__gregs[_REG_RFL];
1091.1Sfvdl	if (((rflags ^ tf->tf_rflags) & PSL_USERSTATIC) != 0 ||
1101.1Sfvdl	    !USERMODE(context.sc_mcontext.__gregs[_REG_CS], rflags))
1111.1Sfvdl		return EINVAL;
1121.1Sfvdl
1131.1Sfvdl	memcpy(tf, &context.sc_mcontext.__gregs, sizeof (*tf));
1141.1Sfvdl
1151.1Sfvdl	/* Restore (possibly fixed up) FP state and force it to be reloaded */
1161.1Sfvdl	if (l->l_md.md_flags & MDP_USEDFPU) {
1171.1Sfvdl		fpusave_lwp(l, 0);
1181.1Sfvdl		if (context.sc_fpstate != NULL && copyin(context.sc_fpstate,
1191.1Sfvdl		    &l->l_addr->u_pcb.pcb_savefpu.fp_fxsave,
1201.1Sfvdl		    sizeof (struct fxsave64)) != 0)
1211.1Sfvdl			return EFAULT;
1221.1Sfvdl	}
1231.1Sfvdl
1241.1Sfvdl	/* Restore signal stack. */
1251.1Sfvdl	if (context.sc_onstack & SS_ONSTACK)
1261.1Sfvdl		p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;
1271.1Sfvdl	else
1281.1Sfvdl		p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK;
1291.1Sfvdl
1301.1Sfvdl	/* Restore signal mask. */
1311.1Sfvdl	(void) sigprocmask1(p, SIG_SETMASK, &context.sc_mask, 0);
1321.1Sfvdl
1331.1Sfvdl	return EJUSTRETURN;
1341.1Sfvdl}
1351.1Sfvdl
1361.1Sfvdl/*
1371.1Sfvdl * Send an interrupt to process.
1381.1Sfvdl *
1391.1Sfvdl * Stack is set up to allow sigcode stored
1401.1Sfvdl * in u. to call routine, followed by kcall
1411.1Sfvdl * to sigreturn routine below.  After sigreturn
1421.1Sfvdl * resets the signal mask, the stack, and the
1431.1Sfvdl * frame pointer, it returns to the user
1441.1Sfvdl * specified pc, psl.
1451.1Sfvdl */
1461.1Sfvdlvoid
1471.1Sfvdlsendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask)
1481.1Sfvdl{
1491.1Sfvdl	struct lwp *l = curlwp;
1501.1Sfvdl	struct proc *p = l->l_proc;
1511.1Sfvdl	struct sigacts *ps = p->p_sigacts;
1521.1Sfvdl	struct trapframe *tf;
1531.1Sfvdl	struct sigframe_sigcontext *fp, frame;
1541.1Sfvdl	int onstack;
1551.1Sfvdl	size_t tocopy;
1561.1Sfvdl	int sig = ksi->ksi_signo;
1571.1Sfvdl	sig_t catcher = SIGACTION(p, sig).sa_handler;
1581.1Sfvdl
1591.1Sfvdl	tf = l->l_md.md_regs;
1601.1Sfvdl
1611.1Sfvdl	fp = getframe(l, sig, &onstack);
1621.1Sfvdl	fp--;
1631.1Sfvdl
1641.1Sfvdl	if (l->l_md.md_flags & MDP_USEDFPU) {
1651.1Sfvdl		fpusave_lwp(l, 1);
1661.1Sfvdl		frame.sf_sc.sc_fpstate =
1671.1Sfvdl		    (struct fxsave64 *)&fp->sf_sc.sc_mcontext.__fpregs;
1681.1Sfvdl		memcpy(&frame.sf_sc.sc_mcontext.__fpregs,
1691.1Sfvdl		    &l->l_addr->u_pcb.pcb_savefpu.fp_fxsave,
1701.1Sfvdl		    sizeof (struct fxsave64));
1711.1Sfvdl		tocopy = sizeof (struct sigframe_sigcontext);
1721.1Sfvdl	} else {
1731.1Sfvdl		frame.sf_sc.sc_fpstate = NULL;
1741.1Sfvdl		tocopy = sizeof (struct sigframe_sigcontext) -
1751.1Sfvdl		    sizeof (fp->sf_sc.sc_mcontext.__fpregs);
1761.1Sfvdl	}
1771.1Sfvdl
1781.1Sfvdl	/* Build stack frame for signal trampoline. */
1791.1Sfvdl	switch (ps->sa_sigdesc[sig].sd_vers) {
1801.1Sfvdl	case 0:		/* legacy on-stack sigtramp */
1811.1Sfvdl		frame.sf_ra = (uint64_t) p->p_sigctx.ps_sigcode;
1821.1Sfvdl		break;
1831.1Sfvdl
1841.1Sfvdl	case 1:
1851.1Sfvdl		frame.sf_ra = (uint64_t) ps->sa_sigdesc[sig].sd_tramp;
1861.1Sfvdl		break;
1871.1Sfvdl
1881.1Sfvdl	default:
1891.1Sfvdl		printf("osendsig: bad version %d\n",
1901.1Sfvdl		    ps->sa_sigdesc[sig].sd_vers);
1911.1Sfvdl		sigexit(l, SIGILL);
1921.1Sfvdl	}
1931.1Sfvdl
1941.1Sfvdl	/* Save register context. */
1951.1Sfvdl	memcpy(&frame.sf_sc.sc_mcontext.__gregs, tf, sizeof (*tf));
1961.1Sfvdl
1971.1Sfvdl	/* Save signal stack. */
1981.1Sfvdl	frame.sf_sc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK;
1991.1Sfvdl
2001.1Sfvdl	/* Save signal mask. */
2011.1Sfvdl	frame.sf_sc.sc_mask = *mask;
2021.1Sfvdl
2031.1Sfvdl	if (copyout(&frame, fp, tocopy) != 0) {
2041.1Sfvdl		/*
2051.1Sfvdl		 * Process has trashed its stack; give it an illegal
2061.1Sfvdl		 * instruction to halt it in its tracks.
2071.1Sfvdl		 */
2081.1Sfvdl		sigexit(l, SIGILL);
2091.1Sfvdl		/* NOTREACHED */
2101.1Sfvdl	}
2111.1Sfvdl
2121.1Sfvdl	buildcontext(l, catcher, fp);
2131.1Sfvdl
2141.1Sfvdl	tf->tf_rdi = sig;
2151.1Sfvdl	tf->tf_rsi = ksi->ksi_trap;
2161.1Sfvdl	tf->tf_rdx = (int64_t) &fp->sf_sc;
2171.1Sfvdl
2181.1Sfvdl
2191.1Sfvdl	/* Remember that we're now on the signal stack. */
2201.1Sfvdl	if (onstack)
2211.1Sfvdl		p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;
2221.1Sfvdl}
223