aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/tools/power/x86/intel-speed-select
diff options
context:
space:
mode:
Diffstat (limited to 'tools/power/x86/intel-speed-select')
-rw-r--r--tools/power/x86/intel-speed-select/Build2
-rw-r--r--tools/power/x86/intel-speed-select/Makefile14
-rw-r--r--tools/power/x86/intel-speed-select/hfi-events.c308
-rw-r--r--tools/power/x86/intel-speed-select/isst-config.c1656
-rw-r--r--tools/power/x86/intel-speed-select/isst-core-mbox.c1067
-rw-r--r--tools/power/x86/intel-speed-select/isst-core-tpmi.c832
-rw-r--r--tools/power/x86/intel-speed-select/isst-core.c923
-rw-r--r--tools/power/x86/intel-speed-select/isst-daemon.c256
-rw-r--r--tools/power/x86/intel-speed-select/isst-display.c385
-rw-r--r--tools/power/x86/intel-speed-select/isst.h192
10 files changed, 4142 insertions, 1493 deletions
diff --git a/tools/power/x86/intel-speed-select/Build b/tools/power/x86/intel-speed-select/Build
index b61456d75190..5a9637e1678c 100644
--- a/tools/power/x86/intel-speed-select/Build
+++ b/tools/power/x86/intel-speed-select/Build
@@ -1 +1 @@
-intel-speed-select-y += isst-config.o isst-core.o isst-display.o
+intel-speed-select-y += isst-config.o isst-core.o isst-display.o isst-daemon.o hfi-events.o isst-core-mbox.o isst-core-tpmi.o
diff --git a/tools/power/x86/intel-speed-select/Makefile b/tools/power/x86/intel-speed-select/Makefile
index 12c6939dca2a..8d3a02a20f3d 100644
--- a/tools/power/x86/intel-speed-select/Makefile
+++ b/tools/power/x86/intel-speed-select/Makefile
@@ -13,8 +13,8 @@ endif
# Do not use make's built-in rules
# (this improves performance and avoids hard-to-debug behaviour);
MAKEFLAGS += -r
-
-override CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include
+override CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include -I$(shell $(CC) -print-sysroot)/usr/include/libnl3
+override LDFLAGS += -lnl-genl-3 -lnl-3
ALL_TARGETS := intel-speed-select
ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS))
@@ -31,19 +31,23 @@ $(OUTPUT)include/linux/isst_if.h: ../../../../include/uapi/linux/isst_if.h
mkdir -p $(OUTPUT)include/linux 2>&1 || true
ln -sf $(CURDIR)/../../../../include/uapi/linux/isst_if.h $@
-prepare: $(OUTPUT)include/linux/isst_if.h
+$(OUTPUT)include/linux/thermal.h: ../../../../include/uapi/linux/thermal.h
+ mkdir -p $(OUTPUT)include/linux 2>&1 || true
+ ln -sf $(CURDIR)/../../../../include/uapi/linux/thermal.h $@
+
+prepare: $(OUTPUT)include/linux/isst_if.h $(OUTPUT)include/linux/thermal.h
ISST_IN := $(OUTPUT)intel-speed-select-in.o
$(ISST_IN): prepare FORCE
$(Q)$(MAKE) $(build)=intel-speed-select
$(OUTPUT)intel-speed-select: $(ISST_IN)
- $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
+ $(QUIET_LINK)$(CC) $(CFLAGS) $< $(LDFLAGS) -o $@
clean:
rm -f $(ALL_PROGRAMS)
rm -rf $(OUTPUT)include/linux/isst_if.h
- find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete
+ find $(or $(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete
install: $(ALL_PROGRAMS)
install -d -m 755 $(DESTDIR)$(bindir); \
diff --git a/tools/power/x86/intel-speed-select/hfi-events.c b/tools/power/x86/intel-speed-select/hfi-events.c
new file mode 100644
index 000000000000..174b99d9f864
--- /dev/null
+++ b/tools/power/x86/intel-speed-select/hfi-events.c
@@ -0,0 +1,308 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel Speed Select -- Read HFI events for OOB
+ * Copyright (c) 2022 Intel Corporation.
+ */
+
+/*
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+
+ * WPA Supplicant - driver interaction with Linux nl80211/cfg80211
+ * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of
+ * BSD license.
+ *
+ * Requires
+ * libnl-genl-3-dev
+ *
+ * For Fedora/CenOS
+ * dnf install libnl3-devel
+ * For Ubuntu
+ * apt install libnl-3-dev libnl-genl-3-dev
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <getopt.h>
+#include <signal.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+
+#include <linux/thermal.h>
+#include "isst.h"
+
+struct hfi_event_data {
+ struct nl_sock *nl_handle;
+ struct nl_cb *nl_cb;
+};
+
+struct hfi_event_data drv;
+
+static int ack_handler(struct nl_msg *msg, void *arg)
+{
+ int *err = arg;
+ *err = 0;
+ return NL_STOP;
+}
+
+static int finish_handler(struct nl_msg *msg, void *arg)
+{
+ int *ret = arg;
+ *ret = 0;
+ return NL_SKIP;
+}
+
+static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
+ void *arg)
+{
+ int *ret = arg;
+ *ret = err->error;
+ return NL_SKIP;
+}
+
+static int seq_check_handler(struct nl_msg *msg, void *arg)
+{
+ return NL_OK;
+}
+
+static int send_and_recv_msgs(struct hfi_event_data *drv,
+ struct nl_msg *msg,
+ int (*valid_handler)(struct nl_msg *, void *),
+ void *valid_data)
+{
+ struct nl_cb *cb;
+ int err = -ENOMEM;
+
+ cb = nl_cb_clone(drv->nl_cb);
+ if (!cb)
+ goto out;
+
+ err = nl_send_auto_complete(drv->nl_handle, msg);
+ if (err < 0)
+ goto out;
+
+ err = 1;
+
+ nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
+ nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
+ nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
+
+ if (valid_handler)
+ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
+ valid_handler, valid_data);
+
+ while (err > 0)
+ nl_recvmsgs(drv->nl_handle, cb);
+ out:
+ nl_cb_put(cb);
+ nlmsg_free(msg);
+ return err;
+}
+
+struct family_data {
+ const char *group;
+ int id;
+};
+
+static int family_handler(struct nl_msg *msg, void *arg)
+{
+ struct family_data *res = arg;
+ struct nlattr *tb[CTRL_ATTR_MAX + 1];
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ struct nlattr *mcgrp;
+ int i;
+
+ nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), NULL);
+ if (!tb[CTRL_ATTR_MCAST_GROUPS])
+ return NL_SKIP;
+
+ nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
+ struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
+ nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, nla_data(mcgrp),
+ nla_len(mcgrp), NULL);
+ if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] ||
+ !tb2[CTRL_ATTR_MCAST_GRP_ID] ||
+ strncmp(nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]),
+ res->group,
+ nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME])) != 0)
+ continue;
+ res->id = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
+ break;
+ }
+
+ return 0;
+}
+
+static int nl_get_multicast_id(struct hfi_event_data *drv,
+ const char *family, const char *group)
+{
+ struct nl_msg *msg;
+ int ret = -1;
+ struct family_data res = { group, -ENOENT };
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -ENOMEM;
+ genlmsg_put(msg, 0, 0, genl_ctrl_resolve(drv->nl_handle, "nlctrl"),
+ 0, 0, CTRL_CMD_GETFAMILY, 0);
+ NLA_PUT_STRING(msg, CTRL_ATTR_FAMILY_NAME, family);
+
+ ret = send_and_recv_msgs(drv, msg, family_handler, &res);
+ msg = NULL;
+ if (ret == 0)
+ ret = res.id;
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return ret;
+}
+
+struct perf_cap {
+ int cpu;
+ int perf;
+ int eff;
+};
+
+static void process_hfi_event(struct perf_cap *perf_cap)
+{
+ struct isst_id id;
+
+ set_isst_id(&id, perf_cap->cpu);
+ process_level_change(&id);
+}
+
+static int handle_event(struct nl_msg *n, void *arg)
+{
+ struct nlmsghdr *nlh = nlmsg_hdr(n);
+ struct genlmsghdr *genlhdr = genlmsg_hdr(nlh);
+ struct nlattr *attrs[THERMAL_GENL_ATTR_MAX + 1];
+ int ret;
+ struct perf_cap perf_cap = {0};
+
+ ret = genlmsg_parse(nlh, 0, attrs, THERMAL_GENL_ATTR_MAX, NULL);
+
+ debug_printf("Received event %d parse_rer:%d\n", genlhdr->cmd, ret);
+ if (genlhdr->cmd == THERMAL_GENL_EVENT_CPU_CAPABILITY_CHANGE) {
+ struct nlattr *cap;
+ int j, index = 0;
+
+ debug_printf("THERMAL_GENL_EVENT_CPU_CAPABILITY_CHANGE\n");
+ nla_for_each_nested(cap, attrs[THERMAL_GENL_ATTR_CPU_CAPABILITY], j) {
+ switch (index) {
+ case 0:
+ perf_cap.cpu = nla_get_u32(cap);
+ break;
+ case 1:
+ perf_cap.perf = nla_get_u32(cap);
+ break;
+ case 2:
+ perf_cap.eff = nla_get_u32(cap);
+ break;
+ default:
+ break;
+ }
+ ++index;
+ if (index == 3) {
+ index = 0;
+ process_hfi_event(&perf_cap);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int _hfi_exit;
+
+static int check_hf_suport(void)
+{
+ unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0;
+
+ __cpuid(6, eax, ebx, ecx, edx);
+ if (eax & BIT(19))
+ return 1;
+
+ return 0;
+}
+
+int hfi_main(void)
+{
+ struct nl_sock *sock;
+ struct nl_cb *cb;
+ int err = 0;
+ int mcast_id;
+
+ if (!check_hf_suport()) {
+ fprintf(stderr, "CPU Doesn't support HFI\n");
+ return -1;
+ }
+
+ sock = nl_socket_alloc();
+ if (!sock) {
+ fprintf(stderr, "nl_socket_alloc failed\n");
+ return -1;
+ }
+
+ if (genl_connect(sock)) {
+ fprintf(stderr, "genl_connect(sk_event) failed\n");
+ goto free_sock;
+ }
+
+ drv.nl_handle = sock;
+ drv.nl_cb = cb = nl_cb_alloc(NL_CB_DEFAULT);
+ if (drv.nl_cb == NULL) {
+ printf("Failed to allocate netlink callbacks");
+ goto free_sock;
+ }
+
+ mcast_id = nl_get_multicast_id(&drv, THERMAL_GENL_FAMILY_NAME,
+ THERMAL_GENL_EVENT_GROUP_NAME);
+ if (mcast_id < 0) {
+ fprintf(stderr, "nl_get_multicast_id failed\n");
+ goto free_sock;
+ }
+
+ if (nl_socket_add_membership(sock, mcast_id)) {
+ fprintf(stderr, "nl_socket_add_membership failed");
+ goto free_sock;
+ }
+
+ nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, seq_check_handler, 0);
+ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, handle_event, NULL);
+
+ debug_printf("hfi is initialized\n");
+
+ while (!_hfi_exit && !err) {
+ err = nl_recvmsgs(sock, cb);
+ debug_printf("nl_recv_message err:%d\n", err);
+ }
+
+ return 0;
+
+ /* Netlink library doesn't have calls to dealloc cb or disconnect */
+free_sock:
+ nl_socket_free(sock);
+
+ return -1;
+}
+
+void hfi_exit(void)
+{
+ _hfi_exit = 1;
+}
diff --git a/tools/power/x86/intel-speed-select/isst-config.c b/tools/power/x86/intel-speed-select/isst-config.c
index 9f68f51ca652..0ce251b8d466 100644
--- a/tools/power/x86/intel-speed-select/isst-config.c
+++ b/tools/power/x86/intel-speed-select/isst-config.c
@@ -4,6 +4,7 @@
* Copyright (c) 2019 Intel Corporation.
*/
+#include <ctype.h>
#include <linux/isst_if.h>
#include "isst.h"
@@ -15,8 +16,9 @@ struct process_cmd_struct {
int arg;
};
-static const char *version_str = "v1.4";
-static const int supported_api_ver = 1;
+static const char *version_str = "v1.23";
+
+static const int supported_api_ver = 3;
static struct isst_if_platform_info isst_platform_info;
static char *progname;
static int debug_flag;
@@ -24,8 +26,9 @@ static FILE *outf;
static int cpu_model;
static int cpu_stepping;
+static int extended_family;
-#define MAX_CPUS_IN_ONE_REQ 256
+#define MAX_CPUS_IN_ONE_REQ 512
static short max_target_cpus;
static unsigned short target_cpus[MAX_CPUS_IN_ONE_REQ];
@@ -43,6 +46,10 @@ static int cmd_help;
static int force_online_offline;
static int auto_mode;
static int fact_enable_fail;
+static int cgroupv2;
+static int max_pkg_id;
+static int max_die_id;
+static int max_die_id_package_0;
/* clos related */
static int current_clos = -1;
@@ -52,13 +59,17 @@ static int clos_min = -1;
static int clos_max = -1;
static int clos_desired = -1;
static int clos_priority_type;
+static int cpu_0_cgroupv2;
+static int cpu_0_workaround(int isolate);
struct _cpu_map {
unsigned short core_id;
unsigned short pkg_id;
unsigned short die_id;
+ unsigned short punit_id;
unsigned short punit_cpu;
unsigned short punit_cpu_core;
+ unsigned short initialized;
};
struct _cpu_map *cpu_map;
@@ -74,6 +85,11 @@ FILE *get_output_file(void)
return outf;
}
+int is_debug_enabled(void)
+{
+ return debug_flag;
+}
+
void debug_printf(const char *format, ...)
{
va_list args;
@@ -103,6 +119,39 @@ int is_skx_based_platform(void)
return 0;
}
+int is_spr_platform(void)
+{
+ if (cpu_model == 0x8F)
+ return 1;
+
+ return 0;
+}
+
+int is_emr_platform(void)
+{
+ if (cpu_model == 0xCF)
+ return 1;
+
+ return 0;
+}
+
+
+int is_icx_platform(void)
+{
+ if (cpu_model == 0x6A || cpu_model == 0x6C)
+ return 1;
+
+ return 0;
+}
+
+static int is_dmr_plus_platform(void)
+{
+ if (extended_family == 0x04)
+ return 1;
+
+ return 0;
+}
+
static int update_cpu_model(void)
{
unsigned int ebx, ecx, edx;
@@ -110,6 +159,7 @@ static int update_cpu_model(void)
__cpuid(1, fms, ebx, ecx, edx);
family = (fms >> 8) & 0xf;
+ extended_family = (fms >> 20) & 0x0f;
cpu_model = (fms >> 4) & 0xf;
if (family == 6 || family == 0xf)
cpu_model += ((fms >> 16) & 0xf) << 4;
@@ -142,6 +192,11 @@ static int update_cpu_model(void)
return 0;
}
+int api_version(void)
+{
+ return isst_platform_info.api_version;
+}
+
/* Open a file, and exit on failure */
static FILE *fopen_or_exit(const char *path, const char *mode)
{
@@ -198,7 +253,7 @@ int out_format_is_json(void)
static int get_stored_topology_info(int cpu, int *core_id, int *pkg_id, int *die_id)
{
- const char *pathname = "/tmp/isst_cpu_topology.dat";
+ const char *pathname = "/var/run/isst_cpu_topology.dat";
struct cpu_topology cpu_top;
FILE *fp;
int ret;
@@ -230,7 +285,7 @@ err_ret:
static void store_cpu_topology(void)
{
- const char *pathname = "/tmp/isst_cpu_topology.dat";
+ const char *pathname = "/var/run/isst_cpu_topology.dat";
FILE *fp;
int i;
@@ -247,6 +302,8 @@ static void store_cpu_topology(void)
return;
}
+ fprintf(stderr, "Caching topology information\n");
+
for (i = 0; i < topo_max_cpus; ++i) {
struct cpu_topology cpu_top;
@@ -276,10 +333,16 @@ static void store_cpu_topology(void)
fclose(fp);
}
-int get_physical_package_id(int cpu)
+static int get_physical_package_id(int cpu)
{
int ret;
+ if (cpu < 0)
+ return -1;
+
+ if (cpu_map && cpu_map[cpu].initialized)
+ return cpu_map[cpu].pkg_id;
+
ret = parse_int_file(0,
"/sys/devices/system/cpu/cpu%d/topology/physical_package_id",
cpu);
@@ -294,10 +357,16 @@ int get_physical_package_id(int cpu)
return ret;
}
-int get_physical_core_id(int cpu)
+static int get_physical_core_id(int cpu)
{
int ret;
+ if (cpu < 0)
+ return -1;
+
+ if (cpu_map && cpu_map[cpu].initialized)
+ return cpu_map[cpu].core_id;
+
ret = parse_int_file(0,
"/sys/devices/system/cpu/cpu%d/topology/core_id",
cpu);
@@ -312,10 +381,16 @@ int get_physical_core_id(int cpu)
return ret;
}
-int get_physical_die_id(int cpu)
+static int get_physical_die_id(int cpu)
{
int ret;
+ if (cpu < 0)
+ return -1;
+
+ if (cpu_map && cpu_map[cpu].initialized)
+ return cpu_map[cpu].die_id;
+
ret = parse_int_file(0,
"/sys/devices/system/cpu/cpu%d/topology/die_id",
cpu);
@@ -323,8 +398,12 @@ int get_physical_die_id(int cpu)
int core_id, pkg_id, die_id;
ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id);
- if (!ret)
+ if (!ret) {
+ if (die_id < 0)
+ die_id = 0;
+
return die_id;
+ }
}
if (ret < 0)
@@ -333,6 +412,46 @@ int get_physical_die_id(int cpu)
return ret;
}
+static int get_physical_punit_id(int cpu)
+{
+ if (cpu < 0)
+ return -1;
+
+ if (cpu_map && cpu_map[cpu].initialized)
+ return cpu_map[cpu].punit_id;
+
+ return -1;
+}
+
+void set_isst_id(struct isst_id *id, int cpu)
+{
+ id->cpu = cpu;
+
+ id->pkg = get_physical_package_id(cpu);
+ if (id->pkg >= MAX_PACKAGE_COUNT)
+ id->pkg = -1;
+
+ id->die = get_physical_die_id(cpu);
+ if (id->die >= MAX_DIE_PER_PACKAGE)
+ id->die = -1;
+
+ id->punit = get_physical_punit_id(cpu);
+ if (id->punit >= MAX_PUNIT_PER_DIE)
+ id->punit = -1;
+}
+
+int is_cpu_in_power_domain(int cpu, struct isst_id *id)
+{
+ struct isst_id tid;
+
+ set_isst_id(&tid, cpu);
+
+ if (id->pkg == tid.pkg && id->die == tid.die && id->punit == tid.punit)
+ return 1;
+
+ return 0;
+}
+
int get_cpufreq_base_freq(int cpu)
{
return parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency", cpu);
@@ -343,19 +462,53 @@ int get_topo_max_cpus(void)
return topo_max_cpus;
}
-static void set_cpu_online_offline(int cpu, int state)
+static unsigned int is_cpu_online(int cpu)
{
char buffer[128];
int fd, ret;
+ unsigned char online;
+
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/cpu%d/online", cpu);
+
+ fd = open(buffer, O_RDONLY);
+ if (fd < 0)
+ return fd;
+
+ ret = read(fd, &online, sizeof(online));
+ close(fd);
+
+ if (ret == -1)
+ return ret;
+
+ if (online == '1')
+ online = 1;
+ else
+ online = 0;
+
+ return online;
+}
+
+void set_cpu_online_offline(int cpu, int state)
+{
+ char buffer[128];
+ int fd, ret;
+
+ if (cpu_0_cgroupv2 && !cpu) {
+ fprintf(stderr, "Will use cgroup v2 for CPU 0\n");
+ cpu_0_workaround(!state);
+ return;
+ }
snprintf(buffer, sizeof(buffer),
"/sys/devices/system/cpu/cpu%d/online", cpu);
fd = open(buffer, O_WRONLY);
if (fd < 0) {
- if (!cpu && state) {
+ if (!cpu) {
fprintf(stderr, "This system is not configured for CPU 0 online/offline\n");
- fprintf(stderr, "Ignoring online request for CPU 0 as this is already online\n");
+ fprintf(stderr, "Will use cgroup v2\n");
+ cpu_0_workaround(!state);
return;
}
err(-1, "%s open failed", buffer);
@@ -372,60 +525,98 @@ static void set_cpu_online_offline(int cpu, int state)
close(fd);
}
-#define MAX_PACKAGE_COUNT 8
-#define MAX_DIE_PER_PACKAGE 2
-static void for_each_online_package_in_set(void (*callback)(int, void *, void *,
- void *, void *),
- void *arg1, void *arg2, void *arg3,
- void *arg4)
+static void force_all_cpus_online(void)
+{
+ int i;
+
+ fprintf(stderr, "Forcing all CPUs online\n");
+
+ for (i = 0; i < topo_max_cpus; ++i)
+ set_cpu_online_offline(i, 1);
+
+ unlink("/var/run/isst_cpu_topology.dat");
+}
+
+void for_each_online_power_domain_in_set(void (*callback)(struct isst_id *, void *, void *,
+ void *, void *),
+ void *arg1, void *arg2, void *arg3,
+ void *arg4)
{
- int max_packages[MAX_PACKAGE_COUNT * MAX_PACKAGE_COUNT];
- int pkg_index = 0, i;
+ struct isst_id id;
+ int cpus[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE][MAX_PUNIT_PER_DIE];
+ int valid_mask[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE] = {0};
+ int i, j, k;
+
+ memset(cpus, -1, sizeof(cpus));
- memset(max_packages, 0xff, sizeof(max_packages));
for (i = 0; i < topo_max_cpus; ++i) {
- int j, online, pkg_id, die_id = 0, skip = 0;
+ int online;
if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
continue;
- if (i)
- online = parse_int_file(
- 1, "/sys/devices/system/cpu/cpu%d/online", i);
- else
- online =
- 1; /* online entry for CPU 0 needs some special configs */
- die_id = get_physical_die_id(i);
- if (die_id < 0)
- die_id = 0;
+ online = parse_int_file(
+ i != 0, "/sys/devices/system/cpu/cpu%d/online", i);
+ if (online < 0)
+ online = 1; /* online entry for CPU 0 needs some special configs */
- pkg_id = parse_int_file(0,
- "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", i);
- if (pkg_id < 0)
+ if (!online)
continue;
- /* Create an unique id for package, die combination to store */
- pkg_id = (MAX_PACKAGE_COUNT * pkg_id + die_id);
+ set_isst_id(&id, i);
- for (j = 0; j < pkg_index; ++j) {
- if (max_packages[j] == pkg_id) {
- skip = 1;
- break;
+ if (id.pkg < 0 || id.die < 0 || id.punit < 0)
+ continue;
+
+ id.die = id.die % (max_die_id_package_0 + 1);
+
+ valid_mask[id.pkg][id.die] = 1;
+
+ if (cpus[id.pkg][id.die][id.punit] == -1)
+ cpus[id.pkg][id.die][id.punit] = i;
+ }
+
+ for (i = 0; i < MAX_PACKAGE_COUNT; i++) {
+ if (max_die_id > max_pkg_id) {
+ for (k = 0; k < MAX_PUNIT_PER_DIE && k < MAX_DIE_PER_PACKAGE; k++) {
+ id.cpu = cpus[i][k][k];
+ id.pkg = i;
+ id.die = get_physical_die_id(id.cpu);
+ id.punit = k;
+ if (isst_is_punit_valid(&id))
+ callback(&id, arg1, arg2, arg3, arg4);
}
+ continue;
}
- if (!skip && online && callback) {
- callback(i, arg1, arg2, arg3, arg4);
- max_packages[pkg_index++] = pkg_id;
+ for (j = 0; j < MAX_DIE_PER_PACKAGE; j++) {
+ /*
+ * Fix me:
+ * How to check a non-cpu die for a package/die with all cpu offlined?
+ */
+ if (!valid_mask[i][j])
+ continue;
+ for (k = 0; k < MAX_PUNIT_PER_DIE; k++) {
+ id.cpu = cpus[i][j][k];
+ id.pkg = i;
+ if (id.cpu >= 0)
+ id.die = get_physical_die_id(id.cpu);
+ else
+ id.die = id.pkg;
+ id.punit = k;
+ if (isst_is_punit_valid(&id))
+ callback(&id, arg1, arg2, arg3, arg4);
+ }
}
}
}
static void for_each_online_target_cpu_in_set(
- void (*callback)(int, void *, void *, void *, void *), void *arg1,
+ void (*callback)(struct isst_id *, void *, void *, void *, void *), void *arg1,
void *arg2, void *arg3, void *arg4)
{
int i, found = 0;
+ struct isst_id id;
for (i = 0; i < topo_max_cpus; ++i) {
int online;
@@ -439,8 +630,9 @@ static void for_each_online_target_cpu_in_set(
online =
1; /* online entry for CPU 0 needs some special configs */
+ set_isst_id(&id, i);
if (online && callback) {
- callback(i, arg1, arg2, arg3, arg4);
+ callback(&id, arg1, arg2, arg3, arg4);
found = 1;
}
}
@@ -499,158 +691,178 @@ void free_cpu_set(cpu_set_t *cpu_set)
CPU_FREE(cpu_set);
}
-static int cpu_cnt[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE];
-static long long core_mask[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE];
-static void set_cpu_present_cpu_mask(void)
-{
- size_t size;
- DIR *dir;
- int i;
-
- size = alloc_cpu_set(&present_cpumask);
- present_cpumask_size = size;
- for (i = 0; i < topo_max_cpus; ++i) {
- char buffer[256];
-
- snprintf(buffer, sizeof(buffer),
- "/sys/devices/system/cpu/cpu%d", i);
- dir = opendir(buffer);
- if (dir) {
- int pkg_id, die_id;
-
- CPU_SET_S(i, size, present_cpumask);
- die_id = get_physical_die_id(i);
- if (die_id < 0)
- die_id = 0;
-
- pkg_id = get_physical_package_id(i);
- if (pkg_id < 0) {
- fprintf(stderr, "Failed to get package id, CPU %d may be offline\n", i);
- continue;
- }
- if (pkg_id < MAX_PACKAGE_COUNT &&
- die_id < MAX_DIE_PER_PACKAGE) {
- int core_id = get_physical_core_id(i);
-
- cpu_cnt[pkg_id][die_id]++;
- core_mask[pkg_id][die_id] |= (1ULL << core_id);
- }
- }
- closedir(dir);
- }
-}
+static int cpu_cnt[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE][MAX_PUNIT_PER_DIE];
-int get_core_count(int pkg_id, int die_id)
+int get_max_punit_core_id(struct isst_id *id)
{
- int cnt = 0;
+ int max_id = 0;
+ int i;
- if (pkg_id < MAX_PACKAGE_COUNT && die_id < MAX_DIE_PER_PACKAGE) {
- int i;
+ for (i = 0; i < topo_max_cpus; ++i)
+ {
+ if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
+ continue;
- for (i = 0; i < sizeof(long long) * 8; ++i) {
- if (core_mask[pkg_id][die_id] & (1ULL << i))
- cnt++;
- }
+ if (is_cpu_in_power_domain(i, id) &&
+ cpu_map[i].punit_cpu_core > max_id)
+ max_id = cpu_map[i].punit_cpu_core;
}
- return cnt;
+ return max_id;
}
-int get_cpu_count(int pkg_id, int die_id)
+int get_cpu_count(struct isst_id *id)
{
- if (pkg_id < MAX_PACKAGE_COUNT && die_id < MAX_DIE_PER_PACKAGE)
- return cpu_cnt[pkg_id][die_id];
+ if (id->pkg < 0 || id->die < 0 || id->punit < 0)
+ return 0;
- return 0;
+ return cpu_cnt[id->pkg][id->die][id->punit];
}
-static void set_cpu_target_cpu_mask(void)
+static void update_punit_cpu_info(__u32 physical_cpu, struct _cpu_map *cpu_map)
{
- size_t size;
- int i;
+ if (api_version() > 1) {
+ /*
+ * MSR 0x54 format
+ * [15:11] PM_DOMAIN_ID
+ * [10:3] MODULE_ID (aka IDI_AGENT_ID)
+ * [2:0] LP_ID (We don't care about these bits we only
+ * care die and core id
+ * For Atom:
+ * [2] Always 0
+ * [1:0] core ID within module
+ * For Core
+ * [2:1] Always 0
+ * [0] thread ID
+ */
+ cpu_map->punit_id = (physical_cpu >> 11) & 0x1f;
+ cpu_map->punit_cpu_core = (physical_cpu >> 3) & 0xff;
+ cpu_map->punit_cpu = physical_cpu & 0x7ff;
+ } else {
+ int punit_id;
- size = alloc_cpu_set(&target_cpumask);
- target_cpumask_size = size;
- for (i = 0; i < max_target_cpus; ++i) {
- if (!CPU_ISSET_S(target_cpus[i], present_cpumask_size,
- present_cpumask))
- continue;
+ /*
+ * MSR 0x53 format
+ * Format
+ * Bit 0 – thread ID
+ * Bit 8:1 – core ID
+ * Bit 13:9 – punit ID
+ */
+ cpu_map->punit_cpu = physical_cpu & 0x1ff;
+ cpu_map->punit_cpu_core = (cpu_map->punit_cpu >> 1); // shift to get core id
+ punit_id = (physical_cpu >> 9) & 0x1f;
- CPU_SET_S(target_cpus[i], size, target_cpumask);
+ if (punit_id >= MAX_PUNIT_PER_DIE)
+ punit_id = 0;
+
+ cpu_map->punit_id = punit_id;
}
}
static void create_cpu_map(void)
{
const char *pathname = "/dev/isst_interface";
+ size_t size;
+ DIR *dir;
int i, fd = 0;
struct isst_if_cpu_maps map;
- cpu_map = malloc(sizeof(*cpu_map) * topo_max_cpus);
+ /* Use calloc to make sure the memory is initialized to Zero */
+ cpu_map = calloc(topo_max_cpus, sizeof(*cpu_map));
if (!cpu_map)
err(3, "cpumap");
fd = open(pathname, O_RDWR);
- if (fd < 0)
+ if (fd < 0 && !is_clx_n_platform())
err(-1, "%s open failed", pathname);
+ size = alloc_cpu_set(&present_cpumask);
+ present_cpumask_size = size;
+
for (i = 0; i < topo_max_cpus; ++i) {
- if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
+ char buffer[256];
+ int pkg_id, die_id, core_id, punit_id;
+
+ /* check if CPU is online */
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/cpu%d", i);
+ dir = opendir(buffer);
+ if (!dir)
continue;
+ closedir(dir);
+
+ CPU_SET_S(i, size, present_cpumask);
- map.cmd_count = 1;
- map.cpu_map[0].logical_cpu = i;
+ pkg_id = get_physical_package_id(i);
+ die_id = get_physical_die_id(i);
+ core_id = get_physical_core_id(i);
- debug_printf(" map logical_cpu:%d\n",
- map.cpu_map[0].logical_cpu);
- if (ioctl(fd, ISST_IF_GET_PHY_ID, &map) == -1) {
- perror("ISST_IF_GET_PHY_ID");
- fprintf(outf, "Error: map logical_cpu:%d\n",
- map.cpu_map[0].logical_cpu);
+ if (pkg_id < 0 || die_id < 0 || core_id < 0)
continue;
+
+ cpu_map[i].pkg_id = pkg_id;
+ cpu_map[i].die_id = die_id;
+ cpu_map[i].core_id = core_id;
+
+ if (max_pkg_id < pkg_id)
+ max_pkg_id = pkg_id;
+
+ punit_id = 0;
+
+ if (fd >= 0) {
+ map.cmd_count = 1;
+ map.cpu_map[0].logical_cpu = i;
+ debug_printf(" map logical_cpu:%d\n",
+ map.cpu_map[0].logical_cpu);
+ if (ioctl(fd, ISST_IF_GET_PHY_ID, &map) == -1) {
+ perror("ISST_IF_GET_PHY_ID");
+ fprintf(outf, "Error: map logical_cpu:%d\n",
+ map.cpu_map[0].logical_cpu);
+ } else {
+ update_punit_cpu_info(map.cpu_map[0].physical_cpu, &cpu_map[i]);
+ punit_id = cpu_map[i].punit_id;
+ }
}
- cpu_map[i].core_id = get_physical_core_id(i);
- cpu_map[i].pkg_id = get_physical_package_id(i);
- cpu_map[i].die_id = get_physical_die_id(i);
- cpu_map[i].punit_cpu = map.cpu_map[0].physical_cpu;
- cpu_map[i].punit_cpu_core = (map.cpu_map[0].physical_cpu >>
- 1); // shift to get core id
+ cpu_map[i].initialized = 1;
+
+ cpu_cnt[pkg_id][die_id][punit_id]++;
+
+ if (max_die_id < die_id)
+ max_die_id = die_id;
+
+ if (!pkg_id && max_die_id_package_0 < die_id)
+ max_die_id_package_0 = die_id;
debug_printf(
- "map logical_cpu:%d core: %d die:%d pkg:%d punit_cpu:%d punit_core:%d\n",
+ "map logical_cpu:%d core: %d die:%d pkg:%d punit:%d punit_cpu:%d punit_core:%d\n",
i, cpu_map[i].core_id, cpu_map[i].die_id,
- cpu_map[i].pkg_id, cpu_map[i].punit_cpu,
- cpu_map[i].punit_cpu_core);
+ cpu_map[i].pkg_id, cpu_map[i].punit_id,
+ cpu_map[i].punit_cpu, cpu_map[i].punit_cpu_core);
}
-
- if (fd)
+ if (fd >= 0)
close(fd);
-}
-int find_logical_cpu(int pkg_id, int die_id, int punit_core_id)
-{
- int i;
+ size = alloc_cpu_set(&target_cpumask);
+ target_cpumask_size = size;
+ for (i = 0; i < max_target_cpus; ++i) {
+ if (!CPU_ISSET_S(target_cpus[i], present_cpumask_size,
+ present_cpumask))
+ continue;
- for (i = 0; i < topo_max_cpus; ++i) {
- if (cpu_map[i].pkg_id == pkg_id &&
- cpu_map[i].die_id == die_id &&
- cpu_map[i].punit_cpu_core == punit_core_id)
- return i;
+ CPU_SET_S(target_cpus[i], size, target_cpumask);
}
-
- return -EINVAL;
}
-void set_cpu_mask_from_punit_coremask(int cpu, unsigned long long core_mask,
+void set_cpu_mask_from_punit_coremask(struct isst_id *id, unsigned long long core_mask,
size_t core_cpumask_size,
cpu_set_t *core_cpumask, int *cpu_cnt)
{
int i, cnt = 0;
- int die_id, pkg_id;
+
+ if (id->cpu < 0)
+ return;
*cpu_cnt = 0;
- die_id = get_physical_die_id(cpu);
- pkg_id = get_physical_package_id(cpu);
for (i = 0; i < 64; ++i) {
if (core_mask & BIT_ULL(i)) {
@@ -660,8 +872,7 @@ void set_cpu_mask_from_punit_coremask(int cpu, unsigned long long core_mask,
if (!CPU_ISSET_S(j, present_cpumask_size, present_cpumask))
continue;
- if (cpu_map[j].pkg_id == pkg_id &&
- cpu_map[j].die_id == die_id &&
+ if (is_cpu_in_power_domain(j, id) &&
cpu_map[j].punit_cpu_core == i) {
CPU_SET_S(j, core_cpumask_size,
core_cpumask);
@@ -682,170 +893,211 @@ int find_phy_core_num(int logical_cpu)
return -EINVAL;
}
-static int isst_send_mmio_command(unsigned int cpu, unsigned int reg, int write,
- unsigned int *value)
+int use_cgroupv2(void)
{
- struct isst_if_io_regs io_regs;
- const char *pathname = "/dev/isst_interface";
- int cmd;
- int fd;
-
- debug_printf("mmio_cmd cpu:%d reg:%d write:%d\n", cpu, reg, write);
+ return cgroupv2;
+}
- fd = open(pathname, O_RDWR);
- if (fd < 0)
- err(-1, "%s open failed", pathname);
+int enable_cpuset_controller(void)
+{
+ int fd, ret;
- io_regs.req_count = 1;
- io_regs.io_reg[0].logical_cpu = cpu;
- io_regs.io_reg[0].reg = reg;
- cmd = ISST_IF_IO_CMD;
- if (write) {
- io_regs.io_reg[0].read_write = 1;
- io_regs.io_reg[0].value = *value;
- } else {
- io_regs.io_reg[0].read_write = 0;
+ fd = open("/sys/fs/cgroup/cgroup.subtree_control", O_RDWR, 0);
+ if (fd < 0) {
+ debug_printf("Can't activate cpuset controller\n");
+ debug_printf("Either you are not root user or CGroup v2 is not supported\n");
+ return fd;
}
- if (ioctl(fd, cmd, &io_regs) == -1) {
- if (errno == ENOTTY) {
- perror("ISST_IF_IO_COMMAND\n");
- fprintf(stderr, "Check presence of kernel modules: isst_if_mmio\n");
- exit(0);
- }
- fprintf(outf, "Error: mmio_cmd cpu:%d reg:%x read_write:%x\n",
- cpu, reg, write);
- } else {
- if (!write)
- *value = io_regs.io_reg[0].value;
+ ret = write(fd, " +cpuset", strlen(" +cpuset"));
+ close(fd);
- debug_printf(
- "mmio_cmd response: cpu:%d reg:%x rd_write:%x resp:%x\n",
- cpu, reg, write, *value);
+ if (ret == -1) {
+ debug_printf("Can't activate cpuset controller: Write failed\n");
+ return ret;
}
- close(fd);
-
return 0;
}
-int isst_send_mbox_command(unsigned int cpu, unsigned char command,
- unsigned char sub_command, unsigned int parameter,
- unsigned int req_data, unsigned int *resp)
+int isolate_cpus(struct isst_id *id, int mask_size, cpu_set_t *cpu_mask, int level, int cpu_0_only)
{
- const char *pathname = "/dev/isst_interface";
- int fd;
- struct isst_if_mbox_cmds mbox_cmds = { 0 };
+ int i, first, curr_index, index, ret, fd;
+ static char str[512], dir_name[64];
+ static char cpuset_cpus[128];
+ int str_len = sizeof(str);
+ DIR *dir;
- debug_printf(
- "mbox_send: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n",
- cpu, command, sub_command, parameter, req_data);
+ snprintf(dir_name, sizeof(dir_name), "/sys/fs/cgroup/%d-%d-%d", id->pkg, id->die, id->punit);
+ dir = opendir(dir_name);
+ if (!dir) {
+ ret = mkdir(dir_name, 0744);
+ if (ret) {
+ debug_printf("Can't create dir:%s errno:%d\n", dir_name, errno);
+ return ret;
+ }
+ }
+ closedir(dir);
- if (!is_skx_based_platform() && command == CONFIG_CLOS &&
- sub_command != CLOS_PM_QOS_CONFIG) {
- unsigned int value;
- int write = 0;
- int clos_id, core_id, ret = 0;
+ if (!level) {
+ sprintf(cpuset_cpus, "%s/cpuset.cpus.partition", dir_name);
- debug_printf("CPU %d\n", cpu);
+ fd = open(cpuset_cpus, O_RDWR, 0);
+ if (fd < 0) {
+ return fd;
+ }
- if (parameter & BIT(MBOX_CMD_WRITE_BIT)) {
- value = req_data;
- write = 1;
+ ret = write(fd, "member", strlen("member"));
+ if (ret == -1) {
+ printf("Can't update to member\n");
+ return ret;
}
- switch (sub_command) {
- case CLOS_PQR_ASSOC:
- core_id = parameter & 0xff;
- ret = isst_send_mmio_command(
- cpu, PQR_ASSOC_OFFSET + core_id * 4, write,
- &value);
- if (!ret && !write)
- *resp = value;
- break;
- case CLOS_PM_CLOS:
- clos_id = parameter & 0x03;
- ret = isst_send_mmio_command(
- cpu, PM_CLOS_OFFSET + clos_id * 4, write,
- &value);
- if (!ret && !write)
- *resp = value;
- break;
- case CLOS_STATUS:
- break;
- default:
- break;
+ return 0;
+ }
+
+ if (!CPU_COUNT_S(mask_size, cpu_mask)) {
+ return -1;
+ }
+
+ curr_index = 0;
+ first = 1;
+ str[0] = '\0';
+
+ if (cpu_0_only) {
+ snprintf(str, str_len, "0");
+ goto create_partition;
+ }
+
+ for (i = 0; i < get_topo_max_cpus(); ++i) {
+ if (!is_cpu_in_power_domain(i, id))
+ continue;
+
+ if (CPU_ISSET_S(i, mask_size, cpu_mask))
+ continue;
+
+ if (!first) {
+ index = snprintf(&str[curr_index],
+ str_len - curr_index, ",");
+ curr_index += index;
+ if (curr_index >= str_len)
+ break;
}
+ index = snprintf(&str[curr_index], str_len - curr_index, "%d",
+ i);
+ curr_index += index;
+ if (curr_index >= str_len)
+ break;
+ first = 0;
+ }
+
+create_partition:
+ debug_printf("isolated CPUs list: package:%d curr_index:%d [%s]\n", id->pkg, curr_index ,str);
+
+ snprintf(cpuset_cpus, sizeof(cpuset_cpus), "%s/cpuset.cpus", dir_name);
+
+ fd = open(cpuset_cpus, O_RDWR, 0);
+ if (fd < 0) {
+ return fd;
+ }
+
+ ret = write(fd, str, strlen(str));
+ close(fd);
+
+ if (ret == -1) {
+ debug_printf("Can't activate cpuset controller: Write failed\n");
return ret;
}
- mbox_cmds.cmd_count = 1;
- mbox_cmds.mbox_cmd[0].logical_cpu = cpu;
- mbox_cmds.mbox_cmd[0].command = command;
- mbox_cmds.mbox_cmd[0].sub_command = sub_command;
- mbox_cmds.mbox_cmd[0].parameter = parameter;
- mbox_cmds.mbox_cmd[0].req_data = req_data;
+ snprintf(cpuset_cpus, sizeof(cpuset_cpus), "%s/cpuset.cpus.partition", dir_name);
- fd = open(pathname, O_RDWR);
- if (fd < 0)
- err(-1, "%s open failed", pathname);
+ fd = open(cpuset_cpus, O_RDWR, 0);
+ if (fd < 0) {
+ return fd;
+ }
- if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) {
- if (errno == ENOTTY) {
- perror("ISST_IF_MBOX_COMMAND\n");
- fprintf(stderr, "Check presence of kernel modules: isst_if_mbox_pci or isst_if_mbox_msr\n");
- exit(0);
- }
- debug_printf(
- "Error: mbox_cmd cpu:%d command:%x sub_command:%x parameter:%x req_data:%x errorno:%d\n",
- cpu, command, sub_command, parameter, req_data, errno);
- return -1;
- } else {
- *resp = mbox_cmds.mbox_cmd[0].resp_data;
- debug_printf(
- "mbox_cmd response: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x resp:%x\n",
- cpu, command, sub_command, parameter, req_data, *resp);
+ ret = write(fd, "isolated", strlen("isolated"));
+ if (ret == -1) {
+ debug_printf("Can't update to isolated\n");
+ ret = write(fd, "root", strlen("root"));
+ if (ret == -1)
+ debug_printf("Can't update to root\n");
}
close(fd);
+ if (ret < 0)
+ return ret;
+
return 0;
}
-int isst_send_msr_command(unsigned int cpu, unsigned int msr, int write,
- unsigned long long *req_resp)
+static int cpu_0_workaround(int isolate)
{
- struct isst_if_msr_cmds msr_cmds;
- const char *pathname = "/dev/isst_interface";
- int fd;
+ int fd, fd1, len, ret;
+ cpu_set_t cpu_mask;
+ struct isst_id id;
+ char str[2];
- fd = open(pathname, O_RDWR);
+ debug_printf("isolate CPU 0 state: %d\n", isolate);
+
+ if (isolate)
+ goto isolate;
+
+ /* First check if CPU 0 was isolated to remove isolation. */
+
+ /* If the cpuset.cpus doesn't exist, that means that none of the CPUs are isolated*/
+ fd = open("/sys/fs/cgroup/0-0-0/cpuset.cpus", O_RDONLY, 0);
if (fd < 0)
- err(-1, "%s open failed", pathname);
+ return 0;
- msr_cmds.cmd_count = 1;
- msr_cmds.msr_cmd[0].logical_cpu = cpu;
- msr_cmds.msr_cmd[0].msr = msr;
- msr_cmds.msr_cmd[0].read_write = write;
- if (write)
- msr_cmds.msr_cmd[0].data = *req_resp;
-
- if (ioctl(fd, ISST_IF_MSR_COMMAND, &msr_cmds) == -1) {
- perror("ISST_IF_MSR_COMMAND");
- fprintf(outf, "Error: msr_cmd cpu:%d msr:%x read_write:%d\n",
- cpu, msr, write);
- } else {
- if (!write)
- *req_resp = msr_cmds.msr_cmd[0].data;
+ len = read(fd, str, sizeof(str));
+ /* Error check, but unlikely to fail. If fails that means that not isolated */
+ if (len == -1)
+ return 0;
- debug_printf(
- "msr_cmd response: cpu:%d msr:%x rd_write:%x resp:%llx %llx\n",
- cpu, msr, write, *req_resp, msr_cmds.msr_cmd[0].data);
+
+ /* Is CPU 0 is in isolate list, the display is sorted so first element will be CPU 0*/
+ if (str[0] != '0') {
+ close(fd);
+ return 0;
+ }
+
+ fd1 = open("/sys/fs/cgroup/0-0-0/cpuset.cpus.partition", O_RDONLY, 0);
+ /* Unlikely that, this attribute is not present, but handle error */
+ if (fd1 < 0) {
+ close(fd);
+ return 0;
+ }
+
+ /* Is CPU 0 already changed partition to "member" */
+ len = read(fd1, str, sizeof(str));
+ if (len != -1 && str[0] == 'm') {
+ close(fd1);
+ close(fd);
+ return 0;
}
+ close(fd1);
close(fd);
- return 0;
+ debug_printf("CPU 0 was isolated before, so remove isolation\n");
+
+isolate:
+ ret = enable_cpuset_controller();
+ if (ret)
+ goto isolate_fail;
+
+ CPU_ZERO(&cpu_mask);
+ memset(&id, 0, sizeof(struct isst_id));
+ CPU_SET(0, &cpu_mask);
+
+ ret = isolate_cpus(&id, sizeof(cpu_mask), &cpu_mask, isolate, 1);
+isolate_fail:
+ if (ret)
+ fprintf(stderr, "Can't isolate CPU 0\n");
+
+ return ret;
}
static int isst_fill_platform_info(void)
@@ -853,6 +1105,11 @@ static int isst_fill_platform_info(void)
const char *pathname = "/dev/isst_interface";
int fd;
+ if (is_clx_n_platform()) {
+ isst_platform_info.api_version = 1;
+ goto set_platform_ops;
+ }
+
fd = open(pathname, O_RDWR);
if (fd < 0)
err(-1, "%s open failed", pathname);
@@ -869,71 +1126,96 @@ static int isst_fill_platform_info(void)
printf("Incompatible API versions; Upgrade of tool is required\n");
return -1;
}
+
+set_platform_ops:
+ if (isst_set_platform_ops(isst_platform_info.api_version)) {
+ fprintf(stderr, "Failed to set platform callbacks\n");
+ exit(0);
+ }
return 0;
}
-static void isst_print_extended_platform_info(void)
+void get_isst_status(struct isst_id *id, void *arg1, void *arg2, void *arg3, void *arg4)
{
- int cp_state, cp_cap, fact_support = 0, pbf_support = 0;
- struct isst_pkg_ctdp_level_info ctdp_level;
struct isst_pkg_ctdp pkg_dev;
- int ret, i, j;
- FILE *filep;
+ struct isst_id *tid = (struct isst_id *)arg2;
+ int *mask = (int *)arg3;
+ int *max_level = (int *)arg4;
+ int j, ret;
- for (i = 0; i < 256; ++i) {
- char path[256];
-
- snprintf(path, sizeof(path),
- "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", i);
- filep = fopen(path, "r");
- if (filep)
- break;
- }
-
- if (!filep)
+ /* Only check the first cpu power domain */
+ if (id->cpu < 0 || tid->cpu >= 0)
return;
- fclose(filep);
-
- ret = isst_get_ctdp_levels(i, &pkg_dev);
+ ret = isst_get_ctdp_levels(id, &pkg_dev);
if (ret)
return;
- if (pkg_dev.enabled) {
- fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is supported\n");
- } else {
- fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is not supported\n");
- fprintf(outf, "Only performance level 0 (base level) is present\n");
- }
+ if (pkg_dev.enabled)
+ *mask |= BIT(0);
if (pkg_dev.locked)
- fprintf(outf, "TDP level change control is locked\n");
- else
- fprintf(outf, "TDP level change control is unlocked, max level: %d \n", pkg_dev.levels);
+ *mask |= BIT(1);
+
+ if (*max_level < pkg_dev.levels)
+ *max_level = pkg_dev.levels;
for (j = 0; j <= pkg_dev.levels; ++j) {
- ret = isst_get_ctdp_control(i, j, &ctdp_level);
+ struct isst_pkg_ctdp_level_info ctdp_level;
+
+ ret = isst_get_ctdp_control(id, j, &ctdp_level);
if (ret)
continue;
- if (!fact_support && ctdp_level.fact_support)
- fact_support = 1;
+ if (ctdp_level.fact_support)
+ *mask |= BIT(2);
- if (!pbf_support && ctdp_level.pbf_support)
- pbf_support = 1;
+ if (ctdp_level.pbf_support)
+ *mask |= BIT(3);
}
- if (fact_support)
+ tid->cpu = id->cpu;
+ tid->pkg = id->pkg;
+ tid->die = id->die;
+ tid->punit = id->punit;
+}
+
+static void isst_print_extended_platform_info(void)
+{
+ int cp_state, cp_cap;
+ struct isst_id id;
+ int mask = 0, max_level = 0;
+
+ id.cpu = -1;
+ for_each_online_power_domain_in_set(get_isst_status, NULL, &id, &mask, &max_level);
+
+ if (mask & BIT(0)) {
+ fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is supported\n");
+ } else {
+ fprintf(outf, "Intel(R) SST-PP (feature perf-profile) is not supported\n");
+ fprintf(outf, "Only performance level 0 (base level) is present\n");
+ }
+
+ if (mask & BIT(1))
+ fprintf(outf, "TDP level change control is locked\n");
+ else
+ fprintf(outf, "TDP level change control is unlocked, max level: %d\n", max_level);
+
+ if (mask & BIT(2))
fprintf(outf, "Intel(R) SST-TF (feature turbo-freq) is supported\n");
else
fprintf(outf, "Intel(R) SST-TF (feature turbo-freq) is not supported\n");
- if (pbf_support)
+ if (mask & BIT(3))
fprintf(outf, "Intel(R) SST-BF (feature base-freq) is supported\n");
else
fprintf(outf, "Intel(R) SST-BF (feature base-freq) is not supported\n");
- ret = isst_read_pm_config(i, &cp_state, &cp_cap);
+ if (isst_read_pm_config(&id, &cp_state, &cp_cap)) {
+ fprintf(outf, "Intel(R) SST-CP (feature core-power) status is unknown\n");
+ return;
+ }
+
if (cp_cap)
fprintf(outf, "Intel(R) SST-CP (feature core-power) is supported\n");
else
@@ -942,51 +1224,41 @@ static void isst_print_extended_platform_info(void)
static void isst_print_platform_information(void)
{
- struct isst_if_platform_info platform_info;
- const char *pathname = "/dev/isst_interface";
- int fd;
-
if (is_clx_n_platform()) {
fprintf(stderr, "\nThis option in not supported on this platform\n");
exit(0);
}
- fd = open(pathname, O_RDWR);
- if (fd < 0)
- err(-1, "%s open failed", pathname);
-
- if (ioctl(fd, ISST_IF_GET_PLATFORM_INFO, &platform_info) == -1) {
- perror("ISST_IF_GET_PLATFORM_INFO");
- } else {
- fprintf(outf, "Platform: API version : %d\n",
- platform_info.api_version);
- fprintf(outf, "Platform: Driver version : %d\n",
- platform_info.driver_version);
- fprintf(outf, "Platform: mbox supported : %d\n",
- platform_info.mbox_supported);
- fprintf(outf, "Platform: mmio supported : %d\n",
- platform_info.mmio_supported);
- isst_print_extended_platform_info();
- }
-
- close(fd);
+ /* Early initialization to create working cpu_map */
+ set_max_cpu_num();
+ create_cpu_map();
+
+ fprintf(outf, "Platform: API version : %d\n",
+ isst_platform_info.api_version);
+ fprintf(outf, "Platform: Driver version : %d\n",
+ isst_platform_info.driver_version);
+ fprintf(outf, "Platform: mbox supported : %d\n",
+ isst_platform_info.mbox_supported);
+ fprintf(outf, "Platform: mmio supported : %d\n",
+ isst_platform_info.mmio_supported);
+ isst_print_extended_platform_info();
exit(0);
}
static char *local_str0, *local_str1;
-static void exec_on_get_ctdp_cpu(int cpu, void *arg1, void *arg2, void *arg3,
+static void exec_on_get_ctdp_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3,
void *arg4)
{
- int (*fn_ptr)(int cpu, void *arg);
+ int (*fn_ptr)(struct isst_id *id, void *arg);
int ret;
fn_ptr = arg1;
- ret = fn_ptr(cpu, arg2);
+ ret = fn_ptr(id, arg2);
if (ret)
isst_display_error_info_message(1, "get_tdp_* failed", 0, 0);
else
- isst_ctdp_display_core_info(cpu, outf, arg3,
+ isst_ctdp_display_core_info(id, outf, arg3,
*(unsigned int *)arg4,
local_str0, local_str1);
}
@@ -1010,7 +1282,7 @@ static void exec_on_get_ctdp_cpu(int cpu, void *arg1, void *arg2, void *arg3,
exec_on_get_ctdp_cpu, isst_get_ctdp_##suffix, \
&ctdp, desc, &ctdp.object); \
else \
- for_each_online_package_in_set(exec_on_get_ctdp_cpu, \
+ for_each_online_power_domain_in_set(exec_on_get_ctdp_cpu, \
isst_get_ctdp_##suffix, \
&ctdp, desc, \
&ctdp.object); \
@@ -1054,9 +1326,9 @@ static int clx_n_get_base_ratio(void)
return (int)(value);
}
-static int clx_n_config(int cpu)
+static int clx_n_config(struct isst_id *id)
{
- int i, ret, pkg_id, die_id;
+ int i, ret;
unsigned long cpu_bf;
struct isst_pkg_ctdp_level_info *ctdp_level;
struct isst_pbf_info *pbf_info;
@@ -1078,15 +1350,11 @@ static int clx_n_config(int cpu)
pbf_info->p1_high = 0;
pbf_info->p1_low = ~0;
- pkg_id = get_physical_package_id(cpu);
- die_id = get_physical_die_id(cpu);
-
for (i = 0; i < topo_max_cpus; i++) {
if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
continue;
- if (pkg_id != get_physical_package_id(i) ||
- die_id != get_physical_die_id(i))
+ if (!is_cpu_in_power_domain(i, id))
continue;
CPU_SET_S(i, ctdp_level->core_cpumask_size,
@@ -1123,8 +1391,7 @@ static int clx_n_config(int cpu)
if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
continue;
- if (pkg_id != get_physical_package_id(i) ||
- die_id != get_physical_die_id(i))
+ if (!is_cpu_in_power_domain(i, id))
continue;
cpu_bf = parse_int_file(1,
@@ -1150,7 +1417,7 @@ error_ret:
return ret;
}
-static void dump_clx_n_config_for_cpu(int cpu, void *arg1, void *arg2,
+static void dump_clx_n_config_for_cpu(struct isst_id *id, void *arg1, void *arg2,
void *arg3, void *arg4)
{
int ret;
@@ -1160,7 +1427,7 @@ static void dump_clx_n_config_for_cpu(int cpu, void *arg1, void *arg2,
exit(0);
}
- ret = clx_n_config(cpu);
+ ret = clx_n_config(id);
if (ret) {
debug_printf("clx_n_config failed");
} else {
@@ -1170,27 +1437,27 @@ static void dump_clx_n_config_for_cpu(int cpu, void *arg1, void *arg2,
ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
pbf_info = &ctdp_level->pbf_info;
clx_n_pkg_dev.processed = 1;
- isst_ctdp_display_information(cpu, outf, tdp_level, &clx_n_pkg_dev);
+ isst_ctdp_display_information(id, outf, tdp_level, &clx_n_pkg_dev);
free_cpu_set(ctdp_level->core_cpumask);
free_cpu_set(pbf_info->core_cpumask);
}
}
-static void dump_isst_config_for_cpu(int cpu, void *arg1, void *arg2,
+static void dump_isst_config_for_cpu(struct isst_id *id, void *arg1, void *arg2,
void *arg3, void *arg4)
{
struct isst_pkg_ctdp pkg_dev;
int ret;
memset(&pkg_dev, 0, sizeof(pkg_dev));
- ret = isst_get_process_ctdp(cpu, tdp_level, &pkg_dev);
+ ret = isst_get_process_ctdp(id, tdp_level, &pkg_dev);
if (ret) {
- isst_display_error_info_message(1, "Failed to get perf-profile info on cpu", 1, cpu);
+ isst_display_error_info_message(1, "Failed to get perf-profile info on cpu", 1, id->cpu);
isst_ctdp_display_information_end(outf);
exit(1);
} else {
- isst_ctdp_display_information(cpu, outf, tdp_level, &pkg_dev);
- isst_get_process_ctdp_complete(cpu, &pkg_dev);
+ isst_ctdp_display_information(id, outf, tdp_level, &pkg_dev);
+ isst_get_process_ctdp_complete(id, &pkg_dev);
}
}
@@ -1219,48 +1486,93 @@ static void dump_isst_config(int arg)
if (max_target_cpus)
for_each_online_target_cpu_in_set(fn, NULL, NULL, NULL, NULL);
else
- for_each_online_package_in_set(fn, NULL, NULL, NULL, NULL);
+ for_each_online_power_domain_in_set(fn, NULL, NULL, NULL, NULL);
isst_ctdp_display_information_end(outf);
}
-static void set_tdp_level_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
+static void adjust_scaling_max_from_base_freq(int cpu);
+
+static void set_tdp_level_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3,
void *arg4)
{
+ struct isst_pkg_ctdp pkg_dev;
int ret;
- ret = isst_set_tdp_level(cpu, tdp_level);
+ ret = isst_get_ctdp_levels(id, &pkg_dev);
+ if (ret) {
+ isst_display_error_info_message(1, "Get TDP level failed", 0, 0);
+ isst_ctdp_display_information_end(outf);
+ exit(1);
+ }
+
+ if (pkg_dev.current_level == tdp_level) {
+ debug_printf("TDP level already set. Skipped\n");
+ goto display_result;
+ }
+
+ ret = isst_set_tdp_level(id, tdp_level);
if (ret) {
isst_display_error_info_message(1, "Set TDP level failed", 0, 0);
isst_ctdp_display_information_end(outf);
exit(1);
- } else {
- isst_display_result(cpu, outf, "perf-profile", "set_tdp_level",
- ret);
- if (force_online_offline) {
- struct isst_pkg_ctdp_level_info ctdp_level;
- int pkg_id = get_physical_package_id(cpu);
- int die_id = get_physical_die_id(cpu);
-
- fprintf(stderr, "Option is set to online/offline\n");
- ctdp_level.core_cpumask_size =
- alloc_cpu_set(&ctdp_level.core_cpumask);
- isst_get_coremask_info(cpu, tdp_level, &ctdp_level);
- if (ctdp_level.cpu_count) {
- int i, max_cpus = get_topo_max_cpus();
- for (i = 0; i < max_cpus; ++i) {
- if (pkg_id != get_physical_package_id(i) || die_id != get_physical_die_id(i))
- continue;
- if (CPU_ISSET_S(i, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask)) {
- fprintf(stderr, "online cpu %d\n", i);
- set_cpu_online_offline(i, 1);
- } else {
- fprintf(stderr, "offline cpu %d\n", i);
- set_cpu_online_offline(i, 0);
- }
+ }
+
+display_result:
+ isst_display_result(id, outf, "perf-profile", "set_tdp_level", ret);
+ if (force_online_offline && id->cpu >= 0) {
+ struct isst_pkg_ctdp_level_info ctdp_level;
+
+ /* Wait for updated base frequencies */
+ usleep(2000);
+
+ /* Adjusting uncore freq */
+ if (!is_dmr_plus_platform())
+ isst_adjust_uncore_freq(id, tdp_level, &ctdp_level);
+
+ fprintf(stderr, "Option is set to online/offline\n");
+ ctdp_level.core_cpumask_size =
+ alloc_cpu_set(&ctdp_level.core_cpumask);
+ ret = isst_get_coremask_info(id, tdp_level, &ctdp_level);
+ if (ret) {
+ isst_display_error_info_message(1, "Can't get coremask, online/offline option is ignored", 0, 0);
+ goto free_mask;
+ }
+
+ if (use_cgroupv2()) {
+ int ret;
+
+ fprintf(stderr, "Using cgroup v2 in lieu of online/offline\n");
+ ret = enable_cpuset_controller();
+ if (ret)
+ goto use_offline;
+
+ ret = isolate_cpus(id, ctdp_level.core_cpumask_size,
+ ctdp_level.core_cpumask, tdp_level, 0);
+ if (ret)
+ goto use_offline;
+
+ goto free_mask;
+ }
+
+use_offline:
+ if (ctdp_level.cpu_count) {
+ int i, max_cpus = get_topo_max_cpus();
+ for (i = 0; i < max_cpus; ++i) {
+ if (!is_cpu_in_power_domain(i, id))
+ continue;
+ if (CPU_ISSET_S(i, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask)) {
+ fprintf(stderr, "online cpu %d\n", i);
+ set_cpu_online_offline(i, 1);
+ adjust_scaling_max_from_base_freq(i);
+ } else {
+ fprintf(stderr, "offline cpu %d\n", i);
+ set_cpu_online_offline(i, 0);
}
}
}
+free_mask:
+ free_cpu_set(ctdp_level.core_cpumask);
}
}
@@ -1286,17 +1598,17 @@ static void set_tdp_level(int arg)
for_each_online_target_cpu_in_set(set_tdp_level_for_cpu, NULL,
NULL, NULL, NULL);
else
- for_each_online_package_in_set(set_tdp_level_for_cpu, NULL,
+ for_each_online_power_domain_in_set(set_tdp_level_for_cpu, NULL,
NULL, NULL, NULL);
isst_ctdp_display_information_end(outf);
}
-static void clx_n_dump_pbf_config_for_cpu(int cpu, void *arg1, void *arg2,
+static void clx_n_dump_pbf_config_for_cpu(struct isst_id *id, void *arg1, void *arg2,
void *arg3, void *arg4)
{
int ret;
- ret = clx_n_config(cpu);
+ ret = clx_n_config(id);
if (ret) {
isst_display_error_info_message(1, "clx_n_config failed", 0, 0);
} else {
@@ -1305,26 +1617,26 @@ static void clx_n_dump_pbf_config_for_cpu(int cpu, void *arg1, void *arg2,
ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
pbf_info = &ctdp_level->pbf_info;
- isst_pbf_display_information(cpu, outf, tdp_level, pbf_info);
+ isst_pbf_display_information(id, outf, tdp_level, pbf_info);
free_cpu_set(ctdp_level->core_cpumask);
free_cpu_set(pbf_info->core_cpumask);
}
}
-static void dump_pbf_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
+static void dump_pbf_config_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3,
void *arg4)
{
struct isst_pbf_info pbf_info;
int ret;
- ret = isst_get_pbf_info(cpu, tdp_level, &pbf_info);
+ ret = isst_get_pbf_info(id, tdp_level, &pbf_info);
if (ret) {
isst_display_error_info_message(1, "Failed to get base-freq info at this level", 1, tdp_level);
isst_ctdp_display_information_end(outf);
exit(1);
} else {
- isst_pbf_display_information(cpu, outf, tdp_level, &pbf_info);
- isst_get_pbf_info_complete(&pbf_info);
+ isst_pbf_display_information(id, outf, tdp_level, &pbf_info);
+ free_cpu_set(pbf_info.core_cpumask);
}
}
@@ -1355,17 +1667,17 @@ static void dump_pbf_config(int arg)
if (max_target_cpus)
for_each_online_target_cpu_in_set(fn, NULL, NULL, NULL, NULL);
else
- for_each_online_package_in_set(fn, NULL, NULL, NULL, NULL);
+ for_each_online_power_domain_in_set(fn, NULL, NULL, NULL, NULL);
isst_ctdp_display_information_end(outf);
}
-static int set_clos_param(int cpu, int clos, int epp, int wt, int min, int max)
+static int set_clos_param(struct isst_id *id, int clos, int epp, int wt, int min, int max)
{
struct isst_clos_config clos_config;
int ret;
- ret = isst_pm_get_clos(cpu, clos, &clos_config);
+ ret = isst_pm_get_clos(id, clos, &clos_config);
if (ret) {
isst_display_error_info_message(1, "isst_pm_get_clos failed", 0, 0);
return ret;
@@ -1374,7 +1686,7 @@ static int set_clos_param(int cpu, int clos, int epp, int wt, int min, int max)
clos_config.clos_max = max;
clos_config.epp = epp;
clos_config.clos_prop_prio = wt;
- ret = isst_set_clos(cpu, clos, &clos_config);
+ ret = isst_set_clos(id, clos, &clos_config);
if (ret) {
isst_display_error_info_message(1, "isst_set_clos failed", 0, 0);
return ret;
@@ -1411,14 +1723,39 @@ static int set_cpufreq_scaling_min_max(int cpu, int max, int freq)
return 0;
}
-static int set_clx_pbf_cpufreq_scaling_min_max(int cpu)
+static int no_turbo(void)
+{
+ return parse_int_file(0, "/sys/devices/system/cpu/intel_pstate/no_turbo");
+}
+
+static void adjust_scaling_max_from_base_freq(int cpu)
+{
+ int base_freq, scaling_max_freq;
+
+ scaling_max_freq = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu);
+ base_freq = get_cpufreq_base_freq(cpu);
+ if (scaling_max_freq < base_freq || no_turbo())
+ set_cpufreq_scaling_min_max(cpu, 1, base_freq);
+}
+
+static void adjust_scaling_min_from_base_freq(int cpu)
+{
+ int base_freq, scaling_min_freq;
+
+ scaling_min_freq = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu);
+ base_freq = get_cpufreq_base_freq(cpu);
+ if (scaling_min_freq < base_freq)
+ set_cpufreq_scaling_min_max(cpu, 0, base_freq);
+}
+
+static int set_clx_pbf_cpufreq_scaling_min_max(struct isst_id *id)
{
struct isst_pkg_ctdp_level_info *ctdp_level;
struct isst_pbf_info *pbf_info;
- int i, pkg_id, die_id, freq, freq_high, freq_low;
+ int i, freq, freq_high, freq_low;
int ret;
- ret = clx_n_config(cpu);
+ ret = clx_n_config(id);
if (ret) {
debug_printf("cpufreq_scaling_min_max failed for CLX");
return ret;
@@ -1429,11 +1766,8 @@ static int set_clx_pbf_cpufreq_scaling_min_max(int cpu)
freq_high = pbf_info->p1_high * 100000;
freq_low = pbf_info->p1_low * 100000;
- pkg_id = get_physical_package_id(cpu);
- die_id = get_physical_die_id(cpu);
for (i = 0; i < get_topo_max_cpus(); ++i) {
- if (pkg_id != get_physical_package_id(i) ||
- die_id != get_physical_die_id(i))
+ if (!is_cpu_in_power_domain(i, id))
continue;
if (CPU_ISSET_S(i, pbf_info->core_cpumask_size,
@@ -1485,6 +1819,7 @@ static int set_cpufreq_scaling_min_max_from_cpuinfo(int cpu, int cpuinfo_max, in
if (fd < 0)
return fd;
+ min_freq[15] = '\0';
len = strlen(min_freq);
ret = write(fd, min_freq, len);
if (ret == -1) {
@@ -1496,83 +1831,87 @@ static int set_cpufreq_scaling_min_max_from_cpuinfo(int cpu, int cpuinfo_max, in
return 0;
}
-static void set_scaling_min_to_cpuinfo_max(int cpu)
+static void set_scaling_min_to_cpuinfo_max(struct isst_id *id)
{
- int i, pkg_id, die_id;
+ int i;
+
+ if (id->cpu < 0)
+ return;
- pkg_id = get_physical_package_id(cpu);
- die_id = get_physical_die_id(cpu);
for (i = 0; i < get_topo_max_cpus(); ++i) {
- if (pkg_id != get_physical_package_id(i) ||
- die_id != get_physical_die_id(i))
+ if (!is_cpu_in_power_domain(i, id))
+ continue;
+
+ if (is_cpu_online(i) != 1)
continue;
+ adjust_scaling_max_from_base_freq(i);
set_cpufreq_scaling_min_max_from_cpuinfo(i, 1, 0);
+ adjust_scaling_min_from_base_freq(i);
}
}
-static void set_scaling_min_to_cpuinfo_min(int cpu)
+static void set_scaling_min_to_cpuinfo_min(struct isst_id *id)
{
- int i, pkg_id, die_id;
+ int i;
+
+ if (id->cpu < 0)
+ return;
- pkg_id = get_physical_package_id(cpu);
- die_id = get_physical_die_id(cpu);
for (i = 0; i < get_topo_max_cpus(); ++i) {
- if (pkg_id != get_physical_package_id(i) ||
- die_id != get_physical_die_id(i))
+ if (!is_cpu_in_power_domain(i, id))
+ continue;
+
+ if (is_cpu_online(i) != 1)
continue;
+ adjust_scaling_max_from_base_freq(i);
set_cpufreq_scaling_min_max_from_cpuinfo(i, 0, 0);
}
}
-static void set_scaling_max_to_cpuinfo_max(int cpu)
+static void set_scaling_max_to_cpuinfo_max(struct isst_id *id)
{
- int i, pkg_id, die_id;
+ int i;
- pkg_id = get_physical_package_id(cpu);
- die_id = get_physical_die_id(cpu);
for (i = 0; i < get_topo_max_cpus(); ++i) {
- if (pkg_id != get_physical_package_id(i) ||
- die_id != get_physical_die_id(i))
+ if (!is_cpu_in_power_domain(i, id))
continue;
set_cpufreq_scaling_min_max_from_cpuinfo(i, 1, 1);
}
}
-static int set_core_priority_and_min(int cpu, int mask_size,
+static int set_core_priority_and_min(struct isst_id *id, int mask_size,
cpu_set_t *cpu_mask, int min_high,
int min_low)
{
- int pkg_id, die_id, ret, i;
+ int ret, i;
if (!CPU_COUNT_S(mask_size, cpu_mask))
return -1;
- ret = set_clos_param(cpu, 0, 0, 0, min_high, 0xff);
+ ret = set_clos_param(id, 0, 0, 0, min_high, 0xff);
if (ret)
return ret;
- ret = set_clos_param(cpu, 1, 15, 15, min_low, 0xff);
+ ret = set_clos_param(id, 1, 15, 15, min_low, 0xff);
if (ret)
return ret;
- ret = set_clos_param(cpu, 2, 15, 15, min_low, 0xff);
+ ret = set_clos_param(id, 2, 15, 15, min_low, 0xff);
if (ret)
return ret;
- ret = set_clos_param(cpu, 3, 15, 15, min_low, 0xff);
+ ret = set_clos_param(id, 3, 15, 15, min_low, 0xff);
if (ret)
return ret;
- pkg_id = get_physical_package_id(cpu);
- die_id = get_physical_die_id(cpu);
for (i = 0; i < get_topo_max_cpus(); ++i) {
int clos;
+ struct isst_id tid;
- if (pkg_id != get_physical_package_id(i) ||
- die_id != get_physical_die_id(i))
+ if (!is_cpu_in_power_domain(i, id))
continue;
if (CPU_ISSET_S(i, mask_size, cpu_mask))
@@ -1581,7 +1920,8 @@ static int set_core_priority_and_min(int cpu, int mask_size,
clos = 3;
debug_printf("Associate cpu: %d clos: %d\n", i, clos);
- ret = isst_clos_associate(i, clos);
+ set_isst_id(&tid, i);
+ ret = isst_clos_associate(&tid, clos);
if (ret) {
isst_display_error_info_message(1, "isst_clos_associate failed", 0, 0);
return ret;
@@ -1591,20 +1931,23 @@ static int set_core_priority_and_min(int cpu, int mask_size,
return 0;
}
-static int set_pbf_core_power(int cpu)
+static int set_pbf_core_power(struct isst_id *id)
{
struct isst_pbf_info pbf_info;
struct isst_pkg_ctdp pkg_dev;
int ret;
- ret = isst_get_ctdp_levels(cpu, &pkg_dev);
+ if (id->cpu < 0)
+ return 0;
+
+ ret = isst_get_ctdp_levels(id, &pkg_dev);
if (ret) {
debug_printf("isst_get_ctdp_levels failed");
return ret;
}
debug_printf("Current_level: %d\n", pkg_dev.current_level);
- ret = isst_get_pbf_info(cpu, pkg_dev.current_level, &pbf_info);
+ ret = isst_get_pbf_info(id, pkg_dev.current_level, &pbf_info);
if (ret) {
debug_printf("isst_get_pbf_info failed");
return ret;
@@ -1612,7 +1955,7 @@ static int set_pbf_core_power(int cpu)
debug_printf("p1_high: %d p1_low: %d\n", pbf_info.p1_high,
pbf_info.p1_low);
- ret = set_core_priority_and_min(cpu, pbf_info.core_cpumask_size,
+ ret = set_core_priority_and_min(id, pbf_info.core_cpumask_size,
pbf_info.core_cpumask,
pbf_info.p1_high, pbf_info.p1_low);
if (ret) {
@@ -1620,7 +1963,7 @@ static int set_pbf_core_power(int cpu)
return ret;
}
- ret = isst_pm_qos_config(cpu, 1, 1);
+ ret = isst_pm_qos_config(id, 1, 1);
if (ret) {
debug_printf("isst_pm_qos_config failed");
return ret;
@@ -1629,7 +1972,7 @@ static int set_pbf_core_power(int cpu)
return 0;
}
-static void set_pbf_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
+static void set_pbf_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3,
void *arg4)
{
struct isst_pkg_ctdp_level_info ctdp_level;
@@ -1640,22 +1983,22 @@ static void set_pbf_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
if (is_clx_n_platform()) {
ret = 0;
if (status) {
- set_clx_pbf_cpufreq_scaling_min_max(cpu);
+ set_clx_pbf_cpufreq_scaling_min_max(id);
} else {
- set_scaling_max_to_cpuinfo_max(cpu);
- set_scaling_min_to_cpuinfo_min(cpu);
+ set_scaling_max_to_cpuinfo_max(id);
+ set_scaling_min_to_cpuinfo_min(id);
}
goto disp_result;
}
- ret = isst_get_ctdp_levels(cpu, &pkg_dev);
+ ret = isst_get_ctdp_levels(id, &pkg_dev);
if (ret) {
isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
goto disp_result;
}
- ret = isst_get_ctdp_control(cpu, pkg_dev.current_level, &ctdp_level);
+ ret = isst_get_ctdp_control(id, pkg_dev.current_level, &ctdp_level);
if (ret) {
isst_display_error_info_message(1, "Failed to get current level", 0, 0);
goto disp_result;
@@ -1668,34 +2011,34 @@ static void set_pbf_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
}
if (auto_mode && status) {
- ret = set_pbf_core_power(cpu);
+ ret = set_pbf_core_power(id);
if (ret)
goto disp_result;
}
- ret = isst_set_pbf_fact_status(cpu, 1, status);
+ ret = isst_set_pbf_fact_status(id, 1, status);
if (ret) {
debug_printf("isst_set_pbf_fact_status failed");
if (auto_mode)
- isst_pm_qos_config(cpu, 0, 0);
+ isst_pm_qos_config(id, 0, 0);
} else {
if (auto_mode) {
if (status)
- set_scaling_min_to_cpuinfo_max(cpu);
+ set_scaling_min_to_cpuinfo_max(id);
else
- set_scaling_min_to_cpuinfo_min(cpu);
+ set_scaling_min_to_cpuinfo_min(id);
}
}
if (auto_mode && !status)
- isst_pm_qos_config(cpu, 0, 1);
+ isst_pm_qos_config(id, 0, 1);
disp_result:
if (status)
- isst_display_result(cpu, outf, "base-freq", "enable",
+ isst_display_result(id, outf, "base-freq", "enable",
ret);
else
- isst_display_result(cpu, outf, "base-freq", "disable",
+ isst_display_result(id, outf, "base-freq", "disable",
ret);
}
@@ -1739,24 +2082,25 @@ static void set_pbf_enable(int arg)
for_each_online_target_cpu_in_set(set_pbf_for_cpu, NULL, NULL,
NULL, &enable);
else
- for_each_online_package_in_set(set_pbf_for_cpu, NULL, NULL,
+ for_each_online_power_domain_in_set(set_pbf_for_cpu, NULL, NULL,
NULL, &enable);
isst_ctdp_display_information_end(outf);
}
-static void dump_fact_config_for_cpu(int cpu, void *arg1, void *arg2,
+static void dump_fact_config_for_cpu(struct isst_id *id, void *arg1, void *arg2,
void *arg3, void *arg4)
{
struct isst_fact_info fact_info;
int ret;
- ret = isst_get_fact_info(cpu, tdp_level, fact_bucket, &fact_info);
+ memset(&fact_info, 0, sizeof(fact_info));
+ ret = isst_get_fact_info(id, tdp_level, fact_bucket, &fact_info);
if (ret) {
isst_display_error_info_message(1, "Failed to get turbo-freq info at this level", 1, tdp_level);
isst_ctdp_display_information_end(outf);
exit(1);
} else {
- isst_fact_display_information(cpu, outf, tdp_level, fact_bucket,
+ isst_fact_display_information(id, outf, tdp_level, fact_bucket,
fact_avx, &fact_info);
}
}
@@ -1785,12 +2129,12 @@ static void dump_fact_config(int arg)
for_each_online_target_cpu_in_set(dump_fact_config_for_cpu,
NULL, NULL, NULL, NULL);
else
- for_each_online_package_in_set(dump_fact_config_for_cpu, NULL,
+ for_each_online_power_domain_in_set(dump_fact_config_for_cpu, NULL,
NULL, NULL, NULL);
isst_ctdp_display_information_end(outf);
}
-static void set_fact_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
+static void set_fact_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3,
void *arg4)
{
struct isst_pkg_ctdp_level_info ctdp_level;
@@ -1798,13 +2142,19 @@ static void set_fact_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
int ret;
int status = *(int *)arg4;
- ret = isst_get_ctdp_levels(cpu, &pkg_dev);
+ if (status && no_turbo()) {
+ isst_display_error_info_message(1, "Turbo mode is disabled", 0, 0);
+ ret = -1;
+ goto disp_results;
+ }
+
+ ret = isst_get_ctdp_levels(id, &pkg_dev);
if (ret) {
isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
goto disp_results;
}
- ret = isst_get_ctdp_control(cpu, pkg_dev.current_level, &ctdp_level);
+ ret = isst_get_ctdp_control(id, pkg_dev.current_level, &ctdp_level);
if (ret) {
isst_display_error_info_message(1, "Failed to get current level", 0, 0);
goto disp_results;
@@ -1817,16 +2167,16 @@ static void set_fact_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
}
if (status) {
- ret = isst_pm_qos_config(cpu, 1, 1);
+ ret = isst_pm_qos_config(id, 1, 1);
if (ret)
goto disp_results;
}
- ret = isst_set_pbf_fact_status(cpu, 0, status);
+ ret = isst_set_pbf_fact_status(id, 0, status);
if (ret) {
debug_printf("isst_set_pbf_fact_status failed");
if (auto_mode)
- isst_pm_qos_config(cpu, 0, 0);
+ isst_pm_qos_config(id, 0, 0);
goto disp_results;
}
@@ -1835,38 +2185,39 @@ static void set_fact_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
if (status) {
struct isst_pkg_ctdp pkg_dev;
- ret = isst_get_ctdp_levels(cpu, &pkg_dev);
- if (!ret)
- ret = isst_set_trl(cpu, fact_trl);
+ ret = isst_get_ctdp_levels(id, &pkg_dev);
+ if (!ret && id->cpu >= 0)
+ ret = isst_set_trl(id, fact_trl);
if (ret && auto_mode)
- isst_pm_qos_config(cpu, 0, 0);
+ isst_pm_qos_config(id, 0, 0);
} else {
if (auto_mode)
- isst_pm_qos_config(cpu, 0, 0);
+ isst_pm_qos_config(id, 0, 0);
}
disp_results:
if (status) {
- isst_display_result(cpu, outf, "turbo-freq", "enable", ret);
+ isst_display_result(id, outf, "turbo-freq", "enable", ret);
if (ret)
fact_enable_fail = ret;
} else {
/* Since we modified TRL during Fact enable, restore it */
- isst_set_trl_from_current_tdp(cpu, fact_trl);
- isst_display_result(cpu, outf, "turbo-freq", "disable", ret);
+ isst_set_trl_from_current_tdp(id, fact_trl);
+ isst_display_result(id, outf, "turbo-freq", "disable", ret);
}
}
static void set_fact_enable(int arg)
{
int i, ret, enable = arg;
+ struct isst_id id;
if (cmd_help) {
if (enable) {
fprintf(stderr,
"Enable Intel Speed Select Technology Turbo frequency feature\n");
fprintf(stderr,
- "Optional: -t|--trl : Specify turbo ratio limit\n");
+ "Optional: -t|--trl : Specify turbo ratio limit in hex starting with 0x\n");
fprintf(stderr,
"\tOptional Arguments: -a|--auto : Designate specified target CPUs with");
fprintf(stderr,
@@ -1875,7 +2226,7 @@ static void set_fact_enable(int arg)
fprintf(stderr,
"Disable Intel Speed Select Technology turbo frequency feature\n");
fprintf(stderr,
- "Optional: -t|--trl : Specify turbo ratio limit\n");
+ "Optional: -t|--trl : Specify turbo ratio limit in hex starting with 0x\n");
fprintf(stderr,
"\tOptional Arguments: -a|--auto : Also disable core-power associations\n");
}
@@ -1887,9 +2238,8 @@ static void set_fact_enable(int arg)
for_each_online_target_cpu_in_set(set_fact_for_cpu, NULL, NULL,
NULL, &enable);
else
- for_each_online_package_in_set(set_fact_for_cpu, NULL, NULL,
+ for_each_online_power_domain_in_set(set_fact_for_cpu, NULL, NULL,
NULL, &enable);
- isst_ctdp_display_information_end(outf);
if (!fact_enable_fail && enable && auto_mode) {
/*
@@ -1917,6 +2267,7 @@ static void set_fact_enable(int arg)
if (len < 0)
continue;
+ sibling_list[127] = '\0';
cpu_str = strtok(sibling_list, ",");
while (cpu_str != NULL) {
int cpu;
@@ -1933,19 +2284,23 @@ static void set_fact_enable(int arg)
if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
continue;
- ret = set_clos_param(i, 0, 0, 0, 0, 0xff);
+ if (is_cpu_online(i) != 1)
+ continue;
+
+ set_isst_id(&id, i);
+ ret = set_clos_param(&id, 0, 0, 0, 0, 0xff);
if (ret)
goto error_disp;
- ret = set_clos_param(i, 1, 15, 15, 0, 0xff);
+ ret = set_clos_param(&id, 1, 15, 15, 0, 0xff);
if (ret)
goto error_disp;
- ret = set_clos_param(i, 2, 15, 15, 0, 0xff);
+ ret = set_clos_param(&id, 2, 15, 15, 0, 0xff);
if (ret)
goto error_disp;
- ret = set_clos_param(i, 3, 15, 15, 0, 0xff);
+ ret = set_clos_param(&id, 3, 15, 15, 0, 0xff);
if (ret)
goto error_disp;
@@ -1955,38 +2310,50 @@ static void set_fact_enable(int arg)
clos = 3;
debug_printf("Associate cpu: %d clos: %d\n", i, clos);
- ret = isst_clos_associate(i, clos);
+ ret = isst_clos_associate(&id, clos);
if (ret)
goto error_disp;
}
- isst_display_result(-1, outf, "turbo-freq --auto", "enable", 0);
+ set_isst_id(&id, -1);
+ isst_display_result(&id, outf, "turbo-freq --auto", "enable", 0);
}
+ isst_ctdp_display_information_end(outf);
+
return;
error_disp:
- isst_display_result(i, outf, "turbo-freq --auto", "enable", ret);
+ isst_display_result(&id, outf, "turbo-freq --auto", "enable", ret);
+ isst_ctdp_display_information_end(outf);
}
-static void enable_clos_qos_config(int cpu, void *arg1, void *arg2, void *arg3,
+static void enable_clos_qos_config(struct isst_id *id, void *arg1, void *arg2, void *arg3,
void *arg4)
{
int ret;
int status = *(int *)arg4;
+ int cp_state, cp_cap;
+
+ if (!isst_read_pm_config(id, &cp_state, &cp_cap)) {
+ if (!cp_cap) {
+ isst_display_error_info_message(1, "core-power not supported", 0, 0);
+ return;
+ }
+ }
if (is_skx_based_platform())
clos_priority_type = 1;
- ret = isst_pm_qos_config(cpu, status, clos_priority_type);
+ ret = isst_pm_qos_config(id, status, clos_priority_type);
if (ret)
isst_display_error_info_message(1, "isst_pm_qos_config failed", 0, 0);
if (status)
- isst_display_result(cpu, outf, "core-power", "enable",
+ isst_display_result(id, outf, "core-power", "enable",
ret);
else
- isst_display_result(cpu, outf, "core-power", "disable",
+ isst_display_result(id, outf, "core-power", "disable",
ret);
}
@@ -2020,22 +2387,22 @@ static void set_clos_enable(int arg)
for_each_online_target_cpu_in_set(enable_clos_qos_config, NULL,
NULL, NULL, &enable);
else
- for_each_online_package_in_set(enable_clos_qos_config, NULL,
+ for_each_online_power_domain_in_set(enable_clos_qos_config, NULL,
NULL, NULL, &enable);
isst_ctdp_display_information_end(outf);
}
-static void dump_clos_config_for_cpu(int cpu, void *arg1, void *arg2,
+static void dump_clos_config_for_cpu(struct isst_id *id, void *arg1, void *arg2,
void *arg3, void *arg4)
{
struct isst_clos_config clos_config;
int ret;
- ret = isst_pm_get_clos(cpu, current_clos, &clos_config);
+ ret = isst_pm_get_clos(id, current_clos, &clos_config);
if (ret)
isst_display_error_info_message(1, "isst_pm_get_clos failed", 0, 0);
else
- isst_clos_display_information(cpu, outf, current_clos,
+ isst_clos_display_information(id, outf, current_clos,
&clos_config);
}
@@ -2059,24 +2426,24 @@ static void dump_clos_config(int arg)
for_each_online_target_cpu_in_set(dump_clos_config_for_cpu,
NULL, NULL, NULL, NULL);
else
- for_each_online_package_in_set(dump_clos_config_for_cpu, NULL,
+ for_each_online_power_domain_in_set(dump_clos_config_for_cpu, NULL,
NULL, NULL, NULL);
isst_ctdp_display_information_end(outf);
}
-static void get_clos_info_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
+static void get_clos_info_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3,
void *arg4)
{
int enable, ret, prio_type;
- ret = isst_clos_get_clos_information(cpu, &enable, &prio_type);
+ ret = isst_clos_get_clos_information(id, &enable, &prio_type);
if (ret)
isst_display_error_info_message(1, "isst_clos_get_info failed", 0, 0);
else {
int cp_state, cp_cap;
- isst_read_pm_config(cpu, &cp_state, &cp_cap);
- isst_clos_display_clos_information(cpu, outf, enable, prio_type,
+ isst_read_pm_config(id, &cp_state, &cp_cap);
+ isst_clos_display_clos_information(id, outf, enable, prio_type,
cp_state, cp_cap);
}
}
@@ -2095,31 +2462,31 @@ static void dump_clos_info(int arg)
for_each_online_target_cpu_in_set(get_clos_info_for_cpu, NULL,
NULL, NULL, NULL);
else
- for_each_online_package_in_set(get_clos_info_for_cpu, NULL,
+ for_each_online_power_domain_in_set(get_clos_info_for_cpu, NULL,
NULL, NULL, NULL);
isst_ctdp_display_information_end(outf);
}
-static void set_clos_config_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
+static void set_clos_config_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3,
void *arg4)
{
struct isst_clos_config clos_config;
int ret;
- clos_config.pkg_id = get_physical_package_id(cpu);
- clos_config.die_id = get_physical_die_id(cpu);
+ if (id->cpu < 0)
+ return;
clos_config.epp = clos_epp;
clos_config.clos_prop_prio = clos_prop_prio;
clos_config.clos_min = clos_min;
clos_config.clos_max = clos_max;
clos_config.clos_desired = clos_desired;
- ret = isst_set_clos(cpu, current_clos, &clos_config);
+ ret = isst_set_clos(id, current_clos, &clos_config);
if (ret)
isst_display_error_info_message(1, "isst_set_clos failed", 0, 0);
else
- isst_display_result(cpu, outf, "core-power", "config", ret);
+ isst_display_result(id, outf, "core-power", "config", ret);
}
static void set_clos_config(int arg)
@@ -2170,21 +2537,21 @@ static void set_clos_config(int arg)
for_each_online_target_cpu_in_set(set_clos_config_for_cpu, NULL,
NULL, NULL, NULL);
else
- for_each_online_package_in_set(set_clos_config_for_cpu, NULL,
+ for_each_online_power_domain_in_set(set_clos_config_for_cpu, NULL,
NULL, NULL, NULL);
isst_ctdp_display_information_end(outf);
}
-static void set_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
+static void set_clos_assoc_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3,
void *arg4)
{
int ret;
- ret = isst_clos_associate(cpu, current_clos);
+ ret = isst_clos_associate(id, current_clos);
if (ret)
debug_printf("isst_clos_associate failed");
else
- isst_display_result(cpu, outf, "core-power", "assoc", ret);
+ isst_display_result(id, outf, "core-power", "assoc", ret);
}
static void set_clos_assoc(int arg)
@@ -2204,24 +2571,28 @@ static void set_clos_assoc(int arg)
isst_display_error_info_message(1, "Invalid clos id\n", 0, 0);
exit(0);
}
+
+ isst_ctdp_display_information_start(outf);
+
if (max_target_cpus)
for_each_online_target_cpu_in_set(set_clos_assoc_for_cpu, NULL,
NULL, NULL, NULL);
else {
isst_display_error_info_message(1, "Invalid target cpu. Specify with [-c|--cpu]", 0, 0);
}
+ isst_ctdp_display_information_end(outf);
}
-static void get_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
+static void get_clos_assoc_for_cpu(struct isst_id *id, void *arg1, void *arg2, void *arg3,
void *arg4)
{
int clos, ret;
- ret = isst_clos_get_assoc_status(cpu, &clos);
+ ret = isst_clos_get_assoc_status(id, &clos);
if (ret)
isst_display_error_info_message(1, "isst_clos_get_assoc_status failed", 0, 0);
else
- isst_clos_display_assoc_information(cpu, outf, clos);
+ isst_clos_display_assoc_information(id, outf, clos);
}
static void get_clos_assoc(int arg)
@@ -2243,6 +2614,108 @@ static void get_clos_assoc(int arg)
isst_ctdp_display_information_end(outf);
}
+static void set_turbo_mode_for_cpu(struct isst_id *id, int status)
+{
+ int base_freq;
+
+ if (status) {
+ base_freq = get_cpufreq_base_freq(id->cpu);
+ set_cpufreq_scaling_min_max(id->cpu, 1, base_freq);
+ } else {
+ set_scaling_max_to_cpuinfo_max(id);
+ }
+
+ if (status) {
+ isst_display_result(id, outf, "turbo-mode", "disable", 0);
+ } else {
+ isst_display_result(id, outf, "turbo-mode", "enable", 0);
+ }
+}
+
+static void set_turbo_mode(int arg)
+{
+ int i, disable = arg;
+ struct isst_id id;
+
+ if (cmd_help) {
+ if (disable)
+ fprintf(stderr, "Set turbo mode disable\n");
+ else
+ fprintf(stderr, "Set turbo mode enable\n");
+ exit(0);
+ }
+
+ isst_ctdp_display_information_start(outf);
+
+ for (i = 0; i < topo_max_cpus; ++i) {
+ int online;
+
+ if (i)
+ online = parse_int_file(
+ 1, "/sys/devices/system/cpu/cpu%d/online", i);
+ else
+ online =
+ 1; /* online entry for CPU 0 needs some special configs */
+
+ if (online) {
+ set_isst_id(&id, i);
+ set_turbo_mode_for_cpu(&id, disable);
+ }
+
+ }
+ isst_ctdp_display_information_end(outf);
+}
+
+static void get_set_trl(struct isst_id *id, void *arg1, void *arg2, void *arg3,
+ void *arg4)
+{
+ unsigned long long trl;
+ int set = *(int *)arg4;
+ int ret;
+
+ if (id->cpu < 0)
+ return;
+
+ if (set && !fact_trl) {
+ isst_display_error_info_message(1, "Invalid TRL. Specify with [-t|--trl]", 0, 0);
+ exit(0);
+ }
+
+ if (set) {
+ ret = isst_set_trl(id, fact_trl);
+ isst_display_result(id, outf, "turbo-mode", "set-trl", ret);
+ return;
+ }
+
+ ret = isst_get_trl(id, &trl);
+ if (ret)
+ isst_display_result(id, outf, "turbo-mode", "get-trl", ret);
+ else
+ isst_trl_display_information(id, outf, trl);
+}
+
+static void process_trl(int arg)
+{
+ if (cmd_help) {
+ if (arg) {
+ fprintf(stderr, "Set TRL (turbo ratio limits)\n");
+ fprintf(stderr, "\t t|--trl: Specify turbo ratio limit for setting TRL in hex starting with 0x\n");
+ } else {
+ fprintf(stderr, "Get TRL (turbo ratio limits)\n");
+ }
+ exit(0);
+ }
+
+ isst_ctdp_display_information_start(outf);
+ if (max_target_cpus)
+ for_each_online_target_cpu_in_set(get_set_trl, NULL,
+ NULL, NULL, &arg);
+ else
+ for_each_online_power_domain_in_set(get_set_trl, NULL,
+ NULL, NULL, &arg);
+ isst_ctdp_display_information_end(outf);
+}
+
static struct process_cmd_struct clx_n_cmds[] = {
{ "perf-profile", "info", dump_isst_config, 0 },
{ "base-freq", "info", dump_pbf_config, 0 },
@@ -2273,6 +2746,10 @@ static struct process_cmd_struct isst_cmds[] = {
{ "core-power", "get-config", dump_clos_config, 0 },
{ "core-power", "assoc", set_clos_assoc, 0 },
{ "core-power", "get-assoc", get_clos_assoc, 0 },
+ { "turbo-mode", "enable", set_turbo_mode, 0 },
+ { "turbo-mode", "disable", set_turbo_mode, 1 },
+ { "turbo-mode", "get-trl", process_trl, 0 },
+ { "turbo-mode", "set-trl", process_trl, 1 },
{ NULL, NULL, NULL }
};
@@ -2282,10 +2759,11 @@ static struct process_cmd_struct isst_cmds[] = {
*/
void parse_cpu_command(char *optarg)
{
- unsigned int start, end;
+ unsigned int start, end, invalid_count;
char *next;
next = optarg;
+ invalid_count = 0;
while (next && *next) {
if (*next == '-') /* no negative cpu numbers */
@@ -2295,6 +2773,8 @@ void parse_cpu_command(char *optarg)
if (max_target_cpus < MAX_CPUS_IN_ONE_REQ)
target_cpus[max_target_cpus++] = start;
+ else
+ invalid_count = 1;
if (*next == '\0')
break;
@@ -2321,6 +2801,8 @@ void parse_cpu_command(char *optarg)
while (++start <= end) {
if (max_target_cpus < MAX_CPUS_IN_ONE_REQ)
target_cpus[max_target_cpus++] = start;
+ else
+ invalid_count = 1;
}
if (*next == ',')
@@ -2329,6 +2811,13 @@ void parse_cpu_command(char *optarg)
goto error;
}
+ if (invalid_count) {
+ isst_ctdp_display_information_start(outf);
+ isst_display_error_info_message(1, "Too many CPUs in one request: max is", 1, MAX_CPUS_IN_ONE_REQ - 1);
+ isst_ctdp_display_information_end(outf);
+ exit(-1);
+ }
+
#ifdef DEBUG
{
int i;
@@ -2344,6 +2833,43 @@ error:
exit(-1);
}
+static void check_optarg(char *option, int hex)
+{
+ if (optarg) {
+ char *start = optarg;
+ int i;
+
+ if (hex && strlen(optarg) < 3) {
+ /* At least 0x plus one character must be present */
+ fprintf(stderr, "malformed arguments for:%s [%s]\n", option, optarg);
+ exit(0);
+ }
+
+ if (hex) {
+ if (optarg[0] != '0' || tolower(optarg[1]) != 'x') {
+ fprintf(stderr, "malformed arguments for:%s [%s]\n",
+ option, optarg);
+ exit(0);
+ }
+ start = &optarg[2];
+ }
+
+ for (i = 0; i < strlen(start); ++i) {
+ if (hex) {
+ if (!isxdigit(start[i])) {
+ fprintf(stderr, "malformed arguments for:%s [%s]\n",
+ option, optarg);
+ exit(0);
+ }
+ } else if (!isdigit(start[i])) {
+ fprintf(stderr, "malformed arguments for:%s [%s]\n",
+ option, optarg);
+ exit(0);
+ }
+ }
+ }
+}
+
static void parse_cmd_args(int argc, int start, char **argv)
{
int opt;
@@ -2377,18 +2903,21 @@ static void parse_cmd_args(int argc, int start, char **argv)
auto_mode = 1;
break;
case 'b':
+ check_optarg("bucket", 0);
fact_bucket = atoi(optarg);
break;
case 'h':
cmd_help = 1;
break;
case 'l':
+ check_optarg("level", 0);
tdp_level = atoi(optarg);
break;
case 'o':
force_online_offline = 1;
break;
case 't':
+ check_optarg("trl", 1);
sscanf(optarg, "0x%llx", &fact_trl);
break;
case 'r':
@@ -2405,13 +2934,16 @@ static void parse_cmd_args(int argc, int start, char **argv)
break;
/* CLOS related */
case 'c':
+ check_optarg("clos", 0);
current_clos = atoi(optarg);
break;
case 'd':
+ check_optarg("desired", 0);
clos_desired = atoi(optarg);
- clos_desired /= DISP_FREQ_MULTIPLIER;
+ clos_desired /= isst_get_disp_freq_multiplier();
break;
case 'e':
+ check_optarg("epp", 0);
clos_epp = atoi(optarg);
if (is_skx_based_platform()) {
isst_display_error_info_message(1, "epp can't be specified on this platform", 0, 0);
@@ -2419,14 +2951,17 @@ static void parse_cmd_args(int argc, int start, char **argv)
}
break;
case 'n':
+ check_optarg("min", 0);
clos_min = atoi(optarg);
- clos_min /= DISP_FREQ_MULTIPLIER;
+ clos_min /= isst_get_disp_freq_multiplier();
break;
case 'm':
+ check_optarg("max", 0);
clos_max = atoi(optarg);
- clos_max /= DISP_FREQ_MULTIPLIER;
+ clos_max /= isst_get_disp_freq_multiplier();
break;
case 'p':
+ check_optarg("priority", 0);
clos_priority_type = atoi(optarg);
if (is_skx_based_platform() && !clos_priority_type) {
isst_display_error_info_message(1, "Invalid clos priority type: proportional for this platform", 0, 0);
@@ -2434,6 +2969,7 @@ static void parse_cmd_args(int argc, int start, char **argv)
}
break;
case 'w':
+ check_optarg("weight", 0);
clos_prop_prio = atoi(optarg);
if (is_skx_based_platform()) {
isst_display_error_info_message(1, "weight can't be specified on this platform", 0, 0);
@@ -2488,6 +3024,16 @@ static void fact_help(void)
printf("\tcommand : disable\n");
}
+static void turbo_mode_help(void)
+{
+ 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");
+ printf("\tcommand : enable\n");
+ printf("\tcommand : disable\n");
+ printf("\tcommand : get-trl\n");
+ printf("\tcommand : set-trl\n");
+}
+
+
static void core_power_help(void)
{
printf("core-power:\tInterface that allows user to define per core/tile\n\
@@ -2512,6 +3058,7 @@ static struct process_cmd_help_struct isst_help_cmds[] = {
{ "base-freq", pbf_help },
{ "turbo-freq", fact_help },
{ "core-power", core_power_help },
+ { "turbo-mode", turbo_mode_help },
{ NULL, NULL }
};
@@ -2543,9 +3090,6 @@ void process_command(int argc, char **argv,
}
}
- if (!is_clx_n_platform())
- create_cpu_map();
-
i = 0;
while (cmds[i].feature) {
if (!strcmp(cmds[i].feature, feature) &&
@@ -2575,7 +3119,7 @@ static void usage(void)
if (is_clx_n_platform())
printf("\nFEATURE : [perf-profile|base-freq]\n");
else
- printf("\nFEATURE : [perf-profile|base-freq|turbo-freq|core-power]\n");
+ printf("\nFEATURE : [perf-profile|base-freq|turbo-freq|core-power|turbo-mode]\n");
printf("\nFor help on each feature, use -h|--help\n");
printf("\tFor example: intel-speed-select perf-profile -h\n");
@@ -2591,10 +3135,17 @@ static void usage(void)
printf("\t[-f|--format] : output format [json|text]. Default: text\n");
printf("\t[-h|--help] : Print help\n");
printf("\t[-i|--info] : Print platform information\n");
+ printf("\t[-a|--all-cpus-online] : Force online every CPU in the system\n");
printf("\t[-o|--out] : Output file\n");
printf("\t\t\tDefault : stderr\n");
+ printf("\t[-p|--pause] : Delay between two mail box commands in milliseconds\n");
+ printf("\t[-r|--retry] : Retry count for mail box commands on failure, default 3\n");
printf("\t[-v|--version] : Print version\n");
-
+ printf("\t[-b|--oob : Start a daemon to process HFI events for perf profile change from Out of Band agent.\n");
+ printf("\t[-n|--no-daemon : Don't run as daemon. By default --oob will turn on daemon mode\n");
+ printf("\t[-w|--delay : Delay for reading config level state change in OOB poll mode.\n");
+ printf("\t[-g|--cgroupv2 : Try to use cgroup v2 CPU isolation instead of CPU online/offline.\n");
+ printf("\t[-u|--cpu0-workaround : Don't try to online/offline CPU0 instead use cgroup v2.\n");
printf("\nResult format\n");
printf("\tResult display uses a common format for each command:\n");
printf("\tResults are formatted in text/JSON with\n");
@@ -2617,26 +3168,38 @@ static void usage(void)
static void print_version(void)
{
fprintf(outf, "Version %s\n", version_str);
- fprintf(outf, "Build date %s time %s\n", __DATE__, __TIME__);
exit(0);
}
static void cmdline(int argc, char **argv)
{
const char *pathname = "/dev/isst_interface";
+ char *ptr;
FILE *fp;
- int opt;
+ int opt, force_cpus_online = 0;
int option_index = 0;
int ret;
+ int oob_mode = 0;
+ int poll_interval = -1;
+ int no_daemon = 0;
+ int mbox_delay = 0, mbox_retries = 3;
static struct option long_options[] = {
+ { "all-cpus-online", no_argument, 0, 'a' },
{ "cpu", required_argument, 0, 'c' },
{ "debug", no_argument, 0, 'd' },
{ "format", required_argument, 0, 'f' },
{ "help", no_argument, 0, 'h' },
{ "info", no_argument, 0, 'i' },
+ { "pause", required_argument, 0, 'p' },
{ "out", required_argument, 0, 'o' },
+ { "retry", required_argument, 0, 'r' },
{ "version", no_argument, 0, 'v' },
+ { "oob", no_argument, 0, 'b' },
+ { "no-daemon", no_argument, 0, 'n' },
+ { "poll-interval", required_argument, 0, 'w' },
+ { "cgroupv2", required_argument, 0, 'g' },
+ { "cpu0-workaround", required_argument, 0, 'u' },
{ 0, 0, 0, 0 }
};
@@ -2662,10 +3225,17 @@ static void cmdline(int argc, char **argv)
fclose(fp);
}
+ ret = isst_fill_platform_info();
+ if (ret)
+ goto out;
+
progname = argv[0];
- while ((opt = getopt_long_only(argc, argv, "+c:df:hio:v", long_options,
+ while ((opt = getopt_long_only(argc, argv, "+c:df:hio:vabw:ngu", long_options,
&option_index)) != -1) {
switch (opt) {
+ case 'a':
+ force_cpus_online = 1;
+ break;
case 'c':
parse_cpu_command(optarg);
break;
@@ -2688,27 +3258,73 @@ static void cmdline(int argc, char **argv)
fclose(outf);
outf = fopen_or_exit(optarg, "w");
break;
+ case 'p':
+ ret = strtol(optarg, &ptr, 10);
+ if (!ret)
+ fprintf(stderr, "Invalid pause interval, ignore\n");
+ else
+ mbox_delay = ret;
+ break;
+ case 'r':
+ ret = strtol(optarg, &ptr, 10);
+ if (!ret)
+ fprintf(stderr, "Invalid retry count, ignore\n");
+ else
+ mbox_retries = ret;
+ break;
case 'v':
print_version();
break;
+ case 'b':
+ oob_mode = 1;
+ break;
+ case 'n':
+ no_daemon = 1;
+ break;
+ case 'w':
+ ret = strtol(optarg, &ptr, 10);
+ if (!ret) {
+ fprintf(stderr, "Invalid poll interval count\n");
+ exit(0);
+ }
+ poll_interval = ret;
+ break;
+ case 'g':
+ cgroupv2 = 1;
+ break;
+ case 'u':
+ cpu_0_cgroupv2 = 1;
+ break;
default:
usage();
}
}
- if (optind > (argc - 2)) {
+ if (optind > (argc - 2) && !oob_mode) {
usage();
exit(0);
}
+
+ isst_update_platform_param(ISST_PARAM_MBOX_DELAY, mbox_delay);
+ isst_update_platform_param(ISST_PARAM_MBOX_RETRIES, mbox_retries);
+
set_max_cpu_num();
+ if (force_cpus_online)
+ force_all_cpus_online();
store_cpu_topology();
- set_cpu_present_cpu_mask();
- set_cpu_target_cpu_mask();
+ create_cpu_map();
- if (!is_clx_n_platform()) {
- ret = isst_fill_platform_info();
+ if (oob_mode) {
+ if (debug_flag)
+ fprintf(stderr, "OOB mode is enabled in debug mode\n");
+
+ ret = isst_daemon(debug_flag, poll_interval, no_daemon);
if (ret)
- goto out;
+ fprintf(stderr, "OOB mode enable failed\n");
+ goto out;
+ }
+
+ if (!is_clx_n_platform()) {
process_command(argc, argv, isst_help_cmds, isst_cmds);
} else {
process_command(argc, argv, clx_n_help_cmds, clx_n_cmds);
diff --git a/tools/power/x86/intel-speed-select/isst-core-mbox.c b/tools/power/x86/intel-speed-select/isst-core-mbox.c
new file mode 100644
index 000000000000..c81ecd602bcf
--- /dev/null
+++ b/tools/power/x86/intel-speed-select/isst-core-mbox.c
@@ -0,0 +1,1067 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel Speed Select -- Enumerate and control features for Mailbox Interface
+ * Copyright (c) 2023 Intel Corporation.
+ */
+#include "isst.h"
+
+static int mbox_delay;
+static int mbox_retries = 3;
+
+#define MAX_TRL_LEVELS_EMR 5
+
+static int mbox_get_disp_freq_multiplier(void)
+{
+ return DISP_FREQ_MULTIPLIER;
+}
+
+static int mbox_get_trl_max_levels(void)
+{
+ if (is_emr_platform())
+ return MAX_TRL_LEVELS_EMR;
+
+ return 3;
+}
+
+static char *mbox_get_trl_level_name(int level)
+{
+ if (is_emr_platform()) {
+ static char level_str[18];
+
+ if (level >= MAX_TRL_LEVELS_EMR)
+ return NULL;
+
+ snprintf(level_str, sizeof(level_str), "level-%d", level);
+ return level_str;
+ }
+
+ switch (level) {
+ case 0:
+ return "sse";
+ case 1:
+ return "avx2";
+ case 2:
+ return "avx512";
+ default:
+ return NULL;
+ }
+}
+
+static void mbox_update_platform_param(enum isst_platform_param param, int value)
+{
+ switch (param) {
+ case ISST_PARAM_MBOX_DELAY:
+ mbox_delay = value;
+ break;
+ case ISST_PARAM_MBOX_RETRIES:
+ mbox_retries = value;
+ break;
+ default:
+ break;
+ }
+}
+
+static int mbox_is_punit_valid(struct isst_id *id)
+{
+ if (id->cpu < 0)
+ return 0;
+
+ if (id->pkg < 0 || id->die < 0 || id->punit)
+ return 0;
+
+ return 1;
+}
+
+static int _send_mmio_command(unsigned int cpu, unsigned int reg, int write,
+ unsigned int *value)
+{
+ struct isst_if_io_regs io_regs;
+ const char *pathname = "/dev/isst_interface";
+ int cmd;
+ FILE *outf = get_output_file();
+ int fd;
+
+ debug_printf("mmio_cmd cpu:%d reg:%d write:%d\n", cpu, reg, write);
+
+ fd = open(pathname, O_RDWR);
+ if (fd < 0)
+ err(-1, "%s open failed", pathname);
+
+ io_regs.req_count = 1;
+ io_regs.io_reg[0].logical_cpu = cpu;
+ io_regs.io_reg[0].reg = reg;
+ cmd = ISST_IF_IO_CMD;
+ if (write) {
+ io_regs.io_reg[0].read_write = 1;
+ io_regs.io_reg[0].value = *value;
+ } else {
+ io_regs.io_reg[0].read_write = 0;
+ }
+
+ if (ioctl(fd, cmd, &io_regs) == -1) {
+ if (errno == ENOTTY) {
+ perror("ISST_IF_IO_COMMAND\n");
+ fprintf(stderr, "Check presence of kernel modules: isst_if_mmio\n");
+ exit(0);
+ }
+ fprintf(outf, "Error: mmio_cmd cpu:%d reg:%x read_write:%x\n",
+ cpu, reg, write);
+ } else {
+ if (!write)
+ *value = io_regs.io_reg[0].value;
+
+ debug_printf(
+ "mmio_cmd response: cpu:%d reg:%x rd_write:%x resp:%x\n",
+ cpu, reg, write, *value);
+ }
+
+ close(fd);
+
+ return 0;
+}
+
+int _send_mbox_command(unsigned int cpu, unsigned char command,
+ unsigned char sub_command, unsigned int parameter,
+ unsigned int req_data, unsigned int *resp)
+{
+ const char *pathname = "/dev/isst_interface";
+ int fd, retry;
+ struct isst_if_mbox_cmds mbox_cmds = { 0 };
+
+ debug_printf(
+ "mbox_send: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n",
+ cpu, command, sub_command, parameter, req_data);
+
+ if (!is_skx_based_platform() && command == CONFIG_CLOS &&
+ sub_command != CLOS_PM_QOS_CONFIG) {
+ unsigned int value;
+ int write = 0;
+ int clos_id, core_id, ret = 0;
+
+ debug_printf("CPU %d\n", cpu);
+
+ if (parameter & BIT(MBOX_CMD_WRITE_BIT)) {
+ value = req_data;
+ write = 1;
+ }
+
+ switch (sub_command) {
+ case CLOS_PQR_ASSOC:
+ core_id = parameter & 0xff;
+ ret = _send_mmio_command(
+ cpu, PQR_ASSOC_OFFSET + core_id * 4, write,
+ &value);
+ if (!ret && !write)
+ *resp = value;
+ break;
+ case CLOS_PM_CLOS:
+ clos_id = parameter & 0x03;
+ ret = _send_mmio_command(
+ cpu, PM_CLOS_OFFSET + clos_id * 4, write,
+ &value);
+ if (!ret && !write)
+ *resp = value;
+ break;
+ case CLOS_STATUS:
+ break;
+ default:
+ break;
+ }
+ return ret;
+ }
+
+ mbox_cmds.cmd_count = 1;
+ mbox_cmds.mbox_cmd[0].logical_cpu = cpu;
+ mbox_cmds.mbox_cmd[0].command = command;
+ mbox_cmds.mbox_cmd[0].sub_command = sub_command;
+ mbox_cmds.mbox_cmd[0].parameter = parameter;
+ mbox_cmds.mbox_cmd[0].req_data = req_data;
+
+ if (mbox_delay)
+ usleep(mbox_delay * 1000);
+
+ fd = open(pathname, O_RDWR);
+ if (fd < 0)
+ err(-1, "%s open failed", pathname);
+
+ retry = mbox_retries;
+ do {
+ if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) {
+ if (errno == ENOTTY) {
+ perror("ISST_IF_MBOX_COMMAND\n");
+ fprintf(stderr, "Check presence of kernel modules: isst_if_mbox_pci or isst_if_mbox_msr\n");
+ exit(0);
+ }
+ debug_printf(
+ "Error: mbox_cmd cpu:%d command:%x sub_command:%x parameter:%x req_data:%x errorno:%d\n",
+ cpu, command, sub_command, parameter, req_data, errno);
+ --retry;
+ } else {
+ *resp = mbox_cmds.mbox_cmd[0].resp_data;
+ debug_printf(
+ "mbox_cmd response: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x resp:%x\n",
+ cpu, command, sub_command, parameter, req_data, *resp);
+ break;
+ }
+ } while (retry);
+
+ close(fd);
+
+ if (!retry) {
+ debug_printf("Failed mbox command even after retries\n");
+ return -1;
+
+ }
+
+ return 0;
+}
+
+static int mbox_read_pm_config(struct isst_id *id, int *cp_state, int *cp_cap)
+{
+ unsigned int resp;
+ int ret;
+
+ ret = _send_mbox_command(id->cpu, READ_PM_CONFIG, PM_FEATURE, 0, 0,
+ &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d READ_PM_CONFIG resp:%x\n", id->cpu, resp);
+
+ *cp_state = resp & BIT(16);
+ *cp_cap = resp & BIT(0) ? 1 : 0;
+
+ return 0;
+}
+
+static int mbox_get_config_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)
+{
+ unsigned int resp;
+ int ret;
+
+ ret = _send_mbox_command(id->cpu, CONFIG_TDP,
+ CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp);
+ if (ret) {
+ pkg_dev->levels = 0;
+ pkg_dev->locked = 1;
+ pkg_dev->current_level = 0;
+ pkg_dev->version = 0;
+ pkg_dev->enabled = 0;
+ return 0;
+ }
+
+ debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", id->cpu, resp);
+
+ pkg_dev->version = resp & 0xff;
+ pkg_dev->levels = (resp >> 8) & 0xff;
+ pkg_dev->current_level = (resp >> 16) & 0xff;
+ pkg_dev->locked = !!(resp & BIT(24));
+ pkg_dev->enabled = !!(resp & BIT(31));
+
+ return 0;
+}
+
+static int mbox_get_ctdp_control(struct isst_id *id, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ int cp_state, cp_cap;
+ unsigned int resp;
+ int ret;
+
+ ret = _send_mbox_command(id->cpu, CONFIG_TDP,
+ CONFIG_TDP_GET_TDP_CONTROL, 0,
+ config_index, &resp);
+ if (ret)
+ return ret;
+
+ ctdp_level->fact_support = resp & BIT(0);
+ ctdp_level->pbf_support = !!(resp & BIT(1));
+ ctdp_level->fact_enabled = !!(resp & BIT(16));
+ ctdp_level->pbf_enabled = !!(resp & BIT(17));
+
+ ret = isst_read_pm_config(id, &cp_state, &cp_cap);
+ if (ret) {
+ debug_printf("cpu:%d pm_config is not supported\n", id->cpu);
+ } else {
+ debug_printf("cpu:%d pm_config SST-CP state:%d cap:%d\n", id->cpu, cp_state, cp_cap);
+ ctdp_level->sst_cp_support = cp_cap;
+ ctdp_level->sst_cp_enabled = cp_state;
+ }
+
+ debug_printf(
+ "cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
+ id->cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support,
+ ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
+
+ return 0;
+}
+
+static void _get_uncore_p0_p1_info(struct isst_id *id, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ unsigned int resp;
+ int ret;
+
+ ctdp_level->uncore_pm = 0;
+ ctdp_level->uncore_p0 = 0;
+ ctdp_level->uncore_p1 = 0;
+
+ ret = _send_mbox_command(id->cpu, CONFIG_TDP,
+ CONFIG_TDP_GET_RATIO_INFO, 0,
+ (BIT(16) | config_index) , &resp);
+ if (ret) {
+ goto try_uncore_mbox;
+ }
+
+ ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
+ ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
+ ctdp_level->uncore_pm = (resp & GENMASK(31, 24)) >> 24;
+
+ debug_printf(
+ "cpu:%d ctdp:%d CONFIG_TDP_GET_RATIO_INFO resp:%x uncore p0:%d uncore p1:%d uncore pm:%d\n",
+ id->cpu, config_index, resp, ctdp_level->uncore_p0, ctdp_level->uncore_p1,
+ ctdp_level->uncore_pm);
+
+ return;
+
+try_uncore_mbox:
+ ret = _send_mbox_command(id->cpu, CONFIG_TDP,
+ CONFIG_TDP_GET_UNCORE_P0_P1_INFO, 0,
+ config_index, &resp);
+ if (ret) {
+ ctdp_level->uncore_p0 = 0;
+ ctdp_level->uncore_p1 = 0;
+ return;
+ }
+
+ ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
+ ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
+ debug_printf(
+ "cpu:%d ctdp:%d CONFIG_TDP_GET_UNCORE_P0_P1_INFO resp:%x uncore p0:%d uncore p1:%d\n",
+ id->cpu, config_index, resp, ctdp_level->uncore_p0,
+ ctdp_level->uncore_p1);
+}
+
+static int _set_uncore_min_max(struct isst_id *id, int max, int freq)
+{
+ char buffer[128], freq_str[16];
+ int fd, ret, len;
+
+ if (max)
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d/max_freq_khz", id->pkg, id->die);
+ else
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d/min_freq_khz", id->pkg, id->die);
+
+ fd = open(buffer, O_WRONLY);
+ if (fd < 0)
+ return fd;
+
+ snprintf(freq_str, sizeof(freq_str), "%d", freq);
+ len = strlen(freq_str);
+ ret = write(fd, freq_str, len);
+ if (ret == -1) {
+ close(fd);
+ return ret;
+ }
+ close(fd);
+
+ return 0;
+}
+
+static void mbox_adjust_uncore_freq(struct isst_id *id, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ _get_uncore_p0_p1_info(id, config_index, ctdp_level);
+ if (ctdp_level->uncore_pm)
+ _set_uncore_min_max(id, 0, ctdp_level->uncore_pm * 100000);
+
+ if (ctdp_level->uncore_p0)
+ _set_uncore_min_max(id, 1, ctdp_level->uncore_p0 * 100000);
+}
+
+static void _get_p1_info(struct isst_id *id, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ unsigned int resp;
+ int ret;
+ ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_P1_INFO, 0,
+ config_index, &resp);
+ if (ret) {
+ ctdp_level->sse_p1 = 0;
+ ctdp_level->avx2_p1 = 0;
+ ctdp_level->avx512_p1 = 0;
+ return;
+ }
+
+ ctdp_level->sse_p1 = resp & GENMASK(7, 0);
+ ctdp_level->avx2_p1 = (resp & GENMASK(15, 8)) >> 8;
+ ctdp_level->avx512_p1 = (resp & GENMASK(23, 16)) >> 16;
+ ctdp_level->amx_p1 = (resp & GENMASK(31, 24)) >> 24;
+ debug_printf(
+ "cpu:%d ctdp:%d CONFIG_TDP_GET_P1_INFO resp:%x sse_p1:%d avx2_p1:%d avx512_p1:%d amx_p1:%d\n",
+ id->cpu, config_index, resp, ctdp_level->sse_p1,
+ ctdp_level->avx2_p1, ctdp_level->avx512_p1, ctdp_level->amx_p1);
+}
+
+static void _get_uncore_mem_freq(struct isst_id *id, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ unsigned int resp;
+ int ret;
+
+ ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_MEM_FREQ,
+ 0, config_index, &resp);
+ if (ret) {
+ ctdp_level->mem_freq = 0;
+ return;
+ }
+
+ ctdp_level->mem_freq = resp & GENMASK(7, 0);
+ if (is_spr_platform() || is_emr_platform()) {
+ ctdp_level->mem_freq *= 200;
+ } else if (is_icx_platform()) {
+ if (ctdp_level->mem_freq < 7) {
+ ctdp_level->mem_freq = (12 - ctdp_level->mem_freq) * 133.33 * 2 * 10;
+ ctdp_level->mem_freq /= 10;
+ if (ctdp_level->mem_freq % 10 > 5)
+ ctdp_level->mem_freq++;
+ } else {
+ ctdp_level->mem_freq = 0;
+ }
+ } else {
+ ctdp_level->mem_freq = 0;
+ }
+ debug_printf(
+ "cpu:%d ctdp:%d CONFIG_TDP_GET_MEM_FREQ resp:%x uncore mem_freq:%d\n",
+ id->cpu, config_index, resp, ctdp_level->mem_freq);
+}
+
+static int mbox_get_tdp_info(struct isst_id *id, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ unsigned int resp;
+ int ret;
+
+ ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_INFO,
+ 0, config_index, &resp);
+ if (ret) {
+ isst_display_error_info_message(1, "Invalid level, Can't get TDP information at level", 1, config_index);
+ return ret;
+ }
+
+ ctdp_level->pkg_tdp = resp & GENMASK(14, 0);
+ ctdp_level->tdp_ratio = (resp & GENMASK(23, 16)) >> 16;
+
+ debug_printf(
+ "cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO resp:%x tdp_ratio:%d pkg_tdp:%d\n",
+ id->cpu, config_index, resp, ctdp_level->tdp_ratio,
+ ctdp_level->pkg_tdp);
+
+ ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TJMAX_INFO,
+ 0, config_index, &resp);
+ if (ret)
+ return ret;
+
+ ctdp_level->t_proc_hot = resp & GENMASK(7, 0);
+
+ _get_uncore_p0_p1_info(id, config_index, ctdp_level);
+ _get_p1_info(id, config_index, ctdp_level);
+ _get_uncore_mem_freq(id, config_index, ctdp_level);
+
+ debug_printf(
+ "cpu:%d ctdp:%d CONFIG_TDP_GET_TJMAX_INFO resp:%x t_proc_hot:%d\n",
+ id->cpu, config_index, resp, ctdp_level->t_proc_hot);
+
+ return 0;
+}
+
+static int mbox_get_pwr_info(struct isst_id *id, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ unsigned int resp;
+ int ret;
+
+ ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_PWR_INFO,
+ 0, config_index, &resp);
+ if (ret)
+ return ret;
+
+ ctdp_level->pkg_max_power = resp & GENMASK(14, 0);
+ ctdp_level->pkg_min_power = (resp & GENMASK(30, 16)) >> 16;
+
+ debug_printf(
+ "cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO resp:%x pkg_max_power:%d pkg_min_power:%d\n",
+ id->cpu, config_index, resp, ctdp_level->pkg_max_power,
+ ctdp_level->pkg_min_power);
+
+ return 0;
+}
+
+static int mbox_get_coremask_info(struct isst_id *id, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ unsigned int resp;
+ int i, ret;
+
+ ctdp_level->cpu_count = 0;
+ for (i = 0; i < 2; ++i) {
+ unsigned long long mask;
+ int cpu_count = 0;
+
+ ret = _send_mbox_command(id->cpu, CONFIG_TDP,
+ CONFIG_TDP_GET_CORE_MASK, 0,
+ (i << 8) | config_index, &resp);
+ if (ret)
+ return ret;
+
+ debug_printf(
+ "cpu:%d ctdp:%d mask:%d CONFIG_TDP_GET_CORE_MASK resp:%x\n",
+ id->cpu, config_index, i, resp);
+
+ mask = (unsigned long long)resp << (32 * i);
+ set_cpu_mask_from_punit_coremask(id, mask,
+ ctdp_level->core_cpumask_size,
+ ctdp_level->core_cpumask,
+ &cpu_count);
+ ctdp_level->cpu_count += cpu_count;
+ debug_printf("cpu:%d ctdp:%d mask:%d cpu count:%d\n", id->cpu,
+ config_index, i, ctdp_level->cpu_count);
+ }
+
+ return 0;
+}
+
+static int mbox_get_get_trl(struct isst_id *id, int level, int avx_level, int *trl)
+{
+ unsigned int req, resp;
+ int ret;
+
+ req = level | (avx_level << 16);
+ ret = _send_mbox_command(id->cpu, CONFIG_TDP,
+ CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
+ &resp);
+ if (ret)
+ return ret;
+
+ debug_printf(
+ "cpu:%d CONFIG_TDP_GET_TURBO_LIMIT_RATIOS req:%x resp:%x\n",
+ id->cpu, req, resp);
+
+ trl[0] = resp & GENMASK(7, 0);
+ trl[1] = (resp & GENMASK(15, 8)) >> 8;
+ trl[2] = (resp & GENMASK(23, 16)) >> 16;
+ trl[3] = (resp & GENMASK(31, 24)) >> 24;
+
+ req = level | BIT(8) | (avx_level << 16);
+ ret = _send_mbox_command(id->cpu, CONFIG_TDP,
+ CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
+ &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CONFIG_TDP_GET_TURBO_LIMIT req:%x resp:%x\n", id->cpu,
+ req, resp);
+
+ trl[4] = resp & GENMASK(7, 0);
+ trl[5] = (resp & GENMASK(15, 8)) >> 8;
+ trl[6] = (resp & GENMASK(23, 16)) >> 16;
+ trl[7] = (resp & GENMASK(31, 24)) >> 24;
+
+ return 0;
+}
+
+static int mbox_get_get_trls(struct isst_id *id, int level, struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ int trl_max_levels = isst_get_trl_max_levels();
+ int i, ret;
+
+ for (i = 0; i < trl_max_levels; i++) {
+ ret = mbox_get_get_trl(id, level, i, ctdp_level->trl_ratios[i]);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+static int mbox_get_trl_bucket_info(struct isst_id *id, int level, unsigned long long *buckets_info)
+{
+ int ret;
+
+ debug_printf("cpu:%d bucket info via MSR\n", id->cpu);
+
+ *buckets_info = 0;
+
+ ret = isst_send_msr_command(id->cpu, 0x1ae, 0, buckets_info);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d bucket info via MSR successful 0x%llx\n", id->cpu,
+ *buckets_info);
+
+ return 0;
+}
+
+static int mbox_set_tdp_level(struct isst_id *id, int tdp_level)
+{
+ unsigned int resp;
+ int ret;
+
+
+ if (isst_get_config_tdp_lock_status(id)) {
+ isst_display_error_info_message(1, "TDP is locked", 0, 0);
+ return -1;
+
+ }
+
+ ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_SET_LEVEL, 0,
+ tdp_level, &resp);
+ if (ret) {
+ isst_display_error_info_message(1, "Set TDP level failed for level", 1, tdp_level);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mbox_get_pbf_info(struct isst_id *id, int level, struct isst_pbf_info *pbf_info)
+{
+ int max_punit_core, max_mask_index;
+ unsigned int req, resp;
+ int i, ret;
+
+ max_punit_core = get_max_punit_core_id(id);
+ max_mask_index = max_punit_core > 32 ? 2 : 1;
+
+ for (i = 0; i < max_mask_index; ++i) {
+ unsigned long long mask;
+ int count;
+
+ ret = _send_mbox_command(id->cpu, CONFIG_TDP,
+ CONFIG_TDP_PBF_GET_CORE_MASK_INFO,
+ 0, (i << 8) | level, &resp);
+ if (ret)
+ break;
+
+ debug_printf(
+ "cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n",
+ id->cpu, resp);
+
+ mask = (unsigned long long)resp << (32 * i);
+ set_cpu_mask_from_punit_coremask(id, mask,
+ pbf_info->core_cpumask_size,
+ pbf_info->core_cpumask,
+ &count);
+ }
+
+ req = level;
+ ret = _send_mbox_command(id->cpu, CONFIG_TDP,
+ CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO, 0, req,
+ &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO resp:%x\n", id->cpu,
+ resp);
+
+ pbf_info->p1_low = resp & 0xff;
+ pbf_info->p1_high = (resp & GENMASK(15, 8)) >> 8;
+
+ req = level;
+ ret = _send_mbox_command(
+ id->cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TDP_INFO, 0, req, &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TDP_INFO resp:%x\n", id->cpu, resp);
+
+ pbf_info->tdp = resp & 0xffff;
+
+ req = level;
+ ret = _send_mbox_command(
+ id->cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TJ_MAX_INFO, 0, req, &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TJ_MAX_INFO resp:%x\n", id->cpu,
+ resp);
+ pbf_info->t_control = (resp >> 8) & 0xff;
+ pbf_info->t_prochot = resp & 0xff;
+
+ return 0;
+}
+
+static int mbox_set_pbf_fact_status(struct isst_id *id, int pbf, int enable)
+{
+ struct isst_pkg_ctdp pkg_dev;
+ struct isst_pkg_ctdp_level_info ctdp_level;
+ int current_level;
+ unsigned int req = 0, resp;
+ int ret;
+
+ ret = isst_get_ctdp_levels(id, &pkg_dev);
+ if (ret)
+ debug_printf("cpu:%d No support for dynamic ISST\n", id->cpu);
+
+ current_level = pkg_dev.current_level;
+
+ ret = isst_get_ctdp_control(id, current_level, &ctdp_level);
+ if (ret)
+ return ret;
+
+ if (pbf) {
+ if (ctdp_level.fact_enabled)
+ req = BIT(16);
+
+ if (enable)
+ req |= BIT(17);
+ else
+ req &= ~BIT(17);
+ } else {
+
+ if (enable && !ctdp_level.sst_cp_enabled)
+ isst_display_error_info_message(0, "Make sure to execute before: core-power enable", 0, 0);
+
+ if (ctdp_level.pbf_enabled)
+ req = BIT(17);
+
+ if (enable)
+ req |= BIT(16);
+ else
+ req &= ~BIT(16);
+ }
+
+ ret = _send_mbox_command(id->cpu, CONFIG_TDP,
+ CONFIG_TDP_SET_TDP_CONTROL, 0, req, &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CONFIG_TDP_SET_TDP_CONTROL pbf/fact:%d req:%x\n",
+ id->cpu, pbf, req);
+
+ return 0;
+}
+
+static int _get_fact_bucket_info(struct isst_id *id, int level,
+ struct isst_fact_bucket_info *bucket_info)
+{
+ int trl_max_levels = isst_get_trl_max_levels();
+ unsigned int resp;
+ int i, k, ret;
+
+ for (i = 0; i < 2; ++i) {
+ int j;
+
+ ret = _send_mbox_command(
+ id->cpu, CONFIG_TDP,
+ CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES, 0,
+ (i << 8) | level, &resp);
+ if (ret)
+ return ret;
+
+ debug_printf(
+ "cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES index:%d level:%d resp:%x\n",
+ id->cpu, i, level, resp);
+
+ for (j = 0; j < 4; ++j) {
+ bucket_info[j + (i * 4)].hp_cores =
+ (resp >> (j * 8)) & 0xff;
+ }
+ }
+
+ for (k = 0; k < trl_max_levels; ++k) {
+ for (i = 0; i < 2; ++i) {
+ int j;
+
+ ret = _send_mbox_command(
+ id->cpu, CONFIG_TDP,
+ CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS, 0,
+ (k << 16) | (i << 8) | level, &resp);
+ if (ret)
+ return ret;
+
+ debug_printf(
+ "cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS index:%d level:%d avx:%d resp:%x\n",
+ id->cpu, i, level, k, resp);
+
+ for (j = 0; j < 4; ++j) {
+ bucket_info[j + (i * 4)].hp_ratios[k] =
+ (resp >> (j * 8)) & 0xff;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int mbox_get_fact_info(struct isst_id *id, int level, int fact_bucket, struct isst_fact_info *fact_info)
+{
+ unsigned int resp;
+ int j, ret, print;
+
+ ret = _send_mbox_command(id->cpu, CONFIG_TDP,
+ CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO, 0,
+ level, &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO resp:%x\n",
+ id->cpu, resp);
+
+ fact_info->lp_ratios[0] = resp & 0xff;
+ fact_info->lp_ratios[1] = (resp >> 8) & 0xff;
+ fact_info->lp_ratios[2] = (resp >> 16) & 0xff;
+
+ ret = _get_fact_bucket_info(id, level, fact_info->bucket_info);
+ if (ret)
+ return ret;
+
+ print = 0;
+ for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
+ if (fact_bucket != 0xff && fact_bucket != j)
+ continue;
+
+ if (!fact_info->bucket_info[j].hp_cores)
+ break;
+
+ print = 1;
+ }
+ if (!print) {
+ isst_display_error_info_message(1, "Invalid bucket", 0, 0);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int mbox_get_clos_information(struct isst_id *id, int *enable, int *type)
+{
+ unsigned int resp;
+ int ret;
+
+ ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
+ &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);
+
+ if (resp & BIT(1))
+ *enable = 1;
+ else
+ *enable = 0;
+
+ if (resp & BIT(2))
+ *type = 1;
+ else
+ *type = 0;
+
+ return 0;
+}
+
+static int _write_pm_config(struct isst_id *id, int cp_state)
+{
+ unsigned int req, resp;
+ int ret;
+
+ if (cp_state)
+ req = BIT(16);
+ else
+ req = 0;
+
+ ret = _send_mbox_command(id->cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req,
+ &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d WRITE_PM_CONFIG resp:%x\n", id->cpu, resp);
+
+ return 0;
+}
+
+static int mbox_pm_qos_config(struct isst_id *id, int enable_clos, int priority_type)
+{
+ unsigned int req, resp;
+ int ret;
+
+ if (!enable_clos) {
+ struct isst_pkg_ctdp pkg_dev;
+ struct isst_pkg_ctdp_level_info ctdp_level;
+
+ ret = isst_get_ctdp_levels(id, &pkg_dev);
+ if (ret) {
+ debug_printf("isst_get_ctdp_levels\n");
+ return ret;
+ }
+
+ ret = isst_get_ctdp_control(id, pkg_dev.current_level,
+ &ctdp_level);
+ if (ret)
+ return ret;
+
+ if (ctdp_level.fact_enabled) {
+ isst_display_error_info_message(1, "Ignoring request, turbo-freq feature is still enabled", 0, 0);
+ return -EINVAL;
+ }
+ ret = _write_pm_config(id, 0);
+ if (ret)
+ isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
+ } else {
+ ret = _write_pm_config(id, 1);
+ if (ret)
+ isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
+ }
+
+ ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
+ &resp);
+ if (ret) {
+ isst_display_error_info_message(1, "CLOS_PM_QOS_CONFIG command failed", 0, 0);
+ return ret;
+ }
+
+ debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);
+
+ req = resp;
+
+ if (enable_clos)
+ req = req | BIT(1);
+ else
+ req = req & ~BIT(1);
+
+ if (priority_type > 1)
+ isst_display_error_info_message(1, "Invalid priority type: Changing type to ordered", 0, 0);
+
+ if (priority_type)
+ req = req | BIT(2);
+ else
+ req = req & ~BIT(2);
+
+ ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG,
+ BIT(MBOX_CMD_WRITE_BIT), req, &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CLOS_PM_QOS_CONFIG priority type:%d req:%x\n", id->cpu,
+ priority_type, req);
+
+ return 0;
+}
+
+static int mbox_pm_get_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
+{
+ unsigned int resp;
+ int ret;
+
+ ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, clos, 0,
+ &resp);
+ if (ret)
+ return ret;
+
+ clos_config->epp = resp & 0x0f;
+ clos_config->clos_prop_prio = (resp >> 4) & 0x0f;
+ clos_config->clos_min = (resp >> 8) & 0xff;
+ clos_config->clos_max = (resp >> 16) & 0xff;
+ clos_config->clos_desired = (resp >> 24) & 0xff;
+
+ return 0;
+}
+
+static int mbox_set_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
+{
+ unsigned int req, resp;
+ unsigned int param;
+ int ret;
+
+ req = clos_config->epp & 0x0f;
+ req |= (clos_config->clos_prop_prio & 0x0f) << 4;
+ req |= (clos_config->clos_min & 0xff) << 8;
+ req |= (clos_config->clos_max & 0xff) << 16;
+ req |= (clos_config->clos_desired & 0xff) << 24;
+
+ param = BIT(MBOX_CMD_WRITE_BIT) | clos;
+
+ ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, param, req,
+ &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CLOS_PM_CLOS param:%x req:%x\n", id->cpu, param, req);
+
+ return 0;
+}
+
+static int mbox_clos_get_assoc_status(struct isst_id *id, int *clos_id)
+{
+ unsigned int resp;
+ unsigned int param;
+ int core_id, ret;
+
+ core_id = find_phy_core_num(id->cpu);
+ param = core_id;
+
+ ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 0,
+ &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x resp:%x\n", id->cpu, param,
+ resp);
+ *clos_id = (resp >> 16) & 0x03;
+
+ return 0;
+}
+
+static int mbox_clos_associate(struct isst_id *id, int clos_id)
+{
+ unsigned int req, resp;
+ unsigned int param;
+ int core_id, ret;
+
+ req = (clos_id & 0x03) << 16;
+ core_id = find_phy_core_num(id->cpu);
+ param = BIT(MBOX_CMD_WRITE_BIT) | core_id;
+
+ ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param,
+ req, &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x req:%x\n", id->cpu, param,
+ req);
+
+ return 0;
+}
+
+static struct isst_platform_ops mbox_ops = {
+ .get_disp_freq_multiplier = mbox_get_disp_freq_multiplier,
+ .get_trl_max_levels = mbox_get_trl_max_levels,
+ .get_trl_level_name = mbox_get_trl_level_name,
+ .update_platform_param = mbox_update_platform_param,
+ .is_punit_valid = mbox_is_punit_valid,
+ .read_pm_config = mbox_read_pm_config,
+ .get_config_levels = mbox_get_config_levels,
+ .get_ctdp_control = mbox_get_ctdp_control,
+ .get_tdp_info = mbox_get_tdp_info,
+ .get_pwr_info = mbox_get_pwr_info,
+ .get_coremask_info = mbox_get_coremask_info,
+ .get_get_trl = mbox_get_get_trl,
+ .get_get_trls = mbox_get_get_trls,
+ .get_trl_bucket_info = mbox_get_trl_bucket_info,
+ .set_tdp_level = mbox_set_tdp_level,
+ .get_pbf_info = mbox_get_pbf_info,
+ .set_pbf_fact_status = mbox_set_pbf_fact_status,
+ .get_fact_info = mbox_get_fact_info,
+ .adjust_uncore_freq = mbox_adjust_uncore_freq,
+ .get_clos_information = mbox_get_clos_information,
+ .pm_qos_config = mbox_pm_qos_config,
+ .pm_get_clos = mbox_pm_get_clos,
+ .set_clos = mbox_set_clos,
+ .clos_get_assoc_status = mbox_clos_get_assoc_status,
+ .clos_associate = mbox_clos_associate,
+};
+
+struct isst_platform_ops *mbox_get_platform_ops(void)
+{
+ return &mbox_ops;
+}
diff --git a/tools/power/x86/intel-speed-select/isst-core-tpmi.c b/tools/power/x86/intel-speed-select/isst-core-tpmi.c
new file mode 100644
index 000000000000..4f389e1c0525
--- /dev/null
+++ b/tools/power/x86/intel-speed-select/isst-core-tpmi.c
@@ -0,0 +1,832 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel Speed Select -- Enumerate and control features for TPMI Interface
+ * Copyright (c) 2022 Intel Corporation.
+ */
+
+#include <linux/isst_if.h>
+#include "isst.h"
+
+int tpmi_process_ioctl(int ioctl_no, void *info)
+{
+ const char *pathname = "/dev/isst_interface";
+ int fd;
+
+ if (is_debug_enabled()) {
+ debug_printf("Issue IOCTL: ");
+ switch (ioctl_no) {
+ case ISST_IF_CORE_POWER_STATE:
+ debug_printf("ISST_IF_CORE_POWER_STATE\n");
+ break;
+ case ISST_IF_CLOS_PARAM:
+ debug_printf("ISST_IF_CLOS_PARAM\n");
+ break;
+ case ISST_IF_CLOS_ASSOC:
+ debug_printf("ISST_IF_CLOS_ASSOC\n");
+ break;
+ case ISST_IF_PERF_LEVELS:
+ debug_printf("ISST_IF_PERF_LEVELS\n");
+ break;
+ case ISST_IF_PERF_SET_LEVEL:
+ debug_printf("ISST_IF_PERF_SET_LEVEL\n");
+ break;
+ case ISST_IF_PERF_SET_FEATURE:
+ debug_printf("ISST_IF_PERF_SET_FEATURE\n");
+ break;
+ case ISST_IF_GET_PERF_LEVEL_INFO:
+ debug_printf("ISST_IF_GET_PERF_LEVEL_INFO\n");
+ break;
+ case ISST_IF_GET_PERF_LEVEL_CPU_MASK:
+ debug_printf("ISST_IF_GET_PERF_LEVEL_CPU_MASK\n");
+ break;
+ case ISST_IF_GET_BASE_FREQ_INFO:
+ debug_printf("ISST_IF_GET_BASE_FREQ_INFO\n");
+ break;
+ case ISST_IF_GET_BASE_FREQ_CPU_MASK:
+ debug_printf("ISST_IF_GET_BASE_FREQ_CPU_MASK\n");
+ break;
+ case ISST_IF_GET_TURBO_FREQ_INFO:
+ debug_printf("ISST_IF_GET_TURBO_FREQ_INFO\n");
+ break;
+ case ISST_IF_COUNT_TPMI_INSTANCES:
+ debug_printf("ISST_IF_COUNT_TPMI_INSTANCES\n");
+ break;
+ default:
+ debug_printf("%d\n", ioctl_no);
+ break;
+ }
+ }
+
+ fd = open(pathname, O_RDWR);
+ if (fd < 0)
+ return -1;
+
+ if (ioctl(fd, ioctl_no, info) == -1) {
+ debug_printf("IOCTL %d Failed\n", ioctl_no);
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+
+ return 0;
+}
+
+static int tpmi_get_disp_freq_multiplier(void)
+{
+ return 1;
+}
+
+static int tpmi_get_trl_max_levels(void)
+{
+ return TRL_MAX_LEVELS;
+}
+
+static char *tpmi_get_trl_level_name(int level)
+{
+ switch (level) {
+ case 0:
+ return "level-0";
+ case 1:
+ return "level-1";
+ case 2:
+ return "level-2";
+ case 3:
+ return "level-3";
+ case 4:
+ return "level-4";
+ case 5:
+ return "level-5";
+ case 6:
+ return "level-6";
+ case 7:
+ return "level-7";
+ default:
+ return NULL;
+ }
+}
+
+
+static void tpmi_update_platform_param(enum isst_platform_param param, int value)
+{
+ /* No params need to be updated for now */
+}
+
+static int tpmi_is_punit_valid(struct isst_id *id)
+{
+ struct isst_tpmi_instance_count info;
+ int ret;
+
+ if (id->punit < 0)
+ return 0;
+
+ info.socket_id = id->pkg;
+ ret = tpmi_process_ioctl(ISST_IF_COUNT_TPMI_INSTANCES, &info);
+ if (ret == -1)
+ return 0;
+
+ if (info.valid_mask & BIT(id->punit))
+ return 1;
+
+ return 0;
+}
+
+static int tpmi_read_pm_config(struct isst_id *id, int *cp_state, int *cp_cap)
+{
+ struct isst_core_power info;
+ int ret;
+
+ info.get_set = 0;
+ info.socket_id = id->pkg;
+ info.power_domain_id = id->punit;
+ ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info);
+ if (ret == -1)
+ return ret;
+
+ *cp_state = info.enable;
+ *cp_cap = info.supported;
+
+ return 0;
+}
+
+int tpmi_get_config_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)
+{
+ struct isst_perf_level_info info;
+ int ret;
+
+ info.socket_id = id->pkg;
+ info.power_domain_id = id->punit;
+
+ ret = tpmi_process_ioctl(ISST_IF_PERF_LEVELS, &info);
+ if (ret == -1)
+ return ret;
+
+ pkg_dev->version = info.feature_rev;
+ pkg_dev->levels = info.max_level;
+ pkg_dev->locked = info.locked;
+ pkg_dev->current_level = info.current_level;
+ pkg_dev->locked = info.locked;
+ pkg_dev->enabled = info.enabled;
+
+ return 0;
+}
+
+static int tpmi_get_ctdp_control(struct isst_id *id, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ struct isst_core_power core_power_info;
+ struct isst_perf_level_info info;
+ int level_mask;
+ int ret;
+
+ info.socket_id = id->pkg;
+ info.power_domain_id = id->punit;
+
+ ret = tpmi_process_ioctl(ISST_IF_PERF_LEVELS, &info);
+ if (ret == -1)
+ return -1;
+
+ if (config_index != 0xff)
+ level_mask = 1 << config_index;
+ else
+ level_mask = config_index;
+
+ if (!(info.level_mask & level_mask))
+ return -1;
+
+ if (api_version() > 2) {
+ ctdp_level->fact_support = info.sst_tf_support & BIT(config_index);
+ ctdp_level->pbf_support = info.sst_bf_support & BIT(config_index);
+ } else {
+ ctdp_level->fact_support = info.sst_tf_support;
+ ctdp_level->pbf_support = info.sst_bf_support;
+ }
+
+ ctdp_level->fact_enabled = !!(info.feature_state & BIT(1));
+ ctdp_level->pbf_enabled = !!(info.feature_state & BIT(0));
+
+ core_power_info.get_set = 0;
+ core_power_info.socket_id = id->pkg;
+ core_power_info.power_domain_id = id->punit;
+
+ ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &core_power_info);
+ if (ret == -1)
+ return ret;
+
+ ctdp_level->sst_cp_support = core_power_info.supported;
+ ctdp_level->sst_cp_enabled = core_power_info.enable;
+
+ debug_printf
+ ("cpu:%d CONFIG_TDP_GET_TDP_CONTROL fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
+ id->cpu, ctdp_level->fact_support, ctdp_level->pbf_support,
+ ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
+
+ return 0;
+}
+
+static int tpmi_get_tdp_info(struct isst_id *id, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ struct isst_perf_level_fabric_info fabric_info;
+ struct isst_perf_level_data_info info;
+ int ret;
+
+ info.socket_id = id->pkg;
+ info.power_domain_id = id->punit;
+ info.level = config_index;
+
+ ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
+ if (ret == -1)
+ return ret;
+
+ ctdp_level->pkg_tdp = info.thermal_design_power_w;
+ ctdp_level->tdp_ratio = info.tdp_ratio;
+ ctdp_level->sse_p1 = info.base_freq_mhz;
+ ctdp_level->avx2_p1 = info.base_freq_avx2_mhz;
+ ctdp_level->avx512_p1 = info.base_freq_avx512_mhz;
+ ctdp_level->amx_p1 = info.base_freq_amx_mhz;
+
+ ctdp_level->t_proc_hot = info.tjunction_max_c;
+ ctdp_level->mem_freq = info.max_memory_freq_mhz;
+ ctdp_level->cooling_type = info.cooling_type;
+
+ ctdp_level->uncore_p0 = info.p0_fabric_freq_mhz;
+ ctdp_level->uncore_p1 = info.p1_fabric_freq_mhz;
+ ctdp_level->uncore_pm = info.pm_fabric_freq_mhz;
+
+ fabric_info.socket_id = id->pkg;
+ fabric_info.power_domain_id = id->punit;
+ fabric_info.level = config_index;
+
+ ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_FABRIC_INFO, &fabric_info);
+ if (ret != -1) {
+ ctdp_level->uncore1_p0 = fabric_info.p0_fabric_freq_mhz[1];
+ ctdp_level->uncore1_p1 = fabric_info.p1_fabric_freq_mhz[1];
+ ctdp_level->uncore1_pm = fabric_info.pm_fabric_freq_mhz[1];
+ }
+
+ debug_printf
+ ("cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO tdp_ratio:%d pkg_tdp:%d ctdp_level->t_proc_hot:%d\n",
+ id->cpu, config_index, ctdp_level->tdp_ratio, ctdp_level->pkg_tdp,
+ ctdp_level->t_proc_hot);
+
+ return 0;
+}
+
+static int tpmi_get_pwr_info(struct isst_id *id, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ /* TBD */
+ ctdp_level->pkg_max_power = 0;
+ ctdp_level->pkg_min_power = 0;
+
+ debug_printf
+ ("cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO pkg_max_power:%d pkg_min_power:%d\n",
+ id->cpu, config_index, ctdp_level->pkg_max_power,
+ ctdp_level->pkg_min_power);
+
+ return 0;
+}
+
+int tpmi_get_coremask_info(struct isst_id *id, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ struct isst_perf_level_cpu_mask info;
+ int ret, cpu_count;
+
+ info.socket_id = id->pkg;
+ info.power_domain_id = id->punit;
+ info.level = config_index;
+ info.punit_cpu_map = 1;
+
+ ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_CPU_MASK, &info);
+ if (ret == -1)
+ return ret;
+
+ set_cpu_mask_from_punit_coremask(id, info.mask,
+ ctdp_level->core_cpumask_size,
+ ctdp_level->core_cpumask, &cpu_count);
+ ctdp_level->cpu_count = cpu_count;
+
+ debug_printf("cpu:%d ctdp:%d core_mask ino cpu count:%d\n",
+ id->cpu, config_index, ctdp_level->cpu_count);
+
+ return 0;
+}
+
+static int tpmi_get_get_trls(struct isst_id *id, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ struct isst_perf_level_data_info info;
+ int ret, i, j;
+
+ info.socket_id = id->pkg;
+ info.power_domain_id = id->punit;
+ info.level = config_index;
+
+ ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
+ if (ret == -1)
+ return ret;
+
+ if (info.max_buckets > TRL_MAX_BUCKETS)
+ info.max_buckets = TRL_MAX_BUCKETS;
+
+ if (info.max_trl_levels > TRL_MAX_LEVELS)
+ info.max_trl_levels = TRL_MAX_LEVELS;
+
+ for (i = 0; i < info.max_trl_levels; ++i)
+ for (j = 0; j < info.max_buckets; ++j)
+ ctdp_level->trl_ratios[i][j] = info.trl_freq_mhz[i][j];
+
+ return 0;
+}
+
+static int tpmi_get_get_trl(struct isst_id *id, int config_index, int level,
+ int *trl)
+{
+ struct isst_pkg_ctdp_level_info ctdp_level;
+ int ret, i;
+
+ ret = tpmi_get_get_trls(id, config_index, &ctdp_level);
+ if (ret)
+ return ret;
+
+ /* FIX ME: Just return for level 0 */
+ for (i = 0; i < 8; ++i)
+ trl[i] = ctdp_level.trl_ratios[0][i];
+
+ return 0;
+}
+
+static int tpmi_get_trl_bucket_info(struct isst_id *id, int config_index,
+ unsigned long long *buckets_info)
+{
+ struct isst_perf_level_data_info info;
+ unsigned char *mask = (unsigned char *)buckets_info;
+ int ret, i;
+
+ info.socket_id = id->pkg;
+ info.power_domain_id = id->punit;
+ info.level = config_index;
+
+ ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
+ if (ret == -1)
+ return ret;
+
+ if (info.max_buckets > TRL_MAX_BUCKETS)
+ info.max_buckets = TRL_MAX_BUCKETS;
+
+ for (i = 0; i < info.max_buckets; ++i)
+ mask[i] = info.bucket_core_counts[i];
+
+ debug_printf("cpu:%d TRL bucket info: 0x%llx\n", id->cpu,
+ *buckets_info);
+
+ return 0;
+}
+
+static int tpmi_set_tdp_level(struct isst_id *id, int tdp_level)
+{
+ struct isst_perf_level_control info;
+ int ret;
+
+ info.socket_id = id->pkg;
+ info.power_domain_id = id->punit;
+ info.level = tdp_level;
+
+ ret = tpmi_process_ioctl(ISST_IF_PERF_SET_LEVEL, &info);
+ if (ret == -1)
+ return ret;
+
+ return 0;
+}
+
+static int _pbf_get_coremask_info(struct isst_id *id, int config_index,
+ struct isst_pbf_info *pbf_info)
+{
+ struct isst_perf_level_cpu_mask info;
+ int ret, cpu_count;
+
+ info.socket_id = id->pkg;
+ info.power_domain_id = id->punit;
+ info.level = config_index;
+ info.punit_cpu_map = 1;
+
+ ret = tpmi_process_ioctl(ISST_IF_GET_BASE_FREQ_CPU_MASK, &info);
+ if (ret == -1)
+ return ret;
+
+ set_cpu_mask_from_punit_coremask(id, info.mask,
+ pbf_info->core_cpumask_size,
+ pbf_info->core_cpumask, &cpu_count);
+
+ debug_printf("cpu:%d ctdp:%d pbf core_mask info cpu count:%d\n",
+ id->cpu, config_index, cpu_count);
+
+ return 0;
+}
+
+static int tpmi_get_pbf_info(struct isst_id *id, int level,
+ struct isst_pbf_info *pbf_info)
+{
+ struct isst_base_freq_info info;
+ int ret;
+
+ info.socket_id = id->pkg;
+ info.power_domain_id = id->punit;
+ info.level = level;
+
+ ret = tpmi_process_ioctl(ISST_IF_GET_BASE_FREQ_INFO, &info);
+ if (ret == -1)
+ return ret;
+
+ pbf_info->p1_low = info.low_base_freq_mhz;
+ pbf_info->p1_high = info.high_base_freq_mhz;
+ pbf_info->tdp = info.thermal_design_power_w;
+ pbf_info->t_prochot = info.tjunction_max_c;
+
+ debug_printf("cpu:%d ctdp:%d pbf info:%d:%d:%d:%d\n",
+ id->cpu, level, pbf_info->p1_low, pbf_info->p1_high,
+ pbf_info->tdp, pbf_info->t_prochot);
+
+ return _pbf_get_coremask_info(id, level, pbf_info);
+}
+
+static int tpmi_set_pbf_fact_status(struct isst_id *id, int pbf, int enable)
+{
+ struct isst_pkg_ctdp pkg_dev;
+ struct isst_pkg_ctdp_level_info ctdp_level;
+ int current_level;
+ struct isst_perf_feature_control info;
+ int ret;
+
+ ret = isst_get_ctdp_levels(id, &pkg_dev);
+ if (ret)
+ debug_printf("cpu:%d No support for dynamic ISST\n", id->cpu);
+
+ current_level = pkg_dev.current_level;
+
+ ret = isst_get_ctdp_control(id, current_level, &ctdp_level);
+ if (ret)
+ return ret;
+
+ info.socket_id = id->pkg;
+ info.power_domain_id = id->punit;
+
+ info.feature = 0;
+
+ if (pbf) {
+ if (ctdp_level.fact_enabled)
+ info.feature |= BIT(1);
+
+ if (enable)
+ info.feature |= BIT(0);
+ else
+ info.feature &= ~BIT(0);
+ } else {
+
+ if (enable && !ctdp_level.sst_cp_enabled)
+ isst_display_error_info_message(0,
+ "Make sure to execute before: core-power enable",
+ 0, 0);
+
+ if (ctdp_level.pbf_enabled)
+ info.feature |= BIT(0);
+
+ if (enable)
+ info.feature |= BIT(1);
+ else
+ info.feature &= ~BIT(1);
+ }
+
+ ret = tpmi_process_ioctl(ISST_IF_PERF_SET_FEATURE, &info);
+ if (ret == -1)
+ return ret;
+
+ return 0;
+}
+
+static int tpmi_get_fact_info(struct isst_id *id, int level, int fact_bucket,
+ struct isst_fact_info *fact_info)
+{
+ struct isst_turbo_freq_info info;
+ int i, j;
+ int ret;
+
+ info.socket_id = id->pkg;
+ info.power_domain_id = id->punit;
+ info.level = level;
+
+ ret = tpmi_process_ioctl(ISST_IF_GET_TURBO_FREQ_INFO, &info);
+ if (ret == -1)
+ return ret;
+
+ for (i = 0; i < info.max_clip_freqs; ++i)
+ fact_info->lp_ratios[i] = info.lp_clip_freq_mhz[i];
+
+ if (info.max_buckets > TRL_MAX_BUCKETS)
+ info.max_buckets = TRL_MAX_BUCKETS;
+
+ if (info.max_trl_levels > TRL_MAX_LEVELS)
+ info.max_trl_levels = TRL_MAX_LEVELS;
+
+ for (i = 0; i < info.max_trl_levels; ++i) {
+ for (j = 0; j < info.max_buckets; ++j)
+ fact_info->bucket_info[j].hp_ratios[i] =
+ info.trl_freq_mhz[i][j];
+ }
+
+ for (i = 0; i < info.max_buckets; ++i)
+ fact_info->bucket_info[i].hp_cores = info.bucket_core_counts[i];
+
+ return 0;
+}
+
+static void _set_uncore_min_max(struct isst_id *id, int max, int freq)
+{
+ DIR *dir;
+ FILE *filep;
+ struct dirent *entry;
+ char buffer[512];
+ unsigned int tmp_id;
+ int ret;
+
+ dir = opendir("/sys/devices/system/cpu/intel_uncore_frequency/");
+ if (!dir)
+ return;
+
+ while ((entry = readdir(dir)) != NULL ) {
+ /* Check domain_id */
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/intel_uncore_frequency/%s/domain_id", entry->d_name);
+
+ filep = fopen(buffer, "r");
+ if (!filep)
+ goto end;
+
+ ret = fscanf(filep, "%u", &tmp_id);
+ fclose(filep);
+ if (ret != 1)
+ goto end;
+
+ if (tmp_id != id->punit)
+ continue;
+
+ /* Check package_id */
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/intel_uncore_frequency/%s/package_id", entry->d_name);
+
+ filep = fopen(buffer, "r");
+ if (!filep)
+ goto end;
+
+ ret = fscanf(filep, "%u", &tmp_id);
+ fclose(filep);
+
+ if (ret != 1)
+ goto end;
+
+ if (tmp_id != id->pkg)
+ continue;
+
+ /* Found the right sysfs path, adjust and quit */
+ if (max)
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/intel_uncore_frequency/%s/max_freq_khz", entry->d_name);
+ else
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/intel_uncore_frequency/%s/min_freq_khz", entry->d_name);
+
+ filep = fopen(buffer, "w");
+ if (!filep)
+ goto end;
+
+ fprintf(filep, "%d\n", freq);
+ fclose(filep);
+ break;
+ }
+
+end:
+ closedir(dir);
+}
+
+static void tpmi_adjust_uncore_freq(struct isst_id *id, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ struct isst_perf_level_data_info info;
+ int ret;
+
+ info.socket_id = id->pkg;
+ info.power_domain_id = id->punit;
+ info.level = config_index;
+
+ ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
+ if (ret == -1)
+ return;
+
+ ctdp_level->uncore_p0 = info.p0_fabric_freq_mhz;
+ ctdp_level->uncore_p1 = info.p1_fabric_freq_mhz;
+ ctdp_level->uncore_pm = info.pm_fabric_freq_mhz;
+
+ if (ctdp_level->uncore_pm)
+ _set_uncore_min_max(id, 0, ctdp_level->uncore_pm * 100000);
+
+ if (ctdp_level->uncore_p0)
+ _set_uncore_min_max(id, 1, ctdp_level->uncore_p0 * 100000);
+
+ return;
+}
+
+static int tpmi_get_clos_information(struct isst_id *id, int *enable, int *type)
+{
+ struct isst_core_power info;
+ int ret;
+
+ info.get_set = 0;
+ info.socket_id = id->pkg;
+ info.power_domain_id = id->punit;
+ ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info);
+ if (ret == -1)
+ return ret;
+
+ *enable = info.enable;
+ *type = info.priority_type;
+
+ return 0;
+}
+
+static int tpmi_pm_qos_config(struct isst_id *id, int enable_clos,
+ int priority_type)
+{
+ struct isst_core_power info;
+ int i, ret, saved_punit;
+
+ info.get_set = 1;
+ info.socket_id = id->pkg;
+ info.power_domain_id = id->punit;
+ info.enable = enable_clos;
+ info.priority_type = priority_type;
+
+ saved_punit = id->punit;
+
+ /* Set for all other dies also. This is per package setting */
+ for (i = 0; i < MAX_PUNIT_PER_DIE; i++) {
+ id->punit = i;
+ if (isst_is_punit_valid(id)) {
+ info.power_domain_id = i;
+ ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info);
+ if (ret == -1) {
+ id->punit = saved_punit;
+ return ret;
+ }
+ }
+ }
+
+ id->punit = saved_punit;
+
+ return 0;
+}
+
+int tpmi_pm_get_clos(struct isst_id *id, int clos,
+ struct isst_clos_config *clos_config)
+{
+ struct isst_clos_param info;
+ int ret;
+
+ info.get_set = 0;
+ info.socket_id = id->pkg;
+ info.power_domain_id = id->punit;
+ info.clos = clos;
+
+ ret = tpmi_process_ioctl(ISST_IF_CLOS_PARAM, &info);
+ if (ret == -1)
+ return ret;
+
+ clos_config->epp = 0;
+ clos_config->clos_prop_prio = info.prop_prio;
+ clos_config->clos_min = info.min_freq_mhz;
+ clos_config->clos_max = info.max_freq_mhz;
+ clos_config->clos_desired = 0;
+
+ debug_printf("cpu:%d clos:%d min:%d max:%d\n", id->cpu, clos,
+ clos_config->clos_min, clos_config->clos_max);
+
+ return 0;
+}
+
+int tpmi_set_clos(struct isst_id *id, int clos,
+ struct isst_clos_config *clos_config)
+{
+ struct isst_clos_param info;
+ int i, ret, saved_punit;
+
+ info.get_set = 1;
+ info.socket_id = id->pkg;
+ info.power_domain_id = id->punit;
+ info.clos = clos;
+ info.prop_prio = clos_config->clos_prop_prio;
+
+ info.min_freq_mhz = clos_config->clos_min;
+ info.max_freq_mhz = clos_config->clos_max;
+
+ if (info.min_freq_mhz <= 0xff)
+ info.min_freq_mhz *= 100;
+ if (info.max_freq_mhz <= 0xff)
+ info.max_freq_mhz *= 100;
+
+ saved_punit = id->punit;
+
+ /* Set for all other dies also. This is per package setting */
+ for (i = 0; i < MAX_PUNIT_PER_DIE; i++) {
+ id->punit = i;
+ if (isst_is_punit_valid(id)) {
+ info.power_domain_id = i;
+ ret = tpmi_process_ioctl(ISST_IF_CLOS_PARAM, &info);
+ if (ret == -1) {
+ id->punit = saved_punit;
+ return ret;
+ }
+ }
+ }
+
+ id->punit = saved_punit;
+
+ debug_printf("set cpu:%d clos:%d min:%d max:%d\n", id->cpu, clos,
+ clos_config->clos_min, clos_config->clos_max);
+
+ return 0;
+}
+
+static int tpmi_clos_get_assoc_status(struct isst_id *id, int *clos_id)
+{
+ struct isst_if_clos_assoc_cmds assoc_cmds;
+ int ret;
+
+ assoc_cmds.cmd_count = 1;
+ assoc_cmds.get_set = 0;
+ assoc_cmds.punit_cpu_map = 1;
+ assoc_cmds.assoc_info[0].logical_cpu = find_phy_core_num(id->cpu);
+ assoc_cmds.assoc_info[0].socket_id = id->pkg;
+ assoc_cmds.assoc_info[0].power_domain_id = id->punit;
+
+ ret = tpmi_process_ioctl(ISST_IF_CLOS_ASSOC, &assoc_cmds);
+ if (ret == -1)
+ return ret;
+
+ *clos_id = assoc_cmds.assoc_info[0].clos;
+
+ return 0;
+}
+
+static int tpmi_clos_associate(struct isst_id *id, int clos_id)
+{
+ struct isst_if_clos_assoc_cmds assoc_cmds;
+ int ret;
+
+ assoc_cmds.cmd_count = 1;
+ assoc_cmds.get_set = 1;
+ assoc_cmds.punit_cpu_map = 1;
+ assoc_cmds.assoc_info[0].logical_cpu = find_phy_core_num(id->cpu);
+ assoc_cmds.assoc_info[0].clos = clos_id;
+ assoc_cmds.assoc_info[0].socket_id = id->pkg;
+ assoc_cmds.assoc_info[0].power_domain_id = id->punit;
+
+ ret = tpmi_process_ioctl(ISST_IF_CLOS_ASSOC, &assoc_cmds);
+ if (ret == -1)
+ return ret;
+
+ return 0;
+}
+
+static struct isst_platform_ops tpmi_ops = {
+ .get_disp_freq_multiplier = tpmi_get_disp_freq_multiplier,
+ .get_trl_max_levels = tpmi_get_trl_max_levels,
+ .get_trl_level_name = tpmi_get_trl_level_name,
+ .update_platform_param = tpmi_update_platform_param,
+ .is_punit_valid = tpmi_is_punit_valid,
+ .read_pm_config = tpmi_read_pm_config,
+ .get_config_levels = tpmi_get_config_levels,
+ .get_ctdp_control = tpmi_get_ctdp_control,
+ .get_tdp_info = tpmi_get_tdp_info,
+ .get_pwr_info = tpmi_get_pwr_info,
+ .get_coremask_info = tpmi_get_coremask_info,
+ .get_get_trl = tpmi_get_get_trl,
+ .get_get_trls = tpmi_get_get_trls,
+ .get_trl_bucket_info = tpmi_get_trl_bucket_info,
+ .set_tdp_level = tpmi_set_tdp_level,
+ .get_pbf_info = tpmi_get_pbf_info,
+ .set_pbf_fact_status = tpmi_set_pbf_fact_status,
+ .get_fact_info = tpmi_get_fact_info,
+ .adjust_uncore_freq = tpmi_adjust_uncore_freq,
+ .get_clos_information = tpmi_get_clos_information,
+ .pm_qos_config = tpmi_pm_qos_config,
+ .pm_get_clos = tpmi_pm_get_clos,
+ .set_clos = tpmi_set_clos,
+ .clos_get_assoc_status = tpmi_clos_get_assoc_status,
+ .clos_associate = tpmi_clos_associate,
+};
+
+struct isst_platform_ops *tpmi_get_platform_ops(void)
+{
+ return &tpmi_ops;
+}
diff --git a/tools/power/x86/intel-speed-select/isst-core.c b/tools/power/x86/intel-speed-select/isst-core.c
index a7f4337c5777..e05561d00458 100644
--- a/tools/power/x86/intel-speed-select/isst-core.c
+++ b/tools/power/x86/intel-speed-select/isst-core.c
@@ -6,274 +6,150 @@
#include "isst.h"
-int isst_write_pm_config(int cpu, int cp_state)
-{
- unsigned int req, resp;
- int ret;
-
- if (cp_state)
- req = BIT(16);
- else
- req = 0;
-
- ret = isst_send_mbox_command(cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req,
- &resp);
- if (ret)
- return ret;
-
- debug_printf("cpu:%d WRITE_PM_CONFIG resp:%x\n", cpu, resp);
+static struct isst_platform_ops *isst_ops;
+
+#define CHECK_CB(_name) \
+ do { \
+ if (!isst_ops || !isst_ops->_name) { \
+ fprintf(stderr, "Invalid ops\n"); \
+ exit(0); \
+ } \
+ } while (0)
+
+int isst_set_platform_ops(int api_version)
+{
+ switch (api_version) {
+ case 1:
+ isst_ops = mbox_get_platform_ops();
+ break;
+ case 2:
+ case 3:
+ isst_ops = tpmi_get_platform_ops();
+ break;
+ default:
+ isst_ops = NULL;
+ break;
+ }
+ if (!isst_ops)
+ return -1;
return 0;
}
-int isst_read_pm_config(int cpu, int *cp_state, int *cp_cap)
+void isst_update_platform_param(enum isst_platform_param param, int value)
{
- unsigned int resp;
- int ret;
+ CHECK_CB(update_platform_param);
- ret = isst_send_mbox_command(cpu, READ_PM_CONFIG, PM_FEATURE, 0, 0,
- &resp);
- if (ret)
- return ret;
-
- debug_printf("cpu:%d READ_PM_CONFIG resp:%x\n", cpu, resp);
-
- *cp_state = resp & BIT(16);
- *cp_cap = resp & BIT(0) ? 1 : 0;
-
- return 0;
+ isst_ops->update_platform_param(param, value);
}
-int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev)
+int isst_get_disp_freq_multiplier(void)
{
- unsigned int resp;
- int ret;
-
- ret = isst_send_mbox_command(cpu, CONFIG_TDP,
- CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp);
- if (ret) {
- pkg_dev->levels = 0;
- pkg_dev->locked = 1;
- pkg_dev->current_level = 0;
- pkg_dev->version = 0;
- pkg_dev->enabled = 0;
- return 0;
- }
+ CHECK_CB(get_disp_freq_multiplier);
+ return isst_ops->get_disp_freq_multiplier();
+}
- debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", cpu, resp);
+int isst_get_trl_max_levels(void)
+{
+ CHECK_CB(get_trl_max_levels);
+ return isst_ops->get_trl_max_levels();
+}
- pkg_dev->version = resp & 0xff;
- pkg_dev->levels = (resp >> 8) & 0xff;
- pkg_dev->current_level = (resp >> 16) & 0xff;
- pkg_dev->locked = !!(resp & BIT(24));
- pkg_dev->enabled = !!(resp & BIT(31));
+char *isst_get_trl_level_name(int level)
+{
+ CHECK_CB(get_trl_level_name);
+ return isst_ops->get_trl_level_name(level);
+}
- return 0;
+int isst_is_punit_valid(struct isst_id *id)
+{
+ CHECK_CB(is_punit_valid);
+ return isst_ops->is_punit_valid(id);
}
-int isst_get_ctdp_control(int cpu, int config_index,
- struct isst_pkg_ctdp_level_info *ctdp_level)
+int isst_send_msr_command(unsigned int cpu, unsigned int msr, int write,
+ unsigned long long *req_resp)
{
- int cp_state, cp_cap;
- unsigned int resp;
- int ret;
+ struct isst_if_msr_cmds msr_cmds;
+ const char *pathname = "/dev/isst_interface";
+ FILE *outf = get_output_file();
+ int fd;
- ret = isst_send_mbox_command(cpu, CONFIG_TDP,
- CONFIG_TDP_GET_TDP_CONTROL, 0,
- config_index, &resp);
- if (ret)
- return ret;
+ fd = open(pathname, O_RDWR);
+ if (fd < 0)
+ err(-1, "%s open failed", pathname);
- ctdp_level->fact_support = resp & BIT(0);
- ctdp_level->pbf_support = !!(resp & BIT(1));
- ctdp_level->fact_enabled = !!(resp & BIT(16));
- ctdp_level->pbf_enabled = !!(resp & BIT(17));
+ msr_cmds.cmd_count = 1;
+ msr_cmds.msr_cmd[0].logical_cpu = cpu;
+ msr_cmds.msr_cmd[0].msr = msr;
+ msr_cmds.msr_cmd[0].read_write = write;
+ if (write)
+ msr_cmds.msr_cmd[0].data = *req_resp;
- ret = isst_read_pm_config(cpu, &cp_state, &cp_cap);
- if (ret) {
- debug_printf("cpu:%d pm_config is not supported \n", cpu);
+ if (ioctl(fd, ISST_IF_MSR_COMMAND, &msr_cmds) == -1) {
+ perror("ISST_IF_MSR_COMMAND");
+ fprintf(outf, "Error: msr_cmd cpu:%d msr:%x read_write:%d\n",
+ cpu, msr, write);
} else {
- debug_printf("cpu:%d pm_config SST-CP state:%d cap:%d \n", cpu, cp_state, cp_cap);
- ctdp_level->sst_cp_support = cp_cap;
- ctdp_level->sst_cp_enabled = cp_state;
- }
-
- debug_printf(
- "cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
- cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support,
- ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
+ if (!write)
+ *req_resp = msr_cmds.msr_cmd[0].data;
- return 0;
-}
-
-int isst_get_tdp_info(int cpu, int config_index,
- struct isst_pkg_ctdp_level_info *ctdp_level)
-{
- unsigned int resp;
- int ret;
-
- ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_INFO,
- 0, config_index, &resp);
- if (ret) {
- isst_display_error_info_message(1, "Invalid level, Can't get TDP information at level", 1, config_index);
- return ret;
+ debug_printf(
+ "msr_cmd response: cpu:%d msr:%x rd_write:%x resp:%llx %llx\n",
+ cpu, msr, write, *req_resp, msr_cmds.msr_cmd[0].data);
}
- ctdp_level->pkg_tdp = resp & GENMASK(14, 0);
- ctdp_level->tdp_ratio = (resp & GENMASK(23, 16)) >> 16;
+ close(fd);
- debug_printf(
- "cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO resp:%x tdp_ratio:%d pkg_tdp:%d\n",
- cpu, config_index, resp, ctdp_level->tdp_ratio,
- ctdp_level->pkg_tdp);
return 0;
}
-int isst_get_pwr_info(int cpu, int config_index,
- struct isst_pkg_ctdp_level_info *ctdp_level)
+int isst_read_pm_config(struct isst_id *id, int *cp_state, int *cp_cap)
{
- unsigned int resp;
- int ret;
-
- ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_PWR_INFO,
- 0, config_index, &resp);
- if (ret)
- return ret;
-
- ctdp_level->pkg_max_power = resp & GENMASK(14, 0);
- ctdp_level->pkg_min_power = (resp & GENMASK(30, 16)) >> 16;
-
- debug_printf(
- "cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO resp:%x pkg_max_power:%d pkg_min_power:%d\n",
- cpu, config_index, resp, ctdp_level->pkg_max_power,
- ctdp_level->pkg_min_power);
-
- return 0;
+ CHECK_CB(read_pm_config);
+ return isst_ops->read_pm_config(id, cp_state, cp_cap);
}
-void isst_get_uncore_p0_p1_info(int cpu, int config_index,
- struct isst_pkg_ctdp_level_info *ctdp_level)
+int isst_get_ctdp_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)
{
- unsigned int resp;
- int ret;
- ret = isst_send_mbox_command(cpu, CONFIG_TDP,
- CONFIG_TDP_GET_UNCORE_P0_P1_INFO, 0,
- config_index, &resp);
- if (ret) {
- ctdp_level->uncore_p0 = 0;
- ctdp_level->uncore_p1 = 0;
- return;
- }
-
- ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
- ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
- debug_printf(
- "cpu:%d ctdp:%d CONFIG_TDP_GET_UNCORE_P0_P1_INFO resp:%x uncore p0:%d uncore p1:%d\n",
- cpu, config_index, resp, ctdp_level->uncore_p0,
- ctdp_level->uncore_p1);
+ CHECK_CB(get_config_levels);
+ return isst_ops->get_config_levels(id, pkg_dev);
}
-void isst_get_p1_info(int cpu, int config_index,
- struct isst_pkg_ctdp_level_info *ctdp_level)
+int isst_get_ctdp_control(struct isst_id *id, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
{
- unsigned int resp;
- int ret;
- ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_P1_INFO, 0,
- config_index, &resp);
- if (ret) {
- ctdp_level->sse_p1 = 0;
- ctdp_level->avx2_p1 = 0;
- ctdp_level->avx512_p1 = 0;
- return;
- }
-
- ctdp_level->sse_p1 = resp & GENMASK(7, 0);
- ctdp_level->avx2_p1 = (resp & GENMASK(15, 8)) >> 8;
- ctdp_level->avx512_p1 = (resp & GENMASK(23, 16)) >> 16;
- debug_printf(
- "cpu:%d ctdp:%d CONFIG_TDP_GET_P1_INFO resp:%x sse_p1:%d avx2_p1:%d avx512_p1:%d\n",
- cpu, config_index, resp, ctdp_level->sse_p1,
- ctdp_level->avx2_p1, ctdp_level->avx512_p1);
+ CHECK_CB(get_ctdp_control);
+ return isst_ops->get_ctdp_control(id, config_index, ctdp_level);
}
-void isst_get_uncore_mem_freq(int cpu, int config_index,
- struct isst_pkg_ctdp_level_info *ctdp_level)
+int isst_get_tdp_info(struct isst_id *id, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
{
- unsigned int resp;
- int ret;
- ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_MEM_FREQ,
- 0, config_index, &resp);
- if (ret) {
- ctdp_level->mem_freq = 0;
- return;
- }
-
- ctdp_level->mem_freq = resp & GENMASK(7, 0);
- debug_printf(
- "cpu:%d ctdp:%d CONFIG_TDP_GET_MEM_FREQ resp:%x uncore mem_freq:%d\n",
- cpu, config_index, resp, ctdp_level->mem_freq);
+ CHECK_CB(get_tdp_info);
+ return isst_ops->get_tdp_info(id, config_index, ctdp_level);
}
-int isst_get_tjmax_info(int cpu, int config_index,
- struct isst_pkg_ctdp_level_info *ctdp_level)
+int isst_get_pwr_info(struct isst_id *id, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
{
- unsigned int resp;
- int ret;
-
- ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_TJMAX_INFO,
- 0, config_index, &resp);
- if (ret)
- return ret;
-
- ctdp_level->t_proc_hot = resp & GENMASK(7, 0);
-
- debug_printf(
- "cpu:%d ctdp:%d CONFIG_TDP_GET_TJMAX_INFO resp:%x t_proc_hot:%d\n",
- cpu, config_index, resp, ctdp_level->t_proc_hot);
-
- return 0;
+ CHECK_CB(get_pwr_info);
+ return isst_ops->get_pwr_info(id, config_index, ctdp_level);
}
-int isst_get_coremask_info(int cpu, int config_index,
+int isst_get_coremask_info(struct isst_id *id, int config_index,
struct isst_pkg_ctdp_level_info *ctdp_level)
{
- unsigned int resp;
- int i, ret;
-
- ctdp_level->cpu_count = 0;
- for (i = 0; i < 2; ++i) {
- unsigned long long mask;
- int cpu_count = 0;
-
- ret = isst_send_mbox_command(cpu, CONFIG_TDP,
- CONFIG_TDP_GET_CORE_MASK, 0,
- (i << 8) | config_index, &resp);
- if (ret)
- return ret;
-
- debug_printf(
- "cpu:%d ctdp:%d mask:%d CONFIG_TDP_GET_CORE_MASK resp:%x\n",
- cpu, config_index, i, resp);
-
- mask = (unsigned long long)resp << (32 * i);
- set_cpu_mask_from_punit_coremask(cpu, mask,
- ctdp_level->core_cpumask_size,
- ctdp_level->core_cpumask,
- &cpu_count);
- ctdp_level->cpu_count += cpu_count;
- debug_printf("cpu:%d ctdp:%d mask:%d cpu count:%d\n", cpu,
- config_index, i, ctdp_level->cpu_count);
- }
-
- return 0;
+ CHECK_CB(get_coremask_info);
+ return isst_ops->get_coremask_info(id, config_index, ctdp_level);
}
-int isst_get_get_trl_from_msr(int cpu, int *trl)
+int isst_get_get_trl_from_msr(struct isst_id *id, int *trl)
{
unsigned long long msr_trl;
int ret;
- ret = isst_send_msr_command(cpu, 0x1AD, 0, &msr_trl);
+ ret = isst_send_msr_command(id->cpu, 0x1AD, 0, &msr_trl);
if (ret)
return ret;
@@ -289,117 +165,37 @@ int isst_get_get_trl_from_msr(int cpu, int *trl)
return 0;
}
-int isst_get_get_trl(int cpu, int level, int avx_level, int *trl)
+int isst_get_get_trl(struct isst_id *id, int level, int avx_level, int *trl)
{
- unsigned int req, resp;
- int ret;
-
- req = level | (avx_level << 16);
- ret = isst_send_mbox_command(cpu, CONFIG_TDP,
- CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
- &resp);
- if (ret)
- return ret;
-
- debug_printf(
- "cpu:%d CONFIG_TDP_GET_TURBO_LIMIT_RATIOS req:%x resp:%x\n",
- cpu, req, resp);
-
- trl[0] = resp & GENMASK(7, 0);
- trl[1] = (resp & GENMASK(15, 8)) >> 8;
- trl[2] = (resp & GENMASK(23, 16)) >> 16;
- trl[3] = (resp & GENMASK(31, 24)) >> 24;
-
- req = level | BIT(8) | (avx_level << 16);
- ret = isst_send_mbox_command(cpu, CONFIG_TDP,
- CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
- &resp);
- if (ret)
- return ret;
-
- debug_printf("cpu:%d CONFIG_TDP_GET_TURBO_LIMIT req:%x resp:%x\n", cpu,
- req, resp);
-
- trl[4] = resp & GENMASK(7, 0);
- trl[5] = (resp & GENMASK(15, 8)) >> 8;
- trl[6] = (resp & GENMASK(23, 16)) >> 16;
- trl[7] = (resp & GENMASK(31, 24)) >> 24;
-
- return 0;
+ CHECK_CB(get_get_trl);
+ return isst_ops->get_get_trl(id, level, avx_level, trl);
}
-int isst_get_trl_bucket_info(int cpu, unsigned long long *buckets_info)
+int isst_get_get_trls(struct isst_id *id, int level, struct isst_pkg_ctdp_level_info *ctdp_level)
{
- int ret;
-
- debug_printf("cpu:%d bucket info via MSR\n", cpu);
-
- *buckets_info = 0;
-
- ret = isst_send_msr_command(cpu, 0x1ae, 0, buckets_info);
- if (ret)
- return ret;
-
- debug_printf("cpu:%d bucket info via MSR successful 0x%llx\n", cpu,
- *buckets_info);
-
- return 0;
+ CHECK_CB(get_get_trls);
+ return isst_ops->get_get_trls(id, level, ctdp_level);
}
-int isst_set_tdp_level_msr(int cpu, int tdp_level)
+int isst_get_trl_bucket_info(struct isst_id *id, int level, unsigned long long *buckets_info)
{
- unsigned long long level = tdp_level;
- int ret;
-
- debug_printf("cpu: tdp_level via MSR %d\n", cpu, tdp_level);
-
- if (isst_get_config_tdp_lock_status(cpu)) {
- isst_display_error_info_message(1, "tdp_locked", 0, 0);
- return -1;
- }
-
- if (tdp_level > 2)
- return -1; /* invalid value */
-
- ret = isst_send_msr_command(cpu, 0x64b, 1, &level);
- if (ret)
- return ret;
-
- debug_printf("cpu: tdp_level via MSR successful %d\n", cpu, tdp_level);
-
- return 0;
+ CHECK_CB(get_trl_bucket_info);
+ return isst_ops->get_trl_bucket_info(id, level, buckets_info);
}
-int isst_set_tdp_level(int cpu, int tdp_level)
+int isst_set_tdp_level(struct isst_id *id, int tdp_level)
{
- unsigned int resp;
- int ret;
-
-
- if (isst_get_config_tdp_lock_status(cpu)) {
- isst_display_error_info_message(1, "TDP is locked", 0, 0);
- return -1;
-
- }
-
- ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_SET_LEVEL, 0,
- tdp_level, &resp);
- if (ret) {
- isst_display_error_info_message(1, "Set TDP level failed for level", 1, tdp_level);
- return ret;
- }
-
- return 0;
+ CHECK_CB(set_tdp_level);
+ return isst_ops->set_tdp_level(id, tdp_level);
}
-int isst_get_pbf_info(int cpu, int level, struct isst_pbf_info *pbf_info)
+int isst_get_pbf_info(struct isst_id *id, int level, struct isst_pbf_info *pbf_info)
{
struct isst_pkg_ctdp_level_info ctdp_level;
struct isst_pkg_ctdp pkg_dev;
- int i, ret, core_cnt, max;
- unsigned int req, resp;
+ int ret;
- ret = isst_get_ctdp_levels(cpu, &pkg_dev);
+ ret = isst_get_ctdp_levels(id, &pkg_dev);
if (ret) {
isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
return ret;
@@ -410,7 +206,7 @@ int isst_get_pbf_info(int cpu, int level, struct isst_pbf_info *pbf_info)
return -1;
}
- ret = isst_get_ctdp_control(cpu, level, &ctdp_level);
+ ret = isst_get_ctdp_control(id, level, &ctdp_level);
if (ret)
return ret;
@@ -421,196 +217,25 @@ int isst_get_pbf_info(int cpu, int level, struct isst_pbf_info *pbf_info)
pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask);
- core_cnt = get_core_count(get_physical_package_id(cpu), get_physical_die_id(cpu));
- max = core_cnt > 32 ? 2 : 1;
-
- for (i = 0; i < max; ++i) {
- unsigned long long mask;
- int count;
-
- ret = isst_send_mbox_command(cpu, CONFIG_TDP,
- CONFIG_TDP_PBF_GET_CORE_MASK_INFO,
- 0, (i << 8) | level, &resp);
- if (ret)
- break;
-
- debug_printf(
- "cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n",
- cpu, resp);
-
- mask = (unsigned long long)resp << (32 * i);
- set_cpu_mask_from_punit_coremask(cpu, mask,
- pbf_info->core_cpumask_size,
- pbf_info->core_cpumask,
- &count);
- }
-
- req = level;
- ret = isst_send_mbox_command(cpu, CONFIG_TDP,
- CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO, 0, req,
- &resp);
- if (ret)
- return ret;
-
- debug_printf("cpu:%d CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO resp:%x\n", cpu,
- resp);
-
- pbf_info->p1_low = resp & 0xff;
- pbf_info->p1_high = (resp & GENMASK(15, 8)) >> 8;
-
- req = level;
- ret = isst_send_mbox_command(
- cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TDP_INFO, 0, req, &resp);
- if (ret)
- return ret;
-
- debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TDP_INFO resp:%x\n", cpu, resp);
-
- pbf_info->tdp = resp & 0xffff;
-
- req = level;
- ret = isst_send_mbox_command(
- cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TJ_MAX_INFO, 0, req, &resp);
- if (ret)
- return ret;
-
- debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TJ_MAX_INFO resp:%x\n", cpu,
- resp);
- pbf_info->t_control = (resp >> 8) & 0xff;
- pbf_info->t_prochot = resp & 0xff;
-
- return 0;
+ CHECK_CB(get_pbf_info);
+ return isst_ops->get_pbf_info(id, level, pbf_info);
}
-void isst_get_pbf_info_complete(struct isst_pbf_info *pbf_info)
+int isst_set_pbf_fact_status(struct isst_id *id, int pbf, int enable)
{
- free_cpu_set(pbf_info->core_cpumask);
+ CHECK_CB(set_pbf_fact_status);
+ return isst_ops->set_pbf_fact_status(id, pbf, enable);
}
-int isst_set_pbf_fact_status(int cpu, int pbf, int enable)
-{
- struct isst_pkg_ctdp pkg_dev;
- struct isst_pkg_ctdp_level_info ctdp_level;
- int current_level;
- unsigned int req = 0, resp;
- int ret;
-
- ret = isst_get_ctdp_levels(cpu, &pkg_dev);
- if (ret)
- debug_printf("cpu:%d No support for dynamic ISST\n", cpu);
-
- current_level = pkg_dev.current_level;
-
- ret = isst_get_ctdp_control(cpu, current_level, &ctdp_level);
- if (ret)
- return ret;
-
- if (pbf) {
- if (ctdp_level.fact_enabled)
- req = BIT(16);
-
- if (enable)
- req |= BIT(17);
- else
- req &= ~BIT(17);
- } else {
-
- if (enable && !ctdp_level.sst_cp_enabled)
- isst_display_error_info_message(0, "Make sure to execute before: core-power enable", 0, 0);
- if (ctdp_level.pbf_enabled)
- req = BIT(17);
- if (enable)
- req |= BIT(16);
- else
- req &= ~BIT(16);
- }
-
- ret = isst_send_mbox_command(cpu, CONFIG_TDP,
- CONFIG_TDP_SET_TDP_CONTROL, 0, req, &resp);
- if (ret)
- return ret;
-
- debug_printf("cpu:%d CONFIG_TDP_SET_TDP_CONTROL pbf/fact:%d req:%x\n",
- cpu, pbf, req);
-
- return 0;
-}
-
-int isst_get_fact_bucket_info(int cpu, int level,
- struct isst_fact_bucket_info *bucket_info)
-{
- unsigned int resp;
- int i, k, ret;
-
- for (i = 0; i < 2; ++i) {
- int j;
-
- ret = isst_send_mbox_command(
- cpu, CONFIG_TDP,
- CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES, 0,
- (i << 8) | level, &resp);
- if (ret)
- return ret;
-
- debug_printf(
- "cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES index:%d level:%d resp:%x\n",
- cpu, i, level, resp);
-
- for (j = 0; j < 4; ++j) {
- bucket_info[j + (i * 4)].high_priority_cores_count =
- (resp >> (j * 8)) & 0xff;
- }
- }
-
- for (k = 0; k < 3; ++k) {
- for (i = 0; i < 2; ++i) {
- int j;
-
- ret = isst_send_mbox_command(
- cpu, CONFIG_TDP,
- CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS, 0,
- (k << 16) | (i << 8) | level, &resp);
- if (ret)
- return ret;
-
- debug_printf(
- "cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS index:%d level:%d avx:%d resp:%x\n",
- cpu, i, level, k, resp);
-
- for (j = 0; j < 4; ++j) {
- switch (k) {
- case 0:
- bucket_info[j + (i * 4)].sse_trl =
- (resp >> (j * 8)) & 0xff;
- break;
- case 1:
- bucket_info[j + (i * 4)].avx_trl =
- (resp >> (j * 8)) & 0xff;
- break;
- case 2:
- bucket_info[j + (i * 4)].avx512_trl =
- (resp >> (j * 8)) & 0xff;
- break;
- default:
- break;
- }
- }
- }
- }
-
- return 0;
-}
-
-int isst_get_fact_info(int cpu, int level, int fact_bucket, struct isst_fact_info *fact_info)
+int isst_get_fact_info(struct isst_id *id, int level, int fact_bucket, struct isst_fact_info *fact_info)
{
struct isst_pkg_ctdp_level_info ctdp_level;
struct isst_pkg_ctdp pkg_dev;
- unsigned int resp;
- int j, ret, print;
+ int ret;
- ret = isst_get_ctdp_levels(cpu, &pkg_dev);
+ ret = isst_get_ctdp_levels(id, &pkg_dev);
if (ret) {
isst_display_error_info_message(1, "Failed to get number of levels", 0, 0);
return ret;
@@ -621,7 +246,7 @@ int isst_get_fact_info(int cpu, int level, int fact_bucket, struct isst_fact_inf
return -1;
}
- ret = isst_get_ctdp_control(cpu, level, &ctdp_level);
+ ret = isst_get_ctdp_control(id, level, &ctdp_level);
if (ret)
return ret;
@@ -629,61 +254,45 @@ int isst_get_fact_info(int cpu, int level, int fact_bucket, struct isst_fact_inf
isst_display_error_info_message(1, "turbo-freq feature is not present at this level", 1, level);
return -1;
}
+ CHECK_CB(get_fact_info);
+ return isst_ops->get_fact_info(id, level, fact_bucket, fact_info);
+}
- ret = isst_send_mbox_command(cpu, CONFIG_TDP,
- CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO, 0,
- level, &resp);
- if (ret)
- return ret;
-
- debug_printf("cpu:%d CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO resp:%x\n",
- cpu, resp);
-
- fact_info->lp_clipping_ratio_license_sse = resp & 0xff;
- fact_info->lp_clipping_ratio_license_avx2 = (resp >> 8) & 0xff;
- fact_info->lp_clipping_ratio_license_avx512 = (resp >> 16) & 0xff;
+int isst_get_trl(struct isst_id *id, unsigned long long *trl)
+{
+ int ret;
- ret = isst_get_fact_bucket_info(cpu, level, fact_info->bucket_info);
+ ret = isst_send_msr_command(id->cpu, 0x1AD, 0, trl);
if (ret)
return ret;
- print = 0;
- for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
- if (fact_bucket != 0xff && fact_bucket != j)
- continue;
-
- if (!fact_info->bucket_info[j].high_priority_cores_count)
- break;
-
- print = 1;
- }
- if (!print) {
- isst_display_error_info_message(1, "Invalid bucket", 0, 0);
- return -1;
- }
-
return 0;
}
-int isst_set_trl(int cpu, unsigned long long trl)
+int isst_set_trl(struct isst_id *id, unsigned long long trl)
{
int ret;
if (!trl)
trl = 0xFFFFFFFFFFFFFFFFULL;
- ret = isst_send_msr_command(cpu, 0x1AD, 1, &trl);
+ ret = isst_send_msr_command(id->cpu, 0x1AD, 1, &trl);
if (ret)
return ret;
return 0;
}
-int isst_set_trl_from_current_tdp(int cpu, unsigned long long trl)
+#define MSR_TRL_FREQ_MULTIPLIER 100
+
+int isst_set_trl_from_current_tdp(struct isst_id *id, unsigned long long trl)
{
unsigned long long msr_trl;
int ret;
+ if (id->cpu < 0)
+ return 0;
+
if (trl) {
msr_trl = trl;
} else {
@@ -691,11 +300,11 @@ int isst_set_trl_from_current_tdp(int cpu, unsigned long long trl)
int trl[8];
int i;
- ret = isst_get_ctdp_levels(cpu, &pkg_dev);
+ ret = isst_get_ctdp_levels(id, &pkg_dev);
if (ret)
return ret;
- ret = isst_get_get_trl(cpu, pkg_dev.current_level, 0, trl);
+ ret = isst_get_get_trl(id, pkg_dev.current_level, 0, trl);
if (ret)
return ret;
@@ -703,10 +312,14 @@ int isst_set_trl_from_current_tdp(int cpu, unsigned long long trl)
for (i = 0; i < 8; ++i) {
unsigned long long _trl = trl[i];
+ /* MSR is always in 100 MHz unit */
+ if (isst_get_disp_freq_multiplier() == 1)
+ _trl /= MSR_TRL_FREQ_MULTIPLIER;
+
msr_trl |= (_trl << (i * 8));
}
}
- ret = isst_send_msr_command(cpu, 0x1AD, 1, &msr_trl);
+ ret = isst_send_msr_command(id->cpu, 0x1AD, 1, &msr_trl);
if (ret)
return ret;
@@ -714,12 +327,12 @@ int isst_set_trl_from_current_tdp(int cpu, unsigned long long trl)
}
/* Return 1 if locked */
-int isst_get_config_tdp_lock_status(int cpu)
+int isst_get_config_tdp_lock_status(struct isst_id *id)
{
unsigned long long tdp_control = 0;
int ret;
- ret = isst_send_msr_command(cpu, 0x64b, 0, &tdp_control);
+ ret = isst_send_msr_command(id->cpu, 0x64b, 0, &tdp_control);
if (ret)
return ret;
@@ -728,7 +341,7 @@ int isst_get_config_tdp_lock_status(int cpu)
return ret;
}
-void isst_get_process_ctdp_complete(int cpu, struct isst_pkg_ctdp *pkg_dev)
+void isst_get_process_ctdp_complete(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)
{
int i;
@@ -745,19 +358,26 @@ void isst_get_process_ctdp_complete(int cpu, struct isst_pkg_ctdp *pkg_dev)
}
}
-int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev)
+void isst_adjust_uncore_freq(struct isst_id *id, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ CHECK_CB(adjust_uncore_freq);
+ return isst_ops->adjust_uncore_freq(id, config_index, ctdp_level);
+}
+
+int isst_get_process_ctdp(struct isst_id *id, int tdp_level, struct isst_pkg_ctdp *pkg_dev)
{
int i, ret, valid = 0;
if (pkg_dev->processed)
return 0;
- ret = isst_get_ctdp_levels(cpu, pkg_dev);
+ ret = isst_get_ctdp_levels(id, pkg_dev);
if (ret)
return ret;
debug_printf("cpu: %d ctdp enable:%d current level: %d levels:%d\n",
- cpu, pkg_dev->enabled, pkg_dev->current_level,
+ id->cpu, pkg_dev->enabled, pkg_dev->current_level,
pkg_dev->levels);
if (tdp_level != 0xff && tdp_level > pkg_dev->levels) {
@@ -774,16 +394,16 @@ int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev)
if (tdp_level != 0xff && i != tdp_level)
continue;
- debug_printf("cpu:%d Get Information for TDP level:%d\n", cpu,
+ debug_printf("cpu:%d Get Information for TDP level:%d\n", id->cpu,
i);
ctdp_level = &pkg_dev->ctdp_level[i];
ctdp_level->level = i;
- ctdp_level->control_cpu = cpu;
- ctdp_level->pkg_id = get_physical_package_id(cpu);
- ctdp_level->die_id = get_physical_die_id(cpu);
+ ctdp_level->control_cpu = id->cpu;
+ ctdp_level->pkg_id = id->pkg;
+ ctdp_level->die_id = id->die;
- ret = isst_get_ctdp_control(cpu, i, ctdp_level);
+ ret = isst_get_ctdp_control(id, i, ctdp_level);
if (ret)
continue;
@@ -792,257 +412,94 @@ int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev)
ctdp_level->processed = 1;
if (ctdp_level->pbf_support) {
- ret = isst_get_pbf_info(cpu, i, &ctdp_level->pbf_info);
+ ret = isst_get_pbf_info(id, i, &ctdp_level->pbf_info);
if (!ret)
ctdp_level->pbf_found = 1;
}
if (ctdp_level->fact_support) {
- ret = isst_get_fact_info(cpu, i, 0xff,
+ ret = isst_get_fact_info(id, i, 0xff,
&ctdp_level->fact_info);
if (ret)
return ret;
}
- if (!pkg_dev->enabled) {
+ if (!pkg_dev->enabled && is_skx_based_platform()) {
int freq;
- freq = get_cpufreq_base_freq(cpu);
+ freq = get_cpufreq_base_freq(id->cpu);
if (freq > 0) {
ctdp_level->sse_p1 = freq / 100000;
ctdp_level->tdp_ratio = ctdp_level->sse_p1;
}
- isst_get_get_trl_from_msr(cpu, ctdp_level->trl_sse_active_cores);
- isst_get_trl_bucket_info(cpu, &ctdp_level->buckets_info);
+ isst_get_get_trl_from_msr(id, ctdp_level->trl_ratios[0]);
+ isst_get_trl_bucket_info(id, i, &ctdp_level->trl_cores);
continue;
}
- ret = isst_get_tdp_info(cpu, i, ctdp_level);
- if (ret)
- return ret;
-
- ret = isst_get_pwr_info(cpu, i, ctdp_level);
+ ret = isst_get_tdp_info(id, i, ctdp_level);
if (ret)
return ret;
- ret = isst_get_tjmax_info(cpu, i, ctdp_level);
+ ret = isst_get_pwr_info(id, i, ctdp_level);
if (ret)
return ret;
ctdp_level->core_cpumask_size =
alloc_cpu_set(&ctdp_level->core_cpumask);
- ret = isst_get_coremask_info(cpu, i, ctdp_level);
+ ret = isst_get_coremask_info(id, i, ctdp_level);
if (ret)
return ret;
- ret = isst_get_trl_bucket_info(cpu, &ctdp_level->buckets_info);
+ ret = isst_get_trl_bucket_info(id, i, &ctdp_level->trl_cores);
if (ret)
return ret;
- ret = isst_get_get_trl(cpu, i, 0,
- ctdp_level->trl_sse_active_cores);
+ ret = isst_get_get_trls(id, i, ctdp_level);
if (ret)
return ret;
-
- ret = isst_get_get_trl(cpu, i, 1,
- ctdp_level->trl_avx_active_cores);
- if (ret)
- return ret;
-
- ret = isst_get_get_trl(cpu, i, 2,
- ctdp_level->trl_avx_512_active_cores);
- if (ret)
- return ret;
-
- isst_get_uncore_p0_p1_info(cpu, i, ctdp_level);
- isst_get_p1_info(cpu, i, ctdp_level);
- isst_get_uncore_mem_freq(cpu, i, ctdp_level);
}
if (!valid)
- isst_display_error_info_message(0, "Invalid level, Can't get TDP control information at specified levels on cpu", 1, cpu);
+ isst_display_error_info_message(0, "Invalid level, Can't get TDP control information at specified levels on cpu", 1, id->cpu);
return 0;
}
-int isst_clos_get_clos_information(int cpu, int *enable, int *type)
+int isst_clos_get_clos_information(struct isst_id *id, int *enable, int *type)
{
- unsigned int resp;
- int ret;
-
- ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
- &resp);
- if (ret)
- return ret;
-
- debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", cpu, resp);
-
- if (resp & BIT(1))
- *enable = 1;
- else
- *enable = 0;
-
- if (resp & BIT(2))
- *type = 1;
- else
- *type = 0;
-
- return 0;
+ CHECK_CB(get_clos_information);
+ return isst_ops->get_clos_information(id, enable, type);
}
-int isst_pm_qos_config(int cpu, int enable_clos, int priority_type)
+int isst_pm_qos_config(struct isst_id *id, int enable_clos, int priority_type)
{
- unsigned int req, resp;
- int ret;
-
- if (!enable_clos) {
- struct isst_pkg_ctdp pkg_dev;
- struct isst_pkg_ctdp_level_info ctdp_level;
-
- ret = isst_get_ctdp_levels(cpu, &pkg_dev);
- if (ret) {
- debug_printf("isst_get_ctdp_levels\n");
- return ret;
- }
-
- ret = isst_get_ctdp_control(cpu, pkg_dev.current_level,
- &ctdp_level);
- if (ret)
- return ret;
-
- if (ctdp_level.fact_enabled) {
- isst_display_error_info_message(1, "Ignoring request, turbo-freq feature is still enabled", 0, 0);
- return -EINVAL;
- }
- ret = isst_write_pm_config(cpu, 0);
- if (ret)
- isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
- } else {
- ret = isst_write_pm_config(cpu, 1);
- if (ret)
- isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
- }
-
- ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
- &resp);
- if (ret) {
- isst_display_error_info_message(1, "CLOS_PM_QOS_CONFIG command failed", 0, 0);
- return ret;
- }
-
- debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", cpu, resp);
-
- req = resp;
-
- if (enable_clos)
- req = req | BIT(1);
- else
- req = req & ~BIT(1);
-
- if (priority_type > 1)
- isst_display_error_info_message(1, "Invalid priority type: Changing type to ordered", 0, 0);
-
- if (priority_type)
- req = req | BIT(2);
- else
- req = req & ~BIT(2);
-
- ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG,
- BIT(MBOX_CMD_WRITE_BIT), req, &resp);
- if (ret)
- return ret;
-
- debug_printf("cpu:%d CLOS_PM_QOS_CONFIG priority type:%d req:%x\n", cpu,
- priority_type, req);
-
- return 0;
+ CHECK_CB(pm_qos_config);
+ return isst_ops->pm_qos_config(id, enable_clos, priority_type);
}
-int isst_pm_get_clos(int cpu, int clos, struct isst_clos_config *clos_config)
+int isst_pm_get_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
{
- unsigned int resp;
- int ret;
-
- ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_CLOS, clos, 0,
- &resp);
- if (ret)
- return ret;
-
- clos_config->pkg_id = get_physical_package_id(cpu);
- clos_config->die_id = get_physical_die_id(cpu);
-
- clos_config->epp = resp & 0x0f;
- clos_config->clos_prop_prio = (resp >> 4) & 0x0f;
- clos_config->clos_min = (resp >> 8) & 0xff;
- clos_config->clos_max = (resp >> 16) & 0xff;
- clos_config->clos_desired = (resp >> 24) & 0xff;
-
- return 0;
+ CHECK_CB(pm_get_clos);
+ return isst_ops->pm_get_clos(id, clos, clos_config);
}
-int isst_set_clos(int cpu, int clos, struct isst_clos_config *clos_config)
+int isst_set_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
{
- unsigned int req, resp;
- unsigned int param;
- int ret;
-
- req = clos_config->epp & 0x0f;
- req |= (clos_config->clos_prop_prio & 0x0f) << 4;
- req |= (clos_config->clos_min & 0xff) << 8;
- req |= (clos_config->clos_max & 0xff) << 16;
- req |= (clos_config->clos_desired & 0xff) << 24;
-
- param = BIT(MBOX_CMD_WRITE_BIT) | clos;
-
- ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_CLOS, param, req,
- &resp);
- if (ret)
- return ret;
-
- debug_printf("cpu:%d CLOS_PM_CLOS param:%x req:%x\n", cpu, param, req);
-
- return 0;
+ CHECK_CB(set_clos);
+ return isst_ops->set_clos(id, clos, clos_config);
}
-int isst_clos_get_assoc_status(int cpu, int *clos_id)
+int isst_clos_get_assoc_status(struct isst_id *id, int *clos_id)
{
- unsigned int resp;
- unsigned int param;
- int core_id, ret;
-
- core_id = find_phy_core_num(cpu);
- param = core_id;
-
- ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 0,
- &resp);
- if (ret)
- return ret;
-
- debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x resp:%x\n", cpu, param,
- resp);
- *clos_id = (resp >> 16) & 0x03;
-
- return 0;
+ CHECK_CB(clos_get_assoc_status);
+ return isst_ops->clos_get_assoc_status(id, clos_id);
}
-int isst_clos_associate(int cpu, int clos_id)
+int isst_clos_associate(struct isst_id *id, int clos_id)
{
- unsigned int req, resp;
- unsigned int param;
- int core_id, ret;
+ CHECK_CB(clos_associate);
+ return isst_ops->clos_associate(id, clos_id);
- req = (clos_id & 0x03) << 16;
- core_id = find_phy_core_num(cpu);
- param = BIT(MBOX_CMD_WRITE_BIT) | core_id;
-
- ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param,
- req, &resp);
- if (ret)
- return ret;
-
- debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x req:%x\n", cpu, param,
- req);
-
- return 0;
}
diff --git a/tools/power/x86/intel-speed-select/isst-daemon.c b/tools/power/x86/intel-speed-select/isst-daemon.c
new file mode 100644
index 000000000000..66df21b2b573
--- /dev/null
+++ b/tools/power/x86/intel-speed-select/isst-daemon.c
@@ -0,0 +1,256 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel Speed Select -- Allow speed select to daemonize
+ * Copyright (c) 2022 Intel Corporation.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/file.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <getopt.h>
+#include <signal.h>
+#include <time.h>
+
+#include "isst.h"
+
+static int per_package_levels_info[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE][MAX_PUNIT_PER_DIE];
+static time_t per_package_levels_tm[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE][MAX_PUNIT_PER_DIE];
+
+static void init_levels(void)
+{
+ int i, j, k;
+
+ for (i = 0; i < MAX_PACKAGE_COUNT; ++i)
+ for (j = 0; j < MAX_DIE_PER_PACKAGE; ++j)
+ for (k = 0; k < MAX_PUNIT_PER_DIE; ++k)
+ per_package_levels_info[i][j][k] = -1;
+}
+
+void process_level_change(struct isst_id *id)
+{
+ struct isst_pkg_ctdp_level_info ctdp_level;
+ struct isst_pkg_ctdp pkg_dev;
+ time_t tm;
+ int ret;
+
+ if (id->pkg < 0 || id->die < 0 || id->punit < 0) {
+ debug_printf("Invalid package/die info for cpu:%d\n", id->cpu);
+ return;
+ }
+
+ tm = time(NULL);
+ if (tm - per_package_levels_tm[id->pkg][id->die][id->punit] < 2)
+ return;
+
+ per_package_levels_tm[id->pkg][id->die][id->punit] = tm;
+
+ ret = isst_get_ctdp_levels(id, &pkg_dev);
+ if (ret) {
+ debug_printf("Can't get tdp levels for cpu:%d\n", id->cpu);
+ return;
+ }
+
+ debug_printf("Get Config level %d pkg:%d die:%d current_level:%d\n", id->cpu,
+ id->pkg, id->die, pkg_dev.current_level);
+
+ if (pkg_dev.locked) {
+ debug_printf("config TDP s locked \n");
+ return;
+ }
+
+ if (per_package_levels_info[id->pkg][id->die][id->punit] == pkg_dev.current_level)
+ return;
+
+ debug_printf("**Config level change for cpu:%d pkg:%d die:%d from %d to %d\n",
+ id->cpu, id->pkg, id->die, per_package_levels_info[id->pkg][id->die][id->punit],
+ pkg_dev.current_level);
+
+ per_package_levels_info[id->pkg][id->die][id->punit] = pkg_dev.current_level;
+
+ ctdp_level.core_cpumask_size =
+ alloc_cpu_set(&ctdp_level.core_cpumask);
+ ret = isst_get_coremask_info(id, pkg_dev.current_level, &ctdp_level);
+ if (ret) {
+ free_cpu_set(ctdp_level.core_cpumask);
+ debug_printf("Can't get core_mask:%d\n", id->cpu);
+ return;
+ }
+
+ if (use_cgroupv2()) {
+ int ret;
+
+ ret = enable_cpuset_controller();
+ if (ret)
+ goto use_offline;
+
+ isolate_cpus(id, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask,
+ pkg_dev.current_level, 0);
+
+ goto free_mask;
+ }
+
+use_offline:
+ if (ctdp_level.cpu_count) {
+ int i, max_cpus = get_topo_max_cpus();
+ for (i = 0; i < max_cpus; ++i) {
+ if (!is_cpu_in_power_domain(i, id))
+ continue;
+ if (CPU_ISSET_S(i, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask)) {
+ fprintf(stderr, "online cpu %d\n", i);
+ set_cpu_online_offline(i, 1);
+ } else {
+ fprintf(stderr, "offline cpu %d\n", i);
+ set_cpu_online_offline(i, 0);
+ }
+ }
+ }
+free_mask:
+ free_cpu_set(ctdp_level.core_cpumask);
+}
+
+static void _poll_for_config_change(struct isst_id *id, void *arg1, void *arg2,
+ void *arg3, void *arg4)
+{
+ process_level_change(id);
+}
+
+static void poll_for_config_change(void)
+{
+ for_each_online_power_domain_in_set(_poll_for_config_change, NULL, NULL,
+ NULL, NULL);
+}
+
+static int done = 0;
+static int pid_file_handle;
+
+static void signal_handler(int sig)
+{
+ switch (sig) {
+ case SIGINT:
+ case SIGTERM:
+ done = 1;
+ hfi_exit();
+ exit(0);
+ break;
+ default:
+ break;
+ }
+}
+
+static void daemonize(char *rundir, char *pidfile)
+{
+ int pid, sid, i;
+ char str[10];
+ struct sigaction sig_actions;
+ sigset_t sig_set;
+ int ret;
+
+ if (getppid() == 1)
+ return;
+
+ sigemptyset(&sig_set);
+ sigaddset(&sig_set, SIGCHLD);
+ sigaddset(&sig_set, SIGTSTP);
+ sigaddset(&sig_set, SIGTTOU);
+ sigaddset(&sig_set, SIGTTIN);
+ sigprocmask(SIG_BLOCK, &sig_set, NULL);
+
+ sig_actions.sa_handler = signal_handler;
+ sigemptyset(&sig_actions.sa_mask);
+ sig_actions.sa_flags = 0;
+
+ sigaction(SIGHUP, &sig_actions, NULL);
+ sigaction(SIGTERM, &sig_actions, NULL);
+ sigaction(SIGINT, &sig_actions, NULL);
+
+ pid = fork();
+ if (pid < 0) {
+ /* Could not fork */
+ exit(EXIT_FAILURE);
+ }
+ if (pid > 0)
+ exit(EXIT_SUCCESS);
+
+ umask(027);
+
+ sid = setsid();
+ if (sid < 0)
+ exit(EXIT_FAILURE);
+
+ /* close all descriptors */
+ for (i = getdtablesize(); i >= 0; --i)
+ close(i);
+
+ i = open("/dev/null", O_RDWR);
+ if (i < 0)
+ exit(EXIT_FAILURE);
+
+ ret = dup(i);
+ if (ret == -1)
+ exit(EXIT_FAILURE);
+
+ ret = chdir(rundir);
+ if (ret == -1)
+ exit(EXIT_FAILURE);
+
+ pid_file_handle = open(pidfile, O_RDWR | O_CREAT, 0600);
+ if (pid_file_handle == -1) {
+ /* Couldn't open lock file */
+ exit(1);
+ }
+ /* Try to lock file */
+#ifdef LOCKF_SUPPORT
+ if (lockf(pid_file_handle, F_TLOCK, 0) == -1) {
+#else
+ if (flock(pid_file_handle, LOCK_EX|LOCK_NB) < 0) {
+#endif
+ /* Couldn't get lock on lock file */
+ fprintf(stderr, "Couldn't get lock file %d\n", getpid());
+ exit(1);
+ }
+ snprintf(str, sizeof(str), "%d\n", getpid());
+ ret = write(pid_file_handle, str, strlen(str));
+ if (ret == -1)
+ exit(EXIT_FAILURE);
+
+ close(i);
+}
+
+int isst_daemon(int debug_mode, int poll_interval, int no_daemon)
+{
+ int ret;
+
+ if (!no_daemon && poll_interval < 0 && !debug_mode) {
+ fprintf(stderr, "OOB mode is enabled and will run as daemon\n");
+ daemonize((char *) "/tmp/",
+ (char *)"/tmp/hfi-events.pid");
+ } else {
+ signal(SIGINT, signal_handler);
+ }
+
+ init_levels();
+
+ if (poll_interval < 0) {
+ ret = hfi_main();
+ if (ret) {
+ fprintf(stderr, "HFI initialization failed\n");
+ }
+ fprintf(stderr, "Must specify poll-interval\n");
+ return ret;
+ }
+
+ debug_printf("Starting loop\n");
+ while (!done) {
+ sleep(poll_interval);
+ poll_for_config_change();
+ }
+
+ return 0;
+}
diff --git a/tools/power/x86/intel-speed-select/isst-display.c b/tools/power/x86/intel-speed-select/isst-display.c
index e105fece47b6..e4884eb02837 100644
--- a/tools/power/x86/intel-speed-select/isst-display.c
+++ b/tools/power/x86/intel-speed-select/isst-display.c
@@ -25,10 +25,14 @@ static void printcpulist(int str_len, char *str, int mask_size,
index = snprintf(&str[curr_index],
str_len - curr_index, ",");
curr_index += index;
+ if (curr_index >= str_len)
+ break;
}
index = snprintf(&str[curr_index], str_len - curr_index, "%d",
i);
curr_index += index;
+ if (curr_index >= str_len)
+ break;
first = 0;
}
}
@@ -64,10 +68,14 @@ static void printcpumask(int str_len, char *str, int mask_size,
index = snprintf(&str[curr_index], str_len - curr_index, "%08x",
mask[i]);
curr_index += index;
+ if (curr_index >= str_len)
+ break;
if (i) {
strncat(&str[curr_index], ",", str_len - curr_index);
curr_index++;
}
+ if (curr_index >= str_len)
+ break;
}
free(mask);
@@ -158,41 +166,67 @@ static void format_and_print(FILE *outf, int level, char *header, char *value)
last_level = level;
}
-static int print_package_info(int cpu, FILE *outf)
+static int print_package_info(struct isst_id *id, FILE *outf)
{
char header[256];
+ int level = 1;
if (out_format_is_json()) {
- snprintf(header, sizeof(header), "package-%d:die-%d:cpu-%d",
- get_physical_package_id(cpu), get_physical_die_id(cpu),
- cpu);
- format_and_print(outf, 1, header, NULL);
+ if (api_version() > 1) {
+ if (id->die < 0 && id->cpu < 0)
+ snprintf(header, sizeof(header),
+ "package-%d:die-IO:powerdomain-%d:cpu-None",
+ id->pkg, id->punit);
+ else if (id->cpu < 0)
+ snprintf(header, sizeof(header),
+ "package-%d:die-%d:powerdomain-%d:cpu-None",
+ id->pkg, id->die, id->punit);
+ else
+ snprintf(header, sizeof(header),
+ "package-%d:die-%d:powerdomain-%d:cpu-%d",
+ id->pkg, id->die, id->punit, id->cpu);
+ } else {
+ snprintf(header, sizeof(header), "package-%d:die-%d:cpu-%d",
+ id->pkg, id->die, id->cpu);
+ }
+ format_and_print(outf, level, header, NULL);
return 1;
}
- snprintf(header, sizeof(header), "package-%d",
- get_physical_package_id(cpu));
- format_and_print(outf, 1, header, NULL);
- snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu));
- format_and_print(outf, 2, header, NULL);
- snprintf(header, sizeof(header), "cpu-%d", cpu);
- format_and_print(outf, 3, header, NULL);
+ snprintf(header, sizeof(header), "package-%d", id->pkg);
+ format_and_print(outf, level++, header, NULL);
+ if (id->die < 0)
+ snprintf(header, sizeof(header), "die-IO");
+ else
+ snprintf(header, sizeof(header), "die-%d", id->die);
+ format_and_print(outf, level++, header, NULL);
+ if (api_version() > 1) {
+ snprintf(header, sizeof(header), "powerdomain-%d", id->punit);
+ format_and_print(outf, level++, header, NULL);
+ }
+
+ if (id->cpu < 0)
+ snprintf(header, sizeof(header), "cpu-None");
+ else
+ snprintf(header, sizeof(header), "cpu-%d", id->cpu);
+
+ format_and_print(outf, level, header, NULL);
- return 3;
+ return level;
}
-static void _isst_pbf_display_information(int cpu, FILE *outf, int level,
+static void _isst_pbf_display_information(struct isst_id *id, FILE *outf, int level,
struct isst_pbf_info *pbf_info,
int disp_level)
{
- char header[256];
- char value[256];
+ static char header[256];
+ static char value[1024];
snprintf(header, sizeof(header), "speed-select-base-freq-properties");
format_and_print(outf, disp_level, header, NULL);
snprintf(header, sizeof(header), "high-priority-base-frequency(MHz)");
snprintf(value, sizeof(value), "%d",
- pbf_info->p1_high * DISP_FREQ_MULTIPLIER);
+ pbf_info->p1_high * isst_get_disp_freq_multiplier());
format_and_print(outf, disp_level + 1, header, value);
snprintf(header, sizeof(header), "high-priority-cpu-mask");
@@ -208,7 +242,7 @@ static void _isst_pbf_display_information(int cpu, FILE *outf, int level,
snprintf(header, sizeof(header), "low-priority-base-frequency(MHz)");
snprintf(value, sizeof(value), "%d",
- pbf_info->p1_low * DISP_FREQ_MULTIPLIER);
+ pbf_info->p1_low * isst_get_disp_freq_multiplier());
format_and_print(outf, disp_level + 1, header, value);
if (is_clx_n_platform())
@@ -223,12 +257,13 @@ static void _isst_pbf_display_information(int cpu, FILE *outf, int level,
format_and_print(outf, disp_level + 1, header, value);
}
-static void _isst_fact_display_information(int cpu, FILE *outf, int level,
+static void _isst_fact_display_information(struct isst_id *id, FILE *outf, int level,
int fact_bucket, int fact_avx,
struct isst_fact_info *fact_info,
int base_level)
{
struct isst_fact_bucket_info *bucket_info = fact_info->bucket_info;
+ int trl_max_levels = isst_get_trl_max_levels();
char header[256];
char value[256];
int print = 0, j;
@@ -237,7 +272,8 @@ static void _isst_fact_display_information(int cpu, FILE *outf, int level,
if (fact_bucket != 0xff && fact_bucket != j)
continue;
- if (!bucket_info[j].high_priority_cores_count)
+ /* core count must be valid for CPU power domain */
+ if (!bucket_info[j].hp_cores && id->cpu >= 0)
break;
print = 1;
@@ -250,10 +286,12 @@ static void _isst_fact_display_information(int cpu, FILE *outf, int level,
snprintf(header, sizeof(header), "speed-select-turbo-freq-properties");
format_and_print(outf, base_level, header, NULL);
for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
+ int i;
+
if (fact_bucket != 0xff && fact_bucket != j)
continue;
- if (!bucket_info[j].high_priority_cores_count)
+ if (!bucket_info[j].hp_cores)
break;
snprintf(header, sizeof(header), "bucket-%d", j);
@@ -261,78 +299,49 @@ static void _isst_fact_display_information(int cpu, FILE *outf, int level,
snprintf(header, sizeof(header), "high-priority-cores-count");
snprintf(value, sizeof(value), "%d",
- bucket_info[j].high_priority_cores_count);
+ bucket_info[j].hp_cores);
format_and_print(outf, base_level + 2, header, value);
-
- if (fact_avx & 0x01) {
- snprintf(header, sizeof(header),
- "high-priority-max-frequency(MHz)");
- snprintf(value, sizeof(value), "%d",
- bucket_info[j].sse_trl * DISP_FREQ_MULTIPLIER);
- format_and_print(outf, base_level + 2, header, value);
- }
-
- if (fact_avx & 0x02) {
- snprintf(header, sizeof(header),
- "high-priority-max-avx2-frequency(MHz)");
- snprintf(value, sizeof(value), "%d",
- bucket_info[j].avx_trl * DISP_FREQ_MULTIPLIER);
- format_and_print(outf, base_level + 2, header, value);
- }
-
- if (fact_avx & 0x04) {
- snprintf(header, sizeof(header),
- "high-priority-max-avx512-frequency(MHz)");
+ for (i = 0; i < trl_max_levels; i++) {
+ if (!bucket_info[j].hp_ratios[i] || (fact_avx != 0xFF && !(fact_avx & (1 << i))))
+ continue;
+ if (i == 0 && api_version() == 1 && !is_emr_platform())
+ snprintf(header, sizeof(header),
+ "high-priority-max-frequency(MHz)");
+ else
+ snprintf(header, sizeof(header),
+ "high-priority-max-%s-frequency(MHz)", isst_get_trl_level_name(i));
snprintf(value, sizeof(value), "%d",
- bucket_info[j].avx512_trl *
- DISP_FREQ_MULTIPLIER);
+ bucket_info[j].hp_ratios[i] * isst_get_disp_freq_multiplier());
format_and_print(outf, base_level + 2, header, value);
}
}
snprintf(header, sizeof(header),
"speed-select-turbo-freq-clip-frequencies");
format_and_print(outf, base_level + 1, header, NULL);
- snprintf(header, sizeof(header), "low-priority-max-frequency(MHz)");
- snprintf(value, sizeof(value), "%d",
- fact_info->lp_clipping_ratio_license_sse *
- DISP_FREQ_MULTIPLIER);
- format_and_print(outf, base_level + 2, header, value);
- snprintf(header, sizeof(header),
- "low-priority-max-avx2-frequency(MHz)");
- snprintf(value, sizeof(value), "%d",
- fact_info->lp_clipping_ratio_license_avx2 *
- DISP_FREQ_MULTIPLIER);
- format_and_print(outf, base_level + 2, header, value);
- snprintf(header, sizeof(header),
- "low-priority-max-avx512-frequency(MHz)");
- snprintf(value, sizeof(value), "%d",
- fact_info->lp_clipping_ratio_license_avx512 *
- DISP_FREQ_MULTIPLIER);
- format_and_print(outf, base_level + 2, header, value);
+
+ for (j = 0; j < trl_max_levels; j++) {
+ if (!fact_info->lp_ratios[j])
+ continue;
+
+ /* No AVX level name for SSE to be consistent with previous formatting */
+ if (j == 0 && api_version() == 1 && !is_emr_platform())
+ snprintf(header, sizeof(header), "low-priority-max-frequency(MHz)");
+ else
+ snprintf(header, sizeof(header), "low-priority-max-%s-frequency(MHz)",
+ isst_get_trl_level_name(j));
+ snprintf(value, sizeof(value), "%d",
+ fact_info->lp_ratios[j] * isst_get_disp_freq_multiplier());
+ format_and_print(outf, base_level + 2, header, value);
+ }
}
-void isst_ctdp_display_core_info(int cpu, FILE *outf, char *prefix,
+void isst_ctdp_display_core_info(struct isst_id *id, FILE *outf, char *prefix,
unsigned int val, char *str0, char *str1)
{
- char header[256];
char value[256];
- int level = 1;
+ int level = print_package_info(id, outf);
- if (out_format_is_json()) {
- snprintf(header, sizeof(header), "package-%d:die-%d:cpu-%d",
- get_physical_package_id(cpu), get_physical_die_id(cpu),
- cpu);
- format_and_print(outf, level++, header, NULL);
- } else {
- snprintf(header, sizeof(header), "package-%d",
- get_physical_package_id(cpu));
- format_and_print(outf, level++, header, NULL);
- snprintf(header, sizeof(header), "die-%d",
- get_physical_die_id(cpu));
- format_and_print(outf, level++, header, NULL);
- snprintf(header, sizeof(header), "cpu-%d", cpu);
- format_and_print(outf, level++, header, NULL);
- }
+ level++;
if (str0 && !val)
snprintf(value, sizeof(value), "%s", str0);
@@ -345,20 +354,21 @@ void isst_ctdp_display_core_info(int cpu, FILE *outf, char *prefix,
format_and_print(outf, 1, NULL, NULL);
}
-void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
+void isst_ctdp_display_information(struct isst_id *id, FILE *outf, int tdp_level,
struct isst_pkg_ctdp *pkg_dev)
{
- char header[256];
- char value[256];
+ static char header[256];
+ static char value[1024];
static int level;
+ int trl_max_levels = isst_get_trl_max_levels();
int i;
if (pkg_dev->processed)
- level = print_package_info(cpu, outf);
+ level = print_package_info(id, outf);
for (i = 0; i <= pkg_dev->levels; ++i) {
struct isst_pkg_ctdp_level_info *ctdp_level;
- int j;
+ int j, k;
ctdp_level = &pkg_dev->ctdp_level[i];
if (!ctdp_level->processed)
@@ -368,32 +378,33 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
ctdp_level->level);
format_and_print(outf, level + 1, header, NULL);
- snprintf(header, sizeof(header), "cpu-count");
- j = get_cpu_count(get_physical_die_id(cpu),
- get_physical_die_id(cpu));
- snprintf(value, sizeof(value), "%d", j);
- format_and_print(outf, level + 2, header, value);
-
- j = CPU_COUNT_S(ctdp_level->core_cpumask_size,
- ctdp_level->core_cpumask);
- if (j) {
- snprintf(header, sizeof(header), "enable-cpu-count");
+ if (id->cpu >= 0) {
+ snprintf(header, sizeof(header), "cpu-count");
+ j = get_cpu_count(id);
snprintf(value, sizeof(value), "%d", j);
format_and_print(outf, level + 2, header, value);
- }
- if (ctdp_level->core_cpumask_size) {
- snprintf(header, sizeof(header), "enable-cpu-mask");
- printcpumask(sizeof(value), value,
- ctdp_level->core_cpumask_size,
- ctdp_level->core_cpumask);
- format_and_print(outf, level + 2, header, value);
+ j = CPU_COUNT_S(ctdp_level->core_cpumask_size,
+ ctdp_level->core_cpumask);
+ if (j) {
+ snprintf(header, sizeof(header), "enable-cpu-count");
+ snprintf(value, sizeof(value), "%d", j);
+ format_and_print(outf, level + 2, header, value);
+ }
- snprintf(header, sizeof(header), "enable-cpu-list");
- printcpulist(sizeof(value), value,
- ctdp_level->core_cpumask_size,
- ctdp_level->core_cpumask);
- format_and_print(outf, level + 2, header, value);
+ if (ctdp_level->core_cpumask_size) {
+ snprintf(header, sizeof(header), "enable-cpu-mask");
+ printcpumask(sizeof(value), value,
+ ctdp_level->core_cpumask_size,
+ ctdp_level->core_cpumask);
+ format_and_print(outf, level + 2, header, value);
+
+ snprintf(header, sizeof(header), "enable-cpu-list");
+ printcpulist(sizeof(value), value,
+ ctdp_level->core_cpumask_size,
+ ctdp_level->core_cpumask);
+ format_and_print(outf, level + 2, header, value);
+ }
}
snprintf(header, sizeof(header), "thermal-design-power-ratio");
@@ -404,41 +415,82 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
if (!ctdp_level->sse_p1)
ctdp_level->sse_p1 = ctdp_level->tdp_ratio;
snprintf(value, sizeof(value), "%d",
- ctdp_level->sse_p1 * DISP_FREQ_MULTIPLIER);
+ ctdp_level->sse_p1 * isst_get_disp_freq_multiplier());
format_and_print(outf, level + 2, header, value);
if (ctdp_level->avx2_p1) {
snprintf(header, sizeof(header), "base-frequency-avx2(MHz)");
snprintf(value, sizeof(value), "%d",
- ctdp_level->avx2_p1 * DISP_FREQ_MULTIPLIER);
+ ctdp_level->avx2_p1 * isst_get_disp_freq_multiplier());
format_and_print(outf, level + 2, header, value);
}
if (ctdp_level->avx512_p1) {
snprintf(header, sizeof(header), "base-frequency-avx512(MHz)");
snprintf(value, sizeof(value), "%d",
- ctdp_level->avx512_p1 * DISP_FREQ_MULTIPLIER);
+ ctdp_level->avx512_p1 * isst_get_disp_freq_multiplier());
format_and_print(outf, level + 2, header, value);
}
- if (ctdp_level->uncore_p1) {
+ if (ctdp_level->uncore_pm) {
snprintf(header, sizeof(header), "uncore-frequency-min(MHz)");
snprintf(value, sizeof(value), "%d",
- ctdp_level->uncore_p1 * DISP_FREQ_MULTIPLIER);
+ ctdp_level->uncore_pm * isst_get_disp_freq_multiplier());
format_and_print(outf, level + 2, header, value);
}
if (ctdp_level->uncore_p0) {
snprintf(header, sizeof(header), "uncore-frequency-max(MHz)");
snprintf(value, sizeof(value), "%d",
- ctdp_level->uncore_p0 * DISP_FREQ_MULTIPLIER);
+ ctdp_level->uncore_p0 * isst_get_disp_freq_multiplier());
+ format_and_print(outf, level + 2, header, value);
+ }
+
+ if (ctdp_level->amx_p1) {
+ snprintf(header, sizeof(header), "base-frequency-amx(MHz)");
+ snprintf(value, sizeof(value), "%d",
+ ctdp_level->amx_p1 * isst_get_disp_freq_multiplier());
+ format_and_print(outf, level + 2, header, value);
+ }
+
+ if (ctdp_level->uncore_p1) {
+ snprintf(header, sizeof(header), "uncore-frequency-base(MHz)");
+ snprintf(value, sizeof(value), "%d",
+ ctdp_level->uncore_p1 * isst_get_disp_freq_multiplier());
+ format_and_print(outf, level + 2, header, value);
+ }
+
+ if (ctdp_level->uncore1_p1) {
+ snprintf(header, sizeof(header), "uncore-1-frequency-base(MHz)");
+ snprintf(value, sizeof(value), "%d",
+ ctdp_level->uncore1_p1 * isst_get_disp_freq_multiplier());
+ format_and_print(outf, level + 2, header, value);
+ }
+ if (ctdp_level->uncore1_pm) {
+ snprintf(header, sizeof(header), "uncore-1-frequency-min(MHz)");
+ snprintf(value, sizeof(value), "%d",
+ ctdp_level->uncore1_pm * isst_get_disp_freq_multiplier());
+ format_and_print(outf, level + 2, header, value);
+ }
+
+ if (ctdp_level->uncore1_p0) {
+ snprintf(header, sizeof(header), "uncore-1-frequency-max(MHz)");
+ snprintf(value, sizeof(value), "%d",
+ ctdp_level->uncore1_p0 * isst_get_disp_freq_multiplier());
format_and_print(outf, level + 2, header, value);
}
if (ctdp_level->mem_freq) {
- snprintf(header, sizeof(header), "mem-frequency(MHz)");
+ snprintf(header, sizeof(header), "max-mem-frequency(MHz)");
snprintf(value, sizeof(value), "%d",
- ctdp_level->mem_freq * DISP_FREQ_MULTIPLIER);
+ ctdp_level->mem_freq);
+ format_and_print(outf, level + 2, header, value);
+ }
+
+ if (api_version() > 1) {
+ snprintf(header, sizeof(header), "cooling_type");
+ snprintf(value, sizeof(value), "%d",
+ ctdp_level->cooling_type);
format_and_print(outf, level + 2, header, value);
}
@@ -477,7 +529,7 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
if (is_clx_n_platform()) {
if (ctdp_level->pbf_support)
- _isst_pbf_display_information(cpu, outf,
+ _isst_pbf_display_information(id, outf,
tdp_level,
&ctdp_level->pbf_info,
level + 2);
@@ -496,64 +548,34 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
format_and_print(outf, level + 2, header, value);
}
- snprintf(header, sizeof(header), "turbo-ratio-limits-sse");
- format_and_print(outf, level + 2, header, NULL);
- for (j = 0; j < 8; ++j) {
- snprintf(header, sizeof(header), "bucket-%d", j);
- format_and_print(outf, level + 3, header, NULL);
-
- snprintf(header, sizeof(header), "core-count");
- snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff);
- format_and_print(outf, level + 4, header, value);
-
- snprintf(header, sizeof(header),
- "max-turbo-frequency(MHz)");
- snprintf(value, sizeof(value), "%d",
- ctdp_level->trl_sse_active_cores[j] *
- DISP_FREQ_MULTIPLIER);
- format_and_print(outf, level + 4, header, value);
- }
+ for (k = 0; k < trl_max_levels; k++) {
+ if (!ctdp_level->trl_ratios[k][0])
+ continue;
- if (ctdp_level->trl_avx_active_cores[0]) {
- snprintf(header, sizeof(header), "turbo-ratio-limits-avx2");
+ snprintf(header, sizeof(header), "turbo-ratio-limits-%s", isst_get_trl_level_name(k));
format_and_print(outf, level + 2, header, NULL);
- for (j = 0; j < 8; ++j) {
- snprintf(header, sizeof(header), "bucket-%d", j);
- format_and_print(outf, level + 3, header, NULL);
-
- snprintf(header, sizeof(header), "core-count");
- snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff);
- format_and_print(outf, level + 4, header, value);
- snprintf(header, sizeof(header), "max-turbo-frequency(MHz)");
- snprintf(value, sizeof(value), "%d", ctdp_level->trl_avx_active_cores[j] * DISP_FREQ_MULTIPLIER);
- format_and_print(outf, level + 4, header, value);
- }
- }
-
- if (ctdp_level->trl_avx_512_active_cores[0]) {
- snprintf(header, sizeof(header), "turbo-ratio-limits-avx512");
- format_and_print(outf, level + 2, header, NULL);
for (j = 0; j < 8; ++j) {
snprintf(header, sizeof(header), "bucket-%d", j);
format_and_print(outf, level + 3, header, NULL);
snprintf(header, sizeof(header), "core-count");
- snprintf(value, sizeof(value), "%llu", (ctdp_level->buckets_info >> (j * 8)) & 0xff);
+
+ snprintf(value, sizeof(value), "%llu", (ctdp_level->trl_cores >> (j * 8)) & 0xff);
format_and_print(outf, level + 4, header, value);
snprintf(header, sizeof(header), "max-turbo-frequency(MHz)");
- snprintf(value, sizeof(value), "%d", ctdp_level->trl_avx_512_active_cores[j] * DISP_FREQ_MULTIPLIER);
+ snprintf(value, sizeof(value), "%d", ctdp_level->trl_ratios[k][j] * isst_get_disp_freq_multiplier());
format_and_print(outf, level + 4, header, value);
}
}
if (ctdp_level->pbf_support)
- _isst_pbf_display_information(cpu, outf, i,
+ _isst_pbf_display_information(id, outf, i,
&ctdp_level->pbf_info,
level + 2);
if (ctdp_level->fact_support)
- _isst_fact_display_information(cpu, outf, i, 0xff, 0xff,
+ _isst_fact_display_information(id, outf, i, 0xff, 0xff,
&ctdp_level->fact_info,
level + 2);
}
@@ -575,36 +597,36 @@ void isst_ctdp_display_information_end(FILE *outf)
start = 0;
}
-void isst_pbf_display_information(int cpu, FILE *outf, int level,
+void isst_pbf_display_information(struct isst_id *id, FILE *outf, int level,
struct isst_pbf_info *pbf_info)
{
int _level;
- _level = print_package_info(cpu, outf);
- _isst_pbf_display_information(cpu, outf, level, pbf_info, _level + 1);
+ _level = print_package_info(id, outf);
+ _isst_pbf_display_information(id, outf, level, pbf_info, _level + 1);
format_and_print(outf, 1, NULL, NULL);
}
-void isst_fact_display_information(int cpu, FILE *outf, int level,
+void isst_fact_display_information(struct isst_id *id, FILE *outf, int level,
int fact_bucket, int fact_avx,
struct isst_fact_info *fact_info)
{
int _level;
- _level = print_package_info(cpu, outf);
- _isst_fact_display_information(cpu, outf, level, fact_bucket, fact_avx,
+ _level = print_package_info(id, outf);
+ _isst_fact_display_information(id, outf, level, fact_bucket, fact_avx,
fact_info, _level + 1);
format_and_print(outf, 1, NULL, NULL);
}
-void isst_clos_display_information(int cpu, FILE *outf, int clos,
+void isst_clos_display_information(struct isst_id *id, FILE *outf, int clos,
struct isst_clos_config *clos_config)
{
char header[256];
char value[256];
int level;
- level = print_package_info(cpu, outf);
+ level = print_package_info(id, outf);
snprintf(header, sizeof(header), "core-power");
format_and_print(outf, level + 1, header, NULL);
@@ -622,24 +644,24 @@ void isst_clos_display_information(int cpu, FILE *outf, int clos,
format_and_print(outf, level + 2, header, value);
snprintf(header, sizeof(header), "clos-min");
- snprintf(value, sizeof(value), "%d MHz", clos_config->clos_min * DISP_FREQ_MULTIPLIER);
+ snprintf(value, sizeof(value), "%d MHz", clos_config->clos_min * isst_get_disp_freq_multiplier());
format_and_print(outf, level + 2, header, value);
snprintf(header, sizeof(header), "clos-max");
- if (clos_config->clos_max == 0xff)
+ if ((clos_config->clos_max * isst_get_disp_freq_multiplier()) == 25500)
snprintf(value, sizeof(value), "Max Turbo frequency");
else
- snprintf(value, sizeof(value), "%d MHz", clos_config->clos_max * DISP_FREQ_MULTIPLIER);
+ snprintf(value, sizeof(value), "%d MHz", clos_config->clos_max * isst_get_disp_freq_multiplier());
format_and_print(outf, level + 2, header, value);
snprintf(header, sizeof(header), "clos-desired");
- snprintf(value, sizeof(value), "%d MHz", clos_config->clos_desired * DISP_FREQ_MULTIPLIER);
+ snprintf(value, sizeof(value), "%d MHz", clos_config->clos_desired * isst_get_disp_freq_multiplier());
format_and_print(outf, level + 2, header, value);
format_and_print(outf, level, NULL, NULL);
}
-void isst_clos_display_clos_information(int cpu, FILE *outf,
+void isst_clos_display_clos_information(struct isst_id *id, FILE *outf,
int clos_enable, int type,
int state, int cap)
{
@@ -647,7 +669,7 @@ void isst_clos_display_clos_information(int cpu, FILE *outf,
char value[256];
int level;
- level = print_package_info(cpu, outf);
+ level = print_package_info(id, outf);
snprintf(header, sizeof(header), "core-power");
format_and_print(outf, level + 1, header, NULL);
@@ -683,13 +705,13 @@ void isst_clos_display_clos_information(int cpu, FILE *outf,
format_and_print(outf, level, NULL, NULL);
}
-void isst_clos_display_assoc_information(int cpu, FILE *outf, int clos)
+void isst_clos_display_assoc_information(struct isst_id *id, FILE *outf, int clos)
{
char header[256];
char value[256];
int level;
- level = print_package_info(cpu, outf);
+ level = print_package_info(id, outf);
snprintf(header, sizeof(header), "get-assoc");
format_and_print(outf, level + 1, header, NULL);
@@ -701,15 +723,14 @@ void isst_clos_display_assoc_information(int cpu, FILE *outf, int clos)
format_and_print(outf, level, NULL, NULL);
}
-void isst_display_result(int cpu, FILE *outf, char *feature, char *cmd,
+void isst_display_result(struct isst_id *id, FILE *outf, char *feature, char *cmd,
int result)
{
char header[256];
char value[256];
int level = 3;
- if (cpu >= 0)
- level = print_package_info(cpu, outf);
+ level = print_package_info(id, outf);
snprintf(header, sizeof(header), "%s", feature);
format_and_print(outf, level + 1, header, NULL);
@@ -763,3 +784,21 @@ void isst_display_error_info_message(int error, char *msg, int arg_valid, int ar
if (!start)
format_and_print(outf, 0, NULL, NULL);
}
+
+void isst_trl_display_information(struct isst_id *id, FILE *outf, unsigned long long trl)
+{
+ char header[256];
+ char value[256];
+ int level;
+
+ level = print_package_info(id, outf);
+
+ snprintf(header, sizeof(header), "get-trl");
+ format_and_print(outf, level + 1, header, NULL);
+
+ snprintf(header, sizeof(header), "trl");
+ snprintf(value, sizeof(value), "0x%llx", trl);
+ format_and_print(outf, level + 2, header, value);
+
+ format_and_print(outf, level, NULL, NULL);
+}
diff --git a/tools/power/x86/intel-speed-select/isst.h b/tools/power/x86/intel-speed-select/isst.h
index 094ba4589a9c..960f647cfc2d 100644
--- a/tools/power/x86/intel-speed-select/isst.h
+++ b/tools/power/x86/intel-speed-select/isst.h
@@ -28,6 +28,8 @@
#include <stdarg.h>
#include <sys/ioctl.h>
+#include <linux/isst_if.h>
+
#define BIT(x) (1 << (x))
#define BIT_ULL(nr) (1ULL << (nr))
#define GENMASK(h, l) (((~0UL) << (l)) & (~0UL >> (sizeof(long) * 8 - 1 - (h))))
@@ -47,6 +49,7 @@
#define CONFIG_TDP_GET_UNCORE_P0_P1_INFO 0X09
#define CONFIG_TDP_GET_P1_INFO 0x0a
#define CONFIG_TDP_GET_MEM_FREQ 0x0b
+#define CONFIG_TDP_GET_RATIO_INFO 0x0c
#define CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES 0x10
#define CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS 0x11
@@ -76,21 +79,29 @@
#define DISP_FREQ_MULTIPLIER 100
+#define MAX_PACKAGE_COUNT 32
+#define MAX_DIE_PER_PACKAGE 16
+#define MAX_PUNIT_PER_DIE 8
+
+/* Unified structure to specific a CPU or a Power Domain */
+struct isst_id {
+ int cpu;
+ int pkg;
+ int die;
+ int punit;
+};
+
struct isst_clos_config {
- int pkg_id;
- int die_id;
+ unsigned int clos_min;
+ unsigned int clos_max;
unsigned char epp;
unsigned char clos_prop_prio;
- unsigned char clos_min;
- unsigned char clos_max;
unsigned char clos_desired;
};
struct isst_fact_bucket_info {
- int high_priority_cores_count;
- int sse_trl;
- int avx_trl;
- int avx512_trl;
+ int hp_cores;
+ int hp_ratios[TRL_MAX_LEVELS];
};
struct isst_pbf_info {
@@ -108,9 +119,7 @@ struct isst_pbf_info {
#define ISST_TRL_MAX_ACTIVE_CORES 8
#define ISST_FACT_MAX_BUCKETS 8
struct isst_fact_info {
- int lp_clipping_ratio_license_sse;
- int lp_clipping_ratio_license_avx2;
- int lp_clipping_ratio_license_avx512;
+ int lp_ratios[TRL_MAX_LEVELS];
struct isst_fact_bucket_info bucket_info[ISST_FACT_MAX_BUCKETS];
};
@@ -134,19 +143,23 @@ struct isst_pkg_ctdp_level_info {
int pkg_max_power;
int fact;
int t_proc_hot;
+ int cooling_type;
int uncore_p0;
int uncore_p1;
+ int uncore_pm;
+ int uncore1_p0;
+ int uncore1_p1;
+ int uncore1_pm;
int sse_p1;
int avx2_p1;
int avx512_p1;
+ int amx_p1;
int mem_freq;
size_t core_cpumask_size;
cpu_set_t *core_cpumask;
int cpu_count;
- unsigned long long buckets_info;
- int trl_sse_active_cores[ISST_TRL_MAX_ACTIVE_CORES];
- int trl_avx_active_cores[ISST_TRL_MAX_ACTIVE_CORES];
- int trl_avx_512_active_cores[ISST_TRL_MAX_ACTIVE_CORES];
+ unsigned long long trl_cores; /* Buckets info */
+ int trl_ratios[TRL_MAX_LEVELS][ISST_TRL_MAX_ACTIVE_CORES];
int kobj_bucket_index;
int active_bucket;
int fact_max_index;
@@ -168,91 +181,148 @@ struct isst_pkg_ctdp {
struct isst_pkg_ctdp_level_info ctdp_level[ISST_MAX_TDP_LEVELS];
};
+enum isst_platform_param {
+ ISST_PARAM_MBOX_DELAY,
+ ISST_PARAM_MBOX_RETRIES,
+};
+
+struct isst_platform_ops {
+ int (*get_disp_freq_multiplier)(void);
+ int (*get_trl_max_levels)(void);
+ char *(*get_trl_level_name)(int level);
+ void (*update_platform_param)(enum isst_platform_param param, int value);
+ int (*is_punit_valid)(struct isst_id *id);
+ int (*read_pm_config)(struct isst_id *id, int *cp_state, int *cp_cap);
+ int (*get_config_levels)(struct isst_id *id, struct isst_pkg_ctdp *pkg_ctdp);
+ int (*get_ctdp_control)(struct isst_id *id, int config_index, struct isst_pkg_ctdp_level_info *ctdp_level);
+ int (*get_tdp_info)(struct isst_id *id, int config_index, struct isst_pkg_ctdp_level_info *ctdp_level);
+ int (*get_pwr_info)(struct isst_id *id, int config_index, struct isst_pkg_ctdp_level_info *ctdp_level);
+ int (*get_coremask_info)(struct isst_id *id, int config_index, struct isst_pkg_ctdp_level_info *ctdp_level);
+ int (*get_get_trl)(struct isst_id *id, int level, int avx_level, int *trl);
+ int (*get_get_trls)(struct isst_id *id, int level, struct isst_pkg_ctdp_level_info *ctdp_level);
+ int (*get_trl_bucket_info)(struct isst_id *id, int level, unsigned long long *buckets_info);
+ int (*set_tdp_level)(struct isst_id *id, int tdp_level);
+ int (*get_pbf_info)(struct isst_id *id, int level, struct isst_pbf_info *pbf_info);
+ int (*set_pbf_fact_status)(struct isst_id *id, int pbf, int enable);
+ int (*get_fact_info)(struct isst_id *id, int level, int fact_bucket, struct isst_fact_info *fact_info);
+ void (*adjust_uncore_freq)(struct isst_id *id, int config_index, struct isst_pkg_ctdp_level_info *ctdp_level);
+ int (*get_clos_information)(struct isst_id *id, int *enable, int *type);
+ int (*pm_qos_config)(struct isst_id *id, int enable_clos, int priority_type);
+ int (*pm_get_clos)(struct isst_id *id, int clos, struct isst_clos_config *clos_config);
+ int (*set_clos)(struct isst_id *id, int clos, struct isst_clos_config *clos_config);
+ int (*clos_get_assoc_status)(struct isst_id *id, int *clos_id);
+ int (*clos_associate)(struct isst_id *id, int clos_id);
+};
+
+extern int is_cpu_in_power_domain(int cpu, struct isst_id *id);
extern int get_topo_max_cpus(void);
-extern int get_cpu_count(int pkg_id, int die_id);
-extern int get_core_count(int pkg_id, int die_id);
+extern int get_cpu_count(struct isst_id *id);
+extern int get_max_punit_core_id(struct isst_id *id);
+extern int api_version(void);
/* Common interfaces */
FILE *get_output_file(void);
+extern int is_debug_enabled(void);
extern void debug_printf(const char *format, ...);
extern int out_format_is_json(void);
-extern int get_physical_package_id(int cpu);
-extern int get_physical_die_id(int cpu);
+extern void set_isst_id(struct isst_id *id, int cpu);
extern size_t alloc_cpu_set(cpu_set_t **cpu_set);
extern void free_cpu_set(cpu_set_t *cpu_set);
-extern int find_logical_cpu(int pkg_id, int die_id, int phy_cpu);
-extern int find_phy_cpu_num(int logical_cpu);
extern int find_phy_core_num(int logical_cpu);
-extern void set_cpu_mask_from_punit_coremask(int cpu,
+extern void set_cpu_mask_from_punit_coremask(struct isst_id *id,
unsigned long long core_mask,
size_t core_cpumask_size,
cpu_set_t *core_cpumask,
int *cpu_cnt);
-
-extern int isst_send_mbox_command(unsigned int cpu, unsigned char command,
- unsigned char sub_command,
- unsigned int write,
- unsigned int req_data, unsigned int *resp);
-
extern int isst_send_msr_command(unsigned int cpu, unsigned int command,
int write, unsigned long long *req_resp);
-extern int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev);
-extern int isst_get_ctdp_control(int cpu, int config_index,
+extern int isst_set_platform_ops(int api_version);
+extern void isst_update_platform_param(enum isst_platform_param, int vale);
+extern int isst_get_disp_freq_multiplier(void);
+extern int isst_get_trl_max_levels(void);
+extern char *isst_get_trl_level_name(int level);
+extern int isst_is_punit_valid(struct isst_id *id);
+
+extern int isst_get_ctdp_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev);
+extern int isst_get_ctdp_control(struct isst_id *id, int config_index,
struct isst_pkg_ctdp_level_info *ctdp_level);
-extern int isst_get_coremask_info(int cpu, int config_index,
+extern int isst_get_coremask_info(struct isst_id *id, int config_index,
struct isst_pkg_ctdp_level_info *ctdp_level);
-extern int isst_get_process_ctdp(int cpu, int tdp_level,
+extern void isst_adjust_uncore_freq(struct isst_id *id, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level);
+extern int isst_get_process_ctdp(struct isst_id *id, int tdp_level,
struct isst_pkg_ctdp *pkg_dev);
-extern void isst_get_process_ctdp_complete(int cpu,
+extern void isst_get_process_ctdp_complete(struct isst_id *id,
struct isst_pkg_ctdp *pkg_dev);
-extern void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
+extern void isst_ctdp_display_information(struct isst_id *id, FILE *outf, int tdp_level,
struct isst_pkg_ctdp *pkg_dev);
-extern void isst_ctdp_display_core_info(int cpu, FILE *outf, char *prefix,
+extern void isst_ctdp_display_core_info(struct isst_id *id, FILE *outf, char *prefix,
unsigned int val, char *str0, char *str1);
extern void isst_ctdp_display_information_start(FILE *outf);
extern void isst_ctdp_display_information_end(FILE *outf);
-extern void isst_pbf_display_information(int cpu, FILE *outf, int level,
+extern void isst_pbf_display_information(struct isst_id *id, FILE *outf, int level,
struct isst_pbf_info *info);
-extern int isst_set_tdp_level(int cpu, int tdp_level);
-extern int isst_set_tdp_level_msr(int cpu, int tdp_level);
-extern int isst_set_pbf_fact_status(int cpu, int pbf, int enable);
-extern int isst_get_pbf_info(int cpu, int level,
+extern int isst_set_tdp_level(struct isst_id *id, int tdp_level);
+extern int isst_set_pbf_fact_status(struct isst_id *id, int pbf, int enable);
+extern int isst_get_pbf_info(struct isst_id *id, int level,
struct isst_pbf_info *pbf_info);
-extern void isst_get_pbf_info_complete(struct isst_pbf_info *pbf_info);
-extern int isst_get_fact_info(int cpu, int level, int fact_bucket,
+extern int isst_get_fact_info(struct isst_id *id, int level, int fact_bucket,
struct isst_fact_info *fact_info);
-extern int isst_get_fact_bucket_info(int cpu, int level,
- struct isst_fact_bucket_info *bucket_info);
-extern void isst_fact_display_information(int cpu, FILE *outf, int level,
+extern void isst_fact_display_information(struct isst_id *id, FILE *outf, int level,
int fact_bucket, int fact_avx,
struct isst_fact_info *fact_info);
-extern int isst_set_trl(int cpu, unsigned long long trl);
-extern int isst_set_trl_from_current_tdp(int cpu, unsigned long long trl);
-extern int isst_get_config_tdp_lock_status(int cpu);
+extern int isst_set_trl(struct isst_id *id, unsigned long long trl);
+extern int isst_get_trl(struct isst_id *id, unsigned long long *trl);
+extern int isst_set_trl_from_current_tdp(struct isst_id *id, unsigned long long trl);
+extern int isst_get_config_tdp_lock_status(struct isst_id *id);
-extern int isst_pm_qos_config(int cpu, int enable_clos, int priority_type);
-extern int isst_pm_get_clos(int cpu, int clos,
+extern int isst_pm_qos_config(struct isst_id *id, int enable_clos, int priority_type);
+extern int isst_pm_get_clos(struct isst_id *id, int clos,
struct isst_clos_config *clos_config);
-extern int isst_set_clos(int cpu, int clos,
+extern int isst_set_clos(struct isst_id *id, int clos,
struct isst_clos_config *clos_config);
-extern int isst_clos_associate(int cpu, int clos);
-extern int isst_clos_get_assoc_status(int cpu, int *clos_id);
-extern void isst_clos_display_information(int cpu, FILE *outf, int clos,
+extern int isst_clos_associate(struct isst_id *id, int clos);
+extern int isst_clos_get_assoc_status(struct isst_id *id, int *clos_id);
+extern void isst_clos_display_information(struct isst_id *id, FILE *outf, int clos,
struct isst_clos_config *clos_config);
-extern void isst_clos_display_assoc_information(int cpu, FILE *outf, int clos);
-extern int isst_read_reg(unsigned short reg, unsigned int *val);
-extern int isst_write_reg(int reg, unsigned int val);
+extern void isst_clos_display_assoc_information(struct isst_id *id, FILE *outf, int clos);
-extern void isst_display_result(int cpu, FILE *outf, char *feature, char *cmd,
+extern void isst_display_result(struct isst_id *id, FILE *outf, char *feature, char *cmd,
int result);
-extern int isst_clos_get_clos_information(int cpu, int *enable, int *type);
-extern void isst_clos_display_clos_information(int cpu, FILE *outf,
+extern int isst_clos_get_clos_information(struct isst_id *id, int *enable, int *type);
+extern void isst_clos_display_clos_information(struct isst_id *id, FILE *outf,
int clos_enable, int type,
int state, int cap);
extern int is_clx_n_platform(void);
extern int get_cpufreq_base_freq(int cpu);
-extern int isst_read_pm_config(int cpu, int *cp_state, int *cp_cap);
+extern int isst_read_pm_config(struct isst_id *id, int *cp_state, int *cp_cap);
extern void isst_display_error_info_message(int error, char *msg, int arg_valid, int arg);
+extern int is_skx_based_platform(void);
+extern int is_spr_platform(void);
+extern int is_emr_platform(void);
+extern int is_icx_platform(void);
+extern void isst_trl_display_information(struct isst_id *id, FILE *outf, unsigned long long trl);
+
+extern void set_cpu_online_offline(int cpu, int state);
+extern void for_each_online_power_domain_in_set(void (*callback)(struct isst_id *, void *, void *,
+ void *, void *),
+ void *arg1, void *arg2, void *arg3,
+ void *arg4);
+extern int isst_daemon(int debug_mode, int poll_interval, int no_daemon);
+extern void process_level_change(struct isst_id *id);
+extern int hfi_main(void);
+extern void hfi_exit(void);
+
+/* Interface specific callbacks */
+extern struct isst_platform_ops *mbox_get_platform_ops(void);
+extern struct isst_platform_ops *tpmi_get_platform_ops(void);
+
+/* Cgroup related interface */
+extern int enable_cpuset_controller(void);
+extern int isolate_cpus(struct isst_id *id, int mask_size, cpu_set_t *cpu_mask,
+ int level, int cpu_0_only);
+extern int use_cgroupv2(void);
+
#endif