First cut at stack trace

This commit is contained in:
Eugene Myers 2018-12-07 11:34:59 -05:00
parent 69eb78f6c8
commit 2cdfe88c33
15 changed files with 117 additions and 13 deletions

Binary file not shown.

View File

@ -19,6 +19,13 @@ typedef struct {
CHAR8 *Str;
} DATA_STR;
extern UINTN
TranslateEPTGuestToHost (
IN UINT64 EptPointer,
IN UINTN Addr,
OUT EPT_ENTRY **EntryPtr OPTIONAL
);
GLOBAL_REMOVE_IF_UNREFERENCED
DATA_STR mVmxCapabilityMsrStr[] = {
{IA32_VMX_BASIC_MSR_INDEX, "VMX_BASIC_MSR "},
@ -503,4 +510,59 @@ DumpRegContext (
for (Index = 0; Index < sizeof(mX86RegisterStr)/sizeof(mX86RegisterStr[0]) / (sizeof(UINT64)/sizeof(UINTN)); Index++) {
DumpRegFiled (Reg, &mX86RegisterStr[Index]);
}
}
/**
This function dumps the guest stack.
@param Index - CPU Index
Assumes 1-1 mapping in the guest page tables between the
guest virtual address and the guest physical address
**/
VOID DumpGuestStack(IN UINT32 Index)
{
UINT32 VmType = mHostContextCommon.HostContextPerCpu[Index].GuestVmType;
UINT32 i;
UINT64 Location;
UINT64 RelLoc;
UINTN StackTop = (UINTN)VmReadN (VMCS_N_GUEST_RSP_INDEX);
UINTN StackLen;
UINT64 Stack[20]; // will limit output to at most the first 20 stack elements (64bit)
StackTop = TranslateEPTGuestToHost(mGuestContextCommonSmm[VmType].EptPointer.Uint64, StackTop, 0L);
// make sure that stack exists within the EPT tables
// otherwise print an error message
if(StackTop == 0)
{
DEBUG ((EFI_D_ERROR, "%ld DumpGuestStack - Stack registers have bad addresses\n", Index));
return;
}
StackLen = (((UINT64)StackTop + 0x1000) & (~0xFFF)) - (UINT64)StackTop;
if(StackLen > 160)
StackLen = 160; // max stackdump of 20 64-bit words
CopyMem (Stack, (VOID *)(UINTN)StackTop, StackLen);
DEBUG((EFI_D_ERROR, "%ld Stacktrace\n", Index));
Location = (UINT64)StackTop;
RelLoc = 0;
for(i = 0; RelLoc < StackLen; i++)
{
DEBUG ((EFI_D_INFO, "%ld: %016lx %016lx\n", Index, Location, Stack[i] ));
RelLoc =+ 8;
}
DEBUG((EFI_D_ERROR, "%ld End Stacktrace\n", Index));
}

View File

@ -41,18 +41,17 @@ InitPeGuestVmcs (
VM_EXEC_2ND_PROCESSOR_BASES_VMEXIT_CONTROLS ProcessorBasedCtrls2nd;
GUEST_INTERRUPTIBILITY_STATE GuestInterruptibilityState;
VM_EXIT_MSR_ENTRY *VmExitMsrEntry;
//UINT32 VmType;
//VmType = mHostContextCommon.HostContextPerCpu[CpuIndex].GuestVmType;
DEBUG((EFI_D_ERROR, "%ld InitPeGuestVmcs Starting - VmType: %d\n", CpuIndex, VmType));
// setup pin based controls
UINT32 ExceptionBitmap;
UINT32 PageFaultErrorCodeMask;
UINT32 PageFaultErrorCodeMatch;
Data64 = AsmReadMsr64 (IA32_VMX_PINBASED_CTLS_MSR_INDEX);
PinBasedCtls.Uint32 = (UINT32)(Data64 & 0xFFFFFFFF);
PinBasedCtls.Bits.ExternalInterrupt = 0; // external interrupt
PinBasedCtls.Bits.Nmi = 1; // NMI is used for the SMI case
PinBasedCtls.Bits.Nmi = 1; // NMI is used to allow for when an SMI occurs when one of the processors
// is running a VM/PE to allow the other processors to interrupt the VM/PE
// so that he SMI handler can process the SMI
PinBasedCtls.Bits.VmxPreemptionTimer = 1; // Timer (was zero)
// Processor based controls
@ -93,6 +92,10 @@ InitPeGuestVmcs (
GuestInterruptibilityState.Uint32 = 0;
GuestInterruptibilityState.Bits.BlockingBySmi = 1;
#define VMCS_32_CONTROL_EXCEPTION_BITMAP_INDEX 0x4004
#define VMCS_32_CONTROL_PAGE_FAULT_ERROR_CODE_MASK_INDEX 0x4006
#define VMCS_32_CONTROL_PAGE_FAULT_ERROR_CODE_MATCH_INDEX 0x4008
//
// Control field
//

View File

@ -151,6 +151,7 @@ ResumeToBiosExceptionHandler (
DEBUG ((EFI_D_ERROR, "VMCS_32_RO_VM_INSTRUCTION_ERROR: %08x\n", (UINTN)VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX)));
DumpVmcsAllField ();
DumpRegContext (Reg);
DumpGuestStack(Index);
ReleaseSpinLock (&mHostContextCommon.DebugLock);
CpuDeadLoop ();
return ;
@ -227,6 +228,7 @@ ReturnFromBiosExceptionHandler (
DEBUG ((EFI_D_ERROR, "VMCS_32_RO_VM_INSTRUCTION_ERROR: %08x\n", (UINTN)VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX)));
DumpVmcsAllField ();
DumpRegContext (Reg);
DumpGuestStack(Index);
ReleaseSpinLock (&mHostContextCommon.DebugLock);
CpuDeadLoop ();
return ;

View File

@ -254,7 +254,7 @@ void LaunchPeVm(UINT32 PeType, UINT32 CpuIndex)
DEBUG ((EFI_D_ERROR, "%ld LaunchPeVm - VMCS_32_RO_VM_INSTRUCTION_ERROR: %08x\n", (UINTN)VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX)));
DumpVmcsAllField ();
DumpRegContext (&mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register);
DumpGuestStack(CpuIndex);
ReleaseSpinLock (&mHostContextCommon.DebugLock);
}
@ -365,6 +365,7 @@ UINT32 PostPeVmProc(UINT32 rc, UINT32 CpuIndex, UINT32 mode)
DumpVmcsAllField(); // temp debug
DumpVmxCapabillityMsr();
DumpRegContext(&mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register);
DumpGuestStack(CpuIndex);
print_region_list(PeType, CpuIndex);
if((PERM_VM_CRASH_BREAKDOWN & PeVmData[PeType].UserModule.VmConfig) == PERM_VM_CRASH_BREAKDOWN)
@ -463,7 +464,6 @@ UINT32 PostPeVmProc(UINT32 rc, UINT32 CpuIndex, UINT32 mode)
VmWriteN (VMCS_N_GUEST_RSP_INDEX, (UINTN)mHostContextCommon.HostContextPerCpu[CpuIndex].TxtProcessorSmmDescriptor->SmmSmiHandlerRsp);
VmWriteN (VMCS_N_GUEST_CR3_INDEX, mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Cr3);
STM_PERF_START (CpuIndex, 0, "BiosSmmHandler", "SmiEventHandler");
if (mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Launched) {

View File

@ -173,7 +173,7 @@ VOID
DEBUG ((EFI_D_ERROR, "%ld PeStmHandlerSmm - VMCS_32_RO_VM_INSTRUCTION_ERROR: %08x\n", Index, (UINTN)VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX)));
DumpVmcsAllField ();
DumpRegContext (&mGuestContextCommonSmm[VmType].GuestContextPerCpu[pIndex].Register);
DumpGuestStack(Index);
ReleaseSpinLock (&mHostContextCommon.DebugLock);
DEBUG((EFI_D_ERROR, "%ld PeStmHandlerSmm - CpuDeadLoop\n", Index));
CpuDeadLoop ();

View File

@ -39,6 +39,8 @@ UINTN
extern VMCSFIELDOFFSET VmcsFieldOffsetTable[];
extern void MapVmcs ();
extern PE_VM_DATA PeVmData[4];
/**
This function is the STM_API_MAP_ADDRESS_RANGEVMCALL handler for SMM VM/PE.
@ -60,6 +62,20 @@ STM_STATUS
UINT32 VmType = mHostContextCommon.HostContextPerCpu[Index].GuestVmType;
UINTN PhysAddressParameter;
UINTN PhysAddressParameterEnd;
UINT64 GuestSmmEnd = PeVmData[VmType].UserModule.AddressSpaceStart + PeVmData[VmType].UserModule.AddressSpaceSize - 1;
// Make sure the parameter address is with the part of the guest that is within SMRAM
if((AddressParameter < PeVmData[VmType].UserModule.AddressSpaceStart)||
(AddressParameter > GuestSmmEnd) ||
((AddressParameter + sizeof(STM_MAP_ADDRESS_RANGE_DESCRIPTOR)) > GuestSmmEnd))
{
DEBUG ((EFI_D_ERROR, "%ld PeSmmVmcallMapAddressRangeHandler - Security Violation! - parameter block not in guest physical within SMRAM\n", Index));
DEBUG ((EFI_D_ERROR, "%ld PeSmmVmcallMapAddressRangeHandler - AddressParameter = 0x%016llx",
Index,
AddressParameter));
return ERROR_STM_SECURITY_VIOLATION;
}
PhysAddressParameter = TranslateEPTGuestToHost(mGuestContextCommonSmm[VmType].EptPointer.Uint64, (UINTN)AddressParameter, 0L);
PhysAddressParameterEnd = TranslateEPTGuestToHost(mGuestContextCommonSmm[VmType].EptPointer.Uint64, (UINTN)AddressParameter + sizeof(STM_MAP_ADDRESS_RANGE_DESCRIPTOR), 0L);
@ -69,7 +85,9 @@ STM_STATUS
if(((PhysAddressParameter == 0)||(PhysAddressParameterEnd == 0))||
((PhysAddressParameter & ~0xFFF) != (PhysAddressParameterEnd & ~0XFFF)))
{
// TODO - need to address the potential of having a parameter block split across tow oages
// TODO - need to address the potential of having a parameter block split across two pages
// currently the VM/PE is created as a single block...
DEBUG ((EFI_D_ERROR, "%ld PeSmmVmcallMapAddressRangeHandler - Security Violation! - parameter block not in guest physical address space or split across two pages\n", Index));
DEBUG ((EFI_D_ERROR, "%ld PeSmmVmcallMapAddressRangeHandler - PhysAddressParameter = 0x%016llx, PhysAddressParameterEnd = 0x%016llx\n",
Index,

View File

@ -107,6 +107,7 @@ SmiEventHandler (
DumpVmcsAllField ();
DumpRegContext (&mGuestContextCommonSmm[SMI_HANDLER].GuestContextPerCpu[Index].Register);
DumpGuestStack(Index);
ReleaseSpinLock (&mHostContextCommon.DebugLock);
CpuDeadLoop ();

View File

@ -164,7 +164,7 @@ VOID
DEBUG ((EFI_D_ERROR, "%ld StmHandlerSmi - VMCS_32_RO_VM_INSTRUCTION_ERROR: %08x\n", Index, (UINTN)VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX)));
DumpVmcsAllField ();
DumpRegContext (&mGuestContextCommonSmi.GuestContextPerCpu[Index].Register);
DumpGuestStack(Index);
ReleaseSpinLock (&mHostContextCommon.DebugLock);
CpuDeadLoop ();

View File

@ -67,6 +67,7 @@ UnknownHandlerSmm (
DEBUG ((EFI_D_ERROR, "!!!UnknownHandlerSmm - %d\n", (UINTN)Index));
DumpVmcsAllField ();
DumpRegContext(&mGuestContextCommonSmm[SMI_HANDLER].GuestContextPerCpu[Index].Register);
DumpGuestStack(Index);
{
UINT8 *Buffer;
@ -158,7 +159,7 @@ StmHandlerSmm (
DEBUG ((EFI_D_ERROR, "VMCS_32_RO_VM_INSTRUCTION_ERROR: %08x\n", (UINTN)VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX)));
DumpVmcsAllField ();
DumpRegContext (&mGuestContextCommonSmm[VmType].GuestContextPerCpu[pIndex].Register);
DumpGuestStack(Index);
ReleaseSpinLock (&mHostContextCommon.DebugLock);
CpuDeadLoop ();

View File

@ -138,6 +138,7 @@ VOID
DEBUG ((EFI_D_ERROR, "%ld RsmHandler VMCS_32_RO_VM_INSTRUCTION_ERROR: %08x\n", (UINTN)Index, (UINTN)VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX)));
DumpVmcsAllField ();
DumpRegContext (&mGuestContextCommonSmi.GuestContextPerCpu[Index].Register);
DumpGuestStack(Index);
ReleaseSpinLock (&mHostContextCommon.DebugLock);
CpuDeadLoop ();

View File

@ -72,6 +72,7 @@ SmmTeardown (
DEBUG ((EFI_D_ERROR, "VMCS_32_RO_VM_INSTRUCTION_ERROR: %08x\n", (UINTN)VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX)));
DumpVmcsAllField ();
DumpRegContext (&mGuestContextCommonSmm[VmType].GuestContextPerCpu[Index].Register);
DumpGuestStack(Index);
ReleaseSpinLock (&mHostContextCommon.DebugLock);
CpuDeadLoop ();
}

View File

@ -123,6 +123,7 @@ StmTeardown (
DEBUG ((EFI_D_ERROR, "VMCS_32_RO_VM_INSTRUCTION_ERROR: %08x\n", (UINTN)VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX)));
DumpVmcsAllField ();
DumpRegContext (Reg);
DumpGuestStack(Index);
ReleaseSpinLock (&mHostContextCommon.DebugLock);
#endif

View File

@ -166,6 +166,7 @@ ResumeToBiosExceptionHandler (
DEBUG ((EFI_D_ERROR, "VMCS_32_RO_VM_INSTRUCTION_ERROR: %08x\n", (UINTN)VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX)));
DumpVmcsAllField ();
DumpRegContext (Reg);
DumpGuestStack(Index);
ReleaseSpinLock (&mHostContextCommon.DebugLock);
CpuDeadLoop ();
return ;
@ -257,6 +258,7 @@ ReturnFromBiosExceptionHandler (
DEBUG ((EFI_D_ERROR, "VMCS_32_RO_VM_INSTRUCTION_ERROR: %08x\n", (UINTN)VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX)));
DumpVmcsAllField ();
DumpRegContext (Reg);
DumpGuestStack(Index);
ReleaseSpinLock (&mHostContextCommon.DebugLock);
CpuDeadLoop ();
return ;

View File

@ -651,6 +651,18 @@ DumpRegContext (
IN X86_REGISTER *Reg
);
/**
This function dumps the guest stack.
@param Index - CPU Index
**/
VOID
DumpGuestStack(
IN UINT32 Index
);
/**
Initialize external vector table pointer.