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
13 #define UNREACHABLE __assume(0)
16 #define __builtin_expect(a,b) (a)
24 KiUserTrap(IN PKTRAP_FRAME TrapFrame
)
26 /* Anything else but Ring 0 is Ring 3 */
27 return !!(TrapFrame
->SegCs
& MODE_MASK
);
35 KiDumpTrapFrame(IN PKTRAP_FRAME TrapFrame
)
37 /* Dump the whole thing */
38 DbgPrint("DbgEbp: %x\n", TrapFrame
->DbgEbp
);
39 DbgPrint("DbgEip: %x\n", TrapFrame
->DbgEip
);
40 DbgPrint("DbgArgMark: %x\n", TrapFrame
->DbgArgMark
);
41 DbgPrint("DbgArgPointer: %x\n", TrapFrame
->DbgArgPointer
);
42 DbgPrint("TempSegCs: %x\n", TrapFrame
->TempSegCs
);
43 DbgPrint("TempEsp: %x\n", TrapFrame
->TempEsp
);
44 DbgPrint("Dr0: %x\n", TrapFrame
->Dr0
);
45 DbgPrint("Dr1: %x\n", TrapFrame
->Dr1
);
46 DbgPrint("Dr2: %x\n", TrapFrame
->Dr2
);
47 DbgPrint("Dr3: %x\n", TrapFrame
->Dr3
);
48 DbgPrint("Dr6: %x\n", TrapFrame
->Dr6
);
49 DbgPrint("Dr7: %x\n", TrapFrame
->Dr7
);
50 DbgPrint("SegGs: %x\n", TrapFrame
->SegGs
);
51 DbgPrint("SegEs: %x\n", TrapFrame
->SegEs
);
52 DbgPrint("SegDs: %x\n", TrapFrame
->SegDs
);
53 DbgPrint("Edx: %x\n", TrapFrame
->Edx
);
54 DbgPrint("Ecx: %x\n", TrapFrame
->Ecx
);
55 DbgPrint("Eax: %x\n", TrapFrame
->Eax
);
56 DbgPrint("PreviousPreviousMode: %x\n", TrapFrame
->PreviousPreviousMode
);
57 DbgPrint("ExceptionList: %p\n", TrapFrame
->ExceptionList
);
58 DbgPrint("SegFs: %x\n", TrapFrame
->SegFs
);
59 DbgPrint("Edi: %x\n", TrapFrame
->Edi
);
60 DbgPrint("Esi: %x\n", TrapFrame
->Esi
);
61 DbgPrint("Ebx: %x\n", TrapFrame
->Ebx
);
62 DbgPrint("Ebp: %x\n", TrapFrame
->Ebp
);
63 DbgPrint("ErrCode: %x\n", TrapFrame
->ErrCode
);
64 DbgPrint("Eip: %x\n", TrapFrame
->Eip
);
65 DbgPrint("SegCs: %x\n", TrapFrame
->SegCs
);
66 DbgPrint("EFlags: %x\n", TrapFrame
->EFlags
);
67 DbgPrint("HardwareEsp: %x\n", TrapFrame
->HardwareEsp
);
68 DbgPrint("HardwareSegSs: %x\n", TrapFrame
->HardwareSegSs
);
69 DbgPrint("V86Es: %x\n", TrapFrame
->V86Es
);
70 DbgPrint("V86Ds: %x\n", TrapFrame
->V86Ds
);
71 DbgPrint("V86Fs: %x\n", TrapFrame
->V86Fs
);
72 DbgPrint("V86Gs: %x\n", TrapFrame
->V86Gs
);
78 KiFillTrapFrameDebug(IN PKTRAP_FRAME TrapFrame
)
80 /* Set the debug information */
81 TrapFrame
->DbgArgPointer
= TrapFrame
->Edx
;
82 TrapFrame
->DbgArgMark
= 0xBADB0D00;
83 TrapFrame
->DbgEip
= TrapFrame
->Eip
;
84 TrapFrame
->DbgEbp
= TrapFrame
->Ebp
;
85 TrapFrame
->PreviousPreviousMode
= -1;
88 #define DR7_RESERVED_READ_AS_1 0x400
90 #define CheckDr(DrNumner, ExpectedValue) \
92 ULONG DrValue = __readdr(DrNumner); \
93 if (DrValue != (ExpectedValue)) \
95 DbgPrint("Dr%ld: expected %.8lx, got %.8lx\n", \
96 DrNumner, ExpectedValue, DrValue); \
101 extern BOOLEAN StopChecking
;
105 KiExitTrapDebugChecks(IN PKTRAP_FRAME TrapFrame
,
106 IN BOOLEAN SkipPreviousMode
)
108 /* Don't check recursively */
109 if (StopChecking
) return;
112 /* Make sure interrupts are disabled */
113 if (__readeflags() & EFLAGS_INTERRUPT_MASK
)
115 DbgPrint("Exiting with interrupts enabled: %lx\n", __readeflags());
119 /* Make sure this is a real trap frame */
120 if (TrapFrame
->DbgArgMark
!= 0xBADB0D00)
122 DbgPrint("Exiting with an invalid trap frame? (No MAGIC in trap frame)\n");
123 KiDumpTrapFrame(TrapFrame
);
127 /* Make sure we're not in user-mode or something */
128 if (Ke386GetFs() != KGDT_R0_PCR
)
130 DbgPrint("Exiting with an invalid FS: %lx\n", Ke386GetFs());
134 /* Make sure we have a valid SEH chain */
135 if (KeGetPcr()->NtTib
.ExceptionList
== 0)
137 DbgPrint("Exiting with NULL exception chain: %p\n", KeGetPcr()->NtTib
.ExceptionList
);
141 /* Make sure we're restoring a valid SEH chain */
142 if (TrapFrame
->ExceptionList
== 0)
144 DbgPrint("Entered a trap with a NULL exception chain: %p\n", TrapFrame
->ExceptionList
);
148 /* If we're ignoring previous mode, make sure caller doesn't actually want it */
149 if (SkipPreviousMode
&& (TrapFrame
->PreviousPreviousMode
!= -1))
151 DbgPrint("Exiting a trap witout restoring previous mode, yet previous mode seems valid: %lx\n", TrapFrame
->PreviousPreviousMode
);
155 /* Check DR values */
156 if (KiUserTrap(TrapFrame
))
158 /* Check for active debugging */
159 if (KeGetCurrentThread()->Header
.DebugActive
)
161 if ((TrapFrame
->Dr7
& ~DR7_RESERVED_MASK
) == 0) __debugbreak();
163 CheckDr(0, TrapFrame
->Dr0
);
164 CheckDr(1, TrapFrame
->Dr1
);
165 CheckDr(2, TrapFrame
->Dr2
);
166 CheckDr(3, TrapFrame
->Dr3
);
167 CheckDr(7, TrapFrame
->Dr7
| DR7_RESERVED_READ_AS_1
);
172 PKPRCB Prcb
= KeGetCurrentPrcb();
173 CheckDr(0, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr0
);
174 CheckDr(1, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr1
);
175 CheckDr(2, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr2
);
176 CheckDr(3, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr3
);
177 //CheckDr(7, Prcb->ProcessorState.SpecialRegisters.KernelDr7);
180 StopChecking
= FALSE
;
184 #define KiExitTrapDebugChecks(x, y)
185 #define KiFillTrapFrameDebug(x)
190 KiExitSystemCallDebugChecks(IN ULONG SystemCall
,
191 IN PKTRAP_FRAME TrapFrame
)
195 /* Check if this was a user call */
196 if (KiUserTrap(TrapFrame
))
198 /* Make sure we are not returning with elevated IRQL */
199 OldIrql
= KeGetCurrentIrql();
200 if (OldIrql
!= PASSIVE_LEVEL
)
202 /* Forcibly put us in a sane state */
203 KeGetPcr()->Irql
= PASSIVE_LEVEL
;
207 KeBugCheckEx(IRQL_GT_ZERO_AT_SYSTEM_SERVICE
,
214 /* Make sure we're not attached and that APCs are not disabled */
215 if ((KeGetCurrentThread()->ApcStateIndex
!= OriginalApcEnvironment
) ||
216 (KeGetCurrentThread()->CombinedApcDisable
!= 0))
219 KeBugCheckEx(APC_INDEX_MISMATCH
,
221 KeGetCurrentThread()->ApcStateIndex
,
222 KeGetCurrentThread()->CombinedApcDisable
,
229 // Generic Exit Routine
231 DECLSPEC_NORETURN VOID FASTCALL
KiSystemCallReturn(IN PKTRAP_FRAME TrapFrame
);
232 DECLSPEC_NORETURN VOID FASTCALL
KiSystemCallSysExitReturn(IN PKTRAP_FRAME TrapFrame
);
233 DECLSPEC_NORETURN VOID FASTCALL
KiSystemCallTrapReturn(IN PKTRAP_FRAME TrapFrame
);
234 DECLSPEC_NORETURN VOID FASTCALL
KiEditedTrapReturn(IN PKTRAP_FRAME TrapFrame
);
235 DECLSPEC_NORETURN VOID FASTCALL
KiTrapReturn(IN PKTRAP_FRAME TrapFrame
);
236 DECLSPEC_NORETURN VOID FASTCALL
KiTrapReturnNoSegments(IN PKTRAP_FRAME TrapFrame
);
237 DECLSPEC_NORETURN VOID FASTCALL
KiTrapReturnNoSegmentsRet8(IN PKTRAP_FRAME TrapFrame
);
242 (FASTCALL
*PFAST_SYSTEM_CALL_EXIT
)(
243 IN PKTRAP_FRAME TrapFrame
246 extern PFAST_SYSTEM_CALL_EXIT KiFastCallExitHandler
;
249 // Save user mode debug registers and restore kernel values
253 KiHandleDebugRegistersOnTrapEntry(
254 IN PKTRAP_FRAME TrapFrame
)
256 PKPRCB Prcb
= KeGetCurrentPrcb();
258 /* Save all debug registers in the trap frame */
259 TrapFrame
->Dr0
= __readdr(0);
260 TrapFrame
->Dr1
= __readdr(1);
261 TrapFrame
->Dr2
= __readdr(2);
262 TrapFrame
->Dr3
= __readdr(3);
263 TrapFrame
->Dr6
= __readdr(6);
264 TrapFrame
->Dr7
= __readdr(7);
266 /* Disable all active debugging */
269 /* Restore kernel values */
270 __writedr(0, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr0
);
271 __writedr(1, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr1
);
272 __writedr(2, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr2
);
273 __writedr(3, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr3
);
274 __writedr(6, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr6
);
275 __writedr(7, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr7
);
280 KiHandleDebugRegistersOnTrapExit(
281 PKTRAP_FRAME TrapFrame
)
283 /* Disable all active debugging */
286 /* Load all debug registers from the trap frame */
287 __writedr(0, TrapFrame
->Dr0
);
288 __writedr(1, TrapFrame
->Dr1
);
289 __writedr(2, TrapFrame
->Dr2
);
290 __writedr(3, TrapFrame
->Dr3
);
291 __writedr(6, TrapFrame
->Dr6
);
292 __writedr(7, TrapFrame
->Dr7
);
296 // Virtual 8086 Mode Optimized Trap Exit
301 KiExitV86Trap(IN PKTRAP_FRAME TrapFrame
)
307 Thread
= KeGetCurrentThread();
310 /* Return if this isn't V86 mode anymore */
311 if (!(TrapFrame
->EFlags
& EFLAGS_V86_MASK
)) KiEoiHelper(TrapFrame
);
313 /* Turn off the alerted state for kernel mode */
314 Thread
->Alerted
[KernelMode
] = FALSE
;
316 /* Are there pending user APCs? */
317 if (__builtin_expect(!Thread
->ApcState
.UserApcPending
, 1)) break;
319 /* Raise to APC level and enable interrupts */
320 OldIrql
= KfRaiseIrql(APC_LEVEL
);
324 KiDeliverApc(UserMode
, NULL
, TrapFrame
);
326 /* Restore IRQL and disable interrupts once again */
327 KfLowerIrql(OldIrql
);
331 /* If we got here, we're still in a valid V8086 context, so quit it */
332 if (__builtin_expect(TrapFrame
->Dr7
& ~DR7_RESERVED_MASK
, 0))
334 /* Restore debug registers from the trap frame */
335 KiHandleDebugRegistersOnTrapExit(TrapFrame
);
338 /* Return from interrupt */
339 KiTrapReturnNoSegments(TrapFrame
);
343 // Virtual 8086 Mode Optimized Trap Entry
347 KiEnterV86Trap(IN PKTRAP_FRAME TrapFrame
)
349 /* Save exception list */
350 TrapFrame
->ExceptionList
= KeGetPcr()->NtTib
.ExceptionList
;
352 /* Save DR7 and check for debugging */
353 TrapFrame
->Dr7
= __readdr(7);
354 if (__builtin_expect(TrapFrame
->Dr7
& ~DR7_RESERVED_MASK
, 0))
356 /* Handle debug registers */
357 KiHandleDebugRegistersOnTrapEntry(TrapFrame
);
362 // Interrupt Trap Entry
366 KiEnterInterruptTrap(IN PKTRAP_FRAME TrapFrame
)
368 /* Save exception list and terminate it */
369 TrapFrame
->ExceptionList
= KeGetPcr()->NtTib
.ExceptionList
;
370 KeGetPcr()->NtTib
.ExceptionList
= EXCEPTION_CHAIN_END
;
372 /* Default to debugging disabled */
375 /* Check if the frame was from user mode or v86 mode */
376 if (KiUserTrap(TrapFrame
) ||
377 (TrapFrame
->EFlags
& EFLAGS_V86_MASK
))
379 /* Check for active debugging */
380 if (KeGetCurrentThread()->Header
.DebugActive
& 0xFF)
382 /* Handle debug registers */
383 KiHandleDebugRegistersOnTrapEntry(TrapFrame
);
387 /* Set debug header */
388 KiFillTrapFrameDebug(TrapFrame
);
392 // Generic Trap Entry
396 KiEnterTrap(IN PKTRAP_FRAME TrapFrame
)
398 /* Save exception list */
399 TrapFrame
->ExceptionList
= KeGetPcr()->NtTib
.ExceptionList
;
401 /* Default to debugging disabled */
404 /* Check if the frame was from user mode or v86 mode */
405 if (KiUserTrap(TrapFrame
) ||
406 (TrapFrame
->EFlags
& EFLAGS_V86_MASK
))
408 /* Check for active debugging */
409 if (KeGetCurrentThread()->Header
.DebugActive
& 0xFF)
411 /* Handle debug registers */
412 KiHandleDebugRegistersOnTrapEntry(TrapFrame
);
416 /* Set debug header */
417 KiFillTrapFrameDebug(TrapFrame
);