Core/Runtime/ - Shutdown VM/PE during STM shutdown

This patch makes sure that the VM/PE is properly shutdown
when the STM is being shutdown. In cases, where the VM is
unplugged from the kernel, it also detects the missing
transaction and ensures that all processors are shutdown.

Signed-off-by: Eugene Myers <edmyers@cyberpackventures.com>
This commit is contained in:
Eugene Myers 2023-05-31 16:41:46 -04:00
parent 7aaadc24f4
commit 3a30f0e296
3 changed files with 53 additions and 8 deletions

View File

@ -30,6 +30,7 @@ extern void AsmSendInt2(); // setup NMI
extern void PeEptFree(IN UINT64 EptPointer);
extern UINT32 GetVmcsOffset( UINT32 field_encoding);
extern UINT32 GetMPState;
extern void StopPeriodicTimer(void);
static int CpuGetState = 0;
@ -40,6 +41,7 @@ void ClearTimerSTS(void);
void SetMaxSwTimerInt(void);
void SetMinSwTimerInt(void);
void SetPeriodicTimerRate(UINT16 value);
UINT32 VMPE_Terminate(UINT32 CpuIndex);
extern void MapVmcs();
void LaunchPeVm(UINT32 PeType, UINT32 CpuIndex);
@ -620,11 +622,7 @@ UINT32 PostPeVmProc(UINT32 rc, UINT32 CpuIndex, UINT32 mode)
// clear out the page table list
if(mode == RELEASE_VM)
{
FreePE_DataStructures(PeType);
// need to add code here in the instance a perm PE VM has crashed
// 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
VMPE_Terminate(CpuIndex);
DEBUG((EFI_D_INFO,
"%ld PostPeVmProc - PE/VM Free (AVAIL) - PeType: %ld\n",
CpuIndex,
@ -743,6 +741,35 @@ UINT32 FreePE_DataStructures(UINT32 PeType)
return STM_SUCCESS;
}
UINT32 VMPE_Terminate(UINT32 CpuIndex)
{
// BUG!! note only handles Perm VM - need to account for non perm vms as well
UINT32 PeType = PE_PERM;
PeType = mHostContextCommon.HostContextPerCpu[CpuIndex].GuestVmType;
// guest VmType is set to PE_PERM only when the VM/PE is running
DEBUG((EFI_D_INFO, "%ld VMPE_Terminate started - PeType: %ld %ld\n",
CpuIndex, PeType, PE_PERM));
if(PeSmiControl.PeCpuIndex != CpuIndex)
return 0;
// if(PeType == PE_PERM)
{
StopPeriodicTimer();
SetEndOfSmi(); // make sure that the timer SMI has been cleared
}
FreePE_DataStructures(PeType);
PeVmData[PeType].PeVmState = PE_VM_AVAIL; // not there anymore
PeSmiControl.PeCpuIndex = -1; // indicate none functioning at this momemnet
DEBUG((EFI_D_INFO,
"%ld VMPE_Terminate done - PeType: %ld\n",
CpuIndex,
PeType));
return 0;
}
//setup the guest physical address space assigned for the module to be RWX
// the remainder of guest physical addrss space will be setup as RW.

View File

@ -28,6 +28,8 @@ extern void StopPeriodicTimer(void);
extern void SetEndOfSmi(void);
extern void PrintVmxState(UINT32 CpuIndex, ROOT_VMX_STATE * RootState);
extern STM_STATUS SmiVmcallStopHandler (IN UINT32 Index, IN UINT64 AddressParameter);
static UINT32 HandleTimer = 0;
static UINT32 HandleSmi = 0;
@ -45,6 +47,15 @@ UINT32 PeSmiHandler(UINT32 CpuIndex)
InterlockedCompareExchange32(&PeSmiControl.PeSmiState, PESMINULL, PESMIHSMI);
//DEBUG((EFI_D_INFO, "%ld PeSmiHandler - CurrPeSmiState %ld\n", CpuIndex, PeSmiControl.PeSmiState));
if (mHostContextCommon.StmShutdown == 1)
{
// we shutdown any processor who comes here as it seems that the
// kernel got it wrong somehow - this has happened in testing...
DEBUG((EFI_D_INFO, "%ld PeSmiHandler - Shutting down STM from SMI\n", CpuIndex));
SmiVmcallStopHandler (CpuIndex, 0);
return 0;
}
if(PeSmiControl.PeCpuIndex == (INT32)CpuIndex ) // when the pe/vm comes in...
{
#if 0
@ -132,6 +143,11 @@ UINT32 PeSmiHandler(UINT32 CpuIndex)
{
InterlockedCompareExchange32(&PeSmiControl.PeWaitTimer, 1, 0);
StopPeriodicTimer();
if (mHostContextCommon.StmShutdown == 1)
{
DEBUG((EFI_D_INFO, "%ld PeSmiHandler - Shutting down STM/PE\n"));
SmiVmcallStopHandler (CpuIndex, 0);
}
// start the VM/PE
PeVmData[PeType].StartMode = PEVM_PRESTART_SMI; // starting from SMI

View File

@ -22,6 +22,7 @@ extern VOID EptDumpPageTable (IN EPT_POINTER *EptPointer );
extern PE_SMI_CONTROL PeSmiControl;
extern void SetSwSmiTimerRate(UINT16 value);
extern void StartSwSmiTimer(void);
extern UINT32 VMPE_Terminate(UINT32 CpuIndex);
/**
@ -126,12 +127,13 @@ SmiVmcallStopHandler (
//
// Launch SMM Teardown handler.
//
DEBUG ((EFI_D_INFO, "STM_API_STOP:\n"));
DEBUG ((EFI_D_INFO, "%ld STM_API_STOP:\n", Index));
VMPE_Terminate(Index);
SmmTeardown (Index);
WriteUnaligned32 ((UINT32 *)&Reg->Rax, STM_SUCCESS);
VmWriteN (VMCS_N_GUEST_RFLAGS_INDEX, VmReadN(VMCS_N_GUEST_RFLAGS_INDEX) & ~RFLAGS_CF);
StmTeardown (Index);
DEBUG((EFI_D_INFO, "CpuDeadLoop\n"));
DEBUG((EFI_D_INFO, "%ld CpuDeadLoop\n", Index));
CpuDeadLoop ();
return STM_SUCCESS;
@ -1021,7 +1023,7 @@ SmiVmcallHandler (
STM_STATUS Status;
STM_VMCALL_HANDLER StmVmcallHandler;
UINT64 AddressParameter;
//DEBUG((EFI_D_ERROR, "%ld SmiVmcallHandler - entereda\n", Index));
DEBUG((EFI_D_ERROR, "%ld SmiVmcallHandler - entereda\n", Index));
Reg = &mGuestContextCommonSmi.GuestContextPerCpu[Index].Register;
StmVmcallHandler = GetSmiVmcallHandlerByIndex (ReadUnaligned32 ((UINT32 *)&Reg->Rax));