diff options
author | dyson <dyson@FreeBSD.org> | 1997-08-09 00:04:06 +0000 |
---|---|---|
committer | dyson <dyson@FreeBSD.org> | 1997-08-09 00:04:06 +0000 |
commit | ad0649e2b977efaa77b68c699a1f44b12e7429d1 (patch) | |
tree | 925573ddb83b4a0cf21a7d136de8f44817243b6c /sys/amd64/amd64/trap.c | |
parent | 56b351207af0157d77bdd770e72c7ff038d57164 (diff) | |
download | FreeBSD-src-ad0649e2b977efaa77b68c699a1f44b12e7429d1.zip FreeBSD-src-ad0649e2b977efaa77b68c699a1f44b12e7429d1.tar.gz |
VM86 kernel support.
Work done by BSDI, Jonathan Lemon <jlemon@americantv.com>,
Mike Smith <msmith@gsoft.com.au>, Sean Eric Fagan <sef@kithrup.com>,
and probably alot of others.
Submitted by: Jnathan Lemon <jlemon@americantv.com>
Diffstat (limited to 'sys/amd64/amd64/trap.c')
-rw-r--r-- | sys/amd64/amd64/trap.c | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index 6e8c0c3..7110933 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)trap.c 7.4 (Berkeley) 5/13/91 - * $Id: trap.c,v 1.100 1997/06/22 16:03:37 peter Exp $ + * $Id: trap.c,v 1.101 1997/07/20 08:37:23 bde Exp $ */ /* @@ -85,6 +85,7 @@ extern struct i386tss common_tss; +int (*vm86_emulate) __P((struct vm86frame *)); int (*pmath_emulate) __P((struct trapframe *)); extern void trap __P((struct trapframe frame)); @@ -192,7 +193,7 @@ trap(frame) type = frame.tf_trapno; code = frame.tf_err; - if (ISPL(frame.tf_cs) == SEL_UPL) { + if ((ISPL(frame.tf_cs) == SEL_UPL) || (frame.tf_eflags & PSL_VM)) { /* user trap */ sticks = p->p_sticks; @@ -225,9 +226,22 @@ trap(frame) } goto out; + /* + * The following two traps can happen in + * vm86 mode, and, if so, we want to handle + * them specially. + */ case T_PROTFLT: /* general protection fault */ - case T_SEGNPFLT: /* segment not present fault */ case T_STKFLT: /* stack fault */ + if (vm86_emulate && (frame.tf_eflags & PSL_VM)) { + i = (*vm86_emulate)((struct vm86frame *)&frame); + if (i == 0) + goto out; + break; + } + /* FALL THROUGH */ + + case T_SEGNPFLT: /* segment not present fault */ case T_TSSFLT: /* invalid TSS fault */ case T_DOUBLEFLT: /* double fault */ default: @@ -694,6 +708,7 @@ trap_fatal(frame) if (type <= MAX_TRAP_MSG) printf("\n\nFatal trap %d: %s while in %s mode\n", type, trap_msg[type], + frame->tf_eflags & PSL_VM ? "vm86" : ISPL(frame->tf_cs) == SEL_UPL ? "user" : "kernel"); #ifdef SMP printf("cpuid = %d\n", cpuid); @@ -707,7 +722,7 @@ trap_fatal(frame) } printf("instruction pointer = 0x%x:0x%x\n", frame->tf_cs & 0xffff, frame->tf_eip); - if (ISPL(frame->tf_cs) == SEL_UPL) { + if ((ISPL(frame->tf_cs) == SEL_UPL) || (frame->tf_eflags & PSL_VM)) { ss = frame->tf_ss & 0xffff; esp = frame->tf_esp; } else { @@ -946,7 +961,7 @@ bad: break; } - if (frame.tf_eflags & PSL_T) { + if ((frame.tf_eflags & PSL_T) && !(frame.tf_eflags & PSL_VM)) { /* Traced syscall. */ frame.tf_eflags &= ~PSL_T; trapsignal(p, SIGTRAP, 0); |