Skip to content

Commit df32cb5

Browse files
committed
Add PawnIO AMD support
1 parent a2120b8 commit df32cb5

File tree

3 files changed

+111
-35
lines changed

3 files changed

+111
-35
lines changed

libcpuid/hwmon_amd.c

Lines changed: 72 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,43 @@
5555
#define MSR_PWR_UNIT 0xC0010299
5656
#define MSR_PKG_ENERGY_STAT 0xC001029B
5757

58+
static inline int
59+
read_amd_msr(struct msr_info_t* info, uint32_t msr_index, uint8_t highbit, uint8_t lowbit, uint64_t* result)
60+
{
61+
if (info->handle->driver_type != WR0_DRIVER_PAWNIO)
62+
return cpu_rdmsr_range(info->handle, msr_index, highbit, lowbit, result);
63+
64+
int err;
65+
const uint8_t bits = highbit - lowbit + 1;
66+
ULONG64 in = msr_index;
67+
ULONG64 out = 0;
68+
struct pio_mod_t* pio = NULL;
69+
70+
if (highbit > 63 || lowbit > highbit)
71+
return cpuid_set_error(ERR_INVRANGE);
72+
73+
if (info->id->x86.ext_family == 0x0f)
74+
pio = &info->handle->pio_amd0f;
75+
else if (info->id->x86.ext_family >= 0x10 && info->id->x86.ext_family <= 0x16)
76+
pio = &info->handle->pio_amd10;
77+
else if (info->id->x86.ext_family >= 0x17 && info->id->x86.ext_family <= 0x1A)
78+
pio = &info->handle->pio_amd17;
79+
else
80+
return cpuid_set_error(ERR_CPU_UNKN);
81+
82+
err = WR0_ExecPawn(info->handle, pio, "ioctl_read_msr", &in, 1, &out, 1, NULL);
83+
84+
if (!err && bits < 64)
85+
{
86+
/* Show only part of register */
87+
out >>= lowbit;
88+
out &= (1ULL << bits) - 1;
89+
*result = out;
90+
}
91+
92+
return err;
93+
}
94+
5895
static int get_amd_multipliers(struct msr_info_t* info, uint32_t pstate, double* multiplier)
5996
{
6097
int i, err;
@@ -97,8 +134,8 @@ static int get_amd_multipliers(struct msr_info_t* info, uint32_t pstate, double*
97134
MSRC001_00[6B:64][3:0] is cpu_did
98135
CPU COF is (100MHz * (cpu_fid + 10h) / (divisor specified by cpu_did))
99136
Note: This family contains only APUs */
100-
err = cpu_rdmsr_range(info->handle, pstate, 8, 4, &cpu_fid);
101-
err += cpu_rdmsr_range(info->handle, pstate, 3, 0, &cpu_did);
137+
err = read_amd_msr(info, pstate, 8, 4, &cpu_fid);
138+
err += read_amd_msr(info, pstate, 3, 0, &cpu_did);
102139
i = 0;
103140
while (i < num_dids && divisor_t[i].did != cpu_did)
104141
i++;
@@ -115,8 +152,8 @@ static int get_amd_multipliers(struct msr_info_t* info, uint32_t pstate, double*
115152
Divisor is (CpuDidMSD + (cpu_did_lsd * 0.25) + 1)
116153
CPU COF is (main PLL frequency specified by D18F3xD4[MainPllOpFreqId]) / (core clock divisor specified by CpuDidMSD and cpu_did_lsd)
117154
Note: This family contains only APUs */
118-
err = cpu_rdmsr_range(info->handle, pstate, 8, 4, &cpu_did);
119-
err += cpu_rdmsr_range(info->handle, pstate, 3, 0, &cpu_did_lsd);
155+
err = read_amd_msr(info, pstate, 8, 4, &cpu_did);
156+
err += read_amd_msr(info, pstate, 3, 0, &cpu_did_lsd);
120157
*multiplier = (double)(((info->cpu_clock + 5LL) / 100 + magic_constant) / (cpu_did + cpu_did_lsd * 0.25 + 1));
121158
break;
122159
case 0x10: /* K10 */
@@ -146,8 +183,8 @@ static int get_amd_multipliers(struct msr_info_t* info, uint32_t pstate, double*
146183
MSRC001_00[6B:64][5:0] is cpu_fid
147184
CoreCOF is (100 * (MSRC001_00[6B:64][cpu_fid] + 10h) / (2^MSRC001_00[6B:64][cpu_did]))
148185
Note: This family contains only APUs */
149-
err = cpu_rdmsr_range(info->handle, pstate, 8, 6, &cpu_did);
150-
err += cpu_rdmsr_range(info->handle, pstate, 5, 0, &cpu_fid);
186+
err = read_amd_msr(info, pstate, 8, 6, &cpu_did);
187+
err += read_amd_msr(info, pstate, 5, 0, &cpu_fid);
151188
*multiplier = ((double)(cpu_fid + magic_constant) / (1ull << cpu_did)) / divisor;
152189
break;
153190
case 0x17: /* Zen / Zen+ / Zen 2 */
@@ -165,15 +202,15 @@ static int get_amd_multipliers(struct msr_info_t* info, uint32_t pstate, double*
165202
MSRC001_006[4...B][13:8] is CpuDfsId
166203
MSRC001_006[4...B][7:0] is cpu_fid
167204
CoreCOF is (Core::X86::Msr::PStateDef[cpu_fid[7:0]]/Core::X86::Msr::PStateDef[CpuDfsId]) *200 */
168-
err = cpu_rdmsr_range(info->handle, pstate, 13, 8, &cpu_did);
169-
err += cpu_rdmsr_range(info->handle, pstate, 7, 0, &cpu_fid);
205+
err = read_amd_msr(info, pstate, 13, 8, &cpu_did);
206+
err += read_amd_msr(info, pstate, 7, 0, &cpu_fid);
170207
*multiplier = ((double)cpu_fid / cpu_did) * 2;
171208
break;
172209
case 0x1A: /* Zen 5 */
173210
/* PPR for AMD Family 1Ah Model 02h C1, pages 235
174211
MSRC001_006[4...B][11:0] is cpu_fid
175212
CoreCOF is Core::X86::Msr::PStateDef[CpuFid[11:0]] *5 */
176-
err = cpu_rdmsr_range(info->handle, pstate, 11, 0, &cpu_fid);
213+
err = read_amd_msr(info, pstate, 11, 0, &cpu_fid);
177214
*multiplier = ((double)cpu_fid) * 0.05;
178215
break;
179216
default:
@@ -196,7 +233,7 @@ static uint32_t get_amd_last_pstate_addr(struct msr_info_t* info)
196233
while ((reg == 0x0) && (last_addr > MSR_PSTATE_0))
197234
{
198235
last_addr--;
199-
cpu_rdmsr_range(info->handle, last_addr, 63, 63, &reg);
236+
read_amd_msr(info, last_addr, 63, 63, &reg);
200237
}
201238
return last_addr;
202239
}
@@ -223,7 +260,7 @@ static double get_cur_multiplier(struct msr_info_t* info)
223260
/* Refer links above
224261
MSRC001_0063[2:0] is CurPstate
225262
*/
226-
if (cpu_rdmsr_range(info->handle, MSR_PSTATE_S, 2, 0, &reg))
263+
if (read_amd_msr(info, MSR_PSTATE_S, 2, 0, &reg))
227264
goto fail;
228265
if (get_amd_multipliers(info, MSR_PSTATE_0 + (uint32_t)reg, &mult))
229266
goto fail;
@@ -396,8 +433,18 @@ static float amd_17h_temperature(struct msr_info_t* info)
396433
uint32_t temperature;
397434
float offset = 0.0f;
398435

399-
WR0_WrPciConf32(info->handle, 0, FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_THM_TCON_CUR_TMP);
400-
temperature = WR0_RdPciConf32(info->handle, 0, FAMILY_17H_PCI_CONTROL_REGISTER + 4);
436+
if (info->handle->driver_type != WR0_DRIVER_PAWNIO)
437+
{
438+
WR0_WrPciConf32(info->handle, 0, FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_THM_TCON_CUR_TMP);
439+
temperature = WR0_RdPciConf32(info->handle, 0, FAMILY_17H_PCI_CONTROL_REGISTER + 4);
440+
}
441+
else
442+
{
443+
ULONG64 in = F17H_M01H_THM_TCON_CUR_TMP;
444+
ULONG64 out = 0;
445+
WR0_ExecPawn(info->handle, &info->handle->pio_amd17, "ioctl_read_smn", &in, 1, &out, 1, NULL);
446+
temperature = (uint32_t)out;
447+
}
401448

402449
if (strstr(info->id->brand_str, "1600X") ||
403450
strstr(info->id->brand_str, "1700X") ||
@@ -417,13 +464,16 @@ static float amd_17h_temperature(struct msr_info_t* info)
417464

418465
static int get_pkg_temperature(struct msr_info_t* info)
419466
{
467+
int ret = CPU_INVALID_VALUE;
468+
WR0_WaitPciBus(10);
420469
if (info->id->x86.ext_family >= 0x17)
421-
return (int)amd_17h_temperature(info);
470+
ret = (int)amd_17h_temperature(info);
422471
else if (info->id->x86.ext_family > 0x0F)
423-
return amd_k10_temperature(info);
472+
ret = amd_k10_temperature(info);
424473
else if (info->id->x86.ext_family == 0x0F)
425-
return amd_k8_temperature(info);
426-
return CPU_INVALID_VALUE;
474+
ret = amd_k8_temperature(info);
475+
WR0_ReleasePciBus();
476+
return ret;
427477
}
428478

429479
static double get_pkg_energy(struct msr_info_t* info)
@@ -434,9 +484,9 @@ static double get_pkg_energy(struct msr_info_t* info)
434484
// 19h: Zen 3 / Zen 3+ / Zen 4
435485
if (info->id->x86.ext_family < 0x17)
436486
goto fail;
437-
if (cpu_rdmsr_range(info->handle, MSR_PKG_ENERGY_STAT, 31, 0, &total_energy))
487+
if (read_amd_msr(info, MSR_PKG_ENERGY_STAT, 31, 0, &total_energy))
438488
goto fail;
439-
if (cpu_rdmsr_range(info->handle, MSR_PWR_UNIT, 12, 8, &energy_units))
489+
if (read_amd_msr(info, MSR_PWR_UNIT, 12, 8, &energy_units))
440490
goto fail;
441491
return (double)total_energy / (1ULL << energy_units);
442492
fail:
@@ -497,7 +547,7 @@ static double get_voltage(struct msr_info_t* info)
497547
uint64_t reg, vid;
498548
uint8_t range_h, range_l;
499549

500-
if (cpu_rdmsr_range(info->handle, MSR_PSTATE_S, 2, 0, &reg))
550+
if (read_amd_msr(info, MSR_PSTATE_S, 2, 0, &reg))
501551
goto fail;
502552
if (info->id->x86.ext_family < 0x15
503553
|| ((info->id->x86.ext_family == 0x15) && (info->id->x86.ext_model < 0x10)))
@@ -515,7 +565,7 @@ static double get_voltage(struct msr_info_t* info)
515565
range_h = 21;
516566
range_l = 14;
517567
}
518-
if (cpu_rdmsr_range(info->handle, MSR_PSTATE_0 + (uint32_t)reg, range_h, range_l, &vid))
568+
if (read_amd_msr(info, MSR_PSTATE_0 + (uint32_t)reg, range_h, range_l, &vid))
519569
goto fail;
520570
if (MSR_PSTATE_0 + (uint32_t)reg <= MSR_PSTATE_7)
521571
return 1.550 - vid_step * vid;
@@ -532,7 +582,7 @@ static double get_bus_clock(struct msr_info_t* info)
532582
double mult;
533583
uint64_t reg;
534584
uint32_t addr = get_amd_last_pstate_addr(info);
535-
if (cpu_rdmsr_range(info->handle, MSR_PSTATE_L, 6, 4, &reg))
585+
if (read_amd_msr(info, MSR_PSTATE_L, 6, 4, &reg))
536586
goto fail;
537587
if (get_amd_multipliers(info, addr - (uint32_t)reg, &mult))
538588
goto fail;

libcpuid/ryzen_smu.c

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,7 @@ static size_t get_pm_table_size_from_version(ry_handle_t* handle, uint32_t versi
760760
case 0x650004: return 0xB74; // CODENAME_KRACKANPOINT
761761
case 0x650005: return 0xB78; // CODENAME_KRACKANPOINT
762762
}
763-
return 0x2000;
763+
return SMU_TABLE_MAX_SIZE;
764764
}
765765

766766
static ry_err_t transfer_table_to_dram(ry_handle_t* handle)
@@ -839,6 +839,20 @@ ry_handle_t* ryzen_smu_init(struct wr0_drv_t* drv_handle, struct cpu_id_t* id)
839839
handle->drv_handle = drv_handle;
840840
handle->debug = drv_handle->debug;
841841

842+
if (drv_handle->driver_type == WR0_DRIVER_PAWNIO)
843+
{
844+
ULONG64 out[2] = { 0 };
845+
if (WR0_ExecPawn(drv_handle, &drv_handle->pio_rysmu, "ioctl_resolve_pm_table", NULL, 0, out, 2, NULL))
846+
goto fail;
847+
if (out[0] == 0 || out[1] == 0)
848+
goto fail;
849+
handle->smu_version = (uint32_t)out[0];
850+
handle->pm_table_base_addr = (uint64_t)out[1];
851+
SMU_DEBUG("SMU Version %Xh", handle->smu_version);
852+
SMU_DEBUG("PM Table Base: %llX", (unsigned long long)handle->pm_table_base_addr);
853+
return handle;
854+
}
855+
842856
if (get_codename(handle, id) != RYZEN_SMU_OK)
843857
goto fail;
844858

@@ -862,13 +876,14 @@ void ryzen_smu_free(ry_handle_t* handle)
862876
{
863877
if (!handle)
864878
return;
865-
if (handle->pm_table_buffer)
866-
free(handle->pm_table_buffer);
867879
free(handle);
868880
}
869881

870882
ry_err_t ryzen_smu_init_pm_table(ry_handle_t* handle)
871883
{
884+
if (handle->drv_handle->driver_type == WR0_DRIVER_PAWNIO)
885+
return RYZEN_SMU_OK;
886+
872887
if (handle->rsmu_cmd_addr == 0)
873888
return RYZEN_SMU_UNSUPPORTED;
874889

@@ -887,21 +902,26 @@ ry_err_t ryzen_smu_init_pm_table(ry_handle_t* handle)
887902
handle->pm_table_size = get_pm_table_size_from_version(handle, handle->pm_table_version);
888903
SMU_DEBUG("PM Table Size: %zu", handle->pm_table_size);
889904

890-
if (handle->pm_table_buffer)
891-
free(handle->pm_table_buffer);
892-
893-
handle->pm_table_buffer = calloc(1, handle->pm_table_size);
894-
if (!handle->pm_table_buffer)
895-
return RYZEN_SMU_MAPPING_ERROR;
905+
ZeroMemory(&handle->pm_table_buffer, sizeof(handle->pm_table_buffer));
896906

897907
return RYZEN_SMU_OK;
898908
}
899909

900910
ry_err_t ryzen_smu_update_pm_table(ry_handle_t* handle)
901911
{
902-
if (!handle->pm_table_base_addr || !handle->pm_table_buffer)
912+
if (!handle->pm_table_base_addr)
903913
return RYZEN_SMU_UNSUPPORTED;
904914

915+
if (handle->drv_handle->driver_type == WR0_DRIVER_PAWNIO)
916+
{
917+
if (WR0_ExecPawn(handle->drv_handle, &handle->drv_handle->pio_rysmu, "ioctl_update_pm_table", NULL, 0, NULL, 0, NULL))
918+
return RYZEN_SMU_DRIVER_ERROR;
919+
if (WR0_ExecPawn(handle->drv_handle, &handle->drv_handle->pio_rysmu, "ioctl_read_pm_table",
920+
NULL, 0, handle->pm_table_buffer_u64, SMU_TABLE_MAX_SIZE / 8, NULL))
921+
return RYZEN_SMU_DRIVER_ERROR;
922+
return RYZEN_SMU_OK;
923+
}
924+
905925
ry_err_t rc = transfer_table_to_dram(handle);
906926
if (rc != RYZEN_SMU_OK)
907927
return rc;
@@ -917,13 +937,13 @@ ry_err_t ryzen_smu_update_pm_table(ry_handle_t* handle)
917937

918938
ry_err_t ryzen_smu_get_pm_table_float(ry_handle_t* handle, size_t offset, float* value)
919939
{
920-
if (!handle || !handle->pm_table_buffer)
940+
if (!handle)
921941
return RYZEN_SMU_NOT_INITIALIZED;
922942
if (offset == OFFSET_INVALID)
923943
return RYZEN_SMU_UNSUPPORTED;
924944
if (offset + sizeof(float) > handle->pm_table_size)
925945
return RYZEN_SMU_INVALID_ARGUMENT;
926-
memcpy(value, (uint8_t*)handle->pm_table_buffer + offset, sizeof(float));
946+
memcpy(value, handle->pm_table_buffer + offset, sizeof(float));
927947
SMU_DEBUG("Get PM Table Float at offset 0x%zX, value %.2f", offset, *value);
928948
return RYZEN_SMU_OK;
929949
}

libcpuid/ryzen_smu.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ typedef union
8787

8888
struct wr0_drv_t;
8989

90+
#define SMU_TABLE_MAX_SIZE 0x2000
91+
9092
typedef struct
9193
{
9294
int debug;
@@ -97,7 +99,11 @@ typedef struct
9799
uint64_t pm_table_base_addr;
98100
uint32_t pm_table_version;
99101
size_t pm_table_size;
100-
void* pm_table_buffer;
102+
union
103+
{
104+
uint8_t pm_table_buffer[SMU_TABLE_MAX_SIZE];
105+
uint64_t pm_table_buffer_u64[SMU_TABLE_MAX_SIZE / 8];
106+
};
101107

102108
struct wr0_drv_t* drv_handle;
103109

0 commit comments

Comments
 (0)