Trap handlers in C Patch 5 of X:
[reactos.git] / reactos / ntoskrnl / include / internal / trap_x.h
1 /*
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
7 */
8
9 //
10 // Debug Macros
11 //
12 VOID
13 NTAPI
14 KiDumpTrapFrame(IN PKTRAP_FRAME TrapFrame)
15 {
16 /* Dump the whole thing */
17 DPRINT1("DbgEbp: %x\n", TrapFrame->DbgEbp);
18 DPRINT1("DbgEip: %x\n", TrapFrame->DbgEip);
19 DPRINT1("DbgArgMark: %x\n", TrapFrame->DbgArgMark);
20 DPRINT1("DbgArgPointer: %x\n", TrapFrame->DbgArgPointer);
21 DPRINT1("TempSegCs: %x\n", TrapFrame->TempSegCs);
22 DPRINT1("TempEsp: %x\n", TrapFrame->TempEsp);
23 DPRINT1("Dr0: %x\n", TrapFrame->Dr0);
24 DPRINT1("Dr1: %x\n", TrapFrame->Dr1);
25 DPRINT1("Dr2: %x\n", TrapFrame->Dr2);
26 DPRINT1("Dr3: %x\n", TrapFrame->Dr3);
27 DPRINT1("Dr6: %x\n", TrapFrame->Dr6);
28 DPRINT1("Dr7: %x\n", TrapFrame->Dr7);
29 DPRINT1("SegGs: %x\n", TrapFrame->SegGs);
30 DPRINT1("SegEs: %x\n", TrapFrame->SegEs);
31 DPRINT1("SegDs: %x\n", TrapFrame->SegDs);
32 DPRINT1("Edx: %x\n", TrapFrame->Edx);
33 DPRINT1("Ecx: %x\n", TrapFrame->Ecx);
34 DPRINT1("Eax: %x\n", TrapFrame->Eax);
35 DPRINT1("PreviousPreviousMode: %x\n", TrapFrame->PreviousPreviousMode);
36 DPRINT1("ExceptionList: %x\n", TrapFrame->ExceptionList);
37 DPRINT1("SegFs: %x\n", TrapFrame->SegFs);
38 DPRINT1("Edi: %x\n", TrapFrame->Edi);
39 DPRINT1("Esi: %x\n", TrapFrame->Esi);
40 DPRINT1("Ebx: %x\n", TrapFrame->Ebx);
41 DPRINT1("Ebp: %x\n", TrapFrame->Ebp);
42 DPRINT1("ErrCode: %x\n", TrapFrame->ErrCode);
43 DPRINT1("Eip: %x\n", TrapFrame->Eip);
44 DPRINT1("SegCs: %x\n", TrapFrame->SegCs);
45 DPRINT1("EFlags: %x\n", TrapFrame->EFlags);
46 DPRINT1("HardwareEsp: %x\n", TrapFrame->HardwareEsp);
47 DPRINT1("HardwareSegSs: %x\n", TrapFrame->HardwareSegSs);
48 DPRINT1("V86Es: %x\n", TrapFrame->V86Es);
49 DPRINT1("V86Ds: %x\n", TrapFrame->V86Ds);
50 DPRINT1("V86Fs: %x\n", TrapFrame->V86Fs);
51 DPRINT1("V86Gs: %x\n", TrapFrame->V86Gs);
52 }
53
54 #if YDEBUG
55 FORCEINLINE
56 VOID
57 KiFillTrapFrameDebug(IN PKTRAP_FRAME TrapFrame)
58 {
59 /* Set the debug information */
60 TrapFrame->DbgArgPointer = TrapFrame->Edx;
61 TrapFrame->DbgArgMark = 0xBADB0D00;
62 TrapFrame->DbgEip = TrapFrame->Eip;
63 TrapFrame->DbgEbp = TrapFrame->Ebp;
64 }
65
66 FORCEINLINE
67 VOID
68 KiExitTrapDebugChecks(IN PKTRAP_FRAME TrapFrame,
69 IN KTRAP_STATE_BITS StateBits)
70 {
71 /* Make sure interrupts are disabled */
72 if (__readeflags() & EFLAGS_INTERRUPT_MASK)
73 {
74 DPRINT1("Exiting with interrupts enabled: %lx\n", __readeflags());
75 while (TRUE);
76 }
77
78 /* Make sure this is a real trap frame */
79 if (TrapFrame->DbgArgMark != 0xBADB0D00)
80 {
81 DPRINT1("Exiting with an invalid trap frame? (No MAGIC in trap frame)\n");
82 KiDumpTrapFrame(TrapFrame);
83 while (TRUE);
84 }
85
86 /* Make sure we're not in user-mode or something */
87 if (Ke386GetFs() != KGDT_R0_PCR)
88 {
89 DPRINT1("Exiting with an invalid FS: %lx\n", Ke386GetFs());
90 while (TRUE);
91 }
92
93 /* Make sure we have a valid SEH chain */
94 if (KeGetPcr()->Tib.ExceptionList == 0)
95 {
96 DPRINT1("Exiting with NULL exception chain: %p\n", KeGetPcr()->Tib.ExceptionList);
97 while (TRUE);
98 }
99
100 /* Make sure we're restoring a valid SEH chain */
101 if (TrapFrame->ExceptionList == 0)
102 {
103 DPRINT1("Entered a trap with a NULL exception chain: %p\n", TrapFrame->ExceptionList);
104 while (TRUE);
105 }
106
107 /* If we're ignoring previous mode, make sure caller doesn't actually want it */
108 if (!(StateBits.PreviousMode) && (TrapFrame->PreviousPreviousMode != -1))
109 {
110 DPRINT1("Exiting a trap witout restoring previous mode, yet previous mode seems valid: %lx", TrapFrame->PreviousPreviousMode);
111 while (TRUE);
112 }
113 }
114 #else
115 #define KiExitTrapDebugChecks(x, y)
116 #define KiFillTrapFrameDebug(x)
117 #endif
118
119 //
120 // Helper Code
121 //
122
123 BOOLEAN
124 FORCEINLINE
125 KiUserTrap(IN PKTRAP_FRAME TrapFrame)
126 {
127 /* Anything else but Ring 0 is Ring 3 */
128 return (TrapFrame->SegCs != KGDT_R0_CODE);
129 }
130
131 BOOLEAN
132 FORCEINLINE
133 KiVdmTrap(IN PKTRAP_FRAME TrapFrame)
134 {
135 /* Either the V8086 flag is on, or this is user-mode with a VDM */
136 return ((TrapFrame->EFlags & EFLAGS_V86_MASK) ||
137 ((KiUserTrap(TrapFrame)) && (PsGetCurrentProcess()->VdmObjects)));
138 }
139
140 VOID
141 FORCEINLINE
142 KiTrapFrameFromPushaStack(IN PKTRAP_FRAME TrapFrame)
143 {
144 /*
145 * This sequence is Bavarian Alchemist Black Magic
146 *
147 * *** DO NOT MODIFY ***
148 */
149 TrapFrame->Edx = TrapFrame->Esi;
150 TrapFrame->Esi = TrapFrame->PreviousPreviousMode;
151 TrapFrame->Ecx = TrapFrame->Ebx;
152 TrapFrame->Ebx = TrapFrame->Edi;
153 TrapFrame->Edi = TrapFrame->Eax;
154 TrapFrame->Eax = TrapFrame->Ebp;
155 TrapFrame->Ebp = (ULONG)TrapFrame->ExceptionList;
156 TrapFrame->TempEsp = TrapFrame->SegFs;
157 }
158
159 VOID
160 FORCEINLINE
161 KiPushaStackFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
162 {
163 /*
164 * This sequence is Bavarian Alchemist Black Magic
165 *
166 * *** DO NOT MODIFY ***
167 */
168 TrapFrame->SegFs = TrapFrame->TempEsp;
169 TrapFrame->ExceptionList = (PVOID)TrapFrame->Ebp;
170 TrapFrame->Ebp = TrapFrame->Eax;
171 TrapFrame->Eax = TrapFrame->Edi;
172 TrapFrame->Edi = TrapFrame->Ebx;
173 TrapFrame->Ebx = TrapFrame->Ecx;
174 TrapFrame->PreviousPreviousMode = TrapFrame->Esi;
175 TrapFrame->Esi = TrapFrame->Edx;
176 }
177
178 VOID
179 FORCEINLINE
180 KiCheckForApcDelivery(IN PKTRAP_FRAME TrapFrame)
181 {
182 PKTHREAD Thread;
183 KIRQL OldIrql;
184
185 /* Check for V8086 or user-mode trap */
186 if ((TrapFrame->EFlags & EFLAGS_V86_MASK) ||
187 (KiUserTrap(TrapFrame)))
188 {
189 /* Get the thread */
190 Thread = KeGetCurrentThread();
191 while (TRUE)
192 {
193 /* Turn off the alerted state for kernel mode */
194 Thread->Alerted[KernelMode] = FALSE;
195
196 /* Are there pending user APCs? */
197 if (!Thread->ApcState.UserApcPending) break;
198
199 /* Raise to APC level and enable interrupts */
200 OldIrql = KfRaiseIrql(APC_LEVEL);
201 _enable();
202
203 /* Deliver APCs */
204 KiDeliverApc(UserMode, NULL, TrapFrame);
205
206 /* Restore IRQL and disable interrupts once again */
207 KfLowerIrql(OldIrql);
208 _disable();
209 }
210 }
211 }
212
213 VOID
214 FORCEINLINE
215 KiDispatchException0Args(IN NTSTATUS Code,
216 IN ULONG_PTR Address,
217 IN PKTRAP_FRAME TrapFrame)
218 {
219 /* Helper for exceptions with no arguments */
220 KiDispatchExceptionFromTrapFrame(Code, Address, 0, 0, 0, 0, TrapFrame);
221 }
222
223 VOID
224 FORCEINLINE
225 KiDispatchException1Args(IN NTSTATUS Code,
226 IN ULONG_PTR Address,
227 IN ULONG P1,
228 IN PKTRAP_FRAME TrapFrame)
229 {
230 /* Helper for exceptions with no arguments */
231 KiDispatchExceptionFromTrapFrame(Code, Address, 1, P1, 0, 0, TrapFrame);
232 }
233
234 VOID
235 FORCEINLINE
236 KiDispatchException2Args(IN NTSTATUS Code,
237 IN ULONG_PTR Address,
238 IN ULONG P1,
239 IN ULONG P2,
240 IN PKTRAP_FRAME TrapFrame)
241 {
242 /* Helper for exceptions with no arguments */
243 KiDispatchExceptionFromTrapFrame(Code, Address, 2, P1, P2, 0, TrapFrame);
244 }
245
246 FORCEINLINE
247 VOID
248 KiTrapReturn(IN PKTRAP_FRAME TrapFrame)
249 {
250 /* Restore registers */
251 KiPushaStackFromTrapFrame(TrapFrame);
252
253 /* Regular interrupt exit */
254 __asm__ __volatile__
255 (
256 "movl %0, %%esp\n"
257 "addl %1, %%esp\n"
258 "popa\n"
259 "addl $4, %%esp\n"
260 "iret\n"
261 :
262 : "r"(TrapFrame), "i"(KTRAP_FRAME_LENGTH - KTRAP_FRAME_PREVIOUS_MODE)
263 : "%esp"
264 );
265 }