If IOMMU protocol is installed, PciBus need call IOMMU
to set access attribute for the PCI device in Map/Ummap.
Only after the access attribute is set, the PCI device can
access the DMA memory.
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Leo Duran <leo.duran@amd.com>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Previous patch Tested-by: Brijesh Singh <brijesh.singh@amd.com>
Previous patch Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
Reviewed-by: Leo Duran <leo.duran@amd.com>
\r
EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtocol;\r
EFI_PCI_OVERRIDE_PROTOCOL *gPciOverrideProtocol;\r
\r
EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtocol;\r
EFI_PCI_OVERRIDE_PROTOCOL *gPciOverrideProtocol;\r
+EDKII_IOMMU_PROTOCOL *mIoMmuProtocol;\r
\r
\r
GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL mPciHotPlugRequest = {\r
\r
\r
GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL mPciHotPlugRequest = {\r
+ if (mIoMmuProtocol == NULL) {\r
+ gBS->LocateProtocol (\r
+ &gEdkiiIoMmuProtocolGuid,\r
+ NULL,\r
+ (VOID **) &mIoMmuProtocol\r
+ );\r
+ }\r
+\r
if (PcdGetBool (PcdPciDisableBusEnumeration)) {\r
gFullEnumeration = FALSE;\r
} else {\r
if (PcdGetBool (PcdPciDisableBusEnumeration)) {\r
gFullEnumeration = FALSE;\r
} else {\r
#include <Protocol/IncompatiblePciDeviceSupport.h>\r
#include <Protocol/PciOverride.h>\r
#include <Protocol/PciEnumerationComplete.h>\r
#include <Protocol/IncompatiblePciDeviceSupport.h>\r
#include <Protocol/PciOverride.h>\r
#include <Protocol/PciEnumerationComplete.h>\r
+#include <Protocol/IoMmu.h>\r
\r
#include <Library/DebugLib.h>\r
#include <Library/UefiDriverEntryPoint.h>\r
\r
#include <Library/DebugLib.h>\r
#include <Library/UefiDriverEntryPoint.h>\r
gEfiPciRootBridgeIoProtocolGuid ## TO_START\r
gEfiIncompatiblePciDeviceSupportProtocolGuid ## SOMETIMES_CONSUMES\r
gEfiLoadFile2ProtocolGuid ## SOMETIMES_PRODUCES\r
gEfiPciRootBridgeIoProtocolGuid ## TO_START\r
gEfiIncompatiblePciDeviceSupportProtocolGuid ## SOMETIMES_CONSUMES\r
gEfiLoadFile2ProtocolGuid ## SOMETIMES_PRODUCES\r
+ gEdkiiIoMmuProtocolGuid ## SOMETIMES_CONSUMES\r
\r
[FeaturePcd]\r
gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport ## CONSUMES\r
\r
[FeaturePcd]\r
gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport ## CONSUMES\r
\r
#include "PciBus.h"\r
\r
\r
#include "PciBus.h"\r
\r
+extern EDKII_IOMMU_PROTOCOL *mIoMmuProtocol;\r
+\r
//\r
// Pci Io Protocol Interface\r
//\r
//\r
// Pci Io Protocol Interface\r
//\r
OUT VOID **Mapping\r
)\r
{\r
OUT VOID **Mapping\r
)\r
{\r
- EFI_STATUS Status;\r
- PCI_IO_DEVICE *PciIoDevice;\r
+ EFI_STATUS Status;\r
+ PCI_IO_DEVICE *PciIoDevice;\r
+ UINT64 IoMmuAttribute;\r
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION RootBridgeIoOperation;\r
\r
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
\r
\r
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
+ RootBridgeIoOperation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION)Operation;\r
if ((PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) != 0) {\r
if ((PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) != 0) {\r
- Operation = (EFI_PCI_IO_PROTOCOL_OPERATION) (Operation + EfiPciOperationBusMasterRead64);\r
+ RootBridgeIoOperation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION)(Operation + EfiPciOperationBusMasterRead64);\r
}\r
\r
Status = PciIoDevice->PciRootBridgeIo->Map (\r
PciIoDevice->PciRootBridgeIo,\r
}\r
\r
Status = PciIoDevice->PciRootBridgeIo->Map (\r
PciIoDevice->PciRootBridgeIo,\r
- (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,\r
+ RootBridgeIoOperation,\r
HostAddress,\r
NumberOfBytes,\r
DeviceAddress,\r
HostAddress,\r
NumberOfBytes,\r
DeviceAddress,\r
+ if (mIoMmuProtocol != NULL) {\r
+ if (!EFI_ERROR (Status)) {\r
+ switch (Operation) {\r
+ case EfiPciIoOperationBusMasterRead:\r
+ IoMmuAttribute = EDKII_IOMMU_ACCESS_READ;\r
+ break;\r
+ case EfiPciIoOperationBusMasterWrite:\r
+ IoMmuAttribute = EDKII_IOMMU_ACCESS_WRITE;\r
+ break;\r
+ case EfiPciIoOperationBusMasterCommonBuffer:\r
+ IoMmuAttribute = EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE;\r
+ break;\r
+ default:\r
+ ASSERT(FALSE);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ mIoMmuProtocol->SetAttribute (\r
+ mIoMmuProtocol,\r
+ PciIoDevice->Handle,\r
+ *Mapping,\r
+ IoMmuAttribute\r
+ );\r
+ }\r
+ }\r
+\r
\r
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
\r
\r
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
\r
+ if (mIoMmuProtocol != NULL) {\r
+ mIoMmuProtocol->SetAttribute (\r
+ mIoMmuProtocol,\r
+ PciIoDevice->Handle,\r
+ Mapping,\r
+ 0\r
+ );\r
+ }\r
+\r
Status = PciIoDevice->PciRootBridgeIo->Unmap (\r
PciIoDevice->PciRootBridgeIo,\r
Mapping\r
Status = PciIoDevice->PciRootBridgeIo->Unmap (\r
PciIoDevice->PciRootBridgeIo,\r
Mapping\r