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/i386/ke.h?rev=45038&r1=45037&r2=45038&view=diff
==============================================================================
--- 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.S?rev=45038&r1=45037&r2=45038&view=diff
==============================================================================
--- 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 _ki386setupandexittov86m...@4
+.func ki386setupandexittov86m...@4
+_ki386setupandexittov86m...@4:
+
+    /* Enter V8086 mode */
+    pushad
+    call @kienterv86m...@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=45038&r1=45037&r2=45038&view=diff
==============================================================================
--- 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 _kidispatchexcept...@20
-
-    /* End the trap */
-    mov esp, ebp
-    jmp _kei386eoihel...@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 _kebugcheckwit...@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 @kfraisei...@4
-
-    /* Save old IRQL and enable interrupts */
-    push eax
-    sti
-
-    /* Handle the opcode */
-    mov ecx, ebp
-    call @ki386handleopcode...@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 @kfloweri...@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 _kei386eoihel...@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 _kei386eoihel...@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?rev=45038&r1=45037&r2=45038&view=diff
==============================================================================
--- 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?rev=45037&view=auto
==============================================================================
--- 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 ([email protected])
- * NOTE:            See asmmacro.S for the V86 trap code.
- */
-
-/* INCLUDES ******************************************************************/
-
-#include <asm.h>
-#include <internal/i386/asmmacro.S>
-.intel_syntax noprefix
-
-/* FUNCTIONS *****************************************************************/
-
-.globl _ki386setupandexittov86m...@4
-.func ki386setupandexittov86m...@4
-_ki386setupandexittov86m...@4:
-
-    /* Enter V8086 mode */
-    pushad
-    call @kienterv86m...@0
-.endfunc
-
-.globl _Ki386BiosCallReturnAddress
-.func Ki386BiosCallReturnAddress
-_Ki386BiosCallReturnAddress:
-
-    /* Exit V8086 mode */
-    mov ecx, ebp
-    call @kiexitv86m...@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?rev=45038&r1=45037&r2=45038&view=diff
==============================================================================
--- 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.rbuild?rev=45038&r1=45037&r2=45038&view=diff
==============================================================================
--- 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">


Reply via email to