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:
parent
d1fddc4533
commit
c15da8eb35
@ -28,6 +28,10 @@ GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mPciResourceTypeStr[] = {
|
|||||||
L"I/O", L"Mem", L"PMem", L"Mem64", L"PMem64", L"Bus"
|
L"I/O", L"Mem", L"PMem", L"Mem64", L"PMem64", L"Bus"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EDKII_IOMMU_PROTOCOL *mIoMmuProtocol;
|
||||||
|
EFI_EVENT mIoMmuEvent;
|
||||||
|
VOID *mIoMmuRegistration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Ensure the compatibility of an IO space descriptor with the IO aperture.
|
Ensure the compatibility of an IO space descriptor with the IO aperture.
|
||||||
|
|
||||||
@ -312,6 +316,28 @@ FreeMemorySpaceMap:
|
|||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Event notification that is fired when IOMMU protocol is installed.
|
||||||
|
|
||||||
|
@param Event The Event that is being processed.
|
||||||
|
@param Context Event Context.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
IoMmuProtocolCallback (
|
||||||
|
IN EFI_EVENT Event,
|
||||||
|
IN VOID *Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
Status = gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **)&mIoMmuProtocol);
|
||||||
|
if (!EFI_ERROR(Status)) {
|
||||||
|
gBS->CloseEvent (mIoMmuEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
Entry point of this driver.
|
Entry point of this driver.
|
||||||
@ -489,6 +515,17 @@ InitializePciHostBridge (
|
|||||||
ASSERT_EFI_ERROR (Status);
|
ASSERT_EFI_ERROR (Status);
|
||||||
}
|
}
|
||||||
PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);
|
PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);
|
||||||
|
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
mIoMmuEvent = EfiCreateProtocolNotifyEvent (
|
||||||
|
&gEdkiiIoMmuProtocolGuid,
|
||||||
|
TPL_CALLBACK,
|
||||||
|
IoMmuProtocolCallback,
|
||||||
|
NULL,
|
||||||
|
&mIoMmuRegistration
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
BaseMemoryLib
|
BaseMemoryLib
|
||||||
BaseLib
|
BaseLib
|
||||||
PciSegmentLib
|
PciSegmentLib
|
||||||
|
UefiLib
|
||||||
PciHostBridgeLib
|
PciHostBridgeLib
|
||||||
|
|
||||||
[Protocols]
|
[Protocols]
|
||||||
@ -49,6 +50,7 @@
|
|||||||
gEfiDevicePathProtocolGuid ## BY_START
|
gEfiDevicePathProtocolGuid ## BY_START
|
||||||
gEfiPciRootBridgeIoProtocolGuid ## BY_START
|
gEfiPciRootBridgeIoProtocolGuid ## BY_START
|
||||||
gEfiPciHostBridgeResourceAllocationProtocolGuid ## BY_START
|
gEfiPciHostBridgeResourceAllocationProtocolGuid ## BY_START
|
||||||
|
gEdkiiIoMmuProtocolGuid ## SOMETIMES_CONSUMES
|
||||||
|
|
||||||
[Depex]
|
[Depex]
|
||||||
gEfiCpuIo2ProtocolGuid AND
|
gEfiCpuIo2ProtocolGuid AND
|
||||||
|
@ -27,6 +27,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#include <Protocol/CpuIo2.h>
|
#include <Protocol/CpuIo2.h>
|
||||||
#include <Protocol/DevicePath.h>
|
#include <Protocol/DevicePath.h>
|
||||||
#include <Protocol/PciRootBridgeIo.h>
|
#include <Protocol/PciRootBridgeIo.h>
|
||||||
|
#include <Protocol/IoMmu.h>
|
||||||
#include <Library/DebugLib.h>
|
#include <Library/DebugLib.h>
|
||||||
#include <Library/DevicePathLib.h>
|
#include <Library/DevicePathLib.h>
|
||||||
#include <Library/BaseMemoryLib.h>
|
#include <Library/BaseMemoryLib.h>
|
||||||
@ -34,6 +35,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#include <Library/UefiBootServicesTableLib.h>
|
#include <Library/UefiBootServicesTableLib.h>
|
||||||
#include <Library/BaseLib.h>
|
#include <Library/BaseLib.h>
|
||||||
#include <Library/PciSegmentLib.h>
|
#include <Library/PciSegmentLib.h>
|
||||||
|
#include <Library/UefiLib.h>
|
||||||
#include "PciHostResource.h"
|
#include "PciHostResource.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,6 +17,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|||||||
#include "PciRootBridge.h"
|
#include "PciRootBridge.h"
|
||||||
#include "PciHostResource.h"
|
#include "PciHostResource.h"
|
||||||
|
|
||||||
|
extern EDKII_IOMMU_PROTOCOL *mIoMmuProtocol;
|
||||||
|
|
||||||
#define NO_MAPPING (VOID *) (UINTN) -1
|
#define NO_MAPPING (VOID *) (UINTN) -1
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -1072,6 +1074,26 @@ RootBridgeIoMap (
|
|||||||
|
|
||||||
RootBridge = ROOT_BRIDGE_FROM_THIS (This);
|
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;
|
PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
|
||||||
if ((!RootBridge->DmaAbove4G ||
|
if ((!RootBridge->DmaAbove4G ||
|
||||||
(Operation != EfiPciOperationBusMasterRead64 &&
|
(Operation != EfiPciOperationBusMasterRead64 &&
|
||||||
@ -1194,8 +1216,18 @@ RootBridgeIoUnmap (
|
|||||||
MAP_INFO *MapInfo;
|
MAP_INFO *MapInfo;
|
||||||
LIST_ENTRY *Link;
|
LIST_ENTRY *Link;
|
||||||
PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
|
PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
if (mIoMmuProtocol != NULL) {
|
||||||
|
Status = mIoMmuProtocol->Unmap (
|
||||||
|
mIoMmuProtocol,
|
||||||
|
Mapping
|
||||||
|
);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
RootBridge = ROOT_BRIDGE_FROM_THIS (This);
|
RootBridge = ROOT_BRIDGE_FROM_THIS (This);
|
||||||
|
|
||||||
//
|
//
|
||||||
// See if the Map() operation associated with this Unmap() required a mapping
|
// See if the Map() operation associated with this Unmap() required a mapping
|
||||||
// buffer. If a mapping buffer was not required, then this function simply
|
// buffer. If a mapping buffer was not required, then this function simply
|
||||||
@ -1312,6 +1344,24 @@ RootBridgeIoAllocateBuffer (
|
|||||||
|
|
||||||
RootBridge = ROOT_BRIDGE_FROM_THIS (This);
|
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;
|
AllocateType = AllocateAnyPages;
|
||||||
if (!RootBridge->DmaAbove4G ||
|
if (!RootBridge->DmaAbove4G ||
|
||||||
(Attributes & EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) {
|
(Attributes & EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) {
|
||||||
@ -1356,6 +1406,17 @@ RootBridgeIoFreeBuffer (
|
|||||||
OUT VOID *HostAddress
|
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);
|
return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user