ReactOS 0.4.16-dev-92-g0c2cdca
trap_x.h
Go to the documentation of this file.
1/*
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
7 */
8
9#pragma once
10
11#if defined(_MSC_VER)
12#define __builtin_expect(a,b) (a)
13#endif
14
15//
16// Helper Code
17//
21{
22 /* Anything else but Ring 0 is Ring 3 */
23 return !!(TrapFrame->SegCs & MODE_MASK);
24}
25
26//
27// Debug Macros
28//
30VOID
32{
33 /* Dump the whole thing */
34 DbgPrint("DbgEbp: %x\n", TrapFrame->DbgEbp);
35 DbgPrint("DbgEip: %x\n", TrapFrame->DbgEip);
36 DbgPrint("DbgArgMark: %x\n", TrapFrame->DbgArgMark);
37 DbgPrint("DbgArgPointer: %x\n", TrapFrame->DbgArgPointer);
38 DbgPrint("TempSegCs: %x\n", TrapFrame->TempSegCs);
39 DbgPrint("TempEsp: %x\n", TrapFrame->TempEsp);
40 DbgPrint("Dr0: %x\n", TrapFrame->Dr0);
41 DbgPrint("Dr1: %x\n", TrapFrame->Dr1);
42 DbgPrint("Dr2: %x\n", TrapFrame->Dr2);
43 DbgPrint("Dr3: %x\n", TrapFrame->Dr3);
44 DbgPrint("Dr6: %x\n", TrapFrame->Dr6);
45 DbgPrint("Dr7: %x\n", TrapFrame->Dr7);
46 DbgPrint("SegGs: %x\n", TrapFrame->SegGs);
47 DbgPrint("SegEs: %x\n", TrapFrame->SegEs);
48 DbgPrint("SegDs: %x\n", TrapFrame->SegDs);
49 DbgPrint("Edx: %x\n", TrapFrame->Edx);
50 DbgPrint("Ecx: %x\n", TrapFrame->Ecx);
51 DbgPrint("Eax: %x\n", TrapFrame->Eax);
52 DbgPrint("PreviousPreviousMode: %x\n", TrapFrame->PreviousPreviousMode);
53 DbgPrint("ExceptionList: %p\n", TrapFrame->ExceptionList);
54 DbgPrint("SegFs: %x\n", TrapFrame->SegFs);
55 DbgPrint("Edi: %x\n", TrapFrame->Edi);
56 DbgPrint("Esi: %x\n", TrapFrame->Esi);
57 DbgPrint("Ebx: %x\n", TrapFrame->Ebx);
58 DbgPrint("Ebp: %x\n", TrapFrame->Ebp);
59 DbgPrint("ErrCode: %x\n", TrapFrame->ErrCode);
60 DbgPrint("Eip: %x\n", TrapFrame->Eip);
61 DbgPrint("SegCs: %x\n", TrapFrame->SegCs);
62 DbgPrint("EFlags: %x\n", TrapFrame->EFlags);
63 DbgPrint("HardwareEsp: %x\n", TrapFrame->HardwareEsp);
64 DbgPrint("HardwareSegSs: %x\n", TrapFrame->HardwareSegSs);
65 DbgPrint("V86Es: %x\n", TrapFrame->V86Es);
66 DbgPrint("V86Ds: %x\n", TrapFrame->V86Ds);
67 DbgPrint("V86Fs: %x\n", TrapFrame->V86Fs);
68 DbgPrint("V86Gs: %x\n", TrapFrame->V86Gs);
69}
70
71#if DBG
73VOID
75{
76 /* Set the debug information */
77 TrapFrame->DbgArgPointer = TrapFrame->Edx;
78 TrapFrame->DbgArgMark = 0xBADB0D00;
79 TrapFrame->DbgEip = TrapFrame->Eip;
80 TrapFrame->DbgEbp = TrapFrame->Ebp;
81 TrapFrame->PreviousPreviousMode = (ULONG)-1;
82}
83
84#define DR7_RESERVED_READ_AS_1 0x400
85
86#define CheckDr(DrNumner, ExpectedValue) \
87 { \
88 ULONG DrValue = __readdr(DrNumner); \
89 if (DrValue != (ExpectedValue)) \
90 { \
91 DbgPrint("Dr%ld: expected %.8lx, got %.8lx\n", \
92 DrNumner, ExpectedValue, DrValue); \
93 __debugbreak(); \
94 } \
95 }
96
97extern BOOLEAN StopChecking;
98
100VOID
102 IN BOOLEAN SkipPreviousMode)
103{
104 /* Don't check recursively */
105 if (StopChecking) return;
106 StopChecking = TRUE;
107
108 /* Make sure interrupts are disabled */
110 {
111 DbgPrint("Exiting with interrupts enabled: %lx\n", __readeflags());
112 __debugbreak();
113 }
114
115 /* Make sure this is a real trap frame */
116 if (TrapFrame->DbgArgMark != 0xBADB0D00)
117 {
118 DbgPrint("Exiting with an invalid trap frame? (No MAGIC in trap frame)\n");
119 KiDumpTrapFrame(TrapFrame);
120 __debugbreak();
121 }
122
123 /* Make sure we're not in user-mode or something */
124 if (Ke386GetFs() != KGDT_R0_PCR)
125 {
126 DbgPrint("Exiting with an invalid FS: %lx\n", Ke386GetFs());
127 __debugbreak();
128 }
129
130 /* Make sure we have a valid SEH chain */
131 if (KeGetPcr()->NtTib.ExceptionList == 0)
132 {
133 DbgPrint("Exiting with NULL exception chain: %p\n", KeGetPcr()->NtTib.ExceptionList);
134 __debugbreak();
135 }
136
137 /* Make sure we're restoring a valid SEH chain */
138 if (TrapFrame->ExceptionList == 0)
139 {
140 DbgPrint("Entered a trap with a NULL exception chain: %p\n", TrapFrame->ExceptionList);
141 __debugbreak();
142 }
143
144 /* If we're ignoring previous mode, make sure caller doesn't actually want it */
145 if (SkipPreviousMode && (TrapFrame->PreviousPreviousMode != (ULONG)-1))
146 {
147 DbgPrint("Exiting a trap witout restoring previous mode, yet previous mode seems valid: %lx\n", TrapFrame->PreviousPreviousMode);
148 __debugbreak();
149 }
150
151 /* FIXME: KDBG messes around with these improperly */
152#if !defined(KDBG)
153 /* Check DR values */
154 if (KiUserTrap(TrapFrame))
155 {
156 /* Check for active debugging */
157 if (KeGetCurrentThread()->Header.DebugActive)
158 {
159 if ((TrapFrame->Dr7 & ~DR7_RESERVED_MASK) == 0) __debugbreak();
160
161 CheckDr(0, TrapFrame->Dr0);
162 CheckDr(1, TrapFrame->Dr1);
163 CheckDr(2, TrapFrame->Dr2);
164 CheckDr(3, TrapFrame->Dr3);
165 CheckDr(7, TrapFrame->Dr7 | DR7_RESERVED_READ_AS_1);
166 }
167 }
168 else
169 {
170 PKPRCB Prcb = KeGetCurrentPrcb();
171 CheckDr(0, Prcb->ProcessorState.SpecialRegisters.KernelDr0);
172 CheckDr(1, Prcb->ProcessorState.SpecialRegisters.KernelDr1);
173 CheckDr(2, Prcb->ProcessorState.SpecialRegisters.KernelDr2);
174 CheckDr(3, Prcb->ProcessorState.SpecialRegisters.KernelDr3);
175 // CheckDr(7, Prcb->ProcessorState.SpecialRegisters.KernelDr7); // Disabled, see CORE-10165 for more details.
176 }
177#endif
178
179 StopChecking = FALSE;
180}
181
182#else
183#define KiExitTrapDebugChecks(x, y)
184#define KiFillTrapFrameDebug(x)
185#endif
186
188VOID
190 IN PKTRAP_FRAME TrapFrame)
191{
193
194 /* Check if this was a user call */
195 if (KiUserTrap(TrapFrame))
196 {
197 /* Make sure we are not returning with elevated IRQL */
199 if (OldIrql != PASSIVE_LEVEL)
200 {
201 /* Forcibly put us in a sane state */
202 KeGetPcr()->Irql = PASSIVE_LEVEL;
203 _disable();
204
205 /* Fail */
206 KeBugCheckEx(IRQL_GT_ZERO_AT_SYSTEM_SERVICE,
207 SystemCall,
208 OldIrql,
209 0,
210 0);
211 }
212
213 /* Make sure we're not attached and that APCs are not disabled */
214 if ((KeGetCurrentThread()->ApcStateIndex != OriginalApcEnvironment) ||
215 (KeGetCurrentThread()->CombinedApcDisable != 0))
216 {
217 /* Fail */
218 KeBugCheckEx(APC_INDEX_MISMATCH,
219 SystemCall,
220 KeGetCurrentThread()->ApcStateIndex,
221 KeGetCurrentThread()->CombinedApcDisable,
222 0);
223 }
224 }
225}
226
227//
228// Generic Exit Routine
229//
237
238typedef
241 IN PKTRAP_FRAME TrapFrame
242);
243
245
246//
247// Save user mode debug registers and restore kernel values
248//
250VOID
252 IN PKTRAP_FRAME TrapFrame)
253{
254 PKPRCB Prcb = KeGetCurrentPrcb();
255
256 /* Save all debug registers in the trap frame */
257 TrapFrame->Dr0 = __readdr(0);
258 TrapFrame->Dr1 = __readdr(1);
259 TrapFrame->Dr2 = __readdr(2);
260 TrapFrame->Dr3 = __readdr(3);
261 TrapFrame->Dr6 = __readdr(6);
262 TrapFrame->Dr7 = __readdr(7);
263
264 /* Disable all active debugging */
265 __writedr(7, 0);
266
267 /* Restore kernel values */
274}
275
277VOID
279 PKTRAP_FRAME TrapFrame)
280{
281 /* Disable all active debugging */
282 __writedr(7, 0);
283
284 /* Load all debug registers from the trap frame */
285 __writedr(0, TrapFrame->Dr0);
286 __writedr(1, TrapFrame->Dr1);
287 __writedr(2, TrapFrame->Dr2);
288 __writedr(3, TrapFrame->Dr3);
289 __writedr(6, TrapFrame->Dr6);
290 __writedr(7, TrapFrame->Dr7);
291}
292
293//
294// Virtual 8086 Mode Optimized Trap Exit
295//
298VOID
300{
303
304 /* Get the thread */
306 while (TRUE)
307 {
308 /* Return if this isn't V86 mode anymore */
309 if (!(TrapFrame->EFlags & EFLAGS_V86_MASK)) KiEoiHelper(TrapFrame);
310
311 /* Turn off the alerted state for kernel mode */
312 Thread->Alerted[KernelMode] = FALSE;
313
314 /* Are there pending user APCs? */
315 if (__builtin_expect(!Thread->ApcState.UserApcPending, 1)) break;
316
317 /* Raise to APC level and enable interrupts */
319 _enable();
320
321 /* Deliver APCs */
322 KiDeliverApc(UserMode, NULL, TrapFrame);
323
324 /* Restore IRQL and disable interrupts once again */
326 _disable();
327 }
328
329 /* If we got here, we're still in a valid V8086 context, so quit it */
330 if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
331 {
332 /* Restore debug registers from the trap frame */
334 }
335
336 /* Return from interrupt */
337 KiTrapReturnNoSegments(TrapFrame);
338}
339
340//
341// Virtual 8086 Mode Optimized Trap Entry
342//
344VOID
346{
347 PVOID ExceptionList;
348
349 /* Check exception list */
350 ExceptionList = KeGetPcr()->NtTib.ExceptionList;
351 ASSERTMSG("V86 trap handler must not register an SEH frame\n",
352 ExceptionList == TrapFrame->ExceptionList);
353
354 /* Save DR7 and check for debugging */
355 TrapFrame->Dr7 = __readdr(7);
356 if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
357 {
358 /* Handle debug registers */
360 }
361}
362
363//
364// Interrupt Trap Entry
365//
367VOID
369{
370 PVOID ExceptionList;
371
372 /* Check exception list and terminate it */
373 ExceptionList = KeGetPcr()->NtTib.ExceptionList;
374 ASSERTMSG("Interrupt handler must not register an SEH frame\n",
375 ExceptionList == TrapFrame->ExceptionList);
376 KeGetPcr()->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
377
378 /* Default to debugging disabled */
379 TrapFrame->Dr7 = 0;
380
381 /* Check if the frame was from user mode or v86 mode */
382 if (KiUserTrap(TrapFrame) ||
383 (TrapFrame->EFlags & EFLAGS_V86_MASK))
384 {
385 /* Check for active debugging */
386 if (KeGetCurrentThread()->Header.DebugActive & 0xFF)
387 {
388 /* Handle debug registers */
390 }
391 }
392
393 /* Set debug header */
394 KiFillTrapFrameDebug(TrapFrame);
395}
396
397//
398// Generic Trap Entry
399//
401VOID
403{
404 PVOID ExceptionList;
405
406 /* Check exception list */
407 ExceptionList = KeGetPcr()->NtTib.ExceptionList;
408 ASSERTMSG("Trap handler must not register an SEH frame\n",
409 ExceptionList == TrapFrame->ExceptionList);
410
411 /* Default to debugging disabled */
412 TrapFrame->Dr7 = 0;
413
414 /* Check if the frame was from user mode or v86 mode */
415 if (KiUserTrap(TrapFrame) ||
416 (TrapFrame->EFlags & EFLAGS_V86_MASK))
417 {
418 /* Check for active debugging */
419 if (KeGetCurrentThread()->Header.DebugActive & 0xFF)
420 {
421 /* Handle debug registers */
423 }
424 }
425
426 /* Set debug header */
427 KiFillTrapFrameDebug(TrapFrame);
428}
unsigned char BOOLEAN
#define EFLAGS_INTERRUPT_MASK
Definition: SystemCall.c:11
#define VOID
Definition: acefi.h:82
#define MODE_MASK
Definition: orders.h:326
Definition: Header.h:9
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
VOID FASTCALL KfLowerIrql(IN KIRQL NewIrql)
Definition: pic.c:232
KIRQL FASTCALL KfRaiseIrql(IN KIRQL NewIrql)
Definition: pic.c:187
#define DbgPrint
Definition: hal.h:12
#define KeGetCurrentThread
Definition: hal.h:55
void __cdecl _disable(void)
Definition: intrin_arm.h:365
void __cdecl _enable(void)
Definition: intrin_arm.h:373
void __cdecl __debugbreak(void)
Definition: intrin_ppc.h:698
__INTRIN_INLINE unsigned int __readdr(unsigned int reg)
Definition: intrin_x86.h:1902
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1674
__INTRIN_INLINE void __writedr(unsigned reg, unsigned int value)
Definition: intrin_x86.h:1935
#define KernelMode
Definition: asm.h:34
#define UserMode
Definition: asm.h:35
#define EFLAGS_V86_MASK
Definition: ketypes.h:193
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1161
#define DR7_RESERVED_MASK
Definition: asm.h:515
#define KeGetPcr()
Definition: ketypes.h:81
#define KGDT_R0_PCR
Definition: ketypes.h:128
@ OriginalApcEnvironment
Definition: ketypes.h:767
#define EXCEPTION_CHAIN_END
Definition: rtltypes.h:63
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
#define FASTCALL
Definition: nt_native.h:50
#define DECLSPEC_NORETURN
Definition: ntbasedef.h:176
DECLSPEC_NORETURN VOID FASTCALL KiEoiHelper(IN PKTRAP_FRAME TrapFrame)
Definition: traphdlr.c:126
VOID NTAPI KiDeliverApc(IN KPROCESSOR_MODE DeliveryMode, IN PKEXCEPTION_FRAME ExceptionFrame, IN PKTRAP_FRAME TrapFrame)
Definition: apc.c:302
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
KPROCESSOR_STATE ProcessorState
Definition: ketypes.h:663
KSPECIAL_REGISTERS SpecialRegisters
Definition: ketypes.h:615
ULONG64 KernelDr1
Definition: ketypes.h:586
ULONG64 KernelDr2
Definition: ketypes.h:587
ULONG64 KernelDr0
Definition: ketypes.h:585
ULONG64 KernelDr7
Definition: ketypes.h:590
ULONG64 KernelDr6
Definition: ketypes.h:589
ULONG64 KernelDr3
Definition: ketypes.h:588
UINT64 Dr0
Definition: ketypes.h:427
UINT64 Dr6
Definition: ketypes.h:431
UINT64 Dr3
Definition: ketypes.h:430
UINT64 Dr7
Definition: ketypes.h:432
UINT64 Dr1
Definition: ketypes.h:428
UINT64 Dr2
Definition: ketypes.h:429
DECLSPEC_NORETURN VOID FASTCALL KiTrapReturnNoSegmentsRet8(IN PKTRAP_FRAME TrapFrame)
FORCEINLINE VOID KiEnterV86Trap(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:345
FORCEINLINE VOID KiHandleDebugRegistersOnTrapEntry(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:251
FORCEINLINE DECLSPEC_NORETURN VOID KiExitV86Trap(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:299
DECLSPEC_NORETURN VOID FASTCALL KiTrapReturn(IN PKTRAP_FRAME TrapFrame)
#define KiFillTrapFrameDebug(x)
Definition: trap_x.h:184
FORCEINLINE VOID KiHandleDebugRegistersOnTrapExit(PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:278
DECLSPEC_NORETURN VOID FASTCALL KiSystemCallTrapReturn(IN PKTRAP_FRAME TrapFrame)
FORCEINLINE VOID KiEnterTrap(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:402
FORCEINLINE VOID KiEnterInterruptTrap(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:368
DECLSPEC_NORETURN VOID FASTCALL KiEditedTrapReturn(IN PKTRAP_FRAME TrapFrame)
DECLSPEC_NORETURN VOID FASTCALL KiSystemCallSysExitReturn(IN PKTRAP_FRAME TrapFrame)
PFAST_SYSTEM_CALL_EXIT KiFastCallExitHandler
Definition: traphdlr.c:56
VOID(FASTCALL * PFAST_SYSTEM_CALL_EXIT)(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:240
DECLSPEC_NORETURN VOID FASTCALL KiTrapReturnNoSegments(IN PKTRAP_FRAME TrapFrame)
#define KiExitTrapDebugChecks(x, y)
Definition: trap_x.h:183
DECLSPEC_NORETURN VOID FASTCALL KiSystemCallReturn(IN PKTRAP_FRAME TrapFrame)
FORCEINLINE VOID KiDumpTrapFrame(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:31
FORCEINLINE BOOLEAN KiUserTrap(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:20
FORCEINLINE VOID KiExitSystemCallDebugChecks(IN ULONG SystemCall, IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:189
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define FORCEINLINE
Definition: wdftypes.h:67
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778