From owner-freebsd-hackers Sun Feb 26 17:59:12 1995 Return-Path: hackers-owner Received: (from majordom@localhost) by freefall.cdrom.com (8.6.9/8.6.6) id RAA17102 for hackers-outgoing; Sun, 26 Feb 1995 17:59:12 -0800 Received: from bunyip.cc.uq.oz.au (bunyip.cc.uq.oz.au [130.102.2.1]) by freefall.cdrom.com (8.6.9/8.6.6) with SMTP id RAA17093 for ; Sun, 26 Feb 1995 17:59:06 -0800 Received: from cc.uq.oz.au by bunyip.cc.uq.oz.au id <02955-0@bunyip.cc.uq.oz.au>; Mon, 27 Feb 1995 11:57:55 +1000 Received: from netfl15a.devetir.qld.gov.au by pandora.devetir.qld.gov.au (8.6.10/DEVETIR-E0.3a) with ESMTP id MAA11208 for ; Mon, 27 Feb 1995 12:01:06 +1000 Received: by netfl15a.devetir.qld.gov.au (8.6.8.1/DEVETIR-0.1) id BAA12599; Mon, 27 Feb 1995 01:58:21 GMT Date: Mon, 27 Feb 1995 01:58:21 GMT From: Stephen Hocking Message-Id: <199502270158.BAA12599@netfl15a.devetir.qld.gov.au> To: hackers@FreeBSD.org Subject: VM86 syscall implementation from NetBSD Sender: hackers-owner@FreeBSD.org Precedence: bulk Below is some stuff FreeBSD has been needing for ages, but a member of the NetBSD camp has finally done. This would do good things for those people who'd like a better DOS emulator than PCemu, I have some programs that would benefit. >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 +.Fd #include +.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 +#include +#include +#include +#include + +#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 #include =================================================================== 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 +#include +#include +#include +#include +#include +#include + +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: