Specifically before running lzma uncompress of the main firmware volume.
This is needed to make sure caching is enabled, otherwise the uncompress
can be extremely slow.

Adapt the ASSERTs and MTRR setup in PlatformInitLib to the changes.

Background:  Depending on virtual machine configuration kvm may uses EPT
memory types to apply guest MTRR settings.  In case MTRRs are disabled
kvm will use the uncachable memory type for all mappings.  Here is the
linux kernel function handling this:

static u8 vmx_get_mt_mask(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio)
{
        /* We wanted to honor guest CD/MTRR/PAT, but doing so could result in
         * memory aliases with conflicting memory types and sometimes MCEs.
         * We have to be careful as to what are honored and when.
         *
         * For MMIO, guest CD/MTRR are ignored.  The EPT memory type is set to
         * UC.  The effective memory type is UC or WC depending on guest PAT.
         * This was historically the source of MCEs and we want to be
         * conservative.
         *
         * When there is no need to deal with noncoherent DMA (e.g., no VT-d
         * or VT-d has snoop control), guest CD/MTRR/PAT are all ignored.  The
         * EPT memory type is set to WB.  The effective memory type is forced
         * WB.
         *
         * Otherwise, we trust guest.  Guest CD/MTRR/PAT are all honored.  The
         * EPT memory type is used to emulate guest CD/MTRR.
         */

        if (is_mmio)
                return MTRR_TYPE_UNCACHABLE << VMX_EPT_MT_EPTE_SHIFT;

        if (!kvm_arch_has_noncoherent_dma(vcpu->kvm))
                return (MTRR_TYPE_WRBACK << VMX_EPT_MT_EPTE_SHIFT) | 
VMX_EPT_IPAT_BIT;

        if (kvm_read_cr0_bits(vcpu, X86_CR0_CD)) {
                if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_CD_NW_CLEARED))
                        return MTRR_TYPE_WRBACK << VMX_EPT_MT_EPTE_SHIFT;
                else
                        return (MTRR_TYPE_UNCACHABLE << VMX_EPT_MT_EPTE_SHIFT) |
                                VMX_EPT_IPAT_BIT;
        }

        return kvm_mtrr_get_guest_memory_type(vcpu, gfn) << 
VMX_EPT_MT_EPTE_SHIFT;
}

In most VM configurations kvm_arch_has_noncoherent_dma() evaluate to
false, so kvm uses MTRR_TYPE_WRBACK.  In case the VM has a mdev device
assigned that is not the case though.

Before commit e8aa4c6546ad ("UefiCpuPkg/ResetVector: Cache Disable
should not be set by default in CR0") the function also ended up using
MTRR_TYPE_WRBACK thanks to KVM_X86_QUIRK_CD_NW_CLEARED.  After that
commit kvm actually evaluates mtrr settings via
kvm_mtrr_get_guest_memory_type().

Signed-off-by: Gerd Hoffmann <kra...@redhat.com>
---
 OvmfPkg/IntelTdx/Sec/SecMain.c              | 32 +++++++++++++++++++++
 OvmfPkg/Library/PlatformInitLib/MemDetect.c | 10 +++----
 OvmfPkg/Sec/SecMain.c                       | 32 +++++++++++++++++++++
 3 files changed, 69 insertions(+), 5 deletions(-)

diff --git a/OvmfPkg/IntelTdx/Sec/SecMain.c b/OvmfPkg/IntelTdx/Sec/SecMain.c
index 42a587adfa57..e8ff0e9081d1 100644
--- a/OvmfPkg/IntelTdx/Sec/SecMain.c
+++ b/OvmfPkg/IntelTdx/Sec/SecMain.c
@@ -27,6 +27,8 @@
 #include <Library/TdxHelperLib.h>
 #include <Library/CcProbeLib.h>
 #include <Library/PeilessStartupLib.h>
+#include <Register/Intel/ArchitecturalMsr.h>
+#include <Register/Intel/Cpuid.h>
 
 #define SEC_IDT_ENTRY_COUNT  34
 
@@ -48,6 +50,31 @@ IA32_IDT_GATE_DESCRIPTOR  mIdtEntryTemplate = {
   }
 };
 
+//
+// Enable MTRR early, set default type to write back.
+// Needed to make sure caching is enabled,
+// without this lzma decompress can be very slow.
+//
+STATIC
+VOID
+SecMtrrSetup (
+  VOID
+  )
+{
+  CPUID_VERSION_INFO_EDX           Edx;
+  MSR_IA32_MTRR_DEF_TYPE_REGISTER  DefType;
+
+  AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &Edx.Uint32);
+  if (!Edx.Bits.MTRR) {
+    return;
+  }
+
+  DefType.Uint64    = AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE);;
+  DefType.Bits.Type = 6; /* write back */
+  DefType.Bits.E    = 1; /* enable */
+  AsmWriteMsr64 (MSR_IA32_MTRR_DEF_TYPE, DefType.Uint64);
+}
+
 VOID
 EFIAPI
 SecCoreStartupWithStack (
@@ -204,6 +231,11 @@ SecCoreStartupWithStack (
   InitializeApicTimer (0, MAX_UINT32, TRUE, 5);
   DisableApicTimerInterrupt ();
 
+  //
+  // Initialize MTRR
+  //
+  SecMtrrSetup ();
+
   PeilessStartup (&SecCoreData);
 
   ASSERT (FALSE);
diff --git a/OvmfPkg/Library/PlatformInitLib/MemDetect.c 
b/OvmfPkg/Library/PlatformInitLib/MemDetect.c
index f042517bb64a..e89f63eee054 100644
--- a/OvmfPkg/Library/PlatformInitLib/MemDetect.c
+++ b/OvmfPkg/Library/PlatformInitLib/MemDetect.c
@@ -1082,18 +1082,18 @@ PlatformQemuInitializeRam (
     MtrrGetAllMtrrs (&MtrrSettings);
 
     //
-    // MTRRs disabled, fixed MTRRs disabled, default type is uncached
+    // See SecMtrrSetup(), default type should be write back
     //
-    ASSERT ((MtrrSettings.MtrrDefType & BIT11) == 0);
+    ASSERT ((MtrrSettings.MtrrDefType & BIT11) != 0);
     ASSERT ((MtrrSettings.MtrrDefType & BIT10) == 0);
-    ASSERT ((MtrrSettings.MtrrDefType & 0xFF) == 0);
+    ASSERT ((MtrrSettings.MtrrDefType & 0xFF) == MTRR_CACHE_WRITE_BACK);
 
     //
     // flip default type to writeback
     //
-    SetMem (&MtrrSettings.Fixed, sizeof MtrrSettings.Fixed, 0x06);
+    SetMem (&MtrrSettings.Fixed, sizeof MtrrSettings.Fixed, 
MTRR_CACHE_WRITE_BACK);
     ZeroMem (&MtrrSettings.Variables, sizeof MtrrSettings.Variables);
-    MtrrSettings.MtrrDefType |= BIT11 | BIT10 | 6;
+    MtrrSettings.MtrrDefType |= BIT10;
     MtrrSetAllMtrrs (&MtrrSettings);
 
     //
diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c
index 31da5d0ace51..a066db34997c 100644
--- a/OvmfPkg/Sec/SecMain.c
+++ b/OvmfPkg/Sec/SecMain.c
@@ -30,6 +30,8 @@
 #include <Ppi/MpInitLibDep.h>
 #include <Library/TdxHelperLib.h>
 #include <Library/CcProbeLib.h>
+#include <Register/Intel/ArchitecturalMsr.h>
+#include <Register/Intel/Cpuid.h>
 #include "AmdSev.h"
 
 #define SEC_IDT_ENTRY_COUNT  34
@@ -744,6 +746,31 @@ FindAndReportEntryPoints (
   return;
 }
 
+//
+// Enable MTRR early, set default type to write back.
+// Needed to make sure caching is enabled,
+// without this lzma decompress can be very slow.
+//
+STATIC
+VOID
+SecMtrrSetup (
+  VOID
+  )
+{
+  CPUID_VERSION_INFO_EDX           Edx;
+  MSR_IA32_MTRR_DEF_TYPE_REGISTER  DefType;
+
+  AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &Edx.Uint32);
+  if (!Edx.Bits.MTRR) {
+    return;
+  }
+
+  DefType.Uint64    = AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE);;
+  DefType.Bits.Type = 6; /* write back */
+  DefType.Bits.E    = 1; /* enable */
+  AsmWriteMsr64 (MSR_IA32_MTRR_DEF_TYPE, DefType.Uint64);
+}
+
 VOID
 EFIAPI
 SecCoreStartupWithStack (
@@ -942,6 +969,11 @@ SecCoreStartupWithStack (
   InitializeApicTimer (0, MAX_UINT32, TRUE, 5);
   DisableApicTimerInterrupt ();
 
+  //
+  // Initialize MTRR
+  //
+  SecMtrrSetup ();
+
   //
   // Initialize Debug Agent to support source level debug in SEC/PEI phases 
before memory ready.
   //
-- 
2.43.0



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114377): https://edk2.groups.io/g/devel/message/114377
Mute This Topic: https://groups.io/mt/103950478/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to