# DF-3622 VERDICT — divide-by-zero on zero MPLL reference clock

## Bottom line

**Real bug, source-certain; runtime inconclusive (no AMD GPU on guest).**

`ci_calculate_mclk_params()` divides by `adev->clock.mpll.reference_freq`
without checking it (ci_dpm.c:2977):

```c
u32 reference_clock = adev->clock.mpll.reference_freq;   /* :2970 */
...
tmp = (freq_nom / reference_clock);                      /* :2977 — #DE if 0 */
```

The value is copied verbatim from the VBIOS FirmwareInfo table
(`usMemoryReferenceClock`) at amdgpu_atombios.c:659-660 — with no zero
fixup, in contrast to the neighboring `pll_out_min` fields that do get
`== 0 → 64800` corrections (:642-643, :668-670). A crafted VBIOS with
`usMemoryReferenceClock == 0` plus any parseable `ASIC_InternalSS_Info`
header (needed for `caps_mclk_ss_support`, ci_dpm.c:6052-6056, which gates
the divide) triggers the division at driver enable time.

`freq_nom` is `memory_clock * 2|4 * (1 << post_div)` and cannot be zero
(mclk == 0 rejected at ci_dpm.c:3480-3481), so zero reference clock is an
unconditional `#DE` → panic during
`ci_dpm_enable → ci_populate_all_memory_levels → ci_populate_single_memory_level
→ ci_calculate_mclk_params` (called at ci_dpm.c:3107), i.e. at boot/bind
and on every resume.

Note the sibling `ci_calculate_sclk_params` only ever *multiplies* by the
SPLL reference clock — the mpll path is the only reference-clock *divide*
in this file. (For completeness: `ci_program_display_gap` divides by
`refresh_rate`, but that is guarded 0→60 at ci_dpm.c:2133-2134.)

## Verification narrative

- Guest lacks any AMD ASIC → kernel path unexecutable → **inconclusive**;
  module presence verified (amdgpu.ko loads).
- The shared `ci_ss_div0.c` executed on the guest demonstrates sink [C]:
  the exact `freq_nom / reference_clock` division with
  `usMemoryReferenceClock = 0` (run.log).
- Twin of si_dpm DF-3613.

## Fix

`fix.diff` returns `-EINVAL` from `ci_calculate_mclk_params` when the mpll
reference clock is zero (SS setup cannot be computed); enable then fails
cleanly instead of panicking. Not testable on this guest.

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
