mirror of https://review.coreboot.org/STM.git
364 lines
21 KiB
C
364 lines
21 KiB
C
/** @file
|
|
VMCS initialization
|
|
|
|
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
|
|
This program and the accompanying materials
|
|
are licensed and made available under the terms and conditions of the BSD License
|
|
which accompanies this distribution. The full text of the license may be found at
|
|
http://opensource.org/licenses/bsd-license.php.
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
**/
|
|
|
|
#include "StmInit.h"
|
|
#include "PeStm.h"
|
|
|
|
//#define COREBOOT32 // coreboot support
|
|
/**
|
|
|
|
This function initialize VMCS for SMI.
|
|
|
|
NOTE: We should not trust VMCS setting by MLE,so we need reinit them to make
|
|
sure the data is valid.
|
|
|
|
@param Index CPU index
|
|
@param Vmcs VMCS pointer
|
|
|
|
**/
|
|
VOID
|
|
InitializeSmiVmcs (
|
|
IN UINT32 Index,
|
|
IN UINT64 *Vmcs
|
|
)
|
|
{
|
|
UINT64 Data64;
|
|
VM_EXIT_CONTROLS VmExitCtrls;
|
|
VM_ENTRY_CONTROLS VmEntryCtrls;
|
|
GUEST_INTERRUPTIBILITY_STATE GuestInterruptibilityState;
|
|
VM_EXIT_MSR_ENTRY *VmExitMsrEntry;
|
|
|
|
Data64 = AsmReadMsr64 (IA32_VMX_ENTRY_CTLS_MSR_INDEX);
|
|
VmEntryCtrls.Uint32 = (UINT32)Data64 & (UINT32)RShiftU64 (Data64, 32);
|
|
VmEntryCtrls.Bits.Ia32eGuest = (sizeof(UINT64) == sizeof(UINTN));
|
|
VmEntryCtrls.Bits.DeactivateDualMonitor = 0;
|
|
// Upon receiving control due to an SMI, the STM shall save the contents of the IA32_PERF_GLOBAL_CTRL MSR, disable any
|
|
// enabled bits in the IA32_PERF_GLOBAL_CTRL MSR
|
|
VmEntryCtrls.Bits.LoadIA32_PERF_GLOBAL_CTRL = 0;
|
|
VmEntryCtrls.Bits.LoadIA32_EFER = 1;
|
|
|
|
Data64 = AsmReadMsr64 (IA32_VMX_EXIT_CTLS_MSR_INDEX);
|
|
VmExitCtrls.Uint32 = (UINT32)Data64 & (UINT32)RShiftU64 (Data64, 32);
|
|
VmExitCtrls.Bits.Ia32eHost = (sizeof(UINT64) == sizeof(UINTN));
|
|
VmExitCtrls.Bits.SaveVmxPreemptionTimerValue = 1; // Save VmxPreemptionTimer
|
|
// Upon receiving control due to an SMI, the STM shall save the contents of the IA32_PERF_GLOBAL_CTRL MSR, disable any
|
|
// enabled bits in the IA32_PERF_GLOBAL_CTRL MSR
|
|
VmExitCtrls.Bits.LoadIA32_PERF_GLOBAL_CTRL = 0;
|
|
VmExitCtrls.Bits.SaveIA32_EFER = 1;
|
|
|
|
GuestInterruptibilityState.Uint32 = VmRead32 (VMCS_32_GUEST_INTERRUPTIBILITY_STATE_INDEX);
|
|
|
|
if(Index != 0)
|
|
{
|
|
GuestInterruptibilityState.Bits.BlockingBySmi = 0;
|
|
}
|
|
else
|
|
{
|
|
GuestInterruptibilityState.Bits.BlockingBySmi = 1; // BSP has to do other stuff before interrupts are enabled
|
|
}
|
|
|
|
//
|
|
// Control field
|
|
//
|
|
VmWrite32 (VMCS_32_CONTROL_VMENTRY_CONTROLS_INDEX, VmEntryCtrls.Uint32);
|
|
VmWrite32 (VMCS_32_CONTROL_VMEXIT_CONTROLS_INDEX, VmExitCtrls.Uint32);
|
|
|
|
//
|
|
// Make sure the value is valid
|
|
//
|
|
VmWrite32 (VMCS_32_CONTROL_VMEXIT_MSR_STORE_COUNT_INDEX, mGuestContextCommonSmi.GuestContextPerCpu[Index].GuestMsrEntryCount);
|
|
VmWrite32 (VMCS_32_CONTROL_VMEXIT_MSR_LOAD_COUNT_INDEX, mHostContextCommon.HostContextPerCpu[Index].HostMsrEntryCount);
|
|
VmWrite32 (VMCS_32_CONTROL_VMENTRY_MSR_LOAD_COUNT_INDEX, mGuestContextCommonSmi.GuestContextPerCpu[Index].GuestMsrEntryCount);
|
|
//
|
|
// Upon receiving control due to an SMI, the STM shall save the contents of the IA32_PERF_GLOBAL_CTRL MSR, disable any
|
|
// enabled bits in the IA32_PERF_GLOBAL_CTRL MSR.
|
|
// Do we need handle IA32_PEBS_ENABLE MSR ???
|
|
//
|
|
VmExitMsrEntry = (VM_EXIT_MSR_ENTRY *)(UINTN)mHostContextCommon.HostContextPerCpu[Index].HostMsrEntryAddress;
|
|
VmExitMsrEntry[0].MsrIndex = IA32_PERF_GLOBAL_CTRL_MSR_INDEX;
|
|
VmExitMsrEntry[0].MsrData = 0;
|
|
VmExitMsrEntry = (VM_EXIT_MSR_ENTRY *)(UINTN)mGuestContextCommonSmi.GuestContextPerCpu[Index].GuestMsrEntryAddress;
|
|
VmExitMsrEntry[0].MsrIndex = IA32_PERF_GLOBAL_CTRL_MSR_INDEX;
|
|
VmExitMsrEntry[0].MsrData = AsmReadMsr64(IA32_PERF_GLOBAL_CTRL_MSR_INDEX);
|
|
VmWrite64 (VMCS_64_CONTROL_VMEXIT_MSR_STORE_INDEX, mGuestContextCommonSmi.GuestContextPerCpu[Index].GuestMsrEntryAddress);
|
|
VmWrite64 (VMCS_64_CONTROL_VMEXIT_MSR_LOAD_INDEX, mHostContextCommon.HostContextPerCpu[Index].HostMsrEntryAddress);
|
|
VmWrite64 (VMCS_64_CONTROL_VMENTRY_MSR_LOAD_INDEX, mGuestContextCommonSmi.GuestContextPerCpu[Index].GuestMsrEntryAddress);
|
|
|
|
//
|
|
// Host field
|
|
//
|
|
VmWriteN (VMCS_N_HOST_CR0_INDEX, AsmReadCr0 ());
|
|
VmWriteN (VMCS_N_HOST_CR3_INDEX, mHostContextCommon.PageTable);
|
|
VmWriteN (VMCS_N_HOST_CR4_INDEX, AsmReadCr4 ());
|
|
VmWrite16 (VMCS_16_HOST_ES_INDEX, AsmReadDs ());
|
|
VmWrite16 (VMCS_16_HOST_CS_INDEX, AsmReadCs ());
|
|
VmWrite16 (VMCS_16_HOST_SS_INDEX, AsmReadDs ());
|
|
VmWrite16 (VMCS_16_HOST_DS_INDEX, AsmReadDs ());
|
|
VmWrite16 (VMCS_16_HOST_FS_INDEX, AsmReadDs ());
|
|
VmWrite16 (VMCS_16_HOST_GS_INDEX, AsmReadDs ());
|
|
VmWrite16 (VMCS_16_HOST_TR_INDEX, AsmReadDs ());
|
|
VmWriteN (VMCS_N_HOST_TR_BASE_INDEX, 0);
|
|
VmWriteN (VMCS_N_HOST_GDTR_BASE_INDEX, mHostContextCommon.Gdtr.Base);
|
|
VmWriteN (VMCS_N_HOST_IDTR_BASE_INDEX, mHostContextCommon.Idtr.Base);
|
|
VmWriteN (VMCS_N_HOST_RSP_INDEX, mHostContextCommon.HostContextPerCpu[Index].Stack);
|
|
VmWriteN (VMCS_N_HOST_RIP_INDEX, (UINTN)AsmHostEntrypointSmi);
|
|
|
|
VmWrite64 (VMCS_64_HOST_IA32_PERF_GLOBAL_CTRL_INDEX, 0);
|
|
|
|
//
|
|
// Guest field
|
|
//
|
|
VmWriteN (VMCS_N_GUEST_RIP_INDEX, VmReadN (VMCS_N_GUEST_RIP_INDEX) + VmRead32(VMCS_32_RO_VMEXIT_INSTRUCTION_LENGTH_INDEX));
|
|
VmWriteN (VMCS_N_GUEST_RFLAGS_INDEX, 0x00000002); // VMCALL success
|
|
VmWrite32 (VMCS_32_GUEST_INTERRUPTIBILITY_STATE_INDEX, GuestInterruptibilityState.Uint32);
|
|
|
|
VmWrite64 (VMCS_64_GUEST_IA32_PERF_GLOBAL_CTRL_INDEX, AsmReadMsr64(IA32_PERF_GLOBAL_CTRL_MSR_INDEX));
|
|
|
|
VmWrite64 (VMCS_64_GUEST_IA32_EFER_INDEX, mGuestContextCommonSmi.GuestContextPerCpu[Index].Efer);
|
|
|
|
return ;
|
|
}
|
|
|
|
/**
|
|
|
|
This function initialize VMCS for SMM.
|
|
|
|
NOTE: We should not trust VMCS setting by MLE,so we need reinit them to make
|
|
sure the data is valid.
|
|
|
|
@param Index CPU index
|
|
@param Vmcs VMCS pointer
|
|
|
|
**/
|
|
VOID
|
|
InitializeSmmVmcs (
|
|
IN UINT32 Index,
|
|
IN UINT64 *Vmcs
|
|
)
|
|
{
|
|
UINT64 Data64;
|
|
VM_EXIT_CONTROLS VmExitCtrls;
|
|
VM_ENTRY_CONTROLS VmEntryCtrls;
|
|
VM_EXEC_PIN_BASES_VMEXIT_CONTROLS PinBasedCtls;
|
|
VM_EXEC_PROCESSOR_BASES_VMEXIT_CONTROLS ProcessorBasedCtrls;
|
|
VM_EXEC_2ND_PROCESSOR_BASES_VMEXIT_CONTROLS ProcessorBasedCtrls2nd;
|
|
GUEST_INTERRUPTIBILITY_STATE GuestInterruptibilityState;
|
|
GDT_ENTRY *GdtEntry;
|
|
VM_EXIT_MSR_ENTRY *VmExitMsrEntry;
|
|
|
|
Data64 = AsmReadMsr64 (IA32_VMX_PINBASED_CTLS_MSR_INDEX);
|
|
PinBasedCtls.Uint32 = (UINT32)Data64 & (UINT32)RShiftU64 (Data64, 32);
|
|
PinBasedCtls.Bits.ExternalInterrupt = 0; // external interrupt
|
|
PinBasedCtls.Bits.Nmi = 0;
|
|
PinBasedCtls.Bits.VmxPreemptionTimer = 0; // Timer
|
|
|
|
Data64 = AsmReadMsr64 (IA32_VMX_PROCBASED_CTLS_MSR_INDEX);
|
|
ProcessorBasedCtrls.Uint32 = (UINT32)Data64 & (UINT32)RShiftU64 (Data64, 32);
|
|
ProcessorBasedCtrls.Bits.Hlt = 0;
|
|
ProcessorBasedCtrls.Bits.InterruptWindow = 0; // interrupt window
|
|
ProcessorBasedCtrls.Bits.NmiWindow = 0;
|
|
ProcessorBasedCtrls.Bits.IoBitmap = 1;
|
|
ProcessorBasedCtrls.Bits.MsrBitmap = 1;
|
|
ProcessorBasedCtrls.Bits.SecondaryControl = 1;
|
|
|
|
Data64 = AsmReadMsr64 (IA32_VMX_PROCBASED_CTLS2_MSR_INDEX);
|
|
ProcessorBasedCtrls2nd.Uint32 = (UINT32)RShiftU64 (Data64, 32);
|
|
if (ProcessorBasedCtrls2nd.Bits.UnrestrictedGuest != 0) {
|
|
mGuestContextCommonSmm[SMI_HANDLER].GuestContextPerCpu[Index].UnrestrictedGuest = TRUE;
|
|
} else {
|
|
mGuestContextCommonSmm[SMI_HANDLER].GuestContextPerCpu[Index].UnrestrictedGuest = FALSE;
|
|
}
|
|
|
|
ProcessorBasedCtrls2nd.Uint32 = (UINT32)Data64 & (UINT32)RShiftU64 (Data64, 32);
|
|
ProcessorBasedCtrls2nd.Bits.Ept = 1;
|
|
if (mGuestContextCommonSmm[SMI_HANDLER].GuestContextPerCpu[Index].UnrestrictedGuest) {
|
|
ProcessorBasedCtrls2nd.Bits.UnrestrictedGuest = 1;
|
|
}
|
|
|
|
Data64 = AsmReadMsr64 (IA32_VMX_ENTRY_CTLS_MSR_INDEX);
|
|
VmEntryCtrls.Uint32 = (UINT32)Data64 & (UINT32)RShiftU64 (Data64, 32);
|
|
VmEntryCtrls.Bits.Ia32eGuest = mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmEntryState.Intel64Mode;
|
|
#if defined(COREBOOT32)
|
|
DEBUG((EFI_D_INFO, "Setting up SMI Handler for 32 bit mode\n"));
|
|
mGuestContextCommonSmm[SMI_HANDLER].GuestContextPerCpu[Index].Efer = 0;//mGuestContextCommonSmm[SMI_HANDLER].GuestContextPerCpu[Index].Efer & (~((1 << 9) & (1 << 10))); // turn off IA32 bits // need to find the proper defines
|
|
#endif
|
|
VmEntryCtrls.Bits.EntryToSmm = 1;
|
|
// Upon receiving control due to an SMI, the STM shall save the contents of the IA32_PERF_GLOBAL_CTRL MSR, disable any
|
|
// enabled bits in the IA32_PERF_GLOBAL_CTRL MSR
|
|
VmEntryCtrls.Bits.LoadIA32_PERF_GLOBAL_CTRL = 0;
|
|
// Need load EFER to support guest enable XD
|
|
VmEntryCtrls.Bits.LoadIA32_EFER = 1;
|
|
|
|
Data64 = AsmReadMsr64 (IA32_VMX_EXIT_CTLS_MSR_INDEX);
|
|
VmExitCtrls.Uint32 = (UINT32)Data64 & (UINT32)RShiftU64 (Data64, 32);
|
|
VmExitCtrls.Bits.Ia32eHost = (sizeof(UINT64) == sizeof(UINTN));
|
|
// Upon receiving control due to an SMI, the STM shall save the contents of the IA32_PERF_GLOBAL_CTRL MSR, disable any
|
|
// enabled bits in the IA32_PERF_GLOBAL_CTRL MSR
|
|
VmExitCtrls.Bits.LoadIA32_PERF_GLOBAL_CTRL = 0;
|
|
// Need load EFER to support guest enable XD
|
|
VmExitCtrls.Bits.SaveIA32_EFER = 1;
|
|
|
|
GuestInterruptibilityState.Uint32 = 0;
|
|
GuestInterruptibilityState.Bits.BlockingBySmi = 1;
|
|
//
|
|
// Control field
|
|
//
|
|
VmWrite32 (VMCS_32_CONTROL_PIN_BASED_VM_EXECUTION_INDEX, PinBasedCtls.Uint32);
|
|
VmWrite32 (VMCS_32_CONTROL_PROCESSOR_BASED_VM_EXECUTION_INDEX, ProcessorBasedCtrls.Uint32);
|
|
VmWrite32 (VMCS_32_CONTROL_2ND_PROCESSOR_BASED_VM_EXECUTION_INDEX, ProcessorBasedCtrls2nd.Uint32);
|
|
VmWrite32 (VMCS_32_CONTROL_EXCEPTION_BITMAP_INDEX, 0);
|
|
VmWrite32 (VMCS_32_CONTROL_VMENTRY_CONTROLS_INDEX, VmEntryCtrls.Uint32);
|
|
VmWrite32 (VMCS_32_CONTROL_VMEXIT_CONTROLS_INDEX, VmExitCtrls.Uint32);
|
|
|
|
VmWrite64 (VMCS_64_CONTROL_EPT_PTR_INDEX, mGuestContextCommonSmm[SMI_HANDLER].EptPointer.Uint64);
|
|
|
|
VmWriteN (VMCS_N_CONTROL_CR0_GUEST_HOST_MASK_INDEX, ((UINTN)AsmReadMsr64 (IA32_VMX_CR0_FIXED0_MSR_INDEX) & (UINTN)AsmReadMsr64 (IA32_VMX_CR0_FIXED1_MSR_INDEX)) | CR0_CD);
|
|
VmWriteN (VMCS_N_CONTROL_CR4_GUEST_HOST_MASK_INDEX, (UINTN)-1);
|
|
|
|
VmWriteN (VMCS_N_CONTROL_CR0_READ_SHADOW_INDEX, mGuestContextCommonSmm[SMI_HANDLER].GuestContextPerCpu[Index].Cr0 | ((UINTN)AsmReadMsr64 (IA32_VMX_CR0_FIXED0_MSR_INDEX) & (UINTN)AsmReadMsr64 (IA32_VMX_CR0_FIXED1_MSR_INDEX)));
|
|
VmWriteN (VMCS_N_CONTROL_CR4_READ_SHADOW_INDEX, mGuestContextCommonSmm[SMI_HANDLER].GuestContextPerCpu[Index].Cr4 | ((UINTN)AsmReadMsr64 (IA32_VMX_CR4_FIXED0_MSR_INDEX) & (UINTN)AsmReadMsr64 (IA32_VMX_CR4_FIXED1_MSR_INDEX)) | CR4_PAE);
|
|
|
|
if (ProcessorBasedCtrls.Bits.IoBitmap != 0) {
|
|
VmWrite64 (VMCS_64_CONTROL_IO_BITMAP_A_INDEX, mGuestContextCommonSmm[SMI_HANDLER].IoBitmapA);
|
|
VmWrite64 (VMCS_64_CONTROL_IO_BITMAP_B_INDEX, mGuestContextCommonSmm[SMI_HANDLER].IoBitmapB);
|
|
}
|
|
|
|
if (ProcessorBasedCtrls.Bits.MsrBitmap != 0) {
|
|
VmWrite64 (VMCS_64_CONTROL_MSR_BITMAP_INDEX, mGuestContextCommonSmm[SMI_HANDLER].MsrBitmap);
|
|
}
|
|
|
|
//
|
|
// Make sure the value is valid
|
|
//
|
|
VmWrite32 (VMCS_32_CONTROL_VMEXIT_MSR_STORE_COUNT_INDEX, mGuestContextCommonSmi.GuestContextPerCpu[Index].GuestMsrEntryCount);
|
|
VmWrite32 (VMCS_32_CONTROL_VMEXIT_MSR_LOAD_COUNT_INDEX, mHostContextCommon.HostContextPerCpu[Index].HostMsrEntryCount);
|
|
VmWrite32 (VMCS_32_CONTROL_VMENTRY_MSR_LOAD_COUNT_INDEX, mGuestContextCommonSmi.GuestContextPerCpu[Index].GuestMsrEntryCount);
|
|
//
|
|
// Upon receiving control due to an SMI, the STM shall save the contents of the IA32_PERF_GLOBAL_CTRL MSR, disable any
|
|
// enabled bits in the IA32_PERF_GLOBAL_CTRL MSR.
|
|
// Do we need handle IA32_PEBS_ENABLE MSR ???
|
|
//
|
|
VmExitMsrEntry = (VM_EXIT_MSR_ENTRY *)(UINTN)mHostContextCommon.HostContextPerCpu[Index].HostMsrEntryAddress;
|
|
VmExitMsrEntry[0].MsrIndex = IA32_PERF_GLOBAL_CTRL_MSR_INDEX;
|
|
VmExitMsrEntry[0].MsrData = 0;
|
|
VmExitMsrEntry = (VM_EXIT_MSR_ENTRY *)(UINTN)mGuestContextCommonSmi.GuestContextPerCpu[Index].GuestMsrEntryAddress;
|
|
VmExitMsrEntry[0].MsrIndex = IA32_PERF_GLOBAL_CTRL_MSR_INDEX;
|
|
VmExitMsrEntry[0].MsrData = AsmReadMsr64(IA32_PERF_GLOBAL_CTRL_MSR_INDEX);
|
|
VmWrite64 (VMCS_64_CONTROL_VMEXIT_MSR_STORE_INDEX, mGuestContextCommonSmi.GuestContextPerCpu[Index].GuestMsrEntryAddress);
|
|
VmWrite64 (VMCS_64_CONTROL_VMEXIT_MSR_LOAD_INDEX, mHostContextCommon.HostContextPerCpu[Index].HostMsrEntryAddress);
|
|
VmWrite64 (VMCS_64_CONTROL_VMENTRY_MSR_LOAD_INDEX, mGuestContextCommonSmi.GuestContextPerCpu[Index].GuestMsrEntryAddress);
|
|
|
|
//
|
|
// Host field
|
|
//
|
|
VmWriteN (VMCS_N_HOST_CR0_INDEX, AsmReadCr0 ());
|
|
VmWriteN (VMCS_N_HOST_CR3_INDEX, mHostContextCommon.PageTable);
|
|
VmWriteN (VMCS_N_HOST_CR4_INDEX, AsmReadCr4 ());
|
|
VmWrite16 (VMCS_16_HOST_ES_INDEX, AsmReadDs ());
|
|
VmWrite16 (VMCS_16_HOST_CS_INDEX, AsmReadCs ());
|
|
VmWrite16 (VMCS_16_HOST_SS_INDEX, AsmReadDs ());
|
|
VmWrite16 (VMCS_16_HOST_DS_INDEX, AsmReadDs ());
|
|
VmWrite16 (VMCS_16_HOST_FS_INDEX, AsmReadDs ());
|
|
VmWrite16 (VMCS_16_HOST_GS_INDEX, AsmReadDs ());
|
|
VmWrite16 (VMCS_16_HOST_TR_INDEX, AsmReadDs ());
|
|
VmWriteN (VMCS_N_HOST_TR_BASE_INDEX, 0);
|
|
VmWriteN (VMCS_N_HOST_GDTR_BASE_INDEX, mHostContextCommon.Gdtr.Base);
|
|
VmWriteN (VMCS_N_HOST_IDTR_BASE_INDEX, mHostContextCommon.Idtr.Base);
|
|
VmWriteN (VMCS_N_HOST_RSP_INDEX, mHostContextCommon.HostContextPerCpu[Index].Stack);
|
|
VmWriteN (VMCS_N_HOST_RIP_INDEX, (UINTN)AsmHostEntrypointSmm);
|
|
|
|
VmWrite64 (VMCS_64_HOST_IA32_PERF_GLOBAL_CTRL_INDEX, 0);
|
|
|
|
//
|
|
// Guest field
|
|
//
|
|
VmWriteN (VMCS_N_GUEST_CR0_INDEX, mGuestContextCommonSmm[SMI_HANDLER].GuestContextPerCpu[Index].Cr0 | ((UINTN)AsmReadMsr64 (IA32_VMX_CR0_FIXED0_MSR_INDEX) & (UINTN)AsmReadMsr64 (IA32_VMX_CR0_FIXED1_MSR_INDEX)));
|
|
VmWriteN (VMCS_N_GUEST_CR3_INDEX, (UINTN)mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmCr3);
|
|
VmWriteN (VMCS_N_GUEST_CR4_INDEX, mGuestContextCommonSmm[SMI_HANDLER].GuestContextPerCpu[Index].Cr4 | ((UINTN)AsmReadMsr64 (IA32_VMX_CR4_FIXED0_MSR_INDEX) & (UINTN)AsmReadMsr64 (IA32_VMX_CR4_FIXED1_MSR_INDEX)));
|
|
if (sizeof(UINTN) == sizeof(UINT64)) {
|
|
VmWriteN (VMCS_N_GUEST_CR4_INDEX, VmReadN(VMCS_N_GUEST_CR4_INDEX) | CR4_PAE);
|
|
} else {
|
|
if (mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmEntryState.Cr4Pae) {
|
|
VmWriteN (VMCS_N_GUEST_CR4_INDEX, VmReadN(VMCS_N_GUEST_CR4_INDEX) | CR4_PAE);
|
|
}
|
|
if (mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmEntryState.Cr4Pse) {
|
|
VmWriteN (VMCS_N_GUEST_CR4_INDEX, VmReadN(VMCS_N_GUEST_CR4_INDEX) | CR4_PSE);
|
|
}
|
|
}
|
|
#if defined(COREBOOT32) // coreboot support
|
|
#define CR0_CLEAR_FLAGS CR0_CD|CR0_NW|CR0_PG|CR0_WP|CR0_NE|CR0_TS
|
|
VmWriteN (VMCS_N_GUEST_CR0_INDEX, ((VmReadN(VMCS_N_GUEST_CR0_INDEX) & ~(CR0_PG)) | CR0_PE ));
|
|
VmWriteN (VMCS_N_GUEST_CR4_INDEX, (VmReadN(VMCS_N_GUEST_CR4_INDEX) | CR4_PAE)); // must be set because host address size vmexit control is 1
|
|
#endif
|
|
|
|
VmWriteN (VMCS_N_GUEST_LDTR_BASE_INDEX, 0);
|
|
VmWriteN (VMCS_N_GUEST_GDTR_BASE_INDEX, (UINTN)mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmGdtPtr);
|
|
VmWriteN (VMCS_N_GUEST_IDTR_BASE_INDEX, 0);
|
|
VmWriteN (VMCS_N_GUEST_RSP_INDEX, (UINTN)mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmSmiHandlerRsp);
|
|
VmWriteN (VMCS_N_GUEST_RIP_INDEX, (UINTN)mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmSmiHandlerRip);
|
|
VmWriteN (VMCS_N_GUEST_RFLAGS_INDEX, 0x00000002);
|
|
VmWriteN (VMCS_N_GUEST_PENDING_DEBUG_EXCEPTIONS_INDEX,0);
|
|
VmWriteN (VMCS_N_GUEST_IA32_SYSENTER_ESP_INDEX, 0);
|
|
VmWriteN (VMCS_N_GUEST_IA32_SYSENTER_EIP_INDEX, 0);
|
|
|
|
VmWrite16 (VMCS_16_GUEST_ES_INDEX, mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmOtherSegment);
|
|
VmWrite16 (VMCS_16_GUEST_CS_INDEX, mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmCs);
|
|
VmWrite16 (VMCS_16_GUEST_SS_INDEX, mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmSs);
|
|
VmWrite16 (VMCS_16_GUEST_DS_INDEX, mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmDs);
|
|
VmWrite16 (VMCS_16_GUEST_FS_INDEX, mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmOtherSegment);
|
|
VmWrite16 (VMCS_16_GUEST_GS_INDEX, mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmOtherSegment);
|
|
VmWrite16 (VMCS_16_GUEST_LDTR_INDEX, 0);
|
|
VmWrite16 (VMCS_16_GUEST_TR_INDEX, mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmTr);
|
|
VmWrite32 (VMCS_32_GUEST_LDTR_LIMIT_INDEX, 0);
|
|
VmWrite32 (VMCS_32_GUEST_GDTR_LIMIT_INDEX, mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmGdtSize - 1);
|
|
VmWrite32 (VMCS_32_GUEST_IDTR_LIMIT_INDEX, 0x0000ffff);
|
|
VmWrite32 (VMCS_32_GUEST_IA32_SYSENTER_CS_INDEX, 0);
|
|
VmWrite32 (VMCS_32_GUEST_LDTR_ACCESS_RIGHT_INDEX, 0x10082);
|
|
|
|
GdtEntry = (GDT_ENTRY *)((UINTN)mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmGdtPtr + mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmCs);
|
|
VmWriteN (VMCS_N_GUEST_CS_BASE_INDEX, BaseFromGdtEntry (GdtEntry));
|
|
VmWrite32 (VMCS_32_GUEST_CS_ACCESS_RIGHT_INDEX, ArFromGdtEntry (GdtEntry));
|
|
VmWrite32 (VMCS_32_GUEST_CS_LIMIT_INDEX, LimitFromGdtEntry (GdtEntry));
|
|
GdtEntry = (GDT_ENTRY *)((UINTN)mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmGdtPtr + mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmSs);
|
|
VmWriteN (VMCS_N_GUEST_SS_BASE_INDEX, BaseFromGdtEntry (GdtEntry));
|
|
VmWrite32 (VMCS_32_GUEST_SS_ACCESS_RIGHT_INDEX, ArFromGdtEntry (GdtEntry));
|
|
VmWrite32 (VMCS_32_GUEST_SS_LIMIT_INDEX, LimitFromGdtEntry (GdtEntry));
|
|
GdtEntry = (GDT_ENTRY *)((UINTN)mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmGdtPtr + mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmDs);
|
|
VmWriteN (VMCS_N_GUEST_DS_BASE_INDEX, BaseFromGdtEntry (GdtEntry));
|
|
VmWrite32 (VMCS_32_GUEST_DS_ACCESS_RIGHT_INDEX, ArFromGdtEntry (GdtEntry));
|
|
VmWrite32 (VMCS_32_GUEST_DS_LIMIT_INDEX, LimitFromGdtEntry (GdtEntry));
|
|
GdtEntry = (GDT_ENTRY *)((UINTN)mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmGdtPtr + mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmOtherSegment);
|
|
VmWriteN (VMCS_N_GUEST_ES_BASE_INDEX, BaseFromGdtEntry (GdtEntry));
|
|
VmWrite32 (VMCS_32_GUEST_ES_ACCESS_RIGHT_INDEX, ArFromGdtEntry (GdtEntry));
|
|
VmWrite32 (VMCS_32_GUEST_ES_LIMIT_INDEX, LimitFromGdtEntry (GdtEntry));
|
|
VmWriteN (VMCS_N_GUEST_FS_BASE_INDEX, BaseFromGdtEntry (GdtEntry));
|
|
VmWrite32 (VMCS_32_GUEST_FS_ACCESS_RIGHT_INDEX, ArFromGdtEntry (GdtEntry));
|
|
VmWrite32 (VMCS_32_GUEST_FS_LIMIT_INDEX, LimitFromGdtEntry (GdtEntry));
|
|
VmWriteN (VMCS_N_GUEST_GS_BASE_INDEX, BaseFromGdtEntry (GdtEntry));
|
|
VmWrite32 (VMCS_32_GUEST_GS_ACCESS_RIGHT_INDEX, ArFromGdtEntry (GdtEntry));
|
|
VmWrite32 (VMCS_32_GUEST_GS_LIMIT_INDEX, LimitFromGdtEntry (GdtEntry));
|
|
|
|
GdtEntry = (GDT_ENTRY *)((UINTN)mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmGdtPtr + mHostContextCommon.HostContextPerCpu[Index].TxtProcessorSmmDescriptor->SmmTr);
|
|
VmWriteN (VMCS_N_GUEST_TR_BASE_INDEX, BaseFromGdtEntry (GdtEntry));
|
|
VmWrite32 (VMCS_32_GUEST_TR_ACCESS_RIGHT_INDEX, ArFromGdtEntry (GdtEntry));
|
|
VmWrite32 (VMCS_32_GUEST_TR_LIMIT_INDEX, LimitFromGdtEntry (GdtEntry));
|
|
|
|
VmWrite32 (VMCS_32_GUEST_INTERRUPTIBILITY_STATE_INDEX, GuestInterruptibilityState.Uint32);
|
|
|
|
VmWrite64 (VMCS_64_GUEST_IA32_PERF_GLOBAL_CTRL_INDEX, AsmReadMsr64(IA32_PERF_GLOBAL_CTRL_MSR_INDEX));
|
|
|
|
VmWrite64 (VMCS_64_GUEST_IA32_EFER_INDEX, mGuestContextCommonSmm[SMI_HANDLER].GuestContextPerCpu[Index].Efer);
|
|
return ;
|
|
}
|