Date: Mon, 27 Feb 1995 08:55:38 +0000 (GMT) From: "Soeren Schmidt" <sos@kmd-ac.dk> To: sysseh@devetir.qld.gov.au (Stephen Hocking) Cc: hackers@FreeBSD.org Subject: Re: VM86 syscall implementation from NetBSD Message-ID: <199502270747.AA24223@dkuug.dk> In-Reply-To: <199502270158.BAA12599@netfl15a.devetir.qld.gov.au> from "Stephen Hocking" at Feb 27, 95 01:58:21 am
next in thread | previous in thread | raw e-mail | index | archive | help
In reply to Stephen Hocking who wrote: > > > 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 <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: > > > -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Soren Schmidt (sos@FreeBSD.org | sos@kmd-ac.dk) FreeBSD Core Team ..
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199502270747.AA24223>