Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/power/cpupower/utils/helpers/misc.c
26299 views
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
#include "cpupower_intern.h"
12
13
#if defined(__i386__) || defined(__x86_64__)
14
15
#define MSR_AMD_HWCR 0xc0010015
16
17
int cpufreq_has_x86_boost_support(unsigned int cpu, int *support, int *active,
18
int *states)
19
{
20
int ret;
21
unsigned long long val;
22
23
*support = *active = *states = 0;
24
25
if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_CPB) {
26
*support = 1;
27
28
/* AMD Family 0x17 does not utilize PCI D18F4 like prior
29
* families and has no fixed discrete boost states but
30
* has Hardware determined variable increments instead.
31
*/
32
33
if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_CPB_MSR) {
34
if (!read_msr(cpu, MSR_AMD_HWCR, &val)) {
35
if (!(val & CPUPOWER_AMD_CPBDIS))
36
*active = 1;
37
}
38
} else {
39
ret = amd_pci_get_num_boost_states(active, states);
40
if (ret)
41
return ret;
42
}
43
} else if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_PSTATE) {
44
amd_pstate_boost_init(cpu, support, active);
45
} else if (cpupower_cpu_info.caps & CPUPOWER_CAP_INTEL_IDA)
46
*support = *active = 1;
47
return 0;
48
}
49
50
int cpupower_intel_get_perf_bias(unsigned int cpu)
51
{
52
char linebuf[MAX_LINE_LEN];
53
char path[SYSFS_PATH_MAX];
54
unsigned long val;
55
char *endp;
56
57
if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS))
58
return -1;
59
60
snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/power/energy_perf_bias", cpu);
61
62
if (cpupower_read_sysfs(path, linebuf, MAX_LINE_LEN) == 0)
63
return -1;
64
65
val = strtol(linebuf, &endp, 0);
66
if (endp == linebuf || errno == ERANGE)
67
return -1;
68
69
return val;
70
}
71
72
int cpupower_intel_set_perf_bias(unsigned int cpu, unsigned int val)
73
{
74
char path[SYSFS_PATH_MAX];
75
char linebuf[3] = {};
76
77
if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_PERF_BIAS))
78
return -1;
79
80
snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/power/energy_perf_bias", cpu);
81
snprintf(linebuf, sizeof(linebuf), "%d", val);
82
83
if (cpupower_write_sysfs(path, linebuf, 3) <= 0)
84
return -1;
85
86
return 0;
87
}
88
89
int cpupower_set_epp(unsigned int cpu, char *epp)
90
{
91
char path[SYSFS_PATH_MAX];
92
char linebuf[30] = {};
93
94
snprintf(path, sizeof(path),
95
PATH_TO_CPU "cpu%u/cpufreq/energy_performance_preference", cpu);
96
97
if (!is_valid_path(path))
98
return -1;
99
100
snprintf(linebuf, sizeof(linebuf), "%s", epp);
101
102
if (cpupower_write_sysfs(path, linebuf, 30) <= 0)
103
return -1;
104
105
return 0;
106
}
107
108
int cpupower_set_amd_pstate_mode(char *mode)
109
{
110
char path[SYSFS_PATH_MAX];
111
char linebuf[20] = {};
112
113
snprintf(path, sizeof(path), PATH_TO_CPU "amd_pstate/status");
114
115
if (!is_valid_path(path))
116
return -1;
117
118
snprintf(linebuf, sizeof(linebuf), "%s\n", mode);
119
120
if (cpupower_write_sysfs(path, linebuf, 20) <= 0)
121
return -1;
122
123
return 0;
124
}
125
126
bool cpupower_amd_pstate_enabled(void)
127
{
128
char *driver = cpufreq_get_driver(0);
129
bool ret = false;
130
131
if (!driver)
132
return ret;
133
134
if (!strncmp(driver, "amd", 3))
135
ret = true;
136
137
cpufreq_put_driver(driver);
138
139
return ret;
140
}
141
142
#endif /* #if defined(__i386__) || defined(__x86_64__) */
143
144
int cpufreq_has_generic_boost_support(bool *active)
145
{
146
char path[SYSFS_PATH_MAX];
147
char linebuf[2] = {};
148
unsigned long val;
149
char *endp;
150
151
snprintf(path, sizeof(path), PATH_TO_CPU "cpufreq/boost");
152
153
if (!is_valid_path(path))
154
return -EACCES;
155
156
if (cpupower_read_sysfs(path, linebuf, 2) <= 0)
157
return -EINVAL;
158
159
val = strtoul(linebuf, &endp, 0);
160
if (endp == linebuf || errno == ERANGE)
161
return -EINVAL;
162
163
switch (val) {
164
case 0:
165
*active = false;
166
break;
167
case 1:
168
*active = true;
169
break;
170
default:
171
return -EINVAL;
172
}
173
174
return 0;
175
}
176
177
/* get_cpustate
178
*
179
* Gather the information of all online CPUs into bitmask struct
180
*/
181
void get_cpustate(void)
182
{
183
unsigned int cpu = 0;
184
185
bitmask_clearall(online_cpus);
186
bitmask_clearall(offline_cpus);
187
188
for (cpu = bitmask_first(cpus_chosen);
189
cpu <= bitmask_last(cpus_chosen); cpu++) {
190
191
if (cpupower_is_cpu_online(cpu) == 1)
192
bitmask_setbit(online_cpus, cpu);
193
else
194
bitmask_setbit(offline_cpus, cpu);
195
196
continue;
197
}
198
}
199
200
/* print_online_cpus
201
*
202
* Print the CPU numbers of all CPUs that are online currently
203
*/
204
void print_online_cpus(void)
205
{
206
int str_len = 0;
207
char *online_cpus_str = NULL;
208
209
str_len = online_cpus->size * 5;
210
online_cpus_str = (void *)malloc(sizeof(char) * str_len);
211
212
if (!bitmask_isallclear(online_cpus)) {
213
bitmask_displaylist(online_cpus_str, str_len, online_cpus);
214
printf(_("Following CPUs are online:\n%s\n"), online_cpus_str);
215
}
216
}
217
218
/* print_offline_cpus
219
*
220
* Print the CPU numbers of all CPUs that are offline currently
221
*/
222
void print_offline_cpus(void)
223
{
224
int str_len = 0;
225
char *offline_cpus_str = NULL;
226
227
str_len = offline_cpus->size * 5;
228
offline_cpus_str = (void *)malloc(sizeof(char) * str_len);
229
230
if (!bitmask_isallclear(offline_cpus)) {
231
bitmask_displaylist(offline_cpus_str, str_len, offline_cpus);
232
printf(_("Following CPUs are offline:\n%s\n"), offline_cpus_str);
233
printf(_("cpupower set operation was not performed on them\n"));
234
}
235
}
236
237
/*
238
* print_speed
239
*
240
* Print the exact CPU frequency with appropriate unit
241
*/
242
void print_speed(unsigned long speed, int no_rounding)
243
{
244
unsigned long tmp;
245
246
if (no_rounding) {
247
if (speed > 1000000)
248
printf("%u.%06u GHz", ((unsigned int)speed / 1000000),
249
((unsigned int)speed % 1000000));
250
else if (speed > 1000)
251
printf("%u.%03u MHz", ((unsigned int)speed / 1000),
252
(unsigned int)(speed % 1000));
253
else
254
printf("%lu kHz", speed);
255
} else {
256
if (speed > 1000000) {
257
tmp = speed % 10000;
258
if (tmp >= 5000)
259
speed += 10000;
260
printf("%u.%02u GHz", ((unsigned int)speed / 1000000),
261
((unsigned int)(speed % 1000000) / 10000));
262
} else if (speed > 100000) {
263
tmp = speed % 1000;
264
if (tmp >= 500)
265
speed += 1000;
266
printf("%u MHz", ((unsigned int)speed / 1000));
267
} else if (speed > 1000) {
268
tmp = speed % 100;
269
if (tmp >= 50)
270
speed += 100;
271
printf("%u.%01u MHz", ((unsigned int)speed / 1000),
272
((unsigned int)(speed % 1000) / 100));
273
}
274
}
275
}
276
277
int cpupower_set_turbo_boost(int turbo_boost)
278
{
279
char path[SYSFS_PATH_MAX];
280
char linebuf[2] = {};
281
282
snprintf(path, sizeof(path), PATH_TO_CPU "cpufreq/boost");
283
284
if (!is_valid_path(path))
285
return -1;
286
287
snprintf(linebuf, sizeof(linebuf), "%d", turbo_boost);
288
289
if (cpupower_write_sysfs(path, linebuf, 2) <= 0)
290
return -1;
291
292
return 0;
293
}
294
295