linux/tools/power/x86/intel-speed-select/isst-display.c
<<
>>
Prefs
   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
  11static 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
  51static 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
  78static int last_level;
  79static 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
 136static 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
 149static 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
 183static 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
 257void 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
 386void isst_ctdp_display_information_start(FILE *outf)
 387{
 388        last_level = 0;
 389        format_and_print(outf, 0, "start", NULL);
 390}
 391
 392void isst_ctdp_display_information_end(FILE *outf)
 393{
 394        format_and_print(outf, 0, NULL, NULL);
 395}
 396
 397void 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
 405void 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
 415void 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
 459void 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}
 480