# DF-5213 - amdgpu df_v3_6_funcs leaves enable_ecc_force_par_wr_rmw NULL # (incomplete vtable; latent NULL-deref) # # struct amdgpu_df_funcs declares .enable_ecc_force_par_wr_rmw # (sys/dev/drm/amd/amdgpu/amdgpu.h:781-782) but df_v3_6_funcs # (df_v3_6.c:108-116, the CHIP_VEGA20 table per soc15.c:519-520) # initializes only 6 of the 7 members. The sole call site # (gmc_v9_0.c:759, gmc_v9_0_late_init) is currently gated on # asic_type == CHIP_VEGA10 (gmc_v9_0.c:753), which uses df_v1_7_funcs # (implements the op, df_v1_7.c:119) - so the NULL slot is not # dispatched today; any future Vega20-reachable caller (or a widening # of the asic gate, as repeatedly happened to this ECC path upstream) # turns it into a boot-time NULL function-pointer dereference. # # Fix: guard the indirect call (cheap, behavior-preserving; matches the # drm convention for optional vtable ops). Shape identical to upstream # Linux, which carries the same latent gap. # # Not compile-validated (full drm/amdgpu module build is out of scope # for this Info-grade finding; the change is a pure NULL-guard on an # existing expression). Authored post-verification; never applied to # the read-only sys/ tree. --- a/sys/dev/drm/amd/amdgpu/gmc_v9_0.c 2026-10-01 04:19:41.034197941 +0000 +++ b/sys/dev/drm/amd/amdgpu/gmc_v9_0.c 2026-10-01 04:19:41.046197788 +0000 @@ -756,7 +756,13 @@ DRM_INFO("ECC is active.\n"); } else if (r == 0) { DRM_INFO("ECC is not present.\n"); - adev->df_funcs->enable_ecc_force_par_wr_rmw(adev, false); + /* + * df_v3_6_funcs (VEGA20) does not implement + * enable_ecc_force_par_wr_rmw - guard the + * indirect call against the NULL slot. + */ + if (adev->df_funcs->enable_ecc_force_par_wr_rmw) + adev->df_funcs->enable_ecc_force_par_wr_rmw(adev, false); } else { DRM_ERROR("gmc_v9_0_ecc_available() failed. r: %d\n", r); return r;