# DF-4360 — cik_sdma_soft_reset(): stale `tmp` makes the SDMA1-busy test read the wrong register → wedged engine survives reset

File: `sys/dev/drm/amd/amdgpu/cik_sdma.c` (pass 2)
Severity: Low · Confidence: certain

## What (static proof)

```c
sys/dev/drm/amd/amdgpu/cik_sdma.c:1089  u32 tmp = RREG32(mmSRBM_STATUS2);
sys/dev/drm/amd/amdgpu/cik_sdma.c:1091  if (tmp & SRBM_STATUS2__SDMA_BUSY_MASK) {
sys/dev/drm/amd/amdgpu/cik_sdma.c:1093          tmp = RREG32(mmSDMA0_F32_CNTL + SDMA0_REGISTER_OFFSET);  /* tmp CLOBBERED */
sys/dev/drm/amd/amdgpu/cik_sdma.c:1094          tmp |= SDMA0_F32_CNTL__HALT_MASK;
sys/dev/drm/amd/amdgpu/cik_sdma.c:1095          WREG32(mmSDMA0_F32_CNTL + SDMA0_REGISTER_OFFSET, tmp);
sys/dev/drm/amd/amdgpu/cik_sdma.c:1096          srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_SDMA_MASK;
sys/dev/drm/amd/amdgpu/cik_sdma.c:1097  }
sys/dev/drm/amd/amdgpu/cik_sdma.c:1098  if (tmp & SRBM_STATUS2__SDMA1_BUSY_MASK) {   /* tests F32_CNTL, NOT SRBM_STATUS2 */
```

The second `if` is meant to test the SDMA1 busy bit of `mmSRBM_STATUS2`, but when the
SDMA0 branch executed, `tmp` now holds `mmSDMA0_F32_CNTL | HALT`. The
`SRBM_STATUS2__SDMA1_BUSY_MASK` bit(s) in that value are meaningless (normally clear),
so **whenever SDMA0 is busy, SDMA1 is never halted/soft-reset**, even if SDMA1 is also
wedged — precisely the both-engines-hung state a reset is supposed to clear.
(If the SDMA0 branch is NOT taken, `tmp` still holds SRBM_STATUS2 and the second test
is accidentally correct — which is why this survives casual reading.)

## Reachability / impact

Callers: `cik_sdma_resume()` (cik_sdma.c:1051 — S3/S4 resume) and the device-reset path
armed by `cik_sdma_process_illegal_inst_irq()` → `schedule_work(&adev->reset_work)`
(cik_sdma.c:1217-1219), which an unprivileged DRI client can trigger by getting an
illegal instruction into an SDMA command stream while both engines have work queued.
Consequence of the missed reset: SDMA1 stays hung → `amdgpu_ring_test_ring()` fails in
`cik_sdma_gfx_resume()` (cik_sdma.c:502-508) → hw_init error → GPU unusable until
reboot. Availability-only, hardware-specific (CIK ASIC required) → Low / dos.

## Fix

```diff
--- a/sys/dev/drm/amd/amdgpu/cik_sdma.c
+++ b/sys/dev/drm/amd/amdgpu/cik_sdma.c
@@ -1086,7 +1086,7 @@ static int cik_sdma_soft_reset(void *handle)
 	u32 srbm_soft_reset = 0;
 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-	u32 tmp = RREG32(mmSRBM_STATUS2);
+	u32 status = RREG32(mmSRBM_STATUS2), tmp;
 
-	if (tmp & SRBM_STATUS2__SDMA_BUSY_MASK) {
+	if (status & SRBM_STATUS2__SDMA_BUSY_MASK) {
 		/* sdma0 */
 		tmp = RREG32(mmSDMA0_F32_CNTL + SDMA0_REGISTER_OFFSET);
@@ -1098,7 +1098,7 @@ static int cik_sdma_soft_reset(void *handle)
 		srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_SDMA_MASK;
 	}
-	if (tmp & SRBM_STATUS2__SDMA1_BUSY_MASK) {
+	if (status & SRBM_STATUS2__SDMA1_BUSY_MASK) {
 		/* sdma1 */
 		tmp = RREG32(mmSDMA0_F32_CNTL + SDMA1_REGISTER_OFFSET);
```

## Verification status

`untested` — requires CIK AMD hardware; the audit QEMU guest has no AMD GPU PCI device
(`pciconf -l`), so `cik_sdma_soft_reset` cannot execute there. Static proof above is
line-accurate; the stale-variable flow is unambiguous from source.
