1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Intel dynamic_speed_select -- Enumerate and control features
4 * Copyright (c) 2019 Intel Corporation.
5 */
6
7 #include "isst.h"
8
9 #define DISP_FREQ_MULTIPLIER 100
10
printcpulist(int str_len,char * str,int mask_size,cpu_set_t * cpu_mask)11 static void printcpulist(int str_len, char *str, int mask_size,
12 cpu_set_t *cpu_mask)
13 {
14 int i, first, curr_index, index;
15
16 if (!CPU_COUNT_S(mask_size, cpu_mask)) {
17 snprintf(str, str_len, "none");
18 return;
19 }
20
21 curr_index = 0;
22 first = 1;
23 for (i = 0; i < get_topo_max_cpus(); ++i) {
24 if (!CPU_ISSET_S(i, mask_size, cpu_mask))
25 continue;
26 if (!first) {
27 index = snprintf(&str[curr_index],
28 str_len - curr_index, ",");
29 curr_index += index;
30 }
31 index = snprintf(&str[curr_index], str_len - curr_index, "%d",
32 i);
33 curr_index += index;
34 first = 0;
35 }
36 }
37
printcpumask(int str_len,char * str,int mask_size,cpu_set_t * cpu_mask)38 static void printcpumask(int str_len, char *str, int mask_size,
39 cpu_set_t *cpu_mask)
40 {
41 int i, max_cpus = get_topo_max_cpus();
42 unsigned int *mask;
43 int size, index, curr_index;
44
45 size = max_cpus / (sizeof(unsigned int) * 8);
46 if (max_cpus % (sizeof(unsigned int) * 8))
47 size++;
48
49 mask = calloc(size, sizeof(unsigned int));
50 if (!mask)
51 return;
52
53 for (i = 0; i < max_cpus; ++i) {
54 int mask_index, bit_index;
55
56 if (!CPU_ISSET_S(i, mask_size, cpu_mask))
57 continue;
58
59 mask_index = i / (sizeof(unsigned int) * 8);
60 bit_index = i % (sizeof(unsigned int) * 8);
61 mask[mask_index] |= BIT(bit_index);
62 }
63
64 curr_index = 0;
65 for (i = size - 1; i >= 0; --i) {
66 index = snprintf(&str[curr_index], str_len - curr_index, "%08x",
67 mask[i]);
68 curr_index += index;
69 if (i) {
70 strncat(&str[curr_index], ",", str_len - curr_index);
71 curr_index++;
72 }
73 }
74
75 free(mask);
76 }
77
format_and_print_txt(FILE * outf,int level,char * header,char * value)78 static void format_and_print_txt(FILE *outf, int level, char *header,
79 char *value)
80 {
81 char *spaces = " ";
82 static char delimiters[256];
83 int i, j = 0;
84
85 if (!level)
86 return;
87
88 if (level == 1) {
89 strcpy(delimiters, " ");
90 } else {
91 for (i = 0; i < level - 1; ++i)
92 j += snprintf(&delimiters[j], sizeof(delimiters) - j,
93 "%s", spaces);
94 }
95
96 if (header && value) {
97 fprintf(outf, "%s", delimiters);
98 fprintf(outf, "%s:%s\n", header, value);
99 } else if (header) {
100 fprintf(outf, "%s", delimiters);
101 fprintf(outf, "%s\n", header);
102 }
103 }
104
105 static int last_level;
format_and_print(FILE * outf,int level,char * header,char * value)106 static void format_and_print(FILE *outf, int level, char *header, char *value)
107 {
108 char *spaces = " ";
109 static char delimiters[256];
110 int i;
111
112 if (!out_format_is_json()) {
113 format_and_print_txt(outf, level, header, value);
114 return;
115 }
116
117 if (level == 0) {
118 if (header)
119 fprintf(outf, "{");
120 else
121 fprintf(outf, "\n}\n");
122
123 } else {
124 int j = 0;
125
126 for (i = 0; i < level; ++i)
127 j += snprintf(&delimiters[j], sizeof(delimiters) - j,
128 "%s", spaces);
129
130 if (last_level == level)
131 fprintf(outf, ",\n");
132
133 if (value) {
134 if (last_level != level)
135 fprintf(outf, "\n");
136
137 fprintf(outf, "%s\"%s\": ", delimiters, header);
138 fprintf(outf, "\"%s\"", value);
139 } else {
140 for (i = last_level - 1; i >= level; --i) {
141 int k = 0;
142
143 for (j = i; j > 0; --j)
144 k += snprintf(&delimiters[k],
145 sizeof(delimiters) - k,
146 "%s", spaces);
147 if (i == level && header)
148 fprintf(outf, "\n%s},", delimiters);
149 else
150 fprintf(outf, "\n%s}", delimiters);
151 }
152 if (abs(last_level - level) < 3)
153 fprintf(outf, "\n");
154 if (header)
155 fprintf(outf, "%s\"%s\": {", delimiters,
156 header);
157 }
158 }
159
160 last_level = level;
161 }
162
print_package_info(int cpu,FILE * outf)163 static void print_package_info(int cpu, FILE *outf)
164 {
165 char header[256];
166
167 snprintf(header, sizeof(header), "package-%d",
168 get_physical_package_id(cpu));
169 format_and_print(outf, 1, header, NULL);
170 snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu));
171 format_and_print(outf, 2, header, NULL);
172 snprintf(header, sizeof(header), "cpu-%d", cpu);
173 format_and_print(outf, 3, header, NULL);
174 }
175
_isst_pbf_display_information(int cpu,FILE * outf,int level,struct isst_pbf_info * pbf_info,int disp_level)176 static void _isst_pbf_display_information(int cpu, FILE *outf, int level,
177 struct isst_pbf_info *pbf_info,
178 int disp_level)
179 {
180 char header[256];
181 char value[256];
182
183 snprintf(header, sizeof(header), "speed-select-base-freq");
184 format_and_print(outf, disp_level, header, NULL);
185
186 snprintf(header, sizeof(header), "high-priority-base-frequency(MHz)");
187 snprintf(value, sizeof(value), "%d",
188 pbf_info->p1_high * DISP_FREQ_MULTIPLIER);
189 format_and_print(outf, disp_level + 1, header, value);
190
191 snprintf(header, sizeof(header), "high-priority-cpu-mask");
192 printcpumask(sizeof(value), value, pbf_info->core_cpumask_size,
193 pbf_info->core_cpumask);
194 format_and_print(outf, disp_level + 1, header, value);
195
196 snprintf(header, sizeof(header), "high-priority-cpu-list");
197 printcpulist(sizeof(value), value,
198 pbf_info->core_cpumask_size,
199 pbf_info->core_cpumask);
200 format_and_print(outf, disp_level + 1, header, value);
201
202 snprintf(header, sizeof(header), "low-priority-base-frequency(MHz)");
203 snprintf(value, sizeof(value), "%d",
204 pbf_info->p1_low * DISP_FREQ_MULTIPLIER);
205 format_and_print(outf, disp_level + 1, header, value);
206
207 snprintf(header, sizeof(header), "tjunction-temperature(C)");
208 snprintf(value, sizeof(value), "%d", pbf_info->t_prochot);
209 format_and_print(outf, disp_level + 1, header, value);
210
211 snprintf(header, sizeof(header), "thermal-design-power(W)");
212 snprintf(value, sizeof(value), "%d", pbf_info->tdp);
213 format_and_print(outf, disp_level + 1, header, value);
214 }
215
_isst_fact_display_information(int cpu,FILE * outf,int level,int fact_bucket,int fact_avx,struct isst_fact_info * fact_info,int base_level)216 static void _isst_fact_display_information(int cpu, FILE *outf, int level,
217 int fact_bucket, int fact_avx,
218 struct isst_fact_info *fact_info,
219 int base_level)
220 {
221 struct isst_fact_bucket_info *bucket_info = fact_info->bucket_info;
222 char header[256];
223 char value[256];
224 int j;
225
226 snprintf(header, sizeof(header), "speed-select-turbo-freq");
227 format_and_print(outf, base_level, header, NULL);
228 for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
229 if (fact_bucket != 0xff && fact_bucket != j)
230 continue;
231
232 if (!bucket_info[j].high_priority_cores_count)
233 break;
234
235 snprintf(header, sizeof(header), "bucket-%d", j);
236 format_and_print(outf, base_level + 1, header, NULL);
237
238 snprintf(header, sizeof(header), "high-priority-cores-count");
239 snprintf(value, sizeof(value), "%d",
240 bucket_info[j].high_priority_cores_count);
241 format_and_print(outf, base_level + 2, header, value);
242
243 if (fact_avx & 0x01) {
244 snprintf(header, sizeof(header),
245 "high-priority-max-frequency(MHz)");
246 snprintf(value, sizeof(value), "%d",
247 bucket_info[j].sse_trl * DISP_FREQ_MULTIPLIER);
248 format_and_print(outf, base_level + 2, header, value);
249 }
250
251 if (fact_avx & 0x02) {
252 snprintf(header, sizeof(header),
253 "high-priority-max-avx2-frequency(MHz)");
254 snprintf(value, sizeof(value), "%d",
255 bucket_info[j].avx_trl * DISP_FREQ_MULTIPLIER);
256 format_and_print(outf, base_level + 2, header, value);
257 }
258
259 if (fact_avx & 0x04) {
260 snprintf(header, sizeof(header),
261 "high-priority-max-avx512-frequency(MHz)");
262 snprintf(value, sizeof(value), "%d",
263 bucket_info[j].avx512_trl *
264 DISP_FREQ_MULTIPLIER);
265 format_and_print(outf, base_level + 2, header, value);
266 }
267 }
268 snprintf(header, sizeof(header),
269 "speed-select-turbo-freq-clip-frequencies");
270 format_and_print(outf, base_level + 1, header, NULL);
271 snprintf(header, sizeof(header), "low-priority-max-frequency(MHz)");
272 snprintf(value, sizeof(value), "%d",
273 fact_info->lp_clipping_ratio_license_sse *
274 DISP_FREQ_MULTIPLIER);
275 format_and_print(outf, base_level + 2, header, value);
276 snprintf(header, sizeof(header),
277 "low-priority-max-avx2-frequency(MHz)");
278 snprintf(value, sizeof(value), "%d",
279 fact_info->lp_clipping_ratio_license_avx2 *
280 DISP_FREQ_MULTIPLIER);
281 format_and_print(outf, base_level + 2, header, value);
282 snprintf(header, sizeof(header),
283 "low-priority-max-avx512-frequency(MHz)");
284 snprintf(value, sizeof(value), "%d",
285 fact_info->lp_clipping_ratio_license_avx512 *
286 DISP_FREQ_MULTIPLIER);
287 format_and_print(outf, base_level + 2, header, value);
288 }
289
isst_ctdp_display_core_info(int cpu,FILE * outf,char * prefix,unsigned int val)290 void isst_ctdp_display_core_info(int cpu, FILE *outf, char *prefix,
291 unsigned int val)
292 {
293 char header[256];
294 char value[256];
295
296 snprintf(header, sizeof(header), "package-%d",
297 get_physical_package_id(cpu));
298 format_and_print(outf, 1, header, NULL);
299 snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu));
300 format_and_print(outf, 2, header, NULL);
301 snprintf(header, sizeof(header), "cpu-%d", cpu);
302 format_and_print(outf, 3, header, NULL);
303
304 snprintf(value, sizeof(value), "%u", val);
305 format_and_print(outf, 4, prefix, value);
306
307 format_and_print(outf, 1, NULL, NULL);
308 }
309
isst_ctdp_display_information(int cpu,FILE * outf,int tdp_level,struct isst_pkg_ctdp * pkg_dev)310 void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
311 struct isst_pkg_ctdp *pkg_dev)
312 {
313 char header[256];
314 char value[256];
315 int i, base_level = 1;
316
317 print_package_info(cpu, outf);
318
319 for (i = 0; i <= pkg_dev->levels; ++i) {
320 struct isst_pkg_ctdp_level_info *ctdp_level;
321 int j;
322
323 ctdp_level = &pkg_dev->ctdp_level[i];
324 if (!ctdp_level->processed)
325 continue;
326
327 snprintf(header, sizeof(header), "perf-profile-level-%d",
328 ctdp_level->level);
329 format_and_print(outf, base_level + 3, header, NULL);
330
331 snprintf(header, sizeof(header), "cpu-count");
332 j = get_cpu_count(get_physical_die_id(cpu),
333 get_physical_die_id(cpu));
334 snprintf(value, sizeof(value), "%d", j);
335 format_and_print(outf, base_level + 4, header, value);
336
337 snprintf(header, sizeof(header), "enable-cpu-mask");
338 printcpumask(sizeof(value), value,
339 ctdp_level->core_cpumask_size,
340 ctdp_level->core_cpumask);
341 format_and_print(outf, base_level + 4, header, value);
342
343 snprintf(header, sizeof(header), "enable-cpu-list");
344 printcpulist(sizeof(value), value,
345 ctdp_level->core_cpumask_size,
346 ctdp_level->core_cpumask);
347 format_and_print(outf, base_level + 4, header, value);
348
349 snprintf(header, sizeof(header), "thermal-design-power-ratio");
350 snprintf(value, sizeof(value), "%d", ctdp_level->tdp_ratio);
351 format_and_print(outf, base_level + 4, header, value);
352
353 snprintf(header, sizeof(header), "base-frequency(MHz)");
354 snprintf(value, sizeof(value), "%d",
355 ctdp_level->tdp_ratio * DISP_FREQ_MULTIPLIER);
356 format_and_print(outf, base_level + 4, header, value);
357
358 snprintf(header, sizeof(header),
359 "speed-select-turbo-freq");
360 if (ctdp_level->fact_support) {
361 if (ctdp_level->fact_enabled)
362 snprintf(value, sizeof(value), "enabled");
363 else
364 snprintf(value, sizeof(value), "disabled");
365 } else
366 snprintf(value, sizeof(value), "unsupported");
367 format_and_print(outf, base_level + 4, header, value);
368
369 snprintf(header, sizeof(header),
370 "speed-select-base-freq");
371 if (ctdp_level->pbf_support) {
372 if (ctdp_level->pbf_enabled)
373 snprintf(value, sizeof(value), "enabled");
374 else
375 snprintf(value, sizeof(value), "disabled");
376 } else
377 snprintf(value, sizeof(value), "unsupported");
378 format_and_print(outf, base_level + 4, header, value);
379
380 snprintf(header, sizeof(header), "thermal-design-power(W)");
381 snprintf(value, sizeof(value), "%d", ctdp_level->pkg_tdp);
382 format_and_print(outf, base_level + 4, header, value);
383
384 snprintf(header, sizeof(header), "tjunction-max(C)");
385 snprintf(value, sizeof(value), "%d", ctdp_level->t_proc_hot);
386 format_and_print(outf, base_level + 4, header, value);
387
388 snprintf(header, sizeof(header), "turbo-ratio-limits-sse");
389 format_and_print(outf, base_level + 4, header, NULL);
390 for (j = 0; j < 8; ++j) {
391 snprintf(header, sizeof(header), "bucket-%d", j);
392 format_and_print(outf, base_level + 5, header, NULL);
393
394 snprintf(header, sizeof(header), "core-count");
395 snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff);
396 format_and_print(outf, base_level + 6, header, value);
397
398 snprintf(header, sizeof(header),
399 "max-turbo-frequency(MHz)");
400 snprintf(value, sizeof(value), "%d",
401 ctdp_level->trl_sse_active_cores[j] *
402 DISP_FREQ_MULTIPLIER);
403 format_and_print(outf, base_level + 6, header, value);
404 }
405 snprintf(header, sizeof(header), "turbo-ratio-limits-avx");
406 format_and_print(outf, base_level + 4, header, NULL);
407 for (j = 0; j < 8; ++j) {
408 snprintf(header, sizeof(header), "bucket-%d", j);
409 format_and_print(outf, base_level + 5, header, NULL);
410
411 snprintf(header, sizeof(header), "core-count");
412 snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff);
413 format_and_print(outf, base_level + 6, header, value);
414
415 snprintf(header, sizeof(header),
416 "max-turbo-frequency(MHz)");
417 snprintf(value, sizeof(value), "%d",
418 ctdp_level->trl_avx_active_cores[j] *
419 DISP_FREQ_MULTIPLIER);
420 format_and_print(outf, base_level + 6, header, value);
421 }
422
423 snprintf(header, sizeof(header), "turbo-ratio-limits-avx512");
424 format_and_print(outf, base_level + 4, header, NULL);
425 for (j = 0; j < 8; ++j) {
426 snprintf(header, sizeof(header), "bucket-%d", j);
427 format_and_print(outf, base_level + 5, header, NULL);
428
429 snprintf(header, sizeof(header), "core-count");
430 snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff);
431 format_and_print(outf, base_level + 6, header, value);
432
433 snprintf(header, sizeof(header),
434 "max-turbo-frequency(MHz)");
435 snprintf(value, sizeof(value), "%d",
436 ctdp_level->trl_avx_512_active_cores[j] *
437 DISP_FREQ_MULTIPLIER);
438 format_and_print(outf, base_level + 6, header, value);
439 }
440 if (ctdp_level->pbf_support)
441 _isst_pbf_display_information(cpu, outf, i,
442 &ctdp_level->pbf_info,
443 base_level + 4);
444 if (ctdp_level->fact_support)
445 _isst_fact_display_information(cpu, outf, i, 0xff, 0xff,
446 &ctdp_level->fact_info,
447 base_level + 4);
448 }
449
450 format_and_print(outf, 1, NULL, NULL);
451 }
452
isst_ctdp_display_information_start(FILE * outf)453 void isst_ctdp_display_information_start(FILE *outf)
454 {
455 last_level = 0;
456 format_and_print(outf, 0, "start", NULL);
457 }
458
isst_ctdp_display_information_end(FILE * outf)459 void isst_ctdp_display_information_end(FILE *outf)
460 {
461 format_and_print(outf, 0, NULL, NULL);
462 }
463
isst_pbf_display_information(int cpu,FILE * outf,int level,struct isst_pbf_info * pbf_info)464 void isst_pbf_display_information(int cpu, FILE *outf, int level,
465 struct isst_pbf_info *pbf_info)
466 {
467 print_package_info(cpu, outf);
468 _isst_pbf_display_information(cpu, outf, level, pbf_info, 4);
469 format_and_print(outf, 1, NULL, NULL);
470 }
471
isst_fact_display_information(int cpu,FILE * outf,int level,int fact_bucket,int fact_avx,struct isst_fact_info * fact_info)472 void isst_fact_display_information(int cpu, FILE *outf, int level,
473 int fact_bucket, int fact_avx,
474 struct isst_fact_info *fact_info)
475 {
476 print_package_info(cpu, outf);
477 _isst_fact_display_information(cpu, outf, level, fact_bucket, fact_avx,
478 fact_info, 4);
479 format_and_print(outf, 1, NULL, NULL);
480 }
481
isst_clos_display_information(int cpu,FILE * outf,int clos,struct isst_clos_config * clos_config)482 void isst_clos_display_information(int cpu, FILE *outf, int clos,
483 struct isst_clos_config *clos_config)
484 {
485 char header[256];
486 char value[256];
487
488 snprintf(header, sizeof(header), "package-%d",
489 get_physical_package_id(cpu));
490 format_and_print(outf, 1, header, NULL);
491 snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu));
492 format_and_print(outf, 2, header, NULL);
493 snprintf(header, sizeof(header), "cpu-%d", cpu);
494 format_and_print(outf, 3, header, NULL);
495
496 snprintf(header, sizeof(header), "core-power");
497 format_and_print(outf, 4, header, NULL);
498
499 snprintf(header, sizeof(header), "clos");
500 snprintf(value, sizeof(value), "%d", clos);
501 format_and_print(outf, 5, header, value);
502
503 snprintf(header, sizeof(header), "epp");
504 snprintf(value, sizeof(value), "%d", clos_config->epp);
505 format_and_print(outf, 5, header, value);
506
507 snprintf(header, sizeof(header), "clos-proportional-priority");
508 snprintf(value, sizeof(value), "%d", clos_config->clos_prop_prio);
509 format_and_print(outf, 5, header, value);
510
511 snprintf(header, sizeof(header), "clos-min");
512 snprintf(value, sizeof(value), "%d", clos_config->clos_min);
513 format_and_print(outf, 5, header, value);
514
515 snprintf(header, sizeof(header), "clos-max");
516 snprintf(value, sizeof(value), "%d", clos_config->clos_max);
517 format_and_print(outf, 5, header, value);
518
519 snprintf(header, sizeof(header), "clos-desired");
520 snprintf(value, sizeof(value), "%d", clos_config->clos_desired);
521 format_and_print(outf, 5, header, value);
522
523 format_and_print(outf, 1, NULL, NULL);
524 }
525
isst_clos_display_clos_information(int cpu,FILE * outf,int clos_enable,int type)526 void isst_clos_display_clos_information(int cpu, FILE *outf,
527 int clos_enable, int type)
528 {
529 char header[256];
530 char value[256];
531
532 snprintf(header, sizeof(header), "package-%d",
533 get_physical_package_id(cpu));
534 format_and_print(outf, 1, header, NULL);
535 snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu));
536 format_and_print(outf, 2, header, NULL);
537 snprintf(header, sizeof(header), "cpu-%d", cpu);
538 format_and_print(outf, 3, header, NULL);
539
540 snprintf(header, sizeof(header), "core-power");
541 format_and_print(outf, 4, header, NULL);
542
543 snprintf(header, sizeof(header), "enable-status");
544 snprintf(value, sizeof(value), "%d", clos_enable);
545 format_and_print(outf, 5, header, value);
546
547 snprintf(header, sizeof(header), "priority-type");
548 snprintf(value, sizeof(value), "%d", type);
549 format_and_print(outf, 5, header, value);
550
551 format_and_print(outf, 1, NULL, NULL);
552 }
553
isst_clos_display_assoc_information(int cpu,FILE * outf,int clos)554 void isst_clos_display_assoc_information(int cpu, FILE *outf, int clos)
555 {
556 char header[256];
557 char value[256];
558
559 snprintf(header, sizeof(header), "package-%d",
560 get_physical_package_id(cpu));
561 format_and_print(outf, 1, header, NULL);
562 snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu));
563 format_and_print(outf, 2, header, NULL);
564 snprintf(header, sizeof(header), "cpu-%d", cpu);
565 format_and_print(outf, 3, header, NULL);
566
567 snprintf(header, sizeof(header), "get-assoc");
568 format_and_print(outf, 4, header, NULL);
569
570 snprintf(header, sizeof(header), "clos");
571 snprintf(value, sizeof(value), "%d", clos);
572 format_and_print(outf, 5, header, value);
573
574 format_and_print(outf, 1, NULL, NULL);
575 }
576
isst_display_result(int cpu,FILE * outf,char * feature,char * cmd,int result)577 void isst_display_result(int cpu, FILE *outf, char *feature, char *cmd,
578 int result)
579 {
580 char header[256];
581 char value[256];
582
583 snprintf(header, sizeof(header), "package-%d",
584 get_physical_package_id(cpu));
585 format_and_print(outf, 1, header, NULL);
586 snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu));
587 format_and_print(outf, 2, header, NULL);
588 snprintf(header, sizeof(header), "cpu-%d", cpu);
589 format_and_print(outf, 3, header, NULL);
590 snprintf(header, sizeof(header), "%s", feature);
591 format_and_print(outf, 4, header, NULL);
592 snprintf(header, sizeof(header), "%s", cmd);
593 if (!result)
594 snprintf(value, sizeof(value), "success");
595 else
596 snprintf(value, sizeof(value), "failed(error %d)", result);
597 format_and_print(outf, 5, header, value);
598
599 format_and_print(outf, 1, NULL, NULL);
600 }
601