2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/include/trap_x.h
5 * PURPOSE: Internal Inlined Functions for the Trap Handling Code
6 * PROGRAMMERS: ReactOS Portable Systems Group
14 // Unreachable code hint for GCC 4.5.x, older GCC versions, and MSVC
17 #if __GNUC__ * 100 + __GNUC_MINOR__ >= 405
18 #define UNREACHABLE __builtin_unreachable()
20 #define UNREACHABLE __builtin_trap()
23 #define UNREACHABLE __assume(0)
33 KiUserTrap(IN PKTRAP_FRAME TrapFrame
)
35 /* Anything else but Ring 0 is Ring 3 */
36 return (TrapFrame
->SegCs
& MODE_MASK
);
44 KiDumpTrapFrame(IN PKTRAP_FRAME TrapFrame
)
46 /* Dump the whole thing */
47 DbgPrint("DbgEbp: %x\n", TrapFrame
->DbgEbp
);
48 DbgPrint("DbgEip: %x\n", TrapFrame
->DbgEip
);
49 DbgPrint("DbgArgMark: %x\n", TrapFrame
->DbgArgMark
);
50 DbgPrint("DbgArgPointer: %x\n", TrapFrame
->DbgArgPointer
);
51 DbgPrint("TempSegCs: %x\n", TrapFrame
->TempSegCs
);
52 DbgPrint("TempEsp: %x\n", TrapFrame
->TempEsp
);
53 DbgPrint("Dr0: %x\n", TrapFrame
->Dr0
);
54 DbgPrint("Dr1: %x\n", TrapFrame
->Dr1
);
55 DbgPrint("Dr2: %x\n", TrapFrame
->Dr2
);
56 DbgPrint("Dr3: %x\n", TrapFrame
->Dr3
);
57 DbgPrint("Dr6: %x\n", TrapFrame
->Dr6
);
58 DbgPrint("Dr7: %x\n", TrapFrame
->Dr7
);
59 DbgPrint("SegGs: %x\n", TrapFrame
->SegGs
);
60 DbgPrint("SegEs: %x\n", TrapFrame
->SegEs
);
61 DbgPrint("SegDs: %x\n", TrapFrame
->SegDs
);
62 DbgPrint("Edx: %x\n", TrapFrame
->Edx
);
63 DbgPrint("Ecx: %x\n", TrapFrame
->Ecx
);
64 DbgPrint("Eax: %x\n", TrapFrame
->Eax
);
65 DbgPrint("PreviousPreviousMode: %x\n", TrapFrame
->PreviousPreviousMode
);
66 DbgPrint("ExceptionList: %x\n", TrapFrame
->ExceptionList
);
67 DbgPrint("SegFs: %x\n", TrapFrame
->SegFs
);
68 DbgPrint("Edi: %x\n", TrapFrame
->Edi
);
69 DbgPrint("Esi: %x\n", TrapFrame
->Esi
);
70 DbgPrint("Ebx: %x\n", TrapFrame
->Ebx
);
71 DbgPrint("Ebp: %x\n", TrapFrame
->Ebp
);
72 DbgPrint("ErrCode: %x\n", TrapFrame
->ErrCode
);
73 DbgPrint("Eip: %x\n", TrapFrame
->Eip
);
74 DbgPrint("SegCs: %x\n", TrapFrame
->SegCs
);
75 DbgPrint("EFlags: %x\n", TrapFrame
->EFlags
);
76 DbgPrint("HardwareEsp: %x\n", TrapFrame
->HardwareEsp
);
77 DbgPrint("HardwareSegSs: %x\n", TrapFrame
->HardwareSegSs
);
78 DbgPrint("V86Es: %x\n", TrapFrame
->V86Es
);
79 DbgPrint("V86Ds: %x\n", TrapFrame
->V86Ds
);
80 DbgPrint("V86Fs: %x\n", TrapFrame
->V86Fs
);
81 DbgPrint("V86Gs: %x\n", TrapFrame
->V86Gs
);
87 KiFillTrapFrameDebug(IN PKTRAP_FRAME TrapFrame
)
89 /* Set the debug information */
90 TrapFrame
->DbgArgPointer
= TrapFrame
->Edx
;
91 TrapFrame
->DbgArgMark
= 0xBADB0D00;
92 TrapFrame
->DbgEip
= TrapFrame
->Eip
;
93 TrapFrame
->DbgEbp
= TrapFrame
->Ebp
;
94 TrapFrame
->PreviousPreviousMode
= -1;
99 KiExitTrapDebugChecks(IN PKTRAP_FRAME TrapFrame
,
100 IN KTRAP_EXIT_SKIP_BITS SkipBits
)
102 /* Make sure interrupts are disabled */
103 if (__readeflags() & EFLAGS_INTERRUPT_MASK
)
105 DbgPrint("Exiting with interrupts enabled: %lx\n", __readeflags());
109 /* Make sure this is a real trap frame */
110 if (TrapFrame
->DbgArgMark
!= 0xBADB0D00)
112 DbgPrint("Exiting with an invalid trap frame? (No MAGIC in trap frame)\n");
113 KiDumpTrapFrame(TrapFrame
);
117 /* Make sure we're not in user-mode or something */
118 if (Ke386GetFs() != KGDT_R0_PCR
)
120 DbgPrint("Exiting with an invalid FS: %lx\n", Ke386GetFs());
124 /* Make sure we have a valid SEH chain */
125 if (KeGetPcr()->NtTib
.ExceptionList
== 0)
127 DbgPrint("Exiting with NULL exception chain: %p\n", KeGetPcr()->NtTib
.ExceptionList
);
131 /* Make sure we're restoring a valid SEH chain */
132 if (TrapFrame
->ExceptionList
== 0)
134 DbgPrint("Entered a trap with a NULL exception chain: %p\n", TrapFrame
->ExceptionList
);
138 /* If we're ignoring previous mode, make sure caller doesn't actually want it */
139 if ((SkipBits
.SkipPreviousMode
) && (TrapFrame
->PreviousPreviousMode
!= -1))
141 DbgPrint("Exiting a trap witout restoring previous mode, yet previous mode seems valid: %lx\n", TrapFrame
->PreviousPreviousMode
);
148 KiExitSystemCallDebugChecks(IN ULONG SystemCall
,
149 IN PKTRAP_FRAME TrapFrame
)
153 /* Check if this was a user call */
154 if (KiUserTrap(TrapFrame
))
156 /* Make sure we are not returning with elevated IRQL */
157 OldIrql
= KeGetCurrentIrql();
158 if (OldIrql
!= PASSIVE_LEVEL
)
160 /* Forcibly put us in a sane state */
161 KeGetPcr()->Irql
= PASSIVE_LEVEL
;
165 KeBugCheckEx(IRQL_GT_ZERO_AT_SYSTEM_SERVICE
,
172 /* Make sure we're not attached and that APCs are not disabled */
173 if ((KeGetCurrentThread()->ApcStateIndex
!= CurrentApcEnvironment
) ||
174 (KeGetCurrentThread()->CombinedApcDisable
!= 0))
177 KeBugCheckEx(APC_INDEX_MISMATCH
,
179 KeGetCurrentThread()->ApcStateIndex
,
180 KeGetCurrentThread()->CombinedApcDisable
,
186 #define KiExitTrapDebugChecks(x, y)
187 #define KiFillTrapFrameDebug(x)
188 #define KiExitSystemCallDebugChecks(x, y)
192 // Generic Exit Routine
194 DECLSPEC_NORETURN VOID FASTCALL
KiSystemCallReturn(IN PKTRAP_FRAME TrapFrame
);
195 DECLSPEC_NORETURN VOID FASTCALL
KiSystemCallSysExitReturn(IN PKTRAP_FRAME TrapFrame
);
196 DECLSPEC_NORETURN VOID FASTCALL
KiSystemCallTrapReturn(IN PKTRAP_FRAME TrapFrame
);
197 DECLSPEC_NORETURN VOID FASTCALL
KiEditedTrapReturn(IN PKTRAP_FRAME TrapFrame
);
198 DECLSPEC_NORETURN VOID FASTCALL
KiTrapReturn(IN PKTRAP_FRAME TrapFrame
);
199 DECLSPEC_NORETURN VOID FASTCALL
KiTrapReturnNoSegments(IN PKTRAP_FRAME TrapFrame
);
204 (FASTCALL
*PFAST_SYSTEM_CALL_EXIT
)(
205 IN PKTRAP_FRAME TrapFrame
208 extern PFAST_SYSTEM_CALL_EXIT KiFastCallExitHandler
;
211 // Virtual 8086 Mode Optimized Trap Exit
216 KiExitV86Trap(IN PKTRAP_FRAME TrapFrame
)
222 Thread
= KeGetCurrentThread();
225 /* Return if this isn't V86 mode anymore */
226 if (!(TrapFrame
->EFlags
& EFLAGS_V86_MASK
)) KiEoiHelper(TrapFrame
);
228 /* Turn off the alerted state for kernel mode */
229 Thread
->Alerted
[KernelMode
] = FALSE
;
231 /* Are there pending user APCs? */
232 if (__builtin_expect(!Thread
->ApcState
.UserApcPending
, 1)) break;
234 /* Raise to APC level and enable interrupts */
235 OldIrql
= KfRaiseIrql(APC_LEVEL
);
239 KiDeliverApc(UserMode
, NULL
, TrapFrame
);
241 /* Restore IRQL and disable interrupts once again */
242 KfLowerIrql(OldIrql
);
246 /* If we got here, we're still in a valid V8086 context, so quit it */
247 if (__builtin_expect(TrapFrame
->Dr7
& ~DR7_RESERVED_MASK
, 0))
249 /* Not handled yet */
250 DbgPrint("Need Hardware Breakpoint Support!\n");
254 /* Return from interrupt */
255 KiTrapReturnNoSegments(TrapFrame
);
259 // Virtual 8086 Mode Optimized Trap Entry
263 KiEnterV86Trap(IN PKTRAP_FRAME TrapFrame
)
265 /* Save exception list */
266 TrapFrame
->ExceptionList
= KeGetPcr()->NtTib
.ExceptionList
;
268 /* Save DR7 and check for debugging */
269 TrapFrame
->Dr7
= __readdr(7);
270 if (__builtin_expect(TrapFrame
->Dr7
& ~DR7_RESERVED_MASK
, 0))
272 DbgPrint("Need Hardware Breakpoint Support!\n");
278 // Interrupt Trap Entry
282 KiEnterInterruptTrap(IN PKTRAP_FRAME TrapFrame
)
284 /* Save exception list and terminate it */
285 TrapFrame
->ExceptionList
= KeGetPcr()->NtTib
.ExceptionList
;
286 KeGetPcr()->NtTib
.ExceptionList
= EXCEPTION_CHAIN_END
;
288 /* Flush DR7 and check for debugging */
290 if (__builtin_expect(KeGetCurrentThread()->DispatcherHeader
.DebugActive
& 0xFF, 0))
292 DbgPrint("Need Hardware Breakpoint Support!\n");
296 /* Set debug header */
297 KiFillTrapFrameDebug(TrapFrame
);
301 // Generic Trap Entry
305 KiEnterTrap(IN PKTRAP_FRAME TrapFrame
)
307 /* Save exception list */
308 TrapFrame
->ExceptionList
= KeGetPcr()->NtTib
.ExceptionList
;
310 /* Flush DR7 and check for debugging */
312 if (__builtin_expect(KeGetCurrentThread()->DispatcherHeader
.DebugActive
& 0xFF, 0))
314 DbgPrint("Need Hardware Breakpoint Support!\n");
318 /* Set debug header */
319 KiFillTrapFrameDebug(TrapFrame
);