Code cleanup - PeLoadVm.c

This commit is contained in:
Eugene D Myers 2020-04-29 16:37:48 -04:00
parent 71f2de651d
commit 50475a6f18
1 changed files with 282 additions and 162 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
@ -127,39 +129,50 @@ void LaunchPeVm(UINT32 PeType, UINT32 CpuIndex)
if(0 >= EndSize)
{
DEBUG((EFI_D_ERROR, "%ld LaunchPeVM - VM/PE heap space not cleared because of DoNotClearSize too large\n", CpuIndex));
DEBUG((EFI_D_ERROR,
"%ld LaunchPeVM - VM/PE heap space not cleared because of DoNotClearSize too large\n",
CpuIndex));
}
else
{
DEBUG((EFI_D_ERROR, "%ld LaunchPeVm - Clearing VM/PE heap space: 0x%016llx:0x%016llx\n", CpuIndex, StartEndBlock, EndSize ));
DEBUG((EFI_D_INFO,
"%ld LaunchPeVm - Clearing VM/PE heap space: 0x%016llx:0x%016llx\n",
CpuIndex,
StartEndBlock,
EndSize ));
ZeroMem ((VOID *)(UINTN)StartEndBlock, EndSize);
}
}
// 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
DEBUG((EFI_D_ERROR, "%ld LaunchPeVm - before check PeSmiState: %ld\n", CpuIndex, PeSmiControl.PeSmiState));
DEBUG((EFI_D_INFO,
"%ld LaunchPeVm - before check PeSmiState: %ld\n",
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
DEBUG((EFI_D_ERROR,"%ld LaunchPeVM - SMI being processed - faking NMI - PeSmiState: %ld\n", CpuIndex, PeSmiControl.PeSmiState));
//InterlockedCompareExchange32(&PeSmiControl.PeSmiState, 2, 0); // reset to zero
//save_Inter_PeVm(CpuIndex);
//DEBUG((EFI_D_ERROR, "%ld LaunchPeVM - Return from non-returnable function\n", CpuIndex));
//NMIReceived = 2; // If an SMI happens we receive two NMI's so fake it
DEBUG((EFI_D_INFO,
"%ld LaunchPeVM - SMI being processed - faking NMI - PeSmiState: %ld\n",
CpuIndex,
PeSmiControl.PeSmiState));
}
else
{
@ -172,77 +185,113 @@ void LaunchPeVm(UINT32 PeType, UINT32 CpuIndex)
// Set InitialStack pointer to the top of User memory...
InitStackPointer = (UINTN) PeVmData[PeType].UserModule.AddressSpaceStart + (UINTN) PeVmData[PeType].UserModule.AddressSpaceSize - (UINTN) 16;
InitStackPointer = (UINTN) PeVmData[PeType].UserModule.AddressSpaceStart +
(UINTN) PeVmData[PeType].UserModule.AddressSpaceSize -
(UINTN) 16;
VmWriteN (VMCS_N_GUEST_RSP_INDEX, InitStackPointer);
DEBUG((EFI_D_ERROR, "%ld LaunchPeVm- IntialStackPointer: 0x%llx\n", CpuIndex, InitStackPointer));
DEBUG((EFI_D_ERROR, "%ld LaunchPeVm- VMCS_N_GUEST_RFLAGS_INDEX: %08llx\n", CpuIndex, VmReadN(VMCS_N_GUEST_RFLAGS_INDEX)));
DEBUG((EFI_D_ERROR, "%ld LaunchPeVm- IA32_EFER_MSR: 0x%llx\n", CpuIndex, AsmReadMsr64 (IA32_EFER_MSR_INDEX)));
DEBUG((EFI_D_ERROR, "%ld LaunchPeVm- VMCS_32_CONTROL_PIN_BASED_VM_EXECUTION_INDEX: 0x%llx\n", CpuIndex, VmRead32(VMCS_32_CONTROL_PIN_BASED_VM_EXECUTION_INDEX)));
DEBUG((EFI_D_INFO,
"%ld LaunchPeVm- IntialStackPointer: 0x%llx\n",
CpuIndex,
InitStackPointer));
DEBUG((EFI_D_INFO,
"%ld LaunchPeVm- VMCS_N_GUEST_RFLAGS_INDEX: %08llx\n",
CpuIndex,
VmReadN(VMCS_N_GUEST_RFLAGS_INDEX)));
DEBUG((EFI_D_INFO,
"%ld LaunchPeVm- IA32_EFER_MSR: 0x%llx\n",
CpuIndex,
AsmReadMsr64 (IA32_EFER_MSR_INDEX)));
DEBUG((EFI_D_INFO,
"%ld LaunchPeVm- VMCS_32_CONTROL_PIN_BASED_VM_EXECUTION_INDEX: 0x%llx\n",
CpuIndex,
VmRead32(VMCS_32_CONTROL_PIN_BASED_VM_EXECUTION_INDEX)));
DEBUG((EFI_D_ERROR, "%ld LaunchPeVm- guest parameter regs:\n RBX: %p (shared page)\n RCX: %p (region list)\n RDX: %p (shared STM)\n",
DEBUG((EFI_D_INFO, "%ld LaunchPeVm- guest parameter regs:\n RBX: %p (shared page)\n RCX: %p (region list)\n RDX: %p (shared STM)\n",
CpuIndex,
mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register.Rbx,
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_ERROR, "%ld LaunchPeVM - Initiating PE/VM run number: %d\n",
DEBUG((EFI_D_INFO, "%ld LaunchPeVM - Initiating PE/VM run number: %d\n",
CpuIndex,
PeVmData[PeType].UserModule.RunCount));
DEBUG((EFI_D_ERROR, "%ld LaunchPeVM - SharedPageStm 0x%016llx 0x%016llx\n",
DEBUG((EFI_D_INFO, "%ld LaunchPeVM - SharedPageStm 0x%016llx 0x%016llx\n",
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_ERROR, "%ld LaunchPeVm - ***Debug*** VmPE ready for launch PeType %d registers-address: 0x%016llx\n",
CpuIndex, PeType, &mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register ));
DEBUG((EFI_D_INFO,
"%ld LaunchPeVm - ***Debug*** 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, PESMIPNMI, PESMIHSMI) == PESMIHSMI)
if(InterlockedCompareExchange32(&PeSmiControl.PeSmiState, PESMIPNMI, PESMIHSMI) == PESMIHSMI)
{
// if we are here, then an SMI has come in and the system is processing it
// we need to get out and let the system process the SMI and then restart
// PeSmiState = 2 means that the other processors are waitng for us to sync up
// so synch and then save up the state for when the processors come out of the SMI
// PeSmiState = 2 means that the other processors are waitng for us
// to sync up
// so synch and then save up the state for when the processors
// come out of the SMI
DEBUG((EFI_D_INFO,"%ld LaunchPeVM - SMI detected during build - delaying launch to handle SMI\n",
CpuIndex));
DEBUG((EFI_D_ERROR,"%ld LaunchPeVM - SMI detected during build - delaying launch to handle SMI\n", CpuIndex));
//CpuReadySync(CpuIndex); // synch up
save_Inter_PeVm(CpuIndex);
DEBUG((EFI_D_ERROR, "%ld LaunchPeVM - Warning: Return from non-returnable function\n", CpuIndex));
DEBUG((EFI_D_INFO, "%ld LaunchPeVM - Warning: Return from non-returnable function\n",
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_ERROR,"%ld LaunchPeVM - NMI detected during build - delaying launch to handle SMI\n", CpuIndex));
DEBUG((EFI_D_INFO,
"%ld LaunchPeVM - NMI detected during build - delaying launch to handle SMI\n",
CpuIndex));
save_Inter_PeVm(CpuIndex);
DEBUG((EFI_D_ERROR, "%ld LaunchPeVM - Warning: Return from non-returnable function\n", CpuIndex));
DEBUG((EFI_D_ERROR, "%ld LaunchPeVM - Warning: Return from non-returnable function\n",
CpuIndex));
// this function should not return
}
DEBUG((EFI_D_ERROR, "%ld LaunchPeVM - Launching PE/VM - NMIReceived: %d\n", CpuIndex, NMIReceived));
DEBUG((EFI_D_INFO, "%ld LaunchPeVM - Launching PE/VM - NMIReceived: %d\n",
CpuIndex,
NMIReceived));
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)));
@ -254,13 +303,19 @@ void LaunchPeVm(UINT32 PeType, UINT32 CpuIndex)
AcquireSpinLock (&mHostContextCommon.DebugLock);
DEBUG ((EFI_D_ERROR, "%ld LaunchPeVm - !!!ResumeGuestSmm 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 - VMCS_32_RO_VM_INSTRUCTION_ERROR: %08x\n",
DEBUG ((EFI_D_ERROR,
"%ld LaunchPeVm - !!!ResumeGuestSmm fail for PeVm!!!\n",
CpuIndex));
DEBUG ((EFI_D_ERROR,
"%ld LaunchPeVm - Rflags: (UINTN)CpuIndex, %08llx\n",
(UINTN)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)));
DumpVmcsAllField (CpuIndex);
DumpRegContext (&mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register, CpuIndex);
DumpRegContext (&mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register,
CpuIndex);
ReleaseSpinLock (&mHostContextCommon.DebugLock);
}
@ -274,22 +329,28 @@ STM_STATUS RunPermVM(UINT32 CpuIndex)
// (for now) start the VM...
DEBUG((EFI_D_ERROR, "%ld RunPermVM entered\n", CpuIndex));
//VmWriteN (VMCS_N_GUEST_RIP_INDEX, VmReadN (VMCS_N_GUEST_RIP_INDEX) + VmRead32 (VMCS_32_RO_VMEXIT_INSTRUCTION_LENGTH_INDEX));
DEBUG((EFI_D_INFO, "%ld RunPermVM entered\n", CpuIndex));
if(PeVmData[PeType].PeVmState != PE_VM_IDLE )
{
DEBUG((EFI_D_ERROR, "%ld RunPermVM - Can not run a Perm PE/VM\n", CpuIndex));
DEBUG((EFI_D_ERROR,
"%ld RunPermVM - Can not run a Perm PE/VM\n",
CpuIndex));
if((PeVmData[PeType].PeVmState == PE_VM_ACTIVE) ||
(PeVmData[PeType].PeVmState == PE_VM_SUSPEND))
{
rc = PE_VM_EXECUTING;
DEBUG((EFI_D_ERROR, "%ld RunPermVM - Attempting to execute an already running Perm PE/VM\n", CpuIndex));
DEBUG((EFI_D_ERROR,
"%ld RunPermVM - Attempting to execute an already running Perm PE/VM\n",
CpuIndex));
}
else
{
rc = PE_VM_NO_PERM_VM;
DEBUG((EFI_D_ERROR, "%ld RunPermVM - Attempt to execute a non-existant PE/VM state: %d\n", CpuIndex, PeVmData[PeType].PeVmState));
DEBUG((EFI_D_ERROR,
"%ld RunPermVM - Attempt to execute a non-existant PE/VM state: %d\n",
CpuIndex,
PeVmData[PeType].PeVmState));
}
return rc;
}
@ -307,14 +368,14 @@ 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
{
DEBUG((EFI_D_ERROR, "%ld - Error in configuring PE VM\n", CpuIndex));
//FreePE_DataStructures(PeType);
//setPEerrorCode(rc, StmVmm); // tell the caller of the problem
//StmVmm->NonSmiHandler = 0; // no longer an PE VM
PeVmData[PeType].PeVmState = PE_VM_AVAIL;
return(rc);
}
@ -350,11 +411,26 @@ UINT32 PostPeVmProc(UINT32 rc, UINT32 CpuIndex, UINT32 mode)
Scale = MultU64x32(PlatformData.Bits.MaxNonTurboRatio, 100000);
TotalScaleTime = DivU64x32(TotalPeTime, (UINT32) Scale);
DEBUG((EFI_D_ERROR, "%ld PostPeVmProc - Platform Data - Max Ratio: %d\n", CpuIndex, PlatformData.Bits.MaxNonTurboRatio));
DEBUG((EFI_D_ERROR, "%ld PostPeVmProc - TSC Info - StartPeTimeStamp: %ld EndTimeStamp: %ld\n", CpuIndex, StartPeTimeStamp, EndTimeStamp));
DEBUG((EFI_D_ERROR, "%ld PostPeVmProc - PeType: %d mode: %d PE clocktime: %ld runtime(scaled): %ldms\n", CpuIndex, PeType, mode, TotalPeTime, TotalScaleTime));
DEBUG((EFI_D_INFO,
"%ld PostPeVmProc - Platform Data - Max Ratio: %d\n",
CpuIndex,
PlatformData.Bits.MaxNonTurboRatio));
DEBUG((EFI_D_INFO,
"%ld PostPeVmProc - TSC Info - StartPeTimeStamp: %ld EndTimeStamp: %ld\n",
CpuIndex,
StartPeTimeStamp,
EndTimeStamp));
DEBUG((EFI_D_INFO,
"%ld PostPeVmProc - PeType: %d mode: %d PE clocktime: %ld runtime(scaled): %ldms\n",
CpuIndex,
PeType,
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:
@ -370,14 +446,18 @@ 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;
DEBUG((EFI_D_ERROR, "%ld PostPeVmProc - Perm VM configured to be released after crash\n", CpuIndex));
DEBUG((EFI_D_INFO,
"%ld PostPeVmProc - Perm VM configured to be released after crash\n",
CpuIndex));
}
else
{
@ -401,22 +481,28 @@ 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_ERROR, "%ld PostPeVmProc - Perm VM configured to run only once\n", CpuIndex));
PeSmiControl.PeCpuIndex = -1; // indicate none functioning at this momemnet
DEBUG((EFI_D_ERROR,
"%ld PostPeVmProc - Perm VM configured to run only once\n",
CpuIndex));
// 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_ERROR, "%ld PostPeVmProc - Perm VM being setup for Timer interrupt\n", CpuIndex));
DEBUG((EFI_D_INFO, "%ld PostPeVmProc - Perm VM being setup for Timer interrupt\n",
CpuIndex));
PeSmiControl.PeCpuIndex = CpuIndex;
//
//InitCpuReadySync(); // Setup the locking
PeSmiControl.PeWaitTimer = 1;
PeVmData[PeType].PeVmState = PE_VM_IDLE;
@ -435,10 +521,15 @@ UINT32 PostPeVmProc(UINT32 rc, UINT32 CpuIndex, UINT32 mode)
// suspending PE/VM so that SMI handler can run
PeVmData[PeType].PeVmState = PE_VM_SUSPEND;
DEBUG((EFI_D_ERROR, "%ld PostPeVmProc - PE/VM suspended - PeType: %ld\n", CpuIndex, PeType));
DEBUG((EFI_D_INFO,
"%ld PostPeVmProc - PE/VM suspended - PeType: %ld\n",
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);
@ -447,48 +538,16 @@ UINT32 PostPeVmProc(UINT32 rc, UINT32 CpuIndex, UINT32 mode)
AsmVmClear(&mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Vmcs);
DEBUG ((EFI_D_ERROR, "%ld PostPeVmProc - !!exiting to allow SMI to fire to Enter SmiHandler\n", CpuIndex));
DEBUG ((EFI_D_INFO,
"%ld PostPeVmProc - !!exiting to allow SMI to fire to Enter SmiHandler\n",
CpuIndex));
mHostContextCommon.HostContextPerCpu[CpuIndex].GuestVmType = SMI_HANDLER;
#ifdef OLDWAY
// set the SMI/Handler VMCS intoplace (note copied the Intel code - need to fix duplication...
STM_PERF_START (CpuIndex, 0, "WriteSyncSmmStateSaveArea", "SmiEventHandler");
WriteSyncSmmStateSaveArea (CpuIndex);
STM_PERF_END (CpuIndex, "WriteSyncSmmStateSaveArea", "SmiEventHandler");
AsmVmPtrStore (&mGuestContextCommonSmi.GuestContextPerCpu[CpuIndex].Vmcs);
Rflags = AsmVmPtrLoad (&mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Vmcs);
if ((Rflags & (RFLAGS_CF | RFLAGS_ZF)) != 0) {
DEBUG ((EFI_D_ERROR, "%ld PostPeVmProc - ERROR: AsmVmPtrLoad - %016lx : %08x\n", (UINTN)CpuIndex, mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Vmcs, Rflags));
DEBUG((EFI_D_ERROR, "%ld, PostPeVmProc - CpuDeadLoop\n", CpuIndex));
CpuDeadLoop ();
}
VmWriteN (VMCS_N_GUEST_RIP_INDEX, (UINTN)mHostContextCommon.HostContextPerCpu[CpuIndex].TxtProcessorSmmDescriptor->SmmSmiHandlerRip);
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) {
Rflags = AsmVmResume (&mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register);
// BUGBUG: - AsmVmLaunch if AsmVmResume fail
if (VmRead32 (VMCS_32_RO_VM_INSTRUCTION_ERROR_INDEX) == VmxFailErrorVmResumeWithNonLaunchedVmcs) {
// DEBUG ((EFI_D_ERROR, "(STM):-(\n", (UINTN)Index));
Rflags = AsmVmLaunch (&mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Register);
}
} else {
mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Launched = TRUE;
Rflags = AsmVmLaunch (&mGuestContextCommonSmm[0].GuestContextPerCpu[CpuIndex].Register);
mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Launched = FALSE;
}
#endif
/**/
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);
}
@ -512,12 +571,15 @@ UINT32 PostPeVmProc(UINT32 rc, UINT32 CpuIndex, UINT32 mode)
{
// fixup return address
DEBUG((EFI_D_ERROR, "%ld PostPeVmProc - PE/VM guest return address bumped\n", CpuIndex));
VmWriteN (VMCS_N_GUEST_RIP_INDEX, VmReadN (VMCS_N_GUEST_RIP_INDEX) + VmRead32 (VMCS_32_RO_VMEXIT_INSTRUCTION_LENGTH_INDEX));
DEBUG((EFI_D_ERROR,
"%ld PostPeVmProc - PE/VM guest return address bumped\n",
CpuIndex));
VmWriteN (VMCS_N_GUEST_RIP_INDEX,
VmReadN (VMCS_N_GUEST_RIP_INDEX) +
VmRead32 (VMCS_32_RO_VMEXIT_INSTRUCTION_LENGTH_INDEX));
}
}
//DEBUG((EFI_D_ERROR, "%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)
{
@ -526,17 +588,20 @@ 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, PeType));
DEBUG((EFI_D_INFO,
"%ld PostPeVmProc - PE/VM Free (AVAIL) - PeType: %ld\n",
CpuIndex,
PeType));
}
else
{
// mark this VM as idle
PeVmData[PeType].PeVmState = PE_VM_IDLE; // Waiting for more actio
DEBUG((EFI_D_INFO, "%ld PostPeVmProc - PE/VM Idle - PeType: %ld\n", CpuIndex, PeType));
DEBUG((EFI_D_INFO,
"%ld PostPeVmProc - PE/VM Idle - PeType: %ld\n",
CpuIndex,
PeType));
}
if(PeVmData[PeType].StartMode == PEVM_START_VMCALL)
@ -548,18 +613,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_ERROR, "%ld PostPeVmProc - Unsucessful return noted in RFLAGS_CF\n", CpuIndex));
VmWriteN (VMCS_N_GUEST_RFLAGS_INDEX, VmReadN(VMCS_N_GUEST_RFLAGS_INDEX) | RFLAGS_CF);
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);
}
}
mHostContextCommon.HostContextPerCpu[CpuIndex].GuestVmType = SMI_HANDLER;
DEBUG((EFI_D_INFO, "%ld PostPeVmProc - sucessfully completed - RC: 0x%x\n", CpuIndex, rc));
//StopSwTimer();
DEBUG((EFI_D_INFO,
"%ld PostPeVmProc - sucessfully completed - RC: 0x%x\n",
CpuIndex,
rc));
CheckPendingMtf (CpuIndex);
//
@ -567,29 +638,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, "%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 - !!!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
}
@ -628,13 +714,17 @@ 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;
mHostContextCommon.HostContextPerCpu[CpuIndex].NonSmiHandler = PeType; // let the STM know that we are waiting to come back
// let the STM know that we are waiting to come back
mHostContextCommon.HostContextPerCpu[CpuIndex].NonSmiHandler = PeType;
EndTimeStamp = AsmReadTsc();
DEBUG((EFI_D_ERROR, "%ld save_Inter_PeVm - sucessfully completed\n", CpuIndex));
DEBUG((EFI_D_INFO,
"%ld save_Inter_PeVm - sucessfully completed\n",
CpuIndex));
PostPeVmProc(PE_SUCCESS, CpuIndex, SUSPEND_VM);
@ -652,12 +742,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
{
@ -666,36 +762,49 @@ UINT32 RestoreInterPeVm(UINT32 CpuIndex, UINT32 PeType)
}
}
if(InterlockedCompareExchange32(&PeSmiControl.PeSmiState, PESMIHSMI, PESMIHSMI) == PESMIHSMI)
if(InterlockedCompareExchange32(&PeSmiControl.PeSmiState,
PESMIHSMI, PESMIHSMI) == PESMIHSMI)
{
DEBUG((EFI_D_ERROR, "%ld RestoreInterPeVm - SMI in progress - aborting PE/VM restart\n", CpuIndex));
DEBUG((EFI_D_INFO,
"%ld RestoreInterPeVm - SMI in progress - aborting PE/VM restart\n",
CpuIndex));
return 1;
}
// 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
AsmVmPtrLoad(&mGuestContextCommonSmm[PeType].GuestContextPerCpu[0].Vmcs);
mHostContextCommon.HostContextPerCpu[CpuIndex].GuestVmType = PeType;
DEBUG((EFI_D_ERROR, "%ld RestoreInterPeVm - setup done, launching PE/VM\n", CpuIndex));
DEBUG((EFI_D_INFO, "%ld RestoreInterPeVm - setup done, launching PE/VM\n",
CpuIndex));
// Launch back
//
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);
}
@ -714,22 +823,28 @@ void print_region_list(UINT32 PeType, UINT32 CpuIndex)
if(rlist == NULL)
{
DEBUG((EFI_D_ERROR, "%ld - No region list\n", CpuIndex));
DEBUG((EFI_D_INFO, "%ld - No region list\n", CpuIndex));
return;
}
DEBUG((EFI_D_ERROR, "%ld --- Region List --- \n", CpuIndex));
DEBUG((EFI_D_INFO, "%ld --- Region List --- \n", CpuIndex));
for(counter = 0; counter < (4096/sizeof(PE_REGION_LIST)); counter++)
{
if(rlist[counter].Address == (UINT64) 0)
{
DEBUG((EFI_D_ERROR, "%ld Finish scanning Region List - %d elements found\n", CpuIndex, counter));
DEBUG((EFI_D_INFO, "%ld Finish scanning Region List - %d elements found\n",
CpuIndex,
counter));
break; // done at end of list
}
EndAddress = rlist[counter].Address + rlist[counter].Size;
DEBUG((EFI_D_ERROR, "%ld region set at 0x%016llx:%016llx - size 0x%016lx\n", CpuIndex, rlist[counter].Address, EndAddress, rlist[counter].Size));
DEBUG((EFI_D_INFO, "%ld region set at 0x%016llx:%016llx size 0x%016lx\n",
CpuIndex,
rlist[counter].Address,
EndAddress,
rlist[counter].Size));
}
}
@ -744,7 +859,7 @@ void enable_nmi()
// the interrupt is fired
while(NMIReceived == 0) {} // wait for NMI interrupt
DEBUG((EFI_D_ERROR, "NMI handler active\n"));
DEBUG((EFI_D_INFO, "NMI handler active\n"));
}
VOID
@ -755,19 +870,24 @@ VOID
)
{
NMIReceived = NMIReceived + 1; // increment
DEBUG((EFI_D_ERROR, "***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_ERROR, "%ld enable_nmi - Return from non-returnable function\n", CpuIndex));
DEBUG((EFI_D_INFO,
"%ld enable_nmi - Return from non-returnable function\n",
CpuIndex));
// this function should not return...
}
@ -806,5 +926,5 @@ void InitPe()
InitializeSpinLock (&PeSmiControl.PeSmiControlLock);
DEBUG((EFI_D_ERROR, "InitPe - PE initialization complete\n"));
DEBUG((EFI_D_INFO, "InitPe - PE initialization complete\n"));
}