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/…
==============================================================================
--- 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?re…
==============================================================================
--- 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.…
==============================================================================
--- 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.…
==============================================================================
--- 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(a)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?…
==============================================================================
--- 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.…
==============================================================================
--- 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">