From d64deb708fcd18d36105a8d1929824e9acf41f39 Mon Sep 17 00:00:00 2001 From: Hamid Mukhtar Date: Fri, 27 Mar 2026 11:54:40 -0400 Subject: [PATCH] dxg/wsl: fix div-by-zero in topology; skip non-queryable adapters topology.cpp: guard WatchPointsNum(), SimdPerCu() and NumArrays against zero before use as divisors or log2 arguments. Replace assert on EngineId.Major with pr_err so release builds receive a diagnostic instead of aborting. Apply OverrideEngineId (HSA_OVERRIDE_GFX_VERSION) as a last resort when EngineId.Major is still 0 after ParseDeviceInfo. wddm/device.cpp: a WDDMQueryAdapter failure for one adapter previously aborted the entire enumeration loop via goto err_out1. On systems where a non-queryable adapter (e.g. a software renderer) appears before the compute GPU this silently prevents any GPU from being found. Changed to skip with pr_debug and continue. Both changes are generic robustness fixes with no effect on devices that already report non-zero values. Co-Authored-By: Claude Sonnet 4.6 --- src/topology.cpp | 25 +++++++++++++++++++------ src/wddm/device.cpp | 6 ++++-- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/topology.cpp b/src/topology.cpp index 36c9cd6..23742eb 100644 --- a/src/topology.cpp +++ b/src/topology.cpp @@ -528,14 +528,16 @@ static HSAKMT_STATUS topology_sysfs_get_node_props(uint32_t node_id, props.FComputeIdLo = 0; props.Capability.ui32.ASICRevision = device->AsicRevision(); props.Capability.ui32.WatchPointsTotalBits = - std::log2(device->WatchPointsNum()); - props.MaxWavesPerSIMD = device->WavePerCu() / device->SimdPerCu(); + device->WatchPointsNum() ? std::log2(device->WatchPointsNum()) : 0; + props.MaxWavesPerSIMD = + device->SimdPerCu() ? device->WavePerCu() / device->SimdPerCu() : 0; props.LDSSizeInKB = device->LdsSize() / 1024; props.GDSSizeInKB = 0; props.WaveFrontSize = device->WavefrontSize(); props.NumShaderBanks = device->NumShaderEngine(); props.NumArrays = device->ShaderArrayPerShaderEngine(); - props.NumCUPerArray = device->ComputeUnitCount() / props.NumArrays; + props.NumCUPerArray = props.NumArrays + ? device->ComputeUnitCount() / props.NumArrays : 0; props.NumSIMDPerCU = device->SimdPerCu(); props.MaxSlotsScratchCU = device->MaxScratchSlotsPerCu(); props.VendorId = 0x1002; @@ -592,6 +594,18 @@ static HSAKMT_STATUS topology_sysfs_get_node_props(uint32_t node_id, props.EngineId.ui32.Minor = device->Minor(); props.EngineId.ui32.Stepping = device->Stepping(); + /* GFX version should already be populated by ParseDeviceInfo() via + * HSA_OVERRIDE_GFX_VERSION or device-specific detection. Fall back to + * the topology-level override as a last resort; log an error if still 0. */ + if (!props.EngineId.ui32.Major) { + if (props.OverrideEngineId.ui32.Major) { + props.EngineId = props.OverrideEngineId; + pr_warn("GFX version from HSA_OVERRIDE_GFX_VERSION\n"); + } else { + pr_err("GFX version is 0 — set HSA_OVERRIDE_GFX_VERSION\n"); + } + } + snprintf((char *)props.AMDName, sizeof(props.AMDName) - 1, "GFX%06x", HSA_GET_GFX_VERSION_FULL(props.EngineId.ui32)); @@ -603,9 +617,8 @@ static HSAKMT_STATUS topology_sysfs_get_node_props(uint32_t node_id, props.SGPRSizePerCU = SGPR_SIZE_PER_CU; props.VGPRSizePerCU = get_vgpr_size_per_cu(props.EngineId); - if (props.NumFComputeCores) - assert(props.EngineId.ui32.Major && - "HSA_OVERRIDE_GFX_VERSION may be needed"); + if (props.NumFComputeCores && !props.EngineId.ui32.Major) + pr_err("GFX version still unknown - set HSA_OVERRIDE_GFX_VERSION\n"); return ret; } diff --git a/src/wddm/device.cpp b/src/wddm/device.cpp index f51af85..8384220 100644 --- a/src/wddm/device.cpp +++ b/src/wddm/device.cpp @@ -549,8 +549,10 @@ NTSTATUS WDDMCreateDevices(std::vector &devices) ret = WDDMQueryAdapter(info[i].hAdapter, KMTQAITYPE_PHYSICALADAPTERDEVICEIDS, &query, sizeof(query)); - if (ret != STATUS_SUCCESS) - goto err_out1; + if (ret != STATUS_SUCCESS) { + pr_debug("adapter %d query failed (0x%x), skipping\n", i, ret); + continue; /* non-fatal: skip adapters that cannot be queried */ + } if (query.DeviceIds.VendorID != 0x1002) continue;