Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 28 Mar 1997 20:29:48 -0800
From:      Sean Eric Fagan <sef@Kithrup.COM>
To:        emulation@freebsd.org
Subject:   New diffs
Message-ID:  <199703290429.UAA14152@kithrup.com>

next in thread | raw e-mail | index | archive | help

These are against 2.2-RELEASE, since I haven't grabbed the 2.2.1
source tree yet.

The only new diffs are in exception.s, icu.s, and npx.c, so just
grab those if you want to just update the old patches.

This version hasn't hung on me (thanks jlemon!).  If it behaves similarly
for others, I think we have a candidate for larger release...

--- ./i386/machdep.c.orig	Thu Feb 13 17:11:30 1997
+++ ./i386/machdep.c	Mon Mar 17 18:07:57 1997
@@ -426,6 +426,10 @@
  * resets the signal mask, the stack, and the
  * frame pointer, it returns to the user
  * specified pc, psl.
+ *
+ * For VM86 processes, a copy of the registe
+ * set is placed on the stack *after* the
+ * sigframe (as a trapframe).
  */
 void
 sendsig(catcher, sig, mask, code)
@@ -439,16 +443,23 @@
 	struct sigframe sf;
 	struct sigacts *psp = p->p_sigacts;
 	int oonstack;
+	int framesize = sizeof(struct sigframe);
 
 	regs = p->p_md.md_regs;
         oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
 	/*
+	 * XXX this will go away
+	 * Are we a vm86 process?  If so, allocate stack space
+	 */
+	if (regs[tEFLAGS] & PSL_VM)
+		framesize += sizeof(struct trapframe_vm86);
+	/*
 	 * Allocate and validate space for the signal handler context.
 	 */
         if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack &&
 	    (psp->ps_sigonstack & sigmask(sig))) {
 		fp = (struct sigframe *)(psp->ps_sigstk.ss_sp +
-		    psp->ps_sigstk.ss_size - sizeof(struct sigframe));
+		    psp->ps_sigstk.ss_size - framesize);
 		psp->ps_sigstk.ss_flags |= SS_ONSTACK;
 	} else {
 		fp = (struct sigframe *)regs[tESP] - 1;
@@ -460,7 +471,7 @@
 	 *	if access is denied.
 	 */
 	if ((grow(p, (int)fp) == FALSE) ||
-	    (useracc((caddr_t)fp, sizeof (struct sigframe), B_WRITE) == FALSE)) {
+	    (useracc((caddr_t)fp, framesize, B_WRITE) == FALSE)) {
 		/*
 		 * Process has trashed its stack; give it an illegal
 		 * instruction to halt it in its tracks.
@@ -511,7 +522,21 @@
 	sf.sf_sc.sc_fp = regs[tEBP];
 	sf.sf_sc.sc_pc = regs[tEIP];
 	sf.sf_sc.sc_ps = regs[tEFLAGS];
+	sf.sf_sc.sc_trapno = regs[tTRAPNO];
+	sf.sf_sc.sc_err = regs[tERR];
+
+	/*
+	 * If we're a vm86 process, we want to save
+	 * the segment registers.
+	 */
+	if (regs[tEFLAGS] & PSL_VM) {
+		struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
 
+		sf.sf_sc.sc_gs = tf->tf_vm86_gs;
+		sf.sf_sc.sc_fs = tf->tf_vm86_fs;
+		sf.sf_sc.sc_es = tf->tf_vm86_es;
+		sf.sf_sc.sc_ds = tf->tf_vm86_ds;
+	}
 	/*
 	 * Copy the sigframe out to the user's stack.
 	 */
@@ -521,11 +546,34 @@
 		 * ...Kill the process.
 		 */
 		sigexit(p, SIGILL);
-	};
+	}
+	/*
+	 * If we're a vm86 process, we put the register set
+	 * out on teh stack, *after* the sigframe structure.
+	 * We do this because BSD/OS' struct sigcontext does not
+	 * have all of the machine registers.  Even though
+	 * we do, we do this for now, until the DOS emulator
+	 * is changed enough.  *However*, we don't depends on
+	 * it in sigreturn!
+	 *
+	 * XXX - we don't check for errors!  (None should happen
+	 * because of the grow() and useracc() we did above, but
+	 * "should" has probably sunk more ships than torpedoes.)
+	 */
+	if (regs[tEFLAGS] & PSL_VM) {
+		copyout(regs, (void*)((unsigned)fp + sizeof(struct sigframe)),
+		    sizeof(struct trapframe_vm86));
+	}
 
 	regs[tESP] = (int)fp;
 	regs[tEIP] = (int)(((char *)PS_STRINGS) - *(p->p_sysent->sv_szsigcode));
 	regs[tEFLAGS] &= ~PSL_VM;
+	/*
+	 * Signal handlers for vm86 processes do not run in
+	 * vm86 mode.  This may seem a bit odd at first glance,
+	 * but it seems even odder to have a signal handler
+	 * written in 16-bit code!
+	 */
 	regs[tCS] = _ucodesel;
 	regs[tDS] = _udatasel;
 	regs[tES] = _udatasel;
@@ -566,43 +614,71 @@
 
 	if (useracc((caddr_t)fp, sizeof (*fp), B_WRITE) == 0)
 		return(EINVAL);
-
-	/*
-	 * Don't allow users to change privileged or reserved flags.
-	 */
-#define	EFLAGS_SECURE(ef, oef)	((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
 	eflags = scp->sc_ps;
 	/*
-	 * XXX do allow users to change the privileged flag PSL_RF.  The
-	 * cpu sets PSL_RF in tf_eflags for faults.  Debuggers should
-	 * sometimes set it there too.  tf_eflags is kept in the signal
-	 * context during signal handling and there is no other place
-	 * to remember it, so the PSL_RF bit may be corrupted by the
-	 * signal handler without us knowing.  Corruption of the PSL_RF
-	 * bit at worst causes one more or one less debugger trap, so
-	 * allowing it is fairly harmless.
+	 * We do funky stuff if it's a vm86 process.
 	 */
-	if (!EFLAGS_SECURE(eflags & ~PSL_RF, regs[tEFLAGS] & ~PSL_RF)) {
+	if (eflags & PSL_VM) {
+		struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs;
+		struct pcb *pcb = &p->p_addr->u_pcb;
+		if (p->p_md.md_connarea == 0)
+			p->p_md.md_connarea = (void*)scp->sc_eax;
+
+		eflags = (eflags & PSL_USERCHANGE) | PSL_VM | PSL_I;
+		/*
+		 * XXX
+		 * BSD/OS also checks to see if it should set the
+		 * PSL_IOPL bit; I think, however, that the IOPL
+		 * bits should always be 0 -- preventing the vm86
+		 * process from executing the "sensitive" instructions.
+		 */
+		eflags &= ~PSL_IOPL;
+		pcb->vm86_eflags = eflags & PSL_I;
+
+		tf->tf_vm86_ds = scp->sc_ds;
+		tf->tf_vm86_es = scp->sc_es;
+		tf->tf_vm86_fs = scp->sc_fs;
+		tf->tf_vm86_gs = scp->sc_gs;
+		regs[tDS] = _udatasel;
+		regs[tES] = _udatasel;
+	} else {
+		/*
+		 * Don't allow users to change privileged or reserved flags.
+		 */
+#define	EFLAGS_SECURE(ef, oef)	((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
+		/*
+		 * XXX do allow users to change the privileged flag PSL_RF.
+		 * The cpu sets PSL_RF in tf_eflags for faults.  Debuggers
+		 * should sometimes set it there too.  tf_eflags is kept in 
+		 * the signal context during signal handling and there is no
+		 * other place to remember it, so the PSL_RF bit may be 
+		 * corrupted by the signal handler without us knowing.
+		 * Corruption of the PSL_RF bit at worst causes one more or
+		 * one less debugger trap, so allowing it is fairly harmless.
+		 */
+		if (!EFLAGS_SECURE(eflags & ~PSL_RF, regs[tEFLAGS] & ~PSL_RF)) {
 #ifdef DEBUG
-    		printf("sigreturn: eflags = 0x%x\n", eflags);
+			printf("sigreturn: eflags = 0x%x\n", eflags);
 #endif
-    		return(EINVAL);
-	}
+			return(EINVAL);
+		}
 
-	/*
-	 * Don't allow users to load a valid privileged %cs.  Let the
-	 * hardware check for invalid selectors, excess privilege in
-	 * other selectors, invalid %eip's and invalid %esp's.
-	 */
+		/*
+		 * Don't allow users to load a valid privileged %cs.  Let the
+		 * hardware check for invalid selectors, excess privilege in
+		 * other selectors, invalid %eip's and invalid %esp's.
+		 */
 #define	CS_SECURE(cs)	(ISPL(cs) == SEL_UPL)
-	if (!CS_SECURE(scp->sc_cs)) {
+		if (!CS_SECURE(scp->sc_cs)) {
 #ifdef DEBUG
-    		printf("sigreturn: cs = 0x%x\n", scp->sc_cs);
+			printf("sigreturn: cs = 0x%x\n", scp->sc_cs);
 #endif
-		trapsignal(p, SIGBUS, T_PROTFLT);
-		return(EINVAL);
+			trapsignal(p, SIGBUS, T_PROTFLT);
+			return(EINVAL);
+		}
+		regs[tDS] = scp->sc_ds;
+		regs[tES] = scp->sc_es;
 	}
-
 	/* restore scratch registers */
 	regs[tEAX] = scp->sc_eax;
 	regs[tEBX] = scp->sc_ebx;
@@ -611,13 +687,11 @@
 	regs[tESI] = scp->sc_esi;
 	regs[tEDI] = scp->sc_edi;
 	regs[tCS] = scp->sc_cs;
-	regs[tDS] = scp->sc_ds;
-	regs[tES] = scp->sc_es;
 	regs[tSS] = scp->sc_ss;
 	regs[tISP] = scp->sc_isp;
 
 	if (useracc((caddr_t)scp, sizeof (*scp), B_WRITE) == 0)
-		return(EINVAL);
+		return(EFAULT);
 
 	if (scp->sc_onstack & 01)
 		p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
@@ -632,7 +706,7 @@
 }
 
 /*
- * Machine depdnetnt boot() routine
+ * Machine dependent boot() routine
  *
  * I haven't seen anything too put here yet
  * Possibly some stuff might be grafted back here from boot()
@@ -1295,7 +1369,8 @@
 	msgbufmapped = 1;
 
 	/* make a initial tss so microp can get interrupt stack on syscall! */
-	proc0.p_addr->u_pcb.pcb_tss.tss_esp0 = (int) kstack + UPAGES*PAGE_SIZE;
+	proc0.p_addr->u_pcb.pcb_tss.tss_esp0 = (int) kstack + 
+	    UPAGES * PAGE_SIZE - (4 * 4);
 	proc0.p_addr->u_pcb.pcb_tss.tss_ss0 = GSEL(GDATA_SEL, SEL_KPL) ;
 	gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
 
--- ./i386/sys_machdep.c.orig	Thu Dec 12 08:51:23 1996
+++ ./i386/sys_machdep.c	Mon Mar 17 18:07:21 1997
@@ -50,11 +50,15 @@
 #include <vm/vm_extern.h>
 
 #include <sys/user.h>
+#include <sys/signal.h>
+#include <sys/signalvar.h>
 
 #include <machine/cpu.h>
 #include <machine/sysarch.h>
+#include <machine/psl.h>
 
 #include <vm/vm_kern.h>		/* for kernel_map */
+#include <machine/vm86.h>	/* For v86 definitions */
 
 #define MAX_LD 8192
 #define LD_PER_PAGE 512
@@ -94,6 +98,9 @@
 		error = i386_set_ldt(p, uap->parms, retval);
 		break;
 #endif
+	case I386_VM86:
+		error = i386_vm86(p, uap->parms, retval);
+		break;
 	default:
 		error = EINVAL;
 		break;
@@ -308,3 +315,72 @@
 	return(error);
 }
 #endif	/* USER_LDT */
+
+int
+i386_vm86(struct proc *p, void *args, int *retval) {
+	struct trapframe_vm86 *tf_v86 = (struct trapframe_vm86*)p->p_md.md_regs;
+/*	struct trapframe_vm86 tf_v86; */
+	struct pcb *pcb = &p->p_addr->u_pcb;
+	struct vm86_kern v_arg;
+	int error;
+
+/* debugging - jlemon */
+printf("i386_vm86() called\n");
+
+	if (error = copyin(args, &v_arg, sizeof(v_arg)))
+		return error;
+/*	bcopy(tf, &tf_v86, sizeof(*tf)); */
+	pcb->vm86_userp = (void*)args;
+
+	/*
+	 * What kind of CPU do we want to emulate?
+	 * 286 and less can't set or clear anything;
+	 * 386 can set/clear the NT and IOPL bits;
+	 * 486 can set/clear alignment checking (AC);
+	 * 586 can set/clear alignment bit as well.
+	 */
+
+	switch (v_arg.ss_cpu_type) {
+	case VCPU_086:
+	case VCPU_186:
+	case VCPU_286:
+		pcb->vm86_flagmask = 0;
+		break;
+	case VCPU_386:
+		pcb->vm86_flagmask = PSL_NT | PSL_IOPL;
+		break;
+	case VCPU_486:
+		pcb->vm86_flagmask = PSL_AC | PSL_NT | PSL_IOPL;
+		break;
+	case VCPU_586:
+	default:
+		pcb->vm86_flagmask = PSL_ID | PSL_AC | PSL_NT | PSL_IOPL;
+		break;
+	}
+
+	/* Assign the registers the way we're told... */
+#define VREG(reg) tf_v86->tf_vm86_##reg = (u_short) v_arg.regs.vmsc.sc_##reg
+#define REG(reg) tf_v86->tf_##reg = (u_short) v_arg.regs.vmsc.sc_##reg
+	VREG(ds);
+	VREG(es);
+	VREG(fs);
+	VREG(gs);
+	REG(edi);
+	REG(esi);
+	REG(ebp);
+	REG(eax);
+	REG(ebx);
+	REG(ecx);
+	REG(edx);
+	REG(eip);
+	REG(cs);
+	REG(esp);
+	REG(ss);
+#undef	DOVREG
+#undef	DOREG
+
+	/* Don't give a signal stack to v86 processes... */
+	p->p_sigacts->ps_sigstk.ss_flags &= ~SA_ONSTACK;
+
+	return EJUSTRETURN;
+}
--- ./i386/trap.c.orig	Wed Feb 12 23:51:53 1997
+++ ./i386/trap.c	Mon Mar 17 18:07:21 1997
@@ -192,7 +192,7 @@
 	type = frame.tf_trapno;
 	code = frame.tf_err;
 
-	if (ISPL(frame.tf_cs) == SEL_UPL) {
+        if ((ISPL(frame.tf_cs) == SEL_UPL) || (frame.tf_eflags & PSL_VM)) {
 		/* user trap */
 
 		sticks = p->p_sticks;
@@ -225,9 +225,26 @@
 			}
 			goto out;
 
+			/*
+			 * The following two traps can happen in
+			 * vm86 mode, and, if so, we want to handle
+			 * them specially.
+			 */
 		case T_PROTFLT:		/* general protection fault */
-		case T_SEGNPFLT:	/* segment not present fault */
 		case T_STKFLT:		/* stack fault */
+			if (frame.tf_eflags & PSL_VM) {
+#if 0
+/*printf("Gonna call emulate_vm86()\n");*/
+			    i = emulate_vm86((struct trapframe_vm86 *)&frame);
+#else
+				i = SIGBUS;
+#endif
+			    if (i == 0)
+				goto out;
+			    break;
+			}
+
+		case T_SEGNPFLT:	/* segment not present fault */
 		case T_TSSFLT:		/* invalid TSS fault */
 		case T_DOUBLEFLT:	/* double fault */
 		default:
@@ -925,7 +942,10 @@
 		break;
 	}
 
+/*
 	if (frame.tf_eflags & PSL_T) {
+*/
+	if ((frame.tf_eflags & PSL_T) && !(frame.tf_eflags & PSL_VM)) {
 		/* Traced syscall. */
 		frame.tf_eflags &= ~PSL_T;
 		trapsignal(p, SIGTRAP, 0);
@@ -937,4 +957,148 @@
 	if (KTRPOINT(p, KTR_SYSRET))
 		ktrsysret(p->p_tracep, code, error, rval[0]);
 #endif
+}
+
+struct vconnect_area {
+        int     int_state;
+        int     magic;                  /* 0x4242 -> PRB format */ 
+        u_long  passthru[256>>5];       /* bitmap of INTs to handle */ 
+        u_long  magiciret[2];           /* Bounds of "magic" IRET */
+};    
+
+#define need_interrupt  magic           /* Russian compatibility */
+#define PRB_V86_FORMAT  0x4242
+
+#define	CLI	0xfa
+#define	STI	0xfb
+#define	PUSHF	0x9c
+#define	POPF	0x9d
+#define	INTn	0xcd
+#define	IRET	0xcf
+#define tf_sp	tf_esp
+#define tf_ip	tf_eip
+#define tf_eflags86	tf_eflags
+inline static int
+MAKE_ADDR(int sel, int off)
+{
+
+	return ((sel << 4) + off);
+}
+
+inline static void
+PUSH(u_short x, struct trapframe_vm86 *frame)
+{
+
+	frame->tf_sp -= 2;
+	susword((void *) MAKE_ADDR(frame->tf_ss, frame->tf_sp), x);
+}
+
+inline static u_short
+POP(struct trapframe_vm86 *frame)
+{
+	u_short x = fusword((void *) MAKE_ADDR(frame->tf_ss, frame->tf_sp));
+
+	frame->tf_sp += 2;
+	return (x);
+}
+
+static int
+emulate_vm86(tf)
+	struct trapframe_vm86 *tf;
+{
+	int intnum, addr;
+	int int_state, old_int_state;
+    	int magic;
+	struct proc *p = curproc;
+	struct pcb *pcb = &p->p_addr->u_pcb;
+	struct vconnect_area *connect_area;
+
+	addr = MAKE_ADDR(tf->tf_cs, tf->tf_ip);
+
+	if (p->p_md.md_connarea == (void *) -1)
+		return (SIGBUS);
+	connect_area = (struct vconnect_area *)p->p_md.md_connarea;
+	old_int_state = int_state = fusword((void *)&connect_area->int_state);
+        magic = fusword((void *)&connect_area->magic);
+	switch (fubyte((void *)addr)) {
+	case CLI:
+#if 1
+printf ("emulate_vm86:  cli\n");
+#endif
+		pcb->vm86_eflags &= ~PSL_I;
+		tf->tf_ip++;
+		return 0;
+	case STI:
+printf ("emulate_vm86:  sti\n");
+		pcb->vm86_eflags |= PSL_I;
+		tf->tf_ip++;
+		/* XXX -- need to check for pending interrupt */
+		return 0;
+	case PUSHF:
+printf("emulate_vm86:  pushf\n");
+		PUSH((tf->tf_eflags86 & ~PSL_I) |
+		     (pcb->vm86_eflags & PSL_I) | PSL_IOPL, tf);
+		tf->tf_ip++;
+		return 0;
+	case POPF:
+printf("emulate_vm86:  popf\n");
+		int_state = POP(tf);
+		tf->tf_eflags86 = (int_state & ~PSL_IOPL) | PSL_I;
+		pcb->vm86_eflags = int_state & PSL_I;
+		tf->tf_ip++;
+		return 0;
+	}
+	/*printf("emulate_vm86:  none of the above\n"); */
+	if (p->p_md.md_connarea == (void *) -1)
+		return (SIGBUS);
+	connect_area = (struct vconnect_area *)p->p_md.md_connarea;
+	old_int_state = int_state = fusword((void *)&connect_area->int_state);
+        magic = fusword((void *)&connect_area->magic);
+
+	switch (fubyte((void *)addr)) {
+	case INTn:
+		intnum = fubyte((void *)(addr + 1));
+                if (magic == PRB_V86_FORMAT) {
+                    u_long pt;
+                    pt = fuword((void *)&connect_area->passthru[intnum>>5]);
+                    if ((pt & (1 << (intnum & 0x1f))) == 0)
+                        return(SIGBUS);
+                }
+		PUSH((tf->tf_eflags86 & ~PSL_I) | int_state | PSL_IOPL, tf);
+		PUSH(tf->tf_cs, tf);
+		PUSH(tf->tf_ip + 2, tf);
+		int_state = 0;
+		tf->tf_eflags86 &= ~PSL_T;
+		tf->tf_cs = fuword((void *)(intnum * 4 + 2));
+		tf->tf_ip = fuword((void *)(intnum * 4));
+		break;
+	case IRET:
+                if (magic == PRB_V86_FORMAT) {
+                    /*
+                     * magiciret[] gives a range of memory in
+                     * which we must return the IRET to the
+                     * emulator
+                     */
+                    u_long ia = (tf->tf_cs << 16) | tf->tf_ip;
+                    if (   fuword((void *)&connect_area->magiciret[0]) <= ia
+                        && fuword((void *)&connect_area->magiciret[1]) >= ia)
+                            return(SIGBUS);
+                }
+		tf->tf_ip = POP(tf);
+		tf->tf_cs = POP(tf);
+		int_state = POP(tf);
+		tf->tf_eflags86 = (int_state & ~PSL_IOPL) | PSL_I;
+		int_state &= PSL_I;
+		break;
+	default:
+		return (SIGBUS);
+	}
+	if (old_int_state != int_state)
+		susword((void *)&connect_area->int_state, int_state);
+	if (old_int_state == 0 && int_state == PSL_I &&
+            magic != PRB_V86_FORMAT &&
+	    fusword((void *)&connect_area->need_interrupt))
+		return (SIGIO);
+	else
+		return (0);
 }
--- ./i386/vm_machdep.c.orig	Wed Jan  1 18:21:09 1997
+++ ./i386/vm_machdep.c	Mon Mar 17 18:07:21 1997
@@ -594,6 +594,8 @@
 	bcopy((caddr_t)kstack + offset, (caddr_t)p2->p_addr + offset,
 	    (unsigned) ctob(UPAGES) - offset);
 	p2->p_md.md_regs = p1->p_md.md_regs;
+	p2->p_md.md_connarea = p1->p_md.md_connarea;
+	p2->p_md.md_flags = p1->p_md.md_flags;
 
 	*pcb2 = p1->p_addr->u_pcb;
 	pcb2->pcb_cr3 = vtophys(p2->p_vmspace->vm_pmap.pm_pdir);
--- ./i386/exception.s.orig	Sun Aug 11 10:41:23 1996
+++ ./i386/exception.s	Fri Mar 28 20:24:43 1997
@@ -176,6 +176,8 @@
 	subl	%eax,%eax
 	testb	$SEL_RPL_MASK,TRAPF_CS_OFF(%esp)
 	jne	1f
+	testl	$PSL_VM,TF_EFLAGS(%esp)
+	jne	1f
 	movl	_cpl,%eax
 1:
 	/*
--- ./include/frame.h.orig	Tue Jan 30 14:54:27 1996
+++ ./include/frame.h	Mon Mar 17 18:07:22 1997
@@ -72,6 +72,35 @@
 	int	tf_ss;
 };
 
+/* Superset of trap frame, for traps from virtual-8086 mode */
+
+struct trapframe_vm86 {
+	int	tf_es;
+	int	tf_ds;
+	int	tf_edi;
+	int	tf_esi;
+	int	tf_ebp;
+	int	tf_isp;
+	int	tf_ebx;
+	int	tf_edx;
+	int	tf_ecx;
+	int	tf_eax;
+	int	tf_trapno;
+	/* below portion defined in 386 hardware */
+	int	tf_err;
+	int	tf_eip;
+	int	tf_cs;
+	int	tf_eflags;
+	/* below only when crossing rings (e.g. user to kernel) */
+	int	tf_esp;
+	int	tf_ss;
+	/* below only when switching out of VM86 mode */
+	int	tf_vm86_es;
+	int	tf_vm86_ds;
+	int	tf_vm86_fs;
+	int	tf_vm86_gs;
+};
+
 /* Interrupt stack frame */
 
 struct intrframe {
--- ./include/pcb.h.orig	Wed Jul 31 05:35:36 1996
+++ ./include/pcb.h	Mon Mar 17 18:07:22 1997
@@ -67,6 +67,9 @@
 	u_char	pcb_flags;
 #define	FP_SOFTFP	0x01	/* process using software fltng pnt emulator */
 	caddr_t	pcb_onfault;	/* copyin/out fault recovery */
+        int	vm86_eflags;	/* Flags for v86 mode dickery */
+        int	vm86_flagmask;	/* Mask for flags registers */
+        struct	vm86_struct	*vm86_userp;
 };
 
 /*
--- ./include/proc.h.orig	Tue Apr  9 22:26:26 1996
+++ ./include/proc.h	Mon Mar 17 18:07:22 1997
@@ -43,6 +43,7 @@
 struct mdproc {
 	int	md_flags;		/* machine-dependent flags */
 	int	*md_regs;		/* registers on current frame */
+	void	*md_connarea;		/* for vm86 */
 };
 
 /* md_flags */
--- ./include/psl.h.orig	Tue Jan 30 14:54:50 1996
+++ ./include/psl.h	Mon Mar 17 18:07:22 1997
@@ -83,6 +83,6 @@
  * 386's.
  */
 #define	PSL_USERCHANGE (PSL_C | PSL_PF | PSL_AF | PSL_Z | PSL_N | PSL_T \
-			| PSL_D | PSL_V | PSL_NT | PSL_AC)
+			| PSL_D | PSL_V | PSL_NT | PSL_AC | PSL_VM)
 
 #endif /* !_MACHINE_PSL_H_ */
--- ./include/reg.h.orig	Tue Jan 30 14:54:56 1996
+++ ./include/reg.h	Mon Mar 17 18:07:22 1997
@@ -59,7 +59,7 @@
 #define	tEDX	(7)
 #define	tECX	(8)
 #define	tEAX	(9)
-
+#define tTRAPNO	(10)
 #define	tERR	(11)
 
 #define	tEIP	(12)
--- ./include/signal.h.orig	Tue Jun 27 19:14:13 1995
+++ ./include/signal.h	Mon Mar 17 18:07:22 1997
@@ -72,10 +72,15 @@
 	int	sc_edx;
 	int	sc_ecx;
 	int	sc_eax;
+	int	sc_gs;
+	int	sc_fs;
 #  define sc_sp sc_esp
 #  define sc_fp sc_ebp
 #  define sc_pc sc_eip
 #  define sc_ps sc_efl
+#  define sc_eflags	sc_efl
+	int	sc_trapno;
+	int	sc_err;
 };
 
 #endif /* !_ANSI_SOURCE && !_POSIX_SOURCE */
--- ./include/sysarch.h.orig	Tue Aug  2 00:39:11 1994
+++ ./include/sysarch.h	Mon Mar 17 18:07:22 1997
@@ -43,6 +43,10 @@
 
 #define I386_GET_LDT	0
 #define I386_SET_LDT	1
+#define	I386_IOPL	2
+#define	I386_GET_IOPERM	3
+#define I386_SET_IOPERM	4
+#define	I386_VM86	6
 
 #ifdef KERNEL
 /* nothing here yet... */
--- ./include/vm86.h.orig	Mon Mar 17 18:07:22 1997
+++ ./include/vm86.h	Mon Mar 17 18:07:22 1997
@@ -0,0 +1,47 @@
+#ifndef _MACHINE_VM86_H
+# define _MACHINE_VM86_H
+
+#define VM86_TYPE(x)	((x) & 0xff)
+#define VM86_ARG(x)	(((x) & 0xff00) >> 8)
+#define	VM86_MAKEVAL(type,arg) ((type) | (((arg) & 0xff) << 8))
+#define		VM86_STI	0
+#define		VM86_INTx	1
+#define		VM86_SIGNAL	2
+#define		VM86_UNKNOWN	3
+
+#define	VM86_SETDIRECT	(~PSL_USERSTATIC)
+#define	VM86_GETDIRECT	(VM86_SETDIRECT|PSL_MBO|PSL_MBZ)
+
+struct vm86_regs {
+  struct sigcontext vmsc;
+};
+
+struct vm86_kern {
+  struct vm86_regs regs;
+  unsigned long ss_cpu_type;
+};
+#define cpu_type substr.ss_cpu_type
+
+struct vm86_struct {
+  struct vm86_kern substr;
+  unsigned long screen_bitmap;	/* XXX -- what is this for?! */
+  unsigned long flags;
+  unsigned char int_byuser[32];	/* Bitmap of interrupts user wants to handle */
+  unsigned char int21_byuser[32]; /* Same, for int21 functions */
+};
+
+#define	VM86_STI	0
+#define	VM86_INTxx	1
+#define	VM86_SIGNAL	2
+#define	VM86_UNKNOWN	3
+
+#define BIOSSEG		0x0f000
+
+#define VCPU_086		0
+#define VCPU_186		1
+#define VCPU_286		2
+#define VCPU_386		3
+#define VCPU_486		4
+#define VCPU_586		5
+
+#endif /* _MACHINE_VM86_H */
--- ./isa/icu.s.orig	Sun Dec 29 14:06:49 1996
+++ ./isa/icu.s	Fri Mar 28 20:24:43 1997
@@ -180,6 +180,7 @@
 	addl	$8,%esp			/* discard raddr & cpl to get trap frame */
 	testb	$SEL_RPL_MASK,TRAPF_CS_OFF(%esp)
 	je	swi_ast_phantom
+swi_ast_user:
 	movl	$T_ASTFLT,(2+8+0)*4(%esp)
 	movb	$0,_intr_nesting_level	/* finish becoming a trap handler */
 	call	_trap
@@ -189,6 +190,12 @@
 
 	ALIGN_TEXT
 swi_ast_phantom:
+	/*
+	 * check for ast from vm86 mode.  Placed down here so the jumps
+	 * do not get taken for mainline code.
+	 */
+	testl	$PSL_VM,TF_EFLAGS(%esp)
+	jne	swi_ast_user
 	/*
 	 * These happen when there is an interrupt in a trap handler before
 	 * ASTs can be masked or in an lcall handler before they can be
--- ./isa/npx.c.orig	Wed Feb 12 22:59:51 1997
+++ ./isa/npx.c	Fri Mar 28 20:24:43 1997
@@ -56,6 +56,7 @@
 
 #include <machine/cpu.h>
 #include <machine/pcb.h>
+#include <machine/psl.h>
 #include <machine/md_var.h>
 #include <machine/trap.h>
 #include <machine/clock.h>
@@ -479,7 +480,7 @@
 	 * Pass exception to process.
 	 */
 	frame = (struct intrframe *)&unit;	/* XXX */
-	if (ISPL(frame->if_cs) == SEL_UPL) {
+	if ((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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199703290429.UAA14152>