SWDEV-558848 - Move DRM calls to thunk for better abstraction (#1912)

* SWDEV-558848 - Move DRM calls to thunk for better abstraction

* Use thunk device handle instead of drm inside agent

* Update IPC functions with new thunk calls

* create hsaKmtHandleImport interface to support ipc

* Reset metadata inside hsaKmtMemHandleFree

* remove whitespaces and NULL usage

* Add thunk apis to libhsakmt.ver

* Add comments to new structs in thunk

* Minor fixes to declarations

* resolve merge conflicts in amd_kfd_driver

---------

Co-authored-by: Rahul Manocha <rmanocha@amd.com>
This commit is contained in:
Rahul Manocha
2026-01-27 08:56:57 -08:00
committed by GitHub
parent 3a479a25ad
commit 324a864bc4
13 changed files with 576 additions and 248 deletions
@@ -90,24 +90,24 @@ namespace AMD {
#if defined(__linux__)
static_assert(
(sizeof(core::ShareableHandle::handle) >= sizeof(amdgpu_bo_handle)) &&
(alignof(core::ShareableHandle::handle) >= alignof(amdgpu_bo_handle)),
"ShareableHandle cannot store a amdgpu_bo_handle");
(sizeof(core::ShareableHandle::handle) >= sizeof(HsaMemoryObjectHandle)) &&
(alignof(core::ShareableHandle::handle) >= alignof(HsaMemoryObjectHandle)),
"ShareableHandle cannot store a HsaMemoryObjectHandle");
#endif
namespace {
__forceinline uint64_t drm_perm(hsa_access_permission_t perm) {
__forceinline HsaMemoryMapFlags mem_perm(hsa_access_permission_t perm) {
switch (perm) {
case HSA_ACCESS_PERMISSION_RO:
return AMDGPU_VM_PAGE_READABLE;
return HSA_MEMORY_ACCESS_RO;
case HSA_ACCESS_PERMISSION_WO:
return AMDGPU_VM_PAGE_WRITEABLE;
return HSA_MEMORY_ACCESS_WO;
case HSA_ACCESS_PERMISSION_RW:
return AMDGPU_VM_PAGE_READABLE | AMDGPU_VM_PAGE_WRITEABLE;
return HSA_MEMORY_ACCESS_RW;
case HSA_ACCESS_PERMISSION_NONE:
default:
return 0;
return HSA_MEMORY_ACCESS_NONE;
}
}
@@ -475,52 +475,70 @@ hsa_status_t KfdDriver::ExportDMABuf(void *mem, size_t size, int *dmabuf_fd,
hsa_status_t KfdDriver::ImportDMABuf(int dmabuf_fd, core::Agent &agent,
core::ShareableHandle &handle) {
auto& gpu_agent = static_cast<GpuAgent&>(agent);
amdgpu_bo_import_result res;
auto ret = DRM_CALL(
amdgpu_bo_import(gpu_agent.libDrmDev(), amdgpu_bo_handle_type_dma_buf_fd, dmabuf_fd, &res));
if (ret) return HSA_STATUS_ERROR;
#if defined(__linux__)
auto &gpu_agent = static_cast<GpuAgent &>(agent);
HsaExternalHandleDesc desc;
desc.device_handle = gpu_agent.libThunkDev();
desc.fd = reinterpret_cast<HSAint32>(dmabuf_fd);
desc.type = HSA_EXTERNAL_HANDLE_DMA_BUF;
desc.metadata = 0;
HsaHandleImportFlags hflags = {0};
HsaHandleImportResult res;
HSAKMT_STATUS status = HSAKMT_CALL(hsaKmtHandleImport(&desc, &res, &hflags));
if (status != HSAKMT_STATUS_SUCCESS) {
return HSA_STATUS_ERROR;
}
handle.handle = reinterpret_cast<uint64_t>(res.buf_handle);
#else
assert(!"Unimplemented!");
#endif
return HSA_STATUS_SUCCESS;
}
hsa_status_t KfdDriver::Map(core::ShareableHandle handle, void *mem,
size_t offset, size_t size,
hsa_access_permission_t perms) {
const auto ldrm_bo = reinterpret_cast<amdgpu_bo_handle>(handle.handle);
if (!ldrm_bo)
return HSA_STATUS_ERROR;
if (DRM_CALL(amdgpu_bo_va_op(ldrm_bo, offset, size, reinterpret_cast<uint64_t>(mem),
drm_perm(perms), AMDGPU_VA_OP_MAP)) != 0)
#if defined(__linux__)
HsaMemoryObjectHandle memhandle = reinterpret_cast<HsaMemoryObjectHandle>(handle.handle);
HSAKMT_STATUS status = HSAKMT_CALL(hsaKmtMemoryVaMap(memhandle, reinterpret_cast<HSAuint64>(offset),
reinterpret_cast<HSAuint64>(size), reinterpret_cast<HSAuint64>(mem),
mem_perm(perms)));
if (status != HSAKMT_STATUS_SUCCESS) {
return HSA_STATUS_ERROR;
}
#else
assert(!"Unimplemented!");
#endif
return HSA_STATUS_SUCCESS;
}
hsa_status_t KfdDriver::Unmap(core::ShareableHandle handle, void *mem,
size_t offset, size_t size) {
const auto ldrm_bo = reinterpret_cast<amdgpu_bo_handle>(handle.handle);
if (!ldrm_bo)
return HSA_STATUS_ERROR;
if (DRM_CALL(amdgpu_bo_va_op(ldrm_bo, offset, size, reinterpret_cast<uint64_t>(mem), 0,
AMDGPU_VA_OP_UNMAP)) != 0)
#if defined(__linux__)
HsaMemoryObjectHandle memhandle = reinterpret_cast<HsaMemoryObjectHandle>(handle.handle);
HSAKMT_STATUS status = HSAKMT_CALL(hsaKmtMemoryVaUnmap(memhandle, (HSAuint64)offset, (HSAuint64)size,
reinterpret_cast<HSAuint64>(mem)));
if (status != HSAKMT_STATUS_SUCCESS) {
return HSA_STATUS_ERROR;
}
#else
assert(!"Unimplemented!");
#endif
return HSA_STATUS_SUCCESS;
}
hsa_status_t KfdDriver::ReleaseShareableHandle(core::ShareableHandle &handle) {
const auto ldrm_bo = reinterpret_cast<amdgpu_bo_handle>(handle.handle);
if (!ldrm_bo)
#if defined(__linux__)
auto memhandle = reinterpret_cast<HsaMemoryObjectHandle>(handle.handle);
HSAKMT_STATUS status = HSAKMT_CALL(hsaKmtMemHandleFree(memhandle));
if (status != HSAKMT_STATUS_SUCCESS) {
return HSA_STATUS_ERROR;
const auto ret = DRM_CALL(amdgpu_bo_free(ldrm_bo));
if (ret)
return HSA_STATUS_ERROR;
}
handle = {};
return HSA_STATUS_SUCCESS;
#else
assert(!"Unimplemented!");
#endif
}
hsa_status_t KfdDriver::SPMAcquire(uint32_t preferred_node_id) const {
@@ -731,15 +749,12 @@ hsa_status_t KfdDriver::IsModelEnabled(bool* enable) const {
hsa_status_t KfdDriver::GetWallclockFrequency(uint32_t node_id, uint64_t* frequency) const {
assert(frequency);
amdgpu_gpu_info info;
amdgpu_device_handle handle;
if (GetDeviceHandle(node_id, reinterpret_cast<void**>(&handle)) != HSA_STATUS_SUCCESS)
HsaNodeProperties props;
if (GetNodeProperties(props, node_id) != HSA_STATUS_SUCCESS) {
return HSA_STATUS_ERROR;
}
if (DRM_CALL(amdgpu_query_gpu_info(handle, &info)) < 0) return HSA_STATUS_ERROR;
// Reported by libdrm in KHz.
*frequency = uint64_t(info.gpu_counter_freq) * 1000ull;
*frequency = uint64_t(props.WallClockKHz) * 1000ull;
return HSA_STATUS_SUCCESS;
}