From 332f59eb2ad804498ecd522c8d6abf0bcb2e3a3c Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Tue, 16 Nov 2021 23:13:11 -0500 Subject: [PATCH] libhsakmt: Implement dmabuf export for RDMA Implement hsaKmtExportDMABufHandle, which can be used for a new upstreamable RDMA solution. It exports a DMABuf handle for an arbitrary virtual address along with the offset of the address within the allocation. It also checks that the size of the intended export does not exceed the allocation. This uses the new AMDKFD_IOC_EXPORT_DMABUF, which requires KFD ioctl API version 1.12. Signed-off-by: Felix Kuehling Change-Id: Ie5fdb1f73ab3c7fa36c315ce326b1fb89eacc8b6 --- include/hsakmt.h | 20 +++++++++++++++++++ include/linux/kfd_ioctl.h | 14 +++++++++++-- src/fmm.c | 42 +++++++++++++++++++++++++++++++++++++++ src/fmm.h | 4 ++++ src/libhsakmt.ver | 1 + src/memory.c | 14 +++++++++++++ 6 files changed, 93 insertions(+), 2 deletions(-) diff --git a/include/hsakmt.h b/include/hsakmt.h index ca586ba36b..63ac299511 100644 --- a/include/hsakmt.h +++ b/include/hsakmt.h @@ -436,6 +436,26 @@ hsaKmtRegisterGraphicsHandleToNodes( HSAuint32* NodeArray //IN ); +/** + * Export a dmabuf handle and offset for a given memory address + * + * Validates that @MemoryAddress belongs to a valid allocation and that the + * @MemorySizeInBytes doesn't exceed the end of that allocation. Returns a + * dmabuf fd of the allocation and the offset of MemoryAddress within that + * allocation. The memory will remain allocated even after the allocation is + * freed by hsaKmtFreeMemory for as long as a dmabuf fd remains open or any + * importer of that fd maintains an active reference to the memory. + */ + +HSAKMT_STATUS +HSAKMTAPI +hsaKmtExportDMABufHandle( + void *MemoryAddress, //IN + HSAuint64 MemorySizeInBytes, //IN + int *DMABufFd, //OUT + HSAuint64 *Offset //OUT + ); + /** Export a memory buffer for sharing with other processes diff --git a/include/linux/kfd_ioctl.h b/include/linux/kfd_ioctl.h index 4898451b22..8dc670a4d6 100644 --- a/include/linux/kfd_ioctl.h +++ b/include/linux/kfd_ioctl.h @@ -37,9 +37,10 @@ * - 1.9 - Add available_memory ioctl * - 1.10 - Add SMI profiler event log * - 1.11 - Add unified memory for ctx save/restore area + * - 1.12 - Add DMA buf export ioctl */ #define KFD_IOCTL_MAJOR_VERSION 1 -#define KFD_IOCTL_MINOR_VERSION 11 +#define KFD_IOCTL_MINOR_VERSION 12 /* * Debug revision change log @@ -847,6 +848,12 @@ struct kfd_ioctl_import_dmabuf_args { __u32 dmabuf_fd; /* to KFD */ }; +struct kfd_ioctl_export_dmabuf_args { + __u64 handle; /* to KFD */ + __u32 flags; /* to KFD */ + __u32 dmabuf_fd; /* from KFD */ +}; + /* * KFD SMI(System Management Interface) events */ @@ -1345,8 +1352,11 @@ struct kfd_ioctl_set_xnack_mode_args { #define AMDKFD_IOC_AVAILABLE_MEMORY \ AMDKFD_IOWR(0x23, struct kfd_ioctl_get_available_memory_args) +#define AMDKFD_IOC_EXPORT_DMABUF \ + AMDKFD_IOWR(0x24, struct kfd_ioctl_export_dmabuf_args) + #define AMDKFD_COMMAND_START 0x01 -#define AMDKFD_COMMAND_END 0x24 +#define AMDKFD_COMMAND_END 0x25 /* non-upstream ioctls */ #define AMDKFD_IOC_IPC_IMPORT_HANDLE \ diff --git a/src/fmm.c b/src/fmm.c index 9f099c5a34..774f9e0cab 100644 --- a/src/fmm.c +++ b/src/fmm.c @@ -3309,6 +3309,48 @@ error_free_metadata: return status; } +HSAKMT_STATUS fmm_export_dma_buf_fd(void *MemoryAddress, + HSAuint64 MemorySizeInBytes, + int *DMABufFd, + HSAuint64 *Offset) +{ + struct kfd_ioctl_export_dmabuf_args exportArgs = {0}; + manageable_aperture_t *aperture; + HsaApertureInfo ApeInfo; + vm_object_t *obj; + HSAuint64 offset; + int r; + + aperture = fmm_find_aperture(MemoryAddress, &ApeInfo); + if (!aperture) + return HSAKMT_STATUS_INVALID_PARAMETER; + + pthread_mutex_lock(&aperture->fmm_mutex); + obj = vm_find_object_by_address_range(aperture, MemoryAddress); + if (obj) { + offset = VOID_PTRS_SUB(MemoryAddress, obj->start); + if (offset + MemorySizeInBytes <= obj->size) { + exportArgs.handle = obj->handle; + exportArgs.flags = O_CLOEXEC; + exportArgs.dmabuf_fd = 0; + } else { + obj = NULL; + } + } + pthread_mutex_unlock(&aperture->fmm_mutex); + if (!obj) + return HSAKMT_STATUS_INVALID_PARAMETER; + + r = kmtIoctl(kfd_fd, AMDKFD_IOC_EXPORT_DMABUF, (void *)&exportArgs); + if (r) + return HSAKMT_STATUS_ERROR; + + *DMABufFd = exportArgs.dmabuf_fd; + *Offset = offset; + + return HSAKMT_STATUS_SUCCESS; +} + HSAKMT_STATUS fmm_share_memory(void *MemoryAddress, HSAuint64 SizeInBytes, HsaSharedMemoryHandle *SharedMemoryHandle) diff --git a/src/fmm.h b/src/fmm.h index 498366e7a0..d0146d74cd 100644 --- a/src/fmm.h +++ b/src/fmm.h @@ -78,6 +78,10 @@ HSAKMT_STATUS fmm_register_graphics_handle(HSAuint64 GraphicsResourceHandle, uint32_t *gpu_id_array, uint32_t gpu_id_array_size); HSAKMT_STATUS fmm_deregister_memory(void *address); +HSAKMT_STATUS fmm_export_dma_buf_fd(void *MemoryAddress, + HSAuint64 MemorySizeInBytes, + int *DMABufFd, + HSAuint64 *Offset); HSAKMT_STATUS fmm_share_memory(void *MemoryAddress, HSAuint64 SizeInBytes, HsaSharedMemoryHandle *SharedMemoryHandle); diff --git a/src/libhsakmt.ver b/src/libhsakmt.ver index 46370c6eee..50564de31b 100644 --- a/src/libhsakmt.ver +++ b/src/libhsakmt.ver @@ -70,6 +70,7 @@ hsaKmtSVMGetAttr; hsaKmtSetXNACKMode; hsaKmtGetXNACKMode; hsaKmtOpenSMI; +hsaKmtExportDMABufHandle; local: *; }; diff --git a/src/memory.c b/src/memory.c index 7f8e45b6e0..4cb05057ad 100644 --- a/src/memory.c +++ b/src/memory.c @@ -318,6 +318,20 @@ HSAKMT_STATUS HSAKMTAPI hsaKmtRegisterGraphicsHandleToNodes(HSAuint64 GraphicsRe return ret; } +HSAKMT_STATUS HSAKMTAPI hsaKmtExportDMABufHandle(void *MemoryAddress, + HSAuint64 MemorySizeInBytes, + int *DMABufFd, + HSAuint64 *Offset) +{ + CHECK_KFD_OPEN(); + CHECK_KFD_MINOR_VERSION(12); + + pr_debug("[%s] address %p\n", __func__, MemoryAddress); + + return fmm_export_dma_buf_fd(MemoryAddress, MemorySizeInBytes, + DMABufFd, Offset); +} + HSAKMT_STATUS HSAKMTAPI hsaKmtShareMemory(void *MemoryAddress, HSAuint64 SizeInBytes, HsaSharedMemoryHandle *SharedMemoryHandle)