UefiCpuPkg: Support TDX in BaseXApicX2ApicLib

RFC: https://bugzilla.tianocore.org/show_bug.cgi?id=3429

MSR is accessed in BaseXApicX2ApicLib. In TDX some MSRs are accessed
directly from/to CPU. Some should be accessed via explicit requests
from the host VMM using TDCALL(TDG.VP.VMCALL). This is done by the
help of TdxLib.

Please refer to [TDX] Section 18.1
TDX: https://software.intel.com/content/dam/develop/external/us/en/
documents/tdx-module-1.0-public-spec-v0.931.pdf

Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Erdem Aktas <erdemaktas@google.com>
Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
Signed-off-by: Min Xu <min.m.xu@intel.com>
This commit is contained in:
Min Xu 2021-07-19 13:50:40 +08:00 committed by mergify[bot]
parent 3571fc906f
commit 7bed7ae6c5
1 changed files with 152 additions and 8 deletions

View File

@ -23,11 +23,155 @@
#include <Library/TimerLib.h>
#include <Library/PcdLib.h>
#include <Library/UefiCpuLib.h>
#include <IndustryStandard/Tdx.h>
//
// Library internal functions
//
/**
Some MSRs in TDX are accessed via TdCall.
Some are directly read/write from/to CPU.
@param MsrIndex Index of the MSR
@retval TRUE MSR accessed via TdCall.
@retval FALSE MSR accessed not via TdCall.
**/
BOOLEAN
AccessMsrTdxCall (
IN UINT32 MsrIndex
)
{
if (!TdIsEnabled ()) {
return FALSE;
}
switch (MsrIndex) {
case MSR_IA32_X2APIC_TPR:
case MSR_IA32_X2APIC_PPR:
case MSR_IA32_X2APIC_EOI:
case MSR_IA32_X2APIC_ISR0:
case MSR_IA32_X2APIC_ISR1:
case MSR_IA32_X2APIC_ISR2:
case MSR_IA32_X2APIC_ISR3:
case MSR_IA32_X2APIC_ISR4:
case MSR_IA32_X2APIC_ISR5:
case MSR_IA32_X2APIC_ISR6:
case MSR_IA32_X2APIC_ISR7:
case MSR_IA32_X2APIC_TMR0:
case MSR_IA32_X2APIC_TMR1:
case MSR_IA32_X2APIC_TMR2:
case MSR_IA32_X2APIC_TMR3:
case MSR_IA32_X2APIC_TMR4:
case MSR_IA32_X2APIC_TMR5:
case MSR_IA32_X2APIC_TMR6:
case MSR_IA32_X2APIC_TMR7:
case MSR_IA32_X2APIC_IRR0:
case MSR_IA32_X2APIC_IRR1:
case MSR_IA32_X2APIC_IRR2:
case MSR_IA32_X2APIC_IRR3:
case MSR_IA32_X2APIC_IRR4:
case MSR_IA32_X2APIC_IRR5:
case MSR_IA32_X2APIC_IRR6:
case MSR_IA32_X2APIC_IRR7:
return FALSE;
default:
break;
}
return TRUE;
}
/**
Read MSR value.
@param MsrIndex Index of the MSR to read
@retval 64-bit Value of MSR.
**/
UINT64
LocalApicReadMsrReg64 (
IN UINT32 MsrIndex
)
{
UINT64 Val;
UINT64 Status;
if (AccessMsrTdxCall (MsrIndex)) {
Status = TdVmCall (TDVMCALL_RDMSR, (UINT64)MsrIndex, 0, 0, 0, &Val);
if (Status != 0) {
TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);
}
} else {
Val = AsmReadMsr64 (MsrIndex);
}
return Val;
}
/**
Write to MSR.
@param MsrIndex Index of the MSR to write to
@param Value Value to be written to the MSR
@return Value
**/
UINT64
LocalApicWriteMsrReg64 (
IN UINT32 MsrIndex,
IN UINT64 Value
)
{
UINT64 Status;
if (AccessMsrTdxCall (MsrIndex)) {
Status = TdVmCall (TDVMCALL_WRMSR, (UINT64)MsrIndex, Value, 0, 0, 0);
if (Status != 0) {
TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);
}
} else {
AsmWriteMsr64 (MsrIndex, Value);
}
return Value;
}
/**
Read MSR value.
@param MsrIndex Index of the MSR to read
@retval 32-bit Value of MSR.
**/
UINT32
LocalApicReadMsrReg32 (
IN UINT32 MsrIndex
)
{
return (UINT32)LocalApicReadMsrReg64 (MsrIndex);
}
/**
Write to MSR.
@param MsrIndex Index of the MSR to write to
@param Value Value to be written to the MSR
@return Value
**/
UINT32
LocalApicWriteMsrReg32 (
IN UINT32 MsrIndex,
IN UINT32 Value
)
{
return (UINT32)LocalApicWriteMsrReg64 (MsrIndex, Value);
}
/**
Determine if the CPU supports the Local APIC Base Address MSR.
@ -78,7 +222,7 @@ GetLocalApicBaseAddress (
return PcdGet32 (PcdCpuLocalApicBaseAddress);
}
ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);
ApicBaseMsr.Uint64 = LocalApicReadMsrReg64 (MSR_IA32_APIC_BASE);
return (UINTN)(LShiftU64 ((UINT64)ApicBaseMsr.Bits.ApicBaseHi, 32)) +
(((UINTN)ApicBaseMsr.Bits.ApicBase) << 12);
@ -109,12 +253,12 @@ SetLocalApicBaseAddress (
return;
}
ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);
ApicBaseMsr.Uint64 = LocalApicReadMsrReg64 (MSR_IA32_APIC_BASE);
ApicBaseMsr.Bits.ApicBase = (UINT32)(BaseAddress >> 12);
ApicBaseMsr.Bits.ApicBaseHi = (UINT32)(RShiftU64 ((UINT64)BaseAddress, 32));
AsmWriteMsr64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64);
LocalApicWriteMsrReg64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64);
}
/**
@ -154,7 +298,7 @@ ReadLocalApicReg (
ASSERT (MmioOffset != XAPIC_ICR_HIGH_OFFSET);
MsrIndex = (UINT32)(MmioOffset >> 4) + X2APIC_MSR_BASE_ADDRESS;
return AsmReadMsr32 (MsrIndex);
return LocalApicReadMsrReg32 (MsrIndex);
}
}
@ -203,7 +347,7 @@ WriteLocalApicReg (
// Use memory fence here to force the serializing semantics to be consisent with xAPIC mode.
//
MemoryFence ();
AsmWriteMsr32 (MsrIndex, Value);
LocalApicWriteMsrReg32 (MsrIndex, Value);
}
}
@ -309,7 +453,7 @@ GetApicMode (
return LOCAL_APIC_MODE_XAPIC;
}
ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);
ApicBaseMsr.Uint64 = LocalApicReadMsrReg64 (MSR_IA32_APIC_BASE);
//
// Local APIC should have been enabled
//
@ -354,9 +498,9 @@ SetApicMode (
case LOCAL_APIC_MODE_XAPIC:
break;
case LOCAL_APIC_MODE_X2APIC:
ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);
ApicBaseMsr.Uint64 = LocalApicReadMsrReg64 (MSR_IA32_APIC_BASE);
ApicBaseMsr.Bits.EXTD = 1;
AsmWriteMsr64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64);
LocalApicWriteMsrReg64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64);
break;
default:
ASSERT (FALSE);