# DF-4601 — dce112_compressor_construct() init-order defects: dead 64-bit-bus LPT guard + lpt_channels_num wipe

**File:** `sys/dev/drm/amd/display/dc/dce112/dce112_compressor.c` (DCE11.2 / Polisar FBC+LPT engine)
**Severity:** Info (correctness/dead-code; no demonstrated kernel memory-safety impact — register-programming logic only)
**Confidence:** certain (both facts provable by source alone; demonstrator reproduces the logic)

## What it is

Two initialization-ordering defects in `dce112_compressor_construct()`
(dce112_compressor.c:787-829):

1. **Dead single-DRAM-channel guard (:802).** The object is `kzalloc`ed by
   `dce112_compressor_create()` (:831-841), so `memory_bus_width == 0` when
   `dce112_compressor_construct()` evaluates
   `if (compressor->base.memory_bus_width == 64)` at :802. The field is
   assigned its real value, `ctx->asic_id.vram_width`, only afterwards at
   :810. The guard's whole purpose ("only 1 DRAM channel -> LPT should not
   be supported") can therefore never fire: **LPT_SUPPORT stays set on
   64-bit-bus ASICs.**

2. **`lpt_channels_num` wipe (:818).** :797 sets
   `lpt_channels_num = 1` ("For DCE 11 always use one DRAM channel for
   LPT"), then :818 unconditionally overwrites it with 0. Consequently the
   only valid `case 1:` of `dce112_compressor_program_lpt_control()`
   (:675-691) is unreachable — the switch always falls to `default`
   (:686-690) and `LOW_POWER_TILING_MODE` is **never programmed** by this
   driver; the register keeps whatever stale value it holds.

Knock-on (same construct): `banks_num`, `raw_size`, `dram_channels_num`,
`channel_interleave_size` are zeroed at :814-817 and **no code anywhere in
the tree ever sets them** (verified by grep across
`sys/dev/drm/amd/display/dc/`), so `lpt_size_alignment()` (:98-103) always
returns 0 and `dce112_compressor_program_lpt_control()` leaves
`LOW_POWER_TILING_ROWS_PER_CHAN` at 0 (:708-714) and
`dce112_compressor_program_compressed_surface_address_and_pitch()` skips the
address alignment (:500-505) — yet `dce112_compressor_enable_lpt()`
(:594-651) still arms `LOW_POWER_TILING_ENABLE=1` and
`GMCON_LPT_TARGET = stale_mode+1` whenever FBC+LPT come up on eDP
(`dce110_hw_sequencer.c:enable_fbc` -> `enable_lpt` when LPT_SUPPORT &&
paths_num<2 && w*h <= 2560*1600).

## Why no runtime reproduction on the audit guest

The QEMU guest has no AMD GPU (virtio only), so the DCE11.2 register path
cannot execute there. The two defects are nevertheless **pure static
facts** — no hardware-dependent behavior is needed to prove them — and the
pack contains a host-compiled demonstrator that mirrors the exact statement
order and asserts both. On-HW impact (LPT armed with unprogrammed config on
Polaris eDP panels) is speculative and out of the audit's demonstrable
scope; worst realistic case is display underflow / GPU hang (local DoS by a
modeset-capable user), not kernel memory corruption. Filed as Info
hardening for upstream.

## Reproduce (host, no GPU)

```
./build.sh    # cc -O2 -Wall -o construct_order construct_order.c
./run.sh      # expects: PROOF-1 OK / PROOF-2 OK / RESULT: DEFECT CONFIRMED, exit 0
```

## Fix

`fix.diff` (authored against the read-only `sys/` tree, never applied
there): assign `memory_bus_width` from `asic_id.vram_width` *before* the
64-bit-bus check, and set `lpt_channels_num = 1` *after* the zeroing block
instead of wiping it. Kernel-build validation on the guest is not possible
(the amd drm driver cannot attach to QEMU virtio hardware), hence
fix_status=not_testable.
