Skip site navigation (1)Skip section navigation (2)
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>