Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentrap_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
1.7.6.1
|