ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

trap_x.h
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Kernel
00003  * LICENSE:         BSD - See COPYING.ARM in the top level directory
00004  * FILE:            ntoskrnl/include/i386/trap_x.h
00005  * PURPOSE:         Internal Inlined Functions for the Trap Handling Code
00006  * PROGRAMMERS:     ReactOS Portable Systems Group
00007  */
00008 
00009 #pragma once
00010 
00011 #define TRAP_DEBUG 0
00012 
00013 //
00014 // Unreachable code hint for GCC 4.5.x, older GCC versions, and MSVC
00015 //
00016 #ifdef __GNUC__
00017 #if __GNUC__ * 100 + __GNUC_MINOR__ >= 405
00018 #define UNREACHABLE __builtin_unreachable()
00019 #else
00020 #define UNREACHABLE __builtin_trap()
00021 #endif
00022 #elif _MSC_VER
00023 #define UNREACHABLE __assume(0)
00024 #define __builtin_expect(a,b) (a)
00025 #else
00026 #define UNREACHABLE
00027 #endif
00028 
00029 //
00030 // Helper Code
00031 //
00032 BOOLEAN
00033 FORCEINLINE
00034 KiUserTrap(IN PKTRAP_FRAME TrapFrame)
00035 {
00036     /* Anything else but Ring 0 is Ring 3 */
00037     return !!(TrapFrame->SegCs & MODE_MASK);
00038 }
00039 
00040 //
00041 // Debug Macros
00042 //
00043 VOID
00044 FORCEINLINE
00045 KiDumpTrapFrame(IN PKTRAP_FRAME TrapFrame)
00046 {
00047     /* Dump the whole thing */
00048     DbgPrint("DbgEbp: %x\n", TrapFrame->DbgEbp);
00049     DbgPrint("DbgEip: %x\n", TrapFrame->DbgEip);
00050     DbgPrint("DbgArgMark: %x\n", TrapFrame->DbgArgMark);
00051     DbgPrint("DbgArgPointer: %x\n", TrapFrame->DbgArgPointer);
00052     DbgPrint("TempSegCs: %x\n", TrapFrame->TempSegCs);
00053     DbgPrint("TempEsp: %x\n", TrapFrame->TempEsp);
00054     DbgPrint("Dr0: %x\n", TrapFrame->Dr0);
00055     DbgPrint("Dr1: %x\n", TrapFrame->Dr1);
00056     DbgPrint("Dr2: %x\n", TrapFrame->Dr2);
00057     DbgPrint("Dr3: %x\n", TrapFrame->Dr3);
00058     DbgPrint("Dr6: %x\n", TrapFrame->Dr6);
00059     DbgPrint("Dr7: %x\n", TrapFrame->Dr7);
00060     DbgPrint("SegGs: %x\n", TrapFrame->SegGs);
00061     DbgPrint("SegEs: %x\n", TrapFrame->SegEs);
00062     DbgPrint("SegDs: %x\n", TrapFrame->SegDs);
00063     DbgPrint("Edx: %x\n", TrapFrame->Edx);
00064     DbgPrint("Ecx: %x\n", TrapFrame->Ecx);
00065     DbgPrint("Eax: %x\n", TrapFrame->Eax);
00066     DbgPrint("PreviousPreviousMode: %x\n", TrapFrame->PreviousPreviousMode);
00067     DbgPrint("ExceptionList: %p\n", TrapFrame->ExceptionList);
00068     DbgPrint("SegFs: %x\n", TrapFrame->SegFs);
00069     DbgPrint("Edi: %x\n", TrapFrame->Edi);
00070     DbgPrint("Esi: %x\n", TrapFrame->Esi);
00071     DbgPrint("Ebx: %x\n", TrapFrame->Ebx);
00072     DbgPrint("Ebp: %x\n", TrapFrame->Ebp);
00073     DbgPrint("ErrCode: %x\n", TrapFrame->ErrCode);
00074     DbgPrint("Eip: %x\n", TrapFrame->Eip);
00075     DbgPrint("SegCs: %x\n", TrapFrame->SegCs);
00076     DbgPrint("EFlags: %x\n", TrapFrame->EFlags);
00077     DbgPrint("HardwareEsp: %x\n", TrapFrame->HardwareEsp);
00078     DbgPrint("HardwareSegSs: %x\n", TrapFrame->HardwareSegSs);
00079     DbgPrint("V86Es: %x\n", TrapFrame->V86Es);
00080     DbgPrint("V86Ds: %x\n", TrapFrame->V86Ds);
00081     DbgPrint("V86Fs: %x\n", TrapFrame->V86Fs);
00082     DbgPrint("V86Gs: %x\n", TrapFrame->V86Gs);
00083 }
00084 
00085 #if TRAP_DEBUG
00086 VOID
00087 FORCEINLINE
00088 KiFillTrapFrameDebug(IN PKTRAP_FRAME TrapFrame)
00089 {
00090     /* Set the debug information */
00091     TrapFrame->DbgArgPointer = TrapFrame->Edx;
00092     TrapFrame->DbgArgMark = 0xBADB0D00;
00093     TrapFrame->DbgEip = TrapFrame->Eip;
00094     TrapFrame->DbgEbp = TrapFrame->Ebp;
00095     TrapFrame->PreviousPreviousMode = -1;
00096 }
00097 
00098 #define DR7_RESERVED_READ_AS_1 0x400
00099 
00100 #define CheckDr(DrNumner, ExpectedValue) \
00101     { \
00102         ULONG DrValue = __readdr(DrNumner); \
00103         if (DrValue != (ExpectedValue)) \
00104         { \
00105             DbgPrint("Dr%ld: expected %.8lx, got %.8lx\n", \
00106                     DrNumner, ExpectedValue, DrValue); \
00107             __debugbreak(); \
00108         } \
00109     }
00110 
00111 extern BOOLEAN StopChecking;
00112 
00113 VOID
00114 FORCEINLINE
00115 KiExitTrapDebugChecks(IN PKTRAP_FRAME TrapFrame,
00116                       IN BOOLEAN SkipPreviousMode)
00117 {
00118     /* Don't check recursively */
00119     if (StopChecking) return;
00120     StopChecking = TRUE;
00121 
00122     /* Make sure interrupts are disabled */
00123     if (__readeflags() & EFLAGS_INTERRUPT_MASK)
00124     {
00125         DbgPrint("Exiting with interrupts enabled: %lx\n", __readeflags());
00126         __debugbreak();
00127     }
00128 
00129     /* Make sure this is a real trap frame */
00130     if (TrapFrame->DbgArgMark != 0xBADB0D00)
00131     {
00132         DbgPrint("Exiting with an invalid trap frame? (No MAGIC in trap frame)\n");
00133         KiDumpTrapFrame(TrapFrame);
00134         __debugbreak();
00135     }
00136 
00137     /* Make sure we're not in user-mode or something */
00138     if (Ke386GetFs() != KGDT_R0_PCR)
00139     {
00140         DbgPrint("Exiting with an invalid FS: %lx\n", Ke386GetFs());
00141         __debugbreak();
00142     }
00143 
00144     /* Make sure we have a valid SEH chain */
00145     if (KeGetPcr()->NtTib.ExceptionList == 0)
00146     {
00147         DbgPrint("Exiting with NULL exception chain: %p\n", KeGetPcr()->NtTib.ExceptionList);
00148         __debugbreak();
00149     }
00150 
00151     /* Make sure we're restoring a valid SEH chain */
00152     if (TrapFrame->ExceptionList == 0)
00153     {
00154         DbgPrint("Entered a trap with a NULL exception chain: %p\n", TrapFrame->ExceptionList);
00155         __debugbreak();
00156     }
00157 
00158     /* If we're ignoring previous mode, make sure caller doesn't actually want it */
00159     if (SkipPreviousMode && (TrapFrame->PreviousPreviousMode != -1))
00160     {
00161         DbgPrint("Exiting a trap witout restoring previous mode, yet previous mode seems valid: %lx\n", TrapFrame->PreviousPreviousMode);
00162         __debugbreak();
00163     }
00164 
00165     /* Check DR values */
00166     if (TrapFrame->SegCs & MODE_MASK)
00167     {
00168         /* Check for active debugging */
00169         if (KeGetCurrentThread()->Header.DebugActive)
00170         {
00171             if ((TrapFrame->Dr7 & ~DR7_RESERVED_MASK) == 0) __debugbreak();
00172 
00173             CheckDr(0, TrapFrame->Dr0);
00174             CheckDr(1, TrapFrame->Dr1);
00175             CheckDr(2, TrapFrame->Dr2);
00176             CheckDr(3, TrapFrame->Dr3);
00177             CheckDr(7, TrapFrame->Dr7 | DR7_RESERVED_READ_AS_1);
00178         }
00179     }
00180     else
00181     {
00182         PKPRCB Prcb = KeGetCurrentPrcb();
00183         CheckDr(0, Prcb->ProcessorState.SpecialRegisters.KernelDr0);
00184         CheckDr(1, Prcb->ProcessorState.SpecialRegisters.KernelDr1);
00185         CheckDr(2, Prcb->ProcessorState.SpecialRegisters.KernelDr2);
00186         CheckDr(3, Prcb->ProcessorState.SpecialRegisters.KernelDr3);
00187         //CheckDr(7, Prcb->ProcessorState.SpecialRegisters.KernelDr7);
00188     }
00189 
00190     StopChecking = FALSE;
00191 }
00192 
00193 VOID
00194 FORCEINLINE
00195 KiExitSystemCallDebugChecks(IN ULONG SystemCall,
00196                             IN PKTRAP_FRAME TrapFrame)
00197 {
00198     KIRQL OldIrql;
00199 
00200     /* Check if this was a user call */
00201     if (KiUserTrap(TrapFrame))
00202     {
00203         /* Make sure we are not returning with elevated IRQL */
00204         OldIrql = KeGetCurrentIrql();
00205         if (OldIrql != PASSIVE_LEVEL)
00206         {
00207             /* Forcibly put us in a sane state */
00208             KeGetPcr()->Irql = PASSIVE_LEVEL;
00209             _disable();
00210 
00211             /* Fail */
00212             KeBugCheckEx(IRQL_GT_ZERO_AT_SYSTEM_SERVICE,
00213                          SystemCall,
00214                          OldIrql,
00215                          0,
00216                          0);
00217         }
00218 
00219         /* Make sure we're not attached and that APCs are not disabled */
00220         if ((KeGetCurrentThread()->ApcStateIndex != OriginalApcEnvironment) ||
00221             (KeGetCurrentThread()->CombinedApcDisable != 0))
00222         {
00223             /* Fail */
00224             KeBugCheckEx(APC_INDEX_MISMATCH,
00225                          SystemCall,
00226                          KeGetCurrentThread()->ApcStateIndex,
00227                          KeGetCurrentThread()->CombinedApcDisable,
00228                          0);
00229         }
00230     }
00231 }
00232 #else
00233 #define KiExitTrapDebugChecks(x, y)
00234 #define KiFillTrapFrameDebug(x)
00235 #define KiExitSystemCallDebugChecks(x, y)
00236 #endif
00237 
00238 //
00239 // Generic Exit Routine
00240 //
00241 DECLSPEC_NORETURN VOID FASTCALL KiSystemCallReturn(IN PKTRAP_FRAME TrapFrame);
00242 DECLSPEC_NORETURN VOID FASTCALL KiSystemCallSysExitReturn(IN PKTRAP_FRAME TrapFrame);
00243 DECLSPEC_NORETURN VOID FASTCALL KiSystemCallTrapReturn(IN PKTRAP_FRAME TrapFrame);
00244 DECLSPEC_NORETURN VOID FASTCALL KiEditedTrapReturn(IN PKTRAP_FRAME TrapFrame);
00245 DECLSPEC_NORETURN VOID FASTCALL KiTrapReturn(IN PKTRAP_FRAME TrapFrame);
00246 DECLSPEC_NORETURN VOID FASTCALL KiTrapReturnNoSegments(IN PKTRAP_FRAME TrapFrame);
00247 
00248 typedef
00249 ATTRIB_NORETURN
00250 VOID
00251 (FASTCALL *PFAST_SYSTEM_CALL_EXIT)(
00252     IN PKTRAP_FRAME TrapFrame
00253 );
00254 
00255 extern PFAST_SYSTEM_CALL_EXIT KiFastCallExitHandler;
00256 
00257 //
00258 // Save user mode debug registers and restore kernel values
00259 //
00260 VOID
00261 FORCEINLINE
00262 KiHandleDebugRegistersOnTrapEntry(
00263     IN PKTRAP_FRAME TrapFrame)
00264 {
00265     PKPRCB Prcb = KeGetCurrentPrcb();
00266 
00267     /* Save all debug registers in the trap frame */
00268     TrapFrame->Dr0 = __readdr(0);
00269     TrapFrame->Dr1 = __readdr(1);
00270     TrapFrame->Dr2 = __readdr(2);
00271     TrapFrame->Dr3 = __readdr(3);
00272     TrapFrame->Dr6 = __readdr(6);
00273     TrapFrame->Dr7 = __readdr(7);
00274 
00275     /* Disable all active debugging */
00276     __writedr(7, 0);
00277 
00278     /* Restore kernel values */
00279     __writedr(0, Prcb->ProcessorState.SpecialRegisters.KernelDr0);
00280     __writedr(1, Prcb->ProcessorState.SpecialRegisters.KernelDr1);
00281     __writedr(2, Prcb->ProcessorState.SpecialRegisters.KernelDr2);
00282     __writedr(3, Prcb->ProcessorState.SpecialRegisters.KernelDr3);
00283     __writedr(6, Prcb->ProcessorState.SpecialRegisters.KernelDr6);
00284     __writedr(7, Prcb->ProcessorState.SpecialRegisters.KernelDr7);
00285 }
00286 
00287 VOID
00288 FORCEINLINE
00289 KiHandleDebugRegistersOnTrapExit(
00290     PKTRAP_FRAME TrapFrame)
00291 {
00292     /* Disable all active debugging */
00293     __writedr(7, 0);
00294 
00295     /* Load all debug registers from the trap frame */
00296     __writedr(0, TrapFrame->Dr0);
00297     __writedr(1, TrapFrame->Dr1);
00298     __writedr(2, TrapFrame->Dr2);
00299     __writedr(3, TrapFrame->Dr3);
00300     __writedr(6, TrapFrame->Dr6);
00301     __writedr(7, TrapFrame->Dr7);
00302 }
00303 
00304 //
00305 // Virtual 8086 Mode Optimized Trap Exit
00306 //
00307 VOID
00308 FORCEINLINE
00309 DECLSPEC_NORETURN
00310 KiExitV86Trap(IN PKTRAP_FRAME TrapFrame)
00311 {
00312     PKTHREAD Thread;
00313     KIRQL OldIrql;
00314 
00315     /* Get the thread */
00316     Thread = KeGetCurrentThread();
00317     while (TRUE)
00318     {
00319         /* Return if this isn't V86 mode anymore */
00320         if (!(TrapFrame->EFlags & EFLAGS_V86_MASK)) KiEoiHelper(TrapFrame);
00321 
00322         /* Turn off the alerted state for kernel mode */
00323         Thread->Alerted[KernelMode] = FALSE;
00324 
00325         /* Are there pending user APCs? */
00326         if (__builtin_expect(!Thread->ApcState.UserApcPending, 1)) break;
00327 
00328         /* Raise to APC level and enable interrupts */
00329         OldIrql = KfRaiseIrql(APC_LEVEL);
00330         _enable();
00331 
00332         /* Deliver APCs */
00333         KiDeliverApc(UserMode, NULL, TrapFrame);
00334 
00335         /* Restore IRQL and disable interrupts once again */
00336         KfLowerIrql(OldIrql);
00337         _disable();
00338     }
00339 
00340     /* If we got here, we're still in a valid V8086 context, so quit it */
00341     if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
00342     {
00343         /* Restore debug registers from the trap frame */
00344         KiHandleDebugRegistersOnTrapExit(TrapFrame);
00345     }
00346 
00347     /* Return from interrupt */
00348     KiTrapReturnNoSegments(TrapFrame);
00349 }
00350 
00351 //
00352 // Virtual 8086 Mode Optimized Trap Entry
00353 //
00354 VOID
00355 FORCEINLINE
00356 KiEnterV86Trap(IN PKTRAP_FRAME TrapFrame)
00357 {
00358     /* Save exception list */
00359     TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
00360 
00361     /* Save DR7 and check for debugging */
00362     TrapFrame->Dr7 = __readdr(7);
00363     if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
00364     {
00365         /* Handle debug registers */
00366         KiHandleDebugRegistersOnTrapEntry(TrapFrame);
00367     }
00368 }
00369 
00370 //
00371 // Interrupt Trap Entry
00372 //
00373 VOID
00374 FORCEINLINE
00375 KiEnterInterruptTrap(IN PKTRAP_FRAME TrapFrame)
00376 {
00377     /* Save exception list and terminate it */
00378     TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
00379     KeGetPcr()->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
00380 
00381     /* Default to debugging disabled */
00382     TrapFrame->Dr7 = 0;
00383 
00384     /* Check if the frame was from user mode or v86 mode */
00385     if ((TrapFrame->SegCs & MODE_MASK) ||
00386         (TrapFrame->EFlags & EFLAGS_V86_MASK))
00387     {
00388         /* Check for active debugging */
00389         if (KeGetCurrentThread()->Header.DebugActive & 0xFF)
00390         {
00391             /* Handle debug registers */
00392             KiHandleDebugRegistersOnTrapEntry(TrapFrame);
00393         }
00394     }
00395 
00396     /* Set debug header */
00397     KiFillTrapFrameDebug(TrapFrame);
00398 }
00399 
00400 //
00401 // Generic Trap Entry
00402 //
00403 VOID
00404 FORCEINLINE
00405 KiEnterTrap(IN PKTRAP_FRAME TrapFrame)
00406 {
00407     /* Save exception list */
00408     TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
00409 
00410     /* Default to debugging disabled */
00411     TrapFrame->Dr7 = 0;
00412 
00413     /* Check if the frame was from user mode or v86 mode */
00414     if ((TrapFrame->SegCs & MODE_MASK) ||
00415         (TrapFrame->EFlags & EFLAGS_V86_MASK))
00416     {
00417         /* Check for active debugging */
00418         if (KeGetCurrentThread()->Header.DebugActive & 0xFF)
00419         {
00420             /* Handle debug registers */
00421             KiHandleDebugRegistersOnTrapEntry(TrapFrame);
00422         }
00423     }
00424 
00425     /* Set debug header */
00426     KiFillTrapFrameDebug(TrapFrame);
00427 }

Generated on Sun May 27 2012 04:37:13 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.