ArmPkg/ArmDmaLib: clean up abuse of device address

In preparation of adding support to ArmDmalib for DMA bus masters whose
view of memory is offset by a constant compared to the CPU's view, clean
up some abuse of the device address.

The device address is not defined in terms of the CPU's address space,
and so it should not be used in CopyMem () or cache maintenance operations
that require a valid mapping. This not only applies to the above use case,
but also to the DebugUncachedMemoryAllocationLib that unmaps the
primary, cached mapping of an allocation, and returns a host address
which is an uncached alias offset by a constant.

Since we should never access the device address from the CPU, there is
no need to record it in the MAPINFO struct. Instead, record the buffer
address in case of double buffering, since we do need to copy the contents
(in case of a bus master write) and free the buffer (in all cases) when
DmaUnmap() is called.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Tested-by: Ryan Harkin <ryan.harkin@linaro.org>
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
This commit is contained in:
Ard Biesheuvel 2016-11-12 14:02:27 +01:00 committed by Leif Lindholm
parent 0a99a65d2c
commit df8c2668d7
1 changed files with 8 additions and 7 deletions

View File

@ -27,7 +27,7 @@
typedef struct { typedef struct {
EFI_PHYSICAL_ADDRESS HostAddress; EFI_PHYSICAL_ADDRESS HostAddress;
EFI_PHYSICAL_ADDRESS DeviceAddress; VOID *BufferAddress;
UINTN NumberOfBytes; UINTN NumberOfBytes;
DMA_MAP_OPERATION Operation; DMA_MAP_OPERATION Operation;
BOOLEAN DoubleBuffer; BOOLEAN DoubleBuffer;
@ -92,7 +92,7 @@ DmaMap (
((*NumberOfBytes & (mCpu->DmaBufferAlignment - 1)) != 0)) { ((*NumberOfBytes & (mCpu->DmaBufferAlignment - 1)) != 0)) {
// Get the cacheability of the region // Get the cacheability of the region
Status = gDS->GetMemorySpaceDescriptor (*DeviceAddress, &GcdDescriptor); Status = gDS->GetMemorySpaceDescriptor ((UINTN)HostAddress, &GcdDescriptor);
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
goto FreeMapInfo; goto FreeMapInfo;
} }
@ -127,6 +127,7 @@ DmaMap (
} }
*DeviceAddress = ConvertToPhysicalAddress ((UINTN)Buffer); *DeviceAddress = ConvertToPhysicalAddress ((UINTN)Buffer);
Map->BufferAddress = Buffer;
} else { } else {
Map->DoubleBuffer = FALSE; Map->DoubleBuffer = FALSE;
} }
@ -142,7 +143,7 @@ DmaMap (
// So duplicate the check here when running in DEBUG mode, just to assert // So duplicate the check here when running in DEBUG mode, just to assert
// that we are not trying to create a consistent mapping for cached memory. // that we are not trying to create a consistent mapping for cached memory.
// //
Status = gDS->GetMemorySpaceDescriptor (*DeviceAddress, &GcdDescriptor); Status = gDS->GetMemorySpaceDescriptor ((UINTN)HostAddress, &GcdDescriptor);
ASSERT_EFI_ERROR(Status); ASSERT_EFI_ERROR(Status);
ASSERT (Operation != MapOperationBusMasterCommonBuffer || ASSERT (Operation != MapOperationBusMasterCommonBuffer ||
@ -151,12 +152,11 @@ DmaMap (
DEBUG_CODE_END (); DEBUG_CODE_END ();
// Flush the Data Cache (should not have any effect if the memory region is uncached) // Flush the Data Cache (should not have any effect if the memory region is uncached)
mCpu->FlushDataCache (mCpu, *DeviceAddress, *NumberOfBytes, mCpu->FlushDataCache (mCpu, (UINTN)HostAddress, *NumberOfBytes,
EfiCpuFlushTypeWriteBackInvalidate); EfiCpuFlushTypeWriteBackInvalidate);
} }
Map->HostAddress = (UINTN)HostAddress; Map->HostAddress = (UINTN)HostAddress;
Map->DeviceAddress = *DeviceAddress;
Map->NumberOfBytes = *NumberOfBytes; Map->NumberOfBytes = *NumberOfBytes;
Map->Operation = Operation; Map->Operation = Operation;
@ -206,10 +206,11 @@ DmaUnmap (
if (Map->Operation == MapOperationBusMasterCommonBuffer) { if (Map->Operation == MapOperationBusMasterCommonBuffer) {
Status = EFI_INVALID_PARAMETER; Status = EFI_INVALID_PARAMETER;
} else if (Map->Operation == MapOperationBusMasterWrite) { } else if (Map->Operation == MapOperationBusMasterWrite) {
CopyMem ((VOID *)(UINTN)Map->HostAddress, (VOID *)(UINTN)Map->DeviceAddress, Map->NumberOfBytes); CopyMem ((VOID *)(UINTN)Map->HostAddress, Map->BufferAddress,
Map->NumberOfBytes);
} }
DmaFreeBuffer (EFI_SIZE_TO_PAGES (Map->NumberOfBytes), (VOID *)(UINTN)Map->DeviceAddress); DmaFreeBuffer (EFI_SIZE_TO_PAGES (Map->NumberOfBytes), Map->BufferAddress);
} else { } else {
if (Map->Operation == MapOperationBusMasterWrite) { if (Map->Operation == MapOperationBusMasterWrite) {