# DF-4499 — amdgpu_amdkfd_gfx_v9.c is dead code on DragonFly; latent unvalidated index arithmetic for the day KFD is enabled

File: `sys/dev/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c` (pass 2)

## What (dead-code proof)

The Vega10/Vega20/Raven KFD backend compiled into the amdgpu KLD is
**unreachable on DragonFly**:

1. `CONFIG_HSA_AMD` is defined nowhere in the tree (no `#define`, no
   `-DCONFIG_HSA_AMD` in `sys/dev/drm/amd/amdgpu/Makefile` KCFLAGS).
2. Therefore `amdgpu_amdkfd_init()` takes the `#else` branch:
   `kgd2kfd = NULL` (`amdgpu_amdkfd.c:33-50`).
3. `amdgpu_amdkfd_device_probe()` returns at `if (!kgd2kfd) return;` before
   ever calling `amdgpu_amdkfd_gfx_9_0_get_functions()`
   (`amdgpu_amdkfd.c:59-71`) — so `adev->kfd` stays NULL.
4. There is **no KFD frontend** in the tree (no `sys/dev/drm/amd/amdkfd/`,
   no `/dev/kfd`): nothing consumes the `kfd2kgd` table
   (`amdgpu_amdkfd_gfx_v9.c:169-225`).
5. `amdgpu_amdkfd_is_kfd_vmid()` (`amdgpu_amdkfd.c:514-523`) gates every
   vmid-taking entry of this file on `adev->kfd` — always NULL here →
   always false → `invalidate_tlbs_vmid()` / `set_vm_context_page_table_base()`
   are no-ops even if reached.

Guest evidence: no AMD (0x1002) PCI devices, no `/dev/dri`, no `/dev/kfd`
(`env.txt`).

## Latent hazards (audit of the exported functions for the day it is enabled)

* `get_sdma_base_addr()` (`amdgpu_amdkfd_gfx_v9.c:372-390`): indexes stack
  array `uint32_t base[2]` with `engine_id` taken from the MQD
  (`m->sdma_engine_id`) with **no local bound**; `queue_id` likewise scales
  the register stride unbounded. Validation currently lives only in the
  absent KFD frontend.
* `kgd_set_pasid_vmid_mapping()` (`:291-346`): `1U << (vmid + 16)` and
  register `+ vmid` offsets rely entirely on the caller keeping `vmid <= 15`;
  a vmid ≥ 16 is silent UB / arbitrary adjacent MMIO writes.
* `amdgpu_amdkfd_is_kfd_vmid()` (`amdgpu_amdkfd.c:514`): `(1 << vmid)` is UB
  for `vmid >= 32`; on x86 the shift wraps mod 32, so e.g. vmid=40 passes the
  `0xFF00` bitmap test and would feed `vmid*2` (80 dwords) offsets into
  `set_vm_context_page_table_base()` (`:1015-1052`).
* Unbounded `cpu_relax()` MMIO ACK polls in `kgd_set_pasid_vmid_mapping()`
  (`:315-319`, `:332-336`) and `write_vmid_invalidate_request()`
  (`:830-837`): a hung GPU wedges the calling kernel thread forever (same
  shape as upstream Linux; noted for completeness).

## Verified in-bounds during this audit (negative results with weight)

* `kgd_hqd_load()` MQD→HQD register walk (`:432-437`): reads exactly the
  contiguous `uint32_t` span `cp_mqd_base_addr_lo … cp_hqd_pq_wptr_hi`
  (`v9_structs.h:289-344`), 56 dwords — matches `HQD_N_REGS 56`.
* `kgd_hqd_dump()` / `kgd_hqd_sdma_dump()` (`:497-531`, `:603-631`):
  allocations sized to the walked ranges (56 and 42 pairs) and `DUMP_REG`
  bounds-checked with `WARN_ON_ONCE`.
* `amdgpu_amdkfd_get_tile_config()` (`:151-167`): `ARRAY_SIZE` over genuine
  fixed-size arrays (`tile_mode_array[32]`, `macrotile_mode_array[16]`,
  `amdgpu_gfx.h`).
* `invalidate_tlbs()` vmid loop is `0..15` with `is_kfd_vmid` + pasid match
  (`:882-892`).
* `get_fw_version()` NULL-checks every firmware pointer before dereference
  (`:1008-1009`).

## Fix

`fix.diff`: add explicit `engine_id < 2` / `vmid < 16` guards at the two
latent index-arithmetic sites in this file. Info severity — defense-in-depth
for a backend that is currently unreachable.
