<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<p style="font-family:Arial;font-size:10pt;color:#0000FF;margin:5pt;" align="Left">
[AMD Official Use Only - General]<br>
</p>
<br>
<div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div id="appendonsend"></div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0)">
<br>
</div>
<hr tabindex="-1" style="display:inline-block; width:98%">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><b>From:</b> Lazar, Lijo <Lijo.Lazar@amd.com><br>
<b>Sent:</b> Monday, May 9, 2022 12:50 AM<br>
<b>To:</b> Powell, Darren <Darren.Powell@amd.com>; amd-gfx@lists.freedesktop.org <amd-gfx@lists.freedesktop.org><br>
<b>Cc:</b> Wang, Yang(Kevin) <KevinYang.Wang@amd.com>; Feng, Kenneth <Kenneth.Feng@amd.com>; Quan, Evan <Evan.Quan@amd.com>; Ma, Le <Le.Ma@amd.com><br>
<b>Subject:</b> Re: [PATCH v1 2/2] amdgpu/pm: Fix possible array out-of-bounds if SCLK levels != 2</font>
<div> </div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt">
<div class="PlainText elementToProof"><br>
<br>
On 5/9/2022 9:28 AM, Darren Powell wrote:<br>
>   added a check to populate and use SCLK shim table freq_values only<br>
>     if using dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL or<br>
>                           AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM<br>
>   removed clocks.num_levels from calculation of shim table size<br>
>   removed unsafe accesses to shim table freq_values<br>
>     output gfx_table values if using other dpm levels<br>
>   added check for freq_match when using freq_values for when now == min_clk<br>
> <br>
> == Test ==<br>
> LOGFILE=aldebaran-sclk.test.log<br>
> AMDGPU_PCI_ADDR=`lspci -nn | grep "VGA\|Display" | cut -d " " -f 1`<br>
> AMDGPU_HWMON=`ls -la /sys/class/hwmon | grep $AMDGPU_PCI_ADDR | awk '{print $9}'`<br>
> HWMON_DIR=/sys/class/hwmon/${AMDGPU_HWMON}<br>
> <br>
> lspci -nn | grep "VGA\|Display"  > $LOGFILE<br>
> FILES="pp_od_clk_voltage<br>
> pp_dpm_sclk"<br>
> <br>
> for f in $FILES<br>
> do<br>
>    echo === $f === >> $LOGFILE<br>
>    cat $HWMON_DIR/device/$f >> $LOGFILE<br>
> done<br>
> cat $LOGFILE<br>
> <br>
> Signed-off-by: Darren Powell <darren.powell@amd.com><br>
> ---<br>
>   .../drm/amd/pm/swsmu/smu13/aldebaran_ppt.c    | 60 +++++++++----------<br>
>   1 file changed, 29 insertions(+), 31 deletions(-)<br>
> <br>
> diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c<br>
> index 6a4fca47ae53..a653668e8402 100644<br>
> --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c<br>
> +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c<br>
> @@ -740,9 +740,8 @@ static int aldebaran_print_clk_levels(struct smu_context *smu,<br>
>        struct smu_13_0_dpm_table *single_dpm_table;<br>
>        struct smu_dpm_context *smu_dpm = &smu->smu_dpm;<br>
>        struct smu_13_0_dpm_context *dpm_context = NULL;<br>
> -     uint32_t display_levels;<br>
>        uint32_t freq_values[3] = {0};<br>
> -     uint32_t min_clk, max_clk;<br>
> +     uint32_t min_clk, max_clk, display_levels = 0;<br>
>   <br>
>        smu_cmn_get_sysfs_buf(&buf, &size);<br>
>   <br>
> @@ -765,46 +764,45 @@ static int aldebaran_print_clk_levels(struct smu_context *smu,<br>
>                        return ret;<br>
>                }<br>
>   <br>
> -             single_dpm_table = &(dpm_context->dpm_tables.gfx_table);<br>
> -             ret = aldebaran_get_clk_table(smu, &clocks, single_dpm_table);<br>
> -             if (ret) {<br>
> -                     dev_err(smu->adev->dev, "Attempt to get gfx clk levels Failed!");<br>
> -                     return ret;<br>
> -             }<br>
> -<br>
> -             display_levels = clocks.num_levels;<br>
> -<br>
> -             min_clk = pstate_table->gfxclk_pstate.curr.min;<br>
> -             max_clk = pstate_table->gfxclk_pstate.curr.max;<br>
> -<br>
> -             freq_values[0] = min_clk;<br>
> -             freq_values[1] = max_clk;<br>
> -<br>
> -             /* fine-grained dpm has only 2 levels */<br>
> -             if (now > min_clk && now < max_clk) {<br>
> -                     display_levels = clocks.num_levels + 1;<br>
> -                     freq_values[2] = max_clk;<br>
> -                     freq_values[1] = now;<br>
> -             }<br>
> +             if ((smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL &&<br>
> +                  smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM)) {<br>
> +                     single_dpm_table = &(dpm_context->dpm_tables.gfx_table);<br>
> +                     ret = aldebaran_get_clk_table(smu, &clocks, single_dpm_table);<br>
> +                     if (ret) {<br>
> +                             dev_err(smu->adev->dev, "Attempt to get gfx clk levels Failed!");<br>
> +                             return ret;<br>
> +                     }<br>
<br>
There are only two levels for GFX clock in aldebaran - min and max. <br>
Regardless of the mode, gfxclk_pstate.curr.min/max should reflect the <br>
current min/max level.<br>
<br>
Could you explain the issue you are seeing? It's not so clear from the <br>
commit message.<br>
<br>
Thanks,<br>
Lijo<br>
[DP] I was concerned by the initialization of display_levels from clocks.num_levels and how it is used as the loop iterator
<div>while accessing the freq_values array. My mistake was that I assumed that meant you intended to access clocks.data array.</div>
<div>If aldebaran only uses the curr.min and curr.max values that simplifies this greatly, </div>
<div>I'll respin this to initialize display_levels to 2 , and then output from freq_values array.</div>
<br>
>   <br>
> -             /*<br>
> -              * For DPM disabled case, there will be only one clock level.<br>
> -              * And it's safe to assume that is always the current clock.<br>
> -              */<br>
> -             if (display_levels == clocks.num_levels) {<br>
>                        for (i = 0; i < clocks.num_levels; i++)<br>
>                                size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i,<br>
> -                                     freq_values[i],<br>
> +                                     clocks.data[i].clocks_in_khz / 1000,<br>
>                                        (clocks.num_levels == 1) ?<br>
>                                                "*" :<br>
>                                                (aldebaran_freqs_in_same_level(<br>
> -                                                      freq_values[i], now) ?<br>
> +                                                      clocks.data[i].clocks_in_khz / 1000, now) ?<br>
>                                                         "*" :<br>
>                                                         ""));<br>
>                } else {<br>
> +                     /* fine-grained dpm has only 2 levels */<br>
> +                     display_levels = 2;<br>
> +<br>
> +                     min_clk = pstate_table->gfxclk_pstate.curr.min;<br>
> +                     max_clk = pstate_table->gfxclk_pstate.curr.max;<br>
> +<br>
> +                     freq_values[0] = min_clk;<br>
> +                     freq_values[1] = max_clk;<br>
> +<br>
> +                     if (now > min_clk && now < max_clk) {<br>
> +                             display_levels++;<br>
> +                             freq_values[2] = max_clk;<br>
> +                             freq_values[1] = now;<br>
> +                     }<br>
> +<br>
>                        for (i = 0; i < display_levels; i++)<br>
>                                size += sysfs_emit_at(buf, size, "%d: %uMhz %s\n", i,<br>
> -                                             freq_values[i], i == 1 ? "*" : "");<br>
> +                                             freq_values[i],<br>
> +                                             aldebaran_freqs_in_same_level(freq_values[i], now) ?<br>
> +                                                     "*" : "");<br>
>                }<br>
>   <br>
>                break;<br>
> <br>
</div>
</span></font></div>
</div>
</body>
</html>