# DF-3857 — Divide-by-zero in `dce_v10_0_latency_watermark` (DCE10, DF-3828 twin)

## What

`sys/dev/drm/amd/amdgpu/dce_v10_0.c:882-884` — `dce_v10_0_latency_watermark()`
computes

```c
u32 worst_chunk_return_time      = (512 * 8 * 1000) / available_bandwidth;  /* :882 */
u32 cursor_line_pair_return_time = (128 * 4 * 1000) / available_bandwidth;  /* :883 */
u32 dc_latency                   = 40000000 / wm->disp_clk;                 /* :884 */
```

all three **before** the function's only guard (`if (wm->num_heads == 0)
return 0;`, `:892`). When `available_bandwidth` collapses to 0 the first
divide takes an integer #DE in kernel context → panic. The `num_heads==0`
guard is additionally dead through this file's only caller:
`dce_v10_0_program_watermarks()` gates the call on
`amdgpu_crtc->base.enabled && num_heads && mode` (`:1024`).

Zero-clock source: with DPM disabled, `wm.yclk/wm.sclk =
adev->pm.current_mclk/current_sclk * 10` (`:1038-1039`, `:1077-1078`);
`pm.current_*` are seeded from the VBIOS `ulDefaultEngineClock/
ulDefaultMemoryClock` with no zero-guard (`amdgpu_atombios.c:677-680`) and are
assigned even when the firmware-info parse fails (`:718-719`) — the exact
seeding DF-3828 proved for DCE11; the parser is asic-agnostic (Tonga/Fiji).
With `yclk == 0` (or `sclk == 0`) the `min()` in
`dce_v10_0_available_bandwidth()` (`:825-833`) is 0.

The `mode->clock == 0` secondary vector is already blocked at the DRM layer
in this tree (`drm_mode_validate_basic()`, `sys/dev/drm/drm_modes.c:1114`
returns `MODE_CLOCK_LOW`), so `wm->disp_clk != 0` for any mode that reaches
`program_watermarks` — the live vector is the zero memory/engine clock.

## Reproduce (arithmetic-level; kernel reach is hardware-gated)

```
build.sh   # cc -O2 -Wall -o /tmp/wm_div0 /tmp/wm_div0.c
run.sh     # /tmp/wm_div0; echo exit=$?
```

Expected (observed on the audit guest, `run.log`):

```
healthy clocks: watermark math returns 2297 (no trap)
affected clocks (current_mclk=0, current_sclk=0): entering latency_watermark()...
exit=136                      # 128+8 -> SIGFPE = #DE, the kernel panic class
```

Control (`/tmp/wm_div0 6000000 3000000 148500`) returns normally.
`run.2.log`: dmesg shows `pid NNNN (wm_div0), uid 0: exited on signal 8`
3/3 runs.

## Impact

Local DoS (kernel panic) on any Tonga/Fiji machine whose default clocks read
as 0 (crafted/blank VBIOS or failed firmware-info parse with DPM off):
an unprivileged DRM client issues a mode set →
`dce_v10_0_crtc_do_set_base` → `dce_v10_0_bandwidth_update` (`:2064`) →
`program_watermarks` → `latency_watermark` → #DE → panic.

## Kernel reach on this guest

Not possible: the audit guest has 0 AMD PCI devices (`pciconf` shows no
`vendor=0x1002`), no `/dev/dri` (`env.txt`) — amdgpu never binds. Hence
`not_reproduced` for the kernel path; the arithmetic primitive and the full
call chain are proven at source level and the trap class is demonstrated.
