Merge branch 'multiSmi' into stmpe-unstable

This commit is contained in:
Eugene D Myers 2020-05-05 18:47:16 -04:00
commit 6d2d68bc37
6 changed files with 399 additions and 211 deletions

View File

@ -36,7 +36,6 @@ static int CpuGetState = 0;
void SetEndOfSmi(void);
void StartTimer(void);
void StopTimer(void);
int CheckTimerSTS(UINT32 Index);
void ClearTimerSTS(void);
void SetMaxSwTimerInt(void);
void SetMinSwTimerInt(void);
@ -109,9 +108,12 @@ void LaunchPeVm(UINT32 PeType, UINT32 CpuIndex)
// load the shared page and region list addresses into the register save area
// so that the PE module will access to those addresses
mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register.Rbx = (UINTN)PeVmData[PeType].UserModule.SharedPage;
mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register.Rcx = (UINT64)PeVmData[PeType].UserModule.Segment;
mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register.Rdx = (UINTN) PeVmData[PeType].UserModule.SharedStmPage;
mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register.Rbx =
(UINTN)PeVmData[PeType].UserModule.SharedPage;
mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register.Rcx =
(UINT64)PeVmData[PeType].UserModule.Segment;
mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register.Rdx =
(UINTN) PeVmData[PeType].UserModule.SharedStmPage;
// check and make aure that the heap is cleared as requested
@ -143,12 +145,16 @@ void LaunchPeVm(UINT32 PeType, UINT32 CpuIndex)
}
}
// setup the variables that are used in case an SMI is taken while the PE VM is running
// setup the variables that are used in case an SMI is taken
// while the PE VM is running
// this needs to be fixed if more than one PE/VM is running
PeSmiControl.PeNmiBreak = 1; // when 1, a NMI has been sent to break the thread in PE_APIC_id
PeSmiControl.PeApicId = ReadLocalApicId (); // APIC id of the thread that is executing the PE V<
// when 1, a NMI has been sent to break the thread in PE_APIC_id
PeSmiControl.PeNmiBreak = 1;
// APIC id of the thread that is executing the PE V<
PeSmiControl.PeApicId = ReadLocalApicId ();
PeSmiControl.PeCpuIndex = CpuIndex;
PeSmiControl.PeExec = 0; // when 1 PE_APIC_ID is executing a
VmPeReady = 0; // set the ready gate
@ -158,7 +164,8 @@ void LaunchPeVm(UINT32 PeType, UINT32 CpuIndex)
CpuIndex,
PeSmiControl.PeSmiState));
if(InterlockedCompareExchange32(&PeSmiControl.PeSmiState, PESMIHSMI, PESMIHSMI) == PESMIHSMI) // try to set the NMI
if(InterlockedCompareExchange32(&PeSmiControl.PeSmiState, PESMIHSMI, PESMIHSMI) ==
PESMIHSMI) // try to set the NMI
{
// if we know that the SMI handler is already active, then don't continue
// save the state, process the SMI, then start the VM/PE afterwards
@ -206,11 +213,11 @@ void LaunchPeVm(UINT32 PeType, UINT32 CpuIndex)
mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register.Rcx,
mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register.Rdx));
//SetMinSwTimerInt();
PeVmData[PeType].UserModule.RunCount++;
// set the runcount into the STM shared page
*((UINT64 *)(PeVmData[PeType].SharedPageStm + sizeof(UINT64))) = PeVmData[PeType].UserModule.RunCount;
*((UINT64 *)(PeVmData[PeType].SharedPageStm + sizeof(UINT64))) =
PeVmData[PeType].UserModule.RunCount;
DEBUG((EFI_D_INFO,
"%ld LaunchPeVM - Initiating PE/VM run number: %d\n",
@ -223,21 +230,25 @@ void LaunchPeVm(UINT32 PeType, UINT32 CpuIndex)
*((UINT64 *)(PeVmData[PeType].SharedPageStm)),
*((UINT64 *)(PeVmData[PeType].SharedPageStm + sizeof(UINT64)))));
mHostContextCommon.HostContextPerCpu[CpuIndex].GuestVmType = PeType; // Make sure we take the correct path upon RSM
// Make sure we take the correct path upon RSM
mHostContextCommon.HostContextPerCpu[CpuIndex].GuestVmType = PeType;
StartPeTimeStamp = AsmReadTsc(); // set start time
AsmWbinvd ();
DEBUG((EFI_D_INFO,
"%ld LaunchPeVm - ***Debug*** VmPE ready for launch PeType %d registers-address: 0x%016llx\n",
"%ld LaunchPeVm - VmPE ready for launch PeType %d registers-address: 0x%016llx\n",
CpuIndex,
PeType,
&mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register ));
// need to check to see if an SMI happend during this period
// first incidcate that the VM/PE is ready for launch
VmPeReady = 1; // this will cause the interrupt handler to save the VM/PE and launch the VM/PE once the SMI is handled
// this will cause the interrupt handler to save the VM/PE and
// launch the VM/PE once the SMI is handled
VmPeReady = 1;
if(InterlockedCompareExchange32(&PeSmiControl.PeSmiState, PESMINULL, PESMIPNMI) == PESMIHSMI) //old PESMIPNMI, PESMIPNMI
{
@ -259,7 +270,9 @@ void LaunchPeVm(UINT32 PeType, UINT32 CpuIndex)
CpuIndex));
}
if(NMIReceived > 1) // check to see if we received an NMI during the build proceess - if so, handle the SMI then launch
// check to see if we received an NMI during the build proceess -
// if so, handle the SMI then launch
if(NMIReceived > 1)
{
DEBUG((EFI_D_INFO,
"%ld LaunchPeVM - NMI detected during build - delaying launch to handle SMI\n",
@ -283,8 +296,13 @@ void LaunchPeVm(UINT32 PeType, UINT32 CpuIndex)
Rflags = AsmVmLaunch (&mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register);
DEBUG ((EFI_D_ERROR, "%ld LaunchPeVm - (STM):o(\n", (UINTN)CpuIndex));
DEBUG ((EFI_D_ERROR, "%ld LaunchPeVm - !!!LaunchGuestSmm fail for PeVm!!!\n", (UINTN)CpuIndex));
DEBUG ((EFI_D_ERROR, "%ld LaunchPeVm - Rflags: (UINTN)CpuIndex, %08llx\n", (UINTN)CpuIndex, Rflags));
DEBUG ((EFI_D_ERROR,
"%ld LaunchPeVm - !!!LaunchGuestSmm fail for PeVm!!!\n",
CpuIndex));
DEBUG ((EFI_D_ERROR,
"%ld LaunchPeVm - Rflags: (UINTN)CpuIndex, %08llx\n",
CpuIndex,
Rflags));
DEBUG ((EFI_D_ERROR, "%ld LaunchPeVm - VMCS_32_RO_VM_INSTRUCTION_ERROR: %08x\n",
(UINTN)CpuIndex,
(UINTN)VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX)));
@ -308,7 +326,8 @@ void LaunchPeVm(UINT32 PeType, UINT32 CpuIndex)
(UINTN) CpuIndex,
(UINTN)VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX)));
DumpVmcsAllField (CpuIndex);
DumpRegContext (&mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register, CpuIndex);
DumpRegContext (&mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register,
CpuIndex);
ReleaseSpinLock (&mHostContextCommon.DebugLock);
}
@ -326,7 +345,8 @@ STM_STATUS RunPermVM(UINT32 CpuIndex)
"%ld RunPermVM entered\n",
CpuIndex));
if(PeVmData[PeType].PeVmState != PE_VM_IDLE )
if((PeVmData[PeType].PeVmState != PE_VM_IDLE) &&
(PeVmData[PeType].PeVmState != PE_VM_WAIT_START))
{
DEBUG((EFI_D_ERROR,
"%ld RunPermVM - Can not run a Perm PE/VM\n",
@ -363,7 +383,10 @@ STM_STATUS RunPermVM(UINT32 CpuIndex)
// setup the return
rc = SetupProtExecVm(CpuIndex, PeVmData[PE_PERM].UserModule.VmConfig, RESTART_VM, PeType); // can only restart PERM_VM
rc = SetupProtExecVm(CpuIndex,
PeVmData[PE_PERM].UserModule.VmConfig,
RESTART_VM,
PeType); // can only restart PERM_VM
if(rc != PE_SUCCESS) // did we have a problem
{
@ -422,7 +445,9 @@ UINT32 PostPeVmProc(UINT32 rc, UINT32 CpuIndex, UINT32 mode)
TotalPeTime,
TotalScaleTime));
switch (rc) // dump guest state upon bad return (eventually place in shared area)
// Dump guest state upon bad return (eventually place in shared area)
switch (rc)
{
case PE_VM_ATTEMPTED_VMCALL:
case PE_VMLAUNCH_ERROR:
@ -438,10 +463,12 @@ UINT32 PostPeVmProc(UINT32 rc, UINT32 CpuIndex, UINT32 mode)
case PE_VM_EXCEPTION:
DumpVmcsAllField(CpuIndex); // temp debug
DumpVmxCapabillityMsr(CpuIndex);
DumpRegContext(&mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register, CpuIndex);
DumpRegContext(&mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register,
CpuIndex);
print_region_list(PeType, CpuIndex);
if((PERM_VM_CRASH_BREAKDOWN & PeVmData[PeType].UserModule.VmConfig) == PERM_VM_CRASH_BREAKDOWN)
if((PERM_VM_CRASH_BREAKDOWN & PeVmData[PeType].UserModule.VmConfig) ==
PERM_VM_CRASH_BREAKDOWN)
{
// user wants perm vm released after crash
mode = RELEASE_VM;
@ -471,24 +498,29 @@ UINT32 PostPeVmProc(UINT32 rc, UINT32 CpuIndex, UINT32 mode)
if(mode == PRESERVE_VM)
{
if((PERM_VM_RUN_ONCE & PeVmData[PeType].UserModule.VmConfig) == PERM_VM_RUN_ONCE)
if((PERM_VM_RUN_ONCE & PeVmData[PeType].UserModule.VmConfig) ==
PERM_VM_RUN_ONCE)
{
// user wants perm vm released after crash
mode = RELEASE_VM;
DEBUG((EFI_D_INFO,
DEBUG ((EFI_D_INFO,
"%ld PostPeVmProc - Perm VM configured to run only once\n",
CpuIndex));
PeSmiControl.PeCpuIndex = -1; // indicate none functioning at this momemnet
// indicate none functioning at this momemnet
PeSmiControl.PeCpuIndex = -1;
}
else
{
if((PERM_VM_RUN_PERIODIC & PeVmData[PeType].UserModule.VmConfig) == PERM_VM_RUN_PERIODIC)
if((PERM_VM_RUN_PERIODIC & PeVmData[PeType].UserModule.VmConfig) ==
PERM_VM_RUN_PERIODIC)
{
// the PE/VM is running in periodic mode
DEBUG((EFI_D_INFO,
"%ld PostPeVmProc - Perm VM being setup for Timer interrupt\n",
CpuIndex));
PeSmiControl.PeCpuIndex = CpuIndex;
//
PeSmiControl.PeWaitTimer = 1;
PeVmData[PeType].PeVmState = PE_VM_IDLE;
@ -513,8 +545,10 @@ UINT32 PostPeVmProc(UINT32 rc, UINT32 CpuIndex, UINT32 mode)
CpuIndex,
PeType));
// we will fake a return to the MLE - that will cause the pending SMI to fire allowing
// the smiEvent handler to process is and release all the processor threads
// we will fake a return to the MLE -
// that will cause the pending SMI to fire allowing
// the smiEvent handler to process it and release all
// he processor threads
// to handle the SMI
AsmVmPtrLoad(&mGuestContextCommonSmi.GuestContextPerCpu[CpuIndex].Vmcs);
@ -531,7 +565,8 @@ UINT32 PostPeVmProc(UINT32 rc, UINT32 CpuIndex, UINT32 mode)
if (mGuestContextCommonSmi.GuestContextPerCpu[CpuIndex].Launched) {
Rflags = AsmVmResume (&mGuestContextCommonSmi.GuestContextPerCpu[CpuIndex].Register);
// BUGBUG: - AsmVmLaunch if AsmVmResume fail
if (VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX) == VmxFailErrorVmResumeWithNonLaunchedVmcs) {
if (VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX) ==
VmxFailErrorVmResumeWithNonLaunchedVmcs) {
// DEBUG ((EFI_D_ERROR, "(STM):-(\n", (UINTN)Index));
Rflags = AsmVmLaunch (&mGuestContextCommonSmi.GuestContextPerCpu[CpuIndex].Register);
}
@ -563,7 +598,6 @@ UINT32 PostPeVmProc(UINT32 rc, UINT32 CpuIndex, UINT32 mode)
VmRead32 (VMCS_32_RO_VMEXIT_INSTRUCTION_LENGTH_INDEX));
}
}
//DEBUG((EFI_D_INFO, "%ld PostPeVmProc - guest return address is %p\n", CpuIndex, VmReadN(VMCS_N_GUEST_RIP_INDEX)));
// clear out the page table list
if(mode == RELEASE_VM)
{
@ -572,9 +606,6 @@ UINT32 PostPeVmProc(UINT32 rc, UINT32 CpuIndex, UINT32 mode)
// so that in production someone cannot take advantange of this case
PeVmData[PeType].PeVmState = PE_VM_AVAIL; // not there anymore
PeSmiControl.PeCpuIndex = -1; // indicate none functioning at this momemnet
//keep the old vmcs around - think about clearing...
//FreePages((UINTN *)mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Vmcs, 2);
//mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Vmcs = 0L; // not there any more
DEBUG((EFI_D_INFO,
"%ld PostPeVmProc - PE/VM Free (AVAIL) - PeType: %ld\n",
CpuIndex,
@ -600,23 +631,24 @@ UINT32 PostPeVmProc(UINT32 rc, UINT32 CpuIndex, UINT32 mode)
WriteUnaligned32 ((UINT32 *)&Reg->Rax, rc);
if (rc == PE_SUCCESS)
{
VmWriteN (VMCS_N_GUEST_RFLAGS_INDEX, VmReadN(VMCS_N_GUEST_RFLAGS_INDEX) & ~RFLAGS_CF);
VmWriteN (VMCS_N_GUEST_RFLAGS_INDEX,
VmReadN(VMCS_N_GUEST_RFLAGS_INDEX) & ~RFLAGS_CF);
}
else
{
DEBUG((EFI_D_INFO,
"%ld PostPeVmProc - Unsucessful return noted in RFLAGS_CF\n",
CpuIndex));
VmWriteN (VMCS_N_GUEST_RFLAGS_INDEX, VmReadN(VMCS_N_GUEST_RFLAGS_INDEX) | RFLAGS_CF);
VmWriteN (VMCS_N_GUEST_RFLAGS_INDEX,
VmReadN(VMCS_N_GUEST_RFLAGS_INDEX) | RFLAGS_CF);
}
}
mHostContextCommon.HostContextPerCpu[CpuIndex].GuestVmType = SMI_HANDLER;
DEBUG((EFI_D_INFO,
"%ld PostPeVmProc - sucessfully completed - RC: 0x%x\n",
"%ld PostPeVmProc - sucessfully completed - RC: 0x%x\n",
CpuIndex,
rc));
//StopSwTimer();
CheckPendingMtf (CpuIndex);
//
@ -624,30 +656,44 @@ UINT32 PostPeVmProc(UINT32 rc, UINT32 CpuIndex, UINT32 mode)
//
Rflags = AsmVmResume (&mGuestContextCommonSmi.GuestContextPerCpu[CpuIndex].Register);
// BUGBUG: - AsmVmLaunch if AsmVmResume fail
if (VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX) == VmxFailErrorVmResumeWithNonLaunchedVmcs) {
DEBUG ((EFI_D_ERROR, "%ld PostPeVmProc - Rflags: %08x\n", CpuIndex, Rflags));
DEBUG ((EFI_D_ERROR, "%ld PostPeVmProc - VMCS_32_RO_VM_INSTRUCTION_ERROR: %08x\n",
CpuIndex,
(UINTN)VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX)));
DEBUG ((EFI_D_ERROR, "%ld PostPeVmProc - (STM):o(\n", (UINTN)CpuIndex));
if (VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX) ==
VmxFailErrorVmResumeWithNonLaunchedVmcs) {
DEBUG ((EFI_D_ERROR,
"%ld PostPeVmProc - Rflags: %08x\n",
CpuIndex,
Rflags));
DEBUG ((EFI_D_ERROR,
"%ld PostPeVmProc - VMCS_32_RO_VM_INSTRUCTION_ERROR: %08x\n",
CpuIndex,
(UINTN)VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX)));
DEBUG ((EFI_D_ERROR,
"%ld PostPeVmProc - (STM):o(\n",
(UINTN)CpuIndex));
Rflags = AsmVmLaunch (&mGuestContextCommonSmi.GuestContextPerCpu[CpuIndex].Register);
}
AcquireSpinLock (&mHostContextCommon.DebugLock);
DEBUG ((EFI_D_ERROR, "%ld PostPeVmProc - !!!PePostVmProcessing FAIL!!!\n", CpuIndex));
DEBUG ((EFI_D_ERROR, "%ld PostPeVmProc - Rflags: %08x\n", CpuIndex, Rflags));
DEBUG ((EFI_D_ERROR,
DEBUG ((EFI_D_ERROR,
"%ld PostPeVmProc - !!!PePostVmProcessing FAIL!!!\n",
CpuIndex));
DEBUG ((EFI_D_ERROR,
"%ld PostPeVmProc - Rflags: %08x\n",
CpuIndex,
Rflags));
DEBUG ((EFI_D_ERROR,
"%ld PostPeVmProc - VMCS_32_RO_VM_INSTRUCTION_ERROR: %08x\n",
CpuIndex,
(UINTN)VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX)));
DumpVmcsAllField (CpuIndex);
DumpRegContext (&mGuestContextCommonSmi.GuestContextPerCpu[CpuIndex].Register, CpuIndex);
DumpRegContext (&mGuestContextCommonSmi.GuestContextPerCpu[CpuIndex].Register,
CpuIndex);
ReleaseSpinLock (&mHostContextCommon.DebugLock);
DEBUG((EFI_D_ERROR, "%ld PostPeVmProc - CpuDeadLoop\n"));
CpuDeadLoop (); // crash here because we cannot get back to the MLE...
// check to see if there is a path through the intel code for going back to the MLE
// check to see if there is a path through the intel code
// for going back to the MLE
return rc; // always succeed
}
@ -686,9 +732,12 @@ UINT32 save_Inter_PeVm(UINT32 CpuIndex)
// come here when the VM has been interrupted by an SMI
// setup for the call to PostPeVmProc
UINT32 PeType = mHostContextCommon.HostContextPerCpu[CpuIndex].GuestVmType; // which PT are we using
// which PT are we using
UINT32 PeType = mHostContextCommon.HostContextPerCpu[CpuIndex].GuestVmType;
// let the STM know that we are waiting to come back
mHostContextCommon.HostContextPerCpu[CpuIndex].NonSmiHandler = PeType;
mHostContextCommon.HostContextPerCpu[CpuIndex].NonSmiHandler = PeType;
EndTimeStamp = AsmReadTsc();
DEBUG((EFI_D_INFO,
@ -711,12 +760,18 @@ UINT32 RestoreInterPeVm(UINT32 CpuIndex, UINT32 PeType)
{
// should only happen when the PEV/VM is initially loaded, otherwise
// this informaition should be normally grabbed upon a smi timer interrupt
// bug - need to consider the case of debug loading of a module for testing
// bug -
// need to consider the case of debug loading of a module for testing
if(GetMultiProcessorState(CpuIndex) == -1)
{
GetMPState = 1; // Indicate that we still need to get the processor state
return 1; // in this case there is an SMI in process and we need to let it be processed.
// Indicate that we still need to get the processor state
GetMPState = 1;
// in this case there is an SMI in process and
// we need to let it be processed.
return 1;
}
else
{
@ -725,7 +780,8 @@ UINT32 RestoreInterPeVm(UINT32 CpuIndex, UINT32 PeType)
}
}
if(InterlockedCompareExchange32(&PeSmiControl.PeSmiState, PESMIHSMI, PESMIHSMI) == PESMIHSMI)
if(InterlockedCompareExchange32(&PeSmiControl.PeSmiState,
PESMIHSMI, PESMIHSMI) == PESMIHSMI)
{
DEBUG((EFI_D_INFO,
"%ld RestoreInterPeVm - SMI in progress - aborting PE/VM restart\n",
@ -735,16 +791,24 @@ UINT32 RestoreInterPeVm(UINT32 CpuIndex, UINT32 PeType)
// need to think about locking here in case there are two smi's in a row...
PeVmData[PeType].PeVmState = PE_VM_ACTIVE;
PeSmiControl.PeNmiBreak = 1; // when 1, a NMI has been sent to break the thread in PE_APIC_id
PeSmiControl.PeApicId = ReadLocalApicId (); // APIC id of the thread that is executing the PE V<
// when 1, a NMI has been sent to break the thread in PE_APIC_id
PeSmiControl.PeNmiBreak = 1;
// APIC id of the thread that is executing the PE V<
PeSmiControl.PeApicId = ReadLocalApicId ();
PeSmiControl.PeCpuIndex = CpuIndex;
//PeSmiControl.PeExec = 0; // when 1 PE_APIC_ID is executing a
// think about break code (BUG)
VmPeReady = 0; // set the ready gate (for here do not get out (BUG - Review this!!! for SMI in this interval)
// set the ready gate (for here do not get out
// (BUG - Review this!!! for SMI in this interval)
VmPeReady = 0;
enable_nmi(); // turn on NMI
PeSmiControl.PeNmiBreak = 0; // when 1, a NMI has been sent to break the thread in PE_APIC_id
// when 1, a NMI has been sent to break the thread in PE_APIC_id
PeSmiControl.PeNmiBreak = 0;
PeSmiControl.PeExec = 1; // when 1 PE_APIC_ID is executing a
// setup the return
@ -758,7 +822,8 @@ UINT32 RestoreInterPeVm(UINT32 CpuIndex, UINT32 PeType)
//
Rflags = AsmVmResume (&mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register);
// BUGBUG: - AsmVmLaunch if AsmVmResume fail
if (VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX) == VmxFailErrorVmResumeWithNonLaunchedVmcs) {
if (VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX) ==
VmxFailErrorVmResumeWithNonLaunchedVmcs) {
// DEBUG ((EFI_D_ERROR, "(STM):o(\n", (UINTN)Index));
Rflags = AsmVmLaunch (&mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register);
}
@ -827,21 +892,24 @@ VOID
)
{
NMIReceived = NMIReceived + 1; // increment
DEBUG((EFI_D_INFO,
"***NMI***Happened****\n"));
//DEBUG((EFI_D_INFO, "***NMI***Happened****\n"));
if(VmPeReady == 1)
{
UINT32 CpuIndex = ApicToIndex (ReadLocalApicId ());
// in this instance, the VmPe is ready for launch, but an SMI has appeared after the NMI has
// been enabled, but during the iteval between VM/PE setup complete and its launch
// so we will hold the launch, service the SMI and then launch the VM/PE once the
// in this instance, the VmPe is ready for launch,
// but an SMI has appeared after the NMI has
// been enabled, but during the iterval between
// VM/PE setup complete and its launch
// so we will hold the launch, service the SMI and
// then launch the VM/PE once the
// SMI is handled
save_Inter_PeVm(CpuIndex);
DEBUG((EFI_D_INFO,
"%ld enable_nmi - Return from non-returnable function\n", CpuIndex));
"%ld enable_nmi - Return from non-returnable function\n",
CpuIndex));
// this function should not return...
}

View File

@ -94,6 +94,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#define PE_VM_SUSPEND 5 // PE VM is suspended because of SMI
#define PE_VM_OPT_OUT_PERM 6 // Perm PE VM Opt Out
#define PE_VM_OPT_OUT_TEMP 7 // Temp PE VM Opt Out
#define PE_VM_WAIT_START 8 // PE VM is waiting to start
typedef unsigned char byte;
typedef unsigned short int word;

View File

@ -120,11 +120,13 @@ UINT16 get_pmbase(void)
(STM_RSC *)mGuestContextCommonSmm[SMI_HANDLER].BiosHwResourceRequirementsPtr,
IO_RANGE);
if(Resource == NULL)
DEBUG((EFI_D_ERROR, "get_pmbase - Error pmbase not found in resource list\n"));
DEBUG((EFI_D_ERROR,
"get_pmbase - Error pmbase not found in resource list\n"));
else
{
pmbase = Resource->Io.Base;
DEBUG((EFI_D_INFO, "get_pmbase - pmbase set at 0x%x\n", pmbase));
DEBUG((EFI_D_INFO,
"get_pmbase - pmbase set at 0x%x\n", pmbase));
}
}
return pmbase;
@ -137,8 +139,12 @@ void StartTimer(void)
UINT32 smi_sts = IoRead32(pmbase + SMI_STS);
smi_en |= PERIODIC_EN;
//DEBUG((EFI_D_INFO, "StartTimer - smi_en: 0x%08lx smi_sts: 0x%08lx\n", smi_en, smi_sts));
#if 0
DEBUG((EFI_D_INFO,
"StartTimer - smi_en: 0x%08lx smi_sts: 0x%08lx\n",
smi_en,
smi_sts));
#endif
IoWrite32(pmbase + SMI_STS, PERIODIC_STS);
IoWrite32(pmbase + SMI_EN, smi_en);
}
@ -149,18 +155,29 @@ void SetEndOfSmi(void)
UINT16 pmbase = get_pmbase();
UINT32 smi_en = IoRead32(pmbase + SMI_EN);
smi_en |= EOS_EN; // set the bit
//DEBUG((EFI_D_INFO, "-- SetEndOfSmi pmbase: %x smi_en: %x \n", pmbase, smi_en));
#if 0
DEBUG((EFI_D_INFO,
"-- SetEndOfSmi pmbase: %x smi_en: %x \n",
pmbase,
smi_en));
#endif
IoWrite32(pmbase + SMI_EN, smi_en);
//DEBUG((EFI_D_INFO, "SetEndOfSmi smi_en: 0x%08lx smi_sts: 0x%08lx\n", IoRead32(pmbase + SMI_EN), IoRead32(pmbase + SMI_STS)));
#if 0
DEBUG((EFI_D_INFO,
"SetEndOfSmi smi_en: 0x%08lx smi_sts: 0x%08lx\n",
IoRead32(pmbase + SMI_EN),
IoRead32(pmbase + SMI_STS)));
#endif
}
void PrintSmiEnRegister(UINT32 Index)
{
UINT16 pmbase = get_pmbase();
DEBUG((EFI_D_INFO, "%ld PrintSmiEnRegister smi_en: 0x%08x smi_sts: 0x%08x\n", Index, IoRead32(pmbase + SMI_EN), IoRead32(pmbase + SMI_STS)));
DEBUG((EFI_D_INFO,
"%ld PrintSmiEnRegister smi_en: 0x%08x smi_sts: 0x%08x\n",
Index,
IoRead32(pmbase + SMI_EN),
IoRead32(pmbase + SMI_STS)));
}
void AckTimer(void)
@ -168,8 +185,12 @@ void AckTimer(void)
UINT16 pmbase = get_pmbase();
IoWrite32(pmbase + SMI_STS, PERIODIC_STS);
//DEBUG((EFI_D_INFO, "AckTimer - smi_en: 0x%08lx smi_sts: 0x%08lx\n", IoRead32(pmbase + SMI_EN), IoRead32(pmbase + SMI_STS)));
#if 0
DEBUG((EFI_D_INFO,
"AckTimer - smi_en: 0x%08lx smi_sts: 0x%08lx\n",
IoRead32(pmbase + SMI_EN),
IoRead32(pmbase + SMI_STS)));
#endif
}
void StopSwTimer(void)
@ -181,21 +202,54 @@ void StopSwTimer(void)
IoWrite32(pmbase + SMI_EN, smi_en);
}
/*
* CheckTimerSTS
* Input:
* Index - cpu number
*
* Output:
* 0 - No timer interrupt detected
* 1 - Timer interrupt detected
* 2 - Timer interrupt plus additional SMI
*/
int CheckTimerSTS(UINT32 Index)
{
UINT16 pmbase = get_pmbase();
UINT32 smi_sts = IoRead32(pmbase + SMI_STS);
//DEBUG((EFI_D_DEBUG, "%ld CheckTimerSTS - 0x%08lx\n", Index, smi_sts));
#if 0
DEBUG((EFI_D_ERROR, "%ld CheckTimerSTS - 0x%08lx\n", Index, smi_sts));
#endif
if((smi_sts & PERIODIC_STS) == PERIODIC_STS)
{
DEBUG((EFI_D_INFO, "%ld CheckTimerSTS - Timer Interrupt Detected\n", Index, smi_sts));
return 1;
UINT32 smi_en = IoRead32(pmbase + SMI_EN);
UINT32 other_smi = (smi_en & smi_sts) & ~PERIODIC_STS;
if(other_smi == 0)
{
DEBUG((EFI_D_INFO,
"%ld CheckTimerSTS - Timer Interrupt Detected\n",
Index,
smi_sts));
return 1;
}
else
{
DEBUG((EFI_D_INFO,
"%ld CheckTimerSTS - Timer + other SMI found\n",
Index,
smi_sts));
return 2;
}
}
else
{
//DEBUG((EFI_D_INFO "%ld CheckTimerSTS - No Timer Interrupt Detected\n", Index, smi_sts));
#if 0
DEBUG((EFI_D_INFO,
"%ld CheckTimerSTS - No Timer Interrupt Detected\n",
Index,
smi_sts));
#endif
return 0;
}
}
@ -203,8 +257,9 @@ int CheckTimerSTS(UINT32 Index)
void ClearTimerSTS()
{
UINT16 pmbase = get_pmbase();
IoWrite32(pmbase + SMI_STS, PERIODIC_STS); // just want to clear the status - do not touch the rest
// just want to clear the status - do not touch the rest
IoWrite32(pmbase + SMI_STS, PERIODIC_STS);
}
void SetMaxSwTimerInt()

View File

@ -41,27 +41,29 @@ UINT32 PeSmiHandler(UINT32 CpuIndex)
UINT64 * NumProcessors;
UINT32 PeType = PE_PERM;
UINT32 CpuNum;
UINT32 TimerSTS = 0;
InterlockedCompareExchange32(&PeSmiControl.PeSmiState, PESMINULL, PESMIHSMI);
//DEBUG((EFI_D_DEBUG, "%ld PeSmiHandler - CurrPeSmiState %ld\n", CpuIndex, PeSmiControl.PeSmiState));
//DEBUG((EFI_D_INFO, "%ld PeSmiHandler - CurrPeSmiState %ld\n", CpuIndex, PeSmiControl.PeSmiState));
if(PeSmiControl.PeCpuIndex == (INT32)CpuIndex ) // when the pe/vm comes in...
{
// The VM/PE comes in here and causes the state to be set to null
//DEBUG((EFI_D_DEBUG, "%ld PeSmiHandler - VM/PE responded to SMI, CurrPeSmiState %ld\n", CpuIndex, PeSmiControl.PeSmiState));
#if 0
DEBUG((EFI_D_INFO,
"%ld PeSmiHandler - VM/PE responded to SMI, CurrPeSmiState %ld\n",
CpuIndex,
PeSmiControl.PeSmiState));
#endif
InterlockedCompareExchange32(&PeSmiControl.PeSmiState, PESMIPNMI2, PESMINULL);
}
if(InterlockedCompareExchange32(&PeSmiControl.PeSmiState, PESMIPNMI, PESMIPNMI2) == PESMIPNMI)
///PESMIPNMI == PeSmiControl.PeSmiState)
{
// eventually the VM/PE will be started (or at least built) and this will cause one of the processors
// to send a NMI to the VM/PE processor causing it to drop out and process the SMI
// when it does, all processors will exit this loop and process the SMI as usual
SignalPeVm(CpuIndex); // make sure that the PE/VM processes this SMI as well
//PeSmiControl.PeSmiState = PESMINULL;
}
CpuReadySync(CpuIndex); // everyone waits until processor 0 figures out what to do
@ -73,17 +75,19 @@ UINT32 PeSmiHandler(UINT32 CpuIndex)
// VM/PE sends a SMI to the other processors when it wants state information from other CPU's
NumProcessors = (UINT64 *) PeVmData[PeType].SharedPageStm;
RootState = (ROOT_VMX_STATE *) ((char *)NumProcessors + 64);//sizeof(*NumProcessors) + sizeof(*NumProcessors));
//sizeof(*NumProcessors) + sizeof(*NumProcessors));
RootState = (ROOT_VMX_STATE *) ((char *)NumProcessors + 64);
// get the local processor state
GetRootVmxState(CpuIndex, &RootState[CpuIndex]);
//retvalue = 1; // we did something
CpuReadySync(CpuIndex); // wait for everyone to finish
if(CpuIndex == 0)
{
InterlockedCompareExchange32(&PeSmiControl.PeSmiState, PESMIPSMI, PESMINULL); // reset the state
// Reset the state
InterlockedCompareExchange32(&PeSmiControl.PeSmiState, PESMIPSMI, PESMINULL);
}
return 1; // tell the SmiEventHandler that there is one less processor
@ -97,48 +101,34 @@ UINT32 PeSmiHandler(UINT32 CpuIndex)
if(InterlockedCompareExchange32(&PeSmiControl.PeWaitTimer, 1, 1) == 1)
{
if(CheckTimerSTS(CpuIndex) != 0)
{
//DEBUG((EFI_D_DEBUG, "%ld CheckAndGetState - (PESMIHSMI) Processing VM/PE startup PeSmiState: %d\n", CpuIndex, PeSmiControl.PeSmiState));
TimerSTS = CheckTimerSTS(CpuIndex);
if (TimerSTS == 2)
{
// we have an additional SMI
InterlockedCompareExchange32 (&retvalue, 1, 0);
}
else
{
InterlockedCompareExchange32 (&retvalue, 0, 1);
}
if(TimerSTS != 0)
{
#if 0
DEBUG((EFI_D_INFO,
"%ld CheckAndGetState - (PESMIHSMI) Processing VM/PE startup PeSmiState: %d\n",
CpuIndex,
PeSmiControl.PeSmiState));
#endif
InterlockedCompareExchange32(&PeSmiControl.PeSmiState, PESMIHSMI, PESMIHTMR);
NumProcessors = (UINT64 *) PeVmData[PeType].SharedPageStm;
RootState = (ROOT_VMX_STATE *) ((char *)NumProcessors + 64);//sizeof(*NumProcessors) + sizeof(*NumProcessors));
// get the local processor state
GetRootVmxState(CpuIndex, &RootState[CpuIndex]);
InterlockedCompareExchange32(&retvalue, 0, 1); // we set to one to indicate we are not there
// the VM/PE Cpu cleans up and runs
//PeSmiControl.PeWaitTimer = 0;
InterlockedCompareExchange32(&PeSmiControl.PeWaitTimer, 1, 0);
//ClearSwTimerSTS();
StopSwTimer();
retvalue = 1;
// start the VM/PE
PeVmData[PeType].StartMode = PEVM_PRESTART_SMI; // starting from SMI
CpuReadySync(CpuIndex); // sync everyone ud
SetEndOfSmi(); // make sure that the timer SMI has been cleared
for(CpuNum = 0; CpuNum < mHostContextCommon.CpuNum; CpuNum++)
{
PrintVmxState(CpuNum, &RootState[CpuNum]);
}
if( mHostContextCommon.StmShutdown == 1)
{
// time to quit
StmTeardown(CpuIndex);
}
RunPermVM(CpuIndex);
//PeVmData[PeType].StartMode = PEVM_START_SMI; // for consistency in error conditions
//CpuDeadLoop ();
// should not get here...
return retvalue; // tell the SmiEventHandler that there is one less processor
//sizeof(*NumProcessors) + sizeof(*NumProcessors));
RootState = (ROOT_VMX_STATE *) ((char *)NumProcessors + 64);
}
}
}
@ -151,7 +141,39 @@ UINT32 PeSmiHandler(UINT32 CpuIndex)
RootState = (ROOT_VMX_STATE *) ((char *)NumProcessors + 64);
GetRootVmxState(CpuIndex, &RootState[CpuIndex]);
retvalue = 1;
CpuReadySync(CpuIndex);
if (PeSmiControl.PeCpuIndex == (INT32)CpuIndex)
{
InterlockedCompareExchange32(&PeSmiControl.PeWaitTimer, 1, 0);
StopSwTimer();
// start the VM/PE
PeVmData[PeType].StartMode = PEVM_PRESTART_SMI; // starting from SMI
SetEndOfSmi(); // make sure that the timer SMI has been cleared
InterlockedCompareExchange32(&PeSmiControl.PeSmiState, PESMIHTMR, PESMINULL);
for(CpuNum = 0; CpuNum < mHostContextCommon.CpuNum; CpuNum++)
{
PrintVmxState(CpuNum, &RootState[CpuNum]);
}
if( mHostContextCommon.StmShutdown == 1)
{
// time to quit
StmTeardown(CpuIndex);
}
if(TimerSTS == 2)
{
// SMI has happened at the same time, so process it
PeVmData[PeType].PeVmState = PE_VM_WAIT_START;
return 0;
}
RunPermVM(CpuIndex);
}
// we do not reset the state here as the VM/PE will be processing
// when it competes it should end with a PeSmiState pf PESMIPNMI (waiting for NMI)
@ -160,8 +182,8 @@ UINT32 PeSmiHandler(UINT32 CpuIndex)
{
if(CpuIndex == 0)
{
//PeSmiControl.PeSmiState = PESMINULL;
InterlockedCompareExchange32(&PeSmiControl.PeSmiState, PESMIHSMI, PESMINULL); // one of these will work
// One of these will work
InterlockedCompareExchange32(&PeSmiControl.PeSmiState, PESMIHSMI, PESMINULL);
}
retvalue = 0;
}

View File

@ -56,7 +56,9 @@ int GetMultiProcessorState(UINT32 CpuIndex)
{
UINT32 PeType = PE_PERM;
UINT64 * NumProcessors = (UINT64 *) PeVmData[PeType].SharedPageStm;
ROOT_VMX_STATE * RootState; // = (ROOT_VMX_STATE *) (NumProcessors + sizeof(*NumProcessors));
// = (ROOT_VMX_STATE *) (NumProcessors + sizeof(*NumProcessors));
ROOT_VMX_STATE * RootState;
UINT32 CpuNum;
DEBUG((EFI_D_INFO,
@ -72,10 +74,12 @@ int GetMultiProcessorState(UINT32 CpuIndex)
}
// first clear out the data structures and set the number of processors
RootState = (ROOT_VMX_STATE *) ((char *)NumProcessors + 64 );//sizeof(*NumProcessors) + sizeof(*NumProcessors));
//sizeof(*NumProcessors) + sizeof(*NumProcessors));
RootState = (ROOT_VMX_STATE *) ((char *)NumProcessors + 64 );
*NumProcessors = mHostContextCommon.CpuNum; // number of CPUs
ZeroMem ((VOID *)(UINTN) RootState, sizeof(ROOT_VMX_STATE) * mHostContextCommon.CpuNum);
ZeroMem ((VOID *)(UINTN) RootState,
sizeof(ROOT_VMX_STATE) * mHostContextCommon.CpuNum);
// make sure that the VMCS offsets are setup
@ -83,9 +87,11 @@ int GetMultiProcessorState(UINT32 CpuIndex)
// send an SMI to the other processors
if(InterlockedCompareExchange32(&PeSmiControl.PeSmiState, PESMINULL, PESMIPSMI) != PESMINULL) //&PeSmiControl.PeSmiState = 1;
if(InterlockedCompareExchange32(&PeSmiControl.PeSmiState,
PESMINULL,
PESMIPSMI) != PESMINULL)
{
DEBUG((EFI_D_INFO,
DEBUG((EFI_D_ERROR,
"%ld x - Aborting, SMI handler already there. PeSmiState %ld\n",
CpuIndex,
PeSmiControl.PeSmiState));
@ -99,14 +105,10 @@ int GetMultiProcessorState(UINT32 CpuIndex)
// get the local processor state
//CpuReadySync(CpuIndex);
GetRootVmxState(CpuIndex, &RootState[CpuIndex]);
// need to think about this --- without it this hangs, what in context of other processors
//InterlockedCompareExchange32(&PeSmiControl.PeSmiState, PESMIPSMI, PESMINULL);//PeSmiControl.PeSmiState = 0; // all done - may need to sync processors in the case of
// another SMI coming in
CpuReadySync(CpuIndex); // wait for everyone to finish the job - PeSmiHandler will set PeSmiState to 0
CpuReadySync(CpuIndex); // wait for everyone to finish the job
//- PeSmiHandler will set PeSmiState to 0
// once everyone has synched up
for(CpuNum = 0; CpuNum < mHostContextCommon.CpuNum; CpuNum++)
@ -114,7 +116,6 @@ int GetMultiProcessorState(UINT32 CpuIndex)
PrintVmxState(CpuNum, &RootState[CpuNum]);
}
DEBUG((EFI_D_INFO,
"%ld GetMultiProcessorState - Completed. PeSmiState: %ld\n",
CpuIndex,
@ -150,14 +151,17 @@ void GetRootVmxState(UINT32 CpuIndex, ROOT_VMX_STATE * RootState)
RootState->Vmxon = mHostContextCommon.HostContextPerCpu[CpuIndex].Vmxon;
//UINT32 ApicId = (UINT32) (get_apic_id() & 0xFF);
RootState->LinkVMCS = VmRead64(VMCS_64_GUEST_VMCS_LINK_PTR_INDEX);
RootState->ExecutiveVMCS = VmRead64(VMCS_64_CONTROL_EXECUTIVE_VMCS_PTR_INDEX); // get the executive VMCS
// DEBUG((EFI_D_ERROR, "%ld GetRootVmxState\n VMXON: 0x%016llx\n ExecutiveVMCS: 0x%016llx\n LinkVMCS: 0x%016llx\n",
// CpuIndex,
// RootState->Vmxon,
// RootState->ExecutiveVMCS,
// RootState->LinkVMCS));
// get the executive VMCS
RootState->ExecutiveVMCS = VmRead64(VMCS_64_CONTROL_EXECUTIVE_VMCS_PTR_INDEX);
#if 0
DEBUG((EFI_D_ERROR, "%ld GetRootVmxState\n VMXON: 0x%016llx\n ExecutiveVMCS: 0x%016llx\n LinkVMCS: 0x%016llx\n",
CpuIndex,
RootState->Vmxon,
RootState->ExecutiveVMCS,
RootState->LinkVMCS));
#endif
RootState->RootGuestCR0 = VmReadN(VMCS_N_GUEST_CR0_INDEX);
RootState->RootGuestCR3 = VmReadN(VMCS_N_GUEST_CR3_INDEX);
RootState->RootGuestCR4 = VmReadN(VMCS_N_GUEST_CR4_INDEX);
@ -178,41 +182,36 @@ void GetRootVmxState(UINT32 CpuIndex, ROOT_VMX_STATE * RootState)
if(RootState->ExecutiveVMCS == RootState->Vmxon) // ref: section 34.15.4.7
{
// we are in root operation, so our VMCS of interest is in the VNCS-Link field
// we are in root operation, so our VMCS of interest
// is in the VNCS-Link field
if(RootState->LinkVMCS != 0xFFFFFFFFFFFFFFFF)
{
RootState->VmcsType = 1; // guest-VM being sericed by VMM
HostRootVMCS = RootState->LinkVMCS;
//HostRootVMCS = VmRead64(VMCS_64_GUEST_VMCS_LINK_PTR_INDEX);
RootState->VmxState = VMX_STATE_ROOT;
//DEBUG((EFI_D_DEBUG, "%ld GetRootVmxState (%d): execVMCS is vmxon: 0x%016llx using VMCS_LINK_POINTER\n",
//CpuIndex, RootState->VmcsType, HostRootVMCS));
}
else
{
HostRootVMCS = RootState->ExecutiveVMCS;
RootState->VmcsType = 2;
//HostRootVMCS = VmRead64(VMCS_64_GUEST_VMCS_LINK_PTR_INDEX);
RootState->VmxState = VMX_STATE_ROOT;
//DEBUG((EFI_D_DEBUG, "%ld GetRootVmxState (%d): execVMCS is vmxon: But LinkVMCS is 0xFFFFFFFFFFFFFFF so no current Vmcs. Using Executive Vmcs: %llx\n",
// CpuIndex, RootState->VmcsType, HostRootVMCS));
}
}
else
{
// in guest operation, so our VMCS of interest is in the executive-VMCS field
// in guest operation, so our VMCS of interest
// is in the executive-VMCS field
RootState->VmcsType = 3;
HostRootVMCS = RootState->ExecutiveVMCS;
RootState->VmxState = VMX_STATE_GUEST;
//DEBUG((EFI_D_DEBUG, "%ld GetRootVmxState (%d): execVMCS is guest VMCS: 0x%016llx using Executive VMCS\n",
//CpuIndex, RootState->VmcsType, HostRootVMCS));
}
AsmVmClear(&(CurrentVMCSSave));
AsmVmPtrStore(&CurrentVMCSSave);
RootGuestRIP_M = *(UINT64 *)((UINTN)CurrentVMCSSave + (UINTN)VMCS_N_GUEST_RIP_OFFSET);
RootGuestRIP_M = *(UINT64 *)((UINTN)CurrentVMCSSave +
(UINTN)VMCS_N_GUEST_RIP_OFFSET);
VmcsFlushStart:
FlushCount = 0;
@ -222,8 +221,12 @@ VmcsFlushStart:
{
// got here because the in-memory copy of the VMCS is different than
// what is in the processor - so we need to flush
//DEBUG((EFI_D_DEBUG, "%ld - GetRootState: RootGuestRIPMemory: 0x%016llx, Location: 0x%016llx\n",
//CpuIndex, RootGuestRIPMemory, ((UINTN)HostRootVMCS + (UINTN)VMCS_N_GUEST_RIP_OFFSET)));
#if 0
DEBUG((EFI_D_INFO, "%ld - GetRootState: RootGuestRIPMemory: 0x%016llx, Location: 0x%016llx\n",
CpuIndex,
RootGuestRIPMemory,
((UINTN)HostRootVMCS + (UINTN)VMCS_N_GUEST_RIP_OFFSET)));
#endif
// first create a dummy VMCS
VmxRevId = AsmReadMsr32(IA32_VMX_BASIC_MSR_INDEX);
DummyVmcs[FlushCount] = (char *) AllocatePages(VmcsSizeInPages);
@ -232,7 +235,7 @@ VmcsFlushStart:
{
// ran out of memory - release everything and start over
// that way someone else hopefully gets a chance to complete
DEBUG((EFI_D_INFO,
DEBUG((EFI_D_ERROR,
"%ld - GetRootState: ran out of memory - so free everything and restart - Flushcount: %d\n",
CpuIndex,
FlushCount));
@ -248,11 +251,13 @@ VmcsFlushStart:
memcpy(DummyVmcs[FlushCount], &VmxRevId, 4);
AsmVmPtrLoad((UINT64 *) &DummyVmcs[FlushCount]);
RootGuestRIP_M = *(UINT64 *)((UINTN)CurrentVMCSSave + (UINTN)VMCS_N_GUEST_RIP_OFFSET); // try again
RootGuestRIP_M = *(UINT64 *)((UINTN)CurrentVMCSSave +
(UINTN)VMCS_N_GUEST_RIP_OFFSET); // try again
FlushCount++;
}
AsmVmPtrLoad(&CurrentVMCSSave); // in any case, reload this and free the dummies if necessary
// in any case, reload this and free the dummies if necessary
AsmVmPtrLoad(&CurrentVMCSSave);
if(FlushCount > 0)
{
@ -260,7 +265,6 @@ VmcsFlushStart:
"%ld GetRootVmxState - Flush necessary to get VMCS in sync. Flushcount=%d\n",
CpuIndex,
FlushCount));
//DEBUG((EFI_D_INFO, "%ld GetRootVmxState: after Flush: VMCS_N_GUEST_RIP_MEMORY: 0x%016llx (test) \n", CpuIndex, RootGuestRIPMemory));
// release the buffers
for(i = 0; i < FlushCount; i++)
{
@ -273,24 +277,35 @@ VmcsFlushStart:
//AsmVmPtrLoad(&HostRootVMCS);
RootState->HostRootVMCS = HostRootVMCS;
//DEBUG((EFI_D_DEBUG, "%ld - GetRootVmxState: HostRootVmcs 0x%016llx\n", CpuIndex, RootState->HostRootVMCS));
RootGuestCR0_M = *(UINT64 *)((UINTN)HostRootVMCS + (UINTN)VMCS_N_GUEST_CR0_OFFSET);
RootGuestCR3_M = *(UINT64 *)((UINTN)HostRootVMCS + (UINTN)VMCS_N_GUEST_CR3_OFFSET);
RootGuestCR4_M = *(UINT64 *)((UINTN)HostRootVMCS + (UINTN)VMCS_N_GUEST_CR4_OFFSET);
RootGuestGDTRBase_M = *(UINT64 *)((UINTN)HostRootVMCS + (UINTN)VMCS_N_GUEST_GDTR_BASE_OFFSET);
RootGuestGDTRLimit_M = (*(UINT64 *)((UINTN)HostRootVMCS + (UINTN)VMCS_32_GUEST_GDTR_LIMIT_OFFSET)) & 0x00000000FFFFFFFF;
RootGuestIDTRBase_M = *(UINT64 *)((UINTN)HostRootVMCS + (UINTN)VMCS_N_GUEST_IDTR_BASE_OFFSET);
RootGuestIDTRLimit_M = (*(UINT64 *)((UINTN)HostRootVMCS + (UINTN)VMCS_32_GUEST_LDTR_LIMIT_OFFSET)) & 0x00000000FFFFFFFF;
RootGuestRSP_M = *(UINT64 *)((UINTN)HostRootVMCS + (UINTN)VMCS_N_GUEST_RSP_OFFSET);
RootGuestRIP_M = *(UINT64 *)((UINTN)HostRootVMCS + (UINTN)VMCS_N_GUEST_RIP_OFFSET);
RootContExecVmcs_M = *(UINT64 *)((UINTN)HostRootVMCS + (UINTN)VMCS_64_CONTROL_EXECUTIVE_VMCS_PTR_OFFSET);
RootContLinkVmcs_M = *(UINT64 *)((UINTN)HostRootVMCS + (UINTN)VMCS_64_GUEST_VMCS_LINK_PTR_OFFSET);
RootGuestCR0_M = *(UINT64 *)((UINTN)HostRootVMCS +
(UINTN)VMCS_N_GUEST_CR0_OFFSET);
RootGuestCR3_M = *(UINT64 *)((UINTN)HostRootVMCS +
(UINTN)VMCS_N_GUEST_CR3_OFFSET);
RootGuestCR4_M = *(UINT64 *)((UINTN)HostRootVMCS +
(UINTN)VMCS_N_GUEST_CR4_OFFSET);
RootGuestGDTRBase_M = *(UINT64 *)((UINTN)HostRootVMCS +
(UINTN)VMCS_N_GUEST_GDTR_BASE_OFFSET);
RootGuestGDTRLimit_M = (*(UINT64 *)((UINTN)HostRootVMCS +
(UINTN)VMCS_32_GUEST_GDTR_LIMIT_OFFSET)) & 0x00000000FFFFFFFF;
RootGuestIDTRBase_M = *(UINT64 *)((UINTN)HostRootVMCS +
(UINTN)VMCS_N_GUEST_IDTR_BASE_OFFSET);
RootGuestIDTRLimit_M = (*(UINT64 *)((UINTN)HostRootVMCS +
(UINTN)VMCS_32_GUEST_LDTR_LIMIT_OFFSET)) & 0x00000000FFFFFFFF;
RootGuestRSP_M = *(UINT64 *)((UINTN)HostRootVMCS +
(UINTN)VMCS_N_GUEST_RSP_OFFSET);
RootGuestRIP_M = *(UINT64 *)((UINTN)HostRootVMCS +
(UINTN)VMCS_N_GUEST_RIP_OFFSET);
RootContExecVmcs_M = *(UINT64 *)((UINTN)HostRootVMCS +
(UINTN)VMCS_64_CONTROL_EXECUTIVE_VMCS_PTR_OFFSET);
RootContLinkVmcs_M = *(UINT64 *)((UINTN)HostRootVMCS +
(UINTN)VMCS_64_GUEST_VMCS_LINK_PTR_OFFSET);
#ifdef VMCSDEBUGPRINT
if(RootState->VmcsType !=2) // only want active Vmcs
{
DEBUG((EFI_D_DEBUG, "%ld GetRootVmxState (%d) HostRootVmcs 0x%016llx\n G_CR0 %llx\n G_CR3 %llx\n G_CR4 %llx\n G_GDTR %llx:%llx\n G_IDTR %llx:%llx\n G_RSP %llx\n G_RIP %llx\n",
DEBUG((EFI_D_INFO,
"%ld GetRootVmxState (%d) HostRootVmcs 0x%016llx\n G_CR0 %llx\n G_CR3 %llx\n G_CR4 %llx\n G_GDTR %llx:%llx\n G_IDTR %llx:%llx\n G_RSP %llx\n G_RIP %llx\n",
CpuIndex,
RootState->VmcsType,
RootState->HostRootVMCS,
@ -304,7 +319,8 @@ VmcsFlushStart:
RootState->RootGuestRSP,
RootState->RootGuestRIP));
DEBUG((EFI_D_DEBIG, "%ld GetRootVmxState (%d) (control) HostRootVmcs 0x%016llx\n VMXON %llx\n ExecutiveVMCS %llx\n LinkVMCS %llx\n EPT %llx\n",
DEBUG((EFI_D_INFO,
"%ld GetRootVmxState (%d) (control) HostRootVmcs 0x%016llx\n VMXON %llx\n ExecutiveVMCS %llx\n LinkVMCS %llx\n EPT %llx\n",
CpuIndex,
RootState->VmcsType,
RootState->HostRootVMCS,
@ -313,9 +329,9 @@ VmcsFlushStart:
RootState->LinkVMCS,
RootState->RootContEPT));
DEBUG((EFI_D_DEBUG, "%ld GetRootVmxState (%d) (memory) HostRootVmcs 0x%016llx\n G_CR0m %llx\n G_CR3m %llx\n G_CR4m %llx\n G_GDTRm %llx:%llx\n G_IDTRm %llx:%llx\n G_RSPm %llx\n G_RIPm %llx\n",
DEBUG((EFI_D_INFO,
"%ld GetRootVmxState (%d) (memory) HostRootVmcs 0x%016llx\n G_CR0m %llx\n G_CR3m %llx\n G_CR4m %llx\n G_GDTRm %llx:%llx\n G_IDTRm %llx:%llx\n G_RSPm %llx\n G_RIPm %llx\n",
CpuIndex,
// "GetRootVmxState (memory)\n G_CR0m %llx\n G_CR3m %llx\n G_CR4m %llx\n G_GDTRm %llx:%llx\n G_IDTRm %llx:%llx\n G_RSPm %llx\n G_RIPm %llx\n C_ExecVMCSm %llx\n C_LinkVMCSm %llx\n",
RootState->VmcsType,
RootState->HostRootVMCS,
RootGuestCR0_M,
@ -328,7 +344,8 @@ VmcsFlushStart:
RootGuestRSP_M,
RootGuestRIP_M));
DEBUG((EFI_D_DEBUG, "%ld GetRootVmxState (%d) (memory) HostRootVmcs 0x%016llx\n C_ExecVMCSm %llx\n C_LinkVMCSm %llx\n",
DEBUG((EFI_D_INFO,
"%ld GetRootVmxState (%d) (memory) HostRootVmcs 0x%016llx\n C_ExecVMCSm %llx\n C_LinkVMCSm %llx\n",
CpuIndex,
RootState->VmcsType,
RootState->HostRootVMCS,
@ -336,8 +353,6 @@ VmcsFlushStart:
RootContLinkVmcs_M));
}
#endif
//DEBUG((EFI_D_DEBUG, "%ld GetRootVmxState: VMCS_N_GUEST_RIP_MEMORY: 0x%016llx VMCS_N_GUEST_RIP: 0x%016llx, Location: 0x%016llx (test) \n",
// CpuIndex, RootGuestRIP_M, RootState->RootGuestRIP, ((UINTN)HostRootVMCS + (UINTN)VMCS_N_GUEST_RIP_OFFSET)));
// need to save the root vmx host structures
#ifdef ZERO
@ -356,15 +371,23 @@ VmcsFlushStart:
else
#endif
{
RootState->RootHostCR0 = *(UINT64 *)((UINTN)HostRootVMCS + (UINTN)VMCS_N_HOST_CR0_OFFSET);
RootState->RootHostCR3 = *(UINT64 *)((UINTN)HostRootVMCS + (UINTN)VMCS_N_HOST_CR3_OFFSET);
RootState->RootHostCR4 = *(UINT64 *)((UINTN)HostRootVMCS + (UINTN)VMCS_N_HOST_CR4_OFFSET);
RootState->RootHostGDTRBase = *(UINTN *)((UINTN)HostRootVMCS + (UINTN)VMCS_N_HOST_GDTR_BASE_OFFSET);
RootState->RootHostIDTRBase = *(UINTN *)((UINTN)HostRootVMCS + (UINTN)VMCS_N_HOST_IDTR_BASE_OFFSET);
RootState->RootHostCR0 = *(UINT64 *)((UINTN)HostRootVMCS +
(UINTN)VMCS_N_HOST_CR0_OFFSET);
RootState->RootHostCR3 = *(UINT64 *)((UINTN)HostRootVMCS +
(UINTN)VMCS_N_HOST_CR3_OFFSET);
RootState->RootHostCR4 = *(UINT64 *)((UINTN)HostRootVMCS +
(UINTN)VMCS_N_HOST_CR4_OFFSET);
RootState->RootHostGDTRBase = *(UINTN *)((UINTN)HostRootVMCS +
(UINTN)VMCS_N_HOST_GDTR_BASE_OFFSET);
RootState->RootHostIDTRBase = *(UINTN *)((UINTN)HostRootVMCS +
(UINTN)VMCS_N_HOST_IDTR_BASE_OFFSET);
RootState->RootHostRSP = *(UINTN*)((UINTN)HostRootVMCS + (UINTN)VMCS_N_HOST_RSP_OFFSET);
RootState->RootHostRIP = *(UINTN*)((UINTN)HostRootVMCS + (UINTN)VMCS_N_HOST_RIP_OFFSET);
RootState->RootHostEPT = *(UINTN*)((UINTN)HostRootVMCS + (UINTN)VMCS_64_CONTROL_EPT_PTR_OFFSET);
RootState->RootHostRSP = *(UINTN*)((UINTN)HostRootVMCS +
(UINTN)VMCS_N_HOST_RSP_OFFSET);
RootState->RootHostRIP = *(UINTN*)((UINTN)HostRootVMCS +
(UINTN)VMCS_N_HOST_RIP_OFFSET);
RootState->RootHostEPT = *(UINTN*)((UINTN)HostRootVMCS +
(UINTN)VMCS_64_CONTROL_EPT_PTR_OFFSET);
}
// Indicate to the master that we are all done
@ -377,7 +400,8 @@ VmcsFlushStart:
#ifdef VMCSDEBUGPRINT
if(RootState->VmcsType != 2)
{
DEBUG((EFI_D_DEBUG, "%ld GetRootVmxState (%d) \n H_CR0 %llx\n H_CR3 %llx\n H_CR4 %llx\n H_GDTR %llx\n H_IDTR %llx\n H_RSP %llx\n H_RIP %llx\n H_EPT %llx\n",
DEBUG((EFI_D_INFO,
"%ld GetRootVmxState (%d) \n H_CR0 %llx\n H_CR3 %llx\n H_CR4 %llx\n H_GDTR %llx\n H_IDTR %llx\n H_RSP %llx\n H_RIP %llx\n H_EPT %llx\n",
CpuIndex,
RootState->VmcsType,
RootState->RootHostCR0,
@ -422,17 +446,20 @@ void SetupGetRootVmxState()
VMCS_N_GUEST_IDTR_BASE_OFFSET = GetVmcsOffset(VMCS_N_GUEST_IDTR_BASE_INDEX);
VMCS_32_GUEST_LDTR_LIMIT_OFFSET = GetVmcsOffset(VMCS_32_GUEST_LDTR_LIMIT_INDEX);
VMCS_N_GUEST_RSP_OFFSET = GetVmcsOffset(VMCS_N_GUEST_RSP_INDEX);
VMCS_64_CONTROL_EXECUTIVE_VMCS_PTR_OFFSET = GetVmcsOffset(VMCS_64_CONTROL_EXECUTIVE_VMCS_PTR_INDEX);
VMCS_64_GUEST_VMCS_LINK_PTR_OFFSET = GetVmcsOffset(VMCS_64_GUEST_VMCS_LINK_PTR_INDEX);
VMCS_64_CONTROL_EXECUTIVE_VMCS_PTR_OFFSET =
GetVmcsOffset(VMCS_64_CONTROL_EXECUTIVE_VMCS_PTR_INDEX);
VMCS_64_GUEST_VMCS_LINK_PTR_OFFSET =
GetVmcsOffset(VMCS_64_GUEST_VMCS_LINK_PTR_INDEX);
// need to initialize the VMCS Offset table, if it has not already been done
VMCS_OFFSET_READY = 1;
}
void PrintVmxState(UINT32 CpuIndex, ROOT_VMX_STATE * RootState)
{
if(RootState->ExecutiveVMCS == RootState->Vmxon) // ref: section 34.15.4.7
if(RootState->ExecutiveVMCS == RootState->Vmxon)// ref: section 34.15.4.7
{
// we are in root operation, so our VMCS of interest is in the VNCS-Link field
// we are in root operation,
//so our VMCS of interest is in the VNCS-Link field
if(RootState->LinkVMCS != 0xFFFFFFFFFFFFFFFF)
{
@ -453,7 +480,8 @@ void PrintVmxState(UINT32 CpuIndex, ROOT_VMX_STATE * RootState)
}
else
{
// in guest operation, so our VMCS of interest is in the executive-VMCS field
// in guest operation,
// so our VMCS of interest is in the executive-VMCS field
DEBUG((EFI_D_INFO,
"%ld PrintVmxState (%d): execVMCS is guest VMCS: 0x%016llx using Executive VMCS\n",
@ -489,7 +517,8 @@ void PrintVmxState(UINT32 CpuIndex, ROOT_VMX_STATE * RootState)
RootState->LinkVMCS,
RootState->RootContEPT));
DEBUG((EFI_D_INFO, "%ld PrintVmxState (%d) \n H_CR0 %llx\n H_CR3 %llx\n H_CR4 %llx\n H_GDTR %llx\n H_IDTR %llx\n H_RSP %llx\n H_RIP %llx\n H_EPT %llx\n",
DEBUG((EFI_D_INFO,
"%ld PrintVmxState (%d) \n H_CR0 %llx\n H_CR3 %llx\n H_CR4 %llx\n H_GDTR %llx\n H_IDTR %llx\n H_RSP %llx\n H_RIP %llx\n H_EPT %llx\n",
CpuIndex,
RootState->VmcsType,
RootState->RootHostCR0,
@ -503,4 +532,3 @@ void PrintVmxState(UINT32 CpuIndex, ROOT_VMX_STATE * RootState)
}
}

View File

@ -69,8 +69,10 @@ VOID
if(PeSmiControl.PeCpuIndex == ((INT32) Index))
{
PeType = mHostContextCommon.HostContextPerCpu[Index].NonSmiHandler;
//PeType = mHostContextCommon.HostContextPerCpu[Index].GuestVmType;
DEBUG((EFI_D_ERROR, "%ld RsmHandler - VmPe Detected - PeType: %ld PeVmState: %ld\n", Index, PeType, PeVmData[PeType].PeVmState));
DEBUG((EFI_D_INFO, "%ld RsmHandler - VmPe Detected - PeType: %ld PeVmState: %ld\n",
Index,
PeType,
PeVmData[PeType].PeVmState));
switch(PeVmData[PeType].PeVmState)
{
@ -81,13 +83,23 @@ VOID
RestoreInterPeVm(Index, PeType);
//should not return... will let the module handle the error processing
// this will return in the case where the VM/PE was being created and it was interrupted by a SMI that was detected
// this will return in the case where the VM/PE was being created and
// it was interrupted by a SMI that was detected
// while doing the processor state gathering.
// we will come out and let it return so that the SMI can get fired and
// when the SMI handler is done will reattempt to regather the processor info
DEBUG((EFI_D_ERROR, "%ld RsmHandler ERROR - Failed to restart PE/VM after SMI, PeType: %ld\n", Index, PeType));
DEBUG((EFI_D_ERROR,
"%ld RsmHandler ERROR - Failed to restart PE/VM after SMI, PeType: %ld\n",
Index,
PeType));
break;
}
case PE_VM_WAIT_START:
{
RunPermVM(Index);
DEBUG ((EFI_D_ERROR, "%ld RsmHandler - Unable to start Perm PE VM", Index));
break;
}
case PE_VM_IDLE:
case PE_VM_AVAIL:
{
@ -96,7 +108,9 @@ VOID
}
default:
{
DEBUG((EFI_D_ERROR, " %ld RsmHandler - data structure inconsistency - suspended PE/VM not found\n", Index));
DEBUG((EFI_D_ERROR,
"%ld RsmHandler - data structure inconsistency - suspended PE/VM not found\n",
Index));
}
}
}