ReactOS  0.4.15-dev-1171-gab82533
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 //
19 BOOLEAN
21 {
22  /* Anything else but Ring 0 is Ring 3 */
23  return !!(TrapFrame->SegCs & MODE_MASK);
24 }
25 
26 //
27 // Debug Macros
28 //
30 VOID
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
73 VOID
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 
97 extern BOOLEAN StopChecking;
98 
100 VOID
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 != -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 
188 VOID
190  IN PKTRAP_FRAME TrapFrame)
191 {
192  KIRQL OldIrql;
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 
238 typedef
239 VOID
241  IN PKTRAP_FRAME TrapFrame
242 );
243 
245 
246 //
247 // Save user mode debug registers and restore kernel values
248 //
250 VOID
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 
277 VOID
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 //
298 VOID
300 {
302  KIRQL OldIrql;
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 //
344 VOID
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 //
367 VOID
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 //
401 VOID
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 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
FORCEINLINE VOID KiEnterV86Trap(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:345
VOID(FASTCALL * PFAST_SYSTEM_CALL_EXIT)(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:240
#define IN
Definition: typedefs.h:39
__INTRIN_INLINE void __writedr(unsigned reg, unsigned int value)
Definition: intrin_x86.h:1846
FORCEINLINE VOID KiDumpTrapFrame(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:31
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
#define TRUE
Definition: types.h:120
void __cdecl _enable(void)
Definition: intrin_arm.h:373
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1063
FORCEINLINE VOID KiHandleDebugRegistersOnTrapEntry(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:251
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:1569
#define FALSE
Definition: types.h:117
Definition: Header.h:8
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
FORCEINLINE DECLSPEC_NORETURN VOID KiExitV86Trap(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:299
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define FORCEINLINE
Definition: ntbasedef.h:216
KIRQL FASTCALL KfRaiseIrql(IN KIRQL NewIrql)
Definition: pic.c:187
FORCEINLINE BOOLEAN KiUserTrap(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:20
#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:184
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:790
#define VOID
Definition: acefi.h:82
__INTRIN_INLINE unsigned int __readdr(unsigned int reg)
Definition: intrin_x86.h:1813
#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:368
#define KiExitTrapDebugChecks(x, y)
Definition: trap_x.h:183
FORCEINLINE VOID KiExitSystemCallDebugChecks(IN ULONG SystemCall, IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:189
FORCEINLINE VOID KiHandleDebugRegistersOnTrapExit(PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:278
FORCEINLINE VOID KiEnterTrap(IN PKTRAP_FRAME TrapFrame)
Definition: trap_x.h:402
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:108
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