From: "Laszlo Ersek" <lersek@redhat.com>
To: Gerd Hoffmann <kraxel@redhat.com>, devel@edk2.groups.io
Cc: Michael Roth <michael.roth@amd.com>,
Tom Lendacky <thomas.lendacky@amd.com>,
Jiewen Yao <jiewen.yao@intel.com>,
Ard Biesheuvel <ardb+tianocore@kernel.org>,
Oliver Steffen <osteffen@redhat.com>, Min Xu <min.m.xu@intel.com>,
Erdem Aktas <erdemaktas@google.com>
Subject: Re: [edk2-devel] [PATCH 1/1] OvmfPkg/Sec: Setup MTRR early in the boot process.
Date: Wed, 24 Jan 2024 17:14:10 +0100 [thread overview]
Message-ID: <6d89f7aa-938c-2a96-3eb8-53169dcfd3db@redhat.com> (raw)
In-Reply-To: <20240124151542.2091782-1-kraxel@redhat.com>
On 1/24/24 16:15, Gerd Hoffmann wrote:
> 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 in PlatformInitLib to the changes.
>
> Background: In some virtual machine configurations with assigned
> devices kvm uses EPT memory types to apply guest MTRR settings.
> In case MTRRs are disabled kvm will use the uncachable memory type
> for all mappings.
I suggest mentioning mdev and noncoherent DMA here (the linux code you
quoted elsewhere would be welcome too).
>
> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
> ---
> OvmfPkg/Library/PlatformInitLib/MemDetect.c | 8 ++++--
> OvmfPkg/Sec/SecMain.c | 32 +++++++++++++++++++++
> 2 files changed, 37 insertions(+), 3 deletions(-)
The original report <https://edk2.groups.io/g/devel/message/113517>
claims that commit e8aa4c6546ad ("UefiCpuPkg/ResetVector: Cache Disable
should not be set by default in CR0", 2023-08-30) triggered the symptom.
I still don't understand how that is possible. Assuming we have
noncoherent DMA due to mdev assignment, KVM will honor "Guest
CD/MTRR/PAT". Let's consider each in turn:
- CD (cache disable): set to zero in recent commit e8aa4c6546ad.
- MTRR: we set DefType to WB, in this patch, but not enabled upstream,
at present
- PAT: IIUC, we don't deal with that at all in edk2
- PCD: not set, minimally through edk2 commit 98f378a7be12
("OvmfPkg/ResetVector: enable caching in initial page tables", 2013-09-24)
I don't understand how *clearing* CD in CR0, could make guest memory
*less* cacheable. I understand the point about MTRR, but exactly the
MTRR's currently upstream state should have masked any changes to CD.
(1) Is the initial report wrong?
>
> diff --git a/OvmfPkg/Library/PlatformInitLib/MemDetect.c b/OvmfPkg/Library/PlatformInitLib/MemDetect.c
> index f042517bb64a..cb2ae0f3d79d 100644
> --- a/OvmfPkg/Library/PlatformInitLib/MemDetect.c
> +++ b/OvmfPkg/Library/PlatformInitLib/MemDetect.c
> @@ -1082,11 +1082,13 @@ PlatformQemuInitializeRam (
> MtrrGetAllMtrrs (&MtrrSettings);
>
> //
> - // MTRRs disabled, fixed MTRRs disabled, default type is uncached
> + // Fixed MTRRs disabled, default type is uncached or write back (see SecMtrrSetup())
> //
> - ASSERT ((MtrrSettings.MtrrDefType & BIT11) == 0);
> ASSERT ((MtrrSettings.MtrrDefType & BIT10) == 0);
> - ASSERT ((MtrrSettings.MtrrDefType & 0xFF) == 0);
> + ASSERT (
> + (MtrrSettings.MtrrDefType & 0xFF) == 0x0 ||
> + (MtrrSettings.MtrrDefType & 0xFF) == 0x6
> + );
>
> //
> // flip default type to writeback
This code comes (originally) from commit 79d274b8b6b1 ("OvmfPkg:
PlatformPei: invert MTRR setup in QemuInitializeRam()", 2015-06-26).
The purpose(s) of that commit include "setting the default to writeback"
-- even in the context quoted above, we see the comment "flip default
type to writeback". A wider context is:
//
// flip default type to writeback
//
SetMem (&MtrrSettings.Fixed, sizeof MtrrSettings.Fixed, 0x06);
ZeroMem (&MtrrSettings.Variables, sizeof MtrrSettings.Variables);
MtrrSettings.MtrrDefType |= BIT11 | BIT10 | 6;
MtrrSetAllMtrrs (&MtrrSettings);
So:
(2) We already assume (minimally since 2015) that MTRRs are supported by
the processor. This means that (a) the CPUID check in SecMtrrSetup() is
superfluous, and that (b) we need not / should not permit
(MtrrSettings.MtrrDefType & 0xFF) == 0x0
in the ASSERT(), going forward.
(3) The rest of the code and *comments* here -- in
PlatformQemuInitializeRam() -- should be updated such that we only
enable the fixed MTRRs (BIT10) on top of what SEC does earlier (which
is: BIT11 (general enable) and DefType=6).
Something like:
ASSERT ((MtrrSettings.MtrrDefType & BIT11) != 0);
ASSERT ((MtrrSettings.MtrrDefType & BIT10) == 0);
ASSERT ((MtrrSettings.MtrrDefType & 0xFF) == 6);
...
MtrrSettings.MtrrDefType |= BIT10;
> diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c
> index 31da5d0ace51..a672751b046a 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>
(4) with the CPUID gone, the second header should not be needed
> #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 = 0;
(5) Can we first read the MSR, instead of explicit zeroing?
> + DefType.Bits.Type = 6; /* write back */
(6) I've noticed an independent (preexistent!) wart: I dislike the naked
constant "6" for WriteBack.
Turns out we have had MTRR_CACHE_WRITE_BACK in
UefiCpuPkg/Include/Library/MtrrLib.h
since historical commit e50466da2437 ("Add MTRR library for IA32 & X64
processor architectures.", 2009-05-27).
This means that my original commit 79d274b8b6b1 ("OvmfPkg: PlatformPei:
invert MTRR setup in QemuInitializeRam()", 2015-06-26) could have been
better: that commit already consumed MtrrLib, so it could have used
MTRR_CACHE_WRITE_BACK, in place of "6", from the lib class header.
OVMF SEC however does not include <Library/MtrrLib.h> -- and it
shouldn't. That means it cannot use MTRR_CACHE_WRITE_BACK. That makes me
somewhat unhappy.
Proposal:
- Copy and rename the MTRR_CACHE_* macros from
"UefiCpuPkg/Include/Library/MtrrLib.h" to
"MdePkg/Include/Register/Intel/ArchitecturalMsr.h"
- Redefine MTRR_CACHE_* in MtrrLib.h in terms of the new macros from
"ArchitecturalMsr.h".
(in a separate patch, of course).
This will preserve compatibility, but also expose the (new) macro names
to modules that don't consume MtrrLib -- for example, OVMF SEC.
Probably consult the MtrrLib and ArchitecturalMsr.h maintainers first,
though -- so I would propose three patch in the end:
- this patch, using naked constant "6"
- macro reorg
- adopting the new macro name in OVMF SEC, in place of 6
If the MtrrLib and ArchitecturalMsr.h maintainers disagree with patch
#2, we can simply drop #2 and #3, and just merge #1.
> + 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.
> //
Ugh, I can't really comment where to place this call. FWIW, the problem
path is:
SecCoreStartupWithStack()
InitializeDebugAgent()
SecStartupPhase2()
FindAndReportEntryPoints()
FindPeiCoreImageBase()
DecompressMemFvs()
ExtractGuidedSectionDecode()
That's where the LZMA decompression happens.
The patch places the call to SecMtrrSetup() "early enough", but is it
the "best" location from all possible, "early enough" locations? I can't
say.
(7) If you have a particular reason for doing it here, please capture
that in the comment.
(8) Just for symmetry -- I'm noticing there are two
SecCoreStartupWithStack() functions; the other being in
"OvmfPkg/IntelTdx/Sec/SecMain.c".
Also, Min's original QEMU command line included TDVF references.
Does that mean this patch should be reflected to the TDX platform's modules?
Thanks,
Laszlo
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114315): https://edk2.groups.io/g/devel/message/114315
Mute This Topic: https://groups.io/mt/103933443/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/leave/12367111/7686176/1913456212/xyzzy [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-
next prev parent reply other threads:[~2024-01-24 16:14 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-24 15:15 [edk2-devel] [PATCH 1/1] OvmfPkg/Sec: Setup MTRR early in the boot process Gerd Hoffmann
2024-01-24 16:14 ` Laszlo Ersek [this message]
2024-01-25 6:52 ` Gerd Hoffmann
2024-01-25 19:44 ` Laszlo Ersek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=6d89f7aa-938c-2a96-3eb8-53169dcfd3db@redhat.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox