https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3c8f19eb2153034b9b47f…
commit 3c8f19eb2153034b9b47fc91284b54b1200f21d8
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Mon Feb 4 01:16:29 2019 +0100
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)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-comman…
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