diff options
Diffstat (limited to 'i386/i386/trap.c')
-rw-r--r-- | i386/i386/trap.c | 484 |
1 files changed, 0 insertions, 484 deletions
diff --git a/i386/i386/trap.c b/i386/i386/trap.c index 2cb81e6..3b51b1a 100644 --- a/i386/i386/trap.c +++ b/i386/i386/trap.c @@ -50,8 +50,6 @@ #include <kern/sched.h> #include <kern/sched_prim.h> -#include <i386/io_emulate.h> - #if MACH_KDB #include <ddb/db_run.h> #include <ddb/db_watch.h> @@ -385,15 +383,6 @@ int user_trap(regs) printf("user trap %d error %d sub %08x\n", type, code, subcode); #endif - if (regs->efl & EFL_VM) { - /* - * If hardware assist can handle exception, - * continue execution. - */ - if (v86_assist(thread, regs)) - return 0; - } - type = regs->trapno; code = 0; subcode = 0; @@ -497,10 +486,6 @@ printf("user trap %d error %d sub %08x\n", type, code, subcode); break; case T_GENERAL_PROTECTION: - if (!(regs->efl & EFL_VM)) { - if (check_io_fault(regs)) - return 0; - } /* Check for an emulated int80 system call. NetBSD-current and Linux use trap instead of call gate. */ if (thread->task->eml_dispatch) { @@ -585,400 +570,6 @@ boolean_t v86_do_sti_immediate = FALSE; int cli_count = 0; int sti_count = 0; -boolean_t -v86_assist(thread, regs) - thread_t thread; - register struct i386_saved_state *regs; -{ - register struct v86_assist_state *v86 = &thread->pcb->ims.v86s; - -/* - * Build an 8086 address. Use only when off is known to be 16 bits. - */ -#define Addr8086(seg,off) ((((seg) & 0xffff) << 4) + (off)) - -#define EFL_V86_SAFE ( EFL_OF | EFL_DF | EFL_TF \ - | EFL_SF | EFL_ZF | EFL_AF \ - | EFL_PF | EFL_CF ) - struct iret_32 { - int eip; - int cs; - int eflags; - }; - struct iret_16 { - unsigned short ip; - unsigned short cs; - unsigned short flags; - }; - union iret_struct { - struct iret_32 iret_32; - struct iret_16 iret_16; - }; - - struct int_vec { - unsigned short ip; - unsigned short cs; - }; - - if (!v86_assist_on) - return FALSE; - - /* - * If delayed STI pending, enable interrupts. - * Turn off tracing if on only to delay STI. - */ - if (v86->flags & V86_IF_PENDING) { - v86->flags &= ~V86_IF_PENDING; - v86->flags |= EFL_IF; - if ((v86->flags & EFL_TF) == 0) - regs->efl &= ~EFL_TF; - } - - if (regs->trapno == T_DEBUG) { - - if (v86->flags & EFL_TF) { - /* - * Trace flag was also set - it has priority - */ - return FALSE; /* handle as single-step */ - } - /* - * Fall through to check for interrupts. - */ - } - else if (regs->trapno == T_GENERAL_PROTECTION) { - /* - * General protection error - must be an 8086 instruction - * to emulate. - */ - register int eip; - boolean_t addr_32 = FALSE; - boolean_t data_32 = FALSE; - int io_port; - - /* - * Set up error handler for bad instruction/data - * fetches. - */ - asm("movl $(addr_error), %0" : "=m" (thread->recover)); - - eip = regs->eip; - while (TRUE) { - unsigned char opcode; - - if (eip > 0xFFFF) { - thread->recover = 0; - return FALSE; /* GP fault: IP out of range */ - } - - opcode = *(unsigned char *)Addr8086(regs->cs,eip); - eip++; - switch (opcode) { - case 0xf0: /* lock */ - case 0xf2: /* repne */ - case 0xf3: /* repe */ - case 0x2e: /* cs */ - case 0x36: /* ss */ - case 0x3e: /* ds */ - case 0x26: /* es */ - case 0x64: /* fs */ - case 0x65: /* gs */ - /* ignore prefix */ - continue; - - case 0x66: /* data size */ - data_32 = TRUE; - continue; - - case 0x67: /* address size */ - addr_32 = TRUE; - continue; - - case 0xe4: /* inb imm */ - case 0xe5: /* inw imm */ - case 0xe6: /* outb imm */ - case 0xe7: /* outw imm */ - io_port = *(unsigned char *)Addr8086(regs->cs, eip); - eip++; - goto do_in_out; - - case 0xec: /* inb dx */ - case 0xed: /* inw dx */ - case 0xee: /* outb dx */ - case 0xef: /* outw dx */ - case 0x6c: /* insb */ - case 0x6d: /* insw */ - case 0x6e: /* outsb */ - case 0x6f: /* outsw */ - io_port = regs->edx & 0xffff; - - do_in_out: - if (!data_32) - opcode |= 0x6600; /* word IO */ - - switch (emulate_io(regs, opcode, io_port)) { - case EM_IO_DONE: - /* instruction executed */ - break; - case EM_IO_RETRY: - /* port mapped, retry instruction */ - thread->recover = 0; - return TRUE; - case EM_IO_ERROR: - /* port not mapped */ - thread->recover = 0; - return FALSE; - } - break; - - case 0xfa: /* cli */ - if (!v86_do_sti_cli) { - thread->recover = 0; - return (FALSE); - } - - v86->flags &= ~EFL_IF; - /* disable simulated interrupts */ - cli_count++; - break; - - case 0xfb: /* sti */ - if (!v86_do_sti_cli) { - thread->recover = 0; - return (FALSE); - } - - if ((v86->flags & EFL_IF) == 0) { - if (v86_do_sti_immediate) { - v86->flags |= EFL_IF; - } else { - v86->flags |= V86_IF_PENDING; - regs->efl |= EFL_TF; - } - /* single step to set IF next inst. */ - } - sti_count++; - break; - - case 0x9c: /* pushf */ - { - int flags; - vm_offset_t sp; - int size; - - flags = regs->efl; - if ((v86->flags & EFL_IF) == 0) - flags &= ~EFL_IF; - - if ((v86->flags & EFL_TF) == 0) - flags &= ~EFL_TF; - else flags |= EFL_TF; - - sp = regs->uesp; - if (!addr_32) - sp &= 0xffff; - else if (sp > 0xffff) - goto stack_error; - size = (data_32) ? 4 : 2; - if (sp < size) - goto stack_error; - sp -= size; - if (copyout((char *)&flags, - (char *)Addr8086(regs->ss,sp), - size)) - goto addr_error; - if (addr_32) - regs->uesp = sp; - else - regs->uesp = (regs->uesp & 0xffff0000) | sp; - break; - } - - case 0x9d: /* popf */ - { - vm_offset_t sp; - int nflags; - - sp = regs->uesp; - if (!addr_32) - sp &= 0xffff; - else if (sp > 0xffff) - goto stack_error; - - if (data_32) { - if (sp > 0xffff - sizeof(int)) - goto stack_error; - nflags = *(int *)Addr8086(regs->ss,sp); - sp += sizeof(int); - } - else { - if (sp > 0xffff - sizeof(short)) - goto stack_error; - nflags = *(unsigned short *) - Addr8086(regs->ss,sp); - sp += sizeof(short); - } - if (addr_32) - regs->uesp = sp; - else - regs->uesp = (regs->uesp & 0xffff0000) | sp; - - if (v86->flags & V86_IRET_PENDING) { - v86->flags = nflags & (EFL_TF | EFL_IF); - v86->flags |= V86_IRET_PENDING; - } else { - v86->flags = nflags & (EFL_TF | EFL_IF); - } - regs->efl = (regs->efl & ~EFL_V86_SAFE) - | (nflags & EFL_V86_SAFE); - break; - } - case 0xcf: /* iret */ - { - vm_offset_t sp; - int nflags; - union iret_struct iret_struct; - - v86->flags &= ~V86_IRET_PENDING; - sp = regs->uesp; - if (!addr_32) - sp &= 0xffff; - else if (sp > 0xffff) - goto stack_error; - - if (data_32) { - if (sp > 0xffff - sizeof(struct iret_32)) - goto stack_error; - iret_struct.iret_32 = - *(struct iret_32 *) Addr8086(regs->ss,sp); - sp += sizeof(struct iret_32); - } - else { - if (sp > 0xffff - sizeof(struct iret_16)) - goto stack_error; - iret_struct.iret_16 = - *(struct iret_16 *) Addr8086(regs->ss,sp); - sp += sizeof(struct iret_16); - } - if (addr_32) - regs->uesp = sp; - else - regs->uesp = (regs->uesp & 0xffff0000) | sp; - - if (data_32) { - eip = iret_struct.iret_32.eip; - regs->cs = iret_struct.iret_32.cs & 0xffff; - nflags = iret_struct.iret_32.eflags; - } - else { - eip = iret_struct.iret_16.ip; - regs->cs = iret_struct.iret_16.cs; - nflags = iret_struct.iret_16.flags; - } - - v86->flags = nflags & (EFL_TF | EFL_IF); - regs->efl = (regs->efl & ~EFL_V86_SAFE) - | (nflags & EFL_V86_SAFE); - break; - } - default: - /* - * Instruction not emulated here. - */ - thread->recover = 0; - return FALSE; - } - break; /* exit from 'while TRUE' */ - } - regs->eip = (regs->eip & 0xffff0000 | eip); - } - else { - /* - * Not a trap we handle. - */ - thread->recover = 0; - return FALSE; - } - - if ((v86->flags & EFL_IF) && ((v86->flags & V86_IRET_PENDING)==0)) { - - struct v86_interrupt_table *int_table; - int int_count; - int vec; - int i; - - int_table = (struct v86_interrupt_table *) v86->int_table; - int_count = v86->int_count; - - vec = 0; - for (i = 0; i < int_count; int_table++, i++) { - if (!int_table->mask && int_table->count > 0) { - int_table->count--; - vec = int_table->vec; - break; - } - } - if (vec != 0) { - /* - * Take this interrupt - */ - vm_offset_t sp; - struct iret_16 iret_16; - struct int_vec int_vec; - - sp = regs->uesp & 0xffff; - if (sp < sizeof(struct iret_16)) - goto stack_error; - sp -= sizeof(struct iret_16); - iret_16.ip = regs->eip; - iret_16.cs = regs->cs; - iret_16.flags = regs->efl & 0xFFFF; - if ((v86->flags & EFL_TF) == 0) - iret_16.flags &= ~EFL_TF; - else iret_16.flags |= EFL_TF; - -#ifdef gcc_1_36_worked - int_vec = ((struct int_vec *)0)[vec]; -#else - memcpy(&int_vec, - (void *)(sizeof(struct int_vec) * vec), - sizeof (struct int_vec)); -#endif - if (copyout((char *)&iret_16, - (char *)Addr8086(regs->ss,sp), - sizeof(struct iret_16))) - goto addr_error; - regs->uesp = (regs->uesp & 0xFFFF0000) | (sp & 0xffff); - regs->eip = int_vec.ip; - regs->cs = int_vec.cs; - regs->efl &= ~EFL_TF; - v86->flags &= ~(EFL_IF | EFL_TF); - v86->flags |= V86_IRET_PENDING; - } - } - - thread->recover = 0; - return TRUE; - - /* - * On address error, report a page fault. - * XXX report GP fault - we don`t save - * the faulting address. - */ - addr_error: - asm("addr_error:;"); - thread->recover = 0; - return FALSE; - - /* - * On stack address error, return stack fault (12). - */ - stack_error: - thread->recover = 0; - regs->trapno = T_STACK_FAULT; - return FALSE; -} - /* * Handle AST traps for i386. * Check for delayed floating-point exception from @@ -1039,81 +630,6 @@ i386_exception(exc, code, subcode) /*NOTREACHED*/ } -boolean_t -check_io_fault(regs) - struct i386_saved_state *regs; -{ - int eip, opcode, io_port; - boolean_t data_16 = FALSE; - - /* - * Get the instruction. - */ - eip = regs->eip; - - for (;;) { - opcode = inst_fetch(eip, regs->cs); - eip++; - switch (opcode) { - case 0x66: /* data-size prefix */ - data_16 = TRUE; - continue; - - case 0xf3: /* rep prefix */ - case 0x26: /* es */ - case 0x2e: /* cs */ - case 0x36: /* ss */ - case 0x3e: /* ds */ - case 0x64: /* fs */ - case 0x65: /* gs */ - continue; - - case 0xE4: /* inb imm */ - case 0xE5: /* inl imm */ - case 0xE6: /* outb imm */ - case 0xE7: /* outl imm */ - /* port is immediate byte */ - io_port = inst_fetch(eip, regs->cs); - eip++; - break; - - case 0xEC: /* inb dx */ - case 0xED: /* inl dx */ - case 0xEE: /* outb dx */ - case 0xEF: /* outl dx */ - case 0x6C: /* insb */ - case 0x6D: /* insl */ - case 0x6E: /* outsb */ - case 0x6F: /* outsl */ - /* port is in DX register */ - io_port = regs->edx & 0xFFFF; - break; - - default: - return FALSE; - } - break; - } - - if (data_16) - opcode |= 0x6600; /* word IO */ - - switch (emulate_io(regs, opcode, io_port)) { - case EM_IO_DONE: - /* instruction executed */ - regs->eip = eip; - return TRUE; - - case EM_IO_RETRY: - /* port mapped, retry instruction */ - return TRUE; - - case EM_IO_ERROR: - /* port not mapped */ - return FALSE; - } -} - #if MACH_PCSAMPLE > 0 /* * return saved state for interrupted user thread |