# DF-4371 trigger (documentation — requires radeon hardware)

Runtime reproduction requires (1) an radeon DPM-family GPU whose VBIOS has a
pplib4+ PowerPlayInfo table with both `usVddcDependencyOnSCLKOffset` and
`usVddciDependencyOnMCLKOffset` set, and (2) one forced allocation failure
inside the second/third/fourth `r600_parse_clk_voltage_dep_table()` call.

## Call chain

```
radeon_device_init → radeon_pm_init → radeon_dpm_init → <asic>_dpm_init
  → r600_get_platform_caps            (r600_dpm.c:846)
  → <asic>_parse_power_table
  → r600_parse_extended_power_table   (r600_dpm.c:874)
      parse vddc_on_sclk OK           (:927-931)  entries allocated
      parse vddci_on_mclk FAILS       (:932-941)  kzalloc NULL at :829
          kfree(vddc_on_sclk.entries) (:939)      pointer dangling
          return -ENOMEM
<asic>_dpm_init returns error         (btc_dpm.c:2578 et al.)
radeon_pm_init: dpm_enabled = false   (radeon_pm.c:1470)
... driver unbind / reboot ...
radeon_pm_fini → radeon_dpm_fini      (radeon_pm.c:1705, unconditional)
  → <asic>_dpm_fini → r600_free_extended_power_table (r600_dpm.c:1299)
      kfree(vddc_on_sclk.entries) AGAIN   <-- double free
```

## Fault-injection runbook (on suitable hardware)

1. Boot a kernel with slab fault injection available (DragonFly: debug
   sysctls / DEBUGFLAGS, or patch `kzalloc` call at r600_dpm.c:829 to fail on
   the 2nd invocation), or attach the card under heavy memory pressure.
2. Load radeon with dpm=1 (default). Observe `radeon: dpm initialization
   failed` in dmesg with the device still present.
3. `kldunload radeon` (or reboot). Observe the double-free: DragonFly's
   malloc flags with `M_WAITOK` + slab invariant checks panic on
   free-list corruption; without redzones the corruption is silent —
   check for subsequent unrelated panics/allocator reports.
4. Expected on patched kernel (fix.diff): clean unload, no second free
   (pointers NULLed).
