root/tools/power/x86/intel-speed-select/isst-config.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. debug_printf
  2. update_cpu_model
  3. fopen_or_exit
  4. parse_int_file
  5. cpufreq_sysfs_present
  6. out_format_is_json
  7. get_physical_package_id
  8. get_physical_core_id
  9. get_physical_die_id
  10. get_topo_max_cpus
  11. set_cpu_online_offline
  12. for_each_online_package_in_set
  13. for_each_online_target_cpu_in_set
  14. set_max_cpu_num
  15. alloc_cpu_set
  16. free_cpu_set
  17. set_cpu_present_cpu_mask
  18. get_cpu_count
  19. set_cpu_target_cpu_mask
  20. create_cpu_map
  21. find_logical_cpu
  22. set_cpu_mask_from_punit_coremask
  23. find_phy_core_num
  24. isst_send_mmio_command
  25. isst_send_mbox_command
  26. isst_send_msr_command
  27. isst_fill_platform_info
  28. isst_print_platform_information
  29. exec_on_get_ctdp_cpu
  30. dump_isst_config_for_cpu
  31. dump_isst_config
  32. set_tdp_level_for_cpu
  33. set_tdp_level
  34. dump_pbf_config_for_cpu
  35. dump_pbf_config
  36. set_pbf_for_cpu
  37. set_pbf_enable
  38. set_pbf_disable
  39. dump_fact_config_for_cpu
  40. dump_fact_config
  41. set_fact_for_cpu
  42. set_fact_enable
  43. set_fact_disable
  44. enable_clos_qos_config
  45. set_clos_enable
  46. set_clos_disable
  47. dump_clos_config_for_cpu
  48. dump_clos_config
  49. get_clos_info_for_cpu
  50. dump_clos_info
  51. set_clos_config_for_cpu
  52. set_clos_config
  53. set_clos_assoc_for_cpu
  54. set_clos_assoc
  55. get_clos_assoc_for_cpu
  56. get_clos_assoc
  57. parse_cpu_command
  58. parse_cmd_args
  59. isst_help
  60. pbf_help
  61. fact_help
  62. core_power_help
  63. process_command
  64. usage
  65. print_version
  66. cmdline
  67. main

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Intel Speed Select -- Enumerate and control features
   4  * Copyright (c) 2019 Intel Corporation.
   5  */
   6 
   7 #include <linux/isst_if.h>
   8 
   9 #include "isst.h"
  10 
  11 struct process_cmd_struct {
  12         char *feature;
  13         char *command;
  14         void (*process_fn)(void);
  15 };
  16 
  17 static const char *version_str = "v1.0";
  18 static const int supported_api_ver = 1;
  19 static struct isst_if_platform_info isst_platform_info;
  20 static char *progname;
  21 static int debug_flag;
  22 static FILE *outf;
  23 
  24 static int cpu_model;
  25 
  26 #define MAX_CPUS_IN_ONE_REQ 64
  27 static short max_target_cpus;
  28 static unsigned short target_cpus[MAX_CPUS_IN_ONE_REQ];
  29 
  30 static int topo_max_cpus;
  31 static size_t present_cpumask_size;
  32 static cpu_set_t *present_cpumask;
  33 static size_t target_cpumask_size;
  34 static cpu_set_t *target_cpumask;
  35 static int tdp_level = 0xFF;
  36 static int fact_bucket = 0xFF;
  37 static int fact_avx = 0xFF;
  38 static unsigned long long fact_trl;
  39 static int out_format_json;
  40 static int cmd_help;
  41 static int force_online_offline;
  42 
  43 /* clos related */
  44 static int current_clos = -1;
  45 static int clos_epp = -1;
  46 static int clos_prop_prio = -1;
  47 static int clos_min = -1;
  48 static int clos_max = -1;
  49 static int clos_desired = -1;
  50 static int clos_priority_type;
  51 
  52 struct _cpu_map {
  53         unsigned short core_id;
  54         unsigned short pkg_id;
  55         unsigned short die_id;
  56         unsigned short punit_cpu;
  57         unsigned short punit_cpu_core;
  58 };
  59 struct _cpu_map *cpu_map;
  60 
  61 void debug_printf(const char *format, ...)
  62 {
  63         va_list args;
  64 
  65         va_start(args, format);
  66 
  67         if (debug_flag)
  68                 vprintf(format, args);
  69 
  70         va_end(args);
  71 }
  72 
  73 static void update_cpu_model(void)
  74 {
  75         unsigned int ebx, ecx, edx;
  76         unsigned int fms, family;
  77 
  78         __cpuid(1, fms, ebx, ecx, edx);
  79         family = (fms >> 8) & 0xf;
  80         cpu_model = (fms >> 4) & 0xf;
  81         if (family == 6 || family == 0xf)
  82                 cpu_model += ((fms >> 16) & 0xf) << 4;
  83 }
  84 
  85 /* Open a file, and exit on failure */
  86 static FILE *fopen_or_exit(const char *path, const char *mode)
  87 {
  88         FILE *filep = fopen(path, mode);
  89 
  90         if (!filep)
  91                 err(1, "%s: open failed", path);
  92 
  93         return filep;
  94 }
  95 
  96 /* Parse a file containing a single int */
  97 static int parse_int_file(int fatal, const char *fmt, ...)
  98 {
  99         va_list args;
 100         char path[PATH_MAX];
 101         FILE *filep;
 102         int value;
 103 
 104         va_start(args, fmt);
 105         vsnprintf(path, sizeof(path), fmt, args);
 106         va_end(args);
 107         if (fatal) {
 108                 filep = fopen_or_exit(path, "r");
 109         } else {
 110                 filep = fopen(path, "r");
 111                 if (!filep)
 112                         return -1;
 113         }
 114         if (fscanf(filep, "%d", &value) != 1)
 115                 err(1, "%s: failed to parse number from file", path);
 116         fclose(filep);
 117 
 118         return value;
 119 }
 120 
 121 int cpufreq_sysfs_present(void)
 122 {
 123         DIR *dir;
 124 
 125         dir = opendir("/sys/devices/system/cpu/cpu0/cpufreq");
 126         if (dir) {
 127                 closedir(dir);
 128                 return 1;
 129         }
 130 
 131         return 0;
 132 }
 133 
 134 int out_format_is_json(void)
 135 {
 136         return out_format_json;
 137 }
 138 
 139 int get_physical_package_id(int cpu)
 140 {
 141         return parse_int_file(
 142                 0, "/sys/devices/system/cpu/cpu%d/topology/physical_package_id",
 143                 cpu);
 144 }
 145 
 146 int get_physical_core_id(int cpu)
 147 {
 148         return parse_int_file(
 149                 0, "/sys/devices/system/cpu/cpu%d/topology/core_id", cpu);
 150 }
 151 
 152 int get_physical_die_id(int cpu)
 153 {
 154         int ret;
 155 
 156         ret = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/topology/die_id",
 157                              cpu);
 158         if (ret < 0)
 159                 ret = 0;
 160 
 161         return ret;
 162 }
 163 
 164 int get_topo_max_cpus(void)
 165 {
 166         return topo_max_cpus;
 167 }
 168 
 169 static void set_cpu_online_offline(int cpu, int state)
 170 {
 171         char buffer[128];
 172         int fd, ret;
 173 
 174         snprintf(buffer, sizeof(buffer),
 175                  "/sys/devices/system/cpu/cpu%d/online", cpu);
 176 
 177         fd = open(buffer, O_WRONLY);
 178         if (fd < 0)
 179                 err(-1, "%s open failed", buffer);
 180 
 181         if (state)
 182                 ret = write(fd, "1\n", 2);
 183         else
 184                 ret = write(fd, "0\n", 2);
 185 
 186         if (ret == -1)
 187                 perror("Online/Offline: Operation failed\n");
 188 
 189         close(fd);
 190 }
 191 
 192 #define MAX_PACKAGE_COUNT 8
 193 #define MAX_DIE_PER_PACKAGE 2
 194 static void for_each_online_package_in_set(void (*callback)(int, void *, void *,
 195                                                             void *, void *),
 196                                            void *arg1, void *arg2, void *arg3,
 197                                            void *arg4)
 198 {
 199         int max_packages[MAX_PACKAGE_COUNT * MAX_PACKAGE_COUNT];
 200         int pkg_index = 0, i;
 201 
 202         memset(max_packages, 0xff, sizeof(max_packages));
 203         for (i = 0; i < topo_max_cpus; ++i) {
 204                 int j, online, pkg_id, die_id = 0, skip = 0;
 205 
 206                 if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
 207                         continue;
 208                 if (i)
 209                         online = parse_int_file(
 210                                 1, "/sys/devices/system/cpu/cpu%d/online", i);
 211                 else
 212                         online =
 213                                 1; /* online entry for CPU 0 needs some special configs */
 214 
 215                 die_id = get_physical_die_id(i);
 216                 if (die_id < 0)
 217                         die_id = 0;
 218                 pkg_id = get_physical_package_id(i);
 219                 /* Create an unique id for package, die combination to store */
 220                 pkg_id = (MAX_PACKAGE_COUNT * pkg_id + die_id);
 221 
 222                 for (j = 0; j < pkg_index; ++j) {
 223                         if (max_packages[j] == pkg_id) {
 224                                 skip = 1;
 225                                 break;
 226                         }
 227                 }
 228 
 229                 if (!skip && online && callback) {
 230                         callback(i, arg1, arg2, arg3, arg4);
 231                         max_packages[pkg_index++] = pkg_id;
 232                 }
 233         }
 234 }
 235 
 236 static void for_each_online_target_cpu_in_set(
 237         void (*callback)(int, void *, void *, void *, void *), void *arg1,
 238         void *arg2, void *arg3, void *arg4)
 239 {
 240         int i;
 241 
 242         for (i = 0; i < topo_max_cpus; ++i) {
 243                 int online;
 244 
 245                 if (!CPU_ISSET_S(i, target_cpumask_size, target_cpumask))
 246                         continue;
 247                 if (i)
 248                         online = parse_int_file(
 249                                 1, "/sys/devices/system/cpu/cpu%d/online", i);
 250                 else
 251                         online =
 252                                 1; /* online entry for CPU 0 needs some special configs */
 253 
 254                 if (online && callback)
 255                         callback(i, arg1, arg2, arg3, arg4);
 256         }
 257 }
 258 
 259 #define BITMASK_SIZE 32
 260 static void set_max_cpu_num(void)
 261 {
 262         FILE *filep;
 263         unsigned long dummy;
 264 
 265         topo_max_cpus = 0;
 266         filep = fopen_or_exit(
 267                 "/sys/devices/system/cpu/cpu0/topology/thread_siblings", "r");
 268         while (fscanf(filep, "%lx,", &dummy) == 1)
 269                 topo_max_cpus += BITMASK_SIZE;
 270         fclose(filep);
 271         topo_max_cpus--; /* 0 based */
 272 
 273         debug_printf("max cpus %d\n", topo_max_cpus);
 274 }
 275 
 276 size_t alloc_cpu_set(cpu_set_t **cpu_set)
 277 {
 278         cpu_set_t *_cpu_set;
 279         size_t size;
 280 
 281         _cpu_set = CPU_ALLOC((topo_max_cpus + 1));
 282         if (_cpu_set == NULL)
 283                 err(3, "CPU_ALLOC");
 284         size = CPU_ALLOC_SIZE((topo_max_cpus + 1));
 285         CPU_ZERO_S(size, _cpu_set);
 286 
 287         *cpu_set = _cpu_set;
 288         return size;
 289 }
 290 
 291 void free_cpu_set(cpu_set_t *cpu_set)
 292 {
 293         CPU_FREE(cpu_set);
 294 }
 295 
 296 static int cpu_cnt[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE];
 297 static void set_cpu_present_cpu_mask(void)
 298 {
 299         size_t size;
 300         DIR *dir;
 301         int i;
 302 
 303         size = alloc_cpu_set(&present_cpumask);
 304         present_cpumask_size = size;
 305         for (i = 0; i < topo_max_cpus; ++i) {
 306                 char buffer[256];
 307 
 308                 snprintf(buffer, sizeof(buffer),
 309                          "/sys/devices/system/cpu/cpu%d", i);
 310                 dir = opendir(buffer);
 311                 if (dir) {
 312                         int pkg_id, die_id;
 313 
 314                         CPU_SET_S(i, size, present_cpumask);
 315                         die_id = get_physical_die_id(i);
 316                         if (die_id < 0)
 317                                 die_id = 0;
 318 
 319                         pkg_id = get_physical_package_id(i);
 320                         if (pkg_id < MAX_PACKAGE_COUNT &&
 321                             die_id < MAX_DIE_PER_PACKAGE)
 322                                 cpu_cnt[pkg_id][die_id]++;
 323                 }
 324                 closedir(dir);
 325         }
 326 }
 327 
 328 int get_cpu_count(int pkg_id, int die_id)
 329 {
 330         if (pkg_id < MAX_PACKAGE_COUNT && die_id < MAX_DIE_PER_PACKAGE)
 331                 return cpu_cnt[pkg_id][die_id];
 332 
 333         return 0;
 334 }
 335 
 336 static void set_cpu_target_cpu_mask(void)
 337 {
 338         size_t size;
 339         int i;
 340 
 341         size = alloc_cpu_set(&target_cpumask);
 342         target_cpumask_size = size;
 343         for (i = 0; i < max_target_cpus; ++i) {
 344                 if (!CPU_ISSET_S(target_cpus[i], present_cpumask_size,
 345                                  present_cpumask))
 346                         continue;
 347 
 348                 CPU_SET_S(target_cpus[i], size, target_cpumask);
 349         }
 350 }
 351 
 352 static void create_cpu_map(void)
 353 {
 354         const char *pathname = "/dev/isst_interface";
 355         int i, fd = 0;
 356         struct isst_if_cpu_maps map;
 357 
 358         cpu_map = malloc(sizeof(*cpu_map) * topo_max_cpus);
 359         if (!cpu_map)
 360                 err(3, "cpumap");
 361 
 362         fd = open(pathname, O_RDWR);
 363         if (fd < 0)
 364                 err(-1, "%s open failed", pathname);
 365 
 366         for (i = 0; i < topo_max_cpus; ++i) {
 367                 if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
 368                         continue;
 369 
 370                 map.cmd_count = 1;
 371                 map.cpu_map[0].logical_cpu = i;
 372 
 373                 debug_printf(" map logical_cpu:%d\n",
 374                              map.cpu_map[0].logical_cpu);
 375                 if (ioctl(fd, ISST_IF_GET_PHY_ID, &map) == -1) {
 376                         perror("ISST_IF_GET_PHY_ID");
 377                         fprintf(outf, "Error: map logical_cpu:%d\n",
 378                                 map.cpu_map[0].logical_cpu);
 379                         continue;
 380                 }
 381                 cpu_map[i].core_id = get_physical_core_id(i);
 382                 cpu_map[i].pkg_id = get_physical_package_id(i);
 383                 cpu_map[i].die_id = get_physical_die_id(i);
 384                 cpu_map[i].punit_cpu = map.cpu_map[0].physical_cpu;
 385                 cpu_map[i].punit_cpu_core = (map.cpu_map[0].physical_cpu >>
 386                                              1); // shift to get core id
 387 
 388                 debug_printf(
 389                         "map logical_cpu:%d core: %d die:%d pkg:%d punit_cpu:%d punit_core:%d\n",
 390                         i, cpu_map[i].core_id, cpu_map[i].die_id,
 391                         cpu_map[i].pkg_id, cpu_map[i].punit_cpu,
 392                         cpu_map[i].punit_cpu_core);
 393         }
 394 
 395         if (fd)
 396                 close(fd);
 397 }
 398 
 399 int find_logical_cpu(int pkg_id, int die_id, int punit_core_id)
 400 {
 401         int i;
 402 
 403         for (i = 0; i < topo_max_cpus; ++i) {
 404                 if (cpu_map[i].pkg_id == pkg_id &&
 405                     cpu_map[i].die_id == die_id &&
 406                     cpu_map[i].punit_cpu_core == punit_core_id)
 407                         return i;
 408         }
 409 
 410         return -EINVAL;
 411 }
 412 
 413 void set_cpu_mask_from_punit_coremask(int cpu, unsigned long long core_mask,
 414                                       size_t core_cpumask_size,
 415                                       cpu_set_t *core_cpumask, int *cpu_cnt)
 416 {
 417         int i, cnt = 0;
 418         int die_id, pkg_id;
 419 
 420         *cpu_cnt = 0;
 421         die_id = get_physical_die_id(cpu);
 422         pkg_id = get_physical_package_id(cpu);
 423 
 424         for (i = 0; i < 64; ++i) {
 425                 if (core_mask & BIT(i)) {
 426                         int j;
 427 
 428                         for (j = 0; j < topo_max_cpus; ++j) {
 429                                 if (!CPU_ISSET_S(j, present_cpumask_size, present_cpumask))
 430                                         continue;
 431 
 432                                 if (cpu_map[j].pkg_id == pkg_id &&
 433                                     cpu_map[j].die_id == die_id &&
 434                                     cpu_map[j].punit_cpu_core == i) {
 435                                         CPU_SET_S(j, core_cpumask_size,
 436                                                   core_cpumask);
 437                                         ++cnt;
 438                                 }
 439                         }
 440                 }
 441         }
 442 
 443         *cpu_cnt = cnt;
 444 }
 445 
 446 int find_phy_core_num(int logical_cpu)
 447 {
 448         if (logical_cpu < topo_max_cpus)
 449                 return cpu_map[logical_cpu].punit_cpu_core;
 450 
 451         return -EINVAL;
 452 }
 453 
 454 static int isst_send_mmio_command(unsigned int cpu, unsigned int reg, int write,
 455                                   unsigned int *value)
 456 {
 457         struct isst_if_io_regs io_regs;
 458         const char *pathname = "/dev/isst_interface";
 459         int cmd;
 460         int fd;
 461 
 462         debug_printf("mmio_cmd cpu:%d reg:%d write:%d\n", cpu, reg, write);
 463 
 464         fd = open(pathname, O_RDWR);
 465         if (fd < 0)
 466                 err(-1, "%s open failed", pathname);
 467 
 468         io_regs.req_count = 1;
 469         io_regs.io_reg[0].logical_cpu = cpu;
 470         io_regs.io_reg[0].reg = reg;
 471         cmd = ISST_IF_IO_CMD;
 472         if (write) {
 473                 io_regs.io_reg[0].read_write = 1;
 474                 io_regs.io_reg[0].value = *value;
 475         } else {
 476                 io_regs.io_reg[0].read_write = 0;
 477         }
 478 
 479         if (ioctl(fd, cmd, &io_regs) == -1) {
 480                 perror("ISST_IF_IO_CMD");
 481                 fprintf(outf, "Error: mmio_cmd cpu:%d reg:%x read_write:%x\n",
 482                         cpu, reg, write);
 483         } else {
 484                 if (!write)
 485                         *value = io_regs.io_reg[0].value;
 486 
 487                 debug_printf(
 488                         "mmio_cmd response: cpu:%d reg:%x rd_write:%x resp:%x\n",
 489                         cpu, reg, write, *value);
 490         }
 491 
 492         close(fd);
 493 
 494         return 0;
 495 }
 496 
 497 int isst_send_mbox_command(unsigned int cpu, unsigned char command,
 498                            unsigned char sub_command, unsigned int parameter,
 499                            unsigned int req_data, unsigned int *resp)
 500 {
 501         const char *pathname = "/dev/isst_interface";
 502         int fd;
 503         struct isst_if_mbox_cmds mbox_cmds = { 0 };
 504 
 505         debug_printf(
 506                 "mbox_send: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n",
 507                 cpu, command, sub_command, parameter, req_data);
 508 
 509         if (isst_platform_info.mmio_supported && command == CONFIG_CLOS) {
 510                 unsigned int value;
 511                 int write = 0;
 512                 int clos_id, core_id, ret = 0;
 513 
 514                 debug_printf("CPU %d\n", cpu);
 515 
 516                 if (parameter & BIT(MBOX_CMD_WRITE_BIT)) {
 517                         value = req_data;
 518                         write = 1;
 519                 }
 520 
 521                 switch (sub_command) {
 522                 case CLOS_PQR_ASSOC:
 523                         core_id = parameter & 0xff;
 524                         ret = isst_send_mmio_command(
 525                                 cpu, PQR_ASSOC_OFFSET + core_id * 4, write,
 526                                 &value);
 527                         if (!ret && !write)
 528                                 *resp = value;
 529                         break;
 530                 case CLOS_PM_CLOS:
 531                         clos_id = parameter & 0x03;
 532                         ret = isst_send_mmio_command(
 533                                 cpu, PM_CLOS_OFFSET + clos_id * 4, write,
 534                                 &value);
 535                         if (!ret && !write)
 536                                 *resp = value;
 537                         break;
 538                 case CLOS_PM_QOS_CONFIG:
 539                         ret = isst_send_mmio_command(cpu, PM_QOS_CONFIG_OFFSET,
 540                                                      write, &value);
 541                         if (!ret && !write)
 542                                 *resp = value;
 543                         break;
 544                 case CLOS_STATUS:
 545                         break;
 546                 default:
 547                         break;
 548                 }
 549                 return ret;
 550         }
 551 
 552         mbox_cmds.cmd_count = 1;
 553         mbox_cmds.mbox_cmd[0].logical_cpu = cpu;
 554         mbox_cmds.mbox_cmd[0].command = command;
 555         mbox_cmds.mbox_cmd[0].sub_command = sub_command;
 556         mbox_cmds.mbox_cmd[0].parameter = parameter;
 557         mbox_cmds.mbox_cmd[0].req_data = req_data;
 558 
 559         fd = open(pathname, O_RDWR);
 560         if (fd < 0)
 561                 err(-1, "%s open failed", pathname);
 562 
 563         if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) {
 564                 perror("ISST_IF_MBOX_COMMAND");
 565                 fprintf(outf,
 566                         "Error: mbox_cmd cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n",
 567                         cpu, command, sub_command, parameter, req_data);
 568         } else {
 569                 *resp = mbox_cmds.mbox_cmd[0].resp_data;
 570                 debug_printf(
 571                         "mbox_cmd response: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x resp:%x\n",
 572                         cpu, command, sub_command, parameter, req_data, *resp);
 573         }
 574 
 575         close(fd);
 576 
 577         return 0;
 578 }
 579 
 580 int isst_send_msr_command(unsigned int cpu, unsigned int msr, int write,
 581                           unsigned long long *req_resp)
 582 {
 583         struct isst_if_msr_cmds msr_cmds;
 584         const char *pathname = "/dev/isst_interface";
 585         int fd;
 586 
 587         fd = open(pathname, O_RDWR);
 588         if (fd < 0)
 589                 err(-1, "%s open failed", pathname);
 590 
 591         msr_cmds.cmd_count = 1;
 592         msr_cmds.msr_cmd[0].logical_cpu = cpu;
 593         msr_cmds.msr_cmd[0].msr = msr;
 594         msr_cmds.msr_cmd[0].read_write = write;
 595         if (write)
 596                 msr_cmds.msr_cmd[0].data = *req_resp;
 597 
 598         if (ioctl(fd, ISST_IF_MSR_COMMAND, &msr_cmds) == -1) {
 599                 perror("ISST_IF_MSR_COMMAD");
 600                 fprintf(outf, "Error: msr_cmd cpu:%d msr:%x read_write:%d\n",
 601                         cpu, msr, write);
 602         } else {
 603                 if (!write)
 604                         *req_resp = msr_cmds.msr_cmd[0].data;
 605 
 606                 debug_printf(
 607                         "msr_cmd response: cpu:%d msr:%x rd_write:%x resp:%llx %llx\n",
 608                         cpu, msr, write, *req_resp, msr_cmds.msr_cmd[0].data);
 609         }
 610 
 611         close(fd);
 612 
 613         return 0;
 614 }
 615 
 616 static int isst_fill_platform_info(void)
 617 {
 618         const char *pathname = "/dev/isst_interface";
 619         int fd;
 620 
 621         fd = open(pathname, O_RDWR);
 622         if (fd < 0)
 623                 err(-1, "%s open failed", pathname);
 624 
 625         if (ioctl(fd, ISST_IF_GET_PLATFORM_INFO, &isst_platform_info) == -1) {
 626                 perror("ISST_IF_GET_PLATFORM_INFO");
 627                 close(fd);
 628                 return -1;
 629         }
 630 
 631         close(fd);
 632 
 633         if (isst_platform_info.api_version > supported_api_ver) {
 634                 printf("Incompatible API versions; Upgrade of tool is required\n");
 635                 return -1;
 636         }
 637         return 0;
 638 }
 639 
 640 static void isst_print_platform_information(void)
 641 {
 642         struct isst_if_platform_info platform_info;
 643         const char *pathname = "/dev/isst_interface";
 644         int fd;
 645 
 646         fd = open(pathname, O_RDWR);
 647         if (fd < 0)
 648                 err(-1, "%s open failed", pathname);
 649 
 650         if (ioctl(fd, ISST_IF_GET_PLATFORM_INFO, &platform_info) == -1) {
 651                 perror("ISST_IF_GET_PLATFORM_INFO");
 652         } else {
 653                 fprintf(outf, "Platform: API version : %d\n",
 654                         platform_info.api_version);
 655                 fprintf(outf, "Platform: Driver version : %d\n",
 656                         platform_info.driver_version);
 657                 fprintf(outf, "Platform: mbox supported : %d\n",
 658                         platform_info.mbox_supported);
 659                 fprintf(outf, "Platform: mmio supported : %d\n",
 660                         platform_info.mmio_supported);
 661         }
 662 
 663         close(fd);
 664 
 665         exit(0);
 666 }
 667 
 668 static void exec_on_get_ctdp_cpu(int cpu, void *arg1, void *arg2, void *arg3,
 669                                  void *arg4)
 670 {
 671         int (*fn_ptr)(int cpu, void *arg);
 672         int ret;
 673 
 674         fn_ptr = arg1;
 675         ret = fn_ptr(cpu, arg2);
 676         if (ret)
 677                 perror("get_tdp_*");
 678         else
 679                 isst_ctdp_display_core_info(cpu, outf, arg3,
 680                                             *(unsigned int *)arg4);
 681 }
 682 
 683 #define _get_tdp_level(desc, suffix, object, help)                                \
 684         static void get_tdp_##object(void)                                        \
 685         {                                                                         \
 686                 struct isst_pkg_ctdp ctdp;                                        \
 687 \
 688                 if (cmd_help) {                                                   \
 689                         fprintf(stderr,                                           \
 690                                 "Print %s [No command arguments are required]\n", \
 691                                 help);                                            \
 692                         exit(0);                                                  \
 693                 }                                                                 \
 694                 isst_ctdp_display_information_start(outf);                        \
 695                 if (max_target_cpus)                                              \
 696                         for_each_online_target_cpu_in_set(                        \
 697                                 exec_on_get_ctdp_cpu, isst_get_ctdp_##suffix,     \
 698                                 &ctdp, desc, &ctdp.object);                       \
 699                 else                                                              \
 700                         for_each_online_package_in_set(exec_on_get_ctdp_cpu,      \
 701                                                        isst_get_ctdp_##suffix,    \
 702                                                        &ctdp, desc,               \
 703                                                        &ctdp.object);             \
 704                 isst_ctdp_display_information_end(outf);                          \
 705         }
 706 
 707 _get_tdp_level("get-config-levels", levels, levels, "TDP levels");
 708 _get_tdp_level("get-config-version", levels, version, "TDP version");
 709 _get_tdp_level("get-config-enabled", levels, enabled, "TDP enable status");
 710 _get_tdp_level("get-config-current_level", levels, current_level,
 711                "Current TDP Level");
 712 _get_tdp_level("get-lock-status", levels, locked, "TDP lock status");
 713 
 714 static void dump_isst_config_for_cpu(int cpu, void *arg1, void *arg2,
 715                                      void *arg3, void *arg4)
 716 {
 717         struct isst_pkg_ctdp pkg_dev;
 718         int ret;
 719 
 720         memset(&pkg_dev, 0, sizeof(pkg_dev));
 721         ret = isst_get_process_ctdp(cpu, tdp_level, &pkg_dev);
 722         if (ret) {
 723                 perror("isst_get_process_ctdp");
 724         } else {
 725                 isst_ctdp_display_information(cpu, outf, tdp_level, &pkg_dev);
 726                 isst_get_process_ctdp_complete(cpu, &pkg_dev);
 727         }
 728 }
 729 
 730 static void dump_isst_config(void)
 731 {
 732         if (cmd_help) {
 733                 fprintf(stderr,
 734                         "Print Intel(R) Speed Select Technology Performance profile configuration\n");
 735                 fprintf(stderr,
 736                         "including base frequency and turbo frequency configurations\n");
 737                 fprintf(stderr, "Optional: -l|--level : Specify tdp level\n");
 738                 fprintf(stderr,
 739                         "\tIf no arguments, dump information for all TDP levels\n");
 740                 exit(0);
 741         }
 742 
 743         isst_ctdp_display_information_start(outf);
 744 
 745         if (max_target_cpus)
 746                 for_each_online_target_cpu_in_set(dump_isst_config_for_cpu,
 747                                                   NULL, NULL, NULL, NULL);
 748         else
 749                 for_each_online_package_in_set(dump_isst_config_for_cpu, NULL,
 750                                                NULL, NULL, NULL);
 751 
 752         isst_ctdp_display_information_end(outf);
 753 }
 754 
 755 static void set_tdp_level_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
 756                                   void *arg4)
 757 {
 758         int ret;
 759 
 760         ret = isst_set_tdp_level(cpu, tdp_level);
 761         if (ret)
 762                 perror("set_tdp_level_for_cpu");
 763         else {
 764                 isst_display_result(cpu, outf, "perf-profile", "set_tdp_level",
 765                                     ret);
 766                 if (force_online_offline) {
 767                         struct isst_pkg_ctdp_level_info ctdp_level;
 768                         int pkg_id = get_physical_package_id(cpu);
 769                         int die_id = get_physical_die_id(cpu);
 770 
 771                         fprintf(stderr, "Option is set to online/offline\n");
 772                         ctdp_level.core_cpumask_size =
 773                                 alloc_cpu_set(&ctdp_level.core_cpumask);
 774                         isst_get_coremask_info(cpu, tdp_level, &ctdp_level);
 775                         if (ctdp_level.cpu_count) {
 776                                 int i, max_cpus = get_topo_max_cpus();
 777                                 for (i = 0; i < max_cpus; ++i) {
 778                                         if (pkg_id != get_physical_package_id(i) || die_id != get_physical_die_id(i))
 779                                                 continue;
 780                                         if (CPU_ISSET_S(i, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask)) {
 781                                                 fprintf(stderr, "online cpu %d\n", i);
 782                                                 set_cpu_online_offline(i, 1);
 783                                         } else {
 784                                                 fprintf(stderr, "offline cpu %d\n", i);
 785                                                 set_cpu_online_offline(i, 0);
 786                                         }
 787                                 }
 788                         }
 789                 }
 790         }
 791 }
 792 
 793 static void set_tdp_level(void)
 794 {
 795         if (cmd_help) {
 796                 fprintf(stderr, "Set Config TDP level\n");
 797                 fprintf(stderr,
 798                         "\t Arguments: -l|--level : Specify tdp level\n");
 799                 fprintf(stderr,
 800                         "\t Optional Arguments: -o | online : online/offline for the tdp level\n");
 801                 exit(0);
 802         }
 803 
 804         if (tdp_level == 0xff) {
 805                 fprintf(outf, "Invalid command: specify tdp_level\n");
 806                 exit(1);
 807         }
 808         isst_ctdp_display_information_start(outf);
 809         if (max_target_cpus)
 810                 for_each_online_target_cpu_in_set(set_tdp_level_for_cpu, NULL,
 811                                                   NULL, NULL, NULL);
 812         else
 813                 for_each_online_package_in_set(set_tdp_level_for_cpu, NULL,
 814                                                NULL, NULL, NULL);
 815         isst_ctdp_display_information_end(outf);
 816 }
 817 
 818 static void dump_pbf_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
 819                                     void *arg4)
 820 {
 821         struct isst_pbf_info pbf_info;
 822         int ret;
 823 
 824         ret = isst_get_pbf_info(cpu, tdp_level, &pbf_info);
 825         if (ret) {
 826                 perror("isst_get_pbf_info");
 827         } else {
 828                 isst_pbf_display_information(cpu, outf, tdp_level, &pbf_info);
 829                 isst_get_pbf_info_complete(&pbf_info);
 830         }
 831 }
 832 
 833 static void dump_pbf_config(void)
 834 {
 835         if (cmd_help) {
 836                 fprintf(stderr,
 837                         "Print Intel(R) Speed Select Technology base frequency configuration for a TDP level\n");
 838                 fprintf(stderr,
 839                         "\tArguments: -l|--level : Specify tdp level\n");
 840                 exit(0);
 841         }
 842 
 843         if (tdp_level == 0xff) {
 844                 fprintf(outf, "Invalid command: specify tdp_level\n");
 845                 exit(1);
 846         }
 847 
 848         isst_ctdp_display_information_start(outf);
 849         if (max_target_cpus)
 850                 for_each_online_target_cpu_in_set(dump_pbf_config_for_cpu, NULL,
 851                                                   NULL, NULL, NULL);
 852         else
 853                 for_each_online_package_in_set(dump_pbf_config_for_cpu, NULL,
 854                                                NULL, NULL, NULL);
 855         isst_ctdp_display_information_end(outf);
 856 }
 857 
 858 static void set_pbf_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
 859                             void *arg4)
 860 {
 861         int ret;
 862         int status = *(int *)arg4;
 863 
 864         ret = isst_set_pbf_fact_status(cpu, 1, status);
 865         if (ret) {
 866                 perror("isst_set_pbf");
 867         } else {
 868                 if (status)
 869                         isst_display_result(cpu, outf, "base-freq", "enable",
 870                                             ret);
 871                 else
 872                         isst_display_result(cpu, outf, "base-freq", "disable",
 873                                             ret);
 874         }
 875 }
 876 
 877 static void set_pbf_enable(void)
 878 {
 879         int status = 1;
 880 
 881         if (cmd_help) {
 882                 fprintf(stderr,
 883                         "Enable Intel Speed Select Technology base frequency feature [No command arguments are required]\n");
 884                 exit(0);
 885         }
 886 
 887         isst_ctdp_display_information_start(outf);
 888         if (max_target_cpus)
 889                 for_each_online_target_cpu_in_set(set_pbf_for_cpu, NULL, NULL,
 890                                                   NULL, &status);
 891         else
 892                 for_each_online_package_in_set(set_pbf_for_cpu, NULL, NULL,
 893                                                NULL, &status);
 894         isst_ctdp_display_information_end(outf);
 895 }
 896 
 897 static void set_pbf_disable(void)
 898 {
 899         int status = 0;
 900 
 901         if (cmd_help) {
 902                 fprintf(stderr,
 903                         "Disable Intel Speed Select Technology base frequency feature [No command arguments are required]\n");
 904                 exit(0);
 905         }
 906 
 907         isst_ctdp_display_information_start(outf);
 908         if (max_target_cpus)
 909                 for_each_online_target_cpu_in_set(set_pbf_for_cpu, NULL, NULL,
 910                                                   NULL, &status);
 911         else
 912                 for_each_online_package_in_set(set_pbf_for_cpu, NULL, NULL,
 913                                                NULL, &status);
 914         isst_ctdp_display_information_end(outf);
 915 }
 916 
 917 static void dump_fact_config_for_cpu(int cpu, void *arg1, void *arg2,
 918                                      void *arg3, void *arg4)
 919 {
 920         struct isst_fact_info fact_info;
 921         int ret;
 922 
 923         ret = isst_get_fact_info(cpu, tdp_level, &fact_info);
 924         if (ret)
 925                 perror("isst_get_fact_bucket_info");
 926         else
 927                 isst_fact_display_information(cpu, outf, tdp_level, fact_bucket,
 928                                               fact_avx, &fact_info);
 929 }
 930 
 931 static void dump_fact_config(void)
 932 {
 933         if (cmd_help) {
 934                 fprintf(stderr,
 935                         "Print complete Intel Speed Select Technology turbo frequency configuration for a TDP level. Other arguments are optional.\n");
 936                 fprintf(stderr,
 937                         "\tArguments: -l|--level : Specify tdp level\n");
 938                 fprintf(stderr,
 939                         "\tArguments: -b|--bucket : Bucket index to dump\n");
 940                 fprintf(stderr,
 941                         "\tArguments: -r|--trl-type : Specify trl type: sse|avx2|avx512\n");
 942                 exit(0);
 943         }
 944 
 945         if (tdp_level == 0xff) {
 946                 fprintf(outf, "Invalid command: specify tdp_level\n");
 947                 exit(1);
 948         }
 949 
 950         isst_ctdp_display_information_start(outf);
 951         if (max_target_cpus)
 952                 for_each_online_target_cpu_in_set(dump_fact_config_for_cpu,
 953                                                   NULL, NULL, NULL, NULL);
 954         else
 955                 for_each_online_package_in_set(dump_fact_config_for_cpu, NULL,
 956                                                NULL, NULL, NULL);
 957         isst_ctdp_display_information_end(outf);
 958 }
 959 
 960 static void set_fact_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
 961                              void *arg4)
 962 {
 963         int ret;
 964         int status = *(int *)arg4;
 965 
 966         ret = isst_set_pbf_fact_status(cpu, 0, status);
 967         if (ret)
 968                 perror("isst_set_fact");
 969         else {
 970                 if (status) {
 971                         struct isst_pkg_ctdp pkg_dev;
 972 
 973                         ret = isst_get_ctdp_levels(cpu, &pkg_dev);
 974                         if (ret) {
 975                                 isst_display_result(cpu, outf, "turbo-freq",
 976                                                     "enable", ret);
 977                                 return;
 978                         }
 979                         ret = isst_set_trl(cpu, fact_trl);
 980                         isst_display_result(cpu, outf, "turbo-freq", "enable",
 981                                             ret);
 982                 } else {
 983                         /* Since we modified TRL during Fact enable, restore it */
 984                         isst_set_trl_from_current_tdp(cpu, fact_trl);
 985                         isst_display_result(cpu, outf, "turbo-freq", "disable",
 986                                             ret);
 987                 }
 988         }
 989 }
 990 
 991 static void set_fact_enable(void)
 992 {
 993         int status = 1;
 994 
 995         if (cmd_help) {
 996                 fprintf(stderr,
 997                         "Enable Intel Speed Select Technology Turbo frequency feature\n");
 998                 fprintf(stderr,
 999                         "Optional: -t|--trl : Specify turbo ratio limit\n");
1000                 exit(0);
1001         }
1002 
1003         isst_ctdp_display_information_start(outf);
1004         if (max_target_cpus)
1005                 for_each_online_target_cpu_in_set(set_fact_for_cpu, NULL, NULL,
1006                                                   NULL, &status);
1007         else
1008                 for_each_online_package_in_set(set_fact_for_cpu, NULL, NULL,
1009                                                NULL, &status);
1010         isst_ctdp_display_information_end(outf);
1011 }
1012 
1013 static void set_fact_disable(void)
1014 {
1015         int status = 0;
1016 
1017         if (cmd_help) {
1018                 fprintf(stderr,
1019                         "Disable Intel Speed Select Technology turbo frequency feature\n");
1020                 fprintf(stderr,
1021                         "Optional: -t|--trl : Specify turbo ratio limit\n");
1022                 exit(0);
1023         }
1024 
1025         isst_ctdp_display_information_start(outf);
1026         if (max_target_cpus)
1027                 for_each_online_target_cpu_in_set(set_fact_for_cpu, NULL, NULL,
1028                                                   NULL, &status);
1029         else
1030                 for_each_online_package_in_set(set_fact_for_cpu, NULL, NULL,
1031                                                NULL, &status);
1032         isst_ctdp_display_information_end(outf);
1033 }
1034 
1035 static void enable_clos_qos_config(int cpu, void *arg1, void *arg2, void *arg3,
1036                                    void *arg4)
1037 {
1038         int ret;
1039         int status = *(int *)arg4;
1040 
1041         ret = isst_pm_qos_config(cpu, status, clos_priority_type);
1042         if (ret) {
1043                 perror("isst_pm_qos_config");
1044         } else {
1045                 if (status)
1046                         isst_display_result(cpu, outf, "core-power", "enable",
1047                                             ret);
1048                 else
1049                         isst_display_result(cpu, outf, "core-power", "disable",
1050                                             ret);
1051         }
1052 }
1053 
1054 static void set_clos_enable(void)
1055 {
1056         int status = 1;
1057 
1058         if (cmd_help) {
1059                 fprintf(stderr, "Enable core-power for a package/die\n");
1060                 fprintf(stderr,
1061                         "\tClos Enable: Specify priority type with [--priority|-p]\n");
1062                 fprintf(stderr, "\t\t 0: Proportional, 1: Ordered\n");
1063                 exit(0);
1064         }
1065 
1066         if (cpufreq_sysfs_present()) {
1067                 fprintf(stderr,
1068                         "cpufreq subsystem and core-power enable will interfere with each other!\n");
1069         }
1070 
1071         isst_ctdp_display_information_start(outf);
1072         if (max_target_cpus)
1073                 for_each_online_target_cpu_in_set(enable_clos_qos_config, NULL,
1074                                                   NULL, NULL, &status);
1075         else
1076                 for_each_online_package_in_set(enable_clos_qos_config, NULL,
1077                                                NULL, NULL, &status);
1078         isst_ctdp_display_information_end(outf);
1079 }
1080 
1081 static void set_clos_disable(void)
1082 {
1083         int status = 0;
1084 
1085         if (cmd_help) {
1086                 fprintf(stderr,
1087                         "Disable core-power: [No command arguments are required]\n");
1088                 exit(0);
1089         }
1090 
1091         isst_ctdp_display_information_start(outf);
1092         if (max_target_cpus)
1093                 for_each_online_target_cpu_in_set(enable_clos_qos_config, NULL,
1094                                                   NULL, NULL, &status);
1095         else
1096                 for_each_online_package_in_set(enable_clos_qos_config, NULL,
1097                                                NULL, NULL, &status);
1098         isst_ctdp_display_information_end(outf);
1099 }
1100 
1101 static void dump_clos_config_for_cpu(int cpu, void *arg1, void *arg2,
1102                                      void *arg3, void *arg4)
1103 {
1104         struct isst_clos_config clos_config;
1105         int ret;
1106 
1107         ret = isst_pm_get_clos(cpu, current_clos, &clos_config);
1108         if (ret)
1109                 perror("isst_pm_get_clos");
1110         else
1111                 isst_clos_display_information(cpu, outf, current_clos,
1112                                               &clos_config);
1113 }
1114 
1115 static void dump_clos_config(void)
1116 {
1117         if (cmd_help) {
1118                 fprintf(stderr,
1119                         "Print Intel Speed Select Technology core power configuration\n");
1120                 fprintf(stderr,
1121                         "\tArguments: [-c | --clos]: Specify clos id\n");
1122                 exit(0);
1123         }
1124         if (current_clos < 0 || current_clos > 3) {
1125                 fprintf(stderr, "Invalid clos id\n");
1126                 exit(0);
1127         }
1128 
1129         isst_ctdp_display_information_start(outf);
1130         if (max_target_cpus)
1131                 for_each_online_target_cpu_in_set(dump_clos_config_for_cpu,
1132                                                   NULL, NULL, NULL, NULL);
1133         else
1134                 for_each_online_package_in_set(dump_clos_config_for_cpu, NULL,
1135                                                NULL, NULL, NULL);
1136         isst_ctdp_display_information_end(outf);
1137 }
1138 
1139 static void get_clos_info_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1140                                   void *arg4)
1141 {
1142         int enable, ret, prio_type;
1143 
1144         ret = isst_clos_get_clos_information(cpu, &enable, &prio_type);
1145         if (ret)
1146                 perror("isst_clos_get_info");
1147         else
1148                 isst_clos_display_clos_information(cpu, outf, enable, prio_type);
1149 }
1150 
1151 static void dump_clos_info(void)
1152 {
1153         if (cmd_help) {
1154                 fprintf(stderr,
1155                         "Print Intel Speed Select Technology core power information\n");
1156                 fprintf(stderr, "\tSpecify targeted cpu id with [--cpu|-c]\n");
1157                 exit(0);
1158         }
1159 
1160         if (!max_target_cpus) {
1161                 fprintf(stderr,
1162                         "Invalid target cpu. Specify with [-c|--cpu]\n");
1163                 exit(0);
1164         }
1165 
1166         isst_ctdp_display_information_start(outf);
1167         for_each_online_target_cpu_in_set(get_clos_info_for_cpu, NULL,
1168                                           NULL, NULL, NULL);
1169         isst_ctdp_display_information_end(outf);
1170 
1171 }
1172 
1173 static void set_clos_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1174                                     void *arg4)
1175 {
1176         struct isst_clos_config clos_config;
1177         int ret;
1178 
1179         clos_config.pkg_id = get_physical_package_id(cpu);
1180         clos_config.die_id = get_physical_die_id(cpu);
1181 
1182         clos_config.epp = clos_epp;
1183         clos_config.clos_prop_prio = clos_prop_prio;
1184         clos_config.clos_min = clos_min;
1185         clos_config.clos_max = clos_max;
1186         clos_config.clos_desired = clos_desired;
1187         ret = isst_set_clos(cpu, current_clos, &clos_config);
1188         if (ret)
1189                 perror("isst_set_clos");
1190         else
1191                 isst_display_result(cpu, outf, "core-power", "config", ret);
1192 }
1193 
1194 static void set_clos_config(void)
1195 {
1196         if (cmd_help) {
1197                 fprintf(stderr,
1198                         "Set core-power configuration for one of the four clos ids\n");
1199                 fprintf(stderr,
1200                         "\tSpecify targeted clos id with [--clos|-c]\n");
1201                 fprintf(stderr, "\tSpecify clos EPP with [--epp|-e]\n");
1202                 fprintf(stderr,
1203                         "\tSpecify clos Proportional Priority [--weight|-w]\n");
1204                 fprintf(stderr, "\tSpecify clos min with [--min|-n]\n");
1205                 fprintf(stderr, "\tSpecify clos max with [--max|-m]\n");
1206                 fprintf(stderr, "\tSpecify clos desired with [--desired|-d]\n");
1207                 exit(0);
1208         }
1209 
1210         if (current_clos < 0 || current_clos > 3) {
1211                 fprintf(stderr, "Invalid clos id\n");
1212                 exit(0);
1213         }
1214         if (clos_epp < 0 || clos_epp > 0x0F) {
1215                 fprintf(stderr, "clos epp is not specified, default: 0\n");
1216                 clos_epp = 0;
1217         }
1218         if (clos_prop_prio < 0 || clos_prop_prio > 0x0F) {
1219                 fprintf(stderr,
1220                         "clos frequency weight is not specified, default: 0\n");
1221                 clos_prop_prio = 0;
1222         }
1223         if (clos_min < 0) {
1224                 fprintf(stderr, "clos min is not specified, default: 0\n");
1225                 clos_min = 0;
1226         }
1227         if (clos_max < 0) {
1228                 fprintf(stderr, "clos max is not specified, default: 0xff\n");
1229                 clos_max = 0xff;
1230         }
1231         if (clos_desired < 0) {
1232                 fprintf(stderr, "clos desired is not specified, default: 0\n");
1233                 clos_desired = 0x00;
1234         }
1235 
1236         isst_ctdp_display_information_start(outf);
1237         if (max_target_cpus)
1238                 for_each_online_target_cpu_in_set(set_clos_config_for_cpu, NULL,
1239                                                   NULL, NULL, NULL);
1240         else
1241                 for_each_online_package_in_set(set_clos_config_for_cpu, NULL,
1242                                                NULL, NULL, NULL);
1243         isst_ctdp_display_information_end(outf);
1244 }
1245 
1246 static void set_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1247                                    void *arg4)
1248 {
1249         int ret;
1250 
1251         ret = isst_clos_associate(cpu, current_clos);
1252         if (ret)
1253                 perror("isst_clos_associate");
1254         else
1255                 isst_display_result(cpu, outf, "core-power", "assoc", ret);
1256 }
1257 
1258 static void set_clos_assoc(void)
1259 {
1260         if (cmd_help) {
1261                 fprintf(stderr, "Associate a clos id to a CPU\n");
1262                 fprintf(stderr,
1263                         "\tSpecify targeted clos id with [--clos|-c]\n");
1264                 exit(0);
1265         }
1266 
1267         if (current_clos < 0 || current_clos > 3) {
1268                 fprintf(stderr, "Invalid clos id\n");
1269                 exit(0);
1270         }
1271         if (max_target_cpus)
1272                 for_each_online_target_cpu_in_set(set_clos_assoc_for_cpu, NULL,
1273                                                   NULL, NULL, NULL);
1274         else {
1275                 fprintf(stderr,
1276                         "Invalid target cpu. Specify with [-c|--cpu]\n");
1277         }
1278 }
1279 
1280 static void get_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1281                                    void *arg4)
1282 {
1283         int clos, ret;
1284 
1285         ret = isst_clos_get_assoc_status(cpu, &clos);
1286         if (ret)
1287                 perror("isst_clos_get_assoc_status");
1288         else
1289                 isst_clos_display_assoc_information(cpu, outf, clos);
1290 }
1291 
1292 static void get_clos_assoc(void)
1293 {
1294         if (cmd_help) {
1295                 fprintf(stderr, "Get associate clos id to a CPU\n");
1296                 fprintf(stderr, "\tSpecify targeted cpu id with [--cpu|-c]\n");
1297                 exit(0);
1298         }
1299 
1300         if (!max_target_cpus) {
1301                 fprintf(stderr,
1302                         "Invalid target cpu. Specify with [-c|--cpu]\n");
1303                 exit(0);
1304         }
1305 
1306         isst_ctdp_display_information_start(outf);
1307         for_each_online_target_cpu_in_set(get_clos_assoc_for_cpu, NULL,
1308                                           NULL, NULL, NULL);
1309         isst_ctdp_display_information_end(outf);
1310 }
1311 
1312 static struct process_cmd_struct isst_cmds[] = {
1313         { "perf-profile", "get-lock-status", get_tdp_locked },
1314         { "perf-profile", "get-config-levels", get_tdp_levels },
1315         { "perf-profile", "get-config-version", get_tdp_version },
1316         { "perf-profile", "get-config-enabled", get_tdp_enabled },
1317         { "perf-profile", "get-config-current-level", get_tdp_current_level },
1318         { "perf-profile", "set-config-level", set_tdp_level },
1319         { "perf-profile", "info", dump_isst_config },
1320         { "base-freq", "info", dump_pbf_config },
1321         { "base-freq", "enable", set_pbf_enable },
1322         { "base-freq", "disable", set_pbf_disable },
1323         { "turbo-freq", "info", dump_fact_config },
1324         { "turbo-freq", "enable", set_fact_enable },
1325         { "turbo-freq", "disable", set_fact_disable },
1326         { "core-power", "info", dump_clos_info },
1327         { "core-power", "enable", set_clos_enable },
1328         { "core-power", "disable", set_clos_disable },
1329         { "core-power", "config", set_clos_config },
1330         { "core-power", "get-config", dump_clos_config },
1331         { "core-power", "assoc", set_clos_assoc },
1332         { "core-power", "get-assoc", get_clos_assoc },
1333         { NULL, NULL, NULL }
1334 };
1335 
1336 /*
1337  * parse cpuset with following syntax
1338  * 1,2,4..6,8-10 and set bits in cpu_subset
1339  */
1340 void parse_cpu_command(char *optarg)
1341 {
1342         unsigned int start, end;
1343         char *next;
1344 
1345         next = optarg;
1346 
1347         while (next && *next) {
1348                 if (*next == '-') /* no negative cpu numbers */
1349                         goto error;
1350 
1351                 start = strtoul(next, &next, 10);
1352 
1353                 if (max_target_cpus < MAX_CPUS_IN_ONE_REQ)
1354                         target_cpus[max_target_cpus++] = start;
1355 
1356                 if (*next == '\0')
1357                         break;
1358 
1359                 if (*next == ',') {
1360                         next += 1;
1361                         continue;
1362                 }
1363 
1364                 if (*next == '-') {
1365                         next += 1; /* start range */
1366                 } else if (*next == '.') {
1367                         next += 1;
1368                         if (*next == '.')
1369                                 next += 1; /* start range */
1370                         else
1371                                 goto error;
1372                 }
1373 
1374                 end = strtoul(next, &next, 10);
1375                 if (end <= start)
1376                         goto error;
1377 
1378                 while (++start <= end) {
1379                         if (max_target_cpus < MAX_CPUS_IN_ONE_REQ)
1380                                 target_cpus[max_target_cpus++] = start;
1381                 }
1382 
1383                 if (*next == ',')
1384                         next += 1;
1385                 else if (*next != '\0')
1386                         goto error;
1387         }
1388 
1389 #ifdef DEBUG
1390         {
1391                 int i;
1392 
1393                 for (i = 0; i < max_target_cpus; ++i)
1394                         printf("cpu [%d] in arg\n", target_cpus[i]);
1395         }
1396 #endif
1397         return;
1398 
1399 error:
1400         fprintf(stderr, "\"--cpu %s\" malformed\n", optarg);
1401         exit(-1);
1402 }
1403 
1404 static void parse_cmd_args(int argc, int start, char **argv)
1405 {
1406         int opt;
1407         int option_index;
1408 
1409         static struct option long_options[] = {
1410                 { "bucket", required_argument, 0, 'b' },
1411                 { "level", required_argument, 0, 'l' },
1412                 { "online", required_argument, 0, 'o' },
1413                 { "trl-type", required_argument, 0, 'r' },
1414                 { "trl", required_argument, 0, 't' },
1415                 { "help", no_argument, 0, 'h' },
1416                 { "clos", required_argument, 0, 'c' },
1417                 { "desired", required_argument, 0, 'd' },
1418                 { "epp", required_argument, 0, 'e' },
1419                 { "min", required_argument, 0, 'n' },
1420                 { "max", required_argument, 0, 'm' },
1421                 { "priority", required_argument, 0, 'p' },
1422                 { "weight", required_argument, 0, 'w' },
1423                 { 0, 0, 0, 0 }
1424         };
1425 
1426         option_index = start;
1427 
1428         optind = start + 1;
1429         while ((opt = getopt_long(argc, argv, "b:l:t:c:d:e:n:m:p:w:ho",
1430                                   long_options, &option_index)) != -1) {
1431                 switch (opt) {
1432                 case 'b':
1433                         fact_bucket = atoi(optarg);
1434                         break;
1435                 case 'h':
1436                         cmd_help = 1;
1437                         break;
1438                 case 'l':
1439                         tdp_level = atoi(optarg);
1440                         break;
1441                 case 'o':
1442                         force_online_offline = 1;
1443                         break;
1444                 case 't':
1445                         sscanf(optarg, "0x%llx", &fact_trl);
1446                         break;
1447                 case 'r':
1448                         if (!strncmp(optarg, "sse", 3)) {
1449                                 fact_avx = 0x01;
1450                         } else if (!strncmp(optarg, "avx2", 4)) {
1451                                 fact_avx = 0x02;
1452                         } else if (!strncmp(optarg, "avx512", 4)) {
1453                                 fact_avx = 0x04;
1454                         } else {
1455                                 fprintf(outf, "Invalid sse,avx options\n");
1456                                 exit(1);
1457                         }
1458                         break;
1459                 /* CLOS related */
1460                 case 'c':
1461                         current_clos = atoi(optarg);
1462                         break;
1463                 case 'd':
1464                         clos_desired = atoi(optarg);
1465                         break;
1466                 case 'e':
1467                         clos_epp = atoi(optarg);
1468                         break;
1469                 case 'n':
1470                         clos_min = atoi(optarg);
1471                         break;
1472                 case 'm':
1473                         clos_max = atoi(optarg);
1474                         break;
1475                 case 'p':
1476                         clos_priority_type = atoi(optarg);
1477                         break;
1478                 case 'w':
1479                         clos_prop_prio = atoi(optarg);
1480                         break;
1481                 default:
1482                         printf("no match\n");
1483                 }
1484         }
1485 }
1486 
1487 static void isst_help(void)
1488 {
1489         printf("perf-profile:\tAn architectural mechanism that allows multiple optimized \n\
1490                 performance profiles per system via static and/or dynamic\n\
1491                 adjustment of core count, workload, Tjmax, and\n\
1492                 TDP, etc.\n");
1493         printf("\nCommands : For feature=perf-profile\n");
1494         printf("\tinfo\n");
1495         printf("\tget-lock-status\n");
1496         printf("\tget-config-levels\n");
1497         printf("\tget-config-version\n");
1498         printf("\tget-config-enabled\n");
1499         printf("\tget-config-current-level\n");
1500         printf("\tset-config-level\n");
1501 }
1502 
1503 static void pbf_help(void)
1504 {
1505         printf("base-freq:\tEnables users to increase guaranteed base frequency\n\
1506                 on certain cores (high priority cores) in exchange for lower\n\
1507                 base frequency on remaining cores (low priority cores).\n");
1508         printf("\tcommand : info\n");
1509         printf("\tcommand : enable\n");
1510         printf("\tcommand : disable\n");
1511 }
1512 
1513 static void fact_help(void)
1514 {
1515         printf("turbo-freq:\tEnables the ability to set different turbo ratio\n\
1516                 limits to cores based on priority.\n");
1517         printf("\nCommand: For feature=turbo-freq\n");
1518         printf("\tcommand : info\n");
1519         printf("\tcommand : enable\n");
1520         printf("\tcommand : disable\n");
1521 }
1522 
1523 static void core_power_help(void)
1524 {
1525         printf("core-power:\tInterface that allows user to define per core/tile\n\
1526                 priority.\n");
1527         printf("\nCommands : For feature=core-power\n");
1528         printf("\tinfo\n");
1529         printf("\tenable\n");
1530         printf("\tdisable\n");
1531         printf("\tconfig\n");
1532         printf("\tget-config\n");
1533         printf("\tassoc\n");
1534         printf("\tget-assoc\n");
1535 }
1536 
1537 struct process_cmd_help_struct {
1538         char *feature;
1539         void (*process_fn)(void);
1540 };
1541 
1542 static struct process_cmd_help_struct isst_help_cmds[] = {
1543         { "perf-profile", isst_help },
1544         { "base-freq", pbf_help },
1545         { "turbo-freq", fact_help },
1546         { "core-power", core_power_help },
1547         { NULL, NULL }
1548 };
1549 
1550 void process_command(int argc, char **argv)
1551 {
1552         int i = 0, matched = 0;
1553         char *feature = argv[optind];
1554         char *cmd = argv[optind + 1];
1555 
1556         if (!feature || !cmd)
1557                 return;
1558 
1559         debug_printf("feature name [%s] command [%s]\n", feature, cmd);
1560         if (!strcmp(cmd, "-h") || !strcmp(cmd, "--help")) {
1561                 while (isst_help_cmds[i].feature) {
1562                         if (!strcmp(isst_help_cmds[i].feature, feature)) {
1563                                 isst_help_cmds[i].process_fn();
1564                                 exit(0);
1565                         }
1566                         ++i;
1567                 }
1568         }
1569 
1570         create_cpu_map();
1571 
1572         i = 0;
1573         while (isst_cmds[i].feature) {
1574                 if (!strcmp(isst_cmds[i].feature, feature) &&
1575                     !strcmp(isst_cmds[i].command, cmd)) {
1576                         parse_cmd_args(argc, optind + 1, argv);
1577                         isst_cmds[i].process_fn();
1578                         matched = 1;
1579                         break;
1580                 }
1581                 ++i;
1582         }
1583 
1584         if (!matched)
1585                 fprintf(stderr, "Invalid command\n");
1586 }
1587 
1588 static void usage(void)
1589 {
1590         printf("Intel(R) Speed Select Technology\n");
1591         printf("\nUsage:\n");
1592         printf("intel-speed-select [OPTIONS] FEATURE COMMAND COMMAND_ARGUMENTS\n");
1593         printf("\nUse this tool to enumerate and control the Intel Speed Select Technology features,\n");
1594         printf("\nFEATURE : [perf-profile|base-freq|turbo-freq|core-power]\n");
1595         printf("\nFor help on each feature, use -h|--help\n");
1596         printf("\tFor example:  intel-speed-select perf-profile -h\n");
1597 
1598         printf("\nFor additional help on each command for a feature, use --h|--help\n");
1599         printf("\tFor example:  intel-speed-select perf-profile get-lock-status -h\n");
1600         printf("\t\t This will print help for the command \"get-lock-status\" for the feature \"perf-profile\"\n");
1601 
1602         printf("\nOPTIONS\n");
1603         printf("\t[-c|--cpu] : logical cpu number\n");
1604         printf("\t\tDefault: Die scoped for all dies in the system with multiple dies/package\n");
1605         printf("\t\t\t Or Package scoped for all Packages when each package contains one die\n");
1606         printf("\t[-d|--debug] : Debug mode\n");
1607         printf("\t[-h|--help] : Print help\n");
1608         printf("\t[-i|--info] : Print platform information\n");
1609         printf("\t[-o|--out] : Output file\n");
1610         printf("\t\t\tDefault : stderr\n");
1611         printf("\t[-f|--format] : output format [json|text]. Default: text\n");
1612         printf("\t[-v|--version] : Print version\n");
1613 
1614         printf("\nResult format\n");
1615         printf("\tResult display uses a common format for each command:\n");
1616         printf("\tResults are formatted in text/JSON with\n");
1617         printf("\t\tPackage, Die, CPU, and command specific results.\n");
1618         exit(1);
1619 }
1620 
1621 static void print_version(void)
1622 {
1623         fprintf(outf, "Version %s\n", version_str);
1624         fprintf(outf, "Build date %s time %s\n", __DATE__, __TIME__);
1625         exit(0);
1626 }
1627 
1628 static void cmdline(int argc, char **argv)
1629 {
1630         int opt;
1631         int option_index = 0;
1632         int ret;
1633 
1634         static struct option long_options[] = {
1635                 { "cpu", required_argument, 0, 'c' },
1636                 { "debug", no_argument, 0, 'd' },
1637                 { "format", required_argument, 0, 'f' },
1638                 { "help", no_argument, 0, 'h' },
1639                 { "info", no_argument, 0, 'i' },
1640                 { "out", required_argument, 0, 'o' },
1641                 { "version", no_argument, 0, 'v' },
1642                 { 0, 0, 0, 0 }
1643         };
1644 
1645         progname = argv[0];
1646         while ((opt = getopt_long_only(argc, argv, "+c:df:hio:v", long_options,
1647                                        &option_index)) != -1) {
1648                 switch (opt) {
1649                 case 'c':
1650                         parse_cpu_command(optarg);
1651                         break;
1652                 case 'd':
1653                         debug_flag = 1;
1654                         printf("Debug Mode ON\n");
1655                         break;
1656                 case 'f':
1657                         if (!strncmp(optarg, "json", 4))
1658                                 out_format_json = 1;
1659                         break;
1660                 case 'h':
1661                         usage();
1662                         break;
1663                 case 'i':
1664                         isst_print_platform_information();
1665                         break;
1666                 case 'o':
1667                         if (outf)
1668                                 fclose(outf);
1669                         outf = fopen_or_exit(optarg, "w");
1670                         break;
1671                 case 'v':
1672                         print_version();
1673                         break;
1674                 default:
1675                         usage();
1676                 }
1677         }
1678 
1679         if (geteuid() != 0) {
1680                 fprintf(stderr, "Must run as root\n");
1681                 exit(0);
1682         }
1683 
1684         if (optind > (argc - 2)) {
1685                 fprintf(stderr, "Feature name and|or command not specified\n");
1686                 exit(0);
1687         }
1688         update_cpu_model();
1689         printf("Intel(R) Speed Select Technology\n");
1690         printf("Executing on CPU model:%d[0x%x]\n", cpu_model, cpu_model);
1691         set_max_cpu_num();
1692         set_cpu_present_cpu_mask();
1693         set_cpu_target_cpu_mask();
1694         ret = isst_fill_platform_info();
1695         if (ret)
1696                 goto out;
1697 
1698         process_command(argc, argv);
1699 out:
1700         free_cpu_set(present_cpumask);
1701         free_cpu_set(target_cpumask);
1702 }
1703 
1704 int main(int argc, char **argv)
1705 {
1706         outf = stderr;
1707         cmdline(argc, argv);
1708         return 0;
1709 }

/* [<][>][^][v][top][bottom][index][help] */