fix.diff — DF-3735: clamp requested_clock_mode_index at the consumer choke point (radeon_set_power_state) so hardcoded profile cm indices (r600.c:685 et seq.) and the DYNPM increment (r600.c:486) can never index past the selected power state's clock_info allocation. Authored against the read-only sys/ tree; never applied there. diff --git a/sys/dev/drm/radeon/radeon_pm.c b/sys/dev/drm/radeon/radeon_pm.c --- a/sys/dev/drm/radeon/radeon_pm.c +++ b/sys/dev/drm/radeon/radeon_pm.c @@ -175,9 +175,20 @@ static void radeon_set_power_state(struct radeon_device *rdev) if ((rdev->pm.requested_clock_mode_index == rdev->pm.current_clock_mode_index) && (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index)) return; + /* + * Clamp the requested clock mode to the selected power state's mode + * count. The r6xx/r7xx profile tables (r600_pm_init_profile) hardcode + * clock-mode indices up to 2 and the DYNPM downclock path can + * increment past the last mode, while PowerPlayInfo frev1/2 tables + * give every state exactly one clock mode — without this clamp both + * paths read past the end of the per-state clock_info allocation + * (OOB heap read feeding clock/voltage programming). + */ + if ((rdev->pm.requested_power_state_index < rdev->pm.num_power_states) && + (rdev->pm.power_state[rdev->pm.requested_power_state_index].num_clock_modes > 0) && + (rdev->pm.requested_clock_mode_index >= + rdev->pm.power_state[rdev->pm.requested_power_state_index].num_clock_modes)) + rdev->pm.requested_clock_mode_index = + rdev->pm.power_state[rdev->pm.requested_power_state_index].num_clock_modes - 1; + if (radeon_gui_idle(rdev)) { sclk = rdev->pm.power_state[rdev->pm.requested_power_state_index]. clock_info[rdev->pm.requested_clock_mode_index].sclk;