162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Intel Speed Select -- Enumerate and control features 462306a36Sopenharmony_ci * Copyright (c) 2019 Intel Corporation. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/isst_if.h> 862306a36Sopenharmony_ci#include <sys/utsname.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include "isst.h" 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_cistruct process_cmd_struct { 1362306a36Sopenharmony_ci char *feature; 1462306a36Sopenharmony_ci char *command; 1562306a36Sopenharmony_ci void (*process_fn)(int arg); 1662306a36Sopenharmony_ci int arg; 1762306a36Sopenharmony_ci}; 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistatic const char *version_str = "v1.17"; 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_cistatic const int supported_api_ver = 2; 2262306a36Sopenharmony_cistatic struct isst_if_platform_info isst_platform_info; 2362306a36Sopenharmony_cistatic char *progname; 2462306a36Sopenharmony_cistatic int debug_flag; 2562306a36Sopenharmony_cistatic FILE *outf; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic int cpu_model; 2862306a36Sopenharmony_cistatic int cpu_stepping; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define MAX_CPUS_IN_ONE_REQ 256 3162306a36Sopenharmony_cistatic short max_target_cpus; 3262306a36Sopenharmony_cistatic unsigned short target_cpus[MAX_CPUS_IN_ONE_REQ]; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic int topo_max_cpus; 3562306a36Sopenharmony_cistatic size_t present_cpumask_size; 3662306a36Sopenharmony_cistatic cpu_set_t *present_cpumask; 3762306a36Sopenharmony_cistatic size_t target_cpumask_size; 3862306a36Sopenharmony_cistatic cpu_set_t *target_cpumask; 3962306a36Sopenharmony_cistatic int tdp_level = 0xFF; 4062306a36Sopenharmony_cistatic int fact_bucket = 0xFF; 4162306a36Sopenharmony_cistatic int fact_avx = 0xFF; 4262306a36Sopenharmony_cistatic unsigned long long fact_trl; 4362306a36Sopenharmony_cistatic int out_format_json; 4462306a36Sopenharmony_cistatic int cmd_help; 4562306a36Sopenharmony_cistatic int force_online_offline; 4662306a36Sopenharmony_cistatic int auto_mode; 4762306a36Sopenharmony_cistatic int fact_enable_fail; 4862306a36Sopenharmony_cistatic int cgroupv2; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci/* clos related */ 5162306a36Sopenharmony_cistatic int current_clos = -1; 5262306a36Sopenharmony_cistatic int clos_epp = -1; 5362306a36Sopenharmony_cistatic int clos_prop_prio = -1; 5462306a36Sopenharmony_cistatic int clos_min = -1; 5562306a36Sopenharmony_cistatic int clos_max = -1; 5662306a36Sopenharmony_cistatic int clos_desired = -1; 5762306a36Sopenharmony_cistatic int clos_priority_type; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistruct _cpu_map { 6062306a36Sopenharmony_ci unsigned short core_id; 6162306a36Sopenharmony_ci unsigned short pkg_id; 6262306a36Sopenharmony_ci unsigned short die_id; 6362306a36Sopenharmony_ci unsigned short punit_id; 6462306a36Sopenharmony_ci unsigned short punit_cpu; 6562306a36Sopenharmony_ci unsigned short punit_cpu_core; 6662306a36Sopenharmony_ci unsigned short initialized; 6762306a36Sopenharmony_ci}; 6862306a36Sopenharmony_cistruct _cpu_map *cpu_map; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistruct cpu_topology { 7162306a36Sopenharmony_ci short cpu; 7262306a36Sopenharmony_ci short core_id; 7362306a36Sopenharmony_ci short pkg_id; 7462306a36Sopenharmony_ci short die_id; 7562306a36Sopenharmony_ci}; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ciFILE *get_output_file(void) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci return outf; 8062306a36Sopenharmony_ci} 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ciint is_debug_enabled(void) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci return debug_flag; 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_civoid debug_printf(const char *format, ...) 8862306a36Sopenharmony_ci{ 8962306a36Sopenharmony_ci va_list args; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci va_start(args, format); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci if (debug_flag) 9462306a36Sopenharmony_ci vprintf(format, args); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci va_end(args); 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ciint is_clx_n_platform(void) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci if (cpu_model == 0x55) 10362306a36Sopenharmony_ci if (cpu_stepping == 0x6 || cpu_stepping == 0x7) 10462306a36Sopenharmony_ci return 1; 10562306a36Sopenharmony_ci return 0; 10662306a36Sopenharmony_ci} 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ciint is_skx_based_platform(void) 10962306a36Sopenharmony_ci{ 11062306a36Sopenharmony_ci if (cpu_model == 0x55) 11162306a36Sopenharmony_ci return 1; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci return 0; 11462306a36Sopenharmony_ci} 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ciint is_spr_platform(void) 11762306a36Sopenharmony_ci{ 11862306a36Sopenharmony_ci if (cpu_model == 0x8F) 11962306a36Sopenharmony_ci return 1; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci return 0; 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ciint is_emr_platform(void) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci if (cpu_model == 0xCF) 12762306a36Sopenharmony_ci return 1; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci return 0; 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ciint is_icx_platform(void) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci if (cpu_model == 0x6A || cpu_model == 0x6C) 13662306a36Sopenharmony_ci return 1; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci return 0; 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistatic int update_cpu_model(void) 14262306a36Sopenharmony_ci{ 14362306a36Sopenharmony_ci unsigned int ebx, ecx, edx; 14462306a36Sopenharmony_ci unsigned int fms, family; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci __cpuid(1, fms, ebx, ecx, edx); 14762306a36Sopenharmony_ci family = (fms >> 8) & 0xf; 14862306a36Sopenharmony_ci cpu_model = (fms >> 4) & 0xf; 14962306a36Sopenharmony_ci if (family == 6 || family == 0xf) 15062306a36Sopenharmony_ci cpu_model += ((fms >> 16) & 0xf) << 4; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci cpu_stepping = fms & 0xf; 15362306a36Sopenharmony_ci /* only three CascadeLake-N models are supported */ 15462306a36Sopenharmony_ci if (is_clx_n_platform()) { 15562306a36Sopenharmony_ci FILE *fp; 15662306a36Sopenharmony_ci size_t n = 0; 15762306a36Sopenharmony_ci char *line = NULL; 15862306a36Sopenharmony_ci int ret = 1; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci fp = fopen("/proc/cpuinfo", "r"); 16162306a36Sopenharmony_ci if (!fp) 16262306a36Sopenharmony_ci err(-1, "cannot open /proc/cpuinfo\n"); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci while (getline(&line, &n, fp) > 0) { 16562306a36Sopenharmony_ci if (strstr(line, "model name")) { 16662306a36Sopenharmony_ci if (strstr(line, "6252N") || 16762306a36Sopenharmony_ci strstr(line, "6230N") || 16862306a36Sopenharmony_ci strstr(line, "5218N")) 16962306a36Sopenharmony_ci ret = 0; 17062306a36Sopenharmony_ci break; 17162306a36Sopenharmony_ci } 17262306a36Sopenharmony_ci } 17362306a36Sopenharmony_ci free(line); 17462306a36Sopenharmony_ci fclose(fp); 17562306a36Sopenharmony_ci return ret; 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci return 0; 17862306a36Sopenharmony_ci} 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ciint api_version(void) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci return isst_platform_info.api_version; 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci/* Open a file, and exit on failure */ 18662306a36Sopenharmony_cistatic FILE *fopen_or_exit(const char *path, const char *mode) 18762306a36Sopenharmony_ci{ 18862306a36Sopenharmony_ci FILE *filep = fopen(path, mode); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci if (!filep) 19162306a36Sopenharmony_ci err(1, "%s: open failed", path); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci return filep; 19462306a36Sopenharmony_ci} 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci/* Parse a file containing a single int */ 19762306a36Sopenharmony_cistatic int parse_int_file(int fatal, const char *fmt, ...) 19862306a36Sopenharmony_ci{ 19962306a36Sopenharmony_ci va_list args; 20062306a36Sopenharmony_ci char path[PATH_MAX]; 20162306a36Sopenharmony_ci FILE *filep; 20262306a36Sopenharmony_ci int value; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci va_start(args, fmt); 20562306a36Sopenharmony_ci vsnprintf(path, sizeof(path), fmt, args); 20662306a36Sopenharmony_ci va_end(args); 20762306a36Sopenharmony_ci if (fatal) { 20862306a36Sopenharmony_ci filep = fopen_or_exit(path, "r"); 20962306a36Sopenharmony_ci } else { 21062306a36Sopenharmony_ci filep = fopen(path, "r"); 21162306a36Sopenharmony_ci if (!filep) 21262306a36Sopenharmony_ci return -1; 21362306a36Sopenharmony_ci } 21462306a36Sopenharmony_ci if (fscanf(filep, "%d", &value) != 1) 21562306a36Sopenharmony_ci err(1, "%s: failed to parse number from file", path); 21662306a36Sopenharmony_ci fclose(filep); 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci return value; 21962306a36Sopenharmony_ci} 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ciint cpufreq_sysfs_present(void) 22262306a36Sopenharmony_ci{ 22362306a36Sopenharmony_ci DIR *dir; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci dir = opendir("/sys/devices/system/cpu/cpu0/cpufreq"); 22662306a36Sopenharmony_ci if (dir) { 22762306a36Sopenharmony_ci closedir(dir); 22862306a36Sopenharmony_ci return 1; 22962306a36Sopenharmony_ci } 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci return 0; 23262306a36Sopenharmony_ci} 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ciint out_format_is_json(void) 23562306a36Sopenharmony_ci{ 23662306a36Sopenharmony_ci return out_format_json; 23762306a36Sopenharmony_ci} 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_cistatic int get_stored_topology_info(int cpu, int *core_id, int *pkg_id, int *die_id) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci const char *pathname = "/var/run/isst_cpu_topology.dat"; 24262306a36Sopenharmony_ci struct cpu_topology cpu_top; 24362306a36Sopenharmony_ci FILE *fp; 24462306a36Sopenharmony_ci int ret; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci fp = fopen(pathname, "rb"); 24762306a36Sopenharmony_ci if (!fp) 24862306a36Sopenharmony_ci return -1; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci ret = fseek(fp, cpu * sizeof(cpu_top), SEEK_SET); 25162306a36Sopenharmony_ci if (ret) 25262306a36Sopenharmony_ci goto err_ret; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci ret = fread(&cpu_top, sizeof(cpu_top), 1, fp); 25562306a36Sopenharmony_ci if (ret != 1) { 25662306a36Sopenharmony_ci ret = -1; 25762306a36Sopenharmony_ci goto err_ret; 25862306a36Sopenharmony_ci } 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci *pkg_id = cpu_top.pkg_id; 26162306a36Sopenharmony_ci *core_id = cpu_top.core_id; 26262306a36Sopenharmony_ci *die_id = cpu_top.die_id; 26362306a36Sopenharmony_ci ret = 0; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_cierr_ret: 26662306a36Sopenharmony_ci fclose(fp); 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci return ret; 26962306a36Sopenharmony_ci} 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_cistatic void store_cpu_topology(void) 27262306a36Sopenharmony_ci{ 27362306a36Sopenharmony_ci const char *pathname = "/var/run/isst_cpu_topology.dat"; 27462306a36Sopenharmony_ci FILE *fp; 27562306a36Sopenharmony_ci int i; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci fp = fopen(pathname, "rb"); 27862306a36Sopenharmony_ci if (fp) { 27962306a36Sopenharmony_ci /* Mapping already exists */ 28062306a36Sopenharmony_ci fclose(fp); 28162306a36Sopenharmony_ci return; 28262306a36Sopenharmony_ci } 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci fp = fopen(pathname, "wb"); 28562306a36Sopenharmony_ci if (!fp) { 28662306a36Sopenharmony_ci fprintf(stderr, "Can't create file:%s\n", pathname); 28762306a36Sopenharmony_ci return; 28862306a36Sopenharmony_ci } 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci fprintf(stderr, "Caching topology information\n"); 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci for (i = 0; i < topo_max_cpus; ++i) { 29362306a36Sopenharmony_ci struct cpu_topology cpu_top; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci cpu_top.core_id = parse_int_file(0, 29662306a36Sopenharmony_ci "/sys/devices/system/cpu/cpu%d/topology/core_id", i); 29762306a36Sopenharmony_ci if (cpu_top.core_id < 0) 29862306a36Sopenharmony_ci cpu_top.core_id = -1; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci cpu_top.pkg_id = parse_int_file(0, 30162306a36Sopenharmony_ci "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", i); 30262306a36Sopenharmony_ci if (cpu_top.pkg_id < 0) 30362306a36Sopenharmony_ci cpu_top.pkg_id = -1; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci cpu_top.die_id = parse_int_file(0, 30662306a36Sopenharmony_ci "/sys/devices/system/cpu/cpu%d/topology/die_id", i); 30762306a36Sopenharmony_ci if (cpu_top.die_id < 0) 30862306a36Sopenharmony_ci cpu_top.die_id = -1; 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci cpu_top.cpu = i; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci if (fwrite(&cpu_top, sizeof(cpu_top), 1, fp) != 1) { 31362306a36Sopenharmony_ci fprintf(stderr, "Can't write to:%s\n", pathname); 31462306a36Sopenharmony_ci break; 31562306a36Sopenharmony_ci } 31662306a36Sopenharmony_ci } 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci fclose(fp); 31962306a36Sopenharmony_ci} 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_cistatic int get_physical_package_id(int cpu) 32262306a36Sopenharmony_ci{ 32362306a36Sopenharmony_ci int ret; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci if (cpu < 0) 32662306a36Sopenharmony_ci return -1; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci if (cpu_map && cpu_map[cpu].initialized) 32962306a36Sopenharmony_ci return cpu_map[cpu].pkg_id; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci ret = parse_int_file(0, 33262306a36Sopenharmony_ci "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", 33362306a36Sopenharmony_ci cpu); 33462306a36Sopenharmony_ci if (ret < 0) { 33562306a36Sopenharmony_ci int core_id, pkg_id, die_id; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id); 33862306a36Sopenharmony_ci if (!ret) 33962306a36Sopenharmony_ci return pkg_id; 34062306a36Sopenharmony_ci } 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci return ret; 34362306a36Sopenharmony_ci} 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_cistatic int get_physical_core_id(int cpu) 34662306a36Sopenharmony_ci{ 34762306a36Sopenharmony_ci int ret; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci if (cpu < 0) 35062306a36Sopenharmony_ci return -1; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci if (cpu_map && cpu_map[cpu].initialized) 35362306a36Sopenharmony_ci return cpu_map[cpu].core_id; 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci ret = parse_int_file(0, 35662306a36Sopenharmony_ci "/sys/devices/system/cpu/cpu%d/topology/core_id", 35762306a36Sopenharmony_ci cpu); 35862306a36Sopenharmony_ci if (ret < 0) { 35962306a36Sopenharmony_ci int core_id, pkg_id, die_id; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id); 36262306a36Sopenharmony_ci if (!ret) 36362306a36Sopenharmony_ci return core_id; 36462306a36Sopenharmony_ci } 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci return ret; 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_cistatic int get_physical_die_id(int cpu) 37062306a36Sopenharmony_ci{ 37162306a36Sopenharmony_ci int ret; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci if (cpu < 0) 37462306a36Sopenharmony_ci return -1; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci if (cpu_map && cpu_map[cpu].initialized) 37762306a36Sopenharmony_ci return cpu_map[cpu].die_id; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci ret = parse_int_file(0, 38062306a36Sopenharmony_ci "/sys/devices/system/cpu/cpu%d/topology/die_id", 38162306a36Sopenharmony_ci cpu); 38262306a36Sopenharmony_ci if (ret < 0) { 38362306a36Sopenharmony_ci int core_id, pkg_id, die_id; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id); 38662306a36Sopenharmony_ci if (!ret) { 38762306a36Sopenharmony_ci if (die_id < 0) 38862306a36Sopenharmony_ci die_id = 0; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci return die_id; 39162306a36Sopenharmony_ci } 39262306a36Sopenharmony_ci } 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci if (ret < 0) 39562306a36Sopenharmony_ci ret = 0; 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci return ret; 39862306a36Sopenharmony_ci} 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_cistatic int get_physical_punit_id(int cpu) 40162306a36Sopenharmony_ci{ 40262306a36Sopenharmony_ci if (cpu < 0) 40362306a36Sopenharmony_ci return -1; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci if (cpu_map && cpu_map[cpu].initialized) 40662306a36Sopenharmony_ci return cpu_map[cpu].punit_id; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci return -1; 40962306a36Sopenharmony_ci} 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_civoid set_isst_id(struct isst_id *id, int cpu) 41262306a36Sopenharmony_ci{ 41362306a36Sopenharmony_ci id->cpu = cpu; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci id->pkg = get_physical_package_id(cpu); 41662306a36Sopenharmony_ci if (id->pkg >= MAX_PACKAGE_COUNT) 41762306a36Sopenharmony_ci id->pkg = -1; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci id->die = get_physical_die_id(cpu); 42062306a36Sopenharmony_ci if (id->die >= MAX_DIE_PER_PACKAGE) 42162306a36Sopenharmony_ci id->die = -1; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci id->punit = get_physical_punit_id(cpu); 42462306a36Sopenharmony_ci if (id->punit >= MAX_PUNIT_PER_DIE) 42562306a36Sopenharmony_ci id->punit = -1; 42662306a36Sopenharmony_ci} 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ciint is_cpu_in_power_domain(int cpu, struct isst_id *id) 42962306a36Sopenharmony_ci{ 43062306a36Sopenharmony_ci struct isst_id tid; 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci set_isst_id(&tid, cpu); 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci if (id->pkg == tid.pkg && id->die == tid.die && id->punit == tid.punit) 43562306a36Sopenharmony_ci return 1; 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci return 0; 43862306a36Sopenharmony_ci} 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ciint get_cpufreq_base_freq(int cpu) 44162306a36Sopenharmony_ci{ 44262306a36Sopenharmony_ci return parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency", cpu); 44362306a36Sopenharmony_ci} 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ciint get_topo_max_cpus(void) 44662306a36Sopenharmony_ci{ 44762306a36Sopenharmony_ci return topo_max_cpus; 44862306a36Sopenharmony_ci} 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_cistatic unsigned int is_cpu_online(int cpu) 45162306a36Sopenharmony_ci{ 45262306a36Sopenharmony_ci char buffer[128]; 45362306a36Sopenharmony_ci int fd, ret; 45462306a36Sopenharmony_ci unsigned char online; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci snprintf(buffer, sizeof(buffer), 45762306a36Sopenharmony_ci "/sys/devices/system/cpu/cpu%d/online", cpu); 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci fd = open(buffer, O_RDONLY); 46062306a36Sopenharmony_ci if (fd < 0) 46162306a36Sopenharmony_ci return fd; 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci ret = read(fd, &online, sizeof(online)); 46462306a36Sopenharmony_ci close(fd); 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci if (ret == -1) 46762306a36Sopenharmony_ci return ret; 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci if (online == '1') 47062306a36Sopenharmony_ci online = 1; 47162306a36Sopenharmony_ci else 47262306a36Sopenharmony_ci online = 0; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci return online; 47562306a36Sopenharmony_ci} 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_cistatic int get_kernel_version(int *major, int *minor) 47862306a36Sopenharmony_ci{ 47962306a36Sopenharmony_ci struct utsname buf; 48062306a36Sopenharmony_ci int ret; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci ret = uname(&buf); 48362306a36Sopenharmony_ci if (ret) 48462306a36Sopenharmony_ci return ret; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci ret = sscanf(buf.release, "%d.%d", major, minor); 48762306a36Sopenharmony_ci if (ret != 2) 48862306a36Sopenharmony_ci return ret; 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci return 0; 49162306a36Sopenharmony_ci} 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci#define CPU0_HOTPLUG_DEPRECATE_MAJOR_VER 6 49462306a36Sopenharmony_ci#define CPU0_HOTPLUG_DEPRECATE_MINOR_VER 5 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_civoid set_cpu_online_offline(int cpu, int state) 49762306a36Sopenharmony_ci{ 49862306a36Sopenharmony_ci char buffer[128]; 49962306a36Sopenharmony_ci int fd, ret; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci if (!cpu) { 50262306a36Sopenharmony_ci int major, minor; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci ret = get_kernel_version(&major, &minor); 50562306a36Sopenharmony_ci if (!ret) { 50662306a36Sopenharmony_ci if (major > CPU0_HOTPLUG_DEPRECATE_MAJOR_VER || (major == CPU0_HOTPLUG_DEPRECATE_MAJOR_VER && 50762306a36Sopenharmony_ci minor >= CPU0_HOTPLUG_DEPRECATE_MINOR_VER)) { 50862306a36Sopenharmony_ci debug_printf("Ignore CPU 0 offline/online for kernel version >= %d.%d\n", major, minor); 50962306a36Sopenharmony_ci debug_printf("Use cgroups to isolate CPU 0\n"); 51062306a36Sopenharmony_ci return; 51162306a36Sopenharmony_ci } 51262306a36Sopenharmony_ci } 51362306a36Sopenharmony_ci } 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci snprintf(buffer, sizeof(buffer), 51662306a36Sopenharmony_ci "/sys/devices/system/cpu/cpu%d/online", cpu); 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci fd = open(buffer, O_WRONLY); 51962306a36Sopenharmony_ci if (fd < 0) { 52062306a36Sopenharmony_ci if (!cpu && state) { 52162306a36Sopenharmony_ci fprintf(stderr, "This system is not configured for CPU 0 online/offline\n"); 52262306a36Sopenharmony_ci fprintf(stderr, "Ignoring online request for CPU 0 as this is already online\n"); 52362306a36Sopenharmony_ci return; 52462306a36Sopenharmony_ci } 52562306a36Sopenharmony_ci err(-1, "%s open failed", buffer); 52662306a36Sopenharmony_ci } 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci if (state) 52962306a36Sopenharmony_ci ret = write(fd, "1\n", 2); 53062306a36Sopenharmony_ci else 53162306a36Sopenharmony_ci ret = write(fd, "0\n", 2); 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci if (ret == -1) 53462306a36Sopenharmony_ci perror("Online/Offline: Operation failed\n"); 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci close(fd); 53762306a36Sopenharmony_ci} 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_cistatic void force_all_cpus_online(void) 54062306a36Sopenharmony_ci{ 54162306a36Sopenharmony_ci int i; 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_ci fprintf(stderr, "Forcing all CPUs online\n"); 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci for (i = 0; i < topo_max_cpus; ++i) 54662306a36Sopenharmony_ci set_cpu_online_offline(i, 1); 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci unlink("/var/run/isst_cpu_topology.dat"); 54962306a36Sopenharmony_ci} 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_civoid for_each_online_power_domain_in_set(void (*callback)(struct isst_id *, void *, void *, 55262306a36Sopenharmony_ci void *, void *), 55362306a36Sopenharmony_ci void *arg1, void *arg2, void *arg3, 55462306a36Sopenharmony_ci void *arg4) 55562306a36Sopenharmony_ci{ 55662306a36Sopenharmony_ci struct isst_id id; 55762306a36Sopenharmony_ci int cpus[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE][MAX_PUNIT_PER_DIE]; 55862306a36Sopenharmony_ci int valid_mask[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE] = {0}; 55962306a36Sopenharmony_ci int i, j, k; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci memset(cpus, -1, sizeof(cpus)); 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci for (i = 0; i < topo_max_cpus; ++i) { 56462306a36Sopenharmony_ci int online; 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask)) 56762306a36Sopenharmony_ci continue; 56862306a36Sopenharmony_ci 56962306a36Sopenharmony_ci online = parse_int_file( 57062306a36Sopenharmony_ci i != 0, "/sys/devices/system/cpu/cpu%d/online", i); 57162306a36Sopenharmony_ci if (online < 0) 57262306a36Sopenharmony_ci online = 1; /* online entry for CPU 0 needs some special configs */ 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci if (!online) 57562306a36Sopenharmony_ci continue; 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci set_isst_id(&id, i); 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci if (id.pkg < 0 || id.die < 0 || id.punit < 0) 58062306a36Sopenharmony_ci continue; 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci valid_mask[id.pkg][id.die] = 1; 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci if (cpus[id.pkg][id.die][id.punit] == -1) 58562306a36Sopenharmony_ci cpus[id.pkg][id.die][id.punit] = i; 58662306a36Sopenharmony_ci } 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci for (i = 0; i < MAX_PACKAGE_COUNT; i++) { 58962306a36Sopenharmony_ci for (j = 0; j < MAX_DIE_PER_PACKAGE; j++) { 59062306a36Sopenharmony_ci /* 59162306a36Sopenharmony_ci * Fix me: 59262306a36Sopenharmony_ci * How to check a non-cpu die for a package/die with all cpu offlined? 59362306a36Sopenharmony_ci */ 59462306a36Sopenharmony_ci if (!valid_mask[i][j]) 59562306a36Sopenharmony_ci continue; 59662306a36Sopenharmony_ci for (k = 0; k < MAX_PUNIT_PER_DIE; k++) { 59762306a36Sopenharmony_ci id.cpu = cpus[i][j][k]; 59862306a36Sopenharmony_ci id.pkg = i; 59962306a36Sopenharmony_ci id.die = j; 60062306a36Sopenharmony_ci id.punit = k; 60162306a36Sopenharmony_ci if (isst_is_punit_valid(&id)) 60262306a36Sopenharmony_ci callback(&id, arg1, arg2, arg3, arg4); 60362306a36Sopenharmony_ci } 60462306a36Sopenharmony_ci } 60562306a36Sopenharmony_ci } 60662306a36Sopenharmony_ci} 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_cistatic void for_each_online_target_cpu_in_set( 60962306a36Sopenharmony_ci void (*callback)(struct isst_id *, void *, void *, void *, void *), void *arg1, 61062306a36Sopenharmony_ci void *arg2, void *arg3, void *arg4) 61162306a36Sopenharmony_ci{ 61262306a36Sopenharmony_ci int i, found = 0; 61362306a36Sopenharmony_ci struct isst_id id; 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci for (i = 0; i < topo_max_cpus; ++i) { 61662306a36Sopenharmony_ci int online; 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci if (!CPU_ISSET_S(i, target_cpumask_size, target_cpumask)) 61962306a36Sopenharmony_ci continue; 62062306a36Sopenharmony_ci if (i) 62162306a36Sopenharmony_ci online = parse_int_file( 62262306a36Sopenharmony_ci 1, "/sys/devices/system/cpu/cpu%d/online", i); 62362306a36Sopenharmony_ci else 62462306a36Sopenharmony_ci online = 62562306a36Sopenharmony_ci 1; /* online entry for CPU 0 needs some special configs */ 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci set_isst_id(&id, i); 62862306a36Sopenharmony_ci if (online && callback) { 62962306a36Sopenharmony_ci callback(&id, arg1, arg2, arg3, arg4); 63062306a36Sopenharmony_ci found = 1; 63162306a36Sopenharmony_ci } 63262306a36Sopenharmony_ci } 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci if (!found) 63562306a36Sopenharmony_ci fprintf(stderr, "No valid CPU in the list\n"); 63662306a36Sopenharmony_ci} 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci#define BITMASK_SIZE 32 63962306a36Sopenharmony_cistatic void set_max_cpu_num(void) 64062306a36Sopenharmony_ci{ 64162306a36Sopenharmony_ci FILE *filep; 64262306a36Sopenharmony_ci unsigned long dummy; 64362306a36Sopenharmony_ci int i; 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci topo_max_cpus = 0; 64662306a36Sopenharmony_ci for (i = 0; i < 256; ++i) { 64762306a36Sopenharmony_ci char path[256]; 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci snprintf(path, sizeof(path), 65062306a36Sopenharmony_ci "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", i); 65162306a36Sopenharmony_ci filep = fopen(path, "r"); 65262306a36Sopenharmony_ci if (filep) 65362306a36Sopenharmony_ci break; 65462306a36Sopenharmony_ci } 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci if (!filep) { 65762306a36Sopenharmony_ci fprintf(stderr, "Can't get max cpu number\n"); 65862306a36Sopenharmony_ci exit(0); 65962306a36Sopenharmony_ci } 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci while (fscanf(filep, "%lx,", &dummy) == 1) 66262306a36Sopenharmony_ci topo_max_cpus += BITMASK_SIZE; 66362306a36Sopenharmony_ci fclose(filep); 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci debug_printf("max cpus %d\n", topo_max_cpus); 66662306a36Sopenharmony_ci} 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_cisize_t alloc_cpu_set(cpu_set_t **cpu_set) 66962306a36Sopenharmony_ci{ 67062306a36Sopenharmony_ci cpu_set_t *_cpu_set; 67162306a36Sopenharmony_ci size_t size; 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci _cpu_set = CPU_ALLOC((topo_max_cpus + 1)); 67462306a36Sopenharmony_ci if (_cpu_set == NULL) 67562306a36Sopenharmony_ci err(3, "CPU_ALLOC"); 67662306a36Sopenharmony_ci size = CPU_ALLOC_SIZE((topo_max_cpus + 1)); 67762306a36Sopenharmony_ci CPU_ZERO_S(size, _cpu_set); 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci *cpu_set = _cpu_set; 68062306a36Sopenharmony_ci return size; 68162306a36Sopenharmony_ci} 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_civoid free_cpu_set(cpu_set_t *cpu_set) 68462306a36Sopenharmony_ci{ 68562306a36Sopenharmony_ci CPU_FREE(cpu_set); 68662306a36Sopenharmony_ci} 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_cistatic int cpu_cnt[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE][MAX_PUNIT_PER_DIE]; 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ciint get_max_punit_core_id(struct isst_id *id) 69162306a36Sopenharmony_ci{ 69262306a36Sopenharmony_ci int max_id = 0; 69362306a36Sopenharmony_ci int i; 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci for (i = 0; i < topo_max_cpus; ++i) 69662306a36Sopenharmony_ci { 69762306a36Sopenharmony_ci if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask)) 69862306a36Sopenharmony_ci continue; 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci if (is_cpu_in_power_domain(i, id) && 70162306a36Sopenharmony_ci cpu_map[i].punit_cpu_core > max_id) 70262306a36Sopenharmony_ci max_id = cpu_map[i].punit_cpu_core; 70362306a36Sopenharmony_ci } 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci return max_id; 70662306a36Sopenharmony_ci} 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ciint get_cpu_count(struct isst_id *id) 70962306a36Sopenharmony_ci{ 71062306a36Sopenharmony_ci if (id->pkg < 0 || id->die < 0 || id->punit < 0) 71162306a36Sopenharmony_ci return 0; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci return cpu_cnt[id->pkg][id->die][id->punit]; 71462306a36Sopenharmony_ci} 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_cistatic void update_punit_cpu_info(__u32 physical_cpu, struct _cpu_map *cpu_map) 71762306a36Sopenharmony_ci{ 71862306a36Sopenharmony_ci if (api_version() > 1) { 71962306a36Sopenharmony_ci /* 72062306a36Sopenharmony_ci * MSR 0x54 format 72162306a36Sopenharmony_ci * [15:11] PM_DOMAIN_ID 72262306a36Sopenharmony_ci * [10:3] MODULE_ID (aka IDI_AGENT_ID) 72362306a36Sopenharmony_ci * [2:0] LP_ID (We don't care about these bits we only 72462306a36Sopenharmony_ci * care die and core id 72562306a36Sopenharmony_ci * For Atom: 72662306a36Sopenharmony_ci * [2] Always 0 72762306a36Sopenharmony_ci * [1:0] core ID within module 72862306a36Sopenharmony_ci * For Core 72962306a36Sopenharmony_ci * [2:1] Always 0 73062306a36Sopenharmony_ci * [0] thread ID 73162306a36Sopenharmony_ci */ 73262306a36Sopenharmony_ci cpu_map->punit_id = (physical_cpu >> 11) & 0x1f; 73362306a36Sopenharmony_ci cpu_map->punit_cpu_core = (physical_cpu >> 3) & 0xff; 73462306a36Sopenharmony_ci cpu_map->punit_cpu = physical_cpu & 0x7ff; 73562306a36Sopenharmony_ci } else { 73662306a36Sopenharmony_ci int punit_id; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci /* 73962306a36Sopenharmony_ci * MSR 0x53 format 74062306a36Sopenharmony_ci * Format 74162306a36Sopenharmony_ci * Bit 0 – thread ID 74262306a36Sopenharmony_ci * Bit 8:1 – core ID 74362306a36Sopenharmony_ci * Bit 13:9 – punit ID 74462306a36Sopenharmony_ci */ 74562306a36Sopenharmony_ci cpu_map->punit_cpu = physical_cpu & 0x1ff; 74662306a36Sopenharmony_ci cpu_map->punit_cpu_core = (cpu_map->punit_cpu >> 1); // shift to get core id 74762306a36Sopenharmony_ci punit_id = (physical_cpu >> 9) & 0x1f; 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci if (punit_id >= MAX_PUNIT_PER_DIE) 75062306a36Sopenharmony_ci punit_id = 0; 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci cpu_map->punit_id = punit_id; 75362306a36Sopenharmony_ci } 75462306a36Sopenharmony_ci} 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_cistatic void create_cpu_map(void) 75762306a36Sopenharmony_ci{ 75862306a36Sopenharmony_ci const char *pathname = "/dev/isst_interface"; 75962306a36Sopenharmony_ci size_t size; 76062306a36Sopenharmony_ci DIR *dir; 76162306a36Sopenharmony_ci int i, fd = 0; 76262306a36Sopenharmony_ci struct isst_if_cpu_maps map; 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci /* Use calloc to make sure the memory is initialized to Zero */ 76562306a36Sopenharmony_ci cpu_map = calloc(topo_max_cpus, sizeof(*cpu_map)); 76662306a36Sopenharmony_ci if (!cpu_map) 76762306a36Sopenharmony_ci err(3, "cpumap"); 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci fd = open(pathname, O_RDWR); 77062306a36Sopenharmony_ci if (fd < 0 && !is_clx_n_platform()) 77162306a36Sopenharmony_ci err(-1, "%s open failed", pathname); 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci size = alloc_cpu_set(&present_cpumask); 77462306a36Sopenharmony_ci present_cpumask_size = size; 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci for (i = 0; i < topo_max_cpus; ++i) { 77762306a36Sopenharmony_ci char buffer[256]; 77862306a36Sopenharmony_ci int pkg_id, die_id, core_id, punit_id; 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci /* check if CPU is online */ 78162306a36Sopenharmony_ci snprintf(buffer, sizeof(buffer), 78262306a36Sopenharmony_ci "/sys/devices/system/cpu/cpu%d", i); 78362306a36Sopenharmony_ci dir = opendir(buffer); 78462306a36Sopenharmony_ci if (!dir) 78562306a36Sopenharmony_ci continue; 78662306a36Sopenharmony_ci closedir(dir); 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci CPU_SET_S(i, size, present_cpumask); 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci pkg_id = get_physical_package_id(i); 79162306a36Sopenharmony_ci die_id = get_physical_die_id(i); 79262306a36Sopenharmony_ci core_id = get_physical_core_id(i); 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci if (pkg_id < 0 || die_id < 0 || core_id < 0) 79562306a36Sopenharmony_ci continue; 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci cpu_map[i].pkg_id = pkg_id; 79862306a36Sopenharmony_ci cpu_map[i].die_id = die_id; 79962306a36Sopenharmony_ci cpu_map[i].core_id = core_id; 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci punit_id = 0; 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci if (fd >= 0) { 80562306a36Sopenharmony_ci map.cmd_count = 1; 80662306a36Sopenharmony_ci map.cpu_map[0].logical_cpu = i; 80762306a36Sopenharmony_ci debug_printf(" map logical_cpu:%d\n", 80862306a36Sopenharmony_ci map.cpu_map[0].logical_cpu); 80962306a36Sopenharmony_ci if (ioctl(fd, ISST_IF_GET_PHY_ID, &map) == -1) { 81062306a36Sopenharmony_ci perror("ISST_IF_GET_PHY_ID"); 81162306a36Sopenharmony_ci fprintf(outf, "Error: map logical_cpu:%d\n", 81262306a36Sopenharmony_ci map.cpu_map[0].logical_cpu); 81362306a36Sopenharmony_ci } else { 81462306a36Sopenharmony_ci update_punit_cpu_info(map.cpu_map[0].physical_cpu, &cpu_map[i]); 81562306a36Sopenharmony_ci punit_id = cpu_map[i].punit_id; 81662306a36Sopenharmony_ci } 81762306a36Sopenharmony_ci } 81862306a36Sopenharmony_ci cpu_map[i].initialized = 1; 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci cpu_cnt[pkg_id][die_id][punit_id]++; 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci debug_printf( 82362306a36Sopenharmony_ci "map logical_cpu:%d core: %d die:%d pkg:%d punit:%d punit_cpu:%d punit_core:%d\n", 82462306a36Sopenharmony_ci i, cpu_map[i].core_id, cpu_map[i].die_id, 82562306a36Sopenharmony_ci cpu_map[i].pkg_id, cpu_map[i].punit_id, 82662306a36Sopenharmony_ci cpu_map[i].punit_cpu, cpu_map[i].punit_cpu_core); 82762306a36Sopenharmony_ci } 82862306a36Sopenharmony_ci if (fd >= 0) 82962306a36Sopenharmony_ci close(fd); 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci size = alloc_cpu_set(&target_cpumask); 83262306a36Sopenharmony_ci target_cpumask_size = size; 83362306a36Sopenharmony_ci for (i = 0; i < max_target_cpus; ++i) { 83462306a36Sopenharmony_ci if (!CPU_ISSET_S(target_cpus[i], present_cpumask_size, 83562306a36Sopenharmony_ci present_cpumask)) 83662306a36Sopenharmony_ci continue; 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci CPU_SET_S(target_cpus[i], size, target_cpumask); 83962306a36Sopenharmony_ci } 84062306a36Sopenharmony_ci} 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_civoid set_cpu_mask_from_punit_coremask(struct isst_id *id, unsigned long long core_mask, 84362306a36Sopenharmony_ci size_t core_cpumask_size, 84462306a36Sopenharmony_ci cpu_set_t *core_cpumask, int *cpu_cnt) 84562306a36Sopenharmony_ci{ 84662306a36Sopenharmony_ci int i, cnt = 0; 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci if (id->cpu < 0) 84962306a36Sopenharmony_ci return; 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci *cpu_cnt = 0; 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci for (i = 0; i < 64; ++i) { 85462306a36Sopenharmony_ci if (core_mask & BIT_ULL(i)) { 85562306a36Sopenharmony_ci int j; 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci for (j = 0; j < topo_max_cpus; ++j) { 85862306a36Sopenharmony_ci if (!CPU_ISSET_S(j, present_cpumask_size, present_cpumask)) 85962306a36Sopenharmony_ci continue; 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci if (is_cpu_in_power_domain(j, id) && 86262306a36Sopenharmony_ci cpu_map[j].punit_cpu_core == i) { 86362306a36Sopenharmony_ci CPU_SET_S(j, core_cpumask_size, 86462306a36Sopenharmony_ci core_cpumask); 86562306a36Sopenharmony_ci ++cnt; 86662306a36Sopenharmony_ci } 86762306a36Sopenharmony_ci } 86862306a36Sopenharmony_ci } 86962306a36Sopenharmony_ci } 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci *cpu_cnt = cnt; 87262306a36Sopenharmony_ci} 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ciint find_phy_core_num(int logical_cpu) 87562306a36Sopenharmony_ci{ 87662306a36Sopenharmony_ci if (logical_cpu < topo_max_cpus) 87762306a36Sopenharmony_ci return cpu_map[logical_cpu].punit_cpu_core; 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci return -EINVAL; 88062306a36Sopenharmony_ci} 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ciint use_cgroupv2(void) 88362306a36Sopenharmony_ci{ 88462306a36Sopenharmony_ci return cgroupv2; 88562306a36Sopenharmony_ci} 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ciint enable_cpuset_controller(void) 88862306a36Sopenharmony_ci{ 88962306a36Sopenharmony_ci int fd, ret; 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci fd = open("/sys/fs/cgroup/cgroup.subtree_control", O_RDWR, 0); 89262306a36Sopenharmony_ci if (fd < 0) { 89362306a36Sopenharmony_ci debug_printf("Can't activate cpuset controller\n"); 89462306a36Sopenharmony_ci debug_printf("Either you are not root user or CGroup v2 is not supported\n"); 89562306a36Sopenharmony_ci return fd; 89662306a36Sopenharmony_ci } 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci ret = write(fd, " +cpuset", strlen(" +cpuset")); 89962306a36Sopenharmony_ci close(fd); 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci if (ret == -1) { 90262306a36Sopenharmony_ci debug_printf("Can't activate cpuset controller: Write failed\n"); 90362306a36Sopenharmony_ci return ret; 90462306a36Sopenharmony_ci } 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci return 0; 90762306a36Sopenharmony_ci} 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ciint isolate_cpus(struct isst_id *id, int mask_size, cpu_set_t *cpu_mask, int level) 91062306a36Sopenharmony_ci{ 91162306a36Sopenharmony_ci int i, first, curr_index, index, ret, fd; 91262306a36Sopenharmony_ci static char str[512], dir_name[64]; 91362306a36Sopenharmony_ci static char cpuset_cpus[128]; 91462306a36Sopenharmony_ci int str_len = sizeof(str); 91562306a36Sopenharmony_ci DIR *dir; 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci snprintf(dir_name, sizeof(dir_name), "/sys/fs/cgroup/%d-%d-%d", id->pkg, id->die, id->punit); 91862306a36Sopenharmony_ci dir = opendir(dir_name); 91962306a36Sopenharmony_ci if (!dir) { 92062306a36Sopenharmony_ci ret = mkdir(dir_name, 0744); 92162306a36Sopenharmony_ci if (ret) { 92262306a36Sopenharmony_ci debug_printf("Can't create dir:%s errno:%d\n", dir_name, errno); 92362306a36Sopenharmony_ci return ret; 92462306a36Sopenharmony_ci } 92562306a36Sopenharmony_ci } 92662306a36Sopenharmony_ci closedir(dir); 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci if (!level) { 92962306a36Sopenharmony_ci sprintf(cpuset_cpus, "%s/cpuset.cpus.partition", dir_name); 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci fd = open(cpuset_cpus, O_RDWR, 0); 93262306a36Sopenharmony_ci if (fd < 0) { 93362306a36Sopenharmony_ci return fd; 93462306a36Sopenharmony_ci } 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci ret = write(fd, "member", strlen("member")); 93762306a36Sopenharmony_ci if (ret == -1) { 93862306a36Sopenharmony_ci printf("Can't update to member\n"); 93962306a36Sopenharmony_ci return ret; 94062306a36Sopenharmony_ci } 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci return 0; 94362306a36Sopenharmony_ci } 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci if (!CPU_COUNT_S(mask_size, cpu_mask)) { 94662306a36Sopenharmony_ci return -1; 94762306a36Sopenharmony_ci } 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci curr_index = 0; 95062306a36Sopenharmony_ci first = 1; 95162306a36Sopenharmony_ci str[0] = '\0'; 95262306a36Sopenharmony_ci for (i = 0; i < get_topo_max_cpus(); ++i) { 95362306a36Sopenharmony_ci if (!is_cpu_in_power_domain(i, id)) 95462306a36Sopenharmony_ci continue; 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci if (CPU_ISSET_S(i, mask_size, cpu_mask)) 95762306a36Sopenharmony_ci continue; 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci if (!first) { 96062306a36Sopenharmony_ci index = snprintf(&str[curr_index], 96162306a36Sopenharmony_ci str_len - curr_index, ","); 96262306a36Sopenharmony_ci curr_index += index; 96362306a36Sopenharmony_ci if (curr_index >= str_len) 96462306a36Sopenharmony_ci break; 96562306a36Sopenharmony_ci } 96662306a36Sopenharmony_ci index = snprintf(&str[curr_index], str_len - curr_index, "%d", 96762306a36Sopenharmony_ci i); 96862306a36Sopenharmony_ci curr_index += index; 96962306a36Sopenharmony_ci if (curr_index >= str_len) 97062306a36Sopenharmony_ci break; 97162306a36Sopenharmony_ci first = 0; 97262306a36Sopenharmony_ci } 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ci debug_printf("isolated CPUs list: package:%d curr_index:%d [%s]\n", id->pkg, curr_index ,str); 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci snprintf(cpuset_cpus, sizeof(cpuset_cpus), "%s/cpuset.cpus", dir_name); 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_ci fd = open(cpuset_cpus, O_RDWR, 0); 97962306a36Sopenharmony_ci if (fd < 0) { 98062306a36Sopenharmony_ci return fd; 98162306a36Sopenharmony_ci } 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_ci ret = write(fd, str, strlen(str)); 98462306a36Sopenharmony_ci close(fd); 98562306a36Sopenharmony_ci 98662306a36Sopenharmony_ci if (ret == -1) { 98762306a36Sopenharmony_ci debug_printf("Can't activate cpuset controller: Write failed\n"); 98862306a36Sopenharmony_ci return ret; 98962306a36Sopenharmony_ci } 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci snprintf(cpuset_cpus, sizeof(cpuset_cpus), "%s/cpuset.cpus.partition", dir_name); 99262306a36Sopenharmony_ci 99362306a36Sopenharmony_ci fd = open(cpuset_cpus, O_RDWR, 0); 99462306a36Sopenharmony_ci if (fd < 0) { 99562306a36Sopenharmony_ci return fd; 99662306a36Sopenharmony_ci } 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_ci ret = write(fd, "isolated", strlen("isolated")); 99962306a36Sopenharmony_ci if (ret == -1) { 100062306a36Sopenharmony_ci debug_printf("Can't update to isolated\n"); 100162306a36Sopenharmony_ci ret = write(fd, "root", strlen("root")); 100262306a36Sopenharmony_ci if (ret == -1) 100362306a36Sopenharmony_ci debug_printf("Can't update to root\n"); 100462306a36Sopenharmony_ci } 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_ci close(fd); 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_ci if (ret < 0) 100962306a36Sopenharmony_ci return ret; 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci return 0; 101262306a36Sopenharmony_ci} 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_cistatic int isst_fill_platform_info(void) 101562306a36Sopenharmony_ci{ 101662306a36Sopenharmony_ci const char *pathname = "/dev/isst_interface"; 101762306a36Sopenharmony_ci int fd; 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_ci if (is_clx_n_platform()) { 102062306a36Sopenharmony_ci isst_platform_info.api_version = 1; 102162306a36Sopenharmony_ci goto set_platform_ops; 102262306a36Sopenharmony_ci } 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci fd = open(pathname, O_RDWR); 102562306a36Sopenharmony_ci if (fd < 0) 102662306a36Sopenharmony_ci err(-1, "%s open failed", pathname); 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci if (ioctl(fd, ISST_IF_GET_PLATFORM_INFO, &isst_platform_info) == -1) { 102962306a36Sopenharmony_ci perror("ISST_IF_GET_PLATFORM_INFO"); 103062306a36Sopenharmony_ci close(fd); 103162306a36Sopenharmony_ci return -1; 103262306a36Sopenharmony_ci } 103362306a36Sopenharmony_ci 103462306a36Sopenharmony_ci close(fd); 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ci if (isst_platform_info.api_version > supported_api_ver) { 103762306a36Sopenharmony_ci printf("Incompatible API versions; Upgrade of tool is required\n"); 103862306a36Sopenharmony_ci return -1; 103962306a36Sopenharmony_ci } 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_ciset_platform_ops: 104262306a36Sopenharmony_ci if (isst_set_platform_ops(isst_platform_info.api_version)) { 104362306a36Sopenharmony_ci fprintf(stderr, "Failed to set platform callbacks\n"); 104462306a36Sopenharmony_ci exit(0); 104562306a36Sopenharmony_ci } 104662306a36Sopenharmony_ci return 0; 104762306a36Sopenharmony_ci} 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_civoid get_isst_status(struct isst_id *id, void *arg1, void *arg2, void *arg3, void *arg4) 105062306a36Sopenharmony_ci{ 105162306a36Sopenharmony_ci struct isst_pkg_ctdp pkg_dev; 105262306a36Sopenharmony_ci struct isst_id *tid = (struct isst_id *)arg2; 105362306a36Sopenharmony_ci int *mask = (int *)arg3; 105462306a36Sopenharmony_ci int *max_level = (int *)arg4; 105562306a36Sopenharmony_ci int j, ret; 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_ci /* Only check the first cpu power domain */ 105862306a36Sopenharmony_ci if (id->cpu < 0 || tid->cpu >= 0) 105962306a36Sopenharmony_ci return; 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci ret = isst_get_ctdp_levels(id, &pkg_dev); 106262306a36Sopenharmony_ci if (ret) 106362306a36Sopenharmony_ci return; 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_ci if (pkg_dev.enabled) 106662306a36Sopenharmony_ci *mask |= BIT(0); 106762306a36Sopenharmony_ci 106862306a36Sopenharmony_ci if (pkg_dev.locked) 106962306a36Sopenharmony_ci *mask |= BIT(1); 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci if (*max_level < pkg_dev.levels) 107262306a36Sopenharmony_ci *max_level = pkg_dev.levels; 107362306a36Sopenharmony_ci 107462306a36Sopenharmony_ci for (j = 0; j <= pkg_dev.levels; ++j) { 107562306a36Sopenharmony_ci struct isst_pkg_ctdp_level_info ctdp_level; 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci ret = isst_get_ctdp_control(id, j, &ctdp_level); 107862306a36Sopenharmony_ci if (ret) 107962306a36Sopenharmony_ci continue; 108062306a36Sopenharmony_ci 108162306a36Sopenharmony_ci if (ctdp_level.fact_support) 108262306a36Sopenharmony_ci *mask |= BIT(2); 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_ci if (ctdp_level.pbf_support) 108562306a36Sopenharmony_ci *mask |= BIT(3); 108662306a36Sopenharmony_ci } 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci tid->cpu = id->cpu; 108962306a36Sopenharmony_ci tid->pkg = id->pkg; 109062306a36Sopenharmony_ci tid->die = id->die; 109162306a36Sopenharmony_ci tid->punit = id->punit; 109262306a36Sopenharmony_ci} 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_cistatic void isst_print_extended_platform_info(void) 109562306a36Sopenharmony_ci{ 109662306a36Sopenharmony_ci int cp_state, cp_cap; 109762306a36Sopenharmony_ci struct isst_id id; 109862306a36Sopenharmony_ci int mask = 0, max_level = 0; 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci id.cpu = -1; 110162306a36Sopenharmony_ci for_each_online_power_domain_in_set(get_isst_status, NULL, &id, &mask, &max_level); 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci if (mask & BIT(0)) { 110462306a36Sopenharmony_ci fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is supported\n"); 110562306a36Sopenharmony_ci } else { 110662306a36Sopenharmony_ci fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is not supported\n"); 110762306a36Sopenharmony_ci fprintf(outf, "Only performance level 0 (base level) is present\n"); 110862306a36Sopenharmony_ci } 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci if (mask & BIT(1)) 111162306a36Sopenharmony_ci fprintf(outf, "TDP level change control is locked\n"); 111262306a36Sopenharmony_ci else 111362306a36Sopenharmony_ci fprintf(outf, "TDP level change control is unlocked, max level: %d\n", max_level); 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_ci if (mask & BIT(2)) 111662306a36Sopenharmony_ci fprintf(outf, "Intel(R) SST-TF (feature turbo-freq) is supported\n"); 111762306a36Sopenharmony_ci else 111862306a36Sopenharmony_ci fprintf(outf, "Intel(R) SST-TF (feature turbo-freq) is not supported\n"); 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci if (mask & BIT(3)) 112162306a36Sopenharmony_ci fprintf(outf, "Intel(R) SST-BF (feature base-freq) is supported\n"); 112262306a36Sopenharmony_ci else 112362306a36Sopenharmony_ci fprintf(outf, "Intel(R) SST-BF (feature base-freq) is not supported\n"); 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_ci if (isst_read_pm_config(&id, &cp_state, &cp_cap)) { 112662306a36Sopenharmony_ci fprintf(outf, "Intel(R) SST-CP (feature core-power) status is unknown\n"); 112762306a36Sopenharmony_ci return; 112862306a36Sopenharmony_ci } 112962306a36Sopenharmony_ci 113062306a36Sopenharmony_ci if (cp_cap) 113162306a36Sopenharmony_ci fprintf(outf, "Intel(R) SST-CP (feature core-power) is supported\n"); 113262306a36Sopenharmony_ci else 113362306a36Sopenharmony_ci fprintf(outf, "Intel(R) SST-CP (feature core-power) is not supported\n"); 113462306a36Sopenharmony_ci} 113562306a36Sopenharmony_ci 113662306a36Sopenharmony_cistatic void isst_print_platform_information(void) 113762306a36Sopenharmony_ci{ 113862306a36Sopenharmony_ci if (is_clx_n_platform()) { 113962306a36Sopenharmony_ci fprintf(stderr, "\nThis option in not supported on this platform\n"); 114062306a36Sopenharmony_ci exit(0); 114162306a36Sopenharmony_ci } 114262306a36Sopenharmony_ci 114362306a36Sopenharmony_ci /* Early initialization to create working cpu_map */ 114462306a36Sopenharmony_ci set_max_cpu_num(); 114562306a36Sopenharmony_ci create_cpu_map(); 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci fprintf(outf, "Platform: API version : %d\n", 114862306a36Sopenharmony_ci isst_platform_info.api_version); 114962306a36Sopenharmony_ci fprintf(outf, "Platform: Driver version : %d\n", 115062306a36Sopenharmony_ci isst_platform_info.driver_version); 115162306a36Sopenharmony_ci fprintf(outf, "Platform: mbox supported : %d\n", 115262306a36Sopenharmony_ci isst_platform_info.mbox_supported); 115362306a36Sopenharmony_ci fprintf(outf, "Platform: mmio supported : %d\n", 115462306a36Sopenharmony_ci isst_platform_info.mmio_supported); 115562306a36Sopenharmony_ci isst_print_extended_platform_info(); 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_ci exit(0); 115862306a36Sopenharmony_ci} 115962306a36Sopenharmony_ci 116062306a36Sopenharmony_cistatic char *local_str0, *local_str1; 116162306a36Sopenharmony_cistatic void exec_on_get_ctdp_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3, 116262306a36Sopenharmony_ci void *arg4) 116362306a36Sopenharmony_ci{ 116462306a36Sopenharmony_ci int (*fn_ptr)(struct isst_id *id, void *arg); 116562306a36Sopenharmony_ci int ret; 116662306a36Sopenharmony_ci 116762306a36Sopenharmony_ci fn_ptr = arg1; 116862306a36Sopenharmony_ci ret = fn_ptr(id, arg2); 116962306a36Sopenharmony_ci if (ret) 117062306a36Sopenharmony_ci isst_display_error_info_message(1, "get_tdp_* failed", 0, 0); 117162306a36Sopenharmony_ci else 117262306a36Sopenharmony_ci isst_ctdp_display_core_info(id, outf, arg3, 117362306a36Sopenharmony_ci *(unsigned int *)arg4, 117462306a36Sopenharmony_ci local_str0, local_str1); 117562306a36Sopenharmony_ci} 117662306a36Sopenharmony_ci 117762306a36Sopenharmony_ci#define _get_tdp_level(desc, suffix, object, help, str0, str1) \ 117862306a36Sopenharmony_ci static void get_tdp_##object(int arg) \ 117962306a36Sopenharmony_ci { \ 118062306a36Sopenharmony_ci struct isst_pkg_ctdp ctdp; \ 118162306a36Sopenharmony_ci\ 118262306a36Sopenharmony_ci if (cmd_help) { \ 118362306a36Sopenharmony_ci fprintf(stderr, \ 118462306a36Sopenharmony_ci "Print %s [No command arguments are required]\n", \ 118562306a36Sopenharmony_ci help); \ 118662306a36Sopenharmony_ci exit(0); \ 118762306a36Sopenharmony_ci } \ 118862306a36Sopenharmony_ci local_str0 = str0; \ 118962306a36Sopenharmony_ci local_str1 = str1; \ 119062306a36Sopenharmony_ci isst_ctdp_display_information_start(outf); \ 119162306a36Sopenharmony_ci if (max_target_cpus) \ 119262306a36Sopenharmony_ci for_each_online_target_cpu_in_set( \ 119362306a36Sopenharmony_ci exec_on_get_ctdp_cpu, isst_get_ctdp_##suffix, \ 119462306a36Sopenharmony_ci &ctdp, desc, &ctdp.object); \ 119562306a36Sopenharmony_ci else \ 119662306a36Sopenharmony_ci for_each_online_power_domain_in_set(exec_on_get_ctdp_cpu, \ 119762306a36Sopenharmony_ci isst_get_ctdp_##suffix, \ 119862306a36Sopenharmony_ci &ctdp, desc, \ 119962306a36Sopenharmony_ci &ctdp.object); \ 120062306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); \ 120162306a36Sopenharmony_ci } 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci_get_tdp_level("get-config-levels", levels, levels, "Max TDP level", NULL, NULL); 120462306a36Sopenharmony_ci_get_tdp_level("get-config-version", levels, version, "TDP version", NULL, NULL); 120562306a36Sopenharmony_ci_get_tdp_level("get-config-enabled", levels, enabled, "perf-profile enable status", "disabled", "enabled"); 120662306a36Sopenharmony_ci_get_tdp_level("get-config-current_level", levels, current_level, 120762306a36Sopenharmony_ci "Current TDP Level", NULL, NULL); 120862306a36Sopenharmony_ci_get_tdp_level("get-lock-status", levels, locked, "TDP lock status", "unlocked", "locked"); 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_cistruct isst_pkg_ctdp clx_n_pkg_dev; 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_cistatic int clx_n_get_base_ratio(void) 121362306a36Sopenharmony_ci{ 121462306a36Sopenharmony_ci FILE *fp; 121562306a36Sopenharmony_ci char *begin, *end, *line = NULL; 121662306a36Sopenharmony_ci char number[5]; 121762306a36Sopenharmony_ci float value = 0; 121862306a36Sopenharmony_ci size_t n = 0; 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci fp = fopen("/proc/cpuinfo", "r"); 122162306a36Sopenharmony_ci if (!fp) 122262306a36Sopenharmony_ci err(-1, "cannot open /proc/cpuinfo\n"); 122362306a36Sopenharmony_ci 122462306a36Sopenharmony_ci while (getline(&line, &n, fp) > 0) { 122562306a36Sopenharmony_ci if (strstr(line, "model name")) { 122662306a36Sopenharmony_ci /* this is true for CascadeLake-N */ 122762306a36Sopenharmony_ci begin = strstr(line, "@ ") + 2; 122862306a36Sopenharmony_ci end = strstr(line, "GHz"); 122962306a36Sopenharmony_ci strncpy(number, begin, end - begin); 123062306a36Sopenharmony_ci value = atof(number) * 10; 123162306a36Sopenharmony_ci break; 123262306a36Sopenharmony_ci } 123362306a36Sopenharmony_ci } 123462306a36Sopenharmony_ci free(line); 123562306a36Sopenharmony_ci fclose(fp); 123662306a36Sopenharmony_ci 123762306a36Sopenharmony_ci return (int)(value); 123862306a36Sopenharmony_ci} 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_cistatic int clx_n_config(struct isst_id *id) 124162306a36Sopenharmony_ci{ 124262306a36Sopenharmony_ci int i, ret; 124362306a36Sopenharmony_ci unsigned long cpu_bf; 124462306a36Sopenharmony_ci struct isst_pkg_ctdp_level_info *ctdp_level; 124562306a36Sopenharmony_ci struct isst_pbf_info *pbf_info; 124662306a36Sopenharmony_ci 124762306a36Sopenharmony_ci ctdp_level = &clx_n_pkg_dev.ctdp_level[0]; 124862306a36Sopenharmony_ci pbf_info = &ctdp_level->pbf_info; 124962306a36Sopenharmony_ci ctdp_level->core_cpumask_size = 125062306a36Sopenharmony_ci alloc_cpu_set(&ctdp_level->core_cpumask); 125162306a36Sopenharmony_ci 125262306a36Sopenharmony_ci /* find the frequency base ratio */ 125362306a36Sopenharmony_ci ctdp_level->tdp_ratio = clx_n_get_base_ratio(); 125462306a36Sopenharmony_ci if (ctdp_level->tdp_ratio == 0) { 125562306a36Sopenharmony_ci debug_printf("CLX: cn base ratio is zero\n"); 125662306a36Sopenharmony_ci ret = -1; 125762306a36Sopenharmony_ci goto error_ret; 125862306a36Sopenharmony_ci } 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_ci /* find the high and low priority frequencies */ 126162306a36Sopenharmony_ci pbf_info->p1_high = 0; 126262306a36Sopenharmony_ci pbf_info->p1_low = ~0; 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_ci for (i = 0; i < topo_max_cpus; i++) { 126562306a36Sopenharmony_ci if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask)) 126662306a36Sopenharmony_ci continue; 126762306a36Sopenharmony_ci 126862306a36Sopenharmony_ci if (!is_cpu_in_power_domain(i, id)) 126962306a36Sopenharmony_ci continue; 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_ci CPU_SET_S(i, ctdp_level->core_cpumask_size, 127262306a36Sopenharmony_ci ctdp_level->core_cpumask); 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ci cpu_bf = parse_int_file(1, 127562306a36Sopenharmony_ci "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency", 127662306a36Sopenharmony_ci i); 127762306a36Sopenharmony_ci if (cpu_bf > pbf_info->p1_high) 127862306a36Sopenharmony_ci pbf_info->p1_high = cpu_bf; 127962306a36Sopenharmony_ci if (cpu_bf < pbf_info->p1_low) 128062306a36Sopenharmony_ci pbf_info->p1_low = cpu_bf; 128162306a36Sopenharmony_ci } 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci if (pbf_info->p1_high == ~0UL) { 128462306a36Sopenharmony_ci debug_printf("CLX: maximum base frequency not set\n"); 128562306a36Sopenharmony_ci ret = -1; 128662306a36Sopenharmony_ci goto error_ret; 128762306a36Sopenharmony_ci } 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_ci if (pbf_info->p1_low == 0) { 129062306a36Sopenharmony_ci debug_printf("CLX: minimum base frequency not set\n"); 129162306a36Sopenharmony_ci ret = -1; 129262306a36Sopenharmony_ci goto error_ret; 129362306a36Sopenharmony_ci } 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci /* convert frequencies back to ratios */ 129662306a36Sopenharmony_ci pbf_info->p1_high = pbf_info->p1_high / 100000; 129762306a36Sopenharmony_ci pbf_info->p1_low = pbf_info->p1_low / 100000; 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_ci /* create high priority cpu mask */ 130062306a36Sopenharmony_ci pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask); 130162306a36Sopenharmony_ci for (i = 0; i < topo_max_cpus; i++) { 130262306a36Sopenharmony_ci if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask)) 130362306a36Sopenharmony_ci continue; 130462306a36Sopenharmony_ci 130562306a36Sopenharmony_ci if (!is_cpu_in_power_domain(i, id)) 130662306a36Sopenharmony_ci continue; 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci cpu_bf = parse_int_file(1, 130962306a36Sopenharmony_ci "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency", 131062306a36Sopenharmony_ci i); 131162306a36Sopenharmony_ci cpu_bf = cpu_bf / 100000; 131262306a36Sopenharmony_ci if (cpu_bf == pbf_info->p1_high) 131362306a36Sopenharmony_ci CPU_SET_S(i, pbf_info->core_cpumask_size, 131462306a36Sopenharmony_ci pbf_info->core_cpumask); 131562306a36Sopenharmony_ci } 131662306a36Sopenharmony_ci 131762306a36Sopenharmony_ci /* extra ctdp & pbf struct parameters */ 131862306a36Sopenharmony_ci ctdp_level->processed = 1; 131962306a36Sopenharmony_ci ctdp_level->pbf_support = 1; /* PBF is always supported and enabled */ 132062306a36Sopenharmony_ci ctdp_level->pbf_enabled = 1; 132162306a36Sopenharmony_ci ctdp_level->fact_support = 0; /* FACT is never supported */ 132262306a36Sopenharmony_ci ctdp_level->fact_enabled = 0; 132362306a36Sopenharmony_ci 132462306a36Sopenharmony_ci return 0; 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_cierror_ret: 132762306a36Sopenharmony_ci free_cpu_set(ctdp_level->core_cpumask); 132862306a36Sopenharmony_ci return ret; 132962306a36Sopenharmony_ci} 133062306a36Sopenharmony_ci 133162306a36Sopenharmony_cistatic void dump_clx_n_config_for_cpu(struct isst_id *id, void *arg1, void *arg2, 133262306a36Sopenharmony_ci void *arg3, void *arg4) 133362306a36Sopenharmony_ci{ 133462306a36Sopenharmony_ci int ret; 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_ci if (tdp_level != 0xff && tdp_level != 0) { 133762306a36Sopenharmony_ci isst_display_error_info_message(1, "Invalid level", 1, tdp_level); 133862306a36Sopenharmony_ci exit(0); 133962306a36Sopenharmony_ci } 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ci ret = clx_n_config(id); 134262306a36Sopenharmony_ci if (ret) { 134362306a36Sopenharmony_ci debug_printf("clx_n_config failed"); 134462306a36Sopenharmony_ci } else { 134562306a36Sopenharmony_ci struct isst_pkg_ctdp_level_info *ctdp_level; 134662306a36Sopenharmony_ci struct isst_pbf_info *pbf_info; 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci ctdp_level = &clx_n_pkg_dev.ctdp_level[0]; 134962306a36Sopenharmony_ci pbf_info = &ctdp_level->pbf_info; 135062306a36Sopenharmony_ci clx_n_pkg_dev.processed = 1; 135162306a36Sopenharmony_ci isst_ctdp_display_information(id, outf, tdp_level, &clx_n_pkg_dev); 135262306a36Sopenharmony_ci free_cpu_set(ctdp_level->core_cpumask); 135362306a36Sopenharmony_ci free_cpu_set(pbf_info->core_cpumask); 135462306a36Sopenharmony_ci } 135562306a36Sopenharmony_ci} 135662306a36Sopenharmony_ci 135762306a36Sopenharmony_cistatic void dump_isst_config_for_cpu(struct isst_id *id, void *arg1, void *arg2, 135862306a36Sopenharmony_ci void *arg3, void *arg4) 135962306a36Sopenharmony_ci{ 136062306a36Sopenharmony_ci struct isst_pkg_ctdp pkg_dev; 136162306a36Sopenharmony_ci int ret; 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_ci memset(&pkg_dev, 0, sizeof(pkg_dev)); 136462306a36Sopenharmony_ci ret = isst_get_process_ctdp(id, tdp_level, &pkg_dev); 136562306a36Sopenharmony_ci if (ret) { 136662306a36Sopenharmony_ci isst_display_error_info_message(1, "Failed to get perf-profile info on cpu", 1, id->cpu); 136762306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); 136862306a36Sopenharmony_ci exit(1); 136962306a36Sopenharmony_ci } else { 137062306a36Sopenharmony_ci isst_ctdp_display_information(id, outf, tdp_level, &pkg_dev); 137162306a36Sopenharmony_ci isst_get_process_ctdp_complete(id, &pkg_dev); 137262306a36Sopenharmony_ci } 137362306a36Sopenharmony_ci} 137462306a36Sopenharmony_ci 137562306a36Sopenharmony_cistatic void dump_isst_config(int arg) 137662306a36Sopenharmony_ci{ 137762306a36Sopenharmony_ci void *fn; 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_ci if (cmd_help) { 138062306a36Sopenharmony_ci fprintf(stderr, 138162306a36Sopenharmony_ci "Print Intel(R) Speed Select Technology Performance profile configuration\n"); 138262306a36Sopenharmony_ci fprintf(stderr, 138362306a36Sopenharmony_ci "including base frequency and turbo frequency configurations\n"); 138462306a36Sopenharmony_ci fprintf(stderr, "Optional: -l|--level : Specify tdp level\n"); 138562306a36Sopenharmony_ci fprintf(stderr, 138662306a36Sopenharmony_ci "\tIf no arguments, dump information for all TDP levels\n"); 138762306a36Sopenharmony_ci exit(0); 138862306a36Sopenharmony_ci } 138962306a36Sopenharmony_ci 139062306a36Sopenharmony_ci if (!is_clx_n_platform()) 139162306a36Sopenharmony_ci fn = dump_isst_config_for_cpu; 139262306a36Sopenharmony_ci else 139362306a36Sopenharmony_ci fn = dump_clx_n_config_for_cpu; 139462306a36Sopenharmony_ci 139562306a36Sopenharmony_ci isst_ctdp_display_information_start(outf); 139662306a36Sopenharmony_ci 139762306a36Sopenharmony_ci if (max_target_cpus) 139862306a36Sopenharmony_ci for_each_online_target_cpu_in_set(fn, NULL, NULL, NULL, NULL); 139962306a36Sopenharmony_ci else 140062306a36Sopenharmony_ci for_each_online_power_domain_in_set(fn, NULL, NULL, NULL, NULL); 140162306a36Sopenharmony_ci 140262306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); 140362306a36Sopenharmony_ci} 140462306a36Sopenharmony_ci 140562306a36Sopenharmony_cistatic void adjust_scaling_max_from_base_freq(int cpu); 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_cistatic void set_tdp_level_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3, 140862306a36Sopenharmony_ci void *arg4) 140962306a36Sopenharmony_ci{ 141062306a36Sopenharmony_ci struct isst_pkg_ctdp pkg_dev; 141162306a36Sopenharmony_ci int ret; 141262306a36Sopenharmony_ci 141362306a36Sopenharmony_ci ret = isst_get_ctdp_levels(id, &pkg_dev); 141462306a36Sopenharmony_ci if (ret) { 141562306a36Sopenharmony_ci isst_display_error_info_message(1, "Get TDP level failed", 0, 0); 141662306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); 141762306a36Sopenharmony_ci exit(1); 141862306a36Sopenharmony_ci } 141962306a36Sopenharmony_ci 142062306a36Sopenharmony_ci if (pkg_dev.current_level == tdp_level) { 142162306a36Sopenharmony_ci debug_printf("TDP level already set. Skipped\n"); 142262306a36Sopenharmony_ci goto display_result; 142362306a36Sopenharmony_ci } 142462306a36Sopenharmony_ci 142562306a36Sopenharmony_ci ret = isst_set_tdp_level(id, tdp_level); 142662306a36Sopenharmony_ci if (ret) { 142762306a36Sopenharmony_ci isst_display_error_info_message(1, "Set TDP level failed", 0, 0); 142862306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); 142962306a36Sopenharmony_ci exit(1); 143062306a36Sopenharmony_ci } 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_cidisplay_result: 143362306a36Sopenharmony_ci isst_display_result(id, outf, "perf-profile", "set_tdp_level", ret); 143462306a36Sopenharmony_ci if (force_online_offline && id->cpu >= 0) { 143562306a36Sopenharmony_ci struct isst_pkg_ctdp_level_info ctdp_level; 143662306a36Sopenharmony_ci 143762306a36Sopenharmony_ci /* Wait for updated base frequencies */ 143862306a36Sopenharmony_ci usleep(2000); 143962306a36Sopenharmony_ci 144062306a36Sopenharmony_ci /* Adjusting uncore freq */ 144162306a36Sopenharmony_ci isst_adjust_uncore_freq(id, tdp_level, &ctdp_level); 144262306a36Sopenharmony_ci 144362306a36Sopenharmony_ci fprintf(stderr, "Option is set to online/offline\n"); 144462306a36Sopenharmony_ci ctdp_level.core_cpumask_size = 144562306a36Sopenharmony_ci alloc_cpu_set(&ctdp_level.core_cpumask); 144662306a36Sopenharmony_ci ret = isst_get_coremask_info(id, tdp_level, &ctdp_level); 144762306a36Sopenharmony_ci if (ret) { 144862306a36Sopenharmony_ci isst_display_error_info_message(1, "Can't get coremask, online/offline option is ignored", 0, 0); 144962306a36Sopenharmony_ci goto free_mask; 145062306a36Sopenharmony_ci } 145162306a36Sopenharmony_ci 145262306a36Sopenharmony_ci if (use_cgroupv2()) { 145362306a36Sopenharmony_ci int ret; 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_ci fprintf(stderr, "Using cgroup v2 in lieu of online/offline\n"); 145662306a36Sopenharmony_ci ret = enable_cpuset_controller(); 145762306a36Sopenharmony_ci if (ret) 145862306a36Sopenharmony_ci goto use_offline; 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_ci ret = isolate_cpus(id, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask, tdp_level); 146162306a36Sopenharmony_ci if (ret) 146262306a36Sopenharmony_ci goto use_offline; 146362306a36Sopenharmony_ci 146462306a36Sopenharmony_ci goto free_mask; 146562306a36Sopenharmony_ci } 146662306a36Sopenharmony_ci 146762306a36Sopenharmony_ciuse_offline: 146862306a36Sopenharmony_ci if (ctdp_level.cpu_count) { 146962306a36Sopenharmony_ci int i, max_cpus = get_topo_max_cpus(); 147062306a36Sopenharmony_ci for (i = 0; i < max_cpus; ++i) { 147162306a36Sopenharmony_ci if (!is_cpu_in_power_domain(i, id)) 147262306a36Sopenharmony_ci continue; 147362306a36Sopenharmony_ci if (CPU_ISSET_S(i, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask)) { 147462306a36Sopenharmony_ci fprintf(stderr, "online cpu %d\n", i); 147562306a36Sopenharmony_ci set_cpu_online_offline(i, 1); 147662306a36Sopenharmony_ci adjust_scaling_max_from_base_freq(i); 147762306a36Sopenharmony_ci } else { 147862306a36Sopenharmony_ci fprintf(stderr, "offline cpu %d\n", i); 147962306a36Sopenharmony_ci set_cpu_online_offline(i, 0); 148062306a36Sopenharmony_ci } 148162306a36Sopenharmony_ci } 148262306a36Sopenharmony_ci } 148362306a36Sopenharmony_cifree_mask: 148462306a36Sopenharmony_ci free_cpu_set(ctdp_level.core_cpumask); 148562306a36Sopenharmony_ci } 148662306a36Sopenharmony_ci} 148762306a36Sopenharmony_ci 148862306a36Sopenharmony_cistatic void set_tdp_level(int arg) 148962306a36Sopenharmony_ci{ 149062306a36Sopenharmony_ci if (cmd_help) { 149162306a36Sopenharmony_ci fprintf(stderr, "Set Config TDP level\n"); 149262306a36Sopenharmony_ci fprintf(stderr, 149362306a36Sopenharmony_ci "\t Arguments: -l|--level : Specify tdp level\n"); 149462306a36Sopenharmony_ci fprintf(stderr, 149562306a36Sopenharmony_ci "\t Optional Arguments: -o | online : online/offline for the tdp level\n"); 149662306a36Sopenharmony_ci fprintf(stderr, 149762306a36Sopenharmony_ci "\t online/offline operation has limitations, refer to Linux hotplug documentation\n"); 149862306a36Sopenharmony_ci exit(0); 149962306a36Sopenharmony_ci } 150062306a36Sopenharmony_ci 150162306a36Sopenharmony_ci if (tdp_level == 0xff) { 150262306a36Sopenharmony_ci isst_display_error_info_message(1, "Invalid command: specify tdp_level", 0, 0); 150362306a36Sopenharmony_ci exit(1); 150462306a36Sopenharmony_ci } 150562306a36Sopenharmony_ci isst_ctdp_display_information_start(outf); 150662306a36Sopenharmony_ci if (max_target_cpus) 150762306a36Sopenharmony_ci for_each_online_target_cpu_in_set(set_tdp_level_for_cpu, NULL, 150862306a36Sopenharmony_ci NULL, NULL, NULL); 150962306a36Sopenharmony_ci else 151062306a36Sopenharmony_ci for_each_online_power_domain_in_set(set_tdp_level_for_cpu, NULL, 151162306a36Sopenharmony_ci NULL, NULL, NULL); 151262306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); 151362306a36Sopenharmony_ci} 151462306a36Sopenharmony_ci 151562306a36Sopenharmony_cistatic void clx_n_dump_pbf_config_for_cpu(struct isst_id *id, void *arg1, void *arg2, 151662306a36Sopenharmony_ci void *arg3, void *arg4) 151762306a36Sopenharmony_ci{ 151862306a36Sopenharmony_ci int ret; 151962306a36Sopenharmony_ci 152062306a36Sopenharmony_ci ret = clx_n_config(id); 152162306a36Sopenharmony_ci if (ret) { 152262306a36Sopenharmony_ci isst_display_error_info_message(1, "clx_n_config failed", 0, 0); 152362306a36Sopenharmony_ci } else { 152462306a36Sopenharmony_ci struct isst_pkg_ctdp_level_info *ctdp_level; 152562306a36Sopenharmony_ci struct isst_pbf_info *pbf_info; 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_ci ctdp_level = &clx_n_pkg_dev.ctdp_level[0]; 152862306a36Sopenharmony_ci pbf_info = &ctdp_level->pbf_info; 152962306a36Sopenharmony_ci isst_pbf_display_information(id, outf, tdp_level, pbf_info); 153062306a36Sopenharmony_ci free_cpu_set(ctdp_level->core_cpumask); 153162306a36Sopenharmony_ci free_cpu_set(pbf_info->core_cpumask); 153262306a36Sopenharmony_ci } 153362306a36Sopenharmony_ci} 153462306a36Sopenharmony_ci 153562306a36Sopenharmony_cistatic void dump_pbf_config_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3, 153662306a36Sopenharmony_ci void *arg4) 153762306a36Sopenharmony_ci{ 153862306a36Sopenharmony_ci struct isst_pbf_info pbf_info; 153962306a36Sopenharmony_ci int ret; 154062306a36Sopenharmony_ci 154162306a36Sopenharmony_ci ret = isst_get_pbf_info(id, tdp_level, &pbf_info); 154262306a36Sopenharmony_ci if (ret) { 154362306a36Sopenharmony_ci isst_display_error_info_message(1, "Failed to get base-freq info at this level", 1, tdp_level); 154462306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); 154562306a36Sopenharmony_ci exit(1); 154662306a36Sopenharmony_ci } else { 154762306a36Sopenharmony_ci isst_pbf_display_information(id, outf, tdp_level, &pbf_info); 154862306a36Sopenharmony_ci free_cpu_set(pbf_info.core_cpumask); 154962306a36Sopenharmony_ci } 155062306a36Sopenharmony_ci} 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_cistatic void dump_pbf_config(int arg) 155362306a36Sopenharmony_ci{ 155462306a36Sopenharmony_ci void *fn; 155562306a36Sopenharmony_ci 155662306a36Sopenharmony_ci if (cmd_help) { 155762306a36Sopenharmony_ci fprintf(stderr, 155862306a36Sopenharmony_ci "Print Intel(R) Speed Select Technology base frequency configuration for a TDP level\n"); 155962306a36Sopenharmony_ci fprintf(stderr, 156062306a36Sopenharmony_ci "\tArguments: -l|--level : Specify tdp level\n"); 156162306a36Sopenharmony_ci exit(0); 156262306a36Sopenharmony_ci } 156362306a36Sopenharmony_ci 156462306a36Sopenharmony_ci if (tdp_level == 0xff) { 156562306a36Sopenharmony_ci isst_display_error_info_message(1, "Invalid command: specify tdp_level", 0, 0); 156662306a36Sopenharmony_ci exit(1); 156762306a36Sopenharmony_ci } 156862306a36Sopenharmony_ci 156962306a36Sopenharmony_ci if (!is_clx_n_platform()) 157062306a36Sopenharmony_ci fn = dump_pbf_config_for_cpu; 157162306a36Sopenharmony_ci else 157262306a36Sopenharmony_ci fn = clx_n_dump_pbf_config_for_cpu; 157362306a36Sopenharmony_ci 157462306a36Sopenharmony_ci isst_ctdp_display_information_start(outf); 157562306a36Sopenharmony_ci 157662306a36Sopenharmony_ci if (max_target_cpus) 157762306a36Sopenharmony_ci for_each_online_target_cpu_in_set(fn, NULL, NULL, NULL, NULL); 157862306a36Sopenharmony_ci else 157962306a36Sopenharmony_ci for_each_online_power_domain_in_set(fn, NULL, NULL, NULL, NULL); 158062306a36Sopenharmony_ci 158162306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); 158262306a36Sopenharmony_ci} 158362306a36Sopenharmony_ci 158462306a36Sopenharmony_cistatic int set_clos_param(struct isst_id *id, int clos, int epp, int wt, int min, int max) 158562306a36Sopenharmony_ci{ 158662306a36Sopenharmony_ci struct isst_clos_config clos_config; 158762306a36Sopenharmony_ci int ret; 158862306a36Sopenharmony_ci 158962306a36Sopenharmony_ci ret = isst_pm_get_clos(id, clos, &clos_config); 159062306a36Sopenharmony_ci if (ret) { 159162306a36Sopenharmony_ci isst_display_error_info_message(1, "isst_pm_get_clos failed", 0, 0); 159262306a36Sopenharmony_ci return ret; 159362306a36Sopenharmony_ci } 159462306a36Sopenharmony_ci clos_config.clos_min = min; 159562306a36Sopenharmony_ci clos_config.clos_max = max; 159662306a36Sopenharmony_ci clos_config.epp = epp; 159762306a36Sopenharmony_ci clos_config.clos_prop_prio = wt; 159862306a36Sopenharmony_ci ret = isst_set_clos(id, clos, &clos_config); 159962306a36Sopenharmony_ci if (ret) { 160062306a36Sopenharmony_ci isst_display_error_info_message(1, "isst_set_clos failed", 0, 0); 160162306a36Sopenharmony_ci return ret; 160262306a36Sopenharmony_ci } 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_ci return 0; 160562306a36Sopenharmony_ci} 160662306a36Sopenharmony_ci 160762306a36Sopenharmony_cistatic int set_cpufreq_scaling_min_max(int cpu, int max, int freq) 160862306a36Sopenharmony_ci{ 160962306a36Sopenharmony_ci char buffer[128], freq_str[16]; 161062306a36Sopenharmony_ci int fd, ret, len; 161162306a36Sopenharmony_ci 161262306a36Sopenharmony_ci if (max) 161362306a36Sopenharmony_ci snprintf(buffer, sizeof(buffer), 161462306a36Sopenharmony_ci "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu); 161562306a36Sopenharmony_ci else 161662306a36Sopenharmony_ci snprintf(buffer, sizeof(buffer), 161762306a36Sopenharmony_ci "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu); 161862306a36Sopenharmony_ci 161962306a36Sopenharmony_ci fd = open(buffer, O_WRONLY); 162062306a36Sopenharmony_ci if (fd < 0) 162162306a36Sopenharmony_ci return fd; 162262306a36Sopenharmony_ci 162362306a36Sopenharmony_ci snprintf(freq_str, sizeof(freq_str), "%d", freq); 162462306a36Sopenharmony_ci len = strlen(freq_str); 162562306a36Sopenharmony_ci ret = write(fd, freq_str, len); 162662306a36Sopenharmony_ci if (ret == -1) { 162762306a36Sopenharmony_ci close(fd); 162862306a36Sopenharmony_ci return ret; 162962306a36Sopenharmony_ci } 163062306a36Sopenharmony_ci close(fd); 163162306a36Sopenharmony_ci 163262306a36Sopenharmony_ci return 0; 163362306a36Sopenharmony_ci} 163462306a36Sopenharmony_ci 163562306a36Sopenharmony_cistatic int no_turbo(void) 163662306a36Sopenharmony_ci{ 163762306a36Sopenharmony_ci return parse_int_file(0, "/sys/devices/system/cpu/intel_pstate/no_turbo"); 163862306a36Sopenharmony_ci} 163962306a36Sopenharmony_ci 164062306a36Sopenharmony_cistatic void adjust_scaling_max_from_base_freq(int cpu) 164162306a36Sopenharmony_ci{ 164262306a36Sopenharmony_ci int base_freq, scaling_max_freq; 164362306a36Sopenharmony_ci 164462306a36Sopenharmony_ci scaling_max_freq = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu); 164562306a36Sopenharmony_ci base_freq = get_cpufreq_base_freq(cpu); 164662306a36Sopenharmony_ci if (scaling_max_freq < base_freq || no_turbo()) 164762306a36Sopenharmony_ci set_cpufreq_scaling_min_max(cpu, 1, base_freq); 164862306a36Sopenharmony_ci} 164962306a36Sopenharmony_ci 165062306a36Sopenharmony_cistatic void adjust_scaling_min_from_base_freq(int cpu) 165162306a36Sopenharmony_ci{ 165262306a36Sopenharmony_ci int base_freq, scaling_min_freq; 165362306a36Sopenharmony_ci 165462306a36Sopenharmony_ci scaling_min_freq = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu); 165562306a36Sopenharmony_ci base_freq = get_cpufreq_base_freq(cpu); 165662306a36Sopenharmony_ci if (scaling_min_freq < base_freq) 165762306a36Sopenharmony_ci set_cpufreq_scaling_min_max(cpu, 0, base_freq); 165862306a36Sopenharmony_ci} 165962306a36Sopenharmony_ci 166062306a36Sopenharmony_cistatic int set_clx_pbf_cpufreq_scaling_min_max(struct isst_id *id) 166162306a36Sopenharmony_ci{ 166262306a36Sopenharmony_ci struct isst_pkg_ctdp_level_info *ctdp_level; 166362306a36Sopenharmony_ci struct isst_pbf_info *pbf_info; 166462306a36Sopenharmony_ci int i, freq, freq_high, freq_low; 166562306a36Sopenharmony_ci int ret; 166662306a36Sopenharmony_ci 166762306a36Sopenharmony_ci ret = clx_n_config(id); 166862306a36Sopenharmony_ci if (ret) { 166962306a36Sopenharmony_ci debug_printf("cpufreq_scaling_min_max failed for CLX"); 167062306a36Sopenharmony_ci return ret; 167162306a36Sopenharmony_ci } 167262306a36Sopenharmony_ci 167362306a36Sopenharmony_ci ctdp_level = &clx_n_pkg_dev.ctdp_level[0]; 167462306a36Sopenharmony_ci pbf_info = &ctdp_level->pbf_info; 167562306a36Sopenharmony_ci freq_high = pbf_info->p1_high * 100000; 167662306a36Sopenharmony_ci freq_low = pbf_info->p1_low * 100000; 167762306a36Sopenharmony_ci 167862306a36Sopenharmony_ci for (i = 0; i < get_topo_max_cpus(); ++i) { 167962306a36Sopenharmony_ci if (!is_cpu_in_power_domain(i, id)) 168062306a36Sopenharmony_ci continue; 168162306a36Sopenharmony_ci 168262306a36Sopenharmony_ci if (CPU_ISSET_S(i, pbf_info->core_cpumask_size, 168362306a36Sopenharmony_ci pbf_info->core_cpumask)) 168462306a36Sopenharmony_ci freq = freq_high; 168562306a36Sopenharmony_ci else 168662306a36Sopenharmony_ci freq = freq_low; 168762306a36Sopenharmony_ci 168862306a36Sopenharmony_ci set_cpufreq_scaling_min_max(i, 1, freq); 168962306a36Sopenharmony_ci set_cpufreq_scaling_min_max(i, 0, freq); 169062306a36Sopenharmony_ci } 169162306a36Sopenharmony_ci 169262306a36Sopenharmony_ci return 0; 169362306a36Sopenharmony_ci} 169462306a36Sopenharmony_ci 169562306a36Sopenharmony_cistatic int set_cpufreq_scaling_min_max_from_cpuinfo(int cpu, int cpuinfo_max, int scaling_max) 169662306a36Sopenharmony_ci{ 169762306a36Sopenharmony_ci char buffer[128], min_freq[16]; 169862306a36Sopenharmony_ci int fd, ret, len; 169962306a36Sopenharmony_ci 170062306a36Sopenharmony_ci if (!CPU_ISSET_S(cpu, present_cpumask_size, present_cpumask)) 170162306a36Sopenharmony_ci return -1; 170262306a36Sopenharmony_ci 170362306a36Sopenharmony_ci if (cpuinfo_max) 170462306a36Sopenharmony_ci snprintf(buffer, sizeof(buffer), 170562306a36Sopenharmony_ci "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", cpu); 170662306a36Sopenharmony_ci else 170762306a36Sopenharmony_ci snprintf(buffer, sizeof(buffer), 170862306a36Sopenharmony_ci "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_min_freq", cpu); 170962306a36Sopenharmony_ci 171062306a36Sopenharmony_ci fd = open(buffer, O_RDONLY); 171162306a36Sopenharmony_ci if (fd < 0) 171262306a36Sopenharmony_ci return fd; 171362306a36Sopenharmony_ci 171462306a36Sopenharmony_ci len = read(fd, min_freq, sizeof(min_freq)); 171562306a36Sopenharmony_ci close(fd); 171662306a36Sopenharmony_ci 171762306a36Sopenharmony_ci if (len < 0) 171862306a36Sopenharmony_ci return len; 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_ci if (scaling_max) 172162306a36Sopenharmony_ci snprintf(buffer, sizeof(buffer), 172262306a36Sopenharmony_ci "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu); 172362306a36Sopenharmony_ci else 172462306a36Sopenharmony_ci snprintf(buffer, sizeof(buffer), 172562306a36Sopenharmony_ci "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu); 172662306a36Sopenharmony_ci 172762306a36Sopenharmony_ci fd = open(buffer, O_WRONLY); 172862306a36Sopenharmony_ci if (fd < 0) 172962306a36Sopenharmony_ci return fd; 173062306a36Sopenharmony_ci 173162306a36Sopenharmony_ci min_freq[15] = '\0'; 173262306a36Sopenharmony_ci len = strlen(min_freq); 173362306a36Sopenharmony_ci ret = write(fd, min_freq, len); 173462306a36Sopenharmony_ci if (ret == -1) { 173562306a36Sopenharmony_ci close(fd); 173662306a36Sopenharmony_ci return ret; 173762306a36Sopenharmony_ci } 173862306a36Sopenharmony_ci close(fd); 173962306a36Sopenharmony_ci 174062306a36Sopenharmony_ci return 0; 174162306a36Sopenharmony_ci} 174262306a36Sopenharmony_ci 174362306a36Sopenharmony_cistatic void set_scaling_min_to_cpuinfo_max(struct isst_id *id) 174462306a36Sopenharmony_ci{ 174562306a36Sopenharmony_ci int i; 174662306a36Sopenharmony_ci 174762306a36Sopenharmony_ci if (id->cpu < 0) 174862306a36Sopenharmony_ci return; 174962306a36Sopenharmony_ci 175062306a36Sopenharmony_ci for (i = 0; i < get_topo_max_cpus(); ++i) { 175162306a36Sopenharmony_ci if (!is_cpu_in_power_domain(i, id)) 175262306a36Sopenharmony_ci continue; 175362306a36Sopenharmony_ci 175462306a36Sopenharmony_ci if (is_cpu_online(i) != 1) 175562306a36Sopenharmony_ci continue; 175662306a36Sopenharmony_ci 175762306a36Sopenharmony_ci adjust_scaling_max_from_base_freq(i); 175862306a36Sopenharmony_ci set_cpufreq_scaling_min_max_from_cpuinfo(i, 1, 0); 175962306a36Sopenharmony_ci adjust_scaling_min_from_base_freq(i); 176062306a36Sopenharmony_ci } 176162306a36Sopenharmony_ci} 176262306a36Sopenharmony_ci 176362306a36Sopenharmony_cistatic void set_scaling_min_to_cpuinfo_min(struct isst_id *id) 176462306a36Sopenharmony_ci{ 176562306a36Sopenharmony_ci int i; 176662306a36Sopenharmony_ci 176762306a36Sopenharmony_ci if (id->cpu < 0) 176862306a36Sopenharmony_ci return; 176962306a36Sopenharmony_ci 177062306a36Sopenharmony_ci for (i = 0; i < get_topo_max_cpus(); ++i) { 177162306a36Sopenharmony_ci if (!is_cpu_in_power_domain(i, id)) 177262306a36Sopenharmony_ci continue; 177362306a36Sopenharmony_ci 177462306a36Sopenharmony_ci if (is_cpu_online(i) != 1) 177562306a36Sopenharmony_ci continue; 177662306a36Sopenharmony_ci 177762306a36Sopenharmony_ci adjust_scaling_max_from_base_freq(i); 177862306a36Sopenharmony_ci set_cpufreq_scaling_min_max_from_cpuinfo(i, 0, 0); 177962306a36Sopenharmony_ci } 178062306a36Sopenharmony_ci} 178162306a36Sopenharmony_ci 178262306a36Sopenharmony_cistatic void set_scaling_max_to_cpuinfo_max(struct isst_id *id) 178362306a36Sopenharmony_ci{ 178462306a36Sopenharmony_ci int i; 178562306a36Sopenharmony_ci 178662306a36Sopenharmony_ci for (i = 0; i < get_topo_max_cpus(); ++i) { 178762306a36Sopenharmony_ci if (!is_cpu_in_power_domain(i, id)) 178862306a36Sopenharmony_ci continue; 178962306a36Sopenharmony_ci 179062306a36Sopenharmony_ci set_cpufreq_scaling_min_max_from_cpuinfo(i, 1, 1); 179162306a36Sopenharmony_ci } 179262306a36Sopenharmony_ci} 179362306a36Sopenharmony_ci 179462306a36Sopenharmony_cistatic int set_core_priority_and_min(struct isst_id *id, int mask_size, 179562306a36Sopenharmony_ci cpu_set_t *cpu_mask, int min_high, 179662306a36Sopenharmony_ci int min_low) 179762306a36Sopenharmony_ci{ 179862306a36Sopenharmony_ci int ret, i; 179962306a36Sopenharmony_ci 180062306a36Sopenharmony_ci if (!CPU_COUNT_S(mask_size, cpu_mask)) 180162306a36Sopenharmony_ci return -1; 180262306a36Sopenharmony_ci 180362306a36Sopenharmony_ci ret = set_clos_param(id, 0, 0, 0, min_high, 0xff); 180462306a36Sopenharmony_ci if (ret) 180562306a36Sopenharmony_ci return ret; 180662306a36Sopenharmony_ci 180762306a36Sopenharmony_ci ret = set_clos_param(id, 1, 15, 15, min_low, 0xff); 180862306a36Sopenharmony_ci if (ret) 180962306a36Sopenharmony_ci return ret; 181062306a36Sopenharmony_ci 181162306a36Sopenharmony_ci ret = set_clos_param(id, 2, 15, 15, min_low, 0xff); 181262306a36Sopenharmony_ci if (ret) 181362306a36Sopenharmony_ci return ret; 181462306a36Sopenharmony_ci 181562306a36Sopenharmony_ci ret = set_clos_param(id, 3, 15, 15, min_low, 0xff); 181662306a36Sopenharmony_ci if (ret) 181762306a36Sopenharmony_ci return ret; 181862306a36Sopenharmony_ci 181962306a36Sopenharmony_ci for (i = 0; i < get_topo_max_cpus(); ++i) { 182062306a36Sopenharmony_ci int clos; 182162306a36Sopenharmony_ci struct isst_id tid; 182262306a36Sopenharmony_ci 182362306a36Sopenharmony_ci if (!is_cpu_in_power_domain(i, id)) 182462306a36Sopenharmony_ci continue; 182562306a36Sopenharmony_ci 182662306a36Sopenharmony_ci if (CPU_ISSET_S(i, mask_size, cpu_mask)) 182762306a36Sopenharmony_ci clos = 0; 182862306a36Sopenharmony_ci else 182962306a36Sopenharmony_ci clos = 3; 183062306a36Sopenharmony_ci 183162306a36Sopenharmony_ci debug_printf("Associate cpu: %d clos: %d\n", i, clos); 183262306a36Sopenharmony_ci set_isst_id(&tid, i); 183362306a36Sopenharmony_ci ret = isst_clos_associate(&tid, clos); 183462306a36Sopenharmony_ci if (ret) { 183562306a36Sopenharmony_ci isst_display_error_info_message(1, "isst_clos_associate failed", 0, 0); 183662306a36Sopenharmony_ci return ret; 183762306a36Sopenharmony_ci } 183862306a36Sopenharmony_ci } 183962306a36Sopenharmony_ci 184062306a36Sopenharmony_ci return 0; 184162306a36Sopenharmony_ci} 184262306a36Sopenharmony_ci 184362306a36Sopenharmony_cistatic int set_pbf_core_power(struct isst_id *id) 184462306a36Sopenharmony_ci{ 184562306a36Sopenharmony_ci struct isst_pbf_info pbf_info; 184662306a36Sopenharmony_ci struct isst_pkg_ctdp pkg_dev; 184762306a36Sopenharmony_ci int ret; 184862306a36Sopenharmony_ci 184962306a36Sopenharmony_ci if (id->cpu < 0) 185062306a36Sopenharmony_ci return 0; 185162306a36Sopenharmony_ci 185262306a36Sopenharmony_ci ret = isst_get_ctdp_levels(id, &pkg_dev); 185362306a36Sopenharmony_ci if (ret) { 185462306a36Sopenharmony_ci debug_printf("isst_get_ctdp_levels failed"); 185562306a36Sopenharmony_ci return ret; 185662306a36Sopenharmony_ci } 185762306a36Sopenharmony_ci debug_printf("Current_level: %d\n", pkg_dev.current_level); 185862306a36Sopenharmony_ci 185962306a36Sopenharmony_ci ret = isst_get_pbf_info(id, pkg_dev.current_level, &pbf_info); 186062306a36Sopenharmony_ci if (ret) { 186162306a36Sopenharmony_ci debug_printf("isst_get_pbf_info failed"); 186262306a36Sopenharmony_ci return ret; 186362306a36Sopenharmony_ci } 186462306a36Sopenharmony_ci debug_printf("p1_high: %d p1_low: %d\n", pbf_info.p1_high, 186562306a36Sopenharmony_ci pbf_info.p1_low); 186662306a36Sopenharmony_ci 186762306a36Sopenharmony_ci ret = set_core_priority_and_min(id, pbf_info.core_cpumask_size, 186862306a36Sopenharmony_ci pbf_info.core_cpumask, 186962306a36Sopenharmony_ci pbf_info.p1_high, pbf_info.p1_low); 187062306a36Sopenharmony_ci if (ret) { 187162306a36Sopenharmony_ci debug_printf("set_core_priority_and_min failed"); 187262306a36Sopenharmony_ci return ret; 187362306a36Sopenharmony_ci } 187462306a36Sopenharmony_ci 187562306a36Sopenharmony_ci ret = isst_pm_qos_config(id, 1, 1); 187662306a36Sopenharmony_ci if (ret) { 187762306a36Sopenharmony_ci debug_printf("isst_pm_qos_config failed"); 187862306a36Sopenharmony_ci return ret; 187962306a36Sopenharmony_ci } 188062306a36Sopenharmony_ci 188162306a36Sopenharmony_ci return 0; 188262306a36Sopenharmony_ci} 188362306a36Sopenharmony_ci 188462306a36Sopenharmony_cistatic void set_pbf_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3, 188562306a36Sopenharmony_ci void *arg4) 188662306a36Sopenharmony_ci{ 188762306a36Sopenharmony_ci struct isst_pkg_ctdp_level_info ctdp_level; 188862306a36Sopenharmony_ci struct isst_pkg_ctdp pkg_dev; 188962306a36Sopenharmony_ci int ret; 189062306a36Sopenharmony_ci int status = *(int *)arg4; 189162306a36Sopenharmony_ci 189262306a36Sopenharmony_ci if (is_clx_n_platform()) { 189362306a36Sopenharmony_ci ret = 0; 189462306a36Sopenharmony_ci if (status) { 189562306a36Sopenharmony_ci set_clx_pbf_cpufreq_scaling_min_max(id); 189662306a36Sopenharmony_ci 189762306a36Sopenharmony_ci } else { 189862306a36Sopenharmony_ci set_scaling_max_to_cpuinfo_max(id); 189962306a36Sopenharmony_ci set_scaling_min_to_cpuinfo_min(id); 190062306a36Sopenharmony_ci } 190162306a36Sopenharmony_ci goto disp_result; 190262306a36Sopenharmony_ci } 190362306a36Sopenharmony_ci 190462306a36Sopenharmony_ci ret = isst_get_ctdp_levels(id, &pkg_dev); 190562306a36Sopenharmony_ci if (ret) { 190662306a36Sopenharmony_ci isst_display_error_info_message(1, "Failed to get number of levels", 0, 0); 190762306a36Sopenharmony_ci goto disp_result; 190862306a36Sopenharmony_ci } 190962306a36Sopenharmony_ci 191062306a36Sopenharmony_ci ret = isst_get_ctdp_control(id, pkg_dev.current_level, &ctdp_level); 191162306a36Sopenharmony_ci if (ret) { 191262306a36Sopenharmony_ci isst_display_error_info_message(1, "Failed to get current level", 0, 0); 191362306a36Sopenharmony_ci goto disp_result; 191462306a36Sopenharmony_ci } 191562306a36Sopenharmony_ci 191662306a36Sopenharmony_ci if (!ctdp_level.pbf_support) { 191762306a36Sopenharmony_ci isst_display_error_info_message(1, "base-freq feature is not present at this level", 1, pkg_dev.current_level); 191862306a36Sopenharmony_ci ret = -1; 191962306a36Sopenharmony_ci goto disp_result; 192062306a36Sopenharmony_ci } 192162306a36Sopenharmony_ci 192262306a36Sopenharmony_ci if (auto_mode && status) { 192362306a36Sopenharmony_ci ret = set_pbf_core_power(id); 192462306a36Sopenharmony_ci if (ret) 192562306a36Sopenharmony_ci goto disp_result; 192662306a36Sopenharmony_ci } 192762306a36Sopenharmony_ci 192862306a36Sopenharmony_ci ret = isst_set_pbf_fact_status(id, 1, status); 192962306a36Sopenharmony_ci if (ret) { 193062306a36Sopenharmony_ci debug_printf("isst_set_pbf_fact_status failed"); 193162306a36Sopenharmony_ci if (auto_mode) 193262306a36Sopenharmony_ci isst_pm_qos_config(id, 0, 0); 193362306a36Sopenharmony_ci } else { 193462306a36Sopenharmony_ci if (auto_mode) { 193562306a36Sopenharmony_ci if (status) 193662306a36Sopenharmony_ci set_scaling_min_to_cpuinfo_max(id); 193762306a36Sopenharmony_ci else 193862306a36Sopenharmony_ci set_scaling_min_to_cpuinfo_min(id); 193962306a36Sopenharmony_ci } 194062306a36Sopenharmony_ci } 194162306a36Sopenharmony_ci 194262306a36Sopenharmony_ci if (auto_mode && !status) 194362306a36Sopenharmony_ci isst_pm_qos_config(id, 0, 1); 194462306a36Sopenharmony_ci 194562306a36Sopenharmony_cidisp_result: 194662306a36Sopenharmony_ci if (status) 194762306a36Sopenharmony_ci isst_display_result(id, outf, "base-freq", "enable", 194862306a36Sopenharmony_ci ret); 194962306a36Sopenharmony_ci else 195062306a36Sopenharmony_ci isst_display_result(id, outf, "base-freq", "disable", 195162306a36Sopenharmony_ci ret); 195262306a36Sopenharmony_ci} 195362306a36Sopenharmony_ci 195462306a36Sopenharmony_cistatic void set_pbf_enable(int arg) 195562306a36Sopenharmony_ci{ 195662306a36Sopenharmony_ci int enable = arg; 195762306a36Sopenharmony_ci 195862306a36Sopenharmony_ci if (cmd_help) { 195962306a36Sopenharmony_ci if (enable) { 196062306a36Sopenharmony_ci fprintf(stderr, 196162306a36Sopenharmony_ci "Enable Intel Speed Select Technology base frequency feature\n"); 196262306a36Sopenharmony_ci if (is_clx_n_platform()) { 196362306a36Sopenharmony_ci fprintf(stderr, 196462306a36Sopenharmony_ci "\tOn this platform this command doesn't enable feature in the hardware.\n"); 196562306a36Sopenharmony_ci fprintf(stderr, 196662306a36Sopenharmony_ci "\tIt updates the cpufreq scaling_min_freq to match cpufreq base_frequency.\n"); 196762306a36Sopenharmony_ci exit(0); 196862306a36Sopenharmony_ci 196962306a36Sopenharmony_ci } 197062306a36Sopenharmony_ci fprintf(stderr, 197162306a36Sopenharmony_ci "\tOptional Arguments: -a|--auto : Use priority of cores to set core-power associations\n"); 197262306a36Sopenharmony_ci } else { 197362306a36Sopenharmony_ci 197462306a36Sopenharmony_ci if (is_clx_n_platform()) { 197562306a36Sopenharmony_ci fprintf(stderr, 197662306a36Sopenharmony_ci "\tOn this platform this command doesn't disable feature in the hardware.\n"); 197762306a36Sopenharmony_ci fprintf(stderr, 197862306a36Sopenharmony_ci "\tIt updates the cpufreq scaling_min_freq to match cpuinfo_min_freq\n"); 197962306a36Sopenharmony_ci exit(0); 198062306a36Sopenharmony_ci } 198162306a36Sopenharmony_ci fprintf(stderr, 198262306a36Sopenharmony_ci "Disable Intel Speed Select Technology base frequency feature\n"); 198362306a36Sopenharmony_ci fprintf(stderr, 198462306a36Sopenharmony_ci "\tOptional Arguments: -a|--auto : Also disable core-power associations\n"); 198562306a36Sopenharmony_ci } 198662306a36Sopenharmony_ci exit(0); 198762306a36Sopenharmony_ci } 198862306a36Sopenharmony_ci 198962306a36Sopenharmony_ci isst_ctdp_display_information_start(outf); 199062306a36Sopenharmony_ci if (max_target_cpus) 199162306a36Sopenharmony_ci for_each_online_target_cpu_in_set(set_pbf_for_cpu, NULL, NULL, 199262306a36Sopenharmony_ci NULL, &enable); 199362306a36Sopenharmony_ci else 199462306a36Sopenharmony_ci for_each_online_power_domain_in_set(set_pbf_for_cpu, NULL, NULL, 199562306a36Sopenharmony_ci NULL, &enable); 199662306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); 199762306a36Sopenharmony_ci} 199862306a36Sopenharmony_ci 199962306a36Sopenharmony_cistatic void dump_fact_config_for_cpu(struct isst_id *id, void *arg1, void *arg2, 200062306a36Sopenharmony_ci void *arg3, void *arg4) 200162306a36Sopenharmony_ci{ 200262306a36Sopenharmony_ci struct isst_fact_info fact_info; 200362306a36Sopenharmony_ci int ret; 200462306a36Sopenharmony_ci 200562306a36Sopenharmony_ci ret = isst_get_fact_info(id, tdp_level, fact_bucket, &fact_info); 200662306a36Sopenharmony_ci if (ret) { 200762306a36Sopenharmony_ci isst_display_error_info_message(1, "Failed to get turbo-freq info at this level", 1, tdp_level); 200862306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); 200962306a36Sopenharmony_ci exit(1); 201062306a36Sopenharmony_ci } else { 201162306a36Sopenharmony_ci isst_fact_display_information(id, outf, tdp_level, fact_bucket, 201262306a36Sopenharmony_ci fact_avx, &fact_info); 201362306a36Sopenharmony_ci } 201462306a36Sopenharmony_ci} 201562306a36Sopenharmony_ci 201662306a36Sopenharmony_cistatic void dump_fact_config(int arg) 201762306a36Sopenharmony_ci{ 201862306a36Sopenharmony_ci if (cmd_help) { 201962306a36Sopenharmony_ci fprintf(stderr, 202062306a36Sopenharmony_ci "Print complete Intel Speed Select Technology turbo frequency configuration for a TDP level. Other arguments are optional.\n"); 202162306a36Sopenharmony_ci fprintf(stderr, 202262306a36Sopenharmony_ci "\tArguments: -l|--level : Specify tdp level\n"); 202362306a36Sopenharmony_ci fprintf(stderr, 202462306a36Sopenharmony_ci "\tArguments: -b|--bucket : Bucket index to dump\n"); 202562306a36Sopenharmony_ci fprintf(stderr, 202662306a36Sopenharmony_ci "\tArguments: -r|--trl-type : Specify trl type: sse|avx2|avx512\n"); 202762306a36Sopenharmony_ci exit(0); 202862306a36Sopenharmony_ci } 202962306a36Sopenharmony_ci 203062306a36Sopenharmony_ci if (tdp_level == 0xff) { 203162306a36Sopenharmony_ci isst_display_error_info_message(1, "Invalid command: specify tdp_level\n", 0, 0); 203262306a36Sopenharmony_ci exit(1); 203362306a36Sopenharmony_ci } 203462306a36Sopenharmony_ci 203562306a36Sopenharmony_ci isst_ctdp_display_information_start(outf); 203662306a36Sopenharmony_ci if (max_target_cpus) 203762306a36Sopenharmony_ci for_each_online_target_cpu_in_set(dump_fact_config_for_cpu, 203862306a36Sopenharmony_ci NULL, NULL, NULL, NULL); 203962306a36Sopenharmony_ci else 204062306a36Sopenharmony_ci for_each_online_power_domain_in_set(dump_fact_config_for_cpu, NULL, 204162306a36Sopenharmony_ci NULL, NULL, NULL); 204262306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); 204362306a36Sopenharmony_ci} 204462306a36Sopenharmony_ci 204562306a36Sopenharmony_cistatic void set_fact_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3, 204662306a36Sopenharmony_ci void *arg4) 204762306a36Sopenharmony_ci{ 204862306a36Sopenharmony_ci struct isst_pkg_ctdp_level_info ctdp_level; 204962306a36Sopenharmony_ci struct isst_pkg_ctdp pkg_dev; 205062306a36Sopenharmony_ci int ret; 205162306a36Sopenharmony_ci int status = *(int *)arg4; 205262306a36Sopenharmony_ci 205362306a36Sopenharmony_ci if (status && no_turbo()) { 205462306a36Sopenharmony_ci isst_display_error_info_message(1, "Turbo mode is disabled", 0, 0); 205562306a36Sopenharmony_ci ret = -1; 205662306a36Sopenharmony_ci goto disp_results; 205762306a36Sopenharmony_ci } 205862306a36Sopenharmony_ci 205962306a36Sopenharmony_ci ret = isst_get_ctdp_levels(id, &pkg_dev); 206062306a36Sopenharmony_ci if (ret) { 206162306a36Sopenharmony_ci isst_display_error_info_message(1, "Failed to get number of levels", 0, 0); 206262306a36Sopenharmony_ci goto disp_results; 206362306a36Sopenharmony_ci } 206462306a36Sopenharmony_ci 206562306a36Sopenharmony_ci ret = isst_get_ctdp_control(id, pkg_dev.current_level, &ctdp_level); 206662306a36Sopenharmony_ci if (ret) { 206762306a36Sopenharmony_ci isst_display_error_info_message(1, "Failed to get current level", 0, 0); 206862306a36Sopenharmony_ci goto disp_results; 206962306a36Sopenharmony_ci } 207062306a36Sopenharmony_ci 207162306a36Sopenharmony_ci if (!ctdp_level.fact_support) { 207262306a36Sopenharmony_ci isst_display_error_info_message(1, "turbo-freq feature is not present at this level", 1, pkg_dev.current_level); 207362306a36Sopenharmony_ci ret = -1; 207462306a36Sopenharmony_ci goto disp_results; 207562306a36Sopenharmony_ci } 207662306a36Sopenharmony_ci 207762306a36Sopenharmony_ci if (status) { 207862306a36Sopenharmony_ci ret = isst_pm_qos_config(id, 1, 1); 207962306a36Sopenharmony_ci if (ret) 208062306a36Sopenharmony_ci goto disp_results; 208162306a36Sopenharmony_ci } 208262306a36Sopenharmony_ci 208362306a36Sopenharmony_ci ret = isst_set_pbf_fact_status(id, 0, status); 208462306a36Sopenharmony_ci if (ret) { 208562306a36Sopenharmony_ci debug_printf("isst_set_pbf_fact_status failed"); 208662306a36Sopenharmony_ci if (auto_mode) 208762306a36Sopenharmony_ci isst_pm_qos_config(id, 0, 0); 208862306a36Sopenharmony_ci 208962306a36Sopenharmony_ci goto disp_results; 209062306a36Sopenharmony_ci } 209162306a36Sopenharmony_ci 209262306a36Sopenharmony_ci /* Set TRL */ 209362306a36Sopenharmony_ci if (status) { 209462306a36Sopenharmony_ci struct isst_pkg_ctdp pkg_dev; 209562306a36Sopenharmony_ci 209662306a36Sopenharmony_ci ret = isst_get_ctdp_levels(id, &pkg_dev); 209762306a36Sopenharmony_ci if (!ret && id->cpu >= 0) 209862306a36Sopenharmony_ci ret = isst_set_trl(id, fact_trl); 209962306a36Sopenharmony_ci if (ret && auto_mode) 210062306a36Sopenharmony_ci isst_pm_qos_config(id, 0, 0); 210162306a36Sopenharmony_ci } else { 210262306a36Sopenharmony_ci if (auto_mode) 210362306a36Sopenharmony_ci isst_pm_qos_config(id, 0, 0); 210462306a36Sopenharmony_ci } 210562306a36Sopenharmony_ci 210662306a36Sopenharmony_cidisp_results: 210762306a36Sopenharmony_ci if (status) { 210862306a36Sopenharmony_ci isst_display_result(id, outf, "turbo-freq", "enable", ret); 210962306a36Sopenharmony_ci if (ret) 211062306a36Sopenharmony_ci fact_enable_fail = ret; 211162306a36Sopenharmony_ci } else { 211262306a36Sopenharmony_ci /* Since we modified TRL during Fact enable, restore it */ 211362306a36Sopenharmony_ci isst_set_trl_from_current_tdp(id, fact_trl); 211462306a36Sopenharmony_ci isst_display_result(id, outf, "turbo-freq", "disable", ret); 211562306a36Sopenharmony_ci } 211662306a36Sopenharmony_ci} 211762306a36Sopenharmony_ci 211862306a36Sopenharmony_cistatic void set_fact_enable(int arg) 211962306a36Sopenharmony_ci{ 212062306a36Sopenharmony_ci int i, ret, enable = arg; 212162306a36Sopenharmony_ci struct isst_id id; 212262306a36Sopenharmony_ci 212362306a36Sopenharmony_ci if (cmd_help) { 212462306a36Sopenharmony_ci if (enable) { 212562306a36Sopenharmony_ci fprintf(stderr, 212662306a36Sopenharmony_ci "Enable Intel Speed Select Technology Turbo frequency feature\n"); 212762306a36Sopenharmony_ci fprintf(stderr, 212862306a36Sopenharmony_ci "Optional: -t|--trl : Specify turbo ratio limit\n"); 212962306a36Sopenharmony_ci fprintf(stderr, 213062306a36Sopenharmony_ci "\tOptional Arguments: -a|--auto : Designate specified target CPUs with"); 213162306a36Sopenharmony_ci fprintf(stderr, 213262306a36Sopenharmony_ci "-C|--cpu option as as high priority using core-power feature\n"); 213362306a36Sopenharmony_ci } else { 213462306a36Sopenharmony_ci fprintf(stderr, 213562306a36Sopenharmony_ci "Disable Intel Speed Select Technology turbo frequency feature\n"); 213662306a36Sopenharmony_ci fprintf(stderr, 213762306a36Sopenharmony_ci "Optional: -t|--trl : Specify turbo ratio limit\n"); 213862306a36Sopenharmony_ci fprintf(stderr, 213962306a36Sopenharmony_ci "\tOptional Arguments: -a|--auto : Also disable core-power associations\n"); 214062306a36Sopenharmony_ci } 214162306a36Sopenharmony_ci exit(0); 214262306a36Sopenharmony_ci } 214362306a36Sopenharmony_ci 214462306a36Sopenharmony_ci isst_ctdp_display_information_start(outf); 214562306a36Sopenharmony_ci if (max_target_cpus) 214662306a36Sopenharmony_ci for_each_online_target_cpu_in_set(set_fact_for_cpu, NULL, NULL, 214762306a36Sopenharmony_ci NULL, &enable); 214862306a36Sopenharmony_ci else 214962306a36Sopenharmony_ci for_each_online_power_domain_in_set(set_fact_for_cpu, NULL, NULL, 215062306a36Sopenharmony_ci NULL, &enable); 215162306a36Sopenharmony_ci 215262306a36Sopenharmony_ci if (!fact_enable_fail && enable && auto_mode) { 215362306a36Sopenharmony_ci /* 215462306a36Sopenharmony_ci * When we adjust CLOS param, we have to set for siblings also. 215562306a36Sopenharmony_ci * So for the each user specified CPU, also add the sibling 215662306a36Sopenharmony_ci * in the present_cpu_mask. 215762306a36Sopenharmony_ci */ 215862306a36Sopenharmony_ci for (i = 0; i < get_topo_max_cpus(); ++i) { 215962306a36Sopenharmony_ci char buffer[128], sibling_list[128], *cpu_str; 216062306a36Sopenharmony_ci int fd, len; 216162306a36Sopenharmony_ci 216262306a36Sopenharmony_ci if (!CPU_ISSET_S(i, target_cpumask_size, target_cpumask)) 216362306a36Sopenharmony_ci continue; 216462306a36Sopenharmony_ci 216562306a36Sopenharmony_ci snprintf(buffer, sizeof(buffer), 216662306a36Sopenharmony_ci "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", i); 216762306a36Sopenharmony_ci 216862306a36Sopenharmony_ci fd = open(buffer, O_RDONLY); 216962306a36Sopenharmony_ci if (fd < 0) 217062306a36Sopenharmony_ci continue; 217162306a36Sopenharmony_ci 217262306a36Sopenharmony_ci len = read(fd, sibling_list, sizeof(sibling_list)); 217362306a36Sopenharmony_ci close(fd); 217462306a36Sopenharmony_ci 217562306a36Sopenharmony_ci if (len < 0) 217662306a36Sopenharmony_ci continue; 217762306a36Sopenharmony_ci 217862306a36Sopenharmony_ci sibling_list[127] = '\0'; 217962306a36Sopenharmony_ci cpu_str = strtok(sibling_list, ","); 218062306a36Sopenharmony_ci while (cpu_str != NULL) { 218162306a36Sopenharmony_ci int cpu; 218262306a36Sopenharmony_ci 218362306a36Sopenharmony_ci sscanf(cpu_str, "%d", &cpu); 218462306a36Sopenharmony_ci CPU_SET_S(cpu, target_cpumask_size, target_cpumask); 218562306a36Sopenharmony_ci cpu_str = strtok(NULL, ","); 218662306a36Sopenharmony_ci } 218762306a36Sopenharmony_ci } 218862306a36Sopenharmony_ci 218962306a36Sopenharmony_ci for (i = 0; i < get_topo_max_cpus(); ++i) { 219062306a36Sopenharmony_ci int clos; 219162306a36Sopenharmony_ci 219262306a36Sopenharmony_ci if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask)) 219362306a36Sopenharmony_ci continue; 219462306a36Sopenharmony_ci 219562306a36Sopenharmony_ci if (is_cpu_online(i) != 1) 219662306a36Sopenharmony_ci continue; 219762306a36Sopenharmony_ci 219862306a36Sopenharmony_ci set_isst_id(&id, i); 219962306a36Sopenharmony_ci ret = set_clos_param(&id, 0, 0, 0, 0, 0xff); 220062306a36Sopenharmony_ci if (ret) 220162306a36Sopenharmony_ci goto error_disp; 220262306a36Sopenharmony_ci 220362306a36Sopenharmony_ci ret = set_clos_param(&id, 1, 15, 15, 0, 0xff); 220462306a36Sopenharmony_ci if (ret) 220562306a36Sopenharmony_ci goto error_disp; 220662306a36Sopenharmony_ci 220762306a36Sopenharmony_ci ret = set_clos_param(&id, 2, 15, 15, 0, 0xff); 220862306a36Sopenharmony_ci if (ret) 220962306a36Sopenharmony_ci goto error_disp; 221062306a36Sopenharmony_ci 221162306a36Sopenharmony_ci ret = set_clos_param(&id, 3, 15, 15, 0, 0xff); 221262306a36Sopenharmony_ci if (ret) 221362306a36Sopenharmony_ci goto error_disp; 221462306a36Sopenharmony_ci 221562306a36Sopenharmony_ci if (CPU_ISSET_S(i, target_cpumask_size, target_cpumask)) 221662306a36Sopenharmony_ci clos = 0; 221762306a36Sopenharmony_ci else 221862306a36Sopenharmony_ci clos = 3; 221962306a36Sopenharmony_ci 222062306a36Sopenharmony_ci debug_printf("Associate cpu: %d clos: %d\n", i, clos); 222162306a36Sopenharmony_ci ret = isst_clos_associate(&id, clos); 222262306a36Sopenharmony_ci if (ret) 222362306a36Sopenharmony_ci goto error_disp; 222462306a36Sopenharmony_ci } 222562306a36Sopenharmony_ci set_isst_id(&id, -1); 222662306a36Sopenharmony_ci isst_display_result(&id, outf, "turbo-freq --auto", "enable", 0); 222762306a36Sopenharmony_ci } 222862306a36Sopenharmony_ci 222962306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); 223062306a36Sopenharmony_ci 223162306a36Sopenharmony_ci return; 223262306a36Sopenharmony_ci 223362306a36Sopenharmony_cierror_disp: 223462306a36Sopenharmony_ci isst_display_result(&id, outf, "turbo-freq --auto", "enable", ret); 223562306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); 223662306a36Sopenharmony_ci 223762306a36Sopenharmony_ci} 223862306a36Sopenharmony_ci 223962306a36Sopenharmony_cistatic void enable_clos_qos_config(struct isst_id *id, void *arg1, void *arg2, void *arg3, 224062306a36Sopenharmony_ci void *arg4) 224162306a36Sopenharmony_ci{ 224262306a36Sopenharmony_ci int ret; 224362306a36Sopenharmony_ci int status = *(int *)arg4; 224462306a36Sopenharmony_ci 224562306a36Sopenharmony_ci if (is_skx_based_platform()) 224662306a36Sopenharmony_ci clos_priority_type = 1; 224762306a36Sopenharmony_ci 224862306a36Sopenharmony_ci ret = isst_pm_qos_config(id, status, clos_priority_type); 224962306a36Sopenharmony_ci if (ret) 225062306a36Sopenharmony_ci isst_display_error_info_message(1, "isst_pm_qos_config failed", 0, 0); 225162306a36Sopenharmony_ci 225262306a36Sopenharmony_ci if (status) 225362306a36Sopenharmony_ci isst_display_result(id, outf, "core-power", "enable", 225462306a36Sopenharmony_ci ret); 225562306a36Sopenharmony_ci else 225662306a36Sopenharmony_ci isst_display_result(id, outf, "core-power", "disable", 225762306a36Sopenharmony_ci ret); 225862306a36Sopenharmony_ci} 225962306a36Sopenharmony_ci 226062306a36Sopenharmony_cistatic void set_clos_enable(int arg) 226162306a36Sopenharmony_ci{ 226262306a36Sopenharmony_ci int enable = arg; 226362306a36Sopenharmony_ci 226462306a36Sopenharmony_ci if (cmd_help) { 226562306a36Sopenharmony_ci if (enable) { 226662306a36Sopenharmony_ci fprintf(stderr, 226762306a36Sopenharmony_ci "Enable core-power for a package/die\n"); 226862306a36Sopenharmony_ci if (!is_skx_based_platform()) { 226962306a36Sopenharmony_ci fprintf(stderr, 227062306a36Sopenharmony_ci "\tClos Enable: Specify priority type with [--priority|-p]\n"); 227162306a36Sopenharmony_ci fprintf(stderr, "\t\t 0: Proportional, 1: Ordered\n"); 227262306a36Sopenharmony_ci } 227362306a36Sopenharmony_ci } else { 227462306a36Sopenharmony_ci fprintf(stderr, 227562306a36Sopenharmony_ci "Disable core-power: [No command arguments are required]\n"); 227662306a36Sopenharmony_ci } 227762306a36Sopenharmony_ci exit(0); 227862306a36Sopenharmony_ci } 227962306a36Sopenharmony_ci 228062306a36Sopenharmony_ci if (enable && cpufreq_sysfs_present()) { 228162306a36Sopenharmony_ci fprintf(stderr, 228262306a36Sopenharmony_ci "cpufreq subsystem and core-power enable will interfere with each other!\n"); 228362306a36Sopenharmony_ci } 228462306a36Sopenharmony_ci 228562306a36Sopenharmony_ci isst_ctdp_display_information_start(outf); 228662306a36Sopenharmony_ci if (max_target_cpus) 228762306a36Sopenharmony_ci for_each_online_target_cpu_in_set(enable_clos_qos_config, NULL, 228862306a36Sopenharmony_ci NULL, NULL, &enable); 228962306a36Sopenharmony_ci else 229062306a36Sopenharmony_ci for_each_online_power_domain_in_set(enable_clos_qos_config, NULL, 229162306a36Sopenharmony_ci NULL, NULL, &enable); 229262306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); 229362306a36Sopenharmony_ci} 229462306a36Sopenharmony_ci 229562306a36Sopenharmony_cistatic void dump_clos_config_for_cpu(struct isst_id *id, void *arg1, void *arg2, 229662306a36Sopenharmony_ci void *arg3, void *arg4) 229762306a36Sopenharmony_ci{ 229862306a36Sopenharmony_ci struct isst_clos_config clos_config; 229962306a36Sopenharmony_ci int ret; 230062306a36Sopenharmony_ci 230162306a36Sopenharmony_ci ret = isst_pm_get_clos(id, current_clos, &clos_config); 230262306a36Sopenharmony_ci if (ret) 230362306a36Sopenharmony_ci isst_display_error_info_message(1, "isst_pm_get_clos failed", 0, 0); 230462306a36Sopenharmony_ci else 230562306a36Sopenharmony_ci isst_clos_display_information(id, outf, current_clos, 230662306a36Sopenharmony_ci &clos_config); 230762306a36Sopenharmony_ci} 230862306a36Sopenharmony_ci 230962306a36Sopenharmony_cistatic void dump_clos_config(int arg) 231062306a36Sopenharmony_ci{ 231162306a36Sopenharmony_ci if (cmd_help) { 231262306a36Sopenharmony_ci fprintf(stderr, 231362306a36Sopenharmony_ci "Print Intel Speed Select Technology core power configuration\n"); 231462306a36Sopenharmony_ci fprintf(stderr, 231562306a36Sopenharmony_ci "\tArguments: [-c | --clos]: Specify clos id\n"); 231662306a36Sopenharmony_ci exit(0); 231762306a36Sopenharmony_ci } 231862306a36Sopenharmony_ci if (current_clos < 0 || current_clos > 3) { 231962306a36Sopenharmony_ci isst_display_error_info_message(1, "Invalid clos id\n", 0, 0); 232062306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); 232162306a36Sopenharmony_ci exit(0); 232262306a36Sopenharmony_ci } 232362306a36Sopenharmony_ci 232462306a36Sopenharmony_ci isst_ctdp_display_information_start(outf); 232562306a36Sopenharmony_ci if (max_target_cpus) 232662306a36Sopenharmony_ci for_each_online_target_cpu_in_set(dump_clos_config_for_cpu, 232762306a36Sopenharmony_ci NULL, NULL, NULL, NULL); 232862306a36Sopenharmony_ci else 232962306a36Sopenharmony_ci for_each_online_power_domain_in_set(dump_clos_config_for_cpu, NULL, 233062306a36Sopenharmony_ci NULL, NULL, NULL); 233162306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); 233262306a36Sopenharmony_ci} 233362306a36Sopenharmony_ci 233462306a36Sopenharmony_cistatic void get_clos_info_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3, 233562306a36Sopenharmony_ci void *arg4) 233662306a36Sopenharmony_ci{ 233762306a36Sopenharmony_ci int enable, ret, prio_type; 233862306a36Sopenharmony_ci 233962306a36Sopenharmony_ci ret = isst_clos_get_clos_information(id, &enable, &prio_type); 234062306a36Sopenharmony_ci if (ret) 234162306a36Sopenharmony_ci isst_display_error_info_message(1, "isst_clos_get_info failed", 0, 0); 234262306a36Sopenharmony_ci else { 234362306a36Sopenharmony_ci int cp_state, cp_cap; 234462306a36Sopenharmony_ci 234562306a36Sopenharmony_ci isst_read_pm_config(id, &cp_state, &cp_cap); 234662306a36Sopenharmony_ci isst_clos_display_clos_information(id, outf, enable, prio_type, 234762306a36Sopenharmony_ci cp_state, cp_cap); 234862306a36Sopenharmony_ci } 234962306a36Sopenharmony_ci} 235062306a36Sopenharmony_ci 235162306a36Sopenharmony_cistatic void dump_clos_info(int arg) 235262306a36Sopenharmony_ci{ 235362306a36Sopenharmony_ci if (cmd_help) { 235462306a36Sopenharmony_ci fprintf(stderr, 235562306a36Sopenharmony_ci "Print Intel Speed Select Technology core power information\n"); 235662306a36Sopenharmony_ci fprintf(stderr, "\t Optionally specify targeted cpu id with [--cpu|-c]\n"); 235762306a36Sopenharmony_ci exit(0); 235862306a36Sopenharmony_ci } 235962306a36Sopenharmony_ci 236062306a36Sopenharmony_ci isst_ctdp_display_information_start(outf); 236162306a36Sopenharmony_ci if (max_target_cpus) 236262306a36Sopenharmony_ci for_each_online_target_cpu_in_set(get_clos_info_for_cpu, NULL, 236362306a36Sopenharmony_ci NULL, NULL, NULL); 236462306a36Sopenharmony_ci else 236562306a36Sopenharmony_ci for_each_online_power_domain_in_set(get_clos_info_for_cpu, NULL, 236662306a36Sopenharmony_ci NULL, NULL, NULL); 236762306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); 236862306a36Sopenharmony_ci 236962306a36Sopenharmony_ci} 237062306a36Sopenharmony_ci 237162306a36Sopenharmony_cistatic void set_clos_config_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3, 237262306a36Sopenharmony_ci void *arg4) 237362306a36Sopenharmony_ci{ 237462306a36Sopenharmony_ci struct isst_clos_config clos_config; 237562306a36Sopenharmony_ci int ret; 237662306a36Sopenharmony_ci 237762306a36Sopenharmony_ci if (id->cpu < 0) 237862306a36Sopenharmony_ci return; 237962306a36Sopenharmony_ci 238062306a36Sopenharmony_ci clos_config.epp = clos_epp; 238162306a36Sopenharmony_ci clos_config.clos_prop_prio = clos_prop_prio; 238262306a36Sopenharmony_ci clos_config.clos_min = clos_min; 238362306a36Sopenharmony_ci clos_config.clos_max = clos_max; 238462306a36Sopenharmony_ci clos_config.clos_desired = clos_desired; 238562306a36Sopenharmony_ci ret = isst_set_clos(id, current_clos, &clos_config); 238662306a36Sopenharmony_ci if (ret) 238762306a36Sopenharmony_ci isst_display_error_info_message(1, "isst_set_clos failed", 0, 0); 238862306a36Sopenharmony_ci else 238962306a36Sopenharmony_ci isst_display_result(id, outf, "core-power", "config", ret); 239062306a36Sopenharmony_ci} 239162306a36Sopenharmony_ci 239262306a36Sopenharmony_cistatic void set_clos_config(int arg) 239362306a36Sopenharmony_ci{ 239462306a36Sopenharmony_ci if (cmd_help) { 239562306a36Sopenharmony_ci fprintf(stderr, 239662306a36Sopenharmony_ci "Set core-power configuration for one of the four clos ids\n"); 239762306a36Sopenharmony_ci fprintf(stderr, 239862306a36Sopenharmony_ci "\tSpecify targeted clos id with [--clos|-c]\n"); 239962306a36Sopenharmony_ci if (!is_skx_based_platform()) { 240062306a36Sopenharmony_ci fprintf(stderr, "\tSpecify clos EPP with [--epp|-e]\n"); 240162306a36Sopenharmony_ci fprintf(stderr, 240262306a36Sopenharmony_ci "\tSpecify clos Proportional Priority [--weight|-w]\n"); 240362306a36Sopenharmony_ci } 240462306a36Sopenharmony_ci fprintf(stderr, "\tSpecify clos min in MHz with [--min|-n]\n"); 240562306a36Sopenharmony_ci fprintf(stderr, "\tSpecify clos max in MHz with [--max|-m]\n"); 240662306a36Sopenharmony_ci exit(0); 240762306a36Sopenharmony_ci } 240862306a36Sopenharmony_ci 240962306a36Sopenharmony_ci if (current_clos < 0 || current_clos > 3) { 241062306a36Sopenharmony_ci isst_display_error_info_message(1, "Invalid clos id\n", 0, 0); 241162306a36Sopenharmony_ci exit(0); 241262306a36Sopenharmony_ci } 241362306a36Sopenharmony_ci if (!is_skx_based_platform() && (clos_epp < 0 || clos_epp > 0x0F)) { 241462306a36Sopenharmony_ci fprintf(stderr, "clos epp is not specified or invalid, default: 0\n"); 241562306a36Sopenharmony_ci clos_epp = 0; 241662306a36Sopenharmony_ci } 241762306a36Sopenharmony_ci if (!is_skx_based_platform() && (clos_prop_prio < 0 || clos_prop_prio > 0x0F)) { 241862306a36Sopenharmony_ci fprintf(stderr, 241962306a36Sopenharmony_ci "clos frequency weight is not specified or invalid, default: 0\n"); 242062306a36Sopenharmony_ci clos_prop_prio = 0; 242162306a36Sopenharmony_ci } 242262306a36Sopenharmony_ci if (clos_min < 0) { 242362306a36Sopenharmony_ci fprintf(stderr, "clos min is not specified, default: 0\n"); 242462306a36Sopenharmony_ci clos_min = 0; 242562306a36Sopenharmony_ci } 242662306a36Sopenharmony_ci if (clos_max < 0) { 242762306a36Sopenharmony_ci fprintf(stderr, "clos max is not specified, default: Max frequency (ratio 0xff)\n"); 242862306a36Sopenharmony_ci clos_max = 0xff; 242962306a36Sopenharmony_ci } 243062306a36Sopenharmony_ci if (clos_desired) { 243162306a36Sopenharmony_ci fprintf(stderr, "clos desired is not supported on this platform\n"); 243262306a36Sopenharmony_ci clos_desired = 0x00; 243362306a36Sopenharmony_ci } 243462306a36Sopenharmony_ci 243562306a36Sopenharmony_ci isst_ctdp_display_information_start(outf); 243662306a36Sopenharmony_ci if (max_target_cpus) 243762306a36Sopenharmony_ci for_each_online_target_cpu_in_set(set_clos_config_for_cpu, NULL, 243862306a36Sopenharmony_ci NULL, NULL, NULL); 243962306a36Sopenharmony_ci else 244062306a36Sopenharmony_ci for_each_online_power_domain_in_set(set_clos_config_for_cpu, NULL, 244162306a36Sopenharmony_ci NULL, NULL, NULL); 244262306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); 244362306a36Sopenharmony_ci} 244462306a36Sopenharmony_ci 244562306a36Sopenharmony_cistatic void set_clos_assoc_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3, 244662306a36Sopenharmony_ci void *arg4) 244762306a36Sopenharmony_ci{ 244862306a36Sopenharmony_ci int ret; 244962306a36Sopenharmony_ci 245062306a36Sopenharmony_ci ret = isst_clos_associate(id, current_clos); 245162306a36Sopenharmony_ci if (ret) 245262306a36Sopenharmony_ci debug_printf("isst_clos_associate failed"); 245362306a36Sopenharmony_ci else 245462306a36Sopenharmony_ci isst_display_result(id, outf, "core-power", "assoc", ret); 245562306a36Sopenharmony_ci} 245662306a36Sopenharmony_ci 245762306a36Sopenharmony_cistatic void set_clos_assoc(int arg) 245862306a36Sopenharmony_ci{ 245962306a36Sopenharmony_ci if (cmd_help) { 246062306a36Sopenharmony_ci fprintf(stderr, "Associate a clos id to a CPU\n"); 246162306a36Sopenharmony_ci fprintf(stderr, 246262306a36Sopenharmony_ci "\tSpecify targeted clos id with [--clos|-c]\n"); 246362306a36Sopenharmony_ci fprintf(stderr, 246462306a36Sopenharmony_ci "\tFor example to associate clos 1 to CPU 0: issue\n"); 246562306a36Sopenharmony_ci fprintf(stderr, 246662306a36Sopenharmony_ci "\tintel-speed-select --cpu 0 core-power assoc --clos 1\n"); 246762306a36Sopenharmony_ci exit(0); 246862306a36Sopenharmony_ci } 246962306a36Sopenharmony_ci 247062306a36Sopenharmony_ci if (current_clos < 0 || current_clos > 3) { 247162306a36Sopenharmony_ci isst_display_error_info_message(1, "Invalid clos id\n", 0, 0); 247262306a36Sopenharmony_ci exit(0); 247362306a36Sopenharmony_ci } 247462306a36Sopenharmony_ci 247562306a36Sopenharmony_ci isst_ctdp_display_information_start(outf); 247662306a36Sopenharmony_ci 247762306a36Sopenharmony_ci if (max_target_cpus) 247862306a36Sopenharmony_ci for_each_online_target_cpu_in_set(set_clos_assoc_for_cpu, NULL, 247962306a36Sopenharmony_ci NULL, NULL, NULL); 248062306a36Sopenharmony_ci else { 248162306a36Sopenharmony_ci isst_display_error_info_message(1, "Invalid target cpu. Specify with [-c|--cpu]", 0, 0); 248262306a36Sopenharmony_ci } 248362306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); 248462306a36Sopenharmony_ci} 248562306a36Sopenharmony_ci 248662306a36Sopenharmony_cistatic void get_clos_assoc_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3, 248762306a36Sopenharmony_ci void *arg4) 248862306a36Sopenharmony_ci{ 248962306a36Sopenharmony_ci int clos, ret; 249062306a36Sopenharmony_ci 249162306a36Sopenharmony_ci ret = isst_clos_get_assoc_status(id, &clos); 249262306a36Sopenharmony_ci if (ret) 249362306a36Sopenharmony_ci isst_display_error_info_message(1, "isst_clos_get_assoc_status failed", 0, 0); 249462306a36Sopenharmony_ci else 249562306a36Sopenharmony_ci isst_clos_display_assoc_information(id, outf, clos); 249662306a36Sopenharmony_ci} 249762306a36Sopenharmony_ci 249862306a36Sopenharmony_cistatic void get_clos_assoc(int arg) 249962306a36Sopenharmony_ci{ 250062306a36Sopenharmony_ci if (cmd_help) { 250162306a36Sopenharmony_ci fprintf(stderr, "Get associate clos id to a CPU\n"); 250262306a36Sopenharmony_ci fprintf(stderr, "\tSpecify targeted cpu id with [--cpu|-c]\n"); 250362306a36Sopenharmony_ci exit(0); 250462306a36Sopenharmony_ci } 250562306a36Sopenharmony_ci 250662306a36Sopenharmony_ci if (!max_target_cpus) { 250762306a36Sopenharmony_ci isst_display_error_info_message(1, "Invalid target cpu. Specify with [-c|--cpu]", 0, 0); 250862306a36Sopenharmony_ci exit(0); 250962306a36Sopenharmony_ci } 251062306a36Sopenharmony_ci 251162306a36Sopenharmony_ci isst_ctdp_display_information_start(outf); 251262306a36Sopenharmony_ci for_each_online_target_cpu_in_set(get_clos_assoc_for_cpu, NULL, 251362306a36Sopenharmony_ci NULL, NULL, NULL); 251462306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); 251562306a36Sopenharmony_ci} 251662306a36Sopenharmony_ci 251762306a36Sopenharmony_cistatic void set_turbo_mode_for_cpu(struct isst_id *id, int status) 251862306a36Sopenharmony_ci{ 251962306a36Sopenharmony_ci int base_freq; 252062306a36Sopenharmony_ci 252162306a36Sopenharmony_ci if (status) { 252262306a36Sopenharmony_ci base_freq = get_cpufreq_base_freq(id->cpu); 252362306a36Sopenharmony_ci set_cpufreq_scaling_min_max(id->cpu, 1, base_freq); 252462306a36Sopenharmony_ci } else { 252562306a36Sopenharmony_ci set_scaling_max_to_cpuinfo_max(id); 252662306a36Sopenharmony_ci } 252762306a36Sopenharmony_ci 252862306a36Sopenharmony_ci if (status) { 252962306a36Sopenharmony_ci isst_display_result(id, outf, "turbo-mode", "enable", 0); 253062306a36Sopenharmony_ci } else { 253162306a36Sopenharmony_ci isst_display_result(id, outf, "turbo-mode", "disable", 0); 253262306a36Sopenharmony_ci } 253362306a36Sopenharmony_ci} 253462306a36Sopenharmony_ci 253562306a36Sopenharmony_cistatic void set_turbo_mode(int arg) 253662306a36Sopenharmony_ci{ 253762306a36Sopenharmony_ci int i, enable = arg; 253862306a36Sopenharmony_ci struct isst_id id; 253962306a36Sopenharmony_ci 254062306a36Sopenharmony_ci if (cmd_help) { 254162306a36Sopenharmony_ci if (enable) 254262306a36Sopenharmony_ci fprintf(stderr, "Set turbo mode enable\n"); 254362306a36Sopenharmony_ci else 254462306a36Sopenharmony_ci fprintf(stderr, "Set turbo mode disable\n"); 254562306a36Sopenharmony_ci exit(0); 254662306a36Sopenharmony_ci } 254762306a36Sopenharmony_ci 254862306a36Sopenharmony_ci isst_ctdp_display_information_start(outf); 254962306a36Sopenharmony_ci 255062306a36Sopenharmony_ci for (i = 0; i < topo_max_cpus; ++i) { 255162306a36Sopenharmony_ci int online; 255262306a36Sopenharmony_ci 255362306a36Sopenharmony_ci if (i) 255462306a36Sopenharmony_ci online = parse_int_file( 255562306a36Sopenharmony_ci 1, "/sys/devices/system/cpu/cpu%d/online", i); 255662306a36Sopenharmony_ci else 255762306a36Sopenharmony_ci online = 255862306a36Sopenharmony_ci 1; /* online entry for CPU 0 needs some special configs */ 255962306a36Sopenharmony_ci 256062306a36Sopenharmony_ci if (online) { 256162306a36Sopenharmony_ci set_isst_id(&id, i); 256262306a36Sopenharmony_ci set_turbo_mode_for_cpu(&id, enable); 256362306a36Sopenharmony_ci } 256462306a36Sopenharmony_ci 256562306a36Sopenharmony_ci } 256662306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); 256762306a36Sopenharmony_ci} 256862306a36Sopenharmony_ci 256962306a36Sopenharmony_cistatic void get_set_trl(struct isst_id *id, void *arg1, void *arg2, void *arg3, 257062306a36Sopenharmony_ci void *arg4) 257162306a36Sopenharmony_ci{ 257262306a36Sopenharmony_ci unsigned long long trl; 257362306a36Sopenharmony_ci int set = *(int *)arg4; 257462306a36Sopenharmony_ci int ret; 257562306a36Sopenharmony_ci 257662306a36Sopenharmony_ci if (set && !fact_trl) { 257762306a36Sopenharmony_ci isst_display_error_info_message(1, "Invalid TRL. Specify with [-t|--trl]", 0, 0); 257862306a36Sopenharmony_ci exit(0); 257962306a36Sopenharmony_ci } 258062306a36Sopenharmony_ci 258162306a36Sopenharmony_ci if (set) { 258262306a36Sopenharmony_ci ret = isst_set_trl(id, fact_trl); 258362306a36Sopenharmony_ci isst_display_result(id, outf, "turbo-mode", "set-trl", ret); 258462306a36Sopenharmony_ci return; 258562306a36Sopenharmony_ci } 258662306a36Sopenharmony_ci 258762306a36Sopenharmony_ci ret = isst_get_trl(id, &trl); 258862306a36Sopenharmony_ci if (ret) 258962306a36Sopenharmony_ci isst_display_result(id, outf, "turbo-mode", "get-trl", ret); 259062306a36Sopenharmony_ci else 259162306a36Sopenharmony_ci isst_trl_display_information(id, outf, trl); 259262306a36Sopenharmony_ci} 259362306a36Sopenharmony_ci 259462306a36Sopenharmony_cistatic void process_trl(int arg) 259562306a36Sopenharmony_ci{ 259662306a36Sopenharmony_ci if (cmd_help) { 259762306a36Sopenharmony_ci if (arg) { 259862306a36Sopenharmony_ci fprintf(stderr, "Set TRL (turbo ratio limits)\n"); 259962306a36Sopenharmony_ci fprintf(stderr, "\t t|--trl: Specify turbo ratio limit for setting TRL\n"); 260062306a36Sopenharmony_ci } else { 260162306a36Sopenharmony_ci fprintf(stderr, "Get TRL (turbo ratio limits)\n"); 260262306a36Sopenharmony_ci } 260362306a36Sopenharmony_ci exit(0); 260462306a36Sopenharmony_ci } 260562306a36Sopenharmony_ci 260662306a36Sopenharmony_ci isst_ctdp_display_information_start(outf); 260762306a36Sopenharmony_ci if (max_target_cpus) 260862306a36Sopenharmony_ci for_each_online_target_cpu_in_set(get_set_trl, NULL, 260962306a36Sopenharmony_ci NULL, NULL, &arg); 261062306a36Sopenharmony_ci else 261162306a36Sopenharmony_ci for_each_online_power_domain_in_set(get_set_trl, NULL, 261262306a36Sopenharmony_ci NULL, NULL, &arg); 261362306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); 261462306a36Sopenharmony_ci} 261562306a36Sopenharmony_ci 261662306a36Sopenharmony_cistatic struct process_cmd_struct clx_n_cmds[] = { 261762306a36Sopenharmony_ci { "perf-profile", "info", dump_isst_config, 0 }, 261862306a36Sopenharmony_ci { "base-freq", "info", dump_pbf_config, 0 }, 261962306a36Sopenharmony_ci { "base-freq", "enable", set_pbf_enable, 1 }, 262062306a36Sopenharmony_ci { "base-freq", "disable", set_pbf_enable, 0 }, 262162306a36Sopenharmony_ci { NULL, NULL, NULL, 0 } 262262306a36Sopenharmony_ci}; 262362306a36Sopenharmony_ci 262462306a36Sopenharmony_cistatic struct process_cmd_struct isst_cmds[] = { 262562306a36Sopenharmony_ci { "perf-profile", "get-lock-status", get_tdp_locked, 0 }, 262662306a36Sopenharmony_ci { "perf-profile", "get-config-levels", get_tdp_levels, 0 }, 262762306a36Sopenharmony_ci { "perf-profile", "get-config-version", get_tdp_version, 0 }, 262862306a36Sopenharmony_ci { "perf-profile", "get-config-enabled", get_tdp_enabled, 0 }, 262962306a36Sopenharmony_ci { "perf-profile", "get-config-current-level", get_tdp_current_level, 263062306a36Sopenharmony_ci 0 }, 263162306a36Sopenharmony_ci { "perf-profile", "set-config-level", set_tdp_level, 0 }, 263262306a36Sopenharmony_ci { "perf-profile", "info", dump_isst_config, 0 }, 263362306a36Sopenharmony_ci { "base-freq", "info", dump_pbf_config, 0 }, 263462306a36Sopenharmony_ci { "base-freq", "enable", set_pbf_enable, 1 }, 263562306a36Sopenharmony_ci { "base-freq", "disable", set_pbf_enable, 0 }, 263662306a36Sopenharmony_ci { "turbo-freq", "info", dump_fact_config, 0 }, 263762306a36Sopenharmony_ci { "turbo-freq", "enable", set_fact_enable, 1 }, 263862306a36Sopenharmony_ci { "turbo-freq", "disable", set_fact_enable, 0 }, 263962306a36Sopenharmony_ci { "core-power", "info", dump_clos_info, 0 }, 264062306a36Sopenharmony_ci { "core-power", "enable", set_clos_enable, 1 }, 264162306a36Sopenharmony_ci { "core-power", "disable", set_clos_enable, 0 }, 264262306a36Sopenharmony_ci { "core-power", "config", set_clos_config, 0 }, 264362306a36Sopenharmony_ci { "core-power", "get-config", dump_clos_config, 0 }, 264462306a36Sopenharmony_ci { "core-power", "assoc", set_clos_assoc, 0 }, 264562306a36Sopenharmony_ci { "core-power", "get-assoc", get_clos_assoc, 0 }, 264662306a36Sopenharmony_ci { "turbo-mode", "enable", set_turbo_mode, 0 }, 264762306a36Sopenharmony_ci { "turbo-mode", "disable", set_turbo_mode, 1 }, 264862306a36Sopenharmony_ci { "turbo-mode", "get-trl", process_trl, 0 }, 264962306a36Sopenharmony_ci { "turbo-mode", "set-trl", process_trl, 1 }, 265062306a36Sopenharmony_ci { NULL, NULL, NULL } 265162306a36Sopenharmony_ci}; 265262306a36Sopenharmony_ci 265362306a36Sopenharmony_ci/* 265462306a36Sopenharmony_ci * parse cpuset with following syntax 265562306a36Sopenharmony_ci * 1,2,4..6,8-10 and set bits in cpu_subset 265662306a36Sopenharmony_ci */ 265762306a36Sopenharmony_civoid parse_cpu_command(char *optarg) 265862306a36Sopenharmony_ci{ 265962306a36Sopenharmony_ci unsigned int start, end, invalid_count; 266062306a36Sopenharmony_ci char *next; 266162306a36Sopenharmony_ci 266262306a36Sopenharmony_ci next = optarg; 266362306a36Sopenharmony_ci invalid_count = 0; 266462306a36Sopenharmony_ci 266562306a36Sopenharmony_ci while (next && *next) { 266662306a36Sopenharmony_ci if (*next == '-') /* no negative cpu numbers */ 266762306a36Sopenharmony_ci goto error; 266862306a36Sopenharmony_ci 266962306a36Sopenharmony_ci start = strtoul(next, &next, 10); 267062306a36Sopenharmony_ci 267162306a36Sopenharmony_ci if (max_target_cpus < MAX_CPUS_IN_ONE_REQ) 267262306a36Sopenharmony_ci target_cpus[max_target_cpus++] = start; 267362306a36Sopenharmony_ci else 267462306a36Sopenharmony_ci invalid_count = 1; 267562306a36Sopenharmony_ci 267662306a36Sopenharmony_ci if (*next == '\0') 267762306a36Sopenharmony_ci break; 267862306a36Sopenharmony_ci 267962306a36Sopenharmony_ci if (*next == ',') { 268062306a36Sopenharmony_ci next += 1; 268162306a36Sopenharmony_ci continue; 268262306a36Sopenharmony_ci } 268362306a36Sopenharmony_ci 268462306a36Sopenharmony_ci if (*next == '-') { 268562306a36Sopenharmony_ci next += 1; /* start range */ 268662306a36Sopenharmony_ci } else if (*next == '.') { 268762306a36Sopenharmony_ci next += 1; 268862306a36Sopenharmony_ci if (*next == '.') 268962306a36Sopenharmony_ci next += 1; /* start range */ 269062306a36Sopenharmony_ci else 269162306a36Sopenharmony_ci goto error; 269262306a36Sopenharmony_ci } 269362306a36Sopenharmony_ci 269462306a36Sopenharmony_ci end = strtoul(next, &next, 10); 269562306a36Sopenharmony_ci if (end <= start) 269662306a36Sopenharmony_ci goto error; 269762306a36Sopenharmony_ci 269862306a36Sopenharmony_ci while (++start <= end) { 269962306a36Sopenharmony_ci if (max_target_cpus < MAX_CPUS_IN_ONE_REQ) 270062306a36Sopenharmony_ci target_cpus[max_target_cpus++] = start; 270162306a36Sopenharmony_ci else 270262306a36Sopenharmony_ci invalid_count = 1; 270362306a36Sopenharmony_ci } 270462306a36Sopenharmony_ci 270562306a36Sopenharmony_ci if (*next == ',') 270662306a36Sopenharmony_ci next += 1; 270762306a36Sopenharmony_ci else if (*next != '\0') 270862306a36Sopenharmony_ci goto error; 270962306a36Sopenharmony_ci } 271062306a36Sopenharmony_ci 271162306a36Sopenharmony_ci if (invalid_count) { 271262306a36Sopenharmony_ci isst_ctdp_display_information_start(outf); 271362306a36Sopenharmony_ci isst_display_error_info_message(1, "Too many CPUs in one request: max is", 1, MAX_CPUS_IN_ONE_REQ - 1); 271462306a36Sopenharmony_ci isst_ctdp_display_information_end(outf); 271562306a36Sopenharmony_ci exit(-1); 271662306a36Sopenharmony_ci } 271762306a36Sopenharmony_ci 271862306a36Sopenharmony_ci#ifdef DEBUG 271962306a36Sopenharmony_ci { 272062306a36Sopenharmony_ci int i; 272162306a36Sopenharmony_ci 272262306a36Sopenharmony_ci for (i = 0; i < max_target_cpus; ++i) 272362306a36Sopenharmony_ci printf("cpu [%d] in arg\n", target_cpus[i]); 272462306a36Sopenharmony_ci } 272562306a36Sopenharmony_ci#endif 272662306a36Sopenharmony_ci return; 272762306a36Sopenharmony_ci 272862306a36Sopenharmony_cierror: 272962306a36Sopenharmony_ci fprintf(stderr, "\"--cpu %s\" malformed\n", optarg); 273062306a36Sopenharmony_ci exit(-1); 273162306a36Sopenharmony_ci} 273262306a36Sopenharmony_ci 273362306a36Sopenharmony_cistatic void parse_cmd_args(int argc, int start, char **argv) 273462306a36Sopenharmony_ci{ 273562306a36Sopenharmony_ci int opt; 273662306a36Sopenharmony_ci int option_index; 273762306a36Sopenharmony_ci 273862306a36Sopenharmony_ci static struct option long_options[] = { 273962306a36Sopenharmony_ci { "bucket", required_argument, 0, 'b' }, 274062306a36Sopenharmony_ci { "level", required_argument, 0, 'l' }, 274162306a36Sopenharmony_ci { "online", required_argument, 0, 'o' }, 274262306a36Sopenharmony_ci { "trl-type", required_argument, 0, 'r' }, 274362306a36Sopenharmony_ci { "trl", required_argument, 0, 't' }, 274462306a36Sopenharmony_ci { "help", no_argument, 0, 'h' }, 274562306a36Sopenharmony_ci { "clos", required_argument, 0, 'c' }, 274662306a36Sopenharmony_ci { "desired", required_argument, 0, 'd' }, 274762306a36Sopenharmony_ci { "epp", required_argument, 0, 'e' }, 274862306a36Sopenharmony_ci { "min", required_argument, 0, 'n' }, 274962306a36Sopenharmony_ci { "max", required_argument, 0, 'm' }, 275062306a36Sopenharmony_ci { "priority", required_argument, 0, 'p' }, 275162306a36Sopenharmony_ci { "weight", required_argument, 0, 'w' }, 275262306a36Sopenharmony_ci { "auto", no_argument, 0, 'a' }, 275362306a36Sopenharmony_ci { 0, 0, 0, 0 } 275462306a36Sopenharmony_ci }; 275562306a36Sopenharmony_ci 275662306a36Sopenharmony_ci option_index = start; 275762306a36Sopenharmony_ci 275862306a36Sopenharmony_ci optind = start + 1; 275962306a36Sopenharmony_ci while ((opt = getopt_long(argc, argv, "b:l:t:c:d:e:n:m:p:w:r:hoa", 276062306a36Sopenharmony_ci long_options, &option_index)) != -1) { 276162306a36Sopenharmony_ci switch (opt) { 276262306a36Sopenharmony_ci case 'a': 276362306a36Sopenharmony_ci auto_mode = 1; 276462306a36Sopenharmony_ci break; 276562306a36Sopenharmony_ci case 'b': 276662306a36Sopenharmony_ci fact_bucket = atoi(optarg); 276762306a36Sopenharmony_ci break; 276862306a36Sopenharmony_ci case 'h': 276962306a36Sopenharmony_ci cmd_help = 1; 277062306a36Sopenharmony_ci break; 277162306a36Sopenharmony_ci case 'l': 277262306a36Sopenharmony_ci tdp_level = atoi(optarg); 277362306a36Sopenharmony_ci break; 277462306a36Sopenharmony_ci case 'o': 277562306a36Sopenharmony_ci force_online_offline = 1; 277662306a36Sopenharmony_ci break; 277762306a36Sopenharmony_ci case 't': 277862306a36Sopenharmony_ci sscanf(optarg, "0x%llx", &fact_trl); 277962306a36Sopenharmony_ci break; 278062306a36Sopenharmony_ci case 'r': 278162306a36Sopenharmony_ci if (!strncmp(optarg, "sse", 3)) { 278262306a36Sopenharmony_ci fact_avx = 0x01; 278362306a36Sopenharmony_ci } else if (!strncmp(optarg, "avx2", 4)) { 278462306a36Sopenharmony_ci fact_avx = 0x02; 278562306a36Sopenharmony_ci } else if (!strncmp(optarg, "avx512", 6)) { 278662306a36Sopenharmony_ci fact_avx = 0x04; 278762306a36Sopenharmony_ci } else { 278862306a36Sopenharmony_ci fprintf(outf, "Invalid sse,avx options\n"); 278962306a36Sopenharmony_ci exit(1); 279062306a36Sopenharmony_ci } 279162306a36Sopenharmony_ci break; 279262306a36Sopenharmony_ci /* CLOS related */ 279362306a36Sopenharmony_ci case 'c': 279462306a36Sopenharmony_ci current_clos = atoi(optarg); 279562306a36Sopenharmony_ci break; 279662306a36Sopenharmony_ci case 'd': 279762306a36Sopenharmony_ci clos_desired = atoi(optarg); 279862306a36Sopenharmony_ci clos_desired /= isst_get_disp_freq_multiplier(); 279962306a36Sopenharmony_ci break; 280062306a36Sopenharmony_ci case 'e': 280162306a36Sopenharmony_ci clos_epp = atoi(optarg); 280262306a36Sopenharmony_ci if (is_skx_based_platform()) { 280362306a36Sopenharmony_ci isst_display_error_info_message(1, "epp can't be specified on this platform", 0, 0); 280462306a36Sopenharmony_ci exit(0); 280562306a36Sopenharmony_ci } 280662306a36Sopenharmony_ci break; 280762306a36Sopenharmony_ci case 'n': 280862306a36Sopenharmony_ci clos_min = atoi(optarg); 280962306a36Sopenharmony_ci clos_min /= isst_get_disp_freq_multiplier(); 281062306a36Sopenharmony_ci break; 281162306a36Sopenharmony_ci case 'm': 281262306a36Sopenharmony_ci clos_max = atoi(optarg); 281362306a36Sopenharmony_ci clos_max /= isst_get_disp_freq_multiplier(); 281462306a36Sopenharmony_ci break; 281562306a36Sopenharmony_ci case 'p': 281662306a36Sopenharmony_ci clos_priority_type = atoi(optarg); 281762306a36Sopenharmony_ci if (is_skx_based_platform() && !clos_priority_type) { 281862306a36Sopenharmony_ci isst_display_error_info_message(1, "Invalid clos priority type: proportional for this platform", 0, 0); 281962306a36Sopenharmony_ci exit(0); 282062306a36Sopenharmony_ci } 282162306a36Sopenharmony_ci break; 282262306a36Sopenharmony_ci case 'w': 282362306a36Sopenharmony_ci clos_prop_prio = atoi(optarg); 282462306a36Sopenharmony_ci if (is_skx_based_platform()) { 282562306a36Sopenharmony_ci isst_display_error_info_message(1, "weight can't be specified on this platform", 0, 0); 282662306a36Sopenharmony_ci exit(0); 282762306a36Sopenharmony_ci } 282862306a36Sopenharmony_ci break; 282962306a36Sopenharmony_ci default: 283062306a36Sopenharmony_ci printf("Unknown option: ignore\n"); 283162306a36Sopenharmony_ci } 283262306a36Sopenharmony_ci } 283362306a36Sopenharmony_ci 283462306a36Sopenharmony_ci if (argv[optind]) 283562306a36Sopenharmony_ci printf("Garbage at the end of command: ignore\n"); 283662306a36Sopenharmony_ci} 283762306a36Sopenharmony_ci 283862306a36Sopenharmony_cistatic void isst_help(void) 283962306a36Sopenharmony_ci{ 284062306a36Sopenharmony_ci printf("perf-profile:\tAn architectural mechanism that allows multiple optimized \n\ 284162306a36Sopenharmony_ci performance profiles per system via static and/or dynamic\n\ 284262306a36Sopenharmony_ci adjustment of core count, workload, Tjmax, and\n\ 284362306a36Sopenharmony_ci TDP, etc.\n"); 284462306a36Sopenharmony_ci printf("\nCommands : For feature=perf-profile\n"); 284562306a36Sopenharmony_ci printf("\tinfo\n"); 284662306a36Sopenharmony_ci 284762306a36Sopenharmony_ci if (!is_clx_n_platform()) { 284862306a36Sopenharmony_ci printf("\tget-lock-status\n"); 284962306a36Sopenharmony_ci printf("\tget-config-levels\n"); 285062306a36Sopenharmony_ci printf("\tget-config-version\n"); 285162306a36Sopenharmony_ci printf("\tget-config-enabled\n"); 285262306a36Sopenharmony_ci printf("\tget-config-current-level\n"); 285362306a36Sopenharmony_ci printf("\tset-config-level\n"); 285462306a36Sopenharmony_ci } 285562306a36Sopenharmony_ci} 285662306a36Sopenharmony_ci 285762306a36Sopenharmony_cistatic void pbf_help(void) 285862306a36Sopenharmony_ci{ 285962306a36Sopenharmony_ci printf("base-freq:\tEnables users to increase guaranteed base frequency\n\ 286062306a36Sopenharmony_ci on certain cores (high priority cores) in exchange for lower\n\ 286162306a36Sopenharmony_ci base frequency on remaining cores (low priority cores).\n"); 286262306a36Sopenharmony_ci printf("\tcommand : info\n"); 286362306a36Sopenharmony_ci printf("\tcommand : enable\n"); 286462306a36Sopenharmony_ci printf("\tcommand : disable\n"); 286562306a36Sopenharmony_ci} 286662306a36Sopenharmony_ci 286762306a36Sopenharmony_cistatic void fact_help(void) 286862306a36Sopenharmony_ci{ 286962306a36Sopenharmony_ci printf("turbo-freq:\tEnables the ability to set different turbo ratio\n\ 287062306a36Sopenharmony_ci limits to cores based on priority.\n"); 287162306a36Sopenharmony_ci printf("\nCommand: For feature=turbo-freq\n"); 287262306a36Sopenharmony_ci printf("\tcommand : info\n"); 287362306a36Sopenharmony_ci printf("\tcommand : enable\n"); 287462306a36Sopenharmony_ci printf("\tcommand : disable\n"); 287562306a36Sopenharmony_ci} 287662306a36Sopenharmony_ci 287762306a36Sopenharmony_cistatic void turbo_mode_help(void) 287862306a36Sopenharmony_ci{ 287962306a36Sopenharmony_ci 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"); 288062306a36Sopenharmony_ci printf("\tcommand : enable\n"); 288162306a36Sopenharmony_ci printf("\tcommand : disable\n"); 288262306a36Sopenharmony_ci printf("\tcommand : get-trl\n"); 288362306a36Sopenharmony_ci printf("\tcommand : set-trl\n"); 288462306a36Sopenharmony_ci} 288562306a36Sopenharmony_ci 288662306a36Sopenharmony_ci 288762306a36Sopenharmony_cistatic void core_power_help(void) 288862306a36Sopenharmony_ci{ 288962306a36Sopenharmony_ci printf("core-power:\tInterface that allows user to define per core/tile\n\ 289062306a36Sopenharmony_ci priority.\n"); 289162306a36Sopenharmony_ci printf("\nCommands : For feature=core-power\n"); 289262306a36Sopenharmony_ci printf("\tinfo\n"); 289362306a36Sopenharmony_ci printf("\tenable\n"); 289462306a36Sopenharmony_ci printf("\tdisable\n"); 289562306a36Sopenharmony_ci printf("\tconfig\n"); 289662306a36Sopenharmony_ci printf("\tget-config\n"); 289762306a36Sopenharmony_ci printf("\tassoc\n"); 289862306a36Sopenharmony_ci printf("\tget-assoc\n"); 289962306a36Sopenharmony_ci} 290062306a36Sopenharmony_ci 290162306a36Sopenharmony_cistruct process_cmd_help_struct { 290262306a36Sopenharmony_ci char *feature; 290362306a36Sopenharmony_ci void (*process_fn)(void); 290462306a36Sopenharmony_ci}; 290562306a36Sopenharmony_ci 290662306a36Sopenharmony_cistatic struct process_cmd_help_struct isst_help_cmds[] = { 290762306a36Sopenharmony_ci { "perf-profile", isst_help }, 290862306a36Sopenharmony_ci { "base-freq", pbf_help }, 290962306a36Sopenharmony_ci { "turbo-freq", fact_help }, 291062306a36Sopenharmony_ci { "core-power", core_power_help }, 291162306a36Sopenharmony_ci { "turbo-mode", turbo_mode_help }, 291262306a36Sopenharmony_ci { NULL, NULL } 291362306a36Sopenharmony_ci}; 291462306a36Sopenharmony_ci 291562306a36Sopenharmony_cistatic struct process_cmd_help_struct clx_n_help_cmds[] = { 291662306a36Sopenharmony_ci { "perf-profile", isst_help }, 291762306a36Sopenharmony_ci { "base-freq", pbf_help }, 291862306a36Sopenharmony_ci { NULL, NULL } 291962306a36Sopenharmony_ci}; 292062306a36Sopenharmony_ci 292162306a36Sopenharmony_civoid process_command(int argc, char **argv, 292262306a36Sopenharmony_ci struct process_cmd_help_struct *help_cmds, 292362306a36Sopenharmony_ci struct process_cmd_struct *cmds) 292462306a36Sopenharmony_ci{ 292562306a36Sopenharmony_ci int i = 0, matched = 0; 292662306a36Sopenharmony_ci char *feature = argv[optind]; 292762306a36Sopenharmony_ci char *cmd = argv[optind + 1]; 292862306a36Sopenharmony_ci 292962306a36Sopenharmony_ci if (!feature || !cmd) 293062306a36Sopenharmony_ci return; 293162306a36Sopenharmony_ci 293262306a36Sopenharmony_ci debug_printf("feature name [%s] command [%s]\n", feature, cmd); 293362306a36Sopenharmony_ci if (!strcmp(cmd, "-h") || !strcmp(cmd, "--help")) { 293462306a36Sopenharmony_ci while (help_cmds[i].feature) { 293562306a36Sopenharmony_ci if (!strcmp(help_cmds[i].feature, feature)) { 293662306a36Sopenharmony_ci help_cmds[i].process_fn(); 293762306a36Sopenharmony_ci exit(0); 293862306a36Sopenharmony_ci } 293962306a36Sopenharmony_ci ++i; 294062306a36Sopenharmony_ci } 294162306a36Sopenharmony_ci } 294262306a36Sopenharmony_ci 294362306a36Sopenharmony_ci i = 0; 294462306a36Sopenharmony_ci while (cmds[i].feature) { 294562306a36Sopenharmony_ci if (!strcmp(cmds[i].feature, feature) && 294662306a36Sopenharmony_ci !strcmp(cmds[i].command, cmd)) { 294762306a36Sopenharmony_ci parse_cmd_args(argc, optind + 1, argv); 294862306a36Sopenharmony_ci cmds[i].process_fn(cmds[i].arg); 294962306a36Sopenharmony_ci matched = 1; 295062306a36Sopenharmony_ci break; 295162306a36Sopenharmony_ci } 295262306a36Sopenharmony_ci ++i; 295362306a36Sopenharmony_ci } 295462306a36Sopenharmony_ci 295562306a36Sopenharmony_ci if (!matched) 295662306a36Sopenharmony_ci fprintf(stderr, "Invalid command\n"); 295762306a36Sopenharmony_ci} 295862306a36Sopenharmony_ci 295962306a36Sopenharmony_cistatic void usage(void) 296062306a36Sopenharmony_ci{ 296162306a36Sopenharmony_ci if (is_clx_n_platform()) { 296262306a36Sopenharmony_ci fprintf(stderr, "\nThere is limited support of Intel Speed Select features on this platform.\n"); 296362306a36Sopenharmony_ci fprintf(stderr, "Everything is pre-configured using BIOS options, this tool can't enable any feature in the hardware.\n\n"); 296462306a36Sopenharmony_ci } 296562306a36Sopenharmony_ci 296662306a36Sopenharmony_ci printf("\nUsage:\n"); 296762306a36Sopenharmony_ci printf("intel-speed-select [OPTIONS] FEATURE COMMAND COMMAND_ARGUMENTS\n"); 296862306a36Sopenharmony_ci printf("\nUse this tool to enumerate and control the Intel Speed Select Technology features:\n"); 296962306a36Sopenharmony_ci if (is_clx_n_platform()) 297062306a36Sopenharmony_ci printf("\nFEATURE : [perf-profile|base-freq]\n"); 297162306a36Sopenharmony_ci else 297262306a36Sopenharmony_ci printf("\nFEATURE : [perf-profile|base-freq|turbo-freq|core-power|turbo-mode]\n"); 297362306a36Sopenharmony_ci printf("\nFor help on each feature, use -h|--help\n"); 297462306a36Sopenharmony_ci printf("\tFor example: intel-speed-select perf-profile -h\n"); 297562306a36Sopenharmony_ci 297662306a36Sopenharmony_ci printf("\nFor additional help on each command for a feature, use --h|--help\n"); 297762306a36Sopenharmony_ci printf("\tFor example: intel-speed-select perf-profile get-lock-status -h\n"); 297862306a36Sopenharmony_ci printf("\t\t This will print help for the command \"get-lock-status\" for the feature \"perf-profile\"\n"); 297962306a36Sopenharmony_ci 298062306a36Sopenharmony_ci printf("\nOPTIONS\n"); 298162306a36Sopenharmony_ci printf("\t[-c|--cpu] : logical cpu number\n"); 298262306a36Sopenharmony_ci printf("\t\tDefault: Die scoped for all dies in the system with multiple dies/package\n"); 298362306a36Sopenharmony_ci printf("\t\t\t Or Package scoped for all Packages when each package contains one die\n"); 298462306a36Sopenharmony_ci printf("\t[-d|--debug] : Debug mode\n"); 298562306a36Sopenharmony_ci printf("\t[-f|--format] : output format [json|text]. Default: text\n"); 298662306a36Sopenharmony_ci printf("\t[-h|--help] : Print help\n"); 298762306a36Sopenharmony_ci printf("\t[-i|--info] : Print platform information\n"); 298862306a36Sopenharmony_ci printf("\t[-a|--all-cpus-online] : Force online every CPU in the system\n"); 298962306a36Sopenharmony_ci printf("\t[-o|--out] : Output file\n"); 299062306a36Sopenharmony_ci printf("\t\t\tDefault : stderr\n"); 299162306a36Sopenharmony_ci printf("\t[-p|--pause] : Delay between two mail box commands in milliseconds\n"); 299262306a36Sopenharmony_ci printf("\t[-r|--retry] : Retry count for mail box commands on failure, default 3\n"); 299362306a36Sopenharmony_ci printf("\t[-v|--version] : Print version\n"); 299462306a36Sopenharmony_ci printf("\t[-b|--oob : Start a daemon to process HFI events for perf profile change from Out of Band agent.\n"); 299562306a36Sopenharmony_ci printf("\t[-n|--no-daemon : Don't run as daemon. By default --oob will turn on daemon mode\n"); 299662306a36Sopenharmony_ci printf("\t[-w|--delay : Delay for reading config level state change in OOB poll mode.\n"); 299762306a36Sopenharmony_ci printf("\t[-g|--cgroupv2 : Try to use cgroup v2 CPU isolation instead of CPU online/offline.\n"); 299862306a36Sopenharmony_ci printf("\nResult format\n"); 299962306a36Sopenharmony_ci printf("\tResult display uses a common format for each command:\n"); 300062306a36Sopenharmony_ci printf("\tResults are formatted in text/JSON with\n"); 300162306a36Sopenharmony_ci printf("\t\tPackage, Die, CPU, and command specific results.\n"); 300262306a36Sopenharmony_ci 300362306a36Sopenharmony_ci printf("\nExamples\n"); 300462306a36Sopenharmony_ci printf("\tTo get platform information:\n"); 300562306a36Sopenharmony_ci printf("\t\tintel-speed-select --info\n"); 300662306a36Sopenharmony_ci printf("\tTo get full perf-profile information dump:\n"); 300762306a36Sopenharmony_ci printf("\t\tintel-speed-select perf-profile info\n"); 300862306a36Sopenharmony_ci printf("\tTo get full base-freq information dump:\n"); 300962306a36Sopenharmony_ci printf("\t\tintel-speed-select base-freq info -l 0\n"); 301062306a36Sopenharmony_ci if (!is_clx_n_platform()) { 301162306a36Sopenharmony_ci printf("\tTo get full turbo-freq information dump:\n"); 301262306a36Sopenharmony_ci printf("\t\tintel-speed-select turbo-freq info -l 0\n"); 301362306a36Sopenharmony_ci } 301462306a36Sopenharmony_ci exit(1); 301562306a36Sopenharmony_ci} 301662306a36Sopenharmony_ci 301762306a36Sopenharmony_cistatic void print_version(void) 301862306a36Sopenharmony_ci{ 301962306a36Sopenharmony_ci fprintf(outf, "Version %s\n", version_str); 302062306a36Sopenharmony_ci exit(0); 302162306a36Sopenharmony_ci} 302262306a36Sopenharmony_ci 302362306a36Sopenharmony_cistatic void cmdline(int argc, char **argv) 302462306a36Sopenharmony_ci{ 302562306a36Sopenharmony_ci const char *pathname = "/dev/isst_interface"; 302662306a36Sopenharmony_ci char *ptr; 302762306a36Sopenharmony_ci FILE *fp; 302862306a36Sopenharmony_ci int opt, force_cpus_online = 0; 302962306a36Sopenharmony_ci int option_index = 0; 303062306a36Sopenharmony_ci int ret; 303162306a36Sopenharmony_ci int oob_mode = 0; 303262306a36Sopenharmony_ci int poll_interval = -1; 303362306a36Sopenharmony_ci int no_daemon = 0; 303462306a36Sopenharmony_ci int mbox_delay = 0, mbox_retries = 3; 303562306a36Sopenharmony_ci 303662306a36Sopenharmony_ci static struct option long_options[] = { 303762306a36Sopenharmony_ci { "all-cpus-online", no_argument, 0, 'a' }, 303862306a36Sopenharmony_ci { "cpu", required_argument, 0, 'c' }, 303962306a36Sopenharmony_ci { "debug", no_argument, 0, 'd' }, 304062306a36Sopenharmony_ci { "format", required_argument, 0, 'f' }, 304162306a36Sopenharmony_ci { "help", no_argument, 0, 'h' }, 304262306a36Sopenharmony_ci { "info", no_argument, 0, 'i' }, 304362306a36Sopenharmony_ci { "pause", required_argument, 0, 'p' }, 304462306a36Sopenharmony_ci { "out", required_argument, 0, 'o' }, 304562306a36Sopenharmony_ci { "retry", required_argument, 0, 'r' }, 304662306a36Sopenharmony_ci { "version", no_argument, 0, 'v' }, 304762306a36Sopenharmony_ci { "oob", no_argument, 0, 'b' }, 304862306a36Sopenharmony_ci { "no-daemon", no_argument, 0, 'n' }, 304962306a36Sopenharmony_ci { "poll-interval", required_argument, 0, 'w' }, 305062306a36Sopenharmony_ci { "cgroupv2", required_argument, 0, 'g' }, 305162306a36Sopenharmony_ci { 0, 0, 0, 0 } 305262306a36Sopenharmony_ci }; 305362306a36Sopenharmony_ci 305462306a36Sopenharmony_ci if (geteuid() != 0) { 305562306a36Sopenharmony_ci fprintf(stderr, "Must run as root\n"); 305662306a36Sopenharmony_ci exit(0); 305762306a36Sopenharmony_ci } 305862306a36Sopenharmony_ci 305962306a36Sopenharmony_ci ret = update_cpu_model(); 306062306a36Sopenharmony_ci if (ret) 306162306a36Sopenharmony_ci err(-1, "Invalid CPU model (%d)\n", cpu_model); 306262306a36Sopenharmony_ci printf("Intel(R) Speed Select Technology\n"); 306362306a36Sopenharmony_ci printf("Executing on CPU model:%d[0x%x]\n", cpu_model, cpu_model); 306462306a36Sopenharmony_ci 306562306a36Sopenharmony_ci if (!is_clx_n_platform()) { 306662306a36Sopenharmony_ci fp = fopen(pathname, "rb"); 306762306a36Sopenharmony_ci if (!fp) { 306862306a36Sopenharmony_ci fprintf(stderr, "Intel speed select drivers are not loaded on this system.\n"); 306962306a36Sopenharmony_ci fprintf(stderr, "Verify that kernel config includes CONFIG_INTEL_SPEED_SELECT_INTERFACE.\n"); 307062306a36Sopenharmony_ci fprintf(stderr, "If the config is included then this is not a supported platform.\n"); 307162306a36Sopenharmony_ci exit(0); 307262306a36Sopenharmony_ci } 307362306a36Sopenharmony_ci fclose(fp); 307462306a36Sopenharmony_ci } 307562306a36Sopenharmony_ci 307662306a36Sopenharmony_ci ret = isst_fill_platform_info(); 307762306a36Sopenharmony_ci if (ret) 307862306a36Sopenharmony_ci goto out; 307962306a36Sopenharmony_ci 308062306a36Sopenharmony_ci progname = argv[0]; 308162306a36Sopenharmony_ci while ((opt = getopt_long_only(argc, argv, "+c:df:hio:vabw:ng", long_options, 308262306a36Sopenharmony_ci &option_index)) != -1) { 308362306a36Sopenharmony_ci switch (opt) { 308462306a36Sopenharmony_ci case 'a': 308562306a36Sopenharmony_ci force_cpus_online = 1; 308662306a36Sopenharmony_ci break; 308762306a36Sopenharmony_ci case 'c': 308862306a36Sopenharmony_ci parse_cpu_command(optarg); 308962306a36Sopenharmony_ci break; 309062306a36Sopenharmony_ci case 'd': 309162306a36Sopenharmony_ci debug_flag = 1; 309262306a36Sopenharmony_ci printf("Debug Mode ON\n"); 309362306a36Sopenharmony_ci break; 309462306a36Sopenharmony_ci case 'f': 309562306a36Sopenharmony_ci if (!strncmp(optarg, "json", 4)) 309662306a36Sopenharmony_ci out_format_json = 1; 309762306a36Sopenharmony_ci break; 309862306a36Sopenharmony_ci case 'h': 309962306a36Sopenharmony_ci usage(); 310062306a36Sopenharmony_ci break; 310162306a36Sopenharmony_ci case 'i': 310262306a36Sopenharmony_ci isst_print_platform_information(); 310362306a36Sopenharmony_ci break; 310462306a36Sopenharmony_ci case 'o': 310562306a36Sopenharmony_ci if (outf) 310662306a36Sopenharmony_ci fclose(outf); 310762306a36Sopenharmony_ci outf = fopen_or_exit(optarg, "w"); 310862306a36Sopenharmony_ci break; 310962306a36Sopenharmony_ci case 'p': 311062306a36Sopenharmony_ci ret = strtol(optarg, &ptr, 10); 311162306a36Sopenharmony_ci if (!ret) 311262306a36Sopenharmony_ci fprintf(stderr, "Invalid pause interval, ignore\n"); 311362306a36Sopenharmony_ci else 311462306a36Sopenharmony_ci mbox_delay = ret; 311562306a36Sopenharmony_ci break; 311662306a36Sopenharmony_ci case 'r': 311762306a36Sopenharmony_ci ret = strtol(optarg, &ptr, 10); 311862306a36Sopenharmony_ci if (!ret) 311962306a36Sopenharmony_ci fprintf(stderr, "Invalid retry count, ignore\n"); 312062306a36Sopenharmony_ci else 312162306a36Sopenharmony_ci mbox_retries = ret; 312262306a36Sopenharmony_ci break; 312362306a36Sopenharmony_ci case 'v': 312462306a36Sopenharmony_ci print_version(); 312562306a36Sopenharmony_ci break; 312662306a36Sopenharmony_ci case 'b': 312762306a36Sopenharmony_ci oob_mode = 1; 312862306a36Sopenharmony_ci break; 312962306a36Sopenharmony_ci case 'n': 313062306a36Sopenharmony_ci no_daemon = 1; 313162306a36Sopenharmony_ci break; 313262306a36Sopenharmony_ci case 'w': 313362306a36Sopenharmony_ci ret = strtol(optarg, &ptr, 10); 313462306a36Sopenharmony_ci if (!ret) { 313562306a36Sopenharmony_ci fprintf(stderr, "Invalid poll interval count\n"); 313662306a36Sopenharmony_ci exit(0); 313762306a36Sopenharmony_ci } 313862306a36Sopenharmony_ci poll_interval = ret; 313962306a36Sopenharmony_ci break; 314062306a36Sopenharmony_ci case 'g': 314162306a36Sopenharmony_ci cgroupv2 = 1; 314262306a36Sopenharmony_ci break; 314362306a36Sopenharmony_ci default: 314462306a36Sopenharmony_ci usage(); 314562306a36Sopenharmony_ci } 314662306a36Sopenharmony_ci } 314762306a36Sopenharmony_ci 314862306a36Sopenharmony_ci if (optind > (argc - 2) && !oob_mode) { 314962306a36Sopenharmony_ci usage(); 315062306a36Sopenharmony_ci exit(0); 315162306a36Sopenharmony_ci } 315262306a36Sopenharmony_ci 315362306a36Sopenharmony_ci isst_update_platform_param(ISST_PARAM_MBOX_DELAY, mbox_delay); 315462306a36Sopenharmony_ci isst_update_platform_param(ISST_PARAM_MBOX_RETRIES, mbox_retries); 315562306a36Sopenharmony_ci 315662306a36Sopenharmony_ci set_max_cpu_num(); 315762306a36Sopenharmony_ci if (force_cpus_online) 315862306a36Sopenharmony_ci force_all_cpus_online(); 315962306a36Sopenharmony_ci store_cpu_topology(); 316062306a36Sopenharmony_ci create_cpu_map(); 316162306a36Sopenharmony_ci 316262306a36Sopenharmony_ci if (oob_mode) { 316362306a36Sopenharmony_ci if (debug_flag) 316462306a36Sopenharmony_ci fprintf(stderr, "OOB mode is enabled in debug mode\n"); 316562306a36Sopenharmony_ci 316662306a36Sopenharmony_ci ret = isst_daemon(debug_flag, poll_interval, no_daemon); 316762306a36Sopenharmony_ci if (ret) 316862306a36Sopenharmony_ci fprintf(stderr, "OOB mode enable failed\n"); 316962306a36Sopenharmony_ci goto out; 317062306a36Sopenharmony_ci } 317162306a36Sopenharmony_ci 317262306a36Sopenharmony_ci if (!is_clx_n_platform()) { 317362306a36Sopenharmony_ci process_command(argc, argv, isst_help_cmds, isst_cmds); 317462306a36Sopenharmony_ci } else { 317562306a36Sopenharmony_ci process_command(argc, argv, clx_n_help_cmds, clx_n_cmds); 317662306a36Sopenharmony_ci } 317762306a36Sopenharmony_ciout: 317862306a36Sopenharmony_ci free_cpu_set(present_cpumask); 317962306a36Sopenharmony_ci free_cpu_set(target_cpumask); 318062306a36Sopenharmony_ci} 318162306a36Sopenharmony_ci 318262306a36Sopenharmony_ciint main(int argc, char **argv) 318362306a36Sopenharmony_ci{ 318462306a36Sopenharmony_ci outf = stderr; 318562306a36Sopenharmony_ci cmdline(argc, argv); 318662306a36Sopenharmony_ci return 0; 318762306a36Sopenharmony_ci} 3188