From a2517e15e22d7318d70f6611167a5fca0f821f4f Mon Sep 17 00:00:00 2001 From: I-Hsuan Huang Date: Tue, 25 Aug 2026 17:29:16 -0500 Subject: [PATCH 1/2] fix(libhsakmt): correct independent DXG state and metadata bugs --- .../rocr-runtime/libhsakmt/librocdxg.pc.in | 2 +- .../libhsakmt/src/dxg/openclose.cpp | 3 +- .../libhsakmt/src/dxg/topology.cpp | 31 ++++++++++++++----- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/projects/rocr-runtime/libhsakmt/librocdxg.pc.in b/projects/rocr-runtime/libhsakmt/librocdxg.pc.in index d9b362399df4..2e9f15a67604 100755 --- a/projects/rocr-runtime/libhsakmt/librocdxg.pc.in +++ b/projects/rocr-runtime/libhsakmt/librocdxg.pc.in @@ -1,4 +1,4 @@ -prefix=${pcfiledir}/../../.. +prefix=${pcfiledir}/../.. exec_prefix=${prefix} libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ diff --git a/projects/rocr-runtime/libhsakmt/src/dxg/openclose.cpp b/projects/rocr-runtime/libhsakmt/src/dxg/openclose.cpp index d1f4b69e3623..58263013dfa5 100644 --- a/projects/rocr-runtime/libhsakmt/src/dxg/openclose.cpp +++ b/projects/rocr-runtime/libhsakmt/src/dxg/openclose.cpp @@ -703,8 +703,9 @@ HSAKMT_STATUS HSAKMTAPI hsaKmtOpenKFD(void) { return result; dxcore_loader_failed: #if defined(__linux__) - close(fd); + if (dxg_runtime->dxg_fd >= 0) close(dxg_runtime->dxg_fd); #endif + dxg_runtime->dxg_fd = -1; open_failed: return result; diff --git a/projects/rocr-runtime/libhsakmt/src/dxg/topology.cpp b/projects/rocr-runtime/libhsakmt/src/dxg/topology.cpp index a96d7983b489..cdd9d34b84f8 100644 --- a/projects/rocr-runtime/libhsakmt/src/dxg/topology.cpp +++ b/projects/rocr-runtime/libhsakmt/src/dxg/topology.cpp @@ -760,12 +760,26 @@ HSAKMT_STATUS topology_sysfs_get_node_props(uint32_t node_id, HsaNodeProperties& props.WaveFrontSize = device->WavefrontSize(); props.NumShaderBanks = device->NumShaderEngine(); props.NumArrays = device->ShaderArrayPerShaderEngine(); - if (props.NumArrays == 0) { - pr_warn("NumArrays is 0 for node %u, forcing NumCUPerArray to 0\n", - node_id); - props.NumCUPerArray = 0; - } else { - props.NumCUPerArray = device->ComputeUnitCount() / props.NumArrays; + /* NumArrays counts shader arrays per shader engine, so the number of arrays + * on the whole GPU is NumShaderBanks * NumArrays. + */ + { + const uint32_t total_arrays = props.NumShaderBanks * props.NumArrays; + if (total_arrays == 0) { + pr_warn( + "NumShaderBanks(%u)*NumArrays(%u) is 0 for node %u, forcing " + "NumCUPerArray to 0\n", + props.NumShaderBanks, props.NumArrays, node_id); + props.NumCUPerArray = 0; + } else { + const uint32_t cu_count = device->ComputeUnitCount(); + if (cu_count % total_arrays != 0) + pr_warn( + "ComputeUnitCount(%u) is not a multiple of the %u shader " + "arrays on node %u; NumCUPerArray is truncated\n", + cu_count, total_arrays, node_id); + props.NumCUPerArray = cu_count / total_arrays; + } } props.NumSIMDPerCU = simd_per_cu; props.MaxSlotsScratchCU = device->MaxScratchSlotsPerCu(); @@ -809,7 +823,10 @@ HSAKMT_STATUS topology_sysfs_get_node_props(uint32_t node_id, HsaNodeProperties& props.Domain = device->Domain(); props.UniqueID = device->Uuid(); props.NumXcc = device->NumXcc(); - props.KFDGpuID = device->DeviceId(); // TODO + /* KFDGpuID is a nonzero snapshot-local key, not the PCI device ID. The node + * ordinal is unique by construction even when two GPUs have the same model. + */ + props.KFDGpuID = node_id + 1; props.FamilyID = device->GfxFamily(); props.LuidLowPart = device->GetLuid().LowPart; props.LuidHighPart = device->GetLuid().HighPart; From 1848427804c1709be5dc9ad24ad93e154050121b Mon Sep 17 00:00:00 2001 From: Huang Date: Wed, 26 Aug 2026 13:28:53 -0500 Subject: [PATCH 2/2] docs(libhsakmt): record KFDGpuID contract at its assignment The comment now states what the synthesized value is and is not: a nonzero snapshot-local key, never a kernel gpu_id. It also names amd_core_dump.cpp as the one consumer where the value becomes externally visible, so a future reader does not have to re-derive that. In response to review; comment text only, no functional change. --- projects/rocr-runtime/libhsakmt/src/dxg/topology.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/projects/rocr-runtime/libhsakmt/src/dxg/topology.cpp b/projects/rocr-runtime/libhsakmt/src/dxg/topology.cpp index cdd9d34b84f8..b87265b4dcff 100644 --- a/projects/rocr-runtime/libhsakmt/src/dxg/topology.cpp +++ b/projects/rocr-runtime/libhsakmt/src/dxg/topology.cpp @@ -823,8 +823,14 @@ HSAKMT_STATUS topology_sysfs_get_node_props(uint32_t node_id, HsaNodeProperties& props.Domain = device->Domain(); props.UniqueID = device->Uuid(); props.NumXcc = device->NumXcc(); - /* KFDGpuID is a nonzero snapshot-local key, not the PCI device ID. The node - * ordinal is unique by construction even when two GPUs have the same model. + /* + * KFDGpuID is a nonzero snapshot-local key: not the PCI device ID, and not a + * kernel gpu_id, which only the native sysfs path supplies. Uniqueness and + * nonzeroness are all the DXG consumers require: a "node is a GPU" predicate + * and the gpuid<->nodeid lookups in this file. It becomes externally visible + * only through amd_core_dump.cpp, which writes it as the core dump's gpu_id, + * so a debugger correlating that field against kernel state will not match + * on WSL. */ props.KFDGpuID = node_id + 1; props.FamilyID = device->GfxFamily();