From: "Laszlo Ersek" <lersek@redhat.com>
To: Tom Lendacky <thomas.lendacky@amd.com>, devel@edk2.groups.io
Cc: Joerg Roedel <joro@8bytes.org>, Borislav Petkov <bp@alien8.de>,
Ard Biesheuvel <ardb+tianocore@kernel.org>,
Jordan Justen <jordan.l.justen@intel.com>,
Brijesh Singh <brijesh.singh@amd.com>,
James Bottomley <jejb@linux.ibm.com>,
Jiewen Yao <jiewen.yao@intel.com>, Min Xu <min.m.xu@intel.com>
Subject: Re: [edk2-devel] [PATCH 3/3] OvmfPkg/PlatformPei: Mark TPM MMIO range as unencrypted for SEV
Date: Wed, 28 Apr 2021 18:12:20 +0200 [thread overview]
Message-ID: <3f2e589d-7258-c372-c1ab-60992351dbde@redhat.com> (raw)
In-Reply-To: <d0e2394f-1212-dc5e-a95a-842274956432@amd.com>
On 04/27/21 16:58, Tom Lendacky wrote:
> On 4/26/21 9:21 AM, Tom Lendacky wrote:
>> On 4/26/21 7:07 AM, Laszlo Ersek wrote:
>>> On 04/23/21 22:02, Tom Lendacky wrote:
>>>> 1. SEV works with the current encrypted mapping, it is only the SEV-ES
>>>> support that fails because of the ValidateMmioMemory() check. I can do
>>>> the mapping change just for SEV-ES since it is X64 only. This works,
>>>> because MemEncryptSevClearPageEncMask() will not return UNSUPPORTED
>>>> when running in 64-bit.
>>>
>>> Can we really say "SEV works" though? Because, even using an X64 PEI
>>> phase, and enabling only SEV (not SEV-ES), TPM access will be broken in
>>> the PEI phase. Is my understanding correct?
>>
>> Because the memory range is marked as MMIO, we'll take a nested page fault
>> (NPF). The GPA passed as part of the NPF does not include the c-bit. So we
>> do in fact work properly with a TPM in SEV.
Thanks for the explanation.
Here's what bothers me about it:
In AmdSevDxe, we clear the C-bit from MMIO and NonExistent areas in the
GCD memory space map. This occurs early in the DXE phase (see "APRIORI
DXE" in the FDF files). The justification is that we want the flash and
(for example) the PCI MMIO apertures decrypted.
Now, I realize there is a difference between flash and TPM. TPM is
purely MMIO (no KVM memslot), but flash (when it is not in programming
mode) is backed by a read-only KVM memslot. IOW, flash is "actual
memory", and so it is affected by SEV. TPM is never "actual memory", so
(according to your explanation, AIUI) it always traps to QEMU, per
access, and the C-bit doesn't interfere with that.
This is consistent with two facts about OVMF's PEI phase:
- We use IO Port-based fw_cfg (never DMA), if SEV is enabled (see
"QemuFwCfgPei.c").
- We access PCI config space via IO Ports (0xCF8, 0xCFC), never ECAM.
(This was not motivated by SEV, see commit 7523788faa51, but it does
play nice with SEV, in the PEI phase -- I think?)
What I'm confused about, now, in retrospect, is the reference to the PCI
MMIO aperture, in AmdSevDxe. If that area isn't backed by a KVM memslot
*either* -- similarly to the TPM area --, then decrypting *that* in
AmdSevDxe (via "nonexistent") is not strictly necessary. Is that correct?
I'm not asking for any code changes, just trying to form a consistent view.
Another question (still for "base SEV"): when OVMF is built with
SMM_REQUIRE, PlatformPei performs a (read-only) variable access. See the
ReadOnlyVariable2->GetVariable() call in the RefreshMemTypeInfo()
function. When SEV is active, does control reach RefreshMemTypeInfo() on
your end? And does ReadOnlyVariable2->GetVariable() succeed for you?
(There is a DEBUG_VERBOSE message in OnReadOnlyVariable2Available(), and
a DEBUG_ERROR in RefreshMemTypeInfo(), so the above questions can be
answered just from the log; no need to modify the code for that.)
Basically, with SEV enabled, I expect ReadOnlyVariable2->GetVariable()
to fail -- or even to remain unreached, as FaultTolerantWritePei and
VariablePei could bail out earlier (before installing the Variable PPI),
due to failing flash accesses. In case I'm *not* wrong -- it's not the
end of the world, I'm only asking this question too for the sake of
clarifying "C-bit vs. MMIO".
More or less it seems to boil down to whether there is a KVM memslot or
not -- which is *not* equivalent to OVMF considering the area MMIO or not.
>> SEV-ES would also work
>> properly if the mitigation for accessing an encrypted address was removed
>> from the #VC handler. It is only this added mitigation to protect MMIO
>> that results in an issue with the TPM in PEI.
>
> So I'm thinking that I can have TpmMmioSevDecryptPeim.c do this:
>
> //
> // If SEV or SEV-ES is active, MMIO succeeds against an encrypted physical
> // address because the nested page fault (NPF) that occurs on access does not
> // include the encryption bit in the guest physical address provided to the
> // hypervisor.
> //
> // However, if SEV-ES is active, before performing the actual MMIO, an
> // additional MMIO mitigation check is performed in the #VC handler to ensure
> // that MMIO is being done to an unencrypted address. To prevent guest
> // termination in this scenario, mark the range unencrypted ahead of access.
> //
> if (MemEncryptSevEsIsEnabled ()) {
> // Do MemEncryptSevClearPageEncMask() ...
> }
>
> Let me submit the next version with this and see what you think.
Yep, I'll review that now.
Thanks
Laszlo
>
> Thanks,
> Tom
>
>>
>>>
>>> I think the behavior you currently see is actually what we want, we
>>> should double down on it -- if MemEncryptSevClearPageEncMask() fails,
>>> report an explicit DEBUG_ERROR, and call CpuDeadLoop(). If the firmware
>>> is built with TPM_ENABLE, and SEV is active, then an IA32 PEI phase is
>>> simply unusable. Silently pretending that the TPM is not there, even
>>> though it may have been configured on the QEMU command line, we just
>>> failed to communicate with it, is not a good idea, IMO.
>>
>> However, because the c-bit is not part of the NPF, we do communicate
>> successfully with the TPM.
>>
>> So we could actually do following:
>> - For IA32:
>> - Remove the Depex on gOvmfTpmMmioAccessiblePpiGuid
>> - Do not add OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf
>>
>> - For X64:
>> - Add the Depex on gOvmfTpmMmioAccessiblePpiGuid
>> - Add OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf
>>
>> That might be confusing, though. So we could just do option #3 below.
>>
>> Thanks,
>> Tom
>>
>>>
>>> This is somewhat similar IMO to the S3Verification() function in
>>> "OvmfPkg/PlatformPei/Platform.c".
>>>
>>> TPM_ENABLE, SEV, IA32 PEI phase: pick any two.
>>>
>>> Thanks,
>>> Laszlo
>>>
>>>>
>>>> 2. Call MemEncryptSevClearPageEncMask() for SEV or SEV-ES, but don't check
>>>> the return status.
>>>>
>>>> 3. Create Ia32 and X64 versions of internal functions, where the Ia32
>>>> version simply returns SUCCESS because it can't do anything and the X64
>>>> version calls MemEncryptSevClearPageEncMask(), allowing the main code
>>>> to ASSERT on any errors.
>>>>
>>>> I'm leaning towards #1, because this is an SEV-ES only issue. Thoughts?
>>>>
>>>> Thanks,
>>>> Tom
>>>>
>>>>>
>>>>> One thing I found is that the Bhyve package makes reference to the
>>>>> OvmfPkg/Bhyve/Tcg directory, but that directory does not exist. So I don't
>>>>> think that TPM enablement has been tested. I didn't update the Bhyve
>>>>> support for that reason.
>>>>>
>>>>> Thanks,
>>>>> Tom
>>>>>
>>>>>> Thanks!
>>>>>> Laszlo
>>>>>>
>>>>
>>>
>
next prev parent reply other threads:[~2021-04-28 16:12 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-04-20 22:54 [PATCH 0/3] SEV-ES TPM enablement fixes Lendacky, Thomas
2021-04-20 22:54 ` [PATCH 1/3] OvfmPkg/VmgExitLib: Properly decode MMIO MOVZX and MOVSX opcodes Lendacky, Thomas
2021-04-22 5:28 ` [edk2-devel] " Laszlo Ersek
2021-04-22 13:35 ` Lendacky, Thomas
2021-04-23 9:07 ` Laszlo Ersek
2021-04-20 22:54 ` [PATCH 2/3] OvmfPkg/VmgExitLib: Add support for new MMIO MOV opcodes Lendacky, Thomas
2021-04-22 5:50 ` [edk2-devel] " Laszlo Ersek
2021-04-22 14:15 ` Lendacky, Thomas
2021-04-22 15:42 ` Lendacky, Thomas
2021-04-23 9:10 ` Laszlo Ersek
2021-04-23 13:24 ` Lendacky, Thomas
2021-04-20 22:54 ` [PATCH 3/3] OvmfPkg/PlatformPei: Mark TPM MMIO range as unencrypted for SEV Lendacky, Thomas
2021-04-20 23:17 ` Eric van Tassell
2021-04-21 14:09 ` [edk2-devel] " Andrew Fish
[not found] ` <1677E4DA25FD7265.31957@groups.io>
2021-04-21 17:20 ` Andrew Fish
2021-04-21 17:45 ` Lendacky, Thomas
2021-04-21 22:24 ` Andrew Fish
2021-04-22 6:07 ` Laszlo Ersek
2021-04-23 10:26 ` Laszlo Ersek
2021-04-23 13:04 ` [edk2-devel] " Laszlo Ersek
2021-04-23 13:09 ` Laszlo Ersek
2021-04-23 17:41 ` Lendacky, Thomas
2021-04-23 20:02 ` Lendacky, Thomas
2021-04-26 12:07 ` Laszlo Ersek
2021-04-26 14:21 ` Lendacky, Thomas
2021-04-27 14:58 ` Lendacky, Thomas
2021-04-28 16:12 ` Laszlo Ersek [this message]
2021-04-28 19:09 ` Lendacky, Thomas
2021-04-30 15:39 ` Laszlo Ersek
2021-04-30 17:37 ` Lendacky, Thomas
2021-04-26 11:08 ` Laszlo Ersek
[not found] ` <1677B2EC90F30786.1355@groups.io>
2021-04-20 23:13 ` Lendacky, Thomas
2021-04-22 7:34 ` Laszlo Ersek
2021-04-22 8:31 ` Laszlo Ersek
2021-04-22 8:39 ` Laszlo Ersek
2021-04-22 19:10 ` Lendacky, Thomas
2021-04-23 9:28 ` Laszlo Ersek
2021-04-22 14:51 ` Lendacky, Thomas
2021-04-22 16:04 ` Lendacky, Thomas
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=3f2e589d-7258-c372-c1ab-60992351dbde@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