Path: blob/master/tools/power/cpupower/utils/helpers/amd.c
26299 views
// SPDX-License-Identifier: GPL-2.01#if defined(__i386__) || defined(__x86_64__)2#include <unistd.h>3#include <errno.h>4#include <stdio.h>5#include <stdint.h>67#include <pci/pci.h>89#include "helpers/helpers.h"10#include "cpufreq.h"11#include "acpi_cppc.h"1213/* ACPI P-States Helper Functions for AMD Processors ***************/14#define MSR_AMD_PSTATE_STATUS 0xc001006315#define MSR_AMD_PSTATE 0xc001006416#define MSR_AMD_PSTATE_LIMIT 0xc00100611718union core_pstate {19/* pre fam 17h: */20struct {21unsigned fid:6;22unsigned did:3;23unsigned vid:7;24unsigned res1:6;25unsigned nbdid:1;26unsigned res2:2;27unsigned nbvid:7;28unsigned iddval:8;29unsigned idddiv:2;30unsigned res3:21;31unsigned en:1;32} pstate;33/* since fam 17h: */34struct {35unsigned fid:8;36unsigned did:6;37unsigned vid:8;38unsigned iddval:8;39unsigned idddiv:2;40unsigned res1:31;41unsigned en:1;42} pstatedef;43/* since fam 1Ah: */44struct {45unsigned fid:12;46unsigned res1:2;47unsigned vid:8;48unsigned iddval:8;49unsigned idddiv:2;50unsigned res2:31;51unsigned en:1;52} pstatedef2;53unsigned long long val;54};5556static int get_did(union core_pstate pstate)57{58int t;5960/* Fam 1Ah onward do not use did */61if (cpupower_cpu_info.family >= 0x1A)62return 0;6364if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_PSTATEDEF)65t = pstate.pstatedef.did;66else if (cpupower_cpu_info.family == 0x12)67t = pstate.val & 0xf;68else69t = pstate.pstate.did;7071return t;72}7374static int get_cof(union core_pstate pstate)75{76int t;77int fid, did, cof = 0;7879did = get_did(pstate);80if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_PSTATEDEF) {81if (cpupower_cpu_info.family >= 0x1A) {82fid = pstate.pstatedef2.fid;83if (fid > 0x0f)84cof = (fid * 5);85} else {86fid = pstate.pstatedef.fid;87cof = 200 * fid / did;88}89} else {90t = 0x10;91fid = pstate.pstate.fid;92if (cpupower_cpu_info.family == 0x11)93t = 0x8;94cof = (100 * (fid + t)) >> did;95}96return cof;97}9899/* Needs:100* cpu -> the cpu that gets evaluated101* boost_states -> how much boost states the machines support102*103* Fills up:104* pstates -> a pointer to an array of size MAX_HW_PSTATES105* must be initialized with zeros.106* All available HW pstates (including boost states)107* no -> amount of pstates above array got filled up with108*109* returns zero on success, -1 on failure110*/111int decode_pstates(unsigned int cpu, int boost_states,112unsigned long *pstates, int *no)113{114int i, psmax;115union core_pstate pstate;116unsigned long long val;117118/* Only read out frequencies from HW if HW Pstate is supported,119* otherwise frequencies are exported via ACPI tables.120*/121if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_HW_PSTATE))122return -1;123124if (read_msr(cpu, MSR_AMD_PSTATE_LIMIT, &val))125return -1;126127psmax = (val >> 4) & 0x7;128psmax += boost_states;129for (i = 0; i <= psmax; i++) {130if (i >= MAX_HW_PSTATES) {131fprintf(stderr, "HW pstates [%d] exceeding max [%d]\n",132psmax, MAX_HW_PSTATES);133return -1;134}135if (read_msr(cpu, MSR_AMD_PSTATE + i, &pstate.val))136return -1;137138/* The enabled bit (bit 63) is common for all families */139if (!pstate.pstatedef.en)140continue;141142pstates[i] = get_cof(pstate);143}144*no = i;145return 0;146}147148int amd_pci_get_num_boost_states(int *active, int *states)149{150struct pci_access *pci_acc;151struct pci_dev *device;152uint8_t val = 0;153154*active = *states = 0;155156device = pci_slot_func_init(&pci_acc, 0x18, 4);157158if (device == NULL)159return -ENODEV;160161val = pci_read_byte(device, 0x15c);162if (val & 3)163*active = 1;164else165*active = 0;166*states = (val >> 2) & 7;167168pci_cleanup(pci_acc);169return 0;170}171172/* ACPI P-States Helper Functions for AMD Processors ***************/173174/* AMD P-State Helper Functions ************************************/175enum amd_pstate_value {176AMD_PSTATE_HIGHEST_PERF,177AMD_PSTATE_MAX_FREQ,178AMD_PSTATE_LOWEST_NONLINEAR_FREQ,179AMD_PSTATE_HW_PREFCORE,180AMD_PSTATE_PREFCORE_RANKING,181MAX_AMD_PSTATE_VALUE_READ_FILES,182};183184static const char *amd_pstate_value_files[MAX_AMD_PSTATE_VALUE_READ_FILES] = {185[AMD_PSTATE_HIGHEST_PERF] = "amd_pstate_highest_perf",186[AMD_PSTATE_MAX_FREQ] = "amd_pstate_max_freq",187[AMD_PSTATE_LOWEST_NONLINEAR_FREQ] = "amd_pstate_lowest_nonlinear_freq",188[AMD_PSTATE_HW_PREFCORE] = "amd_pstate_hw_prefcore",189[AMD_PSTATE_PREFCORE_RANKING] = "amd_pstate_prefcore_ranking",190};191192static unsigned long amd_pstate_get_data(unsigned int cpu,193enum amd_pstate_value value)194{195return cpufreq_get_sysfs_value_from_table(cpu,196amd_pstate_value_files,197value,198MAX_AMD_PSTATE_VALUE_READ_FILES);199}200201void amd_pstate_boost_init(unsigned int cpu, int *support, int *active)202{203unsigned long highest_perf, nominal_perf, cpuinfo_min,204cpuinfo_max, amd_pstate_max;205206highest_perf = amd_pstate_get_data(cpu, AMD_PSTATE_HIGHEST_PERF);207nominal_perf = acpi_cppc_get_data(cpu, NOMINAL_PERF);208209*support = highest_perf > nominal_perf ? 1 : 0;210if (!(*support))211return;212213cpufreq_get_hardware_limits(cpu, &cpuinfo_min, &cpuinfo_max);214amd_pstate_max = amd_pstate_get_data(cpu, AMD_PSTATE_MAX_FREQ);215216*active = cpuinfo_max == amd_pstate_max ? 1 : 0;217}218219void amd_pstate_show_perf_and_freq(unsigned int cpu, int no_rounding)220{221222printf(_(" amd-pstate limits:\n"));223printf(_(" Highest Performance: %lu. Maximum Frequency: "),224amd_pstate_get_data(cpu, AMD_PSTATE_HIGHEST_PERF));225/*226* If boost isn't active, the cpuinfo_max doesn't indicate real max227* frequency. So we read it back from amd-pstate sysfs entry.228*/229print_speed(amd_pstate_get_data(cpu, AMD_PSTATE_MAX_FREQ), no_rounding);230printf(".\n");231232printf(_(" Nominal Performance: %lu. Nominal Frequency: "),233acpi_cppc_get_data(cpu, NOMINAL_PERF));234print_speed(acpi_cppc_get_data(cpu, NOMINAL_FREQ) * 1000,235no_rounding);236printf(".\n");237238printf(_(" Lowest Non-linear Performance: %lu. Lowest Non-linear Frequency: "),239acpi_cppc_get_data(cpu, LOWEST_NONLINEAR_PERF));240print_speed(amd_pstate_get_data(cpu, AMD_PSTATE_LOWEST_NONLINEAR_FREQ),241no_rounding);242printf(".\n");243244printf(_(" Lowest Performance: %lu. Lowest Frequency: "),245acpi_cppc_get_data(cpu, LOWEST_PERF));246print_speed(acpi_cppc_get_data(cpu, LOWEST_FREQ) * 1000, no_rounding);247printf(".\n");248249printf(_(" Preferred Core Support: %lu. Preferred Core Ranking: %lu.\n"),250amd_pstate_get_data(cpu, AMD_PSTATE_HW_PREFCORE),251amd_pstate_get_data(cpu, AMD_PSTATE_PREFCORE_RANKING));252}253254/* AMD P-State Helper Functions ************************************/255#endif /* defined(__i386__) || defined(__x86_64__) */256257258