0001
0002
0003
0004
0005
0006
0007 #include <linux/isst_if.h>
0008
0009 #include "isst.h"
0010
0011 struct process_cmd_struct {
0012 char *feature;
0013 char *command;
0014 void (*process_fn)(int arg);
0015 int arg;
0016 };
0017
0018 static const char *version_str = "v1.12";
0019
0020 static const int supported_api_ver = 1;
0021 static struct isst_if_platform_info isst_platform_info;
0022 static char *progname;
0023 static int debug_flag;
0024 static FILE *outf;
0025
0026 static int cpu_model;
0027 static int cpu_stepping;
0028
0029 #define MAX_CPUS_IN_ONE_REQ 256
0030 static short max_target_cpus;
0031 static unsigned short target_cpus[MAX_CPUS_IN_ONE_REQ];
0032
0033 static int topo_max_cpus;
0034 static size_t present_cpumask_size;
0035 static cpu_set_t *present_cpumask;
0036 static size_t target_cpumask_size;
0037 static cpu_set_t *target_cpumask;
0038 static int tdp_level = 0xFF;
0039 static int fact_bucket = 0xFF;
0040 static int fact_avx = 0xFF;
0041 static unsigned long long fact_trl;
0042 static int out_format_json;
0043 static int cmd_help;
0044 static int force_online_offline;
0045 static int auto_mode;
0046 static int fact_enable_fail;
0047
0048 static int mbox_delay;
0049 static int mbox_retries = 3;
0050
0051
0052 static int current_clos = -1;
0053 static int clos_epp = -1;
0054 static int clos_prop_prio = -1;
0055 static int clos_min = -1;
0056 static int clos_max = -1;
0057 static int clos_desired = -1;
0058 static int clos_priority_type;
0059
0060 struct _cpu_map {
0061 unsigned short core_id;
0062 unsigned short pkg_id;
0063 unsigned short die_id;
0064 unsigned short punit_cpu;
0065 unsigned short punit_cpu_core;
0066 };
0067 struct _cpu_map *cpu_map;
0068
0069 struct cpu_topology {
0070 short cpu;
0071 short core_id;
0072 short pkg_id;
0073 short die_id;
0074 };
0075
0076 FILE *get_output_file(void)
0077 {
0078 return outf;
0079 }
0080
0081 void debug_printf(const char *format, ...)
0082 {
0083 va_list args;
0084
0085 va_start(args, format);
0086
0087 if (debug_flag)
0088 vprintf(format, args);
0089
0090 va_end(args);
0091 }
0092
0093
0094 int is_clx_n_platform(void)
0095 {
0096 if (cpu_model == 0x55)
0097 if (cpu_stepping == 0x6 || cpu_stepping == 0x7)
0098 return 1;
0099 return 0;
0100 }
0101
0102 int is_skx_based_platform(void)
0103 {
0104 if (cpu_model == 0x55)
0105 return 1;
0106
0107 return 0;
0108 }
0109
0110 int is_spr_platform(void)
0111 {
0112 if (cpu_model == 0x8F)
0113 return 1;
0114
0115 return 0;
0116 }
0117
0118 int is_icx_platform(void)
0119 {
0120 if (cpu_model == 0x6A || cpu_model == 0x6C)
0121 return 1;
0122
0123 return 0;
0124 }
0125
0126 static int update_cpu_model(void)
0127 {
0128 unsigned int ebx, ecx, edx;
0129 unsigned int fms, family;
0130
0131 __cpuid(1, fms, ebx, ecx, edx);
0132 family = (fms >> 8) & 0xf;
0133 cpu_model = (fms >> 4) & 0xf;
0134 if (family == 6 || family == 0xf)
0135 cpu_model += ((fms >> 16) & 0xf) << 4;
0136
0137 cpu_stepping = fms & 0xf;
0138
0139 if (is_clx_n_platform()) {
0140 FILE *fp;
0141 size_t n = 0;
0142 char *line = NULL;
0143 int ret = 1;
0144
0145 fp = fopen("/proc/cpuinfo", "r");
0146 if (!fp)
0147 err(-1, "cannot open /proc/cpuinfo\n");
0148
0149 while (getline(&line, &n, fp) > 0) {
0150 if (strstr(line, "model name")) {
0151 if (strstr(line, "6252N") ||
0152 strstr(line, "6230N") ||
0153 strstr(line, "5218N"))
0154 ret = 0;
0155 break;
0156 }
0157 }
0158 free(line);
0159 fclose(fp);
0160 return ret;
0161 }
0162 return 0;
0163 }
0164
0165
0166 static FILE *fopen_or_exit(const char *path, const char *mode)
0167 {
0168 FILE *filep = fopen(path, mode);
0169
0170 if (!filep)
0171 err(1, "%s: open failed", path);
0172
0173 return filep;
0174 }
0175
0176
0177 static int parse_int_file(int fatal, const char *fmt, ...)
0178 {
0179 va_list args;
0180 char path[PATH_MAX];
0181 FILE *filep;
0182 int value;
0183
0184 va_start(args, fmt);
0185 vsnprintf(path, sizeof(path), fmt, args);
0186 va_end(args);
0187 if (fatal) {
0188 filep = fopen_or_exit(path, "r");
0189 } else {
0190 filep = fopen(path, "r");
0191 if (!filep)
0192 return -1;
0193 }
0194 if (fscanf(filep, "%d", &value) != 1)
0195 err(1, "%s: failed to parse number from file", path);
0196 fclose(filep);
0197
0198 return value;
0199 }
0200
0201 int cpufreq_sysfs_present(void)
0202 {
0203 DIR *dir;
0204
0205 dir = opendir("/sys/devices/system/cpu/cpu0/cpufreq");
0206 if (dir) {
0207 closedir(dir);
0208 return 1;
0209 }
0210
0211 return 0;
0212 }
0213
0214 int out_format_is_json(void)
0215 {
0216 return out_format_json;
0217 }
0218
0219 static int get_stored_topology_info(int cpu, int *core_id, int *pkg_id, int *die_id)
0220 {
0221 const char *pathname = "/var/run/isst_cpu_topology.dat";
0222 struct cpu_topology cpu_top;
0223 FILE *fp;
0224 int ret;
0225
0226 fp = fopen(pathname, "rb");
0227 if (!fp)
0228 return -1;
0229
0230 ret = fseek(fp, cpu * sizeof(cpu_top), SEEK_SET);
0231 if (ret)
0232 goto err_ret;
0233
0234 ret = fread(&cpu_top, sizeof(cpu_top), 1, fp);
0235 if (ret != 1) {
0236 ret = -1;
0237 goto err_ret;
0238 }
0239
0240 *pkg_id = cpu_top.pkg_id;
0241 *core_id = cpu_top.core_id;
0242 *die_id = cpu_top.die_id;
0243 ret = 0;
0244
0245 err_ret:
0246 fclose(fp);
0247
0248 return ret;
0249 }
0250
0251 static void store_cpu_topology(void)
0252 {
0253 const char *pathname = "/var/run/isst_cpu_topology.dat";
0254 FILE *fp;
0255 int i;
0256
0257 fp = fopen(pathname, "rb");
0258 if (fp) {
0259
0260 fclose(fp);
0261 return;
0262 }
0263
0264 fp = fopen(pathname, "wb");
0265 if (!fp) {
0266 fprintf(stderr, "Can't create file:%s\n", pathname);
0267 return;
0268 }
0269
0270 fprintf(stderr, "Caching topology information\n");
0271
0272 for (i = 0; i < topo_max_cpus; ++i) {
0273 struct cpu_topology cpu_top;
0274
0275 cpu_top.core_id = parse_int_file(0,
0276 "/sys/devices/system/cpu/cpu%d/topology/core_id", i);
0277 if (cpu_top.core_id < 0)
0278 cpu_top.core_id = -1;
0279
0280 cpu_top.pkg_id = parse_int_file(0,
0281 "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", i);
0282 if (cpu_top.pkg_id < 0)
0283 cpu_top.pkg_id = -1;
0284
0285 cpu_top.die_id = parse_int_file(0,
0286 "/sys/devices/system/cpu/cpu%d/topology/die_id", i);
0287 if (cpu_top.die_id < 0)
0288 cpu_top.die_id = -1;
0289
0290 cpu_top.cpu = i;
0291
0292 if (fwrite(&cpu_top, sizeof(cpu_top), 1, fp) != 1) {
0293 fprintf(stderr, "Can't write to:%s\n", pathname);
0294 break;
0295 }
0296 }
0297
0298 fclose(fp);
0299 }
0300
0301 int get_physical_package_id(int cpu)
0302 {
0303 int ret;
0304
0305 ret = parse_int_file(0,
0306 "/sys/devices/system/cpu/cpu%d/topology/physical_package_id",
0307 cpu);
0308 if (ret < 0) {
0309 int core_id, pkg_id, die_id;
0310
0311 ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id);
0312 if (!ret)
0313 return pkg_id;
0314 }
0315
0316 return ret;
0317 }
0318
0319 int get_physical_core_id(int cpu)
0320 {
0321 int ret;
0322
0323 ret = parse_int_file(0,
0324 "/sys/devices/system/cpu/cpu%d/topology/core_id",
0325 cpu);
0326 if (ret < 0) {
0327 int core_id, pkg_id, die_id;
0328
0329 ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id);
0330 if (!ret)
0331 return core_id;
0332 }
0333
0334 return ret;
0335 }
0336
0337 int get_physical_die_id(int cpu)
0338 {
0339 int ret;
0340
0341 ret = parse_int_file(0,
0342 "/sys/devices/system/cpu/cpu%d/topology/die_id",
0343 cpu);
0344 if (ret < 0) {
0345 int core_id, pkg_id, die_id;
0346
0347 ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id);
0348 if (!ret) {
0349 if (die_id < 0)
0350 die_id = 0;
0351
0352 return die_id;
0353 }
0354 }
0355
0356 if (ret < 0)
0357 ret = 0;
0358
0359 return ret;
0360 }
0361
0362 int get_cpufreq_base_freq(int cpu)
0363 {
0364 return parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency", cpu);
0365 }
0366
0367 int get_topo_max_cpus(void)
0368 {
0369 return topo_max_cpus;
0370 }
0371
0372 void set_cpu_online_offline(int cpu, int state)
0373 {
0374 char buffer[128];
0375 int fd, ret;
0376
0377 snprintf(buffer, sizeof(buffer),
0378 "/sys/devices/system/cpu/cpu%d/online", cpu);
0379
0380 fd = open(buffer, O_WRONLY);
0381 if (fd < 0) {
0382 if (!cpu && state) {
0383 fprintf(stderr, "This system is not configured for CPU 0 online/offline\n");
0384 fprintf(stderr, "Ignoring online request for CPU 0 as this is already online\n");
0385 return;
0386 }
0387 err(-1, "%s open failed", buffer);
0388 }
0389
0390 if (state)
0391 ret = write(fd, "1\n", 2);
0392 else
0393 ret = write(fd, "0\n", 2);
0394
0395 if (ret == -1)
0396 perror("Online/Offline: Operation failed\n");
0397
0398 close(fd);
0399 }
0400
0401 static void force_all_cpus_online(void)
0402 {
0403 int i;
0404
0405 fprintf(stderr, "Forcing all CPUs online\n");
0406
0407 for (i = 0; i < topo_max_cpus; ++i)
0408 set_cpu_online_offline(i, 1);
0409
0410 unlink("/var/run/isst_cpu_topology.dat");
0411 }
0412
0413 void for_each_online_package_in_set(void (*callback)(int, void *, void *,
0414 void *, void *),
0415 void *arg1, void *arg2, void *arg3,
0416 void *arg4)
0417 {
0418 int max_packages[MAX_PACKAGE_COUNT * MAX_PACKAGE_COUNT];
0419 int pkg_index = 0, i;
0420
0421 memset(max_packages, 0xff, sizeof(max_packages));
0422 for (i = 0; i < topo_max_cpus; ++i) {
0423 int j, online, pkg_id, die_id = 0, skip = 0;
0424
0425 if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
0426 continue;
0427 if (i)
0428 online = parse_int_file(
0429 1, "/sys/devices/system/cpu/cpu%d/online", i);
0430 else
0431 online =
0432 1;
0433
0434 die_id = get_physical_die_id(i);
0435 if (die_id < 0)
0436 die_id = 0;
0437
0438 pkg_id = parse_int_file(0,
0439 "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", i);
0440 if (pkg_id < 0)
0441 continue;
0442
0443
0444 pkg_id = (MAX_PACKAGE_COUNT * pkg_id + die_id);
0445
0446 for (j = 0; j < pkg_index; ++j) {
0447 if (max_packages[j] == pkg_id) {
0448 skip = 1;
0449 break;
0450 }
0451 }
0452
0453 if (!skip && online && callback) {
0454 callback(i, arg1, arg2, arg3, arg4);
0455 max_packages[pkg_index++] = pkg_id;
0456 }
0457 }
0458 }
0459
0460 static void for_each_online_target_cpu_in_set(
0461 void (*callback)(int, void *, void *, void *, void *), void *arg1,
0462 void *arg2, void *arg3, void *arg4)
0463 {
0464 int i, found = 0;
0465
0466 for (i = 0; i < topo_max_cpus; ++i) {
0467 int online;
0468
0469 if (!CPU_ISSET_S(i, target_cpumask_size, target_cpumask))
0470 continue;
0471 if (i)
0472 online = parse_int_file(
0473 1, "/sys/devices/system/cpu/cpu%d/online", i);
0474 else
0475 online =
0476 1;
0477
0478 if (online && callback) {
0479 callback(i, arg1, arg2, arg3, arg4);
0480 found = 1;
0481 }
0482 }
0483
0484 if (!found)
0485 fprintf(stderr, "No valid CPU in the list\n");
0486 }
0487
0488 #define BITMASK_SIZE 32
0489 static void set_max_cpu_num(void)
0490 {
0491 FILE *filep;
0492 unsigned long dummy;
0493 int i;
0494
0495 topo_max_cpus = 0;
0496 for (i = 0; i < 256; ++i) {
0497 char path[256];
0498
0499 snprintf(path, sizeof(path),
0500 "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", i);
0501 filep = fopen(path, "r");
0502 if (filep)
0503 break;
0504 }
0505
0506 if (!filep) {
0507 fprintf(stderr, "Can't get max cpu number\n");
0508 exit(0);
0509 }
0510
0511 while (fscanf(filep, "%lx,", &dummy) == 1)
0512 topo_max_cpus += BITMASK_SIZE;
0513 fclose(filep);
0514
0515 debug_printf("max cpus %d\n", topo_max_cpus);
0516 }
0517
0518 size_t alloc_cpu_set(cpu_set_t **cpu_set)
0519 {
0520 cpu_set_t *_cpu_set;
0521 size_t size;
0522
0523 _cpu_set = CPU_ALLOC((topo_max_cpus + 1));
0524 if (_cpu_set == NULL)
0525 err(3, "CPU_ALLOC");
0526 size = CPU_ALLOC_SIZE((topo_max_cpus + 1));
0527 CPU_ZERO_S(size, _cpu_set);
0528
0529 *cpu_set = _cpu_set;
0530 return size;
0531 }
0532
0533 void free_cpu_set(cpu_set_t *cpu_set)
0534 {
0535 CPU_FREE(cpu_set);
0536 }
0537
0538 static int cpu_cnt[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE];
0539 static long long core_mask[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE];
0540 static void set_cpu_present_cpu_mask(void)
0541 {
0542 size_t size;
0543 DIR *dir;
0544 int i;
0545
0546 size = alloc_cpu_set(&present_cpumask);
0547 present_cpumask_size = size;
0548 for (i = 0; i < topo_max_cpus; ++i) {
0549 char buffer[256];
0550
0551 snprintf(buffer, sizeof(buffer),
0552 "/sys/devices/system/cpu/cpu%d", i);
0553 dir = opendir(buffer);
0554 if (dir) {
0555 int pkg_id, die_id;
0556
0557 CPU_SET_S(i, size, present_cpumask);
0558 die_id = get_physical_die_id(i);
0559 if (die_id < 0)
0560 die_id = 0;
0561
0562 pkg_id = get_physical_package_id(i);
0563 if (pkg_id < 0) {
0564 fprintf(stderr, "Failed to get package id, CPU %d may be offline\n", i);
0565 continue;
0566 }
0567 if (pkg_id < MAX_PACKAGE_COUNT &&
0568 die_id < MAX_DIE_PER_PACKAGE) {
0569 int core_id = get_physical_core_id(i);
0570
0571 cpu_cnt[pkg_id][die_id]++;
0572 core_mask[pkg_id][die_id] |= (1ULL << core_id);
0573 }
0574 }
0575 closedir(dir);
0576 }
0577 }
0578
0579 int get_max_punit_core_id(int pkg_id, int die_id)
0580 {
0581 int max_id = 0;
0582 int i;
0583
0584 for (i = 0; i < topo_max_cpus; ++i)
0585 {
0586 if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
0587 continue;
0588
0589 if (cpu_map[i].pkg_id == pkg_id &&
0590 cpu_map[i].die_id == die_id &&
0591 cpu_map[i].punit_cpu_core > max_id)
0592 max_id = cpu_map[i].punit_cpu_core;
0593 }
0594
0595 return max_id;
0596 }
0597
0598 int get_cpu_count(int pkg_id, int die_id)
0599 {
0600 if (pkg_id < MAX_PACKAGE_COUNT && die_id < MAX_DIE_PER_PACKAGE)
0601 return cpu_cnt[pkg_id][die_id];
0602
0603 return 0;
0604 }
0605
0606 static void set_cpu_target_cpu_mask(void)
0607 {
0608 size_t size;
0609 int i;
0610
0611 size = alloc_cpu_set(&target_cpumask);
0612 target_cpumask_size = size;
0613 for (i = 0; i < max_target_cpus; ++i) {
0614 if (!CPU_ISSET_S(target_cpus[i], present_cpumask_size,
0615 present_cpumask))
0616 continue;
0617
0618 CPU_SET_S(target_cpus[i], size, target_cpumask);
0619 }
0620 }
0621
0622 static void create_cpu_map(void)
0623 {
0624 const char *pathname = "/dev/isst_interface";
0625 int i, fd = 0;
0626 struct isst_if_cpu_maps map;
0627
0628 cpu_map = malloc(sizeof(*cpu_map) * topo_max_cpus);
0629 if (!cpu_map)
0630 err(3, "cpumap");
0631
0632 fd = open(pathname, O_RDWR);
0633 if (fd < 0)
0634 err(-1, "%s open failed", pathname);
0635
0636 for (i = 0; i < topo_max_cpus; ++i) {
0637 if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
0638 continue;
0639
0640 map.cmd_count = 1;
0641 map.cpu_map[0].logical_cpu = i;
0642
0643 debug_printf(" map logical_cpu:%d\n",
0644 map.cpu_map[0].logical_cpu);
0645 if (ioctl(fd, ISST_IF_GET_PHY_ID, &map) == -1) {
0646 perror("ISST_IF_GET_PHY_ID");
0647 fprintf(outf, "Error: map logical_cpu:%d\n",
0648 map.cpu_map[0].logical_cpu);
0649 continue;
0650 }
0651 cpu_map[i].core_id = get_physical_core_id(i);
0652 cpu_map[i].pkg_id = get_physical_package_id(i);
0653 cpu_map[i].die_id = get_physical_die_id(i);
0654 cpu_map[i].punit_cpu = map.cpu_map[0].physical_cpu;
0655 cpu_map[i].punit_cpu_core = (map.cpu_map[0].physical_cpu >>
0656 1);
0657
0658 debug_printf(
0659 "map logical_cpu:%d core: %d die:%d pkg:%d punit_cpu:%d punit_core:%d\n",
0660 i, cpu_map[i].core_id, cpu_map[i].die_id,
0661 cpu_map[i].pkg_id, cpu_map[i].punit_cpu,
0662 cpu_map[i].punit_cpu_core);
0663 }
0664
0665 if (fd)
0666 close(fd);
0667 }
0668
0669 int find_logical_cpu(int pkg_id, int die_id, int punit_core_id)
0670 {
0671 int i;
0672
0673 for (i = 0; i < topo_max_cpus; ++i) {
0674 if (cpu_map[i].pkg_id == pkg_id &&
0675 cpu_map[i].die_id == die_id &&
0676 cpu_map[i].punit_cpu_core == punit_core_id)
0677 return i;
0678 }
0679
0680 return -EINVAL;
0681 }
0682
0683 void set_cpu_mask_from_punit_coremask(int cpu, unsigned long long core_mask,
0684 size_t core_cpumask_size,
0685 cpu_set_t *core_cpumask, int *cpu_cnt)
0686 {
0687 int i, cnt = 0;
0688 int die_id, pkg_id;
0689
0690 *cpu_cnt = 0;
0691 die_id = get_physical_die_id(cpu);
0692 pkg_id = get_physical_package_id(cpu);
0693
0694 for (i = 0; i < 64; ++i) {
0695 if (core_mask & BIT_ULL(i)) {
0696 int j;
0697
0698 for (j = 0; j < topo_max_cpus; ++j) {
0699 if (!CPU_ISSET_S(j, present_cpumask_size, present_cpumask))
0700 continue;
0701
0702 if (cpu_map[j].pkg_id == pkg_id &&
0703 cpu_map[j].die_id == die_id &&
0704 cpu_map[j].punit_cpu_core == i) {
0705 CPU_SET_S(j, core_cpumask_size,
0706 core_cpumask);
0707 ++cnt;
0708 }
0709 }
0710 }
0711 }
0712
0713 *cpu_cnt = cnt;
0714 }
0715
0716 int find_phy_core_num(int logical_cpu)
0717 {
0718 if (logical_cpu < topo_max_cpus)
0719 return cpu_map[logical_cpu].punit_cpu_core;
0720
0721 return -EINVAL;
0722 }
0723
0724 static int isst_send_mmio_command(unsigned int cpu, unsigned int reg, int write,
0725 unsigned int *value)
0726 {
0727 struct isst_if_io_regs io_regs;
0728 const char *pathname = "/dev/isst_interface";
0729 int cmd;
0730 int fd;
0731
0732 debug_printf("mmio_cmd cpu:%d reg:%d write:%d\n", cpu, reg, write);
0733
0734 fd = open(pathname, O_RDWR);
0735 if (fd < 0)
0736 err(-1, "%s open failed", pathname);
0737
0738 io_regs.req_count = 1;
0739 io_regs.io_reg[0].logical_cpu = cpu;
0740 io_regs.io_reg[0].reg = reg;
0741 cmd = ISST_IF_IO_CMD;
0742 if (write) {
0743 io_regs.io_reg[0].read_write = 1;
0744 io_regs.io_reg[0].value = *value;
0745 } else {
0746 io_regs.io_reg[0].read_write = 0;
0747 }
0748
0749 if (ioctl(fd, cmd, &io_regs) == -1) {
0750 if (errno == ENOTTY) {
0751 perror("ISST_IF_IO_COMMAND\n");
0752 fprintf(stderr, "Check presence of kernel modules: isst_if_mmio\n");
0753 exit(0);
0754 }
0755 fprintf(outf, "Error: mmio_cmd cpu:%d reg:%x read_write:%x\n",
0756 cpu, reg, write);
0757 } else {
0758 if (!write)
0759 *value = io_regs.io_reg[0].value;
0760
0761 debug_printf(
0762 "mmio_cmd response: cpu:%d reg:%x rd_write:%x resp:%x\n",
0763 cpu, reg, write, *value);
0764 }
0765
0766 close(fd);
0767
0768 return 0;
0769 }
0770
0771 int isst_send_mbox_command(unsigned int cpu, unsigned char command,
0772 unsigned char sub_command, unsigned int parameter,
0773 unsigned int req_data, unsigned int *resp)
0774 {
0775 const char *pathname = "/dev/isst_interface";
0776 int fd, retry;
0777 struct isst_if_mbox_cmds mbox_cmds = { 0 };
0778
0779 debug_printf(
0780 "mbox_send: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n",
0781 cpu, command, sub_command, parameter, req_data);
0782
0783 if (!is_skx_based_platform() && command == CONFIG_CLOS &&
0784 sub_command != CLOS_PM_QOS_CONFIG) {
0785 unsigned int value;
0786 int write = 0;
0787 int clos_id, core_id, ret = 0;
0788
0789 debug_printf("CPU %d\n", cpu);
0790
0791 if (parameter & BIT(MBOX_CMD_WRITE_BIT)) {
0792 value = req_data;
0793 write = 1;
0794 }
0795
0796 switch (sub_command) {
0797 case CLOS_PQR_ASSOC:
0798 core_id = parameter & 0xff;
0799 ret = isst_send_mmio_command(
0800 cpu, PQR_ASSOC_OFFSET + core_id * 4, write,
0801 &value);
0802 if (!ret && !write)
0803 *resp = value;
0804 break;
0805 case CLOS_PM_CLOS:
0806 clos_id = parameter & 0x03;
0807 ret = isst_send_mmio_command(
0808 cpu, PM_CLOS_OFFSET + clos_id * 4, write,
0809 &value);
0810 if (!ret && !write)
0811 *resp = value;
0812 break;
0813 case CLOS_STATUS:
0814 break;
0815 default:
0816 break;
0817 }
0818 return ret;
0819 }
0820
0821 mbox_cmds.cmd_count = 1;
0822 mbox_cmds.mbox_cmd[0].logical_cpu = cpu;
0823 mbox_cmds.mbox_cmd[0].command = command;
0824 mbox_cmds.mbox_cmd[0].sub_command = sub_command;
0825 mbox_cmds.mbox_cmd[0].parameter = parameter;
0826 mbox_cmds.mbox_cmd[0].req_data = req_data;
0827
0828 if (mbox_delay)
0829 usleep(mbox_delay * 1000);
0830
0831 fd = open(pathname, O_RDWR);
0832 if (fd < 0)
0833 err(-1, "%s open failed", pathname);
0834
0835 retry = mbox_retries;
0836
0837 do {
0838 if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) {
0839 if (errno == ENOTTY) {
0840 perror("ISST_IF_MBOX_COMMAND\n");
0841 fprintf(stderr, "Check presence of kernel modules: isst_if_mbox_pci or isst_if_mbox_msr\n");
0842 exit(0);
0843 }
0844 debug_printf(
0845 "Error: mbox_cmd cpu:%d command:%x sub_command:%x parameter:%x req_data:%x errorno:%d\n",
0846 cpu, command, sub_command, parameter, req_data, errno);
0847 --retry;
0848 } else {
0849 *resp = mbox_cmds.mbox_cmd[0].resp_data;
0850 debug_printf(
0851 "mbox_cmd response: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x resp:%x\n",
0852 cpu, command, sub_command, parameter, req_data, *resp);
0853 break;
0854 }
0855 } while (retry);
0856
0857 close(fd);
0858
0859 if (!retry) {
0860 debug_printf("Failed mbox command even after retries\n");
0861 return -1;
0862
0863 }
0864 return 0;
0865 }
0866
0867 int isst_send_msr_command(unsigned int cpu, unsigned int msr, int write,
0868 unsigned long long *req_resp)
0869 {
0870 struct isst_if_msr_cmds msr_cmds;
0871 const char *pathname = "/dev/isst_interface";
0872 int fd;
0873
0874 fd = open(pathname, O_RDWR);
0875 if (fd < 0)
0876 err(-1, "%s open failed", pathname);
0877
0878 msr_cmds.cmd_count = 1;
0879 msr_cmds.msr_cmd[0].logical_cpu = cpu;
0880 msr_cmds.msr_cmd[0].msr = msr;
0881 msr_cmds.msr_cmd[0].read_write = write;
0882 if (write)
0883 msr_cmds.msr_cmd[0].data = *req_resp;
0884
0885 if (ioctl(fd, ISST_IF_MSR_COMMAND, &msr_cmds) == -1) {
0886 perror("ISST_IF_MSR_COMMAND");
0887 fprintf(outf, "Error: msr_cmd cpu:%d msr:%x read_write:%d\n",
0888 cpu, msr, write);
0889 } else {
0890 if (!write)
0891 *req_resp = msr_cmds.msr_cmd[0].data;
0892
0893 debug_printf(
0894 "msr_cmd response: cpu:%d msr:%x rd_write:%x resp:%llx %llx\n",
0895 cpu, msr, write, *req_resp, msr_cmds.msr_cmd[0].data);
0896 }
0897
0898 close(fd);
0899
0900 return 0;
0901 }
0902
0903 static int isst_fill_platform_info(void)
0904 {
0905 const char *pathname = "/dev/isst_interface";
0906 int fd;
0907
0908 fd = open(pathname, O_RDWR);
0909 if (fd < 0)
0910 err(-1, "%s open failed", pathname);
0911
0912 if (ioctl(fd, ISST_IF_GET_PLATFORM_INFO, &isst_platform_info) == -1) {
0913 perror("ISST_IF_GET_PLATFORM_INFO");
0914 close(fd);
0915 return -1;
0916 }
0917
0918 close(fd);
0919
0920 if (isst_platform_info.api_version > supported_api_ver) {
0921 printf("Incompatible API versions; Upgrade of tool is required\n");
0922 return -1;
0923 }
0924 return 0;
0925 }
0926
0927 static void isst_print_extended_platform_info(void)
0928 {
0929 int cp_state, cp_cap, fact_support = 0, pbf_support = 0;
0930 struct isst_pkg_ctdp_level_info ctdp_level;
0931 struct isst_pkg_ctdp pkg_dev;
0932 int ret, i, j;
0933 FILE *filep;
0934
0935 for (i = 0; i < 256; ++i) {
0936 char path[256];
0937
0938 snprintf(path, sizeof(path),
0939 "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", i);
0940 filep = fopen(path, "r");
0941 if (filep)
0942 break;
0943 }
0944
0945 if (!filep)
0946 return;
0947
0948 fclose(filep);
0949
0950 ret = isst_get_ctdp_levels(i, &pkg_dev);
0951 if (ret)
0952 return;
0953
0954 if (pkg_dev.enabled) {
0955 fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is supported\n");
0956 } else {
0957 fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is not supported\n");
0958 fprintf(outf, "Only performance level 0 (base level) is present\n");
0959 }
0960
0961 if (pkg_dev.locked)
0962 fprintf(outf, "TDP level change control is locked\n");
0963 else
0964 fprintf(outf, "TDP level change control is unlocked, max level: %d \n", pkg_dev.levels);
0965
0966 for (j = 0; j <= pkg_dev.levels; ++j) {
0967 ret = isst_get_ctdp_control(i, j, &ctdp_level);
0968 if (ret)
0969 continue;
0970
0971 if (!fact_support && ctdp_level.fact_support)
0972 fact_support = 1;
0973
0974 if (!pbf_support && ctdp_level.pbf_support)
0975 pbf_support = 1;
0976 }
0977
0978 if (fact_support)
0979 fprintf(outf, "Intel(R) SST-TF (feature turbo-freq) is supported\n");
0980 else
0981 fprintf(outf, "Intel(R) SST-TF (feature turbo-freq) is not supported\n");
0982
0983 if (pbf_support)
0984 fprintf(outf, "Intel(R) SST-BF (feature base-freq) is supported\n");
0985 else
0986 fprintf(outf, "Intel(R) SST-BF (feature base-freq) is not supported\n");
0987
0988 ret = isst_read_pm_config(i, &cp_state, &cp_cap);
0989 if (ret) {
0990 fprintf(outf, "Intel(R) SST-CP (feature core-power) status is unknown\n");
0991 return;
0992 }
0993 if (cp_cap)
0994 fprintf(outf, "Intel(R) SST-CP (feature core-power) is supported\n");
0995 else
0996 fprintf(outf, "Intel(R) SST-CP (feature core-power) is not supported\n");
0997 }
0998
0999 static void isst_print_platform_information(void)
1000 {
1001 struct isst_if_platform_info platform_info;
1002 const char *pathname = "/dev/isst_interface";
1003 int fd;
1004
1005 if (is_clx_n_platform()) {
1006 fprintf(stderr, "\nThis option in not supported on this platform\n");
1007 exit(0);
1008 }
1009
1010 fd = open(pathname, O_RDWR);
1011 if (fd < 0)
1012 err(-1, "%s open failed", pathname);
1013
1014 if (ioctl(fd, ISST_IF_GET_PLATFORM_INFO, &platform_info) == -1) {
1015 perror("ISST_IF_GET_PLATFORM_INFO");
1016 } else {
1017 fprintf(outf, "Platform: API version : %d\n",
1018 platform_info.api_version);
1019 fprintf(outf, "Platform: Driver version : %d\n",
1020 platform_info.driver_version);
1021 fprintf(outf, "Platform: mbox supported : %d\n",
1022 platform_info.mbox_supported);
1023 fprintf(outf, "Platform: mmio supported : %d\n",
1024 platform_info.mmio_supported);
1025 isst_print_extended_platform_info();
1026 }
1027
1028 close(fd);
1029
1030 exit(0);
1031 }
1032
1033 static char *local_str0, *local_str1;
1034 static void exec_on_get_ctdp_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1035 void *arg4)
1036 {
1037 int (*fn_ptr)(int cpu, void *arg);
1038 int ret;
1039
1040 fn_ptr = arg1;
1041 ret = fn_ptr(cpu, arg2);
1042 if (ret)
1043 isst_display_error_info_message(1, "get_tdp_* failed", 0, 0);
1044 else
1045 isst_ctdp_display_core_info(cpu, outf, arg3,
1046 *(unsigned int *)arg4,
1047 local_str0, local_str1);
1048 }
1049
1050 #define _get_tdp_level(desc, suffix, object, help, str0, str1) \
1051 static void get_tdp_##object(int arg) \
1052 { \
1053 struct isst_pkg_ctdp ctdp; \
1054 \
1055 if (cmd_help) { \
1056 fprintf(stderr, \
1057 "Print %s [No command arguments are required]\n", \
1058 help); \
1059 exit(0); \
1060 } \
1061 local_str0 = str0; \
1062 local_str1 = str1; \
1063 isst_ctdp_display_information_start(outf); \
1064 if (max_target_cpus) \
1065 for_each_online_target_cpu_in_set( \
1066 exec_on_get_ctdp_cpu, isst_get_ctdp_##suffix, \
1067 &ctdp, desc, &ctdp.object); \
1068 else \
1069 for_each_online_package_in_set(exec_on_get_ctdp_cpu, \
1070 isst_get_ctdp_##suffix, \
1071 &ctdp, desc, \
1072 &ctdp.object); \
1073 isst_ctdp_display_information_end(outf); \
1074 }
1075
1076 _get_tdp_level("get-config-levels", levels, levels, "Max TDP level", NULL, NULL);
1077 _get_tdp_level("get-config-version", levels, version, "TDP version", NULL, NULL);
1078 _get_tdp_level("get-config-enabled", levels, enabled, "perf-profile enable status", "disabled", "enabled");
1079 _get_tdp_level("get-config-current_level", levels, current_level,
1080 "Current TDP Level", NULL, NULL);
1081 _get_tdp_level("get-lock-status", levels, locked, "TDP lock status", "unlocked", "locked");
1082
1083 struct isst_pkg_ctdp clx_n_pkg_dev;
1084
1085 static int clx_n_get_base_ratio(void)
1086 {
1087 FILE *fp;
1088 char *begin, *end, *line = NULL;
1089 char number[5];
1090 float value = 0;
1091 size_t n = 0;
1092
1093 fp = fopen("/proc/cpuinfo", "r");
1094 if (!fp)
1095 err(-1, "cannot open /proc/cpuinfo\n");
1096
1097 while (getline(&line, &n, fp) > 0) {
1098 if (strstr(line, "model name")) {
1099
1100 begin = strstr(line, "@ ") + 2;
1101 end = strstr(line, "GHz");
1102 strncpy(number, begin, end - begin);
1103 value = atof(number) * 10;
1104 break;
1105 }
1106 }
1107 free(line);
1108 fclose(fp);
1109
1110 return (int)(value);
1111 }
1112
1113 static int clx_n_config(int cpu)
1114 {
1115 int i, ret, pkg_id, die_id;
1116 unsigned long cpu_bf;
1117 struct isst_pkg_ctdp_level_info *ctdp_level;
1118 struct isst_pbf_info *pbf_info;
1119
1120 ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
1121 pbf_info = &ctdp_level->pbf_info;
1122 ctdp_level->core_cpumask_size =
1123 alloc_cpu_set(&ctdp_level->core_cpumask);
1124
1125
1126 ctdp_level->tdp_ratio = clx_n_get_base_ratio();
1127 if (ctdp_level->tdp_ratio == 0) {
1128 debug_printf("CLX: cn base ratio is zero\n");
1129 ret = -1;
1130 goto error_ret;
1131 }
1132
1133
1134 pbf_info->p1_high = 0;
1135 pbf_info->p1_low = ~0;
1136
1137 pkg_id = get_physical_package_id(cpu);
1138 die_id = get_physical_die_id(cpu);
1139
1140 for (i = 0; i < topo_max_cpus; i++) {
1141 if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
1142 continue;
1143
1144 if (pkg_id != get_physical_package_id(i) ||
1145 die_id != get_physical_die_id(i))
1146 continue;
1147
1148 CPU_SET_S(i, ctdp_level->core_cpumask_size,
1149 ctdp_level->core_cpumask);
1150
1151 cpu_bf = parse_int_file(1,
1152 "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency",
1153 i);
1154 if (cpu_bf > pbf_info->p1_high)
1155 pbf_info->p1_high = cpu_bf;
1156 if (cpu_bf < pbf_info->p1_low)
1157 pbf_info->p1_low = cpu_bf;
1158 }
1159
1160 if (pbf_info->p1_high == ~0UL) {
1161 debug_printf("CLX: maximum base frequency not set\n");
1162 ret = -1;
1163 goto error_ret;
1164 }
1165
1166 if (pbf_info->p1_low == 0) {
1167 debug_printf("CLX: minimum base frequency not set\n");
1168 ret = -1;
1169 goto error_ret;
1170 }
1171
1172
1173 pbf_info->p1_high = pbf_info->p1_high / 100000;
1174 pbf_info->p1_low = pbf_info->p1_low / 100000;
1175
1176
1177 pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask);
1178 for (i = 0; i < topo_max_cpus; i++) {
1179 if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
1180 continue;
1181
1182 if (pkg_id != get_physical_package_id(i) ||
1183 die_id != get_physical_die_id(i))
1184 continue;
1185
1186 cpu_bf = parse_int_file(1,
1187 "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency",
1188 i);
1189 cpu_bf = cpu_bf / 100000;
1190 if (cpu_bf == pbf_info->p1_high)
1191 CPU_SET_S(i, pbf_info->core_cpumask_size,
1192 pbf_info->core_cpumask);
1193 }
1194
1195
1196 ctdp_level->processed = 1;
1197 ctdp_level->pbf_support = 1;
1198 ctdp_level->pbf_enabled = 1;
1199 ctdp_level->fact_support = 0;
1200 ctdp_level->fact_enabled = 0;
1201
1202 return 0;
1203
1204 error_ret:
1205 free_cpu_set(ctdp_level->core_cpumask);
1206 return ret;
1207 }
1208
1209 static void dump_clx_n_config_for_cpu(int cpu, void *arg1, void *arg2,
1210 void *arg3, void *arg4)
1211 {
1212 int ret;
1213
1214 if (tdp_level != 0xff && tdp_level != 0) {
1215 isst_display_error_info_message(1, "Invalid level", 1, tdp_level);
1216 exit(0);
1217 }
1218
1219 ret = clx_n_config(cpu);
1220 if (ret) {
1221 debug_printf("clx_n_config failed");
1222 } else {
1223 struct isst_pkg_ctdp_level_info *ctdp_level;
1224 struct isst_pbf_info *pbf_info;
1225
1226 ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
1227 pbf_info = &ctdp_level->pbf_info;
1228 clx_n_pkg_dev.processed = 1;
1229 isst_ctdp_display_information(cpu, outf, tdp_level, &clx_n_pkg_dev);
1230 free_cpu_set(ctdp_level->core_cpumask);
1231 free_cpu_set(pbf_info->core_cpumask);
1232 }
1233 }
1234
1235 static void dump_isst_config_for_cpu(int cpu, void *arg1, void *arg2,
1236 void *arg3, void *arg4)
1237 {
1238 struct isst_pkg_ctdp pkg_dev;
1239 int ret;
1240
1241 memset(&pkg_dev, 0, sizeof(pkg_dev));
1242 ret = isst_get_process_ctdp(cpu, tdp_level, &pkg_dev);
1243 if (ret) {
1244 isst_display_error_info_message(1, "Failed to get perf-profile info on cpu", 1, cpu);
1245 isst_ctdp_display_information_end(outf);
1246 exit(1);
1247 } else {
1248 isst_ctdp_display_information(cpu, outf, tdp_level, &pkg_dev);
1249 isst_get_process_ctdp_complete(cpu, &pkg_dev);
1250 }
1251 }
1252
1253 static void dump_isst_config(int arg)
1254 {
1255 void *fn;
1256
1257 if (cmd_help) {
1258 fprintf(stderr,
1259 "Print Intel(R) Speed Select Technology Performance profile configuration\n");
1260 fprintf(stderr,
1261 "including base frequency and turbo frequency configurations\n");
1262 fprintf(stderr, "Optional: -l|--level : Specify tdp level\n");
1263 fprintf(stderr,
1264 "\tIf no arguments, dump information for all TDP levels\n");
1265 exit(0);
1266 }
1267
1268 if (!is_clx_n_platform())
1269 fn = dump_isst_config_for_cpu;
1270 else
1271 fn = dump_clx_n_config_for_cpu;
1272
1273 isst_ctdp_display_information_start(outf);
1274
1275 if (max_target_cpus)
1276 for_each_online_target_cpu_in_set(fn, NULL, NULL, NULL, NULL);
1277 else
1278 for_each_online_package_in_set(fn, NULL, NULL, NULL, NULL);
1279
1280 isst_ctdp_display_information_end(outf);
1281 }
1282
1283 static void adjust_scaling_max_from_base_freq(int cpu);
1284
1285 static void set_tdp_level_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1286 void *arg4)
1287 {
1288 int ret;
1289
1290 ret = isst_set_tdp_level(cpu, tdp_level);
1291 if (ret) {
1292 isst_display_error_info_message(1, "Set TDP level failed", 0, 0);
1293 isst_ctdp_display_information_end(outf);
1294 exit(1);
1295 } else {
1296 isst_display_result(cpu, outf, "perf-profile", "set_tdp_level",
1297 ret);
1298 if (force_online_offline) {
1299 struct isst_pkg_ctdp_level_info ctdp_level;
1300 int pkg_id = get_physical_package_id(cpu);
1301 int die_id = get_physical_die_id(cpu);
1302
1303
1304 usleep(2000);
1305
1306 fprintf(stderr, "Option is set to online/offline\n");
1307 ctdp_level.core_cpumask_size =
1308 alloc_cpu_set(&ctdp_level.core_cpumask);
1309 ret = isst_get_coremask_info(cpu, tdp_level, &ctdp_level);
1310 if (ret) {
1311 isst_display_error_info_message(1, "Can't get coremask, online/offline option is ignored", 0, 0);
1312 return;
1313 }
1314 if (ctdp_level.cpu_count) {
1315 int i, max_cpus = get_topo_max_cpus();
1316 for (i = 0; i < max_cpus; ++i) {
1317 if (pkg_id != get_physical_package_id(i) || die_id != get_physical_die_id(i))
1318 continue;
1319 if (CPU_ISSET_S(i, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask)) {
1320 fprintf(stderr, "online cpu %d\n", i);
1321 set_cpu_online_offline(i, 1);
1322 adjust_scaling_max_from_base_freq(i);
1323 } else {
1324 fprintf(stderr, "offline cpu %d\n", i);
1325 set_cpu_online_offline(i, 0);
1326 }
1327 }
1328 }
1329 }
1330 }
1331 }
1332
1333 static void set_tdp_level(int arg)
1334 {
1335 if (cmd_help) {
1336 fprintf(stderr, "Set Config TDP level\n");
1337 fprintf(stderr,
1338 "\t Arguments: -l|--level : Specify tdp level\n");
1339 fprintf(stderr,
1340 "\t Optional Arguments: -o | online : online/offline for the tdp level\n");
1341 fprintf(stderr,
1342 "\t online/offline operation has limitations, refer to Linux hotplug documentation\n");
1343 exit(0);
1344 }
1345
1346 if (tdp_level == 0xff) {
1347 isst_display_error_info_message(1, "Invalid command: specify tdp_level", 0, 0);
1348 exit(1);
1349 }
1350 isst_ctdp_display_information_start(outf);
1351 if (max_target_cpus)
1352 for_each_online_target_cpu_in_set(set_tdp_level_for_cpu, NULL,
1353 NULL, NULL, NULL);
1354 else
1355 for_each_online_package_in_set(set_tdp_level_for_cpu, NULL,
1356 NULL, NULL, NULL);
1357 isst_ctdp_display_information_end(outf);
1358 }
1359
1360 static void clx_n_dump_pbf_config_for_cpu(int cpu, void *arg1, void *arg2,
1361 void *arg3, void *arg4)
1362 {
1363 int ret;
1364
1365 ret = clx_n_config(cpu);
1366 if (ret) {
1367 isst_display_error_info_message(1, "clx_n_config failed", 0, 0);
1368 } else {
1369 struct isst_pkg_ctdp_level_info *ctdp_level;
1370 struct isst_pbf_info *pbf_info;
1371
1372 ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
1373 pbf_info = &ctdp_level->pbf_info;
1374 isst_pbf_display_information(cpu, outf, tdp_level, pbf_info);
1375 free_cpu_set(ctdp_level->core_cpumask);
1376 free_cpu_set(pbf_info->core_cpumask);
1377 }
1378 }
1379
1380 static void dump_pbf_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1381 void *arg4)
1382 {
1383 struct isst_pbf_info pbf_info;
1384 int ret;
1385
1386 ret = isst_get_pbf_info(cpu, tdp_level, &pbf_info);
1387 if (ret) {
1388 isst_display_error_info_message(1, "Failed to get base-freq info at this level", 1, tdp_level);
1389 isst_ctdp_display_information_end(outf);
1390 exit(1);
1391 } else {
1392 isst_pbf_display_information(cpu, outf, tdp_level, &pbf_info);
1393 isst_get_pbf_info_complete(&pbf_info);
1394 }
1395 }
1396
1397 static void dump_pbf_config(int arg)
1398 {
1399 void *fn;
1400
1401 if (cmd_help) {
1402 fprintf(stderr,
1403 "Print Intel(R) Speed Select Technology base frequency configuration for a TDP level\n");
1404 fprintf(stderr,
1405 "\tArguments: -l|--level : Specify tdp level\n");
1406 exit(0);
1407 }
1408
1409 if (tdp_level == 0xff) {
1410 isst_display_error_info_message(1, "Invalid command: specify tdp_level", 0, 0);
1411 exit(1);
1412 }
1413
1414 if (!is_clx_n_platform())
1415 fn = dump_pbf_config_for_cpu;
1416 else
1417 fn = clx_n_dump_pbf_config_for_cpu;
1418
1419 isst_ctdp_display_information_start(outf);
1420
1421 if (max_target_cpus)
1422 for_each_online_target_cpu_in_set(fn, NULL, NULL, NULL, NULL);
1423 else
1424 for_each_online_package_in_set(fn, NULL, NULL, NULL, NULL);
1425
1426 isst_ctdp_display_information_end(outf);
1427 }
1428
1429 static int set_clos_param(int cpu, int clos, int epp, int wt, int min, int max)
1430 {
1431 struct isst_clos_config clos_config;
1432 int ret;
1433
1434 ret = isst_pm_get_clos(cpu, clos, &clos_config);
1435 if (ret) {
1436 isst_display_error_info_message(1, "isst_pm_get_clos failed", 0, 0);
1437 return ret;
1438 }
1439 clos_config.clos_min = min;
1440 clos_config.clos_max = max;
1441 clos_config.epp = epp;
1442 clos_config.clos_prop_prio = wt;
1443 ret = isst_set_clos(cpu, clos, &clos_config);
1444 if (ret) {
1445 isst_display_error_info_message(1, "isst_set_clos failed", 0, 0);
1446 return ret;
1447 }
1448
1449 return 0;
1450 }
1451
1452 static int set_cpufreq_scaling_min_max(int cpu, int max, int freq)
1453 {
1454 char buffer[128], freq_str[16];
1455 int fd, ret, len;
1456
1457 if (max)
1458 snprintf(buffer, sizeof(buffer),
1459 "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu);
1460 else
1461 snprintf(buffer, sizeof(buffer),
1462 "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu);
1463
1464 fd = open(buffer, O_WRONLY);
1465 if (fd < 0)
1466 return fd;
1467
1468 snprintf(freq_str, sizeof(freq_str), "%d", freq);
1469 len = strlen(freq_str);
1470 ret = write(fd, freq_str, len);
1471 if (ret == -1) {
1472 close(fd);
1473 return ret;
1474 }
1475 close(fd);
1476
1477 return 0;
1478 }
1479
1480 static int no_turbo(void)
1481 {
1482 return parse_int_file(0, "/sys/devices/system/cpu/intel_pstate/no_turbo");
1483 }
1484
1485 static void adjust_scaling_max_from_base_freq(int cpu)
1486 {
1487 int base_freq, scaling_max_freq;
1488
1489 scaling_max_freq = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu);
1490 base_freq = get_cpufreq_base_freq(cpu);
1491 if (scaling_max_freq < base_freq || no_turbo())
1492 set_cpufreq_scaling_min_max(cpu, 1, base_freq);
1493 }
1494
1495 static void adjust_scaling_min_from_base_freq(int cpu)
1496 {
1497 int base_freq, scaling_min_freq;
1498
1499 scaling_min_freq = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu);
1500 base_freq = get_cpufreq_base_freq(cpu);
1501 if (scaling_min_freq < base_freq)
1502 set_cpufreq_scaling_min_max(cpu, 0, base_freq);
1503 }
1504
1505 static int set_clx_pbf_cpufreq_scaling_min_max(int cpu)
1506 {
1507 struct isst_pkg_ctdp_level_info *ctdp_level;
1508 struct isst_pbf_info *pbf_info;
1509 int i, pkg_id, die_id, freq, freq_high, freq_low;
1510 int ret;
1511
1512 ret = clx_n_config(cpu);
1513 if (ret) {
1514 debug_printf("cpufreq_scaling_min_max failed for CLX");
1515 return ret;
1516 }
1517
1518 ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
1519 pbf_info = &ctdp_level->pbf_info;
1520 freq_high = pbf_info->p1_high * 100000;
1521 freq_low = pbf_info->p1_low * 100000;
1522
1523 pkg_id = get_physical_package_id(cpu);
1524 die_id = get_physical_die_id(cpu);
1525 for (i = 0; i < get_topo_max_cpus(); ++i) {
1526 if (pkg_id != get_physical_package_id(i) ||
1527 die_id != get_physical_die_id(i))
1528 continue;
1529
1530 if (CPU_ISSET_S(i, pbf_info->core_cpumask_size,
1531 pbf_info->core_cpumask))
1532 freq = freq_high;
1533 else
1534 freq = freq_low;
1535
1536 set_cpufreq_scaling_min_max(i, 1, freq);
1537 set_cpufreq_scaling_min_max(i, 0, freq);
1538 }
1539
1540 return 0;
1541 }
1542
1543 static int set_cpufreq_scaling_min_max_from_cpuinfo(int cpu, int cpuinfo_max, int scaling_max)
1544 {
1545 char buffer[128], min_freq[16];
1546 int fd, ret, len;
1547
1548 if (!CPU_ISSET_S(cpu, present_cpumask_size, present_cpumask))
1549 return -1;
1550
1551 if (cpuinfo_max)
1552 snprintf(buffer, sizeof(buffer),
1553 "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", cpu);
1554 else
1555 snprintf(buffer, sizeof(buffer),
1556 "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_min_freq", cpu);
1557
1558 fd = open(buffer, O_RDONLY);
1559 if (fd < 0)
1560 return fd;
1561
1562 len = read(fd, min_freq, sizeof(min_freq));
1563 close(fd);
1564
1565 if (len < 0)
1566 return len;
1567
1568 if (scaling_max)
1569 snprintf(buffer, sizeof(buffer),
1570 "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu);
1571 else
1572 snprintf(buffer, sizeof(buffer),
1573 "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu);
1574
1575 fd = open(buffer, O_WRONLY);
1576 if (fd < 0)
1577 return fd;
1578
1579 len = strlen(min_freq);
1580 ret = write(fd, min_freq, len);
1581 if (ret == -1) {
1582 close(fd);
1583 return ret;
1584 }
1585 close(fd);
1586
1587 return 0;
1588 }
1589
1590 static void set_scaling_min_to_cpuinfo_max(int cpu)
1591 {
1592 int i, pkg_id, die_id;
1593
1594 pkg_id = get_physical_package_id(cpu);
1595 die_id = get_physical_die_id(cpu);
1596 for (i = 0; i < get_topo_max_cpus(); ++i) {
1597 if (pkg_id != get_physical_package_id(i) ||
1598 die_id != get_physical_die_id(i))
1599 continue;
1600
1601 adjust_scaling_max_from_base_freq(i);
1602 set_cpufreq_scaling_min_max_from_cpuinfo(i, 1, 0);
1603 adjust_scaling_min_from_base_freq(i);
1604 }
1605 }
1606
1607 static void set_scaling_min_to_cpuinfo_min(int cpu)
1608 {
1609 int i, pkg_id, die_id;
1610
1611 pkg_id = get_physical_package_id(cpu);
1612 die_id = get_physical_die_id(cpu);
1613 for (i = 0; i < get_topo_max_cpus(); ++i) {
1614 if (pkg_id != get_physical_package_id(i) ||
1615 die_id != get_physical_die_id(i))
1616 continue;
1617
1618 adjust_scaling_max_from_base_freq(i);
1619 set_cpufreq_scaling_min_max_from_cpuinfo(i, 0, 0);
1620 }
1621 }
1622
1623 static void set_scaling_max_to_cpuinfo_max(int cpu)
1624 {
1625 int i, pkg_id, die_id;
1626
1627 pkg_id = get_physical_package_id(cpu);
1628 die_id = get_physical_die_id(cpu);
1629 for (i = 0; i < get_topo_max_cpus(); ++i) {
1630 if (pkg_id != get_physical_package_id(i) ||
1631 die_id != get_physical_die_id(i))
1632 continue;
1633
1634 set_cpufreq_scaling_min_max_from_cpuinfo(i, 1, 1);
1635 }
1636 }
1637
1638 static int set_core_priority_and_min(int cpu, int mask_size,
1639 cpu_set_t *cpu_mask, int min_high,
1640 int min_low)
1641 {
1642 int pkg_id, die_id, ret, i;
1643
1644 if (!CPU_COUNT_S(mask_size, cpu_mask))
1645 return -1;
1646
1647 ret = set_clos_param(cpu, 0, 0, 0, min_high, 0xff);
1648 if (ret)
1649 return ret;
1650
1651 ret = set_clos_param(cpu, 1, 15, 15, min_low, 0xff);
1652 if (ret)
1653 return ret;
1654
1655 ret = set_clos_param(cpu, 2, 15, 15, min_low, 0xff);
1656 if (ret)
1657 return ret;
1658
1659 ret = set_clos_param(cpu, 3, 15, 15, min_low, 0xff);
1660 if (ret)
1661 return ret;
1662
1663 pkg_id = get_physical_package_id(cpu);
1664 die_id = get_physical_die_id(cpu);
1665 for (i = 0; i < get_topo_max_cpus(); ++i) {
1666 int clos;
1667
1668 if (pkg_id != get_physical_package_id(i) ||
1669 die_id != get_physical_die_id(i))
1670 continue;
1671
1672 if (CPU_ISSET_S(i, mask_size, cpu_mask))
1673 clos = 0;
1674 else
1675 clos = 3;
1676
1677 debug_printf("Associate cpu: %d clos: %d\n", i, clos);
1678 ret = isst_clos_associate(i, clos);
1679 if (ret) {
1680 isst_display_error_info_message(1, "isst_clos_associate failed", 0, 0);
1681 return ret;
1682 }
1683 }
1684
1685 return 0;
1686 }
1687
1688 static int set_pbf_core_power(int cpu)
1689 {
1690 struct isst_pbf_info pbf_info;
1691 struct isst_pkg_ctdp pkg_dev;
1692 int ret;
1693
1694 ret = isst_get_ctdp_levels(cpu, &pkg_dev);
1695 if (ret) {
1696 debug_printf("isst_get_ctdp_levels failed");
1697 return ret;
1698 }
1699 debug_printf("Current_level: %d\n", pkg_dev.current_level);
1700
1701 ret = isst_get_pbf_info(cpu, pkg_dev.current_level, &pbf_info);
1702 if (ret) {
1703 debug_printf("isst_get_pbf_info failed");
1704 return ret;
1705 }
1706 debug_printf("p1_high: %d p1_low: %d\n", pbf_info.p1_high,
1707 pbf_info.p1_low);
1708
1709 ret = set_core_priority_and_min(cpu, pbf_info.core_cpumask_size,
1710 pbf_info.core_cpumask,
1711 pbf_info.p1_high, pbf_info.p1_low);
1712 if (ret) {
1713 debug_printf("set_core_priority_and_min failed");
1714 return ret;
1715 }
1716
1717 ret = isst_pm_qos_config(cpu, 1, 1);
1718 if (ret) {
1719 debug_printf("isst_pm_qos_config failed");
1720 return ret;
1721 }
1722
1723 return 0;
1724 }
1725
1726 static void set_pbf_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1727 void *arg4)
1728 {
1729 struct isst_pkg_ctdp_level_info ctdp_level;
1730 struct isst_pkg_ctdp pkg_dev;
1731 int ret;
1732 int status = *(int *)arg4;
1733
1734 if (is_clx_n_platform()) {
1735 ret = 0;
1736 if (status) {
1737 set_clx_pbf_cpufreq_scaling_min_max(cpu);
1738
1739 } else {
1740 set_scaling_max_to_cpuinfo_max(cpu);
1741 set_scaling_min_to_cpuinfo_min(cpu);
1742 }
1743 goto disp_result;
1744 }
1745
1746 ret = isst_get_ctdp_levels(cpu, &pkg_dev);
1747 if (ret) {
1748 isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
1749 goto disp_result;
1750 }
1751
1752 ret = isst_get_ctdp_control(cpu, pkg_dev.current_level, &ctdp_level);
1753 if (ret) {
1754 isst_display_error_info_message(1, "Failed to get current level", 0, 0);
1755 goto disp_result;
1756 }
1757
1758 if (!ctdp_level.pbf_support) {
1759 isst_display_error_info_message(1, "base-freq feature is not present at this level", 1, pkg_dev.current_level);
1760 ret = -1;
1761 goto disp_result;
1762 }
1763
1764 if (auto_mode && status) {
1765 ret = set_pbf_core_power(cpu);
1766 if (ret)
1767 goto disp_result;
1768 }
1769
1770 ret = isst_set_pbf_fact_status(cpu, 1, status);
1771 if (ret) {
1772 debug_printf("isst_set_pbf_fact_status failed");
1773 if (auto_mode)
1774 isst_pm_qos_config(cpu, 0, 0);
1775 } else {
1776 if (auto_mode) {
1777 if (status)
1778 set_scaling_min_to_cpuinfo_max(cpu);
1779 else
1780 set_scaling_min_to_cpuinfo_min(cpu);
1781 }
1782 }
1783
1784 if (auto_mode && !status)
1785 isst_pm_qos_config(cpu, 0, 1);
1786
1787 disp_result:
1788 if (status)
1789 isst_display_result(cpu, outf, "base-freq", "enable",
1790 ret);
1791 else
1792 isst_display_result(cpu, outf, "base-freq", "disable",
1793 ret);
1794 }
1795
1796 static void set_pbf_enable(int arg)
1797 {
1798 int enable = arg;
1799
1800 if (cmd_help) {
1801 if (enable) {
1802 fprintf(stderr,
1803 "Enable Intel Speed Select Technology base frequency feature\n");
1804 if (is_clx_n_platform()) {
1805 fprintf(stderr,
1806 "\tOn this platform this command doesn't enable feature in the hardware.\n");
1807 fprintf(stderr,
1808 "\tIt updates the cpufreq scaling_min_freq to match cpufreq base_frequency.\n");
1809 exit(0);
1810
1811 }
1812 fprintf(stderr,
1813 "\tOptional Arguments: -a|--auto : Use priority of cores to set core-power associations\n");
1814 } else {
1815
1816 if (is_clx_n_platform()) {
1817 fprintf(stderr,
1818 "\tOn this platform this command doesn't disable feature in the hardware.\n");
1819 fprintf(stderr,
1820 "\tIt updates the cpufreq scaling_min_freq to match cpuinfo_min_freq\n");
1821 exit(0);
1822 }
1823 fprintf(stderr,
1824 "Disable Intel Speed Select Technology base frequency feature\n");
1825 fprintf(stderr,
1826 "\tOptional Arguments: -a|--auto : Also disable core-power associations\n");
1827 }
1828 exit(0);
1829 }
1830
1831 isst_ctdp_display_information_start(outf);
1832 if (max_target_cpus)
1833 for_each_online_target_cpu_in_set(set_pbf_for_cpu, NULL, NULL,
1834 NULL, &enable);
1835 else
1836 for_each_online_package_in_set(set_pbf_for_cpu, NULL, NULL,
1837 NULL, &enable);
1838 isst_ctdp_display_information_end(outf);
1839 }
1840
1841 static void dump_fact_config_for_cpu(int cpu, void *arg1, void *arg2,
1842 void *arg3, void *arg4)
1843 {
1844 struct isst_fact_info fact_info;
1845 int ret;
1846
1847 ret = isst_get_fact_info(cpu, tdp_level, fact_bucket, &fact_info);
1848 if (ret) {
1849 isst_display_error_info_message(1, "Failed to get turbo-freq info at this level", 1, tdp_level);
1850 isst_ctdp_display_information_end(outf);
1851 exit(1);
1852 } else {
1853 isst_fact_display_information(cpu, outf, tdp_level, fact_bucket,
1854 fact_avx, &fact_info);
1855 }
1856 }
1857
1858 static void dump_fact_config(int arg)
1859 {
1860 if (cmd_help) {
1861 fprintf(stderr,
1862 "Print complete Intel Speed Select Technology turbo frequency configuration for a TDP level. Other arguments are optional.\n");
1863 fprintf(stderr,
1864 "\tArguments: -l|--level : Specify tdp level\n");
1865 fprintf(stderr,
1866 "\tArguments: -b|--bucket : Bucket index to dump\n");
1867 fprintf(stderr,
1868 "\tArguments: -r|--trl-type : Specify trl type: sse|avx2|avx512\n");
1869 exit(0);
1870 }
1871
1872 if (tdp_level == 0xff) {
1873 isst_display_error_info_message(1, "Invalid command: specify tdp_level\n", 0, 0);
1874 exit(1);
1875 }
1876
1877 isst_ctdp_display_information_start(outf);
1878 if (max_target_cpus)
1879 for_each_online_target_cpu_in_set(dump_fact_config_for_cpu,
1880 NULL, NULL, NULL, NULL);
1881 else
1882 for_each_online_package_in_set(dump_fact_config_for_cpu, NULL,
1883 NULL, NULL, NULL);
1884 isst_ctdp_display_information_end(outf);
1885 }
1886
1887 static void set_fact_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
1888 void *arg4)
1889 {
1890 struct isst_pkg_ctdp_level_info ctdp_level;
1891 struct isst_pkg_ctdp pkg_dev;
1892 int ret;
1893 int status = *(int *)arg4;
1894
1895 if (status && no_turbo()) {
1896 isst_display_error_info_message(1, "Turbo mode is disabled", 0, 0);
1897 ret = -1;
1898 goto disp_results;
1899 }
1900
1901 ret = isst_get_ctdp_levels(cpu, &pkg_dev);
1902 if (ret) {
1903 isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
1904 goto disp_results;
1905 }
1906
1907 ret = isst_get_ctdp_control(cpu, pkg_dev.current_level, &ctdp_level);
1908 if (ret) {
1909 isst_display_error_info_message(1, "Failed to get current level", 0, 0);
1910 goto disp_results;
1911 }
1912
1913 if (!ctdp_level.fact_support) {
1914 isst_display_error_info_message(1, "turbo-freq feature is not present at this level", 1, pkg_dev.current_level);
1915 ret = -1;
1916 goto disp_results;
1917 }
1918
1919 if (status) {
1920 ret = isst_pm_qos_config(cpu, 1, 1);
1921 if (ret)
1922 goto disp_results;
1923 }
1924
1925 ret = isst_set_pbf_fact_status(cpu, 0, status);
1926 if (ret) {
1927 debug_printf("isst_set_pbf_fact_status failed");
1928 if (auto_mode)
1929 isst_pm_qos_config(cpu, 0, 0);
1930
1931 goto disp_results;
1932 }
1933
1934
1935 if (status) {
1936 struct isst_pkg_ctdp pkg_dev;
1937
1938 ret = isst_get_ctdp_levels(cpu, &pkg_dev);
1939 if (!ret)
1940 ret = isst_set_trl(cpu, fact_trl);
1941 if (ret && auto_mode)
1942 isst_pm_qos_config(cpu, 0, 0);
1943 } else {
1944 if (auto_mode)
1945 isst_pm_qos_config(cpu, 0, 0);
1946 }
1947
1948 disp_results:
1949 if (status) {
1950 isst_display_result(cpu, outf, "turbo-freq", "enable", ret);
1951 if (ret)
1952 fact_enable_fail = ret;
1953 } else {
1954
1955 isst_set_trl_from_current_tdp(cpu, fact_trl);
1956 isst_display_result(cpu, outf, "turbo-freq", "disable", ret);
1957 }
1958 }
1959
1960 static void set_fact_enable(int arg)
1961 {
1962 int i, ret, enable = arg;
1963
1964 if (cmd_help) {
1965 if (enable) {
1966 fprintf(stderr,
1967 "Enable Intel Speed Select Technology Turbo frequency feature\n");
1968 fprintf(stderr,
1969 "Optional: -t|--trl : Specify turbo ratio limit\n");
1970 fprintf(stderr,
1971 "\tOptional Arguments: -a|--auto : Designate specified target CPUs with");
1972 fprintf(stderr,
1973 "-C|--cpu option as as high priority using core-power feature\n");
1974 } else {
1975 fprintf(stderr,
1976 "Disable Intel Speed Select Technology turbo frequency feature\n");
1977 fprintf(stderr,
1978 "Optional: -t|--trl : Specify turbo ratio limit\n");
1979 fprintf(stderr,
1980 "\tOptional Arguments: -a|--auto : Also disable core-power associations\n");
1981 }
1982 exit(0);
1983 }
1984
1985 isst_ctdp_display_information_start(outf);
1986 if (max_target_cpus)
1987 for_each_online_target_cpu_in_set(set_fact_for_cpu, NULL, NULL,
1988 NULL, &enable);
1989 else
1990 for_each_online_package_in_set(set_fact_for_cpu, NULL, NULL,
1991 NULL, &enable);
1992 isst_ctdp_display_information_end(outf);
1993
1994 if (!fact_enable_fail && enable && auto_mode) {
1995
1996
1997
1998
1999
2000 for (i = 0; i < get_topo_max_cpus(); ++i) {
2001 char buffer[128], sibling_list[128], *cpu_str;
2002 int fd, len;
2003
2004 if (!CPU_ISSET_S(i, target_cpumask_size, target_cpumask))
2005 continue;
2006
2007 snprintf(buffer, sizeof(buffer),
2008 "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", i);
2009
2010 fd = open(buffer, O_RDONLY);
2011 if (fd < 0)
2012 continue;
2013
2014 len = read(fd, sibling_list, sizeof(sibling_list));
2015 close(fd);
2016
2017 if (len < 0)
2018 continue;
2019
2020 cpu_str = strtok(sibling_list, ",");
2021 while (cpu_str != NULL) {
2022 int cpu;
2023
2024 sscanf(cpu_str, "%d", &cpu);
2025 CPU_SET_S(cpu, target_cpumask_size, target_cpumask);
2026 cpu_str = strtok(NULL, ",");
2027 }
2028 }
2029
2030 for (i = 0; i < get_topo_max_cpus(); ++i) {
2031 int clos;
2032
2033 if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
2034 continue;
2035
2036 ret = set_clos_param(i, 0, 0, 0, 0, 0xff);
2037 if (ret)
2038 goto error_disp;
2039
2040 ret = set_clos_param(i, 1, 15, 15, 0, 0xff);
2041 if (ret)
2042 goto error_disp;
2043
2044 ret = set_clos_param(i, 2, 15, 15, 0, 0xff);
2045 if (ret)
2046 goto error_disp;
2047
2048 ret = set_clos_param(i, 3, 15, 15, 0, 0xff);
2049 if (ret)
2050 goto error_disp;
2051
2052 if (CPU_ISSET_S(i, target_cpumask_size, target_cpumask))
2053 clos = 0;
2054 else
2055 clos = 3;
2056
2057 debug_printf("Associate cpu: %d clos: %d\n", i, clos);
2058 ret = isst_clos_associate(i, clos);
2059 if (ret)
2060 goto error_disp;
2061 }
2062 isst_display_result(-1, outf, "turbo-freq --auto", "enable", 0);
2063 }
2064
2065 return;
2066
2067 error_disp:
2068 isst_display_result(i, outf, "turbo-freq --auto", "enable", ret);
2069
2070 }
2071
2072 static void enable_clos_qos_config(int cpu, void *arg1, void *arg2, void *arg3,
2073 void *arg4)
2074 {
2075 int ret;
2076 int status = *(int *)arg4;
2077
2078 if (is_skx_based_platform())
2079 clos_priority_type = 1;
2080
2081 ret = isst_pm_qos_config(cpu, status, clos_priority_type);
2082 if (ret)
2083 isst_display_error_info_message(1, "isst_pm_qos_config failed", 0, 0);
2084
2085 if (status)
2086 isst_display_result(cpu, outf, "core-power", "enable",
2087 ret);
2088 else
2089 isst_display_result(cpu, outf, "core-power", "disable",
2090 ret);
2091 }
2092
2093 static void set_clos_enable(int arg)
2094 {
2095 int enable = arg;
2096
2097 if (cmd_help) {
2098 if (enable) {
2099 fprintf(stderr,
2100 "Enable core-power for a package/die\n");
2101 if (!is_skx_based_platform()) {
2102 fprintf(stderr,
2103 "\tClos Enable: Specify priority type with [--priority|-p]\n");
2104 fprintf(stderr, "\t\t 0: Proportional, 1: Ordered\n");
2105 }
2106 } else {
2107 fprintf(stderr,
2108 "Disable core-power: [No command arguments are required]\n");
2109 }
2110 exit(0);
2111 }
2112
2113 if (enable && cpufreq_sysfs_present()) {
2114 fprintf(stderr,
2115 "cpufreq subsystem and core-power enable will interfere with each other!\n");
2116 }
2117
2118 isst_ctdp_display_information_start(outf);
2119 if (max_target_cpus)
2120 for_each_online_target_cpu_in_set(enable_clos_qos_config, NULL,
2121 NULL, NULL, &enable);
2122 else
2123 for_each_online_package_in_set(enable_clos_qos_config, NULL,
2124 NULL, NULL, &enable);
2125 isst_ctdp_display_information_end(outf);
2126 }
2127
2128 static void dump_clos_config_for_cpu(int cpu, void *arg1, void *arg2,
2129 void *arg3, void *arg4)
2130 {
2131 struct isst_clos_config clos_config;
2132 int ret;
2133
2134 ret = isst_pm_get_clos(cpu, current_clos, &clos_config);
2135 if (ret)
2136 isst_display_error_info_message(1, "isst_pm_get_clos failed", 0, 0);
2137 else
2138 isst_clos_display_information(cpu, outf, current_clos,
2139 &clos_config);
2140 }
2141
2142 static void dump_clos_config(int arg)
2143 {
2144 if (cmd_help) {
2145 fprintf(stderr,
2146 "Print Intel Speed Select Technology core power configuration\n");
2147 fprintf(stderr,
2148 "\tArguments: [-c | --clos]: Specify clos id\n");
2149 exit(0);
2150 }
2151 if (current_clos < 0 || current_clos > 3) {
2152 isst_display_error_info_message(1, "Invalid clos id\n", 0, 0);
2153 isst_ctdp_display_information_end(outf);
2154 exit(0);
2155 }
2156
2157 isst_ctdp_display_information_start(outf);
2158 if (max_target_cpus)
2159 for_each_online_target_cpu_in_set(dump_clos_config_for_cpu,
2160 NULL, NULL, NULL, NULL);
2161 else
2162 for_each_online_package_in_set(dump_clos_config_for_cpu, NULL,
2163 NULL, NULL, NULL);
2164 isst_ctdp_display_information_end(outf);
2165 }
2166
2167 static void get_clos_info_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
2168 void *arg4)
2169 {
2170 int enable, ret, prio_type;
2171
2172 ret = isst_clos_get_clos_information(cpu, &enable, &prio_type);
2173 if (ret)
2174 isst_display_error_info_message(1, "isst_clos_get_info failed", 0, 0);
2175 else {
2176 int cp_state, cp_cap;
2177
2178 isst_read_pm_config(cpu, &cp_state, &cp_cap);
2179 isst_clos_display_clos_information(cpu, outf, enable, prio_type,
2180 cp_state, cp_cap);
2181 }
2182 }
2183
2184 static void dump_clos_info(int arg)
2185 {
2186 if (cmd_help) {
2187 fprintf(stderr,
2188 "Print Intel Speed Select Technology core power information\n");
2189 fprintf(stderr, "\t Optionally specify targeted cpu id with [--cpu|-c]\n");
2190 exit(0);
2191 }
2192
2193 isst_ctdp_display_information_start(outf);
2194 if (max_target_cpus)
2195 for_each_online_target_cpu_in_set(get_clos_info_for_cpu, NULL,
2196 NULL, NULL, NULL);
2197 else
2198 for_each_online_package_in_set(get_clos_info_for_cpu, NULL,
2199 NULL, NULL, NULL);
2200 isst_ctdp_display_information_end(outf);
2201
2202 }
2203
2204 static void set_clos_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
2205 void *arg4)
2206 {
2207 struct isst_clos_config clos_config;
2208 int ret;
2209
2210 clos_config.pkg_id = get_physical_package_id(cpu);
2211 clos_config.die_id = get_physical_die_id(cpu);
2212
2213 clos_config.epp = clos_epp;
2214 clos_config.clos_prop_prio = clos_prop_prio;
2215 clos_config.clos_min = clos_min;
2216 clos_config.clos_max = clos_max;
2217 clos_config.clos_desired = clos_desired;
2218 ret = isst_set_clos(cpu, current_clos, &clos_config);
2219 if (ret)
2220 isst_display_error_info_message(1, "isst_set_clos failed", 0, 0);
2221 else
2222 isst_display_result(cpu, outf, "core-power", "config", ret);
2223 }
2224
2225 static void set_clos_config(int arg)
2226 {
2227 if (cmd_help) {
2228 fprintf(stderr,
2229 "Set core-power configuration for one of the four clos ids\n");
2230 fprintf(stderr,
2231 "\tSpecify targeted clos id with [--clos|-c]\n");
2232 if (!is_skx_based_platform()) {
2233 fprintf(stderr, "\tSpecify clos EPP with [--epp|-e]\n");
2234 fprintf(stderr,
2235 "\tSpecify clos Proportional Priority [--weight|-w]\n");
2236 }
2237 fprintf(stderr, "\tSpecify clos min in MHz with [--min|-n]\n");
2238 fprintf(stderr, "\tSpecify clos max in MHz with [--max|-m]\n");
2239 exit(0);
2240 }
2241
2242 if (current_clos < 0 || current_clos > 3) {
2243 isst_display_error_info_message(1, "Invalid clos id\n", 0, 0);
2244 exit(0);
2245 }
2246 if (!is_skx_based_platform() && (clos_epp < 0 || clos_epp > 0x0F)) {
2247 fprintf(stderr, "clos epp is not specified or invalid, default: 0\n");
2248 clos_epp = 0;
2249 }
2250 if (!is_skx_based_platform() && (clos_prop_prio < 0 || clos_prop_prio > 0x0F)) {
2251 fprintf(stderr,
2252 "clos frequency weight is not specified or invalid, default: 0\n");
2253 clos_prop_prio = 0;
2254 }
2255 if (clos_min < 0) {
2256 fprintf(stderr, "clos min is not specified, default: 0\n");
2257 clos_min = 0;
2258 }
2259 if (clos_max < 0) {
2260 fprintf(stderr, "clos max is not specified, default: Max frequency (ratio 0xff)\n");
2261 clos_max = 0xff;
2262 }
2263 if (clos_desired) {
2264 fprintf(stderr, "clos desired is not supported on this platform\n");
2265 clos_desired = 0x00;
2266 }
2267
2268 isst_ctdp_display_information_start(outf);
2269 if (max_target_cpus)
2270 for_each_online_target_cpu_in_set(set_clos_config_for_cpu, NULL,
2271 NULL, NULL, NULL);
2272 else
2273 for_each_online_package_in_set(set_clos_config_for_cpu, NULL,
2274 NULL, NULL, NULL);
2275 isst_ctdp_display_information_end(outf);
2276 }
2277
2278 static void set_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
2279 void *arg4)
2280 {
2281 int ret;
2282
2283 ret = isst_clos_associate(cpu, current_clos);
2284 if (ret)
2285 debug_printf("isst_clos_associate failed");
2286 else
2287 isst_display_result(cpu, outf, "core-power", "assoc", ret);
2288 }
2289
2290 static void set_clos_assoc(int arg)
2291 {
2292 if (cmd_help) {
2293 fprintf(stderr, "Associate a clos id to a CPU\n");
2294 fprintf(stderr,
2295 "\tSpecify targeted clos id with [--clos|-c]\n");
2296 fprintf(stderr,
2297 "\tFor example to associate clos 1 to CPU 0: issue\n");
2298 fprintf(stderr,
2299 "\tintel-speed-select --cpu 0 core-power assoc --clos 1\n");
2300 exit(0);
2301 }
2302
2303 if (current_clos < 0 || current_clos > 3) {
2304 isst_display_error_info_message(1, "Invalid clos id\n", 0, 0);
2305 exit(0);
2306 }
2307 if (max_target_cpus)
2308 for_each_online_target_cpu_in_set(set_clos_assoc_for_cpu, NULL,
2309 NULL, NULL, NULL);
2310 else {
2311 isst_display_error_info_message(1, "Invalid target cpu. Specify with [-c|--cpu]", 0, 0);
2312 }
2313 }
2314
2315 static void get_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
2316 void *arg4)
2317 {
2318 int clos, ret;
2319
2320 ret = isst_clos_get_assoc_status(cpu, &clos);
2321 if (ret)
2322 isst_display_error_info_message(1, "isst_clos_get_assoc_status failed", 0, 0);
2323 else
2324 isst_clos_display_assoc_information(cpu, outf, clos);
2325 }
2326
2327 static void get_clos_assoc(int arg)
2328 {
2329 if (cmd_help) {
2330 fprintf(stderr, "Get associate clos id to a CPU\n");
2331 fprintf(stderr, "\tSpecify targeted cpu id with [--cpu|-c]\n");
2332 exit(0);
2333 }
2334
2335 if (!max_target_cpus) {
2336 isst_display_error_info_message(1, "Invalid target cpu. Specify with [-c|--cpu]", 0, 0);
2337 exit(0);
2338 }
2339
2340 isst_ctdp_display_information_start(outf);
2341 for_each_online_target_cpu_in_set(get_clos_assoc_for_cpu, NULL,
2342 NULL, NULL, NULL);
2343 isst_ctdp_display_information_end(outf);
2344 }
2345
2346 static void set_turbo_mode_for_cpu(int cpu, int status)
2347 {
2348 int base_freq;
2349
2350 if (status) {
2351 base_freq = get_cpufreq_base_freq(cpu);
2352 set_cpufreq_scaling_min_max(cpu, 1, base_freq);
2353 } else {
2354 set_scaling_max_to_cpuinfo_max(cpu);
2355 }
2356
2357 if (status) {
2358 isst_display_result(cpu, outf, "turbo-mode", "enable", 0);
2359 } else {
2360 isst_display_result(cpu, outf, "turbo-mode", "disable", 0);
2361 }
2362 }
2363
2364 static void set_turbo_mode(int arg)
2365 {
2366 int i, enable = arg;
2367
2368 if (cmd_help) {
2369 if (enable)
2370 fprintf(stderr, "Set turbo mode enable\n");
2371 else
2372 fprintf(stderr, "Set turbo mode disable\n");
2373 exit(0);
2374 }
2375
2376 isst_ctdp_display_information_start(outf);
2377
2378 for (i = 0; i < topo_max_cpus; ++i) {
2379 int online;
2380
2381 if (i)
2382 online = parse_int_file(
2383 1, "/sys/devices/system/cpu/cpu%d/online", i);
2384 else
2385 online =
2386 1;
2387
2388 if (online)
2389 set_turbo_mode_for_cpu(i, enable);
2390
2391 }
2392 isst_ctdp_display_information_end(outf);
2393 }
2394
2395 static void get_set_trl(int cpu, void *arg1, void *arg2, void *arg3,
2396 void *arg4)
2397 {
2398 unsigned long long trl;
2399 int set = *(int *)arg4;
2400 int ret;
2401
2402 if (set && !fact_trl) {
2403 isst_display_error_info_message(1, "Invalid TRL. Specify with [-t|--trl]", 0, 0);
2404 exit(0);
2405 }
2406
2407 if (set) {
2408 ret = isst_set_trl(cpu, fact_trl);
2409 isst_display_result(cpu, outf, "turbo-mode", "set-trl", ret);
2410 return;
2411 }
2412
2413 ret = isst_get_trl(cpu, &trl);
2414 if (ret)
2415 isst_display_result(cpu, outf, "turbo-mode", "get-trl", ret);
2416 else
2417 isst_trl_display_information(cpu, outf, trl);
2418 }
2419
2420 static void process_trl(int arg)
2421 {
2422 if (cmd_help) {
2423 if (arg) {
2424 fprintf(stderr, "Set TRL (turbo ratio limits)\n");
2425 fprintf(stderr, "\t t|--trl: Specify turbo ratio limit for setting TRL\n");
2426 } else {
2427 fprintf(stderr, "Get TRL (turbo ratio limits)\n");
2428 }
2429 exit(0);
2430 }
2431
2432 isst_ctdp_display_information_start(outf);
2433 if (max_target_cpus)
2434 for_each_online_target_cpu_in_set(get_set_trl, NULL,
2435 NULL, NULL, &arg);
2436 else
2437 for_each_online_package_in_set(get_set_trl, NULL,
2438 NULL, NULL, &arg);
2439 isst_ctdp_display_information_end(outf);
2440 }
2441
2442 static struct process_cmd_struct clx_n_cmds[] = {
2443 { "perf-profile", "info", dump_isst_config, 0 },
2444 { "base-freq", "info", dump_pbf_config, 0 },
2445 { "base-freq", "enable", set_pbf_enable, 1 },
2446 { "base-freq", "disable", set_pbf_enable, 0 },
2447 { NULL, NULL, NULL, 0 }
2448 };
2449
2450 static struct process_cmd_struct isst_cmds[] = {
2451 { "perf-profile", "get-lock-status", get_tdp_locked, 0 },
2452 { "perf-profile", "get-config-levels", get_tdp_levels, 0 },
2453 { "perf-profile", "get-config-version", get_tdp_version, 0 },
2454 { "perf-profile", "get-config-enabled", get_tdp_enabled, 0 },
2455 { "perf-profile", "get-config-current-level", get_tdp_current_level,
2456 0 },
2457 { "perf-profile", "set-config-level", set_tdp_level, 0 },
2458 { "perf-profile", "info", dump_isst_config, 0 },
2459 { "base-freq", "info", dump_pbf_config, 0 },
2460 { "base-freq", "enable", set_pbf_enable, 1 },
2461 { "base-freq", "disable", set_pbf_enable, 0 },
2462 { "turbo-freq", "info", dump_fact_config, 0 },
2463 { "turbo-freq", "enable", set_fact_enable, 1 },
2464 { "turbo-freq", "disable", set_fact_enable, 0 },
2465 { "core-power", "info", dump_clos_info, 0 },
2466 { "core-power", "enable", set_clos_enable, 1 },
2467 { "core-power", "disable", set_clos_enable, 0 },
2468 { "core-power", "config", set_clos_config, 0 },
2469 { "core-power", "get-config", dump_clos_config, 0 },
2470 { "core-power", "assoc", set_clos_assoc, 0 },
2471 { "core-power", "get-assoc", get_clos_assoc, 0 },
2472 { "turbo-mode", "enable", set_turbo_mode, 0 },
2473 { "turbo-mode", "disable", set_turbo_mode, 1 },
2474 { "turbo-mode", "get-trl", process_trl, 0 },
2475 { "turbo-mode", "set-trl", process_trl, 1 },
2476 { NULL, NULL, NULL }
2477 };
2478
2479
2480
2481
2482
2483 void parse_cpu_command(char *optarg)
2484 {
2485 unsigned int start, end;
2486 char *next;
2487
2488 next = optarg;
2489
2490 while (next && *next) {
2491 if (*next == '-')
2492 goto error;
2493
2494 start = strtoul(next, &next, 10);
2495
2496 if (max_target_cpus < MAX_CPUS_IN_ONE_REQ)
2497 target_cpus[max_target_cpus++] = start;
2498
2499 if (*next == '\0')
2500 break;
2501
2502 if (*next == ',') {
2503 next += 1;
2504 continue;
2505 }
2506
2507 if (*next == '-') {
2508 next += 1;
2509 } else if (*next == '.') {
2510 next += 1;
2511 if (*next == '.')
2512 next += 1;
2513 else
2514 goto error;
2515 }
2516
2517 end = strtoul(next, &next, 10);
2518 if (end <= start)
2519 goto error;
2520
2521 while (++start <= end) {
2522 if (max_target_cpus < MAX_CPUS_IN_ONE_REQ)
2523 target_cpus[max_target_cpus++] = start;
2524 }
2525
2526 if (*next == ',')
2527 next += 1;
2528 else if (*next != '\0')
2529 goto error;
2530 }
2531
2532 #ifdef DEBUG
2533 {
2534 int i;
2535
2536 for (i = 0; i < max_target_cpus; ++i)
2537 printf("cpu [%d] in arg\n", target_cpus[i]);
2538 }
2539 #endif
2540 return;
2541
2542 error:
2543 fprintf(stderr, "\"--cpu %s\" malformed\n", optarg);
2544 exit(-1);
2545 }
2546
2547 static void parse_cmd_args(int argc, int start, char **argv)
2548 {
2549 int opt;
2550 int option_index;
2551
2552 static struct option long_options[] = {
2553 { "bucket", required_argument, 0, 'b' },
2554 { "level", required_argument, 0, 'l' },
2555 { "online", required_argument, 0, 'o' },
2556 { "trl-type", required_argument, 0, 'r' },
2557 { "trl", required_argument, 0, 't' },
2558 { "help", no_argument, 0, 'h' },
2559 { "clos", required_argument, 0, 'c' },
2560 { "desired", required_argument, 0, 'd' },
2561 { "epp", required_argument, 0, 'e' },
2562 { "min", required_argument, 0, 'n' },
2563 { "max", required_argument, 0, 'm' },
2564 { "priority", required_argument, 0, 'p' },
2565 { "weight", required_argument, 0, 'w' },
2566 { "auto", no_argument, 0, 'a' },
2567 { 0, 0, 0, 0 }
2568 };
2569
2570 option_index = start;
2571
2572 optind = start + 1;
2573 while ((opt = getopt_long(argc, argv, "b:l:t:c:d:e:n:m:p:w:r:hoa",
2574 long_options, &option_index)) != -1) {
2575 switch (opt) {
2576 case 'a':
2577 auto_mode = 1;
2578 break;
2579 case 'b':
2580 fact_bucket = atoi(optarg);
2581 break;
2582 case 'h':
2583 cmd_help = 1;
2584 break;
2585 case 'l':
2586 tdp_level = atoi(optarg);
2587 break;
2588 case 'o':
2589 force_online_offline = 1;
2590 break;
2591 case 't':
2592 sscanf(optarg, "0x%llx", &fact_trl);
2593 break;
2594 case 'r':
2595 if (!strncmp(optarg, "sse", 3)) {
2596 fact_avx = 0x01;
2597 } else if (!strncmp(optarg, "avx2", 4)) {
2598 fact_avx = 0x02;
2599 } else if (!strncmp(optarg, "avx512", 6)) {
2600 fact_avx = 0x04;
2601 } else {
2602 fprintf(outf, "Invalid sse,avx options\n");
2603 exit(1);
2604 }
2605 break;
2606
2607 case 'c':
2608 current_clos = atoi(optarg);
2609 break;
2610 case 'd':
2611 clos_desired = atoi(optarg);
2612 clos_desired /= DISP_FREQ_MULTIPLIER;
2613 break;
2614 case 'e':
2615 clos_epp = atoi(optarg);
2616 if (is_skx_based_platform()) {
2617 isst_display_error_info_message(1, "epp can't be specified on this platform", 0, 0);
2618 exit(0);
2619 }
2620 break;
2621 case 'n':
2622 clos_min = atoi(optarg);
2623 clos_min /= DISP_FREQ_MULTIPLIER;
2624 break;
2625 case 'm':
2626 clos_max = atoi(optarg);
2627 clos_max /= DISP_FREQ_MULTIPLIER;
2628 break;
2629 case 'p':
2630 clos_priority_type = atoi(optarg);
2631 if (is_skx_based_platform() && !clos_priority_type) {
2632 isst_display_error_info_message(1, "Invalid clos priority type: proportional for this platform", 0, 0);
2633 exit(0);
2634 }
2635 break;
2636 case 'w':
2637 clos_prop_prio = atoi(optarg);
2638 if (is_skx_based_platform()) {
2639 isst_display_error_info_message(1, "weight can't be specified on this platform", 0, 0);
2640 exit(0);
2641 }
2642 break;
2643 default:
2644 printf("Unknown option: ignore\n");
2645 }
2646 }
2647
2648 if (argv[optind])
2649 printf("Garbage at the end of command: ignore\n");
2650 }
2651
2652 static void isst_help(void)
2653 {
2654 printf("perf-profile:\tAn architectural mechanism that allows multiple optimized \n\
2655 performance profiles per system via static and/or dynamic\n\
2656 adjustment of core count, workload, Tjmax, and\n\
2657 TDP, etc.\n");
2658 printf("\nCommands : For feature=perf-profile\n");
2659 printf("\tinfo\n");
2660
2661 if (!is_clx_n_platform()) {
2662 printf("\tget-lock-status\n");
2663 printf("\tget-config-levels\n");
2664 printf("\tget-config-version\n");
2665 printf("\tget-config-enabled\n");
2666 printf("\tget-config-current-level\n");
2667 printf("\tset-config-level\n");
2668 }
2669 }
2670
2671 static void pbf_help(void)
2672 {
2673 printf("base-freq:\tEnables users to increase guaranteed base frequency\n\
2674 on certain cores (high priority cores) in exchange for lower\n\
2675 base frequency on remaining cores (low priority cores).\n");
2676 printf("\tcommand : info\n");
2677 printf("\tcommand : enable\n");
2678 printf("\tcommand : disable\n");
2679 }
2680
2681 static void fact_help(void)
2682 {
2683 printf("turbo-freq:\tEnables the ability to set different turbo ratio\n\
2684 limits to cores based on priority.\n");
2685 printf("\nCommand: For feature=turbo-freq\n");
2686 printf("\tcommand : info\n");
2687 printf("\tcommand : enable\n");
2688 printf("\tcommand : disable\n");
2689 }
2690
2691 static void turbo_mode_help(void)
2692 {
2693 printf("turbo-mode:\tEnables users to enable/disable turbo mode by adjusting frequency settings. Also allows to get and set turbo ratio limits (TRL).\n");
2694 printf("\tcommand : enable\n");
2695 printf("\tcommand : disable\n");
2696 printf("\tcommand : get-trl\n");
2697 printf("\tcommand : set-trl\n");
2698 }
2699
2700
2701 static void core_power_help(void)
2702 {
2703 printf("core-power:\tInterface that allows user to define per core/tile\n\
2704 priority.\n");
2705 printf("\nCommands : For feature=core-power\n");
2706 printf("\tinfo\n");
2707 printf("\tenable\n");
2708 printf("\tdisable\n");
2709 printf("\tconfig\n");
2710 printf("\tget-config\n");
2711 printf("\tassoc\n");
2712 printf("\tget-assoc\n");
2713 }
2714
2715 struct process_cmd_help_struct {
2716 char *feature;
2717 void (*process_fn)(void);
2718 };
2719
2720 static struct process_cmd_help_struct isst_help_cmds[] = {
2721 { "perf-profile", isst_help },
2722 { "base-freq", pbf_help },
2723 { "turbo-freq", fact_help },
2724 { "core-power", core_power_help },
2725 { "turbo-mode", turbo_mode_help },
2726 { NULL, NULL }
2727 };
2728
2729 static struct process_cmd_help_struct clx_n_help_cmds[] = {
2730 { "perf-profile", isst_help },
2731 { "base-freq", pbf_help },
2732 { NULL, NULL }
2733 };
2734
2735 void process_command(int argc, char **argv,
2736 struct process_cmd_help_struct *help_cmds,
2737 struct process_cmd_struct *cmds)
2738 {
2739 int i = 0, matched = 0;
2740 char *feature = argv[optind];
2741 char *cmd = argv[optind + 1];
2742
2743 if (!feature || !cmd)
2744 return;
2745
2746 debug_printf("feature name [%s] command [%s]\n", feature, cmd);
2747 if (!strcmp(cmd, "-h") || !strcmp(cmd, "--help")) {
2748 while (help_cmds[i].feature) {
2749 if (!strcmp(help_cmds[i].feature, feature)) {
2750 help_cmds[i].process_fn();
2751 exit(0);
2752 }
2753 ++i;
2754 }
2755 }
2756
2757 if (!is_clx_n_platform())
2758 create_cpu_map();
2759
2760 i = 0;
2761 while (cmds[i].feature) {
2762 if (!strcmp(cmds[i].feature, feature) &&
2763 !strcmp(cmds[i].command, cmd)) {
2764 parse_cmd_args(argc, optind + 1, argv);
2765 cmds[i].process_fn(cmds[i].arg);
2766 matched = 1;
2767 break;
2768 }
2769 ++i;
2770 }
2771
2772 if (!matched)
2773 fprintf(stderr, "Invalid command\n");
2774 }
2775
2776 static void usage(void)
2777 {
2778 if (is_clx_n_platform()) {
2779 fprintf(stderr, "\nThere is limited support of Intel Speed Select features on this platform.\n");
2780 fprintf(stderr, "Everything is pre-configured using BIOS options, this tool can't enable any feature in the hardware.\n\n");
2781 }
2782
2783 printf("\nUsage:\n");
2784 printf("intel-speed-select [OPTIONS] FEATURE COMMAND COMMAND_ARGUMENTS\n");
2785 printf("\nUse this tool to enumerate and control the Intel Speed Select Technology features:\n");
2786 if (is_clx_n_platform())
2787 printf("\nFEATURE : [perf-profile|base-freq]\n");
2788 else
2789 printf("\nFEATURE : [perf-profile|base-freq|turbo-freq|core-power|turbo-mode]\n");
2790 printf("\nFor help on each feature, use -h|--help\n");
2791 printf("\tFor example: intel-speed-select perf-profile -h\n");
2792
2793 printf("\nFor additional help on each command for a feature, use --h|--help\n");
2794 printf("\tFor example: intel-speed-select perf-profile get-lock-status -h\n");
2795 printf("\t\t This will print help for the command \"get-lock-status\" for the feature \"perf-profile\"\n");
2796
2797 printf("\nOPTIONS\n");
2798 printf("\t[-c|--cpu] : logical cpu number\n");
2799 printf("\t\tDefault: Die scoped for all dies in the system with multiple dies/package\n");
2800 printf("\t\t\t Or Package scoped for all Packages when each package contains one die\n");
2801 printf("\t[-d|--debug] : Debug mode\n");
2802 printf("\t[-f|--format] : output format [json|text]. Default: text\n");
2803 printf("\t[-h|--help] : Print help\n");
2804 printf("\t[-i|--info] : Print platform information\n");
2805 printf("\t[-a|--all-cpus-online] : Force online every CPU in the system\n");
2806 printf("\t[-o|--out] : Output file\n");
2807 printf("\t\t\tDefault : stderr\n");
2808 printf("\t[-p|--pause] : Delay between two mail box commands in milliseconds\n");
2809 printf("\t[-r|--retry] : Retry count for mail box commands on failure, default 3\n");
2810 printf("\t[-v|--version] : Print version\n");
2811 printf("\t[-b|--oob : Start a daemon to process HFI events for perf profile change from Out of Band agent.\n");
2812 printf("\t[-n|--no-daemon : Don't run as daemon. By default --oob will turn on daemon mode\n");
2813 printf("\t[-w|--delay : Delay for reading config level state change in OOB poll mode.\n");
2814 printf("\nResult format\n");
2815 printf("\tResult display uses a common format for each command:\n");
2816 printf("\tResults are formatted in text/JSON with\n");
2817 printf("\t\tPackage, Die, CPU, and command specific results.\n");
2818
2819 printf("\nExamples\n");
2820 printf("\tTo get platform information:\n");
2821 printf("\t\tintel-speed-select --info\n");
2822 printf("\tTo get full perf-profile information dump:\n");
2823 printf("\t\tintel-speed-select perf-profile info\n");
2824 printf("\tTo get full base-freq information dump:\n");
2825 printf("\t\tintel-speed-select base-freq info -l 0\n");
2826 if (!is_clx_n_platform()) {
2827 printf("\tTo get full turbo-freq information dump:\n");
2828 printf("\t\tintel-speed-select turbo-freq info -l 0\n");
2829 }
2830 exit(1);
2831 }
2832
2833 static void print_version(void)
2834 {
2835 fprintf(outf, "Version %s\n", version_str);
2836 exit(0);
2837 }
2838
2839 static void cmdline(int argc, char **argv)
2840 {
2841 const char *pathname = "/dev/isst_interface";
2842 char *ptr;
2843 FILE *fp;
2844 int opt, force_cpus_online = 0;
2845 int option_index = 0;
2846 int ret;
2847 int oob_mode = 0;
2848 int poll_interval = -1;
2849 int no_daemon = 0;
2850
2851 static struct option long_options[] = {
2852 { "all-cpus-online", no_argument, 0, 'a' },
2853 { "cpu", required_argument, 0, 'c' },
2854 { "debug", no_argument, 0, 'd' },
2855 { "format", required_argument, 0, 'f' },
2856 { "help", no_argument, 0, 'h' },
2857 { "info", no_argument, 0, 'i' },
2858 { "pause", required_argument, 0, 'p' },
2859 { "out", required_argument, 0, 'o' },
2860 { "retry", required_argument, 0, 'r' },
2861 { "version", no_argument, 0, 'v' },
2862 { "oob", no_argument, 0, 'b' },
2863 { "no-daemon", no_argument, 0, 'n' },
2864 { "poll-interval", required_argument, 0, 'w' },
2865 { 0, 0, 0, 0 }
2866 };
2867
2868 if (geteuid() != 0) {
2869 fprintf(stderr, "Must run as root\n");
2870 exit(0);
2871 }
2872
2873 ret = update_cpu_model();
2874 if (ret)
2875 err(-1, "Invalid CPU model (%d)\n", cpu_model);
2876 printf("Intel(R) Speed Select Technology\n");
2877 printf("Executing on CPU model:%d[0x%x]\n", cpu_model, cpu_model);
2878
2879 if (!is_clx_n_platform()) {
2880 fp = fopen(pathname, "rb");
2881 if (!fp) {
2882 fprintf(stderr, "Intel speed select drivers are not loaded on this system.\n");
2883 fprintf(stderr, "Verify that kernel config includes CONFIG_INTEL_SPEED_SELECT_INTERFACE.\n");
2884 fprintf(stderr, "If the config is included then this is not a supported platform.\n");
2885 exit(0);
2886 }
2887 fclose(fp);
2888 }
2889
2890 progname = argv[0];
2891 while ((opt = getopt_long_only(argc, argv, "+c:df:hio:vabw:n", long_options,
2892 &option_index)) != -1) {
2893 switch (opt) {
2894 case 'a':
2895 force_cpus_online = 1;
2896 break;
2897 case 'c':
2898 parse_cpu_command(optarg);
2899 break;
2900 case 'd':
2901 debug_flag = 1;
2902 printf("Debug Mode ON\n");
2903 break;
2904 case 'f':
2905 if (!strncmp(optarg, "json", 4))
2906 out_format_json = 1;
2907 break;
2908 case 'h':
2909 usage();
2910 break;
2911 case 'i':
2912 isst_print_platform_information();
2913 break;
2914 case 'o':
2915 if (outf)
2916 fclose(outf);
2917 outf = fopen_or_exit(optarg, "w");
2918 break;
2919 case 'p':
2920 ret = strtol(optarg, &ptr, 10);
2921 if (!ret)
2922 fprintf(stderr, "Invalid pause interval, ignore\n");
2923 else
2924 mbox_delay = ret;
2925 break;
2926 case 'r':
2927 ret = strtol(optarg, &ptr, 10);
2928 if (!ret)
2929 fprintf(stderr, "Invalid retry count, ignore\n");
2930 else
2931 mbox_retries = ret;
2932 break;
2933 case 'v':
2934 print_version();
2935 break;
2936 case 'b':
2937 oob_mode = 1;
2938 break;
2939 case 'n':
2940 no_daemon = 1;
2941 break;
2942 case 'w':
2943 ret = strtol(optarg, &ptr, 10);
2944 if (!ret) {
2945 fprintf(stderr, "Invalid poll interval count\n");
2946 exit(0);
2947 }
2948 poll_interval = ret;
2949 break;
2950 default:
2951 usage();
2952 }
2953 }
2954
2955 if (optind > (argc - 2) && !oob_mode) {
2956 usage();
2957 exit(0);
2958 }
2959 set_max_cpu_num();
2960 if (force_cpus_online)
2961 force_all_cpus_online();
2962 store_cpu_topology();
2963 set_cpu_present_cpu_mask();
2964 set_cpu_target_cpu_mask();
2965
2966 if (oob_mode) {
2967 create_cpu_map();
2968 if (debug_flag)
2969 fprintf(stderr, "OOB mode is enabled in debug mode\n");
2970
2971 ret = isst_daemon(debug_flag, poll_interval, no_daemon);
2972 if (ret)
2973 fprintf(stderr, "OOB mode enable failed\n");
2974 goto out;
2975 }
2976
2977 if (!is_clx_n_platform()) {
2978 ret = isst_fill_platform_info();
2979 if (ret)
2980 goto out;
2981 process_command(argc, argv, isst_help_cmds, isst_cmds);
2982 } else {
2983 process_command(argc, argv, clx_n_help_cmds, clx_n_cmds);
2984 }
2985 out:
2986 free_cpu_set(present_cpumask);
2987 free_cpu_set(target_cpumask);
2988 }
2989
2990 int main(int argc, char **argv)
2991 {
2992 outf = stderr;
2993 cmdline(argc, argv);
2994 return 0;
2995 }