1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: BSD - See COPYING.ARM in the top level directory 4 * FILE: ntoskrnl/include/internal/i386/trap_x.h 5 * PURPOSE: Internal Inlined Functions for the Trap Handling Code 6 * PROGRAMMERS: ReactOS Portable Systems Group 7 */ 8 9 #pragma once 10 11 #if defined(_MSC_VER) 12 #define __builtin_expect(a,b) (a) 13 #endif 14 15 // 16 // Helper Code 17 // 18 FORCEINLINE 19 BOOLEAN 20 KiUserTrap(IN PKTRAP_FRAME TrapFrame) 21 { 22 /* Anything else but Ring 0 is Ring 3 */ 23 return !!(TrapFrame->SegCs & MODE_MASK); 24 } 25 26 // 27 // Debug Macros 28 // 29 FORCEINLINE 30 VOID 31 KiDumpTrapFrame(IN PKTRAP_FRAME TrapFrame) 32 { 33 /* Dump the whole thing */ 34 DbgPrint("DbgEbp: %x\n", TrapFrame->DbgEbp); 35 DbgPrint("DbgEip: %x\n", TrapFrame->DbgEip); 36 DbgPrint("DbgArgMark: %x\n", TrapFrame->DbgArgMark); 37 DbgPrint("DbgArgPointer: %x\n", TrapFrame->DbgArgPointer); 38 DbgPrint("TempSegCs: %x\n", TrapFrame->TempSegCs); 39 DbgPrint("TempEsp: %x\n", TrapFrame->TempEsp); 40 DbgPrint("Dr0: %x\n", TrapFrame->Dr0); 41 DbgPrint("Dr1: %x\n", TrapFrame->Dr1); 42 DbgPrint("Dr2: %x\n", TrapFrame->Dr2); 43 DbgPrint("Dr3: %x\n", TrapFrame->Dr3); 44 DbgPrint("Dr6: %x\n", TrapFrame->Dr6); 45 DbgPrint("Dr7: %x\n", TrapFrame->Dr7); 46 DbgPrint("SegGs: %x\n", TrapFrame->SegGs); 47 DbgPrint("SegEs: %x\n", TrapFrame->SegEs); 48 DbgPrint("SegDs: %x\n", TrapFrame->SegDs); 49 DbgPrint("Edx: %x\n", TrapFrame->Edx); 50 DbgPrint("Ecx: %x\n", TrapFrame->Ecx); 51 DbgPrint("Eax: %x\n", TrapFrame->Eax); 52 DbgPrint("PreviousPreviousMode: %x\n", TrapFrame->PreviousPreviousMode); 53 DbgPrint("ExceptionList: %p\n", TrapFrame->ExceptionList); 54 DbgPrint("SegFs: %x\n", TrapFrame->SegFs); 55 DbgPrint("Edi: %x\n", TrapFrame->Edi); 56 DbgPrint("Esi: %x\n", TrapFrame->Esi); 57 DbgPrint("Ebx: %x\n", TrapFrame->Ebx); 58 DbgPrint("Ebp: %x\n", TrapFrame->Ebp); 59 DbgPrint("ErrCode: %x\n", TrapFrame->ErrCode); 60 DbgPrint("Eip: %x\n", TrapFrame->Eip); 61 DbgPrint("SegCs: %x\n", TrapFrame->SegCs); 62 DbgPrint("EFlags: %x\n", TrapFrame->EFlags); 63 DbgPrint("HardwareEsp: %x\n", TrapFrame->HardwareEsp); 64 DbgPrint("HardwareSegSs: %x\n", TrapFrame->HardwareSegSs); 65 DbgPrint("V86Es: %x\n", TrapFrame->V86Es); 66 DbgPrint("V86Ds: %x\n", TrapFrame->V86Ds); 67 DbgPrint("V86Fs: %x\n", TrapFrame->V86Fs); 68 DbgPrint("V86Gs: %x\n", TrapFrame->V86Gs); 69 } 70 71 #if DBG 72 FORCEINLINE 73 VOID 74 KiFillTrapFrameDebug(IN PKTRAP_FRAME TrapFrame) 75 { 76 /* Set the debug information */ 77 TrapFrame->DbgArgPointer = TrapFrame->Edx; 78 TrapFrame->DbgArgMark = 0xBADB0D00; 79 TrapFrame->DbgEip = TrapFrame->Eip; 80 TrapFrame->DbgEbp = TrapFrame->Ebp; 81 TrapFrame->PreviousPreviousMode = (ULONG)-1; 82 } 83 84 #define DR7_RESERVED_READ_AS_1 0x400 85 86 #define CheckDr(DrNumner, ExpectedValue) \ 87 { \ 88 ULONG DrValue = __readdr(DrNumner); \ 89 if (DrValue != (ExpectedValue)) \ 90 { \ 91 DbgPrint("Dr%ld: expected %.8lx, got %.8lx\n", \ 92 DrNumner, ExpectedValue, DrValue); \ 93 __debugbreak(); \ 94 } \ 95 } 96 97 extern BOOLEAN StopChecking; 98 99 FORCEINLINE 100 VOID 101 KiExitTrapDebugChecks(IN PKTRAP_FRAME TrapFrame, 102 IN BOOLEAN SkipPreviousMode) 103 { 104 /* Don't check recursively */ 105 if (StopChecking) return; 106 StopChecking = TRUE; 107 108 /* Make sure interrupts are disabled */ 109 if (__readeflags() & EFLAGS_INTERRUPT_MASK) 110 { 111 DbgPrint("Exiting with interrupts enabled: %lx\n", __readeflags()); 112 __debugbreak(); 113 } 114 115 /* Make sure this is a real trap frame */ 116 if (TrapFrame->DbgArgMark != 0xBADB0D00) 117 { 118 DbgPrint("Exiting with an invalid trap frame? (No MAGIC in trap frame)\n"); 119 KiDumpTrapFrame(TrapFrame); 120 __debugbreak(); 121 } 122 123 /* Make sure we're not in user-mode or something */ 124 if (Ke386GetFs() != KGDT_R0_PCR) 125 { 126 DbgPrint("Exiting with an invalid FS: %lx\n", Ke386GetFs()); 127 __debugbreak(); 128 } 129 130 /* Make sure we have a valid SEH chain */ 131 if (KeGetPcr()->NtTib.ExceptionList == 0) 132 { 133 DbgPrint("Exiting with NULL exception chain: %p\n", KeGetPcr()->NtTib.ExceptionList); 134 __debugbreak(); 135 } 136 137 /* Make sure we're restoring a valid SEH chain */ 138 if (TrapFrame->ExceptionList == 0) 139 { 140 DbgPrint("Entered a trap with a NULL exception chain: %p\n", TrapFrame->ExceptionList); 141 __debugbreak(); 142 } 143 144 /* If we're ignoring previous mode, make sure caller doesn't actually want it */ 145 if (SkipPreviousMode && (TrapFrame->PreviousPreviousMode != (ULONG)-1)) 146 { 147 DbgPrint("Exiting a trap witout restoring previous mode, yet previous mode seems valid: %lx\n", TrapFrame->PreviousPreviousMode); 148 __debugbreak(); 149 } 150 151 /* FIXME: KDBG messes around with these improperly */ 152 #if !defined(KDBG) 153 /* Check DR values */ 154 if (KiUserTrap(TrapFrame)) 155 { 156 /* Check for active debugging */ 157 if (KeGetCurrentThread()->Header.DebugActive) 158 { 159 if ((TrapFrame->Dr7 & ~DR7_RESERVED_MASK) == 0) __debugbreak(); 160 161 CheckDr(0, TrapFrame->Dr0); 162 CheckDr(1, TrapFrame->Dr1); 163 CheckDr(2, TrapFrame->Dr2); 164 CheckDr(3, TrapFrame->Dr3); 165 CheckDr(7, TrapFrame->Dr7 | DR7_RESERVED_READ_AS_1); 166 } 167 } 168 else 169 { 170 PKPRCB Prcb = KeGetCurrentPrcb(); 171 CheckDr(0, Prcb->ProcessorState.SpecialRegisters.KernelDr0); 172 CheckDr(1, Prcb->ProcessorState.SpecialRegisters.KernelDr1); 173 CheckDr(2, Prcb->ProcessorState.SpecialRegisters.KernelDr2); 174 CheckDr(3, Prcb->ProcessorState.SpecialRegisters.KernelDr3); 175 // CheckDr(7, Prcb->ProcessorState.SpecialRegisters.KernelDr7); // Disabled, see CORE-10165 for more details. 176 } 177 #endif 178 179 StopChecking = FALSE; 180 } 181 182 #else 183 #define KiExitTrapDebugChecks(x, y) 184 #define KiFillTrapFrameDebug(x) 185 #endif 186 187 FORCEINLINE 188 VOID 189 KiExitSystemCallDebugChecks(IN ULONG SystemCall, 190 IN PKTRAP_FRAME TrapFrame) 191 { 192 KIRQL OldIrql; 193 194 /* Check if this was a user call */ 195 if (KiUserTrap(TrapFrame)) 196 { 197 /* Make sure we are not returning with elevated IRQL */ 198 OldIrql = KeGetCurrentIrql(); 199 if (OldIrql != PASSIVE_LEVEL) 200 { 201 /* Forcibly put us in a sane state */ 202 KeGetPcr()->Irql = PASSIVE_LEVEL; 203 _disable(); 204 205 /* Fail */ 206 KeBugCheckEx(IRQL_GT_ZERO_AT_SYSTEM_SERVICE, 207 SystemCall, 208 OldIrql, 209 0, 210 0); 211 } 212 213 /* Make sure we're not attached and that APCs are not disabled */ 214 if ((KeGetCurrentThread()->ApcStateIndex != OriginalApcEnvironment) || 215 (KeGetCurrentThread()->CombinedApcDisable != 0)) 216 { 217 /* Fail */ 218 KeBugCheckEx(APC_INDEX_MISMATCH, 219 SystemCall, 220 KeGetCurrentThread()->ApcStateIndex, 221 KeGetCurrentThread()->CombinedApcDisable, 222 0); 223 } 224 } 225 } 226 227 // 228 // Generic Exit Routine 229 // 230 DECLSPEC_NORETURN VOID FASTCALL KiSystemCallReturn(IN PKTRAP_FRAME TrapFrame); 231 DECLSPEC_NORETURN VOID FASTCALL KiSystemCallSysExitReturn(IN PKTRAP_FRAME TrapFrame); 232 DECLSPEC_NORETURN VOID FASTCALL KiSystemCallTrapReturn(IN PKTRAP_FRAME TrapFrame); 233 DECLSPEC_NORETURN VOID FASTCALL KiEditedTrapReturn(IN PKTRAP_FRAME TrapFrame); 234 DECLSPEC_NORETURN VOID FASTCALL KiTrapReturn(IN PKTRAP_FRAME TrapFrame); 235 DECLSPEC_NORETURN VOID FASTCALL KiTrapReturnNoSegments(IN PKTRAP_FRAME TrapFrame); 236 DECLSPEC_NORETURN VOID FASTCALL KiTrapReturnNoSegmentsRet8(IN PKTRAP_FRAME TrapFrame); 237 238 typedef 239 VOID 240 (FASTCALL *PFAST_SYSTEM_CALL_EXIT)( 241 IN PKTRAP_FRAME TrapFrame 242 ); 243 244 extern PFAST_SYSTEM_CALL_EXIT KiFastCallExitHandler; 245 246 // 247 // Save user mode debug registers and restore kernel values 248 // 249 FORCEINLINE 250 VOID 251 KiHandleDebugRegistersOnTrapEntry( 252 IN PKTRAP_FRAME TrapFrame) 253 { 254 PKPRCB Prcb = KeGetCurrentPrcb(); 255 256 /* Save all debug registers in the trap frame */ 257 TrapFrame->Dr0 = __readdr(0); 258 TrapFrame->Dr1 = __readdr(1); 259 TrapFrame->Dr2 = __readdr(2); 260 TrapFrame->Dr3 = __readdr(3); 261 TrapFrame->Dr6 = __readdr(6); 262 TrapFrame->Dr7 = __readdr(7); 263 264 /* Disable all active debugging */ 265 __writedr(7, 0); 266 267 /* Restore kernel values */ 268 __writedr(0, Prcb->ProcessorState.SpecialRegisters.KernelDr0); 269 __writedr(1, Prcb->ProcessorState.SpecialRegisters.KernelDr1); 270 __writedr(2, Prcb->ProcessorState.SpecialRegisters.KernelDr2); 271 __writedr(3, Prcb->ProcessorState.SpecialRegisters.KernelDr3); 272 __writedr(6, Prcb->ProcessorState.SpecialRegisters.KernelDr6); 273 __writedr(7, Prcb->ProcessorState.SpecialRegisters.KernelDr7); 274 } 275 276 FORCEINLINE 277 VOID 278 KiHandleDebugRegistersOnTrapExit( 279 PKTRAP_FRAME TrapFrame) 280 { 281 /* Disable all active debugging */ 282 __writedr(7, 0); 283 284 /* Load all debug registers from the trap frame */ 285 __writedr(0, TrapFrame->Dr0); 286 __writedr(1, TrapFrame->Dr1); 287 __writedr(2, TrapFrame->Dr2); 288 __writedr(3, TrapFrame->Dr3); 289 __writedr(6, TrapFrame->Dr6); 290 __writedr(7, TrapFrame->Dr7); 291 } 292 293 // 294 // Virtual 8086 Mode Optimized Trap Exit 295 // 296 FORCEINLINE 297 DECLSPEC_NORETURN 298 VOID 299 KiExitV86Trap(IN PKTRAP_FRAME TrapFrame) 300 { 301 PKTHREAD Thread; 302 KIRQL OldIrql; 303 304 /* Get the thread */ 305 Thread = KeGetCurrentThread(); 306 while (TRUE) 307 { 308 /* Return if this isn't V86 mode anymore */ 309 if (!(TrapFrame->EFlags & EFLAGS_V86_MASK)) KiEoiHelper(TrapFrame); 310 311 /* Turn off the alerted state for kernel mode */ 312 Thread->Alerted[KernelMode] = FALSE; 313 314 /* Are there pending user APCs? */ 315 if (__builtin_expect(!Thread->ApcState.UserApcPending, 1)) break; 316 317 /* Raise to APC level and enable interrupts */ 318 OldIrql = KfRaiseIrql(APC_LEVEL); 319 _enable(); 320 321 /* Deliver APCs */ 322 KiDeliverApc(UserMode, NULL, TrapFrame); 323 324 /* Restore IRQL and disable interrupts once again */ 325 KfLowerIrql(OldIrql); 326 _disable(); 327 } 328 329 /* If we got here, we're still in a valid V8086 context, so quit it */ 330 if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0)) 331 { 332 /* Restore debug registers from the trap frame */ 333 KiHandleDebugRegistersOnTrapExit(TrapFrame); 334 } 335 336 /* Return from interrupt */ 337 KiTrapReturnNoSegments(TrapFrame); 338 } 339 340 // 341 // Virtual 8086 Mode Optimized Trap Entry 342 // 343 FORCEINLINE 344 VOID 345 KiEnterV86Trap(IN PKTRAP_FRAME TrapFrame) 346 { 347 PVOID ExceptionList; 348 349 /* Check exception list */ 350 ExceptionList = KeGetPcr()->NtTib.ExceptionList; 351 ASSERTMSG("V86 trap handler must not register an SEH frame\n", 352 ExceptionList == TrapFrame->ExceptionList); 353 354 /* Save DR7 and check for debugging */ 355 TrapFrame->Dr7 = __readdr(7); 356 if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0)) 357 { 358 /* Handle debug registers */ 359 KiHandleDebugRegistersOnTrapEntry(TrapFrame); 360 } 361 } 362 363 // 364 // Interrupt Trap Entry 365 // 366 FORCEINLINE 367 VOID 368 KiEnterInterruptTrap(IN PKTRAP_FRAME TrapFrame) 369 { 370 PVOID ExceptionList; 371 372 /* Check exception list and terminate it */ 373 ExceptionList = KeGetPcr()->NtTib.ExceptionList; 374 ASSERTMSG("Interrupt handler must not register an SEH frame\n", 375 ExceptionList == TrapFrame->ExceptionList); 376 KeGetPcr()->NtTib.ExceptionList = EXCEPTION_CHAIN_END; 377 378 /* Default to debugging disabled */ 379 TrapFrame->Dr7 = 0; 380 381 /* Check if the frame was from user mode or v86 mode */ 382 if (KiUserTrap(TrapFrame) || 383 (TrapFrame->EFlags & EFLAGS_V86_MASK)) 384 { 385 /* Check for active debugging */ 386 if (KeGetCurrentThread()->Header.DebugActive & 0xFF) 387 { 388 /* Handle debug registers */ 389 KiHandleDebugRegistersOnTrapEntry(TrapFrame); 390 } 391 } 392 393 /* Set debug header */ 394 KiFillTrapFrameDebug(TrapFrame); 395 } 396 397 // 398 // Generic Trap Entry 399 // 400 FORCEINLINE 401 VOID 402 KiEnterTrap(IN PKTRAP_FRAME TrapFrame) 403 { 404 PVOID ExceptionList; 405 406 /* Check exception list */ 407 ExceptionList = KeGetPcr()->NtTib.ExceptionList; 408 ASSERTMSG("Trap handler must not register an SEH frame\n", 409 ExceptionList == TrapFrame->ExceptionList); 410 411 /* Default to debugging disabled */ 412 TrapFrame->Dr7 = 0; 413 414 /* Check if the frame was from user mode or v86 mode */ 415 if (KiUserTrap(TrapFrame) || 416 (TrapFrame->EFlags & EFLAGS_V86_MASK)) 417 { 418 /* Check for active debugging */ 419 if (KeGetCurrentThread()->Header.DebugActive & 0xFF) 420 { 421 /* Handle debug registers */ 422 KiHandleDebugRegistersOnTrapEntry(TrapFrame); 423 } 424 } 425 426 /* Set debug header */ 427 KiFillTrapFrameDebug(TrapFrame); 428 } 429