# DF-4843 — unvalidated IH wptr + unbounded ring walk = permanent interrupt-thread livelock

`sys/dev/drm/amd/amdgpu/tonga_ih.c` + `amdgpu_ih.c`.

The VI IH writeback slot (`adev->irq.ih.ring[wptr_offs]`, a device-DMA'd u32)
is consumed by `tonga_ih_get_wptr()` (tonga_ih.c:196-219) with nothing but a
`ptr_mask` — no alignment validation, no sanity bound.  `amdgpu_ih_process()`
(amdgpu_ih.c:131-168) then walks `while (ih->rptr != wptr)` with `rptr`
advancing only in 16-byte IV steps (tonga_ih.c:245/277) and re-reads wptr in
`restart_ih` (amdgpu_ih.c:163-165).

A wptr that is not a multiple of 16 — arbitrary in the hostile-device model
(compromised GPU/firmware DMA), plausible in the faulting-device model
(garbage writeback after a PCIe error) — can never equal `rptr`: the walk
laps the 64 KiB ring forever, re-dispatching 4096 entries per lap through the
full `amdgpu_irq_dispatch()` chain (MMIO-heavy handlers), with `ih->lock`
held.  Result: permanent hard-spin of the amdgpu ithread — one CPU pegged in
interrupt context, all GPU interrupt delivery dead for the life of the box.
No entry-count cap exists anywhere on the path (an interrupt *storm* from a
livelier hostile device keeps it equally busy even with an aligned wptr).

## Status: UNTESTED

Requires a Tonga/Vega10 device (or an adev fake whose `set_rptr` MMIO is
stubbed) to drive the real loop; the audit guest has no GPU.  The code path
is certain by inspection (see `trigger_sketch.c` for the exact loop-lap
argument).  DoS only — no memory-safety impact found on this file's surface:
entry reads are bounded by `rptr & ptr_mask` + 4-dword entries inside the
64 KiB + 8 allocation, `src_id`/`client_id` are bounds-checked in dispatch
(amdgpu_irq.c:409-417), and the NULL `.process` sibling issue is DF-4713.

## Suggested fix

Validate wptr alignment/relationship in the `amdgpu_ih_get_wptr`
implementations (tonga_ih.c:218: reject/align `wptr & ~0xf` mismatch with a
dev_err + ring reset), and cap the per-invocation entry count in
`amdgpu_ih_process()` (amdgpu_ih.c:154) so a storm or a bad wptr yields to
the scheduler instead of hard-spinning the ithread.
