If IOMMU protocol is installed, PciHostBridge just calls
IOMMU AllocateBuffer/FreeBuffer/Map/Unmap.
PciHostBridge does not set IOMMU access attribute,
because it does not know which device request the DMA.
This work is done by PciBus driver.
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>
L"I/O", L"Mem", L"PMem", L"Mem64", L"PMem64", L"Bus"\r
};\r
\r
L"I/O", L"Mem", L"PMem", L"Mem64", L"PMem64", L"Bus"\r
};\r
\r
+EDKII_IOMMU_PROTOCOL *mIoMmuProtocol;\r
+EFI_EVENT mIoMmuEvent;\r
+VOID *mIoMmuRegistration;\r
+\r
/**\r
Ensure the compatibility of an IO space descriptor with the IO aperture.\r
\r
/**\r
Ensure the compatibility of an IO space descriptor with the IO aperture.\r
\r
+/**\r
+ Event notification that is fired when IOMMU protocol is installed.\r
+\r
+ @param Event The Event that is being processed.\r
+ @param Context Event Context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+IoMmuProtocolCallback (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **)&mIoMmuProtocol);\r
+ if (!EFI_ERROR(Status)) {\r
+ gBS->CloseEvent (mIoMmuEvent);\r
+ }\r
+}\r
+\r
/**\r
\r
Entry point of this driver.\r
/**\r
\r
Entry point of this driver.\r
ASSERT_EFI_ERROR (Status);\r
}\r
PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);\r
ASSERT_EFI_ERROR (Status);\r
}\r
PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ mIoMmuEvent = EfiCreateProtocolNotifyEvent (\r
+ &gEdkiiIoMmuProtocolGuid,\r
+ TPL_CALLBACK,\r
+ IoMmuProtocolCallback,\r
+ NULL,\r
+ &mIoMmuRegistration\r
+ );\r
+ }\r
+\r
BaseMemoryLib\r
BaseLib\r
PciSegmentLib\r
BaseMemoryLib\r
BaseLib\r
PciSegmentLib\r
PciHostBridgeLib\r
\r
[Protocols]\r
PciHostBridgeLib\r
\r
[Protocols]\r
gEfiDevicePathProtocolGuid ## BY_START\r
gEfiPciRootBridgeIoProtocolGuid ## BY_START\r
gEfiPciHostBridgeResourceAllocationProtocolGuid ## BY_START\r
gEfiDevicePathProtocolGuid ## BY_START\r
gEfiPciRootBridgeIoProtocolGuid ## BY_START\r
gEfiPciHostBridgeResourceAllocationProtocolGuid ## BY_START\r
+ gEdkiiIoMmuProtocolGuid ## SOMETIMES_CONSUMES\r
\r
[Depex]\r
gEfiCpuIo2ProtocolGuid AND\r
\r
[Depex]\r
gEfiCpuIo2ProtocolGuid AND\r
#include <Protocol/CpuIo2.h>\r
#include <Protocol/DevicePath.h>\r
#include <Protocol/PciRootBridgeIo.h>\r
#include <Protocol/CpuIo2.h>\r
#include <Protocol/DevicePath.h>\r
#include <Protocol/PciRootBridgeIo.h>\r
+#include <Protocol/IoMmu.h>\r
#include <Library/DebugLib.h>\r
#include <Library/DevicePathLib.h>\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/DebugLib.h>\r
#include <Library/DevicePathLib.h>\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/UefiBootServicesTableLib.h>\r
#include <Library/BaseLib.h>\r
#include <Library/PciSegmentLib.h>\r
#include <Library/UefiBootServicesTableLib.h>\r
#include <Library/BaseLib.h>\r
#include <Library/PciSegmentLib.h>\r
+#include <Library/UefiLib.h>\r
#include "PciHostResource.h"\r
\r
\r
#include "PciHostResource.h"\r
\r
\r
#include "PciRootBridge.h"\r
#include "PciHostResource.h"\r
\r
#include "PciRootBridge.h"\r
#include "PciHostResource.h"\r
\r
+extern EDKII_IOMMU_PROTOCOL *mIoMmuProtocol;\r
+\r
#define NO_MAPPING (VOID *) (UINTN) -1\r
\r
//\r
#define NO_MAPPING (VOID *) (UINTN) -1\r
\r
//\r
\r
RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
\r
\r
RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
\r
+ if (mIoMmuProtocol != NULL) {\r
+ if (!RootBridge->DmaAbove4G) {\r
+ //\r
+ // Clear 64bit support\r
+ //\r
+ if (Operation > EfiPciOperationBusMasterCommonBuffer) {\r
+ Operation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) (Operation - EfiPciOperationBusMasterRead64);\r
+ }\r
+ }\r
+ Status = mIoMmuProtocol->Map (\r
+ mIoMmuProtocol,\r
+ Operation,\r
+ HostAddress,\r
+ NumberOfBytes,\r
+ DeviceAddress,\r
+ Mapping\r
+ );\r
+ return Status;\r
+ }\r
+\r
PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;\r
if ((!RootBridge->DmaAbove4G ||\r
(Operation != EfiPciOperationBusMasterRead64 &&\r
PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;\r
if ((!RootBridge->DmaAbove4G ||\r
(Operation != EfiPciOperationBusMasterRead64 &&\r
MAP_INFO *MapInfo;\r
LIST_ENTRY *Link;\r
PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
MAP_INFO *MapInfo;\r
LIST_ENTRY *Link;\r
PCI_ROOT_BRIDGE_INSTANCE *RootBridge;\r
+ EFI_STATUS Status;\r
+\r
+ if (mIoMmuProtocol != NULL) {\r
+ Status = mIoMmuProtocol->Unmap (\r
+ mIoMmuProtocol,\r
+ Mapping\r
+ );\r
+ return Status;\r
+ }\r
\r
RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
\r
RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
//\r
// See if the Map() operation associated with this Unmap() required a mapping\r
// buffer. If a mapping buffer was not required, then this function simply\r
//\r
// See if the Map() operation associated with this Unmap() required a mapping\r
// buffer. If a mapping buffer was not required, then this function simply\r
\r
RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
\r
\r
RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
\r
+ if (mIoMmuProtocol != NULL) {\r
+ if (!RootBridge->DmaAbove4G) {\r
+ //\r
+ // Clear DUAL_ADDRESS_CYCLE\r
+ //\r
+ Attributes &= ~EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;\r
+ }\r
+ Status = mIoMmuProtocol->AllocateBuffer (\r
+ mIoMmuProtocol,\r
+ Type,\r
+ MemoryType,\r
+ Pages,\r
+ HostAddress,\r
+ Attributes\r
+ );\r
+ return Status;\r
+ }\r
+\r
AllocateType = AllocateAnyPages;\r
if (!RootBridge->DmaAbove4G ||\r
(Attributes & EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) {\r
AllocateType = AllocateAnyPages;\r
if (!RootBridge->DmaAbove4G ||\r
(Attributes & EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) {\r
OUT VOID *HostAddress\r
)\r
{\r
OUT VOID *HostAddress\r
)\r
{\r
+ EFI_STATUS Status;\r
+\r
+ if (mIoMmuProtocol != NULL) {\r
+ Status = mIoMmuProtocol->FreeBuffer (\r
+ mIoMmuProtocol,\r
+ Pages,\r
+ HostAddress\r
+ );\r
+ return Status;\r
+ }\r
+\r
return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);\r
}\r
\r
return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);\r
}\r
\r