[ASM/AMD64]

- Add multiple amd64 asm constant and structure offset definitions
- Add more unwind information to the amd64 trap entry code
- Add IRQL check, APC check and segment sanitize code to trap entry/exit

svn path=/trunk/; revision=55404
This commit is contained in:
Timo Kreuzer 2012-02-04 11:01:19 +00:00
parent 0fcb7d138d
commit de74279d5b
3 changed files with 133 additions and 57 deletions

View file

@ -16,6 +16,16 @@
#include <wdbgexts.h>
#include <kddll.h>
#ifdef _M_AMD64
enum
{
P1Home = 1 * sizeof(PVOID),
P2Home = 2 * sizeof(PVOID),
P3Home = 3 * sizeof(PVOID),
P4Home = 4 * sizeof(PVOID),
};
#endif
// FIXME: where to put this?
typedef struct _FIBER /* Field offsets: */
{ /* 32 bit 64 bit */

View file

@ -112,10 +112,10 @@ CONSTANT(EXCEPTION_NPX_ERROR),
CONSTANT(EXCEPTION_ALIGNMENT_CHECK),
HEADER("Argument Home Address"),
OFFSET(P1Home, CONTEXT, P1Home),
OFFSET(P2Home, CONTEXT, P1Home),
OFFSET(P3Home, CONTEXT, P1Home),
OFFSET(P4Home, CONTEXT, P1Home),
CONSTANT(P1Home),
CONSTANT(P2Home),
CONSTANT(P3Home),
CONSTANT(P4Home),
HEADER("CONTEXT"),
OFFSET(CONTEXT_P1Home, CONTEXT, P1Home),
@ -377,53 +377,55 @@ OFFSET(PcHalReserved, KPCR, HalReserved),
//OFFSET(PcNumber, KPCR, Number),
//OFFSET(PcInterruptRequest, KPCR, InterruptRequest),
//OFFSET(PcIdleHalt, KPCR, IdleHalt),
//OFFSET(PcCurrentThread, KPCR, CurrentThread),
OFFSET(PcCurrentThread, KIPCR, Prcb.CurrentThread),
//OFFSET(PcNextThread, KPCR, NextThread),
//OFFSET(PcIdleThread, KPCR, IdleThread),
//OFFSET(PcIpiFrozen, KPCR, IpiFrozen),
//OFFSET(PcNestingLevel, KPCR, NestingLevel),
//OFFSET(PcRspBase, KPCR, RspBase),
OFFSET(PcRspBase, KIPCR, Prcb.RspBase),
//OFFSET(PcPrcbLock, KPCR, PrcbLock),
OFFSET(PcSetMember, KIPCR, Prcb.SetMember),
#if 0
OFFSET(PcSetMember, KPCR, SetMember),
OFFSET(PcCr0, KPCR, Cr0),
OFFSET(PcCr2, KPCR, Cr2),
OFFSET(PcCr3, KPCR, Cr3),
OFFSET(PcCr4, KPCR, Cr4),
OFFSET(PcKernelDr0, KPCR, KernelDr0),
OFFSET(PcKernelDr1, KPCR, KernelDr1),
OFFSET(PcKernelDr2, KPCR, KernelDr2),
OFFSET(PcKernelDr3, KPCR, KernelDr3),
OFFSET(PcKernelDr7, KPCR, KernelDr7),
OFFSET(PcGdtrLimit, KPCR, GdtrLimit),
OFFSET(PcGdtrBase, KPCR, GdtrBase),
OFFSET(PcIdtrLimit, KPCR, IdtrLimit),
OFFSET(PcIdtrBase, KPCR, IdtrBase),
OFFSET(PcTr, KPCR, Tr),
OFFSET(PcLdtr, KPCR, Ldtr),
OFFSET(PcDebugControl, KPCR, DebugControl),
OFFSET(PcLastBranchToRip, KPCR, LastBranchToRip),
OFFSET(PcLastBranchFromRip, KPCR, LastBranchFromRip),
OFFSET(PcLastExceptionToRip, KPCR, LastExceptionToRip),
OFFSET(PcLastExceptionFromRip, KPCR, LastExceptionFromRip),
OFFSET(PcCr8, KPCR, Cr8),
OFFSET(PcCpuType, KPCR, CpuType),
OFFSET(PcCpuID, KPCR, CpuID),
OFFSET(PcCpuStep, KPCR, CpuStep),
OFFSET(PcCpuVendor, KPCR, CpuVendor),
OFFSET(PcVirtualApicAssist, KPCR, VirtualApicAssist),
OFFSET(PcCFlushSize, KPCR, CFlushSize),
OFFSET(PcDeferredReadyListHead, KPCR, DeferredReadyListHead),
OFFSET(PcSystemCalls, KPCR, SystemCalls),
OFFSET(PcDpcRoutineActive, KPCR, DpcRoutineActive),
OFFSET(PcInterruptCount, KPCR, InterruptCount),
OFFSET(PcDebuggerSavedIRQL, KPCR, DebuggerSavedIRQL),
OFFSET(PcTickOffset, KPCR, TickOffset),
OFFSET(PcMasterOffset, KPCR, MasterOffset),
OFFSET(PcSkipTick, KPCR, SkipTick),
OFFSET(PcStartCycles, KPCR, StartCycles),
SIZE(ProcessorControlRegisterLength, KPCR),
OFFSET(PcCr0, KIPCR, Prcb.Cr0),
OFFSET(PcCr2, KIPCR, Prcb.Cr2),
OFFSET(PcCr3, KIPCR, Prcb.Cr3),
OFFSET(PcCr4, KIPCR, Prcb.Cr4),
OFFSET(PcKernelDr0, KIPCR, Prcb.KernelDr0),
OFFSET(PcKernelDr1, KIPCR, Prcb.KernelDr1),
OFFSET(PcKernelDr2, KIPCR, Prcb.KernelDr2),
OFFSET(PcKernelDr3, KIPCR, Prcb.KernelDr3),
OFFSET(PcKernelDr7, KIPCR, Prcb.KernelDr7),
OFFSET(PcGdtrLimit, KIPCR, Prcb.GdtrLimit),
OFFSET(PcGdtrBase, KIPCR, Prcb.GdtrBase),
OFFSET(PcIdtrLimit, KIPCR, IdtrLimit),
OFFSET(PcIdtrBase, KIPCR, IdtrBase),
OFFSET(PcTr, KIPCR, Tr),
OFFSET(PcLdtr, KIPCR, Ldtr),
OFFSET(PcDebugControl, KIPCR, DebugControl),
OFFSET(PcLastBranchToRip, KIPCR, LastBranchToRip),
OFFSET(PcLastBranchFromRip, KIPCR, LastBranchFromRip),
OFFSET(PcLastExceptionToRip, KIPCR, LastExceptionToRip),
OFFSET(PcLastExceptionFromRip, KIPCR, LastExceptionFromRip),
OFFSET(PcCr8, KIPCR, Cr8),
#endif
OFFSET(PcCpuType, KIPCR, Prcb.CpuType),
OFFSET(PcCpuID, KIPCR, Prcb.CpuID),
OFFSET(PcCpuStep, KIPCR, Prcb.CpuStep),
OFFSET(PcCpuVendor, KIPCR, Prcb.CpuVendor),
OFFSET(PcCFlushSize, KIPCR, Prcb.CFlushSize),
OFFSET(PcDeferredReadyListHead, KIPCR, Prcb.DeferredReadyListHead),
OFFSET(PcSystemCalls, KIPCR, Prcb.KeSystemCalls),
OFFSET(PcDpcRoutineActive, KIPCR, Prcb.DpcRoutineActive),
OFFSET(PcInterruptCount, KIPCR, Prcb.InterruptCount),
OFFSET(PcDebuggerSavedIRQL, KIPCR, Prcb.DebuggerSavedIRQL),
OFFSET(PcTickOffset, KIPCR, Prcb.TickOffset),
OFFSET(PcMasterOffset, KIPCR, Prcb.MasterOffset),
OFFSET(PcSkipTick, KIPCR, Prcb.SkipTick),
#if (NTDDI_VERSION >= NTDDI_LONGHORN)
OFFSET(PcVirtualApicAssist, KIPCR, Prcb.VirtualApicAssist),
OFFSET(PcStartCycles, KIPCR, Prcb.StartCycles),
#endif
SIZE(ProcessorControlRegisterLength, KIPCR),
HEADER("KPROCESSOR_STATE"),
OFFSET(PsSpecialRegisters, KPROCESSOR_STATE, SpecialRegisters),
@ -578,4 +580,33 @@ OFFSET(EXCEPTION_RECORD_ExceptionAddress, EXCEPTION_RECORD, ExceptionAddress),
OFFSET(EXCEPTION_RECORD_NumberParameters, EXCEPTION_RECORD, NumberParameters),
OFFSET(EXCEPTION_RECORD_ExceptionInformation, EXCEPTION_RECORD, ExceptionInformation),
HEADER("KTHREAD"),
OFFSET(KTHREAD_WAIT_IRQL, KTHREAD, WaitIrql),
OFFSET(KTHREAD_TrapFrame, KTHREAD, TrapFrame),
OFFSET(KTHREAD_PreviousMode, KTHREAD, PreviousMode),
OFFSET(KTHREAD_KernelStack, KTHREAD, KernelStack),
OFFSET(KTHREAD_UserApcPending, KTHREAD, ApcState.UserApcPending),
HEADER("KINTERRUPT"),
OFFSET(KINTERRUPT_Type, KINTERRUPT, Type),
OFFSET(KINTERRUPT_Size, KINTERRUPT, Size),
OFFSET(KINTERRUPT_InterruptListEntry, KINTERRUPT, InterruptListEntry),
OFFSET(KINTERRUPT_ServiceRoutine, KINTERRUPT, ServiceRoutine),
OFFSET(KINTERRUPT_ServiceContext, KINTERRUPT, ServiceContext),
OFFSET(KINTERRUPT_SpinLock, KINTERRUPT, SpinLock),
OFFSET(KINTERRUPT_TickCount, KINTERRUPT, TickCount),
OFFSET(KINTERRUPT_ActualLock, KINTERRUPT, ActualLock),
OFFSET(KINTERRUPT_DispatchAddress, KINTERRUPT, DispatchAddress),
OFFSET(KINTERRUPT_Vector, KINTERRUPT, Vector),
OFFSET(KINTERRUPT_Irql, KINTERRUPT, Irql),
OFFSET(KINTERRUPT_SynchronizeIrql, KINTERRUPT, SynchronizeIrql),
OFFSET(KINTERRUPT_FloatingSave, KINTERRUPT, FloatingSave),
OFFSET(KINTERRUPT_Connected, KINTERRUPT, Connected),
OFFSET(KINTERRUPT_Number, KINTERRUPT, Number),
OFFSET(KINTERRUPT_ShareVector, KINTERRUPT, ShareVector),
OFFSET(KINTERRUPT_Mode, KINTERRUPT, Mode),
OFFSET(KINTERRUPT_ServiceCount, KINTERRUPT, ServiceCount),
OFFSET(KINTERRUPT_DispatchCount, KINTERRUPT, DispatchCount),
OFFSET(KINTERRUPT_TrapFrame, KINTERRUPT, TrapFrame),
OFFSET(KINTERRUPT_DispatchCode, KINTERRUPT, DispatchCode),

View file

@ -11,6 +11,7 @@ TF_SAVE_ALL = (TF_VOLATILES OR TF_NONVOLATILES OR TF_XMM OR TF_SEGME
TF_HAS_ERROR_CODE = HEX(40)
TF_SEND_EOI = HEX(80)
//TF_SYSTEMSERVICE = (TRAPFLAG_VOLATILES or TRAPFLAG_DEBUG)
TF_CHECKUSERAPC = HEX(100)
/*
* Stack Layout:
@ -28,7 +29,7 @@ TF_SEND_EOI = HEX(80)
* EnterTrap - Allocate KTRAP_FRAME_LENGTH and save registers to it
*/
MACRO(EnterTrap, Flags)
LOCAL dont_swap
LOCAL kernel_mode_entry
/* Save the trap flags for this trap */
CurrentTrapFlags = VAL(Flags)
@ -45,22 +46,29 @@ MACRO(EnterTrap, Flags)
/* Make room for a KTRAP_FRAME */
sub rsp, (KTRAP_FRAME_LENGTH - SIZE_INITIAL_FRAME)
.allocstack (KTRAP_FRAME_LENGTH - SIZE_INITIAL_FRAME)
.endprolog
/* Save rbp and rax */
mov [rsp + KTRAP_FRAME_Rbp], rbp
.savereg rbp, KTRAP_FRAME_Rbp
mov [rsp + KTRAP_FRAME_Rax], rax
.savereg rax, KTRAP_FRAME_Rax
/* Point rbp to the KTRAP_FRAME */
lea rbp, [rsp]
.setframe rbp, 0
if (Flags AND TF_NONVOLATILES)
/* Save non-volatile registers */
mov [rbp + KTRAP_FRAME_Rbx], rbx
.savereg rbx, KTRAP_FRAME_Rbx
mov [rbp + KTRAP_FRAME_Rdi], rdi
.savereg rdi, KTRAP_FRAME_Rdi
mov [rbp + KTRAP_FRAME_Rsi], rsi
.savereg rsi, KTRAP_FRAME_Rsi
endif
.endprolog
if (Flags AND TF_VOLATILES)
/* Save volatile registers */
mov [rbp + KTRAP_FRAME_Rcx], rcx
@ -89,19 +97,25 @@ MACRO(EnterTrap, Flags)
mov [rbp + KTRAP_FRAME_SegGs], gs
endif
/* Save previous mode and swap gs when it was UserMode */
/* Save previous mode and check if it was user mode */
mov ax, [rbp + KTRAP_FRAME_SegCs]
and al, 1
mov [rbp + KTRAP_FRAME_PreviousMode], al
jz dont_swap
swapgs
dont_swap:
jz kernel_mode_entry
if (Flags AND TF_IRQL)
/* Set sane segments */
mov ax, (KGDT64_R3_DATA or RPL_MASK)
mov ds, ax
mov es, ax
swapgs
kernel_mode_entry:
// if (Flags AND TF_IRQL)
/* Save previous irql */
mov rax, cr8
mov [rbp + KTRAP_FRAME_PreviousIrql], al
endif
// endif
if (Flags AND TF_DEBUG)
/* Save debug registers */
@ -127,7 +141,16 @@ ENDM
* ExitTrap - Restore registers and free stack space
*/
MACRO(ExitTrap, Flags)
LOCAL dont_swap_back
LOCAL kernel_mode_return
#if DBG
/* Check previous irql */
mov rax, cr8
cmp [rbp + KTRAP_FRAME_PreviousIrql], al
je .irql_ok
int 3
.irql_ok:
#endif
if (Flags AND TF_SEGMENTS)
/* Restore segment selectors */
@ -142,10 +165,22 @@ MACRO(ExitTrap, Flags)
mov cr8, rax
endif
test byte ptr [rbp + KTRAP_FRAME_PreviousMode], 1
jz dont_swap_back
/* Check if we came from user mode */
test byte ptr [rbp + KTRAP_FRAME_SegCs], 1
jz kernel_mode_return
if (Flags AND TF_CHECKUSERAPC)
/* Load current thread into r10 */
mov r10, gs:[PcCurrentThread]
cmp byte ptr [r10 + KTHREAD_UserApcPending], 0
jne KiExitToUserApc
endif
/* Swap gs to user mode */
swapgs
dont_swap_back:
kernel_mode_return:
if (Flags AND TF_NONVOLATILES)
/* Restore non-volatile registers */
@ -204,6 +239,6 @@ MACRO(TRAP_ENTRY, Trap, Flags)
/* Leave */
ExitTrap Flags
ENDFUNC &Trap
ENDFUNC
ENDM