2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/include/i386/trap_x.h
5 * PURPOSE: Internal Inlined Functions for the Trap Handling Code
6 * PROGRAMMERS: ReactOS Portable Systems Group
14 // Unreachable code hint for GCC 4.5.x, older GCC versions, and MSVC
17 #if __GNUC__ * 100 + __GNUC_MINOR__ >= 405
18 #define UNREACHABLE __builtin_unreachable()
20 #define UNREACHABLE __builtin_trap()
23 #define UNREACHABLE __assume(0)
24 #define __builtin_expect(a,b) (a)
34 KiUserTrap(IN PKTRAP_FRAME TrapFrame
)
36 /* Anything else but Ring 0 is Ring 3 */
37 return !!(TrapFrame
->SegCs
& MODE_MASK
);
45 KiDumpTrapFrame(IN PKTRAP_FRAME TrapFrame
)
47 /* Dump the whole thing */
48 DbgPrint("DbgEbp: %x\n", TrapFrame
->DbgEbp
);
49 DbgPrint("DbgEip: %x\n", TrapFrame
->DbgEip
);
50 DbgPrint("DbgArgMark: %x\n", TrapFrame
->DbgArgMark
);
51 DbgPrint("DbgArgPointer: %x\n", TrapFrame
->DbgArgPointer
);
52 DbgPrint("TempSegCs: %x\n", TrapFrame
->TempSegCs
);
53 DbgPrint("TempEsp: %x\n", TrapFrame
->TempEsp
);
54 DbgPrint("Dr0: %x\n", TrapFrame
->Dr0
);
55 DbgPrint("Dr1: %x\n", TrapFrame
->Dr1
);
56 DbgPrint("Dr2: %x\n", TrapFrame
->Dr2
);
57 DbgPrint("Dr3: %x\n", TrapFrame
->Dr3
);
58 DbgPrint("Dr6: %x\n", TrapFrame
->Dr6
);
59 DbgPrint("Dr7: %x\n", TrapFrame
->Dr7
);
60 DbgPrint("SegGs: %x\n", TrapFrame
->SegGs
);
61 DbgPrint("SegEs: %x\n", TrapFrame
->SegEs
);
62 DbgPrint("SegDs: %x\n", TrapFrame
->SegDs
);
63 DbgPrint("Edx: %x\n", TrapFrame
->Edx
);
64 DbgPrint("Ecx: %x\n", TrapFrame
->Ecx
);
65 DbgPrint("Eax: %x\n", TrapFrame
->Eax
);
66 DbgPrint("PreviousPreviousMode: %x\n", TrapFrame
->PreviousPreviousMode
);
67 DbgPrint("ExceptionList: %p\n", TrapFrame
->ExceptionList
);
68 DbgPrint("SegFs: %x\n", TrapFrame
->SegFs
);
69 DbgPrint("Edi: %x\n", TrapFrame
->Edi
);
70 DbgPrint("Esi: %x\n", TrapFrame
->Esi
);
71 DbgPrint("Ebx: %x\n", TrapFrame
->Ebx
);
72 DbgPrint("Ebp: %x\n", TrapFrame
->Ebp
);
73 DbgPrint("ErrCode: %x\n", TrapFrame
->ErrCode
);
74 DbgPrint("Eip: %x\n", TrapFrame
->Eip
);
75 DbgPrint("SegCs: %x\n", TrapFrame
->SegCs
);
76 DbgPrint("EFlags: %x\n", TrapFrame
->EFlags
);
77 DbgPrint("HardwareEsp: %x\n", TrapFrame
->HardwareEsp
);
78 DbgPrint("HardwareSegSs: %x\n", TrapFrame
->HardwareSegSs
);
79 DbgPrint("V86Es: %x\n", TrapFrame
->V86Es
);
80 DbgPrint("V86Ds: %x\n", TrapFrame
->V86Ds
);
81 DbgPrint("V86Fs: %x\n", TrapFrame
->V86Fs
);
82 DbgPrint("V86Gs: %x\n", TrapFrame
->V86Gs
);
88 KiFillTrapFrameDebug(IN PKTRAP_FRAME TrapFrame
)
90 /* Set the debug information */
91 TrapFrame
->DbgArgPointer
= TrapFrame
->Edx
;
92 TrapFrame
->DbgArgMark
= 0xBADB0D00;
93 TrapFrame
->DbgEip
= TrapFrame
->Eip
;
94 TrapFrame
->DbgEbp
= TrapFrame
->Ebp
;
95 TrapFrame
->PreviousPreviousMode
= -1;
98 #define DR7_RESERVED_READ_AS_1 0x400
100 #define CheckDr(DrNumner, ExpectedValue) \
102 ULONG DrValue = __readdr(DrNumner); \
103 if (DrValue != (ExpectedValue)) \
105 DbgPrint("Dr%ld: expected %.8lx, got %.8lx\n", \
106 DrNumner, ExpectedValue, DrValue); \
111 extern BOOLEAN StopChecking
;
115 KiExitTrapDebugChecks(IN PKTRAP_FRAME TrapFrame
,
116 IN BOOLEAN SkipPreviousMode
)
118 /* Don't check recursively */
119 if (StopChecking
) return;
122 /* Make sure interrupts are disabled */
123 if (__readeflags() & EFLAGS_INTERRUPT_MASK
)
125 DbgPrint("Exiting with interrupts enabled: %lx\n", __readeflags());
129 /* Make sure this is a real trap frame */
130 if (TrapFrame
->DbgArgMark
!= 0xBADB0D00)
132 DbgPrint("Exiting with an invalid trap frame? (No MAGIC in trap frame)\n");
133 KiDumpTrapFrame(TrapFrame
);
137 /* Make sure we're not in user-mode or something */
138 if (Ke386GetFs() != KGDT_R0_PCR
)
140 DbgPrint("Exiting with an invalid FS: %lx\n", Ke386GetFs());
144 /* Make sure we have a valid SEH chain */
145 if (KeGetPcr()->NtTib
.ExceptionList
== 0)
147 DbgPrint("Exiting with NULL exception chain: %p\n", KeGetPcr()->NtTib
.ExceptionList
);
151 /* Make sure we're restoring a valid SEH chain */
152 if (TrapFrame
->ExceptionList
== 0)
154 DbgPrint("Entered a trap with a NULL exception chain: %p\n", TrapFrame
->ExceptionList
);
158 /* If we're ignoring previous mode, make sure caller doesn't actually want it */
159 if (SkipPreviousMode
&& (TrapFrame
->PreviousPreviousMode
!= -1))
161 DbgPrint("Exiting a trap witout restoring previous mode, yet previous mode seems valid: %lx\n", TrapFrame
->PreviousPreviousMode
);
165 /* Check DR values */
166 if (KiUserTrap(TrapFrame
)
168 /* Check for active debugging */
169 if (KeGetCurrentThread()->Header
.DebugActive
)
171 if ((TrapFrame
->Dr7
& ~DR7_RESERVED_MASK
) == 0) __debugbreak();
173 CheckDr(0, TrapFrame
->Dr0
);
174 CheckDr(1, TrapFrame
->Dr1
);
175 CheckDr(2, TrapFrame
->Dr2
);
176 CheckDr(3, TrapFrame
->Dr3
);
177 CheckDr(7, TrapFrame
->Dr7
| DR7_RESERVED_READ_AS_1
);
182 PKPRCB Prcb
= KeGetCurrentPrcb();
183 CheckDr(0, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr0
);
184 CheckDr(1, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr1
);
185 CheckDr(2, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr2
);
186 CheckDr(3, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr3
);
187 //CheckDr(7, Prcb->ProcessorState.SpecialRegisters.KernelDr7);
190 StopChecking
= FALSE
;
195 KiExitSystemCallDebugChecks(IN ULONG SystemCall
,
196 IN PKTRAP_FRAME TrapFrame
)
200 /* Check if this was a user call */
201 if (KiUserTrap(TrapFrame
))
203 /* Make sure we are not returning with elevated IRQL */
204 OldIrql
= KeGetCurrentIrql();
205 if (OldIrql
!= PASSIVE_LEVEL
)
207 /* Forcibly put us in a sane state */
208 KeGetPcr()->Irql
= PASSIVE_LEVEL
;
212 KeBugCheckEx(IRQL_GT_ZERO_AT_SYSTEM_SERVICE
,
219 /* Make sure we're not attached and that APCs are not disabled */
220 if ((KeGetCurrentThread()->ApcStateIndex
!= OriginalApcEnvironment
) ||
221 (KeGetCurrentThread()->CombinedApcDisable
!= 0))
224 KeBugCheckEx(APC_INDEX_MISMATCH
,
226 KeGetCurrentThread()->ApcStateIndex
,
227 KeGetCurrentThread()->CombinedApcDisable
,
233 #define KiExitTrapDebugChecks(x, y)
234 #define KiFillTrapFrameDebug(x)
235 #define KiExitSystemCallDebugChecks(x, y)
239 // Generic Exit Routine
241 DECLSPEC_NORETURN VOID FASTCALL
KiSystemCallReturn(IN PKTRAP_FRAME TrapFrame
);
242 DECLSPEC_NORETURN VOID FASTCALL
KiSystemCallSysExitReturn(IN PKTRAP_FRAME TrapFrame
);
243 DECLSPEC_NORETURN VOID FASTCALL
KiSystemCallTrapReturn(IN PKTRAP_FRAME TrapFrame
);
244 DECLSPEC_NORETURN VOID FASTCALL
KiEditedTrapReturn(IN PKTRAP_FRAME TrapFrame
);
245 DECLSPEC_NORETURN VOID FASTCALL
KiTrapReturn(IN PKTRAP_FRAME TrapFrame
);
246 DECLSPEC_NORETURN VOID FASTCALL
KiTrapReturnNoSegments(IN PKTRAP_FRAME TrapFrame
);
247 DECLSPEC_NORETURN VOID FASTCALL
KiTrapReturnNoSegmentsRet8(IN PKTRAP_FRAME TrapFrame
);
252 (FASTCALL
*PFAST_SYSTEM_CALL_EXIT
)(
253 IN PKTRAP_FRAME TrapFrame
256 extern PFAST_SYSTEM_CALL_EXIT KiFastCallExitHandler
;
259 // Save user mode debug registers and restore kernel values
263 KiHandleDebugRegistersOnTrapEntry(
264 IN PKTRAP_FRAME TrapFrame
)
266 PKPRCB Prcb
= KeGetCurrentPrcb();
268 /* Save all debug registers in the trap frame */
269 TrapFrame
->Dr0
= __readdr(0);
270 TrapFrame
->Dr1
= __readdr(1);
271 TrapFrame
->Dr2
= __readdr(2);
272 TrapFrame
->Dr3
= __readdr(3);
273 TrapFrame
->Dr6
= __readdr(6);
274 TrapFrame
->Dr7
= __readdr(7);
276 /* Disable all active debugging */
279 /* Restore kernel values */
280 __writedr(0, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr0
);
281 __writedr(1, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr1
);
282 __writedr(2, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr2
);
283 __writedr(3, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr3
);
284 __writedr(6, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr6
);
285 __writedr(7, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr7
);
290 KiHandleDebugRegistersOnTrapExit(
291 PKTRAP_FRAME TrapFrame
)
293 /* Disable all active debugging */
296 /* Load all debug registers from the trap frame */
297 __writedr(0, TrapFrame
->Dr0
);
298 __writedr(1, TrapFrame
->Dr1
);
299 __writedr(2, TrapFrame
->Dr2
);
300 __writedr(3, TrapFrame
->Dr3
);
301 __writedr(6, TrapFrame
->Dr6
);
302 __writedr(7, TrapFrame
->Dr7
);
306 // Virtual 8086 Mode Optimized Trap Exit
311 KiExitV86Trap(IN PKTRAP_FRAME TrapFrame
)
317 Thread
= KeGetCurrentThread();
320 /* Return if this isn't V86 mode anymore */
321 if (!(TrapFrame
->EFlags
& EFLAGS_V86_MASK
)) KiEoiHelper(TrapFrame
);
323 /* Turn off the alerted state for kernel mode */
324 Thread
->Alerted
[KernelMode
] = FALSE
;
326 /* Are there pending user APCs? */
327 if (__builtin_expect(!Thread
->ApcState
.UserApcPending
, 1)) break;
329 /* Raise to APC level and enable interrupts */
330 OldIrql
= KfRaiseIrql(APC_LEVEL
);
334 KiDeliverApc(UserMode
, NULL
, TrapFrame
);
336 /* Restore IRQL and disable interrupts once again */
337 KfLowerIrql(OldIrql
);
341 /* If we got here, we're still in a valid V8086 context, so quit it */
342 if (__builtin_expect(TrapFrame
->Dr7
& ~DR7_RESERVED_MASK
, 0))
344 /* Restore debug registers from the trap frame */
345 KiHandleDebugRegistersOnTrapExit(TrapFrame
);
348 /* Return from interrupt */
349 KiTrapReturnNoSegments(TrapFrame
);
353 // Virtual 8086 Mode Optimized Trap Entry
357 KiEnterV86Trap(IN PKTRAP_FRAME TrapFrame
)
359 /* Save exception list */
360 TrapFrame
->ExceptionList
= KeGetPcr()->NtTib
.ExceptionList
;
362 /* Save DR7 and check for debugging */
363 TrapFrame
->Dr7
= __readdr(7);
364 if (__builtin_expect(TrapFrame
->Dr7
& ~DR7_RESERVED_MASK
, 0))
366 /* Handle debug registers */
367 KiHandleDebugRegistersOnTrapEntry(TrapFrame
);
372 // Interrupt Trap Entry
376 KiEnterInterruptTrap(IN PKTRAP_FRAME TrapFrame
)
378 /* Save exception list and terminate it */
379 TrapFrame
->ExceptionList
= KeGetPcr()->NtTib
.ExceptionList
;
380 KeGetPcr()->NtTib
.ExceptionList
= EXCEPTION_CHAIN_END
;
382 /* Default to debugging disabled */
385 /* Check if the frame was from user mode or v86 mode */
386 if (KiUserTrap(TrapFrame
) ||
387 (TrapFrame
->EFlags
& EFLAGS_V86_MASK
))
389 /* Check for active debugging */
390 if (KeGetCurrentThread()->Header
.DebugActive
& 0xFF)
392 /* Handle debug registers */
393 KiHandleDebugRegistersOnTrapEntry(TrapFrame
);
397 /* Set debug header */
398 KiFillTrapFrameDebug(TrapFrame
);
402 // Generic Trap Entry
406 KiEnterTrap(IN PKTRAP_FRAME TrapFrame
)
408 /* Save exception list */
409 TrapFrame
->ExceptionList
= KeGetPcr()->NtTib
.ExceptionList
;
411 /* Default to debugging disabled */
414 /* Check if the frame was from user mode or v86 mode */
415 if (KiUserTrap(TrapFrame
) ||
416 (TrapFrame
->EFlags
& EFLAGS_V86_MASK
))
418 /* Check for active debugging */
419 if (KeGetCurrentThread()->Header
.DebugActive
& 0xFF)
421 /* Handle debug registers */
422 KiHandleDebugRegistersOnTrapEntry(TrapFrame
);
426 /* Set debug header */
427 KiFillTrapFrameDebug(TrapFrame
);