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>
