]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg/PciHostBridgeDxe: restrict 64-bit DMA to devices that support it
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Mon, 5 Sep 2016 08:55:16 +0000 (09:55 +0100)
committerArd Biesheuvel <ard.biesheuvel@linaro.org>
Tue, 6 Sep 2016 14:46:38 +0000 (15:46 +0100)
Currently, the EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE attribute is completely
ignored by the PCI host bridge driver, which means that, on an implementation
that supports DMA above 4 GB, allocations above 4 GB may be provided to
devices that have not expressed support for it.

So in addition to checking 'RootBridge->DmaAbove4G' to establish whether the
root bridge itself supports DMA above 4 GB, we must also take into account
the operation type (EfiPciOperationBusMaster{Read|Write|CommonBuffer}64),
and the EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE attribute, when mapping and
allocating DMA memory, respectively.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Ruiyu Ni <Ruiyu.ni@intel.com>
MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c

index b2d76d67afa231bdb07c2027b138f5d7a79f9f89..8af131b0af375ed083e5fa635a65fbe79bef5ae5 100644 (file)
@@ -1073,10 +1073,15 @@ RootBridgeIoMap (
   RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
 \r
   PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;\r
-  if (!RootBridge->DmaAbove4G && ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) {\r
+  if ((!RootBridge->DmaAbove4G ||\r
+       (Operation != EfiPciOperationBusMasterRead64 &&\r
+        Operation != EfiPciOperationBusMasterWrite64 &&\r
+        Operation != EfiPciOperationBusMasterCommonBuffer64)) &&\r
+      ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) {\r
+\r
     //\r
-    // If the root bridge can not handle performing DMA above 4GB but\r
-    // any part of the DMA transfer being mapped is above 4GB, then\r
+    // If the root bridge or the device cannot handle performing DMA above\r
+    // 4GB but any part of the DMA transfer being mapped is above 4GB, then\r
     // map the DMA transfer to a buffer below 4GB.\r
     //\r
 \r
@@ -1308,7 +1313,8 @@ RootBridgeIoAllocateBuffer (
   RootBridge = ROOT_BRIDGE_FROM_THIS (This);\r
 \r
   AllocateType = AllocateAnyPages;\r
-  if (!RootBridge->DmaAbove4G) {\r
+  if (!RootBridge->DmaAbove4G ||\r
+      (Attributes & EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) {\r
     //\r
     // Limit allocations to memory below 4GB\r
     //\r