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/TimerLib.h>
#include <Library/PcdLib.h> #include <Library/PcdLib.h>
#include <Library/UefiCpuLib.h> #include <Library/UefiCpuLib.h>
#include <IndustryStandard/Tdx.h>
// //
// Library internal functions // 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. Determine if the CPU supports the Local APIC Base Address MSR.
@ -78,7 +222,7 @@ GetLocalApicBaseAddress (
return PcdGet32 (PcdCpuLocalApicBaseAddress); 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)) + return (UINTN)(LShiftU64 ((UINT64)ApicBaseMsr.Bits.ApicBaseHi, 32)) +
(((UINTN)ApicBaseMsr.Bits.ApicBase) << 12); (((UINTN)ApicBaseMsr.Bits.ApicBase) << 12);
@ -109,12 +253,12 @@ SetLocalApicBaseAddress (
return; return;
} }
ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE); ApicBaseMsr.Uint64 = LocalApicReadMsrReg64 (MSR_IA32_APIC_BASE);
ApicBaseMsr.Bits.ApicBase = (UINT32)(BaseAddress >> 12); ApicBaseMsr.Bits.ApicBase = (UINT32)(BaseAddress >> 12);
ApicBaseMsr.Bits.ApicBaseHi = (UINT32)(RShiftU64 ((UINT64)BaseAddress, 32)); 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); ASSERT (MmioOffset != XAPIC_ICR_HIGH_OFFSET);
MsrIndex = (UINT32)(MmioOffset >> 4) + X2APIC_MSR_BASE_ADDRESS; 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. // Use memory fence here to force the serializing semantics to be consisent with xAPIC mode.
// //
MemoryFence (); MemoryFence ();
AsmWriteMsr32 (MsrIndex, Value); LocalApicWriteMsrReg32 (MsrIndex, Value);
} }
} }
@ -309,7 +453,7 @@ GetApicMode (
return LOCAL_APIC_MODE_XAPIC; 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 // Local APIC should have been enabled
// //
@ -354,9 +498,9 @@ SetApicMode (
case LOCAL_APIC_MODE_XAPIC: case LOCAL_APIC_MODE_XAPIC:
break; break;
case LOCAL_APIC_MODE_X2APIC: case LOCAL_APIC_MODE_X2APIC:
ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE); ApicBaseMsr.Uint64 = LocalApicReadMsrReg64 (MSR_IA32_APIC_BASE);
ApicBaseMsr.Bits.EXTD = 1; ApicBaseMsr.Bits.EXTD = 1;
AsmWriteMsr64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64); LocalApicWriteMsrReg64 (MSR_IA32_APIC_BASE, ApicBaseMsr.Uint64);
break; break;
default: default:
ASSERT (FALSE); ASSERT (FALSE);