AMD General

Reviewed-by: Hawking Zhang <[email protected]>

Regards,
Hawking
-----Original Message-----
From: Kamal, Asad <[email protected]>
Sent: Thursday, June 4, 2026 5:19 PM
To: [email protected]
Cc: Lazar, Lijo <[email protected]>; Zhang, Hawking <[email protected]>; 
Ma, Le <[email protected]>; Zhang, Morris <[email protected]>; Deucher, Alexander 
<[email protected]>; Wang, Yang(Kevin) <[email protected]>; Kamal, 
Asad <[email protected]>
Subject: [PATCH v3] drm/amd/pm: Validate OD DPM triples before mutating tables

vega10_odn_edit_dpm_table() and smu7_odn_edit_dpm_table() could mutate the live 
ODN table for valid triples, then return 0 after detecting a truncated buffer 
or out-of-range index. Validate all (index, clock,
voltage) triples first and return -EINVAL on any failure; only then apply 
updates.

v2: Use distinct message for different error case, removed unused input_level 
from validation loop (Lijo)

v3: Reject negative level indices, input[] is long but was compared only 
against unsigned table bounds, so negative values could pass and truncate when 
assigned to uint32_t input_level.

Set DPMTABLE_OD_UPDATE_SCLK/MCLK only after validation passes, so a failed 
sysfs write does not leave need_update_dpm_table set for a later commit.

Signed-off-by: Asad Kamal <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
---
 .../drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c   | 34 ++++++++++-------
 .../drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c | 37 ++++++++++++-------
 2 files changed, 43 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c 
b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
index 416b9380a70e..aac6a0fa5d7b 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
@@ -5648,23 +5648,29 @@ static int smu7_odn_edit_dpm_table(struct pp_hwmgr 
*hwmgr,
        }

        for (i = 0; i < size; i += 3) {
-               if (i + 3 > size || input[i] >= 
podn_dpm_table_in_backend->num_of_pl) {
-                       pr_info("invalid clock voltage input \n");
-                       return 0;
+               if (i + 3 > size) {
+                       pr_info("truncated clock/voltage input\n");
+                       return -EINVAL;
                }
-               input_level = input[i];
-               input_clk = input[i+1] * 100;
-               input_vol = input[i+2];
-
-               if (smu7_check_clk_voltage_valid(hwmgr, type, input_clk, 
input_vol)) {
-                       podn_dpm_table_in_backend->entries[input_level].clock = 
input_clk;
-                       podn_vdd_dep_in_backend->entries[input_level].clk = 
input_clk;
-                       podn_dpm_table_in_backend->entries[input_level].vddc = 
input_vol;
-                       podn_vdd_dep_in_backend->entries[input_level].vddc = 
input_vol;
-                       podn_vdd_dep_in_backend->entries[input_level].vddgfx = 
input_vol;
-               } else {
+               if (input[i] < 0 || input[i] >= 
podn_dpm_table_in_backend->num_of_pl) {
+                       pr_info("invalid clock/voltage level\n");
                        return -EINVAL;
                }
+               input_clk = input[i + 1] * 100;
+               input_vol = input[i + 2];
+               if (!smu7_check_clk_voltage_valid(hwmgr, type, input_clk, 
input_vol))
+                       return -EINVAL;
+       }
+
+       for (i = 0; i < size; i += 3) {
+               input_level = input[i];
+               input_clk = input[i + 1] * 100;
+               input_vol = input[i + 2];
+               podn_dpm_table_in_backend->entries[input_level].clock = 
input_clk;
+               podn_vdd_dep_in_backend->entries[input_level].clk = input_clk;
+               podn_dpm_table_in_backend->entries[input_level].vddc = 
input_vol;
+               podn_vdd_dep_in_backend->entries[input_level].vddc = input_vol;
+               podn_vdd_dep_in_backend->entries[input_level].vddgfx = 
input_vol;
        }

        return 0;
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c 
b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
index 8b8c4e899878..076e10f26546 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
@@ -5455,11 +5455,9 @@ static int vega10_odn_edit_dpm_table(struct pp_hwmgr 
*hwmgr,
        if (PP_OD_EDIT_SCLK_VDDC_TABLE == type) {
                dpm_table = &data->dpm_table.gfx_table;
                podn_vdd_dep_table = &data->odn_dpm_table.vdd_dep_on_sclk;
-               data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
        } else if (PP_OD_EDIT_MCLK_VDDC_TABLE == type) {
                dpm_table = &data->dpm_table.mem_table;
                podn_vdd_dep_table = &data->odn_dpm_table.vdd_dep_on_mclk;
-               data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
        } else if (PP_OD_RESTORE_DEFAULT_TABLE == type) {
                memcpy(&(data->dpm_table), &(data->golden_dpm_table), 
sizeof(struct vega10_dpm_table));
                vega10_odn_initial_default_setting(hwmgr);
@@ -5477,21 +5475,32 @@ static int vega10_odn_edit_dpm_table(struct pp_hwmgr 
*hwmgr,
        }

        for (i = 0; i < size; i += 3) {
-               if (i + 3 > size || input[i] >= podn_vdd_dep_table->count) {
-                       pr_info("invalid clock voltage input\n");
-                       return 0;
+               if (i + 3 > size) {
+                       pr_info("truncated clock/voltage input\n");
+                       return -EINVAL;
                }
-               input_level = input[i];
-               input_clk = input[i+1] * 100;
-               input_vol = input[i+2];
-
-               if (vega10_check_clk_voltage_valid(hwmgr, type, input_clk, 
input_vol)) {
-                       dpm_table->dpm_levels[input_level].value = input_clk;
-                       podn_vdd_dep_table->entries[input_level].clk = 
input_clk;
-                       podn_vdd_dep_table->entries[input_level].vddc = 
input_vol;
-               } else {
+               if (input[i] < 0 || input[i] >= podn_vdd_dep_table->count) {
+                       pr_info("invalid clock/voltage level\n");
                        return -EINVAL;
                }
+               input_clk = input[i + 1] * 100;
+               input_vol = input[i + 2];
+               if (!vega10_check_clk_voltage_valid(hwmgr, type, input_clk, 
input_vol))
+                       return -EINVAL;
+       }
+
+       if (type == PP_OD_EDIT_SCLK_VDDC_TABLE)
+               data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK;
+       else
+               data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_MCLK;
+
+       for (i = 0; i < size; i += 3) {
+               input_level = input[i];
+               input_clk = input[i + 1] * 100;
+               input_vol = input[i + 2];
+               dpm_table->dpm_levels[input_level].value = input_clk;
+               podn_vdd_dep_table->entries[input_level].clk = input_clk;
+               podn_vdd_dep_table->entries[input_level].vddc = input_vol;
        }
        vega10_odn_update_soc_table(hwmgr, type);
        return 0;
--
2.46.0

Reply via email to