β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-3870

bw_calcs_init: number_of_dram_channels = vram_width / dram_channel_width truncates to 0 -> #DE divisor family at boot/first modeset

Summary

Every per-asic table computes vbios.number_of_dram_channels = asic_id.vram_width / dram_channel_width_in_bits with no clamp; a board misdetecting vram_width below the channel width yields 0 channels, and calculate_bandwidth then divides by number_of_dram_channels at multiple sites and bw_mod's divisor 256*banks*channels -> kernel #DE panic on the first bw_calcs run. Boot-time/first-modeset panic on misdetecting hardware; requires abnormal VBIOS/MC reporting, not user input. Clamp-at-all-six-sites fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-3870 Β· 6 files
FileTypeDescriptionSize
README.md β€” 1.1 KB ↓ raw
VERDICT.md β€” 1.0 KB ↓ raw
fix.diff β€” 582 B view raw
manifest.json β€” 700 B view raw
verdict.json β€” 1.2 KB view raw
env.txt β€” 283 B view raw

DF-3870 β€” bw_calcs_init: number_of_dram_channels = vram_width / dram_channel_width can be 0

dce_calcs.c:2041/2157/2270/2386/2502/2615 (every asic table):

vbios.number_of_dram_channels = asic_id.vram_width / vbios.dram_channel_width_in_bits;

asic_id.vram_width comes from amdgpu gmc_v7/v8 (atombios or MC-register fallback). If a part reports a vram_width smaller than the per-table channel width (64 for CZ/Stoney, 32 for Polaris, 128 for Vega10 HBM) β€” e.g. 32 on a Carrizon-class part β€” the division truncates to 0 channels.

data->number_of_dram_channels (dce_calcs.c:591) is then used as a multiplier-turned-divisor at dce_calcs.c:1185/1187 (dmif/mcifwr burst time), 1526/1532/1540/1546/1552/1557 (dram_bandwidth), i.e. bw_div(..., bw_int_to_fixed(0)) -> bw_frc_to_fixed(n, 0) -> div64_u64_rem(n, 0) -> kernel #DE panic at the first mode validation after boot.

Also inefficient_linear_pitch_in_bytes = 256*banks*channels (1050) becomes 0 -> bw_mod(pitch, 0) (1098) is a second zero-divisor on the same value.

Hardware/VBIOS-gated (needs a misdetecting board); reported as Low.

VERDICT.md
↓ download raw

DF-3870 VERDICT β€” inconclusive (hardware/VBIOS-gated), speculative

  • Source chain verified: dce_calcs.c:2041 (etc.) integer division truncation; gmc_v8_0.c:525-568 (atombios value, MC-register fallback) β€” a zero or sub-channel-width detection survives into bw_calcs_init; no clamp exists anywhere between amdgpu_device and the bw tables.
  • Divisor sites confirmed by reading calculate_bandwidth: 1185, 1187, 1526, 1532, 1540, 1546, 1552, 1557 (bw_int_to_fixed(data->number_of_dram_channels)) and bw_mod at 1098.
  • Cannot be exercised on the guest (no AMD HW); real boards normally report a sane width, hence speculative/Low. Defensive clamp is one line (fix.diff).

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.

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

one-line clamp, cannot validate on guest

fix.diff
↓ fix.diffper-fix-DF-3870

Confirmed kernel references

Detail

Evidence (decisive lines)

VERDICT.md source chain; dce_calcs.c:2041->1185/1098

PoC changes

no runnable PoC (hardware-gated)

Verified recommended fix

clamp number_of_dram_channels to >=1 in bw_calcs_init

Verdict

vram_width/dram_channel_width integer truncation can yield 0 dram channels; number_of_dram_channels is used as a bw_div/bw_mod divisor in calculate_bandwidth -> kernel #DE. Requires a misdetecting VBIOS/board (hardware-gated); defensive clamp recommended.