2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ke/amd64/except.c
5 * PURPOSE: Exception Dispatching for amd64
6 * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
7 * Alex Ionescu (alex.ionescu@reactos.org)
10 /* INCLUDES ******************************************************************/
16 /* GLOBALS *******************************************************************/
18 KIDT_INIT KiInterruptInitTable
[] =
20 /* Id, Dpl, IST, ServiceRoutine */
21 {0x00, 0x00, 0x00, KiDivideErrorFault
},
22 {0x01, 0x00, 0x00, KiDebugTrapOrFault
},
23 {0x02, 0x00, 0x03, KiNmiInterrupt
},
24 {0x03, 0x03, 0x00, KiBreakpointTrap
},
25 {0x04, 0x03, 0x00, KiOverflowTrap
},
26 {0x05, 0x00, 0x00, KiBoundFault
},
27 {0x06, 0x00, 0x00, KiInvalidOpcodeFault
},
28 {0x07, 0x00, 0x00, KiNpxNotAvailableFault
},
29 {0x08, 0x00, 0x01, KiDoubleFaultAbort
},
30 {0x09, 0x00, 0x00, KiNpxSegmentOverrunAbort
},
31 {0x0A, 0x00, 0x00, KiInvalidTssFault
},
32 {0x0B, 0x00, 0x00, KiSegmentNotPresentFault
},
33 {0x0C, 0x00, 0x00, KiStackFault
},
34 {0x0D, 0x00, 0x00, KiGeneralProtectionFault
},
35 {0x0E, 0x00, 0x00, KiPageFault
},
36 {0x10, 0x00, 0x00, KiFloatingErrorFault
},
37 {0x11, 0x00, 0x00, KiAlignmentFault
},
38 {0x12, 0x00, 0x02, KiMcheckAbort
},
39 {0x13, 0x00, 0x00, KiXmmException
},
40 {0x1F, 0x00, 0x00, KiApcInterrupt
},
41 {0x2C, 0x03, 0x00, KiRaiseAssertion
},
42 {0x2D, 0x03, 0x00, KiDebugServiceTrap
},
43 {0x2F, 0x00, 0x00, KiDpcInterrupt
},
44 {0xE1, 0x00, 0x00, KiIpiInterrupt
},
48 KIDTENTRY64 KiIdt
[256];
49 KDESCRIPTOR KiIdtDescriptor
= {{0}, sizeof(KiIdt
) - 1, KiIdt
};
51 /* FUNCTIONS *****************************************************************/
58 KeInitExceptions(VOID
)
62 /* Initialize the Idt */
63 for (j
= i
= 0; i
< 256; i
++)
67 if (KiInterruptInitTable
[j
].InterruptId
== i
)
69 Offset
= (ULONG64
)KiInterruptInitTable
[j
].ServiceRoutine
;
70 KiIdt
[i
].Dpl
= KiInterruptInitTable
[j
].Dpl
;
71 KiIdt
[i
].IstIndex
= KiInterruptInitTable
[j
].IstIndex
;
76 Offset
= (ULONG64
)KiUnexpectedInterrupt
;
78 KiIdt
[i
].IstIndex
= 0;
80 KiIdt
[i
].OffsetLow
= Offset
& 0xffff;
81 KiIdt
[i
].Selector
= KGDT_64_R0_CODE
;
83 KiIdt
[i
].Reserved0
= 0;
85 KiIdt
[i
].OffsetMiddle
= (Offset
>> 16) & 0xffff;
86 KiIdt
[i
].OffsetHigh
= (Offset
>> 32);
87 KiIdt
[i
].Reserved1
= 0;
90 KeGetPcr()->IdtBase
= KiIdt
;
91 __lidt(&KiIdtDescriptor
.Limit
);
96 KiDispatchException(IN PEXCEPTION_RECORD ExceptionRecord
,
97 IN PKEXCEPTION_FRAME ExceptionFrame
,
98 IN PKTRAP_FRAME TrapFrame
,
99 IN KPROCESSOR_MODE PreviousMode
,
100 IN BOOLEAN FirstChance
)
104 // FrLdrDbgPrint("KiDispatchException(%p, %p, %p, %d, %d)\n",
105 // ExceptionRecord, ExceptionFrame, TrapFrame, PreviousMode, FirstChance);
107 /* Increase number of Exception Dispatches */
108 KeGetCurrentPrcb()->KeExceptionDispatchCount
++;
110 /* Set the context flags */
111 Context
.ContextFlags
= CONTEXT_ALL
;
114 KeTrapFrameToContext(TrapFrame
, ExceptionFrame
, &Context
);
116 /* Look at our exception code */
117 switch (ExceptionRecord
->ExceptionCode
)
120 case STATUS_BREAKPOINT
:
122 /* Decrement RIP by one */
126 /* Internal exception */
127 case KI_EXCEPTION_ACCESS_VIOLATION
:
129 /* Set correct code */
130 ExceptionRecord
->ExceptionCode
= STATUS_ACCESS_VIOLATION
;
131 if (PreviousMode
== UserMode
)
133 /* FIXME: Handle no execute */
138 /* Handle kernel-mode first, it's simpler */
139 if (PreviousMode
== KernelMode
)
141 /* Check if this is a first-chance exception */
142 if (FirstChance
== TRUE
)
144 /* Break into the debugger for the first time */
145 if (KiDebugRoutine(TrapFrame
,
152 /* Exception was handled */
156 /* If the Debugger couldn't handle it, dispatch the exception */
157 if (RtlDispatchException(ExceptionRecord
, &Context
)) goto Handled
;
160 /* This is a second-chance exception, only for the debugger */
161 if (KiDebugRoutine(TrapFrame
,
168 /* Exception was handled */
172 /* Third strike; you're out */
173 KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED
,
174 ExceptionRecord
->ExceptionCode
,
175 (ULONG_PTR
)ExceptionRecord
->ExceptionAddress
,
176 (ULONG_PTR
)TrapFrame
,
181 /* FIXME: user-mode exception handling unimplemented */
186 /* Convert the context back into Trap/Exception Frames */
187 KeContextToTrapFrame(&Context
,
190 Context
.ContextFlags
,
197 KeRaiseUserException(IN NTSTATUS ExceptionCode
)
200 return STATUS_UNSUCCESSFUL
;