2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/include/internal/i386/trap_x.h
5 * PURPOSE: Internal Inlined Functions for the Trap Handling Code
6 * PROGRAMMERS: ReactOS Portable Systems Group
12 #define UNREACHABLE __assume(0)
13 #define __builtin_expect(a,b) (a)
14 #elif defined(__GNUC__)
15 #define UNREACHABLE __builtin_unreachable()
25 KiUserTrap(IN PKTRAP_FRAME TrapFrame
)
27 /* Anything else but Ring 0 is Ring 3 */
28 return !!(TrapFrame
->SegCs
& MODE_MASK
);
36 KiDumpTrapFrame(IN PKTRAP_FRAME TrapFrame
)
38 /* Dump the whole thing */
39 DbgPrint("DbgEbp: %x\n", TrapFrame
->DbgEbp
);
40 DbgPrint("DbgEip: %x\n", TrapFrame
->DbgEip
);
41 DbgPrint("DbgArgMark: %x\n", TrapFrame
->DbgArgMark
);
42 DbgPrint("DbgArgPointer: %x\n", TrapFrame
->DbgArgPointer
);
43 DbgPrint("TempSegCs: %x\n", TrapFrame
->TempSegCs
);
44 DbgPrint("TempEsp: %x\n", TrapFrame
->TempEsp
);
45 DbgPrint("Dr0: %x\n", TrapFrame
->Dr0
);
46 DbgPrint("Dr1: %x\n", TrapFrame
->Dr1
);
47 DbgPrint("Dr2: %x\n", TrapFrame
->Dr2
);
48 DbgPrint("Dr3: %x\n", TrapFrame
->Dr3
);
49 DbgPrint("Dr6: %x\n", TrapFrame
->Dr6
);
50 DbgPrint("Dr7: %x\n", TrapFrame
->Dr7
);
51 DbgPrint("SegGs: %x\n", TrapFrame
->SegGs
);
52 DbgPrint("SegEs: %x\n", TrapFrame
->SegEs
);
53 DbgPrint("SegDs: %x\n", TrapFrame
->SegDs
);
54 DbgPrint("Edx: %x\n", TrapFrame
->Edx
);
55 DbgPrint("Ecx: %x\n", TrapFrame
->Ecx
);
56 DbgPrint("Eax: %x\n", TrapFrame
->Eax
);
57 DbgPrint("PreviousPreviousMode: %x\n", TrapFrame
->PreviousPreviousMode
);
58 DbgPrint("ExceptionList: %p\n", TrapFrame
->ExceptionList
);
59 DbgPrint("SegFs: %x\n", TrapFrame
->SegFs
);
60 DbgPrint("Edi: %x\n", TrapFrame
->Edi
);
61 DbgPrint("Esi: %x\n", TrapFrame
->Esi
);
62 DbgPrint("Ebx: %x\n", TrapFrame
->Ebx
);
63 DbgPrint("Ebp: %x\n", TrapFrame
->Ebp
);
64 DbgPrint("ErrCode: %x\n", TrapFrame
->ErrCode
);
65 DbgPrint("Eip: %x\n", TrapFrame
->Eip
);
66 DbgPrint("SegCs: %x\n", TrapFrame
->SegCs
);
67 DbgPrint("EFlags: %x\n", TrapFrame
->EFlags
);
68 DbgPrint("HardwareEsp: %x\n", TrapFrame
->HardwareEsp
);
69 DbgPrint("HardwareSegSs: %x\n", TrapFrame
->HardwareSegSs
);
70 DbgPrint("V86Es: %x\n", TrapFrame
->V86Es
);
71 DbgPrint("V86Ds: %x\n", TrapFrame
->V86Ds
);
72 DbgPrint("V86Fs: %x\n", TrapFrame
->V86Fs
);
73 DbgPrint("V86Gs: %x\n", TrapFrame
->V86Gs
);
79 KiFillTrapFrameDebug(IN PKTRAP_FRAME TrapFrame
)
81 /* Set the debug information */
82 TrapFrame
->DbgArgPointer
= TrapFrame
->Edx
;
83 TrapFrame
->DbgArgMark
= 0xBADB0D00;
84 TrapFrame
->DbgEip
= TrapFrame
->Eip
;
85 TrapFrame
->DbgEbp
= TrapFrame
->Ebp
;
86 TrapFrame
->PreviousPreviousMode
= -1;
89 #define DR7_RESERVED_READ_AS_1 0x400
91 #define CheckDr(DrNumner, ExpectedValue) \
93 ULONG DrValue = __readdr(DrNumner); \
94 if (DrValue != (ExpectedValue)) \
96 DbgPrint("Dr%ld: expected %.8lx, got %.8lx\n", \
97 DrNumner, ExpectedValue, DrValue); \
102 extern BOOLEAN StopChecking
;
106 KiExitTrapDebugChecks(IN PKTRAP_FRAME TrapFrame
,
107 IN BOOLEAN SkipPreviousMode
)
109 /* Don't check recursively */
110 if (StopChecking
) return;
113 /* Make sure interrupts are disabled */
114 if (__readeflags() & EFLAGS_INTERRUPT_MASK
)
116 DbgPrint("Exiting with interrupts enabled: %lx\n", __readeflags());
120 /* Make sure this is a real trap frame */
121 if (TrapFrame
->DbgArgMark
!= 0xBADB0D00)
123 DbgPrint("Exiting with an invalid trap frame? (No MAGIC in trap frame)\n");
124 KiDumpTrapFrame(TrapFrame
);
128 /* Make sure we're not in user-mode or something */
129 if (Ke386GetFs() != KGDT_R0_PCR
)
131 DbgPrint("Exiting with an invalid FS: %lx\n", Ke386GetFs());
135 /* Make sure we have a valid SEH chain */
136 if (KeGetPcr()->NtTib
.ExceptionList
== 0)
138 DbgPrint("Exiting with NULL exception chain: %p\n", KeGetPcr()->NtTib
.ExceptionList
);
142 /* Make sure we're restoring a valid SEH chain */
143 if (TrapFrame
->ExceptionList
== 0)
145 DbgPrint("Entered a trap with a NULL exception chain: %p\n", TrapFrame
->ExceptionList
);
149 /* If we're ignoring previous mode, make sure caller doesn't actually want it */
150 if (SkipPreviousMode
&& (TrapFrame
->PreviousPreviousMode
!= -1))
152 DbgPrint("Exiting a trap witout restoring previous mode, yet previous mode seems valid: %lx\n", TrapFrame
->PreviousPreviousMode
);
156 /* FIXME: KDBG messes around with these improperly */
158 /* Check DR values */
159 if (KiUserTrap(TrapFrame
))
161 /* Check for active debugging */
162 if (KeGetCurrentThread()->Header
.DebugActive
)
164 if ((TrapFrame
->Dr7
& ~DR7_RESERVED_MASK
) == 0) __debugbreak();
166 CheckDr(0, TrapFrame
->Dr0
);
167 CheckDr(1, TrapFrame
->Dr1
);
168 CheckDr(2, TrapFrame
->Dr2
);
169 CheckDr(3, TrapFrame
->Dr3
);
170 CheckDr(7, TrapFrame
->Dr7
| DR7_RESERVED_READ_AS_1
);
175 PKPRCB Prcb
= KeGetCurrentPrcb();
176 CheckDr(0, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr0
);
177 CheckDr(1, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr1
);
178 CheckDr(2, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr2
);
179 CheckDr(3, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr3
);
180 // CheckDr(7, Prcb->ProcessorState.SpecialRegisters.KernelDr7); // Disabled, see CORE-10165 for more details.
184 StopChecking
= FALSE
;
188 #define KiExitTrapDebugChecks(x, y)
189 #define KiFillTrapFrameDebug(x)
194 KiExitSystemCallDebugChecks(IN ULONG SystemCall
,
195 IN PKTRAP_FRAME TrapFrame
)
199 /* Check if this was a user call */
200 if (KiUserTrap(TrapFrame
))
202 /* Make sure we are not returning with elevated IRQL */
203 OldIrql
= KeGetCurrentIrql();
204 if (OldIrql
!= PASSIVE_LEVEL
)
206 /* Forcibly put us in a sane state */
207 KeGetPcr()->Irql
= PASSIVE_LEVEL
;
211 KeBugCheckEx(IRQL_GT_ZERO_AT_SYSTEM_SERVICE
,
218 /* Make sure we're not attached and that APCs are not disabled */
219 if ((KeGetCurrentThread()->ApcStateIndex
!= OriginalApcEnvironment
) ||
220 (KeGetCurrentThread()->CombinedApcDisable
!= 0))
223 KeBugCheckEx(APC_INDEX_MISMATCH
,
225 KeGetCurrentThread()->ApcStateIndex
,
226 KeGetCurrentThread()->CombinedApcDisable
,
233 // Generic Exit Routine
235 DECLSPEC_NORETURN VOID FASTCALL
KiSystemCallReturn(IN PKTRAP_FRAME TrapFrame
);
236 DECLSPEC_NORETURN VOID FASTCALL
KiSystemCallSysExitReturn(IN PKTRAP_FRAME TrapFrame
);
237 DECLSPEC_NORETURN VOID FASTCALL
KiSystemCallTrapReturn(IN PKTRAP_FRAME TrapFrame
);
238 DECLSPEC_NORETURN VOID FASTCALL
KiEditedTrapReturn(IN PKTRAP_FRAME TrapFrame
);
239 DECLSPEC_NORETURN VOID FASTCALL
KiTrapReturn(IN PKTRAP_FRAME TrapFrame
);
240 DECLSPEC_NORETURN VOID FASTCALL
KiTrapReturnNoSegments(IN PKTRAP_FRAME TrapFrame
);
241 DECLSPEC_NORETURN VOID FASTCALL
KiTrapReturnNoSegmentsRet8(IN PKTRAP_FRAME TrapFrame
);
245 (FASTCALL
*PFAST_SYSTEM_CALL_EXIT
)(
246 IN PKTRAP_FRAME TrapFrame
249 extern PFAST_SYSTEM_CALL_EXIT KiFastCallExitHandler
;
252 // Save user mode debug registers and restore kernel values
256 KiHandleDebugRegistersOnTrapEntry(
257 IN PKTRAP_FRAME TrapFrame
)
259 PKPRCB Prcb
= KeGetCurrentPrcb();
261 /* Save all debug registers in the trap frame */
262 TrapFrame
->Dr0
= __readdr(0);
263 TrapFrame
->Dr1
= __readdr(1);
264 TrapFrame
->Dr2
= __readdr(2);
265 TrapFrame
->Dr3
= __readdr(3);
266 TrapFrame
->Dr6
= __readdr(6);
267 TrapFrame
->Dr7
= __readdr(7);
269 /* Disable all active debugging */
272 /* Restore kernel values */
273 __writedr(0, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr0
);
274 __writedr(1, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr1
);
275 __writedr(2, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr2
);
276 __writedr(3, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr3
);
277 __writedr(6, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr6
);
278 __writedr(7, Prcb
->ProcessorState
.SpecialRegisters
.KernelDr7
);
283 KiHandleDebugRegistersOnTrapExit(
284 PKTRAP_FRAME TrapFrame
)
286 /* Disable all active debugging */
289 /* Load all debug registers from the trap frame */
290 __writedr(0, TrapFrame
->Dr0
);
291 __writedr(1, TrapFrame
->Dr1
);
292 __writedr(2, TrapFrame
->Dr2
);
293 __writedr(3, TrapFrame
->Dr3
);
294 __writedr(6, TrapFrame
->Dr6
);
295 __writedr(7, TrapFrame
->Dr7
);
299 // Virtual 8086 Mode Optimized Trap Exit
304 KiExitV86Trap(IN PKTRAP_FRAME TrapFrame
)
310 Thread
= KeGetCurrentThread();
313 /* Return if this isn't V86 mode anymore */
314 if (!(TrapFrame
->EFlags
& EFLAGS_V86_MASK
)) KiEoiHelper(TrapFrame
);
316 /* Turn off the alerted state for kernel mode */
317 Thread
->Alerted
[KernelMode
] = FALSE
;
319 /* Are there pending user APCs? */
320 if (__builtin_expect(!Thread
->ApcState
.UserApcPending
, 1)) break;
322 /* Raise to APC level and enable interrupts */
323 OldIrql
= KfRaiseIrql(APC_LEVEL
);
327 KiDeliverApc(UserMode
, NULL
, TrapFrame
);
329 /* Restore IRQL and disable interrupts once again */
330 KfLowerIrql(OldIrql
);
334 /* If we got here, we're still in a valid V8086 context, so quit it */
335 if (__builtin_expect(TrapFrame
->Dr7
& ~DR7_RESERVED_MASK
, 0))
337 /* Restore debug registers from the trap frame */
338 KiHandleDebugRegistersOnTrapExit(TrapFrame
);
341 /* Return from interrupt */
342 KiTrapReturnNoSegments(TrapFrame
);
346 // Virtual 8086 Mode Optimized Trap Entry
350 KiEnterV86Trap(IN PKTRAP_FRAME TrapFrame
)
352 /* Save exception list */
353 TrapFrame
->ExceptionList
= KeGetPcr()->NtTib
.ExceptionList
;
355 /* Save DR7 and check for debugging */
356 TrapFrame
->Dr7
= __readdr(7);
357 if (__builtin_expect(TrapFrame
->Dr7
& ~DR7_RESERVED_MASK
, 0))
359 /* Handle debug registers */
360 KiHandleDebugRegistersOnTrapEntry(TrapFrame
);
365 // Interrupt Trap Entry
369 KiEnterInterruptTrap(IN PKTRAP_FRAME TrapFrame
)
371 /* Save exception list and terminate it */
372 TrapFrame
->ExceptionList
= KeGetPcr()->NtTib
.ExceptionList
;
373 KeGetPcr()->NtTib
.ExceptionList
= EXCEPTION_CHAIN_END
;
375 /* Default to debugging disabled */
378 /* Check if the frame was from user mode or v86 mode */
379 if (KiUserTrap(TrapFrame
) ||
380 (TrapFrame
->EFlags
& EFLAGS_V86_MASK
))
382 /* Check for active debugging */
383 if (KeGetCurrentThread()->Header
.DebugActive
& 0xFF)
385 /* Handle debug registers */
386 KiHandleDebugRegistersOnTrapEntry(TrapFrame
);
390 /* Set debug header */
391 KiFillTrapFrameDebug(TrapFrame
);
395 // Generic Trap Entry
399 KiEnterTrap(IN PKTRAP_FRAME TrapFrame
)
401 /* Save exception list */
402 TrapFrame
->ExceptionList
= KeGetPcr()->NtTib
.ExceptionList
;
404 /* Default to debugging disabled */
407 /* Check if the frame was from user mode or v86 mode */
408 if (KiUserTrap(TrapFrame
) ||
409 (TrapFrame
->EFlags
& EFLAGS_V86_MASK
))
411 /* Check for active debugging */
412 if (KeGetCurrentThread()->Header
.DebugActive
& 0xFF)
414 /* Handle debug registers */
415 KiHandleDebugRegistersOnTrapEntry(TrapFrame
);
419 /* Set debug header */
420 KiFillTrapFrameDebug(TrapFrame
);