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>
This commit is contained in:
Jiewen Yao 2017-04-29 16:57:54 +08:00
parent c15da8eb35
commit 11a6cc5bda
4 changed files with 54 additions and 4 deletions

View File

@ -42,6 +42,7 @@ UINT64 gAllZero = 0;
EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtocol;
EFI_PCI_OVERRIDE_PROTOCOL *gPciOverrideProtocol;
EDKII_IOMMU_PROTOCOL *mIoMmuProtocol;
GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL mPciHotPlugRequest = {
@ -284,6 +285,14 @@ PciBusDriverBindingStart (
);
}
if (mIoMmuProtocol == NULL) {
gBS->LocateProtocol (
&gEdkiiIoMmuProtocolGuid,
NULL,
(VOID **) &mIoMmuProtocol
);
}
if (PcdGetBool (PcdPciDisableBusEnumeration)) {
gFullEnumeration = FALSE;
} else {

View File

@ -32,6 +32,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Protocol/IncompatiblePciDeviceSupport.h>
#include <Protocol/PciOverride.h>
#include <Protocol/PciEnumerationComplete.h>
#include <Protocol/IoMmu.h>
#include <Library/DebugLib.h>
#include <Library/UefiDriverEntryPoint.h>

View File

@ -95,6 +95,7 @@
gEfiPciRootBridgeIoProtocolGuid ## TO_START
gEfiIncompatiblePciDeviceSupportProtocolGuid ## SOMETIMES_CONSUMES
gEfiLoadFile2ProtocolGuid ## SOMETIMES_PRODUCES
gEdkiiIoMmuProtocolGuid ## SOMETIMES_CONSUMES
[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdPciBusHotplugDeviceSupport ## CONSUMES

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