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>
