aboutsummaryrefslogtreecommitdiffstats
path: root/tools/power/x86
diff options
context:
space:
mode:
Diffstat (limited to 'tools/power/x86')
-rwxr-xr-xtools/power/x86/amd_pstate_tracer/amd_pstate_trace.py354
-rw-r--r--tools/power/x86/intel-speed-select/.gitignore1
-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.c312
-rw-r--r--tools/power/x86/intel-speed-select/isst-config.c1388
-rw-r--r--tools/power/x86/intel-speed-select/isst-core.c434
-rw-r--r--tools/power/x86/intel-speed-select/isst-daemon.c242
-rw-r--r--tools/power/x86/intel-speed-select/isst-display.c368
-rw-r--r--tools/power/x86/intel-speed-select/isst.h105
-rwxr-xr-xtools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py263
-rw-r--r--tools/power/x86/turbostat/.gitignore1
-rw-r--r--tools/power/x86/turbostat/Makefile5
-rw-r--r--tools/power/x86/turbostat/turbostat.8210
-rw-r--r--tools/power/x86/turbostat/turbostat.c2536
-rw-r--r--tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c176
16 files changed, 4631 insertions, 1780 deletions
diff --git a/tools/power/x86/amd_pstate_tracer/amd_pstate_trace.py b/tools/power/x86/amd_pstate_tracer/amd_pstate_trace.py
new file mode 100755
index 000000000000..2dea4032ac56
--- /dev/null
+++ b/tools/power/x86/amd_pstate_tracer/amd_pstate_trace.py
@@ -0,0 +1,354 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-only
+# -*- coding: utf-8 -*-
+#
+""" This utility can be used to debug and tune the performance of the
+AMD P-State driver. It imports intel_pstate_tracer to analyze AMD P-State
+trace event.
+
+Prerequisites:
+ Python version 2.7.x or higher
+ gnuplot 5.0 or higher
+ gnuplot-py 1.8 or higher
+ (Most of the distributions have these required packages. They may be called
+ gnuplot-py, phython-gnuplot or phython3-gnuplot, gnuplot-nox, ... )
+
+ Kernel config for Linux trace is enabled
+
+ see print_help(): for Usage and Output details
+
+"""
+from __future__ import print_function
+from datetime import datetime
+import subprocess
+import os
+import time
+import re
+import signal
+import sys
+import getopt
+import Gnuplot
+from numpy import *
+from decimal import *
+sys.path.append('../intel_pstate_tracer')
+#import intel_pstate_tracer
+import intel_pstate_tracer as ipt
+
+__license__ = "GPL version 2"
+
+MAX_CPUS = 256
+# Define the csv file columns
+C_COMM = 15
+C_ELAPSED = 14
+C_SAMPLE = 13
+C_DURATION = 12
+C_LOAD = 11
+C_TSC = 10
+C_APERF = 9
+C_MPERF = 8
+C_FREQ = 7
+C_MAX_PERF = 6
+C_DES_PERF = 5
+C_MIN_PERF = 4
+C_USEC = 3
+C_SEC = 2
+C_CPU = 1
+
+global sample_num, last_sec_cpu, last_usec_cpu, start_time, test_name, trace_file
+
+getcontext().prec = 11
+
+sample_num =0
+last_sec_cpu = [0] * MAX_CPUS
+last_usec_cpu = [0] * MAX_CPUS
+
+def plot_per_cpu_freq(cpu_index):
+ """ Plot per cpu frequency """
+
+ file_name = 'cpu{:0>3}.csv'.format(cpu_index)
+ if os.path.exists(file_name):
+ output_png = "cpu%03d_frequency.png" % cpu_index
+ g_plot = ipt.common_gnuplot_settings()
+ g_plot('set output "' + output_png + '"')
+ g_plot('set yrange [0:7]')
+ g_plot('set ytics 0, 1')
+ g_plot('set ylabel "CPU Frequency (GHz)"')
+ g_plot('set title "{} : frequency : CPU {:0>3} : {:%F %H:%M}"'.format(test_name, cpu_index, datetime.now()))
+ g_plot('set ylabel "CPU frequency"')
+ g_plot('set key off')
+ ipt.set_4_plot_linestyles(g_plot)
+ g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y1'.format(C_ELAPSED, C_FREQ))
+
+def plot_per_cpu_des_perf(cpu_index):
+ """ Plot per cpu desired perf """
+
+ file_name = 'cpu{:0>3}.csv'.format(cpu_index)
+ if os.path.exists(file_name):
+ output_png = "cpu%03d_des_perf.png" % cpu_index
+ g_plot = ipt.common_gnuplot_settings()
+ g_plot('set output "' + output_png + '"')
+ g_plot('set yrange [0:255]')
+ g_plot('set ylabel "des perf"')
+ g_plot('set title "{} : cpu des perf : CPU {:0>3} : {:%F %H:%M}"'.format(test_name, cpu_index, datetime.now()))
+ g_plot('set key off')
+ ipt.set_4_plot_linestyles(g_plot)
+ g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y1'.format(C_ELAPSED, C_DES_PERF))
+
+def plot_per_cpu_load(cpu_index):
+ """ Plot per cpu load """
+
+ file_name = 'cpu{:0>3}.csv'.format(cpu_index)
+ if os.path.exists(file_name):
+ output_png = "cpu%03d_load.png" % cpu_index
+ g_plot = ipt.common_gnuplot_settings()
+ g_plot('set output "' + output_png + '"')
+ g_plot('set yrange [0:100]')
+ g_plot('set ytics 0, 10')
+ g_plot('set ylabel "CPU load (percent)"')
+ g_plot('set title "{} : cpu load : CPU {:0>3} : {:%F %H:%M}"'.format(test_name, cpu_index, datetime.now()))
+ g_plot('set key off')
+ ipt.set_4_plot_linestyles(g_plot)
+ g_plot('plot "' + file_name + '" using {:d}:{:d} with linespoints linestyle 1 axis x1y1'.format(C_ELAPSED, C_LOAD))
+
+def plot_all_cpu_frequency():
+ """ Plot all cpu frequencies """
+
+ output_png = 'all_cpu_frequencies.png'
+ g_plot = ipt.common_gnuplot_settings()
+ g_plot('set output "' + output_png + '"')
+ g_plot('set ylabel "CPU Frequency (GHz)"')
+ g_plot('set title "{} : cpu frequencies : {:%F %H:%M}"'.format(test_name, datetime.now()))
+
+ title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
+ plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 7 ps 1 title i".format(C_ELAPSED, C_FREQ)
+ g_plot('title_list = "{}"'.format(title_list))
+ g_plot(plot_str)
+
+def plot_all_cpu_des_perf():
+ """ Plot all cpu desired perf """
+
+ output_png = 'all_cpu_des_perf.png'
+ g_plot = ipt.common_gnuplot_settings()
+ g_plot('set output "' + output_png + '"')
+ g_plot('set ylabel "des perf"')
+ g_plot('set title "{} : cpu des perf : {:%F %H:%M}"'.format(test_name, datetime.now()))
+
+ title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
+ plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 255 ps 1 title i".format(C_ELAPSED, C_DES_PERF)
+ g_plot('title_list = "{}"'.format(title_list))
+ g_plot(plot_str)
+
+def plot_all_cpu_load():
+ """ Plot all cpu load """
+
+ output_png = 'all_cpu_load.png'
+ g_plot = ipt.common_gnuplot_settings()
+ g_plot('set output "' + output_png + '"')
+ g_plot('set yrange [0:100]')
+ g_plot('set ylabel "CPU load (percent)"')
+ g_plot('set title "{} : cpu load : {:%F %H:%M}"'.format(test_name, datetime.now()))
+
+ title_list = subprocess.check_output('ls cpu???.csv | sed -e \'s/.csv//\'',shell=True).decode('utf-8').replace('\n', ' ')
+ plot_str = "plot for [i in title_list] i.'.csv' using {:d}:{:d} pt 255 ps 1 title i".format(C_ELAPSED, C_LOAD)
+ g_plot('title_list = "{}"'.format(title_list))
+ g_plot(plot_str)
+
+def store_csv(cpu_int, time_pre_dec, time_post_dec, min_perf, des_perf, max_perf, freq_ghz, mperf, aperf, tsc, common_comm, load, duration_ms, sample_num, elapsed_time, cpu_mask):
+ """ Store master csv file information """
+
+ global graph_data_present
+
+ if cpu_mask[cpu_int] == 0:
+ return
+
+ try:
+ f_handle = open('cpu.csv', 'a')
+ string_buffer = "CPU_%03u, %05u, %06u, %u, %u, %u, %.4f, %u, %u, %u, %.2f, %.3f, %u, %.3f, %s\n" % (cpu_int, int(time_pre_dec), int(time_post_dec), int(min_perf), int(des_perf), int(max_perf), freq_ghz, int(mperf), int(aperf), int(tsc), load, duration_ms, sample_num, elapsed_time, common_comm)
+ f_handle.write(string_buffer)
+ f_handle.close()
+ except:
+ print('IO error cpu.csv')
+ return
+
+ graph_data_present = True;
+
+
+def cleanup_data_files():
+ """ clean up existing data files """
+
+ if os.path.exists('cpu.csv'):
+ os.remove('cpu.csv')
+ f_handle = open('cpu.csv', 'a')
+ f_handle.write('common_cpu, common_secs, common_usecs, min_perf, des_perf, max_perf, freq, mperf, aperf, tsc, load, duration_ms, sample_num, elapsed_time, common_comm')
+ f_handle.write('\n')
+ f_handle.close()
+
+def read_trace_data(file_name, cpu_mask):
+ """ Read and parse trace data """
+
+ global current_max_cpu
+ global sample_num, last_sec_cpu, last_usec_cpu, start_time
+
+ try:
+ data = open(file_name, 'r').read()
+ except:
+ print('Error opening ', file_name)
+ sys.exit(2)
+
+ for line in data.splitlines():
+ search_obj = \
+ re.search(r'(^(.*?)\[)((\d+)[^\]])(.*?)(\d+)([.])(\d+)(.*?amd_min_perf=)(\d+)(.*?amd_des_perf=)(\d+)(.*?amd_max_perf=)(\d+)(.*?freq=)(\d+)(.*?mperf=)(\d+)(.*?aperf=)(\d+)(.*?tsc=)(\d+)'
+ , line)
+
+ if search_obj:
+ cpu = search_obj.group(3)
+ cpu_int = int(cpu)
+ cpu = str(cpu_int)
+
+ time_pre_dec = search_obj.group(6)
+ time_post_dec = search_obj.group(8)
+ min_perf = search_obj.group(10)
+ des_perf = search_obj.group(12)
+ max_perf = search_obj.group(14)
+ freq = search_obj.group(16)
+ mperf = search_obj.group(18)
+ aperf = search_obj.group(20)
+ tsc = search_obj.group(22)
+
+ common_comm = search_obj.group(2).replace(' ', '')
+
+ if sample_num == 0 :
+ start_time = Decimal(time_pre_dec) + Decimal(time_post_dec) / Decimal(1000000)
+ sample_num += 1
+
+ if last_sec_cpu[cpu_int] == 0 :
+ last_sec_cpu[cpu_int] = time_pre_dec
+ last_usec_cpu[cpu_int] = time_post_dec
+ else :
+ duration_us = (int(time_pre_dec) - int(last_sec_cpu[cpu_int])) * 1000000 + (int(time_post_dec) - int(last_usec_cpu[cpu_int]))
+ duration_ms = Decimal(duration_us) / Decimal(1000)
+ last_sec_cpu[cpu_int] = time_pre_dec
+ last_usec_cpu[cpu_int] = time_post_dec
+ elapsed_time = Decimal(time_pre_dec) + Decimal(time_post_dec) / Decimal(1000000) - start_time
+ load = Decimal(int(mperf)*100)/ Decimal(tsc)
+ freq_ghz = Decimal(freq)/Decimal(1000000)
+ store_csv(cpu_int, time_pre_dec, time_post_dec, min_perf, des_perf, max_perf, freq_ghz, mperf, aperf, tsc, common_comm, load, duration_ms, sample_num, elapsed_time, cpu_mask)
+
+ if cpu_int > current_max_cpu:
+ current_max_cpu = cpu_int
+# Now separate the main overall csv file into per CPU csv files.
+ ipt.split_csv(current_max_cpu, cpu_mask)
+
+
+def signal_handler(signal, frame):
+ print(' SIGINT: Forcing cleanup before exit.')
+ if interval:
+ ipt.disable_trace(trace_file)
+ ipt.clear_trace_file()
+ ipt.free_trace_buffer()
+ sys.exit(0)
+
+trace_file = "/sys/kernel/debug/tracing/events/amd_cpu/enable"
+signal.signal(signal.SIGINT, signal_handler)
+
+interval = ""
+file_name = ""
+cpu_list = ""
+test_name = ""
+memory = "10240"
+graph_data_present = False;
+
+valid1 = False
+valid2 = False
+
+cpu_mask = zeros((MAX_CPUS,), dtype=int)
+
+
+try:
+ opts, args = getopt.getopt(sys.argv[1:],"ht:i:c:n:m:",["help","trace_file=","interval=","cpu=","name=","memory="])
+except getopt.GetoptError:
+ ipt.print_help('amd_pstate')
+ sys.exit(2)
+for opt, arg in opts:
+ if opt == '-h':
+ print()
+ sys.exit()
+ elif opt in ("-t", "--trace_file"):
+ valid1 = True
+ location = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
+ file_name = os.path.join(location, arg)
+ elif opt in ("-i", "--interval"):
+ valid1 = True
+ interval = arg
+ elif opt in ("-c", "--cpu"):
+ cpu_list = arg
+ elif opt in ("-n", "--name"):
+ valid2 = True
+ test_name = arg
+ elif opt in ("-m", "--memory"):
+ memory = arg
+
+if not (valid1 and valid2):
+ ipt.print_help('amd_pstate')
+ sys.exit()
+
+if cpu_list:
+ for p in re.split("[,]", cpu_list):
+ if int(p) < MAX_CPUS :
+ cpu_mask[int(p)] = 1
+else:
+ for i in range (0, MAX_CPUS):
+ cpu_mask[i] = 1
+
+if not os.path.exists('results'):
+ os.mkdir('results')
+ ipt.fix_ownership('results')
+
+os.chdir('results')
+if os.path.exists(test_name):
+ print('The test name directory already exists. Please provide a unique test name. Test re-run not supported, yet.')
+ sys.exit()
+os.mkdir(test_name)
+ipt.fix_ownership(test_name)
+os.chdir(test_name)
+
+cur_version = sys.version_info
+print('python version (should be >= 2.7):')
+print(cur_version)
+
+cleanup_data_files()
+
+if interval:
+ file_name = "/sys/kernel/debug/tracing/trace"
+ ipt.clear_trace_file()
+ ipt.set_trace_buffer_size(memory)
+ ipt.enable_trace(trace_file)
+ time.sleep(int(interval))
+ ipt.disable_trace(trace_file)
+
+current_max_cpu = 0
+
+read_trace_data(file_name, cpu_mask)
+
+if interval:
+ ipt.clear_trace_file()
+ ipt.free_trace_buffer()
+
+if graph_data_present == False:
+ print('No valid data to plot')
+ sys.exit(2)
+
+for cpu_no in range(0, current_max_cpu + 1):
+ plot_per_cpu_freq(cpu_no)
+ plot_per_cpu_des_perf(cpu_no)
+ plot_per_cpu_load(cpu_no)
+
+plot_all_cpu_des_perf()
+plot_all_cpu_frequency()
+plot_all_cpu_load()
+
+for root, dirs, files in os.walk('.'):
+ for f in files:
+ ipt.fix_ownership(f)
+
+os.chdir('../../')
diff --git a/tools/power/x86/intel-speed-select/.gitignore b/tools/power/x86/intel-speed-select/.gitignore
index f61145925ce9..a814f89fe75f 100644
--- a/tools/power/x86/intel-speed-select/.gitignore
+++ b/tools/power/x86/intel-speed-select/.gitignore
@@ -1,2 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
include/
intel-speed-select
diff --git a/tools/power/x86/intel-speed-select/Build b/tools/power/x86/intel-speed-select/Build
index b61456d75190..81e36bd578b1 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
diff --git a/tools/power/x86/intel-speed-select/Makefile b/tools/power/x86/intel-speed-select/Makefile
index 12c6939dca2a..7221f2f55e8b 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/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..be96e90cc2a1
--- /dev/null
+++ b/tools/power/x86/intel-speed-select/hfi-events.c
@@ -0,0 +1,312 @@
+// 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;
+ int no_block = 0;
+
+ 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);
+
+ if (no_block)
+ nl_socket_set_nonblocking(sock);
+
+ 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 2b2b8167c65b..a160bad291eb 100644
--- a/tools/power/x86/intel-speed-select/isst-config.c
+++ b/tools/power/x86/intel-speed-select/isst-config.c
@@ -15,7 +15,8 @@ struct process_cmd_struct {
int arg;
};
-static const char *version_str = "v1.2";
+static const char *version_str = "v1.13";
+
static const int supported_api_ver = 1;
static struct isst_if_platform_info isst_platform_info;
static char *progname;
@@ -25,7 +26,7 @@ static FILE *outf;
static int cpu_model;
static int cpu_stepping;
-#define MAX_CPUS_IN_ONE_REQ 64
+#define MAX_CPUS_IN_ONE_REQ 256
static short max_target_cpus;
static unsigned short target_cpus[MAX_CPUS_IN_ONE_REQ];
@@ -42,6 +43,10 @@ static int out_format_json;
static int cmd_help;
static int force_online_offline;
static int auto_mode;
+static int fact_enable_fail;
+
+static int mbox_delay;
+static int mbox_retries = 3;
/* clos related */
static int current_clos = -1;
@@ -58,9 +63,22 @@ struct _cpu_map {
unsigned short die_id;
unsigned short punit_cpu;
unsigned short punit_cpu_core;
+ unsigned short initialized;
};
struct _cpu_map *cpu_map;
+struct cpu_topology {
+ short cpu;
+ short core_id;
+ short pkg_id;
+ short die_id;
+};
+
+FILE *get_output_file(void)
+{
+ return outf;
+}
+
void debug_printf(const char *format, ...)
{
va_list args;
@@ -82,6 +100,30 @@ int is_clx_n_platform(void)
return 0;
}
+int is_skx_based_platform(void)
+{
+ if (cpu_model == 0x55)
+ return 1;
+
+ return 0;
+}
+
+int is_spr_platform(void)
+{
+ if (cpu_model == 0x8F)
+ return 1;
+
+ return 0;
+}
+
+int is_icx_platform(void)
+{
+ if (cpu_model == 0x6A || cpu_model == 0x6C)
+ return 1;
+
+ return 0;
+}
+
static int update_cpu_model(void)
{
unsigned int ebx, ecx, edx;
@@ -175,31 +217,192 @@ int out_format_is_json(void)
return out_format_json;
}
-int get_physical_package_id(int cpu)
+static int get_stored_topology_info(int cpu, int *core_id, int *pkg_id, int *die_id)
+{
+ const char *pathname = "/var/run/isst_cpu_topology.dat";
+ struct cpu_topology cpu_top;
+ FILE *fp;
+ int ret;
+
+ fp = fopen(pathname, "rb");
+ if (!fp)
+ return -1;
+
+ ret = fseek(fp, cpu * sizeof(cpu_top), SEEK_SET);
+ if (ret)
+ goto err_ret;
+
+ ret = fread(&cpu_top, sizeof(cpu_top), 1, fp);
+ if (ret != 1) {
+ ret = -1;
+ goto err_ret;
+ }
+
+ *pkg_id = cpu_top.pkg_id;
+ *core_id = cpu_top.core_id;
+ *die_id = cpu_top.die_id;
+ ret = 0;
+
+err_ret:
+ fclose(fp);
+
+ return ret;
+}
+
+static void store_cpu_topology(void)
+{
+ const char *pathname = "/var/run/isst_cpu_topology.dat";
+ FILE *fp;
+ int i;
+
+ fp = fopen(pathname, "rb");
+ if (fp) {
+ /* Mapping already exists */
+ fclose(fp);
+ return;
+ }
+
+ fp = fopen(pathname, "wb");
+ if (!fp) {
+ fprintf(stderr, "Can't create file:%s\n", pathname);
+ return;
+ }
+
+ fprintf(stderr, "Caching topology information\n");
+
+ for (i = 0; i < topo_max_cpus; ++i) {
+ struct cpu_topology cpu_top;
+
+ cpu_top.core_id = parse_int_file(0,
+ "/sys/devices/system/cpu/cpu%d/topology/core_id", i);
+ if (cpu_top.core_id < 0)
+ cpu_top.core_id = -1;
+
+ cpu_top.pkg_id = parse_int_file(0,
+ "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", i);
+ if (cpu_top.pkg_id < 0)
+ cpu_top.pkg_id = -1;
+
+ cpu_top.die_id = parse_int_file(0,
+ "/sys/devices/system/cpu/cpu%d/topology/die_id", i);
+ if (cpu_top.die_id < 0)
+ cpu_top.die_id = -1;
+
+ cpu_top.cpu = i;
+
+ if (fwrite(&cpu_top, sizeof(cpu_top), 1, fp) != 1) {
+ fprintf(stderr, "Can't write to:%s\n", pathname);
+ break;
+ }
+ }
+
+ fclose(fp);
+}
+
+static int get_physical_package_id(int cpu)
{
- return parse_int_file(
- 0, "/sys/devices/system/cpu/cpu%d/topology/physical_package_id",
- 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);
+ if (ret < 0) {
+ int core_id, pkg_id, die_id;
+
+ ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id);
+ if (!ret)
+ return pkg_id;
+ }
+
+ return ret;
}
-int get_physical_core_id(int cpu)
+static int get_physical_core_id(int cpu)
{
- return parse_int_file(
- 0, "/sys/devices/system/cpu/cpu%d/topology/core_id", 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);
+ if (ret < 0) {
+ int core_id, pkg_id, die_id;
+
+ ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id);
+ if (!ret)
+ return core_id;
+ }
+
+ return ret;
}
-int get_physical_die_id(int cpu)
+static int get_physical_die_id(int cpu)
{
int ret;
- ret = parse_int_file(0, "/sys/devices/system/cpu/cpu%d/topology/die_id",
- cpu);
+ 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);
+ if (ret < 0) {
+ int core_id, pkg_id, die_id;
+
+ ret = get_stored_topology_info(cpu, &core_id, &pkg_id, &die_id);
+ if (!ret) {
+ if (die_id < 0)
+ die_id = 0;
+
+ return die_id;
+ }
+ }
+
if (ret < 0)
ret = 0;
return ret;
}
+void set_isst_id(struct isst_id *id, int cpu)
+{
+ id->cpu = cpu;
+
+ id->pkg = get_physical_package_id(cpu);
+ if (id < 0 || id->pkg >= MAX_PACKAGE_COUNT)
+ id->pkg = -1;
+
+ id->die = get_physical_die_id(cpu);
+ if (id < 0 || id->die >= MAX_DIE_PER_PACKAGE)
+ id->die = -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)
+ 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);
@@ -210,7 +413,7 @@ int get_topo_max_cpus(void)
return topo_max_cpus;
}
-static void set_cpu_online_offline(int cpu, int state)
+void set_cpu_online_offline(int cpu, int state)
{
char buffer[128];
int fd, ret;
@@ -219,8 +422,14 @@ static void set_cpu_online_offline(int cpu, int state)
"/sys/devices/system/cpu/cpu%d/online", cpu);
fd = open(buffer, O_WRONLY);
- if (fd < 0)
+ if (fd < 0) {
+ if (!cpu && state) {
+ 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");
+ return;
+ }
err(-1, "%s open failed", buffer);
+ }
if (state)
ret = write(fd, "1\n", 2);
@@ -233,15 +442,26 @@ 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_package_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;
memset(max_packages, 0xff, sizeof(max_packages));
for (i = 0; i < topo_max_cpus; ++i) {
@@ -259,7 +479,12 @@ static void for_each_online_package_in_set(void (*callback)(int, void *, void *,
die_id = get_physical_die_id(i);
if (die_id < 0)
die_id = 0;
- pkg_id = get_physical_package_id(i);
+
+ pkg_id = parse_int_file(0,
+ "/sys/devices/system/cpu/cpu%d/topology/physical_package_id", i);
+ if (pkg_id < 0)
+ continue;
+
/* Create an unique id for package, die combination to store */
pkg_id = (MAX_PACKAGE_COUNT * pkg_id + die_id);
@@ -270,18 +495,20 @@ static void for_each_online_package_in_set(void (*callback)(int, void *, void *,
}
}
+ set_isst_id(&id, i);
if (!skip && online && callback) {
- callback(i, arg1, arg2, arg3, arg4);
+ callback(&id, arg1, arg2, arg3, arg4);
max_packages[pkg_index++] = pkg_id;
}
}
}
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;
+ int i, found = 0;
+ struct isst_id id;
for (i = 0; i < topo_max_cpus; ++i) {
int online;
@@ -295,9 +522,15 @@ static void for_each_online_target_cpu_in_set(
online =
1; /* online entry for CPU 0 needs some special configs */
- if (online && callback)
- callback(i, arg1, arg2, arg3, arg4);
+ set_isst_id(&id, i);
+ if (online && callback) {
+ callback(&id, arg1, arg2, arg3, arg4);
+ found = 1;
+ }
}
+
+ if (!found)
+ fprintf(stderr, "No valid CPU in the list\n");
}
#define BITMASK_SIZE 32
@@ -305,14 +538,27 @@ static void set_max_cpu_num(void)
{
FILE *filep;
unsigned long dummy;
+ int i;
topo_max_cpus = 0;
- filep = fopen_or_exit(
- "/sys/devices/system/cpu/cpu0/topology/thread_siblings", "r");
+ 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) {
+ fprintf(stderr, "Can't get max cpu number\n");
+ exit(0);
+ }
+
while (fscanf(filep, "%lx,", &dummy) == 1)
topo_max_cpus += BITMASK_SIZE;
fclose(filep);
- topo_max_cpus--; /* 0 based */
debug_printf("max cpus %d\n", topo_max_cpus);
}
@@ -338,103 +584,85 @@ void free_cpu_set(cpu_set_t *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 < 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);
- }
-}
-
-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;
-}
-
-int get_cpu_count(int pkg_id, int die_id)
-{
- if (pkg_id < MAX_PACKAGE_COUNT && die_id < MAX_DIE_PER_PACKAGE)
- return cpu_cnt[pkg_id][die_id];
-
- return 0;
+ return max_id;
}
-static void set_cpu_target_cpu_mask(void)
+int get_cpu_count(struct isst_id *id)
{
- size_t size;
- 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;
+ if (id->pkg < 0 || id->die < 0)
+ return 0;
- CPU_SET_S(target_cpus[i], size, target_cpumask);
- }
+ return cpu_cnt[id->pkg][id->die];
}
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;
+
+ /* 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);
+
+ pkg_id = get_physical_package_id(i);
+ die_id = get_physical_die_id(i);
+ core_id = get_physical_core_id(i);
+
+ 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;
+ cpu_map[i].initialized = 1;
+
+ cpu_cnt[pkg_id][die_id]++;
+
+ if (fd < 0)
+ continue;
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) {
@@ -443,9 +671,6 @@ static void create_cpu_map(void)
map.cpu_map[0].logical_cpu);
continue;
}
- 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
@@ -456,46 +681,37 @@ static void create_cpu_map(void)
cpu_map[i].pkg_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;
*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(i)) {
+ if (core_mask & BIT_ULL(i)) {
int j;
for (j = 0; j < topo_max_cpus; ++j) {
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);
@@ -542,7 +758,11 @@ static int isst_send_mmio_command(unsigned int cpu, unsigned int reg, int write,
}
if (ioctl(fd, cmd, &io_regs) == -1) {
- perror("ISST_IF_IO_CMD");
+ 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 {
@@ -564,14 +784,15 @@ int isst_send_mbox_command(unsigned int cpu, unsigned char command,
unsigned int req_data, unsigned int *resp)
{
const char *pathname = "/dev/isst_interface";
- int fd;
+ 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 (isst_platform_info.mmio_supported && command == CONFIG_CLOS) {
+ 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;
@@ -615,25 +836,42 @@ int isst_send_mbox_command(unsigned int cpu, unsigned char 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);
- if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) {
- perror("ISST_IF_MBOX_COMMAND");
- fprintf(outf,
- "Error: mbox_cmd cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n",
- cpu, command, sub_command, parameter, req_data);
- 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);
- }
+ 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;
}
@@ -656,7 +894,7 @@ int isst_send_msr_command(unsigned int cpu, unsigned int msr, int write,
msr_cmds.msr_cmd[0].data = *req_resp;
if (ioctl(fd, ISST_IF_MSR_COMMAND, &msr_cmds) == -1) {
- perror("ISST_IF_MSR_COMMAD");
+ perror("ISST_IF_MSR_COMMAND");
fprintf(outf, "Error: msr_cmd cpu:%d msr:%x read_write:%d\n",
cpu, msr, write);
} else {
@@ -697,12 +935,95 @@ static int isst_fill_platform_info(void)
return 0;
}
+static void isst_print_extended_platform_info(void)
+{
+ 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 id;
+
+ 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)
+ return;
+
+ fclose(filep);
+
+ set_isst_id(&id, i);
+ 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.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);
+
+ for (j = 0; j <= pkg_dev.levels; ++j) {
+ ret = isst_get_ctdp_control(&id, j, &ctdp_level);
+ if (ret)
+ continue;
+
+ if (!fact_support && ctdp_level.fact_support)
+ fact_support = 1;
+
+ if (!pbf_support && ctdp_level.pbf_support)
+ pbf_support = 1;
+ }
+
+ if (fact_support)
+ 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)
+ 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(&id, &cp_state, &cp_cap);
+ if (ret) {
+ 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
+ fprintf(outf, "Intel(R) SST-CP (feature core-power) is not supported\n");
+}
+
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);
+ }
+
+ /* Early initialization to create working cpu_map */
+ set_max_cpu_num();
+ create_cpu_map();
+
fd = open(pathname, O_RDWR);
if (fd < 0)
err(-1, "%s open failed", pathname);
@@ -718,6 +1039,7 @@ static void isst_print_platform_information(void)
platform_info.mbox_supported);
fprintf(outf, "Platform: mmio supported : %d\n",
platform_info.mmio_supported);
+ isst_print_extended_platform_info();
}
close(fd);
@@ -725,22 +1047,24 @@ static void isst_print_platform_information(void)
exit(0);
}
-static void exec_on_get_ctdp_cpu(int cpu, void *arg1, void *arg2, void *arg3,
+static char *local_str0, *local_str1;
+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)
- perror("get_tdp_*");
+ isst_display_error_info_message(1, "get_tdp_* failed", 0, 0);
else
- isst_ctdp_display_core_info(cpu, outf, arg3,
- *(unsigned int *)arg4);
+ isst_ctdp_display_core_info(id, outf, arg3,
+ *(unsigned int *)arg4,
+ local_str0, local_str1);
}
-#define _get_tdp_level(desc, suffix, object, help) \
+#define _get_tdp_level(desc, suffix, object, help, str0, str1) \
static void get_tdp_##object(int arg) \
{ \
struct isst_pkg_ctdp ctdp; \
@@ -751,6 +1075,8 @@ static void exec_on_get_ctdp_cpu(int cpu, void *arg1, void *arg2, void *arg3,
help); \
exit(0); \
} \
+ local_str0 = str0; \
+ local_str1 = str1; \
isst_ctdp_display_information_start(outf); \
if (max_target_cpus) \
for_each_online_target_cpu_in_set( \
@@ -764,12 +1090,12 @@ static void exec_on_get_ctdp_cpu(int cpu, void *arg1, void *arg2, void *arg3,
isst_ctdp_display_information_end(outf); \
}
-_get_tdp_level("get-config-levels", levels, levels, "TDP levels");
-_get_tdp_level("get-config-version", levels, version, "TDP version");
-_get_tdp_level("get-config-enabled", levels, enabled, "TDP enable status");
+_get_tdp_level("get-config-levels", levels, levels, "Max TDP level", NULL, NULL);
+_get_tdp_level("get-config-version", levels, version, "TDP version", NULL, NULL);
+_get_tdp_level("get-config-enabled", levels, enabled, "perf-profile enable status", "disabled", "enabled");
_get_tdp_level("get-config-current_level", levels, current_level,
- "Current TDP Level");
-_get_tdp_level("get-lock-status", levels, locked, "TDP lock status");
+ "Current TDP Level", NULL, NULL);
+_get_tdp_level("get-lock-status", levels, locked, "TDP lock status", "unlocked", "locked");
struct isst_pkg_ctdp clx_n_pkg_dev;
@@ -801,9 +1127,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;
@@ -825,15 +1151,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,
@@ -870,8 +1192,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,
@@ -897,39 +1218,47 @@ 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;
- ret = clx_n_config(cpu);
+ if (tdp_level != 0xff && tdp_level != 0) {
+ isst_display_error_info_message(1, "Invalid level", 1, tdp_level);
+ exit(0);
+ }
+
+ ret = clx_n_config(id);
if (ret) {
- perror("isst_get_process_ctdp");
+ debug_printf("clx_n_config failed");
} else {
struct isst_pkg_ctdp_level_info *ctdp_level;
struct isst_pbf_info *pbf_info;
ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
pbf_info = &ctdp_level->pbf_info;
- isst_ctdp_display_information(cpu, outf, tdp_level, &clx_n_pkg_dev);
+ clx_n_pkg_dev.processed = 1;
+ 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) {
- perror("isst_get_process_ctdp");
+ 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);
}
}
@@ -963,34 +1292,44 @@ static void dump_isst_config(int arg)
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)
{
int ret;
- ret = isst_set_tdp_level(cpu, tdp_level);
- if (ret)
- perror("set_tdp_level_for_cpu");
- else {
- isst_display_result(cpu, outf, "perf-profile", "set_tdp_level",
+ 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(id, 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);
+
+ /* Wait for updated base frequencies */
+ usleep(2000);
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);
+ 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);
+ return;
+ }
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))
+ 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);
@@ -1009,11 +1348,13 @@ static void set_tdp_level(int arg)
"\t Arguments: -l|--level : Specify tdp level\n");
fprintf(stderr,
"\t Optional Arguments: -o | online : online/offline for the tdp level\n");
+ fprintf(stderr,
+ "\t online/offline operation has limitations, refer to Linux hotplug documentation\n");
exit(0);
}
if (tdp_level == 0xff) {
- fprintf(outf, "Invalid command: specify tdp_level\n");
+ isst_display_error_info_message(1, "Invalid command: specify tdp_level", 0, 0);
exit(1);
}
isst_ctdp_display_information_start(outf);
@@ -1026,37 +1367,39 @@ static void set_tdp_level(int arg)
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) {
- perror("isst_get_process_ctdp");
+ isst_display_error_info_message(1, "clx_n_config failed", 0, 0);
} else {
struct isst_pkg_ctdp_level_info *ctdp_level;
struct isst_pbf_info *pbf_info;
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) {
- perror("isst_get_pbf_info");
+ 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_pbf_display_information(id, outf, tdp_level, &pbf_info);
isst_get_pbf_info_complete(&pbf_info);
}
}
@@ -1074,7 +1417,7 @@ static void dump_pbf_config(int arg)
}
if (tdp_level == 0xff) {
- fprintf(outf, "Invalid command: specify tdp_level\n");
+ isst_display_error_info_message(1, "Invalid command: specify tdp_level", 0, 0);
exit(1);
}
@@ -1093,23 +1436,23 @@ static void dump_pbf_config(int arg)
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) {
- perror("isst_pm_get_clos");
+ isst_display_error_info_message(1, "isst_pm_get_clos failed", 0, 0);
return ret;
}
clos_config.clos_min = min;
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) {
- perror("isst_pm_set_clos");
+ isst_display_error_info_message(1, "isst_set_clos failed", 0, 0);
return ret;
}
@@ -1144,16 +1487,41 @@ 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) {
- perror("set_clx_pbf_cpufreq_scaling_min_max");
+ debug_printf("cpufreq_scaling_min_max failed for CLX");
return ret;
}
@@ -1162,11 +1530,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,
@@ -1229,83 +1594,75 @@ 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;
- 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;
+ 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;
- 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;
+ 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))
@@ -1314,9 +1671,10 @@ 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) {
- perror("isst_clos_associate");
+ isst_display_error_info_message(1, "isst_clos_associate failed", 0, 0);
return ret;
}
}
@@ -1324,95 +1682,111 @@ 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);
+ ret = isst_get_ctdp_levels(id, &pkg_dev);
if (ret) {
- perror("isst_get_ctdp_levels");
+ 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) {
- perror("isst_get_pbf_info");
+ debug_printf("isst_get_pbf_info failed");
return ret;
}
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) {
- perror("set_core_priority_and_min");
+ debug_printf("set_core_priority_and_min failed");
return ret;
}
- ret = isst_pm_qos_config(cpu, 1, 1);
+ ret = isst_pm_qos_config(id, 1, 1);
if (ret) {
- perror("isst_pm_qos_config");
+ debug_printf("isst_pm_qos_config failed");
return ret;
}
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;
+ struct isst_pkg_ctdp pkg_dev;
int ret;
int status = *(int *)arg4;
if (is_clx_n_platform()) {
+ ret = 0;
if (status) {
- ret = 0;
- if (auto_mode)
- set_clx_pbf_cpufreq_scaling_min_max(cpu);
+ set_clx_pbf_cpufreq_scaling_min_max(id);
} else {
- ret = -1;
- if (auto_mode) {
- 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(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(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;
+ }
+
+ if (!ctdp_level.pbf_support) {
+ isst_display_error_info_message(1, "base-freq feature is not present at this level", 1, pkg_dev.current_level);
+ ret = -1;
+ goto disp_result;
+ }
+
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) {
- perror("isst_set_pbf");
+ 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, 0);
+ 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);
}
@@ -1424,10 +1798,25 @@ static void set_pbf_enable(int arg)
if (enable) {
fprintf(stderr,
"Enable Intel Speed Select Technology base frequency feature\n");
+ if (is_clx_n_platform()) {
+ fprintf(stderr,
+ "\tOn this platform this command doesn't enable feature in the hardware.\n");
+ fprintf(stderr,
+ "\tIt updates the cpufreq scaling_min_freq to match cpufreq base_frequency.\n");
+ exit(0);
+
+ }
fprintf(stderr,
"\tOptional Arguments: -a|--auto : Use priority of cores to set core-power associations\n");
} else {
+ if (is_clx_n_platform()) {
+ fprintf(stderr,
+ "\tOn this platform this command doesn't disable feature in the hardware.\n");
+ fprintf(stderr,
+ "\tIt updates the cpufreq scaling_min_freq to match cpuinfo_min_freq\n");
+ exit(0);
+ }
fprintf(stderr,
"Disable Intel Speed Select Technology base frequency feature\n");
fprintf(stderr,
@@ -1446,18 +1835,21 @@ static void set_pbf_enable(int arg)
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_info);
- if (ret)
- perror("isst_get_fact_bucket_info");
- else
- isst_fact_display_information(cpu, outf, tdp_level, fact_bucket,
+ 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(id, outf, tdp_level, fact_bucket,
fact_avx, &fact_info);
+ }
}
static void dump_fact_config(int arg)
@@ -1475,7 +1867,7 @@ static void dump_fact_config(int arg)
}
if (tdp_level == 0xff) {
- fprintf(outf, "Invalid command: specify tdp_level\n");
+ isst_display_error_info_message(1, "Invalid command: specify tdp_level\n", 0, 0);
exit(1);
}
@@ -1489,23 +1881,49 @@ static void dump_fact_config(int arg)
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;
+ struct isst_pkg_ctdp pkg_dev;
int ret;
int status = *(int *)arg4;
- if (auto_mode && status) {
- ret = isst_pm_qos_config(cpu, 1, 1);
+ 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(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;
+ }
+
+ if (!ctdp_level.fact_support) {
+ isst_display_error_info_message(1, "turbo-freq feature is not present at this level", 1, pkg_dev.current_level);
+ ret = -1;
+ goto disp_results;
+ }
+
+ if (status) {
+ 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) {
- perror("isst_set_fact");
+ 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;
}
@@ -1514,29 +1932,32 @@ 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);
+ ret = isst_get_ctdp_levels(id, &pkg_dev);
if (!ret)
- ret = isst_set_trl(cpu, fact_trl);
+ 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) {
@@ -1568,7 +1989,7 @@ static void set_fact_enable(int arg)
NULL, &enable);
isst_ctdp_display_information_end(outf);
- if (enable && auto_mode) {
+ if (!fact_enable_fail && enable && auto_mode) {
/*
* When we adjust CLOS param, we have to set for siblings also.
* So for the each user specified CPU, also add the sibling
@@ -1610,19 +2031,20 @@ 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);
+ 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;
@@ -1632,35 +2054,39 @@ 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);
}
return;
error_disp:
- isst_display_result(i, outf, "turbo-freq --auto", "enable", ret);
+ isst_display_result(&id, outf, "turbo-freq --auto", "enable", ret);
}
-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;
- ret = isst_pm_qos_config(cpu, status, clos_priority_type);
+ if (is_skx_based_platform())
+ clos_priority_type = 1;
+
+ ret = isst_pm_qos_config(id, status, clos_priority_type);
if (ret)
- perror("isst_pm_qos_config");
+ 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);
}
@@ -1672,9 +2098,11 @@ static void set_clos_enable(int arg)
if (enable) {
fprintf(stderr,
"Enable core-power for a package/die\n");
- fprintf(stderr,
- "\tClos Enable: Specify priority type with [--priority|-p]\n");
- fprintf(stderr, "\t\t 0: Proportional, 1: Ordered\n");
+ if (!is_skx_based_platform()) {
+ fprintf(stderr,
+ "\tClos Enable: Specify priority type with [--priority|-p]\n");
+ fprintf(stderr, "\t\t 0: Proportional, 1: Ordered\n");
+ }
} else {
fprintf(stderr,
"Disable core-power: [No command arguments are required]\n");
@@ -1697,17 +2125,17 @@ static void set_clos_enable(int arg)
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)
- perror("isst_pm_get_clos");
+ 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);
}
@@ -1721,7 +2149,8 @@ static void dump_clos_config(int arg)
exit(0);
}
if (current_clos < 0 || current_clos > 3) {
- fprintf(stderr, "Invalid clos id\n");
+ isst_display_error_info_message(1, "Invalid clos id\n", 0, 0);
+ isst_ctdp_display_information_end(outf);
exit(0);
}
@@ -1735,16 +2164,21 @@ static void dump_clos_config(int arg)
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)
- perror("isst_clos_get_info");
- else
- isst_clos_display_clos_information(cpu, outf, enable, prio_type);
+ isst_display_error_info_message(1, "isst_clos_get_info failed", 0, 0);
+ else {
+ int cp_state, cp_cap;
+
+ isst_read_pm_config(id, &cp_state, &cp_cap);
+ isst_clos_display_clos_information(id, outf, enable, prio_type,
+ cp_state, cp_cap);
+ }
}
static void dump_clos_info(int arg)
@@ -1752,42 +2186,37 @@ static void dump_clos_info(int arg)
if (cmd_help) {
fprintf(stderr,
"Print Intel Speed Select Technology core power information\n");
- fprintf(stderr, "\tSpecify targeted cpu id with [--cpu|-c]\n");
- exit(0);
- }
-
- if (!max_target_cpus) {
- fprintf(stderr,
- "Invalid target cpu. Specify with [-c|--cpu]\n");
+ fprintf(stderr, "\t Optionally specify targeted cpu id with [--cpu|-c]\n");
exit(0);
}
isst_ctdp_display_information_start(outf);
- for_each_online_target_cpu_in_set(get_clos_info_for_cpu, NULL,
- NULL, NULL, NULL);
+ if (max_target_cpus)
+ 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,
+ 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);
-
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)
- perror("isst_set_clos");
+ 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)
@@ -1797,26 +2226,27 @@ static void set_clos_config(int arg)
"Set core-power configuration for one of the four clos ids\n");
fprintf(stderr,
"\tSpecify targeted clos id with [--clos|-c]\n");
- fprintf(stderr, "\tSpecify clos EPP with [--epp|-e]\n");
- fprintf(stderr,
- "\tSpecify clos Proportional Priority [--weight|-w]\n");
+ if (!is_skx_based_platform()) {
+ fprintf(stderr, "\tSpecify clos EPP with [--epp|-e]\n");
+ fprintf(stderr,
+ "\tSpecify clos Proportional Priority [--weight|-w]\n");
+ }
fprintf(stderr, "\tSpecify clos min in MHz with [--min|-n]\n");
fprintf(stderr, "\tSpecify clos max in MHz with [--max|-m]\n");
- fprintf(stderr, "\tSpecify clos desired in MHz with [--desired|-d]\n");
exit(0);
}
if (current_clos < 0 || current_clos > 3) {
- fprintf(stderr, "Invalid clos id\n");
+ isst_display_error_info_message(1, "Invalid clos id\n", 0, 0);
exit(0);
}
- if (clos_epp < 0 || clos_epp > 0x0F) {
- fprintf(stderr, "clos epp is not specified, default: 0\n");
+ if (!is_skx_based_platform() && (clos_epp < 0 || clos_epp > 0x0F)) {
+ fprintf(stderr, "clos epp is not specified or invalid, default: 0\n");
clos_epp = 0;
}
- if (clos_prop_prio < 0 || clos_prop_prio > 0x0F) {
+ if (!is_skx_based_platform() && (clos_prop_prio < 0 || clos_prop_prio > 0x0F)) {
fprintf(stderr,
- "clos frequency weight is not specified, default: 0\n");
+ "clos frequency weight is not specified or invalid, default: 0\n");
clos_prop_prio = 0;
}
if (clos_min < 0) {
@@ -1824,11 +2254,11 @@ static void set_clos_config(int arg)
clos_min = 0;
}
if (clos_max < 0) {
- fprintf(stderr, "clos max is not specified, default: 25500 MHz\n");
+ fprintf(stderr, "clos max is not specified, default: Max frequency (ratio 0xff)\n");
clos_max = 0xff;
}
- if (clos_desired < 0) {
- fprintf(stderr, "clos desired is not specified, default: 0\n");
+ if (clos_desired) {
+ fprintf(stderr, "clos desired is not supported on this platform\n");
clos_desired = 0x00;
}
@@ -1842,16 +2272,16 @@ static void set_clos_config(int arg)
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)
- perror("isst_clos_associate");
+ 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)
@@ -1860,32 +2290,35 @@ static void set_clos_assoc(int arg)
fprintf(stderr, "Associate a clos id to a CPU\n");
fprintf(stderr,
"\tSpecify targeted clos id with [--clos|-c]\n");
+ fprintf(stderr,
+ "\tFor example to associate clos 1 to CPU 0: issue\n");
+ fprintf(stderr,
+ "\tintel-speed-select --cpu 0 core-power assoc --clos 1\n");
exit(0);
}
if (current_clos < 0 || current_clos > 3) {
- fprintf(stderr, "Invalid clos id\n");
+ isst_display_error_info_message(1, "Invalid clos id\n", 0, 0);
exit(0);
}
if (max_target_cpus)
for_each_online_target_cpu_in_set(set_clos_assoc_for_cpu, NULL,
NULL, NULL, NULL);
else {
- fprintf(stderr,
- "Invalid target cpu. Specify with [-c|--cpu]\n");
+ isst_display_error_info_message(1, "Invalid target cpu. Specify with [-c|--cpu]", 0, 0);
}
}
-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)
- perror("isst_clos_get_assoc_status");
+ 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)
@@ -1897,8 +2330,7 @@ static void get_clos_assoc(int arg)
}
if (!max_target_cpus) {
- fprintf(stderr,
- "Invalid target cpu. Specify with [-c|--cpu]\n");
+ isst_display_error_info_message(1, "Invalid target cpu. Specify with [-c|--cpu]", 0, 0);
exit(0);
}
@@ -1908,6 +2340,105 @@ 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", "enable", 0);
+ } else {
+ isst_display_result(id, outf, "turbo-mode", "disable", 0);
+ }
+}
+
+static void set_turbo_mode(int arg)
+{
+ int i, enable = arg;
+ struct isst_id id;
+
+ if (cmd_help) {
+ if (enable)
+ fprintf(stderr, "Set turbo mode enable\n");
+ else
+ fprintf(stderr, "Set turbo mode disable\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, enable);
+ }
+
+ }
+ 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 (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\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_package_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 },
@@ -1938,6 +2469,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 }
};
@@ -2035,7 +2570,7 @@ static void parse_cmd_args(int argc, int start, char **argv)
option_index = start;
optind = start + 1;
- while ((opt = getopt_long(argc, argv, "b:l:t:c:d:e:n:m:p:w:hoa",
+ while ((opt = getopt_long(argc, argv, "b:l:t:c:d:e:n:m:p:w:r:hoa",
long_options, &option_index)) != -1) {
switch (opt) {
case 'a':
@@ -2061,7 +2596,7 @@ static void parse_cmd_args(int argc, int start, char **argv)
fact_avx = 0x01;
} else if (!strncmp(optarg, "avx2", 4)) {
fact_avx = 0x02;
- } else if (!strncmp(optarg, "avx512", 4)) {
+ } else if (!strncmp(optarg, "avx512", 6)) {
fact_avx = 0x04;
} else {
fprintf(outf, "Invalid sse,avx options\n");
@@ -2078,6 +2613,10 @@ static void parse_cmd_args(int argc, int start, char **argv)
break;
case 'e':
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);
+ exit(0);
+ }
break;
case 'n':
clos_min = atoi(optarg);
@@ -2089,14 +2628,25 @@ static void parse_cmd_args(int argc, int start, char **argv)
break;
case 'p':
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);
+ exit(0);
+ }
break;
case 'w':
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);
+ exit(0);
+ }
break;
default:
- printf("no match\n");
+ printf("Unknown option: ignore\n");
}
}
+
+ if (argv[optind])
+ printf("Garbage at the end of command: ignore\n");
}
static void isst_help(void)
@@ -2138,6 +2688,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\
@@ -2162,6 +2722,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 }
};
@@ -2193,9 +2754,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) &&
@@ -2214,11 +2772,18 @@ void process_command(int argc, char **argv,
static void usage(void)
{
- printf("Intel(R) Speed Select Technology\n");
+ if (is_clx_n_platform()) {
+ fprintf(stderr, "\nThere is limited support of Intel Speed Select features on this platform.\n");
+ fprintf(stderr, "Everything is pre-configured using BIOS options, this tool can't enable any feature in the hardware.\n\n");
+ }
+
printf("\nUsage:\n");
printf("intel-speed-select [OPTIONS] FEATURE COMMAND COMMAND_ARGUMENTS\n");
- printf("\nUse this tool to enumerate and control the Intel Speed Select Technology features,\n");
- printf("\nFEATURE : [perf-profile|base-freq|turbo-freq|core-power]\n");
+ printf("\nUse this tool to enumerate and control the Intel Speed Select Technology features:\n");
+ if (is_clx_n_platform())
+ printf("\nFEATURE : [perf-profile|base-freq]\n");
+ else
+ 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");
@@ -2231,48 +2796,101 @@ static void usage(void)
printf("\t\tDefault: Die scoped for all dies in the system with multiple dies/package\n");
printf("\t\t\t Or Package scoped for all Packages when each package contains one die\n");
printf("\t[-d|--debug] : Debug mode\n");
+ 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[-f|--format] : output format [json|text]. Default: text\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("\nResult format\n");
printf("\tResult display uses a common format for each command:\n");
printf("\tResults are formatted in text/JSON with\n");
printf("\t\tPackage, Die, CPU, and command specific results.\n");
+
+ printf("\nExamples\n");
+ printf("\tTo get platform information:\n");
+ printf("\t\tintel-speed-select --info\n");
+ printf("\tTo get full perf-profile information dump:\n");
+ printf("\t\tintel-speed-select perf-profile info\n");
+ printf("\tTo get full base-freq information dump:\n");
+ printf("\t\tintel-speed-select base-freq info -l 0\n");
+ if (!is_clx_n_platform()) {
+ printf("\tTo get full turbo-freq information dump:\n");
+ printf("\t\tintel-speed-select turbo-freq info -l 0\n");
+ }
exit(1);
}
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)
{
- int opt;
+ const char *pathname = "/dev/isst_interface";
+ char *ptr;
+ FILE *fp;
+ int opt, force_cpus_online = 0;
int option_index = 0;
int ret;
+ int oob_mode = 0;
+ int poll_interval = -1;
+ int no_daemon = 0;
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' },
{ 0, 0, 0, 0 }
};
+ if (geteuid() != 0) {
+ fprintf(stderr, "Must run as root\n");
+ exit(0);
+ }
+
+ ret = update_cpu_model();
+ if (ret)
+ err(-1, "Invalid CPU model (%d)\n", cpu_model);
+ printf("Intel(R) Speed Select Technology\n");
+ printf("Executing on CPU model:%d[0x%x]\n", cpu_model, cpu_model);
+
+ if (!is_clx_n_platform()) {
+ fp = fopen(pathname, "rb");
+ if (!fp) {
+ fprintf(stderr, "Intel speed select drivers are not loaded on this system.\n");
+ fprintf(stderr, "Verify that kernel config includes CONFIG_INTEL_SPEED_SELECT_INTERFACE.\n");
+ fprintf(stderr, "If the config is included then this is not a supported platform.\n");
+ exit(0);
+ }
+ fclose(fp);
+ }
+
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:n", long_options,
&option_index)) != -1) {
switch (opt) {
+ case 'a':
+ force_cpus_online = 1;
+ break;
case 'c':
parse_cpu_command(optarg);
break;
@@ -2295,31 +2913,61 @@ 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;
default:
usage();
}
}
- if (geteuid() != 0) {
- fprintf(stderr, "Must run as root\n");
+ if (optind > (argc - 2) && !oob_mode) {
+ usage();
exit(0);
}
+ set_max_cpu_num();
+ if (force_cpus_online)
+ force_all_cpus_online();
+ store_cpu_topology();
+ create_cpu_map();
- if (optind > (argc - 2)) {
- fprintf(stderr, "Feature name and|or command not specified\n");
- exit(0);
+ 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)
+ fprintf(stderr, "OOB mode enable failed\n");
+ goto out;
}
- ret = update_cpu_model();
- if (ret)
- err(-1, "Invalid CPU model (%d)\n", cpu_model);
- printf("Intel(R) Speed Select Technology\n");
- printf("Executing on CPU model:%d[0x%x]\n", cpu_model, cpu_model);
- set_max_cpu_num();
- set_cpu_present_cpu_mask();
- set_cpu_target_cpu_mask();
if (!is_clx_n_platform()) {
ret = isst_fill_platform_info();
diff --git a/tools/power/x86/intel-speed-select/isst-core.c b/tools/power/x86/intel-speed-select/isst-core.c
index 81a119f688a3..f701b45c832c 100644
--- a/tools/power/x86/intel-speed-select/isst-core.c
+++ b/tools/power/x86/intel-speed-select/isst-core.c
@@ -6,7 +6,7 @@
#include "isst.h"
-int isst_write_pm_config(int cpu, int cp_state)
+int isst_write_pm_config(struct isst_id *id, int cp_state)
{
unsigned int req, resp;
int ret;
@@ -16,27 +16,27 @@ int isst_write_pm_config(int cpu, int cp_state)
else
req = 0;
- ret = isst_send_mbox_command(cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req,
+ ret = isst_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", cpu, resp);
+ debug_printf("cpu:%d WRITE_PM_CONFIG resp:%x\n", id->cpu, resp);
return 0;
}
-int isst_read_pm_config(int cpu, int *cp_state, int *cp_cap)
+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, READ_PM_CONFIG, PM_FEATURE, 0, 0,
+ ret = isst_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", cpu, resp);
+ 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;
@@ -44,12 +44,12 @@ int isst_read_pm_config(int cpu, int *cp_state, int *cp_cap)
return 0;
}
-int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev)
+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,
+ ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp);
if (ret) {
pkg_dev->levels = 0;
@@ -60,7 +60,7 @@ int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev)
return 0;
}
- debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", cpu, resp);
+ 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;
@@ -71,14 +71,14 @@ int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev)
return 0;
}
-int isst_get_ctdp_control(int cpu, int config_index,
+int isst_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 = isst_send_mbox_command(cpu, CONFIG_TDP,
+ ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
CONFIG_TDP_GET_TDP_CONTROL, 0,
config_index, &resp);
if (ret)
@@ -89,51 +89,53 @@ int isst_get_ctdp_control(int cpu, int config_index,
ctdp_level->fact_enabled = !!(resp & BIT(16));
ctdp_level->pbf_enabled = !!(resp & BIT(17));
- ret = isst_read_pm_config(cpu, &cp_state, &cp_cap);
+ ret = isst_read_pm_config(id, &cp_state, &cp_cap);
if (ret) {
- debug_printf("cpu:%d pm_config is not supported \n", cpu);
+ 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", cpu, cp_state, cp_cap);
+ 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",
- cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support,
+ id->cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support,
ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
return 0;
}
-int isst_get_tdp_info(int cpu, int config_index,
+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_TDP_INFO,
+ ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_INFO,
0, config_index, &resp);
- if (ret)
+ 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",
- cpu, config_index, resp, ctdp_level->tdp_ratio,
+ id->cpu, config_index, resp, ctdp_level->tdp_ratio,
ctdp_level->pkg_tdp);
return 0;
}
-int isst_get_pwr_info(int cpu, int config_index,
+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_PWR_INFO,
+ ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_PWR_INFO,
0, config_index, &resp);
if (ret)
return ret;
@@ -143,18 +145,18 @@ int isst_get_pwr_info(int cpu, int config_index,
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,
+ id->cpu, config_index, resp, ctdp_level->pkg_max_power,
ctdp_level->pkg_min_power);
return 0;
}
-void isst_get_uncore_p0_p1_info(int cpu, int config_index,
+void isst_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;
- ret = isst_send_mbox_command(cpu, CONFIG_TDP,
+ ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
CONFIG_TDP_GET_UNCORE_P0_P1_INFO, 0,
config_index, &resp);
if (ret) {
@@ -167,16 +169,16 @@ void isst_get_uncore_p0_p1_info(int cpu, int config_index,
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,
+ id->cpu, config_index, resp, ctdp_level->uncore_p0,
ctdp_level->uncore_p1);
}
-void isst_get_p1_info(int cpu, int config_index,
+void isst_get_p1_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_P1_INFO, 0,
+ ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_P1_INFO, 0,
config_index, &resp);
if (ret) {
ctdp_level->sse_p1 = 0;
@@ -190,16 +192,17 @@ void isst_get_p1_info(int cpu, int config_index,
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,
+ id->cpu, config_index, resp, ctdp_level->sse_p1,
ctdp_level->avx2_p1, ctdp_level->avx512_p1);
}
-void isst_get_uncore_mem_freq(int cpu, int config_index,
+void isst_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 = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_MEM_FREQ,
+
+ ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_MEM_FREQ,
0, config_index, &resp);
if (ret) {
ctdp_level->mem_freq = 0;
@@ -207,18 +210,32 @@ void isst_get_uncore_mem_freq(int cpu, int config_index,
}
ctdp_level->mem_freq = resp & GENMASK(7, 0);
+ if (is_spr_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",
- cpu, config_index, resp, ctdp_level->mem_freq);
+ id->cpu, config_index, resp, ctdp_level->mem_freq);
}
-int isst_get_tjmax_info(int cpu, int config_index,
+int isst_get_tjmax_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,
+ ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TJMAX_INFO,
0, config_index, &resp);
if (ret)
return ret;
@@ -227,12 +244,12 @@ int isst_get_tjmax_info(int cpu, int config_index,
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);
+ id->cpu, config_index, resp, ctdp_level->t_proc_hot);
return 0;
}
-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;
@@ -243,7 +260,7 @@ int isst_get_coremask_info(int cpu, int config_index,
unsigned long long mask;
int cpu_count = 0;
- ret = isst_send_mbox_command(cpu, CONFIG_TDP,
+ ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
CONFIG_TDP_GET_CORE_MASK, 0,
(i << 8) | config_index, &resp);
if (ret)
@@ -251,27 +268,27 @@ int isst_get_coremask_info(int cpu, int config_index,
debug_printf(
"cpu:%d ctdp:%d mask:%d CONFIG_TDP_GET_CORE_MASK resp:%x\n",
- cpu, config_index, i, resp);
+ id->cpu, config_index, i, resp);
mask = (unsigned long long)resp << (32 * i);
- set_cpu_mask_from_punit_coremask(cpu, mask,
+ 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", cpu,
+ debug_printf("cpu:%d ctdp:%d mask:%d cpu count:%d\n", id->cpu,
config_index, i, ctdp_level->cpu_count);
}
return 0;
}
-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;
@@ -287,13 +304,13 @@ 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,
+ ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
&resp);
if (ret)
@@ -301,7 +318,7 @@ int isst_get_get_trl(int cpu, int level, int avx_level, int *trl)
debug_printf(
"cpu:%d CONFIG_TDP_GET_TURBO_LIMIT_RATIOS req:%x resp:%x\n",
- cpu, req, resp);
+ id->cpu, req, resp);
trl[0] = resp & GENMASK(7, 0);
trl[1] = (resp & GENMASK(15, 8)) >> 8;
@@ -309,13 +326,13 @@ int isst_get_get_trl(int cpu, int level, int avx_level, int *trl)
trl[3] = (resp & GENMASK(31, 24)) >> 24;
req = level | BIT(8) | (avx_level << 16);
- ret = isst_send_mbox_command(cpu, CONFIG_TDP,
+ ret = isst_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", cpu,
+ debug_printf("cpu:%d CONFIG_TDP_GET_TURBO_LIMIT req:%x resp:%x\n", id->cpu,
req, resp);
trl[4] = resp & GENMASK(7, 0);
@@ -326,76 +343,83 @@ int isst_get_get_trl(int cpu, int level, int avx_level, int *trl)
return 0;
}
-int isst_get_trl_bucket_info(int cpu, unsigned long long *buckets_info)
+int isst_get_trl_bucket_info(struct isst_id *id, unsigned long long *buckets_info)
{
int ret;
- debug_printf("cpu:%d bucket info via MSR\n", cpu);
+ debug_printf("cpu:%d bucket info via MSR\n", id->cpu);
*buckets_info = 0;
- ret = isst_send_msr_command(cpu, 0x1ae, 0, buckets_info);
+ 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", cpu,
+ debug_printf("cpu:%d bucket info via MSR successful 0x%llx\n", id->cpu,
*buckets_info);
return 0;
}
-int isst_set_tdp_level_msr(int cpu, int tdp_level)
+int isst_set_tdp_level(struct isst_id *id, int tdp_level)
{
- unsigned long long level = tdp_level;
+ unsigned int resp;
int ret;
- debug_printf("cpu: tdp_level via MSR %d\n", cpu, tdp_level);
- if (isst_get_config_tdp_lock_status(cpu)) {
- debug_printf("cpu: tdp_locked %d\n", cpu);
+ if (isst_get_config_tdp_lock_status(id)) {
+ isst_display_error_info_message(1, "TDP is locked", 0, 0);
return -1;
- }
- if (tdp_level > 2)
- return -1; /* invalid value */
+ }
- ret = isst_send_msr_command(cpu, 0x64b, 1, &level);
- if (ret)
+ ret = isst_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;
-
- debug_printf("cpu: tdp_level via MSR successful %d\n", cpu, tdp_level);
+ }
return 0;
}
-int isst_set_tdp_level(int cpu, int tdp_level)
+int isst_get_pbf_info(struct isst_id *id, int level, struct isst_pbf_info *pbf_info)
{
- unsigned int resp;
- int ret;
+ struct isst_pkg_ctdp_level_info ctdp_level;
+ struct isst_pkg_ctdp pkg_dev;
+ int i, ret, max_punit_core, max_mask_index;
+ unsigned int req, resp;
- ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_SET_LEVEL, 0,
- tdp_level, &resp);
- if (ret)
- return isst_set_tdp_level_msr(cpu, tdp_level);
+ 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;
+ }
- return 0;
-}
+ if (level > pkg_dev.levels) {
+ isst_display_error_info_message(1, "Invalid level", 1, level);
+ return -1;
+ }
-int isst_get_pbf_info(int cpu, int level, struct isst_pbf_info *pbf_info)
-{
- int i, ret, core_cnt, max;
- unsigned int req, resp;
+ ret = isst_get_ctdp_control(id, level, &ctdp_level);
+ if (ret)
+ return ret;
+
+ if (!ctdp_level.pbf_support) {
+ isst_display_error_info_message(1, "base-freq feature is not present at this level", 1, level);
+ return -1;
+ }
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;
+ max_punit_core = get_max_punit_core_id(id);
+ max_mask_index = max_punit_core > 32 ? 2 : 1;
- for (i = 0; i < max; ++i) {
+ for (i = 0; i < max_mask_index; ++i) {
unsigned long long mask;
int count;
- ret = isst_send_mbox_command(cpu, CONFIG_TDP,
+ ret = isst_send_mbox_command(id->cpu, CONFIG_TDP,
CONFIG_TDP_PBF_GET_CORE_MASK_INFO,
0, (i << 8) | level, &resp);
if (ret)
@@ -403,23 +427,23 @@ int isst_get_pbf_info(int cpu, int level, struct isst_pbf_info *pbf_info)
debug_printf(
"cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n",
- cpu, resp);
+ id->cpu, resp);
mask = (unsigned long long)resp << (32 * i);
- set_cpu_mask_from_punit_coremask(cpu, mask,
+ set_cpu_mask_from_punit_coremask(id, mask,
pbf_info->core_cpumask_size,
pbf_info->core_cpumask,
&count);
}
req = level;
- ret = isst_send_mbox_command(cpu, CONFIG_TDP,
+ ret = isst_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", cpu,
+ debug_printf("cpu:%d CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO resp:%x\n", id->cpu,
resp);
pbf_info->p1_low = resp & 0xff;
@@ -427,21 +451,21 @@ int isst_get_pbf_info(int cpu, int level, struct isst_pbf_info *pbf_info)
req = level;
ret = isst_send_mbox_command(
- cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TDP_INFO, 0, req, &resp);
+ 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", cpu, resp);
+ debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TDP_INFO resp:%x\n", id->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);
+ 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", cpu,
+ 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;
@@ -454,7 +478,7 @@ void isst_get_pbf_info_complete(struct isst_pbf_info *pbf_info)
free_cpu_set(pbf_info->core_cpumask);
}
-int isst_set_pbf_fact_status(int cpu, int pbf, int enable)
+int isst_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;
@@ -462,13 +486,13 @@ int isst_set_pbf_fact_status(int cpu, int pbf, int enable)
unsigned int req = 0, resp;
int ret;
- ret = isst_get_ctdp_levels(cpu, &pkg_dev);
+ ret = isst_get_ctdp_levels(id, &pkg_dev);
if (ret)
- debug_printf("cpu:%d No support for dynamic ISST\n", cpu);
+ debug_printf("cpu:%d No support for dynamic ISST\n", id->cpu);
current_level = pkg_dev.current_level;
- ret = isst_get_ctdp_control(cpu, current_level, &ctdp_level);
+ ret = isst_get_ctdp_control(id, current_level, &ctdp_level);
if (ret)
return ret;
@@ -481,6 +505,10 @@ int isst_set_pbf_fact_status(int cpu, int pbf, int enable)
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);
@@ -490,18 +518,18 @@ int isst_set_pbf_fact_status(int cpu, int pbf, int enable)
req &= ~BIT(16);
}
- ret = isst_send_mbox_command(cpu, CONFIG_TDP,
+ ret = isst_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",
- cpu, pbf, req);
+ id->cpu, pbf, req);
return 0;
}
-int isst_get_fact_bucket_info(int cpu, int level,
+int isst_get_fact_bucket_info(struct isst_id *id, int level,
struct isst_fact_bucket_info *bucket_info)
{
unsigned int resp;
@@ -511,7 +539,7 @@ int isst_get_fact_bucket_info(int cpu, int level,
int j;
ret = isst_send_mbox_command(
- cpu, CONFIG_TDP,
+ id->cpu, CONFIG_TDP,
CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES, 0,
(i << 8) | level, &resp);
if (ret)
@@ -519,7 +547,7 @@ int isst_get_fact_bucket_info(int cpu, int level,
debug_printf(
"cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES index:%d level:%d resp:%x\n",
- cpu, i, level, resp);
+ id->cpu, i, level, resp);
for (j = 0; j < 4; ++j) {
bucket_info[j + (i * 4)].high_priority_cores_count =
@@ -532,7 +560,7 @@ int isst_get_fact_bucket_info(int cpu, int level,
int j;
ret = isst_send_mbox_command(
- cpu, CONFIG_TDP,
+ id->cpu, CONFIG_TDP,
CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS, 0,
(k << 16) | (i << 8) | level, &resp);
if (ret)
@@ -540,7 +568,7 @@ int isst_get_fact_bucket_info(int cpu, int level,
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);
+ id->cpu, i, level, k, resp);
for (j = 0; j < 4; ++j) {
switch (k) {
@@ -566,44 +594,94 @@ int isst_get_fact_bucket_info(int cpu, int level,
return 0;
}
-int isst_get_fact_info(int cpu, int level, 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 ret;
+ int j, ret, print;
- ret = isst_send_mbox_command(cpu, CONFIG_TDP,
+ 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;
+ }
+
+ if (level > pkg_dev.levels) {
+ isst_display_error_info_message(1, "Invalid level", 1, level);
+ return -1;
+ }
+
+ ret = isst_get_ctdp_control(id, level, &ctdp_level);
+ if (ret)
+ return ret;
+
+ if (!ctdp_level.fact_support) {
+ isst_display_error_info_message(1, "turbo-freq feature is not present at this level", 1, level);
+ return -1;
+ }
+
+ ret = isst_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",
- cpu, resp);
+ id->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;
- ret = isst_get_fact_bucket_info(cpu, level, fact_info->bucket_info);
+ ret = isst_get_fact_bucket_info(id, level, fact_info->bucket_info);
+ if (ret)
+ return 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_get_trl(struct isst_id *id, unsigned long long *trl)
+{
+ int ret;
+
+ ret = isst_send_msr_command(id->cpu, 0x1AD, 0, trl);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+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)
+int isst_set_trl_from_current_tdp(struct isst_id *id, unsigned long long trl)
{
unsigned long long msr_trl;
int ret;
@@ -615,11 +693,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;
@@ -630,7 +708,7 @@ int isst_set_trl_from_current_tdp(int cpu, unsigned long long trl)
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;
@@ -638,12 +716,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;
@@ -652,7 +730,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;
@@ -669,126 +747,138 @@ 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)
+int isst_get_process_ctdp(struct isst_id *id, int tdp_level, struct isst_pkg_ctdp *pkg_dev)
{
- int i, ret;
+ 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) {
+ isst_display_error_info_message(1, "Invalid level", 0, 0);
+ return -1;
+ }
+
+ if (!pkg_dev->enabled)
+ isst_display_error_info_message(0, "perf-profile feature is not supported, just base-config level 0 is valid", 0, 0);
+
for (i = 0; i <= pkg_dev->levels; ++i) {
struct isst_pkg_ctdp_level_info *ctdp_level;
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;
+ valid = 1;
pkg_dev->processed = 1;
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,
+ 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_sse_active_cores);
+ isst_get_trl_bucket_info(id, &ctdp_level->buckets_info);
continue;
}
- ret = isst_get_tdp_info(cpu, i, ctdp_level);
+ ret = isst_get_tdp_info(id, i, ctdp_level);
if (ret)
return ret;
- ret = isst_get_pwr_info(cpu, i, ctdp_level);
+ ret = isst_get_pwr_info(id, i, ctdp_level);
if (ret)
return ret;
- ret = isst_get_tjmax_info(cpu, i, ctdp_level);
+ ret = isst_get_tjmax_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, &ctdp_level->buckets_info);
if (ret)
return ret;
- ret = isst_get_get_trl(cpu, i, 0,
+ ret = isst_get_get_trl(id, i, 0,
ctdp_level->trl_sse_active_cores);
if (ret)
return ret;
- ret = isst_get_get_trl(cpu, i, 1,
+ ret = isst_get_get_trl(id, i, 1,
ctdp_level->trl_avx_active_cores);
if (ret)
return ret;
- ret = isst_get_get_trl(cpu, i, 2,
+ ret = isst_get_get_trl(id, 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);
+ isst_get_uncore_p0_p1_info(id, i, ctdp_level);
+ isst_get_p1_info(id, i, ctdp_level);
+ isst_get_uncore_mem_freq(id, 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, 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,
+ ret = isst_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", cpu, resp);
+ debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);
if (resp & BIT(1))
*enable = 1;
@@ -803,7 +893,7 @@ int isst_clos_get_clos_information(int cpu, int *enable, int *type)
return 0;
}
-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;
@@ -812,36 +902,38 @@ int isst_pm_qos_config(int cpu, int enable_clos, int priority_type)
struct isst_pkg_ctdp pkg_dev;
struct isst_pkg_ctdp_level_info ctdp_level;
- ret = isst_get_ctdp_levels(cpu, &pkg_dev);
+ ret = isst_get_ctdp_levels(id, &pkg_dev);
if (ret) {
debug_printf("isst_get_ctdp_levels\n");
return ret;
}
- ret = isst_get_ctdp_control(cpu, pkg_dev.current_level,
+ ret = isst_get_ctdp_control(id, pkg_dev.current_level,
&ctdp_level);
if (ret)
return ret;
if (ctdp_level.fact_enabled) {
- debug_printf("Turbo-freq feature must be disabled first\n");
+ 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);
+ ret = isst_write_pm_config(id, 0);
if (ret)
- perror("isst_write_pm_config\n");
+ isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
} else {
- ret = isst_write_pm_config(cpu, 1);
+ ret = isst_write_pm_config(id, 1);
if (ret)
- perror("isst_write_pm_config\n");
+ 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,
+ ret = isst_send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
&resp);
- if (ret)
+ 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);
+ debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);
req = resp;
@@ -850,35 +942,35 @@ int isst_pm_qos_config(int cpu, int enable_clos, int priority_type)
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,
+ ret = isst_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", cpu,
+ debug_printf("cpu:%d CLOS_PM_QOS_CONFIG priority type:%d req:%x\n", id->cpu,
priority_type, req);
return 0;
}
-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,
+ ret = isst_send_mbox_command(id->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;
@@ -888,7 +980,7 @@ int isst_pm_get_clos(int cpu, int clos, struct isst_clos_config *clos_config)
return 0;
}
-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;
@@ -902,53 +994,53 @@ int isst_set_clos(int cpu, int clos, struct isst_clos_config *clos_config)
param = BIT(MBOX_CMD_WRITE_BIT) | clos;
- ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_CLOS, param, req,
+ ret = isst_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", cpu, param, req);
+ debug_printf("cpu:%d CLOS_PM_CLOS param:%x req:%x\n", id->cpu, param, req);
return 0;
}
-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);
+ core_id = find_phy_core_num(id->cpu);
param = core_id;
- ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 0,
+ ret = isst_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", cpu, param,
+ debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x resp:%x\n", id->cpu, param,
resp);
*clos_id = (resp >> 16) & 0x03;
return 0;
}
-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;
req = (clos_id & 0x03) << 16;
- core_id = find_phy_core_num(cpu);
+ core_id = find_phy_core_num(id->cpu);
param = BIT(MBOX_CMD_WRITE_BIT) | core_id;
- ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param,
+ ret = isst_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", cpu, param,
+ debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x req:%x\n", id->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..0699137c0901
--- /dev/null
+++ b/tools/power/x86/intel-speed-select/isst-daemon.c
@@ -0,0 +1,242 @@
+// 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];
+static time_t per_package_levels_tm[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE];
+
+static void init_levels(void)
+{
+ int i, j;
+
+ for (i = 0; i < MAX_PACKAGE_COUNT; ++i)
+ for (j = 0; j < MAX_DIE_PER_PACKAGE; ++j)
+ per_package_levels_info[i][j] = -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) {
+ 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] < 2)
+ return;
+
+ per_package_levels_tm[id->pkg][id->die] = 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] == 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],
+ pkg_dev.current_level);
+
+ per_package_levels_info[id->pkg][id->die] = 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 (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_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_package_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);
+ ret = dup(i);
+ if (ret == -1)
+ 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 4fb0c1d49d64..b19f57d30f55 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,27 +166,34 @@ static void format_and_print(FILE *outf, int level, char *header, char *value)
last_level = level;
}
-static void print_package_info(int cpu, FILE *outf)
+static int print_package_info(struct isst_id *id, FILE *outf)
{
char header[256];
- snprintf(header, sizeof(header), "package-%d",
- get_physical_package_id(cpu));
+ if (out_format_is_json()) {
+ snprintf(header, sizeof(header), "package-%d:die-%d:cpu-%d",
+ id->pkg, id->die, id->cpu);
+ format_and_print(outf, 1, header, NULL);
+ return 1;
+ }
+ snprintf(header, sizeof(header), "package-%d", id->pkg);
format_and_print(outf, 1, header, NULL);
- snprintf(header, sizeof(header), "die-%d", get_physical_die_id(cpu));
+ snprintf(header, sizeof(header), "die-%d", id->die);
format_and_print(outf, 2, header, NULL);
- snprintf(header, sizeof(header), "cpu-%d", cpu);
+ snprintf(header, sizeof(header), "cpu-%d", id->cpu);
format_and_print(outf, 3, header, NULL);
+
+ return 3;
}
-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];
+ char value[512];
- snprintf(header, sizeof(header), "speed-select-base-freq");
+ 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)");
@@ -214,7 +229,7 @@ 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)
@@ -222,9 +237,23 @@ static void _isst_fact_display_information(int cpu, FILE *outf, int level,
struct isst_fact_bucket_info *bucket_info = fact_info->bucket_info;
char header[256];
char value[256];
- int j;
+ int print = 0, j;
+
+ for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
+ if (fact_bucket != 0xff && fact_bucket != j)
+ continue;
+
+ if (!bucket_info[j].high_priority_cores_count)
+ break;
+
+ print = 1;
+ }
+ if (!print) {
+ fprintf(stderr, "Invalid bucket\n");
+ return;
+ }
- snprintf(header, sizeof(header), "speed-select-turbo-freq");
+ 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) {
if (fact_bucket != 0xff && fact_bucket != j)
@@ -288,35 +317,47 @@ static void _isst_fact_display_information(int cpu, FILE *outf, int level,
format_and_print(outf, base_level + 2, header, value);
}
-void isst_ctdp_display_core_info(int cpu, FILE *outf, char *prefix,
- unsigned int val)
+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;
- 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);
+ if (out_format_is_json()) {
+ snprintf(header, sizeof(header), "package-%d:die-%d:cpu-%d",
+ id->pkg, id->die, id->cpu);
+ format_and_print(outf, level++, header, NULL);
+ } else {
+ snprintf(header, sizeof(header), "package-%d", id->pkg);
+ format_and_print(outf, level++, header, NULL);
+ snprintf(header, sizeof(header), "die-%d", id->die);
+ format_and_print(outf, level++, header, NULL);
+ snprintf(header, sizeof(header), "cpu-%d", id->cpu);
+ format_and_print(outf, level++, header, NULL);
+ }
- snprintf(value, sizeof(value), "%u", val);
- format_and_print(outf, 4, prefix, value);
+ if (str0 && !val)
+ snprintf(value, sizeof(value), "%s", str0);
+ else if (str1 && val)
+ snprintf(value, sizeof(value), "%s", str1);
+ else
+ snprintf(value, sizeof(value), "%u", val);
+ format_and_print(outf, level, prefix, value);
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];
- int i, base_level = 1;
+ char value[512];
+ static int level;
+ int i;
if (pkg_dev->processed)
- 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;
@@ -328,72 +369,79 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
snprintf(header, sizeof(header), "perf-profile-level-%d",
ctdp_level->level);
- format_and_print(outf, base_level + 3, header, NULL);
+ 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));
+ j = get_cpu_count(id);
snprintf(value, sizeof(value), "%d", j);
- format_and_print(outf, base_level + 4, header, value);
+ 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);
+ }
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, base_level + 4, header, value);
+ 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, base_level + 4, header, value);
+ format_and_print(outf, level + 2, header, value);
}
snprintf(header, sizeof(header), "thermal-design-power-ratio");
snprintf(value, sizeof(value), "%d", ctdp_level->tdp_ratio);
- format_and_print(outf, base_level + 4, header, value);
+ format_and_print(outf, level + 2, header, value);
snprintf(header, sizeof(header), "base-frequency(MHz)");
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);
- format_and_print(outf, base_level + 4, header, value);
+ 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);
- format_and_print(outf, base_level + 4, header, value);
+ 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);
- format_and_print(outf, base_level + 4, header, value);
+ format_and_print(outf, level + 2, header, value);
}
if (ctdp_level->uncore_p1) {
snprintf(header, sizeof(header), "uncore-frequency-min(MHz)");
snprintf(value, sizeof(value), "%d",
ctdp_level->uncore_p1 * DISP_FREQ_MULTIPLIER);
- format_and_print(outf, base_level + 4, header, value);
+ 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);
- format_and_print(outf, base_level + 4, header, value);
+ format_and_print(outf, level + 2, header, value);
}
if (ctdp_level->mem_freq) {
snprintf(header, sizeof(header), "mem-frequency(MHz)");
snprintf(value, sizeof(value), "%d",
- ctdp_level->mem_freq * DISP_FREQ_MULTIPLIER);
- format_and_print(outf, base_level + 4, header, value);
+ ctdp_level->mem_freq);
+ format_and_print(outf, level + 2, header, value);
}
snprintf(header, sizeof(header),
@@ -405,7 +453,7 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
snprintf(value, sizeof(value), "disabled");
} else
snprintf(value, sizeof(value), "unsupported");
- format_and_print(outf, base_level + 4, header, value);
+ format_and_print(outf, level + 2, header, value);
snprintf(header, sizeof(header),
"speed-select-base-freq");
@@ -416,7 +464,7 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
snprintf(value, sizeof(value), "disabled");
} else
snprintf(value, sizeof(value), "unsupported");
- format_and_print(outf, base_level + 4, header, value);
+ format_and_print(outf, level + 2, header, value);
snprintf(header, sizeof(header),
"speed-select-core-power");
@@ -427,241 +475,311 @@ void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
snprintf(value, sizeof(value), "disabled");
} else
snprintf(value, sizeof(value), "unsupported");
- format_and_print(outf, base_level + 4, header, value);
+ format_and_print(outf, level + 2, header, value);
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,
- base_level + 4);
+ level + 2);
continue;
}
if (ctdp_level->pkg_tdp) {
snprintf(header, sizeof(header), "thermal-design-power(W)");
snprintf(value, sizeof(value), "%d", ctdp_level->pkg_tdp);
- format_and_print(outf, base_level + 4, header, value);
+ format_and_print(outf, level + 2, header, value);
}
if (ctdp_level->t_proc_hot) {
snprintf(header, sizeof(header), "tjunction-max(C)");
snprintf(value, sizeof(value), "%d", ctdp_level->t_proc_hot);
- format_and_print(outf, base_level + 4, header, value);
+ format_and_print(outf, level + 2, header, value);
}
snprintf(header, sizeof(header), "turbo-ratio-limits-sse");
- format_and_print(outf, base_level + 4, header, NULL);
+ 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, base_level + 5, header, NULL);
+ 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, base_level + 6, header, value);
+ 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, base_level + 6, header, value);
+ format_and_print(outf, level + 4, header, value);
}
if (ctdp_level->trl_avx_active_cores[0]) {
snprintf(header, sizeof(header), "turbo-ratio-limits-avx2");
- format_and_print(outf, base_level + 4, header, NULL);
+ 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, base_level + 5, header, NULL);
+ 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, base_level + 6, header, value);
+ 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, base_level + 6, header, value);
+ 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, base_level + 4, header, NULL);
+ 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, base_level + 5, header, NULL);
+ 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, base_level + 6, header, value);
+ 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);
- format_and_print(outf, base_level + 6, header, value);
+ 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,
- base_level + 4);
+ 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,
- base_level + 4);
+ level + 2);
}
format_and_print(outf, 1, NULL, NULL);
}
+static int start;
void isst_ctdp_display_information_start(FILE *outf)
{
last_level = 0;
format_and_print(outf, 0, "start", NULL);
+ start = 1;
}
void isst_ctdp_display_information_end(FILE *outf)
{
format_and_print(outf, 0, NULL, NULL);
+ 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)
{
- print_package_info(cpu, outf);
- _isst_pbf_display_information(cpu, outf, level, pbf_info, 4);
+ int _level;
+
+ _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)
{
- print_package_info(cpu, outf);
- _isst_fact_display_information(cpu, outf, level, fact_bucket, fact_avx,
- fact_info, 4);
+ int _level;
+
+ _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;
- 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);
+ level = print_package_info(id, outf);
snprintf(header, sizeof(header), "core-power");
- format_and_print(outf, 4, header, NULL);
+ format_and_print(outf, level + 1, header, NULL);
snprintf(header, sizeof(header), "clos");
snprintf(value, sizeof(value), "%d", clos);
- format_and_print(outf, 5, header, value);
+ format_and_print(outf, level + 2, header, value);
snprintf(header, sizeof(header), "epp");
snprintf(value, sizeof(value), "%d", clos_config->epp);
- format_and_print(outf, 5, header, value);
+ format_and_print(outf, level + 2, header, value);
snprintf(header, sizeof(header), "clos-proportional-priority");
snprintf(value, sizeof(value), "%d", clos_config->clos_prop_prio);
- format_and_print(outf, 5, header, value);
+ 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);
- format_and_print(outf, 5, header, value);
+ format_and_print(outf, level + 2, header, value);
snprintf(header, sizeof(header), "clos-max");
- snprintf(value, sizeof(value), "%d MHz", clos_config->clos_max * DISP_FREQ_MULTIPLIER);
- format_and_print(outf, 5, header, value);
+ if (clos_config->clos_max == 0xff)
+ snprintf(value, sizeof(value), "Max Turbo frequency");
+ else
+ snprintf(value, sizeof(value), "%d MHz", clos_config->clos_max * 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);
- format_and_print(outf, 5, header, value);
+ format_and_print(outf, level + 2, header, value);
- format_and_print(outf, 1, NULL, NULL);
+ format_and_print(outf, level, NULL, NULL);
}
-void isst_clos_display_clos_information(int cpu, FILE *outf,
- int clos_enable, int type)
+void isst_clos_display_clos_information(struct isst_id *id, FILE *outf,
+ int clos_enable, int type,
+ int state, int cap)
{
char header[256];
char value[256];
+ int level;
- 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);
+ level = print_package_info(id, outf);
snprintf(header, sizeof(header), "core-power");
- format_and_print(outf, 4, header, NULL);
+ format_and_print(outf, level + 1, header, NULL);
+
+ snprintf(header, sizeof(header), "support-status");
+ if (cap)
+ snprintf(value, sizeof(value), "supported");
+ else
+ snprintf(value, sizeof(value), "unsupported");
+ format_and_print(outf, level + 2, header, value);
snprintf(header, sizeof(header), "enable-status");
- snprintf(value, sizeof(value), "%d", clos_enable);
- format_and_print(outf, 5, header, value);
+ if (state)
+ snprintf(value, sizeof(value), "enabled");
+ else
+ snprintf(value, sizeof(value), "disabled");
+ format_and_print(outf, level + 2, header, value);
+
+ snprintf(header, sizeof(header), "clos-enable-status");
+ if (clos_enable)
+ snprintf(value, sizeof(value), "enabled");
+ else
+ snprintf(value, sizeof(value), "disabled");
+ format_and_print(outf, level + 2, header, value);
snprintf(header, sizeof(header), "priority-type");
- snprintf(value, sizeof(value), "%d", type);
- format_and_print(outf, 5, header, value);
+ if (type)
+ snprintf(value, sizeof(value), "ordered");
+ else
+ snprintf(value, sizeof(value), "proportional");
+ format_and_print(outf, level + 2, header, value);
- format_and_print(outf, 1, NULL, NULL);
+ 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;
- 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);
+ level = print_package_info(id, outf);
snprintf(header, sizeof(header), "get-assoc");
- format_and_print(outf, 4, header, NULL);
+ format_and_print(outf, level + 1, header, NULL);
snprintf(header, sizeof(header), "clos");
snprintf(value, sizeof(value), "%d", clos);
- format_and_print(outf, 5, header, value);
+ format_and_print(outf, level + 2, header, value);
- format_and_print(outf, 1, NULL, NULL);
+ 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 (id->cpu >= 0)
+ level = print_package_info(id, outf);
- if (cpu >= 0) {
- 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), "%s", feature);
- format_and_print(outf, 4, header, NULL);
+ format_and_print(outf, level + 1, header, NULL);
snprintf(header, sizeof(header), "%s", cmd);
if (!result)
snprintf(value, sizeof(value), "success");
else
snprintf(value, sizeof(value), "failed(error %d)", result);
- format_and_print(outf, 5, header, value);
+ format_and_print(outf, level + 2, header, value);
+
+ format_and_print(outf, level, NULL, NULL);
+}
+
+void isst_display_error_info_message(int error, char *msg, int arg_valid, int arg)
+{
+ FILE *outf = get_output_file();
+ static int error_index;
+ char header[256];
+ char value[256];
+
+ if (!out_format_is_json()) {
+ if (arg_valid)
+ snprintf(value, sizeof(value), "%s %d", msg, arg);
+ else
+ snprintf(value, sizeof(value), "%s", msg);
+ if (error)
+ fprintf(outf, "Error: %s\n", value);
+ else
+ fprintf(outf, "Information: %s\n", value);
+ return;
+ }
+
+ if (!start)
+ format_and_print(outf, 0, "start", NULL);
+
+ if (error)
+ snprintf(header, sizeof(header), "Error%d", error_index++);
+ else
+ snprintf(header, sizeof(header), "Information:%d", error_index++);
+ format_and_print(outf, 1, header, NULL);
+
+ snprintf(header, sizeof(header), "message");
+ if (arg_valid)
+ snprintf(value, sizeof(value), "%s %d", msg, arg);
+ else
+ snprintf(value, sizeof(value), "%s", msg);
+
+ format_and_print(outf, 2, header, value);
format_and_print(outf, 1, NULL, NULL);
+ 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 ad5aa6341d0f..409fcc9c8033 100644
--- a/tools/power/x86/intel-speed-select/isst.h
+++ b/tools/power/x86/intel-speed-select/isst.h
@@ -29,6 +29,7 @@
#include <sys/ioctl.h>
#define BIT(x) (1 << (x))
+#define BIT_ULL(nr) (1ULL << (nr))
#define GENMASK(h, l) (((~0UL) << (l)) & (~0UL >> (sizeof(long) * 8 - 1 - (h))))
#define GENMASK_ULL(h, l) \
(((~0ULL) << (l)) & (~0ULL >> (sizeof(long long) * 8 - 1 - (h))))
@@ -75,9 +76,17 @@
#define DISP_FREQ_MULTIPLIER 100
+#define MAX_PACKAGE_COUNT 8
+#define MAX_DIE_PER_PACKAGE 2
+
+/* Unified structure to specific a CPU or a Power Domain */
+struct isst_id {
+ int cpu;
+ int pkg;
+ int die;
+};
+
struct isst_clos_config {
- int pkg_id;
- int die_id;
unsigned char epp;
unsigned char clos_prop_prio;
unsigned char clos_min;
@@ -167,21 +176,20 @@ struct isst_pkg_ctdp {
struct isst_pkg_ctdp_level_info ctdp_level[ISST_MAX_TDP_LEVELS];
};
+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);
/* Common interfaces */
+FILE *get_output_file(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,
@@ -195,57 +203,74 @@ extern int isst_send_mbox_command(unsigned int cpu, unsigned char command,
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_coremask_info(int cpu, int config_index,
+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(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 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,
- unsigned int val);
+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,
+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,
+extern int isst_get_fact_bucket_info(struct isst_id *id, 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,
- int clos_enable, int type);
+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(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_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_package_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);
#endif
diff --git a/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py b/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py
index 256199c7a182..b46e9eb8f5aa 100755
--- a/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py
+++ b/tools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
# SPDX-License-Identifier: GPL-2.0-only
# -*- coding: utf-8 -*-
#
@@ -63,7 +63,7 @@ C_USEC = 3
C_SEC = 2
C_CPU = 1
-global sample_num, last_sec_cpu, last_usec_cpu, start_time, testname
+global sample_num, last_sec_cpu, last_usec_cpu, start_time, testname, trace_file
# 11 digits covers uptime to 115 days
getcontext().prec = 11
@@ -72,17 +72,17 @@ sample_num =0
last_sec_cpu = [0] * MAX_CPUS
last_usec_cpu = [0] * MAX_CPUS
-def print_help():
- print('intel_pstate_tracer.py:')
+def print_help(driver_name):
+ print('%s_tracer.py:'%driver_name)
print(' Usage:')
print(' If the trace file is available, then to simply parse and plot, use (sudo not required):')
- print(' ./intel_pstate_tracer.py [-c cpus] -t <trace_file> -n <test_name>')
+ print(' ./%s_tracer.py [-c cpus] -t <trace_file> -n <test_name>'%driver_name)
print(' Or')
- print(' ./intel_pstate_tracer.py [--cpu cpus] ---trace_file <trace_file> --name <test_name>')
+ print(' ./%s_tracer.py [--cpu cpus] ---trace_file <trace_file> --name <test_name>'%driver_name)
print(' To generate trace file, parse and plot, use (sudo required):')
- print(' sudo ./intel_pstate_tracer.py [-c cpus] -i <interval> -n <test_name> -m <kbytes>')
+ print(' sudo ./%s_tracer.py [-c cpus] -i <interval> -n <test_name> -m <kbytes>'%driver_name)
print(' Or')
- print(' sudo ./intel_pstate_tracer.py [--cpu cpus] --interval <interval> --name <test_name> --memory <kbytes>')
+ print(' sudo ./%s_tracer.py [--cpu cpus] --interval <interval> --name <test_name> --memory <kbytes>'%driver_name)
print(' Optional argument:')
print(' cpus: comma separated list of CPUs')
print(' kbytes: Kilo bytes of memory per CPU to allocate to the trace buffer. Default: 10240')
@@ -235,7 +235,6 @@ def plot_duration_cpu():
output_png = 'all_cpu_durations.png'
g_plot = common_all_gnuplot_settings(output_png)
# autoscale this one, no set y range
- g_plot('set ytics 0, 500')
g_plot('set ylabel "Timer Duration (MilliSeconds)"')
g_plot('set title "{} : cpu durations : {:%F %H:%M}"'.format(testname, datetime.now()))
@@ -324,7 +323,7 @@ def set_4_plot_linestyles(g_plot):
g_plot('set style line 3 linetype 1 linecolor rgb "purple" pointtype -1')
g_plot('set style line 4 linetype 1 linecolor rgb "blue" pointtype -1')
-def store_csv(cpu_int, time_pre_dec, time_post_dec, core_busy, scaled, _from, _to, mperf, aperf, tsc, freq_ghz, io_boost, common_comm, load, duration_ms, sample_num, elapsed_time, tsc_ghz):
+def store_csv(cpu_int, time_pre_dec, time_post_dec, core_busy, scaled, _from, _to, mperf, aperf, tsc, freq_ghz, io_boost, common_comm, load, duration_ms, sample_num, elapsed_time, tsc_ghz, cpu_mask):
""" Store master csv file information """
global graph_data_present
@@ -343,11 +342,9 @@ def store_csv(cpu_int, time_pre_dec, time_post_dec, core_busy, scaled, _from, _t
graph_data_present = True;
-def split_csv():
+def split_csv(current_max_cpu, cpu_mask):
""" seperate the all csv file into per CPU csv files. """
- global current_max_cpu
-
if os.path.exists('cpu.csv'):
for index in range(0, current_max_cpu + 1):
if cpu_mask[int(index)] != 0:
@@ -382,27 +379,25 @@ def clear_trace_file():
print('IO error clearing trace file ')
sys.exit(2)
-def enable_trace():
+def enable_trace(trace_file):
""" Enable trace """
try:
- open('/sys/kernel/debug/tracing/events/power/pstate_sample/enable'
- , 'w').write("1")
+ open(trace_file,'w').write("1")
except:
print('IO error enabling trace ')
sys.exit(2)
-def disable_trace():
+def disable_trace(trace_file):
""" Disable trace """
try:
- open('/sys/kernel/debug/tracing/events/power/pstate_sample/enable'
- , 'w').write("0")
+ open(trace_file, 'w').write("0")
except:
print('IO error disabling trace ')
sys.exit(2)
-def set_trace_buffer_size():
+def set_trace_buffer_size(memory):
""" Set trace buffer size """
try:
@@ -422,7 +417,7 @@ def free_trace_buffer():
print('IO error freeing trace buffer ')
sys.exit(2)
-def read_trace_data(filename):
+def read_trace_data(filename, cpu_mask):
""" Read and parse trace data """
global current_max_cpu
@@ -482,135 +477,137 @@ def read_trace_data(filename):
tsc_ghz = Decimal(0)
if duration_ms != Decimal(0) :
tsc_ghz = Decimal(tsc)/duration_ms/Decimal(1000000)
- store_csv(cpu_int, time_pre_dec, time_post_dec, core_busy, scaled, _from, _to, mperf, aperf, tsc, freq_ghz, io_boost, common_comm, load, duration_ms, sample_num, elapsed_time, tsc_ghz)
+ store_csv(cpu_int, time_pre_dec, time_post_dec, core_busy, scaled, _from, _to, mperf, aperf, tsc, freq_ghz, io_boost, common_comm, load, duration_ms, sample_num, elapsed_time, tsc_ghz, cpu_mask)
if cpu_int > current_max_cpu:
current_max_cpu = cpu_int
# End of for each trace line loop
# Now seperate the main overall csv file into per CPU csv files.
- split_csv()
+ split_csv(current_max_cpu, cpu_mask)
def signal_handler(signal, frame):
print(' SIGINT: Forcing cleanup before exit.')
if interval:
- disable_trace()
+ disable_trace(trace_file)
clear_trace_file()
# Free the memory
free_trace_buffer()
sys.exit(0)
-signal.signal(signal.SIGINT, signal_handler)
+if __name__ == "__main__":
+ trace_file = "/sys/kernel/debug/tracing/events/power/pstate_sample/enable"
+ signal.signal(signal.SIGINT, signal_handler)
-interval = ""
-filename = ""
-cpu_list = ""
-testname = ""
-memory = "10240"
-graph_data_present = False;
+ interval = ""
+ filename = ""
+ cpu_list = ""
+ testname = ""
+ memory = "10240"
+ graph_data_present = False;
-valid1 = False
-valid2 = False
+ valid1 = False
+ valid2 = False
-cpu_mask = zeros((MAX_CPUS,), dtype=int)
+ cpu_mask = zeros((MAX_CPUS,), dtype=int)
-try:
- opts, args = getopt.getopt(sys.argv[1:],"ht:i:c:n:m:",["help","trace_file=","interval=","cpu=","name=","memory="])
-except getopt.GetoptError:
- print_help()
- sys.exit(2)
-for opt, arg in opts:
- if opt == '-h':
- print()
+ try:
+ opts, args = getopt.getopt(sys.argv[1:],"ht:i:c:n:m:",["help","trace_file=","interval=","cpu=","name=","memory="])
+ except getopt.GetoptError:
+ print_help('intel_pstate')
+ sys.exit(2)
+ for opt, arg in opts:
+ if opt == '-h':
+ print_help('intel_pstate')
+ sys.exit()
+ elif opt in ("-t", "--trace_file"):
+ valid1 = True
+ location = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
+ filename = os.path.join(location, arg)
+ elif opt in ("-i", "--interval"):
+ valid1 = True
+ interval = arg
+ elif opt in ("-c", "--cpu"):
+ cpu_list = arg
+ elif opt in ("-n", "--name"):
+ valid2 = True
+ testname = arg
+ elif opt in ("-m", "--memory"):
+ memory = arg
+
+ if not (valid1 and valid2):
+ print_help('intel_pstate')
sys.exit()
- elif opt in ("-t", "--trace_file"):
- valid1 = True
- location = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
- filename = os.path.join(location, arg)
- elif opt in ("-i", "--interval"):
- valid1 = True
- interval = arg
- elif opt in ("-c", "--cpu"):
- cpu_list = arg
- elif opt in ("-n", "--name"):
- valid2 = True
- testname = arg
- elif opt in ("-m", "--memory"):
- memory = arg
-
-if not (valid1 and valid2):
- print_help()
- sys.exit()
-
-if cpu_list:
- for p in re.split("[,]", cpu_list):
- if int(p) < MAX_CPUS :
- cpu_mask[int(p)] = 1
-else:
- for i in range (0, MAX_CPUS):
- cpu_mask[i] = 1
-
-if not os.path.exists('results'):
- os.mkdir('results')
+
+ if cpu_list:
+ for p in re.split("[,]", cpu_list):
+ if int(p) < MAX_CPUS :
+ cpu_mask[int(p)] = 1
+ else:
+ for i in range (0, MAX_CPUS):
+ cpu_mask[i] = 1
+
+ if not os.path.exists('results'):
+ os.mkdir('results')
+ # The regular user needs to own the directory, not root.
+ fix_ownership('results')
+
+ os.chdir('results')
+ if os.path.exists(testname):
+ print('The test name directory already exists. Please provide a unique test name. Test re-run not supported, yet.')
+ sys.exit()
+ os.mkdir(testname)
# The regular user needs to own the directory, not root.
- fix_ownership('results')
-
-os.chdir('results')
-if os.path.exists(testname):
- print('The test name directory already exists. Please provide a unique test name. Test re-run not supported, yet.')
- sys.exit()
-os.mkdir(testname)
-# The regular user needs to own the directory, not root.
-fix_ownership(testname)
-os.chdir(testname)
-
-# Temporary (or perhaps not)
-cur_version = sys.version_info
-print('python version (should be >= 2.7):')
-print(cur_version)
-
-# Left as "cleanup" for potential future re-run ability.
-cleanup_data_files()
-
-if interval:
- filename = "/sys/kernel/debug/tracing/trace"
- clear_trace_file()
- set_trace_buffer_size()
- enable_trace()
- print('Sleeping for ', interval, 'seconds')
- time.sleep(int(interval))
- disable_trace()
-
-current_max_cpu = 0
-
-read_trace_data(filename)
-
-if interval:
- clear_trace_file()
- # Free the memory
- free_trace_buffer()
-
-if graph_data_present == False:
- print('No valid data to plot')
- sys.exit(2)
-
-for cpu_no in range(0, current_max_cpu + 1):
- plot_perf_busy_with_sample(cpu_no)
- plot_perf_busy(cpu_no)
- plot_durations(cpu_no)
- plot_loads(cpu_no)
-
-plot_pstate_cpu_with_sample()
-plot_pstate_cpu()
-plot_load_cpu()
-plot_frequency_cpu()
-plot_duration_cpu()
-plot_scaled_cpu()
-plot_boost_cpu()
-plot_ghz_cpu()
-
-# It is preferrable, but not necessary, that the regular user owns the files, not root.
-for root, dirs, files in os.walk('.'):
- for f in files:
- fix_ownership(f)
-
-os.chdir('../../')
+ fix_ownership(testname)
+ os.chdir(testname)
+
+ # Temporary (or perhaps not)
+ cur_version = sys.version_info
+ print('python version (should be >= 2.7):')
+ print(cur_version)
+
+ # Left as "cleanup" for potential future re-run ability.
+ cleanup_data_files()
+
+ if interval:
+ filename = "/sys/kernel/debug/tracing/trace"
+ clear_trace_file()
+ set_trace_buffer_size(memory)
+ enable_trace(trace_file)
+ print('Sleeping for ', interval, 'seconds')
+ time.sleep(int(interval))
+ disable_trace(trace_file)
+
+ current_max_cpu = 0
+
+ read_trace_data(filename, cpu_mask)
+
+ if interval:
+ clear_trace_file()
+ # Free the memory
+ free_trace_buffer()
+
+ if graph_data_present == False:
+ print('No valid data to plot')
+ sys.exit(2)
+
+ for cpu_no in range(0, current_max_cpu + 1):
+ plot_perf_busy_with_sample(cpu_no)
+ plot_perf_busy(cpu_no)
+ plot_durations(cpu_no)
+ plot_loads(cpu_no)
+
+ plot_pstate_cpu_with_sample()
+ plot_pstate_cpu()
+ plot_load_cpu()
+ plot_frequency_cpu()
+ plot_duration_cpu()
+ plot_scaled_cpu()
+ plot_boost_cpu()
+ plot_ghz_cpu()
+
+ # It is preferrable, but not necessary, that the regular user owns the files, not root.
+ for root, dirs, files in os.walk('.'):
+ for f in files:
+ fix_ownership(f)
+
+ os.chdir('../../')
diff --git a/tools/power/x86/turbostat/.gitignore b/tools/power/x86/turbostat/.gitignore
index 7521370d3568..e13109b43cd1 100644
--- a/tools/power/x86/turbostat/.gitignore
+++ b/tools/power/x86/turbostat/.gitignore
@@ -1 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
turbostat
diff --git a/tools/power/x86/turbostat/Makefile b/tools/power/x86/turbostat/Makefile
index 2b6551269e43..92e139b9c792 100644
--- a/tools/power/x86/turbostat/Makefile
+++ b/tools/power/x86/turbostat/Makefile
@@ -9,14 +9,15 @@ ifeq ("$(origin O)", "command line")
endif
turbostat : turbostat.c
-override CFLAGS += -O2 -Wall -I../../../include
+override CFLAGS += -O2 -Wall -Wextra -I../../../include
override CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"'
override CFLAGS += -DINTEL_FAMILY_HEADER='"../../../../arch/x86/include/asm/intel-family.h"'
+override CFLAGS += -D_FILE_OFFSET_BITS=64
override CFLAGS += -D_FORTIFY_SOURCE=2
%: %.c
@mkdir -p $(BUILD_OUTPUT)
- $(CC) $(CFLAGS) $< -o $(BUILD_OUTPUT)/$@ $(LDFLAGS) -lcap
+ $(CC) $(CFLAGS) $< -o $(BUILD_OUTPUT)/$@ $(LDFLAGS) -lcap -lrt
.PHONY : clean
clean :
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index a6db83a88e85..c7b26a3603af 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -54,12 +54,14 @@ name as necessary to disambiguate it from others is necessary. Note that option
.PP
\fB--cpu cpu-set\fP limit output to system summary plus the specified cpu-set. If cpu-set is the string "core", then the system summary plus the first CPU in each core are printed -- eg. subsequent HT siblings are not printed. Or if cpu-set is the string "package", then the system summary plus the first CPU in each package is printed. Otherwise, the system summary plus the specified set of CPUs are printed. The cpu-set is ordered from low to high, comma delimited with ".." and "-" permitted to denote a range. eg. 1,2,8,14..17,21-44
.PP
-\fB--hide column\fP do not show the specified built-in columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--hide sysfs" to hide the sysfs statistics columns as a group.
+\fB--hide column\fP do not show the specified built-in columns. May be invoked multiple times, or with a comma-separated list of column names.
.PP
\fB--enable column\fP show the specified built-in columns, which are otherwise disabled, by default. Currently the only built-in counters disabled by default are "usec", "Time_Of_Day_Seconds", "APIC" and "X2APIC".
The column name "all" can be used to enable all disabled-by-default built-in counters.
.PP
-\fB--show column\fP show only the specified built-in columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--show sysfs" to show the sysfs statistics columns as a group.
+\fB--show column\fP show only the specified built-in columns. May be invoked multiple times, or with a comma-separated list of column names.
+.PP
+\fB--show CATEGORY --hide CATEGORY\fP Show and hide also accept a single CATEGORY of columns: "all", "topology", "idle", "frequency", "power", "sysfs", "other".
.PP
\fB--Dump\fP displays the raw counter values.
.PP
@@ -90,40 +92,66 @@ displays the statistics gathered since it was forked.
.SH ROW DESCRIPTIONS
The system configuration dump (if --quiet is not used) is followed by statistics. The first row of the statistics labels the content of each column (below). The second row of statistics is the system summary line. The system summary line has a '-' in the columns for the Package, Core, and CPU. The contents of the system summary line depends on the type of column. Columns that count items (eg. IRQ) show the sum across all CPUs in the system. Columns that show a percentage show the average across all CPUs in the system. Columns that dump raw MSR values simply show 0 in the summary. After the system summary row, each row describes a specific Package/Core/CPU. Note that if the --cpu parameter is used to limit which specific CPUs are displayed, turbostat will still collect statistics for all CPUs in the system and will still show the system summary for all CPUs in the system.
.SH COLUMN DESCRIPTIONS
-.nf
+.PP
\fBusec\fP For each CPU, the number of microseconds elapsed during counter collection, including thread migration -- if any. This counter is disabled by default, and is enabled with "--enable usec", or --debug. On the summary row, usec refers to the total elapsed time to collect the counters on all cpus.
+.PP
\fBTime_Of_Day_Seconds\fP For each CPU, the gettimeofday(2) value (seconds.subsec since Epoch) when the counters ending the measurement interval were collected. This column is disabled by default, and can be enabled with "--enable Time_Of_Day_Seconds" or "--debug". On the summary row, Time_Of_Day_Seconds refers to the timestamp following collection of counters on the last CPU.
+.PP
\fBCore\fP processor core number. Note that multiple CPUs per core indicate support for Intel(R) Hyper-Threading Technology (HT).
+.PP
\fBCPU\fP Linux CPU (logical processor) number. Yes, it is okay that on many systems the CPUs are not listed in numerical order -- for efficiency reasons, turbostat runs in topology order, so HT siblings appear together.
+.PP
\fBPackage\fP processor package number -- not present on systems with a single processor package.
+.PP
\fBAvg_MHz\fP number of cycles executed divided by time elapsed. Note that this includes idle-time when 0 instructions are executed.
+.PP
\fBBusy%\fP percent of the measurement interval that the CPU executes instructions, aka. % of time in "C0" state.
+.PP
\fBBzy_MHz\fP average clock rate while the CPU was not idle (ie. in "c0" state).
+.PP
\fBTSC_MHz\fP average MHz that the TSC ran during the entire interval.
+.PP
\fBIRQ\fP The number of interrupts serviced by that CPU during the measurement interval. The system total line is the sum of interrupts serviced across all CPUs. turbostat parses /proc/interrupts to generate this summary.
+.PP
\fBSMI\fP The number of System Management Interrupts serviced CPU during the measurement interval. While this counter is actually per-CPU, SMI are triggered on all processors, so the number should be the same for all CPUs.
+.PP
\fBC1, C2, C3...\fP The number times Linux requested the C1, C2, C3 idle state during the measurement interval. The system summary line shows the sum for all CPUs. These are C-state names as exported in /sys/devices/system/cpu/cpu*/cpuidle/state*/name. While their names are generic, their attributes are processor specific. They the system description section of output shows what MWAIT sub-states they are mapped to on each system.
+.PP
\fBC1%, C2%, C3%\fP The residency percentage that Linux requested C1, C2, C3.... The system summary is the average of all CPUs in the system. Note that these are software, reflecting what was requested. The hardware counters reflect what was actually achieved.
+.PP
\fBCPU%c1, CPU%c3, CPU%c6, CPU%c7\fP show the percentage residency in hardware core idle states. These numbers are from hardware residency counters.
+.PP
\fBCoreTmp\fP Degrees Celsius reported by the per-core Digital Thermal Sensor.
+.PP
\fBPkgTmp\fP Degrees Celsius reported by the per-package Package Thermal Monitor.
+.PP
\fBGFX%rc6\fP The percentage of time the GPU is in the "render C6" state, rc6, during the measurement interval. From /sys/class/drm/card0/power/rc6_residency_ms.
+.PP
\fBGFXMHz\fP Instantaneous snapshot of what sysfs presents at the end of the measurement interval. From /sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz.
+.PP
\fBPkg%pc2, Pkg%pc3, Pkg%pc6, Pkg%pc7\fP percentage residency in hardware package idle states. These numbers are from hardware residency counters.
+.PP
\fBPkgWatt\fP Watts consumed by the whole package.
+.PP
\fBCorWatt\fP Watts consumed by the core part of the package.
+.PP
\fBGFXWatt\fP Watts consumed by the Graphics part of the package -- available only on client processors.
+.PP
\fBRAMWatt\fP Watts consumed by the DRAM DIMMS -- available only on server processors.
+.PP
\fBPKG_%\fP percent of the interval that RAPL throttling was active on the Package. Note that the system summary is the sum of the package throttling time, and thus may be higher than 100% on a multi-package system. Note that the meaning of this field is model specific. For example, some hardware increments this counter when RAPL responds to thermal limits, but does not increment this counter when RAPL responds to power limits. Comparing PkgWatt and PkgTmp to system limits is necessary.
+.PP
\fBRAM_%\fP percent of the interval that RAPL throttling was active on DRAM.
-.fi
+.PP
+\fBUncMHz\fP uncore MHz, instantaneous sample.
.SH TOO MUCH INFORMATION EXAMPLE
By default, turbostat dumps all possible information -- a system configuration header, followed by columns for all counters.
This is ideal for remote debugging, use the "--out" option to save everything to a text file, and get that file to the expert helping you debug.
.PP
When you are not interested in all that information, and there are several ways to see only what you want. First the "--quiet" option will skip the configuration information, and turbostat will show only the counter columns. Second, you can reduce the columns with the "--hide" and "--show" options. If you use the "--show" option, then turbostat will show only the columns you list. If you use the "--hide" option, turbostat will show all columns, except the ones you list.
.PP
-To find out what columns are available for --show and --hide, the "--list" option is available. For convenience, the special strings "sysfs" can be used to refer to all of the sysfs C-state counters at once:
+To find out what columns are available for --show and --hide, the "--list" option is available. Usually, the CATEGORY names above are used to refer to groups of counters. Also, for convenience, the special string "sysfs" can be used to refer to all of the sysfs C-state counters at once:
+.PP
.nf
sudo ./turbostat --show sysfs --quiet sleep 10
10.003837 sec
@@ -156,32 +184,29 @@ Without a command to fork, turbostat displays statistics ever 5 seconds.
Periodic output goes to stdout, by default, unless --out is used to specify an output file.
The 5-second interval can be changed with the "-i sec" option.
.nf
-sudo ./turbostat --quiet --hide sysfs,IRQ,SMI,CoreTmp,PkgTmp,GFX%rc6,GFXMHz,PkgWatt,CorWatt,GFXWatt
- Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz CPU%c1 CPU%c3 CPU%c6 CPU%c7
- - - 488 12.52 3900 3498 12.50 0.00 0.00 74.98
- 0 0 5 0.13 3900 3498 99.87 0.00 0.00 0.00
- 0 4 3897 99.99 3900 3498 0.01
- 1 1 0 0.00 3856 3498 0.01 0.00 0.00 99.98
- 1 5 0 0.00 3861 3498 0.01
- 2 2 1 0.02 3889 3498 0.03 0.00 0.00 99.95
- 2 6 0 0.00 3863 3498 0.05
- 3 3 0 0.01 3869 3498 0.02 0.00 0.00 99.97
- 3 7 0 0.00 3878 3498 0.03
- Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz CPU%c1 CPU%c3 CPU%c6 CPU%c7
- - - 491 12.59 3900 3498 12.42 0.00 0.00 74.99
- 0 0 27 0.69 3900 3498 99.31 0.00 0.00 0.00
- 0 4 3898 99.99 3900 3498 0.01
- 1 1 0 0.00 3883 3498 0.01 0.00 0.00 99.99
- 1 5 0 0.00 3898 3498 0.01
- 2 2 0 0.01 3889 3498 0.02 0.00 0.00 99.98
- 2 6 0 0.00 3889 3498 0.02
- 3 3 0 0.00 3856 3498 0.01 0.00 0.00 99.99
- 3 7 0 0.00 3897 3498 0.01
+sudo turbostat --quiet --show CPU,frequency
+ Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz CPU%c7 UncMhz
+ - - 524 12.48 4198 3096 74.53 3800
+ 0 0 4 0.09 4081 3096 98.88 3800
+ 0 4 1 0.02 4063 3096
+ 1 1 2 0.06 4063 3096 99.60
+ 1 5 2 0.05 4070 3096
+ 2 2 4178 99.52 4199 3096 0.00
+ 2 6 3 0.08 4159 3096
+ 3 3 1 0.04 4046 3096 99.66
+ 3 7 0 0.01 3989 3096
+ Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz CPU%c7 UncMhz
+ - - 525 12.52 4198 3096 74.54 3800
+ 0 0 4 0.10 4051 3096 99.49 3800
+ 0 4 2 0.04 3993 3096
+ 1 1 3 0.07 4054 3096 99.56
+ 1 5 4 0.10 4018 3096
+ 2 2 4178 99.51 4199 3096 0.00
+ 2 6 4 0.09 4143 3096
+ 3 3 2 0.06 4026 3096 99.10
+ 3 7 7 0.17 4074 3096
.fi
-This example also shows the use of the --hide option to skip columns that are not wanted.
-Note that cpu4 in this example is 99.99% busy, while the other CPUs are all under 1% busy.
-Notice that cpu4's HT sibling is cpu0, which is under 1% busy, but can get into CPU%c1 only,
-because its cpu4's activity on shared hardware keeps it from entering a deeper C-state.
+This example also shows the use of the --show option to show only the desired columns.
.SH SYSTEM CONFIGURATION INFORMATION EXAMPLE
@@ -189,61 +214,86 @@ By default, turbostat always dumps system configuration information
before taking measurements. In the example above, "--quiet" is used
to suppress that output. Here is an example of the configuration information:
.nf
-turbostat version 2017.02.15 - Len Brown <lenb@kernel.org>
-CPUID(0): GenuineIntel 13 CPUID levels; family:model:stepping 0x6:3c:3 (6:60:3)
-CPUID(1): SSE3 MONITOR - EIST TM2 TSC MSR ACPI-TM TM
-CPUID(6): APERF, TURBO, DTS, PTM, No-HWP, No-HWPnotify, No-HWPwindow, No-HWPepp, No-HWPpkg, EPB
-cpu4: MSR_IA32_MISC_ENABLE: 0x00850089 (TCC EIST No-MWAIT PREFETCH TURBO)
-CPUID(7): No-SGX
-cpu4: MSR_MISC_PWR_MGMT: 0x00400000 (ENable-EIST_Coordination DISable-EPB DISable-OOB)
-RAPL: 3121 sec. Joule Counter Range, at 84 Watts
-cpu4: MSR_PLATFORM_INFO: 0x80838f3012300
+turbostat version 2022.04.16 - Len Brown <lenb@kernel.org>
+Kernel command line: BOOT_IMAGE=/boot/vmlinuz-5.18.0-rc6-00001-ge6891250e3b5 ...
+CPUID(0): GenuineIntel 0x16 CPUID levels
+CPUID(1): family:model:stepping 0x6:9e:9 (6:158:9) microcode 0xea
+CPUID(0x80000000): max_extended_levels: 0x80000008
+CPUID(1): SSE3 MONITOR - EIST TM2 TSC MSR ACPI-TM HT TM
+CPUID(6): APERF, TURBO, DTS, PTM, HWP, HWPnotify, HWPwindow, HWPepp, No-HWPpkg, EPB
+cpu7: MSR_IA32_MISC_ENABLE: 0x00850089 (TCC EIST MWAIT PREFETCH TURBO)
+CPUID(7): SGX
+cpu7: MSR_IA32_FEATURE_CONTROL: 0x00000005 (Locked )
+CPUID(0x15): eax_crystal: 2 ebx_tsc: 258 ecx_crystal_hz: 0
+TSC: 3096 MHz (24000000 Hz * 258 / 2 / 1000000)
+CPUID(0x16): base_mhz: 3100 max_mhz: 4200 bus_mhz: 100
+cpu7: MSR_MISC_PWR_MGMT: 0x00401cc0 (ENable-EIST_Coordination DISable-EPB DISable-OOB)
+RAPL: 5825 sec. Joule Counter Range, at 45 Watts
+cpu7: MSR_PLATFORM_INFO: 0x80839f1011f00
8 * 100.0 = 800.0 MHz max efficiency frequency
-35 * 100.0 = 3500.0 MHz base frequency
-cpu4: MSR_IA32_POWER_CTL: 0x0004005d (C1E auto-promotion: DISabled)
-cpu4: MSR_TURBO_RATIO_LIMIT: 0x25262727
-37 * 100.0 = 3700.0 MHz max turbo 4 active cores
-38 * 100.0 = 3800.0 MHz max turbo 3 active cores
-39 * 100.0 = 3900.0 MHz max turbo 2 active cores
-39 * 100.0 = 3900.0 MHz max turbo 1 active cores
-cpu4: MSR_CONFIG_TDP_NOMINAL: 0x00000023 (base_ratio=35)
-cpu4: MSR_CONFIG_TDP_LEVEL_1: 0x00000000 ()
-cpu4: MSR_CONFIG_TDP_LEVEL_2: 0x00000000 ()
-cpu4: MSR_CONFIG_TDP_CONTROL: 0x80000000 ( lock=1)
-cpu4: MSR_TURBO_ACTIVATION_RATIO: 0x00000000 (MAX_NON_TURBO_RATIO=0 lock=0)
-cpu4: MSR_PKG_CST_CONFIG_CONTROL: 0x1e000400 (UNdemote-C3, UNdemote-C1, demote-C3, demote-C1, UNlocked: pkg-cstate-limit=0: pc0)
-cpu4: POLL: CPUIDLE CORE POLL IDLE
-cpu4: C1: MWAIT 0x00
-cpu4: C1E: MWAIT 0x01
-cpu4: C3: MWAIT 0x10
-cpu4: C6: MWAIT 0x20
-cpu4: C7s: MWAIT 0x32
-cpu4: MSR_MISC_FEATURE_CONTROL: 0x00000000 (L2-Prefetch L2-Prefetch-pair L1-Prefetch L1-IP-Prefetch)
-cpu0: MSR_IA32_ENERGY_PERF_BIAS: 0x00000006 (balanced)
-cpu0: MSR_CORE_PERF_LIMIT_REASONS, 0x31200000 (Active: ) (Logged: Transitions, MultiCoreTurbo, Amps, Auto-HWP, )
-cpu0: MSR_GFX_PERF_LIMIT_REASONS, 0x00000000 (Active: ) (Logged: )
-cpu0: MSR_RING_PERF_LIMIT_REASONS, 0x0d000000 (Active: ) (Logged: Amps, PkgPwrL1, PkgPwrL2, )
+31 * 100.0 = 3100.0 MHz base frequency
+cpu7: MSR_IA32_POWER_CTL: 0x002c005d (C1E auto-promotion: DISabled)
+cpu7: MSR_TURBO_RATIO_LIMIT: 0x2728292a
+39 * 100.0 = 3900.0 MHz max turbo 4 active cores
+40 * 100.0 = 4000.0 MHz max turbo 3 active cores
+41 * 100.0 = 4100.0 MHz max turbo 2 active cores
+42 * 100.0 = 4200.0 MHz max turbo 1 active cores
+cpu7: MSR_CONFIG_TDP_NOMINAL: 0x0000001f (base_ratio=31)
+cpu7: MSR_CONFIG_TDP_LEVEL_1: 0x00000000 ()
+cpu7: MSR_CONFIG_TDP_LEVEL_2: 0x00000000 ()
+cpu7: MSR_CONFIG_TDP_CONTROL: 0x80000000 ( lock=1)
+cpu7: MSR_TURBO_ACTIVATION_RATIO: 0x00000000 (MAX_NON_TURBO_RATIO=0 lock=0)
+cpu7: MSR_PKG_CST_CONFIG_CONTROL: 0x1e008008 (UNdemote-C3, UNdemote-C1, demote-C3, demote-C1, locked, pkg-cstate-limit=8 (unlimited))
+Uncore Frequency pkg0 die0: 800 - 3900 MHz (800 - 3900 MHz)
+/dev/cpu_dma_latency: 2000000000 usec (default)
+current_driver: intel_idle
+current_governor: menu
+current_governor_ro: menu
+cpu7: POLL: CPUIDLE CORE POLL IDLE
+cpu7: C1: MWAIT 0x00
+cpu7: C1E: MWAIT 0x01
+cpu7: C3: MWAIT 0x10
+cpu7: C6: MWAIT 0x20
+cpu7: C7s: MWAIT 0x33
+cpu7: C8: MWAIT 0x40
+cpu7: C9: MWAIT 0x50
+cpu7: C10: MWAIT 0x60
+cpu7: cpufreq driver: intel_pstate
+cpu7: cpufreq governor: performance
+cpufreq intel_pstate no_turbo: 0
+cpu7: MSR_MISC_FEATURE_CONTROL: 0x00000000 (L2-Prefetch L2-Prefetch-pair L1-Prefetch L1-IP-Prefetch)
+cpu0: MSR_PM_ENABLE: 0x00000001 (HWP)
+cpu0: MSR_HWP_CAPABILITIES: 0x01101f53 (high 83 guar 31 eff 16 low 1)
+cpu0: MSR_HWP_REQUEST: 0x00005353 (min 83 max 83 des 0 epp 0x0 window 0x0 pkg 0x0)
+cpu0: MSR_HWP_INTERRUPT: 0x00000001 (EN_Guaranteed_Perf_Change, Dis_Excursion_Min)
+cpu0: MSR_HWP_STATUS: 0x00000004 (No-Guaranteed_Perf_Change, No-Excursion_Min)
+cpu0: EPB: 6 (balanced)
cpu0: MSR_RAPL_POWER_UNIT: 0x000a0e03 (0.125000 Watts, 0.000061 Joules, 0.000977 sec.)
-cpu0: MSR_PKG_POWER_INFO: 0x000002a0 (84 W TDP, RAPL 0 - 0 W, 0.000000 sec.)
-cpu0: MSR_PKG_POWER_LIMIT: 0x428348001a82a0 (UNlocked)
-cpu0: PKG Limit #1: ENabled (84.000000 Watts, 8.000000 sec, clamp DISabled)
-cpu0: PKG Limit #2: ENabled (105.000000 Watts, 0.002441* sec, clamp DISabled)
+cpu0: MSR_PKG_POWER_INFO: 0x00000168 (45 W TDP, RAPL 0 - 0 W, 0.000000 sec.)
+cpu0: MSR_PKG_POWER_LIMIT: 0x42820800218208 (UNlocked)
+cpu0: PKG Limit #1: ENabled (65.000 Watts, 64.000000 sec, clamp ENabled)
+cpu0: PKG Limit #2: ENabled (65.000 Watts, 0.002441* sec, clamp DISabled)
+cpu0: MSR_VR_CURRENT_CONFIG: 0x00000000
+cpu0: PKG Limit #4: 0.000000 Watts (UNlocked)
+cpu0: MSR_DRAM_POWER_LIMIT: 0x5400de00000000 (UNlocked)
+cpu0: DRAM Limit: DISabled (0.000 Watts, 0.000977 sec, clamp DISabled)
cpu0: MSR_PP0_POLICY: 0
cpu0: MSR_PP0_POWER_LIMIT: 0x00000000 (UNlocked)
-cpu0: Cores Limit: DISabled (0.000000 Watts, 0.000977 sec, clamp DISabled)
+cpu0: Cores Limit: DISabled (0.000 Watts, 0.000977 sec, clamp DISabled)
cpu0: MSR_PP1_POLICY: 0
cpu0: MSR_PP1_POWER_LIMIT: 0x00000000 (UNlocked)
-cpu0: GFX Limit: DISabled (0.000000 Watts, 0.000977 sec, clamp DISabled)
-cpu0: MSR_IA32_TEMPERATURE_TARGET: 0x00641400 (100 C)
-cpu0: MSR_IA32_PACKAGE_THERM_STATUS: 0x884c0800 (24 C)
-cpu0: MSR_IA32_THERM_STATUS: 0x884c0000 (24 C +/- 1)
-cpu1: MSR_IA32_THERM_STATUS: 0x88510000 (19 C +/- 1)
-cpu2: MSR_IA32_THERM_STATUS: 0x884e0000 (22 C +/- 1)
-cpu3: MSR_IA32_THERM_STATUS: 0x88510000 (19 C +/- 1)
-cpu4: MSR_PKGC3_IRTL: 0x00008842 (valid, 67584 ns)
-cpu4: MSR_PKGC6_IRTL: 0x00008873 (valid, 117760 ns)
-cpu4: MSR_PKGC7_IRTL: 0x00008891 (valid, 148480 ns)
+cpu0: GFX Limit: DISabled (0.000 Watts, 0.000977 sec, clamp DISabled)
+cpu0: MSR_IA32_TEMPERATURE_TARGET: 0x00640000 (100 C) (100 default - 0 offset)
+cpu0: MSR_IA32_PACKAGE_THERM_STATUS: 0x88200800 (68 C)
+cpu0: MSR_IA32_PACKAGE_THERM_INTERRUPT: 0x00000003 (100 C, 100 C)
+cpu7: MSR_PKGC3_IRTL: 0x0000884e (valid, 79872 ns)
+cpu7: MSR_PKGC6_IRTL: 0x00008876 (valid, 120832 ns)
+cpu7: MSR_PKGC7_IRTL: 0x00008894 (valid, 151552 ns)
+cpu7: MSR_PKGC8_IRTL: 0x000088fa (valid, 256000 ns)
+cpu7: MSR_PKGC9_IRTL: 0x0000894c (valid, 339968 ns)
+cpu7: MSR_PKGC10_IRTL: 0x00008bf2 (valid, 1034240 ns)
.fi
+.PP
The \fBmax efficiency\fP frequency, a.k.a. Low Frequency Mode, is the frequency
available at the minimum package voltage. The \fBTSC frequency\fP is the base
frequency of the processor -- this should match the brand string
@@ -290,7 +340,7 @@ starts a new interval.
must be run as root.
Alternatively, non-root users can be enabled to run turbostat this way:
-# setcap cap_sys_rawio=ep ./turbostat
+# setcap cap_sys_admin,cap_sys_rawio,cap_sys_nice=+ep ./turbostat
# chmod +r /dev/cpu/*/msr
@@ -335,7 +385,7 @@ that they count at TSC rate, which is true on all processors tested to date.
.SH REFERENCES
Volume 3B: System Programming Guide"
-http://www.intel.com/products/processor/manuals/
+https://www.intel.com/products/processor/manuals/
.SH FILES
.ta
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 33b370865d16..aba460410dbd 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -3,7 +3,7 @@
* turbostat -- show CPU frequency and C-state residency
* on modern Intel and AMD processors.
*
- * Copyright (c) 2013 Intel Corporation.
+ * Copyright (c) 2022 Intel Corporation.
* Len Brown <len.brown@intel.com>
*/
@@ -33,13 +33,189 @@
#include <sys/capability.h>
#include <errno.h>
#include <math.h>
+#include <linux/perf_event.h>
+#include <asm/unistd.h>
+#include <stdbool.h>
+
+#define UNUSED(x) (void)(x)
+
+/*
+ * This list matches the column headers, except
+ * 1. built-in only, the sysfs counters are not here -- we learn of those at run-time
+ * 2. Core and CPU are moved to the end, we can't have strings that contain them
+ * matching on them for --show and --hide.
+ */
+
+/*
+ * buffer size used by sscanf() for added column names
+ * Usually truncated to 7 characters, but also handles 18 columns for raw 64-bit counters
+ */
+#define NAME_BYTES 20
+#define PATH_BYTES 128
+
+enum counter_scope { SCOPE_CPU, SCOPE_CORE, SCOPE_PACKAGE };
+enum counter_type { COUNTER_ITEMS, COUNTER_CYCLES, COUNTER_SECONDS, COUNTER_USEC };
+enum counter_format { FORMAT_RAW, FORMAT_DELTA, FORMAT_PERCENT };
+
+struct msr_counter {
+ unsigned int msr_num;
+ char name[NAME_BYTES];
+ char path[PATH_BYTES];
+ unsigned int width;
+ enum counter_type type;
+ enum counter_format format;
+ struct msr_counter *next;
+ unsigned int flags;
+#define FLAGS_HIDE (1 << 0)
+#define FLAGS_SHOW (1 << 1)
+#define SYSFS_PERCPU (1 << 1)
+};
+
+struct msr_counter bic[] = {
+ { 0x0, "usec", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "Time_Of_Day_Seconds", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "Package", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "Node", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "Avg_MHz", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "Busy%", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "Bzy_MHz", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "TSC_MHz", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "IRQ", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "SMI", "", 32, 0, FORMAT_DELTA, NULL, 0 },
+ { 0x0, "sysfs", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "CPU%c1", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "CPU%c3", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "CPU%c6", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "CPU%c7", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "ThreadC", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "CoreTmp", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "CoreCnt", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "PkgTmp", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "GFX%rc6", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "GFXMHz", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "Pkg%pc2", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "Pkg%pc3", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "Pkg%pc6", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "Pkg%pc7", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "Pkg%pc8", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "Pkg%pc9", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "Pk%pc10", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "CPU%LPI", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "SYS%LPI", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "PkgWatt", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "CorWatt", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "GFXWatt", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "PkgCnt", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "RAMWatt", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "PKG_%", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "RAM_%", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "Pkg_J", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "Cor_J", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "GFX_J", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "RAM_J", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "Mod%c6", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "Totl%C0", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "Any%C0", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "GFX%C0", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "CPUGFX%", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "Core", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "CPU", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "APIC", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "X2APIC", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "Die", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "GFXAMHz", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "IPC", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "CoreThr", "", 0, 0, 0, NULL, 0 },
+ { 0x0, "UncMHz", "", 0, 0, 0, NULL, 0 },
+};
+
+#define MAX_BIC (sizeof(bic) / sizeof(struct msr_counter))
+#define BIC_USEC (1ULL << 0)
+#define BIC_TOD (1ULL << 1)
+#define BIC_Package (1ULL << 2)
+#define BIC_Node (1ULL << 3)
+#define BIC_Avg_MHz (1ULL << 4)
+#define BIC_Busy (1ULL << 5)
+#define BIC_Bzy_MHz (1ULL << 6)
+#define BIC_TSC_MHz (1ULL << 7)
+#define BIC_IRQ (1ULL << 8)
+#define BIC_SMI (1ULL << 9)
+#define BIC_sysfs (1ULL << 10)
+#define BIC_CPU_c1 (1ULL << 11)
+#define BIC_CPU_c3 (1ULL << 12)
+#define BIC_CPU_c6 (1ULL << 13)
+#define BIC_CPU_c7 (1ULL << 14)
+#define BIC_ThreadC (1ULL << 15)
+#define BIC_CoreTmp (1ULL << 16)
+#define BIC_CoreCnt (1ULL << 17)
+#define BIC_PkgTmp (1ULL << 18)
+#define BIC_GFX_rc6 (1ULL << 19)
+#define BIC_GFXMHz (1ULL << 20)
+#define BIC_Pkgpc2 (1ULL << 21)
+#define BIC_Pkgpc3 (1ULL << 22)
+#define BIC_Pkgpc6 (1ULL << 23)
+#define BIC_Pkgpc7 (1ULL << 24)
+#define BIC_Pkgpc8 (1ULL << 25)
+#define BIC_Pkgpc9 (1ULL << 26)
+#define BIC_Pkgpc10 (1ULL << 27)
+#define BIC_CPU_LPI (1ULL << 28)
+#define BIC_SYS_LPI (1ULL << 29)
+#define BIC_PkgWatt (1ULL << 30)
+#define BIC_CorWatt (1ULL << 31)
+#define BIC_GFXWatt (1ULL << 32)
+#define BIC_PkgCnt (1ULL << 33)
+#define BIC_RAMWatt (1ULL << 34)
+#define BIC_PKG__ (1ULL << 35)
+#define BIC_RAM__ (1ULL << 36)
+#define BIC_Pkg_J (1ULL << 37)
+#define BIC_Cor_J (1ULL << 38)
+#define BIC_GFX_J (1ULL << 39)
+#define BIC_RAM_J (1ULL << 40)
+#define BIC_Mod_c6 (1ULL << 41)
+#define BIC_Totl_c0 (1ULL << 42)
+#define BIC_Any_c0 (1ULL << 43)
+#define BIC_GFX_c0 (1ULL << 44)
+#define BIC_CPUGFX (1ULL << 45)
+#define BIC_Core (1ULL << 46)
+#define BIC_CPU (1ULL << 47)
+#define BIC_APIC (1ULL << 48)
+#define BIC_X2APIC (1ULL << 49)
+#define BIC_Die (1ULL << 50)
+#define BIC_GFXACTMHz (1ULL << 51)
+#define BIC_IPC (1ULL << 52)
+#define BIC_CORE_THROT_CNT (1ULL << 53)
+#define BIC_UNCORE_MHZ (1ULL << 54)
+
+#define BIC_TOPOLOGY (BIC_Package | BIC_Node | BIC_CoreCnt | BIC_PkgCnt | BIC_Core | BIC_CPU | BIC_Die )
+#define BIC_THERMAL_PWR ( BIC_CoreTmp | BIC_PkgTmp | BIC_PkgWatt | BIC_CorWatt | BIC_GFXWatt | BIC_RAMWatt | BIC_PKG__ | BIC_RAM__)
+#define BIC_FREQUENCY ( BIC_Avg_MHz | BIC_Busy | BIC_Bzy_MHz | BIC_TSC_MHz | BIC_GFXMHz | BIC_GFXACTMHz | BIC_UNCORE_MHZ)
+#define BIC_IDLE ( BIC_sysfs | BIC_CPU_c1 | BIC_CPU_c3 | BIC_CPU_c6 | BIC_CPU_c7 | BIC_GFX_rc6 | BIC_Pkgpc2 | BIC_Pkgpc3 | BIC_Pkgpc6 | BIC_Pkgpc7 | BIC_Pkgpc8 | BIC_Pkgpc9 | BIC_Pkgpc10 | BIC_CPU_LPI | BIC_SYS_LPI | BIC_Mod_c6 | BIC_Totl_c0 | BIC_Any_c0 | BIC_GFX_c0 | BIC_CPUGFX)
+#define BIC_OTHER ( BIC_IRQ | BIC_SMI | BIC_ThreadC | BIC_CoreTmp | BIC_IPC)
+
+#define BIC_DISABLED_BY_DEFAULT (BIC_USEC | BIC_TOD | BIC_APIC | BIC_X2APIC)
+
+unsigned long long bic_enabled = (0xFFFFFFFFFFFFFFFFULL & ~BIC_DISABLED_BY_DEFAULT);
+unsigned long long bic_present = BIC_USEC | BIC_TOD | BIC_sysfs | BIC_APIC | BIC_X2APIC;
+
+#define DO_BIC(COUNTER_NAME) (bic_enabled & bic_present & COUNTER_NAME)
+#define DO_BIC_READ(COUNTER_NAME) (bic_present & COUNTER_NAME)
+#define ENABLE_BIC(COUNTER_NAME) (bic_enabled |= COUNTER_NAME)
+#define BIC_PRESENT(COUNTER_BIT) (bic_present |= COUNTER_BIT)
+#define BIC_NOT_PRESENT(COUNTER_BIT) (bic_present &= ~COUNTER_BIT)
+#define BIC_IS_ENABLED(COUNTER_BIT) (bic_enabled & COUNTER_BIT)
char *proc_stat = "/proc/stat";
FILE *outf;
int *fd_percpu;
-struct timeval interval_tv = {5, 0};
-struct timespec interval_ts = {5, 0};
+int *fd_instr_count_percpu;
+struct timeval interval_tv = { 5, 0 };
+struct timespec interval_ts = { 5, 0 };
+
+/* Save original CPU model */
+unsigned int model_orig;
+
unsigned int num_iterations;
+unsigned int header_iterations;
unsigned int debug;
unsigned int quiet;
unsigned int shown;
@@ -54,6 +230,8 @@ unsigned int do_slm_cstates;
unsigned int use_c1_residency_msr;
unsigned int has_aperf;
unsigned int has_epb;
+unsigned int has_turbo;
+unsigned int is_hybrid;
unsigned int do_irtl_snb;
unsigned int do_irtl_hsw;
unsigned int units = 1000000; /* MHz etc */
@@ -75,29 +253,33 @@ char *output_buffer, *outp;
unsigned int do_rapl;
unsigned int do_dts;
unsigned int do_ptm;
-unsigned long long gfx_cur_rc6_ms;
+unsigned int do_ipc;
+unsigned long long gfx_cur_rc6_ms;
unsigned long long cpuidle_cur_cpu_lpi_us;
unsigned long long cpuidle_cur_sys_lpi_us;
unsigned int gfx_cur_mhz;
-unsigned int tcc_activation_temp;
-unsigned int tcc_activation_temp_override;
+unsigned int gfx_act_mhz;
+unsigned int tj_max;
+unsigned int tj_max_override;
+int tcc_offset_bits;
double rapl_power_units, rapl_time_units;
double rapl_dram_energy_units, rapl_energy_units;
double rapl_joule_counter_range;
unsigned int do_core_perf_limit_reasons;
unsigned int has_automatic_cstate_conversion;
+unsigned int dis_cstate_prewake;
unsigned int do_gfx_perf_limit_reasons;
unsigned int do_ring_perf_limit_reasons;
unsigned int crystal_hz;
unsigned long long tsc_hz;
int base_cpu;
double discover_bclk(unsigned int family, unsigned int model);
-unsigned int has_hwp; /* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */
+unsigned int has_hwp; /* IA32_PM_ENABLE, IA32_HWP_CAPABILITIES */
/* IA32_HWP_REQUEST, IA32_HWP_STATUS */
-unsigned int has_hwp_notify; /* IA32_HWP_INTERRUPT */
+unsigned int has_hwp_notify; /* IA32_HWP_INTERRUPT */
unsigned int has_hwp_activity_window; /* IA32_HWP_REQUEST[bits 41:32] */
-unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */
-unsigned int has_hwp_pkg; /* IA32_HWP_REQUEST_PKG */
+unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */
+unsigned int has_hwp_pkg; /* IA32_HWP_REQUEST_PKG */
unsigned int has_misc_feature_control;
unsigned int first_counter_read = 1;
int ignore_stdin;
@@ -147,13 +329,6 @@ int ignore_stdin;
#define MAX(a, b) ((a) > (b) ? (a) : (b))
-/*
- * buffer size used by sscanf() for added column names
- * Usually truncated to 7 characters, but also handles 18 columns for raw 64-bit counters
- */
-#define NAME_BYTES 20
-#define PATH_BYTES 128
-
int backwards_count;
char *progname;
@@ -172,12 +347,14 @@ struct thread_data {
unsigned long long aperf;
unsigned long long mperf;
unsigned long long c1;
- unsigned long long irq_count;
+ unsigned long long instr_count;
+ unsigned long long irq_count;
unsigned int smi_count;
unsigned int cpu_id;
unsigned int apic_id;
unsigned int x2apic_id;
unsigned int flags;
+ bool is_atom;
#define CPU_IS_FIRST_THREAD_IN_CORE 0x2
#define CPU_IS_FIRST_CORE_IN_PACKAGE 0x4
unsigned long long counter[MAX_ADDED_THREAD_COUNTERS];
@@ -191,6 +368,7 @@ struct core_data {
unsigned int core_temp_c;
unsigned int core_energy; /* MSR_CORE_ENERGY_STAT */
unsigned int core_id;
+ unsigned long long core_throt_cnt;
unsigned long long counter[MAX_ADDED_COUNTERS];
} *core_even, *core_odd;
@@ -210,14 +388,16 @@ struct pkg_data {
unsigned long long pkg_both_core_gfxe_c0;
long long gfx_rc6_ms;
unsigned int gfx_mhz;
+ unsigned int gfx_act_mhz;
unsigned int package_id;
- unsigned int energy_pkg; /* MSR_PKG_ENERGY_STATUS */
- unsigned int energy_dram; /* MSR_DRAM_ENERGY_STATUS */
- unsigned int energy_cores; /* MSR_PP0_ENERGY_STATUS */
- unsigned int energy_gfx; /* MSR_PP1_ENERGY_STATUS */
- unsigned int rapl_pkg_perf_status; /* MSR_PKG_PERF_STATUS */
- unsigned int rapl_dram_perf_status; /* MSR_DRAM_PERF_STATUS */
+ unsigned long long energy_pkg; /* MSR_PKG_ENERGY_STATUS */
+ unsigned long long energy_dram; /* MSR_DRAM_ENERGY_STATUS */
+ unsigned long long energy_cores; /* MSR_PP0_ENERGY_STATUS */
+ unsigned long long energy_gfx; /* MSR_PP1_ENERGY_STATUS */
+ unsigned long long rapl_pkg_perf_status; /* MSR_PKG_PERF_STATUS */
+ unsigned long long rapl_dram_perf_status; /* MSR_DRAM_PERF_STATUS */
unsigned int pkg_temp_c;
+ unsigned int uncore_mhz;
unsigned long long counter[MAX_ADDED_COUNTERS];
} *package_even, *package_odd;
@@ -238,27 +418,120 @@ struct pkg_data {
((node_no) * topo.cores_per_node) + \
(core_no))
-
#define GET_PKG(pkg_base, pkg_no) (pkg_base + pkg_no)
-enum counter_scope {SCOPE_CPU, SCOPE_CORE, SCOPE_PACKAGE};
-enum counter_type {COUNTER_ITEMS, COUNTER_CYCLES, COUNTER_SECONDS, COUNTER_USEC};
-enum counter_format {FORMAT_RAW, FORMAT_DELTA, FORMAT_PERCENT};
+/*
+ * The accumulated sum of MSR is defined as a monotonic
+ * increasing MSR, it will be accumulated periodically,
+ * despite its register's bit width.
+ */
+enum {
+ IDX_PKG_ENERGY,
+ IDX_DRAM_ENERGY,
+ IDX_PP0_ENERGY,
+ IDX_PP1_ENERGY,
+ IDX_PKG_PERF,
+ IDX_DRAM_PERF,
+ IDX_COUNT,
+};
-struct msr_counter {
- unsigned int msr_num;
- char name[NAME_BYTES];
- char path[PATH_BYTES];
- unsigned int width;
- enum counter_type type;
- enum counter_format format;
- struct msr_counter *next;
- unsigned int flags;
-#define FLAGS_HIDE (1 << 0)
-#define FLAGS_SHOW (1 << 1)
-#define SYSFS_PERCPU (1 << 1)
+int get_msr_sum(int cpu, off_t offset, unsigned long long *msr);
+
+struct msr_sum_array {
+ /* get_msr_sum() = sum + (get_msr() - last) */
+ struct {
+ /*The accumulated MSR value is updated by the timer */
+ unsigned long long sum;
+ /*The MSR footprint recorded in last timer */
+ unsigned long long last;
+ } entries[IDX_COUNT];
};
+/* The percpu MSR sum array.*/
+struct msr_sum_array *per_cpu_msr_sum;
+
+off_t idx_to_offset(int idx)
+{
+ off_t offset;
+
+ switch (idx) {
+ case IDX_PKG_ENERGY:
+ if (do_rapl & RAPL_AMD_F17H)
+ offset = MSR_PKG_ENERGY_STAT;
+ else
+ offset = MSR_PKG_ENERGY_STATUS;
+ break;
+ case IDX_DRAM_ENERGY:
+ offset = MSR_DRAM_ENERGY_STATUS;
+ break;
+ case IDX_PP0_ENERGY:
+ offset = MSR_PP0_ENERGY_STATUS;
+ break;
+ case IDX_PP1_ENERGY:
+ offset = MSR_PP1_ENERGY_STATUS;
+ break;
+ case IDX_PKG_PERF:
+ offset = MSR_PKG_PERF_STATUS;
+ break;
+ case IDX_DRAM_PERF:
+ offset = MSR_DRAM_PERF_STATUS;
+ break;
+ default:
+ offset = -1;
+ }
+ return offset;
+}
+
+int offset_to_idx(off_t offset)
+{
+ int idx;
+
+ switch (offset) {
+ case MSR_PKG_ENERGY_STATUS:
+ case MSR_PKG_ENERGY_STAT:
+ idx = IDX_PKG_ENERGY;
+ break;
+ case MSR_DRAM_ENERGY_STATUS:
+ idx = IDX_DRAM_ENERGY;
+ break;
+ case MSR_PP0_ENERGY_STATUS:
+ idx = IDX_PP0_ENERGY;
+ break;
+ case MSR_PP1_ENERGY_STATUS:
+ idx = IDX_PP1_ENERGY;
+ break;
+ case MSR_PKG_PERF_STATUS:
+ idx = IDX_PKG_PERF;
+ break;
+ case MSR_DRAM_PERF_STATUS:
+ idx = IDX_DRAM_PERF;
+ break;
+ default:
+ idx = -1;
+ }
+ return idx;
+}
+
+int idx_valid(int idx)
+{
+ switch (idx) {
+ case IDX_PKG_ENERGY:
+ return do_rapl & (RAPL_PKG | RAPL_AMD_F17H);
+ case IDX_DRAM_ENERGY:
+ return do_rapl & RAPL_DRAM;
+ case IDX_PP0_ENERGY:
+ return do_rapl & RAPL_CORES_ENERGY_STATUS;
+ case IDX_PP1_ENERGY:
+ return do_rapl & RAPL_GFX;
+ case IDX_PKG_PERF:
+ return do_rapl & RAPL_PKG_PERF_STATUS;
+ case IDX_DRAM_PERF:
+ return do_rapl & RAPL_DRAM_PERF_STATUS;
+ default:
+ return 0;
+ }
+}
+
struct sys_counters {
unsigned int added_thread_counters;
unsigned int added_core_counters;
@@ -282,7 +555,7 @@ struct cpu_topology {
int logical_node_id; /* 0-based count within the package */
int physical_core_id;
int thread_id;
- cpu_set_t *put_ids; /* Processing Unit/Thread IDs */
+ cpu_set_t *put_ids; /* Processing Unit/Thread IDs */
} *cpus;
struct topo_params {
@@ -299,7 +572,7 @@ struct topo_params {
struct timeval tv_even, tv_odd, tv_delta;
-int *irq_column_2_cpu; /* /proc/interrupts column numbers */
+int *irq_column_2_cpu; /* /proc/interrupts column numbers */
int *irqs_per_cpu; /* indexed by cpu_num */
void setup_all_buffers(void);
@@ -312,34 +585,31 @@ int cpu_is_not_present(int cpu)
{
return !CPU_ISSET_S(cpu, cpu_present_setsize, cpu_present_set);
}
+
/*
* run func(thread, core, package) in topology order
* skip non-present cpus
*/
-int for_all_cpus(int (func)(struct thread_data *, struct core_data *, struct pkg_data *),
- struct thread_data *thread_base, struct core_data *core_base, struct pkg_data *pkg_base)
+int for_all_cpus(int (func) (struct thread_data *, struct core_data *, struct pkg_data *),
+ struct thread_data *thread_base, struct core_data *core_base, struct pkg_data *pkg_base)
{
int retval, pkg_no, core_no, thread_no, node_no;
for (pkg_no = 0; pkg_no < topo.num_packages; ++pkg_no) {
for (node_no = 0; node_no < topo.nodes_per_pkg; node_no++) {
for (core_no = 0; core_no < topo.cores_per_node; ++core_no) {
- for (thread_no = 0; thread_no <
- topo.threads_per_core; ++thread_no) {
+ for (thread_no = 0; thread_no < topo.threads_per_core; ++thread_no) {
struct thread_data *t;
struct core_data *c;
struct pkg_data *p;
- t = GET_THREAD(thread_base, thread_no,
- core_no, node_no,
- pkg_no);
+ t = GET_THREAD(thread_base, thread_no, core_no, node_no, pkg_no);
if (cpu_is_not_present(t->cpu_id))
continue;
- c = GET_CORE(core_base, core_no,
- node_no, pkg_no);
+ c = GET_CORE(core_base, core_no, node_no, pkg_no);
p = GET_PKG(pkg_base, pkg_no);
retval = func(t, c, p);
@@ -361,6 +631,7 @@ int cpu_migrate(int cpu)
else
return 0;
}
+
int get_msr_fd(int cpu)
{
char pathname[32];
@@ -381,145 +652,57 @@ int get_msr_fd(int cpu)
return fd;
}
-int get_msr(int cpu, off_t offset, unsigned long long *msr)
+static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags)
{
- ssize_t retval;
+ return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags);
+}
- retval = pread(get_msr_fd(cpu), msr, sizeof(*msr), offset);
+static int perf_instr_count_open(int cpu_num)
+{
+ struct perf_event_attr pea;
+ int fd;
- if (retval != sizeof *msr)
- err(-1, "cpu%d: msr offset 0x%llx read failed", cpu, (unsigned long long)offset);
+ memset(&pea, 0, sizeof(struct perf_event_attr));
+ pea.type = PERF_TYPE_HARDWARE;
+ pea.size = sizeof(struct perf_event_attr);
+ pea.config = PERF_COUNT_HW_INSTRUCTIONS;
- return 0;
+ /* counter for cpu_num, including user + kernel and all processes */
+ fd = perf_event_open(&pea, -1, cpu_num, -1, 0);
+ if (fd == -1) {
+ warn("cpu%d: perf instruction counter", cpu_num);
+ BIC_NOT_PRESENT(BIC_IPC);
+ }
+
+ return fd;
}
-/*
- * This list matches the column headers, except
- * 1. built-in only, the sysfs counters are not here -- we learn of those at run-time
- * 2. Core and CPU are moved to the end, we can't have strings that contain them
- * matching on them for --show and --hide.
- */
-struct msr_counter bic[] = {
- { 0x0, "usec" },
- { 0x0, "Time_Of_Day_Seconds" },
- { 0x0, "Package" },
- { 0x0, "Node" },
- { 0x0, "Avg_MHz" },
- { 0x0, "Busy%" },
- { 0x0, "Bzy_MHz" },
- { 0x0, "TSC_MHz" },
- { 0x0, "IRQ" },
- { 0x0, "SMI", "", 32, 0, FORMAT_DELTA, NULL},
- { 0x0, "sysfs" },
- { 0x0, "CPU%c1" },
- { 0x0, "CPU%c3" },
- { 0x0, "CPU%c6" },
- { 0x0, "CPU%c7" },
- { 0x0, "ThreadC" },
- { 0x0, "CoreTmp" },
- { 0x0, "CoreCnt" },
- { 0x0, "PkgTmp" },
- { 0x0, "GFX%rc6" },
- { 0x0, "GFXMHz" },
- { 0x0, "Pkg%pc2" },
- { 0x0, "Pkg%pc3" },
- { 0x0, "Pkg%pc6" },
- { 0x0, "Pkg%pc7" },
- { 0x0, "Pkg%pc8" },
- { 0x0, "Pkg%pc9" },
- { 0x0, "Pk%pc10" },
- { 0x0, "CPU%LPI" },
- { 0x0, "SYS%LPI" },
- { 0x0, "PkgWatt" },
- { 0x0, "CorWatt" },
- { 0x0, "GFXWatt" },
- { 0x0, "PkgCnt" },
- { 0x0, "RAMWatt" },
- { 0x0, "PKG_%" },
- { 0x0, "RAM_%" },
- { 0x0, "Pkg_J" },
- { 0x0, "Cor_J" },
- { 0x0, "GFX_J" },
- { 0x0, "RAM_J" },
- { 0x0, "Mod%c6" },
- { 0x0, "Totl%C0" },
- { 0x0, "Any%C0" },
- { 0x0, "GFX%C0" },
- { 0x0, "CPUGFX%" },
- { 0x0, "Core" },
- { 0x0, "CPU" },
- { 0x0, "APIC" },
- { 0x0, "X2APIC" },
- { 0x0, "Die" },
-};
+int get_instr_count_fd(int cpu)
+{
+ if (fd_instr_count_percpu[cpu])
+ return fd_instr_count_percpu[cpu];
-#define MAX_BIC (sizeof(bic) / sizeof(struct msr_counter))
-#define BIC_USEC (1ULL << 0)
-#define BIC_TOD (1ULL << 1)
-#define BIC_Package (1ULL << 2)
-#define BIC_Node (1ULL << 3)
-#define BIC_Avg_MHz (1ULL << 4)
-#define BIC_Busy (1ULL << 5)
-#define BIC_Bzy_MHz (1ULL << 6)
-#define BIC_TSC_MHz (1ULL << 7)
-#define BIC_IRQ (1ULL << 8)
-#define BIC_SMI (1ULL << 9)
-#define BIC_sysfs (1ULL << 10)
-#define BIC_CPU_c1 (1ULL << 11)
-#define BIC_CPU_c3 (1ULL << 12)
-#define BIC_CPU_c6 (1ULL << 13)
-#define BIC_CPU_c7 (1ULL << 14)
-#define BIC_ThreadC (1ULL << 15)
-#define BIC_CoreTmp (1ULL << 16)
-#define BIC_CoreCnt (1ULL << 17)
-#define BIC_PkgTmp (1ULL << 18)
-#define BIC_GFX_rc6 (1ULL << 19)
-#define BIC_GFXMHz (1ULL << 20)
-#define BIC_Pkgpc2 (1ULL << 21)
-#define BIC_Pkgpc3 (1ULL << 22)
-#define BIC_Pkgpc6 (1ULL << 23)
-#define BIC_Pkgpc7 (1ULL << 24)
-#define BIC_Pkgpc8 (1ULL << 25)
-#define BIC_Pkgpc9 (1ULL << 26)
-#define BIC_Pkgpc10 (1ULL << 27)
-#define BIC_CPU_LPI (1ULL << 28)
-#define BIC_SYS_LPI (1ULL << 29)
-#define BIC_PkgWatt (1ULL << 30)
-#define BIC_CorWatt (1ULL << 31)
-#define BIC_GFXWatt (1ULL << 32)
-#define BIC_PkgCnt (1ULL << 33)
-#define BIC_RAMWatt (1ULL << 34)
-#define BIC_PKG__ (1ULL << 35)
-#define BIC_RAM__ (1ULL << 36)
-#define BIC_Pkg_J (1ULL << 37)
-#define BIC_Cor_J (1ULL << 38)
-#define BIC_GFX_J (1ULL << 39)
-#define BIC_RAM_J (1ULL << 40)
-#define BIC_Mod_c6 (1ULL << 41)
-#define BIC_Totl_c0 (1ULL << 42)
-#define BIC_Any_c0 (1ULL << 43)
-#define BIC_GFX_c0 (1ULL << 44)
-#define BIC_CPUGFX (1ULL << 45)
-#define BIC_Core (1ULL << 46)
-#define BIC_CPU (1ULL << 47)
-#define BIC_APIC (1ULL << 48)
-#define BIC_X2APIC (1ULL << 49)
-#define BIC_Die (1ULL << 50)
+ fd_instr_count_percpu[cpu] = perf_instr_count_open(cpu);
-#define BIC_DISABLED_BY_DEFAULT (BIC_USEC | BIC_TOD | BIC_APIC | BIC_X2APIC)
+ return fd_instr_count_percpu[cpu];
+}
-unsigned long long bic_enabled = (0xFFFFFFFFFFFFFFFFULL & ~BIC_DISABLED_BY_DEFAULT);
-unsigned long long bic_present = BIC_USEC | BIC_TOD | BIC_sysfs | BIC_APIC | BIC_X2APIC;
+int get_msr(int cpu, off_t offset, unsigned long long *msr)
+{
+ ssize_t retval;
-#define DO_BIC(COUNTER_NAME) (bic_enabled & bic_present & COUNTER_NAME)
-#define DO_BIC_READ(COUNTER_NAME) (bic_present & COUNTER_NAME)
-#define ENABLE_BIC(COUNTER_NAME) (bic_enabled |= COUNTER_NAME)
-#define BIC_PRESENT(COUNTER_BIT) (bic_present |= COUNTER_BIT)
-#define BIC_NOT_PRESENT(COUNTER_BIT) (bic_present &= ~COUNTER_BIT)
+ retval = pread(get_msr_fd(cpu), msr, sizeof(*msr), offset);
+ if (retval != sizeof *msr)
+ err(-1, "cpu%d: msr offset 0x%llx read failed", cpu, (unsigned long long)offset);
+
+ return 0;
+}
#define MAX_DEFERRED 16
+char *deferred_add_names[MAX_DEFERRED];
char *deferred_skip_names[MAX_DEFERRED];
+int deferred_add_index;
int deferred_skip_index;
/*
@@ -531,42 +714,42 @@ enum show_hide_mode { SHOW_LIST, HIDE_LIST } global_show_hide_mode = HIDE_LIST;
void help(void)
{
fprintf(outf,
- "Usage: turbostat [OPTIONS][(--interval seconds) | COMMAND ...]\n"
- "\n"
- "Turbostat forks the specified COMMAND and prints statistics\n"
- "when COMMAND completes.\n"
- "If no COMMAND is specified, turbostat wakes every 5-seconds\n"
- "to print statistics, until interrupted.\n"
- " -a, --add add a counter\n"
- " eg. --add msr0x10,u64,cpu,delta,MY_TSC\n"
- " -c, --cpu cpu-set limit output to summary plus cpu-set:\n"
- " {core | package | j,k,l..m,n-p }\n"
- " -d, --debug displays usec, Time_Of_Day_Seconds and more debugging\n"
- " -D, --Dump displays the raw counter values\n"
- " -e, --enable [all | column]\n"
- " shows all or the specified disabled column\n"
- " -H, --hide [column|column,column,...]\n"
- " hide the specified column(s)\n"
- " -i, --interval sec.subsec\n"
- " Override default 5-second measurement interval\n"
- " -J, --Joules displays energy in Joules instead of Watts\n"
- " -l, --list list column headers only\n"
- " -n, --num_iterations num\n"
- " number of the measurement iterations\n"
- " -o, --out file\n"
- " create or truncate \"file\" for all output\n"
- " -q, --quiet skip decoding system configuration header\n"
- " -s, --show [column|column,column,...]\n"
- " show only the specified column(s)\n"
- " -S, --Summary\n"
- " limits output to 1-line system summary per interval\n"
- " -T, --TCC temperature\n"
- " sets the Thermal Control Circuit temperature in\n"
- " degrees Celsius\n"
- " -h, --help print this help message\n"
- " -v, --version print version information\n"
- "\n"
- "For more help, run \"man turbostat\"\n");
+ "Usage: turbostat [OPTIONS][(--interval seconds) | COMMAND ...]\n"
+ "\n"
+ "Turbostat forks the specified COMMAND and prints statistics\n"
+ "when COMMAND completes.\n"
+ "If no COMMAND is specified, turbostat wakes every 5-seconds\n"
+ "to print statistics, until interrupted.\n"
+ " -a, --add add a counter\n"
+ " eg. --add msr0x10,u64,cpu,delta,MY_TSC\n"
+ " -c, --cpu cpu-set limit output to summary plus cpu-set:\n"
+ " {core | package | j,k,l..m,n-p }\n"
+ " -d, --debug displays usec, Time_Of_Day_Seconds and more debugging\n"
+ " -D, --Dump displays the raw counter values\n"
+ " -e, --enable [all | column]\n"
+ " shows all or the specified disabled column\n"
+ " -H, --hide [column|column,column,...]\n"
+ " hide the specified column(s)\n"
+ " -i, --interval sec.subsec\n"
+ " Override default 5-second measurement interval\n"
+ " -J, --Joules displays energy in Joules instead of Watts\n"
+ " -l, --list list column headers only\n"
+ " -n, --num_iterations num\n"
+ " number of the measurement iterations\n"
+ " -N, --header_iterations num\n"
+ " print header every num iterations\n"
+ " -o, --out file\n"
+ " create or truncate \"file\" for all output\n"
+ " -q, --quiet skip decoding system configuration header\n"
+ " -s, --show [column|column,column,...]\n"
+ " show only the specified column(s)\n"
+ " -S, --Summary\n"
+ " limits output to 1-line system summary per interval\n"
+ " -T, --TCC temperature\n"
+ " sets the Thermal Control Circuit temperature in\n"
+ " degrees Celsius\n"
+ " -h, --help print this help message\n"
+ " -v, --version print version information\n" "\n" "For more help, run \"man turbostat\"\n");
}
/*
@@ -576,7 +759,7 @@ void help(void)
*/
unsigned long long bic_lookup(char *name_list, enum show_hide_mode mode)
{
- int i;
+ unsigned int i;
unsigned long long retval = 0;
while (name_list) {
@@ -587,28 +770,51 @@ unsigned long long bic_lookup(char *name_list, enum show_hide_mode mode)
if (comma)
*comma = '\0';
- if (!strcmp(name_list, "all"))
- return ~0;
-
for (i = 0; i < MAX_BIC; ++i) {
if (!strcmp(name_list, bic[i].name)) {
retval |= (1ULL << i);
break;
}
+ if (!strcmp(name_list, "all")) {
+ retval |= ~0;
+ break;
+ } else if (!strcmp(name_list, "topology")) {
+ retval |= BIC_TOPOLOGY;
+ break;
+ } else if (!strcmp(name_list, "power")) {
+ retval |= BIC_THERMAL_PWR;
+ break;
+ } else if (!strcmp(name_list, "idle")) {
+ retval |= BIC_IDLE;
+ break;
+ } else if (!strcmp(name_list, "frequency")) {
+ retval |= BIC_FREQUENCY;
+ break;
+ } else if (!strcmp(name_list, "other")) {
+ retval |= BIC_OTHER;
+ break;
+ }
+
}
if (i == MAX_BIC) {
if (mode == SHOW_LIST) {
- fprintf(stderr, "Invalid counter name: %s\n", name_list);
- exit(-1);
- }
- deferred_skip_names[deferred_skip_index++] = name_list;
- if (debug)
- fprintf(stderr, "deferred \"%s\"\n", name_list);
- if (deferred_skip_index >= MAX_DEFERRED) {
- fprintf(stderr, "More than max %d un-recognized --skip options '%s'\n",
- MAX_DEFERRED, name_list);
- help();
- exit(1);
+ deferred_add_names[deferred_add_index++] = name_list;
+ if (deferred_add_index >= MAX_DEFERRED) {
+ fprintf(stderr, "More than max %d un-recognized --add options '%s'\n",
+ MAX_DEFERRED, name_list);
+ help();
+ exit(1);
+ }
+ } else {
+ deferred_skip_names[deferred_skip_index++] = name_list;
+ if (debug)
+ fprintf(stderr, "deferred \"%s\"\n", name_list);
+ if (deferred_skip_index >= MAX_DEFERRED) {
+ fprintf(stderr, "More than max %d un-recognized --skip options '%s'\n",
+ MAX_DEFERRED, name_list);
+ help();
+ exit(1);
+ }
}
}
@@ -620,7 +826,6 @@ unsigned long long bic_lookup(char *name_list, enum show_hide_mode mode)
return retval;
}
-
void print_header(char *delim)
{
struct msr_counter *mp;
@@ -653,6 +858,9 @@ void print_header(char *delim)
if (DO_BIC(BIC_TSC_MHz))
outp += sprintf(outp, "%sTSC_MHz", (printed++ ? delim : ""));
+ if (DO_BIC(BIC_IPC))
+ outp += sprintf(outp, "%sIPC", (printed++ ? delim : ""));
+
if (DO_BIC(BIC_IRQ)) {
if (sums_need_wide_columns)
outp += sprintf(outp, "%s IRQ", (printed++ ? delim : ""));
@@ -693,6 +901,9 @@ void print_header(char *delim)
if (DO_BIC(BIC_CoreTmp))
outp += sprintf(outp, "%sCoreTmp", (printed++ ? delim : ""));
+ if (DO_BIC(BIC_CORE_THROT_CNT))
+ outp += sprintf(outp, "%sCoreThr", (printed++ ? delim : ""));
+
if (do_rapl && !rapl_joules) {
if (DO_BIC(BIC_CorWatt) && (do_rapl & RAPL_PER_CORE_ENERGY))
outp += sprintf(outp, "%sCorWatt", (printed++ ? delim : ""));
@@ -724,6 +935,9 @@ void print_header(char *delim)
if (DO_BIC(BIC_GFXMHz))
outp += sprintf(outp, "%sGFXMHz", (printed++ ? delim : ""));
+ if (DO_BIC(BIC_GFXACTMHz))
+ outp += sprintf(outp, "%sGFXAMHz", (printed++ ? delim : ""));
+
if (DO_BIC(BIC_Totl_c0))
outp += sprintf(outp, "%sTotl%%C0", (printed++ ? delim : ""));
if (DO_BIC(BIC_Any_c0))
@@ -779,6 +993,9 @@ void print_header(char *delim)
if (DO_BIC(BIC_RAM__))
outp += sprintf(outp, "%sRAM_%%", (printed++ ? delim : ""));
}
+ if (DO_BIC(BIC_UNCORE_MHZ))
+ outp += sprintf(outp, "%sUncMHz", (printed++ ? delim : ""));
+
for (mp = sys.pp; mp; mp = mp->next) {
if (mp->format == FORMAT_RAW) {
if (mp->width == 64)
@@ -796,8 +1013,7 @@ void print_header(char *delim)
outp += sprintf(outp, "\n");
}
-int dump_counters(struct thread_data *t, struct core_data *c,
- struct pkg_data *p)
+int dump_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
{
int i;
struct msr_counter *mp;
@@ -805,21 +1021,22 @@ int dump_counters(struct thread_data *t, struct core_data *c,
outp += sprintf(outp, "t %p, c %p, p %p\n", t, c, p);
if (t) {
- outp += sprintf(outp, "CPU: %d flags 0x%x\n",
- t->cpu_id, t->flags);
+ outp += sprintf(outp, "CPU: %d flags 0x%x\n", t->cpu_id, t->flags);
outp += sprintf(outp, "TSC: %016llX\n", t->tsc);
outp += sprintf(outp, "aperf: %016llX\n", t->aperf);
outp += sprintf(outp, "mperf: %016llX\n", t->mperf);
outp += sprintf(outp, "c1: %016llX\n", t->c1);
+ if (DO_BIC(BIC_IPC))
+ outp += sprintf(outp, "IPC: %lld\n", t->instr_count);
+
if (DO_BIC(BIC_IRQ))
outp += sprintf(outp, "IRQ: %lld\n", t->irq_count);
if (DO_BIC(BIC_SMI))
outp += sprintf(outp, "SMI: %d\n", t->smi_count);
for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
- outp += sprintf(outp, "tADDED [%d] msr0x%x: %08llX\n",
- i, mp->msr_num, t->counter[i]);
+ outp += sprintf(outp, "tADDED [%d] msr0x%x: %08llX\n", i, mp->msr_num, t->counter[i]);
}
}
@@ -829,11 +1046,11 @@ int dump_counters(struct thread_data *t, struct core_data *c,
outp += sprintf(outp, "c6: %016llX\n", c->c6);
outp += sprintf(outp, "c7: %016llX\n", c->c7);
outp += sprintf(outp, "DTS: %dC\n", c->core_temp_c);
+ outp += sprintf(outp, "cpu_throt_count: %016llX\n", c->core_throt_cnt);
outp += sprintf(outp, "Joules: %0X\n", c->core_energy);
for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
- outp += sprintf(outp, "cADDED [%d] msr0x%x: %08llX\n",
- i, mp->msr_num, c->counter[i]);
+ outp += sprintf(outp, "cADDED [%d] msr0x%x: %08llX\n", i, mp->msr_num, c->counter[i]);
}
outp += sprintf(outp, "mc6_us: %016llX\n", c->mc6_us);
}
@@ -858,19 +1075,16 @@ int dump_counters(struct thread_data *t, struct core_data *c,
outp += sprintf(outp, "pc10: %016llX\n", p->pc10);
outp += sprintf(outp, "cpu_lpi: %016llX\n", p->cpu_lpi);
outp += sprintf(outp, "sys_lpi: %016llX\n", p->sys_lpi);
- outp += sprintf(outp, "Joules PKG: %0X\n", p->energy_pkg);
- outp += sprintf(outp, "Joules COR: %0X\n", p->energy_cores);
- outp += sprintf(outp, "Joules GFX: %0X\n", p->energy_gfx);
- outp += sprintf(outp, "Joules RAM: %0X\n", p->energy_dram);
- outp += sprintf(outp, "Throttle PKG: %0X\n",
- p->rapl_pkg_perf_status);
- outp += sprintf(outp, "Throttle RAM: %0X\n",
- p->rapl_dram_perf_status);
+ outp += sprintf(outp, "Joules PKG: %0llX\n", p->energy_pkg);
+ outp += sprintf(outp, "Joules COR: %0llX\n", p->energy_cores);
+ outp += sprintf(outp, "Joules GFX: %0llX\n", p->energy_gfx);
+ outp += sprintf(outp, "Joules RAM: %0llX\n", p->energy_dram);
+ outp += sprintf(outp, "Throttle PKG: %0llX\n", p->rapl_pkg_perf_status);
+ outp += sprintf(outp, "Throttle RAM: %0llX\n", p->rapl_dram_perf_status);
outp += sprintf(outp, "PTM: %dC\n", p->pkg_temp_c);
for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
- outp += sprintf(outp, "pADDED [%d] msr0x%x: %08llX\n",
- i, mp->msr_num, p->counter[i]);
+ outp += sprintf(outp, "pADDED [%d] msr0x%x: %08llX\n", i, mp->msr_num, p->counter[i]);
}
}
@@ -882,8 +1096,7 @@ int dump_counters(struct thread_data *t, struct core_data *c,
/*
* column formatting convention & formats
*/
-int format_counters(struct thread_data *t, struct core_data *c,
- struct pkg_data *p)
+int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
{
double interval_float, tsc;
char *fmt8;
@@ -892,17 +1105,16 @@ int format_counters(struct thread_data *t, struct core_data *c,
char *delim = "\t";
int printed = 0;
- /* if showing only 1st thread in core and this isn't one, bail out */
+ /* if showing only 1st thread in core and this isn't one, bail out */
if (show_core_only && !(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
return 0;
- /* if showing only 1st thread in pkg and this isn't one, bail out */
+ /* if showing only 1st thread in pkg and this isn't one, bail out */
if (show_pkg_only && !(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
return 0;
/*if not summary line and --cpu is used */
- if ((t != &average.threads) &&
- (cpu_subset && !CPU_ISSET_S(t->cpu_id, cpu_subset_size, cpu_subset)))
+ if ((t != &average.threads) && (cpu_subset && !CPU_ISSET_S(t->cpu_id, cpu_subset_size, cpu_subset)))
return 0;
if (DO_BIC(BIC_USEC)) {
@@ -917,7 +1129,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
if (DO_BIC(BIC_TOD))
outp += sprintf(outp, "%10ld.%06ld\t", t->tv_end.tv_sec, t->tv_end.tv_usec);
- interval_float = t->tv_delta.tv_sec + t->tv_delta.tv_usec/1000000.0;
+ interval_float = t->tv_delta.tv_sec + t->tv_delta.tv_usec / 1000000.0;
tsc = t->tsc * tsc_tweak;
@@ -953,11 +1165,9 @@ int format_counters(struct thread_data *t, struct core_data *c,
if (DO_BIC(BIC_Node)) {
if (t)
outp += sprintf(outp, "%s%d",
- (printed++ ? delim : ""),
- cpus[t->cpu_id].physical_node_id);
+ (printed++ ? delim : ""), cpus[t->cpu_id].physical_node_id);
else
- outp += sprintf(outp, "%s-",
- (printed++ ? delim : ""));
+ outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
}
if (DO_BIC(BIC_Core)) {
if (c)
@@ -974,22 +1184,25 @@ int format_counters(struct thread_data *t, struct core_data *c,
}
if (DO_BIC(BIC_Avg_MHz))
- outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""),
- 1.0 / units * t->aperf / interval_float);
+ outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), 1.0 / units * t->aperf / interval_float);
if (DO_BIC(BIC_Busy))
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->mperf/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->mperf / tsc);
if (DO_BIC(BIC_Bzy_MHz)) {
if (has_base_hz)
- outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), base_hz / units * t->aperf / t->mperf);
+ outp +=
+ sprintf(outp, "%s%.0f", (printed++ ? delim : ""), base_hz / units * t->aperf / t->mperf);
else
outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""),
- tsc / units * t->aperf / t->mperf / interval_float);
+ tsc / units * t->aperf / t->mperf / interval_float);
}
if (DO_BIC(BIC_TSC_MHz))
- outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), 1.0 * t->tsc/units/interval_float);
+ outp += sprintf(outp, "%s%.0f", (printed++ ? delim : ""), 1.0 * t->tsc / units / interval_float);
+
+ if (DO_BIC(BIC_IPC))
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 1.0 * t->instr_count / t->aperf);
/* IRQ */
if (DO_BIC(BIC_IRQ)) {
@@ -1007,7 +1220,8 @@ int format_counters(struct thread_data *t, struct core_data *c,
for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) {
if (mp->format == FORMAT_RAW) {
if (mp->width == 32)
- outp += sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int) t->counter[i]);
+ outp +=
+ sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int)t->counter[i]);
else
outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), t->counter[i]);
} else if (mp->format == FORMAT_DELTA) {
@@ -1017,27 +1231,28 @@ int format_counters(struct thread_data *t, struct core_data *c,
outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), t->counter[i]);
} else if (mp->format == FORMAT_PERCENT) {
if (mp->type == COUNTER_USEC)
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), t->counter[i]/interval_float/10000);
+ outp +=
+ sprintf(outp, "%s%.2f", (printed++ ? delim : ""),
+ t->counter[i] / interval_float / 10000);
else
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->counter[i]/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->counter[i] / tsc);
}
}
/* C1 */
if (DO_BIC(BIC_CPU_c1))
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->c1/tsc);
-
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * t->c1 / tsc);
/* print per-core data only for 1st thread in core */
if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
goto done;
if (DO_BIC(BIC_CPU_c3))
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c3/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c3 / tsc);
if (DO_BIC(BIC_CPU_c6))
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c6/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c6 / tsc);
if (DO_BIC(BIC_CPU_c7))
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c7/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->c7 / tsc);
/* Mod%c6 */
if (DO_BIC(BIC_Mod_c6))
@@ -1046,10 +1261,15 @@ int format_counters(struct thread_data *t, struct core_data *c,
if (DO_BIC(BIC_CoreTmp))
outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), c->core_temp_c);
+ /* Core throttle count */
+ if (DO_BIC(BIC_CORE_THROT_CNT))
+ outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), c->core_throt_cnt);
+
for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) {
if (mp->format == FORMAT_RAW) {
if (mp->width == 32)
- outp += sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int) c->counter[i]);
+ outp +=
+ sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int)c->counter[i]);
else
outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), c->counter[i]);
} else if (mp->format == FORMAT_DELTA) {
@@ -1058,21 +1278,15 @@ int format_counters(struct thread_data *t, struct core_data *c,
else
outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), c->counter[i]);
} else if (mp->format == FORMAT_PERCENT) {
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->counter[i]/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * c->counter[i] / tsc);
}
}
- /*
- * If measurement interval exceeds minimum RAPL Joule Counter range,
- * indicate that results are suspect by printing "**" in fraction place.
- */
- if (interval_float < rapl_joule_counter_range)
- fmt8 = "%s%.2f";
- else
- fmt8 = "%6.0f**";
+ fmt8 = "%s%.2f";
if (DO_BIC(BIC_CorWatt) && (do_rapl & RAPL_PER_CORE_ENERGY))
- outp += sprintf(outp, fmt8, (printed++ ? delim : ""), c->core_energy * rapl_energy_units / interval_float);
+ outp +=
+ sprintf(outp, fmt8, (printed++ ? delim : ""), c->core_energy * rapl_energy_units / interval_float);
if (DO_BIC(BIC_Cor_J) && (do_rapl & RAPL_PER_CORE_ENERGY))
outp += sprintf(outp, fmt8, (printed++ ? delim : ""), c->core_energy * rapl_energy_units);
@@ -1090,7 +1304,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
outp += sprintf(outp, "%s**.**", (printed++ ? delim : ""));
} else {
outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""),
- p->gfx_rc6_ms / 10.0 / interval_float);
+ p->gfx_rc6_ms / 10.0 / interval_float);
}
}
@@ -1098,44 +1312,56 @@ int format_counters(struct thread_data *t, struct core_data *c,
if (DO_BIC(BIC_GFXMHz))
outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_mhz);
+ /* GFXACTMHz */
+ if (DO_BIC(BIC_GFXACTMHz))
+ outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_act_mhz);
+
/* Totl%C0, Any%C0 GFX%C0 CPUGFX% */
if (DO_BIC(BIC_Totl_c0))
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_wtd_core_c0/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_wtd_core_c0 / tsc);
if (DO_BIC(BIC_Any_c0))
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_any_core_c0/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_any_core_c0 / tsc);
if (DO_BIC(BIC_GFX_c0))
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_any_gfxe_c0/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_any_gfxe_c0 / tsc);
if (DO_BIC(BIC_CPUGFX))
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_both_core_gfxe_c0/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_both_core_gfxe_c0 / tsc);
if (DO_BIC(BIC_Pkgpc2))
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc2/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc2 / tsc);
if (DO_BIC(BIC_Pkgpc3))
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc3/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc3 / tsc);
if (DO_BIC(BIC_Pkgpc6))
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc6/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc6 / tsc);
if (DO_BIC(BIC_Pkgpc7))
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc7/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc7 / tsc);
if (DO_BIC(BIC_Pkgpc8))
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc8/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc8 / tsc);
if (DO_BIC(BIC_Pkgpc9))
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc9/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc9 / tsc);
if (DO_BIC(BIC_Pkgpc10))
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc10/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc10 / tsc);
if (DO_BIC(BIC_CPU_LPI))
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->cpu_lpi / 1000000.0 / interval_float);
+ outp +=
+ sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->cpu_lpi / 1000000.0 / interval_float);
if (DO_BIC(BIC_SYS_LPI))
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->sys_lpi / 1000000.0 / interval_float);
+ outp +=
+ sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->sys_lpi / 1000000.0 / interval_float);
if (DO_BIC(BIC_PkgWatt))
- outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_pkg * rapl_energy_units / interval_float);
+ outp +=
+ sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_pkg * rapl_energy_units / interval_float);
+
if (DO_BIC(BIC_CorWatt) && !(do_rapl & RAPL_PER_CORE_ENERGY))
- outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_cores * rapl_energy_units / interval_float);
+ outp +=
+ sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_cores * rapl_energy_units / interval_float);
if (DO_BIC(BIC_GFXWatt))
- outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_gfx * rapl_energy_units / interval_float);
+ outp +=
+ sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_gfx * rapl_energy_units / interval_float);
if (DO_BIC(BIC_RAMWatt))
- outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_dram * rapl_dram_energy_units / interval_float);
+ outp +=
+ sprintf(outp, fmt8, (printed++ ? delim : ""),
+ p->energy_dram * rapl_dram_energy_units / interval_float);
if (DO_BIC(BIC_Pkg_J))
outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_pkg * rapl_energy_units);
if (DO_BIC(BIC_Cor_J) && !(do_rapl & RAPL_PER_CORE_ENERGY))
@@ -1145,14 +1371,22 @@ int format_counters(struct thread_data *t, struct core_data *c,
if (DO_BIC(BIC_RAM_J))
outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_dram * rapl_dram_energy_units);
if (DO_BIC(BIC_PKG__))
- outp += sprintf(outp, fmt8, (printed++ ? delim : ""), 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float);
+ outp +=
+ sprintf(outp, fmt8, (printed++ ? delim : ""),
+ 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float);
if (DO_BIC(BIC_RAM__))
- outp += sprintf(outp, fmt8, (printed++ ? delim : ""), 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float);
+ outp +=
+ sprintf(outp, fmt8, (printed++ ? delim : ""),
+ 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float);
+ /* UncMHz */
+ if (DO_BIC(BIC_UNCORE_MHZ))
+ outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->uncore_mhz);
for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
if (mp->format == FORMAT_RAW) {
if (mp->width == 32)
- outp += sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int) p->counter[i]);
+ outp +=
+ sprintf(outp, "%s0x%08x", (printed++ ? delim : ""), (unsigned int)p->counter[i]);
else
outp += sprintf(outp, "%s0x%016llx", (printed++ ? delim : ""), p->counter[i]);
} else if (mp->format == FORMAT_DELTA) {
@@ -1161,7 +1395,7 @@ int format_counters(struct thread_data *t, struct core_data *c,
else
outp += sprintf(outp, "%s%lld", (printed++ ? delim : ""), p->counter[i]);
} else if (mp->format == FORMAT_PERCENT) {
- outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->counter[i]/tsc);
+ outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->counter[i] / tsc);
}
}
@@ -1186,22 +1420,24 @@ void flush_output_stdout(void)
outp = output_buffer;
}
+
void flush_output_stderr(void)
{
fputs(output_buffer, outf);
fflush(outf);
outp = output_buffer;
}
+
void format_all_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
{
- static int printed;
+ static int count;
- if (!printed || !summary_only)
+ if ((!count || (header_iterations && !(count % header_iterations))) || !summary_only)
print_header("\t");
format_counters(&average.threads, &average.cores, &average.packages);
- printed = 1;
+ count++;
if (summary_only)
return;
@@ -1210,19 +1446,13 @@ void format_all_counters(struct thread_data *t, struct core_data *c, struct pkg_
}
#define DELTA_WRAP32(new, old) \
- if (new > old) { \
- old = new - old; \
- } else { \
- old = 0x100000000 + new - old; \
- }
+ old = ((((unsigned long long)new << 32) - ((unsigned long long)old << 32)) >> 32);
-int
-delta_package(struct pkg_data *new, struct pkg_data *old)
+int delta_package(struct pkg_data *new, struct pkg_data *old)
{
int i;
struct msr_counter *mp;
-
if (DO_BIC(BIC_Totl_c0))
old->pkg_wtd_core_c0 = new->pkg_wtd_core_c0 - old->pkg_wtd_core_c0;
if (DO_BIC(BIC_Any_c0))
@@ -1247,19 +1477,21 @@ delta_package(struct pkg_data *new, struct pkg_data *old)
old->pkg_temp_c = new->pkg_temp_c;
/* flag an error when rc6 counter resets/wraps */
- if (old->gfx_rc6_ms > new->gfx_rc6_ms)
+ if (old->gfx_rc6_ms > new->gfx_rc6_ms)
old->gfx_rc6_ms = -1;
else
old->gfx_rc6_ms = new->gfx_rc6_ms - old->gfx_rc6_ms;
+ old->uncore_mhz = new->uncore_mhz;
old->gfx_mhz = new->gfx_mhz;
+ old->gfx_act_mhz = new->gfx_act_mhz;
- DELTA_WRAP32(new->energy_pkg, old->energy_pkg);
- DELTA_WRAP32(new->energy_cores, old->energy_cores);
- DELTA_WRAP32(new->energy_gfx, old->energy_gfx);
- DELTA_WRAP32(new->energy_dram, old->energy_dram);
- DELTA_WRAP32(new->rapl_pkg_perf_status, old->rapl_pkg_perf_status);
- DELTA_WRAP32(new->rapl_dram_perf_status, old->rapl_dram_perf_status);
+ old->energy_pkg = new->energy_pkg - old->energy_pkg;
+ old->energy_cores = new->energy_cores - old->energy_cores;
+ old->energy_gfx = new->energy_gfx - old->energy_gfx;
+ old->energy_dram = new->energy_dram - old->energy_dram;
+ old->rapl_pkg_perf_status = new->rapl_pkg_perf_status - old->rapl_pkg_perf_status;
+ old->rapl_dram_perf_status = new->rapl_dram_perf_status - old->rapl_dram_perf_status;
for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
if (mp->format == FORMAT_RAW)
@@ -1271,8 +1503,7 @@ delta_package(struct pkg_data *new, struct pkg_data *old)
return 0;
}
-void
-delta_core(struct core_data *new, struct core_data *old)
+void delta_core(struct core_data *new, struct core_data *old)
{
int i;
struct msr_counter *mp;
@@ -1281,6 +1512,7 @@ delta_core(struct core_data *new, struct core_data *old)
old->c6 = new->c6 - old->c6;
old->c7 = new->c7 - old->c7;
old->core_temp_c = new->core_temp_c;
+ old->core_throt_cnt = new->core_throt_cnt;
old->mc6_us = new->mc6_us - old->mc6_us;
DELTA_WRAP32(new->core_energy, old->core_energy);
@@ -1304,9 +1536,7 @@ int soft_c1_residency_display(int bic)
/*
* old = new - old
*/
-int
-delta_thread(struct thread_data *new, struct thread_data *old,
- struct core_data *core_delta)
+int delta_thread(struct thread_data *new, struct thread_data *old, struct core_data *core_delta)
{
int i;
struct msr_counter *mp;
@@ -1337,8 +1567,7 @@ delta_thread(struct thread_data *new, struct thread_data *old,
old->c1 = new->c1 - old->c1;
- if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) ||
- soft_c1_residency_display(BIC_Avg_MHz)) {
+ if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) || soft_c1_residency_display(BIC_Avg_MHz)) {
if ((new->aperf > old->aperf) && (new->mperf > old->mperf)) {
old->aperf = new->aperf - old->aperf;
old->mperf = new->mperf - old->mperf;
@@ -1347,7 +1576,6 @@ delta_thread(struct thread_data *new, struct thread_data *old,
}
}
-
if (use_c1_residency_msr) {
/*
* Some models have a dedicated C1 residency MSR,
@@ -1364,7 +1592,7 @@ delta_thread(struct thread_data *new, struct thread_data *old,
else {
/* normal case, derive c1 */
old->c1 = (old->tsc * tsc_tweak) - old->mperf - core_delta->c3
- - core_delta->c6 - core_delta->c7;
+ - core_delta->c6 - core_delta->c7;
}
}
@@ -1374,6 +1602,9 @@ delta_thread(struct thread_data *new, struct thread_data *old,
old->mperf = 1; /* divide by 0 protection */
}
+ if (DO_BIC(BIC_IPC))
+ old->instr_count = new->instr_count - old->instr_count;
+
if (DO_BIC(BIC_IRQ))
old->irq_count = new->irq_count - old->irq_count;
@@ -1390,8 +1621,7 @@ delta_thread(struct thread_data *new, struct thread_data *old,
}
int delta_cpu(struct thread_data *t, struct core_data *c,
- struct pkg_data *p, struct thread_data *t2,
- struct core_data *c2, struct pkg_data *p2)
+ struct pkg_data *p, struct thread_data *t2, struct core_data *c2, struct pkg_data *p2)
{
int retval = 0;
@@ -1414,7 +1644,7 @@ int delta_cpu(struct thread_data *t, struct core_data *c,
void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
{
int i;
- struct msr_counter *mp;
+ struct msr_counter *mp;
t->tv_begin.tv_sec = 0;
t->tv_begin.tv_usec = 0;
@@ -1428,6 +1658,8 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
t->mperf = 0;
t->c1 = 0;
+ t->instr_count = 0;
+
t->irq_count = 0;
t->smi_count = 0;
@@ -1440,6 +1672,7 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
c->mc6_us = 0;
c->core_temp_c = 0;
c->core_energy = 0;
+ c->core_throt_cnt = 0;
p->pkg_wtd_core_c0 = 0;
p->pkg_any_core_c0 = 0;
@@ -1468,7 +1701,9 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
p->pkg_temp_c = 0;
p->gfx_rc6_ms = 0;
+ p->uncore_mhz = 0;
p->gfx_mhz = 0;
+ p->gfx_act_mhz = 0;
for (i = 0, mp = sys.tp; mp; i++, mp = mp->next)
t->counter[i] = 0;
@@ -1478,8 +1713,8 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
for (i = 0, mp = sys.pp; mp; i++, mp = mp->next)
p->counter[i] = 0;
}
-int sum_counters(struct thread_data *t, struct core_data *c,
- struct pkg_data *p)
+
+int sum_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
{
int i;
struct msr_counter *mp;
@@ -1502,6 +1737,8 @@ int sum_counters(struct thread_data *t, struct core_data *c,
average.threads.mperf += t->mperf;
average.threads.c1 += t->c1;
+ average.threads.instr_count += t->instr_count;
+
average.threads.irq_count += t->irq_count;
average.threads.smi_count += t->smi_count;
@@ -1521,6 +1758,7 @@ int sum_counters(struct thread_data *t, struct core_data *c,
average.cores.mc6_us += c->mc6_us;
average.cores.core_temp_c = MAX(average.cores.core_temp_c, c->core_temp_c);
+ average.cores.core_throt_cnt = MAX(average.cores.core_throt_cnt, c->core_throt_cnt);
average.cores.core_energy += c->core_energy;
@@ -1563,7 +1801,9 @@ int sum_counters(struct thread_data *t, struct core_data *c,
average.packages.energy_gfx += p->energy_gfx;
average.packages.gfx_rc6_ms = p->gfx_rc6_ms;
+ average.packages.uncore_mhz = p->uncore_mhz;
average.packages.gfx_mhz = p->gfx_mhz;
+ average.packages.gfx_act_mhz = p->gfx_act_mhz;
average.packages.pkg_temp_c = MAX(average.packages.pkg_temp_c, p->pkg_temp_c);
@@ -1577,12 +1817,12 @@ int sum_counters(struct thread_data *t, struct core_data *c,
}
return 0;
}
+
/*
* sum the counters for all cpus in the system
* compute the weighted average
*/
-void compute_average(struct thread_data *t, struct core_data *c,
- struct pkg_data *p)
+void compute_average(struct thread_data *t, struct core_data *c, struct pkg_data *p)
{
int i;
struct msr_counter *mp;
@@ -1597,6 +1837,7 @@ void compute_average(struct thread_data *t, struct core_data *c,
average.threads.tsc /= topo.num_cpus;
average.threads.aperf /= topo.num_cpus;
average.threads.mperf /= topo.num_cpus;
+ average.threads.instr_count /= topo.num_cpus;
average.threads.c1 /= topo.num_cpus;
if (average.threads.irq_count > 9999999)
@@ -1662,7 +1903,7 @@ static unsigned long long rdtsc(void)
{
unsigned int low, high;
- asm volatile("rdtsc" : "=a" (low), "=d" (high));
+ asm volatile ("rdtsc":"=a" (low), "=d"(high));
return low | ((unsigned long long)high) << 32;
}
@@ -1678,6 +1919,7 @@ FILE *fopen_or_die(const char *path, const char *mode)
err(1, "%s: open failed", path);
return filep;
}
+
/*
* snapshot_sysfs_counter()
*
@@ -1709,8 +1951,7 @@ int get_mp(int cpu, struct msr_counter *mp, unsigned long long *counterp)
char path[128 + PATH_BYTES];
if (mp->flags & SYSFS_PERCPU) {
- sprintf(path, "/sys/devices/system/cpu/cpu%d/%s",
- cpu, mp->path);
+ sprintf(path, "/sys/devices/system/cpu/cpu%d/%s", cpu, mp->path);
*counterp = snapshot_sysfs_counter(path);
} else {
@@ -1721,6 +1962,43 @@ int get_mp(int cpu, struct msr_counter *mp, unsigned long long *counterp)
return 0;
}
+unsigned long long get_uncore_mhz(int package, int die)
+{
+ char path[128];
+
+ sprintf(path, "/sys/devices/system/cpu/intel_uncore_frequency/package_0%d_die_0%d/current_freq_khz", package,
+ die);
+
+ return (snapshot_sysfs_counter(path) / 1000);
+}
+
+int get_epb(int cpu)
+{
+ char path[128 + PATH_BYTES];
+ unsigned long long msr;
+ int ret, epb = -1;
+ FILE *fp;
+
+ sprintf(path, "/sys/devices/system/cpu/cpu%d/power/energy_perf_bias", cpu);
+
+ fp = fopen(path, "r");
+ if (!fp)
+ goto msr_fallback;
+
+ ret = fscanf(fp, "%d", &epb);
+ if (ret != 1)
+ err(1, "%s(%s)", __func__, path);
+
+ fclose(fp);
+
+ return epb;
+
+msr_fallback:
+ get_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, &msr);
+
+ return msr & 0xf;
+}
+
void get_apic_id(struct thread_data *t)
{
unsigned int eax, ebx, ecx, edx;
@@ -1743,7 +2021,7 @@ void get_apic_id(struct thread_data *t)
eax = ebx = ecx = edx = 0;
__cpuid(0x80000001, eax, ebx, ecx, edx);
- topology_extensions = ecx & (1 << 22);
+ topology_extensions = ecx & (1 << 22);
if (topology_extensions == 0)
return;
@@ -1766,8 +2044,27 @@ void get_apic_id(struct thread_data *t)
t->x2apic_id = edx;
if (debug && (t->apic_id != (t->x2apic_id & 0xff)))
- fprintf(outf, "cpu%d: BIOS BUG: apic 0x%x x2apic 0x%x\n",
- t->cpu_id, t->apic_id, t->x2apic_id);
+ fprintf(outf, "cpu%d: BIOS BUG: apic 0x%x x2apic 0x%x\n", t->cpu_id, t->apic_id, t->x2apic_id);
+}
+
+int get_core_throt_cnt(int cpu, unsigned long long *cnt)
+{
+ char path[128 + PATH_BYTES];
+ unsigned long long tmp;
+ FILE *fp;
+ int ret;
+
+ sprintf(path, "/sys/devices/system/cpu/cpu%d/thermal_throttle/core_throttle_count", cpu);
+ fp = fopen(path, "r");
+ if (!fp)
+ return -1;
+ ret = fscanf(fp, "%lld", &tmp);
+ fclose(fp);
+ if (ret != 1)
+ return -1;
+ *cnt = tmp;
+
+ return 0;
}
/*
@@ -1784,7 +2081,7 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
int i;
if (cpu_migrate(cpu)) {
- fprintf(outf, "Could not migrate to CPU %d\n", cpu);
+ fprintf(outf, "get_counters: Could not migrate to CPU %d\n", cpu);
return -1;
}
@@ -1795,8 +2092,7 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
retry:
t->tsc = rdtsc(); /* we are running on local CPU of interest */
- if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) ||
- soft_c1_residency_display(BIC_Avg_MHz)) {
+ if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) || soft_c1_residency_display(BIC_Avg_MHz)) {
unsigned long long tsc_before, tsc_between, tsc_after, aperf_time, mperf_time;
/*
@@ -1843,8 +2139,7 @@ retry:
if (aperf_mperf_retry_count < 5)
goto retry;
else
- warnx("cpu%d jitter %lld %lld",
- cpu, aperf_time, mperf_time);
+ warnx("cpu%d jitter %lld %lld", cpu, aperf_time, mperf_time);
}
aperf_mperf_retry_count = 0;
@@ -1852,6 +2147,10 @@ retry:
t->mperf = t->mperf * aperf_mperf_multiplier;
}
+ if (DO_BIC(BIC_IPC))
+ if (read(get_instr_count_fd(cpu), &t->instr_count, sizeof(long long)) != sizeof(long long))
+ return -4;
+
if (DO_BIC(BIC_IRQ))
t->irq_count = irqs_per_cpu[cpu];
if (DO_BIC(BIC_SMI)) {
@@ -1886,9 +2185,19 @@ retry:
return -7;
}
- if (DO_BIC(BIC_CPU_c7) || soft_c1_residency_display(BIC_CPU_c7))
+ if (DO_BIC(BIC_CPU_c7) || soft_c1_residency_display(BIC_CPU_c7)) {
if (get_msr(cpu, MSR_CORE_C7_RESIDENCY, &c->c7))
return -8;
+ else if (t->is_atom) {
+ /*
+ * For Atom CPUs that has core cstate deeper than c6,
+ * MSR_CORE_C6_RESIDENCY returns residency of cc6 and deeper.
+ * Minus CC7 (and deeper cstates) residency to get
+ * accturate cc6 residency.
+ */
+ c->c6 -= c->c7;
+ }
+ }
if (DO_BIC(BIC_Mod_c6))
if (get_msr(cpu, MSR_MODULE_C6_RES_MS, &c->mc6_us))
@@ -1897,9 +2206,12 @@ retry:
if (DO_BIC(BIC_CoreTmp)) {
if (get_msr(cpu, MSR_IA32_THERM_STATUS, &msr))
return -9;
- c->core_temp_c = tcc_activation_temp - ((msr >> 16) & 0x7F);
+ c->core_temp_c = tj_max - ((msr >> 16) & 0x7F);
}
+ if (DO_BIC(BIC_CORE_THROT_CNT))
+ get_core_throt_cnt(cpu, &c->core_throt_cnt);
+
if (do_rapl & RAPL_AMD_F17H) {
if (get_msr(cpu, MSR_CORE_ENERGY_STAT, &msr))
return -14;
@@ -1966,52 +2278,59 @@ retry:
p->sys_lpi = cpuidle_cur_sys_lpi_us;
if (do_rapl & RAPL_PKG) {
- if (get_msr(cpu, MSR_PKG_ENERGY_STATUS, &msr))
+ if (get_msr_sum(cpu, MSR_PKG_ENERGY_STATUS, &msr))
return -13;
- p->energy_pkg = msr & 0xFFFFFFFF;
+ p->energy_pkg = msr;
}
if (do_rapl & RAPL_CORES_ENERGY_STATUS) {
- if (get_msr(cpu, MSR_PP0_ENERGY_STATUS, &msr))
+ if (get_msr_sum(cpu, MSR_PP0_ENERGY_STATUS, &msr))
return -14;
- p->energy_cores = msr & 0xFFFFFFFF;
+ p->energy_cores = msr;
}
if (do_rapl & RAPL_DRAM) {
- if (get_msr(cpu, MSR_DRAM_ENERGY_STATUS, &msr))
+ if (get_msr_sum(cpu, MSR_DRAM_ENERGY_STATUS, &msr))
return -15;
- p->energy_dram = msr & 0xFFFFFFFF;
+ p->energy_dram = msr;
}
if (do_rapl & RAPL_GFX) {
- if (get_msr(cpu, MSR_PP1_ENERGY_STATUS, &msr))
+ if (get_msr_sum(cpu, MSR_PP1_ENERGY_STATUS, &msr))
return -16;
- p->energy_gfx = msr & 0xFFFFFFFF;
+ p->energy_gfx = msr;
}
if (do_rapl & RAPL_PKG_PERF_STATUS) {
- if (get_msr(cpu, MSR_PKG_PERF_STATUS, &msr))
+ if (get_msr_sum(cpu, MSR_PKG_PERF_STATUS, &msr))
return -16;
- p->rapl_pkg_perf_status = msr & 0xFFFFFFFF;
+ p->rapl_pkg_perf_status = msr;
}
if (do_rapl & RAPL_DRAM_PERF_STATUS) {
- if (get_msr(cpu, MSR_DRAM_PERF_STATUS, &msr))
+ if (get_msr_sum(cpu, MSR_DRAM_PERF_STATUS, &msr))
return -16;
- p->rapl_dram_perf_status = msr & 0xFFFFFFFF;
+ p->rapl_dram_perf_status = msr;
}
if (do_rapl & RAPL_AMD_F17H) {
- if (get_msr(cpu, MSR_PKG_ENERGY_STAT, &msr))
+ if (get_msr_sum(cpu, MSR_PKG_ENERGY_STAT, &msr))
return -13;
- p->energy_pkg = msr & 0xFFFFFFFF;
+ p->energy_pkg = msr;
}
if (DO_BIC(BIC_PkgTmp)) {
if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr))
return -17;
- p->pkg_temp_c = tcc_activation_temp - ((msr >> 16) & 0x7F);
+ p->pkg_temp_c = tj_max - ((msr >> 16) & 0x7F);
}
if (DO_BIC(BIC_GFX_rc6))
p->gfx_rc6_ms = gfx_cur_rc6_ms;
+ /* n.b. assume die0 uncore frequency applies to whole package */
+ if (DO_BIC(BIC_UNCORE_MHZ))
+ p->uncore_mhz = get_uncore_mhz(p->package_id, 0);
+
if (DO_BIC(BIC_GFXMHz))
p->gfx_mhz = gfx_cur_mhz;
+ if (DO_BIC(BIC_GFXACTMHz))
+ p->gfx_act_mhz = gfx_act_mhz;
+
for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) {
if (get_mp(cpu, mp, &p->counter[i]))
return -10;
@@ -2028,45 +2347,81 @@ done:
* (>= PCL__7) and to index pkg_cstate_limit_strings[].
*/
-#define PCLUKN 0 /* Unknown */
-#define PCLRSV 1 /* Reserved */
-#define PCL__0 2 /* PC0 */
-#define PCL__1 3 /* PC1 */
-#define PCL__2 4 /* PC2 */
-#define PCL__3 5 /* PC3 */
-#define PCL__4 6 /* PC4 */
-#define PCL__6 7 /* PC6 */
-#define PCL_6N 8 /* PC6 No Retention */
-#define PCL_6R 9 /* PC6 Retention */
-#define PCL__7 10 /* PC7 */
-#define PCL_7S 11 /* PC7 Shrink */
-#define PCL__8 12 /* PC8 */
-#define PCL__9 13 /* PC9 */
-#define PCL_10 14 /* PC10 */
-#define PCLUNL 15 /* Unlimited */
+#define PCLUKN 0 /* Unknown */
+#define PCLRSV 1 /* Reserved */
+#define PCL__0 2 /* PC0 */
+#define PCL__1 3 /* PC1 */
+#define PCL__2 4 /* PC2 */
+#define PCL__3 5 /* PC3 */
+#define PCL__4 6 /* PC4 */
+#define PCL__6 7 /* PC6 */
+#define PCL_6N 8 /* PC6 No Retention */
+#define PCL_6R 9 /* PC6 Retention */
+#define PCL__7 10 /* PC7 */
+#define PCL_7S 11 /* PC7 Shrink */
+#define PCL__8 12 /* PC8 */
+#define PCL__9 13 /* PC9 */
+#define PCL_10 14 /* PC10 */
+#define PCLUNL 15 /* Unlimited */
int pkg_cstate_limit = PCLUKN;
char *pkg_cstate_limit_strings[] = { "reserved", "unknown", "pc0", "pc1", "pc2",
- "pc3", "pc4", "pc6", "pc6n", "pc6r", "pc7", "pc7s", "pc8", "pc9", "pc10", "unlimited"};
+ "pc3", "pc4", "pc6", "pc6n", "pc6r", "pc7", "pc7s", "pc8", "pc9", "pc10", "unlimited"
+};
-int nhm_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCL__3, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
-int snb_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCL__7, PCL_7S, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
-int hsw_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL__3, PCL__6, PCL__7, PCL_7S, PCL__8, PCL__9, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
-int slv_pkg_cstate_limits[16] = {PCL__0, PCL__1, PCLRSV, PCLRSV, PCL__4, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7};
-int amt_pkg_cstate_limits[16] = {PCLUNL, PCL__1, PCL__2, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
-int phi_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
-int glm_pkg_cstate_limits[16] = {PCLUNL, PCL__1, PCL__3, PCL__6, PCL__7, PCL_7S, PCL__8, PCL__9, PCL_10, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
-int skx_pkg_cstate_limits[16] = {PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV};
+int nhm_pkg_cstate_limits[16] =
+ { PCL__0, PCL__1, PCL__3, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,
+ PCLRSV, PCLRSV
+};
+
+int snb_pkg_cstate_limits[16] =
+ { PCL__0, PCL__2, PCL_6N, PCL_6R, PCL__7, PCL_7S, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,
+ PCLRSV, PCLRSV
+};
+int hsw_pkg_cstate_limits[16] =
+ { PCL__0, PCL__2, PCL__3, PCL__6, PCL__7, PCL_7S, PCL__8, PCL__9, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,
+ PCLRSV, PCLRSV
+};
-static void
-calculate_tsc_tweak()
+int slv_pkg_cstate_limits[16] =
+ { PCL__0, PCL__1, PCLRSV, PCLRSV, PCL__4, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,
+ PCL__6, PCL__7
+};
+
+int amt_pkg_cstate_limits[16] =
+ { PCLUNL, PCL__1, PCL__2, PCLRSV, PCLRSV, PCLRSV, PCL__6, PCL__7, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,
+ PCLRSV, PCLRSV
+};
+
+int phi_pkg_cstate_limits[16] =
+ { PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,
+ PCLRSV, PCLRSV
+};
+
+int glm_pkg_cstate_limits[16] =
+ { PCLUNL, PCL__1, PCL__3, PCL__6, PCL__7, PCL_7S, PCL__8, PCL__9, PCL_10, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,
+ PCLRSV, PCLRSV
+};
+
+int skx_pkg_cstate_limits[16] =
+ { PCL__0, PCL__2, PCL_6N, PCL_6R, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,
+ PCLRSV, PCLRSV
+};
+
+int icx_pkg_cstate_limits[16] =
+ { PCL__0, PCL__2, PCL__6, PCL__6, PCLRSV, PCLRSV, PCLRSV, PCLUNL, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV, PCLRSV,
+ PCLRSV, PCLRSV
+};
+
+static void calculate_tsc_tweak()
{
tsc_tweak = base_hz / tsc_hz;
}
-static void
-dump_nhm_platform_info(void)
+void prewake_cstate_probe(unsigned int family, unsigned int model);
+
+static void dump_nhm_platform_info(void)
{
unsigned long long msr;
unsigned int ratio;
@@ -2076,22 +2431,23 @@ dump_nhm_platform_info(void)
fprintf(outf, "cpu%d: MSR_PLATFORM_INFO: 0x%08llx\n", base_cpu, msr);
ratio = (msr >> 40) & 0xFF;
- fprintf(outf, "%d * %.1f = %.1f MHz max efficiency frequency\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max efficiency frequency\n", ratio, bclk, ratio * bclk);
ratio = (msr >> 8) & 0xFF;
- fprintf(outf, "%d * %.1f = %.1f MHz base frequency\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz base frequency\n", ratio, bclk, ratio * bclk);
get_msr(base_cpu, MSR_IA32_POWER_CTL, &msr);
fprintf(outf, "cpu%d: MSR_IA32_POWER_CTL: 0x%08llx (C1E auto-promotion: %sabled)\n",
base_cpu, msr, msr & 0x2 ? "EN" : "DIS");
+ /* C-state Pre-wake Disable (CSTATE_PREWAKE_DISABLE) */
+ if (dis_cstate_prewake)
+ fprintf(outf, "C-state Pre-wake: %sabled\n", msr & 0x40000000 ? "DIS" : "EN");
+
return;
}
-static void
-dump_hsw_turbo_ratio_limits(void)
+static void dump_hsw_turbo_ratio_limits(void)
{
unsigned long long msr;
unsigned int ratio;
@@ -2102,18 +2458,15 @@ dump_hsw_turbo_ratio_limits(void)
ratio = (msr >> 8) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo 18 active cores\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 18 active cores\n", ratio, bclk, ratio * bclk);
ratio = (msr >> 0) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo 17 active cores\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 17 active cores\n", ratio, bclk, ratio * bclk);
return;
}
-static void
-dump_ivt_turbo_ratio_limits(void)
+static void dump_ivt_turbo_ratio_limits(void)
{
unsigned long long msr;
unsigned int ratio;
@@ -2124,68 +2477,68 @@ dump_ivt_turbo_ratio_limits(void)
ratio = (msr >> 56) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo 16 active cores\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 16 active cores\n", ratio, bclk, ratio * bclk);
ratio = (msr >> 48) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo 15 active cores\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 15 active cores\n", ratio, bclk, ratio * bclk);
ratio = (msr >> 40) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo 14 active cores\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 14 active cores\n", ratio, bclk, ratio * bclk);
ratio = (msr >> 32) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo 13 active cores\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 13 active cores\n", ratio, bclk, ratio * bclk);
ratio = (msr >> 24) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo 12 active cores\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 12 active cores\n", ratio, bclk, ratio * bclk);
ratio = (msr >> 16) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo 11 active cores\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 11 active cores\n", ratio, bclk, ratio * bclk);
ratio = (msr >> 8) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo 10 active cores\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 10 active cores\n", ratio, bclk, ratio * bclk);
ratio = (msr >> 0) & 0xFF;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo 9 active cores\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 9 active cores\n", ratio, bclk, ratio * bclk);
return;
}
+
int has_turbo_ratio_group_limits(int family, int model)
{
if (!genuine_intel)
return 0;
+ if (family != 6)
+ return 0;
+
switch (model) {
case INTEL_FAM6_ATOM_GOLDMONT:
case INTEL_FAM6_SKYLAKE_X:
+ case INTEL_FAM6_ICELAKE_X:
+ case INTEL_FAM6_SAPPHIRERAPIDS_X:
case INTEL_FAM6_ATOM_GOLDMONT_D:
+ case INTEL_FAM6_ATOM_TREMONT_D:
return 1;
+ default:
+ return 0;
}
- return 0;
}
-static void
-dump_turbo_ratio_limits(int family, int model)
+static void dump_turbo_ratio_limits(int trl_msr_offset, int family, int model)
{
unsigned long long msr, core_counts;
- unsigned int ratio, group_size;
+ int shift;
- get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr);
- fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", base_cpu, msr);
+ get_msr(base_cpu, trl_msr_offset, &msr);
+ fprintf(outf, "cpu%d: MSR_%sTURBO_RATIO_LIMIT: 0x%08llx\n",
+ base_cpu, trl_msr_offset == MSR_SECONDARY_TURBO_RATIO_LIMIT ? "SECONDARY" : "", msr);
if (has_turbo_ratio_group_limits(family, model)) {
get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT1, &core_counts);
@@ -2194,58 +2547,20 @@ dump_turbo_ratio_limits(int family, int model)
core_counts = 0x0807060504030201;
}
- ratio = (msr >> 56) & 0xFF;
- group_size = (core_counts >> 56) & 0xFF;
- if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
- ratio, bclk, ratio * bclk, group_size);
-
- ratio = (msr >> 48) & 0xFF;
- group_size = (core_counts >> 48) & 0xFF;
- if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
- ratio, bclk, ratio * bclk, group_size);
-
- ratio = (msr >> 40) & 0xFF;
- group_size = (core_counts >> 40) & 0xFF;
- if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
- ratio, bclk, ratio * bclk, group_size);
-
- ratio = (msr >> 32) & 0xFF;
- group_size = (core_counts >> 32) & 0xFF;
- if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
- ratio, bclk, ratio * bclk, group_size);
-
- ratio = (msr >> 24) & 0xFF;
- group_size = (core_counts >> 24) & 0xFF;
- if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
- ratio, bclk, ratio * bclk, group_size);
-
- ratio = (msr >> 16) & 0xFF;
- group_size = (core_counts >> 16) & 0xFF;
- if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
- ratio, bclk, ratio * bclk, group_size);
+ for (shift = 56; shift >= 0; shift -= 8) {
+ unsigned int ratio, group_size;
- ratio = (msr >> 8) & 0xFF;
- group_size = (core_counts >> 8) & 0xFF;
- if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
- ratio, bclk, ratio * bclk, group_size);
+ ratio = (msr >> shift) & 0xFF;
+ group_size = (core_counts >> shift) & 0xFF;
+ if (ratio)
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
+ ratio, bclk, ratio * bclk, group_size);
+ }
- ratio = (msr >> 0) & 0xFF;
- group_size = (core_counts >> 0) & 0xFF;
- if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo %d active cores\n",
- ratio, bclk, ratio * bclk, group_size);
return;
}
-static void
-dump_atom_turbo_ratio_limits(void)
+static void dump_atom_turbo_ratio_limits(void)
{
unsigned long long msr;
unsigned int ratio;
@@ -2255,45 +2570,37 @@ dump_atom_turbo_ratio_limits(void)
ratio = (msr >> 0) & 0x3F;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz minimum operating frequency\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz minimum operating frequency\n", ratio, bclk, ratio * bclk);
ratio = (msr >> 8) & 0x3F;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz low frequency mode (LFM)\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz low frequency mode (LFM)\n", ratio, bclk, ratio * bclk);
ratio = (msr >> 16) & 0x3F;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz base frequency\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz base frequency\n", ratio, bclk, ratio * bclk);
get_msr(base_cpu, MSR_ATOM_CORE_TURBO_RATIOS, &msr);
fprintf(outf, "cpu%d: MSR_ATOM_CORE_TURBO_RATIOS: 0x%08llx\n", base_cpu, msr & 0xFFFFFFFF);
ratio = (msr >> 24) & 0x3F;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo 4 active cores\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 4 active cores\n", ratio, bclk, ratio * bclk);
ratio = (msr >> 16) & 0x3F;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo 3 active cores\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 3 active cores\n", ratio, bclk, ratio * bclk);
ratio = (msr >> 8) & 0x3F;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo 2 active cores\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 2 active cores\n", ratio, bclk, ratio * bclk);
ratio = (msr >> 0) & 0x3F;
if (ratio)
- fprintf(outf, "%d * %.1f = %.1f MHz max turbo 1 active core\n",
- ratio, bclk, ratio * bclk);
+ fprintf(outf, "%d * %.1f = %.1f MHz max turbo 1 active core\n", ratio, bclk, ratio * bclk);
}
-static void
-dump_knl_turbo_ratio_limits(void)
+static void dump_knl_turbo_ratio_limits(void)
{
const unsigned int buckets_no = 7;
@@ -2305,10 +2612,9 @@ dump_knl_turbo_ratio_limits(void)
get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr);
- fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n",
- base_cpu, msr);
+ fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", base_cpu, msr);
- /**
+ /*
* Turbo encoding in KNL is as follows:
* [0] -- Reserved
* [7:1] -- Base value of number of active cores of bucket 1.
@@ -2351,8 +2657,7 @@ dump_knl_turbo_ratio_limits(void)
ratio[i], bclk, ratio[i] * bclk, cores[i]);
}
-static void
-dump_nhm_cst_cfg(void)
+static void dump_nhm_cst_cfg(void)
{
unsigned long long msr;
@@ -2365,14 +2670,11 @@ dump_nhm_cst_cfg(void)
(msr & SNB_C1_AUTO_UNDEMOTE) ? "UNdemote-C1, " : "",
(msr & NHM_C3_AUTO_DEMOTE) ? "demote-C3, " : "",
(msr & NHM_C1_AUTO_DEMOTE) ? "demote-C1, " : "",
- (msr & (1 << 15)) ? "" : "UN",
- (unsigned int)msr & 0xF,
- pkg_cstate_limit_strings[pkg_cstate_limit]);
+ (msr & (1 << 15)) ? "" : "UN", (unsigned int)msr & 0xF, pkg_cstate_limit_strings[pkg_cstate_limit]);
#define AUTOMATIC_CSTATE_CONVERSION (1UL << 16)
if (has_automatic_cstate_conversion) {
- fprintf(outf, ", automatic c-state conversion=%s",
- (msr & AUTOMATIC_CSTATE_CONVERSION) ? "on" : "off");
+ fprintf(outf, ", automatic c-state conversion=%s", (msr & AUTOMATIC_CSTATE_CONVERSION) ? "on" : "off");
}
fprintf(outf, ")\n");
@@ -2380,8 +2682,7 @@ dump_nhm_cst_cfg(void)
return;
}
-static void
-dump_config_tdp(void)
+static void dump_config_tdp(void)
{
unsigned long long msr;
@@ -2423,7 +2724,7 @@ dump_config_tdp(void)
fprintf(outf, ")\n");
}
-unsigned int irtl_time_units[] = {1, 32, 1024, 32768, 1048576, 33554432, 0, 0 };
+unsigned int irtl_time_units[] = { 1, 32, 1024, 32768, 1048576, 33554432, 0, 0 };
void print_irtl(void)
{
@@ -2463,6 +2764,7 @@ void print_irtl(void)
(msr & 0x3FF) * irtl_time_units[(msr >> 10) & 0x3]);
}
+
void free_fd_percpu(void)
{
int i;
@@ -2519,7 +2821,6 @@ void free_all_buffers(void)
free(cpus);
}
-
/*
* Parse a file containing a single int.
* Return 0 if file can not be opened
@@ -2594,8 +2895,7 @@ void set_node_data(void)
* the logical_node_id
*/
for (cpux = cpu; cpux <= topo.max_cpu_num; cpux++) {
- if ((cpus[cpux].physical_package_id == pkg) &&
- (cpus[cpux].physical_node_id == node)) {
+ if ((cpus[cpux].physical_package_id == pkg) && (cpus[cpux].physical_node_id == node)) {
cpus[cpux].logical_node_id = lnode;
cpu_count++;
}
@@ -2617,8 +2917,7 @@ int get_physical_node_id(struct cpu_topology *thiscpu)
int cpu = thiscpu->logical_cpu_id;
for (i = 0; i <= topo.max_cpu_num; i++) {
- sprintf(path, "/sys/devices/system/cpu/cpu%d/node%i/cpulist",
- cpu, i);
+ sprintf(path, "/sys/devices/system/cpu/cpu%d/node%i/cpulist", cpu, i);
filep = fopen(path, "r");
if (!filep)
continue;
@@ -2648,9 +2947,13 @@ int get_thread_siblings(struct cpu_topology *thiscpu)
size = CPU_ALLOC_SIZE((topo.max_cpu_num + 1));
CPU_ZERO_S(size, thiscpu->put_ids);
- sprintf(path,
- "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", cpu);
- filep = fopen_or_die(path, "r");
+ sprintf(path, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", cpu);
+ filep = fopen(path, "r");
+
+ if (!filep) {
+ warnx("%s: open failed", path);
+ return -1;
+ }
do {
offset -= BITMASK_SIZE;
if (fscanf(filep, "%lx%c", &map, &character) != 2)
@@ -2661,14 +2964,12 @@ int get_thread_siblings(struct cpu_topology *thiscpu)
sib_core = get_core_id(so);
if (sib_core == thiscpu->physical_core_id) {
CPU_SET_S(so, size, thiscpu->put_ids);
- if ((so != cpu) &&
- (cpus[so].thread_id < 0))
- cpus[so].thread_id =
- thread_id++;
+ if ((so != cpu) && (cpus[so].thread_id < 0))
+ cpus[so].thread_id = thread_id++;
}
}
}
- } while (!strncmp(&character, ",", 1));
+ } while (character == ',');
fclose(filep);
return CPU_COUNT_S(size, thiscpu->put_ids);
@@ -2679,41 +2980,31 @@ int get_thread_siblings(struct cpu_topology *thiscpu)
* skip non-present cpus
*/
-int for_all_cpus_2(int (func)(struct thread_data *, struct core_data *,
- struct pkg_data *, struct thread_data *, struct core_data *,
- struct pkg_data *), struct thread_data *thread_base,
- struct core_data *core_base, struct pkg_data *pkg_base,
- struct thread_data *thread_base2, struct core_data *core_base2,
- struct pkg_data *pkg_base2)
+int for_all_cpus_2(int (func) (struct thread_data *, struct core_data *,
+ struct pkg_data *, struct thread_data *, struct core_data *,
+ struct pkg_data *), struct thread_data *thread_base,
+ struct core_data *core_base, struct pkg_data *pkg_base,
+ struct thread_data *thread_base2, struct core_data *core_base2, struct pkg_data *pkg_base2)
{
int retval, pkg_no, node_no, core_no, thread_no;
for (pkg_no = 0; pkg_no < topo.num_packages; ++pkg_no) {
for (node_no = 0; node_no < topo.nodes_per_pkg; ++node_no) {
- for (core_no = 0; core_no < topo.cores_per_node;
- ++core_no) {
- for (thread_no = 0; thread_no <
- topo.threads_per_core; ++thread_no) {
+ for (core_no = 0; core_no < topo.cores_per_node; ++core_no) {
+ for (thread_no = 0; thread_no < topo.threads_per_core; ++thread_no) {
struct thread_data *t, *t2;
struct core_data *c, *c2;
struct pkg_data *p, *p2;
- t = GET_THREAD(thread_base, thread_no,
- core_no, node_no,
- pkg_no);
+ t = GET_THREAD(thread_base, thread_no, core_no, node_no, pkg_no);
if (cpu_is_not_present(t->cpu_id))
continue;
- t2 = GET_THREAD(thread_base2, thread_no,
- core_no, node_no,
- pkg_no);
+ t2 = GET_THREAD(thread_base2, thread_no, core_no, node_no, pkg_no);
- c = GET_CORE(core_base, core_no,
- node_no, pkg_no);
- c2 = GET_CORE(core_base2, core_no,
- node_no,
- pkg_no);
+ c = GET_CORE(core_base, core_no, node_no, pkg_no);
+ c2 = GET_CORE(core_base2, core_no, node_no, pkg_no);
p = GET_PKG(pkg_base, pkg_no);
p2 = GET_PKG(pkg_base2, pkg_no);
@@ -2732,7 +3023,7 @@ int for_all_cpus_2(int (func)(struct thread_data *, struct core_data *,
* run func(cpu) on every cpu in /proc/stat
* return max_cpu number
*/
-int for_all_proc_cpus(int (func)(int))
+int for_all_proc_cpus(int (func) (int))
{
FILE *fp;
int cpu_num;
@@ -2752,7 +3043,7 @@ int for_all_proc_cpus(int (func)(int))
retval = func(cpu_num);
if (retval) {
fclose(fp);
- return(retval);
+ return (retval);
}
}
fclose(fp);
@@ -2763,22 +3054,27 @@ void re_initialize(void)
{
free_all_buffers();
setup_all_buffers();
- printf("turbostat: re-initialized with num_cpus %d\n", topo.num_cpus);
+ fprintf(outf, "turbostat: re-initialized with num_cpus %d\n", topo.num_cpus);
}
void set_max_cpu_num(void)
{
FILE *filep;
+ int base_cpu;
unsigned long dummy;
+ char pathname[64];
+ base_cpu = sched_getcpu();
+ if (base_cpu < 0)
+ err(1, "cannot find calling cpu ID");
+ sprintf(pathname, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings", base_cpu);
+
+ filep = fopen_or_die(pathname, "r");
topo.max_cpu_num = 0;
- filep = fopen_or_die(
- "/sys/devices/system/cpu/cpu0/topology/thread_siblings",
- "r");
while (fscanf(filep, "%lx,", &dummy) == 1)
topo.max_cpu_num += BITMASK_SIZE;
fclose(filep);
- topo.max_cpu_num--; /* 0 based */
+ topo.max_cpu_num--; /* 0 based */
}
/*
@@ -2787,9 +3083,12 @@ void set_max_cpu_num(void)
*/
int count_cpus(int cpu)
{
+ UNUSED(cpu);
+
topo.num_cpus++;
return 0;
}
+
int mark_cpu_present(int cpu)
{
CPU_SET_S(cpu, cpu_present_setsize, cpu_present_set);
@@ -2859,12 +3158,12 @@ int snapshot_proc_interrupts(void)
}
- while (getc(fp) != '\n')
- ; /* flush interrupt description */
+ while (getc(fp) != '\n') ; /* flush interrupt description */
}
return 0;
}
+
/*
* snapshot_gfx_rc6_ms()
*
@@ -2888,6 +3187,7 @@ int snapshot_gfx_rc6_ms(void)
return 0;
}
+
/*
* snapshot_gfx_mhz()
*
@@ -2916,6 +3216,33 @@ int snapshot_gfx_mhz(void)
}
/*
+ * snapshot_gfx_cur_mhz()
+ *
+ * record snapshot of
+ * /sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz
+ *
+ * return 1 if config change requires a restart, else return 0
+ */
+int snapshot_gfx_act_mhz(void)
+{
+ static FILE *fp;
+ int retval;
+
+ if (fp == NULL)
+ fp = fopen_or_die("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", "r");
+ else {
+ rewind(fp);
+ fflush(fp);
+ }
+
+ retval = fscanf(fp, "%d", &gfx_act_mhz);
+ if (retval != 1)
+ err(1, "GFX ACT MHz");
+
+ return 0;
+}
+
+/*
* snapshot_cpu_lpi()
*
* record snapshot of
@@ -2940,6 +3267,7 @@ int snapshot_cpu_lpi_us(void)
return 0;
}
+
/*
* snapshot_sys_lpi()
*
@@ -2963,6 +3291,7 @@ int snapshot_sys_lpi_us(void)
return 0;
}
+
/*
* snapshot /proc and /sys files
*
@@ -2980,6 +3309,9 @@ int snapshot_proc_sysfs_files(void)
if (DO_BIC(BIC_GFXMHz))
snapshot_gfx_mhz();
+ if (DO_BIC(BIC_GFXACTMHz))
+ snapshot_gfx_act_mhz();
+
if (DO_BIC(BIC_CPU_LPI))
snapshot_cpu_lpi_us();
@@ -2991,7 +3323,7 @@ int snapshot_proc_sysfs_files(void)
int exit_requested;
-static void signal_handler (int signal)
+static void signal_handler(int signal)
{
switch (signal) {
case SIGINT:
@@ -3057,15 +3389,158 @@ void do_sleep(void)
}
}
+int get_msr_sum(int cpu, off_t offset, unsigned long long *msr)
+{
+ int ret, idx;
+ unsigned long long msr_cur, msr_last;
+
+ if (!per_cpu_msr_sum)
+ return 1;
+
+ idx = offset_to_idx(offset);
+ if (idx < 0)
+ return idx;
+ /* get_msr_sum() = sum + (get_msr() - last) */
+ ret = get_msr(cpu, offset, &msr_cur);
+ if (ret)
+ return ret;
+ msr_last = per_cpu_msr_sum[cpu].entries[idx].last;
+ DELTA_WRAP32(msr_cur, msr_last);
+ *msr = msr_last + per_cpu_msr_sum[cpu].entries[idx].sum;
+
+ return 0;
+}
+
+timer_t timerid;
+
+/* Timer callback, update the sum of MSRs periodically. */
+static int update_msr_sum(struct thread_data *t, struct core_data *c, struct pkg_data *p)
+{
+ int i, ret;
+ int cpu = t->cpu_id;
+
+ UNUSED(c);
+ UNUSED(p);
+
+ for (i = IDX_PKG_ENERGY; i < IDX_COUNT; i++) {
+ unsigned long long msr_cur, msr_last;
+ off_t offset;
+
+ if (!idx_valid(i))
+ continue;
+ offset = idx_to_offset(i);
+ if (offset < 0)
+ continue;
+ ret = get_msr(cpu, offset, &msr_cur);
+ if (ret) {
+ fprintf(outf, "Can not update msr(0x%llx)\n", (unsigned long long)offset);
+ continue;
+ }
+
+ msr_last = per_cpu_msr_sum[cpu].entries[i].last;
+ per_cpu_msr_sum[cpu].entries[i].last = msr_cur & 0xffffffff;
+
+ DELTA_WRAP32(msr_cur, msr_last);
+ per_cpu_msr_sum[cpu].entries[i].sum += msr_last;
+ }
+ return 0;
+}
+
+static void msr_record_handler(union sigval v)
+{
+ UNUSED(v);
+
+ for_all_cpus(update_msr_sum, EVEN_COUNTERS);
+}
+
+void msr_sum_record(void)
+{
+ struct itimerspec its;
+ struct sigevent sev;
+
+ per_cpu_msr_sum = calloc(topo.max_cpu_num + 1, sizeof(struct msr_sum_array));
+ if (!per_cpu_msr_sum) {
+ fprintf(outf, "Can not allocate memory for long time MSR.\n");
+ return;
+ }
+ /*
+ * Signal handler might be restricted, so use thread notifier instead.
+ */
+ memset(&sev, 0, sizeof(struct sigevent));
+ sev.sigev_notify = SIGEV_THREAD;
+ sev.sigev_notify_function = msr_record_handler;
+
+ sev.sigev_value.sival_ptr = &timerid;
+ if (timer_create(CLOCK_REALTIME, &sev, &timerid) == -1) {
+ fprintf(outf, "Can not create timer.\n");
+ goto release_msr;
+ }
+
+ its.it_value.tv_sec = 0;
+ its.it_value.tv_nsec = 1;
+ /*
+ * A wraparound time has been calculated early.
+ * Some sources state that the peak power for a
+ * microprocessor is usually 1.5 times the TDP rating,
+ * use 2 * TDP for safety.
+ */
+ its.it_interval.tv_sec = rapl_joule_counter_range / 2;
+ its.it_interval.tv_nsec = 0;
+
+ if (timer_settime(timerid, 0, &its, NULL) == -1) {
+ fprintf(outf, "Can not set timer.\n");
+ goto release_timer;
+ }
+ return;
+
+release_timer:
+ timer_delete(timerid);
+release_msr:
+ free(per_cpu_msr_sum);
+}
+
+/*
+ * set_my_sched_priority(pri)
+ * return previous
+ *
+ * if non-root, do this:
+ * # /sbin/setcap cap_sys_rawio,cap_sys_nice=+ep /usr/bin/turbostat
+ */
+int set_my_sched_priority(int priority)
+{
+ int retval;
+ int original_priority;
+
+ errno = 0;
+ original_priority = getpriority(PRIO_PROCESS, 0);
+ if (errno && (original_priority == -1))
+ err(errno, "getpriority");
+
+ retval = setpriority(PRIO_PROCESS, 0, priority);
+ if (retval)
+ err(retval, "setpriority(%d)", priority);
+
+ errno = 0;
+ retval = getpriority(PRIO_PROCESS, 0);
+ if (retval != priority)
+ err(retval, "getpriority(%d) != setpriority(%d)", retval, priority);
+
+ return original_priority;
+}
void turbostat_loop()
{
int retval;
int restarted = 0;
- int done_iters = 0;
+ unsigned int done_iters = 0;
setup_signal_handler();
+ /*
+ * elevate own priority for interval mode
+ */
+ set_my_sched_priority(-20);
+
restart:
restarted++;
@@ -3075,7 +3550,7 @@ restart:
if (retval < -1) {
exit(retval);
} else if (retval == -1) {
- if (restarted > 1) {
+ if (restarted > 10) {
exit(retval);
}
re_initialize();
@@ -3146,7 +3621,7 @@ void check_dev_msr()
sprintf(pathname, "/dev/cpu/%d/msr", base_cpu);
if (stat(pathname, &sb))
- if (system("/sbin/modprobe msr > /dev/null 2>&1"))
+ if (system("/sbin/modprobe msr > /dev/null 2>&1"))
err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" ");
}
@@ -3168,8 +3643,7 @@ int check_for_cap_sys_rawio(void)
err(-6, "cap_get\n");
if (cap_flag_value != CAP_SET) {
- warnx("capget(CAP_SYS_RAWIO) failed,"
- " try \"# setcap cap_sys_rawio=ep %s\"", progname);
+ warnx("capget(CAP_SYS_RAWIO) failed," " try \"# setcap cap_sys_rawio=ep %s\"", progname);
return 1;
}
@@ -3178,6 +3652,7 @@ int check_for_cap_sys_rawio(void)
return 0;
}
+
void check_permissions(void)
{
int do_exit = 0;
@@ -3260,11 +3735,17 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
has_misc_feature_control = 1;
break;
case INTEL_FAM6_SKYLAKE_X: /* SKX */
+ case INTEL_FAM6_SAPPHIRERAPIDS_X: /* SPR */
pkg_cstate_limits = skx_pkg_cstate_limits;
has_misc_feature_control = 1;
break;
+ case INTEL_FAM6_ICELAKE_X: /* ICX */
+ pkg_cstate_limits = icx_pkg_cstate_limits;
+ has_misc_feature_control = 1;
+ break;
case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */
no_MSR_MISC_PWR_MGMT = 1;
+ /* FALLTHRU */
case INTEL_FAM6_ATOM_SILVERMONT_D: /* AVN */
pkg_cstate_limits = slv_pkg_cstate_limits;
break;
@@ -3279,6 +3760,7 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */
case INTEL_FAM6_ATOM_TREMONT: /* EHL */
+ case INTEL_FAM6_ATOM_TREMONT_D: /* JVL */
pkg_cstate_limits = glm_pkg_cstate_limits;
break;
default:
@@ -3294,6 +3776,7 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
has_base_hz = 1;
return 1;
}
+
/*
* SLV client has support for unique MSRs:
*
@@ -3306,6 +3789,9 @@ int has_slv_msrs(unsigned int family, unsigned int model)
if (!genuine_intel)
return 0;
+ if (family != 6)
+ return 0;
+
switch (model) {
case INTEL_FAM6_ATOM_SILVERMONT:
case INTEL_FAM6_ATOM_SILVERMONT_MID:
@@ -3314,47 +3800,95 @@ int has_slv_msrs(unsigned int family, unsigned int model)
}
return 0;
}
+
int is_dnv(unsigned int family, unsigned int model)
{
if (!genuine_intel)
return 0;
+ if (family != 6)
+ return 0;
+
switch (model) {
case INTEL_FAM6_ATOM_GOLDMONT_D:
return 1;
}
return 0;
}
+
int is_bdx(unsigned int family, unsigned int model)
{
if (!genuine_intel)
return 0;
+ if (family != 6)
+ return 0;
+
switch (model) {
case INTEL_FAM6_BROADWELL_X:
return 1;
}
return 0;
}
+
int is_skx(unsigned int family, unsigned int model)
{
if (!genuine_intel)
return 0;
+ if (family != 6)
+ return 0;
+
switch (model) {
case INTEL_FAM6_SKYLAKE_X:
return 1;
}
return 0;
}
+
+int is_icx(unsigned int family, unsigned int model)
+{
+
+ if (!genuine_intel)
+ return 0;
+
+ if (family != 6)
+ return 0;
+
+ switch (model) {
+ case INTEL_FAM6_ICELAKE_X:
+ return 1;
+ }
+ return 0;
+}
+
+int is_spr(unsigned int family, unsigned int model)
+{
+
+ if (!genuine_intel)
+ return 0;
+
+ if (family != 6)
+ return 0;
+
+ switch (model) {
+ case INTEL_FAM6_SAPPHIRERAPIDS_X:
+ return 1;
+ }
+ return 0;
+}
+
int is_ehl(unsigned int family, unsigned int model)
{
if (!genuine_intel)
return 0;
+ if (family != 6)
+ return 0;
+
switch (model) {
case INTEL_FAM6_ATOM_TREMONT:
return 1;
@@ -3362,13 +3896,31 @@ int is_ehl(unsigned int family, unsigned int model)
return 0;
}
+int is_jvl(unsigned int family, unsigned int model)
+{
+ if (!genuine_intel)
+ return 0;
+
+ if (family != 6)
+ return 0;
+
+ switch (model) {
+ case INTEL_FAM6_ATOM_TREMONT_D:
+ return 1;
+ }
+ return 0;
+}
+
int has_turbo_ratio_limit(unsigned int family, unsigned int model)
{
if (has_slv_msrs(family, model))
return 0;
+ if (family != 6)
+ return 0;
+
switch (model) {
- /* Nehalem compatible, but do not include turbo-ratio limit support */
+ /* Nehalem compatible, but do not include turbo-ratio limit support */
case INTEL_FAM6_NEHALEM_EX: /* Nehalem-EX Xeon - Beckton */
case INTEL_FAM6_XEON_PHI_KNL: /* PHI - Knights Landing (different MSR definition) */
return 0;
@@ -3376,6 +3928,7 @@ int has_turbo_ratio_limit(unsigned int family, unsigned int model)
return 1;
}
}
+
int has_atom_turbo_ratio_limit(unsigned int family, unsigned int model)
{
if (has_slv_msrs(family, model))
@@ -3383,6 +3936,7 @@ int has_atom_turbo_ratio_limit(unsigned int family, unsigned int model)
return 0;
}
+
int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model)
{
if (!genuine_intel)
@@ -3399,6 +3953,7 @@ int has_ivt_turbo_ratio_limit(unsigned int family, unsigned int model)
return 0;
}
}
+
int has_hsw_turbo_ratio_limit(unsigned int family, unsigned int model)
{
if (!genuine_intel)
@@ -3430,6 +3985,7 @@ int has_knl_turbo_ratio_limit(unsigned int family, unsigned int model)
return 0;
}
}
+
int has_glm_turbo_ratio_limit(unsigned int family, unsigned int model)
{
if (!genuine_intel)
@@ -3441,11 +3997,14 @@ int has_glm_turbo_ratio_limit(unsigned int family, unsigned int model)
switch (model) {
case INTEL_FAM6_ATOM_GOLDMONT:
case INTEL_FAM6_SKYLAKE_X:
+ case INTEL_FAM6_ICELAKE_X:
+ case INTEL_FAM6_SAPPHIRERAPIDS_X:
return 1;
default:
return 0;
}
}
+
int has_config_tdp(unsigned int family, unsigned int model)
{
if (!genuine_intel)
@@ -3466,7 +4025,8 @@ int has_config_tdp(unsigned int family, unsigned int model)
case INTEL_FAM6_SKYLAKE_L: /* SKL */
case INTEL_FAM6_CANNONLAKE_L: /* CNL */
case INTEL_FAM6_SKYLAKE_X: /* SKX */
-
+ case INTEL_FAM6_ICELAKE_X: /* ICX */
+ case INTEL_FAM6_SAPPHIRERAPIDS_X: /* SPR */
case INTEL_FAM6_XEON_PHI_KNL: /* Knights Landing */
return 1;
default:
@@ -3474,13 +4034,57 @@ int has_config_tdp(unsigned int family, unsigned int model)
}
}
-static void
-dump_cstate_pstate_config_info(unsigned int family, unsigned int model)
+/*
+ * tcc_offset_bits:
+ * 0: Tcc Offset not supported (Default)
+ * 6: Bit 29:24 of MSR_PLATFORM_INFO
+ * 4: Bit 27:24 of MSR_PLATFORM_INFO
+ */
+void check_tcc_offset(int model)
{
- if (!do_nhm_platform_info)
+ unsigned long long msr;
+
+ if (!genuine_intel)
return;
- dump_nhm_platform_info();
+ switch (model) {
+ case INTEL_FAM6_SKYLAKE_L:
+ case INTEL_FAM6_SKYLAKE:
+ case INTEL_FAM6_KABYLAKE_L:
+ case INTEL_FAM6_KABYLAKE:
+ case INTEL_FAM6_ICELAKE_L:
+ case INTEL_FAM6_ICELAKE:
+ case INTEL_FAM6_TIGERLAKE_L:
+ case INTEL_FAM6_TIGERLAKE:
+ case INTEL_FAM6_COMETLAKE:
+ if (!get_msr(base_cpu, MSR_PLATFORM_INFO, &msr)) {
+ msr = (msr >> 30) & 1;
+ if (msr)
+ tcc_offset_bits = 6;
+ }
+ return;
+ default:
+ return;
+ }
+}
+
+static void remove_underbar(char *s)
+{
+ char *to = s;
+
+ while (*s) {
+ if (*s != '_')
+ *to++ = *s;
+ s++;
+ }
+
+ *to = 0;
+}
+
+static void dump_turbo_ratio_info(unsigned int family, unsigned int model)
+{
+ if (!has_turbo)
+ return;
if (has_hsw_turbo_ratio_limit(family, model))
dump_hsw_turbo_ratio_limits();
@@ -3488,8 +4092,12 @@ dump_cstate_pstate_config_info(unsigned int family, unsigned int model)
if (has_ivt_turbo_ratio_limit(family, model))
dump_ivt_turbo_ratio_limits();
- if (has_turbo_ratio_limit(family, model))
- dump_turbo_ratio_limits(family, model);
+ if (has_turbo_ratio_limit(family, model)) {
+ dump_turbo_ratio_limits(MSR_TURBO_RATIO_LIMIT, family, model);
+
+ if (is_hybrid)
+ dump_turbo_ratio_limits(MSR_SECONDARY_TURBO_RATIO_LIMIT, family, model);
+ }
if (has_atom_turbo_ratio_limit(family, model))
dump_atom_turbo_ratio_limits();
@@ -3499,10 +4107,36 @@ dump_cstate_pstate_config_info(unsigned int family, unsigned int model)
if (has_config_tdp(family, model))
dump_config_tdp();
+}
+static void dump_cstate_pstate_config_info(unsigned int family, unsigned int model)
+{
+ if (!do_nhm_platform_info)
+ return;
+
+ dump_nhm_platform_info();
+ dump_turbo_ratio_info(family, model);
dump_nhm_cst_cfg();
}
+static int read_sysfs_int(char *path)
+{
+ FILE *input;
+ int retval = -1;
+
+ input = fopen(path, "r");
+ if (input == NULL) {
+ if (debug)
+ fprintf(outf, "NSFOD %s\n", path);
+ return (-1);
+ }
+ if (fscanf(input, "%d", &retval) != 1)
+ err(1, "%s: failed to read int from file", path);
+ fclose(input);
+
+ return (retval);
+}
+
static void dump_sysfs_file(char *path)
{
FILE *input;
@@ -3520,8 +4154,50 @@ static void dump_sysfs_file(char *path)
fprintf(outf, "%s: %s", strrchr(path, '/') + 1, cpuidle_buf);
}
-static void
-dump_sysfs_cstate_config(void)
+
+static void intel_uncore_frequency_probe(void)
+{
+ int i, j;
+ char path[128];
+
+ if (!genuine_intel)
+ return;
+
+ if (access("/sys/devices/system/cpu/intel_uncore_frequency/package_00_die_00", R_OK))
+ return;
+
+ if (!access("/sys/devices/system/cpu/intel_uncore_frequency/package_00_die_00/current_freq_khz", R_OK))
+ BIC_PRESENT(BIC_UNCORE_MHZ);
+
+ if (quiet)
+ return;
+
+ for (i = 0; i < topo.num_packages; ++i) {
+ for (j = 0; j < topo.num_die; ++j) {
+ int k, l;
+
+ sprintf(path, "/sys/devices/system/cpu/intel_uncore_frequency/package_0%d_die_0%d/min_freq_khz",
+ i, j);
+ k = read_sysfs_int(path);
+ sprintf(path, "/sys/devices/system/cpu/intel_uncore_frequency/package_0%d_die_0%d/max_freq_khz",
+ i, j);
+ l = read_sysfs_int(path);
+ fprintf(outf, "Uncore Frequency pkg%d die%d: %d - %d MHz ", i, j, k / 1000, l / 1000);
+
+ sprintf(path,
+ "/sys/devices/system/cpu/intel_uncore_frequency/package_0%d_die_0%d/initial_min_freq_khz",
+ i, j);
+ k = read_sysfs_int(path);
+ sprintf(path,
+ "/sys/devices/system/cpu/intel_uncore_frequency/package_0%d_die_0%d/initial_max_freq_khz",
+ i, j);
+ l = read_sysfs_int(path);
+ fprintf(outf, "(%d - %d MHz)\n", k / 1000, l / 1000);
+ }
+ }
+}
+
+static void dump_sysfs_cstate_config(void)
{
char path[64];
char name_buf[16];
@@ -3530,9 +4206,6 @@ dump_sysfs_cstate_config(void)
int state;
char *sp;
- if (!DO_BIC(BIC_sysfs))
- return;
-
if (access("/sys/devices/system/cpu/cpuidle", R_OK)) {
fprintf(outf, "cpuidle not loaded\n");
return;
@@ -3544,23 +4217,23 @@ dump_sysfs_cstate_config(void)
for (state = 0; state < 10; ++state) {
- sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name",
- base_cpu, state);
+ sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name", base_cpu, state);
input = fopen(path, "r");
if (input == NULL)
continue;
if (!fgets(name_buf, sizeof(name_buf), input))
err(1, "%s: failed to read file", path);
- /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */
+ /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */
sp = strchr(name_buf, '-');
if (!sp)
sp = strchrnul(name_buf, '\n');
*sp = '\0';
fclose(input);
- sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/desc",
- base_cpu, state);
+ remove_underbar(name_buf);
+
+ sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/desc", base_cpu, state);
input = fopen(path, "r");
if (input == NULL)
continue;
@@ -3571,8 +4244,8 @@ dump_sysfs_cstate_config(void)
fclose(input);
}
}
-static void
-dump_sysfs_pstate_config(void)
+
+static void dump_sysfs_pstate_config(void)
{
char path[64];
char driver_buf[64];
@@ -3580,8 +4253,7 @@ dump_sysfs_pstate_config(void)
FILE *input;
int turbo;
- sprintf(path, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_driver",
- base_cpu);
+ sprintf(path, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_driver", base_cpu);
input = fopen(path, "r");
if (input == NULL) {
fprintf(outf, "NSFOD %s\n", path);
@@ -3591,8 +4263,7 @@ dump_sysfs_pstate_config(void)
err(1, "%s: failed to read file", path);
fclose(input);
- sprintf(path, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor",
- base_cpu);
+ sprintf(path, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor", base_cpu);
input = fopen(path, "r");
if (input == NULL) {
fprintf(outf, "NSFOD %s\n", path);
@@ -3624,16 +4295,17 @@ dump_sysfs_pstate_config(void)
}
}
-
/*
* print_epb()
* Decode the ENERGY_PERF_BIAS MSR
*/
int print_epb(struct thread_data *t, struct core_data *c, struct pkg_data *p)
{
- unsigned long long msr;
char *epb_string;
- int cpu;
+ int cpu, epb;
+
+ UNUSED(c);
+ UNUSED(p);
if (!has_epb)
return 0;
@@ -3645,14 +4317,15 @@ int print_epb(struct thread_data *t, struct core_data *c, struct pkg_data *p)
return 0;
if (cpu_migrate(cpu)) {
- fprintf(outf, "Could not migrate to CPU %d\n", cpu);
+ fprintf(outf, "print_epb: Could not migrate to CPU %d\n", cpu);
return -1;
}
- if (get_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, &msr))
+ epb = get_epb(cpu);
+ if (epb < 0)
return 0;
- switch (msr & 0xF) {
+ switch (epb) {
case ENERGY_PERF_BIAS_PERFORMANCE:
epb_string = "performance";
break;
@@ -3666,10 +4339,11 @@ int print_epb(struct thread_data *t, struct core_data *c, struct pkg_data *p)
epb_string = "custom";
break;
}
- fprintf(outf, "cpu%d: MSR_IA32_ENERGY_PERF_BIAS: 0x%08llx (%s)\n", cpu, msr, epb_string);
+ fprintf(outf, "cpu%d: EPB: %d (%s)\n", cpu, epb, epb_string);
return 0;
}
+
/*
* print_hwp()
* Decode the MSR_HWP_CAPABILITIES
@@ -3679,6 +4353,9 @@ int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p)
unsigned long long msr;
int cpu;
+ UNUSED(c);
+ UNUSED(p);
+
if (!has_hwp)
return 0;
@@ -3689,15 +4366,14 @@ int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p)
return 0;
if (cpu_migrate(cpu)) {
- fprintf(outf, "Could not migrate to CPU %d\n", cpu);
+ fprintf(outf, "print_hwp: Could not migrate to CPU %d\n", cpu);
return -1;
}
if (get_msr(cpu, MSR_PM_ENABLE, &msr))
return 0;
- fprintf(outf, "cpu%d: MSR_PM_ENABLE: 0x%08llx (%sHWP)\n",
- cpu, msr, (msr & (1 << 0)) ? "" : "No-");
+ fprintf(outf, "cpu%d: MSR_PM_ENABLE: 0x%08llx (%sHWP)\n", cpu, msr, (msr & (1 << 0)) ? "" : "No-");
/* MSR_PM_ENABLE[1] == 1 if HWP is enabled and MSRs visible */
if ((msr & (1 << 0)) == 0)
@@ -3707,25 +4383,23 @@ int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p)
return 0;
fprintf(outf, "cpu%d: MSR_HWP_CAPABILITIES: 0x%08llx "
- "(high %d guar %d eff %d low %d)\n",
- cpu, msr,
- (unsigned int)HWP_HIGHEST_PERF(msr),
- (unsigned int)HWP_GUARANTEED_PERF(msr),
- (unsigned int)HWP_MOSTEFFICIENT_PERF(msr),
- (unsigned int)HWP_LOWEST_PERF(msr));
+ "(high %d guar %d eff %d low %d)\n",
+ cpu, msr,
+ (unsigned int)HWP_HIGHEST_PERF(msr),
+ (unsigned int)HWP_GUARANTEED_PERF(msr),
+ (unsigned int)HWP_MOSTEFFICIENT_PERF(msr), (unsigned int)HWP_LOWEST_PERF(msr));
if (get_msr(cpu, MSR_HWP_REQUEST, &msr))
return 0;
fprintf(outf, "cpu%d: MSR_HWP_REQUEST: 0x%08llx "
- "(min %d max %d des %d epp 0x%x window 0x%x pkg 0x%x)\n",
- cpu, msr,
- (unsigned int)(((msr) >> 0) & 0xff),
- (unsigned int)(((msr) >> 8) & 0xff),
- (unsigned int)(((msr) >> 16) & 0xff),
- (unsigned int)(((msr) >> 24) & 0xff),
- (unsigned int)(((msr) >> 32) & 0xff3),
- (unsigned int)(((msr) >> 42) & 0x1));
+ "(min %d max %d des %d epp 0x%x window 0x%x pkg 0x%x)\n",
+ cpu, msr,
+ (unsigned int)(((msr) >> 0) & 0xff),
+ (unsigned int)(((msr) >> 8) & 0xff),
+ (unsigned int)(((msr) >> 16) & 0xff),
+ (unsigned int)(((msr) >> 24) & 0xff),
+ (unsigned int)(((msr) >> 32) & 0xff3), (unsigned int)(((msr) >> 42) & 0x1));
if (has_hwp_pkg) {
if (get_msr(cpu, MSR_HWP_REQUEST_PKG, &msr))
@@ -3737,8 +4411,7 @@ int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p)
(unsigned int)(((msr) >> 0) & 0xff),
(unsigned int)(((msr) >> 8) & 0xff),
(unsigned int)(((msr) >> 16) & 0xff),
- (unsigned int)(((msr) >> 24) & 0xff),
- (unsigned int)(((msr) >> 32) & 0xff3));
+ (unsigned int)(((msr) >> 24) & 0xff), (unsigned int)(((msr) >> 32) & 0xff3));
}
if (has_hwp_notify) {
if (get_msr(cpu, MSR_HWP_INTERRUPT, &msr))
@@ -3746,18 +4419,14 @@ int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p)
fprintf(outf, "cpu%d: MSR_HWP_INTERRUPT: 0x%08llx "
"(%s_Guaranteed_Perf_Change, %s_Excursion_Min)\n",
- cpu, msr,
- ((msr) & 0x1) ? "EN" : "Dis",
- ((msr) & 0x2) ? "EN" : "Dis");
+ cpu, msr, ((msr) & 0x1) ? "EN" : "Dis", ((msr) & 0x2) ? "EN" : "Dis");
}
if (get_msr(cpu, MSR_HWP_STATUS, &msr))
return 0;
fprintf(outf, "cpu%d: MSR_HWP_STATUS: 0x%08llx "
- "(%sGuaranteed_Perf_Change, %sExcursion_Min)\n",
- cpu, msr,
- ((msr) & 0x1) ? "" : "No-",
- ((msr) & 0x2) ? "" : "No-");
+ "(%sGuaranteed_Perf_Change, %sExcursion_Min)\n",
+ cpu, msr, ((msr) & 0x1) ? "" : "No-", ((msr) & 0x2) ? "" : "No-");
return 0;
}
@@ -3770,6 +4439,9 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data
unsigned long long msr;
int cpu;
+ UNUSED(c);
+ UNUSED(p);
+
cpu = t->cpu_id;
/* per-package */
@@ -3777,7 +4449,7 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data
return 0;
if (cpu_migrate(cpu)) {
- fprintf(outf, "Could not migrate to CPU %d\n", cpu);
+ fprintf(outf, "print_perf_limit: Could not migrate to CPU %d\n", cpu);
return -1;
}
@@ -3797,8 +4469,7 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data
(msr & 1 << 5) ? "Auto-HWP, " : "",
(msr & 1 << 4) ? "Graphics, " : "",
(msr & 1 << 2) ? "bit2, " : "",
- (msr & 1 << 1) ? "ThermStatus, " : "",
- (msr & 1 << 0) ? "PROCHOT, " : "");
+ (msr & 1 << 1) ? "ThermStatus, " : "", (msr & 1 << 0) ? "PROCHOT, " : "");
fprintf(outf, " (Logged: %s%s%s%s%s%s%s%s%s%s%s%s%s%s)\n",
(msr & 1 << 31) ? "bit31, " : "",
(msr & 1 << 30) ? "bit30, " : "",
@@ -3812,8 +4483,7 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data
(msr & 1 << 21) ? "Auto-HWP, " : "",
(msr & 1 << 20) ? "Graphics, " : "",
(msr & 1 << 18) ? "bit18, " : "",
- (msr & 1 << 17) ? "ThermStatus, " : "",
- (msr & 1 << 16) ? "PROCHOT, " : "");
+ (msr & 1 << 17) ? "ThermStatus, " : "", (msr & 1 << 16) ? "PROCHOT, " : "");
}
if (do_gfx_perf_limit_reasons) {
@@ -3826,8 +4496,7 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data
(msr & 1 << 6) ? "VR-Therm, " : "",
(msr & 1 << 8) ? "Amps, " : "",
(msr & 1 << 9) ? "GFXPwr, " : "",
- (msr & 1 << 10) ? "PkgPwrL1, " : "",
- (msr & 1 << 11) ? "PkgPwrL2, " : "");
+ (msr & 1 << 10) ? "PkgPwrL1, " : "", (msr & 1 << 11) ? "PkgPwrL2, " : "");
fprintf(outf, " (Logged: %s%s%s%s%s%s%s%s)\n",
(msr & 1 << 16) ? "PROCHOT, " : "",
(msr & 1 << 17) ? "ThermStatus, " : "",
@@ -3835,8 +4504,7 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data
(msr & 1 << 22) ? "VR-Therm, " : "",
(msr & 1 << 24) ? "Amps, " : "",
(msr & 1 << 25) ? "GFXPwr, " : "",
- (msr & 1 << 26) ? "PkgPwrL1, " : "",
- (msr & 1 << 27) ? "PkgPwrL2, " : "");
+ (msr & 1 << 26) ? "PkgPwrL1, " : "", (msr & 1 << 27) ? "PkgPwrL2, " : "");
}
if (do_ring_perf_limit_reasons) {
get_msr(cpu, MSR_RING_PERF_LIMIT_REASONS, &msr);
@@ -3846,21 +4514,19 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data
(msr & 1 << 1) ? "ThermStatus, " : "",
(msr & 1 << 6) ? "VR-Therm, " : "",
(msr & 1 << 8) ? "Amps, " : "",
- (msr & 1 << 10) ? "PkgPwrL1, " : "",
- (msr & 1 << 11) ? "PkgPwrL2, " : "");
+ (msr & 1 << 10) ? "PkgPwrL1, " : "", (msr & 1 << 11) ? "PkgPwrL2, " : "");
fprintf(outf, " (Logged: %s%s%s%s%s%s)\n",
(msr & 1 << 16) ? "PROCHOT, " : "",
(msr & 1 << 17) ? "ThermStatus, " : "",
(msr & 1 << 22) ? "VR-Therm, " : "",
(msr & 1 << 24) ? "Amps, " : "",
- (msr & 1 << 26) ? "PkgPwrL1, " : "",
- (msr & 1 << 27) ? "PkgPwrL2, " : "");
+ (msr & 1 << 26) ? "PkgPwrL1, " : "", (msr & 1 << 27) ? "PkgPwrL2, " : "");
}
return 0;
}
#define RAPL_POWER_GRANULARITY 0x7FFF /* 15 bit power granularity */
-#define RAPL_TIME_GRANULARITY 0x3F /* 6 bit time granularity */
+#define RAPL_TIME_GRANULARITY 0x3F /* 6 bit time granularity */
double get_tdp_intel(unsigned int model)
{
@@ -3881,28 +4547,26 @@ double get_tdp_intel(unsigned int model)
double get_tdp_amd(unsigned int family)
{
- switch (family) {
- case 0x17:
- case 0x18:
- default:
- /* This is the max stock TDP of HEDT/Server Fam17h chips */
- return 250.0;
- }
+ UNUSED(family);
+
+ /* This is the max stock TDP of HEDT/Server Fam17h+ chips */
+ return 280.0;
}
/*
* rapl_dram_energy_units_probe()
* Energy units are either hard-coded, or come from RAPL Energy Unit MSR.
*/
-static double
-rapl_dram_energy_units_probe(int model, double rapl_energy_units)
+static double rapl_dram_energy_units_probe(int model, double rapl_energy_units)
{
/* only called for genuine_intel, family 6 */
switch (model) {
case INTEL_FAM6_HASWELL_X: /* HSX */
case INTEL_FAM6_BROADWELL_X: /* BDX */
+ case INTEL_FAM6_SKYLAKE_X: /* SKX */
case INTEL_FAM6_XEON_PHI_KNL: /* KNL */
+ case INTEL_FAM6_ICELAKE_X: /* ICX */
return (rapl_dram_energy_units = 15.3 / 1000000);
default:
return (rapl_energy_units);
@@ -3946,7 +4610,9 @@ void rapl_probe_intel(unsigned int family, unsigned int model)
BIC_PRESENT(BIC_PkgWatt);
break;
case INTEL_FAM6_ATOM_TREMONT: /* EHL */
- do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_GFX | RAPL_PKG_POWER_INFO;
+ do_rapl =
+ RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS
+ | RAPL_GFX | RAPL_PKG_POWER_INFO;
if (rapl_joules) {
BIC_PRESENT(BIC_Pkg_J);
BIC_PRESENT(BIC_Cor_J);
@@ -3959,9 +4625,19 @@ void rapl_probe_intel(unsigned int family, unsigned int model)
BIC_PRESENT(BIC_GFXWatt);
}
break;
+ case INTEL_FAM6_ATOM_TREMONT_D: /* JVL */
+ do_rapl = RAPL_PKG | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO;
+ BIC_PRESENT(BIC_PKG__);
+ if (rapl_joules)
+ BIC_PRESENT(BIC_Pkg_J);
+ else
+ BIC_PRESENT(BIC_PkgWatt);
+ break;
case INTEL_FAM6_SKYLAKE_L: /* SKL */
case INTEL_FAM6_CANNONLAKE_L: /* CNL */
- do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_GFX | RAPL_PKG_POWER_INFO;
+ do_rapl =
+ RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS
+ | RAPL_GFX | RAPL_PKG_POWER_INFO;
BIC_PRESENT(BIC_PKG__);
BIC_PRESENT(BIC_RAM__);
if (rapl_joules) {
@@ -3979,8 +4655,12 @@ void rapl_probe_intel(unsigned int family, unsigned int model)
case INTEL_FAM6_HASWELL_X: /* HSX */
case INTEL_FAM6_BROADWELL_X: /* BDX */
case INTEL_FAM6_SKYLAKE_X: /* SKX */
+ case INTEL_FAM6_ICELAKE_X: /* ICX */
+ case INTEL_FAM6_SAPPHIRERAPIDS_X: /* SPR */
case INTEL_FAM6_XEON_PHI_KNL: /* KNL */
- do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO;
+ do_rapl =
+ RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS |
+ RAPL_PKG_POWER_INFO;
BIC_PRESENT(BIC_PKG__);
BIC_PRESENT(BIC_RAM__);
if (rapl_joules) {
@@ -3993,7 +4673,9 @@ void rapl_probe_intel(unsigned int family, unsigned int model)
break;
case INTEL_FAM6_SANDYBRIDGE_X:
case INTEL_FAM6_IVYBRIDGE_X:
- do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_PKG_PERF_STATUS | RAPL_DRAM_PERF_STATUS | RAPL_PKG_POWER_INFO;
+ do_rapl =
+ RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_PKG_PERF_STATUS |
+ RAPL_DRAM_PERF_STATUS | RAPL_PKG_POWER_INFO;
BIC_PRESENT(BIC_PKG__);
BIC_PRESENT(BIC_RAM__);
if (rapl_joules) {
@@ -4018,7 +4700,9 @@ void rapl_probe_intel(unsigned int family, unsigned int model)
}
break;
case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */
- do_rapl = RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO | RAPL_CORES_ENERGY_STATUS;
+ do_rapl =
+ RAPL_PKG | RAPL_DRAM | RAPL_DRAM_POWER_INFO | RAPL_DRAM_PERF_STATUS | RAPL_PKG_PERF_STATUS |
+ RAPL_PKG_POWER_INFO | RAPL_CORES_ENERGY_STATUS;
BIC_PRESENT(BIC_PKG__);
BIC_PRESENT(BIC_RAM__);
if (rapl_joules) {
@@ -4067,29 +4751,24 @@ void rapl_probe_amd(unsigned int family, unsigned int model)
unsigned int has_rapl = 0;
double tdp;
+ UNUSED(model);
+
if (max_extended_level >= 0x80000007) {
__cpuid(0x80000007, eax, ebx, ecx, edx);
- /* RAPL (Fam 17h) */
+ /* RAPL (Fam 17h+) */
has_rapl = edx & (1 << 14);
}
- if (!has_rapl)
+ if (!has_rapl || family < 0x17)
return;
- switch (family) {
- case 0x17: /* Zen, Zen+ */
- case 0x18: /* Hygon Dhyana */
- do_rapl = RAPL_AMD_F17H | RAPL_PER_CORE_ENERGY;
- if (rapl_joules) {
- BIC_PRESENT(BIC_Pkg_J);
- BIC_PRESENT(BIC_Cor_J);
- } else {
- BIC_PRESENT(BIC_PkgWatt);
- BIC_PRESENT(BIC_CorWatt);
- }
- break;
- default:
- return;
+ do_rapl = RAPL_AMD_F17H | RAPL_PER_CORE_ENERGY;
+ if (rapl_joules) {
+ BIC_PRESENT(BIC_Pkg_J);
+ BIC_PRESENT(BIC_Cor_J);
+ } else {
+ BIC_PRESENT(BIC_PkgWatt);
+ BIC_PRESENT(BIC_CorWatt);
}
if (get_msr(base_cpu, MSR_RAPL_PWR_UNIT, &msr))
@@ -4132,6 +4811,7 @@ void perf_limit_reasons_probe(unsigned int family, unsigned int model)
case INTEL_FAM6_HASWELL_L: /* HSW */
case INTEL_FAM6_HASWELL_G: /* HSW */
do_gfx_perf_limit_reasons = 1;
+ /* FALLTHRU */
case INTEL_FAM6_HASWELL_X: /* HSX */
do_core_perf_limit_reasons = 1;
do_ring_perf_limit_reasons = 1;
@@ -4142,8 +4822,20 @@ void perf_limit_reasons_probe(unsigned int family, unsigned int model)
void automatic_cstate_conversion_probe(unsigned int family, unsigned int model)
{
- if (is_skx(family, model) || is_bdx(family, model))
+ if (family != 6)
+ return;
+
+ switch (model) {
+ case INTEL_FAM6_BROADWELL_X:
+ case INTEL_FAM6_SKYLAKE_X:
has_automatic_cstate_conversion = 1;
+ }
+}
+
+void prewake_cstate_probe(unsigned int family, unsigned int model)
+{
+ if (is_icx(family, model) || is_spr(family, model))
+ dis_cstate_prewake = 1;
}
int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p)
@@ -4152,6 +4844,9 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p
unsigned int dts, dts2;
int cpu;
+ UNUSED(c);
+ UNUSED(p);
+
if (!(do_dts || do_ptm))
return 0;
@@ -4162,7 +4857,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p
return 0;
if (cpu_migrate(cpu)) {
- fprintf(outf, "Could not migrate to CPU %d\n", cpu);
+ fprintf(outf, "print_thermal: Could not migrate to CPU %d\n", cpu);
return -1;
}
@@ -4171,8 +4866,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p
return 0;
dts = (msr >> 16) & 0x7F;
- fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_STATUS: 0x%08llx (%d C)\n",
- cpu, msr, tcc_activation_temp - dts);
+ fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_STATUS: 0x%08llx (%d C)\n", cpu, msr, tj_max - dts);
if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_INTERRUPT, &msr))
return 0;
@@ -4180,10 +4874,9 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p
dts = (msr >> 16) & 0x7F;
dts2 = (msr >> 8) & 0x7F;
fprintf(outf, "cpu%d: MSR_IA32_PACKAGE_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n",
- cpu, msr, tcc_activation_temp - dts, tcc_activation_temp - dts2);
+ cpu, msr, tj_max - dts, tj_max - dts2);
}
-
if (do_dts && debug) {
unsigned int resolution;
@@ -4193,7 +4886,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p
dts = (msr >> 16) & 0x7F;
resolution = (msr >> 27) & 0xF;
fprintf(outf, "cpu%d: MSR_IA32_THERM_STATUS: 0x%08llx (%d C +/- %d)\n",
- cpu, msr, tcc_activation_temp - dts, resolution);
+ cpu, msr, tj_max - dts, resolution);
if (get_msr(cpu, MSR_IA32_THERM_INTERRUPT, &msr))
return 0;
@@ -4201,7 +4894,7 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p
dts = (msr >> 16) & 0x7F;
dts2 = (msr >> 8) & 0x7F;
fprintf(outf, "cpu%d: MSR_IA32_THERM_INTERRUPT: 0x%08llx (%d C, %d C)\n",
- cpu, msr, tcc_activation_temp - dts, tcc_activation_temp - dts2);
+ cpu, msr, tj_max - dts, tj_max - dts2);
}
return 0;
@@ -4209,11 +4902,11 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p
void print_power_limit_msr(int cpu, unsigned long long msr, char *label)
{
- fprintf(outf, "cpu%d: %s: %sabled (%f Watts, %f sec, clamp %sabled)\n",
+ fprintf(outf, "cpu%d: %s: %sabled (%0.3f Watts, %f sec, clamp %sabled)\n",
cpu, label,
((msr >> 15) & 1) ? "EN" : "DIS",
((msr >> 0) & 0x7FFF) * rapl_power_units,
- (1.0 + (((msr >> 22) & 0x3)/4.0)) * (1 << ((msr >> 17) & 0x1F)) * rapl_time_units,
+ (1.0 + (((msr >> 22) & 0x3) / 4.0)) * (1 << ((msr >> 17) & 0x1F)) * rapl_time_units,
(((msr >> 16) & 1) ? "EN" : "DIS"));
return;
@@ -4225,6 +4918,9 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
const char *msr_name;
int cpu;
+ UNUSED(c);
+ UNUSED(p);
+
if (!do_rapl)
return 0;
@@ -4234,7 +4930,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
cpu = t->cpu_id;
if (cpu_migrate(cpu)) {
- fprintf(outf, "Could not migrate to CPU %d\n", cpu);
+ fprintf(outf, "print_rapl: Could not migrate to CPU %d\n", cpu);
return -1;
}
@@ -4254,12 +4950,11 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (do_rapl & RAPL_PKG_POWER_INFO) {
if (get_msr(cpu, MSR_PKG_POWER_INFO, &msr))
- return -5;
-
+ return -5;
fprintf(outf, "cpu%d: MSR_PKG_POWER_INFO: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n",
cpu, msr,
- ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units,
+ ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units,
((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units,
((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units,
((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units);
@@ -4274,21 +4969,28 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
cpu, msr, (msr >> 63) & 1 ? "" : "UN");
print_power_limit_msr(cpu, msr, "PKG Limit #1");
- fprintf(outf, "cpu%d: PKG Limit #2: %sabled (%f Watts, %f* sec, clamp %sabled)\n",
+ fprintf(outf, "cpu%d: PKG Limit #2: %sabled (%0.3f Watts, %f* sec, clamp %sabled)\n",
cpu,
((msr >> 47) & 1) ? "EN" : "DIS",
((msr >> 32) & 0x7FFF) * rapl_power_units,
- (1.0 + (((msr >> 54) & 0x3)/4.0)) * (1 << ((msr >> 49) & 0x1F)) * rapl_time_units,
+ (1.0 + (((msr >> 54) & 0x3) / 4.0)) * (1 << ((msr >> 49) & 0x1F)) * rapl_time_units,
((msr >> 48) & 1) ? "EN" : "DIS");
+
+ if (get_msr(cpu, MSR_VR_CURRENT_CONFIG, &msr))
+ return -9;
+
+ fprintf(outf, "cpu%d: MSR_VR_CURRENT_CONFIG: 0x%08llx\n", cpu, msr);
+ fprintf(outf, "cpu%d: PKG Limit #4: %f Watts (%slocked)\n",
+ cpu, ((msr >> 0) & 0x1FFF) * rapl_power_units, (msr >> 31) & 1 ? "" : "UN");
}
if (do_rapl & RAPL_DRAM_POWER_INFO) {
if (get_msr(cpu, MSR_DRAM_POWER_INFO, &msr))
- return -6;
+ return -6;
fprintf(outf, "cpu%d: MSR_DRAM_POWER_INFO,: 0x%08llx (%.0f W TDP, RAPL %.0f - %.0f W, %f sec.)\n",
cpu, msr,
- ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units,
+ ((msr >> 0) & RAPL_POWER_GRANULARITY) * rapl_power_units,
((msr >> 16) & RAPL_POWER_GRANULARITY) * rapl_power_units,
((msr >> 32) & RAPL_POWER_GRANULARITY) * rapl_power_units,
((msr >> 48) & RAPL_TIME_GRANULARITY) * rapl_time_units);
@@ -4297,7 +4999,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (get_msr(cpu, MSR_DRAM_POWER_LIMIT, &msr))
return -9;
fprintf(outf, "cpu%d: MSR_DRAM_POWER_LIMIT: 0x%08llx (%slocked)\n",
- cpu, msr, (msr >> 31) & 1 ? "" : "UN");
+ cpu, msr, (msr >> 31) & 1 ? "" : "UN");
print_power_limit_msr(cpu, msr, "DRAM Limit");
}
@@ -4311,7 +5013,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (get_msr(cpu, MSR_PP0_POWER_LIMIT, &msr))
return -9;
fprintf(outf, "cpu%d: MSR_PP0_POWER_LIMIT: 0x%08llx (%slocked)\n",
- cpu, msr, (msr >> 31) & 1 ? "" : "UN");
+ cpu, msr, (msr >> 31) & 1 ? "" : "UN");
print_power_limit_msr(cpu, msr, "Cores Limit");
}
if (do_rapl & RAPL_GFX) {
@@ -4323,7 +5025,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p)
if (get_msr(cpu, MSR_PP1_POWER_LIMIT, &msr))
return -9;
fprintf(outf, "cpu%d: MSR_PP1_POWER_LIMIT: 0x%08llx (%slocked)\n",
- cpu, msr, (msr >> 31) & 1 ? "" : "UN");
+ cpu, msr, (msr >> 31) & 1 ? "" : "UN");
print_power_limit_msr(cpu, msr, "GFX Limit");
}
return 0;
@@ -4342,25 +5044,31 @@ int has_snb_msrs(unsigned int family, unsigned int model)
if (!genuine_intel)
return 0;
+ if (family != 6)
+ return 0;
+
switch (model) {
case INTEL_FAM6_SANDYBRIDGE:
case INTEL_FAM6_SANDYBRIDGE_X:
- case INTEL_FAM6_IVYBRIDGE: /* IVB */
- case INTEL_FAM6_IVYBRIDGE_X: /* IVB Xeon */
- case INTEL_FAM6_HASWELL: /* HSW */
- case INTEL_FAM6_HASWELL_X: /* HSW */
- case INTEL_FAM6_HASWELL_L: /* HSW */
- case INTEL_FAM6_HASWELL_G: /* HSW */
- case INTEL_FAM6_BROADWELL: /* BDW */
- case INTEL_FAM6_BROADWELL_G: /* BDW */
- case INTEL_FAM6_BROADWELL_X: /* BDX */
- case INTEL_FAM6_SKYLAKE_L: /* SKL */
- case INTEL_FAM6_CANNONLAKE_L: /* CNL */
- case INTEL_FAM6_SKYLAKE_X: /* SKX */
- case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
+ case INTEL_FAM6_IVYBRIDGE: /* IVB */
+ case INTEL_FAM6_IVYBRIDGE_X: /* IVB Xeon */
+ case INTEL_FAM6_HASWELL: /* HSW */
+ case INTEL_FAM6_HASWELL_X: /* HSW */
+ case INTEL_FAM6_HASWELL_L: /* HSW */
+ case INTEL_FAM6_HASWELL_G: /* HSW */
+ case INTEL_FAM6_BROADWELL: /* BDW */
+ case INTEL_FAM6_BROADWELL_G: /* BDW */
+ case INTEL_FAM6_BROADWELL_X: /* BDX */
+ case INTEL_FAM6_SKYLAKE_L: /* SKL */
+ case INTEL_FAM6_CANNONLAKE_L: /* CNL */
+ case INTEL_FAM6_SKYLAKE_X: /* SKX */
+ case INTEL_FAM6_ICELAKE_X: /* ICX */
+ case INTEL_FAM6_SAPPHIRERAPIDS_X: /* SPR */
+ case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */
- case INTEL_FAM6_ATOM_TREMONT: /* EHL */
+ case INTEL_FAM6_ATOM_TREMONT: /* EHL */
+ case INTEL_FAM6_ATOM_TREMONT_D: /* JVL */
return 1;
}
return 0;
@@ -4383,6 +5091,9 @@ int has_c8910_msrs(unsigned int family, unsigned int model)
if (!genuine_intel)
return 0;
+ if (family != 6)
+ return 0;
+
switch (model) {
case INTEL_FAM6_HASWELL_L: /* HSW */
case INTEL_FAM6_BROADWELL: /* BDW */
@@ -4409,6 +5120,9 @@ int has_skl_msrs(unsigned int family, unsigned int model)
if (!genuine_intel)
return 0;
+ if (family != 6)
+ return 0;
+
switch (model) {
case INTEL_FAM6_SKYLAKE_L: /* SKL */
case INTEL_FAM6_CANNONLAKE_L: /* CNL */
@@ -4421,6 +5135,10 @@ int is_slm(unsigned int family, unsigned int model)
{
if (!genuine_intel)
return 0;
+
+ if (family != 6)
+ return 0;
+
switch (model) {
case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */
case INTEL_FAM6_ATOM_SILVERMONT_D: /* AVN */
@@ -4433,6 +5151,10 @@ int is_knl(unsigned int family, unsigned int model)
{
if (!genuine_intel)
return 0;
+
+ if (family != 6)
+ return 0;
+
switch (model) {
case INTEL_FAM6_XEON_PHI_KNL: /* KNL */
return 1;
@@ -4445,8 +5167,11 @@ int is_cnl(unsigned int family, unsigned int model)
if (!genuine_intel)
return 0;
+ if (family != 6)
+ return 0;
+
switch (model) {
- case INTEL_FAM6_CANNONLAKE_L: /* CNL */
+ case INTEL_FAM6_CANNONLAKE_L: /* CNL */
return 1;
}
@@ -4461,7 +5186,7 @@ unsigned int get_aperf_mperf_multiplier(unsigned int family, unsigned int model)
}
#define SLM_BCLK_FREQS 5
-double slm_freq_table[SLM_BCLK_FREQS] = { 83.3, 100.0, 133.3, 116.7, 80.0};
+double slm_freq_table[SLM_BCLK_FREQS] = { 83.3, 100.0, 133.3, 116.7, 80.0 };
double slm_bclk(void)
{
@@ -4495,6 +5220,31 @@ double discover_bclk(unsigned int family, unsigned int model)
return 133.33;
}
+int get_cpu_type(struct thread_data *t, struct core_data *c, struct pkg_data *p)
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ UNUSED(c);
+ UNUSED(p);
+
+ if (!genuine_intel)
+ return 0;
+
+ if (cpu_migrate(t->cpu_id)) {
+ fprintf(outf, "Could not migrate to CPU %d\n", t->cpu_id);
+ return -1;
+ }
+
+ if (max_level < 0x1a)
+ return 0;
+
+ __cpuid(0x1a, eax, ebx, ecx, edx);
+ eax = (eax >> 24) & 0xFF;
+ if (eax == 0x20)
+ t->is_atom = true;
+ return 0;
+}
+
/*
* MSR_IA32_TEMPERATURE_TARGET indicates the temperature where
* the Thermal Control Circuit (TCC) activates.
@@ -4510,10 +5260,13 @@ double discover_bclk(unsigned int family, unsigned int model)
int set_temperature_target(struct thread_data *t, struct core_data *c, struct pkg_data *p)
{
unsigned long long msr;
- unsigned int target_c_local;
+ unsigned int tcc_default, tcc_offset;
int cpu;
- /* tcc_activation_temp is used only for dts or ptm */
+ UNUSED(c);
+ UNUSED(p);
+
+ /* tj_max is used only for dts or ptm */
if (!(do_dts || do_ptm))
return 0;
@@ -4527,10 +5280,9 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk
return -1;
}
- if (tcc_activation_temp_override != 0) {
- tcc_activation_temp = tcc_activation_temp_override;
- fprintf(outf, "cpu%d: Using cmdline TCC Target (%d C)\n",
- cpu, tcc_activation_temp);
+ if (tj_max_override != 0) {
+ tj_max = tj_max_override;
+ fprintf(outf, "cpu%d: Using cmdline TCC Target (%d C)\n", cpu, tj_max);
return 0;
}
@@ -4541,23 +5293,36 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk
if (get_msr(base_cpu, MSR_IA32_TEMPERATURE_TARGET, &msr))
goto guess;
- target_c_local = (msr >> 16) & 0xFF;
+ tcc_default = (msr >> 16) & 0xFF;
- if (!quiet)
- fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n",
- cpu, msr, target_c_local);
+ if (!quiet) {
+ switch (tcc_offset_bits) {
+ case 4:
+ tcc_offset = (msr >> 24) & 0xF;
+ fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C) (%d default - %d offset)\n",
+ cpu, msr, tcc_default - tcc_offset, tcc_default, tcc_offset);
+ break;
+ case 6:
+ tcc_offset = (msr >> 24) & 0x3F;
+ fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C) (%d default - %d offset)\n",
+ cpu, msr, tcc_default - tcc_offset, tcc_default, tcc_offset);
+ break;
+ default:
+ fprintf(outf, "cpu%d: MSR_IA32_TEMPERATURE_TARGET: 0x%08llx (%d C)\n", cpu, msr, tcc_default);
+ break;
+ }
+ }
- if (!target_c_local)
+ if (!tcc_default)
goto guess;
- tcc_activation_temp = target_c_local;
+ tj_max = tcc_default;
return 0;
guess:
- tcc_activation_temp = TJMAX_DEFAULT;
- fprintf(outf, "cpu%d: Guessing tjMax %d C, Please use -T to specify\n",
- cpu, tcc_activation_temp);
+ tj_max = TJMAX_DEFAULT;
+ fprintf(outf, "cpu%d: Guessing tjMax %d C, Please use -T to specify\n", cpu, tj_max);
return 0;
}
@@ -4568,9 +5333,7 @@ void decode_feature_control_msr(void)
if (!get_msr(base_cpu, MSR_IA32_FEAT_CTL, &msr))
fprintf(outf, "cpu%d: MSR_IA32_FEATURE_CONTROL: 0x%08llx (%sLocked %s)\n",
- base_cpu, msr,
- msr & FEAT_CTL_LOCKED ? "" : "UN-",
- msr & (1 << 18) ? "SGX" : "");
+ base_cpu, msr, msr & FEAT_CTL_LOCKED ? "" : "UN-", msr & (1 << 18) ? "SGX" : "");
}
void decode_misc_enable_msr(void)
@@ -4598,13 +5361,12 @@ void decode_misc_feature_control(void)
return;
if (!get_msr(base_cpu, MSR_MISC_FEATURE_CONTROL, &msr))
- fprintf(outf, "cpu%d: MSR_MISC_FEATURE_CONTROL: 0x%08llx (%sL2-Prefetch %sL2-Prefetch-pair %sL1-Prefetch %sL1-IP-Prefetch)\n",
- base_cpu, msr,
- msr & (0 << 0) ? "No-" : "",
- msr & (1 << 0) ? "No-" : "",
- msr & (2 << 0) ? "No-" : "",
- msr & (3 << 0) ? "No-" : "");
+ fprintf(outf,
+ "cpu%d: MSR_MISC_FEATURE_CONTROL: 0x%08llx (%sL2-Prefetch %sL2-Prefetch-pair %sL1-Prefetch %sL1-IP-Prefetch)\n",
+ base_cpu, msr, msr & (0 << 0) ? "No-" : "", msr & (1 << 0) ? "No-" : "",
+ msr & (2 << 0) ? "No-" : "", msr & (3 << 0) ? "No-" : "");
}
+
/*
* Decode MSR_MISC_PWR_MGMT
*
@@ -4625,10 +5387,9 @@ void decode_misc_pwr_mgmt_msr(void)
if (!get_msr(base_cpu, MSR_MISC_PWR_MGMT, &msr))
fprintf(outf, "cpu%d: MSR_MISC_PWR_MGMT: 0x%08llx (%sable-EIST_Coordination %sable-EPB %sable-OOB)\n",
base_cpu, msr,
- msr & (1 << 0) ? "DIS" : "EN",
- msr & (1 << 1) ? "EN" : "DIS",
- msr & (1 << 8) ? "EN" : "DIS");
+ msr & (1 << 0) ? "DIS" : "EN", msr & (1 << 1) ? "EN" : "DIS", msr & (1 << 8) ? "EN" : "DIS");
}
+
/*
* Decode MSR_CC6_DEMOTION_POLICY_CONFIG, MSR_MC6_DEMOTION_POLICY_CONFIG
*
@@ -4654,10 +5415,10 @@ void decode_c6_demotion_policy_msr(void)
unsigned int intel_model_duplicates(unsigned int model)
{
- switch(model) {
+ switch (model) {
case INTEL_FAM6_NEHALEM_EP: /* Core i7, Xeon 5500 series - Bloomfield, Gainstown NHM-EP */
case INTEL_FAM6_NEHALEM: /* Core i7 and i5 Processor - Clarksfield, Lynnfield, Jasper Forest */
- case 0x1F: /* Core i7 and i5 Processor - Nehalem */
+ case 0x1F: /* Core i7 and i5 Processor - Nehalem */
case INTEL_FAM6_WESTMERE: /* Westmere Client - Clarkdale, Arrandale */
case INTEL_FAM6_WESTMERE_EP: /* Westmere EP - Gulftown */
return INTEL_FAM6_NEHALEM;
@@ -4685,24 +5446,75 @@ unsigned int intel_model_duplicates(unsigned int model)
case INTEL_FAM6_ICELAKE_NNPI:
case INTEL_FAM6_TIGERLAKE_L:
case INTEL_FAM6_TIGERLAKE:
+ case INTEL_FAM6_ROCKETLAKE:
+ case INTEL_FAM6_LAKEFIELD:
+ case INTEL_FAM6_ALDERLAKE:
+ case INTEL_FAM6_ALDERLAKE_L:
+ case INTEL_FAM6_ALDERLAKE_N:
+ case INTEL_FAM6_RAPTORLAKE:
+ case INTEL_FAM6_RAPTORLAKE_P:
+ case INTEL_FAM6_RAPTORLAKE_S:
+ case INTEL_FAM6_METEORLAKE:
+ case INTEL_FAM6_METEORLAKE_L:
return INTEL_FAM6_CANNONLAKE_L;
- case INTEL_FAM6_ATOM_TREMONT_D:
- return INTEL_FAM6_ATOM_GOLDMONT_D;
-
case INTEL_FAM6_ATOM_TREMONT_L:
return INTEL_FAM6_ATOM_TREMONT;
- case INTEL_FAM6_ICELAKE_X:
- return INTEL_FAM6_SKYLAKE_X;
+ case INTEL_FAM6_ICELAKE_D:
+ return INTEL_FAM6_ICELAKE_X;
}
return model;
}
+
+void print_dev_latency(void)
+{
+ char *path = "/dev/cpu_dma_latency";
+ int fd;
+ int value;
+ int retval;
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ warn("fopen %s\n", path);
+ return;
+ }
+
+ retval = read(fd, (void *)&value, sizeof(int));
+ if (retval != sizeof(int)) {
+ warn("read %s\n", path);
+ close(fd);
+ return;
+ }
+ fprintf(outf, "/dev/cpu_dma_latency: %d usec (%s)\n", value, value == 2000000000 ? "default" : "constrained");
+
+ close(fd);
+}
+
+/*
+ * Linux-perf manages the HW instructions-retired counter
+ * by enabling when requested, and hiding rollover
+ */
+void linux_perf_init(void)
+{
+ if (!BIC_IS_ENABLED(BIC_IPC))
+ return;
+
+ if (access("/proc/sys/kernel/perf_event_paranoid", F_OK))
+ return;
+
+ fd_instr_count_percpu = calloc(topo.max_cpu_num + 1, sizeof(int));
+ if (fd_instr_count_percpu == NULL)
+ err(-1, "calloc fd_instr_count_percpu");
+
+ BIC_PRESENT(BIC_IPC);
+}
+
void process_cpuid()
{
unsigned int eax, ebx, ecx, edx;
unsigned int fms, family, model, stepping, ecx_flags, edx_flags;
- unsigned int has_turbo;
+ unsigned long long ucode_patch = 0;
eax = ebx = ecx = edx = 0;
@@ -4716,8 +5528,8 @@ void process_cpuid()
hygon_genuine = 1;
if (!quiet)
- fprintf(outf, "CPUID(0): %.4s%.4s%.4s ",
- (char *)&ebx, (char *)&edx, (char *)&ecx);
+ fprintf(outf, "CPUID(0): %.4s%.4s%.4s 0x%x CPUID levels\n",
+ (char *)&ebx, (char *)&edx, (char *)&ecx, max_level);
__cpuid(1, fms, ebx, ecx, edx);
family = (fms >> 8) & 0xf;
@@ -4730,6 +5542,9 @@ void process_cpuid()
ecx_flags = ecx;
edx_flags = edx;
+ if (get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch))
+ warnx("get_msr(UCODE)\n");
+
/*
* check max extended function levels of CPUID.
* This is needed to check for invariant TSC.
@@ -4739,8 +5554,10 @@ void process_cpuid()
__cpuid(0x80000000, max_extended_level, ebx, ecx, edx);
if (!quiet) {
- fprintf(outf, "0x%x CPUID levels; 0x%x xlevels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n",
- max_level, max_extended_level, family, model, stepping, family, model, stepping);
+ fprintf(outf, "CPUID(1): family:model:stepping 0x%x:%x:%x (%d:%d:%d) microcode 0x%x\n",
+ family, model, stepping, family, model, stepping,
+ (unsigned int)((ucode_patch >> 32) & 0xFFFFFFFF));
+ fprintf(outf, "CPUID(0x80000000): max_extended_levels: 0x%x\n", max_extended_level);
fprintf(outf, "CPUID(1): %s %s %s %s %s %s %s %s %s %s\n",
ecx_flags & (1 << 0) ? "SSE3" : "-",
ecx_flags & (1 << 3) ? "MONITOR" : "-",
@@ -4750,11 +5567,12 @@ void process_cpuid()
edx_flags & (1 << 4) ? "TSC" : "-",
edx_flags & (1 << 5) ? "MSR" : "-",
edx_flags & (1 << 22) ? "ACPI-TM" : "-",
- edx_flags & (1 << 28) ? "HT" : "-",
- edx_flags & (1 << 29) ? "TM" : "-");
+ edx_flags & (1 << 28) ? "HT" : "-", edx_flags & (1 << 29) ? "TM" : "-");
}
- if (genuine_intel)
+ if (genuine_intel) {
+ model_orig = model;
model = intel_model_duplicates(model);
+ }
if (!(edx_flags & (1 << 5)))
errx(1, "CPUID: no MSR");
@@ -4805,14 +5623,11 @@ void process_cpuid()
has_hwp ? "" : "No-",
has_hwp_notify ? "" : "No-",
has_hwp_activity_window ? "" : "No-",
- has_hwp_epp ? "" : "No-",
- has_hwp_pkg ? "" : "No-",
- has_epb ? "" : "No-");
+ has_hwp_epp ? "" : "No-", has_hwp_pkg ? "" : "No-", has_epb ? "" : "No-");
if (!quiet)
decode_misc_enable_msr();
-
if (max_level >= 0x7 && !quiet) {
int has_sgx;
@@ -4821,7 +5636,10 @@ void process_cpuid()
__cpuid_count(0x7, 0, eax, ebx, ecx, edx);
has_sgx = ebx & (1 << 2);
- fprintf(outf, "CPUID(7): %sSGX\n", has_sgx ? "" : "No-");
+
+ is_hybrid = edx & (1 << 15);
+
+ fprintf(outf, "CPUID(7): %sSGX %sHybrid\n", has_sgx ? "" : "No-", is_hybrid ? "" : "No-");
if (has_sgx)
decode_feature_control_msr();
@@ -4844,7 +5662,7 @@ void process_cpuid()
eax_crystal, ebx_tsc, crystal_hz);
if (crystal_hz == 0)
- switch(model) {
+ switch (model) {
case INTEL_FAM6_SKYLAKE_L: /* SKL */
crystal_hz = 24000000; /* 24.0 MHz */
break;
@@ -4857,13 +5675,13 @@ void process_cpuid()
break;
default:
crystal_hz = 0;
- }
+ }
if (crystal_hz) {
- tsc_hz = (unsigned long long) crystal_hz * ebx_tsc / eax_crystal;
+ tsc_hz = (unsigned long long)crystal_hz *ebx_tsc / eax_crystal;
if (!quiet)
fprintf(outf, "TSC: %lld MHz (%d Hz * %d / %d / 1000000)\n",
- tsc_hz / 1000000, crystal_hz, ebx_tsc, eax_crystal);
+ tsc_hz / 1000000, crystal_hz, ebx_tsc, eax_crystal);
}
}
}
@@ -4916,6 +5734,14 @@ void process_cpuid()
BIC_PRESENT(BIC_Mod_c6);
use_c1_residency_msr = 1;
}
+ if (is_jvl(family, model)) {
+ BIC_NOT_PRESENT(BIC_CPU_c3);
+ BIC_NOT_PRESENT(BIC_CPU_c7);
+ BIC_NOT_PRESENT(BIC_Pkgpc2);
+ BIC_NOT_PRESENT(BIC_Pkgpc3);
+ BIC_NOT_PRESENT(BIC_Pkgpc6);
+ BIC_NOT_PRESENT(BIC_Pkgpc7);
+ }
if (is_dnv(family, model)) {
BIC_PRESENT(BIC_CPU_c1);
BIC_NOT_PRESENT(BIC_CPU_c3);
@@ -4924,7 +5750,7 @@ void process_cpuid()
BIC_NOT_PRESENT(BIC_Pkgpc7);
use_c1_residency_msr = 1;
}
- if (is_skx(family, model)) {
+ if (is_skx(family, model) || is_icx(family, model) || is_spr(family, model)) {
BIC_NOT_PRESENT(BIC_CPU_c3);
BIC_NOT_PRESENT(BIC_Pkgpc3);
BIC_NOT_PRESENT(BIC_CPU_c7);
@@ -4935,9 +5761,12 @@ void process_cpuid()
BIC_NOT_PRESENT(BIC_Pkgpc7);
}
if (has_c8910_msrs(family, model)) {
- BIC_PRESENT(BIC_Pkgpc8);
- BIC_PRESENT(BIC_Pkgpc9);
- BIC_PRESENT(BIC_Pkgpc10);
+ if (pkg_cstate_limit >= PCL__8)
+ BIC_PRESENT(BIC_Pkgpc8);
+ if (pkg_cstate_limit >= PCL__9)
+ BIC_PRESENT(BIC_Pkgpc9);
+ if (pkg_cstate_limit >= PCL_10)
+ BIC_PRESENT(BIC_Pkgpc10);
}
do_irtl_hsw = has_c8910_msrs(family, model);
if (has_skl_msrs(family, model)) {
@@ -4947,10 +5776,9 @@ void process_cpuid()
BIC_PRESENT(BIC_CPUGFX);
}
do_slm_cstates = is_slm(family, model);
- do_knl_cstates = is_knl(family, model);
+ do_knl_cstates = is_knl(family, model);
- if (do_slm_cstates || do_knl_cstates || is_cnl(family, model) ||
- is_ehl(family, model))
+ if (do_slm_cstates || do_knl_cstates || is_cnl(family, model) || is_ehl(family, model))
BIC_NOT_PRESENT(BIC_CPU_c3);
if (!quiet)
@@ -4963,15 +5791,20 @@ void process_cpuid()
perf_limit_reasons_probe(family, model);
automatic_cstate_conversion_probe(family, model);
+ check_tcc_offset(model_orig);
+
if (!quiet)
dump_cstate_pstate_config_info(family, model);
+ intel_uncore_frequency_probe();
if (!quiet)
+ print_dev_latency();
+ if (!quiet)
dump_sysfs_cstate_config();
if (!quiet)
dump_sysfs_pstate_config();
- if (has_skl_msrs(family, model))
+ if (has_skl_msrs(family, model) || is_ehl(family, model))
calculate_tsc_tweak();
if (!access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK))
@@ -4980,11 +5813,19 @@ void process_cpuid()
if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK))
BIC_PRESENT(BIC_GFXMHz);
+ if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", R_OK))
+ BIC_PRESENT(BIC_GFXACTMHz);
+
if (!access("/sys/devices/system/cpu/cpuidle/low_power_idle_cpu_residency_us", R_OK))
BIC_PRESENT(BIC_CPU_LPI);
else
BIC_NOT_PRESENT(BIC_CPU_LPI);
+ if (!access("/sys/devices/system/cpu/cpu0/thermal_throttle/core_throttle_count", R_OK))
+ BIC_PRESENT(BIC_CORE_THROT_CNT);
+ else
+ BIC_NOT_PRESENT(BIC_CORE_THROT_CNT);
+
if (!access(sys_lpi_file_sysfs, R_OK)) {
sys_lpi_file = sys_lpi_file_sysfs;
BIC_PRESENT(BIC_SYS_LPI);
@@ -5014,11 +5855,6 @@ int dir_filter(const struct dirent *dirp)
return 0;
}
-int open_dev_cpu_msr(int dummy1)
-{
- return 0;
-}
-
void topology_probe()
{
int i;
@@ -5037,7 +5873,7 @@ void topology_probe()
if (debug > 1)
fprintf(outf, "num_cpus %d max_cpu_num %d\n", topo.num_cpus, topo.max_cpu_num);
- cpus = calloc(1, (topo.max_cpu_num + 1) * sizeof(struct cpu_topology));
+ cpus = calloc(1, (topo.max_cpu_num + 1) * sizeof(struct cpu_topology));
if (cpus == NULL)
err(1, "calloc cpus");
@@ -5116,22 +5952,19 @@ void topology_probe()
topo.cores_per_node = max_core_id + 1;
if (debug > 1)
- fprintf(outf, "max_core_id %d, sizing for %d cores per package\n",
- max_core_id, topo.cores_per_node);
+ fprintf(outf, "max_core_id %d, sizing for %d cores per package\n", max_core_id, topo.cores_per_node);
if (!summary_only && topo.cores_per_node > 1)
BIC_PRESENT(BIC_Core);
topo.num_die = max_die_id + 1;
if (debug > 1)
- fprintf(outf, "max_die_id %d, sizing for %d die\n",
- max_die_id, topo.num_die);
+ fprintf(outf, "max_die_id %d, sizing for %d die\n", max_die_id, topo.num_die);
if (!summary_only && topo.num_die > 1)
BIC_PRESENT(BIC_Die);
topo.num_packages = max_package_id + 1;
if (debug > 1)
- fprintf(outf, "max_package_id %d, sizing for %d packages\n",
- max_package_id, topo.num_packages);
+ fprintf(outf, "max_package_id %d, sizing for %d packages\n", max_package_id, topo.num_packages);
if (!summary_only && topo.num_packages > 1)
BIC_PRESENT(BIC_Package);
@@ -5154,21 +5987,15 @@ void topology_probe()
fprintf(outf,
"cpu %d pkg %d die %d node %d lnode %d core %d thread %d\n",
i, cpus[i].physical_package_id, cpus[i].die_id,
- cpus[i].physical_node_id,
- cpus[i].logical_node_id,
- cpus[i].physical_core_id,
- cpus[i].thread_id);
+ cpus[i].physical_node_id, cpus[i].logical_node_id, cpus[i].physical_core_id, cpus[i].thread_id);
}
}
-void
-allocate_counters(struct thread_data **t, struct core_data **c,
- struct pkg_data **p)
+void allocate_counters(struct thread_data **t, struct core_data **c, struct pkg_data **p)
{
int i;
- int num_cores = topo.cores_per_node * topo.nodes_per_pkg *
- topo.num_packages;
+ int num_cores = topo.cores_per_node * topo.nodes_per_pkg * topo.num_packages;
int num_threads = topo.threads_per_core * num_cores;
*t = calloc(num_threads, sizeof(struct thread_data));
@@ -5196,13 +6023,13 @@ allocate_counters(struct thread_data **t, struct core_data **c,
error:
err(1, "calloc counters");
}
+
/*
* init_counter()
*
* set FIRST_THREAD_IN_CORE and FIRST_CORE_IN_PACKAGE
*/
-void init_counter(struct thread_data *thread_base, struct core_data *core_base,
- struct pkg_data *pkg_base, int cpu_id)
+void init_counter(struct thread_data *thread_base, struct core_data *core_base, struct pkg_data *pkg_base, int cpu_id)
{
int pkg_id = cpus[cpu_id].physical_package_id;
int node_id = cpus[cpu_id].logical_node_id;
@@ -5212,7 +6039,6 @@ void init_counter(struct thread_data *thread_base, struct core_data *core_base,
struct core_data *c;
struct pkg_data *p;
-
/* Workaround for systems where physical_node_id==-1
* and logical_node_id==(-1 - topo.num_cpus)
*/
@@ -5234,7 +6060,6 @@ void init_counter(struct thread_data *thread_base, struct core_data *core_base,
p->package_id = pkg_id;
}
-
int initialize_counters(int cpu_id)
{
init_counter(EVEN_COUNTERS, cpu_id);
@@ -5249,12 +6074,14 @@ void allocate_output_buffer()
if (outp == NULL)
err(-1, "calloc output buffer");
}
+
void allocate_fd_percpu(void)
{
fd_percpu = calloc(topo.max_cpu_num + 1, sizeof(int));
if (fd_percpu == NULL)
err(-1, "calloc fd_percpu");
}
+
void allocate_irq_buffers(void)
{
irq_column_2_cpu = calloc(topo.num_cpus, sizeof(int));
@@ -5265,6 +6092,7 @@ void allocate_irq_buffers(void)
if (irqs_per_cpu == NULL)
err(-1, "calloc %d", topo.max_cpu_num + 1);
}
+
void setup_all_buffers(void)
{
topology_probe();
@@ -5293,7 +6121,7 @@ void turbostat_init()
check_dev_msr();
check_permissions();
process_cpuid();
-
+ linux_perf_init();
if (!quiet)
for_all_cpus(print_hwp, ODD_COUNTERS);
@@ -5309,11 +6137,17 @@ void turbostat_init()
for_all_cpus(set_temperature_target, ODD_COUNTERS);
+ for_all_cpus(get_cpu_type, ODD_COUNTERS);
+ for_all_cpus(get_cpu_type, EVEN_COUNTERS);
+
if (!quiet)
for_all_cpus(print_thermal, ODD_COUNTERS);
if (!quiet && do_irtl_snb)
print_irtl();
+
+ if (DO_BIC(BIC_IPC))
+ (void)get_instr_count_fd(base_cpu);
}
int fork_it(char **argv)
@@ -5364,7 +6198,7 @@ int fork_it(char **argv)
format_all_counters(EVEN_COUNTERS);
}
- fprintf(outf, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec/1000000.0);
+ fprintf(outf, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec / 1000000.0);
flush_output_stderr();
@@ -5389,14 +6223,37 @@ int get_and_dump_counters(void)
return status;
}
-void print_version() {
- fprintf(outf, "turbostat version 20.03.20"
- " - Len Brown <lenb@kernel.org>\n");
+void print_version()
+{
+ fprintf(outf, "turbostat version 2022.10.04 - Len Brown <lenb@kernel.org>\n");
+}
+
+#define COMMAND_LINE_SIZE 2048
+
+void print_bootcmd(void)
+{
+ char bootcmd[COMMAND_LINE_SIZE];
+ FILE *fp;
+ int ret;
+
+ memset(bootcmd, 0, COMMAND_LINE_SIZE);
+ fp = fopen("/proc/cmdline", "r");
+ if (!fp)
+ return;
+
+ ret = fread(bootcmd, sizeof(char), COMMAND_LINE_SIZE - 1, fp);
+ if (ret) {
+ bootcmd[ret] = '\0';
+ /* the last character is already '\n' */
+ fprintf(outf, "Kernel command line: %s", bootcmd);
+ }
+
+ fclose(fp);
}
int add_counter(unsigned int msr_num, char *path, char *name,
- unsigned int width, enum counter_scope scope,
- enum counter_type type, enum counter_format format, int flags)
+ unsigned int width, enum counter_scope scope,
+ enum counter_type type, enum counter_format format, int flags)
{
struct msr_counter *msrp;
@@ -5422,8 +6279,7 @@ int add_counter(unsigned int msr_num, char *path, char *name,
sys.tp = msrp;
sys.added_thread_counters++;
if (sys.added_thread_counters > MAX_ADDED_THREAD_COUNTERS) {
- fprintf(stderr, "exceeded max %d added thread counters\n",
- MAX_ADDED_COUNTERS);
+ fprintf(stderr, "exceeded max %d added thread counters\n", MAX_ADDED_COUNTERS);
exit(-1);
}
break;
@@ -5433,8 +6289,7 @@ int add_counter(unsigned int msr_num, char *path, char *name,
sys.cp = msrp;
sys.added_core_counters++;
if (sys.added_core_counters > MAX_ADDED_COUNTERS) {
- fprintf(stderr, "exceeded max %d added core counters\n",
- MAX_ADDED_COUNTERS);
+ fprintf(stderr, "exceeded max %d added core counters\n", MAX_ADDED_COUNTERS);
exit(-1);
}
break;
@@ -5444,8 +6299,7 @@ int add_counter(unsigned int msr_num, char *path, char *name,
sys.pp = msrp;
sys.added_package_counters++;
if (sys.added_package_counters > MAX_ADDED_COUNTERS) {
- fprintf(stderr, "exceeded max %d added package counters\n",
- MAX_ADDED_COUNTERS);
+ fprintf(stderr, "exceeded max %d added package counters\n", MAX_ADDED_COUNTERS);
exit(-1);
}
break;
@@ -5559,6 +6413,16 @@ next:
}
}
+int is_deferred_add(char *name)
+{
+ int i;
+
+ for (i = 0; i < deferred_add_index; ++i)
+ if (!strcmp(name, deferred_add_names[i]))
+ return 1;
+ return 0;
+}
+
int is_deferred_skip(char *name)
{
int i;
@@ -5577,65 +6441,67 @@ void probe_sysfs(void)
int state;
char *sp;
- if (!DO_BIC(BIC_sysfs))
- return;
-
for (state = 10; state >= 0; --state) {
- sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name",
- base_cpu, state);
+ sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name", base_cpu, state);
input = fopen(path, "r");
if (input == NULL)
continue;
if (!fgets(name_buf, sizeof(name_buf), input))
err(1, "%s: failed to read file", path);
- /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */
+ /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */
sp = strchr(name_buf, '-');
if (!sp)
sp = strchrnul(name_buf, '\n');
*sp = '%';
*(sp + 1) = '\0';
+ remove_underbar(name_buf);
+
fclose(input);
sprintf(path, "cpuidle/state%d/time", state);
+ if (!DO_BIC(BIC_sysfs) && !is_deferred_add(name_buf))
+ continue;
+
if (is_deferred_skip(name_buf))
continue;
- add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_USEC,
- FORMAT_PERCENT, SYSFS_PERCPU);
+ add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_USEC, FORMAT_PERCENT, SYSFS_PERCPU);
}
for (state = 10; state >= 0; --state) {
- sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name",
- base_cpu, state);
+ sprintf(path, "/sys/devices/system/cpu/cpu%d/cpuidle/state%d/name", base_cpu, state);
input = fopen(path, "r");
if (input == NULL)
continue;
if (!fgets(name_buf, sizeof(name_buf), input))
err(1, "%s: failed to read file", path);
- /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */
+ /* truncate "C1-HSW\n" to "C1", or truncate "C1\n" to "C1" */
sp = strchr(name_buf, '-');
if (!sp)
sp = strchrnul(name_buf, '\n');
*sp = '\0';
fclose(input);
+ remove_underbar(name_buf);
+
sprintf(path, "cpuidle/state%d/usage", state);
+ if (!DO_BIC(BIC_sysfs) && !is_deferred_add(name_buf))
+ continue;
+
if (is_deferred_skip(name_buf))
continue;
- add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS,
- FORMAT_DELTA, SYSFS_PERCPU);
+ add_counter(0, path, name_buf, 64, SCOPE_CPU, COUNTER_ITEMS, FORMAT_DELTA, SYSFS_PERCPU);
}
}
-
/*
* parse cpuset with following syntax
* 1,2,4..6,8-10 and set bits in cpu_subset
@@ -5722,36 +6588,36 @@ error:
exit(-1);
}
-
void cmdline(int argc, char **argv)
{
int opt;
int option_index = 0;
static struct option long_options[] = {
- {"add", required_argument, 0, 'a'},
- {"cpu", required_argument, 0, 'c'},
- {"Dump", no_argument, 0, 'D'},
- {"debug", no_argument, 0, 'd'}, /* internal, not documented */
- {"enable", required_argument, 0, 'e'},
- {"interval", required_argument, 0, 'i'},
- {"num_iterations", required_argument, 0, 'n'},
- {"help", no_argument, 0, 'h'},
- {"hide", required_argument, 0, 'H'}, // meh, -h taken by --help
- {"Joules", no_argument, 0, 'J'},
- {"list", no_argument, 0, 'l'},
- {"out", required_argument, 0, 'o'},
- {"quiet", no_argument, 0, 'q'},
- {"show", required_argument, 0, 's'},
- {"Summary", no_argument, 0, 'S'},
- {"TCC", required_argument, 0, 'T'},
- {"version", no_argument, 0, 'v' },
- {0, 0, 0, 0 }
+ { "add", required_argument, 0, 'a' },
+ { "cpu", required_argument, 0, 'c' },
+ { "Dump", no_argument, 0, 'D' },
+ { "debug", no_argument, 0, 'd' }, /* internal, not documented */
+ { "enable", required_argument, 0, 'e' },
+ { "interval", required_argument, 0, 'i' },
+ { "IPC", no_argument, 0, 'I' },
+ { "num_iterations", required_argument, 0, 'n' },
+ { "header_iterations", required_argument, 0, 'N' },
+ { "help", no_argument, 0, 'h' },
+ { "hide", required_argument, 0, 'H' }, // meh, -h taken by --help
+ { "Joules", no_argument, 0, 'J' },
+ { "list", no_argument, 0, 'l' },
+ { "out", required_argument, 0, 'o' },
+ { "quiet", no_argument, 0, 'q' },
+ { "show", required_argument, 0, 's' },
+ { "Summary", no_argument, 0, 'S' },
+ { "TCC", required_argument, 0, 'T' },
+ { "version", no_argument, 0, 'v' },
+ { 0, 0, 0, 0 }
};
progname = argv[0];
- while ((opt = getopt_long_only(argc, argv, "+C:c:Dde:hi:Jn:o:qST:v",
- long_options, &option_index)) != -1) {
+ while ((opt = getopt_long_only(argc, argv, "+C:c:Dde:hi:Jn:o:qST:v", long_options, &option_index)) != -1) {
switch (opt) {
case 'a':
parse_add_command(optarg);
@@ -5786,8 +6652,7 @@ void cmdline(int argc, char **argv)
double interval = strtod(optarg, NULL);
if (interval < 0.001) {
- fprintf(outf, "interval %f seconds is too small\n",
- interval);
+ fprintf(outf, "interval %f seconds is too small\n", interval);
exit(2);
}
@@ -5814,8 +6679,15 @@ void cmdline(int argc, char **argv)
num_iterations = strtod(optarg, NULL);
if (num_iterations <= 0) {
- fprintf(outf, "iterations %d should be positive number\n",
- num_iterations);
+ fprintf(outf, "iterations %d should be positive number\n", num_iterations);
+ exit(2);
+ }
+ break;
+ case 'N':
+ header_iterations = strtod(optarg, NULL);
+
+ if (header_iterations <= 0) {
+ fprintf(outf, "iterations %d should be positive number\n", header_iterations);
exit(2);
}
break;
@@ -5835,7 +6707,7 @@ void cmdline(int argc, char **argv)
summary_only++;
break;
case 'T':
- tcc_activation_temp_override = atoi(optarg);
+ tj_max_override = atoi(optarg);
break;
case 'v':
print_version();
@@ -5850,13 +6722,17 @@ int main(int argc, char **argv)
outf = stderr;
cmdline(argc, argv);
- if (!quiet)
+ if (!quiet) {
print_version();
+ print_bootcmd();
+ }
probe_sysfs();
turbostat_init();
+ msr_sum_record();
+
/* dump counters and exit */
if (dump_only)
return get_and_dump_counters();
diff --git a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
index 3fe1eed900d4..5fd9e594079c 100644
--- a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
+++ b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c
@@ -91,6 +91,9 @@ unsigned int has_hwp_request_pkg; /* IA32_HWP_REQUEST_PKG */
unsigned int bdx_highest_ratio;
+#define PATH_TO_CPU "/sys/devices/system/cpu/"
+#define SYSFS_PATH_MAX 255
+
/*
* maintain compatibility with original implementation, but don't document it:
*/
@@ -622,6 +625,57 @@ void cmdline(int argc, char **argv)
}
}
+/*
+ * Open a file, and exit on failure
+ */
+FILE *fopen_or_die(const char *path, const char *mode)
+{
+ FILE *filep = fopen(path, "r");
+
+ if (!filep)
+ err(1, "%s: open failed", path);
+ return filep;
+}
+
+void err_on_hypervisor(void)
+{
+ FILE *cpuinfo;
+ char *flags, *hypervisor;
+ char *buffer;
+
+ /* On VMs /proc/cpuinfo contains a "flags" entry for hypervisor */
+ cpuinfo = fopen_or_die("/proc/cpuinfo", "ro");
+
+ buffer = malloc(4096);
+ if (!buffer) {
+ fclose(cpuinfo);
+ err(-ENOMEM, "buffer malloc fail");
+ }
+
+ if (!fread(buffer, 1024, 1, cpuinfo)) {
+ fclose(cpuinfo);
+ free(buffer);
+ err(1, "Reading /proc/cpuinfo failed");
+ }
+
+ flags = strstr(buffer, "flags");
+ rewind(cpuinfo);
+ fseek(cpuinfo, flags - buffer, SEEK_SET);
+ if (!fgets(buffer, 4096, cpuinfo)) {
+ fclose(cpuinfo);
+ free(buffer);
+ err(1, "Reading /proc/cpuinfo failed");
+ }
+ fclose(cpuinfo);
+
+ hypervisor = strstr(buffer, "hypervisor");
+
+ free(buffer);
+
+ if (hypervisor)
+ err(-1,
+ "not supported on this virtual machine");
+}
int get_msr(int cpu, int offset, unsigned long long *msr)
{
@@ -635,8 +689,10 @@ int get_msr(int cpu, int offset, unsigned long long *msr)
err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname);
retval = pread(fd, msr, sizeof(*msr), offset);
- if (retval != sizeof(*msr))
+ if (retval != sizeof(*msr)) {
+ err_on_hypervisor();
err(-1, "%s offset 0x%llx read failed", pathname, (unsigned long long)offset);
+ }
if (debug > 1)
fprintf(stderr, "get_msr(cpu%d, 0x%X, 0x%llX)\n", cpu, offset, *msr);
@@ -668,6 +724,48 @@ int put_msr(int cpu, int offset, unsigned long long new_msr)
return 0;
}
+static unsigned int read_sysfs(const char *path, char *buf, size_t buflen)
+{
+ ssize_t numread;
+ int fd;
+
+ fd = open(path, O_RDONLY);
+ if (fd == -1)
+ return 0;
+
+ numread = read(fd, buf, buflen - 1);
+ if (numread < 1) {
+ close(fd);
+ return 0;
+ }
+
+ buf[numread] = '\0';
+ close(fd);
+
+ return (unsigned int) numread;
+}
+
+static unsigned int write_sysfs(const char *path, char *buf, size_t buflen)
+{
+ ssize_t numwritten;
+ int fd;
+
+ fd = open(path, O_WRONLY);
+ if (fd == -1)
+ return 0;
+
+ numwritten = write(fd, buf, buflen - 1);
+ if (numwritten < 1) {
+ perror("write failed\n");
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+
+ return (unsigned int) numwritten;
+}
+
void print_hwp_cap(int cpu, struct msr_hwp_cap *cap, char *str)
{
if (cpu != -1)
@@ -745,17 +843,61 @@ void write_hwp_request(int cpu, struct msr_hwp_request *hwp_req, unsigned int ms
put_msr(cpu, msr_offset, msr);
}
+static int get_epb(int cpu)
+{
+ char path[SYSFS_PATH_MAX];
+ char linebuf[3];
+ char *endp;
+ long val;
+
+ if (!has_epb)
+ return -1;
+
+ snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/power/energy_perf_bias", cpu);
+
+ if (!read_sysfs(path, linebuf, 3))
+ return -1;
+
+ val = strtol(linebuf, &endp, 0);
+ if (endp == linebuf || errno == ERANGE)
+ return -1;
+
+ return (int)val;
+}
+
+static int set_epb(int cpu, int val)
+{
+ char path[SYSFS_PATH_MAX];
+ char linebuf[3];
+ char *endp;
+ int ret;
+
+ if (!has_epb)
+ return -1;
+
+ snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/power/energy_perf_bias", cpu);
+ snprintf(linebuf, sizeof(linebuf), "%d", val);
+
+ ret = write_sysfs(path, linebuf, 3);
+ if (ret <= 0)
+ return -1;
+
+ val = strtol(linebuf, &endp, 0);
+ if (endp == linebuf || errno == ERANGE)
+ return -1;
+
+ return (int)val;
+}
+
int print_cpu_msrs(int cpu)
{
- unsigned long long msr;
struct msr_hwp_request req;
struct msr_hwp_cap cap;
+ int epb;
- if (has_epb) {
- get_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, &msr);
-
- printf("cpu%d: EPB %u\n", cpu, (unsigned int) msr);
- }
+ epb = get_epb(cpu);
+ if (epb >= 0)
+ printf("cpu%d: EPB %u\n", cpu, (unsigned int) epb);
if (!has_hwp)
return 0;
@@ -1038,15 +1180,15 @@ int enable_hwp_on_cpu(int cpu)
int update_cpu_msrs(int cpu)
{
unsigned long long msr;
-
+ int epb;
if (update_epb) {
- get_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, &msr);
- put_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, new_epb);
+ epb = get_epb(cpu);
+ set_epb(cpu, new_epb);
if (verbose)
printf("cpu%d: ENERGY_PERF_BIAS old: %d new: %d\n",
- cpu, (unsigned int) msr, (unsigned int) new_epb);
+ cpu, epb, (unsigned int) new_epb);
}
if (update_turbo) {
@@ -1086,18 +1228,6 @@ int update_cpu_msrs(int cpu)
return 0;
}
-/*
- * Open a file, and exit on failure
- */
-FILE *fopen_or_die(const char *path, const char *mode)
-{
- FILE *filep = fopen(path, "r");
-
- if (!filep)
- err(1, "%s: open failed", path);
- return filep;
-}
-
unsigned int get_pkg_num(int cpu)
{
FILE *fp;