1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 28113ab20SBorislav Petkov 38113ab20SBorislav Petkov #include <stdio.h> 48113ab20SBorislav Petkov #include <errno.h> 58113ab20SBorislav Petkov #include <stdlib.h> 68113ab20SBorislav Petkov 77fe2f639SDominik Brodowski #include "helpers/helpers.h" 88113ab20SBorislav Petkov #include "helpers/sysfs.h" 98113ab20SBorislav Petkov 10748f0d70SBrahadambal Srinivasan #if defined(__i386__) || defined(__x86_64__) 11748f0d70SBrahadambal Srinivasan 128113ab20SBorislav Petkov #include "cpupower_intern.h" 137fe2f639SDominik Brodowski 14902bef73SSherry Hurwitz #define MSR_AMD_HWCR 0xc0010015 15902bef73SSherry Hurwitz 162cd005caSDominik Brodowski int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active, 172cd005caSDominik Brodowski int *states) 187fe2f639SDominik Brodowski { 197fe2f639SDominik Brodowski int ret; 20902bef73SSherry Hurwitz unsigned long long val; 217fe2f639SDominik Brodowski 227fe2f639SDominik Brodowski *support = *active = *states = 0; 237fe2f639SDominik Brodowski 247a136a8fSRobert Richter if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_CPB) { 257fe2f639SDominik Brodowski *support = 1; 26902bef73SSherry Hurwitz 27902bef73SSherry Hurwitz /* AMD Family 0x17 does not utilize PCI D18F4 like prior 28902bef73SSherry Hurwitz * families and has no fixed discrete boost states but 29902bef73SSherry Hurwitz * has Hardware determined variable increments instead. 30902bef73SSherry Hurwitz */ 31902bef73SSherry Hurwitz 32*3a3ecfdbSNathan Fontenot if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_CPB_MSR) { 33902bef73SSherry Hurwitz if (!read_msr(cpu, MSR_AMD_HWCR, &val)) { 34902bef73SSherry Hurwitz if (!(val & CPUPOWER_AMD_CPBDIS)) 35902bef73SSherry Hurwitz *active = 1; 36902bef73SSherry Hurwitz } 37902bef73SSherry Hurwitz } else { 386ae78b4eSSherry Hurwitz ret = amd_pci_get_num_boost_states(active, states); 396ae78b4eSSherry Hurwitz if (ret) 407fe2f639SDominik Brodowski return ret; 41902bef73SSherry Hurwitz } 42029e9f73SThomas Renninger } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_INTEL_IDA) 43029e9f73SThomas Renninger *support = *active = 1; 447fe2f639SDominik Brodowski return 0; 457fe2f639SDominik Brodowski } 468113ab20SBorislav Petkov 478113ab20SBorislav Petkov int cpupower_intel_get_perf_bias(unsigned int cpu) 488113ab20SBorislav Petkov { 498113ab20SBorislav Petkov char linebuf[MAX_LINE_LEN]; 508113ab20SBorislav Petkov char path[SYSFS_PATH_MAX]; 518113ab20SBorislav Petkov unsigned long val; 528113ab20SBorislav Petkov char *endp; 538113ab20SBorislav Petkov 548113ab20SBorislav Petkov if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS)) 558113ab20SBorislav Petkov return -1; 568113ab20SBorislav Petkov 578113ab20SBorislav Petkov snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/power/energy_perf_bias", cpu); 588113ab20SBorislav Petkov 598113ab20SBorislav Petkov if (cpupower_read_sysfs(path, linebuf, MAX_LINE_LEN) == 0) 608113ab20SBorislav Petkov return -1; 618113ab20SBorislav Petkov 628113ab20SBorislav Petkov val = strtol(linebuf, &endp, 0); 638113ab20SBorislav Petkov if (endp == linebuf || errno == ERANGE) 648113ab20SBorislav Petkov return -1; 658113ab20SBorislav Petkov 668113ab20SBorislav Petkov return val; 678113ab20SBorislav Petkov } 688113ab20SBorislav Petkov 698113ab20SBorislav Petkov int cpupower_intel_set_perf_bias(unsigned int cpu, unsigned int val) 708113ab20SBorislav Petkov { 718113ab20SBorislav Petkov char path[SYSFS_PATH_MAX]; 728113ab20SBorislav Petkov char linebuf[3] = {}; 738113ab20SBorislav Petkov 748113ab20SBorislav Petkov if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS)) 758113ab20SBorislav Petkov return -1; 768113ab20SBorislav Petkov 778113ab20SBorislav Petkov snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/power/energy_perf_bias", cpu); 788113ab20SBorislav Petkov snprintf(linebuf, sizeof(linebuf), "%d", val); 798113ab20SBorislav Petkov 808113ab20SBorislav Petkov if (cpupower_write_sysfs(path, linebuf, 3) <= 0) 818113ab20SBorislav Petkov return -1; 828113ab20SBorislav Petkov 838113ab20SBorislav Petkov return 0; 848113ab20SBorislav Petkov } 858113ab20SBorislav Petkov 867fe2f639SDominik Brodowski #endif /* #if defined(__i386__) || defined(__x86_64__) */ 87748f0d70SBrahadambal Srinivasan 88748f0d70SBrahadambal Srinivasan /* get_cpustate 89748f0d70SBrahadambal Srinivasan * 90748f0d70SBrahadambal Srinivasan * Gather the information of all online CPUs into bitmask struct 91748f0d70SBrahadambal Srinivasan */ 92748f0d70SBrahadambal Srinivasan void get_cpustate(void) 93748f0d70SBrahadambal Srinivasan { 94748f0d70SBrahadambal Srinivasan unsigned int cpu = 0; 95748f0d70SBrahadambal Srinivasan 96748f0d70SBrahadambal Srinivasan bitmask_clearall(online_cpus); 97748f0d70SBrahadambal Srinivasan bitmask_clearall(offline_cpus); 98748f0d70SBrahadambal Srinivasan 99748f0d70SBrahadambal Srinivasan for (cpu = bitmask_first(cpus_chosen); 100748f0d70SBrahadambal Srinivasan cpu <= bitmask_last(cpus_chosen); cpu++) { 101748f0d70SBrahadambal Srinivasan 102748f0d70SBrahadambal Srinivasan if (cpupower_is_cpu_online(cpu) == 1) 103748f0d70SBrahadambal Srinivasan bitmask_setbit(online_cpus, cpu); 104748f0d70SBrahadambal Srinivasan else 105748f0d70SBrahadambal Srinivasan bitmask_setbit(offline_cpus, cpu); 106748f0d70SBrahadambal Srinivasan 107748f0d70SBrahadambal Srinivasan continue; 108748f0d70SBrahadambal Srinivasan } 109748f0d70SBrahadambal Srinivasan } 110748f0d70SBrahadambal Srinivasan 111748f0d70SBrahadambal Srinivasan /* print_online_cpus 112748f0d70SBrahadambal Srinivasan * 113748f0d70SBrahadambal Srinivasan * Print the CPU numbers of all CPUs that are online currently 114748f0d70SBrahadambal Srinivasan */ 115748f0d70SBrahadambal Srinivasan void print_online_cpus(void) 116748f0d70SBrahadambal Srinivasan { 117748f0d70SBrahadambal Srinivasan int str_len = 0; 118748f0d70SBrahadambal Srinivasan char *online_cpus_str = NULL; 119748f0d70SBrahadambal Srinivasan 120748f0d70SBrahadambal Srinivasan str_len = online_cpus->size * 5; 121748f0d70SBrahadambal Srinivasan online_cpus_str = (void *)malloc(sizeof(char) * str_len); 122748f0d70SBrahadambal Srinivasan 123748f0d70SBrahadambal Srinivasan if (!bitmask_isallclear(online_cpus)) { 124748f0d70SBrahadambal Srinivasan bitmask_displaylist(online_cpus_str, str_len, online_cpus); 125748f0d70SBrahadambal Srinivasan printf(_("Following CPUs are online:\n%s\n"), online_cpus_str); 126748f0d70SBrahadambal Srinivasan } 127748f0d70SBrahadambal Srinivasan } 128748f0d70SBrahadambal Srinivasan 129748f0d70SBrahadambal Srinivasan /* print_offline_cpus 130748f0d70SBrahadambal Srinivasan * 131748f0d70SBrahadambal Srinivasan * Print the CPU numbers of all CPUs that are offline currently 132748f0d70SBrahadambal Srinivasan */ 133748f0d70SBrahadambal Srinivasan void print_offline_cpus(void) 134748f0d70SBrahadambal Srinivasan { 135748f0d70SBrahadambal Srinivasan int str_len = 0; 136748f0d70SBrahadambal Srinivasan char *offline_cpus_str = NULL; 137748f0d70SBrahadambal Srinivasan 138748f0d70SBrahadambal Srinivasan str_len = offline_cpus->size * 5; 139748f0d70SBrahadambal Srinivasan offline_cpus_str = (void *)malloc(sizeof(char) * str_len); 140748f0d70SBrahadambal Srinivasan 141748f0d70SBrahadambal Srinivasan if (!bitmask_isallclear(offline_cpus)) { 142748f0d70SBrahadambal Srinivasan bitmask_displaylist(offline_cpus_str, str_len, offline_cpus); 143748f0d70SBrahadambal Srinivasan printf(_("Following CPUs are offline:\n%s\n"), offline_cpus_str); 144748f0d70SBrahadambal Srinivasan printf(_("cpupower set operation was not performed on them\n")); 145748f0d70SBrahadambal Srinivasan } 146748f0d70SBrahadambal Srinivasan } 147