Trap Handlers in C Patch 1 of X (Patch by Sir_Richard <ros.arm@reactos.org>):
[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 #if YDEBUG
13 VOID
14 NTAPI
15 KiDumpTrapFrame(IN PKTRAP_FRAME TrapFrame)
16 {
17 /* Dump the whole thing */
18 DPRINT1("DbgEbp: %x\n", TrapFrame->DbgEbp);
19 DPRINT1("DbgEip: %x\n", TrapFrame->DbgEip);
20 DPRINT1("DbgArgMark: %x\n", TrapFrame->DbgArgMark);
21 DPRINT1("DbgArgPointer: %x\n", TrapFrame->DbgArgPointer);
22 DPRINT1("TempSegCs: %x\n", TrapFrame->TempSegCs);
23 DPRINT1("TempEsp: %x\n", TrapFrame->TempEsp);
24 DPRINT1("Dr0: %x\n", TrapFrame->Dr0);
25 DPRINT1("Dr1: %x\n", TrapFrame->Dr1);
26 DPRINT1("Dr2: %x\n", TrapFrame->Dr2);
27 DPRINT1("Dr3: %x\n", TrapFrame->Dr3);
28 DPRINT1("Dr6: %x\n", TrapFrame->Dr6);
29 DPRINT1("Dr7: %x\n", TrapFrame->Dr7);
30 DPRINT1("SegGs: %x\n", TrapFrame->SegGs);
31 DPRINT1("SegEs: %x\n", TrapFrame->SegEs);
32 DPRINT1("SegDs: %x\n", TrapFrame->SegDs);
33 DPRINT1("Edx: %x\n", TrapFrame->Edx);
34 DPRINT1("Ecx: %x\n", TrapFrame->Ecx);
35 DPRINT1("Eax: %x\n", TrapFrame->Eax);
36 DPRINT1("PreviousPreviousMode: %x\n", TrapFrame->PreviousPreviousMode);
37 DPRINT1("ExceptionList: %x\n", TrapFrame->ExceptionList);
38 DPRINT1("SegFs: %x\n", TrapFrame->SegFs);
39 DPRINT1("Edi: %x\n", TrapFrame->Edi);
40 DPRINT1("Esi: %x\n", TrapFrame->Esi);
41 DPRINT1("Ebx: %x\n", TrapFrame->Ebx);
42 DPRINT1("Ebp: %x\n", TrapFrame->Ebp);
43 DPRINT1("ErrCode: %x\n", TrapFrame->ErrCode);
44 DPRINT1("Eip: %x\n", TrapFrame->Eip);
45 DPRINT1("SegCs: %x\n", TrapFrame->SegCs);
46 DPRINT1("EFlags: %x\n", TrapFrame->EFlags);
47 DPRINT1("HardwareEsp: %x\n", TrapFrame->HardwareEsp);
48 DPRINT1("HardwareSegSs: %x\n", TrapFrame->HardwareSegSs);
49 DPRINT1("V86Es: %x\n", TrapFrame->V86Es);
50 DPRINT1("V86Ds: %x\n", TrapFrame->V86Ds);
51 DPRINT1("V86Fs: %x\n", TrapFrame->V86Fs);
52 DPRINT1("V86Gs: %x\n", TrapFrame->V86Gs);
53 }
54
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)
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
214 VOID
215 FORCEINLINE
216 KiDispatchException0Args(IN NTSTATUS Code,
217 IN ULONG_PTR Address,
218 IN PKTRAP_FRAME TrapFrame)
219 {
220 /* Helper for exceptions with no arguments */
221 KiDispatchExceptionFromTrapFrame(Code, Address, 0, 0, 0, 0, TrapFrame);
222 }
223
224 FORCEINLINE
225 VOID
226 KiTrapReturn(IN PKTRAP_FRAME TrapFrame)
227 {
228 /* Restore registers */
229 KiPushaStackFromTrapFrame(TrapFrame);
230
231 /* Regular interrupt exit */
232 __asm__ __volatile__
233 (
234 "movl %0, %%esp\n"
235 "addl %1, %%esp\n"
236 "popa\n"
237 "addl $4, %%esp\n"
238 "iret\n"
239 :
240 : "r"(TrapFrame), "i"(KTRAP_FRAME_LENGTH - KTRAP_FRAME_PREVIOUS_MODE)
241 : "%esp"
242 );
243 }