[dma] Use virtual addresses for dma_map()

Cache management operations must generally be performed on virtual
addresses rather than physical addresses.

Change the address parameter in dma_map() to be a virtual address, and
make dma() the API-level primitive instead of dma_phys().

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2025-07-08 12:38:05 +01:00
parent 06083d2676
commit 22de0c4edf
5 changed files with 29 additions and 45 deletions

View File

@@ -47,7 +47,7 @@ PROVIDE_DMAAPI_INLINE ( flat, dma_free );
PROVIDE_DMAAPI_INLINE ( flat, dma_umalloc ); PROVIDE_DMAAPI_INLINE ( flat, dma_umalloc );
PROVIDE_DMAAPI_INLINE ( flat, dma_ufree ); PROVIDE_DMAAPI_INLINE ( flat, dma_ufree );
PROVIDE_DMAAPI_INLINE ( flat, dma_set_mask ); PROVIDE_DMAAPI_INLINE ( flat, dma_set_mask );
PROVIDE_DMAAPI_INLINE ( flat, dma_phys ); PROVIDE_DMAAPI_INLINE ( flat, dma );
/****************************************************************************** /******************************************************************************
* *
@@ -67,7 +67,7 @@ PROVIDE_DMAAPI_INLINE ( flat, dma_phys );
* @ret rc Return status code * @ret rc Return status code
*/ */
static int dma_op_map ( struct dma_device *dma, struct dma_mapping *map, static int dma_op_map ( struct dma_device *dma, struct dma_mapping *map,
physaddr_t addr, size_t len, int flags ) { void *addr, size_t len, int flags ) {
struct dma_operations *op = dma->op; struct dma_operations *op = dma->op;
if ( ! op ) if ( ! op )
@@ -175,4 +175,4 @@ PROVIDE_DMAAPI ( op, dma_free, dma_op_free );
PROVIDE_DMAAPI ( op, dma_umalloc, dma_op_umalloc ); PROVIDE_DMAAPI ( op, dma_umalloc, dma_op_umalloc );
PROVIDE_DMAAPI ( op, dma_ufree, dma_op_ufree ); PROVIDE_DMAAPI ( op, dma_ufree, dma_op_ufree );
PROVIDE_DMAAPI ( op, dma_set_mask, dma_op_set_mask ); PROVIDE_DMAAPI ( op, dma_set_mask, dma_op_set_mask );
PROVIDE_DMAAPI_INLINE ( op, dma_phys ); PROVIDE_DMAAPI_INLINE ( op, dma );

View File

@@ -65,8 +65,8 @@ int intelxl_msix_enable ( struct intelxl_nic *intelxl,
/* Map dummy target location */ /* Map dummy target location */
if ( ( rc = dma_map ( intelxl->dma, &intelxl->msix.map, if ( ( rc = dma_map ( intelxl->dma, &intelxl->msix.map,
virt_to_phys ( &intelxl->msix.msg ), &intelxl->msix.msg, sizeof ( intelxl->msix.msg ),
sizeof ( intelxl->msix.msg ), DMA_RX ) ) != 0 ) { DMA_RX ) ) != 0 ) {
DBGC ( intelxl, "INTELXL %p could not map MSI-X target: %s\n", DBGC ( intelxl, "INTELXL %p could not map MSI-X target: %s\n",
intelxl, strerror ( rc ) ); intelxl, strerror ( rc ) );
goto err_map; goto err_map;

View File

@@ -68,7 +68,7 @@ struct dma_operations {
* @ret rc Return status code * @ret rc Return status code
*/ */
int ( * map ) ( struct dma_device *dma, struct dma_mapping *map, int ( * map ) ( struct dma_device *dma, struct dma_mapping *map,
physaddr_t addr, size_t len, int flags ); void *addr, size_t len, int flags );
/** /**
* Unmap buffer * Unmap buffer
* *
@@ -178,8 +178,7 @@ struct dma_operations {
*/ */
static inline __always_inline int static inline __always_inline int
DMAAPI_INLINE ( flat, dma_map ) ( struct dma_device *dma, DMAAPI_INLINE ( flat, dma_map ) ( struct dma_device *dma,
struct dma_mapping *map, struct dma_mapping *map, void *addr __unused,
physaddr_t addr __unused,
size_t len __unused, int flags __unused ) { size_t len __unused, int flags __unused ) {
/* Increment mapping count (for debugging) */ /* Increment mapping count (for debugging) */
@@ -319,32 +318,31 @@ DMAAPI_INLINE ( flat, dma_set_mask ) ( struct dma_device *dma __unused,
} }
/** /**
* Get DMA address from physical address * Get DMA address from virtual address
* *
* @v map DMA mapping * @v map DMA mapping
* @v addr Physical address within the mapped region * @v addr Address within the mapped region
* @ret addr Device-side DMA address * @ret addr Device-side DMA address
*/ */
static inline __always_inline physaddr_t static inline __always_inline physaddr_t
DMAAPI_INLINE ( flat, dma_phys ) ( struct dma_mapping *map __unused, DMAAPI_INLINE ( flat, dma ) ( struct dma_mapping *map __unused, void *addr ) {
physaddr_t addr ) {
/* Use physical address as device address */ /* Use physical address as device address */
return addr; return virt_to_phys ( addr );
} }
/** /**
* Get DMA address from physical address * Get DMA address from virtual address
* *
* @v map DMA mapping * @v map DMA mapping
* @v addr Physical address within the mapped region * @v addr Address within the mapped region
* @ret addr Device-side DMA address * @ret addr Device-side DMA address
*/ */
static inline __always_inline physaddr_t static inline __always_inline physaddr_t
DMAAPI_INLINE ( op, dma_phys ) ( struct dma_mapping *map, physaddr_t addr ) { DMAAPI_INLINE ( op, dma ) ( struct dma_mapping *map, void *addr ) {
/* Adjust physical address using mapping offset */ /* Adjust physical address using mapping offset */
return ( addr + map->offset ); return ( virt_to_phys ( addr ) + map->offset );
} }
/** /**
@@ -358,7 +356,7 @@ DMAAPI_INLINE ( op, dma_phys ) ( struct dma_mapping *map, physaddr_t addr ) {
* @ret rc Return status code * @ret rc Return status code
*/ */
int dma_map ( struct dma_device *dma, struct dma_mapping *map, int dma_map ( struct dma_device *dma, struct dma_mapping *map,
physaddr_t addr, size_t len, int flags ); void *addr, size_t len, int flags );
/** /**
* Unmap buffer * Unmap buffer
@@ -417,28 +415,14 @@ void dma_ufree ( struct dma_mapping *map, void *addr, size_t len );
*/ */
void dma_set_mask ( struct dma_device *dma, physaddr_t mask ); void dma_set_mask ( struct dma_device *dma, physaddr_t mask );
/**
* Get DMA address from physical address
*
* @v map DMA mapping
* @v addr Physical address within the mapped region
* @ret addr Device-side DMA address
*/
physaddr_t dma_phys ( struct dma_mapping *map, physaddr_t addr );
/** /**
* Get DMA address from virtual address * Get DMA address from virtual address
* *
* @v map DMA mapping * @v map DMA mapping
* @v addr Virtual address within the mapped region * @v addr Address within the mapped region
* @ret addr Device-side DMA address * @ret addr Device-side DMA address
*/ */
static inline __always_inline physaddr_t dma ( struct dma_mapping *map, physaddr_t dma ( struct dma_mapping *map, void *addr );
void *addr ) {
/* Get DMA address from corresponding physical address */
return dma_phys ( map, virt_to_phys ( addr ) );
}
/** /**
* Check if DMA unmapping is required * Check if DMA unmapping is required

View File

@@ -230,8 +230,7 @@ static inline void iob_populate ( struct io_buffer *iobuf,
static inline __always_inline int iob_map ( struct io_buffer *iobuf, static inline __always_inline int iob_map ( struct io_buffer *iobuf,
struct dma_device *dma, struct dma_device *dma,
size_t len, int flags ) { size_t len, int flags ) {
return dma_map ( dma, &iobuf->map, virt_to_phys ( iobuf->data ), return dma_map ( dma, &iobuf->map, iobuf->data, len, flags );
len, flags );
} }
/** /**

View File

@@ -455,7 +455,7 @@ PROVIDE_PCIAPI ( efi, pci_ioremap, efipci_ioremap );
* @ret rc Return status code * @ret rc Return status code
*/ */
static int efipci_dma_map ( struct dma_device *dma, struct dma_mapping *map, static int efipci_dma_map ( struct dma_device *dma, struct dma_mapping *map,
physaddr_t addr, size_t len, int flags ) { void *addr, size_t len, int flags ) {
struct efi_pci_device *efipci = struct efi_pci_device *efipci =
container_of ( dma, struct efi_pci_device, pci.dma ); container_of ( dma, struct efi_pci_device, pci.dma );
struct pci_device *pci = &efipci->pci; struct pci_device *pci = &efipci->pci;
@@ -464,6 +464,7 @@ static int efipci_dma_map ( struct dma_device *dma, struct dma_mapping *map,
EFI_PHYSICAL_ADDRESS bus; EFI_PHYSICAL_ADDRESS bus;
UINTN count; UINTN count;
VOID *mapping; VOID *mapping;
physaddr_t phys;
EFI_STATUS efirc; EFI_STATUS efirc;
int rc; int rc;
@@ -486,18 +487,19 @@ static int efipci_dma_map ( struct dma_device *dma, struct dma_mapping *map,
} }
/* Map buffer (if non-zero length) */ /* Map buffer (if non-zero length) */
phys = virt_to_phys ( addr );
count = len; count = len;
if ( len ) { if ( len ) {
if ( ( efirc = pci_io->Map ( pci_io, op, phys_to_virt ( addr ), if ( ( efirc = pci_io->Map ( pci_io, op, addr, &count, &bus,
&count, &bus, &mapping ) ) != 0 ) { &mapping ) ) != 0 ) {
rc = -EEFI ( efirc ); rc = -EEFI ( efirc );
DBGC ( pci, "EFIPCI " PCI_FMT " cannot map %08lx+%zx: " DBGC ( pci, "EFIPCI " PCI_FMT " cannot map %p+%zx: "
"%s\n", PCI_ARGS ( pci ), addr, len, "%s\n", PCI_ARGS ( pci ), addr, len,
strerror ( rc ) ); strerror ( rc ) );
goto err_map; goto err_map;
} }
} else { } else {
bus = addr; bus = phys;
mapping = NULL; mapping = NULL;
} }
@@ -508,14 +510,14 @@ static int efipci_dma_map ( struct dma_device *dma, struct dma_mapping *map,
*/ */
if ( count != len ) { if ( count != len ) {
DBGC ( pci, "EFIPCI " PCI_FMT " attempted split mapping for " DBGC ( pci, "EFIPCI " PCI_FMT " attempted split mapping for "
"%08lx+%zx\n", PCI_ARGS ( pci ), addr, len ); "%p+%zx\n", PCI_ARGS ( pci ), addr, len );
rc = -ENOTSUP; rc = -ENOTSUP;
goto err_len; goto err_len;
} }
/* Populate mapping */ /* Populate mapping */
map->dma = dma; map->dma = dma;
map->offset = ( bus - addr ); map->offset = ( bus - phys );
map->token = mapping; map->token = mapping;
/* Increment mapping count (for debugging) */ /* Increment mapping count (for debugging) */
@@ -594,8 +596,7 @@ static void * efipci_dma_alloc ( struct dma_device *dma,
memset ( addr, 0, ( pages * EFI_PAGE_SIZE ) ); memset ( addr, 0, ( pages * EFI_PAGE_SIZE ) );
/* Map buffer */ /* Map buffer */
if ( ( rc = efipci_dma_map ( dma, map, virt_to_phys ( addr ), if ( ( rc = efipci_dma_map ( dma, map, addr, ( pages * EFI_PAGE_SIZE ),
( pages * EFI_PAGE_SIZE ),
DMA_BI ) ) != 0 ) DMA_BI ) ) != 0 )
goto err_map; goto err_map;