diff mbox

[edk2,6/7] MdeModulePkg/PciHostBridgeDxe: restrict 64-bit DMA to devices that support it

Message ID 1473067049-16252-7-git-send-email-ard.biesheuvel@linaro.org
State Accepted
Commit e58a71d9c50ba641b5ab19f5ce2cbf772187de4d
Headers show

Commit Message

Ard Biesheuvel Sept. 5, 2016, 9:17 a.m. UTC
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|CommBuffer}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>

---
 MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

-- 
2.7.4

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Comments

Laszlo Ersek Sept. 5, 2016, 12:04 p.m. UTC | #1
On 09/05/16 11:17, Ard Biesheuvel wrote:
> 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|CommBuffer}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>

> ---

>  MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c | 14 ++++++++++----

>  1 file changed, 10 insertions(+), 4 deletions(-)

> 

> diff --git a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c

> index b2d76d67afa2..8af131b0af37 100644

> --- a/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c

> +++ b/MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciRootBridgeIo.c

> @@ -1073,10 +1073,15 @@ RootBridgeIoMap (

>    RootBridge = ROOT_BRIDGE_FROM_THIS (This);

>  

>    PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;

> -  if (!RootBridge->DmaAbove4G && ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) {

> +  if ((!RootBridge->DmaAbove4G ||

> +       (Operation != EfiPciOperationBusMasterRead64 &&

> +        Operation != EfiPciOperationBusMasterWrite64 &&

> +        Operation != EfiPciOperationBusMasterCommonBuffer64)) &&

> +      ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) {

> +

>      //

> -    // If the root bridge can not handle performing DMA above 4GB but

> -    // any part of the DMA transfer being mapped is above 4GB, then

> +    // If the root bridge or the device cannot handle performing DMA above

> +    // 4GB but any part of the DMA transfer being mapped is above 4GB, then

>      // map the DMA transfer to a buffer below 4GB.

>      //

>  

> @@ -1308,7 +1313,8 @@ RootBridgeIoAllocateBuffer (

>    RootBridge = ROOT_BRIDGE_FROM_THIS (This);

>  

>    AllocateType = AllocateAnyPages;

> -  if (!RootBridge->DmaAbove4G) {

> +  if (!RootBridge->DmaAbove4G ||

> +      (Attributes & EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) {

>      //

>      // Limit allocations to memory below 4GB

>      //

> 


Reviewed-by: Laszlo Ersek <lersek@redhat.com>


_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
diff mbox

Patch

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