misc.c (4761B)
1// SPDX-License-Identifier: GPL-2.0 2 3#include <stdio.h> 4#include <errno.h> 5#include <stdlib.h> 6#include <string.h> 7 8#include "helpers/helpers.h" 9#include "helpers/sysfs.h" 10#include "cpufreq.h" 11 12#if defined(__i386__) || defined(__x86_64__) 13 14#include "cpupower_intern.h" 15 16#define MSR_AMD_HWCR 0xc0010015 17 18int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active, 19 int *states) 20{ 21 int ret; 22 unsigned long long val; 23 24 *support = *active = *states = 0; 25 26 if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_CPB) { 27 *support = 1; 28 29 /* AMD Family 0x17 does not utilize PCI D18F4 like prior 30 * families and has no fixed discrete boost states but 31 * has Hardware determined variable increments instead. 32 */ 33 34 if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_CPB_MSR) { 35 if (!read_msr(cpu, MSR_AMD_HWCR, &val)) { 36 if (!(val & CPUPOWER_AMD_CPBDIS)) 37 *active = 1; 38 } 39 } else { 40 ret = amd_pci_get_num_boost_states(active, states); 41 if (ret) 42 return ret; 43 } 44 } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_PSTATE) { 45 amd_pstate_boost_init(cpu, support, active); 46 } else if (cpupower_cpu_info.caps & CPUPOWER_CAP_INTEL_IDA) 47 *support = *active = 1; 48 return 0; 49} 50 51int cpupower_intel_get_perf_bias(unsigned int cpu) 52{ 53 char linebuf[MAX_LINE_LEN]; 54 char path[SYSFS_PATH_MAX]; 55 unsigned long val; 56 char *endp; 57 58 if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS)) 59 return -1; 60 61 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/power/energy_perf_bias", cpu); 62 63 if (cpupower_read_sysfs(path, linebuf, MAX_LINE_LEN) == 0) 64 return -1; 65 66 val = strtol(linebuf, &endp, 0); 67 if (endp == linebuf || errno == ERANGE) 68 return -1; 69 70 return val; 71} 72 73int cpupower_intel_set_perf_bias(unsigned int cpu, unsigned int val) 74{ 75 char path[SYSFS_PATH_MAX]; 76 char linebuf[3] = {}; 77 78 if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS)) 79 return -1; 80 81 snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/power/energy_perf_bias", cpu); 82 snprintf(linebuf, sizeof(linebuf), "%d", val); 83 84 if (cpupower_write_sysfs(path, linebuf, 3) <= 0) 85 return -1; 86 87 return 0; 88} 89 90bool cpupower_amd_pstate_enabled(void) 91{ 92 char *driver = cpufreq_get_driver(0); 93 bool ret = false; 94 95 if (!driver) 96 return ret; 97 98 if (!strcmp(driver, "amd-pstate")) 99 ret = true; 100 101 cpufreq_put_driver(driver); 102 103 return ret; 104} 105 106#endif /* #if defined(__i386__) || defined(__x86_64__) */ 107 108/* get_cpustate 109 * 110 * Gather the information of all online CPUs into bitmask struct 111 */ 112void get_cpustate(void) 113{ 114 unsigned int cpu = 0; 115 116 bitmask_clearall(online_cpus); 117 bitmask_clearall(offline_cpus); 118 119 for (cpu = bitmask_first(cpus_chosen); 120 cpu <= bitmask_last(cpus_chosen); cpu++) { 121 122 if (cpupower_is_cpu_online(cpu) == 1) 123 bitmask_setbit(online_cpus, cpu); 124 else 125 bitmask_setbit(offline_cpus, cpu); 126 127 continue; 128 } 129} 130 131/* print_online_cpus 132 * 133 * Print the CPU numbers of all CPUs that are online currently 134 */ 135void print_online_cpus(void) 136{ 137 int str_len = 0; 138 char *online_cpus_str = NULL; 139 140 str_len = online_cpus->size * 5; 141 online_cpus_str = (void *)malloc(sizeof(char) * str_len); 142 143 if (!bitmask_isallclear(online_cpus)) { 144 bitmask_displaylist(online_cpus_str, str_len, online_cpus); 145 printf(_("Following CPUs are online:\n%s\n"), online_cpus_str); 146 } 147} 148 149/* print_offline_cpus 150 * 151 * Print the CPU numbers of all CPUs that are offline currently 152 */ 153void print_offline_cpus(void) 154{ 155 int str_len = 0; 156 char *offline_cpus_str = NULL; 157 158 str_len = offline_cpus->size * 5; 159 offline_cpus_str = (void *)malloc(sizeof(char) * str_len); 160 161 if (!bitmask_isallclear(offline_cpus)) { 162 bitmask_displaylist(offline_cpus_str, str_len, offline_cpus); 163 printf(_("Following CPUs are offline:\n%s\n"), offline_cpus_str); 164 printf(_("cpupower set operation was not performed on them\n")); 165 } 166} 167 168/* 169 * print_speed 170 * 171 * Print the exact CPU frequency with appropriate unit 172 */ 173void print_speed(unsigned long speed, int no_rounding) 174{ 175 unsigned long tmp; 176 177 if (no_rounding) { 178 if (speed > 1000000) 179 printf("%u.%06u GHz", ((unsigned int)speed / 1000000), 180 ((unsigned int)speed % 1000000)); 181 else if (speed > 1000) 182 printf("%u.%03u MHz", ((unsigned int)speed / 1000), 183 (unsigned int)(speed % 1000)); 184 else 185 printf("%lu kHz", speed); 186 } else { 187 if (speed > 1000000) { 188 tmp = speed % 10000; 189 if (tmp >= 5000) 190 speed += 10000; 191 printf("%u.%02u GHz", ((unsigned int)speed / 1000000), 192 ((unsigned int)(speed % 1000000) / 10000)); 193 } else if (speed > 100000) { 194 tmp = speed % 1000; 195 if (tmp >= 500) 196 speed += 1000; 197 printf("%u MHz", ((unsigned int)speed / 1000)); 198 } else if (speed > 1000) { 199 tmp = speed % 100; 200 if (tmp >= 50) 201 speed += 100; 202 printf("%u.%01u MHz", ((unsigned int)speed / 1000), 203 ((unsigned int)(speed % 1000) / 100)); 204 } 205 } 206}