public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Lendacky, Thomas via groups.io" <thomas.lendacky=amd.com@groups.io>
To: Laszlo Ersek <lersek@redhat.com>,
	devel@edk2.groups.io, w.sheng@intel.com, "Xu,
	Min M" <min.m.xu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>, Huang Jenny <jenny.huang@intel.com>,
	Chiang Chris <chris.chiang@intel.com>
Subject: Re: [edk2-devel] [PATCH] MdeModulePkg/PciBusDxe: Add feedback status for PciIoMap
Date: Mon, 29 Jan 2024 13:30:34 -0600	[thread overview]
Message-ID: <3474f3a1-f90e-4e61-a7fc-5c659ce150c6@amd.com> (raw)
In-Reply-To: <451fee11-e982-802f-c30b-1b90b2251d70@redhat.com>

On 1/29/24 11:20, Laszlo Ersek wrote:
> On 1/26/24 18:56, Lendacky, Thomas via groups.io wrote:
>> On 1/26/24 11:38, Tom Lendacky wrote:
>>> +Min
>>>
>>> Adding Min to see if TDX is also experiencing issues around this
>>> recent change.
>>>
>>> Thanks,
>>> Tom
>>>
>>> On 1/26/24 11:21, Tom Lendacky wrote:
>>>> On 1/22/24 00:47, Sheng Wei via groups.io wrote:
>>>>> PciIoMap () need to feedback the status of
>>>>> mIoMmuProtocol->SetAttribute () return value.
>>>>>
>>>>> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4652
>>>>
>>>> I'm still investigating, but this commit breaks booting all types of
>>>> SEV guests. Without this patch, there is a boot device mapping and
>>>> the Grub menu is displayed. But with this patch, I receive:
>>>>
>>>> map: No mapping found.
>>>> Press ESC in 1 seconds to skip startup.nsh or any other key to continue.
>>>>
>>>> and then drop to the shell prompt.
>>
>> The IOMMU protocol is installed under OVMF when either SEV or TDX is
>> active. The SetAttribute() function of this implementation has always
>> returned EFI_UNSUPPORTED, which is now being passed pack to the caller
>> of PciIoMap() and thus causing a failure.
>>
>> Should the SetAttribute() function in OvmfPkg/IoMmuDxe/CcIoMmu.c return
>> success by default?
> 
> I don't understand why the EDKII_IOMMU_PROTOCOL.SetAttribute() member
> function exists in the first place. The documentation on
> EDKII_IOMMU_SET_ATTRIBUTE says that having specified BusMasterRead
> earlier as Operation for Map() corresponds to EDKII_IOMMU_ACCESS_READ,
> BusMasterWrite to EDKII_IOMMU_ACCESS_WRITE, and BusMasterCommonBuffer to
> EDKII_IOMMU_ACCESS_READ|EDKII_IOMMU_ACCESS_WRITE. This makes no sense to
> me because (a) these settings carry zero new information related to the
> earlier Map() call, and (b) the Map() call will have set up the
> IOMMU/memory config already, based on Operation.
> 
> In PciIoMap() [MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c], there is first a
> call to RootBridgeIoMap()
> [MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c], which in turn
> calls Map() on the IOMMU protocol. Thus, I don't see why PciBusDxe has
> to do anything extra here, in the first place. I wouldn't call
> EDKII_IOMMU_PROTOCOL.SetAttribute(); what's more, I'd argue that
> EDKII_IOMMU_PROTOCOL.SetAttribute() itself is mostly useless. (Not sure
> about "ACPI" devices; i.e. not PCI(e)).
> 
> Yet more confusion is that in the documentation of
> EDKII_IOMMU_SET_ATTRIBUTE [MdeModulePkg/Include/Protocol/IoMmu.h], the
> EFI_SUCCESS return status is described as "The IoMmuAccess is set for
> the memory range specified by DeviceAddress and Length" -- but there
> aren't even parameters called "DeviceAddress" and "Length"!
> 
> Then *even more* problems: EFI_INVALID_PARAMETER is supposed to be
> returned for DeviceHandle being invalid, EFI_UNSUPPORTED is supposed to
> be reutrned for DeviceHandle being unknown. So not only does the IOMMU
> driver have to recognize handles it doesn't know about, it even has to
> *distinguish* "plain unknown" from "invalid". That makes no sense at
> all. The IOMMU protocol has no use for a DeviceHandle anywhere else in
> the first place.
> 
> Either way, the right thing to do in OvmfPkg/IoMmuDxe should be:
> 
> - in IoMmuMap() [OvmfPkg/IoMmuDxe/CcIoMmu.c], we already save the
> requested operation in MapInfo->Operation (note that this is not
> EFI_PCI_IO_PROTOCOL_OPERATION, but EDKII_IOMMU_OPERATION: the former is
> mapped to the latter in the root bridge protocol impl., IIRC, but the
> latter also encodes 32-bit vs. 64-bit in the enum!)
> 
> - therefore in IoMmuSetAttribute() [OvmfPkg/IoMmuDxe/CcIoMmu.c], we
> should just ignore DeviceHandle, cast Mapping back to MAP_INFO (we could
> make an attempt to look it up first in "mMapInfos", but that's a total
> waste of time: just don't pass in crap, and then you won't get undefined
> behavior), and then compare MapInfo->Operation against IoMmuAccess.
> 
> For operations Read and Read64, accept EDKII_IOMMU_ACCESS_READ.
> 
> For operations Write and Write64, accept EDKII_IOMMU_ACCESS_WRITE.
> 
> For operations CommonBuffer and CommonBuffer64, accept
> EDKII_IOMMU_ACCESS_READ|EDKII_IOMMU_ACCESS_WRITE.
> 
> Always accept 0 as IoMmuAccess, too [*].
> 
> "Accept" means do nothing, and return EFI_SUCCESS.
> 
> Reject anything else with EFI_INVALID_PARAMETER or EFI_UNSUPPORTED.

Laszlo, if you mean something like this, I'll submit it as a proper patch:


OvmfPkg/IoMmuDxe: Provide an implementation for SetAttribute

From: Tom Lendacky <thomas.lendacky@amd.com>

A recent change to the PciIoMap() function now propagates the return code
from the IoMmu protocol SetAttribute() operation. The implementation of
this operation in OvmfPkg/IoMmuDxe/CcIoMmu.c returns EFI_UNSUPPORTED,
resulting in a failure to boot the guest.

Provide an implementation for SetAttribute() that validates that the IoMmu
access method being requested against the IoMmu mapping operation.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
  OvmfPkg/IoMmuDxe/CcIoMmu.c |   50 +++++++++++++++++++++++++++++++++++++++++++-
  1 file changed, 49 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/IoMmuDxe/CcIoMmu.c b/OvmfPkg/IoMmuDxe/CcIoMmu.c
index b83a9690062b..8bd95bfc6b90 100644
--- a/OvmfPkg/IoMmuDxe/CcIoMmu.c
+++ b/OvmfPkg/IoMmuDxe/CcIoMmu.c
@@ -751,7 +751,55 @@ IoMmuSetAttribute (
    IN UINT64                IoMmuAccess
    )
  {
-  return EFI_UNSUPPORTED;
+  MAP_INFO    *MapInfo;
+  EFI_STATUS  Status;
+
+  DEBUG ((DEBUG_VERBOSE, "%a: Mapping=0x%p Access=%ld\n", __func__, Mapping, IoMmuAccess));
+
+  if (Mapping == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = EFI_SUCCESS;
+
+  //
+  // An IoMmuAccess value of 0 is always accepted, validate any non-zero value.
+  //
+  if (IoMmuAccess != 0) {
+    MapInfo = (MAP_INFO *)Mapping;
+
+    //
+    // The mapping operation already implied the access mode. Validate that
+    // the supplied access mode matches operation access mode.
+    //
+    switch (MapInfo->Operation) {
+      case EdkiiIoMmuOperationBusMasterRead:
+      case EdkiiIoMmuOperationBusMasterRead64:
+        if (IoMmuAccess != EDKII_IOMMU_ACCESS_READ) {
+          Status = EFI_INVALID_PARAMETER;
+        }
+        break;
+
+      case EdkiiIoMmuOperationBusMasterWrite:
+      case EdkiiIoMmuOperationBusMasterWrite64:
+        if (IoMmuAccess != EDKII_IOMMU_ACCESS_WRITE) {
+          Status = EFI_INVALID_PARAMETER;
+        }
+        break;
+
+      case EdkiiIoMmuOperationBusMasterCommonBuffer:
+      case EdkiiIoMmuOperationBusMasterCommonBuffer64:
+        if (IoMmuAccess != (EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE)) {
+          Status = EFI_INVALID_PARAMETER;
+        }
+        break;
+
+      default:
+        Status = EFI_UNSUPPORTED;
+    }
+  }
+
+  return Status;
  }
  
  EDKII_IOMMU_PROTOCOL  mIoMmu = {


> 
> This would at least allow for a superficial consistency check, without
> (a) incurring large performance penalty (such as list walking) and (b)
> turning the SetAttribute() member function into a total joke. (Really,
> IMO it should not even exist at the protocol specification level!)
> 
> [*] OK, you might want to know why we should accept 0 too. Here's why:
> we have *another* mIoMmuProtocol->SetAttribute() call, namely in
> PciIoUnmap() [MdeModulePkg/Bus/Pci/PciBusDxe/PciIo.c]. It passes in
> IoMmuAccess=0.
> 
> Here's the sad bit: while this patch -- now commit 049695a0b1e2 --
> propagates the return status of mIoMmuProtocol->SetAttribute() out of
> PciIoMap(), the patch doesn't do the same for the other such call in
> PciIoUnmap(). That seems like a bug (omission) itself, but once that one
> gets fixed, we'll need to permit IoMmuAccess=0 too in OVMF's IOMMU driver.
> 
> I guess I could live with OVMF's IoMmuMap () doing nothing,
> successfully, rather than doing nothing, unsuccessfully, *if*
> EDKII_IOMMU_PROTOCOL.SetAttribute() had some public documentation rooted
> in reality, *and* if PciBusDxe called that function with proper error
> checking everywhere. Otherwise it's just another terrible, mis-specified
> API, that platforms must route around.
> 
> Wow I didn't expect to be worked up this much about it, but here I am. I
> dunno, seeing crap interfaces just makes me unreasonably irate.
> 
> Laszlo
> 


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114738): https://edk2.groups.io/g/devel/message/114738
Mute This Topic: https://groups.io/mt/103881889/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



  reply	other threads:[~2024-01-29 19:30 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-22  6:47 [edk2-devel] [PATCH] MdeModulePkg/PciBusDxe: Add feedback status for PciIoMap Sheng Wei
2024-01-23  3:26 ` Huang, Jenny
2024-01-24 12:25   ` Ni, Ray
2024-01-26 17:21 ` Lendacky, Thomas via groups.io
2024-01-26 17:38   ` Lendacky, Thomas via groups.io
2024-01-26 17:56     ` Lendacky, Thomas via groups.io
2024-01-29  5:20       ` Min Xu
2024-01-29 17:20       ` Laszlo Ersek
2024-01-29 19:30         ` Lendacky, Thomas via groups.io [this message]
2024-01-30 16:37           ` Laszlo Ersek
  -- strict thread matches above, loose matches on Subject: below --
2024-01-22  6:46 Sheng Wei

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=3474f3a1-f90e-4e61-a7fc-5c659ce150c6@amd.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