Author: sir_richard Date: Mon Jan 11 06:53:57 2010 New Revision: 45038
URL: http://svn.reactos.org/svn/reactos?rev=45038&view=rev Log: Trap handlers in C patch 7 of X: [NTOS]: Implement GPF handler (trap 13) in C. This was by far the most complex one of them, since it also servces two complex purposes: to handle V86 emulation since the real-mode code will generate GPFs during privileged instructions, and it will detect an illegal IRET, check if it's the known V8086 Exit IRET, and then jump to V86 exit code. [NTOS]: Get rid of even more V8086 assembly since the GPF handler is now C. Deleted the entire V8086 assembly file. [NTOS]: Get rid of a bunch of helper ASM functions that nobody is using anymore since almost all the trap handlers are in C.
Removed: trunk/reactos/ntoskrnl/ke/i386/v86m_sup.S Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S trunk/reactos/ntoskrnl/ke/i386/trap.s trunk/reactos/ntoskrnl/ke/i386/traphdlr.c trunk/reactos/ntoskrnl/ke/i386/v86vdm.c trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/i... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/i386/ke.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/i386/ke.h [iso-8859-1] Mon Jan 11 06:53:57 2010 @@ -406,6 +406,12 @@ VOID FASTCALL KiEoiHelper( + IN PKTRAP_FRAME TrapFrame +); + +VOID +FASTCALL +KiExitV86Mode( IN PKTRAP_FRAME TrapFrame );
@@ -518,5 +524,20 @@ (DrAddress <= MM_HIGHEST_USER_ADDRESS) ? DrAddress : 0); }
+FORCEINLINE +VOID +KiV86TrapReturn(IN ULONG_PTR Stack) +{ + /* Restore volatiles and stack */ + __asm__ __volatile__ + ( + "movl %0, %%esp\n" + "popa\n" + "ret\n" + : + : "r"(Stack) + : "%esp" + ); +} #endif #endif /* __NTOSKRNL_INCLUDE_INTERNAL_I386_KE_H */
Modified: trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/ctxswitch.... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S [iso-8859-1] Mon Jan 11 06:53:57 2010 @@ -864,3 +864,13 @@ int 3 #endif .endfunc + +.globl _Ki386SetupAndExitToV86Mode@4 +.func Ki386SetupAndExitToV86Mode@4 +_Ki386SetupAndExitToV86Mode@4: + + /* Enter V8086 mode */ + pushad + call @KiEnterV86Mode@0 +.endfunc +
Modified: trunk/reactos/ntoskrnl/ke/i386/trap.s URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/trap.s?rev... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/trap.s [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ke/i386/trap.s [iso-8859-1] Mon Jan 11 06:53:57 2010 @@ -573,95 +573,6 @@ jmp _KiServiceExit .endfunc
-/* EXCEPTION DISPATCHERS *****************************************************/ - -.func CommonDispatchException -_CommonDispatchException: - - /* Make space for an exception record */ - sub esp, EXCEPTION_RECORD_LENGTH - - /* Set it up */ - mov [esp+EXCEPTION_RECORD_EXCEPTION_CODE], eax - xor eax, eax - mov [esp+EXCEPTION_RECORD_EXCEPTION_FLAGS], eax - mov [esp+EXCEPTION_RECORD_EXCEPTION_RECORD], eax - mov [esp+EXCEPTION_RECORD_EXCEPTION_ADDRESS], ebx - mov [esp+EXCEPTION_RECORD_NUMBER_PARAMETERS], ecx - - /* Check parameter count */ - cmp ecx, 0 - jz NoParams - - /* Get information */ - lea ebx, [esp+SIZEOF_EXCEPTION_RECORD] - mov [ebx], edx - mov [ebx+4], esi - mov [ebx+8], edi - -NoParams: - - /* Set the record in ECX and check if this was V86 */ - mov ecx, esp - test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK - jz SetPreviousMode - - /* Set V86 mode */ - mov eax, 0xFFFF - jmp MaskMode - -SetPreviousMode: - - /* Get the caller's CS */ - mov eax, [ebp+KTRAP_FRAME_CS] - -MaskMode: - /* Check if it was user-mode or kernel-mode */ - and eax, MODE_MASK - - /* Dispatch the exception */ - push 1 - push eax - push ebp - push 0 - push ecx - call _KiDispatchException@20 - - /* End the trap */ - mov esp, ebp - jmp _Kei386EoiHelper@0 -.endfunc - -.func DispatchNoParam -_DispatchNoParam: - /* Call the common dispatcher */ - xor ecx, ecx - call _CommonDispatchException -.endfunc - -.func DispatchOneParamZero -_DispatchOneParamZero: - /* Call the common dispatcher */ - xor edx, edx - mov ecx, 1 - call _CommonDispatchException -.endfunc - -.func DispatchTwoParamZero -_DispatchTwoParamZero: - /* Call the common dispatcher */ - xor edx, edx - mov ecx, 2 - call _CommonDispatchException -.endfunc - -.func DispatchTwoParam -_DispatchTwoParam: - /* Call the common dispatcher */ - mov ecx, 2 - call _CommonDispatchException -.endfunc - /* HARDWARE TRAP HANDLERS ****************************************************/
GENERATE_TRAP_HANDLER KiTrap0, 1 @@ -699,492 +610,7 @@ GENERATE_TRAP_HANDLER KiTrap10, 0 GENERATE_TRAP_HANDLER KiTrap11, 0 GENERATE_TRAP_HANDLER KiTrap12, 0 - -.func KiTrapExceptHandler -_KiTrapExceptHandler: - - /* Setup SEH handler frame */ - mov esp, [esp+8] - pop PCR[KPCR_EXCEPTION_LIST] - add esp, 4 - pop ebp - - /* Check if the fault came from user mode */ - test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK - jnz SetException - - /* Kernel fault, bugcheck */ - push ebp - push 0 - push 0 - push 0 - push 0 - push KMODE_EXCEPTION_NOT_HANDLED - call _KeBugCheckWithTf@24 -.endfunc - -.func KiTrap13 -TRAP_FIXUPS kitd_a, kitd_t, DoFixupV86, DoNotFixupAbios -_KiTrap13: - - /* It this a V86 GPF? */ - test dword ptr [esp+12], EFLAGS_V86_MASK - jz NotV86 - - /* Enter V86 Trap */ - V86_TRAP_PROLOG kitd_a, kitd_v - - /* Make sure that this is a V86 process */ - mov ecx, PCR[KPCR_CURRENT_THREAD] - mov ecx, [ecx+KTHREAD_APCSTATE_PROCESS] - cmp dword ptr [ecx+EPROCESS_VDM_OBJECTS], 0 - jnz RaiseIrql - - /* Otherwise, something is very wrong, raise an exception */ - sti - jmp SetException - -RaiseIrql: - - /* Go to APC level */ - mov ecx, APC_LEVEL - call @KfRaiseIrql@4 - - /* Save old IRQL and enable interrupts */ - push eax - sti - - /* Handle the opcode */ - mov ecx, ebp - call @Ki386HandleOpcodeV86@4 - - /* Check if this was VDM */ - test al, 0xFF - jnz NoReflect - - /* FIXME: TODO */ - UNHANDLED_V86_PATH - -NoReflect: - - /* Lower IRQL and disable interrupts */ - pop ecx - call @KfLowerIrql@4 - cli - - /* Check if this was a V86 trap */ - test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK - jz NotV86Trap - - /* Exit the V86 Trap */ - V86_TRAP_EPILOG - -NotV86Trap: - - /* Either this wasn't V86, or it was, but an APC interrupted us */ - jmp _Kei386EoiHelper@0 - -NotV86: - /* Enter trap */ - TRAP_PROLOG kitd_a, kitd_t - - /* Check if this was from kernel-mode */ - test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK - jnz UserModeGpf - - ///* Check if we have a VDM alert */ - //cmp dword ptr PCR[KPCR_VDM_ALERT], 0 // BUGBUG: Add this back later - //jnz VdmAlertGpf - - /* Check for GPF during GPF */ - mov eax, [ebp+KTRAP_FRAME_EIP] - cmp eax, offset CheckPrivilegedInstruction - jbe KmodeGpf - cmp eax, offset CheckPrivilegedInstruction2 - jae KmodeGpf - - /* FIXME: TODO */ - UNHANDLED_PATH "Double GPF" - - /* Get the opcode and trap frame */ -KmodeGpf: - mov eax, [ebp+KTRAP_FRAME_EIP] - mov eax, [eax] - mov edx, [ebp+KTRAP_FRAME_EBP] - - /* We want to check if this was POP [DS/ES/FS/GS] */ - add edx, KTRAP_FRAME_DS - cmp al, 0x1F - jz SegPopGpf - add edx, KTRAP_FRAME_ES - KTRAP_FRAME_DS - cmp al, 7 - jz SegPopGpf - add edx, KTRAP_FRAME_FS - KTRAP_FRAME_ES - cmp ax, 0xA10F - jz SegPopGpf - add edx, KTRAP_FRAME_GS - KTRAP_FRAME_FS - cmp ax, 0xA90F - jz SegPopGpf - - /* It isn't, was it IRETD? */ - cmp al, 0xCF - jne NotIretGpf - - /* Get error code */ - lea edx, [ebp+KTRAP_FRAME_ESP] - mov ax, [ebp+KTRAP_FRAME_ERROR_CODE] - and ax, ~RPL_MASK - - /* Get CS */ - mov cx, word ptr [edx+4] - and cx, ~RPL_MASK - cmp cx, ax - jnz NotCsGpf - - /* This should be a Ki386CallBios return */ - mov eax, offset _Ki386BiosCallReturnAddress - cmp eax, [edx] - jne NotBiosGpf - mov eax, [edx+4] - cmp ax, KGDT_R0_CODE + RPL_MASK - jne NotBiosGpf - - /* Jump to return address */ - jmp _Ki386BiosCallReturnAddress - -NotBiosGpf: - /* Check if the thread was in kernel mode */ - mov ebx, PCR[KPCR_CURRENT_THREAD] - test byte ptr [ebx+KTHREAD_PREVIOUS_MODE], 0xFF - jz UserModeGpf - - /* Set RPL_MASK for check below */ - or word ptr [edx+4], RPL_MASK - -NotCsGpf: - /* Check if the IRET goes to user-mode */ - test dword ptr [edx+4], RPL_MASK - jz UserModeGpf - - /* Setup trap frame to copy */ - mov ecx, (KTRAP_FRAME_LENGTH - 12) / 4 - lea edx, [ebp+KTRAP_FRAME_ERROR_CODE] - -TrapCopy: - - /* Copy each field */ - mov eax, [edx] - mov [edx+12], eax - sub edx, 4 - loop TrapCopy - - /* Enable interrupts and adjust stack */ - sti - add esp, 12 - add ebp, 12 - - /* Setup exception record */ - mov ebx, [ebp+KTRAP_FRAME_EIP] - mov esi, [ebp+KTRAP_FRAME_ERROR_CODE] - and esi, 0xFFFF - mov eax, STATUS_ACCESS_VIOLATION - jmp _DispatchTwoParamZero - -MsrCheck: - - /* FIXME: Handle RDMSR/WRMSR */ - UNHANDLED_PATH "RDMSR/WRMSR" - -NotIretGpf: - - /* Check if this was an MSR opcode */ - cmp al, 0xF - jz MsrCheck - - /* Check if DS is Ring 3 */ - cmp word ptr [ebp+KTRAP_FRAME_DS], KGDT_R3_DATA + RPL_MASK - jz CheckEs - - /* Otherwise, fix it up */ - mov dword ptr [ebp+KTRAP_FRAME_DS], KGDT_R3_DATA + RPL_MASK - jmp ExitGpfTrap - -CheckEs: - - /* Check if ES is Ring 3 */ - cmp word ptr [ebp+KTRAP_FRAME_ES], KGDT_R3_DATA + RPL_MASK - jz UserModeGpf - - /* Otherwise, fix it up */ - mov dword ptr [ebp+KTRAP_FRAME_ES], KGDT_R3_DATA + RPL_MASK - jmp ExitGpfTrap - -SegPopGpf: - - /* Sanity check */ - lea eax, [ebp+KTRAP_FRAME_ESP] - cmp edx, eax - jz HandleSegPop - int 3 - - /* Handle segment POP fault by setting it to 0 */ -HandleSegPop: - xor eax, eax - mov dword ptr [edx], eax - -ExitGpfTrap: - - /* Do a trap exit */ - TRAP_EPILOG NotFromSystemCall, DoNotRestorePreviousMode, DoNotRestoreSegments, DoRestoreVolatiles, DoRestoreEverything - -UserModeGpf: - - /* If the previous mode was kernel, raise a fatal exception */ - mov eax, 13 - test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK - jz _KiSystemFatalException - - /* Get the process and check which CS this came from */ - mov ebx, PCR[KPCR_CURRENT_THREAD] - mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS] - cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK - jz CheckVdmGpf - - /* Check if this is a VDM */ - cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0 - jnz DispatchV86Gpf - - /* Enable interrupts and check if we have an error code */ - sti - cmp word ptr [ebp+KTRAP_FRAME_ERROR_CODE], 0 - jnz SetException - jmp CheckPrivilegedInstruction - -HandleSegPop2: - /* Update EIP (will be updated below again) */ - add dword ptr [ebp+KTRAP_FRAME_EIP], 1 - -HandleEsPop: - /* Clear the segment, update EIP and ESP */ - mov dword ptr [edx], 0 - add dword ptr [ebp+KTRAP_FRAME_EIP], 1 - add dword ptr [ebp+KTRAP_FRAME_ESP], 4 - jmp _Kei386EoiHelper@0 - -CheckVdmGpf: - /* Check if this is a VDM */ - cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0 - jz CheckPrivilegedInstruction - - /* Bring interrupts back */ - sti - - /* Check what kind of instruction this is */ - mov eax, [ebp+KTRAP_FRAME_EIP] - mov eax, [eax] - - /* FIXME: Check for BOP4 */ - - /* Check if this is POP ES */ - mov edx, ebp - add edx, KTRAP_FRAME_ES - cmp al, 0x07 - jz HandleEsPop - - /* Check if this is POP FS */ - add edx, KTRAP_FRAME_FS - KTRAP_FRAME_ES - cmp ax, 0xA10F - jz HandleSegPop2 - - /* Check if this is POP GS */ - add edx, KTRAP_FRAME_GS - KTRAP_FRAME_FS - cmp ax, 0xA90F - jz HandleSegPop2 - -CheckPrivilegedInstruction: - /* Bring interrupts back */ - sti - - /* Setup a SEH handler */ - push ebp - push offset _KiTrapExceptHandler - push PCR[KPCR_EXCEPTION_LIST] - mov PCR[KPCR_EXCEPTION_LIST], esp - - /* Get EIP */ - mov esi, [ebp+KTRAP_FRAME_EIP] - - /* Setup loop count */ - mov ecx, 15 - -InstLoop: - /* Save loop count */ - push ecx - - /* Get the instruction */ - lods byte ptr [esi] - - /* Now lookup in the prefix table */ - mov ecx, 11 - mov edi, offset _KiTrapPrefixTable - repnz scasb - - /* Restore loop count */ - pop ecx - - /* If it's not a prefix byte, check other instructions */ - jnz NotPrefixByte - - /* Keep looping */ - loop InstLoop - - /* Fixup the stack */ - pop PCR[KPCR_EXCEPTION_LIST] - add esp, 8 - - /* Re-enable interrupts */ - sti - - /* Setup illegal instruction exception and dispatch it */ - mov ebx, [ebp+KTRAP_FRAME_EIP] - mov eax, STATUS_ILLEGAL_INSTRUCTION - jmp _DispatchNoParam - -NotPrefixByte: - /* Check if it's a HLT */ - cmp al, 0x0F4 - je IsPrivInstruction - - /* Check if the instruction has two bytes */ - cmp al, 0xF - jne CheckRing3Io - - /* Check if this is a LLDT or LTR */ - lods byte ptr [esi] - cmp al, 0 - jne NotLldt - - /* Check if this is an LLDT */ - lods byte ptr [esi] - and al, 0x38 - cmp al, 0x10 - je IsPrivInstruction - - /* Check if this is an LTR */ - cmp al, 0x18 - je IsPrivInstruction - - /* Otherwise, access violation */ - jmp NotIoViolation - -NotLldt: - /* Check if this is LGDT or LIDT or LMSW */ - cmp al, 0x01 - jne NotGdt - - /* Check if this is an LGDT */ - lods byte ptr [esi] - and al, 0x38 - cmp al, 0x10 - je IsPrivInstruction - - /* Check if this is an LIDT */ - cmp al, 0x18 - je IsPrivInstruction - - /* Check if this is an LMSW */ - cmp al, 0x30 - je IsPrivInstruction - - /* Otherwise, access violation */ - jmp NotIoViolation - -NotGdt: - /* Check if it's INVD or WBINVD */ - cmp al, 0x8 - je IsPrivInstruction - cmp al, 0x9 - je IsPrivInstruction - - /* Check if it's sysexit */ - cmp al, 0x35 - je IsPrivInstruction - - /* Check if it's a DR move */ - cmp al, 0x26 - je IsPrivInstruction - - /* Check if it's a CLTS */ - cmp al, 0x6 - je IsPrivInstruction - - /* Check if it's a CR move */ - cmp al, 0x20 - jb NotIoViolation - - /* Check if it's a DR move */ - cmp al, 0x24 - jbe IsPrivInstruction - - /* Everything else is an access violation */ - jmp NotIoViolation - -CheckRing3Io: - /* Get EFLAGS and IOPL */ - mov ebx, [ebp+KTRAP_FRAME_EFLAGS] - and ebx, EFLAGS_IOPL - shr ebx, 12 - - /* Check the CS's RPL mask */ - mov ecx, [ebp+KTRAP_FRAME_CS] - and ecx, RPL_MASK - cmp ebx, ecx - jge NotIoViolation - -CheckPrivilegedInstruction2: - /* Check if this is a CLI or STI */ - cmp al, 0xFA - je IsPrivInstruction - cmp al, 0xFB - je IsPrivInstruction - - /* Setup I/O table lookup */ - mov ecx, 13 - mov edi, offset _KiTrapIoTable - - /* Loopup in the table */ - repnz scasb - jnz NotIoViolation - - /* FIXME: Check IOPM!!! */ - -IsPrivInstruction: - /* Cleanup the SEH frame */ - pop PCR[KPCR_EXCEPTION_LIST] - add esp, 8 - - /* Setup the exception */ - mov ebx, [ebp+KTRAP_FRAME_EIP] - mov eax, STATUS_PRIVILEGED_INSTRUCTION - jmp _DispatchNoParam - -NotIoViolation: - /* Cleanup the SEH frame */ - pop PCR[KPCR_EXCEPTION_LIST] - add esp, 8 - -SetException: - /* Setup the exception */ - mov ebx, [ebp+KTRAP_FRAME_EIP] - mov esi, -1 - mov eax, STATUS_ACCESS_VIOLATION - jmp _DispatchTwoParamZero - -DispatchV86Gpf: - /* FIXME */ - UNHANDLED_V86_PATH -.endfunc - +GENERATE_TRAP_HANDLER KiTrap13, 0 GENERATE_TRAP_HANDLER KiTrap14, 0 GENERATE_TRAP_HANDLER KiTrap0F, 1 GENERATE_TRAP_HANDLER KiTrap16, 1
Modified: trunk/reactos/ntoskrnl/ke/i386/traphdlr.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/traphdlr.c... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] Mon Jan 11 06:53:57 2010 @@ -6,13 +6,46 @@ * PROGRAMMERS: ReactOS Portable Systems Group */
-/* INCLUDES *****************************************************************/ +/* INCLUDES *******************************************************************/
#include <ntoskrnl.h> #define NDEBUG #include <debug.h> #include "internal/trap_x.h"
+/* GLOBALS ********************************************************************/ + +UCHAR KiTrapPrefixTable[] = +{ + 0xF2, /* REP */ + 0xF3, /* REP INS/OUTS */ + 0x67, /* ADDR */ + 0xF0, /* LOCK */ + 0x66, /* OP */ + 0x2E, /* SEG */ + 0x3E, /* DS */ + 0x26, /* ES */ + 0x64, /* FS */ + 0x65, /* GS */ + 0x36, /* SS */ +}; + +UCHAR KiTrapIoTable[] = +{ + 0xE4, /* IN */ + 0xE5, /* IN */ + 0xEC, /* IN */ + 0xED, /* IN */ + 0x6C, /* INS */ + 0x6D, /* INS */ + 0xE6, /* OUT */ + 0xE7, /* OUT */ + 0xEE, /* OUT */ + 0xEF, /* OUT */ + 0x6E, /* OUTS */ + 0x6F, /* OUTS */ +}; + /* TRAP EXIT CODE *************************************************************/
VOID @@ -780,6 +813,288 @@ /* FIXME: Kill the system */ UNIMPLEMENTED; KiSystemFatalException(EXCEPTION_STACK_FAULT, TrapFrame); +} + +VOID +FASTCALL +KiTrap13Handler(IN PKTRAP_FRAME TrapFrame) +{ + ULONG i, j, Iopl; + BOOLEAN Privileged = FALSE; + PUCHAR Instructions; + UCHAR Instruction = 0; + KIRQL OldIrql; + + /* Check for V86 GPF */ + if (TrapFrame->EFlags & EFLAGS_V86_MASK) + { + /* Enter V86 trap */ + KiEnterV86Trap(TrapFrame); + + /* Must be a VDM process */ + if (!PsGetCurrentProcess()->VdmObjects) + { + /* Enable interrupts */ + _enable(); + + /* Setup illegal instruction fault */ + KiDispatchException0Args(STATUS_ILLEGAL_INSTRUCTION, + TrapFrame->Eip, + TrapFrame); + } + + /* Go to APC level */ + OldIrql = KfRaiseIrql(APC_LEVEL); + _enable(); + + /* Handle the V86 opcode */ + if (Ki386HandleOpcodeV86(TrapFrame) == 0xFF) + { + /* Should only happen in VDM mode */ + UNIMPLEMENTED; + while (TRUE); + } + + /* Bring IRQL back */ + KfLowerIrql(OldIrql); + _disable(); + + /* Do a quick V86 exit if possible */ + if (TrapFrame->EFlags & EFLAGS_V86_MASK) KiExitV86Trap(TrapFrame); + + /* Exit trap the slow way */ + KiEoiHelper(TrapFrame); + } + + /* Save trap frame */ + KiEnterTrap(TrapFrame); + + /* Check for user-mode GPF */ + if (KiUserTrap(TrapFrame)) + { + /* Must be user-mode! */ + if (!KiUserTrap(TrapFrame)) KiSystemFatalException(EXCEPTION_GP_FAULT, TrapFrame); + + /* Should not be VDM */ + ASSERT(KiVdmTrap(TrapFrame) == FALSE); + + /* Enable interrupts and check error code */ + _enable(); + if (!TrapFrame->ErrCode) + { + /* FIXME: Use SEH */ + Instructions = (PUCHAR)TrapFrame->Eip; + + /* Scan next 15 opcodes */ + for (i = 0; i < 15; i++) + { + /* Skip prefix instructions */ + for (j = 0; j < sizeof(KiTrapPrefixTable); j++) + { + /* Is this NOT a prefix instruction? */ + if (Instructions[i] != KiTrapPrefixTable[j]) + { + /* We can go ahead and handle the fault now */ + Instruction = Instructions[i]; + break; + } + } + + /* Do we need to keep looking? */ + if (Instruction) break; + } + + /* If all we found was prefixes, then this instruction is too long */ + if (!Instruction) + { + /* Setup illegal instruction fault */ + KiDispatchException0Args(STATUS_ILLEGAL_INSTRUCTION, + TrapFrame->Eip, + TrapFrame); + } + + /* Check for privileged instructions */ + if (Instruction == 0xF4) // HLT + { + /* HLT is privileged */ + Privileged = TRUE; + } + else if (Instruction == 0x0F) + { + /* Test if it's any of the privileged two-byte opcodes */ + if (((Instructions[i + 1] == 0x00) && // LLDT or LTR + (((Instructions[i + 2] & 0x38) == 0x10) || // LLDT + (Instructions[i + 2] == 0x18))) || // LTR + ((Instructions[i + 1] == 0x01) && // LGDT or LIDT or LMSW + (((Instructions[i + 2] & 0x38) == 0x10) || // LLGT + (Instructions[i + 2] == 0x18) || // LIDT + (Instructions[i + 2] == 0x30))) || // LMSW + (Instructions[i + 1] == 0x08) || // INVD + (Instructions[i + 1] == 0x09) || // WBINVD + (Instructions[i + 1] == 0x35) || // SYSEXIT + (Instructions[i + 1] == 0x26) || // MOV DR, XXX + (Instructions[i + 1] == 0x06) || // CLTS + (Instructions[i + 1] == 0x20) || // MOV CR, XXX + (Instructions[i + 1] == 0x24) || // MOV YYY, DR + (Instructions[i + 1] == 0x30) || // WRMSR + (Instructions[i + 1] == 0x33)) // RDPMC + { + /* These are all privileged */ + Privileged = TRUE; + } + } + else + { + /* Get the IOPL and compare with the RPL mask */ + Iopl = (TrapFrame->EFlags & EFLAGS_IOPL) >> 12; + if ((TrapFrame->SegCs & RPL_MASK) == Iopl) + { + /* I/O privilege error -- check for known instructions */ + if ((Instruction == 0xFA) || (Instruction == 0xFB)) // CLI or STI + { + /* These are privileged */ + Privileged = TRUE; + } + else + { + /* Last hope: an IN/OUT instruction */ + for (j = 0; j < sizeof(KiTrapIoTable); j++) + { + /* Is this an I/O instruction? */ + if (Instruction == KiTrapIoTable[j]) + { + /* Then it's privileged */ + Privileged = TRUE; + break; + } + } + } + } + } + + /* So now... was the instruction privileged or not? */ + if (Privileged) + { + /* Whew! We have a privileged instruction, so dispatch the fault */ + KiDispatchException0Args(STATUS_PRIVILEGED_INSTRUCTION, + TrapFrame->Eip, + TrapFrame); + } + } + + /* If we got here, send an access violation */ + KiDispatchException2Args(STATUS_ACCESS_VIOLATION, + TrapFrame->Eip, + 0, + 0xFFFFFFFF, + TrapFrame); + } + + /* Check for custom VDM trap handler */ + if (KeGetPcr()->VdmAlert) + { + /* Not implemented */ + UNIMPLEMENTED; + while (TRUE); + } + + /* + * Check for a fault during checking of the user instruction. + * + * Note that the SEH handler will catch invalid EIP, but we could be dealing + * with an invalid CS, which will generate another GPF instead. + * + */ + if (((PVOID)TrapFrame->Eip >= (PVOID)KiTrap13Handler) && + ((PVOID)TrapFrame->Eip < (PVOID)KiTrap13Handler)) + { + /* Not implemented */ + UNIMPLEMENTED; + while (TRUE); + } + + /* + * NOTE: The ASM trap exit code would restore segment registers by doing + * a POP <SEG>, which could cause an invalid segment if someone had messed + * with the segment values. + * + * Another case is a bogus SS, which would hit a GPF when doing the ired. + * This could only be done through a buggy or malicious driver, or perhaps + * the kernel debugger. + * + * The kernel normally restores the "true" segment if this happens. + * + * However, since we're restoring in C, not ASM, we can't detect + * POP <SEG> since the actual instructions will be different. + * + * A better technique would be to check the EIP and somehow edit the + * trap frame before restarting the instruction -- but we would need to + * know the extract instruction that was used first. + * + * We could force a special instrinsic to use stack instructions, or write + * a simple instruction length checker. + * + * Nevertheless, this is a lot of work for the purpose of avoiding a crash + * when the user is purposedly trying to create one from kernel-mode, so + * we should probably table this for now since it's not a "real" issue. + */ + + /* + * NOTE2: Another scenario is the IRET during a V8086 restore (BIOS Call) + * which will cause a GPF since the trap frame is a total mess (on purpose) + * as built in KiEnterV86Mode. + * + * The idea is to scan for IRET, scan for the known EIP adress, validate CS + * and then manually issue a jump to the V8086 return EIP. + */ + Instructions = (PUCHAR)TrapFrame->Eip; + if (Instructions[0] == 0xCF) + { + /* + * Some evil shit is going on here -- this is not the SS:ESP you're + * looking for! Instead, this is actually CS:EIP you're looking at! + * Why? Because part of the trap frame actually corresponds to the IRET + * stack during the trap exit! + */ + if ((TrapFrame->HardwareEsp == (ULONG)KiExitV86Mode) && + (TrapFrame->HardwareSegSs == (KGDT_R0_CODE | RPL_MASK))) + { + /* Exit the V86 trap! */ + KiExitV86Mode(TrapFrame); + } + else + { + /* Otherwise, this is another kind of IRET fault */ + UNIMPLEMENTED; + while (TRUE); + } + } + + /* So since we're not dealing with the above case, check for RDMSR/WRMSR */ + if ((Instructions[0] == 0xF) && // 2-byte opcode + (((Instructions[1] >> 8) == 0x30) || // RDMSR + ((Instructions[2] >> 8) == 0x32))) // WRMSR + { + /* Unknown CPU MSR, so raise an access violation */ + KiDispatchException0Args(STATUS_ACCESS_VIOLATION, + TrapFrame->Eip, + TrapFrame); + } + + /* Check for lazy segment load */ + if (TrapFrame->SegDs != (KGDT_R3_DATA | RPL_MASK)) + { + /* Fix it */ + TrapFrame->SegDs = (KGDT_R3_DATA | RPL_MASK); + } + else if (TrapFrame->SegEs != (KGDT_R3_DATA | RPL_MASK)) + { + /* Fix it */ + TrapFrame->SegEs = (KGDT_R3_DATA | RPL_MASK); + } + + /* Do a direct trap exit: restore volatiles only */ + KiExitTrap(TrapFrame, KTE_SKIP_PM_BIT | KTE_SKIP_SEG_BIT); }
VOID
Removed: trunk/reactos/ntoskrnl/ke/i386/v86m_sup.S URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/v86m_sup.S... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/v86m_sup.S [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ke/i386/v86m_sup.S (removed) @@ -1,37 +1,0 @@ -/* - * FILE: ntoskrnl/ke/i386/v86m_sup.S - * COPYRIGHT: See COPYING in the top level directory - * PURPOSE: Virtual 8086 (V86) Mode Support - * PROGRAMMER: Alex Ionescu (alex@relsoft.net) - * NOTE: See asmmacro.S for the V86 trap code. - */ - -/* INCLUDES ******************************************************************/ - -#include <asm.h> -#include <internal/i386/asmmacro.S> -.intel_syntax noprefix - -/* FUNCTIONS *****************************************************************/ - -.globl _Ki386SetupAndExitToV86Mode@4 -.func Ki386SetupAndExitToV86Mode@4 -_Ki386SetupAndExitToV86Mode@4: - - /* Enter V8086 mode */ - pushad - call @KiEnterV86Mode@0 -.endfunc - -.globl _Ki386BiosCallReturnAddress -.func Ki386BiosCallReturnAddress -_Ki386BiosCallReturnAddress: - - /* Exit V8086 mode */ - mov ecx, ebp - call @KiExitV86Mode@4 - mov esp, eax - popad -.endfunc - -
Modified: trunk/reactos/ntoskrnl/ke/i386/v86vdm.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/v86vdm.c?r... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/v86vdm.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ke/i386/v86vdm.c [iso-8859-1] Mon Jan 11 06:53:57 2010 @@ -429,7 +429,7 @@ return KiVdmHandleOpcode(TrapFrame, 1); }
-ULONG_PTR +VOID FASTCALL KiExitV86Mode(IN PKTRAP_FRAME TrapFrame) { @@ -466,9 +466,9 @@ GdtEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)Thread->Teb >> 16); GdtEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)Thread->Teb >> 24);
- /* Enable interrupts and pop back non-volatiles */ + /* Enable interrupts and get back to protected mode */ _enable(); - return TrapFrame->Edi; + KiV86TrapReturn(TrapFrame->Edi); }
VOID @@ -497,7 +497,7 @@ V86Frame->PcrTeb = KeGetPcr()->Tib.Self;
/* Save return EIP */ - TrapFrame->Eip = (ULONG_PTR)Ki386BiosCallReturnAddress; + TrapFrame->Eip = (ULONG_PTR)KiExitV86Mode;
/* Save our stack (after the frames) */ TrapFrame->Esi = (ULONG_PTR)V86Frame;
Modified: trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl-generic.r... ============================================================================== --- trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] Mon Jan 11 06:53:57 2010 @@ -55,7 +55,6 @@ <file>usercall_asm.S</file> <file>usercall.c</file> <file>v86vdm.c</file> - <file>v86m_sup.S</file> </directory> </if> <if property="ARCH" value="arm">