VM86 support, by John Kohl, touched up a bit by me.
This commit is contained in:
parent
269329a42b
commit
7149c5ff14
@ -1,4 +1,4 @@
|
||||
# $NetBSD: files.i386,v 1.60 1995/10/11 04:19:29 mycroft Exp $
|
||||
# $NetBSD: files.i386,v 1.61 1996/01/08 13:51:30 mycroft Exp $
|
||||
#
|
||||
# new style config file for i386 architecture
|
||||
#
|
||||
@ -126,6 +126,9 @@ file arch/i386/pci/pci_machdep.c pci
|
||||
# Compatibility modules
|
||||
#
|
||||
|
||||
# VM86 mode
|
||||
file arch/i386/i386/vm86.c vm86
|
||||
|
||||
# SVR4 binary compatibility (COMPAT_SVR4)
|
||||
include "../../../compat/svr4/files.svr4"
|
||||
file arch/i386/i386/svr4_machdep.c compat_svr4
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: machdep.c,v 1.183 1996/01/04 22:22:01 jtc Exp $ */
|
||||
/* $NetBSD: machdep.c,v 1.184 1996/01/08 13:51:34 mycroft Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1993, 1994, 1995 Charles M. Hannum. All rights reserved.
|
||||
@ -92,6 +92,10 @@
|
||||
#include <i386/isa/isa_machdep.h>
|
||||
#include <i386/isa/nvram.h>
|
||||
|
||||
#ifdef VM86
|
||||
#include <machine/vm86.h>
|
||||
#endif
|
||||
|
||||
#include "isa.h"
|
||||
#include "npx.h"
|
||||
#if NNPX > 0
|
||||
@ -537,6 +541,8 @@ sendsig(catcher, sig, mask, code)
|
||||
/*
|
||||
* Build the signal context to be used by sigreturn.
|
||||
*/
|
||||
frame.sf_sc.sc_err = tf->tf_err;
|
||||
frame.sf_sc.sc_trapno = tf->tf_trapno;
|
||||
frame.sf_sc.sc_onstack = oonstack;
|
||||
frame.sf_sc.sc_mask = mask;
|
||||
#ifdef VM86
|
||||
@ -545,6 +551,9 @@ sendsig(catcher, sig, mask, code)
|
||||
frame.sf_sc.sc_fs = tf->tf_vm86_fs;
|
||||
frame.sf_sc.sc_es = tf->tf_vm86_es;
|
||||
frame.sf_sc.sc_ds = tf->tf_vm86_ds;
|
||||
frame.sf_sc.sc_eflags = tf->tf_eflags;
|
||||
SETFLAGS(frame.sf_sc.sc_eflags, VM86_EFLAGS(p),
|
||||
VM86_FLAGMASK(p)|PSL_VIF);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@ -552,19 +561,19 @@ sendsig(catcher, sig, mask, code)
|
||||
__asm("movl %%fs,%w0" : "=r" (frame.sf_sc.sc_fs));
|
||||
frame.sf_sc.sc_es = tf->tf_es;
|
||||
frame.sf_sc.sc_ds = tf->tf_ds;
|
||||
frame.sf_sc.sc_eflags = tf->tf_eflags;
|
||||
}
|
||||
frame.sf_sc.sc_edi = tf->tf_edi;
|
||||
frame.sf_sc.sc_esi = tf->tf_esi;
|
||||
frame.sf_sc.sc_ebp = tf->tf_ebp;
|
||||
frame.sf_sc.sc_ebx = tf->tf_ebx;
|
||||
frame.sf_sc.sc_edx = tf->tf_edx;
|
||||
frame.sf_sc.sc_ecx = tf->tf_ecx;
|
||||
frame.sf_sc.sc_eax = tf->tf_eax;
|
||||
frame.sf_sc.sc_eip = tf->tf_eip;
|
||||
frame.sf_sc.sc_cs = tf->tf_cs;
|
||||
frame.sf_sc.sc_eflags = tf->tf_eflags;
|
||||
frame.sf_sc.sc_esp = tf->tf_esp;
|
||||
frame.sf_sc.sc_ss = tf->tf_ss;
|
||||
frame.sf_sc.sc_edi = tf->tf_edi;
|
||||
frame.sf_sc.sc_esi = tf->tf_esi;
|
||||
frame.sf_sc.sc_ebp = tf->tf_ebp;
|
||||
frame.sf_sc.sc_ebx = tf->tf_ebx;
|
||||
frame.sf_sc.sc_edx = tf->tf_edx;
|
||||
frame.sf_sc.sc_ecx = tf->tf_ecx;
|
||||
frame.sf_sc.sc_eax = tf->tf_eax;
|
||||
frame.sf_sc.sc_eip = tf->tf_eip;
|
||||
frame.sf_sc.sc_cs = tf->tf_cs;
|
||||
frame.sf_sc.sc_esp = tf->tf_esp;
|
||||
frame.sf_sc.sc_ss = tf->tf_ss;
|
||||
|
||||
if (copyout(&frame, fp, sizeof(frame)) != 0) {
|
||||
/*
|
||||
@ -646,25 +655,28 @@ sys_sigreturn(p, v, retval)
|
||||
tf->tf_vm86_fs = context.sc_fs;
|
||||
tf->tf_vm86_es = context.sc_es;
|
||||
tf->tf_vm86_ds = context.sc_ds;
|
||||
tf->tf_eflags = context.sc_eflags;
|
||||
SETFLAGS(VM86_EFLAGS(p), context.sc_eflags,
|
||||
VM86_FLAGMASK(p)|PSL_VIF);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/* %fs and %gs were restored by the trampoline. */
|
||||
tf->tf_es = context.sc_es;
|
||||
tf->tf_ds = context.sc_ds;
|
||||
tf->tf_eflags = context.sc_eflags;
|
||||
}
|
||||
tf->tf_edi = context.sc_edi;
|
||||
tf->tf_esi = context.sc_esi;
|
||||
tf->tf_ebp = context.sc_ebp;
|
||||
tf->tf_ebx = context.sc_ebx;
|
||||
tf->tf_edx = context.sc_edx;
|
||||
tf->tf_ecx = context.sc_ecx;
|
||||
tf->tf_eax = context.sc_eax;
|
||||
tf->tf_eip = context.sc_eip;
|
||||
tf->tf_cs = context.sc_cs;
|
||||
tf->tf_eflags = context.sc_eflags;
|
||||
tf->tf_esp = context.sc_esp;
|
||||
tf->tf_ss = context.sc_ss;
|
||||
tf->tf_edi = context.sc_edi;
|
||||
tf->tf_esi = context.sc_esi;
|
||||
tf->tf_ebp = context.sc_ebp;
|
||||
tf->tf_ebx = context.sc_ebx;
|
||||
tf->tf_edx = context.sc_edx;
|
||||
tf->tf_ecx = context.sc_ecx;
|
||||
tf->tf_eax = context.sc_eax;
|
||||
tf->tf_eip = context.sc_eip;
|
||||
tf->tf_cs = context.sc_cs;
|
||||
tf->tf_esp = context.sc_esp;
|
||||
tf->tf_ss = context.sc_ss;
|
||||
|
||||
return (EJUSTRETURN);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: sys_machdep.c,v 1.26 1995/10/15 05:48:08 mycroft Exp $ */
|
||||
/* $NetBSD: sys_machdep.c,v 1.27 1996/01/08 13:51:36 mycroft Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1995 Charles M. Hannum. All rights reserved.
|
||||
@ -66,6 +66,10 @@
|
||||
#include <machine/reg.h>
|
||||
#include <machine/sysarch.h>
|
||||
|
||||
#ifdef VM86
|
||||
#include <machine/vm86.h>
|
||||
#endif
|
||||
|
||||
extern vm_map_t kernel_map;
|
||||
|
||||
#ifdef TRACE
|
||||
@ -270,6 +274,14 @@ i386_set_ldt(p, args, retval)
|
||||
if (n == fsslot || n == gsslot)
|
||||
return (EBUSY);
|
||||
break;
|
||||
case SDT_MEMEC:
|
||||
case SDT_MEMEAC:
|
||||
case SDT_MEMERC:
|
||||
case SDT_MEMERAC:
|
||||
/* Must be "present" if executable and conforming. */
|
||||
if (desc.sd.sd_p == 0)
|
||||
return (EACCES);
|
||||
break;
|
||||
case SDT_MEMRO:
|
||||
case SDT_MEMROA:
|
||||
case SDT_MEMRW:
|
||||
@ -411,6 +423,12 @@ sys_sysarch(p, v, retval)
|
||||
error = i386_set_ioperm(p, SCARG(uap, parms), retval);
|
||||
break;
|
||||
|
||||
#ifdef VM86
|
||||
case I386_VM86:
|
||||
error = i386_vm86(p, SCARG(uap, parms), retval);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: trap.c,v 1.91 1995/12/09 05:00:27 mycroft Exp $ */
|
||||
/* $NetBSD: trap.c,v 1.92 1996/01/08 13:51:38 mycroft Exp $ */
|
||||
|
||||
#undef DEBUG
|
||||
#define DEBUG
|
||||
@ -262,9 +262,15 @@ trap(frame)
|
||||
frame.tf_eip = resume;
|
||||
return;
|
||||
|
||||
case T_PROTFLT|T_USER: /* protection fault */
|
||||
#ifdef VM86
|
||||
if (frame.tf_eflags & PSL_VM) {
|
||||
vm86_gpfault(p, type & ~T_USER);
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
case T_SEGNPFLT|T_USER:
|
||||
case T_STKFLT|T_USER:
|
||||
case T_PROTFLT|T_USER: /* protection fault */
|
||||
case T_ALIGNFLT|T_USER:
|
||||
trapsignal(p, SIGBUS, type &~ T_USER);
|
||||
goto out;
|
||||
@ -521,6 +527,17 @@ syscall(frame)
|
||||
#endif
|
||||
params = (caddr_t)frame.tf_esp + sizeof(int);
|
||||
|
||||
#ifdef VM86
|
||||
/*
|
||||
* VM86 mode application found our syscall trap gate by accident; let
|
||||
* it get a SIGSYS and have the VM86 handler in the process take care
|
||||
* of it.
|
||||
*/
|
||||
if (frame.tf_eflags & PSL_VM)
|
||||
code = -1;
|
||||
else
|
||||
#endif
|
||||
|
||||
switch (code) {
|
||||
case SYS_syscall:
|
||||
#ifdef COMPAT_LINUX
|
||||
|
449
sys/arch/i386/i386/vm86.c
Normal file
449
sys/arch/i386/i386/vm86.c
Normal file
@ -0,0 +1,449 @@
|
||||
/* $NetBSD: vm86.c,v 1.1 1996/01/08 13:51:40 mycroft Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 John T. Kohl
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/signalvar.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/map.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/exec.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/callout.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/msgbuf.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/device.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/syscallargs.h>
|
||||
#ifdef SYSVMSG
|
||||
#include <sys/msg.h>
|
||||
#endif
|
||||
#ifdef SYSVSEM
|
||||
#include <sys/sem.h>
|
||||
#endif
|
||||
#ifdef SYSVSHM
|
||||
#include <sys/shm.h>
|
||||
#endif
|
||||
|
||||
#include <sys/ktrace.h>
|
||||
#include <machine/sysarch.h>
|
||||
#include <machine/vm86.h>
|
||||
|
||||
static void return_to_32bit __P((struct proc *, int));
|
||||
static void fast_intxx __P((struct proc *, int));
|
||||
|
||||
#define ADDR(segment, addr) ((caddr_t)((segment << 4) + addr))
|
||||
|
||||
#define IP_ADVANCE(x) { ip += (x); tf->tf_eip = ip; }
|
||||
#define SP_ADJUST(x) { sp += (x); tf->tf_esp = sp; }
|
||||
|
||||
#define SETDIRECT ((~(PSL_USERSTATIC|PSL_NT)) & 0xffff)
|
||||
#define GETDIRECT (SETDIRECT|0x02a) /* add in two MBZ bits */
|
||||
|
||||
|
||||
static __inline__ int
|
||||
is_bitset(nr, bitmap)
|
||||
int nr;
|
||||
caddr_t bitmap;
|
||||
{
|
||||
u_int byte; /* bt instruction doesn't do
|
||||
bytes--it examines ints! */
|
||||
bitmap += nr / NBBY;
|
||||
nr = nr % NBBY;
|
||||
byte = fubyte(bitmap);
|
||||
|
||||
__asm__ __volatile__("btl %2,%1\n\tsbbl %0,%0"
|
||||
:"=r" (nr)
|
||||
:"r" (byte),"r" (nr));
|
||||
return (nr);
|
||||
}
|
||||
|
||||
|
||||
static __inline__ void
|
||||
set_vif(p)
|
||||
struct proc *p;
|
||||
{
|
||||
|
||||
VM86_EFLAGS(p) |= PSL_VIF;
|
||||
if (VM86_EFLAGS(p) & PSL_VIP)
|
||||
return_to_32bit(p, VM86_STI);
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
set_vflags(p, flags)
|
||||
struct proc *p;
|
||||
int flags;
|
||||
{
|
||||
struct trapframe *tf = p->p_md.md_regs;
|
||||
|
||||
SETFLAGS(VM86_EFLAGS(p), flags, VM86_FLAGMASK(p));
|
||||
SETFLAGS(tf->tf_eflags, flags, SETDIRECT);
|
||||
if (flags & PSL_I)
|
||||
set_vif(p);
|
||||
}
|
||||
|
||||
static __inline__ void
|
||||
set_vflags_short(p, flags)
|
||||
struct proc *p;
|
||||
int flags;
|
||||
{
|
||||
struct trapframe *tf = p->p_md.md_regs;
|
||||
|
||||
SETFLAGS(VM86_EFLAGS(p), flags, VM86_FLAGMASK(p) & 0xffff);
|
||||
SETFLAGS(tf->tf_eflags, flags, SETDIRECT);
|
||||
if (flags & PSL_I)
|
||||
set_vif(p);
|
||||
}
|
||||
|
||||
static __inline__ int
|
||||
get_vflags(p)
|
||||
struct proc *p;
|
||||
{
|
||||
struct trapframe *tf = p->p_md.md_regs;
|
||||
int flags = 0;
|
||||
|
||||
SETFLAGS(flags, VM86_EFLAGS(p), VM86_FLAGMASK(p));
|
||||
SETFLAGS(flags, tf->tf_eflags, GETDIRECT);
|
||||
if (VM86_EFLAGS(p) & PSL_VIF)
|
||||
flags |= PSL_I;
|
||||
return (flags);
|
||||
}
|
||||
|
||||
|
||||
#define V86_AH(regs) (((u_char *)&((regs)->tf_eax))[1])
|
||||
#define V86_AL(regs) (((u_char *)&((regs)->tf_eax))[0])
|
||||
|
||||
static void
|
||||
fast_intxx(p, intrno)
|
||||
struct proc *p;
|
||||
int intrno;
|
||||
{
|
||||
struct trapframe *tf = p->p_md.md_regs;
|
||||
/*
|
||||
* handle certain interrupts directly by pushing the interrupt
|
||||
* frame and resetting registers, but only if user said that's ok
|
||||
* (i.e. not revectored.) Otherwise bump to 32-bit user handler.
|
||||
*/
|
||||
struct vm86_struct *u_vm86p;
|
||||
struct { u_short ip, cs; } ihand;
|
||||
struct { u_short short1, short2, short3; } threeshorts;
|
||||
|
||||
u_short ip, cs, sp, ss;
|
||||
|
||||
/*
|
||||
* Note: u_vm86p points to user-space, we only compute offsets
|
||||
* and don't deref it. is_revectored() above does fubyte() to
|
||||
* get stuff from it
|
||||
*/
|
||||
u_vm86p = (struct vm86_struct *)p->p_addr->u_pcb.vm86_userp;
|
||||
|
||||
/*
|
||||
* If coming from BIOS segment, or going to BIOS segment, or user
|
||||
* requested special handling, return to user space with indication
|
||||
* of which INT was requested.
|
||||
*/
|
||||
cs = tf->tf_cs;
|
||||
if (cs == BIOSSEG || is_bitset(intrno, &u_vm86p->int_byuser[0]))
|
||||
goto vector;
|
||||
|
||||
/*
|
||||
* If it's interrupt 0x21 (special in the DOS world) and the
|
||||
* sub-command (in AH) was requested for special handling,
|
||||
* return to user mode.
|
||||
*/
|
||||
if (intrno == 0x21 && is_bitset(V86_AH(tf), &u_vm86p->int21_byuser[0]))
|
||||
goto vector;
|
||||
|
||||
/*
|
||||
* Fetch intr handler info from "real-mode" IDT based at addr 0 in
|
||||
* the user address space.
|
||||
*/
|
||||
if (copyin((caddr_t)(intrno * sizeof(ihand)), &ihand, sizeof(ihand)))
|
||||
goto bad;
|
||||
|
||||
if (ihand.cs == BIOSSEG)
|
||||
goto vector;
|
||||
|
||||
/*
|
||||
* Otherwise, push flags, cs, eip, and jump to handler to
|
||||
* simulate direct INT call.
|
||||
*/
|
||||
ip = tf->tf_eip;
|
||||
sp = tf->tf_esp;
|
||||
ss = tf->tf_ss;
|
||||
|
||||
threeshorts.short1 = ip;
|
||||
threeshorts.short2 = cs;
|
||||
SP_ADJUST(-6);
|
||||
threeshorts.short3 = get_vflags(p);
|
||||
if (copyout(&threeshorts, ADDR(ss, sp), sizeof(threeshorts)))
|
||||
goto bad;
|
||||
|
||||
tf->tf_eip = ihand.ip;
|
||||
tf->tf_cs = ihand.cs;
|
||||
|
||||
/* disable further "hardware" interrupts, turn off any tracing. */
|
||||
VM86_EFLAGS(p) &= ~PSL_VIF;
|
||||
tf->tf_eflags &= ~PSL_VIF|PSL_T;
|
||||
return;
|
||||
|
||||
vector:
|
||||
return_to_32bit(p, VM86_MAKEVAL(VM86_INTx, intrno));
|
||||
return;
|
||||
|
||||
bad:
|
||||
return_to_32bit(p, VM86_UNKNOWN);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
return_to_32bit(p, retval)
|
||||
struct proc *p;
|
||||
int retval;
|
||||
{
|
||||
|
||||
/*
|
||||
* We can't set the virtual flags in our real trap frame,
|
||||
* since it's used to jump to the signal handler. Instead we
|
||||
* let sendsig() pull in the VM86_EFLAGS bits.
|
||||
*/
|
||||
if (p->p_sigmask & sigmask(SIGURG)) {
|
||||
#ifdef DIAGNOSTIC
|
||||
printf("pid %d killed on VM86 protocol screwup (SIGURG blocked)\n",
|
||||
p->p_pid);
|
||||
#endif
|
||||
sigexit(p, SIGILL);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
trapsignal(p, SIGURG, retval);
|
||||
}
|
||||
|
||||
#define CLI 0xFA
|
||||
#define STI 0xFB
|
||||
#define INTxx 0xCD
|
||||
#define IRET 0xCF
|
||||
#define OPSIZ 0x66
|
||||
#define INT3 0xCC /* Actually the process gets 32-bit IDT to handle it */
|
||||
#define LOCK 0xF0
|
||||
#define PUSHF 0x9C
|
||||
#define POPF 0x9D
|
||||
|
||||
/*
|
||||
* Handle a GP fault that occurred while in VM86 mode. Things that are easy
|
||||
* to handle here are done here (much more efficient than trapping to 32-bit
|
||||
* handler code and then having it restart VM86 mode).
|
||||
*/
|
||||
void
|
||||
vm86_gpfault(p, type)
|
||||
struct proc *p;
|
||||
int type;
|
||||
{
|
||||
struct trapframe *tf = p->p_md.md_regs;
|
||||
/*
|
||||
* we want to fetch some stuff from the current user virtual
|
||||
* address space for checking. remember that the frame's
|
||||
* segment selectors are real-mode style selectors.
|
||||
*/
|
||||
u_short tmpshort; /* for fetching */
|
||||
u_int tmpint; /* for fetching */
|
||||
struct { u_short short1, short2, short3; } threeshorts;
|
||||
struct { u_int int1, int2, int3; } threeints;
|
||||
|
||||
u_short ip, cs, sp, ss;
|
||||
|
||||
ip = tf->tf_eip;
|
||||
cs = tf->tf_cs;
|
||||
sp = tf->tf_esp;
|
||||
ss = tf->tf_ss;
|
||||
|
||||
/*
|
||||
* For most of these, we must set all the registers before calling
|
||||
* macros/functions which might do a return_to_32bit.
|
||||
*/
|
||||
switch (fubyte(ADDR(cs, ip))) {
|
||||
case CLI:
|
||||
/* simulate handling of IF */
|
||||
IP_ADVANCE(1);
|
||||
VM86_EFLAGS(p) &= ~PSL_VIF;
|
||||
tf->tf_eflags &= ~PSL_VIF;
|
||||
return;
|
||||
|
||||
case STI:
|
||||
/* simulate handling of IF.
|
||||
* XXX the i386 enables interrupts one instruction later.
|
||||
* code here is wrong, but much simpler than doing it Right.
|
||||
*/
|
||||
IP_ADVANCE(1);
|
||||
set_vif(p);
|
||||
return;
|
||||
|
||||
case INTxx:
|
||||
/* try fast intxx, or return to 32bit mode to handle it. */
|
||||
IP_ADVANCE(2);
|
||||
fast_intxx(p, fubyte(ADDR(cs, ip - 1)));
|
||||
return;
|
||||
|
||||
case POPF:
|
||||
tmpshort = fusword(ADDR(ss, sp));
|
||||
SP_ADJUST(2);
|
||||
IP_ADVANCE(1);
|
||||
set_vflags_short(p, tmpshort);
|
||||
return;
|
||||
|
||||
case PUSHF:
|
||||
tmpshort = get_vflags(p);
|
||||
SP_ADJUST(-2);
|
||||
IP_ADVANCE(1);
|
||||
susword(ADDR(ss, sp), tmpshort);
|
||||
return;
|
||||
|
||||
case IRET:
|
||||
/* pop ip, cs, flags */
|
||||
if (copyin(ADDR(ss, sp), &threeshorts, sizeof(threeshorts)))
|
||||
break;
|
||||
|
||||
tf->tf_eip = threeshorts.short1;
|
||||
tf->tf_cs = threeshorts.short2;
|
||||
SP_ADJUST(6);
|
||||
set_vflags_short(p, threeshorts.short3);
|
||||
return;
|
||||
|
||||
case OPSIZ:
|
||||
switch (fubyte(ADDR(cs, ip + 1))) {
|
||||
case POPF: /* popfd */
|
||||
tmpint = fuword(ADDR(ss, sp));
|
||||
SP_ADJUST(4);
|
||||
IP_ADVANCE(2);
|
||||
set_vflags(p, tmpint);
|
||||
return;
|
||||
|
||||
case PUSHF: /* pushfd */
|
||||
tmpint = get_vflags(p);
|
||||
SP_ADJUST(-4);
|
||||
IP_ADVANCE(2);
|
||||
suword(ADDR(ss, sp), tmpint);
|
||||
return;
|
||||
|
||||
case IRET:
|
||||
if (copyin(ADDR(ss, sp), &threeints, sizeof(threeints)))
|
||||
break;
|
||||
|
||||
tf->tf_eip = threeints.int1;
|
||||
tf->tf_cs = threeints.int2;
|
||||
SP_ADJUST(12);
|
||||
set_vflags(p, threeints.int3);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCK:
|
||||
break;
|
||||
}
|
||||
|
||||
return_to_32bit(p, VM86_UNKNOWN);
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
i386_vm86(p, args, retval)
|
||||
struct proc *p;
|
||||
char *args;
|
||||
register_t *retval;
|
||||
{
|
||||
struct trapframe *tf = p->p_md.md_regs;
|
||||
struct vm86_kern vm86s;
|
||||
int psl, err;
|
||||
|
||||
if (err = copyin(args, &vm86s, sizeof(vm86s)))
|
||||
return err;
|
||||
|
||||
p->p_addr->u_pcb.vm86_userp = (void *)args;
|
||||
|
||||
#define DOVREG(reg) tf->tf_vm86_##reg = (u_short) vm86s.regs.vmsc.sc_##reg
|
||||
#define DOREG(reg) tf->tf_##reg = (u_short) vm86s.regs.vmsc.sc_##reg
|
||||
|
||||
DOVREG(ds);
|
||||
DOVREG(es);
|
||||
DOVREG(fs);
|
||||
DOVREG(gs);
|
||||
DOREG(edi);
|
||||
DOREG(esi);
|
||||
DOREG(ebp);
|
||||
DOREG(eax);
|
||||
DOREG(ebx);
|
||||
DOREG(ecx);
|
||||
DOREG(edx);
|
||||
DOREG(eip);
|
||||
DOREG(cs);
|
||||
DOREG(esp);
|
||||
DOREG(ss);
|
||||
|
||||
#undef DOVREG
|
||||
#undef DOREG
|
||||
|
||||
SETFLAGS(VM86_EFLAGS(p), vm86s.regs.vmsc.sc_eflags, VM86_FLAGMASK(p)|PSL_VIF);
|
||||
SETFLAGS(tf->tf_eflags, vm86s.regs.vmsc.sc_eflags, SETDIRECT);
|
||||
tf->tf_eflags |= PSL_VM;
|
||||
|
||||
/*
|
||||
* Keep mask of flags we simulate to simulate a particular type of
|
||||
* processor.
|
||||
*/
|
||||
switch (vm86s.ss_cpu_type) {
|
||||
case VCPU_086:
|
||||
case VCPU_186:
|
||||
case VCPU_286:
|
||||
VM86_FLAGMASK(p) = 0;
|
||||
break;
|
||||
case VCPU_386:
|
||||
VM86_FLAGMASK(p) = PSL_NT|PSL_IOPL;
|
||||
break;
|
||||
case VCPU_486:
|
||||
VM86_FLAGMASK(p) = PSL_AC|PSL_NT|PSL_IOPL;
|
||||
break;
|
||||
case VCPU_586:
|
||||
default:
|
||||
VM86_FLAGMASK(p) = PSL_ID|PSL_AC|PSL_NT|PSL_IOPL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Going into vm86 mode jumps off the signal stack. */
|
||||
p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
|
||||
|
||||
return (EJUSTRETURN);
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: pcb.h,v 1.20 1995/10/11 04:20:16 mycroft Exp $ */
|
||||
/* $NetBSD: pcb.h,v 1.21 1996/01/08 13:51:42 mycroft Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1995 Charles M. Hannum. All rights reserved.
|
||||
@ -53,6 +53,8 @@
|
||||
#include <machine/npx.h>
|
||||
#include <machine/sysarch.h>
|
||||
|
||||
#define NIOPORTS 1024 /* # of ports we allow to be mapped */
|
||||
|
||||
struct pcb {
|
||||
struct i386tss pcb_tss;
|
||||
#define pcb_cr3 pcb_tss.tss_cr3
|
||||
@ -73,7 +75,10 @@ struct pcb {
|
||||
int pcb_flags;
|
||||
#define PCB_USER_LDT 0x01 /* has user-set LDT */
|
||||
caddr_t pcb_onfault; /* copyin/out fault recovery */
|
||||
u_long pcb_iomap[1024/32]; /* I/O bitmap */
|
||||
int vm86_eflags; /* virtual eflags for vm86 mode */
|
||||
int vm86_flagmask; /* flag mask for vm86 mode */
|
||||
void *vm86_userp; /* XXX performance hack */
|
||||
u_long pcb_iomap[NIOPORTS/32]; /* I/O bitmap */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: signal.h,v 1.5 1995/05/01 14:14:11 mycroft Exp $ */
|
||||
/* $NetBSD: signal.h,v 1.6 1996/01/08 13:51:43 mycroft Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
|
||||
@ -65,6 +65,7 @@ struct sigcontext {
|
||||
int sc_edx;
|
||||
int sc_ecx;
|
||||
int sc_eax;
|
||||
/* XXX */
|
||||
int sc_eip;
|
||||
int sc_cs;
|
||||
int sc_eflags;
|
||||
@ -73,6 +74,9 @@ struct sigcontext {
|
||||
|
||||
int sc_onstack; /* sigstack state to restore */
|
||||
int sc_mask; /* signal mask to restore */
|
||||
|
||||
int sc_trapno; /* XXX should be above */
|
||||
int sc_err;
|
||||
};
|
||||
|
||||
#define sc_sp sc_esp
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: sysarch.h,v 1.7 1995/10/11 04:20:26 mycroft Exp $ */
|
||||
/* $NetBSD: sysarch.h,v 1.8 1996/01/08 13:51:44 mycroft Exp $ */
|
||||
|
||||
#ifndef _I386_SYSARCH_H_
|
||||
#define _I386_SYSARCH_H_
|
||||
@ -11,6 +11,7 @@
|
||||
#define I386_IOPL 2
|
||||
#define I386_GET_IOPERM 3
|
||||
#define I386_SET_IOPERM 4
|
||||
#define I386_VM86 5
|
||||
|
||||
struct i386_get_ldt_args {
|
||||
int start;
|
||||
|
79
sys/arch/i386/include/vm86.h
Normal file
79
sys/arch/i386/include/vm86.h
Normal file
@ -0,0 +1,79 @@
|
||||
/* $NetBSD: vm86.h,v 1.1 1996/01/08 13:51:45 mycroft Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 John T. Kohl
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#define SETFLAGS(targ, new, newmask) (targ) = ((targ) & ~(newmask)) | ((new) & (newmask))
|
||||
#define VM86_EFLAGS(p) ((p)->p_addr->u_pcb.vm86_eflags)
|
||||
#define VM86_FLAGMASK(p) ((p)->p_addr->u_pcb.vm86_flagmask)
|
||||
|
||||
#define VM86_TYPE(x) ((x) & 0xff)
|
||||
#define VM86_ARG(x) (((x) & 0xff00) >> 8)
|
||||
#define VM86_MAKEVAL(type,arg) ((type) | (((arg) & 0xff) << 8))
|
||||
#define VM86_STI 0
|
||||
#define VM86_INTx 1
|
||||
#define VM86_SIGNAL 2
|
||||
#define VM86_UNKNOWN 3
|
||||
|
||||
struct vm86_regs {
|
||||
struct sigcontext vmsc;
|
||||
};
|
||||
|
||||
struct vm86_kern { /* kernel uses this stuff */
|
||||
struct vm86_regs regs;
|
||||
unsigned long ss_cpu_type;
|
||||
};
|
||||
#define cpu_type substr.ss_cpu_type
|
||||
|
||||
/*
|
||||
* Kernel keeps copy of user-mode address of this, but doesn't copy it in.
|
||||
*/
|
||||
struct vm86_struct {
|
||||
struct vm86_kern substr;
|
||||
unsigned long screen_bitmap; /* not used/supported (yet) */
|
||||
unsigned long flags; /* not used/supported (yet) */
|
||||
unsigned char int_byuser[32]; /* 256 bits each: pass control to user */
|
||||
unsigned char int21_byuser[32]; /* otherwise, handle directly */
|
||||
};
|
||||
|
||||
#define BIOSSEG 0x0f000
|
||||
|
||||
#define VCPU_086 0
|
||||
#define VCPU_186 1
|
||||
#define VCPU_286 2
|
||||
#define VCPU_386 3
|
||||
#define VCPU_486 4
|
||||
#define VCPU_586 5
|
||||
|
||||
#ifdef _KERNEL
|
||||
int i386_vm86 __P((struct proc *, char *, register_t *));
|
||||
void vm86_gpfault __P((struct proc *, int));
|
||||
#else
|
||||
int i386_vm86 __P((struct vm86_struct *vmcp));
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user