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

DCC/PTE read-bandwidth overhead factors (1 + 1/256)/(1 + 1/64)/(1 + 1/512) are C integer constant divisions that compile to *1 β€” the DCN1 DCC/PTE bandwidth overhead accounting is dead code

Summary

mode_support_and_system_configuration transcribes the DCN1 spreadsheet overhead factors as integer constant expressions: each 1/N is an int division evaluating to 0, so every factor compiles to exactly 1 and the DCC-compression and PTE-row overhead on read_bandwidth is never applied. total_read_bandwidth under-counts by up to ~1.5%/plane and bandwidth_support can validate a configuration the hardware model would reject - marginal modes pass validation and can hit DRAM/DCFCLK underruns (flicker/underflow) on Raven APUs. No kernel memory-safety impact (all consumers are float comparisons that fail safe). Reproduced by compiling the REAL kernel source on the guest: two planes differing only in dcc_enable yield byte-identical read_bandwidth (ratio 1.000000000); fix flips it to exactly 1.00390625. The identical transcription bug exists upstream. Float-constant fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4199 Β· 15 files
FileTypeDescriptionSize
README.md β€” 2.7 KB ↓ raw
VERDICT.md β€” 5.1 KB ↓ raw
dcnauto_harness.c β€” 12.6 KB view raw
dm_services.h β€” 1.9 KB view raw
display_clock.h β€” 452 B view raw
build.sh β€” 163 B view raw
run.sh β€” 89 B view raw
build.log β€” 1.6 KB view raw
run.log β€” 1.8 KB view raw
run.2.log β€” 1.8 KB view raw
run.3.log β€” 243 B view raw
env.txt β€” 244 B view raw
fix.diff β€” 1.9 KB view raw
manifest.json β€” 1.3 KB view raw
verdict.json β€” 3.9 KB view raw

DF-4199 β€” dead DCC/PTE bandwidth-overhead factors in dcn_calc_auto.c (integer-constant division transcription bug)

File: sys/dev/drm/amd/display/dc/calcs/dcn_calc_auto.c (pass 2) Severity: Info (correctness; no kernel memory-safety impact) Status: reproduced at source level on the audit guest by compiling the REAL kernel source (DF-4198 pattern).

What

mode_support_and_system_configuration() applies DCC-compression and PTE-row read-bandwidth overhead factors that were transcribed from the DCN1 spreadsheet ("HW gospel", REVISION#250) as C integer constant expressions:

v->read_bandwidth[k] = v->read_bandwidth[k] * (1 + 1 / 256);   /* :178 DCC  */
v->read_bandwidth[k] = v->read_bandwidth[k] * (1 + 1 / 64);    /* :181 PTE  */
v->read_bandwidth[k] = v->read_bandwidth[k] * (1 + 1 / 256);   /* :184 PTE  */
v->read_bandwidth[k] = v->read_bandwidth[k] * (1 + 1 / 512);   /* :187 PTE  */

In C, 1 / 256, 1 / 64, 1 / 512 are int divisions that evaluate to 0, so every factor compiles to exactly 1 and the entire DCC/PTE overhead accounting is dead code. The spreadsheet intends 1.00390625, 1.015625, 1.00390625, 1.001953125 respectively.

Impact

total_read_bandwidth_consumed_gbyte_per_second (dcn_calc_auto.c:189) is under-estimated by up to ~1.5% per DCC+PTE plane, and bandwidth_support[i] (:231) can therefore say yes for a configuration the hardware model would reject β€” a marginal mode passes DCN1 validation and can hit DRAM/DCFCLK underruns (visual corruption / flicker on Raven APUs). No kernel memory corruption: every consumer in the file is an IEEE-754 float comparison; the only float->int conversions (voltage_level, dispclk_dppclk_ratio) are provably in-range (see VERDICT.md "killed candidates").

Reproduce

./build.sh    # pulls REAL dcn_calc_auto.c + dcn_calc_math.c + real DCN
              # headers from guest /usr/src; only dm_services.h and
              # display_clock.h are stubs; builds baseline + fixed
./run.sh      # dcc / pte / degen / log0 tests

Expected (see run.log / run.2.log):

baseline: read_bw[dcc]=518.400024  read_bw[nodcc]=518.400024  ratio=1.000000000
          DEFECT PRESENT: factor (1 + 1/256) evaluated to exactly 1
fixed:    read_bw[dcc]=522.457947  read_bw[nodcc]=520.425049  ratio=1.003906250
          FIXED: factor is (1.0 + 1.0/256.0) = 1.00390625

The same binary also documents the pass-2 negative results: degenerate crafted inputs (pixel_clock=0, htotal=0, all-zero socBB clocks, viewport_width=0 feeding dcn_bw_log(0) = -127) produce no SIGFPE/#DE β€” every division in this file is float β€” validation fails safe, and voltage_level stays within [0,5].

Fix

fix.diff (4 lines, applied and validated in this pack).

VERDICT.md
↓ download raw

DF-4199 VERDICT β€” dead (1 + 1/N) overhead factors in dcn_calc_auto.c

Verdict: reproduced (source-level, on-guest, real-source harness), impact = none (Info-class correctness defect: DCC/PTE bandwidth overhead accounting is dead code on DCN1). Confidence: certain.

How reproduced

The REAL sys/dev/drm/amd/display/dc/calcs/dcn_calc_auto.c and calcs/dcn_calc_math.c were compiled unmodified on the audit guest (DragonFly 6.5-DEVELOPMENT, cc 8.3) together with the REAL header chain (inc/dcn_calcs.h, inc/bw_fixed.h, dml/*.h); only dm_services.h (non-fatal ASSERT / log sinks β€” matches release os_types.h WARN_ON semantics) and display_clock.h (opaque struct dc_clocks only) are stubs. The harness (dcnauto_harness.c) fills struct dcn_bw_internal_vars exactly the way the kernel does β€” memset(v,0,sizeof(*v)) (dcn_calcs.c:716) + DCN1 socbb/ip defaults transcribed verbatim from dcn_calcs.c:57-157 + the same per-state tables (dcn_calcs.c:796-831) and per-plane fill (dcn_calcs.c:845-984) β€” then runs the kernel's full call sequence scaler_settings_calculation β†’ mode_support_and_system_configuration β†’ display_pipe_configuration β†’ dispclkdppclkdcfclk_… (dcn_calcs.c:987-1035).

Decisive output (run.log, deterministic 2/2):

baseline read_bw[dcc]  = 518.400024
baseline read_bw[nodcc]= 518.400024   ratio=1.000000000  -> DEFECT PRESENT
fixed    ratio         = 1.003906250                      -> FIXED

Two byte-identical planes differing only in dcc_enable produce byte-identical read_bandwidth[], proving the * (1 + 1 / 256) factor at dcn_calc_auto.c:178 compiles to * 1. The PTE factors at :181/:184/:187 are dead the same way (pte test: 4KB_S-vert vs var_d-vert read_bw equal). With fix.diff applied to the real source and recompiled, the DCC plane reads exactly 1.00390625Γ— the non-DCC plane.

Why it matters (and why only Info)

total_read_bandwidth_consumed_gbyte_per_second (:189) under-counts by up to ~1.5%/plane; bandwidth_support[i] (:231) can pass a configuration the DCN1 hardware model would reject β†’ marginal mode validated β†’ DRAM/DCFCLK underrun (flicker/underflow) on Raven. Every consumer of these values in the file is a float comparison; no kernel memory safety is affected. Upstream Linux carries the identical transcription bug (same REVISION#250 file), so the defect is not DFly-specific.

Pass-2 killed candidates (evidence in run.log "degen"/"log0" sections)

  • Integer #DE family (DF-3869/3870, DF-4198 class): there are NO runtime integer divisions and NO explicit floatβ†’int casts in this file; every division is IEEE-754 float. Degenerate crafted inputs (pixel_clock=0, htotal=0, all-zero socBB clocks incl. dcfclk/dram/phy) run all four functions with no SIGFPE; NaN/inf make every support comparison false β†’ validation fails safe (mode_support= no, voltage_level=5).
  • Index safety (output writes vs declared sizes, checklist c): k is bounded by number_of_active_planes = streams-with-pipes ≀ pool->pipe_count = res_cap->num_timing_generator ≀ 6 = number_of_planes_minus_one + 1 arrays (dcn10_resource.c:1212); i ≀ 5 into [number_of_states_plus_one + 1] = 6; j ∈ {0,1} into [1+1]; voltage_level ∈ [0,5] because voltage_override_level is memset-0 and never set elsewhere, so the loops at :963/:968 always assign at i=5 first (verified in all degen runs: voltage_level=5).
  • dcn_bw_log(0)/negative (checklist b): dcn_bw_log(0.0f,2.0f) returns exactly -127.0 (dml_log2 twin) and dcn_bw_pow(2,-127) = 5.877e-39 subnormal β€” garbage floats only, no trap; with a degenerate viewport_width=0 plane the dpte row math produces garbage but the mode is rejected. All four call sites (:665, :726, :1491, :1550) take strictly positive arguments for validated planes (viewport β‰₯ 1 px, no_of_dpp ∈ {1,2}), so this is unreachable from UABI-legal input and fails safe even when forced.
  • byte-per-element zero (checklist e, DF-4198 class): the byte_per_pixel_in_dety/detc switch (:153-172, :1016-1035, :1233-1252) has an else-branch (4/3, 8/3) covering every unhandled enum β€” no 0-divisor family here.
  • Do/while prefetch loops (:1608-1755): terminate β€” once v_startup_lines exceeds every max_vstartup_lines[k] the three planes_with_room… flags keep their re-initialized values (yes/no/no) and the inner loop exits; outer loop exits at prefetch_mode == 2.0; NaN comparisons are false, which also exits.

Fix validation

fix.diff (4 one-line changes, int constants β†’ float constants) applied to the real source and rebuilt on the guest: baseline defect 2/2 runs, fixed 0/2 (ratio exactly 1.00390625) β€” fix_status fixed (harness-level; kernel build validation not possible on this guest, no AMD GPU β€” env.txt).

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

fixed
baseline reproduced→ patch + rebuild →patched clean

fix.diff applied to the REAL dcn_calc_auto.c and recompiled on the guest: baseline defect 2/2 runs (ratio exactly 1.000000000), patched 0/2 with DCC plane exactly 1.00390625x the non-DCC plane. Harness-level validation complete; kernel-build validation not possible (guest has no AMD GPU).

run.log + run.2.log baseline 'DEFECT PRESENT'; run.3.log fixed 'FIXED: factor is (1.0 + 1.0/256.0) = 1.00390625'; fix.diff
↓ fix.diffper-fix-DF-4199

Confirmed kernel references

Detail

Evidence (decisive lines)

run.log/run.2.log baseline 'DEFECT PRESENT ... ratio=1.000000000' vs fixed 'FIXED ... ratio=1.003906250'; degen sections show no SIGFPE for zero clocks and safe voltage_level=5; log0 section documents dcn_bw_log(0)=-127 no-trap twin; build.log real-source compile; env.txt guest uname + no AMD GPU

PoC changes

harness written fresh (no seed): kernel-faithful fill of struct dcn_bw_internal_vars (memset-0 + dcn10_soc/ip_defaults transcribed from dcn_calcs.c:57-157 + per-state tables dcn_calcs.c:796-831); dm_services.h stub extended with u64/BUILD_BUG_ON/div64_u64_rem for the real bw_fixed.h inlines; display_clock.h stub = opaque struct dc_clocks

Verified recommended fix

Replace the four integer-constant factors with float constants: (1.0 + 1.0/256.0), (1.0 + 1.0/64.0), (1.0 + 1.0/256.0), (1.0 + 1.0/512.0) β€” see fix.diff.

Verdict

REAL dcn_calc_auto.c + dcn_calc_math.c compiled unmodified on the audit guest and driven exactly like the kernel (memset-0 vars + DCN1 socbb/ip defaults + kernel call sequence): two byte-identical planes differing only in dcc_enable produce byte-identical read_bandwidth, proving the four overhead factors (1 + 1/256)/:(1 + 1/64)/:(1 + 1/512) at dcn_calc_auto.c:178/181/184/187 are C integer constant divisions that compile to *1 β€” the DCC/PTE bandwidth overhead accounting is dead code. Same harness proves the pass-2 negative results: no integer #DE sites exist (all-float arithmetic; zero clocks/pixel_clock/htotal/viewport yield inf/NaN that fail validation safe, voltage_level stays in [0,5]). Info severity: worst realistic impact is marginal DCN1 modes passing validation and hitting display underruns; identical transcription bug exists upstream.