ReactOS  0.4.14-dev-554-g2f8d847
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 UNREACHABLE __assume(0)
13 #define __builtin_expect(a,b) (a)
14 #elif defined(__GNUC__)
15 #define UNREACHABLE __builtin_unreachable()
16 #else
17 #error
18 #endif
19 
20 //
21 // Helper Code
22 //
24 BOOLEAN
26 {
27  /* Anything else but Ring 0 is Ring 3 */
28  return !!(TrapFrame->SegCs & MODE_MASK);
29 }
30 
31 //
32 // Debug Macros
33 //
35 VOID
37 {
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);
74 }
75 
76 #if DBG
78 VOID
80 {
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 = (ULONG)-1;
87 }
88 
89 #define DR7_RESERVED_READ_AS_1 0x400
90 
91 #define CheckDr(DrNumner, ExpectedValue) \
92  { \
93  ULONG DrValue = __readdr(DrNumner); \
94  if (DrValue != (ExpectedValue)) \
95  { \
96  DbgPrint("Dr%ld: expected %.8lx, got %.8lx\n", \
97  DrNumner, ExpectedValue, DrValue); \
98  __debugbreak(); \
99  } \
100  }
101 
102 extern BOOLEAN StopChecking;
103 
105 VOID
107  IN BOOLEAN SkipPreviousMode)
108 {
109  /* Don't check recursively */
110  if (StopChecking) return;
111  StopChecking = TRUE;
112 
113  /* Make sure interrupts are disabled */
115  {
116  DbgPrint("Exiting with interrupts enabled: %lx\n", __readeflags());
117  __debugbreak();
118  }
119 
120  /* Make sure this is a real trap frame */
121  if (TrapFrame->DbgArgMark != 0xBADB0D00)
122  {
123  DbgPrint("Exiting with an invalid trap frame? (No MAGIC in trap frame)\n");
124  KiDumpTrapFrame(TrapFrame);
125  __debugbreak();
126  }
127 
128  /* Make sure we're not in user-mode or something */
129  if (Ke386GetFs() != KGDT_R0_PCR)
130  {
131  DbgPrint("Exiting with an invalid FS: %lx\n", Ke386GetFs());
132  __debugbreak();
133  }
134 
135  /* Make sure we have a valid SEH chain */
136  if (KeGetPcr()->NtTib.ExceptionList == 0)
137  {
138  DbgPrint("Exiting with NULL exception chain: %p\n", KeGetPcr()->NtTib.ExceptionList);
139  __debugbreak();
140  }
141 
142  /* Make sure we're restoring a valid SEH chain */
143  if (TrapFrame->ExceptionList == 0)
144  {
145  DbgPrint("Entered a trap with a NULL exception chain: %p\n", TrapFrame->ExceptionList);
146  __debugbreak();
147  }
148 
149  /* If we're ignoring previous mode, make sure caller doesn't actually want it */
150  if (SkipPreviousMode && (TrapFrame->PreviousPreviousMode != -1))
151  {
152  DbgPrint("Exiting a trap witout restoring previous mode, yet previous mode seems valid: %lx\n", TrapFrame->PreviousPreviousMode);
153  __debugbreak();
154  }
155 
156  /* FIXME: KDBG messes around with these improperly */
157 #if !defined(KDBG)
158  /* Check DR values */
159  if (KiUserTrap(TrapFrame))
160  {
161  /* Check for active debugging */
162  if (KeGetCurrentThread()->Header.DebugActive)
163  {
164  if ((TrapFrame->Dr7 & ~DR7_RESERVED_MASK) == 0) __debugbreak();
165 
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);
171  }
172  }
173  else
174  {
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.
181  }
182 #endif
183 
184  StopChecking = FALSE;
185 }
186 
187 #else
188 #define KiExitTrapDebugChecks(x, y)
189 #define KiFillTrapFrameDebug(x)
190 #endif
191 
193 VOID
195  IN PKTRAP_FRAME TrapFrame)
196 {
197  KIRQL OldIrql;
198 
199  /* Check if this was a user call */
200  if (KiUserTrap(TrapFrame))
201  {
202  /* Make sure we are not returning with elevated IRQL */
204  if (OldIrql != PASSIVE_LEVEL)
205  {
206  /* Forcibly put us in a sane state */
207  KeGetPcr()->Irql = PASSIVE_LEVEL;
208  _disable();
209 
210  /* Fail */
211  KeBugCheckEx(IRQL_GT_ZERO_AT_SYSTEM_SERVICE,
212  SystemCall,
213  OldIrql,
214  0,
215  0);
216  }
217 
218  /* Make sure we're not attached and that APCs are not disabled */
219  if ((KeGetCurrentThread()->ApcStateIndex != OriginalApcEnvironment) ||
220  (KeGetCurrentThread()->CombinedApcDisable != 0))
221  {
222  /* Fail */
223  KeBugCheckEx(APC_INDEX_MISMATCH,
224  SystemCall,
225  KeGetCurrentThread()->ApcStateIndex,
226  KeGetCurrentThread()->CombinedApcDisable,
227  0);
228  }
229  }
230 }
231 
232 //
233 // Generic Exit Routine
234 //
242 
243 typedef
244 VOID
246  IN PKTRAP_FRAME TrapFrame
247 );
248 
250 
251 //
252 // Save user mode debug registers and restore kernel values
253 //
255 VOID
257  IN PKTRAP_FRAME TrapFrame)
258 {
259  PKPRCB Prcb = KeGetCurrentPrcb();
260 
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);
268 
269  /* Disable all active debugging */
270  __writedr(7, 0);
271 
272  /* Restore kernel values */
279 }
280 
282 VOID
284  PKTRAP_FRAME TrapFrame)
285 {
286  /* Disable all active debugging */
287  __writedr(7, 0);
288 
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);
296 }
297 
298 //
299 // Virtual 8086 Mode Optimized Trap Exit
300 //
303 VOID
305 {
307  KIRQL OldIrql;
308 
309  /* Get the thread */
311  while (TRUE)
312  {
313  /* Return if this isn't V86 mode anymore */
314  if (!(TrapFrame->EFlags & EFLAGS_V86_MASK)) KiEoiHelper(TrapFrame);
315 
316  /* Turn off the alerted state for kernel mode */
317  Thread->Alerted[KernelMode] = FALSE;
318 
319  /* Are there pending user APCs? */
320  if (__builtin_expect(!Thread->ApcState.UserApcPending, 1)) break;
321 
322  /* Raise to APC level and enable interrupts */
324  _enable();
325 
326  /* Deliver APCs */
327  KiDeliverApc(UserMode, NULL, TrapFrame);
328 
329  /* Restore IRQL and disable interrupts once again */
331  _disable();
332  }
333 
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))
336  {
337  /* Restore debug registers from the trap frame */
339  }
340 
341  /* Return from interrupt */
342  KiTrapReturnNoSegments(TrapFrame);
343 }
344 
345 //
346 // Virtual 8086 Mode Optimized Trap Entry
347 //
349 VOID
351 {
352  /* Save exception list */
353  TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
354 
355  /* Save DR7 and check for debugging */
356  TrapFrame->Dr7 = __readdr(7);
357  if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
358  {
359  /* Handle debug registers */
361  }
362 }
363 
364 //
365 // Interrupt Trap Entry
366 //
368 VOID
370 {
371  /* Save exception list and terminate it */
372  TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
373  KeGetPcr()->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
374 
375  /* Default to debugging disabled */
376  TrapFrame->Dr7 = 0;
377 
378  /* Check if the frame was from user mode or v86 mode */
379  if (KiUserTrap(TrapFrame) ||
380  (TrapFrame->EFlags & EFLAGS_V86_MASK))
381  {
382  /* Check for active debugging */
383  if (KeGetCurrentThread()->Header.DebugActive & 0xFF)
384  {
385  /* Handle debug registers */
387  }
388  }
389 
390  /* Set debug header */
391  KiFillTrapFrameDebug(TrapFrame);
392 }
393 
394 //
395 // Generic Trap Entry
396 //
398 VOID
400 {
401  /* Save exception list */
402  TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
403 
404  /* Default to debugging disabled */
405  TrapFrame->Dr7 = 0;
406 
407  /* Check if the frame was from user mode or v86 mode */
408  if (KiUserTrap(TrapFrame) ||
409  (TrapFrame->EFlags & EFLAGS_V86_MASK))
410  {
411  /* Check for active debugging */
412  if (KeGetCurrentThread()->Header.DebugActive & 0xFF)
413  {
414  /* Handle debug registers */
416  }
417  }
418 
419  /* Set debug header */
420  KiFillTrapFrameDebug(TrapFrame);
421 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
FORCEINLINE VOID KiEnterV86Trap(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:350
VOID(FASTCALL * PFAST_SYSTEM_CALL_EXIT)(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:245
#define IN
Definition: typedefs.h:38
__INTRIN_INLINE void __writedr(unsigned reg, unsigned int value)
Definition: intrin_x86.h:1832
FORCEINLINE VOID KiDumpTrapFrame(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:36
#define TRUE
Definition: types.h:120
DECLSPEC_NORETURN VOID FASTCALL KiTrapReturnNoSegmentsRet8(IN PKTRAP_FRAME TrapFrame)
#define MODE_MASK
Definition: orders.h:326
DECLSPEC_NORETURN VOID FASTCALL KiTrapReturnNoSegments(IN PKTRAP_FRAME TrapFrame)
#define DbgPrint
Definition: loader.c:25
DECLSPEC_NORETURN VOID FASTCALL KiTrapReturn(IN PKTRAP_FRAME TrapFrame)
ULONG64 KernelDr7
Definition: ketypes.h:505
void __cdecl _enable(void)
Definition: intrin_arm.h:373
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1062
FORCEINLINE VOID KiHandleDebugRegistersOnTrapEntry(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:256
ULONG64 KernelDr2
Definition: ketypes.h:502
KSPECIAL_REGISTERS SpecialRegisters
Definition: ketypes.h:530
ULONG64 KernelDr1
Definition: ketypes.h:501
#define FASTCALL
Definition: nt_native.h:50
DECLSPEC_NORETURN VOID FASTCALL KiEoiHelper(IN PKTRAP_FRAME TrapFrame)
Definition: traphdlr.c:126
void __cdecl __debugbreak(void)
Definition: intrin_ppc.h:698
#define DECLSPEC_NORETURN
Definition: ntbasedef.h:176
#define KeGetPcr()
Definition: ke.h:25
#define EFLAGS_V86_MASK
Definition: ketypes.h:129
DECLSPEC_NORETURN VOID FASTCALL KiSystemCallReturn(IN PKTRAP_FRAME TrapFrame)
UCHAR KIRQL
Definition: env_spec_w32.h:591
UINT64 Dr2
Definition: ketypes.h:344
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1555
Definition: Header.h:8
FORCEINLINE DECLSPEC_NORETURN VOID KiExitV86Trap(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:304
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define FORCEINLINE
Definition: ntbasedef.h:221
KIRQL FASTCALL KfRaiseIrql(IN KIRQL NewIrql)
Definition: pic.c:187
FORCEINLINE BOOLEAN KiUserTrap(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:25
#define DR7_RESERVED_MASK
Definition: asm.h:514
UINT64 Dr6
Definition: ketypes.h:346
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define KiFillTrapFrameDebug(x)
Definition: trap_x.h:189
DECLSPEC_NORETURN VOID FASTCALL KiSystemCallSysExitReturn(IN PKTRAP_FRAME TrapFrame)
#define KGDT_R0_PCR
Definition: ketypes.h:80
UINT64 Dr3
Definition: ketypes.h:345
KPROCESSOR_STATE ProcessorState
Definition: ketypes.h:579
UINT64 Dr1
Definition: ketypes.h:343
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
#define VOID
Definition: acefi.h:82
__INTRIN_INLINE unsigned int __readdr(unsigned int reg)
Definition: intrin_x86.h:1799
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
UINT64 Dr0
Definition: ketypes.h:342
VOID FASTCALL KfLowerIrql(IN KIRQL NewIrql)
Definition: pic.c:232
ULONG64 KernelDr3
Definition: ketypes.h:503
#define EXCEPTION_CHAIN_END
Definition: rtltypes.h:63
FORCEINLINE VOID KiEnterInterruptTrap(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:369
#define KiExitTrapDebugChecks(x, y)
Definition: trap_x.h:188
FORCEINLINE VOID KiExitSystemCallDebugChecks(IN ULONG SystemCall, IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:194
FORCEINLINE VOID KiHandleDebugRegistersOnTrapExit(PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:283
FORCEINLINE VOID KiEnterTrap(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:399
void __cdecl _disable(void)
Definition: intrin_arm.h:365
unsigned int ULONG
Definition: retypes.h:1
ULONG64 KernelDr6
Definition: ketypes.h:504
UINT64 Dr7
Definition: ketypes.h:347
#define KeGetCurrentThread
Definition: hal.h:44
VOID NTAPI KiDeliverApc(IN KPROCESSOR_MODE DeliveryMode, IN PKEXCEPTION_FRAME ExceptionFrame, IN PKTRAP_FRAME TrapFrame)
Definition: apc.c:302
#define APC_LEVEL
Definition: env_spec_w32.h:695
ULONG64 KernelDr0
Definition: ketypes.h:500
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:107
DECLSPEC_NORETURN VOID FASTCALL KiSystemCallTrapReturn(IN PKTRAP_FRAME TrapFrame)
DECLSPEC_NORETURN VOID FASTCALL KiEditedTrapReturn(IN PKTRAP_FRAME TrapFrame)
#define EFLAGS_INTERRUPT_MASK
Definition: ketypes.h:126
PFAST_SYSTEM_CALL_EXIT KiFastCallExitHandler
Definition: traphdlr.c:56