[PERF]: Make the trap entry/exit macros inlined, just as they used to be before in...
[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 #ifndef _TRAP_X_
9 #define _TRAP_X_
10
11 //
12 // Unreachable code hint for GCC 4.5.x, 4.4.x, and MSVC
13 //
14 #if __GNUC__ * 100 + __GNUC_MINOR__ >= 405
15 #define UNREACHABLE __builtin_unreachable()
16 #elif __GNUC__ * 100 + __GNUC_MINOR__ >= 404
17 #define UNREACHABLE __builtin_trap()
18 #elif _MSC_VER
19 #define UNREACHABLE __assume(0)
20 #else
21 #define UNREACHABLE
22 #endif
23
24 //
25 // Debug Macros
26 //
27 VOID
28 FORCEINLINE
29 KiDumpTrapFrame(IN PKTRAP_FRAME TrapFrame)
30 {
31 /* Dump the whole thing */
32 DbgPrint("DbgEbp: %x\n", TrapFrame->DbgEbp);
33 DbgPrint("DbgEip: %x\n", TrapFrame->DbgEip);
34 DbgPrint("DbgArgMark: %x\n", TrapFrame->DbgArgMark);
35 DbgPrint("DbgArgPointer: %x\n", TrapFrame->DbgArgPointer);
36 DbgPrint("TempSegCs: %x\n", TrapFrame->TempSegCs);
37 DbgPrint("TempEsp: %x\n", TrapFrame->TempEsp);
38 DbgPrint("Dr0: %x\n", TrapFrame->Dr0);
39 DbgPrint("Dr1: %x\n", TrapFrame->Dr1);
40 DbgPrint("Dr2: %x\n", TrapFrame->Dr2);
41 DbgPrint("Dr3: %x\n", TrapFrame->Dr3);
42 DbgPrint("Dr6: %x\n", TrapFrame->Dr6);
43 DbgPrint("Dr7: %x\n", TrapFrame->Dr7);
44 DbgPrint("SegGs: %x\n", TrapFrame->SegGs);
45 DbgPrint("SegEs: %x\n", TrapFrame->SegEs);
46 DbgPrint("SegDs: %x\n", TrapFrame->SegDs);
47 DbgPrint("Edx: %x\n", TrapFrame->Edx);
48 DbgPrint("Ecx: %x\n", TrapFrame->Ecx);
49 DbgPrint("Eax: %x\n", TrapFrame->Eax);
50 DbgPrint("PreviousPreviousMode: %x\n", TrapFrame->PreviousPreviousMode);
51 DbgPrint("ExceptionList: %x\n", TrapFrame->ExceptionList);
52 DbgPrint("SegFs: %x\n", TrapFrame->SegFs);
53 DbgPrint("Edi: %x\n", TrapFrame->Edi);
54 DbgPrint("Esi: %x\n", TrapFrame->Esi);
55 DbgPrint("Ebx: %x\n", TrapFrame->Ebx);
56 DbgPrint("Ebp: %x\n", TrapFrame->Ebp);
57 DbgPrint("ErrCode: %x\n", TrapFrame->ErrCode);
58 DbgPrint("Eip: %x\n", TrapFrame->Eip);
59 DbgPrint("SegCs: %x\n", TrapFrame->SegCs);
60 DbgPrint("EFlags: %x\n", TrapFrame->EFlags);
61 DbgPrint("HardwareEsp: %x\n", TrapFrame->HardwareEsp);
62 DbgPrint("HardwareSegSs: %x\n", TrapFrame->HardwareSegSs);
63 DbgPrint("V86Es: %x\n", TrapFrame->V86Es);
64 DbgPrint("V86Ds: %x\n", TrapFrame->V86Ds);
65 DbgPrint("V86Fs: %x\n", TrapFrame->V86Fs);
66 DbgPrint("V86Gs: %x\n", TrapFrame->V86Gs);
67 }
68
69 #ifdef TRAP_DEBUG
70 VOID
71 FORCEINLINE
72 KiFillTrapFrameDebug(IN PKTRAP_FRAME TrapFrame)
73 {
74 /* Set the debug information */
75 TrapFrame->DbgArgPointer = TrapFrame->Edx;
76 TrapFrame->DbgArgMark = 0xBADB0D00;
77 TrapFrame->DbgEip = TrapFrame->Eip;
78 TrapFrame->DbgEbp = TrapFrame->Ebp;
79 }
80
81 VOID
82 FORCEINLINE
83 KiExitTrapDebugChecks(IN PKTRAP_FRAME TrapFrame,
84 IN KTRAP_STATE_BITS SkipBits)
85 {
86 /* Make sure interrupts are disabled */
87 if (__readeflags() & EFLAGS_INTERRUPT_MASK)
88 {
89 DbgPrint("Exiting with interrupts enabled: %lx\n", __readeflags());
90 while (TRUE);
91 }
92
93 /* Make sure this is a real trap frame */
94 if (TrapFrame->DbgArgMark != 0xBADB0D00)
95 {
96 DbgPrint("Exiting with an invalid trap frame? (No MAGIC in trap frame)\n");
97 KiDumpTrapFrame(TrapFrame);
98 while (TRUE);
99 }
100
101 /* Make sure we're not in user-mode or something */
102 if (Ke386GetFs() != KGDT_R0_PCR)
103 {
104 DbgPrint("Exiting with an invalid FS: %lx\n", Ke386GetFs());
105 while (TRUE);
106 }
107
108 /* Make sure we have a valid SEH chain */
109 if (KeGetPcr()->Tib.ExceptionList == 0)
110 {
111 DbgPrint("Exiting with NULL exception chain: %p\n", KeGetPcr()->Tib.ExceptionList);
112 while (TRUE);
113 }
114
115 /* Make sure we're restoring a valid SEH chain */
116 if (TrapFrame->ExceptionList == 0)
117 {
118 DbgPrint("Entered a trap with a NULL exception chain: %p\n", TrapFrame->ExceptionList);
119 while (TRUE);
120 }
121
122 /* If we're ignoring previous mode, make sure caller doesn't actually want it */
123 if ((SkipBits.SkipPreviousMode) && (TrapFrame->PreviousPreviousMode != -1))
124 {
125 DbgPrint("Exiting a trap witout restoring previous mode, yet previous mode seems valid: %lx", TrapFrame->PreviousPreviousMode);
126 while (TRUE);
127 }
128 }
129
130 VOID
131 FORCEINLINE
132 KiExitSystemCallDebugChecks(IN ULONG SystemCall,
133 IN PKTRAP_FRAME TrapFrame)
134 {
135 KIRQL OldIrql;
136
137 /* Check if this was a user call */
138 if (KiUserMode(TrapFrame))
139 {
140 /* Make sure we are not returning with elevated IRQL */
141 OldIrql = KeGetCurrentIrql();
142 if (OldIrql != PASSIVE_LEVEL)
143 {
144 /* Forcibly put us in a sane state */
145 KeGetPcr()->CurrentIrql = PASSIVE_LEVEL;
146 _disable();
147
148 /* Fail */
149 KeBugCheckEx(IRQL_GT_ZERO_AT_SYSTEM_SERVICE,
150 SystemCall,
151 OldIrql,
152 0,
153 0);
154 }
155
156 /* Make sure we're not attached and that APCs are not disabled */
157 if ((KeGetCurrentThread()->ApcStateIndex != CurrentApcEnvironment) ||
158 (KeGetCurrentThread()->CombinedApcDisable != 0))
159 {
160 /* Fail */
161 KeBugCheckEx(APC_INDEX_MISMATCH,
162 SystemCall,
163 KeGetCurrentThread()->ApcStateIndex,
164 KeGetCurrentThread()->CombinedApcDisable,
165 0);
166 }
167 }
168 }
169 #else
170 #define KiExitTrapDebugChecks(x, y)
171 #define KiFillTrapFrameDebug(x)
172 #define KiExitSystemCallDebugChecks(x, y)
173 #endif
174
175 //
176 // Helper Code
177 //
178 BOOLEAN
179 FORCEINLINE
180 KiUserTrap(IN PKTRAP_FRAME TrapFrame)
181 {
182 /* Anything else but Ring 0 is Ring 3 */
183 return (TrapFrame->SegCs & MODE_MASK);
184 }
185
186 //
187 // Assembly exit stubs
188 //
189 VOID
190 FORCEINLINE
191 //DECLSPEC_NORETURN
192 KiSystemCallReturn(IN PKTRAP_FRAME TrapFrame)
193 {
194 /* Restore nonvolatiles, EAX, and do a "jump" back to the kernel caller */
195 __asm__ __volatile__
196 (
197 "movl %0, %%esp\n"
198 "movl %c[b](%%esp), %%ebx\n"
199 "movl %c[s](%%esp), %%esi\n"
200 "movl %c[i](%%esp), %%edi\n"
201 "movl %c[p](%%esp), %%ebp\n"
202 "movl %c[a](%%esp), %%eax\n"
203 "movl %c[e](%%esp), %%edx\n"
204 "addl $%c[v],%%esp\n" /* A WHOLE *KERNEL* frame since we're not IRET'ing */
205 "jmp *%%edx\n"
206 :
207 : "r"(TrapFrame),
208 [b] "i"(KTRAP_FRAME_EBX),
209 [s] "i"(KTRAP_FRAME_ESI),
210 [i] "i"(KTRAP_FRAME_EDI),
211 [p] "i"(KTRAP_FRAME_EBP),
212 [a] "i"(KTRAP_FRAME_EAX),
213 [e] "i"(KTRAP_FRAME_EIP),
214 [v] "i"(KTRAP_FRAME_ESP)
215 : "%esp"
216 );
217 UNREACHABLE;
218 }
219
220 VOID
221 FORCEINLINE
222 //DECLSPEC_NORETURN
223 KiSystemCallTrapReturn(IN PKTRAP_FRAME TrapFrame)
224 {
225 /* Regular interrupt exit, but we only restore EAX as a volatile */
226 __asm__ __volatile__
227 (
228 "movl %0, %%esp\n"
229 "movl %c[b](%%esp), %%ebx\n"
230 "movl %c[s](%%esp), %%esi\n"
231 "movl %c[i](%%esp), %%edi\n"
232 "movl %c[p](%%esp), %%ebp\n"
233 "movl %c[a](%%esp), %%eax\n"
234 "addl $%c[e],%%esp\n"
235 "iret\n"
236 :
237 : "r"(TrapFrame),
238 [b] "i"(KTRAP_FRAME_EBX),
239 [s] "i"(KTRAP_FRAME_ESI),
240 [i] "i"(KTRAP_FRAME_EDI),
241 [p] "i"(KTRAP_FRAME_EBP),
242 [a] "i"(KTRAP_FRAME_EAX),
243 [e] "i"(KTRAP_FRAME_EIP)
244 : "%esp"
245 );
246 UNREACHABLE;
247 }
248
249 VOID
250 FORCEINLINE
251 //DECLSPEC_NORETURN
252 KiSystemCallSysExitReturn(IN PKTRAP_FRAME TrapFrame)
253 {
254 /* Restore nonvolatiles, EAX, and do a SYSEXIT back to the user caller */
255 __asm__ __volatile__
256 (
257 "movl %0, %%esp\n"
258 "movl %c[s](%%esp), %%esi\n"
259 "movl %c[b](%%esp), %%ebx\n"
260 "movl %c[i](%%esp), %%edi\n"
261 "movl %c[p](%%esp), %%ebp\n"
262 "movl %c[a](%%esp), %%eax\n"
263 "movl %c[e](%%esp), %%edx\n" /* SYSEXIT says EIP in EDX */
264 "movl %c[x](%%esp), %%ecx\n" /* SYSEXIT says ESP in ECX */
265 "addl $%c[v],%%esp\n" /* A WHOLE *USER* frame since we're not IRET'ing */
266 "sti\nsysexit\n"
267 :
268 : "r"(TrapFrame),
269 [b] "i"(KTRAP_FRAME_EBX),
270 [s] "i"(KTRAP_FRAME_ESI),
271 [i] "i"(KTRAP_FRAME_EDI),
272 [p] "i"(KTRAP_FRAME_EBP),
273 [a] "i"(KTRAP_FRAME_EAX),
274 [e] "i"(KTRAP_FRAME_EIP),
275 [x] "i"(KTRAP_FRAME_ESP),
276 [v] "i"(KTRAP_FRAME_V86_ES)
277 : "%esp"
278 );
279 UNREACHABLE;
280 }
281
282 VOID
283 FORCEINLINE
284 //DECLSPEC_NORETURN
285 KiTrapReturn(IN PKTRAP_FRAME TrapFrame)
286 {
287 /* Regular interrupt exit */
288 __asm__ __volatile__
289 (
290 "movl %0, %%esp\n"
291 "movl %c[a](%%esp), %%eax\n"
292 "movl %c[b](%%esp), %%ebx\n"
293 "movl %c[c](%%esp), %%ecx\n"
294 "movl %c[d](%%esp), %%edx\n"
295 "movl %c[s](%%esp), %%esi\n"
296 "movl %c[i](%%esp), %%edi\n"
297 "movl %c[p](%%esp), %%ebp\n"
298 "addl $%c[e],%%esp\n"
299 "iret\n"
300 :
301 : "r"(TrapFrame),
302 [a] "i"(KTRAP_FRAME_EAX),
303 [b] "i"(KTRAP_FRAME_EBX),
304 [c] "i"(KTRAP_FRAME_ECX),
305 [d] "i"(KTRAP_FRAME_EDX),
306 [s] "i"(KTRAP_FRAME_ESI),
307 [i] "i"(KTRAP_FRAME_EDI),
308 [p] "i"(KTRAP_FRAME_EBP),
309 [e] "i"(KTRAP_FRAME_EIP)
310 : "%esp"
311 );
312 UNREACHABLE;
313 }
314
315 VOID
316 FORCEINLINE
317 //DECLSPEC_NORETURN
318 KiEditedTrapReturn(IN PKTRAP_FRAME TrapFrame)
319 {
320 /* Regular interrupt exit */
321 __asm__ __volatile__
322 (
323 "movl %0, %%esp\n"
324 "movl %c[a](%%esp), %%eax\n"
325 "movl %c[b](%%esp), %%ebx\n"
326 "movl %c[c](%%esp), %%ecx\n"
327 "movl %c[d](%%esp), %%edx\n"
328 "movl %c[s](%%esp), %%esi\n"
329 "movl %c[i](%%esp), %%edi\n"
330 "movl %c[p](%%esp), %%ebp\n"
331 "addl $%c[e],%%esp\n"
332 "movl (%%esp), %%esp\n"
333 "iret\n"
334 :
335 : "r"(TrapFrame),
336 [a] "i"(KTRAP_FRAME_EAX),
337 [b] "i"(KTRAP_FRAME_EBX),
338 [c] "i"(KTRAP_FRAME_ECX),
339 [d] "i"(KTRAP_FRAME_EDX),
340 [s] "i"(KTRAP_FRAME_ESI),
341 [i] "i"(KTRAP_FRAME_EDI),
342 [p] "i"(KTRAP_FRAME_EBP),
343 [e] "i"(KTRAP_FRAME_ERROR_CODE) /* We *WANT* the error code since ESP is there! */
344 : "%esp"
345 );
346 UNREACHABLE;
347 }
348
349 //
350 // Generic Exit Routine
351 //
352 VOID
353 FORCEINLINE
354 //DECLSPEC_NORETURN
355 KiExitTrap(IN PKTRAP_FRAME TrapFrame,
356 IN UCHAR Skip)
357 {
358 KTRAP_EXIT_SKIP_BITS SkipBits = { .Bits = Skip };
359 PULONG ReturnStack;
360
361 /* Debugging checks */
362 KiExitTrapDebugChecks(TrapFrame, SkipBits);
363
364 /* Restore the SEH handler chain */
365 KeGetPcr()->Tib.ExceptionList = TrapFrame->ExceptionList;
366
367 /* Check if the previous mode must be restored */
368 if (__builtin_expect(!SkipBits.SkipPreviousMode, 0)) /* More INTS than SYSCALLs */
369 {
370 /* Restore it */
371 KeGetCurrentThread()->PreviousMode = TrapFrame->PreviousPreviousMode;
372 }
373
374 /* Check if there are active debug registers */
375 if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
376 {
377 /* Not handled yet */
378 DbgPrint("Need Hardware Breakpoint Support!\n");
379 DbgBreakPoint();
380 while (TRUE);
381 }
382
383 /* Check if this was a V8086 trap */
384 if (__builtin_expect(TrapFrame->EFlags & EFLAGS_V86_MASK, 0)) KiTrapReturn(TrapFrame);
385
386 /* Check if the trap frame was edited */
387 if (__builtin_expect(!(TrapFrame->SegCs & FRAME_EDITED), 0))
388 {
389 /*
390 * An edited trap frame happens when we need to modify CS and/or ESP but
391 * don't actually have a ring transition. This happens when a kernelmode
392 * caller wants to perform an NtContinue to another kernel address, such
393 * as in the case of SEH (basically, a longjmp), or to a user address.
394 *
395 * Therefore, the CPU never saved CS/ESP on the stack because we did not
396 * get a trap frame due to a ring transition (there was no interrupt).
397 * Even if we didn't want to restore CS to a new value, a problem occurs
398 * due to the fact a normal RET would not work if we restored ESP since
399 * RET would then try to read the result off the stack.
400 *
401 * The NT kernel solves this by adding 12 bytes of stack to the exiting
402 * trap frame, in which EFLAGS, CS, and EIP are stored, and then saving
403 * the ESP that's being requested into the ErrorCode field. It will then
404 * exit with an IRET. This fixes both issues, because it gives the stack
405 * some space where to hold the return address and then end up with the
406 * wanted stack, and it uses IRET which allows a new CS to be inputted.
407 *
408 */
409
410 /* Set CS that is requested */
411 TrapFrame->SegCs = TrapFrame->TempSegCs;
412
413 /* First make space on requested stack */
414 ReturnStack = (PULONG)(TrapFrame->TempEsp - 12);
415 TrapFrame->ErrCode = (ULONG_PTR)ReturnStack;
416
417 /* Now copy IRET frame */
418 ReturnStack[0] = TrapFrame->Eip;
419 ReturnStack[1] = TrapFrame->SegCs;
420 ReturnStack[2] = TrapFrame->EFlags;
421
422 /* Do special edited return */
423 KiEditedTrapReturn(TrapFrame);
424 }
425
426 /* Check if this is a user trap */
427 if (__builtin_expect(KiUserTrap(TrapFrame), 1)) /* Ring 3 is where we spend time */
428 {
429 /* Check if segments should be restored */
430 if (!SkipBits.SkipSegments)
431 {
432 /* Restore segments */
433 Ke386SetGs(TrapFrame->SegGs);
434 Ke386SetEs(TrapFrame->SegEs);
435 Ke386SetDs(TrapFrame->SegDs);
436 Ke386SetFs(TrapFrame->SegFs);
437 }
438
439 /* Always restore FS since it goes from KPCR to TEB */
440 Ke386SetFs(TrapFrame->SegFs);
441 }
442
443 /* Check for system call -- a system call skips volatiles! */
444 if (__builtin_expect(SkipBits.SkipVolatiles, 0)) /* More INTs than SYSCALLs */
445 {
446 /* Kernel call or user call? */
447 if (__builtin_expect(KiUserTrap(TrapFrame), 1)) /* More Ring 3 than 0 */
448 {
449 /* Is SYSENTER supported and/or enabled, or are we stepping code? */
450 if (__builtin_expect((KiFastSystemCallDisable) ||
451 (TrapFrame->EFlags & EFLAGS_TF), 0))
452 {
453 /* Exit normally */
454 KiSystemCallTrapReturn(TrapFrame);
455 }
456 else
457 {
458 /* Restore user FS */
459 Ke386SetFs(KGDT_R3_TEB | RPL_MASK);
460
461 /* Remove interrupt flag */
462 TrapFrame->EFlags &= ~EFLAGS_INTERRUPT_MASK;
463 __writeeflags(TrapFrame->EFlags);
464
465 /* Exit through SYSEXIT */
466 KiSystemCallSysExitReturn(TrapFrame);
467 }
468 }
469 else
470 {
471 /* Restore EFLags */
472 __writeeflags(TrapFrame->EFlags);
473
474 /* Call is kernel, so do a jump back since this wasn't a real INT */
475 KiSystemCallReturn(TrapFrame);
476 }
477 }
478 else
479 {
480 /* Return from interrupt */
481 KiTrapReturn(TrapFrame);
482 }
483 }
484
485 //
486 // Virtual 8086 Mode Optimized Trap Exit
487 //
488 VOID
489 FORCEINLINE
490 KiExitV86Trap(IN PKTRAP_FRAME TrapFrame)
491 {
492 PKTHREAD Thread;
493 KIRQL OldIrql;
494
495 /* Get the thread */
496 Thread = KeGetCurrentThread();
497 while (TRUE)
498 {
499 /* Turn off the alerted state for kernel mode */
500 Thread->Alerted[KernelMode] = FALSE;
501
502 /* Are there pending user APCs? */
503 if (__builtin_expect(!Thread->ApcState.UserApcPending, 1)) break;
504
505 /* Raise to APC level and enable interrupts */
506 OldIrql = KfRaiseIrql(APC_LEVEL);
507 _enable();
508
509 /* Deliver APCs */
510 KiDeliverApc(UserMode, NULL, TrapFrame);
511
512 /* Restore IRQL and disable interrupts once again */
513 KfLowerIrql(OldIrql);
514 _disable();
515
516 /* Return if this isn't V86 mode anymore */
517 if (__builtin_expect(TrapFrame->EFlags & EFLAGS_V86_MASK, 0)) return;
518 }
519
520 /* If we got here, we're still in a valid V8086 context, so quit it */
521 if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
522 {
523 /* Not handled yet */
524 DbgPrint("Need Hardware Breakpoint Support!\n");
525 while (TRUE);
526 }
527
528 /* Return from interrupt */
529 KiTrapReturn(TrapFrame);
530 }
531
532 //
533 // Virtual 8086 Mode Optimized Trap Entry
534 //
535 VOID
536 FORCEINLINE
537 KiEnterV86Trap(IN PKTRAP_FRAME TrapFrame)
538 {
539 /* Load correct registers */
540 Ke386SetFs(KGDT_R0_PCR);
541 Ke386SetDs(KGDT_R3_DATA | RPL_MASK);
542 Ke386SetEs(KGDT_R3_DATA | RPL_MASK);
543
544 /* Save exception list and bogus previous mode */
545 TrapFrame->PreviousPreviousMode = -1;
546 TrapFrame->ExceptionList = KeGetPcr()->Tib.ExceptionList;
547
548 /* Clear direction flag */
549 Ke386ClearDirectionFlag();
550
551 /* Save DR7 and check for debugging */
552 TrapFrame->Dr7 = __readdr(7);
553 if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
554 {
555 DbgPrint("Need Hardware Breakpoint Support!\n");
556 while (TRUE);
557 }
558 }
559
560 //
561 // Interrupt Trap Entry
562 //
563 VOID
564 FORCEINLINE
565 KiEnterInterruptTrap(IN PKTRAP_FRAME TrapFrame)
566 {
567 /* Set bogus previous mode */
568 TrapFrame->PreviousPreviousMode = -1;
569
570 /* Check for V86 mode */
571 if (__builtin_expect(TrapFrame->EFlags & EFLAGS_V86_MASK, 0))
572 {
573 DbgPrint("Need V8086 Interrupt Support!\n");
574 while (TRUE);
575 }
576
577 /* Check if this wasn't kernel code */
578 if (__builtin_expect(TrapFrame->SegCs != KGDT_R0_CODE, 1)) /* Ring 3 is more common */
579 {
580 /* Save segments and then switch to correct ones */
581 TrapFrame->SegFs = Ke386GetFs();
582 TrapFrame->SegGs = Ke386GetGs();
583 TrapFrame->SegDs = Ke386GetDs();
584 TrapFrame->SegEs = Ke386GetEs();
585 Ke386SetFs(KGDT_R0_PCR);
586 Ke386SetDs(KGDT_R3_DATA | RPL_MASK);
587 Ke386SetEs(KGDT_R3_DATA | RPL_MASK);
588 }
589
590 /* Save exception list and terminate it */
591 TrapFrame->ExceptionList = KeGetPcr()->Tib.ExceptionList;
592 KeGetPcr()->Tib.ExceptionList = EXCEPTION_CHAIN_END;
593
594 /* No error code */
595 TrapFrame->ErrCode = 0;
596
597 /* Clear direction flag */
598 Ke386ClearDirectionFlag();
599
600 /* Flush DR7 and check for debugging */
601 TrapFrame->Dr7 = 0;
602 if (__builtin_expect(KeGetCurrentThread()->DispatcherHeader.DebugActive & 0xFF, 0))
603 {
604 DbgPrint("Need Hardware Breakpoint Support!\n");
605 while (TRUE);
606 }
607
608 /* Set debug header */
609 KiFillTrapFrameDebug(TrapFrame);
610 }
611
612 //
613 // Generic Trap Entry
614 //
615 VOID
616 FORCEINLINE
617 KiEnterTrap(IN PKTRAP_FRAME TrapFrame)
618 {
619 ULONG Ds, Es;
620
621 /*
622 * We really have to get a good DS/ES first before touching any data.
623 *
624 * These two reads will either go in a register (with optimizations ON) or
625 * a stack variable (which is on SS:ESP, guaranteed to be good/valid).
626 *
627 * Because the assembly is marked volatile, the order of instructions is
628 * as-is, otherwise the optimizer could simply get rid of our DS/ES.
629 *
630 */
631 Ds = Ke386GetDs();
632 Es = Ke386GetEs();
633 Ke386SetDs(KGDT_R3_DATA | RPL_MASK);
634 Ke386SetEs(KGDT_R3_DATA | RPL_MASK);
635 TrapFrame->SegDs = Ds;
636 TrapFrame->SegEs = Es;
637
638 /* Now we can save the other segments and then switch to the correct FS */
639 TrapFrame->SegFs = Ke386GetFs();
640 TrapFrame->SegGs = Ke386GetGs();
641 Ke386SetFs(KGDT_R0_PCR);
642
643 /* Save exception list and bogus previous mode */
644 TrapFrame->PreviousPreviousMode = -1;
645 TrapFrame->ExceptionList = KeGetPcr()->Tib.ExceptionList;
646
647 /* Check for V86 mode */
648 if (__builtin_expect(TrapFrame->EFlags & EFLAGS_V86_MASK, 0))
649 {
650 /* Restore V8086 segments into Protected Mode segments */
651 TrapFrame->SegFs = TrapFrame->V86Fs;
652 TrapFrame->SegGs = TrapFrame->V86Gs;
653 TrapFrame->SegDs = TrapFrame->V86Ds;
654 TrapFrame->SegEs = TrapFrame->V86Es;
655 }
656
657 /* Clear direction flag */
658 Ke386ClearDirectionFlag();
659
660 /* Flush DR7 and check for debugging */
661 TrapFrame->Dr7 = 0;
662 if (__builtin_expect(KeGetCurrentThread()->DispatcherHeader.DebugActive & 0xFF, 0))
663 {
664 DbgPrint("Need Hardware Breakpoint Support!\n");
665 while (TRUE);
666 }
667
668 /* Set debug header */
669 KiFillTrapFrameDebug(TrapFrame);
670 }
671 #endif