2006-01-16 19:59:32 +00:00
|
|
|
/*
|
2006-01-17 06:36:35 +00:00
|
|
|
* FILE: ntoskrnl/ke/i386/trap.S
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PURPOSE: System Traps, Entrypoints and Exitpoints
|
|
|
|
* PROGRAMMER: Alex Ionescu (alex@relsoft.net)
|
2010-02-10 23:24:59 +00:00
|
|
|
* Timo Kreuzer (timo.kreuzer@reactos.org)
|
2006-01-17 06:36:35 +00:00
|
|
|
* NOTE: See asmmacro.S for the shared entry/exit code.
|
2000-07-04 08:52:47 +00:00
|
|
|
*/
|
|
|
|
|
2000-12-23 02:37:41 +00:00
|
|
|
/* INCLUDES ******************************************************************/
|
2005-06-25 17:01:17 +00:00
|
|
|
|
2010-02-10 23:24:59 +00:00
|
|
|
#include <reactos/asm.h>
|
|
|
|
#include <ndk/i386/asm.h>
|
2006-01-16 21:14:32 +00:00
|
|
|
#include <internal/i386/asmmacro.S>
|
2010-02-10 23:24:59 +00:00
|
|
|
|
|
|
|
MACRO(GENERATE_IDT_STUB, Number)
|
|
|
|
idt _KiUnexpectedInterrupt&Number, INT_32_DPL0
|
|
|
|
ENDM
|
|
|
|
|
|
|
|
MACRO(GENERATE_INT_HANDLER, Number)
|
|
|
|
.func KiUnexpectedInterrupt&Number
|
|
|
|
_KiUnexpectedInterrupt&Number:
|
2010-02-13 02:01:33 +00:00
|
|
|
push PRIMARY_VECTOR_BASE + Number
|
2010-02-10 23:24:59 +00:00
|
|
|
jmp _KiEndUnexpectedRange@0
|
|
|
|
.endfunc
|
|
|
|
ENDM
|
2000-07-04 08:52:47 +00:00
|
|
|
|
2006-08-24 06:27:29 +00:00
|
|
|
/* GLOBALS *******************************************************************/
|
2006-01-17 06:36:35 +00:00
|
|
|
|
2006-10-01 07:24:24 +00:00
|
|
|
.data
|
2010-02-10 23:24:59 +00:00
|
|
|
|
|
|
|
PUBLIC _KiIdt
|
2006-01-17 17:28:41 +00:00
|
|
|
_KiIdt:
|
2006-01-17 06:36:35 +00:00
|
|
|
/* This is the Software Interrupt Table that we handle in this file: */
|
Patch that fixes VMWare boot (and should fix QEMu/KVM boot on the testbot):
[NTOS]: A trap can get us into a state where DS/ES are invalid, making any pointer dereference (on DS/ES segmented memory, not SS, the stack) crash (and probably double-fault). Therefore, we have to be careful to switch to a good DS/ES before touching the TrapFrame pointer, which we don't have in ESP like the ASM code, but in a DS/ES-segmented register. For V8086 traps we can switch to the good DS/ES immediately, but for other kinds of traps, we actually need to save the current (bad) segments first. So we save them on the stack now, then switch to the good ones, then store the stack values into the trap frame. This is what happens on a non-optimized (-O0) build. On an optimized build, the segments will end up in registers instead, which is fine too (they'll be direct values). The order of instructions is guaranteed since the segment macros are volatile.
[NTOS]: The GPF and Invalid Opcode handlers are performance critical when talking about V8086 traps, because they control the main flow of execution during that mode (GPFs will be issued for any privileged instruction we need to emulate, and invalid opcode might be generated for BOPs). Because of this, we employ a fast entry/exit macro into V8086 mode since we can make certain assumptions. We detect, and use, such scenarios when the V8086 flag is enabled in EFLAGS. However, because we can land in a GPF handler with an invalid DS/ES, as some V8086 code could trample this during BIOS calls for example, we must make sure that we are on a valid DS/ES before dereferencing any pointer. We fixup DS/ES either in KiEnterTrap (for normal entry/exit) or, for V86, in KiEnterV86Trap. Notice the problem: we need to detect which of these to use early on but we can't touch the EFLAGS in the frame because DS/ES could be invalid. Thankfully SS is always guaranteed valid, so stack dereferences are game! We therefore read the EFLAGS here, in assembly, where we can touch ESP as we please. We save this in EDX, which will be used as the second argument for the FASTCALL C trap entry. When we make the fast V86 check, we use the parameter instead of the trap frame, leading us to using the correct trap entry function, which fixes up DS/ES and lets us go on our merry way...
[NTOS]: Make appropriate changes to GENERATE_TRAP_HANDLERS macro.
[NTOS]: Switch to using well-known NT trap handler names (hex-based, double-zeroed) instead of decimal-based trap handler names which are confusing.
[NTOS]: Clean up some debug spew.
svn path=/trunk/; revision=45052
2010-01-12 05:50:45 +00:00
|
|
|
idt _KiTrap00, INT_32_DPL0 /* INT 00: Divide Error (#DE) */
|
|
|
|
idt _KiTrap01, INT_32_DPL0 /* INT 01: Debug Exception (#DB) */
|
|
|
|
idt _KiTrap02, INT_32_DPL0 /* INT 02: NMI Interrupt */
|
|
|
|
idt _KiTrap03, INT_32_DPL3 /* INT 03: Breakpoint Exception (#BP) */
|
|
|
|
idt _KiTrap04, INT_32_DPL3 /* INT 04: Overflow Exception (#OF) */
|
|
|
|
idt _KiTrap05, INT_32_DPL0 /* INT 05: BOUND Range Exceeded (#BR) */
|
|
|
|
idt _KiTrap06, INT_32_DPL0 /* INT 06: Invalid Opcode Code (#UD) */
|
|
|
|
idt _KiTrap07, INT_32_DPL0 /* INT 07: Device Not Available (#NM) */
|
|
|
|
idt _KiTrap08, INT_32_DPL0 /* INT 08: Double Fault Exception (#DF) */
|
|
|
|
idt _KiTrap09, INT_32_DPL0 /* INT 09: RESERVED */
|
|
|
|
idt _KiTrap0A, INT_32_DPL0 /* INT 0A: Invalid TSS Exception (#TS) */
|
|
|
|
idt _KiTrap0B, INT_32_DPL0 /* INT 0B: Segment Not Present (#NP) */
|
|
|
|
idt _KiTrap0C, INT_32_DPL0 /* INT 0C: Stack Fault Exception (#SS) */
|
|
|
|
idt _KiTrap0D, INT_32_DPL0 /* INT 0D: General Protection (#GP) */
|
|
|
|
idt _KiTrap0E, INT_32_DPL0 /* INT 0E: Page-Fault Exception (#PF) */
|
2006-08-21 03:01:47 +00:00
|
|
|
idt _KiTrap0F, INT_32_DPL0 /* INT 0F: RESERVED */
|
Patch that fixes VMWare boot (and should fix QEMu/KVM boot on the testbot):
[NTOS]: A trap can get us into a state where DS/ES are invalid, making any pointer dereference (on DS/ES segmented memory, not SS, the stack) crash (and probably double-fault). Therefore, we have to be careful to switch to a good DS/ES before touching the TrapFrame pointer, which we don't have in ESP like the ASM code, but in a DS/ES-segmented register. For V8086 traps we can switch to the good DS/ES immediately, but for other kinds of traps, we actually need to save the current (bad) segments first. So we save them on the stack now, then switch to the good ones, then store the stack values into the trap frame. This is what happens on a non-optimized (-O0) build. On an optimized build, the segments will end up in registers instead, which is fine too (they'll be direct values). The order of instructions is guaranteed since the segment macros are volatile.
[NTOS]: The GPF and Invalid Opcode handlers are performance critical when talking about V8086 traps, because they control the main flow of execution during that mode (GPFs will be issued for any privileged instruction we need to emulate, and invalid opcode might be generated for BOPs). Because of this, we employ a fast entry/exit macro into V8086 mode since we can make certain assumptions. We detect, and use, such scenarios when the V8086 flag is enabled in EFLAGS. However, because we can land in a GPF handler with an invalid DS/ES, as some V8086 code could trample this during BIOS calls for example, we must make sure that we are on a valid DS/ES before dereferencing any pointer. We fixup DS/ES either in KiEnterTrap (for normal entry/exit) or, for V86, in KiEnterV86Trap. Notice the problem: we need to detect which of these to use early on but we can't touch the EFLAGS in the frame because DS/ES could be invalid. Thankfully SS is always guaranteed valid, so stack dereferences are game! We therefore read the EFLAGS here, in assembly, where we can touch ESP as we please. We save this in EDX, which will be used as the second argument for the FASTCALL C trap entry. When we make the fast V86 check, we use the parameter instead of the trap frame, leading us to using the correct trap entry function, which fixes up DS/ES and lets us go on our merry way...
[NTOS]: Make appropriate changes to GENERATE_TRAP_HANDLERS macro.
[NTOS]: Switch to using well-known NT trap handler names (hex-based, double-zeroed) instead of decimal-based trap handler names which are confusing.
[NTOS]: Clean up some debug spew.
svn path=/trunk/; revision=45052
2010-01-12 05:50:45 +00:00
|
|
|
idt _KiTrap10, INT_32_DPL0 /* INT 10: x87 FPU Error (#MF) */
|
|
|
|
idt _KiTrap11, INT_32_DPL0 /* INT 11: Align Check Exception (#AC) */
|
2006-01-17 22:41:39 +00:00
|
|
|
idt _KiTrap0F, INT_32_DPL0 /* INT 12: Machine Check Exception (#MC)*/
|
|
|
|
idt _KiTrap0F, INT_32_DPL0 /* INT 13: SIMD FPU Exception (#XF) */
|
2006-01-17 17:28:41 +00:00
|
|
|
.rept 22
|
2006-01-17 22:41:39 +00:00
|
|
|
idt _KiTrap0F, INT_32_DPL0 /* INT 14-29: UNDEFINED INTERRUPTS */
|
2006-01-17 17:28:41 +00:00
|
|
|
.endr
|
|
|
|
idt _KiGetTickCount, INT_32_DPL3 /* INT 2A: Get Tick Count Handler */
|
|
|
|
idt _KiCallbackReturn, INT_32_DPL3 /* INT 2B: User-Mode Callback Return */
|
|
|
|
idt _KiRaiseAssertion, INT_32_DPL3 /* INT 2C: Debug Assertion Handler */
|
|
|
|
idt _KiDebugService, INT_32_DPL3 /* INT 2D: Debug Service Handler */
|
|
|
|
idt _KiSystemService, INT_32_DPL3 /* INT 2E: System Call Service Handler */
|
2006-01-17 22:41:39 +00:00
|
|
|
idt _KiTrap0F, INT_32_DPL0 /* INT 2F: RESERVED */
|
2010-02-10 23:24:59 +00:00
|
|
|
i = 0
|
|
|
|
.rept 208
|
|
|
|
GENERATE_IDT_STUB %i
|
|
|
|
i = i + 1
|
|
|
|
.endr
|
2006-01-17 17:28:41 +00:00
|
|
|
|
2010-02-10 23:24:59 +00:00
|
|
|
PUBLIC _KiIdtDescriptor
|
2006-01-17 17:28:41 +00:00
|
|
|
_KiIdtDescriptor:
|
2007-08-09 07:12:59 +00:00
|
|
|
.short 0
|
2008-04-17 19:08:26 +00:00
|
|
|
.short 0x7FF
|
2006-01-17 17:28:41 +00:00
|
|
|
.long _KiIdt
|
|
|
|
|
2010-02-10 23:24:59 +00:00
|
|
|
PUBLIC _KiUnexpectedEntrySize
|
2006-08-24 01:53:54 +00:00
|
|
|
_KiUnexpectedEntrySize:
|
|
|
|
.long _KiUnexpectedInterrupt1 - _KiUnexpectedInterrupt0
|
|
|
|
|
2010-02-10 23:24:59 +00:00
|
|
|
/******************************************************************************/
|
|
|
|
.code32
|
2006-10-01 07:24:24 +00:00
|
|
|
.text
|
2006-08-21 22:40:23 +00:00
|
|
|
|
2010-02-10 23:24:59 +00:00
|
|
|
TRAP_ENTRY KiTrap00, KI_PUSH_FAKE_ERROR_CODE
|
|
|
|
TRAP_ENTRY KiTrap01, KI_PUSH_FAKE_ERROR_CODE
|
|
|
|
TRAP_ENTRY KiTrap03, KI_PUSH_FAKE_ERROR_CODE
|
|
|
|
TRAP_ENTRY KiTrap04, KI_PUSH_FAKE_ERROR_CODE
|
|
|
|
TRAP_ENTRY KiTrap05, KI_PUSH_FAKE_ERROR_CODE
|
|
|
|
TRAP_ENTRY KiTrap06, KI_PUSH_FAKE_ERROR_CODE
|
|
|
|
TRAP_ENTRY KiTrap07, KI_PUSH_FAKE_ERROR_CODE
|
|
|
|
TRAP_ENTRY KiTrap08, 0
|
|
|
|
TRAP_ENTRY KiTrap09, KI_PUSH_FAKE_ERROR_CODE
|
|
|
|
TRAP_ENTRY KiTrap0A, 0
|
|
|
|
TRAP_ENTRY KiTrap0B, 0
|
|
|
|
TRAP_ENTRY KiTrap0C, 0
|
|
|
|
TRAP_ENTRY KiTrap0D, 0
|
|
|
|
TRAP_ENTRY KiTrap0E, 0
|
|
|
|
TRAP_ENTRY KiTrap0F, KI_PUSH_FAKE_ERROR_CODE
|
|
|
|
TRAP_ENTRY KiTrap10, KI_PUSH_FAKE_ERROR_CODE
|
|
|
|
TRAP_ENTRY KiTrap11, KI_PUSH_FAKE_ERROR_CODE
|
|
|
|
TRAP_ENTRY KiTrap13, KI_PUSH_FAKE_ERROR_CODE
|
|
|
|
TRAP_ENTRY KiGetTickCount, KI_PUSH_FAKE_ERROR_CODE
|
|
|
|
TRAP_ENTRY KiCallbackReturn, KI_PUSH_FAKE_ERROR_CODE
|
|
|
|
TRAP_ENTRY KiRaiseAssertion, KI_PUSH_FAKE_ERROR_CODE
|
|
|
|
TRAP_ENTRY KiDebugService, KI_PUSH_FAKE_ERROR_CODE
|
2010-02-13 02:01:33 +00:00
|
|
|
TRAP_ENTRY KiUnexpectedInterruptTail, 0
|
2006-08-21 22:40:23 +00:00
|
|
|
|
2010-02-10 23:24:59 +00:00
|
|
|
ALIGN 4
|
|
|
|
EXTERN @KiInterruptTemplateHandler@8
|
|
|
|
PUBLIC _KiInterruptTemplate
|
|
|
|
_KiInterruptTemplate:
|
|
|
|
KiEnterTrap KI_PUSH_FAKE_ERROR_CODE
|
|
|
|
PUBLIC _KiInterruptTemplate2ndDispatch
|
|
|
|
_KiInterruptTemplate2ndDispatch:
|
|
|
|
mov edx, 0
|
|
|
|
PUBLIC _KiInterruptTemplateObject
|
|
|
|
_KiInterruptTemplateObject:
|
|
|
|
mov eax, offset @KiInterruptTemplateHandler@8
|
|
|
|
jmp eax
|
|
|
|
PUBLIC _KiInterruptTemplateDispatch
|
|
|
|
_KiInterruptTemplateDispatch:
|
2006-08-21 22:40:23 +00:00
|
|
|
|
2010-03-03 02:27:14 +00:00
|
|
|
EXTERN @KiSystemServiceHandler@8:PROC
|
|
|
|
PUBLIC _KiSystemService
|
|
|
|
_KiSystemService:
|
|
|
|
KiEnterTrap (KI_PUSH_FAKE_ERROR_CODE OR KI_NONVOLATILES_ONLY OR KI_DONT_SAVE_SEGS)
|
2010-03-17 13:12:46 +00:00
|
|
|
KiCallHandler @KiSystemServiceHandler@8
|
2010-03-03 16:30:56 +00:00
|
|
|
|
|
|
|
EXTERN @KiFastCallEntryHandler@8:PROC
|
|
|
|
PUBLIC _KiFastCallEntry
|
|
|
|
_KiFastCallEntry:
|
|
|
|
KiEnterTrap (KI_FAST_SYSTEM_CALL OR KI_NONVOLATILES_ONLY OR KI_DONT_SAVE_SEGS)
|
2010-03-17 13:12:46 +00:00
|
|
|
KiCallHandler @KiFastCallEntryHandler@8
|
2010-02-10 23:24:59 +00:00
|
|
|
|
|
|
|
PUBLIC _KiStartUnexpectedRange@0
|
|
|
|
_KiStartUnexpectedRange@0:
|
|
|
|
i = 0
|
|
|
|
.rept 208
|
|
|
|
GENERATE_INT_HANDLER %i
|
|
|
|
i = i + 1
|
|
|
|
.endr
|
|
|
|
PUBLIC _KiEndUnexpectedRange@0
|
2006-08-24 01:53:54 +00:00
|
|
|
_KiEndUnexpectedRange@0:
|
2006-08-21 22:40:23 +00:00
|
|
|
jmp _KiUnexpectedInterruptTail
|
2010-02-10 23:24:59 +00:00
|
|
|
|
2010-03-17 13:12:46 +00:00
|
|
|
|
|
|
|
/* EXIT CODE *****************************************************************/
|
|
|
|
|
|
|
|
KiTrapExitStub KiSystemCallReturn, (KI_RESTORE_EAX OR KI_RESTORE_EFLAGS OR KI_EXIT_JMP)
|
|
|
|
KiTrapExitStub KiSystemCallSysExitReturn, (KI_RESTORE_EAX OR KI_RESTORE_FS OR KI_RESTORE_EFLAGS OR KI_EXIT_SYSCALL)
|
|
|
|
KiTrapExitStub KiSystemCallTrapReturn, (KI_RESTORE_EAX OR KI_RESTORE_FS OR KI_EXIT_IRET)
|
|
|
|
|
|
|
|
KiTrapExitStub KiEditedTrapReturn, (KI_RESTORE_VOLATILES OR KI_RESTORE_EFLAGS OR KI_EDITED_FRAME OR KI_EXIT_RET)
|
|
|
|
KiTrapExitStub KiTrapReturn, (KI_RESTORE_VOLATILES OR KI_RESTORE_SEGMENTS OR KI_EXIT_IRET)
|
|
|
|
KiTrapExitStub KiTrapReturnNoSegments, (KI_RESTORE_VOLATILES OR KI_EXIT_IRET)
|
|
|
|
|
2010-02-10 23:24:59 +00:00
|
|
|
END
|