]> asedeno.scripts.mit.edu Git - linux.git/blob - tools/power/x86/intel-speed-select/isst-display.c
tools/power/x86: A tool to validate Intel Speed Select commands
[linux.git] / tools / power / x86 / intel-speed-select / isst-display.c
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 100000
10
11 static void printcpumask(int str_len, char *str, int mask_size,
12                          cpu_set_t *cpu_mask)
13 {
14         int i, max_cpus = get_topo_max_cpus();
15         unsigned int *mask;
16         int size, index, curr_index;
17
18         size = max_cpus / (sizeof(unsigned int) * 8);
19         if (max_cpus % (sizeof(unsigned int) * 8))
20                 size++;
21
22         mask = calloc(size, sizeof(unsigned int));
23         if (!mask)
24                 return;
25
26         for (i = 0; i < max_cpus; ++i) {
27                 int mask_index, bit_index;
28
29                 if (!CPU_ISSET_S(i, mask_size, cpu_mask))
30                         continue;
31
32                 mask_index = i / (sizeof(unsigned int) * 8);
33                 bit_index = i % (sizeof(unsigned int) * 8);
34                 mask[mask_index] |= BIT(bit_index);
35         }
36
37         curr_index = 0;
38         for (i = size - 1; i >= 0; --i) {
39                 index = snprintf(&str[curr_index], str_len - curr_index, "%08x",
40                                  mask[i]);
41                 curr_index += index;
42                 if (i) {
43                         strncat(&str[curr_index], ",", str_len - curr_index);
44                         curr_index++;
45                 }
46         }
47
48         free(mask);
49 }
50
51 static void format_and_print_txt(FILE *outf, int level, char *header,
52                                  char *value)
53 {
54         char *spaces = "  ";
55         static char delimiters[256];
56         int i, j = 0;
57
58         if (!level)
59                 return;
60
61         if (level == 1) {
62                 strcpy(delimiters, " ");
63         } else {
64                 for (i = 0; i < level - 1; ++i)
65                         j += snprintf(&delimiters[j], sizeof(delimiters) - j,
66                                       "%s", spaces);
67         }
68
69         if (header && value) {
70                 fprintf(outf, "%s", delimiters);
71                 fprintf(outf, "%s:%s\n", header, value);
72         } else if (header) {
73                 fprintf(outf, "%s", delimiters);
74                 fprintf(outf, "%s\n", header);
75         }
76 }
77
78 static int last_level;
79 static void format_and_print(FILE *outf, int level, char *header, char *value)
80 {
81         char *spaces = "  ";
82         static char delimiters[256];
83         int i;
84
85         if (!out_format_is_json()) {
86                 format_and_print_txt(outf, level, header, value);
87                 return;
88         }
89
90         if (level == 0) {
91                 if (header)
92                         fprintf(outf, "{");
93                 else
94                         fprintf(outf, "\n}\n");
95
96         } else {
97                 int j = 0;
98
99                 for (i = 0; i < level; ++i)
100                         j += snprintf(&delimiters[j], sizeof(delimiters) - j,
101                                       "%s", spaces);
102
103                 if (last_level == level)
104                         fprintf(outf, ",\n");
105
106                 if (value) {
107                         if (last_level != level)
108                                 fprintf(outf, "\n");
109
110                         fprintf(outf, "%s\"%s\": ", delimiters, header);
111                         fprintf(outf, "\"%s\"", value);
112                 } else {
113                         for (i = last_level - 1; i >= level; --i) {
114                                 int k = 0;
115
116                                 for (j = i; j > 0; --j)
117                                         k += snprintf(&delimiters[k],
118                                                       sizeof(delimiters) - k,
119                                                       "%s", spaces);
120                                 if (i == level && header)
121                                         fprintf(outf, "\n%s},", delimiters);
122                                 else
123                                         fprintf(outf, "\n%s}", delimiters);
124                         }
125                         if (abs(last_level - level) < 3)
126                                 fprintf(outf, "\n");
127                         if (header)
128                                 fprintf(outf, "%s\"%s\": {", delimiters,
129                                         header);
130                 }
131         }
132
133         last_level = level;
134 }
135
136 static void print_packag_info(int cpu, FILE *outf)
137 {
138         char header[256];
139
140         snprintf(header, sizeof(header), "package-%d",
141                  get_physical_package_id(cpu));
142         format_and_print(outf, 1, header, NULL);
143         snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu));
144         format_and_print(outf, 2, header, NULL);
145         snprintf(header, sizeof(header), "cpu-%d", cpu);
146         format_and_print(outf, 3, header, NULL);
147 }
148
149 static void _isst_pbf_display_information(int cpu, FILE *outf, int level,
150                                           struct isst_pbf_info *pbf_info,
151                                           int disp_level)
152 {
153         char header[256];
154         char value[256];
155
156         snprintf(header, sizeof(header), "speed-select-base-freq");
157         format_and_print(outf, disp_level, header, NULL);
158
159         snprintf(header, sizeof(header), "high-priority-base-frequency(KHz)");
160         snprintf(value, sizeof(value), "%d",
161                  pbf_info->p1_high * DISP_FREQ_MULTIPLIER);
162         format_and_print(outf, disp_level + 1, header, value);
163
164         snprintf(header, sizeof(header), "high-priority-cpu-mask");
165         printcpumask(sizeof(value), value, pbf_info->core_cpumask_size,
166                      pbf_info->core_cpumask);
167         format_and_print(outf, disp_level + 1, header, value);
168
169         snprintf(header, sizeof(header), "low-priority-base-frequency(KHz)");
170         snprintf(value, sizeof(value), "%d",
171                  pbf_info->p1_low * DISP_FREQ_MULTIPLIER);
172         format_and_print(outf, disp_level + 1, header, value);
173
174         snprintf(header, sizeof(header), "tjunction-temperature(C)");
175         snprintf(value, sizeof(value), "%d", pbf_info->t_prochot);
176         format_and_print(outf, disp_level + 1, header, value);
177
178         snprintf(header, sizeof(header), "thermal-design-power(W)");
179         snprintf(value, sizeof(value), "%d", pbf_info->tdp);
180         format_and_print(outf, disp_level + 1, header, value);
181 }
182
183 static void _isst_fact_display_information(int cpu, FILE *outf, int level,
184                                            int fact_bucket, int fact_avx,
185                                            struct isst_fact_info *fact_info,
186                                            int base_level)
187 {
188         struct isst_fact_bucket_info *bucket_info = fact_info->bucket_info;
189         char header[256];
190         char value[256];
191         int j;
192
193         snprintf(header, sizeof(header), "speed-select-turbo-freq");
194         format_and_print(outf, base_level, header, NULL);
195         for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
196                 if (fact_bucket != 0xff && fact_bucket != j)
197                         continue;
198
199                 if (!bucket_info[j].high_priority_cores_count)
200                         break;
201
202                 snprintf(header, sizeof(header), "bucket-%d", j);
203                 format_and_print(outf, base_level + 1, header, NULL);
204
205                 snprintf(header, sizeof(header), "high-priority-cores-count");
206                 snprintf(value, sizeof(value), "%d",
207                          bucket_info[j].high_priority_cores_count);
208                 format_and_print(outf, base_level + 2, header, value);
209
210                 if (fact_avx & 0x01) {
211                         snprintf(header, sizeof(header),
212                                  "high-priority-max-frequency(KHz)");
213                         snprintf(value, sizeof(value), "%d",
214                                  bucket_info[j].sse_trl * DISP_FREQ_MULTIPLIER);
215                         format_and_print(outf, base_level + 2, header, value);
216                 }
217
218                 if (fact_avx & 0x02) {
219                         snprintf(header, sizeof(header),
220                                  "high-priority-max-avx2-frequency(KHz)");
221                         snprintf(value, sizeof(value), "%d",
222                                  bucket_info[j].avx_trl * DISP_FREQ_MULTIPLIER);
223                         format_and_print(outf, base_level + 2, header, value);
224                 }
225
226                 if (fact_avx & 0x04) {
227                         snprintf(header, sizeof(header),
228                                  "high-priority-max-avx512-frequency(KHz)");
229                         snprintf(value, sizeof(value), "%d",
230                                  bucket_info[j].avx512_trl *
231                                          DISP_FREQ_MULTIPLIER);
232                         format_and_print(outf, base_level + 2, header, value);
233                 }
234         }
235         snprintf(header, sizeof(header),
236                  "speed-select-turbo-freq-clip-frequencies");
237         format_and_print(outf, base_level + 1, header, NULL);
238         snprintf(header, sizeof(header), "low-priority-max-frequency(KHz)");
239         snprintf(value, sizeof(value), "%d",
240                  fact_info->lp_clipping_ratio_license_sse *
241                          DISP_FREQ_MULTIPLIER);
242         format_and_print(outf, base_level + 2, header, value);
243         snprintf(header, sizeof(header),
244                  "low-priority-max-avx2-frequency(KHz)");
245         snprintf(value, sizeof(value), "%d",
246                  fact_info->lp_clipping_ratio_license_avx2 *
247                          DISP_FREQ_MULTIPLIER);
248         format_and_print(outf, base_level + 2, header, value);
249         snprintf(header, sizeof(header),
250                  "low-priority-max-avx512-frequency(KHz)");
251         snprintf(value, sizeof(value), "%d",
252                  fact_info->lp_clipping_ratio_license_avx512 *
253                          DISP_FREQ_MULTIPLIER);
254         format_and_print(outf, base_level + 2, header, value);
255 }
256
257 void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
258                                    struct isst_pkg_ctdp *pkg_dev)
259 {
260         char header[256];
261         char value[256];
262         int i, base_level = 1;
263
264         print_packag_info(cpu, outf);
265
266         for (i = 0; i <= pkg_dev->levels; ++i) {
267                 struct isst_pkg_ctdp_level_info *ctdp_level;
268                 int j;
269
270                 ctdp_level = &pkg_dev->ctdp_level[i];
271                 if (!ctdp_level->processed)
272                         continue;
273
274                 snprintf(header, sizeof(header), "perf-profile-level-%d",
275                          ctdp_level->level);
276                 format_and_print(outf, base_level + 3, header, NULL);
277
278                 snprintf(header, sizeof(header), "cpu-count");
279                 j = get_cpu_count(get_physical_die_id(cpu),
280                                   get_physical_die_id(cpu));
281                 snprintf(value, sizeof(value), "%d", j);
282                 format_and_print(outf, base_level + 4, header, value);
283
284                 snprintf(header, sizeof(header), "enable-cpu-mask");
285                 printcpumask(sizeof(value), value,
286                              ctdp_level->core_cpumask_size,
287                              ctdp_level->core_cpumask);
288                 format_and_print(outf, base_level + 4, header, value);
289
290                 snprintf(header, sizeof(header), "thermal-design-power-ratio");
291                 snprintf(value, sizeof(value), "%d", ctdp_level->tdp_ratio);
292                 format_and_print(outf, base_level + 4, header, value);
293
294                 snprintf(header, sizeof(header), "base-frequency(KHz)");
295                 snprintf(value, sizeof(value), "%d",
296                          ctdp_level->tdp_ratio * DISP_FREQ_MULTIPLIER);
297                 format_and_print(outf, base_level + 4, header, value);
298
299                 snprintf(header, sizeof(header),
300                          "speed-select-turbo-freq-support");
301                 snprintf(value, sizeof(value), "%d", ctdp_level->fact_support);
302                 format_and_print(outf, base_level + 4, header, value);
303
304                 snprintf(header, sizeof(header),
305                          "speed-select-base-freq-support");
306                 snprintf(value, sizeof(value), "%d", ctdp_level->pbf_support);
307                 format_and_print(outf, base_level + 4, header, value);
308
309                 snprintf(header, sizeof(header),
310                          "speed-select-base-freq-enabled");
311                 snprintf(value, sizeof(value), "%d", ctdp_level->pbf_enabled);
312                 format_and_print(outf, base_level + 4, header, value);
313
314                 snprintf(header, sizeof(header),
315                          "speed-select-turbo-freq-enabled");
316                 snprintf(value, sizeof(value), "%d", ctdp_level->fact_enabled);
317                 format_and_print(outf, base_level + 4, header, value);
318
319                 snprintf(header, sizeof(header), "thermal-design-power(W)");
320                 snprintf(value, sizeof(value), "%d", ctdp_level->pkg_tdp);
321                 format_and_print(outf, base_level + 4, header, value);
322
323                 snprintf(header, sizeof(header), "tjunction-max(C)");
324                 snprintf(value, sizeof(value), "%d", ctdp_level->t_proc_hot);
325                 format_and_print(outf, base_level + 4, header, value);
326
327                 snprintf(header, sizeof(header), "turbo-ratio-limits-sse");
328                 format_and_print(outf, base_level + 4, header, NULL);
329                 for (j = 0; j < 8; ++j) {
330                         snprintf(header, sizeof(header), "bucket-%d", j);
331                         format_and_print(outf, base_level + 5, header, NULL);
332
333                         snprintf(header, sizeof(header), "core-count");
334                         snprintf(value, sizeof(value), "%d", j);
335                         format_and_print(outf, base_level + 6, header, value);
336
337                         snprintf(header, sizeof(header), "turbo-ratio");
338                         snprintf(value, sizeof(value), "%d",
339                                  ctdp_level->trl_sse_active_cores[j]);
340                         format_and_print(outf, base_level + 6, header, value);
341                 }
342                 snprintf(header, sizeof(header), "turbo-ratio-limits-avx");
343                 format_and_print(outf, base_level + 4, header, NULL);
344                 for (j = 0; j < 8; ++j) {
345                         snprintf(header, sizeof(header), "bucket-%d", j);
346                         format_and_print(outf, base_level + 5, header, NULL);
347
348                         snprintf(header, sizeof(header), "core-count");
349                         snprintf(value, sizeof(value), "%d", j);
350                         format_and_print(outf, base_level + 6, header, value);
351
352                         snprintf(header, sizeof(header), "turbo-ratio");
353                         snprintf(value, sizeof(value), "%d",
354                                  ctdp_level->trl_avx_active_cores[j]);
355                         format_and_print(outf, base_level + 6, header, value);
356                 }
357
358                 snprintf(header, sizeof(header), "turbo-ratio-limits-avx512");
359                 format_and_print(outf, base_level + 4, header, NULL);
360                 for (j = 0; j < 8; ++j) {
361                         snprintf(header, sizeof(header), "bucket-%d", j);
362                         format_and_print(outf, base_level + 5, header, NULL);
363
364                         snprintf(header, sizeof(header), "core-count");
365                         snprintf(value, sizeof(value), "%d", j);
366                         format_and_print(outf, base_level + 6, header, value);
367
368                         snprintf(header, sizeof(header), "turbo-ratio");
369                         snprintf(value, sizeof(value), "%d",
370                                  ctdp_level->trl_avx_512_active_cores[j]);
371                         format_and_print(outf, base_level + 6, header, value);
372                 }
373                 if (ctdp_level->pbf_support)
374                         _isst_pbf_display_information(cpu, outf, i,
375                                                       &ctdp_level->pbf_info,
376                                                       base_level + 4);
377                 if (ctdp_level->fact_support)
378                         _isst_fact_display_information(cpu, outf, i, 0xff, 0xff,
379                                                        &ctdp_level->fact_info,
380                                                        base_level + 4);
381         }
382
383         format_and_print(outf, 1, NULL, NULL);
384 }
385
386 void isst_ctdp_display_information_start(FILE *outf)
387 {
388         last_level = 0;
389         format_and_print(outf, 0, "start", NULL);
390 }
391
392 void isst_ctdp_display_information_end(FILE *outf)
393 {
394         format_and_print(outf, 0, NULL, NULL);
395 }
396
397 void isst_pbf_display_information(int cpu, FILE *outf, int level,
398                                   struct isst_pbf_info *pbf_info)
399 {
400         print_packag_info(cpu, outf);
401         _isst_pbf_display_information(cpu, outf, level, pbf_info, 4);
402         format_and_print(outf, 1, NULL, NULL);
403 }
404
405 void isst_fact_display_information(int cpu, FILE *outf, int level,
406                                    int fact_bucket, int fact_avx,
407                                    struct isst_fact_info *fact_info)
408 {
409         print_packag_info(cpu, outf);
410         _isst_fact_display_information(cpu, outf, level, fact_bucket, fact_avx,
411                                        fact_info, 4);
412         format_and_print(outf, 1, NULL, NULL);
413 }
414
415 void isst_clos_display_information(int cpu, FILE *outf, int clos,
416                                    struct isst_clos_config *clos_config)
417 {
418         char header[256];
419         char value[256];
420
421         snprintf(header, sizeof(header), "package-%d",
422                  get_physical_package_id(cpu));
423         format_and_print(outf, 1, header, NULL);
424         snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu));
425         format_and_print(outf, 2, header, NULL);
426         snprintf(header, sizeof(header), "cpu-%d", cpu);
427         format_and_print(outf, 3, header, NULL);
428
429         snprintf(header, sizeof(header), "core-power");
430         format_and_print(outf, 4, header, NULL);
431
432         snprintf(header, sizeof(header), "clos");
433         snprintf(value, sizeof(value), "%d", clos);
434         format_and_print(outf, 5, header, value);
435
436         snprintf(header, sizeof(header), "epp");
437         snprintf(value, sizeof(value), "%d", clos_config->epp);
438         format_and_print(outf, 5, header, value);
439
440         snprintf(header, sizeof(header), "clos-proportional-priority");
441         snprintf(value, sizeof(value), "%d", clos_config->clos_prop_prio);
442         format_and_print(outf, 5, header, value);
443
444         snprintf(header, sizeof(header), "clos-min");
445         snprintf(value, sizeof(value), "%d", clos_config->clos_min);
446         format_and_print(outf, 5, header, value);
447
448         snprintf(header, sizeof(header), "clos-max");
449         snprintf(value, sizeof(value), "%d", clos_config->clos_max);
450         format_and_print(outf, 5, header, value);
451
452         snprintf(header, sizeof(header), "clos-desired");
453         snprintf(value, sizeof(value), "%d", clos_config->clos_desired);
454         format_and_print(outf, 5, header, value);
455
456         format_and_print(outf, 1, NULL, NULL);
457 }
458
459 void isst_display_result(int cpu, FILE *outf, char *feature, char *cmd,
460                          int result)
461 {
462         char header[256];
463         char value[256];
464
465         snprintf(header, sizeof(header), "package-%d",
466                  get_physical_package_id(cpu));
467         format_and_print(outf, 1, header, NULL);
468         snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu));
469         format_and_print(outf, 2, header, NULL);
470         snprintf(header, sizeof(header), "cpu-%d", cpu);
471         format_and_print(outf, 3, header, NULL);
472         snprintf(header, sizeof(header), "%s", feature);
473         format_and_print(outf, 4, header, NULL);
474         snprintf(header, sizeof(header), "%s", cmd);
475         snprintf(value, sizeof(value), "%d", result);
476         format_and_print(outf, 5, header, value);
477
478         format_and_print(outf, 1, NULL, NULL);
479 }