mirror of
https://github.com/reactos/reactos.git
synced 2025-07-24 14:23:41 +00:00
NMI Support Patch 10:
[NTOS]: Write barebones NMI Trap handler which does a TSS context switch to the NMI TSS and then calls the HAL NMI handler. [NTOS]: Implement KiSaveProcessorState for doing a PRCB context save/restore. You should now be able to test the new NMI functionality by either building the circuit referenced in my e-mail and attaching it to your PCI bus, or by using "nmi 0" in the QEMU stdio console. svn path=/trunk/; revision=44871
This commit is contained in:
parent
b1e02d2174
commit
0926ed6652
2 changed files with 152 additions and 2 deletions
|
@ -924,6 +924,26 @@ KeZeroPages(IN PVOID Address,
|
|||
RtlZeroMemory(Address, Size);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KiSaveProcessorState(IN PKTRAP_FRAME TrapFrame,
|
||||
IN PKEXCEPTION_FRAME ExceptionFrame)
|
||||
{
|
||||
PKPRCB Prcb = KeGetCurrentPrcb();
|
||||
|
||||
//
|
||||
// Save full context
|
||||
//
|
||||
Prcb->ProcessorState.ContextFrame.ContextFlags = CONTEXT_FULL |
|
||||
CONTEXT_DEBUG_REGISTERS;
|
||||
KeTrapFrameToContext(TrapFrame, NULL, &Prcb->ProcessorState.ContextFrame);
|
||||
|
||||
//
|
||||
// Save control registers
|
||||
//
|
||||
KiSaveProcessorControlState(&Prcb->ProcessorState);
|
||||
}
|
||||
|
||||
/* PUBLIC FUNCTIONS **********************************************************/
|
||||
|
||||
/*
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <asm.h>
|
||||
#include <internal/i386/asmmacro.S>
|
||||
#include <internal/i386/callconv.s>
|
||||
.intel_syntax noprefix
|
||||
|
||||
#define Running 2
|
||||
|
@ -790,9 +791,138 @@ V86Int1:
|
|||
.globl _KiTrap2
|
||||
.func KiTrap2
|
||||
_KiTrap2:
|
||||
//
|
||||
// Don't allow any other NMIs to come in for now
|
||||
//
|
||||
cli // Disable interrupts
|
||||
|
||||
/* FIXME: This is an NMI, nothing like a normal exception */
|
||||
mov eax, 2
|
||||
//
|
||||
// Save current state data in registers
|
||||
//
|
||||
mov eax, PCR[KPCR_TSS] // Save KTSS
|
||||
mov ecx, PCR[KPCR_CURRENT_THREAD] // Save ETHREAD
|
||||
mov edi, [ecx+KTHREAD_APCSTATE_PROCESS] // Save EPROCESS
|
||||
|
||||
//
|
||||
// Migrate state data to TSS
|
||||
//
|
||||
mov ecx, [edi+KPROCESS_DIRECTORY_TABLE_BASE] // Page Directory Table
|
||||
mov [eax+KTSS_CR3], ecx // Saved in CR3
|
||||
mov cx, [edi+KPROCESS_IOPM_OFFSET] // IOPM Offset
|
||||
mov [eax+KTSS_IOMAPBASE], cx // Saved in IOPM Base
|
||||
mov ecx, [edi+KPROCESS_LDT_DESCRIPTOR0] // Get LDT descriptor
|
||||
test ecx, ecx // Check if ne
|
||||
jz 1f // Doesn't exist
|
||||
mov cx, KGDT_LDT // Load LDT descriptor
|
||||
1:
|
||||
mov [eax+KTSS_LDT], cx // Saved in LDT
|
||||
|
||||
//
|
||||
// Migrate to NMI TSS
|
||||
//
|
||||
push PCR[KPCR_TSS] // Save current TSS
|
||||
mov eax, PCR[KPCR_GDT] // Get GDT
|
||||
mov ch, [eax+KGDT_NMI_TSS+KGDT_BASE_HI] // Get High KTSS Base
|
||||
mov cl, [eax+KGDT_NMI_TSS+KGDT_BASE_MID] // Get Mid KTSS Base
|
||||
shl ecx, 16 // Build Top KTSS Base
|
||||
mov cx, [eax+KGDT_NMI_TSS+KGDT_BASE_LOW] // Add Low KTSS Base
|
||||
mov PCR[KPCR_TSS], ecx
|
||||
|
||||
//
|
||||
// Clear nested flag and activate the NMI TSS
|
||||
//
|
||||
pushf // Get EFLAGS
|
||||
and dword ptr [esp], ~EFLAGS_NESTED_TASK // Clear nested task
|
||||
popf // Set EFLAGS
|
||||
mov ecx, PCR[KPCR_GDT] // Get GDT
|
||||
lea eax, [ecx+KGDT_NMI_TSS] // Get NMI TSS
|
||||
mov byte ptr [eax+5], 0x89 // DPL 0, Present, NonBusy
|
||||
|
||||
//
|
||||
// Build the trap frame and save it into the KPRCB
|
||||
//
|
||||
mov eax, [esp] // KGDT_TSS from earlier
|
||||
push 0 // V86 segments
|
||||
push 0 // V86 segments
|
||||
push 0 // V86 segments
|
||||
push 0 // V86 segments
|
||||
push [eax+KTSS_SS] // TSS fields -> Trap Frame
|
||||
push [eax+KTSS_ESP] // TSS fields -> Trap Frame
|
||||
push [eax+KTSS_EFLAGS] // TSS fields -> Trap Frame
|
||||
push [eax+KTSS_CS] // TSS fields -> Trap Frame
|
||||
push [eax+KTSS_EIP] // TSS fields -> Trap Frame
|
||||
push 0 // Error Code
|
||||
push [eax+KTSS_EBP] // TSS fields -> Trap Frame
|
||||
push [eax+KTSS_EBX] // TSS fields -> Trap Frame
|
||||
push [eax+KTSS_ESI] // TSS fields -> Trap Frame
|
||||
push [eax+KTSS_EDI] // TSS fields -> Trap Frame
|
||||
push [eax+KTSS_FS] // TSS fields -> Trap Frame
|
||||
push PCR[KPCR_EXCEPTION_LIST] // SEH Handler from KPCR
|
||||
push -1 // Bogus previous mode
|
||||
push [eax+KTSS_EAX] // TSS fields -> Trap Frame
|
||||
push [eax+KTSS_ECX] // TSS fields -> Trap Frame
|
||||
push [eax+KTSS_EDX] // TSS fields -> Trap Frame
|
||||
push [eax+KTSS_DS] // TSS fields -> Trap Frame
|
||||
push [eax+KTSS_ES] // TSS fields -> Trap Frame
|
||||
push [eax+KTSS_GS] // TSS fields -> Trap Frame
|
||||
push 0 // Debug registers
|
||||
push 0 // Debug registers
|
||||
push 0 // Debug registers
|
||||
push 0 // Debug registers
|
||||
push 0 // Debug registers
|
||||
push 0 // Debug registers
|
||||
push 0 // Temp
|
||||
push 0 // Temp
|
||||
push 0 // Debug Pointer
|
||||
push 0 // Debug Marker
|
||||
push [eax+KTSS_EIP] // Debug EIP
|
||||
push [eax+KTSS_EBP] // Debug EBP
|
||||
mov ebp, esp // Set trap frame address
|
||||
stdCall _KiSaveProcessorState, ebp, 0 // Save to KPRCB CONTEXT
|
||||
|
||||
//
|
||||
// BUGBUG: Call Registered NMI handlers
|
||||
//
|
||||
|
||||
//
|
||||
// Call the platform driver for NMI handling (panic, etc)
|
||||
// Do this with IRQL at HIGH
|
||||
//
|
||||
push PCR[KPCR_IRQL] // Save real IRQL
|
||||
mov dword ptr PCR[KPCR_IRQL], HIGH_LEVEL // Force HIGH
|
||||
stdCall _HalHandleNMI, 0 // Call the HAL
|
||||
pop PCR[KPCR_IRQL] // Restore real IRQL
|
||||
|
||||
//
|
||||
// In certain situations, nested NMIs can corrupt the TSS, making us lose
|
||||
// the original context. If this happens, we have no choice but to panic.
|
||||
//
|
||||
mov eax, PCR[KPCR_TSS] // Get current TSS
|
||||
cmp word ptr [eax], KGDT_NMI_TSS // Check who its points to
|
||||
je 2f // Back to the NMI TSS crash
|
||||
|
||||
//
|
||||
// Otherwise, recover the original state
|
||||
//
|
||||
add esp, KTRAP_FRAME_LENGTH // Clear the trap frame
|
||||
pop PCR[KPCR_TSS] // Restore original TSS
|
||||
mov ecx, PCR[KPCR_GDT] // Get GDT
|
||||
lea eax, [ecx+KGDT_TSS] // Get KTSS
|
||||
mov byte ptr [eax+5], 0x8B // DPL 0, Present, Busy
|
||||
pushf // Get EFLAGS
|
||||
or dword ptr [esp], EFLAGS_NESTED_TASK // Set nested flags
|
||||
popf // Set EFLAGS
|
||||
|
||||
//
|
||||
// Return from NMI
|
||||
//
|
||||
iretd // Interrupt return
|
||||
jmp _KiTrap2 // Handle recursion
|
||||
2:
|
||||
//
|
||||
// Crash the system
|
||||
//
|
||||
mov eax, EXCEPTION_NMI
|
||||
jmp _KiSystemFatalException
|
||||
.endfunc
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue