MdeModulePkg/PciHostBridge: Add IOMMU support.

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>
This commit is contained in:
Jiewen Yao
2017-04-29 16:23:58 +08:00
parent d1fddc4533
commit c15da8eb35
4 changed files with 102 additions and 0 deletions

View File

@@ -17,6 +17,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "PciRootBridge.h"
#include "PciHostResource.h"
extern EDKII_IOMMU_PROTOCOL *mIoMmuProtocol;
#define NO_MAPPING (VOID *) (UINTN) -1
//
@@ -1072,6 +1074,26 @@ RootBridgeIoMap (
RootBridge = ROOT_BRIDGE_FROM_THIS (This);
if (mIoMmuProtocol != NULL) {
if (!RootBridge->DmaAbove4G) {
//
// Clear 64bit support
//
if (Operation > EfiPciOperationBusMasterCommonBuffer) {
Operation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) (Operation - EfiPciOperationBusMasterRead64);
}
}
Status = mIoMmuProtocol->Map (
mIoMmuProtocol,
Operation,
HostAddress,
NumberOfBytes,
DeviceAddress,
Mapping
);
return Status;
}
PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
if ((!RootBridge->DmaAbove4G ||
(Operation != EfiPciOperationBusMasterRead64 &&
@@ -1194,8 +1216,18 @@ RootBridgeIoUnmap (
MAP_INFO *MapInfo;
LIST_ENTRY *Link;
PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
EFI_STATUS Status;
if (mIoMmuProtocol != NULL) {
Status = mIoMmuProtocol->Unmap (
mIoMmuProtocol,
Mapping
);
return Status;
}
RootBridge = ROOT_BRIDGE_FROM_THIS (This);
//
// See if the Map() operation associated with this Unmap() required a mapping
// buffer. If a mapping buffer was not required, then this function simply
@@ -1312,6 +1344,24 @@ RootBridgeIoAllocateBuffer (
RootBridge = ROOT_BRIDGE_FROM_THIS (This);
if (mIoMmuProtocol != NULL) {
if (!RootBridge->DmaAbove4G) {
//
// Clear DUAL_ADDRESS_CYCLE
//
Attributes &= ~EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;
}
Status = mIoMmuProtocol->AllocateBuffer (
mIoMmuProtocol,
Type,
MemoryType,
Pages,
HostAddress,
Attributes
);
return Status;
}
AllocateType = AllocateAnyPages;
if (!RootBridge->DmaAbove4G ||
(Attributes & EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) {
@@ -1356,6 +1406,17 @@ RootBridgeIoFreeBuffer (
OUT VOID *HostAddress
)
{
EFI_STATUS Status;
if (mIoMmuProtocol != NULL) {
Status = mIoMmuProtocol->FreeBuffer (
mIoMmuProtocol,
Pages,
HostAddress
);
return Status;
}
return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);
}