Subject: port-i386/825: no support for Virtual 8086 mode
To: None <gnats-admin@NetBSD.ORG>
From: John Kohl <jtk@kolvir.blrc.ma.us>
List: netbsd-bugs
Date: 02/25/1995 21:20:06
>Number: 825
>Category: port-i386
>Synopsis: the i386 port doesn't have support for virtual 8086 mode
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: gnats-admin (GNATS administrator)
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Sat Feb 25 21:20:04 1995
>Originator: John Kohl
>Organization:
NetBSD Kernel Hackers `R` Us
>Release: -current
>Environment:
System: NetBSD kolvir 1.0A NetBSD 1.0A (KOLVIR) #105: Sat Feb 25 23:20:46 EST 1995 jtk@kolvir:/u1/NetBSD-current/src/sys/arch/i386/compile/KOLVIR i386
>Description:
The i386 port doesn't implement v8086 mode.
>How-To-Repeat:
Try using it, or finding an interface for it.
>Fix:
Here is a preliminary implementation. Known problems:
(a) the syscall glue to get to the alternate interrupt gate is totally
disgusting, but I didn't feel like chewing up SYS.h and the libc build
macros. Besides, I learned about gcc's asm directives.
(b) The interrupt gate code for the vm86 trap gate is clunky--there is
certainly a more efficient way to jack up the trap frame.
(c) I haven't tested this extensively--there may still be some lurking
problems with interrupts while in v8086 mode?
(d) I rev'ed the minor version on libi386.so (added a function). Is
this appropriate?
(e) the out-of-band bit passing between Xvm86 and sysarch() is gross
too--maybe there's a better way to do that too?
At the end of the diffs you'll find a program which jumps into a v8086
tight loop. You should be able to ^C out of it (shows that CPU
rescheduling works), and to give it a SIGQUIT and have it longjmp back
to safety.
===================================================================
RCS file: lib/libarch/RCS/shlib_version,v
retrieving revision 1.1
diff -ubw -r1.1 lib/libarch/shlib_version
--- 1.1 1995/02/25 19:53:55
+++ lib/libarch/shlib_version 1995/02/25 19:54:13
@@ -1,2 +1,2 @@
major=0
-minor=0
+minor=1
===================================================================
RCS file: lib/libarch/i386/RCS/Makefile.inc,v
retrieving revision 1.1
diff -ubw -r1.1 lib/libarch/i386/Makefile.inc
--- 1.1 1995/02/25 19:43:52
+++ lib/libarch/i386/Makefile.inc 1995/02/25 19:44:11
@@ -2,8 +2,8 @@
.PATH: ${LIBC}/i386
-SRCS+= i386_get_ldt.c i386_set_ldt.c
+SRCS+= i386_get_ldt.c i386_set_ldt.c i386_vm86.c
-MAN+= i386_get_ldt.2
+MAN+= i386_get_ldt.2 i386_vm86.2
MLINKS+=i386_get_ldt.2 i386_set_ldt.2
--- /dev/null Sat Feb 25 23:23:15 1995
+++ lib/libarch/i386/i386_vm86.2 Sat Feb 25 15:29:12 1995
@@ -0,0 +1,66 @@
+.\" Copyright (c) 1980, 1991 Regents of the University of California.
+.\" 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. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+.\"
+.\" from: @(#)fork.2 6.5 (Berkeley) 3/10/91
+.\" $Id: i386_vm86.2,v 1.3 1995/02/25 20:29:12 jtk Exp $
+.\"
+.Dd September 20, 1993
+.Dt I386_VM86 2
+.Os NetBSD
+.Sh NAME
+.Nm i386_vm86
+.Nd set virtual 8086 processor registers and mode
+.Sh SYNOPSIS
+.Fd #include <machine/segments.h>
+.Fd #include <machine/sysarch.h>
+.Ft int
+.Fn i386_vm86 "struct vm86_context *vmcp"
+.Sh DESCRIPTION
+.Fn i386_vm86
+will set the process into virtual 8086 mode using the registers and
+selectors specified by the context pointed to by
+.Fa vmcp .
+.Sh RETURN VALUES
+This routine does not normally return--32-bit mode will be restored by
+the delivery of a signal to the process. In case of an error in setting
+the VM86 mode, a value of -1 is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Fn i386_vm86
+will fail if:
+.Bl -tag -width [EINVAL]
+.It Bq Er EINVAL
+An inappropriate parameter was specified in the signal context.
+.Sh REFERENCES
+i386 Microprocessor Programmer's Reference Manual, Intel
+.Sh WARNING
+You can really hose your process using this.
--- /dev/null Sat Feb 25 23:23:15 1995
+++ lib/libarch/i386/i386_vm86.c Sat Feb 25 21:30:13 1995
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1995 John 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/cdefs.h>
+#include <machine/segments.h>
+#include <machine/sysarch.h>
+#include <errno.h>
+#include <sys/syscall.h>
+
+#define _quote(x) # x
+#define quote(x) _quote(x)
+
+#define concat(a,b) a##b
+
+static int
+int129(int op, void *arg);
+
+__asm(".globl cerror");
+__asm("_int129:");
+__asm("movl $" quote(SYS_sysarch) ",%eax");
+__asm("int $" quote(INT_VM86));
+#ifdef PIC
+ __asm("jc cerror@PLT");
+#else
+ __asm("jc cerror");
+#endif
+__asm("ret");
+
+int
+i386_vm86(register struct vm86_context *vmcp)
+{
+ /* we need a special INT entry into the kernel so that we can
+ * set up the proper stack state to be munged by the trap code
+ * in order to be loaded up by the iret.
+ */
+#if 0
+ __asm(" pushl %0" : : "g" (vmcp));
+ __asm(" pushl $" quote(I386_VM86));
+ return EINVAL;
+#endif
+ return int129(I386_VM86, vmcp);
+}
===================================================================
RCS file: sys/arch/i386/include/RCS/cpu.h,v
retrieving revision 1.1
diff -ubw -r1.1 sys/arch/i386/include/cpu.h
--- 1.1 1995/02/25 20:21:33
+++ sys/arch/i386/include/cpu.h 1995/02/26 03:57:43
@@ -68,7 +68,7 @@
*/
#define clockframe intrframe
-#define CLKF_USERMODE(frame) (ISPL((frame)->if_cs) == SEL_UPL)
+#define CLKF_USERMODE(frame) (ISPL((frame)->if_cs) == SEL_UPL || ((frame)->if_eflags & PSL_VM))
#define CLKF_BASEPRI(frame) ((frame)->if_ppl == 0)
#define CLKF_PC(frame) ((frame)->if_eip)
#define CLKF_INTR(frame) (0) /* XXX should have an interrupt stack */
===================================================================
RCS file: sys/arch/i386/include/RCS/frame.h,v
retrieving revision 1.1
diff -ubw -r1.1 sys/arch/i386/include/frame.h
--- 1.1 1995/02/25 22:27:19
+++ sys/arch/i386/include/frame.h 1995/02/26 02:15:50
@@ -91,6 +91,19 @@
int if_ss;
};
+struct vm86_frame {
+ struct trapframe tframe;
+ int vm_es;
+ int vm_ds;
+ int vm_fs;
+ int vm_gs;
+};
+/*
+ * A kludge for locore to tell the sysarch() handler that this
+ * trap has a VM86 mode frame.
+ */
+#define VM86_TRAP 0x80000000
+
/*
* Signal frame
*/
===================================================================
RCS file: sys/arch/i386/include/RCS/sysarch.h,v
retrieving revision 1.1
diff -ubw -r1.1 sys/arch/i386/include/sysarch.h
--- 1.1 1995/02/25 19:38:01
+++ sys/arch/i386/include/sysarch.h 1995/02/25 22:01:34
@@ -8,10 +8,35 @@
*/
#define I386_GET_LDT 0
#define I386_SET_LDT 1
+#define I386_VM86 2
+
+#define INT_VM86 0x81 /* special interrupt gate # */
+
+struct vm86_context {
+ int sc_edi;
+ int sc_esi;
+ int sc_ebp;
+ int sc_ebx;
+ int sc_edx;
+ int sc_ecx;
+ int sc_eax;
+ /* hardware stack frame for vm86 iret: */
+ int sc_eip;
+ int sc_cs;
+ int sc_eflags;
+ int sc_esp;
+ int sc_ss;
+ /* extra vm86 stuff is: */
+ int sc_es;
+ int sc_ds;
+ int sc_fs;
+ int sc_gs;
+};
#ifndef KERNEL
int i386_get_ldt __P((int, union descriptor *, int));
int i386_set_ldt __P((int, union descriptor *, int));
+int i386_vm86 __P((struct vm86_context *));
#endif
#endif /* !_I386_SYSARCH_H_ */
===================================================================
RCS file: sys/arch/i386/isa/RCS/icu.s,v
retrieving revision 1.1
diff -ubw -r1.1 sys/arch/i386/isa/icu.s
--- 1.1 1995/02/26 04:15:16
+++ sys/arch/i386/isa/icu.s 1995/02/26 04:16:20
@@ -132,8 +132,10 @@
cmpb $0,_astpending
je 3f
testb $SEL_RPL_MASK,TF_CS(%esp)
+ jnz 4f
+ testl $PSL_VM,TF_EFLAGS(%esp)
jz 3f
- movb $0,_astpending
+4: movb $0,_astpending
sti
/* Pushed T_ASTFLT into tf_trapno on entry. */
call _trap
===================================================================
RCS file: sys/arch/i386/isa/RCS/npx.c,v
retrieving revision 1.1
diff -ubw -r1.1 sys/arch/i386/isa/npx.c
--- 1.1 1995/02/25 20:21:56
+++ sys/arch/i386/isa/npx.c 1995/02/25 23:44:34
@@ -419,7 +419,8 @@
* Pass exception to process. If it's the current process, try to do
* it immediately.
*/
- if (p == curproc && ISPL(frame->if_cs) == SEL_UPL) {
+ if (p == curproc &&
+ (ISPL(frame->if_cs) == SEL_UPL || (frame->if_eflags & PSL_VM))) {
/*
* Interrupt is essentially a trap, so we can afford to call
* the SIGFPE handler (if any) as soon as the interrupt
===================================================================
RCS file: sys/arch/i386/i386/RCS/db_interface.c,v
retrieving revision 1.2
diff -ubw -r1.2 sys/arch/i386/i386/db_interface.c
--- 1.2 1995/01/30 02:58:58
+++ sys/arch/i386/i386/db_interface.c 1995/02/25 20:23:17
@@ -79,7 +79,7 @@
/* XXX Should switch to kdb`s own stack here. */
ddb_regs = *regs;
- if (ISPL(regs->tf_cs) == SEL_KPL) {
+ if (ISPL(regs->tf_cs) == SEL_KPL && !(regs->tf_eflags & PSL_VM)) {
/*
* Kernel mode - esp and ss not saved
*/
@@ -107,7 +107,7 @@
regs->tf_eip = ddb_regs.tf_eip;
regs->tf_cs = ddb_regs.tf_cs;
regs->tf_eflags = ddb_regs.tf_eflags;
- if (ISPL(regs->tf_cs) != SEL_KPL) {
+ if (ISPL(regs->tf_cs) != SEL_KPL || (regs->tf_eflags & PSL_VM)) {
/* ring transit - saved esp and ss valid */
regs->tf_esp = ddb_regs.tf_esp;
regs->tf_ss = ddb_regs.tf_ss;
===================================================================
RCS file: sys/arch/i386/i386/RCS/locore.s,v
retrieving revision 1.1
diff -ubw -r1.1 sys/arch/i386/i386/locore.s
--- 1.1 1995/02/26 04:18:17
+++ sys/arch/i386/i386/locore.s 1995/02/26 04:19:02
@@ -63,7 +63,7 @@
#define IOM_BEGIN 0x0a0000 /* start of I/O memory "hole" */
#define IOM_END 0x100000 /* end of I/O memory "hole" */
#define IOM_SIZE (IOM_END - IOM_BEGIN)
-
+#define VM86_TRAP 0x80000000 /* see frame.h ?? */
#define ALIGN_DATA .align 2
#define ALIGN_TEXT .align 2,0x90 /* 4-byte boundaries, NOP-filled */
@@ -1973,8 +1973,10 @@
cmpb $0,_astpending
je 1f
testb $SEL_RPL_MASK,TF_CS(%esp)
+ jnz 5f
+ testl $PSL_VM,TF_EFLAGS(%esp)
jz 1f
- movb $0,_astpending
+5: movb $0,_astpending
sti
movl $T_ASTFLT,TF_TRAPNO(%esp)
call _trap
@@ -2062,6 +2064,45 @@
4: .asciz "WARNING: SPL NOT LOWERED ON SYSCALL EXIT\n"
#endif /* DIAGNOSTIC */
+ /*
+ * For VM86 support, we need a special gate that makes room
+ * on the kernel-mode stack for the extra selectors (gs,fs,ds,es)
+ * The user-space expects it to behave like the syscall interrupt,
+ * and calls the sysarch() syscall.
+ */
+IDTVEC(vm86)
+ cmpl $SYS_sysarch,%eax
+ jne 1f # only jack the stack for sysarch
+ testl $PSL_VM,8(%esp)
+ jnz 1f # don't jack if already VM86 mode
+ /* We need to jack up the existing stack frame by 4 longwords, */
+ /* and shift the existing 5 longword args to the new top. */
+ subl $0x10,%esp
+ movl 0x10(%esp),%eax
+ movl %eax,(%esp)
+ movl 0x14(%esp),%eax
+ movl %eax,0x4(%esp)
+ movl 0x18(%esp),%eax
+ movl %eax,0x8(%esp)
+ movl 0x1c(%esp),%eax
+ movl %eax,0xc(%esp)
+ movl 0x20(%esp),%eax
+ movl %eax,0x10(%esp)
+ /* and zero out what was there */
+ movl $0,0x14(%esp)
+ movl $0,0x18(%esp)
+ movl $0,0x1c(%esp)
+ movl $0,0x20(%esp)
+ /* leave marker for sysarch to test in the frame
+ (unused bits of CS word) */
+ movl 4(%esp),%eax
+ orl $VM86_TRAP,%eax
+ movl %eax,4(%esp)
+ movl $SYS_sysarch,%eax
+1:
+ pushl $2 # size of instruction for restart
+ jmp syscall1 # go do real syscall
+
#include <i386/isa/vector.s>
#include <i386/isa/icu.s>
===================================================================
RCS file: sys/arch/i386/i386/RCS/machdep.c,v
retrieving revision 1.4
diff -ubw -r1.4 sys/arch/i386/i386/machdep.c
--- 1.4 1995/02/04 14:41:07
+++ sys/arch/i386/i386/machdep.c 1995/02/25 23:23:12
@@ -1004,7 +1004,7 @@
IDTVEC(dble), IDTVEC(fpusegm), IDTVEC(tss), IDTVEC(missing),
IDTVEC(stk), IDTVEC(prot), IDTVEC(page), IDTVEC(rsvd),
IDTVEC(fpu), IDTVEC(align),
- IDTVEC(syscall), IDTVEC(osyscall);
+ IDTVEC(syscall), IDTVEC(osyscall), IDTVEC(vm86);
void
sdtossd(sd, ssd)
@@ -1087,6 +1087,7 @@
setgate(&idt[ 16], &IDTVEC(fpu), 0, SDT_SYS386TGT, SEL_KPL);
setgate(&idt[ 17], &IDTVEC(align), 0, SDT_SYS386TGT, SEL_KPL);
setgate(&idt[128], &IDTVEC(syscall), 0, SDT_SYS386TGT, SEL_UPL);
+ setgate(&idt[129], &IDTVEC(vm86), 0, SDT_SYS386TGT, SEL_UPL);
#if NISA > 0
isa_defaultirq();
===================================================================
RCS file: sys/arch/i386/i386/RCS/math_emulate.c,v
retrieving revision 1.1
diff -ubw -r1.1 sys/arch/i386/i386/math_emulate.c
--- 1.1 1995/02/25 20:04:28
+++ sys/arch/i386/i386/math_emulate.c 1995/02/25 20:05:03
@@ -75,7 +75,7 @@
char * address;
u_long oldeip;
- if (ISPL(info->tf_cs) != SEL_UPL)
+ if (ISPL(info->tf_cs) != SEL_UPL && !(frame.tf_eflags & PSL_VM))
panic("math emulator called from supervisor mode");
/* ever used fp? */
===================================================================
RCS file: sys/arch/i386/i386/RCS/sys_machdep.c,v
retrieving revision 1.1
diff -ubw -r1.1 sys/arch/i386/i386/sys_machdep.c
--- 1.1 1995/02/25 19:39:33
+++ sys/arch/i386/i386/sys_machdep.c 1995/02/26 02:49:28
@@ -322,6 +322,63 @@
#endif /* USER_LDT */
int
+i386_set_vm86mode(p, vmcp)
+ struct proc *p;
+ struct vm86_context *vmcp;
+{
+ struct vm86_frame *vf;
+ struct trapframe *tf;
+ int error;
+ struct vm86_context vmcontext;
+
+ if (error = copyin(vmcp, &vmcontext, sizeof(vmcontext)))
+ return(error);
+
+ vmcp = &vmcontext;
+
+ if (p->p_addr->u_pcb.pcb_psl & PSL_VM)
+ return EINVAL; /* already there??! */
+ vf = (struct vm86_frame *)p->p_md.md_regs;
+ tf = &vf->tframe;
+
+ printf("vf=%lx, esp=%lx, ss=%lx\n", vf, tf->tf_esp, tf->tf_ss);
+ printf("es=%lx,ds=%lx,fs=%lx,gs=%lx\n",
+ vf->vm_es, vf->vm_ds, vf->vm_fs, vf->vm_gs);
+ /*
+ * Check for security violations. Only let them diddle PSL_VM bit.
+ * They must set PSL_VM bit, it must not be on.
+ */
+ if ((vmcp->sc_eflags & PSL_VM) == 0 || (tf->tf_eflags & PSL_VM) != 0 ||
+ ((vmcp->sc_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != PSL_VM)
+ return (EINVAL);
+
+ /*
+ * Restore signal context.
+ */
+/* tf->tf_es = vmcp->sc_es;*/
+/* tf->tf_ds = vmcp->sc_ds;*/
+ tf->tf_edi = vmcp->sc_edi;
+ tf->tf_esi = vmcp->sc_esi;
+ tf->tf_ebp = vmcp->sc_ebp;
+ tf->tf_ebx = vmcp->sc_ebx;
+ tf->tf_edx = vmcp->sc_edx;
+ tf->tf_ecx = vmcp->sc_ecx;
+ tf->tf_eax = vmcp->sc_eax;
+ tf->tf_eip = vmcp->sc_eip;
+ tf->tf_cs = vmcp->sc_cs;
+ tf->tf_eflags = vmcp->sc_eflags;
+ tf->tf_esp = vmcp->sc_esp;
+ tf->tf_ss = vmcp->sc_ss;
+
+ vf->vm_es = vmcp->sc_es;
+ vf->vm_ds = vmcp->sc_ds;
+ vf->vm_fs = vmcp->sc_fs;
+ vf->vm_gs = vmcp->sc_gs;
+
+ return (EJUSTRETURN);
+}
+
+int
sysarch(p, uap, retval)
struct proc *p;
struct sysarch_args /* {
@@ -331,7 +388,20 @@
register_t *retval;
{
int error = 0;
+ struct trapframe *tf;
+
+ tf = (struct trapframe *)p->p_md.md_regs;
+ if (tf->tf_cs & VM86_TRAP) { /* marker for vm86 jacked stack */
+ tf->tf_cs &= ~VM86_TRAP;
+ printf("vm86: tf %lx endtf %lx\n", tf, tf+1);
+ printf("op=%x,parms=%x\n", SCARG(uap,op), SCARG(uap,parms));
+ if (SCARG(uap,op) == I386_VM86)
+ error = i386_set_vm86mode(p, (struct vm86_context *)SCARG(uap, parms));
+ else
+ error = EINVAL; /* XXX can we go back and not die? */
+ printf("vm86: returning %d\n", error);
+ }
switch(SCARG(uap, op)) {
#ifdef USER_LDT
case I386_GET_LDT:
@@ -342,6 +412,7 @@
error = i386_set_ldt(p, SCARG(uap, parms), retval);
break;
#endif
+ case I386_VM86:
default:
error = EINVAL;
break;
===================================================================
RCS file: sys/arch/i386/i386/RCS/trap.c,v
retrieving revision 1.1
diff -ubw -r1.1 sys/arch/i386/i386/trap.c
--- 1.1 1995/02/25 20:03:49
+++ sys/arch/i386/i386/trap.c 1995/02/25 20:18:26
@@ -179,7 +179,7 @@
}
#endif
- if (ISPL(frame.tf_cs) != SEL_KPL) {
+ if (ISPL(frame.tf_cs) != SEL_KPL || (frame.tf_eflags & PSL_VM)) {
type |= T_USER;
sticks = p->p_sticks;
p->p_md.md_regs = (int *)&frame;
@@ -500,8 +500,9 @@
extern struct sysent ibcs2_sysent[];
#endif
+
cnt.v_syscall++;
- if (ISPL(frame.tf_cs) != SEL_UPL)
+ if (ISPL(frame.tf_cs) != SEL_UPL && !(frame.tf_eflags & PSL_VM))
panic("syscall");
p = curproc;
sticks = p->p_sticks;
@@ -539,6 +540,9 @@
#endif
}
+ if (frame.tf_eflags & PSL_VM)
+ code = -1;
+ else
switch (code) {
case SYS_syscall:
code = fuword(params);
--- /dev/null Sat Feb 25 23:23:15 1995
+++ /var/tmp/Makefile Sat Feb 25 23:27:57 1995
@@ -0,0 +1,2 @@
+sigill: sigill.c
+ $(CC) -static -I/usr/include.current -g -o sigill sigill.c -li386
--- /dev/null Sat Feb 25 23:23:15 1995
+++ /var/tmp/sigill.c Sat Feb 25 23:26:52 1995
@@ -0,0 +1,57 @@
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <setjmp.h>
+#include <machine/segments.h>
+#include <machine/sysarch.h>
+#include <machine/psl.h>
+
+jmp_buf jbuf;
+
+void
+sigill(int sig, int code, struct sigcontext *scp)
+{
+ printf("sig %d, code %d, eip %#08lx, eflags=%#08lx\n",
+ sig, code, scp->sc_eip, scp->sc_eflags);
+ longjmp(jbuf, 1);
+ _exit(2);
+}
+
+unsigned long vmstack[256];
+
+unsigned char ill[] = { 144, 144, 144, 0xeb, 0xfb /* nop, nop, nop, loop */ };
+
+foo()
+{
+ asm("1: nop; nop; nop");
+ asm("jmp 1b");
+}
+
+main()
+{
+ struct vm86_context vmctx;
+ int rval;
+ int psl;
+
+ signal(SIGILL, sigill);
+ signal(SIGBUS, sigill);
+ signal(SIGQUIT, sigill);
+ memset(&vmctx, 0, sizeof(vmctx));
+
+
+ vmctx.sc_esp = (int) &vmstack[sizeof(vmstack)/4-1];
+ vmctx.sc_eip = (int) &ill[0];
+ vmctx.sc_cs = 0;
+ __asm("pushfl");
+ __asm("popl %0" : "=r" (psl));
+ vmctx.sc_eflags = psl | PSL_VM;
+
+ if (setjmp(jbuf)) {
+ printf("jumped out of sighandler, exiting\n");
+ exit(2);
+ }
+ rval = i386_vm86(&vmctx);
+ printf("returning from vm86 with rval=%d?\n", rval);
+ exit(1);
+}
+
>Audit-Trail:
>Unformatted: