STM/Test/FrmPkg/Core/Init/VmcsInit.c

247 lines
12 KiB
C

/** @file
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 <Base.h>
#include "FrmInit.h"
//#define NOT_USE_UNRESTRICTEDGUEST
/**
This function set VMCS host field.
@param Index CPU index
**/
VOID
SetVmcsHostField (
IN UINT32 Index
)
{
VmWrite16 (VMCS_16_HOST_ES_INDEX, AsmReadDs ());
VmWrite16 (VMCS_16_HOST_CS_INDEX, AsmReadCs ());
VmWrite16 (VMCS_16_HOST_SS_INDEX, AsmReadSs ());
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_CR0_INDEX, AsmReadCr0 () | ((UINTN)AsmReadMsr64 (IA32_VMX_CR0_FIXED0_MSR_INDEX) & (UINTN)AsmReadMsr64 (IA32_VMX_CR0_FIXED1_MSR_INDEX)));
VmWriteN (VMCS_N_HOST_CR3_INDEX, mHostContextCommon.PageTable);
VmWriteN (VMCS_N_HOST_CR4_INDEX, AsmReadCr4 () | CR4_PAE | CR4_OSFXSR | CR4_OSXMMEXCPT | ((UINTN)AsmReadMsr64 (IA32_VMX_CR4_FIXED0_MSR_INDEX) & (UINTN)AsmReadMsr64 (IA32_VMX_CR4_FIXED1_MSR_INDEX)));
VmWriteN (VMCS_N_HOST_FS_BASE_INDEX, 0);
VmWriteN (VMCS_N_HOST_GS_BASE_INDEX, 0);
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)AsmHostEntrypoint);
}
/**
This function set VMCS control field.
@param Index CPU index
**/
VOID
SetVmcsControlField (
IN UINT32 Index
)
{
UINT64 Data64;
VM_EXEC_PIN_BASES_VMEXIT_CONTROLS PinBasedCtls;
VM_EXEC_PROCESSOR_BASES_VMEXIT_CONTROLS ProcessorBasedCtrls;
VM_EXEC_2ND_PROCESSOR_BASES_VMEXIT_CONTROLS ProcessorBasedCtrls2nd;
VM_EXIT_CONTROLS VmExitCtrls;
VM_ENTRY_CONTROLS VmEntryCtrls;
//
// Init VM Exit control fields
// Init VM Entry control fields
// Init VM Execution control fields
//
Data64 = AsmReadMsr64 (IA32_VMX_PINBASED_CTLS_MSR_INDEX);
PinBasedCtls.Uint32 = (UINT32)Data64 & (UINT32)RShiftU64 (Data64, 32);
PinBasedCtls.Bits.ExternalInterrupt = 0; // external interrupt (To be configured)
PinBasedCtls.Bits.Nmi = 0;
PinBasedCtls.Bits.VmxPreemptionTimer = 1; // Enable Periodic Timer to tear down AP.
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 == 1) {
mGuestContextCommon.GuestContextPerCpu[Index].UnrestrictedGuest = TRUE;
} else {
mGuestContextCommon.GuestContextPerCpu[Index].UnrestrictedGuest = FALSE;
}
#ifdef NOT_USE_UNRESTRICTEDGUEST
mGuestContextCommon.GuestContextPerCpu[Index].UnrestrictedGuest = FALSE;
#endif
ProcessorBasedCtrls2nd.Uint32 = (UINT32)Data64 & (UINT32)RShiftU64 (Data64, 32);
ProcessorBasedCtrls2nd.Bits.Ept = 1;
ProcessorBasedCtrls2nd.Bits.VirtualizeX2Apic = 0;
if (mGuestContextCommon.GuestContextPerCpu[Index].UnrestrictedGuest) {
ProcessorBasedCtrls2nd.Bits.UnrestrictedGuest = 1;
}
Data64 = AsmReadMsr64 (IA32_VMX_EXIT_CTLS_MSR_INDEX);
VmExitCtrls.Uint32 = (UINT32)Data64 & (UINT32)RShiftU64 (Data64, 32);
VmExitCtrls.Bits.AcknowledgeInterrupt = 0; // Ack
VmExitCtrls.Bits.Ia32eHost = (sizeof(UINT64) == sizeof(UINTN));
if (PinBasedCtls.Bits.VmxPreemptionTimer) {
VmExitCtrls.Bits.SaveVmxPreemptionTimerValue = 1;
}
VmExitCtrls.Bits.SaveIA32_EFER = 1;
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.LoadIA32_EFER = 1;
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_VMEXIT_CONTROLS_INDEX, VmExitCtrls.Uint32);
VmWrite32 (VMCS_32_CONTROL_VMENTRY_CONTROLS_INDEX, VmEntryCtrls.Uint32);
VmWrite64 (VMCS_64_GUEST_IA32_EFER_INDEX, mGuestContextCommon.GuestContextPerCpu[Index].EFER);
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)));
VmWriteN (VMCS_N_CONTROL_CR4_GUEST_HOST_MASK_INDEX, (UINTN)-1);
VmWriteN (VMCS_N_CONTROL_CR0_READ_SHADOW_INDEX, mGuestContextCommon.GuestContextPerCpu[Index].Cr0);
VmWriteN (VMCS_N_CONTROL_CR4_READ_SHADOW_INDEX, mGuestContextCommon.GuestContextPerCpu[Index].Cr4);
if (ProcessorBasedCtrls.Bits.IoBitmap) {
VmWrite64 (VMCS_64_CONTROL_IO_BITMAP_A_INDEX, mGuestContextCommon.IoBitmapA);
VmWrite64 (VMCS_64_CONTROL_IO_BITMAP_B_INDEX, mGuestContextCommon.IoBitmapB);
}
if (ProcessorBasedCtrls.Bits.MsrBitmap) {
VmWrite64 (VMCS_64_CONTROL_MSR_BITMAP_INDEX, mGuestContextCommon.MsrBitmap);
}
VmWrite32 (VMCS_32_CONTROL_VMEXIT_MSR_STORE_COUNT_INDEX, 0);
VmWrite64 (VMCS_64_CONTROL_VMEXIT_MSR_STORE_INDEX, mGuestContextCommon.GuestContextPerCpu[Index].VmExitMsrStore);
VmWrite32 (VMCS_32_CONTROL_VMEXIT_MSR_LOAD_COUNT_INDEX, 0);
VmWrite64 (VMCS_64_CONTROL_VMEXIT_MSR_LOAD_INDEX, mGuestContextCommon.GuestContextPerCpu[Index].VmExitMsrLoad);
VmWrite32 (VMCS_32_CONTROL_VMENTRY_MSR_LOAD_COUNT_INDEX, 0);
VmWrite64 (VMCS_64_CONTROL_VMENTRY_MSR_LOAD_INDEX, mGuestContextCommon.GuestContextPerCpu[Index].VmEnterMsrLoad);
VmWrite32 (VMCS_32_CONTROL_CR3_TARGET_COUNT_INDEX, 0);
for (Index = 0; Index < 4; Index++) {
VmWriteN ((UINT32)(VMCS_N_CONTROL_CR3_TARGET_VALUE0_INDEX + (Index << 1)), (UINTN)-1);
}
VmWrite32 (VMCS_32_CONTROL_PAGE_FAULT_ERROR_CODE_MASK_INDEX, 0);
VmWrite32 (VMCS_32_CONTROL_PAGE_FAULT_ERROR_CODE_MATCH_INDEX, 0);
VmWrite32 (VMCS_32_CONTROL_VMENTRY_INTERRUPTION_INFO_INDEX, 0);
VmWrite32 (VMCS_32_CONTROL_VMENTRY_EXCEPTION_ERROR_CODE_INDEX, 0);
VmWrite64 (VMCS_64_CONTROL_EPT_PTR_INDEX, mGuestContextCommon.EptPointer.Uint64);
}
/**
This function set VMCS guest field.
@param Index CPU index
**/
VOID
SetVmcsGuestField (
IN UINT32 Index
)
{
VmWriteN (VMCS_N_GUEST_CR0_INDEX, mGuestContextCommon.GuestContextPerCpu[mBspIndex].Cr0 | ((UINTN)AsmReadMsr64 (IA32_VMX_CR0_FIXED0_MSR_INDEX) & (UINTN)AsmReadMsr64 (IA32_VMX_CR0_FIXED1_MSR_INDEX)));
VmWriteN (VMCS_N_GUEST_CR3_INDEX, mGuestContextCommon.GuestContextPerCpu[mBspIndex].Cr3);
VmWriteN (VMCS_N_GUEST_CR4_INDEX, mGuestContextCommon.GuestContextPerCpu[mBspIndex].Cr4 | ((UINTN)AsmReadMsr64 (IA32_VMX_CR4_FIXED0_MSR_INDEX) & (UINTN)AsmReadMsr64 (IA32_VMX_CR4_FIXED1_MSR_INDEX)));
VmWriteN (VMCS_N_GUEST_ES_BASE_INDEX, 0);
VmWriteN (VMCS_N_GUEST_CS_BASE_INDEX, 0);
VmWriteN (VMCS_N_GUEST_SS_BASE_INDEX, 0);
VmWriteN (VMCS_N_GUEST_DS_BASE_INDEX, 0);
VmWriteN (VMCS_N_GUEST_FS_BASE_INDEX, 0);
VmWriteN (VMCS_N_GUEST_GS_BASE_INDEX, 0);
VmWriteN (VMCS_N_GUEST_LDTR_BASE_INDEX, 0);
VmWriteN (VMCS_N_GUEST_TR_BASE_INDEX, 0);
VmWriteN (VMCS_N_GUEST_GDTR_BASE_INDEX, mGuestContextCommon.GuestContextPerCpu[mBspIndex].Gdtr.Base);
VmWriteN (VMCS_N_GUEST_IDTR_BASE_INDEX, mGuestContextCommon.GuestContextPerCpu[mBspIndex].Idtr.Base);
VmWriteN (VMCS_N_GUEST_DR7_INDEX, AsmReadDr7 ());
VmWriteN (VMCS_N_GUEST_RSP_INDEX, mGuestContextCommon.GuestContextPerCpu[Index].Stack);
VmWriteN (VMCS_N_GUEST_RIP_INDEX, (UINTN)GuestEntrypoint);
VmWriteN (VMCS_N_GUEST_RFLAGS_INDEX, 0x00000002); // not interrupt for S3
VmWriteN (VMCS_N_GUEST_PENDING_DEBUG_EXCEPTIONS_INDEX, 0);
VmWrite16 (VMCS_16_GUEST_ES_INDEX, AsmReadEs ());
VmWrite16 (VMCS_16_GUEST_CS_INDEX, AsmReadCs ());
VmWrite16 (VMCS_16_GUEST_SS_INDEX, AsmReadSs ());
VmWrite16 (VMCS_16_GUEST_DS_INDEX, AsmReadDs ());
VmWrite16 (VMCS_16_GUEST_FS_INDEX, AsmReadFs ());
VmWrite16 (VMCS_16_GUEST_GS_INDEX, AsmReadGs ());
VmWrite16 (VMCS_16_GUEST_LDTR_INDEX, 0);
VmWrite16 (VMCS_16_GUEST_TR_INDEX, AsmReadDs ());
VmWrite32 (VMCS_32_GUEST_ES_LIMIT_INDEX, 0xffffffff);
VmWrite32 (VMCS_32_GUEST_CS_LIMIT_INDEX, 0xffffffff);
VmWrite32 (VMCS_32_GUEST_SS_LIMIT_INDEX, 0xffffffff);
VmWrite32 (VMCS_32_GUEST_DS_LIMIT_INDEX, 0xffffffff);
VmWrite32 (VMCS_32_GUEST_FS_LIMIT_INDEX, 0xffffffff);
VmWrite32 (VMCS_32_GUEST_GS_LIMIT_INDEX, 0xffffffff);
VmWrite32 (VMCS_32_GUEST_LDTR_LIMIT_INDEX, 0);
VmWrite32 (VMCS_32_GUEST_TR_LIMIT_INDEX, 0x0000ffff);
VmWrite32 (VMCS_32_GUEST_GDTR_LIMIT_INDEX, mGuestContextCommon.GuestContextPerCpu[mBspIndex].Gdtr.Limit);
VmWrite32 (VMCS_32_GUEST_IDTR_LIMIT_INDEX, mGuestContextCommon.GuestContextPerCpu[mBspIndex].Idtr.Limit);
VmWrite32 (VMCS_32_GUEST_ES_ACCESS_RIGHT_INDEX, 0xc093);
if (sizeof(UINTN) == sizeof(UINT32)) {
VmWrite32 (VMCS_32_GUEST_CS_ACCESS_RIGHT_INDEX, 0xc09b);
} else {
VmWrite32 (VMCS_32_GUEST_CS_ACCESS_RIGHT_INDEX, 0xa09b);
}
VmWrite32 (VMCS_32_GUEST_SS_ACCESS_RIGHT_INDEX, 0xc093);
VmWrite32 (VMCS_32_GUEST_DS_ACCESS_RIGHT_INDEX, 0xc093);
VmWrite32 (VMCS_32_GUEST_FS_ACCESS_RIGHT_INDEX, 0xc093);
VmWrite32 (VMCS_32_GUEST_GS_ACCESS_RIGHT_INDEX, 0xc093);
VmWrite32 (VMCS_32_GUEST_LDTR_ACCESS_RIGHT_INDEX, 0x10082);
VmWrite32 (VMCS_32_GUEST_TR_ACCESS_RIGHT_INDEX, 0x008b);
VmWrite32 (VMCS_32_GUEST_INTERRUPTIBILITY_STATE_INDEX, 0);
VmWrite32 (VMCS_32_GUEST_ACTIVITY_STATE_INDEX, GUEST_ACTIVITY_STATE_ACTIVE);
VmWrite32 (VMCS_32_GUEST_VMX_PREEMPTION_TIMER_VALUE_INDEX, mGuestContextCommon.VmxTimerValue);
VmWrite64 (VMCS_64_GUEST_IA32_DEBUGCTL_INDEX, AsmReadMsr64 (IA32_DBG_CTL_MSR_INDEX));
VmWrite64 (VMCS_64_GUEST_VMCS_LINK_PTR_INDEX, 0xffffffffffffffff);
if ((mGuestContextCommon.GuestContextPerCpu[mBspIndex].Cr0 & CR0_PG) == 0) {
// do not assert here, because it will be assigned later.
//ASSERT(mGuestContextCommon.GuestContextPerCpu[Index].UnrestrictedGuest);
VmWriteN(VMCS_N_GUEST_CR0_INDEX, VmReadN(VMCS_N_GUEST_CR0_INDEX) & (~CR0_PG));
}
VmWrite64 (VMCS_64_GUEST_IA32_EFER_INDEX, mGuestContextCommon.GuestContextPerCpu[Index].EFER);
return ;
}