MdeModulePkg/PciBus: Add IOMMU support.

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>

(cherry picked from commit 11a6cc5bda)
This commit is contained in:
Jiewen Yao
2017-04-29 16:57:54 +08:00
committed by Star Zeng
parent 87ed293135
commit d4fd304f8e
4 changed files with 54 additions and 4 deletions

View File

@@ -14,6 +14,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "PciBus.h"
extern EDKII_IOMMU_PROTOCOL *mIoMmuProtocol;
//
// Pci Io Protocol Interface
//
@@ -965,8 +967,10 @@ PciIoMap (
OUT VOID **Mapping
)
{
EFI_STATUS Status;
PCI_IO_DEVICE *PciIoDevice;
EFI_STATUS Status;
PCI_IO_DEVICE *PciIoDevice;
UINT64 IoMmuAttribute;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION RootBridgeIoOperation;
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
@@ -978,13 +982,14 @@ PciIoMap (
return EFI_INVALID_PARAMETER;
}
RootBridgeIoOperation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION)Operation;
if ((PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) != 0) {
Operation = (EFI_PCI_IO_PROTOCOL_OPERATION) (Operation + EfiPciOperationBusMasterRead64);
RootBridgeIoOperation = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION)(Operation + EfiPciOperationBusMasterRead64);
}
Status = PciIoDevice->PciRootBridgeIo->Map (
PciIoDevice->PciRootBridgeIo,
(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,
RootBridgeIoOperation,
HostAddress,
NumberOfBytes,
DeviceAddress,
@@ -999,6 +1004,31 @@ PciIoMap (
);
}
if (mIoMmuProtocol != NULL) {
if (!EFI_ERROR (Status)) {
switch (Operation) {
case EfiPciIoOperationBusMasterRead:
IoMmuAttribute = EDKII_IOMMU_ACCESS_READ;
break;
case EfiPciIoOperationBusMasterWrite:
IoMmuAttribute = EDKII_IOMMU_ACCESS_WRITE;
break;
case EfiPciIoOperationBusMasterCommonBuffer:
IoMmuAttribute = EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE;
break;
default:
ASSERT(FALSE);
return EFI_INVALID_PARAMETER;
}
mIoMmuProtocol->SetAttribute (
mIoMmuProtocol,
PciIoDevice->Handle,
*Mapping,
IoMmuAttribute
);
}
}
return Status;
}
@@ -1024,6 +1054,15 @@ PciIoUnmap (
PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);
if (mIoMmuProtocol != NULL) {
mIoMmuProtocol->SetAttribute (
mIoMmuProtocol,
PciIoDevice->Handle,
Mapping,
0
);
}
Status = PciIoDevice->PciRootBridgeIo->Unmap (
PciIoDevice->PciRootBridgeIo,
Mapping