https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3c8f19eb2153034b9b47fc...
commit 3c8f19eb2153034b9b47fc91284b54b1200f21d8 Author: Hermès Bélusca-Maïto hermes.belusca-maito@reactos.org AuthorDate: Mon Feb 4 01:16:29 2019 +0100 Commit: Hermès Bélusca-Maïto hermes.belusca-maito@reactos.org CommitDate: Thu Jun 20 19:38:56 2019 +0200
[NTOS:KE] Improvements for the Trap02 (NMI) and Trap08 (double-fault) exception handlers.
- Add FRAME_TSS FPO debug information for Trap02 and Trap08. - Switch the active TSS in Trap08 in the very same way as is done in Trap02.
This allows to correctly debug NMI and double-fault exceptions with WinDbg, by following the different TSS contexts, as described in: https://blogs.msdn.microsoft.com/debuggingtoolbox/2008/02/22/special-command... https://blogs.msdn.microsoft.com/ntdebugging/2009/11/25/part-1-got-stack-no-... http://www.osronline.com/article.cfm?article=254 and http://www.osronline.com/article.cfm?article=328 --- ntoskrnl/include/internal/i386/asmmacro.S | 16 ++++++++++ ntoskrnl/include/internal/i386/ke.h | 2 +- ntoskrnl/ke/i386/trap.s | 5 ++- ntoskrnl/ke/i386/traphdlr.c | 52 ++++++++++++++++++++++++++++--- 4 files changed, 66 insertions(+), 9 deletions(-)
diff --git a/ntoskrnl/include/internal/i386/asmmacro.S b/ntoskrnl/include/internal/i386/asmmacro.S index 6d2d213c3d..57f83b7ced 100644 --- a/ntoskrnl/include/internal/i386/asmmacro.S +++ b/ntoskrnl/include/internal/i386/asmmacro.S @@ -249,6 +249,22 @@ MACRO(TRAP_ENTRY, Trap, Flags) .ENDP ENDM
+MACRO(TASK_ENTRY, Trap, Flags) + // EXTERN @&Trap&Handler@0 :PROC + EXTERN _&Trap&Handler :PROC + PUBLIC _&Trap + .PROC _&Trap + /* Generate proper debugging symbols */ + FPO 0, 0, 0, 0, 0, FRAME_TSS + + // /* Common code to create the trap frame */ + // KiEnterTrap Flags + + /* Call the C handler */ + KiCallHandler _&Trap&Handler // @&Trap&Handler@0 + .ENDP +ENDM + #define KI_RESTORE_EAX HEX(0001) #define KI_RESTORE_ECX_EDX HEX(0002) #define KI_RESTORE_FS HEX(0004) diff --git a/ntoskrnl/include/internal/i386/ke.h b/ntoskrnl/include/internal/i386/ke.h index 10eb6eb1be..7ce491e291 100644 --- a/ntoskrnl/include/internal/i386/ke.h +++ b/ntoskrnl/include/internal/i386/ke.h @@ -575,7 +575,7 @@ extern ULONG KeI386CpuStep; extern ULONG KiFastSystemCallDisable; extern UCHAR KiDebugRegisterTrapOffsets[9]; extern UCHAR KiDebugRegisterContextOffsets[9]; -extern DECLSPEC_NORETURN VOID __cdecl KiTrap02(VOID); +extern VOID __cdecl KiTrap02(VOID); extern VOID __cdecl KiTrap08(VOID); extern VOID __cdecl KiTrap13(VOID); extern VOID __cdecl KiFastCallEntry(VOID); diff --git a/ntoskrnl/ke/i386/trap.s b/ntoskrnl/ke/i386/trap.s index 6bd57e8053..d70ff66404 100644 --- a/ntoskrnl/ke/i386/trap.s +++ b/ntoskrnl/ke/i386/trap.s @@ -27,8 +27,6 @@ _KiUnexpectedInterrupt&Vector: //.endfunc ENDM
-EXTERN _KiTrap02:PROC - /* GLOBALS *******************************************************************/
.data @@ -99,12 +97,13 @@ ENDR
TRAP_ENTRY KiTrap00, KI_PUSH_FAKE_ERROR_CODE TRAP_ENTRY KiTrap01, KI_PUSH_FAKE_ERROR_CODE +TASK_ENTRY KiTrap02, 0 TRAP_ENTRY KiTrap03, KI_PUSH_FAKE_ERROR_CODE TRAP_ENTRY KiTrap04, KI_PUSH_FAKE_ERROR_CODE TRAP_ENTRY KiTrap05, KI_PUSH_FAKE_ERROR_CODE TRAP_ENTRY KiTrap06, KI_PUSH_FAKE_ERROR_CODE TRAP_ENTRY KiTrap07, KI_PUSH_FAKE_ERROR_CODE -TRAP_ENTRY KiTrap08, 0 +TASK_ENTRY KiTrap08, 0 TRAP_ENTRY KiTrap09, KI_PUSH_FAKE_ERROR_CODE TRAP_ENTRY KiTrap0A, 0 TRAP_ENTRY KiTrap0B, 0 diff --git a/ntoskrnl/ke/i386/traphdlr.c b/ntoskrnl/ke/i386/traphdlr.c index 7cf1fcde37..863641bb68 100644 --- a/ntoskrnl/ke/i386/traphdlr.c +++ b/ntoskrnl/ke/i386/traphdlr.c @@ -458,7 +458,7 @@ KiTrap01Handler(IN PKTRAP_FRAME TrapFrame) DECLSPEC_NORETURN VOID __cdecl -KiTrap02(VOID) +KiTrap02Handler(VOID) { PKTSS Tss, NmiTss; PKTHREAD Thread; @@ -829,11 +829,53 @@ KiTrap07Handler(IN PKTRAP_FRAME TrapFrame)
DECLSPEC_NORETURN VOID -FASTCALL -KiTrap08Handler(IN PKTRAP_FRAME TrapFrame) +__cdecl +KiTrap08Handler(VOID) { - /* FIXME: Not handled */ - KiSystemFatalException(EXCEPTION_DOUBLE_FAULT, TrapFrame); + PKTSS Tss, DfTss; + PKTHREAD Thread; + PKPROCESS Process; + PKGDTENTRY TssGdt; + + /* For sanity's sake, make sure interrupts are disabled */ + _disable(); + + /* Get the current TSS, thread, and process */ + Tss = KeGetPcr()->TSS; + Thread = ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread; + Process = Thread->ApcState.Process; + + /* Save data usually not present in the TSS */ + Tss->CR3 = Process->DirectoryTableBase[0]; + Tss->IoMapBase = Process->IopmOffset; + Tss->LDT = Process->LdtDescriptor.LimitLow ? KGDT_LDT : 0; + + /* Now get the base address of the double-fault TSS */ + TssGdt = &((PKIPCR)KeGetPcr())->GDT[KGDT_DF_TSS / sizeof(KGDTENTRY)]; + DfTss = (PKTSS)(ULONG_PTR)(TssGdt->BaseLow | + TssGdt->HighWord.Bytes.BaseMid << 16 | + TssGdt->HighWord.Bytes.BaseHi << 24); + + /* + * Switch to it and activate it, masking off the nested flag. + * + * Note that in reality, we are already on the double-fault TSS + * -- we just need to update the PCR to reflect this. + */ + KeGetPcr()->TSS = DfTss; + __writeeflags(__readeflags() &~ EFLAGS_NESTED_TASK); + TssGdt->HighWord.Bits.Dpl = 0; + TssGdt->HighWord.Bits.Pres = 1; + // TssGdt->HighWord.Bits.Type &= ~0x2; /* I386_ACTIVE_TSS --> I386_TSS */ + TssGdt->HighWord.Bits.Type = I386_TSS; // Busy bit cleared in the TSS selector. + + /* Bugcheck the system */ + KeBugCheckWithTf(UNEXPECTED_KERNEL_MODE_TRAP, + EXCEPTION_DOUBLE_FAULT, + (ULONG_PTR)Tss, + 0, + 0, + NULL); }
DECLSPEC_NORETURN