summaryrefslogtreecommitdiffstats
path: root/tools/power
diff options
context:
space:
mode:
Diffstat (limited to 'tools/power')
-rw-r--r--tools/power/acpi/.gitignore8
-rw-r--r--tools/power/acpi/Makefile5
-rw-r--r--tools/power/acpi/Makefile.config5
-rw-r--r--tools/power/acpi/Makefile.rules5
-rw-r--r--tools/power/acpi/os_specific/service_layers/oslinuxtbl.c48
-rw-r--r--tools/power/acpi/tools/acpidbg/Makefile5
-rw-r--r--tools/power/acpi/tools/acpidbg/acpidbg.c5
-rw-r--r--tools/power/acpi/tools/acpidump/Makefile5
-rw-r--r--tools/power/acpi/tools/acpidump/apdump.c8
-rw-r--r--tools/power/acpi/tools/acpidump/apfiles.c18
-rw-r--r--tools/power/acpi/tools/ec/Makefile5
-rw-r--r--tools/power/acpi/tools/ec/ec_access.c3
-rw-r--r--tools/power/cpupower/Makefile28
-rw-r--r--tools/power/cpupower/ToDo14
-rw-r--r--tools/power/cpupower/bench/benchmark.c15
-rw-r--r--tools/power/cpupower/bench/benchmark.h15
-rw-r--r--tools/power/cpupower/bench/config.h15
-rw-r--r--tools/power/cpupower/bench/cpufreq-bench_plot.sh17
-rw-r--r--tools/power/cpupower/bench/cpufreq-bench_script.sh17
-rw-r--r--tools/power/cpupower/bench/main.c15
-rw-r--r--tools/power/cpupower/bench/parse.c15
-rw-r--r--tools/power/cpupower/bench/parse.h15
-rw-r--r--tools/power/cpupower/bench/system.c15
-rw-r--r--tools/power/cpupower/bench/system.h15
-rw-r--r--tools/power/cpupower/debug/i386/centrino-decode.c3
-rw-r--r--tools/power/cpupower/debug/i386/intel_gsic.c3
-rw-r--r--tools/power/cpupower/debug/i386/powernow-k8-decode.c3
-rw-r--r--tools/power/cpupower/debug/kernel/Makefile4
-rw-r--r--tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c1
-rw-r--r--tools/power/cpupower/lib/cpufreq.c3
-rw-r--r--tools/power/cpupower/lib/cpufreq.h10
-rw-r--r--tools/power/cpupower/lib/cpuidle.c3
-rw-r--r--tools/power/cpupower/lib/cpupower.c3
-rw-r--r--tools/power/cpupower/man/cpupower-monitor.12
-rw-r--r--tools/power/cpupower/po/cs.po2
-rw-r--r--tools/power/cpupower/po/de.po346
-rw-r--r--tools/power/cpupower/po/fr.po2
-rw-r--r--tools/power/cpupower/po/it.po2
-rw-r--r--tools/power/cpupower/po/pt.po2
-rw-r--r--tools/power/cpupower/utils/cpufreq-info.c3
-rw-r--r--tools/power/cpupower/utils/cpufreq-set.c5
-rw-r--r--tools/power/cpupower/utils/cpuidle-info.c3
-rw-r--r--tools/power/cpupower/utils/cpupower-info.c12
-rw-r--r--tools/power/cpupower/utils/cpupower-set.c12
-rw-r--r--tools/power/cpupower/utils/cpupower.c3
-rw-r--r--tools/power/cpupower/utils/helpers/cpuid.c4
-rw-r--r--tools/power/cpupower/utils/helpers/helpers.h4
-rw-r--r--tools/power/cpupower/utils/helpers/sysfs.c3
-rw-r--r--tools/power/cpupower/utils/helpers/topology.c3
-rw-r--r--tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c5
-rw-r--r--tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c6
-rw-r--r--tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c6
-rw-r--r--tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h9
-rw-r--r--tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c6
-rw-r--r--tools/power/cpupower/utils/idle_monitor/idle_monitors.h4
-rw-r--r--tools/power/cpupower/utils/idle_monitor/mperf_monitor.c67
-rw-r--r--tools/power/cpupower/utils/idle_monitor/nhm_idle.c5
-rw-r--r--tools/power/cpupower/utils/idle_monitor/snb_idle.c5
-rw-r--r--tools/power/pm-graph/README556
-rwxr-xr-xtools/power/pm-graph/bootgraph.py59
-rw-r--r--tools/power/pm-graph/config/example.cfg26
-rw-r--r--tools/power/pm-graph/sleepgraph.816
-rwxr-xr-xtools/power/pm-graph/sleepgraph.py1375
-rw-r--r--tools/power/x86/intel-speed-select/.gitignore2
-rw-r--r--tools/power/x86/intel-speed-select/Build1
-rw-r--r--tools/power/x86/intel-speed-select/Makefile56
-rw-r--r--tools/power/x86/intel-speed-select/isst-config.c2344
-rw-r--r--tools/power/x86/intel-speed-select/isst-core.c900
-rw-r--r--tools/power/x86/intel-speed-select/isst-display.c654
-rw-r--r--tools/power/x86/intel-speed-select/isst.h245
-rwxr-xr-xtools/power/x86/intel_pstate_tracer/intel_pstate_tracer.py1
-rw-r--r--tools/power/x86/turbostat/Makefile3
-rw-r--r--tools/power/x86/turbostat/turbostat.c229
-rw-r--r--tools/power/x86/x86_energy_perf_policy/Makefile3
-rw-r--r--tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.82
-rw-r--r--tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c31
76 files changed, 6318 insertions, 1055 deletions
diff --git a/tools/power/acpi/.gitignore b/tools/power/acpi/.gitignore
index cba3d994995c..f698a0e5bfa6 100644
--- a/tools/power/acpi/.gitignore
+++ b/tools/power/acpi/.gitignore
@@ -1,4 +1,4 @@
-acpidbg
-acpidump
-ec
-include
+/acpidbg
+/acpidump
+/ec
+/include/
diff --git a/tools/power/acpi/Makefile b/tools/power/acpi/Makefile
index a8bf9081512b..ebd3e1a1c28e 100644
--- a/tools/power/acpi/Makefile
+++ b/tools/power/acpi/Makefile
@@ -1,12 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-only
# tools/power/acpi/Makefile - ACPI tool Makefile
#
# Copyright (c) 2013, Intel Corporation
# Author: Lv Zheng <lv.zheng@intel.com>
#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; version 2
-# of the License.
include ../../scripts/Makefile.include
diff --git a/tools/power/acpi/Makefile.config b/tools/power/acpi/Makefile.config
index f304be71c278..0111d246d1ca 100644
--- a/tools/power/acpi/Makefile.config
+++ b/tools/power/acpi/Makefile.config
@@ -1,12 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-only
# tools/power/acpi/Makefile.config - ACPI tool Makefile
#
# Copyright (c) 2015, Intel Corporation
# Author: Lv Zheng <lv.zheng@intel.com>
#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; version 2
-# of the License.
ifeq ($(srctree),)
srctree := $(patsubst %/,%,$(dir $(shell pwd)))
diff --git a/tools/power/acpi/Makefile.rules b/tools/power/acpi/Makefile.rules
index 373738338f51..2a6c170b57cd 100644
--- a/tools/power/acpi/Makefile.rules
+++ b/tools/power/acpi/Makefile.rules
@@ -1,12 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-only
# tools/power/acpi/Makefile.rules - ACPI tool Makefile
#
# Copyright (c) 2015, Intel Corporation
# Author: Lv Zheng <lv.zheng@intel.com>
#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; version 2
-# of the License.
objdir := $(OUTPUT)tools/$(TOOL)/
toolobjs := $(addprefix $(objdir),$(TOOL_OBJS))
diff --git a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
index 2a1fd9182f94..d1f3d44e315e 100644
--- a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
+++ b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
@@ -19,7 +19,7 @@ ACPI_MODULE_NAME("oslinuxtbl")
typedef struct osl_table_info {
struct osl_table_info *next;
u32 instance;
- char signature[ACPI_NAME_SIZE];
+ char signature[ACPI_NAMESEG_SIZE];
} osl_table_info;
@@ -286,14 +286,14 @@ static acpi_status osl_add_table_to_list(char *signature, u32 instance)
return (AE_NO_MEMORY);
}
- ACPI_MOVE_NAME(new_info->signature, signature);
+ ACPI_COPY_NAMESEG(new_info->signature, signature);
if (!gbl_table_list_head) {
gbl_table_list_head = new_info;
} else {
next = gbl_table_list_head;
while (1) {
- if (ACPI_COMPARE_NAME(next->signature, signature)) {
+ if (ACPI_COMPARE_NAMESEG(next->signature, signature)) {
if (next->instance == instance) {
found = TRUE;
}
@@ -782,11 +782,11 @@ osl_get_bios_table(char *signature,
/* Handle special tables whose addresses are not in RSDT/XSDT */
- if (ACPI_COMPARE_NAME(signature, ACPI_RSDP_NAME) ||
- ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT) ||
- ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT) ||
- ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT) ||
- ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) {
+ if (ACPI_COMPARE_NAMESEG(signature, ACPI_RSDP_NAME) ||
+ ACPI_COMPARE_NAMESEG(signature, ACPI_SIG_RSDT) ||
+ ACPI_COMPARE_NAMESEG(signature, ACPI_SIG_XSDT) ||
+ ACPI_COMPARE_NAMESEG(signature, ACPI_SIG_DSDT) ||
+ ACPI_COMPARE_NAMESEG(signature, ACPI_SIG_FACS)) {
find_next_instance:
@@ -797,7 +797,7 @@ find_next_instance:
* careful about the FADT length and validate table addresses.
* Note: The 64-bit addresses have priority.
*/
- if (ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT)) {
+ if (ACPI_COMPARE_NAMESEG(signature, ACPI_SIG_DSDT)) {
if (current_instance < 2) {
if ((gbl_fadt->header.length >=
MIN_FADT_FOR_XDSDT) && gbl_fadt->Xdsdt
@@ -815,7 +815,7 @@ find_next_instance:
dsdt;
}
}
- } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) {
+ } else if (ACPI_COMPARE_NAMESEG(signature, ACPI_SIG_FACS)) {
if (current_instance < 2) {
if ((gbl_fadt->header.length >=
MIN_FADT_FOR_XFACS) && gbl_fadt->Xfacs
@@ -833,7 +833,7 @@ find_next_instance:
facs;
}
}
- } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT)) {
+ } else if (ACPI_COMPARE_NAMESEG(signature, ACPI_SIG_XSDT)) {
if (!gbl_revision) {
return (AE_BAD_SIGNATURE);
}
@@ -842,7 +842,7 @@ find_next_instance:
(acpi_physical_address)gbl_rsdp.
xsdt_physical_address;
}
- } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT)) {
+ } else if (ACPI_COMPARE_NAMESEG(signature, ACPI_SIG_RSDT)) {
if (current_instance == 0) {
table_address =
(acpi_physical_address)gbl_rsdp.
@@ -931,7 +931,7 @@ find_next_instance:
/* Does this table match the requested signature? */
- if (!ACPI_COMPARE_NAME
+ if (!ACPI_COMPARE_NAMESEG
(mapped_table->signature, signature)) {
osl_unmap_table(mapped_table);
mapped_table = NULL;
@@ -995,7 +995,7 @@ static acpi_status osl_list_customized_tables(char *directory)
{
void *table_dir;
u32 instance;
- char temp_name[ACPI_NAME_SIZE];
+ char temp_name[ACPI_NAMESEG_SIZE];
char *filename;
acpi_status status = AE_OK;
@@ -1086,8 +1086,8 @@ osl_map_table(acpi_size address,
return (AE_BAD_SIGNATURE);
}
} else
- if (!ACPI_COMPARE_NAME(signature, mapped_table->signature))
- {
+ if (!ACPI_COMPARE_NAMESEG
+ (signature, mapped_table->signature)) {
acpi_os_unmap_memory(mapped_table,
sizeof(struct acpi_table_header));
return (AE_BAD_SIGNATURE);
@@ -1158,15 +1158,15 @@ osl_table_name_from_file(char *filename, char *signature, u32 *instance)
/* Ignore meaningless files */
- if (strlen(filename) < ACPI_NAME_SIZE) {
+ if (strlen(filename) < ACPI_NAMESEG_SIZE) {
return (AE_BAD_SIGNATURE);
}
/* Extract instance number */
- if (isdigit((int)filename[ACPI_NAME_SIZE])) {
- sscanf(&filename[ACPI_NAME_SIZE], "%u", instance);
- } else if (strlen(filename) != ACPI_NAME_SIZE) {
+ if (isdigit((int)filename[ACPI_NAMESEG_SIZE])) {
+ sscanf(&filename[ACPI_NAMESEG_SIZE], "%u", instance);
+ } else if (strlen(filename) != ACPI_NAMESEG_SIZE) {
return (AE_BAD_SIGNATURE);
} else {
*instance = 0;
@@ -1174,7 +1174,7 @@ osl_table_name_from_file(char *filename, char *signature, u32 *instance)
/* Extract signature */
- ACPI_MOVE_NAME(signature, filename);
+ ACPI_COPY_NAMESEG(signature, filename);
return (AE_OK);
}
@@ -1236,7 +1236,7 @@ osl_read_table_from_file(char *filename,
status = AE_BAD_SIGNATURE;
goto exit;
}
- } else if (!ACPI_COMPARE_NAME(signature, header.signature)) {
+ } else if (!ACPI_COMPARE_NAMESEG(signature, header.signature)) {
fprintf(stderr,
"Incorrect signature: Expecting %4.4s, found %4.4s\n",
signature, header.signature);
@@ -1311,7 +1311,7 @@ osl_get_customized_table(char *pathname,
{
void *table_dir;
u32 current_instance = 0;
- char temp_name[ACPI_NAME_SIZE];
+ char temp_name[ACPI_NAMESEG_SIZE];
char table_filename[PATH_MAX];
char *filename;
acpi_status status;
@@ -1329,7 +1329,7 @@ osl_get_customized_table(char *pathname,
/* Ignore meaningless files */
- if (!ACPI_COMPARE_NAME(filename, signature)) {
+ if (!ACPI_COMPARE_NAMESEG(filename, signature)) {
continue;
}
diff --git a/tools/power/acpi/tools/acpidbg/Makefile b/tools/power/acpi/tools/acpidbg/Makefile
index f2d06e773eb4..2ce0ee5d0deb 100644
--- a/tools/power/acpi/tools/acpidbg/Makefile
+++ b/tools/power/acpi/tools/acpidbg/Makefile
@@ -1,12 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-only
# tools/power/acpi/tools/acpidbg/Makefile - ACPI tool Makefile
#
# Copyright (c) 2015, Intel Corporation
# Author: Lv Zheng <lv.zheng@intel.com>
#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; version 2
-# of the License.
include ../../Makefile.config
diff --git a/tools/power/acpi/tools/acpidbg/acpidbg.c b/tools/power/acpi/tools/acpidbg/acpidbg.c
index 4308362d7068..3d2bfd716028 100644
--- a/tools/power/acpi/tools/acpidbg/acpidbg.c
+++ b/tools/power/acpi/tools/acpidbg/acpidbg.c
@@ -1,12 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* ACPI AML interfacing userspace utility
*
* Copyright (C) 2015, Intel Corporation
* Authors: Lv Zheng <lv.zheng@intel.com>
- *
- * 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.
*/
#include <acpi/acpi.h>
diff --git a/tools/power/acpi/tools/acpidump/Makefile b/tools/power/acpi/tools/acpidump/Makefile
index b436f8675f6a..1208a105a871 100644
--- a/tools/power/acpi/tools/acpidump/Makefile
+++ b/tools/power/acpi/tools/acpidump/Makefile
@@ -1,12 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-only
# tools/power/acpi/tools/acpidump/Makefile - ACPI tool Makefile
#
# Copyright (c) 2015, Intel Corporation
# Author: Lv Zheng <lv.zheng@intel.com>
#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; version 2
-# of the License.
include ../../Makefile.config
diff --git a/tools/power/acpi/tools/acpidump/apdump.c b/tools/power/acpi/tools/acpidump/apdump.c
index e256c2ac5ddc..820baeb5092b 100644
--- a/tools/power/acpi/tools/acpidump/apdump.c
+++ b/tools/power/acpi/tools/acpidump/apdump.c
@@ -289,14 +289,14 @@ int ap_dump_table_by_address(char *ascii_address)
int ap_dump_table_by_name(char *signature)
{
- char local_signature[ACPI_NAME_SIZE + 1];
+ char local_signature[ACPI_NAMESEG_SIZE + 1];
u32 instance;
struct acpi_table_header *table;
acpi_physical_address address;
acpi_status status;
int table_status;
- if (strlen(signature) != ACPI_NAME_SIZE) {
+ if (strlen(signature) != ACPI_NAMESEG_SIZE) {
fprintf(stderr,
"Invalid table signature [%s]: must be exactly 4 characters\n",
signature);
@@ -310,9 +310,9 @@ int ap_dump_table_by_name(char *signature)
/* To be friendly, handle tables whose signatures do not match the name */
- if (ACPI_COMPARE_NAME(local_signature, "FADT")) {
+ if (ACPI_COMPARE_NAMESEG(local_signature, "FADT")) {
strcpy(local_signature, ACPI_SIG_FADT);
- } else if (ACPI_COMPARE_NAME(local_signature, "MADT")) {
+ } else if (ACPI_COMPARE_NAMESEG(local_signature, "MADT")) {
strcpy(local_signature, ACPI_SIG_MADT);
}
diff --git a/tools/power/acpi/tools/acpidump/apfiles.c b/tools/power/acpi/tools/acpidump/apfiles.c
index 49972bc78bc5..16d919bd133b 100644
--- a/tools/power/acpi/tools/acpidump/apfiles.c
+++ b/tools/power/acpi/tools/acpidump/apfiles.c
@@ -29,18 +29,24 @@ static int ap_is_existing_file(char *pathname)
{
#if !defined(_GNU_EFI) && !defined(_EDK2_EFI)
struct stat stat_info;
+ int in_char;
if (!stat(pathname, &stat_info)) {
fprintf(stderr,
"Target path already exists, overwrite? [y|n] ");
- if (getchar() != 'y') {
+ in_char = fgetc(stdin);
+ if (in_char == '\n') {
+ in_char = fgetc(stdin);
+ }
+
+ if (in_char != 'y' && in_char != 'Y') {
return (-1);
}
}
#endif
- return 0;
+ return (0);
}
/******************************************************************************
@@ -97,7 +103,7 @@ int ap_open_output_file(char *pathname)
int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance)
{
- char filename[ACPI_NAME_SIZE + 16];
+ char filename[ACPI_NAMESEG_SIZE + 16];
char instance_str[16];
ACPI_FILE file;
acpi_size actual;
@@ -110,16 +116,16 @@ int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance)
/* Construct lower-case filename from the table local signature */
if (ACPI_VALIDATE_RSDP_SIG(table->signature)) {
- ACPI_MOVE_NAME(filename, ACPI_RSDP_NAME);
+ ACPI_COPY_NAMESEG(filename, ACPI_RSDP_NAME);
} else {
- ACPI_MOVE_NAME(filename, table->signature);
+ ACPI_COPY_NAMESEG(filename, table->signature);
}
filename[0] = (char)tolower((int)filename[0]);
filename[1] = (char)tolower((int)filename[1]);
filename[2] = (char)tolower((int)filename[2]);
filename[3] = (char)tolower((int)filename[3]);
- filename[ACPI_NAME_SIZE] = 0;
+ filename[ACPI_NAMESEG_SIZE] = 0;
/* Handle multiple SSDts - create different filenames for each */
diff --git a/tools/power/acpi/tools/ec/Makefile b/tools/power/acpi/tools/ec/Makefile
index 75d8a127b6ee..d0abac0ec23a 100644
--- a/tools/power/acpi/tools/ec/Makefile
+++ b/tools/power/acpi/tools/ec/Makefile
@@ -1,12 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-only
# tools/power/acpi/tools/acpidump/Makefile - ACPI tool Makefile
#
# Copyright (c) 2015, Intel Corporation
# Author: Lv Zheng <lv.zheng@intel.com>
#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; version 2
-# of the License.
include ../../Makefile.config
diff --git a/tools/power/acpi/tools/ec/ec_access.c b/tools/power/acpi/tools/ec/ec_access.c
index 5f50642386db..8bb271b210d8 100644
--- a/tools/power/acpi/tools/ec/ec_access.c
+++ b/tools/power/acpi/tools/ec/ec_access.c
@@ -1,11 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* ec_access.c
*
* Copyright (C) 2010 SUSE Linux Products GmbH
* Author:
* Thomas Renninger <trenn@suse.de>
- *
- * This work is licensed under the terms of the GNU GPL, version 2.
*/
#include <fcntl.h>
diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile
index fd8765af19bb..c8622497ef23 100644
--- a/tools/power/cpupower/Makefile
+++ b/tools/power/cpupower/Makefile
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
# Makefile for cpupower
#
# Copyright (C) 2005,2006 Dominik Brodowski <linux@dominikbrodowski.net>
@@ -6,19 +7,6 @@
#
# Copyright (C) 2003,2004 Greg Kroah-Hartman <greg@kroah.com>
#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; version 2 of the License.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
OUTPUT=./
ifeq ("$(origin O)", "command line")
OUTPUT := $(O)/
@@ -30,7 +18,6 @@ OUTDIR := $(shell cd $(OUTPUT) && pwd)
$(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist))
endif
-include ../../scripts/Makefile.arch
# --- CONFIGURATION BEGIN ---
@@ -81,11 +68,6 @@ bindir ?= /usr/bin
sbindir ?= /usr/sbin
mandir ?= /usr/man
includedir ?= /usr/include
-ifeq ($(IS_64_BIT), 1)
-libdir ?= /usr/lib64
-else
-libdir ?= /usr/lib
-endif
localedir ?= /usr/share/locale
docdir ?= /usr/share/doc/packages/cpupower
confdir ?= /etc/
@@ -112,6 +94,14 @@ RANLIB = $(CROSS)ranlib
HOSTCC = gcc
MKDIR = mkdir
+# 64bit library detection
+include ../../scripts/Makefile.arch
+
+ifeq ($(IS_64_BIT), 1)
+libdir ?= /usr/lib64
+else
+libdir ?= /usr/lib
+endif
# Now we set up the build system
#
diff --git a/tools/power/cpupower/ToDo b/tools/power/cpupower/ToDo
index 6e8b89f282e6..b196a139a3e4 100644
--- a/tools/power/cpupower/ToDo
+++ b/tools/power/cpupower/ToDo
@@ -8,3 +8,17 @@ ToDos sorted by priority:
- Add another c1e debug idle monitor
-> Is by design racy with BIOS, but could be added
with a --force option and some "be careful" messages
+- Add cpu_start()/cpu_stop() callbacks for monitor
+ -> This is to move the per_cpu logic from inside the
+ monitor to outside it. This can be given higher
+ priority in fork_it.
+- Fork as many processes as there are CPUs in case the
+ per_cpu_schedule flag is set.
+ -> Bind forked process to each cpu.
+ -> Execute start measures via the forked processes on
+ each cpu.
+ -> Run test executable in a forked process.
+ -> Execute stop measures via the forked processes on
+ each cpu.
+ This would be ideal as it will not introduce noise in the
+ tested executable.
diff --git a/tools/power/cpupower/bench/benchmark.c b/tools/power/cpupower/bench/benchmark.c
index 429d51ab8031..c7234cf3f6ff 100644
--- a/tools/power/cpupower/bench/benchmark.c
+++ b/tools/power/cpupower/bench/benchmark.c
@@ -1,20 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/* cpufreq-bench CPUFreq microbenchmark
*
* Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
diff --git a/tools/power/cpupower/bench/benchmark.h b/tools/power/cpupower/bench/benchmark.h
index 51d7f50ac2bb..bf612de897eb 100644
--- a/tools/power/cpupower/bench/benchmark.h
+++ b/tools/power/cpupower/bench/benchmark.h
@@ -1,20 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/* cpufreq-bench CPUFreq microbenchmark
*
* Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* load loop, this schould take about 1 to 2ms to complete */
diff --git a/tools/power/cpupower/bench/config.h b/tools/power/cpupower/bench/config.h
index ee6f258e5336..fec5b0b055f2 100644
--- a/tools/power/cpupower/bench/config.h
+++ b/tools/power/cpupower/bench/config.h
@@ -1,20 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/* cpufreq-bench CPUFreq microbenchmark
*
* Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* initial loop count for the load calibration */
diff --git a/tools/power/cpupower/bench/cpufreq-bench_plot.sh b/tools/power/cpupower/bench/cpufreq-bench_plot.sh
index 410021a12f40..f5f8b3c8f062 100644
--- a/tools/power/cpupower/bench/cpufreq-bench_plot.sh
+++ b/tools/power/cpupower/bench/cpufreq-bench_plot.sh
@@ -1,19 +1,6 @@
#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-or-later
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
# Author/Copyright(c): 2009, Thomas Renninger <trenn@suse.de>, Novell Inc.
@@ -101,4 +88,4 @@ done
echo >> $dir/plot_script.gpl
gnuplot $dir/plot_script.gpl
-rm -r $dir \ No newline at end of file
+rm -r $dir
diff --git a/tools/power/cpupower/bench/cpufreq-bench_script.sh b/tools/power/cpupower/bench/cpufreq-bench_script.sh
index de20d2a06879..785a3679c704 100644
--- a/tools/power/cpupower/bench/cpufreq-bench_script.sh
+++ b/tools/power/cpupower/bench/cpufreq-bench_script.sh
@@ -1,19 +1,6 @@
#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-or-later
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
# Author/Copyright(c): 2009, Thomas Renninger <trenn@suse.de>, Novell Inc.
@@ -98,4 +85,4 @@ function create_plots()
}
measure
-create_plots \ No newline at end of file
+create_plots
diff --git a/tools/power/cpupower/bench/main.c b/tools/power/cpupower/bench/main.c
index 24910313a521..429d1b6b8bc8 100644
--- a/tools/power/cpupower/bench/main.c
+++ b/tools/power/cpupower/bench/main.c
@@ -1,20 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/* cpufreq-bench CPUFreq microbenchmark
*
* Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
diff --git a/tools/power/cpupower/bench/parse.c b/tools/power/cpupower/bench/parse.c
index 84caee38418f..e63dc11fa3a5 100644
--- a/tools/power/cpupower/bench/parse.c
+++ b/tools/power/cpupower/bench/parse.c
@@ -1,20 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/* cpufreq-bench CPUFreq microbenchmark
*
* Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
diff --git a/tools/power/cpupower/bench/parse.h b/tools/power/cpupower/bench/parse.h
index a8dc632d9eee..d5b3e34d7064 100644
--- a/tools/power/cpupower/bench/parse.h
+++ b/tools/power/cpupower/bench/parse.h
@@ -1,20 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/* cpufreq-bench CPUFreq microbenchmark
*
* Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* struct that holds the required config parameters */
diff --git a/tools/power/cpupower/bench/system.c b/tools/power/cpupower/bench/system.c
index 2bb3eef7d5c1..40f3679e70b5 100644
--- a/tools/power/cpupower/bench/system.c
+++ b/tools/power/cpupower/bench/system.c
@@ -1,20 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/* cpufreq-bench CPUFreq microbenchmark
*
* Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
diff --git a/tools/power/cpupower/bench/system.h b/tools/power/cpupower/bench/system.h
index 3a8c858b78f0..530fa28230d1 100644
--- a/tools/power/cpupower/bench/system.h
+++ b/tools/power/cpupower/bench/system.h
@@ -1,20 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/* cpufreq-bench CPUFreq microbenchmark
*
* Copyright (C) 2008 Christian Kornacker <ckornacker@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "parse.h"
diff --git a/tools/power/cpupower/debug/i386/centrino-decode.c b/tools/power/cpupower/debug/i386/centrino-decode.c
index 7ef24cce4926..700cd31a7d02 100644
--- a/tools/power/cpupower/debug/i386/centrino-decode.c
+++ b/tools/power/cpupower/debug/i386/centrino-decode.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* (C) 2003 - 2004 Dominik Brodowski <linux@dominikbrodowski.de>
*
- * Licensed under the terms of the GNU GPL License version 2.
- *
* Based on code found in
* linux/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
* and originally developed by Jeremy Fitzhardinge.
diff --git a/tools/power/cpupower/debug/i386/intel_gsic.c b/tools/power/cpupower/debug/i386/intel_gsic.c
index d032c826d42e..e5e926f46d6b 100644
--- a/tools/power/cpupower/debug/i386/intel_gsic.c
+++ b/tools/power/cpupower/debug/i386/intel_gsic.c
@@ -1,9 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* (C) 2003 Bruno Ducrot
* (C) 2004 Dominik Brodowski <linux@dominikbrodowski.de>
*
- * Licensed under the terms of the GNU GPL License version 2.
- *
* Based on code found in
* linux/include/asm-i386/ist.h and linux/arch/i386/kernel/setup.c
* and originally developed by Andy Grover <andrew.grover@intel.com>
diff --git a/tools/power/cpupower/debug/i386/powernow-k8-decode.c b/tools/power/cpupower/debug/i386/powernow-k8-decode.c
index 638a6b3bfd97..735dca1e25bc 100644
--- a/tools/power/cpupower/debug/i386/powernow-k8-decode.c
+++ b/tools/power/cpupower/debug/i386/powernow-k8-decode.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* (C) 2004 Bruno Ducrot <ducrot@poupinou.org>
*
- * Licensed under the terms of the GNU GPL License version 2.
- *
* Based on code found in
* linux/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
* and originally developed by Paul Devriendt
diff --git a/tools/power/cpupower/debug/kernel/Makefile b/tools/power/cpupower/debug/kernel/Makefile
index c23e5a6ceb7e..7b5c43684be1 100644
--- a/tools/power/cpupower/debug/kernel/Makefile
+++ b/tools/power/cpupower/debug/kernel/Makefile
@@ -12,8 +12,8 @@ default:
$(MAKE) -C $(KDIR) M=$(CURDIR)
clean:
- - rm -rf *.o *.ko .tmp-versions .*.cmd .*.mod.* *.mod.c
- - rm -rf .tmp_versions* Module.symvers modules.order
+ - rm -rf *.o *.ko .*.cmd .*.mod.* *.mod.c
+ - rm -rf Module.symvers modules.order
install: default
install -d $(KMISC)
diff --git a/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c b/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c
index 6ff8383f2941..e364b170bf85 100644
--- a/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c
+++ b/tools/power/cpupower/debug/kernel/cpufreq-test_tsc.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* test module to check whether the TSC-based delay routine continues
* to work properly after cpufreq transitions. Needs ACPI to work
diff --git a/tools/power/cpupower/lib/cpufreq.c b/tools/power/cpupower/lib/cpufreq.c
index 80650497fb80..2f55d4d23446 100644
--- a/tools/power/cpupower/lib/cpufreq.c
+++ b/tools/power/cpupower/lib/cpufreq.c
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
- *
- * Licensed under the terms of the GNU GPL License version 2.
*/
diff --git a/tools/power/cpupower/lib/cpufreq.h b/tools/power/cpupower/lib/cpufreq.h
index 775738269cbf..a55f0d19215b 100644
--- a/tools/power/cpupower/lib/cpufreq.h
+++ b/tools/power/cpupower/lib/cpufreq.h
@@ -1,16 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* cpufreq.h - definitions for libcpufreq
*
* Copyright (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#ifndef __CPUPOWER_CPUFREQ_H__
diff --git a/tools/power/cpupower/lib/cpuidle.c b/tools/power/cpupower/lib/cpuidle.c
index 852d25462388..479c5971aa6d 100644
--- a/tools/power/cpupower/lib/cpuidle.c
+++ b/tools/power/cpupower/lib/cpuidle.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
* (C) 2011 Thomas Renninger <trenn@novell.com> Novell Inc.
- *
- * Licensed under the terms of the GNU GPL License version 2.
*/
#include <stdio.h>
diff --git a/tools/power/cpupower/lib/cpupower.c b/tools/power/cpupower/lib/cpupower.c
index 9711d628b0f4..3656e697537e 100644
--- a/tools/power/cpupower/lib/cpupower.c
+++ b/tools/power/cpupower/lib/cpupower.c
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
- *
- * Licensed under the terms of the GNU GPL License version 2.
*/
#include <sys/types.h>
diff --git a/tools/power/cpupower/man/cpupower-monitor.1 b/tools/power/cpupower/man/cpupower-monitor.1
index 914cbb9d9cd0..70a56476f4b0 100644
--- a/tools/power/cpupower/man/cpupower-monitor.1
+++ b/tools/power/cpupower/man/cpupower-monitor.1
@@ -61,7 +61,7 @@ Only display specific monitors. Use the monitor string(s) provided by \-l option
.PP
\-i seconds
.RS 4
-Measure intervall.
+Measure interval.
.RE
.PP
\-c
diff --git a/tools/power/cpupower/po/cs.po b/tools/power/cpupower/po/cs.po
index cb22c45c5069..bfc7e1702ec9 100644
--- a/tools/power/cpupower/po/cs.po
+++ b/tools/power/cpupower/po/cs.po
@@ -98,7 +98,7 @@ msgstr ""
#: utils/idle_monitor/cpupower-monitor.c:74
#, c-format
-msgid "\t -i: time intervall to measure for in seconds (default 1)\n"
+msgid "\t -i: time interval to measure for in seconds (default 1)\n"
msgstr ""
#: utils/idle_monitor/cpupower-monitor.c:75
diff --git a/tools/power/cpupower/po/de.po b/tools/power/cpupower/po/de.po
index 840c17cc450a..9780a447bb55 100644
--- a/tools/power/cpupower/po/de.po
+++ b/tools/power/cpupower/po/de.po
@@ -8,66 +8,66 @@ msgstr ""
"Project-Id-Version: cpufrequtils 006\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-03-08 17:03+0100\n"
-"PO-Revision-Date: 2009-08-08 17:18+0100\n"
-"Last-Translator: <linux@dominikbrodowski.net>\n"
+"PO-Revision-Date: 2019-06-02 15:23+0200\n"
+"Last-Translator: Benjamin Weis <benjamin.weis@gmx.com>\n"
"Language-Team: NONE\n"
"Language: \n"
"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: utils/idle_monitor/nhm_idle.c:36
msgid "Processor Core C3"
-msgstr ""
+msgstr "Prozessorkern C3"
#: utils/idle_monitor/nhm_idle.c:43
msgid "Processor Core C6"
-msgstr ""
+msgstr "Prozessorkern C6"
#: utils/idle_monitor/nhm_idle.c:51
msgid "Processor Package C3"
-msgstr ""
+msgstr "Prozessorpaket C3"
#: utils/idle_monitor/nhm_idle.c:58 utils/idle_monitor/amd_fam14h_idle.c:70
msgid "Processor Package C6"
-msgstr ""
+msgstr "Prozessorpaket C6"
#: utils/idle_monitor/snb_idle.c:33
msgid "Processor Core C7"
-msgstr ""
+msgstr "Prozessorkern C7"
#: utils/idle_monitor/snb_idle.c:40
msgid "Processor Package C2"
-msgstr ""
+msgstr "Prozessorpaket C2"
#: utils/idle_monitor/snb_idle.c:47
msgid "Processor Package C7"
-msgstr ""
+msgstr "Prozessorpaket C7"
#: utils/idle_monitor/amd_fam14h_idle.c:56
msgid "Package in sleep state (PC1 or deeper)"
-msgstr ""
+msgstr "Paket in Schlafzustand (PC1 oder tiefer)"
#: utils/idle_monitor/amd_fam14h_idle.c:63
msgid "Processor Package C1"
-msgstr ""
+msgstr "Prozessorpaket C1"
#: utils/idle_monitor/amd_fam14h_idle.c:77
msgid "North Bridge P1 boolean counter (returns 0 or 1)"
-msgstr ""
+msgstr "North Bridge P1 boolescher Zähler (gibt 0 oder 1 zurück)"
#: utils/idle_monitor/mperf_monitor.c:35
msgid "Processor Core not idle"
-msgstr ""
+msgstr "Prozessorkern ist nicht im Leerlauf"
#: utils/idle_monitor/mperf_monitor.c:42
msgid "Processor Core in an idle state"
-msgstr ""
+msgstr "Prozessorkern ist in einem Ruhezustand"
#: utils/idle_monitor/mperf_monitor.c:50
msgid "Average Frequency (including boost) in MHz"
-msgstr ""
+msgstr "Durchschnittliche Frequenz (einschlieĂźlich Boost) in MHz"
#: utils/idle_monitor/cpupower-monitor.c:66
#, c-format
@@ -75,6 +75,8 @@ msgid ""
"cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
"interval_sec | -c command ...]\n"
msgstr ""
+"cpupower monitor: [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
+"interval_sec | -c Befehl ...]\n"
#: utils/idle_monitor/cpupower-monitor.c:69
#, c-format
@@ -82,36 +84,40 @@ msgid ""
"cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
"interval_sec | -c command ...]\n"
msgstr ""
+"cpupower monitor: [-v] [-h] [ [-t] | [-l] | [-m <mon1>,[<mon2>] ] ] [-i "
+"interval_sec | -c Befehl ...]\n"
#: utils/idle_monitor/cpupower-monitor.c:71
#, c-format
msgid "\t -v: be more verbose\n"
-msgstr ""
+msgstr "\t -v: ausfĂĽhrlicher\n"
#: utils/idle_monitor/cpupower-monitor.c:73
#, c-format
msgid "\t -h: print this help\n"
-msgstr ""
+msgstr "\t -h: diese Hilfe ausgeben\n"
#: utils/idle_monitor/cpupower-monitor.c:74
#, c-format
-msgid "\t -i: time intervall to measure for in seconds (default 1)\n"
-msgstr ""
+msgid "\t -i: time interval to measure for in seconds (default 1)\n"
+msgstr "\t -i: Zeitintervall fĂĽr die Messung in Sekunden (Standard 1)\n"
#: utils/idle_monitor/cpupower-monitor.c:75
#, c-format
msgid "\t -t: show CPU topology/hierarchy\n"
-msgstr ""
+msgstr "\t -t: CPU-Topologie/Hierarchie anzeigen\n"
#: utils/idle_monitor/cpupower-monitor.c:76
#, c-format
msgid "\t -l: list available CPU sleep monitors (for use with -m)\n"
msgstr ""
+"\t -l: verfügbare CPU-Schlafwächter auflisten (für Verwendung mit -m)\n"
#: utils/idle_monitor/cpupower-monitor.c:77
#, c-format
msgid "\t -m: show specific CPU sleep monitors only (in same order)\n"
msgstr ""
+"\t -m: spezifische CPU-Schlafwächter anzeigen (in gleicher Reihenfolge)\n"
#: utils/idle_monitor/cpupower-monitor.c:79
#, c-format
@@ -119,71 +125,73 @@ msgid ""
"only one of: -t, -l, -m are allowed\n"
"If none of them is passed,"
msgstr ""
+"nur einer von: -t, -l, -m ist erlaubt\n"
+"Wenn keiner von ihnen ĂĽbergeben wird,"
#: utils/idle_monitor/cpupower-monitor.c:80
#, c-format
msgid " all supported monitors are shown\n"
-msgstr ""
+msgstr " werden alle unterstützten Wächter angezeigt\n"
#: utils/idle_monitor/cpupower-monitor.c:197
#, c-format
msgid "Monitor %s, Counter %s has no count function. Implementation error\n"
-msgstr ""
+msgstr "Wächter %s, Zähler %s hat keine Zählfunktion. Implementierungsfehler\n"
#: utils/idle_monitor/cpupower-monitor.c:207
#, c-format
msgid " *is offline\n"
-msgstr ""
+msgstr " *ist offline\n"
#: utils/idle_monitor/cpupower-monitor.c:236
#, c-format
msgid "%s: max monitor name length (%d) exceeded\n"
-msgstr ""
+msgstr "%s: max. Wächternamenslänge (%d) überschritten\n"
#: utils/idle_monitor/cpupower-monitor.c:250
#, c-format
msgid "No matching monitor found in %s, try -l option\n"
-msgstr ""
+msgstr "Kein passender Wächter in %s gefunden, versuchen Sie die Option -l\n"
#: utils/idle_monitor/cpupower-monitor.c:266
#, c-format
msgid "Monitor \"%s\" (%d states) - Might overflow after %u s\n"
-msgstr ""
+msgstr "Wächter \"%s\" (%d Zustände) - Könnte nach %u s überlaufen\n"
#: utils/idle_monitor/cpupower-monitor.c:319
#, c-format
msgid "%s took %.5f seconds and exited with status %d\n"
-msgstr ""
+msgstr "%s hat %.5f Sekunden gedauert und hat sich mit Status %d beendet\n"
#: utils/idle_monitor/cpupower-monitor.c:406
#, c-format
msgid "Cannot read number of available processors\n"
-msgstr ""
+msgstr "Anzahl der verfĂĽgbaren Prozessoren kann nicht gelesen werden\n"
#: utils/idle_monitor/cpupower-monitor.c:417
#, c-format
msgid "Available monitor %s needs root access\n"
-msgstr ""
+msgstr "Verfügbarer Wächter %s benötigt root-Zugriff\n"
#: utils/idle_monitor/cpupower-monitor.c:428
#, c-format
msgid "No HW Cstate monitors found\n"
-msgstr ""
+msgstr "Keine HW C-Zustandswächter gefunden\n"
#: utils/cpupower.c:78
#, c-format
msgid "cpupower [ -c cpulist ] subcommand [ARGS]\n"
-msgstr ""
+msgstr "cpupower [ -c cpulist ] Unterbefehl [ARGS]\n"
#: utils/cpupower.c:79
#, c-format
msgid "cpupower --version\n"
-msgstr ""
+msgstr "cpupower --version\n"
#: utils/cpupower.c:80
#, c-format
msgid "Supported subcommands are:\n"
-msgstr ""
+msgstr "UnterstĂĽtzte Unterbefehle sind:\n"
#: utils/cpupower.c:83
#, c-format
@@ -191,11 +199,15 @@ msgid ""
"\n"
"Some subcommands can make use of the -c cpulist option.\n"
msgstr ""
+"\n"
+"Einige Unterbefehle können die Option -c cpulist verwenden.\n"
#: utils/cpupower.c:84
#, c-format
msgid "Look at the general cpupower manpage how to use it\n"
msgstr ""
+"Schauen Sie sich die allgemeine cpupower manpage an, um zu erfahren, wie man "
+"es benutzt\n"
#: utils/cpupower.c:85
#, c-format
@@ -217,30 +229,31 @@ msgstr "Bitte melden Sie Fehler an %s.\n"
#: utils/cpupower.c:114
#, c-format
msgid "Error parsing cpu list\n"
-msgstr ""
+msgstr "Fehler beim Parsen der CPU-Liste\n"
#: utils/cpupower.c:172
#, c-format
msgid "Subcommand %s needs root privileges\n"
-msgstr ""
+msgstr "Unterbefehl %s benötigt root-Rechte\n"
#: utils/cpufreq-info.c:31
#, c-format
msgid "Couldn't count the number of CPUs (%s: %s), assuming 1\n"
msgstr ""
-"Konnte nicht die Anzahl der CPUs herausfinden (%s : %s), nehme daher 1 an.\n"
+"Anzahl der CPUs konnte nicht herausgefinden werden (%s: %s), es wird daher 1 "
+"angenommen\n"
#: utils/cpufreq-info.c:63
#, c-format
msgid ""
" minimum CPU frequency - maximum CPU frequency - governor\n"
-msgstr ""
-" minimale CPU-Taktfreq. - maximale CPU-Taktfreq. - Regler \n"
+msgstr " minimale CPU-Frequenz - maximale CPU-Frequenz - Regler\n"
#: utils/cpufreq-info.c:151
#, c-format
msgid "Error while evaluating Boost Capabilities on CPU %d -- are you root?\n"
msgstr ""
+"Fehler beim Evaluieren der Boost-Fähigkeiten bei CPU %d -- sind Sie root?\n"
#. P state changes via MSR are identified via cpuid 80000007
#. on Intel and AMD, but we assume boost capable machines can do that
@@ -250,50 +263,50 @@ msgstr ""
#: utils/cpufreq-info.c:161
#, c-format
msgid " boost state support: \n"
-msgstr ""
+msgstr " Boost-Zustand-UnterstĂĽtzung: \n"
#: utils/cpufreq-info.c:163
#, c-format
msgid " Supported: %s\n"
-msgstr ""
+msgstr " UnterstĂĽtzt: %s\n"
#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
msgid "yes"
-msgstr ""
+msgstr "ja"
#: utils/cpufreq-info.c:163 utils/cpufreq-info.c:164
msgid "no"
-msgstr ""
+msgstr "nein"
#: utils/cpufreq-info.c:164
-#, fuzzy, c-format
+#, c-format
msgid " Active: %s\n"
-msgstr " Treiber: %s\n"
+msgstr " Aktiv: %s\n"
#: utils/cpufreq-info.c:177
#, c-format
msgid " Boost States: %d\n"
-msgstr ""
+msgstr " Boost-Zustände: %d\n"
#: utils/cpufreq-info.c:178
#, c-format
msgid " Total States: %d\n"
-msgstr ""
+msgstr " Gesamtzustände: %d\n"
#: utils/cpufreq-info.c:181
#, c-format
msgid " Pstate-Pb%d: %luMHz (boost state)\n"
-msgstr ""
+msgstr " Pstate-Pb%d: %luMHz (Boost-Zustand)\n"
#: utils/cpufreq-info.c:184
#, c-format
msgid " Pstate-P%d: %luMHz\n"
-msgstr ""
+msgstr " Pstate-P%d: %luMHz\n"
#: utils/cpufreq-info.c:211
#, c-format
msgid " no or unknown cpufreq driver is active on this CPU\n"
-msgstr " kein oder nicht bestimmbarer cpufreq-Treiber aktiv\n"
+msgstr " kein oder ein unbekannter cpufreq-Treiber ist auf dieser CPU aktiv\n"
#: utils/cpufreq-info.c:213
#, c-format
@@ -303,12 +316,12 @@ msgstr " Treiber: %s\n"
#: utils/cpufreq-info.c:219
#, c-format
msgid " CPUs which run at the same hardware frequency: "
-msgstr " Folgende CPUs laufen mit der gleichen Hardware-Taktfrequenz: "
+msgstr " CPUs, die mit der gleichen Hardwarefrequenz laufen: "
#: utils/cpufreq-info.c:230
#, c-format
msgid " CPUs which need to have their frequency coordinated by software: "
-msgstr " Die Taktfrequenz folgender CPUs werden per Software koordiniert: "
+msgstr " CPUs, die ihre Frequenz mit Software koordinieren mĂĽssen: "
#: utils/cpufreq-info.c:241
#, c-format
@@ -318,22 +331,22 @@ msgstr " Maximale Dauer eines Taktfrequenzwechsels: "
#: utils/cpufreq-info.c:247
#, c-format
msgid " hardware limits: "
-msgstr " Hardwarebedingte Grenzen der Taktfrequenz: "
+msgstr " Hardwarebegrenzungen: "
#: utils/cpufreq-info.c:256
#, c-format
msgid " available frequency steps: "
-msgstr " mögliche Taktfrequenzen: "
+msgstr " verfĂĽgbare Frequenzschritte: "
#: utils/cpufreq-info.c:269
#, c-format
msgid " available cpufreq governors: "
-msgstr " mögliche Regler: "
+msgstr " verfĂĽgbare cpufreq-Regler: "
#: utils/cpufreq-info.c:280
#, c-format
msgid " current policy: frequency should be within "
-msgstr " momentane Taktik: die Frequenz soll innerhalb "
+msgstr " momentane Richtlinie: Frequenz sollte innerhalb "
#: utils/cpufreq-info.c:282
#, c-format
@@ -346,29 +359,28 @@ msgid ""
"The governor \"%s\" may decide which speed to use\n"
" within this range.\n"
msgstr ""
-" liegen. Der Regler \"%s\" kann frei entscheiden,\n"
-" welche Taktfrequenz innerhalb dieser Grenze verwendet "
-"wird.\n"
+" sein. Der Regler \"%s\" kann frei entscheiden,\n"
+" welche Geschwindigkeit er in diesem Bereich verwendet.\n"
#: utils/cpufreq-info.c:293
#, c-format
msgid " current CPU frequency is "
-msgstr " momentane Taktfrequenz ist "
+msgstr " momentane CPU-Frequenz ist "
#: utils/cpufreq-info.c:296
#, c-format
msgid " (asserted by call to hardware)"
-msgstr " (verifiziert durch Nachfrage bei der Hardware)"
+msgstr " (durch Aufruf der Hardware sichergestellt)"
#: utils/cpufreq-info.c:304
#, c-format
msgid " cpufreq stats: "
-msgstr " Statistik:"
+msgstr " cpufreq-Statistiken: "
#: utils/cpufreq-info.c:472
-#, fuzzy, c-format
+#, c-format
msgid "Usage: cpupower freqinfo [options]\n"
-msgstr "Aufruf: cpufreq-info [Optionen]\n"
+msgstr "Aufruf: cpupower freqinfo [Optionen]\n"
#: utils/cpufreq-info.c:473 utils/cpufreq-set.c:26 utils/cpupower-set.c:23
#: utils/cpupower-info.c:22 utils/cpuidle-info.c:148
@@ -377,11 +389,9 @@ msgid "Options:\n"
msgstr "Optionen:\n"
#: utils/cpufreq-info.c:474
-#, fuzzy, c-format
+#, c-format
msgid " -e, --debug Prints out debug information [default]\n"
-msgstr ""
-" -e, --debug Erzeugt detaillierte Informationen, hilfreich\n"
-" zum AufspĂĽren von Fehlern\n"
+msgstr " -e, --debug Gibt Debug-Informationen aus [Standard]\n"
#: utils/cpufreq-info.c:475
#, c-format
@@ -424,7 +434,7 @@ msgstr " -p, --policy Findet die momentane Taktik heraus *\n"
#: utils/cpufreq-info.c:482
#, c-format
msgid " -g, --governors Determines available cpufreq governors *\n"
-msgstr " -g, --governors Erzeugt eine Liste mit verfĂĽgbaren Reglern *\n"
+msgstr " -g, --governors Ermittelt verfĂĽgbare cpufreq-Regler *\n"
#: utils/cpufreq-info.c:483
#, c-format
@@ -449,8 +459,7 @@ msgstr ""
#: utils/cpufreq-info.c:486
#, c-format
msgid " -s, --stats Shows cpufreq statistics if available\n"
-msgstr ""
-" -s, --stats Zeigt, sofern möglich, Statistiken über cpufreq an.\n"
+msgstr " -s, --stats Zeigt cpufreq-Statistiken an, falls vorhanden\n"
#: utils/cpufreq-info.c:487
#, c-format
@@ -464,13 +473,13 @@ msgstr ""
#: utils/cpufreq-info.c:488
#, c-format
msgid " -b, --boost Checks for turbo or boost modes *\n"
-msgstr ""
+msgstr " -b, --boost PrĂĽft auf Turbo- oder Boost-Modi *\n"
#: utils/cpufreq-info.c:489
#, c-format
msgid ""
-" -o, --proc Prints out information like provided by the /proc/"
-"cpufreq\n"
+" -o, --proc Prints out information like provided by the "
+"/proc/cpufreq\n"
" interface in 2.4. and early 2.6. kernels\n"
msgstr ""
" -o, --proc Erzeugt Informationen in einem ähnlichem Format zu "
@@ -509,8 +518,8 @@ msgid ""
"For the arguments marked with *, omitting the -c or --cpu argument is\n"
"equivalent to setting it to zero\n"
msgstr ""
-"Bei den mit * markierten Parametern wird '--cpu 0' angenommen, soweit nicht\n"
-"mittels -c oder --cpu etwas anderes angegeben wird\n"
+"FĂĽr die mit * markierten Argumente ist das Weglassen des Arguments\n"
+"-c oder --cpu gleichbedeutend mit der Einstellung auf Null\n"
#: utils/cpufreq-info.c:580
#, c-format
@@ -525,8 +534,8 @@ msgid ""
"You can't specify more than one --cpu parameter and/or\n"
"more than one output-specific argument\n"
msgstr ""
-"Man kann nicht mehr als einen --cpu-Parameter und/oder mehr als einen\n"
-"informationsspezifischen Parameter gleichzeitig angeben\n"
+"Sie können nicht mehr als einen Parameter --cpu und/oder\n"
+"mehr als ein ausgabespezifisches Argument angeben\n"
#: utils/cpufreq-info.c:600 utils/cpufreq-set.c:82 utils/cpupower-set.c:42
#: utils/cpupower-info.c:42 utils/cpuidle-info.c:213
@@ -538,17 +547,17 @@ msgstr "unbekannter oder falscher Parameter\n"
#, c-format
msgid "couldn't analyze CPU %d as it doesn't seem to be present\n"
msgstr ""
-"Konnte nicht die CPU %d analysieren, da sie (scheinbar?) nicht existiert.\n"
+"CPU %d konnte nicht analysiert werden, da sie scheinbar nicht existiert\n"
#: utils/cpufreq-info.c:620 utils/cpupower-info.c:142
#, c-format
msgid "analyzing CPU %d:\n"
-msgstr "analysiere CPU %d:\n"
+msgstr "CPU %d wird analysiert:\n"
#: utils/cpufreq-set.c:25
-#, fuzzy, c-format
+#, c-format
msgid "Usage: cpupower frequency-set [options]\n"
-msgstr "Aufruf: cpufreq-set [Optionen]\n"
+msgstr "Aufruf: cpupower frequency-set [Optionen]\n"
#: utils/cpufreq-set.c:27
#, c-format
@@ -556,7 +565,7 @@ msgid ""
" -d FREQ, --min FREQ new minimum CPU frequency the governor may "
"select\n"
msgstr ""
-" -d FREQ, --min FREQ neue minimale Taktfrequenz, die der Regler\n"
+" -d FREQ, --min FREQ neue minimale CPU-Frequenz, die der Regler\n"
" auswählen darf\n"
#: utils/cpufreq-set.c:28
@@ -571,7 +580,7 @@ msgstr ""
#: utils/cpufreq-set.c:29
#, c-format
msgid " -g GOV, --governor GOV new cpufreq governor\n"
-msgstr " -g GOV, --governors GOV wechsle zu Regler GOV\n"
+msgstr " -g GOV, --governors GOV neuer cpufreq-Regler\n"
#: utils/cpufreq-set.c:30
#, c-format
@@ -579,29 +588,29 @@ msgid ""
" -f FREQ, --freq FREQ specific frequency to be set. Requires userspace\n"
" governor to be available and loaded\n"
msgstr ""
-" -f FREQ, --freq FREQ setze exakte Taktfrequenz. Benötigt den Regler\n"
-" 'userspace'.\n"
+" -f FREQ, --freq FREQ bestimmte Frequenz, die eingestellt werden soll.\n"
+" Erfordert einen verfĂĽgbaren und geladenen "
+"userspace-Regler\n"
#: utils/cpufreq-set.c:32
#, c-format
msgid " -r, --related Switches all hardware-related CPUs\n"
-msgstr ""
-" -r, --related Setze Werte fĂĽr alle CPUs, deren Taktfrequenz\n"
-" hardwarebedingt identisch ist.\n"
+msgstr " -r, --related Schaltet alle hardwarebezogenen CPUs um\n"
#: utils/cpufreq-set.c:33 utils/cpupower-set.c:28 utils/cpupower-info.c:27
#, c-format
msgid " -h, --help Prints out this screen\n"
-msgstr " -h, --help Gibt diese KurzĂĽbersicht aus\n"
+msgstr " -h, --help Gibt diesen Bildschirm aus\n"
#: utils/cpufreq-set.c:35
-#, fuzzy, c-format
+#, c-format
msgid ""
"Notes:\n"
"1. Omitting the -c or --cpu argument is equivalent to setting it to \"all\"\n"
msgstr ""
-"Bei den mit * markierten Parametern wird '--cpu 0' angenommen, soweit nicht\n"
-"mittels -c oder --cpu etwas anderes angegeben wird\n"
+"Hinweis:\n"
+"1. Das Weglassen des Arguments -c oder --cpu ist gleichbedeutend mit der "
+"Einstellung auf \"all\"\n"
#: utils/cpufreq-set.c:37
#, fuzzy, c-format
@@ -636,17 +645,21 @@ msgid ""
"frequency\n"
" or because the userspace governor isn't loaded?\n"
msgstr ""
-"Beim Einstellen ist ein Fehler aufgetreten. Typische Fehlerquellen sind:\n"
-"- nicht ausreichende Rechte (Administrator)\n"
-"- der Regler ist nicht verfĂĽgbar bzw. nicht geladen\n"
-"- die angegebene Taktik ist inkorrekt\n"
-"- eine spezifische Frequenz wurde angegeben, aber der Regler 'userspace'\n"
-" kann entweder hardwarebedingt nicht genutzt werden oder ist nicht geladen\n"
+"Fehler beim Festlegen neuer Werte. Häufige Fehler:\n"
+"- VerfĂĽgen Sie ĂĽber die erforderlichen Administrationsrechte? (Superuser?)\n"
+"- Ist der von Ihnen gewĂĽnschte Regler verfĂĽgbar und mittels modprobe "
+"geladen?\n"
+"- Versuchen Sie eine ungĂĽltige Richtlinie festzulegen?\n"
+"- Versuchen Sie eine bestimmte Frequenz festzulegen, aber der "
+"userspace-Regler ist nicht verfĂĽgbar,\n"
+" z.B. wegen Hardware, die nicht auf eine bestimmte Frequenz eingestellt "
+"werden kann\n"
+" oder weil der userspace-Regler nicht geladen ist?\n"
#: utils/cpufreq-set.c:170
#, c-format
msgid "wrong, unknown or unhandled CPU?\n"
-msgstr "unbekannte oder nicht regelbare CPU\n"
+msgstr "falsche, unbekannte oder nicht regelbare CPU?\n"
#: utils/cpufreq-set.c:302
#, c-format
@@ -654,8 +667,8 @@ msgid ""
"the -f/--freq parameter cannot be combined with -d/--min, -u/--max or\n"
"-g/--governor parameters\n"
msgstr ""
-"Der -f bzw. --freq-Parameter kann nicht mit den Parametern -d/--min, -u/--"
-"max\n"
+"Der -f bzw. --freq-Parameter kann nicht mit den Parametern -d/--min, "
+"-u/--max\n"
"oder -g/--governor kombiniert werden\n"
#: utils/cpufreq-set.c:308
@@ -664,18 +677,18 @@ msgid ""
"At least one parameter out of -f/--freq, -d/--min, -u/--max, and\n"
"-g/--governor must be passed\n"
msgstr ""
-"Es muss mindestens ein Parameter aus -f/--freq, -d/--min, -u/--max oder\n"
-"-g/--governor angegeben werden.\n"
+"Mindestens ein Parameter aus -f/--freq, -d/--min, -u/--max und\n"
+"-g/--governor muss ĂĽbergeben werden\n"
#: utils/cpufreq-set.c:347
#, c-format
msgid "Setting cpu: %d\n"
-msgstr ""
+msgstr "CPU einstellen: %d\n"
#: utils/cpupower-set.c:22
#, c-format
msgid "Usage: cpupower set [ -b val ] [ -m val ] [ -s val ]\n"
-msgstr ""
+msgstr "Aufruf: cpupower set [ -b val ] [ -m val ] [ -s val ]\n"
#: utils/cpupower-set.c:24
#, c-format
@@ -689,6 +702,8 @@ msgstr ""
msgid ""
" -m, --sched-mc [VAL] Sets the kernel's multi core scheduler policy.\n"
msgstr ""
+" -m, --sched-mc [VAL] Legt die Mehrkern-Scheduler-Richtlinie des "
+"Kernels fest.\n"
#: utils/cpupower-set.c:27
#, c-format
@@ -700,37 +715,37 @@ msgstr ""
#: utils/cpupower-set.c:80
#, c-format
msgid "--perf-bias param out of range [0-%d]\n"
-msgstr ""
+msgstr "--perf-bias-Parameter auĂźerhalb des Bereichs [0-%d]\n"
#: utils/cpupower-set.c:91
#, c-format
msgid "--sched-mc param out of range [0-%d]\n"
-msgstr ""
+msgstr "Parameter --sched-mc auĂźerhalb des Bereichs [0-%d]\n"
#: utils/cpupower-set.c:102
#, c-format
msgid "--sched-smt param out of range [0-%d]\n"
-msgstr ""
+msgstr "Parameter --sched-smt auĂźerhalb des Bereichs [0-%d]\n"
#: utils/cpupower-set.c:121
#, c-format
msgid "Error setting sched-mc %s\n"
-msgstr ""
+msgstr "Fehler beim Einstellen von sched-mc %s\n"
#: utils/cpupower-set.c:127
#, c-format
msgid "Error setting sched-smt %s\n"
-msgstr ""
+msgstr "Fehler beim Einstellen von sched-smt %s\n"
#: utils/cpupower-set.c:146
#, c-format
msgid "Error setting perf-bias value on CPU %d\n"
-msgstr ""
+msgstr "Fehler beim Einstellen des perf-bias-Wertes auf der CPU %d\n"
#: utils/cpupower-info.c:21
#, c-format
msgid "Usage: cpupower info [ -b ] [ -m ] [ -s ]\n"
-msgstr ""
+msgstr "Aufruf: cpupower info [ -b ] [ -m ] [ -s ]\n"
#: utils/cpupower-info.c:23
#, c-format
@@ -740,9 +755,10 @@ msgid ""
msgstr ""
#: utils/cpupower-info.c:25
-#, fuzzy, c-format
+#, c-format
msgid " -m, --sched-mc Gets the kernel's multi core scheduler policy.\n"
-msgstr " -p, --policy Findet die momentane Taktik heraus *\n"
+msgstr ""
+" -m, --sched-mc Ruft die Mehrkern-Scheduler-Richtlinie des Kernels ab.\n"
#: utils/cpupower-info.c:26
#, c-format
@@ -756,17 +772,20 @@ msgid ""
"\n"
"Passing no option will show all info, by default only on core 0\n"
msgstr ""
+"\n"
+"Wenn Sie keine Option ĂĽbergeben, werden alle Informationen angezeigt, "
+"standardmäßig nur auf Kern 0\n"
#: utils/cpupower-info.c:102
#, c-format
msgid "System's multi core scheduler setting: "
-msgstr ""
+msgstr "Mehrkern-Scheduler-Einstellung des Systems: "
#. if sysfs file is missing it's: errno == ENOENT
#: utils/cpupower-info.c:105 utils/cpupower-info.c:114
#, c-format
msgid "not supported\n"
-msgstr ""
+msgstr "nicht unterstĂĽtzt\n"
#: utils/cpupower-info.c:111
#, c-format
@@ -786,164 +805,161 @@ msgstr ""
#: utils/cpupower-info.c:147
#, c-format
msgid "Could not read perf-bias value\n"
-msgstr ""
+msgstr "perf-bias-Wert konnte nicht gelesen werden\n"
#: utils/cpupower-info.c:150
#, c-format
msgid "perf-bias: %d\n"
-msgstr ""
+msgstr "perf-bias: %d\n"
#: utils/cpuidle-info.c:28
-#, fuzzy, c-format
+#, c-format
msgid "Analyzing CPU %d:\n"
-msgstr "analysiere CPU %d:\n"
+msgstr "CPU %d wird analysiert:\n"
#: utils/cpuidle-info.c:32
#, c-format
msgid "CPU %u: No idle states\n"
-msgstr ""
+msgstr "CPU %u: Keine Ruhezustände\n"
#: utils/cpuidle-info.c:36
#, c-format
msgid "CPU %u: Can't read idle state info\n"
-msgstr ""
+msgstr "CPU %u: Ruhezustands-Informationen können nicht gelesen werden\n"
#: utils/cpuidle-info.c:41
#, c-format
msgid "Could not determine max idle state %u\n"
-msgstr ""
+msgstr "Max. Ruhezustand %u konnte nicht bestimmt werden\n"
#: utils/cpuidle-info.c:46
#, c-format
msgid "Number of idle states: %d\n"
-msgstr ""
+msgstr "Anzahl der Ruhezustände: %d\n"
#: utils/cpuidle-info.c:48
-#, fuzzy, c-format
+#, c-format
msgid "Available idle states:"
-msgstr " mögliche Taktfrequenzen: "
+msgstr "Verfügbare Ruhezustände:"
#: utils/cpuidle-info.c:71
#, c-format
msgid "Flags/Description: %s\n"
-msgstr ""
+msgstr "Merker/Beschreibung: %s\n"
#: utils/cpuidle-info.c:74
#, c-format
msgid "Latency: %lu\n"
-msgstr ""
+msgstr "Latenz: %lu\n"
#: utils/cpuidle-info.c:76
#, c-format
msgid "Usage: %lu\n"
-msgstr ""
+msgstr "Aufruf: %lu\n"
#: utils/cpuidle-info.c:78
#, c-format
msgid "Duration: %llu\n"
-msgstr ""
+msgstr "Dauer: %llu\n"
#: utils/cpuidle-info.c:90
#, c-format
msgid "Could not determine cpuidle driver\n"
-msgstr ""
+msgstr "cpuidle-Treiber konnte nicht bestimmt werden\n"
#: utils/cpuidle-info.c:94
-#, fuzzy, c-format
+#, c-format
msgid "CPUidle driver: %s\n"
-msgstr " Treiber: %s\n"
+msgstr "CPUidle-Treiber: %s\n"
#: utils/cpuidle-info.c:99
#, c-format
msgid "Could not determine cpuidle governor\n"
-msgstr ""
+msgstr "cpuidle-Regler konnte nicht bestimmt werden\n"
#: utils/cpuidle-info.c:103
#, c-format
msgid "CPUidle governor: %s\n"
-msgstr ""
+msgstr "CPUidle-Regler: %s\n"
#: utils/cpuidle-info.c:122
#, c-format
msgid "CPU %u: Can't read C-state info\n"
-msgstr ""
+msgstr "CPU %u: C-Zustands-Informationen können nicht gelesen werden\n"
#. printf("Cstates: %d\n", cstates);
#: utils/cpuidle-info.c:127
#, c-format
msgid "active state: C0\n"
-msgstr ""
+msgstr "aktiver Zustand: C0\n"
#: utils/cpuidle-info.c:128
#, c-format
msgid "max_cstate: C%u\n"
-msgstr ""
+msgstr "max_cstate: C%u\n"
#: utils/cpuidle-info.c:129
-#, fuzzy, c-format
+#, c-format
msgid "maximum allowed latency: %lu usec\n"
-msgstr " Maximale Dauer eines Taktfrequenzwechsels: "
+msgstr "maximal erlaubte Latenz: %lu usec\n"
#: utils/cpuidle-info.c:130
#, c-format
msgid "states:\t\n"
-msgstr ""
+msgstr "Zustände:\t\n"
#: utils/cpuidle-info.c:132
#, c-format
msgid " C%d: type[C%d] "
-msgstr ""
+msgstr " C%d: Typ[C%d] "
#: utils/cpuidle-info.c:134
#, c-format
msgid "promotion[--] demotion[--] "
-msgstr ""
+msgstr "promotion[--] demotion[--] "
#: utils/cpuidle-info.c:135
#, c-format
msgid "latency[%03lu] "
-msgstr ""
+msgstr "Latenz[%03lu] "
#: utils/cpuidle-info.c:137
#, c-format
msgid "usage[%08lu] "
-msgstr ""
+msgstr "Aufruf[%08lu] "
#: utils/cpuidle-info.c:139
#, c-format
msgid "duration[%020Lu] \n"
-msgstr ""
+msgstr "Dauer[%020Lu] \n"
#: utils/cpuidle-info.c:147
-#, fuzzy, c-format
+#, c-format
msgid "Usage: cpupower idleinfo [options]\n"
-msgstr "Aufruf: cpufreq-info [Optionen]\n"
+msgstr "Aufruf: cpupower idleinfo [Optionen]\n"
#: utils/cpuidle-info.c:149
-#, fuzzy, c-format
+#, c-format
msgid " -s, --silent Only show general C-state information\n"
msgstr ""
-" -e, --debug Erzeugt detaillierte Informationen, hilfreich\n"
-" zum AufspĂĽren von Fehlern\n"
+" -s, --silent Nur allgemeine C-Zustands-Informationen anzeigen\n"
#: utils/cpuidle-info.c:150
-#, fuzzy, c-format
+#, c-format
msgid ""
-" -o, --proc Prints out information like provided by the /proc/"
-"acpi/processor/*/power\n"
+" -o, --proc Prints out information like provided by the "
+"/proc/acpi/processor/*/power\n"
" interface in older kernels\n"
msgstr ""
-" -o, --proc Erzeugt Informationen in einem ähnlichem Format zu "
-"dem\n"
-" der /proc/cpufreq-Datei in 2.4. und frĂĽhen 2.6.\n"
-" Kernel-Versionen\n"
+" -o, --proc Gibt Informationen so aus, wie sie von der "
+"Schnittstelle\n"
+" /proc/acpi/processor/*/power in älteren Kerneln "
+"bereitgestellt werden\n"
#: utils/cpuidle-info.c:209
-#, fuzzy, c-format
+#, c-format
msgid "You can't specify more than one output-specific argument\n"
-msgstr ""
-"Man kann nicht mehr als einen --cpu-Parameter und/oder mehr als einen\n"
-"informationsspezifischen Parameter gleichzeitig angeben\n"
+msgstr "Sie können nicht mehr als ein ausgabenspezifisches Argument angeben\n"
#~ msgid ""
#~ " -c CPU, --cpu CPU CPU number which information shall be determined "
@@ -956,6 +972,6 @@ msgstr ""
#~ " -c CPU, --cpu CPU number of CPU where cpufreq settings shall be "
#~ "modified\n"
#~ msgstr ""
-#~ " -c CPU, --cpu CPU Nummer der CPU, deren Taktfrequenz-"
-#~ "Einstellung\n"
+#~ " -c CPU, --cpu CPU Nummer der CPU, deren "
+#~ "Taktfrequenz-Einstellung\n"
#~ " werden soll\n"
diff --git a/tools/power/cpupower/po/fr.po b/tools/power/cpupower/po/fr.po
index b46ca2548f86..b6e505b34e4a 100644
--- a/tools/power/cpupower/po/fr.po
+++ b/tools/power/cpupower/po/fr.po
@@ -95,7 +95,7 @@ msgstr ""
#: utils/idle_monitor/cpupower-monitor.c:74
#, c-format
-msgid "\t -i: time intervall to measure for in seconds (default 1)\n"
+msgid "\t -i: time interval to measure for in seconds (default 1)\n"
msgstr ""
#: utils/idle_monitor/cpupower-monitor.c:75
diff --git a/tools/power/cpupower/po/it.po b/tools/power/cpupower/po/it.po
index f80c4ddb9bda..a1deeb52c9e0 100644
--- a/tools/power/cpupower/po/it.po
+++ b/tools/power/cpupower/po/it.po
@@ -95,7 +95,7 @@ msgstr ""
#: utils/idle_monitor/cpupower-monitor.c:74
#, c-format
-msgid "\t -i: time intervall to measure for in seconds (default 1)\n"
+msgid "\t -i: time interval to measure for in seconds (default 1)\n"
msgstr ""
#: utils/idle_monitor/cpupower-monitor.c:75
diff --git a/tools/power/cpupower/po/pt.po b/tools/power/cpupower/po/pt.po
index 990f5267ffe8..902186585bb9 100644
--- a/tools/power/cpupower/po/pt.po
+++ b/tools/power/cpupower/po/pt.po
@@ -93,7 +93,7 @@ msgstr ""
#: utils/idle_monitor/cpupower-monitor.c:74
#, c-format
-msgid "\t -i: time intervall to measure for in seconds (default 1)\n"
+msgid "\t -i: time interval to measure for in seconds (default 1)\n"
msgstr ""
#: utils/idle_monitor/cpupower-monitor.c:75
diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c
index 10290b308797..e63cf55f81cf 100644
--- a/tools/power/cpupower/utils/cpufreq-info.c
+++ b/tools/power/cpupower/utils/cpufreq-info.c
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
- *
- * Licensed under the terms of the GNU GPL License version 2.
*/
diff --git a/tools/power/cpupower/utils/cpufreq-set.c b/tools/power/cpupower/utils/cpufreq-set.c
index 1eef0aed6423..6ed82fba5aaa 100644
--- a/tools/power/cpupower/utils/cpufreq-set.c
+++ b/tools/power/cpupower/utils/cpufreq-set.c
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
- *
- * Licensed under the terms of the GNU GPL License version 2.
*/
@@ -306,6 +305,8 @@ int cmd_freq_set(int argc, char **argv)
bitmask_setbit(cpus_chosen, cpus->cpu);
cpus = cpus->next;
}
+ /* Set the last cpu in related cpus list */
+ bitmask_setbit(cpus_chosen, cpus->cpu);
cpufreq_put_related_cpus(cpus);
}
}
diff --git a/tools/power/cpupower/utils/cpuidle-info.c b/tools/power/cpupower/utils/cpuidle-info.c
index b59c85defa05..f2b202c5552a 100644
--- a/tools/power/cpupower/utils/cpuidle-info.c
+++ b/tools/power/cpupower/utils/cpuidle-info.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
* (C) 2010 Thomas Renninger <trenn@suse.de>
- *
- * Licensed under the terms of the GNU GPL License version 2.
*/
diff --git a/tools/power/cpupower/utils/cpupower-info.c b/tools/power/cpupower/utils/cpupower-info.c
index c7caa8eaa6d0..d3755ea70d4d 100644
--- a/tools/power/cpupower/utils/cpupower-info.c
+++ b/tools/power/cpupower/utils/cpupower-info.c
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* (C) 2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
- *
- * Licensed under the terms of the GNU GPL License version 2.
*/
@@ -11,6 +10,7 @@
#include <errno.h>
#include <string.h>
#include <getopt.h>
+#include <sys/utsname.h>
#include "helpers/helpers.h"
#include "helpers/sysfs.h"
@@ -31,6 +31,7 @@ int cmd_info(int argc, char **argv)
extern char *optarg;
extern int optind, opterr, optopt;
unsigned int cpu;
+ struct utsname uts;
union {
struct {
@@ -40,6 +41,13 @@ int cmd_info(int argc, char **argv)
} params = {};
int ret = 0;
+ ret = uname(&uts);
+ if (!ret && (!strcmp(uts.machine, "ppc64le") ||
+ !strcmp(uts.machine, "ppc64"))) {
+ fprintf(stderr, _("Subcommand not supported on POWER.\n"));
+ return ret;
+ }
+
setlocale(LC_ALL, "");
textdomain(PACKAGE);
diff --git a/tools/power/cpupower/utils/cpupower-set.c b/tools/power/cpupower/utils/cpupower-set.c
index 532f46b9a335..3cca6f715dd9 100644
--- a/tools/power/cpupower/utils/cpupower-set.c
+++ b/tools/power/cpupower/utils/cpupower-set.c
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* (C) 2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
- *
- * Licensed under the terms of the GNU GPL License version 2.
*/
@@ -11,6 +10,7 @@
#include <errno.h>
#include <string.h>
#include <getopt.h>
+#include <sys/utsname.h>
#include "helpers/helpers.h"
#include "helpers/sysfs.h"
@@ -32,6 +32,7 @@ int cmd_set(int argc, char **argv)
extern char *optarg;
extern int optind, opterr, optopt;
unsigned int cpu;
+ struct utsname uts;
union {
struct {
@@ -42,6 +43,13 @@ int cmd_set(int argc, char **argv)
int perf_bias = 0;
int ret = 0;
+ ret = uname(&uts);
+ if (!ret && (!strcmp(uts.machine, "ppc64le") ||
+ !strcmp(uts.machine, "ppc64"))) {
+ fprintf(stderr, _("Subcommand not supported on POWER.\n"));
+ return ret;
+ }
+
setlocale(LC_ALL, "");
textdomain(PACKAGE);
diff --git a/tools/power/cpupower/utils/cpupower.c b/tools/power/cpupower/utils/cpupower.c
index 2dccf4998599..8e3d08042825 100644
--- a/tools/power/cpupower/utils/cpupower.c
+++ b/tools/power/cpupower/utils/cpupower.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
*
- * Licensed under the terms of the GNU GPL License version 2.
- *
* Ideas taken over from the perf userspace tool (included in the Linus
* kernel git repo): subcommand builtins and param parsing.
*/
diff --git a/tools/power/cpupower/utils/helpers/cpuid.c b/tools/power/cpupower/utils/helpers/cpuid.c
index 5cc39d4e23ed..73bfafc60e9b 100644
--- a/tools/power/cpupower/utils/helpers/cpuid.c
+++ b/tools/power/cpupower/utils/helpers/cpuid.c
@@ -131,6 +131,10 @@ out:
if (ext_cpuid_level >= 0x80000007 &&
(cpuid_edx(0x80000007) & (1 << 9)))
cpu_info->caps |= CPUPOWER_CAP_AMD_CBP;
+
+ if (ext_cpuid_level >= 0x80000008 &&
+ cpuid_ebx(0x80000008) & (1 << 4))
+ cpu_info->caps |= CPUPOWER_CAP_AMD_RDPRU;
}
if (cpu_info->vendor == X86_VENDOR_INTEL) {
diff --git a/tools/power/cpupower/utils/helpers/helpers.h b/tools/power/cpupower/utils/helpers/helpers.h
index 902139689315..c258eeccd05f 100644
--- a/tools/power/cpupower/utils/helpers/helpers.h
+++ b/tools/power/cpupower/utils/helpers/helpers.h
@@ -1,8 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
*
- * Licensed under the terms of the GNU GPL License version 2.
- *
* Miscellaneous helpers which do not fit or are worth
* to put into separate headers
*/
@@ -70,6 +69,7 @@ enum cpupower_cpu_vendor {X86_VENDOR_UNKNOWN = 0, X86_VENDOR_INTEL,
#define CPUPOWER_CAP_HAS_TURBO_RATIO 0x00000010
#define CPUPOWER_CAP_IS_SNB 0x00000020
#define CPUPOWER_CAP_INTEL_IDA 0x00000040
+#define CPUPOWER_CAP_AMD_RDPRU 0x00000080
#define CPUPOWER_AMD_CPBDIS 0x02000000
diff --git a/tools/power/cpupower/utils/helpers/sysfs.c b/tools/power/cpupower/utils/helpers/sysfs.c
index 4e8fe2c7b054..e13ff38329a0 100644
--- a/tools/power/cpupower/utils/helpers/sysfs.c
+++ b/tools/power/cpupower/utils/helpers/sysfs.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* (C) 2004-2009 Dominik Brodowski <linux@dominikbrodowski.de>
* (C) 2011 Thomas Renninger <trenn@novell.com> Novell Inc.
- *
- * Licensed under the terms of the GNU GPL License version 2.
*/
#include <stdio.h>
diff --git a/tools/power/cpupower/utils/helpers/topology.c b/tools/power/cpupower/utils/helpers/topology.c
index a1a6c6041a1e..3dd0925d7594 100644
--- a/tools/power/cpupower/utils/helpers/topology.c
+++ b/tools/power/cpupower/utils/helpers/topology.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
*
- * Licensed under the terms of the GNU GPL License version 2.
- *
* ToDo: Needs to be done more properly for AMD/Intel specifics
*/
diff --git a/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c b/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c
index 2116df9ad832..33dc34db4f3c 100644
--- a/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c
+++ b/tools/power/cpupower/utils/idle_monitor/amd_fam14h_idle.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
*
- * Licensed under the terms of the GNU GPL License version 2.
- *
* PCI initialization based on example code from:
* Andreas Herrmann <andreas.herrmann3@amd.com>
*/
@@ -329,7 +328,7 @@ struct cpuidle_monitor amd_fam14h_monitor = {
.stop = amd_fam14h_stop,
.do_register = amd_fam14h_register,
.unregister = amd_fam14h_unregister,
- .needs_root = 1,
+ .flags.needs_root = 1,
.overflow_s = OVERFLOW_MS / 1000,
};
#endif /* #if defined(__i386__) || defined(__x86_64__) */
diff --git a/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c b/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c
index 5b8c4956ff9a..3c4cee160b0e 100644
--- a/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c
+++ b/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c
@@ -1,8 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc
- *
- * Licensed under the terms of the GNU GPL License version 2.
- *
*/
#include <stdio.h>
@@ -209,6 +207,6 @@ struct cpuidle_monitor cpuidle_sysfs_monitor = {
.stop = cpuidle_stop,
.do_register = cpuidle_register,
.unregister = cpuidle_unregister,
- .needs_root = 0,
+ .flags.needs_root = 0,
.overflow_s = UINT_MAX,
};
diff --git a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
index 051da0a7c454..6d44fec55ad5 100644
--- a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
+++ b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
@@ -1,10 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
*
- * Licensed under the terms of the GNU GPL License version 2.
- *
* Output format inspired by Len Brown's <lenb@kernel.org> turbostat tool.
- *
*/
@@ -410,7 +408,7 @@ int cmd_monitor(int argc, char **argv)
dprint("Try to register: %s\n", all_monitors[num]->name);
test_mon = all_monitors[num]->do_register();
if (test_mon) {
- if (test_mon->needs_root && !run_as_root) {
+ if (test_mon->flags.needs_root && !run_as_root) {
fprintf(stderr, _("Available monitor %s needs "
"root access\n"), test_mon->name);
continue;
diff --git a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h
index 2ae50b499e0a..5b5eb1da0cce 100644
--- a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h
+++ b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h
@@ -1,8 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
- *
- * Licensed under the terms of the GNU GPL License version 2.
- *
*/
#ifndef __CPUIDLE_INFO_HW__
@@ -62,7 +60,10 @@ struct cpuidle_monitor {
struct cpuidle_monitor* (*do_register) (void);
void (*unregister)(void);
unsigned int overflow_s;
- int needs_root;
+ struct {
+ unsigned int needs_root:1;
+ unsigned int per_cpu_schedule:1;
+ } flags;
};
extern long long timespec_diff_us(struct timespec start, struct timespec end);
diff --git a/tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c b/tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c
index f794d6bbb7e9..97ad3233a521 100644
--- a/tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c
+++ b/tools/power/cpupower/utils/idle_monitor/hsw_ext_idle.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
*
- * Licensed under the terms of the GNU GPL License version 2.
- *
* Based on SandyBridge monitor. Implements the new package C-states
* (PC8, PC9, PC10) coming with a specific Haswell (family 0x45) CPU.
*/
@@ -40,7 +39,6 @@ static cstate_t hsw_ext_cstates[HSW_EXT_CSTATE_COUNT] = {
{
.name = "PC9",
.desc = N_("Processor Package C9"),
- .desc = N_("Processor Package C2"),
.id = PC9,
.range = RANGE_PACKAGE,
.get_count_percent = hsw_ext_get_count_percent,
@@ -189,7 +187,7 @@ struct cpuidle_monitor intel_hsw_ext_monitor = {
.stop = hsw_ext_stop,
.do_register = hsw_ext_register,
.unregister = hsw_ext_unregister,
- .needs_root = 1,
+ .flags.needs_root = 1,
.overflow_s = 922000000 /* 922337203 seconds TSC overflow
at 20GHz */
};
diff --git a/tools/power/cpupower/utils/idle_monitor/idle_monitors.h b/tools/power/cpupower/utils/idle_monitor/idle_monitors.h
index 4fcdeb1e07e8..e9e567ec879e 100644
--- a/tools/power/cpupower/utils/idle_monitor/idle_monitors.h
+++ b/tools/power/cpupower/utils/idle_monitor/idle_monitors.h
@@ -1,10 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
*
- * Licensed under the terms of the GNU GPL License version 2.
- *
* Based on the idea from Michael Matz <matz@suse.de>
- *
*/
#ifndef _CPUIDLE_IDLE_MONITORS_H_
diff --git a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
index f2a7e9cfd577..e7d48cb563c0 100644
--- a/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
+++ b/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
- *
- * Licensed under the terms of the GNU GPL License version 2.
*/
#if defined(__i386__) || defined(__x86_64__)
@@ -20,6 +19,10 @@
#define MSR_APERF 0xE8
#define MSR_MPERF 0xE7
+#define RDPRU ".byte 0x0f, 0x01, 0xfd"
+#define RDPRU_ECX_MPERF 0
+#define RDPRU_ECX_APERF 1
+
#define MSR_TSC 0x10
#define MSR_AMD_HWCR 0xc0010015
@@ -87,15 +90,51 @@ static int mperf_get_tsc(unsigned long long *tsc)
return ret;
}
+static int get_aperf_mperf(int cpu, unsigned long long *aval,
+ unsigned long long *mval)
+{
+ unsigned long low_a, high_a;
+ unsigned long low_m, high_m;
+ int ret;
+
+ /*
+ * Running on the cpu from which we read the registers will
+ * prevent APERF/MPERF from going out of sync because of IPI
+ * latency introduced by read_msr()s.
+ */
+ if (mperf_monitor.flags.per_cpu_schedule) {
+ if (bind_cpu(cpu))
+ return 1;
+ }
+
+ if (cpupower_cpu_info.caps & CPUPOWER_CAP_AMD_RDPRU) {
+ asm volatile(RDPRU
+ : "=a" (low_a), "=d" (high_a)
+ : "c" (RDPRU_ECX_APERF));
+ asm volatile(RDPRU
+ : "=a" (low_m), "=d" (high_m)
+ : "c" (RDPRU_ECX_MPERF));
+
+ *aval = ((low_a) | (high_a) << 32);
+ *mval = ((low_m) | (high_m) << 32);
+
+ return 0;
+ }
+
+ ret = read_msr(cpu, MSR_APERF, aval);
+ ret |= read_msr(cpu, MSR_MPERF, mval);
+
+ return ret;
+}
+
static int mperf_init_stats(unsigned int cpu)
{
- unsigned long long val;
+ unsigned long long aval, mval;
int ret;
- ret = read_msr(cpu, MSR_APERF, &val);
- aperf_previous_count[cpu] = val;
- ret |= read_msr(cpu, MSR_MPERF, &val);
- mperf_previous_count[cpu] = val;
+ ret = get_aperf_mperf(cpu, &aval, &mval);
+ aperf_previous_count[cpu] = aval;
+ mperf_previous_count[cpu] = mval;
is_valid[cpu] = !ret;
return 0;
@@ -103,13 +142,12 @@ static int mperf_init_stats(unsigned int cpu)
static int mperf_measure_stats(unsigned int cpu)
{
- unsigned long long val;
+ unsigned long long aval, mval;
int ret;
- ret = read_msr(cpu, MSR_APERF, &val);
- aperf_current_count[cpu] = val;
- ret |= read_msr(cpu, MSR_MPERF, &val);
- mperf_current_count[cpu] = val;
+ ret = get_aperf_mperf(cpu, &aval, &mval);
+ aperf_current_count[cpu] = aval;
+ mperf_current_count[cpu] = mval;
is_valid[cpu] = !ret;
return 0;
@@ -306,6 +344,9 @@ struct cpuidle_monitor *mperf_register(void)
if (init_maxfreq_mode())
return NULL;
+ if (cpupower_cpu_info.vendor == X86_VENDOR_AMD)
+ mperf_monitor.flags.per_cpu_schedule = 1;
+
/* Free this at program termination */
is_valid = calloc(cpu_count, sizeof(int));
mperf_previous_count = calloc(cpu_count, sizeof(unsigned long long));
@@ -334,7 +375,7 @@ struct cpuidle_monitor mperf_monitor = {
.stop = mperf_stop,
.do_register = mperf_register,
.unregister = mperf_unregister,
- .needs_root = 1,
+ .flags.needs_root = 1,
.overflow_s = 922000000 /* 922337203 seconds TSC overflow
at 20GHz */
};
diff --git a/tools/power/cpupower/utils/idle_monitor/nhm_idle.c b/tools/power/cpupower/utils/idle_monitor/nhm_idle.c
index abf8cb5f7349..114271165182 100644
--- a/tools/power/cpupower/utils/idle_monitor/nhm_idle.c
+++ b/tools/power/cpupower/utils/idle_monitor/nhm_idle.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
*
- * Licensed under the terms of the GNU GPL License version 2.
- *
* Based on Len Brown's <lenb@kernel.org> turbostat tool.
*/
@@ -209,7 +208,7 @@ struct cpuidle_monitor intel_nhm_monitor = {
.stop = nhm_stop,
.do_register = intel_nhm_register,
.unregister = intel_nhm_unregister,
- .needs_root = 1,
+ .flags.needs_root = 1,
.overflow_s = 922000000 /* 922337203 seconds TSC overflow
at 20GHz */
};
diff --git a/tools/power/cpupower/utils/idle_monitor/snb_idle.c b/tools/power/cpupower/utils/idle_monitor/snb_idle.c
index a2b45219648d..df8b223cc096 100644
--- a/tools/power/cpupower/utils/idle_monitor/snb_idle.c
+++ b/tools/power/cpupower/utils/idle_monitor/snb_idle.c
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* (C) 2010,2011 Thomas Renninger <trenn@suse.de>, Novell Inc.
*
- * Licensed under the terms of the GNU GPL License version 2.
- *
* Based on Len Brown's <lenb@kernel.org> turbostat tool.
*/
@@ -193,7 +192,7 @@ struct cpuidle_monitor intel_snb_monitor = {
.stop = snb_stop,
.do_register = snb_register,
.unregister = snb_unregister,
- .needs_root = 1,
+ .flags.needs_root = 1,
.overflow_s = 922000000 /* 922337203 seconds TSC overflow
at 20GHz */
};
diff --git a/tools/power/pm-graph/README b/tools/power/pm-graph/README
new file mode 100644
index 000000000000..96259f6e5715
--- /dev/null
+++ b/tools/power/pm-graph/README
@@ -0,0 +1,556 @@
+ p m - g r a p h
+
+ pm-graph: suspend/resume/boot timing analysis tools
+ Version: 5.5
+ Author: Todd Brandt <todd.e.brandt@intel.com>
+ Home Page: https://01.org/pm-graph
+
+ Report bugs/issues at bugzilla.kernel.org Tools/pm-graph
+ - https://bugzilla.kernel.org/buglist.cgi?component=pm-graph&product=Tools
+
+ Full documentation available online & in man pages
+ - Getting Started:
+ https://01.org/pm-graph/documentation/getting-started
+
+ - Config File Format:
+ https://01.org/pm-graph/documentation/3-config-file-format
+
+ - upstream version in git:
+ https://github.com/intel/pm-graph/
+
+ Requirements:
+ - runs with python2 or python3, choice is made by /usr/bin/python link
+ - python2 now requires python-configparser be installed
+
+ Table of Contents
+ - Overview
+ - Setup
+ - Usage
+ - Basic Usage
+ - Dev Mode Usage
+ - Proc Mode Usage
+ - Configuration Files
+ - Usage Examples
+ - Config File Options
+ - Custom Timeline Entries
+ - Adding/Editing Timeline Functions
+ - Adding/Editing Dev Timeline Source Functions
+ - Verifying your Custom Functions
+ - Testing on consumer linux Operating Systems
+ - Android
+
+------------------------------------------------------------------
+| OVERVIEW |
+------------------------------------------------------------------
+
+ This tool suite is designed to assist kernel and OS developers in optimizing
+ their linux stack's suspend/resume & boot time. Using a kernel image built
+ with a few extra options enabled, the tools will execute a suspend or boot,
+ and will capture dmesg and ftrace data. This data is transformed into a set of
+ timelines and a callgraph to give a quick and detailed view of which devices
+ and kernel processes are taking the most time in suspend/resume & boot.
+
+------------------------------------------------------------------
+| SETUP |
+------------------------------------------------------------------
+
+ These packages are required to execute the scripts
+ - python
+ - python-requests
+
+ Ubuntu:
+ sudo apt-get install python python-requests
+
+ Fedora:
+ sudo dnf install python python-requests
+
+ The tools can most easily be installed via git clone and make install
+
+ $> git clone http://github.com/intel/pm-graph.git
+ $> cd pm-graph
+ $> sudo make install
+ $> man sleepgraph ; man bootgraph
+
+ Setup involves some minor kernel configuration
+
+ The following kernel build options are required for all kernels:
+ CONFIG_DEVMEM=y
+ CONFIG_PM_DEBUG=y
+ CONFIG_PM_SLEEP_DEBUG=y
+ CONFIG_FTRACE=y
+ CONFIG_FUNCTION_TRACER=y
+ CONFIG_FUNCTION_GRAPH_TRACER=y
+ CONFIG_KPROBES=y
+ CONFIG_KPROBES_ON_FTRACE=y
+
+ In kernel 3.15.0, two patches were upstreamed which enable the
+ v3.0 behavior. These patches allow the tool to read all the
+ data from trace events instead of from dmesg. You can enable
+ this behavior on earlier kernels with these patches:
+
+ (kernel/pre-3.15/enable_trace_events_suspend_resume.patch)
+ (kernel/pre-3.15/enable_trace_events_device_pm_callback.patch)
+
+ If you're using a kernel older than 3.15.0, the following
+ additional kernel parameters are required:
+ (e.g. in file /etc/default/grub)
+ GRUB_CMDLINE_LINUX_DEFAULT="... initcall_debug log_buf_len=32M ..."
+
+ If you're using a kernel older than 3.11-rc2, the following simple
+ patch must be applied to enable ftrace data:
+ in file: kernel/power/suspend.c
+ in function: int suspend_devices_and_enter(suspend_state_t state)
+ remove call to "ftrace_stop();"
+ remove call to "ftrace_start();"
+
+ There is a patch which does this for kernel v3.8.0:
+ (kernel/pre-3.11-rc2/enable_ftrace_in_suspendresume.patch)
+
+
+
+------------------------------------------------------------------
+| USAGE |
+------------------------------------------------------------------
+
+Basic Usage
+___________
+
+ 1) First configure a kernel using the instructions from the previous sections.
+ Then build, install, and boot with it.
+ 2) Open up a terminal window and execute the mode list command:
+
+ %> sudo ./sleepgraph.py -modes
+ ['freeze', 'mem', 'disk']
+
+ Execute a test using one of the available power modes, e.g. mem (S3):
+
+ %> sudo ./sleepgraph.py -m mem -rtcwake 15
+
+ or with a config file
+
+ %> sudo ./sleepgraph.py -config config/suspend.cfg
+
+ When the system comes back you'll see the script finishing up and
+ creating the output files in the test subdir. It generates output
+ files in subdirectory: suspend-mmddyy-HHMMSS. The ftrace file can
+ be used to regenerate the html timeline with different options
+
+ HTML output: <hostname>_<mode>.html
+ raw dmesg output: <hostname>_<mode>_dmesg.txt
+ raw ftrace output: <hostname>_<mode>_ftrace.txt
+
+ View the html in firefox or chrome.
+
+
+Dev Mode Usage
+______________
+
+ Developer mode adds information on low level source calls to the timeline.
+ The tool sets kprobes on all delay and mutex calls to see which devices
+ are waiting for something and when. It also sets a suite of kprobes on
+ subsystem dependent calls to better fill out the timeline.
+
+ The tool will also expose kernel threads that don't normally show up in the
+ timeline. This is useful in discovering dependent threads to get a better
+ idea of what each device is waiting for. For instance, the scsi_eh thread,
+ a.k.a. scsi resume error handler, is what each SATA disk device waits for
+ before it can continue resume.
+
+ The timeline will be much larger if run with dev mode, so it can be useful
+ to set the -mindev option to clip out any device blocks that are too small
+ to see easily. The following command will give a nice dev mode run:
+
+ %> sudo ./sleepgraph.py -m mem -rtcwake 15 -mindev 1 -dev
+
+ or with a config file
+
+ %> sudo ./sleepgraph.py -config config/suspend-dev.cfg
+
+
+Proc Mode Usage
+_______________
+
+ Proc mode adds user process info to the timeline. This is done in a manner
+ similar to the bootchart utility, which graphs init processes and their
+ execution as the system boots. This tool option does the same thing but for
+ the period before and after suspend/resume.
+
+ In order to see any process info, there needs to be some delay before or
+ after resume since processes are frozen in suspend_prepare and thawed in
+ resume_complete. The predelay and postdelay args allow you to do this. It
+ can also be useful to run in x2 mode with an x2 delay, this way you can
+ see process activity before and after resume, and in between two
+ successive suspend/resumes.
+
+ The command can be run like this:
+
+ %> sudo ./sleepgraph.py -m mem -rtcwake 15 -x2 -x2delay 1000 -predelay 1000 -postdelay 1000 -proc
+
+ or with a config file
+
+ %> sudo ./sleepgraph.py -config config/suspend-proc.cfg
+
+
+------------------------------------------------------------------
+| CONFIGURATION FILES |
+------------------------------------------------------------------
+
+ Since 4.0 we've moved to using config files in lieu of command line options.
+ The config folder contains a collection of typical use cases.
+ There are corresponding configs for other power modes:
+
+ Simple suspend/resume with basic timeline (mem/freeze/standby)
+ config/suspend.cfg
+ config/freeze.cfg
+ config/standby.cfg
+
+ Dev mode suspend/resume with dev timeline (mem/freeze/standby)
+ config/suspend-dev.cfg
+ config/freeze-dev.cfg
+ config/standby-dev.cfg
+
+ Simple suspend/resume with timeline and callgraph (mem/freeze/standby)
+ config/suspend-callgraph.cfg
+ config/freeze-callgraph.cfg
+ config/standby-callgraph.cfg
+
+ Sample proc mode x2 run using mem suspend
+ config/suspend-x2-proc.cfg
+
+ Sample for editing timeline funcs (moves internal functions into config)
+ config/custom-timeline-functions.cfg
+
+ Sample debug config for serio subsystem
+ config/debug-serio-suspend.cfg
+
+
+Usage Examples
+______________
+
+ Run a simple mem suspend:
+ %> sudo ./sleepgraph.py -config config/suspend.cfg
+
+ Run a mem suspend with callgraph data:
+ %> sudo ./sleepgraph.py -config config/suspend-callgraph.cfg
+
+ Run a mem suspend with dev mode detail:
+ %> sudo ./sleepgraph.py -config config/suspend-dev.cfg
+
+
+Config File Options
+___________________
+
+ [Settings]
+
+ # Verbosity: print verbose messages (def: false)
+ verbose: false
+
+ # Suspend Mode: e.g. standby, mem, freeze, disk (def: mem)
+ mode: mem
+
+ # Output Directory Format: {hostname}, {date}, {time} give current values
+ output-dir: suspend-{hostname}-{date}-{time}
+
+ # Automatic Wakeup: use rtcwake to wakeup after X seconds (def: infinity)
+ rtcwake: 15
+
+ # Add Logs: add the dmesg and ftrace log to the html output (def: false)
+ addlogs: false
+
+ # Sus/Res Gap: insert a gap between sus & res in the timeline (def: false)
+ srgap: false
+
+ # Custom Command: Command to execute in lieu of suspend (def: "")
+ command: echo mem > /sys/power/state
+
+ # Proc mode: graph user processes and cpu usage in the timeline (def: false)
+ proc: false
+
+ # Dev mode: graph source functions in the timeline (def: false)
+ dev: false
+
+ # Suspend/Resume x2: run 2 suspend/resumes back to back (def: false)
+ x2: false
+
+ # x2 Suspend Delay: time delay between the two test runs in ms (def: 0 ms)
+ x2delay: 0
+
+ # Pre Suspend Delay: nclude an N ms delay before (1st) suspend (def: 0 ms)
+ predelay: 0
+
+ # Post Resume Delay: include an N ms delay after (last) resume (def: 0 ms)
+ postdelay: 0
+
+ # Min Device Length: graph only dev callbacks longer than min (def: 0.001 ms)
+ mindev: 0.001
+
+ # Callgraph: gather ftrace callgraph data on all timeline events (def: false)
+ callgraph: false
+
+ # Expand Callgraph: pre-expand the callgraph treeviews in html (def: false)
+ expandcg: false
+
+ # Min Callgraph Length: show callgraphs only if longer than min (def: 1 ms)
+ mincg: 1
+
+ # Timestamp Precision: number of sig digits in timestamps (0:S, [3:ms], 6:us)
+ timeprec: 3
+
+ # Device Filter: show only devs whose name/driver includes one of these strings
+ devicefilter: _cpu_up,_cpu_down,i915,usb
+
+ # Override default timeline entries:
+ # Do not use the internal default functions for timeline entries (def: false)
+ # Set this to true if you intend to only use the ones defined in the config
+ override-timeline-functions: true
+
+ # Override default dev timeline entries:
+ # Do not use the internal default functions for dev timeline entries (def: false)
+ # Set this to true if you intend to only use the ones defined in the config
+ override-dev-timeline-functions: true
+
+ # Call Loop Max Gap (dev mode only)
+ # merge loops of the same call if each is less than maxgap apart (def: 100us)
+ callloop-maxgap: 0.0001
+
+ # Call Loop Max Length (dev mode only)
+ # merge loops of the same call if each is less than maxlen in length (def: 5ms)
+ callloop-maxlen: 0.005
+
+------------------------------------------------------------------
+| CUSTOM TIMELINE ENTRIES |
+------------------------------------------------------------------
+
+Adding or Editing Timeline Functions
+____________________________________
+
+ The tool uses an array of function names to fill out empty spaces in the
+ timeline where device callbacks don't appear. For instance, in suspend_prepare
+ the tool adds the sys_sync and freeze_processes calls as virtual device blocks
+ in the timeline to show you where the time is going. These calls should fill
+ the timeline with contiguous data so that most kernel execution is covered.
+
+ It is possible to add new function calls to the timeline by adding them to
+ the config. It's also possible to copy the internal timeline functions into
+ the config so that you can override and edit them. Place them in the
+ timeline_functions_ARCH section with the name of your architecture appended.
+ i.e. for x86_64: [timeline_functions_x86_64]
+
+ Use the override-timeline-functions option if you only want to use your
+ custom calls, or leave it false to append them to the internal ones.
+
+ This section includes a list of functions (set using kprobes) which use both
+ symbol data and function arg data. The args are pulled directly from the
+ stack using this architecture's registers and stack formatting. Each entry
+ can include up to four pieces of info: The function name, a format string,
+ an argument list, and a color. But only a function name is required.
+
+ For a full example config, see config/custom-timeline-functions.cfg. It pulls
+ all the internal timeline functions into the config and allows you to edit
+ them.
+
+ Entry format:
+
+ function: format{fn_arg1}_{fn_arg2} fn_arg1 fn_arg2 ... [color=purple]
+
+ Required Arguments:
+
+ function: The symbol name for the function you want probed, this is the
+ minimum required for an entry, it will show up as the function
+ name with no arguments.
+
+ example: _cpu_up:
+
+ Optional Arguments:
+
+ format: The format to display the data on the timeline in. Use braces to
+ enclose the arg names.
+
+ example: CPU_ON[{cpu}]
+
+ color: The color of the entry block in the timeline. The default color is
+ transparent, so the entry shares the phase color. The color is an
+ html color string, either a word, or an RGB.
+
+ example: [color=#CC00CC]
+
+ arglist: A list of arguments from registers/stack addresses. See URL:
+ https://www.kernel.org/doc/Documentation/trace/kprobetrace.txt
+
+ example: cpu=%di:s32
+
+ Here is a full example entry. It displays cpu resume calls in the timeline
+ in orange. They will appear as CPU_ON[0], CPU_ON[1], etc.
+
+ [timeline_functions_x86_64]
+ _cpu_up: CPU_ON[{cpu}] cpu=%di:s32 [color=orange]
+
+
+Adding or Editing Dev Mode Timeline Source Functions
+____________________________________________________
+
+ In dev mode, the tool uses an array of function names to monitor source
+ execution within the timeline entries.
+
+ The function calls are displayed inside the main device/call blocks in the
+ timeline. However, if a function call is not within a main timeline event,
+ it will spawn an entirely new event named after the caller's kernel thread.
+ These asynchronous kernel threads will populate in a separate section
+ beneath the main device/call section.
+
+ The tool has a set of hard coded calls which focus on the most common use
+ cases: msleep, udelay, schedule_timeout, mutex_lock_slowpath, etc. These are
+ the functions that add a hardcoded time delay to the suspend/resume path.
+ The tool also includes some common functions native to important
+ subsystems: ata, i915, and ACPI, etc.
+
+ It is possible to add new function calls to the dev timeline by adding them
+ to the config. It's also possible to copy the internal dev timeline
+ functions into the config so that you can override and edit them. Place them
+ in the dev_timeline_functions_ARCH section with the name of your architecture
+ appended. i.e. for x86_64: [dev_timeline_functions_x86_64]
+
+ Use the override-dev-timeline-functions option if you only want to use your
+ custom calls, or leave it false to append them to the internal ones.
+
+ The format is the same as the timeline_functions_x86_64 section. It's a
+ list of functions (set using kprobes) which use both symbol data and function
+ arg data. The args are pulled directly from the stack using this
+ architecture's registers and stack formatting. Each entry can include up
+ to four pieces of info: The function name, a format string, an argument list,
+ and a color. But only the function name is required.
+
+ For a full example config, see config/custom-timeline-functions.cfg. It pulls
+ all the internal dev timeline functions into the config and allows you to edit
+ them.
+
+ Here is a full example entry. It displays the ATA port reset calls as
+ ataN_port_reset in the timeline. This is where most of the SATA disk resume
+ time goes, so it can be helpful to see the low level call.
+
+ [dev_timeline_functions_x86_64]
+ ata_eh_recover: ata{port}_port_reset port=+36(%di):s32 [color=#CC00CC]
+
+
+Verifying your custom functions
+_______________________________
+
+ Once you have a set of functions (kprobes) defined, it can be useful to
+ perform a quick check to see if you formatted them correctly and if the system
+ actually supports them. To do this, run the tool with your config file
+ and the -status option. The tool will go through all the kprobes (both
+ custom and internal if you haven't overridden them) and actually attempts
+ to set them in ftrace. It will then print out success or fail for you.
+
+ Note that kprobes which don't actually exist in the kernel won't stop the
+ tool, they just wont show up.
+
+ For example:
+
+ sudo ./sleepgraph.py -config config/custom-timeline-functions.cfg -status
+ Checking this system (myhostname)...
+ have root access: YES
+ is sysfs mounted: YES
+ is "mem" a valid power mode: YES
+ is ftrace supported: YES
+ are kprobes supported: YES
+ timeline data source: FTRACE (all trace events found)
+ is rtcwake supported: YES
+ verifying timeline kprobes work:
+ _cpu_down: YES
+ _cpu_up: YES
+ acpi_pm_finish: YES
+ acpi_pm_prepare: YES
+ freeze_kernel_threads: YES
+ freeze_processes: YES
+ sys_sync: YES
+ thaw_processes: YES
+ verifying dev kprobes work:
+ __const_udelay: YES
+ __mutex_lock_slowpath: YES
+ acpi_os_stall: YES
+ acpi_ps_parse_aml: YES
+ intel_opregion_init: NO
+ intel_opregion_register: NO
+ intel_opregion_setup: NO
+ msleep: YES
+ schedule_timeout: YES
+ schedule_timeout_uninterruptible: YES
+ usleep_range: YES
+
+
+------------------------------------------------------------------
+| TESTING ON CONSUMER LINUX OPERATING SYSTEMS |
+------------------------------------------------------------------
+
+Android
+_______
+
+ The easiest way to execute on an android device is to run the android.sh
+ script on the device, then pull the ftrace log back to the host and run
+ sleepgraph.py on it.
+
+ Here are the steps:
+
+ [download and install the tool on the device]
+
+ host%> wget https://raw.githubusercontent.com/intel/pm-graph/master/tools/android.sh
+ host%> adb connect 192.168.1.6
+ host%> adb root
+ # push the script to a writeable location
+ host%> adb push android.sh /sdcard/
+
+ [check whether the tool will run on your device]
+
+ host%> adb shell
+ dev%> cd /sdcard
+ dev%> sh android.sh status
+ host : asus_t100
+ kernel : 3.14.0-i386-dirty
+ modes : freeze mem
+ rtcwake : supported
+ ftrace : supported
+ trace events {
+ suspend_resume: found
+ device_pm_callback_end: found
+ device_pm_callback_start: found
+ }
+ # the above is what you see on a system that's properly patched
+
+ [execute the suspend]
+
+ # NOTE: The suspend will only work if the screen isn't timed out,
+ # so you have to press some keys first to wake it up b4 suspend)
+ dev%> sh android.sh suspend mem
+ ------------------------------------
+ Suspend/Resume timing test initiated
+ ------------------------------------
+ hostname : asus_t100
+ kernel : 3.14.0-i386-dirty
+ mode : mem
+ ftrace out : /mnt/shell/emulated/0/ftrace.txt
+ dmesg out : /mnt/shell/emulated/0/dmesg.txt
+ log file : /mnt/shell/emulated/0/log.txt
+ ------------------------------------
+ INITIALIZING FTRACE........DONE
+ STARTING FTRACE
+ SUSPEND START @ 21:24:02 (rtcwake in 10 seconds)
+ <adb connection will now terminate>
+
+ [retrieve the data from the device]
+
+ # I find that you have to actually kill the adb process and
+ # reconnect sometimes in order for the connection to work post-suspend
+ host%> adb connect 192.168.1.6
+ # (required) get the ftrace data, this is the most important piece
+ host%> adb pull /sdcard/ftrace.txt
+ # (optional) get the dmesg data, this is for debugging
+ host%> adb pull /sdcard/dmesg.txt
+ # (optional) get the log, which just lists some test times for comparison
+ host%> adb pull /sdcard/log.txt
+
+ [create an output html file using sleepgraph.py]
+
+ host%> sleepgraph.py -ftrace ftrace.txt
+
+ You should now have an output.html with the android data, enjoy!
diff --git a/tools/power/pm-graph/bootgraph.py b/tools/power/pm-graph/bootgraph.py
index 6dae57041537..d3b99a1e92d6 100755
--- a/tools/power/pm-graph/bootgraph.py
+++ b/tools/power/pm-graph/bootgraph.py
@@ -1,4 +1,5 @@
-#!/usr/bin/python2
+#!/usr/bin/python
+# SPDX-License-Identifier: GPL-2.0-only
#
# Tool for analyzing boot timing
# Copyright (c) 2013, Intel Corporation.
@@ -89,7 +90,7 @@ class SystemValues(aslib.SystemValues):
cmdline = 'initcall_debug log_buf_len=32M'
if self.useftrace:
if self.cpucount > 0:
- bs = min(self.memtotal / 2, 2*1024*1024) / self.cpucount
+ bs = min(self.memtotal // 2, 2*1024*1024) // self.cpucount
else:
bs = 131072
cmdline += ' trace_buf_size=%dK trace_clock=global '\
@@ -145,13 +146,13 @@ class SystemValues(aslib.SystemValues):
if arg in ['-h', '-v', '-cronjob', '-reboot', '-verbose']:
continue
elif arg in ['-o', '-dmesg', '-ftrace', '-func']:
- args.next()
+ next(args)
continue
elif arg == '-result':
- cmdline += ' %s "%s"' % (arg, os.path.abspath(args.next()))
+ cmdline += ' %s "%s"' % (arg, os.path.abspath(next(args)))
continue
elif arg == '-cgskip':
- file = self.configFile(args.next())
+ file = self.configFile(next(args))
cmdline += ' %s "%s"' % (arg, os.path.abspath(file))
continue
cmdline += ' '+arg
@@ -300,11 +301,11 @@ def parseKernelLog():
tp = aslib.TestProps()
devtemp = dict()
if(sysvals.dmesgfile):
- lf = open(sysvals.dmesgfile, 'r')
+ lf = open(sysvals.dmesgfile, 'rb')
else:
lf = Popen('dmesg', stdout=PIPE).stdout
for line in lf:
- line = line.replace('\r\n', '')
+ line = aslib.ascii(line).replace('\r\n', '')
# grab the stamp and sysinfo
if re.match(tp.stampfmt, line):
tp.stamp = line
@@ -333,9 +334,9 @@ def parseKernelLog():
if(not sysvals.stamp['kernel']):
sysvals.stamp['kernel'] = sysvals.kernelVersion(msg)
continue
- m = re.match('.* setting system clock to (?P<t>.*) UTC.*', msg)
+ m = re.match('.* setting system clock to (?P<d>[0-9\-]*)[ A-Z](?P<t>[0-9:]*) UTC.*', msg)
if(m):
- bt = datetime.strptime(m.group('t'), '%Y-%m-%d %H:%M:%S')
+ bt = datetime.strptime(m.group('d')+' '+m.group('t'), '%Y-%m-%d %H:%M:%S')
bt = bt - timedelta(seconds=int(ktime))
data.boottime = bt.strftime('%Y-%m-%d_%H:%M:%S')
sysvals.stamp['time'] = bt.strftime('%B %d %Y, %I:%M:%S %p')
@@ -356,7 +357,7 @@ def parseKernelLog():
data.newAction(phase, f, pid, start, ktime, int(r), int(t))
del devtemp[f]
continue
- if(re.match('^Freeing unused kernel memory.*', msg)):
+ if(re.match('^Freeing unused kernel .*', msg)):
data.tUserMode = ktime
data.dmesg['kernel']['end'] = ktime
data.dmesg['user']['start'] = ktime
@@ -657,7 +658,7 @@ def createBootGraph(data):
statinfo += '\t"%s": [\n\t\t"%s",\n' % (n, devstats[n]['info'])
if 'fstat' in devstats[n]:
funcs = devstats[n]['fstat']
- for f in sorted(funcs, key=funcs.get, reverse=True):
+ for f in sorted(funcs, key=lambda k:(funcs[k], k), reverse=True):
if funcs[f][0] < 0.01 and len(funcs) > 10:
break
statinfo += '\t\t"%f|%s|%d",\n' % (funcs[f][0], f, funcs[f][1])
@@ -737,7 +738,7 @@ def updateCron(restore=False):
op.write('@reboot python %s\n' % sysvals.cronjobCmdString())
op.close()
res = call([cmd, cronfile])
- except Exception, e:
+ except Exception as e:
pprint('Exception: %s' % str(e))
shutil.move(backfile, cronfile)
res = -1
@@ -753,7 +754,7 @@ def updateGrub(restore=False):
try:
call(sysvals.blexec, stderr=PIPE, stdout=PIPE,
env={'PATH': '.:/sbin:/usr/sbin:/usr/bin:/sbin:/bin'})
- except Exception, e:
+ except Exception as e:
pprint('Exception: %s\n' % str(e))
return
# extract the option and create a grub config without it
@@ -800,7 +801,7 @@ def updateGrub(restore=False):
op.close()
res = call(sysvals.blexec)
os.remove(grubfile)
- except Exception, e:
+ except Exception as e:
pprint('Exception: %s' % str(e))
res = -1
# cleanup
@@ -874,6 +875,7 @@ def printHelp():
'Other commands:\n'\
' -flistall Print all functions capable of being captured in ftrace\n'\
' -sysinfo Print out system info extracted from BIOS\n'\
+ ' -which exec Print an executable path, should function even without PATH\n'\
' [redo]\n'\
' -dmesg file Create HTML output using dmesg input (used with -ftrace)\n'\
' -ftrace file Create HTML output using ftrace input (used with -dmesg)\n'\
@@ -915,13 +917,13 @@ if __name__ == '__main__':
sysvals.mincglen = aslib.getArgFloat('-mincg', args, 0.0, 10000.0)
elif(arg == '-cgfilter'):
try:
- val = args.next()
+ val = next(args)
except:
doError('No callgraph functions supplied', True)
sysvals.setCallgraphFilter(val)
elif(arg == '-cgskip'):
try:
- val = args.next()
+ val = next(args)
except:
doError('No file supplied', True)
if val.lower() in switchoff:
@@ -932,7 +934,7 @@ if __name__ == '__main__':
doError('%s does not exist' % cgskip)
elif(arg == '-bl'):
try:
- val = args.next()
+ val = next(args)
except:
doError('No boot loader name supplied', True)
if val.lower() not in ['grub']:
@@ -945,7 +947,7 @@ if __name__ == '__main__':
sysvals.max_graph_depth = aslib.getArgInt('-maxdepth', args, 0, 1000)
elif(arg == '-func'):
try:
- val = args.next()
+ val = next(args)
except:
doError('No filter functions supplied', True)
sysvals.useftrace = True
@@ -954,7 +956,7 @@ if __name__ == '__main__':
sysvals.setGraphFilter(val)
elif(arg == '-ftrace'):
try:
- val = args.next()
+ val = next(args)
except:
doError('No ftrace file supplied', True)
if(os.path.exists(val) == False):
@@ -967,7 +969,7 @@ if __name__ == '__main__':
sysvals.cgexp = True
elif(arg == '-dmesg'):
try:
- val = args.next()
+ val = next(args)
except:
doError('No dmesg file supplied', True)
if(os.path.exists(val) == False):
@@ -976,13 +978,13 @@ if __name__ == '__main__':
sysvals.dmesgfile = val
elif(arg == '-o'):
try:
- val = args.next()
+ val = next(args)
except:
doError('No subdirectory name supplied', True)
sysvals.testdir = sysvals.setOutputFolder(val)
elif(arg == '-result'):
try:
- val = args.next()
+ val = next(args)
except:
doError('No result file supplied', True)
sysvals.result = val
@@ -994,6 +996,17 @@ if __name__ == '__main__':
# remaining options are only for cron job use
elif(arg == '-cronjob'):
sysvals.iscronjob = True
+ elif(arg == '-which'):
+ try:
+ val = next(args)
+ except:
+ doError('No executable supplied', True)
+ out = sysvals.getExec(val)
+ if not out:
+ print('%s not found' % val)
+ sys.exit(1)
+ print(out)
+ sys.exit(0)
else:
doError('Invalid argument: '+arg, True)
@@ -1016,7 +1029,7 @@ if __name__ == '__main__':
updateKernelParams()
elif cmd == 'flistall':
for f in sysvals.getBootFtraceFilterFunctions():
- print f
+ print(f)
elif cmd == 'checkbl':
sysvals.getBootLoader()
pprint('Boot Loader: %s\n%s' % (sysvals.bootloader, sysvals.blexec))
diff --git a/tools/power/pm-graph/config/example.cfg b/tools/power/pm-graph/config/example.cfg
index 05b2efb9bb54..1ef3eb9383fa 100644
--- a/tools/power/pm-graph/config/example.cfg
+++ b/tools/power/pm-graph/config/example.cfg
@@ -98,12 +98,34 @@ postdelay: 0
# graph only devices longer than min in the timeline (default: 0.001 ms)
mindev: 0.001
+# Call Loop Max Gap (dev mode only)
+# merge loops of the same call if each is less than maxgap apart (def: 100us)
+callloop-maxgap: 0.0001
+
+# Call Loop Max Length (dev mode only)
+# merge loops of the same call if each is less than maxlen in length (def: 5ms)
+callloop-maxlen: 0.005
+
+# Override default timeline entries:
+# Do not use the internal default functions for timeline entries (def: false)
+# Set this to true if you intend to only use the ones defined in the config
+override-timeline-functions: true
+
+# Override default dev timeline entries:
+# Do not use the internal default functions for dev timeline entries (def: false)
+# Set this to true if you intend to only use the ones defined in the config
+override-dev-timeline-functions: true
+
# ---- Debug Options ----
# Callgraph
# gather detailed ftrace callgraph data on all timeline events (default: false)
callgraph: false
+# Max graph depth
+# limit the callgraph trace to this depth (default: 0 = all)
+maxdepth: 2
+
# Callgraph phase filter
# Only enable callgraphs for one phase, i.e. resume_noirq (default: all)
cgphase: suspend
@@ -131,3 +153,7 @@ timeprec: 6
# Add kprobe functions to the timeline
# Add functions to the timeline from a text file (default: no-action)
# fadd: file.txt
+
+# Ftrace buffer size
+# Set trace buffer size to N kilo-bytes (default: all of free memory up to 3GB)
+# bufsize: 1000
diff --git a/tools/power/pm-graph/sleepgraph.8 b/tools/power/pm-graph/sleepgraph.8
index 24a2e7d0ae63..43aee64316df 100644
--- a/tools/power/pm-graph/sleepgraph.8
+++ b/tools/power/pm-graph/sleepgraph.8
@@ -53,6 +53,11 @@ disable rtcwake and require a user keypress to resume.
Add the dmesg and ftrace logs to the html output. They will be viewable by
clicking buttons in the timeline.
.TP
+\fB-noturbostat\fR
+By default, if turbostat is found and the requested mode is freeze, sleepgraph
+will execute the suspend via turbostat and collect data in the timeline log.
+This option disables the use of turbostat.
+.TP
\fB-result \fIfile\fR
Export a results table to a text file for parsing.
.TP
@@ -121,6 +126,10 @@ be created in a new subdirectory with a summary page: suspend-xN-{date}-{time}.
Use ftrace to create device callgraphs (default: disabled). This can produce
very large outputs, i.e. 10MB - 100MB.
.TP
+\fB-ftop\fR
+Use ftrace on the top level call: "suspend_devices_and_enter" only (default: disabled).
+This option implies -f and creates a single callgraph covering all of suspend/resume.
+.TP
\fB-maxdepth \fIlevel\fR
limit the callgraph trace depth to \fIlevel\fR (default: 0=all). This is
the best way to limit the output size when using callgraphs via -f.
@@ -138,8 +147,8 @@ which are barely visible in the timeline.
The value is a float: e.g. 0.001 represents 1 us.
.TP
\fB-cgfilter \fI"func1,func2,..."\fR
-Reduce callgraph output in the timeline by limiting it to a list of calls. The
-argument can be a single function name or a comma delimited list.
+Reduce callgraph output in the timeline by limiting it certain devices. The
+argument can be a single device name or a comma delimited list.
(default: none)
.TP
\fB-cgskip \fIfile\fR
@@ -183,6 +192,9 @@ Print out the contents of the ACPI Firmware Performance Data Table.
\fB-battery\fR
Print out battery status and current charge.
.TP
+\fB-wifi\fR
+Print out wifi status and connection details.
+.TP
\fB-xon/-xoff/-xstandby/-xsuspend\fR
Test xset by attempting to switch the display to the given mode. This
is the same command which will be issued by \fB-display \fImode\fR.
diff --git a/tools/power/pm-graph/sleepgraph.py b/tools/power/pm-graph/sleepgraph.py
index 52618f3444d4..f7d1c1f62f86 100755
--- a/tools/power/pm-graph/sleepgraph.py
+++ b/tools/power/pm-graph/sleepgraph.py
@@ -1,4 +1,5 @@
-#!/usr/bin/python2
+#!/usr/bin/python
+# SPDX-License-Identifier: GPL-2.0-only
#
# Tool for analyzing suspend/resume timing
# Copyright (c) 2013, Intel Corporation.
@@ -17,9 +18,9 @@
#
# Links:
# Home Page
-# https://01.org/suspendresume
+# https://01.org/pm-graph
# Source repo
-# git@github.com:01org/pm-graph
+# git@github.com:intel/pm-graph
#
# Description:
# This tool is designed to assist kernel and OS developers in optimizing
@@ -32,6 +33,7 @@
# viewed in firefox or chrome.
#
# The following kernel build options are required:
+# CONFIG_DEVMEM=y
# CONFIG_PM_DEBUG=y
# CONFIG_PM_SLEEP_DEBUG=y
# CONFIG_FTRACE=y
@@ -55,17 +57,22 @@ import string
import re
import platform
import signal
+import codecs
from datetime import datetime
import struct
-import ConfigParser
+import configparser
import gzip
from threading import Thread
from subprocess import call, Popen, PIPE
+import base64
def pprint(msg):
print(msg)
sys.stdout.flush()
+def ascii(text):
+ return text.decode('ascii', 'ignore')
+
# ----------------- CLASSES --------------------
# Class: SystemValues
@@ -74,7 +81,7 @@ def pprint(msg):
# store system values and test parameters
class SystemValues:
title = 'SleepGraph'
- version = '5.2'
+ version = '5.5'
ansi = False
rs = 0
display = ''
@@ -82,8 +89,9 @@ class SystemValues:
sync = False
verbose = False
testlog = True
- dmesglog = False
+ dmesglog = True
ftracelog = False
+ tstat = True
mindevlen = 0.0
mincglen = 0.0
cgphase = ''
@@ -107,6 +115,8 @@ class SystemValues:
pmdpath = '/sys/power/pm_debug_messages'
traceevents = [
'suspend_resume',
+ 'wakeup_source_activate',
+ 'wakeup_source_deactivate',
'device_pm_callback_end',
'device_pm_callback_start'
]
@@ -138,6 +148,8 @@ class SystemValues:
x2delay = 0
skiphtml = False
usecallgraph = False
+ ftopfunc = 'suspend_devices_and_enter'
+ ftop = False
usetraceevents = False
usetracemarkers = True
usekprobes = True
@@ -148,6 +160,7 @@ class SystemValues:
devdump = False
mixedphaseheight = True
devprops = dict()
+ platinfo = []
predelay = 0
postdelay = 0
pmdebug = ''
@@ -166,6 +179,13 @@ class SystemValues:
'acpi_hibernation_leave': {},
'acpi_pm_freeze': {},
'acpi_pm_thaw': {},
+ 'acpi_s2idle_end': {},
+ 'acpi_s2idle_sync': {},
+ 'acpi_s2idle_begin': {},
+ 'acpi_s2idle_prepare': {},
+ 'acpi_s2idle_wake': {},
+ 'acpi_s2idle_wakeup': {},
+ 'acpi_s2idle_restore': {},
'hibernate_preallocate_memory': {},
'create_basic_memory_bitmaps': {},
'swsusp_write': {},
@@ -199,9 +219,14 @@ class SystemValues:
'usleep_range': { 'args_x86_64': {'min':'%di:s32', 'max':'%si:s32'}, 'ub': 1 },
'mutex_lock_slowpath': { 'func':'__mutex_lock_slowpath', 'ub': 1 },
'acpi_os_stall': {'ub': 1},
+ 'rt_mutex_slowlock': {'ub': 1},
# ACPI
'acpi_resume_power_resources': {},
- 'acpi_ps_parse_aml': {},
+ 'acpi_ps_execute_method': { 'args_x86_64': {
+ 'fullpath':'+0(+40(%di)):string',
+ }},
+ # mei_me
+ 'mei_reset': {},
# filesystem
'ext4_sync_fs': {},
# 80211
@@ -250,6 +275,7 @@ class SystemValues:
timeformat = '%.3f'
cmdline = '%s %s' % \
(os.path.basename(sys.argv[0]), ' '.join(sys.argv[1:]))
+ kparams = ''
sudouser = ''
def __init__(self):
self.archargs = 'args_'+platform.machine()
@@ -311,13 +337,20 @@ class SystemValues:
sys.exit(1)
return False
def getExec(self, cmd):
- dirlist = ['/sbin', '/bin', '/usr/sbin', '/usr/bin',
- '/usr/local/sbin', '/usr/local/bin']
- for path in dirlist:
+ try:
+ fp = Popen(['which', cmd], stdout=PIPE, stderr=PIPE).stdout
+ out = ascii(fp.read()).strip()
+ fp.close()
+ except:
+ out = ''
+ if out:
+ return out
+ for path in ['/sbin', '/bin', '/usr/sbin', '/usr/bin',
+ '/usr/local/sbin', '/usr/local/bin']:
cmdfull = os.path.join(path, cmd)
if os.path.exists(cmdfull):
return cmdfull
- return ''
+ return out
def setPrecision(self, num):
if num < 0 or num > 6:
return
@@ -328,6 +361,7 @@ class SystemValues:
args['date'] = n.strftime('%y%m%d')
args['time'] = n.strftime('%H%M%S')
args['hostname'] = args['host'] = self.hostname
+ args['mode'] = self.suspendmode
return value.format(**args)
def setOutputFile(self):
if self.dmesgfile != '':
@@ -339,21 +373,28 @@ class SystemValues:
if(m):
self.htmlfile = m.group('name')+'.html'
def systemInfo(self, info):
- p = c = m = b = ''
+ p = m = ''
if 'baseboard-manufacturer' in info:
m = info['baseboard-manufacturer']
elif 'system-manufacturer' in info:
m = info['system-manufacturer']
- if 'baseboard-product-name' in info:
- p = info['baseboard-product-name']
- elif 'system-product-name' in info:
+ if 'system-product-name' in info:
p = info['system-product-name']
- if 'processor-version' in info:
- c = info['processor-version']
- if 'bios-version' in info:
- b = info['bios-version']
- self.sysstamp = '# sysinfo | man:%s | plat:%s | cpu:%s | bios:%s | numcpu:%d | memsz:%d | memfr:%d' % \
- (m, p, c, b, self.cpucount, self.memtotal, self.memfree)
+ elif 'baseboard-product-name' in info:
+ p = info['baseboard-product-name']
+ if m[:5].lower() == 'intel' and 'baseboard-product-name' in info:
+ p = info['baseboard-product-name']
+ c = info['processor-version'] if 'processor-version' in info else ''
+ b = info['bios-version'] if 'bios-version' in info else ''
+ r = info['bios-release-date'] if 'bios-release-date' in info else ''
+ self.sysstamp = '# sysinfo | man:%s | plat:%s | cpu:%s | bios:%s | biosdate:%s | numcpu:%d | memsz:%d | memfr:%d' % \
+ (m, p, c, b, r, self.cpucount, self.memtotal, self.memfree)
+ try:
+ kcmd = open('/proc/cmdline', 'r').read().strip()
+ except:
+ kcmd = ''
+ if kcmd:
+ self.sysstamp += '\n# kparams | %s' % kcmd
def printSystemInfo(self, fatal=False):
self.rootCheck(True)
out = dmidecode(self.mempath, fatal)
@@ -361,10 +402,10 @@ class SystemValues:
return
fmt = '%-24s: %s'
for name in sorted(out):
- print fmt % (name, out[name])
- print fmt % ('cpucount', ('%d' % self.cpucount))
- print fmt % ('memtotal', ('%d kB' % self.memtotal))
- print fmt % ('memfree', ('%d kB' % self.memfree))
+ print(fmt % (name, out[name]))
+ print(fmt % ('cpucount', ('%d' % self.cpucount)))
+ print(fmt % ('memtotal', ('%d kB' % self.memtotal)))
+ print(fmt % ('memfree', ('%d kB' % self.memfree)))
def cpuInfo(self):
self.cpucount = 0
fp = open('/proc/cpuinfo', 'r')
@@ -384,7 +425,7 @@ class SystemValues:
def initTestOutput(self, name):
self.prefix = self.hostname
v = open('/proc/version', 'r').read().strip()
- kver = string.split(v)[2]
+ kver = v.split()[2]
fmt = name+'-%m%d%y-%H%M%S'
testtime = datetime.now().strftime(fmt)
self.teststamp = \
@@ -399,7 +440,7 @@ class SystemValues:
self.htmlfile = \
self.testdir+'/'+self.prefix+'_'+self.suspendmode+'.html'
if not os.path.isdir(self.testdir):
- os.mkdir(self.testdir)
+ os.makedirs(self.testdir)
def getValueList(self, value):
out = []
for i in value.split(','):
@@ -410,6 +451,12 @@ class SystemValues:
self.devicefilter = self.getValueList(value)
def setCallgraphFilter(self, value):
self.cgfilter = self.getValueList(value)
+ def skipKprobes(self, value):
+ for k in self.getValueList(value):
+ if k in self.tracefuncs:
+ del self.tracefuncs[k]
+ if k in self.dev_tracefuncs:
+ del self.dev_tracefuncs[k]
def setCallgraphBlacklist(self, file):
self.cgblacklist = self.listFromFile(file)
def rtcWakeAlarmOn(self):
@@ -429,7 +476,7 @@ class SystemValues:
fp = Popen('dmesg', stdout=PIPE).stdout
ktime = '0'
for line in fp:
- line = line.replace('\r\n', '')
+ line = ascii(line).replace('\r\n', '')
idx = line.find('[')
if idx > 1:
line = line[idx:]
@@ -443,7 +490,7 @@ class SystemValues:
# store all new dmesg lines since initdmesg was called
fp = Popen('dmesg', stdout=PIPE).stdout
for line in fp:
- line = line.replace('\r\n', '')
+ line = ascii(line).replace('\r\n', '')
idx = line.find('[')
if idx > 1:
line = line[idx:]
@@ -475,13 +522,13 @@ class SystemValues:
call('cat '+self.tpath+'available_filter_functions', shell=True)
return
master = self.listFromFile(self.tpath+'available_filter_functions')
- for i in self.tracefuncs:
+ for i in sorted(self.tracefuncs):
if 'func' in self.tracefuncs[i]:
i = self.tracefuncs[i]['func']
if i in master:
- print i
+ print(i)
else:
- print self.colorText(i)
+ print(self.colorText(i))
def setFtraceFilterFunctions(self, list):
master = self.listFromFile(self.tpath+'available_filter_functions')
flist = ''
@@ -602,7 +649,7 @@ class SystemValues:
self.fsetVal(kprobeevents, 'kprobe_events')
if output:
check = self.fgetVal('kprobe_events')
- linesack = (len(check.split('\n')) - 1) / 2
+ linesack = (len(check.split('\n')) - 1) // 2
pprint(' kprobe functions enabled: %d/%d' % (linesack, linesout))
self.fsetVal('1', 'events/kprobes/enable')
def testKprobe(self, kname, kprobe):
@@ -620,19 +667,19 @@ class SystemValues:
if linesack < linesout:
return False
return True
- def setVal(self, val, file, mode='w'):
+ def setVal(self, val, file):
if not os.path.exists(file):
return False
try:
- fp = open(file, mode, 0)
- fp.write(val)
+ fp = open(file, 'wb', 0)
+ fp.write(val.encode())
fp.flush()
fp.close()
except:
return False
return True
- def fsetVal(self, val, path, mode='w'):
- return self.setVal(val, self.tpath+path, mode)
+ def fsetVal(self, val, path):
+ return self.setVal(val, self.tpath+path)
def getVal(self, file):
res = ''
if not os.path.exists(file):
@@ -688,11 +735,12 @@ class SystemValues:
if self.bufsize > 0:
tgtsize = self.bufsize
elif self.usecallgraph or self.usedevsrc:
- bmax = (1*1024*1024) if self.suspendmode == 'disk' else (3*1024*1024)
+ bmax = (1*1024*1024) if self.suspendmode in ['disk', 'command'] \
+ else (3*1024*1024)
tgtsize = min(self.memfree, bmax)
else:
tgtsize = 65536
- while not self.fsetVal('%d' % (tgtsize / cpus), 'buffer_size_kb'):
+ while not self.fsetVal('%d' % (tgtsize // cpus), 'buffer_size_kb'):
# if the size failed to set, lower it and keep trying
tgtsize -= 65536
if tgtsize < 65536:
@@ -723,7 +771,10 @@ class SystemValues:
cf.append(self.tracefuncs[fn]['func'])
else:
cf.append(fn)
- self.setFtraceFilterFunctions(cf)
+ if self.ftop:
+ self.setFtraceFilterFunctions([self.ftopfunc])
+ else:
+ self.setFtraceFilterFunctions(cf)
# initialize the kprobe trace
elif self.usekprobes:
for name in self.tracefuncs:
@@ -776,9 +827,21 @@ class SystemValues:
fw = test['fw']
if(fw):
fp.write('# fwsuspend %u fwresume %u\n' % (fw[0], fw[1]))
+ if 'mcelog' in test:
+ fp.write('# mcelog %s\n' % test['mcelog'])
+ if 'turbo' in test:
+ fp.write('# turbostat %s\n' % test['turbo'])
if 'bat' in test:
(a1, c1), (a2, c2) = test['bat']
fp.write('# battery %s %d %s %d\n' % (a1, c1, a2, c2))
+ if 'wifi' in test:
+ wstr = []
+ for wifi in test['wifi']:
+ tmp = []
+ for key in sorted(wifi):
+ tmp.append('%s:%s' % (key, wifi[key]))
+ wstr.append('|'.join(tmp))
+ fp.write('# wifi %s\n' % (','.join(wstr)))
if test['error'] or len(testdata) > 1:
fp.write('# enter_sleep_error %s\n' % test['error'])
return fp
@@ -821,14 +884,244 @@ class SystemValues:
isgz = self.gzip
if mode == 'r':
try:
- with gzip.open(filename, mode+'b') as fp:
+ with gzip.open(filename, mode+'t') as fp:
test = fp.read(64)
isgz = True
except:
isgz = False
if isgz:
- return gzip.open(filename, mode+'b')
+ return gzip.open(filename, mode+'t')
return open(filename, mode)
+ def b64unzip(self, data):
+ try:
+ out = codecs.decode(base64.b64decode(data), 'zlib').decode()
+ except:
+ out = data
+ return out
+ def b64zip(self, data):
+ out = base64.b64encode(codecs.encode(data.encode(), 'zlib')).decode()
+ return out
+ def mcelog(self, clear=False):
+ cmd = self.getExec('mcelog')
+ if not cmd:
+ return ''
+ if clear:
+ call(cmd+' > /dev/null 2>&1', shell=True)
+ return ''
+ try:
+ fp = Popen([cmd], stdout=PIPE, stderr=PIPE).stdout
+ out = ascii(fp.read()).strip()
+ fp.close()
+ except:
+ return ''
+ if not out:
+ return ''
+ return self.b64zip(out)
+ def platforminfo(self):
+ # add platform info on to a completed ftrace file
+ if not os.path.exists(self.ftracefile):
+ return False
+ footer = '#\n'
+
+ # add test command string line if need be
+ if self.suspendmode == 'command' and self.testcommand:
+ footer += '# platform-testcmd: %s\n' % (self.testcommand)
+
+ # get a list of target devices from the ftrace file
+ props = dict()
+ tp = TestProps()
+ tf = self.openlog(self.ftracefile, 'r')
+ for line in tf:
+ # determine the trace data type (required for further parsing)
+ m = re.match(tp.tracertypefmt, line)
+ if(m):
+ tp.setTracerType(m.group('t'))
+ continue
+ # parse only valid lines, if this is not one move on
+ m = re.match(tp.ftrace_line_fmt, line)
+ if(not m or 'device_pm_callback_start' not in line):
+ continue
+ m = re.match('.*: (?P<drv>.*) (?P<d>.*), parent: *(?P<p>.*), .*', m.group('msg'));
+ if(not m):
+ continue
+ dev = m.group('d')
+ if dev not in props:
+ props[dev] = DevProps()
+ tf.close()
+
+ # now get the syspath for each target device
+ for dirname, dirnames, filenames in os.walk('/sys/devices'):
+ if(re.match('.*/power', dirname) and 'async' in filenames):
+ dev = dirname.split('/')[-2]
+ if dev in props and (not props[dev].syspath or len(dirname) < len(props[dev].syspath)):
+ props[dev].syspath = dirname[:-6]
+
+ # now fill in the properties for our target devices
+ for dev in sorted(props):
+ dirname = props[dev].syspath
+ if not dirname or not os.path.exists(dirname):
+ continue
+ with open(dirname+'/power/async') as fp:
+ text = fp.read()
+ props[dev].isasync = False
+ if 'enabled' in text:
+ props[dev].isasync = True
+ fields = os.listdir(dirname)
+ if 'product' in fields:
+ with open(dirname+'/product', 'rb') as fp:
+ props[dev].altname = ascii(fp.read())
+ elif 'name' in fields:
+ with open(dirname+'/name', 'rb') as fp:
+ props[dev].altname = ascii(fp.read())
+ elif 'model' in fields:
+ with open(dirname+'/model', 'rb') as fp:
+ props[dev].altname = ascii(fp.read())
+ elif 'description' in fields:
+ with open(dirname+'/description', 'rb') as fp:
+ props[dev].altname = ascii(fp.read())
+ elif 'id' in fields:
+ with open(dirname+'/id', 'rb') as fp:
+ props[dev].altname = ascii(fp.read())
+ elif 'idVendor' in fields and 'idProduct' in fields:
+ idv, idp = '', ''
+ with open(dirname+'/idVendor', 'rb') as fp:
+ idv = ascii(fp.read()).strip()
+ with open(dirname+'/idProduct', 'rb') as fp:
+ idp = ascii(fp.read()).strip()
+ props[dev].altname = '%s:%s' % (idv, idp)
+ if props[dev].altname:
+ out = props[dev].altname.strip().replace('\n', ' ')\
+ .replace(',', ' ').replace(';', ' ')
+ props[dev].altname = out
+
+ # add a devinfo line to the bottom of ftrace
+ out = ''
+ for dev in sorted(props):
+ out += props[dev].out(dev)
+ footer += '# platform-devinfo: %s\n' % self.b64zip(out)
+
+ # add a line for each of these commands with their outputs
+ cmds = [
+ ['pcidevices', 'lspci', '-tv'],
+ ['interrupts', 'cat', '/proc/interrupts'],
+ ['gpecounts', 'sh', '-c', 'grep -v invalid /sys/firmware/acpi/interrupts/gpe*'],
+ ]
+ for cargs in cmds:
+ name = cargs[0]
+ cmdline = ' '.join(cargs[1:])
+ cmdpath = self.getExec(cargs[1])
+ if not cmdpath:
+ continue
+ cmd = [cmdpath] + cargs[2:]
+ try:
+ fp = Popen(cmd, stdout=PIPE, stderr=PIPE).stdout
+ info = ascii(fp.read()).strip()
+ fp.close()
+ except:
+ continue
+ if not info:
+ continue
+ footer += '# platform-%s: %s | %s\n' % (name, cmdline, self.b64zip(info))
+
+ with self.openlog(self.ftracefile, 'a') as fp:
+ fp.write(footer)
+ return True
+ def haveTurbostat(self):
+ if not self.tstat:
+ return False
+ cmd = self.getExec('turbostat')
+ if not cmd:
+ return False
+ fp = Popen([cmd, '-v'], stdout=PIPE, stderr=PIPE).stderr
+ out = ascii(fp.read()).strip()
+ fp.close()
+ if re.match('turbostat version [0-9\.]* .*', out):
+ sysvals.vprint(out)
+ return True
+ return False
+ def turbostat(self):
+ cmd = self.getExec('turbostat')
+ rawout = keyline = valline = ''
+ fullcmd = '%s -q -S echo freeze > %s' % (cmd, self.powerfile)
+ fp = Popen(['sh', '-c', fullcmd], stdout=PIPE, stderr=PIPE).stderr
+ for line in fp:
+ line = ascii(line)
+ rawout += line
+ if keyline and valline:
+ continue
+ if re.match('(?i)Avg_MHz.*', line):
+ keyline = line.strip().split()
+ elif keyline:
+ valline = line.strip().split()
+ fp.close()
+ if not keyline or not valline or len(keyline) != len(valline):
+ errmsg = 'unrecognized turbostat output:\n'+rawout.strip()
+ sysvals.vprint(errmsg)
+ if not sysvals.verbose:
+ pprint(errmsg)
+ return ''
+ if sysvals.verbose:
+ pprint(rawout.strip())
+ out = []
+ for key in keyline:
+ idx = keyline.index(key)
+ val = valline[idx]
+ out.append('%s=%s' % (key, val))
+ return '|'.join(out)
+ def checkWifi(self):
+ out = dict()
+ iwcmd, ifcmd = self.getExec('iwconfig'), self.getExec('ifconfig')
+ if not iwcmd or not ifcmd:
+ return out
+ fp = Popen(iwcmd, stdout=PIPE, stderr=PIPE).stdout
+ for line in fp:
+ m = re.match('(?P<dev>\S*) .* ESSID:(?P<ess>\S*)', ascii(line))
+ if not m:
+ continue
+ out['device'] = m.group('dev')
+ if '"' in m.group('ess'):
+ out['essid'] = m.group('ess').strip('"')
+ break
+ fp.close()
+ if 'device' in out:
+ fp = Popen([ifcmd, out['device']], stdout=PIPE, stderr=PIPE).stdout
+ for line in fp:
+ m = re.match('.* inet (?P<ip>[0-9\.]*)', ascii(line))
+ if m:
+ out['ip'] = m.group('ip')
+ break
+ fp.close()
+ return out
+ def errorSummary(self, errinfo, msg):
+ found = False
+ for entry in errinfo:
+ if re.match(entry['match'], msg):
+ entry['count'] += 1
+ if self.hostname not in entry['urls']:
+ entry['urls'][self.hostname] = [self.htmlfile]
+ elif self.htmlfile not in entry['urls'][self.hostname]:
+ entry['urls'][self.hostname].append(self.htmlfile)
+ found = True
+ break
+ if found:
+ return
+ arr = msg.split()
+ for j in range(len(arr)):
+ if re.match('^[0-9,\-\.]*$', arr[j]):
+ arr[j] = '[0-9,\-\.]*'
+ else:
+ arr[j] = arr[j]\
+ .replace('\\', '\\\\').replace(']', '\]').replace('[', '\[')\
+ .replace('.', '\.').replace('+', '\+').replace('*', '\*')\
+ .replace('(', '\(').replace(')', '\)')
+ mstr = ' '.join(arr)
+ entry = {
+ 'line': msg,
+ 'match': mstr,
+ 'count': 1,
+ 'urls': {self.hostname: [self.htmlfile]}
+ }
+ errinfo.append(entry)
sysvals = SystemValues()
switchvalues = ['enable', 'disable', 'on', 'off', 'true', 'false', '1', '0']
@@ -848,13 +1141,13 @@ class DevProps:
def __init__(self):
self.syspath = ''
self.altname = ''
- self.async = True
+ self.isasync = True
self.xtraclass = ''
self.xtrainfo = ''
def out(self, dev):
- return '%s,%s,%d;' % (dev, self.altname, self.async)
+ return '%s,%s,%d;' % (dev, self.altname, self.isasync)
def debug(self, dev):
- pprint('%s:\n\taltname = %s\n\t async = %s' % (dev, self.altname, self.async))
+ pprint('%s:\n\taltname = %s\n\t async = %s' % (dev, self.altname, self.isasync))
def altName(self, dev):
if not self.altname or self.altname == dev:
return dev
@@ -862,13 +1155,13 @@ class DevProps:
def xtraClass(self):
if self.xtraclass:
return ' '+self.xtraclass
- if not self.async:
+ if not self.isasync:
return ' sync'
return ''
def xtraInfo(self):
if self.xtraclass:
return ' '+self.xtraclass
- if self.async:
+ if self.isasync:
return ' async_device'
return ' sync_device'
@@ -923,7 +1216,14 @@ class Data:
'ERROR' : '.*ERROR.*',
'WARNING' : '.*WARNING.*',
'IRQ' : '.*genirq: .*',
- 'TASKFAIL': '.*Freezing of tasks failed.*',
+ 'TASKFAIL': '.*Freezing of tasks *.*',
+ 'ACPI' : '.*ACPI *(?P<b>[A-Za-z]*) *Error[: ].*',
+ 'DEVFAIL' : '.* failed to (?P<b>[a-z]*) async: .*',
+ 'DISKFULL': '.*No space left on device.*',
+ 'USBERR' : '.*usb .*device .*, error [0-9-]*',
+ 'ATAERR' : ' *ata[0-9\.]*: .*failed.*',
+ 'MEIERR' : ' *mei.*: .*failed.*',
+ 'TPMERR' : '(?i) *tpm *tpm[0-9]*: .*error.*',
}
def __init__(self, num):
idchar = 'abcdefghij'
@@ -941,6 +1241,9 @@ class Data:
self.outfile = ''
self.kerror = False
self.battery = 0
+ self.wifi = 0
+ self.turbostat = 0
+ self.mcelog = 0
self.enterfail = ''
self.currphase = ''
self.pstl = dict() # process timeline
@@ -956,7 +1259,7 @@ class Data:
return sorted(self.dmesg, key=lambda k:self.dmesg[k]['order'])
def initDevicegroups(self):
# called when phases are all finished being added
- for phase in self.dmesg.keys():
+ for phase in sorted(self.dmesg.keys()):
if '*' in phase:
p = phase.split('*')
pnew = '%s%d' % (p[0], len(p))
@@ -975,8 +1278,24 @@ class Data:
if len(plist) < 1:
return ''
return plist[-1]
+ def turbostatInfo(self):
+ tp = TestProps()
+ out = {'syslpi':'N/A','pkgpc10':'N/A'}
+ for line in self.dmesgtext:
+ m = re.match(tp.tstatfmt, line)
+ if not m:
+ continue
+ for i in m.group('t').split('|'):
+ if 'SYS%LPI' in i:
+ out['syslpi'] = i.split('=')[-1]+'%'
+ elif 'pc10' in i:
+ out['pkgpc10'] = i.split('=')[-1]+'%'
+ break
+ return out
def extractErrorInfo(self):
- lf = sysvals.openlog(sysvals.dmesgfile, 'r')
+ lf = self.dmesgtext
+ if len(self.dmesgtext) < 1 and sysvals.dmesgfile:
+ lf = sysvals.openlog(sysvals.dmesgfile, 'r')
i = 0
list = []
for line in lf:
@@ -991,16 +1310,19 @@ class Data:
msg = m.group('msg')
for err in self.errlist:
if re.match(self.errlist[err], msg):
- list.append((err, dir, t, i, i))
+ list.append((msg, err, dir, t, i, i))
self.kerror = True
break
- for e in list:
- type, dir, t, idx1, idx2 = e
+ msglist = []
+ for msg, type, dir, t, idx1, idx2 in list:
+ msglist.append(msg)
sysvals.vprint('kernel %s found in %s at %f' % (type, dir, t))
self.errorinfo[dir].append((type, t, idx1, idx2))
if self.kerror:
sysvals.dmesglog = True
- lf.close()
+ if len(self.dmesgtext) < 1 and sysvals.dmesgfile:
+ lf.close()
+ return msglist
def setStart(self, time):
self.start = time
def setEnd(self, time):
@@ -1259,16 +1581,7 @@ class Data:
return phase
def sortedDevices(self, phase):
list = self.dmesg[phase]['list']
- slist = []
- tmp = dict()
- for devname in list:
- dev = list[devname]
- if dev['length'] == 0:
- continue
- tmp[dev['start']] = devname
- for t in sorted(tmp):
- slist.append(tmp[t])
- return slist
+ return sorted(list, key=lambda k:list[k]['start'])
def fixupInitcalls(self, phase):
# if any calls never returned, clip them at system resume end
phaselist = self.dmesg[phase]['list']
@@ -1405,7 +1718,7 @@ class Data:
maxname = '%d' % self.maxDeviceNameSize(phase)
fmt = '%3d) %'+maxname+'s - %f - %f'
c = 1
- for name in devlist:
+ for name in sorted(devlist):
s = devlist[name]['start']
e = devlist[name]['end']
sysvals.vprint(fmt % (c, name, s, e))
@@ -1417,7 +1730,7 @@ class Data:
devlist = []
for phase in self.sortedPhases():
list = self.deviceChildren(devname, phase)
- for dev in list:
+ for dev in sorted(list):
if dev not in devlist:
devlist.append(dev)
return devlist
@@ -1457,16 +1770,16 @@ class Data:
def rootDeviceList(self):
# list of devices graphed
real = []
- for phase in self.dmesg:
+ for phase in self.sortedPhases():
list = self.dmesg[phase]['list']
- for dev in list:
+ for dev in sorted(list):
if list[dev]['pid'] >= 0 and dev not in real:
real.append(dev)
# list of top-most root devices
rootlist = []
- for phase in self.dmesg:
+ for phase in self.sortedPhases():
list = self.dmesg[phase]['list']
- for dev in list:
+ for dev in sorted(list):
pdev = list[dev]['par']
pid = list[dev]['pid']
if(pid < 0 or re.match('[0-9]*-[0-9]*\.[0-9]*[\.0-9]*\:[\.0-9]*$', pdev)):
@@ -1547,9 +1860,9 @@ class Data:
def createProcessUsageEvents(self):
# get an array of process names
proclist = []
- for t in self.pstl:
+ for t in sorted(self.pstl):
pslist = self.pstl[t]
- for ps in pslist:
+ for ps in sorted(pslist):
if ps not in proclist:
proclist.append(ps)
# get a list of data points for suspend and resume
@@ -1594,7 +1907,7 @@ class Data:
def debugPrint(self):
for p in self.sortedPhases():
list = self.dmesg[p]['list']
- for devname in list:
+ for devname in sorted(list):
dev = list[devname]
if 'ftrace' in dev:
dev['ftrace'].debugPrint(' [%s]' % devname)
@@ -2053,7 +2366,7 @@ class FTraceCallGraph:
if(data.dmesg[p]['start'] <= self.start and
self.start <= data.dmesg[p]['end']):
list = data.dmesg[p]['list']
- for devname in list:
+ for devname in sorted(list, key=lambda k:list[k]['start']):
dev = list[devname]
if(pid == dev['pid'] and
self.start <= dev['start'] and
@@ -2295,7 +2608,7 @@ class Timeline:
# if there is 1 line per row, draw them the standard way
for t, p in standardphases:
for i in sorted(self.rowheight[t][p]):
- self.rowheight[t][p][i] = self.bodyH/len(self.rowlines[t][p])
+ self.rowheight[t][p][i] = float(self.bodyH)/len(self.rowlines[t][p])
def createZoomBox(self, mode='command', testcount=1):
# Create bounding box, add buttons
html_zoombox = '<center><button id="zoomin">ZOOM IN +</button><button id="zoomout">ZOOM OUT -</button><button id="zoomdef">ZOOM 1:1</button></center>\n'
@@ -2358,11 +2671,15 @@ class TestProps:
'(?P<H>[0-9]{2})(?P<M>[0-9]{2})(?P<S>[0-9]{2})'+\
' (?P<host>.*) (?P<mode>.*) (?P<kernel>.*)$'
batteryfmt = '^# battery (?P<a1>\w*) (?P<c1>\d*) (?P<a2>\w*) (?P<c2>\d*)'
+ wififmt = '^# wifi (?P<w>.*)'
+ tstatfmt = '^# turbostat (?P<t>\S*)'
+ mcelogfmt = '^# mcelog (?P<m>\S*)'
testerrfmt = '^# enter_sleep_error (?P<e>.*)'
sysinfofmt = '^# sysinfo .*'
cmdlinefmt = '^# command \| (?P<cmd>.*)'
kparamsfmt = '^# kparams \| (?P<kp>.*)'
devpropfmt = '# Device Properties: .*'
+ pinfofmt = '# platform-(?P<val>[a-z,A-Z,0-9]*): (?P<info>.*)'
tracertypefmt = '# tracer: (?P<t>.*)'
firmwarefmt = '# fwsuspend (?P<s>[0-9]*) fwresume (?P<r>[0-9]*)$'
procexecfmt = 'ps - (?P<ps>.*)$'
@@ -2380,7 +2697,10 @@ class TestProps:
self.cmdline = ''
self.kparams = ''
self.testerror = []
+ self.mcelog = []
+ self.turbostat = []
self.battery = []
+ self.wifi = []
self.fwdata = []
self.ftrace_line_fmt = self.ftrace_line_fmt_nop
self.cgformat = False
@@ -2394,6 +2714,38 @@ class TestProps:
self.ftrace_line_fmt = self.ftrace_line_fmt_nop
else:
doError('Invalid tracer format: [%s]' % tracer)
+ def stampInfo(self, line):
+ if re.match(self.stampfmt, line):
+ self.stamp = line
+ return True
+ elif re.match(self.sysinfofmt, line):
+ self.sysinfo = line
+ return True
+ elif re.match(self.kparamsfmt, line):
+ self.kparams = line
+ return True
+ elif re.match(self.cmdlinefmt, line):
+ self.cmdline = line
+ return True
+ elif re.match(self.mcelogfmt, line):
+ self.mcelog.append(line)
+ return True
+ elif re.match(self.tstatfmt, line):
+ self.turbostat.append(line)
+ return True
+ elif re.match(self.batteryfmt, line):
+ self.battery.append(line)
+ return True
+ elif re.match(self.wififmt, line):
+ self.wifi.append(line)
+ return True
+ elif re.match(self.testerrfmt, line):
+ self.testerror.append(line)
+ return True
+ elif re.match(self.firmwarefmt, line):
+ self.fwdata.append(line)
+ return True
+ return False
def parseStamp(self, data, sv):
# global test data
m = re.match(self.stampfmt, self.stamp)
@@ -2436,19 +2788,76 @@ class TestProps:
sv.stamp = data.stamp
# firmware data
if sv.suspendmode == 'mem' and len(self.fwdata) > data.testnumber:
- data.fwSuspend, data.fwResume = self.fwdata[data.testnumber]
- if(data.fwSuspend > 0 or data.fwResume > 0):
- data.fwValid = True
+ m = re.match(self.firmwarefmt, self.fwdata[data.testnumber])
+ if m:
+ data.fwSuspend, data.fwResume = int(m.group('s')), int(m.group('r'))
+ if(data.fwSuspend > 0 or data.fwResume > 0):
+ data.fwValid = True
+ # mcelog data
+ if len(self.mcelog) > data.testnumber:
+ m = re.match(self.mcelogfmt, self.mcelog[data.testnumber])
+ if m:
+ data.mcelog = sv.b64unzip(m.group('m'))
+ # turbostat data
+ if len(self.turbostat) > data.testnumber:
+ m = re.match(self.tstatfmt, self.turbostat[data.testnumber])
+ if m:
+ data.turbostat = m.group('t')
# battery data
if len(self.battery) > data.testnumber:
m = re.match(self.batteryfmt, self.battery[data.testnumber])
if m:
data.battery = m.groups()
+ # wifi data
+ if len(self.wifi) > data.testnumber:
+ m = re.match(self.wififmt, self.wifi[data.testnumber])
+ if m:
+ data.wifi = m.group('w')
# sleep mode enter errors
if len(self.testerror) > data.testnumber:
m = re.match(self.testerrfmt, self.testerror[data.testnumber])
if m:
data.enterfail = m.group('e')
+ def devprops(self, data):
+ props = dict()
+ devlist = data.split(';')
+ for dev in devlist:
+ f = dev.split(',')
+ if len(f) < 3:
+ continue
+ dev = f[0]
+ props[dev] = DevProps()
+ props[dev].altname = f[1]
+ if int(f[2]):
+ props[dev].isasync = True
+ else:
+ props[dev].isasync = False
+ return props
+ def parseDevprops(self, line, sv):
+ idx = line.index(': ') + 2
+ if idx >= len(line):
+ return
+ props = self.devprops(line[idx:])
+ if sv.suspendmode == 'command' and 'testcommandstring' in props:
+ sv.testcommand = props['testcommandstring'].altname
+ sv.devprops = props
+ def parsePlatformInfo(self, line, sv):
+ m = re.match(self.pinfofmt, line)
+ if not m:
+ return
+ name, info = m.group('val'), m.group('info')
+ if name == 'devinfo':
+ sv.devprops = self.devprops(sv.b64unzip(info))
+ return
+ elif name == 'testcmd':
+ sv.testcommand = info
+ return
+ field = info.split('|')
+ if len(field) < 2:
+ return
+ cmdline = field[0].strip()
+ output = sv.b64unzip(field[1].strip())
+ sv.platinfo.append([name, cmdline, output])
# Class: TestRun
# Description:
@@ -2469,7 +2878,7 @@ class ProcessMonitor:
process = Popen(c, shell=True, stdout=PIPE)
running = dict()
for line in process.stdout:
- data = line.split()
+ data = ascii(line).split()
pid = data[0]
name = re.sub('[()]', '', data[1])
user = int(data[13])
@@ -2513,9 +2922,9 @@ class ProcessMonitor:
# Quickly determine if the ftrace log has all of the trace events,
# markers, and/or kprobes required for primary parsing.
def doesTraceLogHaveTraceEvents():
- kpcheck = ['_cal: (', '_cpu_down()']
+ kpcheck = ['_cal: (', '_ret: (']
techeck = ['suspend_resume', 'device_pm_callback']
- tmcheck = ['tracing_mark_write']
+ tmcheck = ['SUSPEND START', 'RESUME COMPLETE']
sysvals.usekprobes = False
fp = sysvals.openlog(sysvals.ftracefile, 'r')
for line in fp:
@@ -2564,21 +2973,7 @@ def appendIncompleteTraceLog(testruns):
for line in tf:
# remove any latent carriage returns
line = line.replace('\r\n', '')
- # grab the stamp and sysinfo
- if re.match(tp.stampfmt, line):
- tp.stamp = line
- continue
- elif re.match(tp.sysinfofmt, line):
- tp.sysinfo = line
- continue
- elif re.match(tp.cmdlinefmt, line):
- tp.cmdline = line
- continue
- elif re.match(tp.batteryfmt, line):
- tp.battery.append(line)
- continue
- elif re.match(tp.testerrfmt, line):
- tp.testerror.append(line)
+ if tp.stampInfo(line):
continue
# determine the trace data type (required for further parsing)
m = re.match(tp.tracertypefmt, line)
@@ -2587,7 +2982,11 @@ def appendIncompleteTraceLog(testruns):
continue
# device properties line
if(re.match(tp.devpropfmt, line)):
- devProps(line)
+ tp.parseDevprops(line, sysvals)
+ continue
+ # platform info line
+ if(re.match(tp.pinfofmt, line)):
+ tp.parsePlatformInfo(line, sysvals)
continue
# parse only valid lines, if this is not one move on
m = re.match(tp.ftrace_line_fmt, line)
@@ -2684,7 +3083,7 @@ def parseTraceLog(live=False):
sysvals.setupAllKprobes()
ksuscalls = ['pm_prepare_console']
krescalls = ['pm_restore_console']
- tracewatch = []
+ tracewatch = ['irq_wakeup']
if sysvals.usekprobes:
tracewatch += ['sync_filesystems', 'freeze_processes', 'syscore_suspend',
'syscore_resume', 'resume_console', 'thaw_processes', 'CPU_ON',
@@ -2701,26 +3100,7 @@ def parseTraceLog(live=False):
for line in tf:
# remove any latent carriage returns
line = line.replace('\r\n', '')
- # stamp and sysinfo lines
- if re.match(tp.stampfmt, line):
- tp.stamp = line
- continue
- elif re.match(tp.sysinfofmt, line):
- tp.sysinfo = line
- continue
- elif re.match(tp.cmdlinefmt, line):
- tp.cmdline = line
- continue
- elif re.match(tp.batteryfmt, line):
- tp.battery.append(line)
- continue
- elif re.match(tp.testerrfmt, line):
- tp.testerror.append(line)
- continue
- # firmware line: pull out any firmware data
- m = re.match(tp.firmwarefmt, line)
- if(m):
- tp.fwdata.append((int(m.group('s')), int(m.group('r'))))
+ if tp.stampInfo(line):
continue
# tracer type line: determine the trace data type
m = re.match(tp.tracertypefmt, line)
@@ -2729,7 +3109,11 @@ def parseTraceLog(live=False):
continue
# device properties line
if(re.match(tp.devpropfmt, line)):
- devProps(line)
+ tp.parseDevprops(line, sysvals)
+ continue
+ # platform info line
+ if(re.match(tp.pinfofmt, line)):
+ tp.parsePlatformInfo(line, sysvals)
continue
# ignore all other commented lines
if line[0] == '#':
@@ -2802,16 +3186,11 @@ def parseTraceLog(live=False):
isbegin = False
else:
continue
- m = re.match('(?P<name>.*)\[(?P<val>[0-9]*)\] .*', t.name)
- if(m):
- val = m.group('val')
- if val == '0':
- name = m.group('name')
- else:
- name = m.group('name')+'['+val+']'
+ if '[' in t.name:
+ m = re.match('(?P<name>.*)\[.*', t.name)
else:
m = re.match('(?P<name>.*) .*', t.name)
- name = m.group('name')
+ name = m.group('name')
# ignore these events
if(name.split('[')[0] in tracewatch):
continue
@@ -2846,6 +3225,8 @@ def parseTraceLog(live=False):
elif(re.match('machine_suspend\[.*', t.name)):
if(isbegin):
lp = data.lastPhase()
+ if lp == 'resume_machine':
+ data.dmesg[lp]['end'] = t.time
phase = data.setPhase('suspend_machine', data.dmesg[lp]['end'], True)
data.setPhase(phase, t.time, False)
if data.tSuspended == 0:
@@ -2933,7 +3314,7 @@ def parseTraceLog(live=False):
tp.ktemp[key].append({
'pid': pid,
'begin': t.time,
- 'end': t.time,
+ 'end': -1,
'name': displayname,
'cdata': kprobedata,
'proc': m_proc,
@@ -2944,12 +3325,11 @@ def parseTraceLog(live=False):
elif(t.freturn):
if(key not in tp.ktemp) or len(tp.ktemp[key]) < 1:
continue
- e = tp.ktemp[key][-1]
- if e['begin'] < 0.0 or t.time - e['begin'] < 0.000001:
- tp.ktemp[key].pop()
- else:
- e['end'] = t.time
- e['rdata'] = kprobedata
+ e = next((x for x in reversed(tp.ktemp[key]) if x['end'] < 0), 0)
+ if not e:
+ continue
+ e['end'] = t.time
+ e['rdata'] = kprobedata
# end of kernel resume
if(phase != 'suspend_prepare' and kprobename in krescalls):
if phase in data.dmesg:
@@ -2971,8 +3351,10 @@ def parseTraceLog(live=False):
if(res == -1):
testrun.ftemp[key][-1].addLine(t)
tf.close()
+ if len(testdata) < 1:
+ sysvals.vprint('WARNING: ftrace start marker is missing')
if data and not data.devicegroups:
- sysvals.vprint('WARNING: end marker is missing')
+ sysvals.vprint('WARNING: ftrace end marker is missing')
data.handleEndMarker(t.time)
if sysvals.suspendmode == 'command':
@@ -3013,36 +3395,38 @@ def parseTraceLog(live=False):
# add the traceevent data to the device hierarchy
if(sysvals.usetraceevents):
# add actual trace funcs
- for name in test.ttemp:
+ for name in sorted(test.ttemp):
for event in test.ttemp[name]:
data.newActionGlobal(name, event['begin'], event['end'], event['pid'])
# add the kprobe based virtual tracefuncs as actual devices
- for key in tp.ktemp:
+ for key in sorted(tp.ktemp):
name, pid = key
if name not in sysvals.tracefuncs:
continue
+ if pid not in data.devpids:
+ data.devpids.append(pid)
for e in tp.ktemp[key]:
kb, ke = e['begin'], e['end']
- if kb == ke or tlb > kb or tle <= kb:
+ if ke - kb < 0.000001 or tlb > kb or tle <= kb:
continue
color = sysvals.kprobeColor(name)
data.newActionGlobal(e['name'], kb, ke, pid, color)
# add config base kprobes and dev kprobes
if sysvals.usedevsrc:
- for key in tp.ktemp:
+ for key in sorted(tp.ktemp):
name, pid = key
if name in sysvals.tracefuncs or name not in sysvals.dev_tracefuncs:
continue
for e in tp.ktemp[key]:
kb, ke = e['begin'], e['end']
- if kb == ke or tlb > kb or tle <= kb:
+ if ke - kb < 0.000001 or tlb > kb or tle <= kb:
continue
data.addDeviceFunctionCall(e['name'], name, e['proc'], pid, kb,
ke, e['cdata'], e['rdata'])
if sysvals.usecallgraph:
# add the callgraph data to the device hierarchy
sortlist = dict()
- for key in test.ftemp:
+ for key in sorted(test.ftemp):
proc, pid = key
for cg in test.ftemp[key]:
if len(cg.list) < 1 or cg.invalid or (cg.end - cg.start == 0):
@@ -3059,7 +3443,7 @@ def parseTraceLog(live=False):
if not devname:
sortkey = '%f%f%d' % (cg.start, cg.end, pid)
sortlist[sortkey] = cg
- elif len(cg.list) > 1000000:
+ elif len(cg.list) > 1000000 and cg.name != sysvals.ftopfunc:
sysvals.vprint('WARNING: the callgraph for %s is massive (%d lines)' %\
(devname, len(cg.list)))
# create blocks for orphan cg data
@@ -3141,25 +3525,7 @@ def loadKernelLog():
idx = line.find('[')
if idx > 1:
line = line[idx:]
- # grab the stamp and sysinfo
- if re.match(tp.stampfmt, line):
- tp.stamp = line
- continue
- elif re.match(tp.sysinfofmt, line):
- tp.sysinfo = line
- continue
- elif re.match(tp.cmdlinefmt, line):
- tp.cmdline = line
- continue
- elif re.match(tp.batteryfmt, line):
- tp.battery.append(line)
- continue
- elif re.match(tp.testerrfmt, line):
- tp.testerror.append(line)
- continue
- m = re.match(tp.firmwarefmt, line)
- if(m):
- tp.fwdata.append((int(m.group('s')), int(m.group('r'))))
+ if tp.stampInfo(line):
continue
m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line)
if(not m):
@@ -3184,7 +3550,7 @@ def loadKernelLog():
if data:
testruns.append(data)
if len(testruns) < 1:
- pprint('ERROR: dmesg log has no suspend/resume data: %s' \
+ doError('dmesg log has no suspend/resume data: %s' \
% sysvals.dmesgfile)
# fix lines with same timestamp/function with the call and return swapped
@@ -3398,7 +3764,7 @@ def parseKernelLog(data):
# if trace events are not available, these are better than nothing
if(not sysvals.usetraceevents):
# look for known actions
- for a in at:
+ for a in sorted(at):
if(re.match(at[a]['smsg'], msg)):
if(a not in actions):
actions[a] = []
@@ -3457,7 +3823,7 @@ def parseKernelLog(data):
data.tResumed = data.tSuspended
# fill in any actions we've found
- for name in actions:
+ for name in sorted(actions):
for event in actions[name]:
data.newActionGlobal(name, event['begin'], event['end'])
@@ -3523,6 +3889,8 @@ def addCallgraphs(sv, hf, data):
name += ' '+p
if('ftrace' in dev):
cg = dev['ftrace']
+ if cg.name == sv.ftopfunc:
+ name = 'top level suspend/resume call'
num = callgraphHTML(sv, hf, num, cg,
name, color, dev['id'])
if('ftraces' in dev):
@@ -3531,22 +3899,16 @@ def addCallgraphs(sv, hf, data):
name+' &rarr; '+cg.name, color, dev['id'])
hf.write('\n\n </section>\n')
-# Function: createHTMLSummarySimple
-# Description:
-# Create summary html file for a series of tests
-# Arguments:
-# testruns: array of Data objects from parseTraceLog
-def createHTMLSummarySimple(testruns, htmlfile, title):
- # write the html header first (html head, css code, up to body start)
- html = '<!DOCTYPE html>\n<html>\n<head>\n\
+def summaryCSS(title, center=True):
+ tdcenter = 'text-align:center;' if center else ''
+ out = '<!DOCTYPE html>\n<html>\n<head>\n\
<meta http-equiv="content-type" content="text/html; charset=UTF-8">\n\
- <title>SleepGraph Summary</title>\n\
+ <title>'+title+'</title>\n\
<style type=\'text/css\'>\n\
.stamp {width: 100%;text-align:center;background:#888;line-height:30px;color:white;font: 25px Arial;}\n\
- table {width:100%;border-collapse: collapse;}\n\
- .summary {border:1px solid;}\n\
+ table {width:100%;border-collapse: collapse;border:1px solid;}\n\
th {border: 1px solid black;background:#222;color:white;}\n\
- td {font: 14px "Times New Roman";text-align: center;}\n\
+ td {font: 14px "Times New Roman";'+tdcenter+'}\n\
tr.head td {border: 1px solid black;background:#aaa;}\n\
tr.alt {background-color:#ddd;}\n\
tr.notice {color:red;}\n\
@@ -3555,12 +3917,23 @@ def createHTMLSummarySimple(testruns, htmlfile, title):
.maxval {background-color:#FFBBBB;}\n\
.head a {color:#000;text-decoration: none;}\n\
</style>\n</head>\n<body>\n'
+ return out
+
+# Function: createHTMLSummarySimple
+# Description:
+# Create summary html file for a series of tests
+# Arguments:
+# testruns: array of Data objects from parseTraceLog
+def createHTMLSummarySimple(testruns, htmlfile, title):
+ # write the html header first (html head, css code, up to body start)
+ html = summaryCSS('Summary - SleepGraph')
# extract the test data into list
list = dict()
- tAvg, tMin, tMax, tMed = [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [[], []]
+ tAvg, tMin, tMax, tMed = [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [dict(), dict()]
iMin, iMed, iMax = [0, 0], [0, 0], [0, 0]
num = 0
+ useturbo = False
lastmode = ''
cnt = dict()
for data in sorted(testruns, key=lambda v:(v['mode'], v['host'], v['kernel'], v['time'])):
@@ -3570,28 +3943,36 @@ def createHTMLSummarySimple(testruns, htmlfile, title):
if lastmode and lastmode != mode and num > 0:
for i in range(2):
s = sorted(tMed[i])
- list[lastmode]['med'][i] = s[int(len(s)/2)]
- iMed[i] = tMed[i].index(list[lastmode]['med'][i])
+ list[lastmode]['med'][i] = s[int(len(s)//2)]
+ iMed[i] = tMed[i][list[lastmode]['med'][i]]
list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num]
list[lastmode]['min'] = tMin
list[lastmode]['max'] = tMax
list[lastmode]['idx'] = (iMin, iMed, iMax)
- tAvg, tMin, tMax, tMed = [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [[], []]
+ tAvg, tMin, tMax, tMed = [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [dict(), dict()]
iMin, iMed, iMax = [0, 0], [0, 0], [0, 0]
num = 0
+ pkgpc10 = syslpi = ''
+ if 'pkgpc10' in data and 'syslpi' in data:
+ pkgpc10 = data['pkgpc10']
+ syslpi = data['syslpi']
+ useturbo = True
+ res = data['result']
tVal = [float(data['suspend']), float(data['resume'])]
list[mode]['data'].append([data['host'], data['kernel'],
- data['time'], tVal[0], tVal[1], data['url'], data['result'],
+ data['time'], tVal[0], tVal[1], data['url'], res,
data['issues'], data['sus_worst'], data['sus_worsttime'],
- data['res_worst'], data['res_worsttime']])
+ data['res_worst'], data['res_worsttime'], pkgpc10, syslpi])
idx = len(list[mode]['data']) - 1
- if data['result'] not in cnt:
- cnt[data['result']] = 1
+ if res.startswith('fail in'):
+ res = 'fail'
+ if res not in cnt:
+ cnt[res] = 1
else:
- cnt[data['result']] += 1
- if data['result'] == 'pass':
+ cnt[res] += 1
+ if res == 'pass':
for i in range(2):
- tMed[i].append(tVal[i])
+ tMed[i][tVal[i]] = idx
tAvg[i] += tVal[i]
if tMin[i] == 0 or tVal[i] < tMin[i]:
iMin[i] = idx
@@ -3604,8 +3985,8 @@ def createHTMLSummarySimple(testruns, htmlfile, title):
if lastmode and num > 0:
for i in range(2):
s = sorted(tMed[i])
- list[lastmode]['med'][i] = s[int(len(s)/2)]
- iMed[i] = tMed[i].index(list[lastmode]['med'][i])
+ list[lastmode]['med'][i] = s[int(len(s)//2)]
+ iMed[i] = tMed[i][list[lastmode]['med'][i]]
list[lastmode]['avg'] = [tAvg[0] / num, tAvg[1] / num]
list[lastmode]['min'] = tMin
list[lastmode]['max'] = tMax
@@ -3621,19 +4002,21 @@ def createHTMLSummarySimple(testruns, htmlfile, title):
td = '\t<td>{0}</td>\n'
tdh = '\t<td{1}>{0}</td>\n'
tdlink = '\t<td><a href="{0}">html</a></td>\n'
+ colspan = '14' if useturbo else '12'
# table header
- html += '<table class="summary">\n<tr>\n' + th.format('#') +\
+ html += '<table>\n<tr>\n' + th.format('#') +\
th.format('Mode') + th.format('Host') + th.format('Kernel') +\
th.format('Test Time') + th.format('Result') + th.format('Issues') +\
th.format('Suspend') + th.format('Resume') +\
th.format('Worst Suspend Device') + th.format('SD Time') +\
- th.format('Worst Resume Device') + th.format('RD Time') +\
- th.format('Detail') + '</tr>\n'
-
+ th.format('Worst Resume Device') + th.format('RD Time')
+ if useturbo:
+ html += th.format('PkgPC10') + th.format('SysLPI')
+ html += th.format('Detail')+'</tr>\n'
# export list into html
head = '<tr class="head"><td>{0}</td><td>{1}</td>'+\
- '<td colspan=12 class="sus">Suspend Avg={2} '+\
+ '<td colspan='+colspan+' class="sus">Suspend Avg={2} '+\
'<span class=minval><a href="#s{10}min">Min={3}</a></span> '+\
'<span class=medval><a href="#s{10}med">Med={4}</a></span> '+\
'<span class=maxval><a href="#s{10}max">Max={5}</a></span> '+\
@@ -3642,8 +4025,9 @@ def createHTMLSummarySimple(testruns, htmlfile, title):
'<span class=medval><a href="#r{10}med">Med={8}</a></span> '+\
'<span class=maxval><a href="#r{10}max">Max={9}</a></span></td>'+\
'</tr>\n'
- headnone = '<tr class="head"><td>{0}</td><td>{1}</td><td colspan=12></td></tr>\n'
- for mode in list:
+ headnone = '<tr class="head"><td>{0}</td><td>{1}</td><td colspan='+\
+ colspan+'></td></tr>\n'
+ for mode in sorted(list):
# header line for each suspend mode
num = 0
tAvg, tMin, tMax, tMed = list[mode]['avg'], list[mode]['min'],\
@@ -3689,6 +4073,9 @@ def createHTMLSummarySimple(testruns, htmlfile, title):
html += td.format('%.3f ms' % d[9]) if d[9] else td.format('') # sus_worst time
html += td.format(d[10]) # res_worst
html += td.format('%.3f ms' % d[11]) if d[11] else td.format('') # res_worst time
+ if useturbo:
+ html += td.format(d[12]) # pkg_pc10
+ html += td.format(d[13]) # syslpi
html += tdlink.format(d[5]) if d[5] else td.format('') # url
html += '</tr>\n'
num += 1
@@ -3698,6 +4085,116 @@ def createHTMLSummarySimple(testruns, htmlfile, title):
hf.write(html+'</table>\n</body>\n</html>\n')
hf.close()
+def createHTMLDeviceSummary(testruns, htmlfile, title):
+ html = summaryCSS('Device Summary - SleepGraph', False)
+
+ # create global device list from all tests
+ devall = dict()
+ for data in testruns:
+ host, url, devlist = data['host'], data['url'], data['devlist']
+ for type in devlist:
+ if type not in devall:
+ devall[type] = dict()
+ mdevlist, devlist = devall[type], data['devlist'][type]
+ for name in devlist:
+ length = devlist[name]
+ if name not in mdevlist:
+ mdevlist[name] = {'name': name, 'host': host,
+ 'worst': length, 'total': length, 'count': 1,
+ 'url': url}
+ else:
+ if length > mdevlist[name]['worst']:
+ mdevlist[name]['worst'] = length
+ mdevlist[name]['url'] = url
+ mdevlist[name]['host'] = host
+ mdevlist[name]['total'] += length
+ mdevlist[name]['count'] += 1
+
+ # generate the html
+ th = '\t<th>{0}</th>\n'
+ td = '\t<td align=center>{0}</td>\n'
+ tdr = '\t<td align=right>{0}</td>\n'
+ tdlink = '\t<td align=center><a href="{0}">html</a></td>\n'
+ limit = 1
+ for type in sorted(devall, reverse=True):
+ num = 0
+ devlist = devall[type]
+ # table header
+ html += '<div class="stamp">%s (%s devices > %d ms)</div><table>\n' % \
+ (title, type.upper(), limit)
+ html += '<tr>\n' + '<th align=right>Device Name</th>' +\
+ th.format('Average Time') + th.format('Count') +\
+ th.format('Worst Time') + th.format('Host (worst time)') +\
+ th.format('Link (worst time)') + '</tr>\n'
+ for name in sorted(devlist, key=lambda k:(devlist[k]['worst'], \
+ devlist[k]['total'], devlist[k]['name']), reverse=True):
+ data = devall[type][name]
+ data['average'] = data['total'] / data['count']
+ if data['average'] < limit:
+ continue
+ # row classes - alternate row color
+ rcls = ['alt'] if num % 2 == 1 else []
+ html += '<tr class="'+(' '.join(rcls))+'">\n' if len(rcls) > 0 else '<tr>\n'
+ html += tdr.format(data['name']) # name
+ html += td.format('%.3f ms' % data['average']) # average
+ html += td.format(data['count']) # count
+ html += td.format('%.3f ms' % data['worst']) # worst
+ html += td.format(data['host']) # host
+ html += tdlink.format(data['url']) # url
+ html += '</tr>\n'
+ num += 1
+ html += '</table>\n'
+
+ # flush the data to file
+ hf = open(htmlfile, 'w')
+ hf.write(html+'</body>\n</html>\n')
+ hf.close()
+ return devall
+
+def createHTMLIssuesSummary(testruns, issues, htmlfile, title, extra=''):
+ multihost = len([e for e in issues if len(e['urls']) > 1]) > 0
+ html = summaryCSS('Issues Summary - SleepGraph', False)
+ total = len(testruns)
+
+ # generate the html
+ th = '\t<th>{0}</th>\n'
+ td = '\t<td align={0}>{1}</td>\n'
+ tdlink = '<a href="{1}">{0}</a>'
+ subtitle = '%d issues' % len(issues) if len(issues) > 0 else 'no issues'
+ html += '<div class="stamp">%s (%s)</div><table>\n' % (title, subtitle)
+ html += '<tr>\n' + th.format('Issue') + th.format('Count')
+ if multihost:
+ html += th.format('Hosts')
+ html += th.format('Tests') + th.format('Fail Rate') +\
+ th.format('First Instance') + '</tr>\n'
+
+ num = 0
+ for e in sorted(issues, key=lambda v:v['count'], reverse=True):
+ testtotal = 0
+ links = []
+ for host in sorted(e['urls']):
+ links.append(tdlink.format(host, e['urls'][host][0]))
+ testtotal += len(e['urls'][host])
+ rate = '%d/%d (%.2f%%)' % (testtotal, total, 100*float(testtotal)/float(total))
+ # row classes - alternate row color
+ rcls = ['alt'] if num % 2 == 1 else []
+ html += '<tr class="'+(' '.join(rcls))+'">\n' if len(rcls) > 0 else '<tr>\n'
+ html += td.format('left', e['line']) # issue
+ html += td.format('center', e['count']) # count
+ if multihost:
+ html += td.format('center', len(e['urls'])) # hosts
+ html += td.format('center', testtotal) # test count
+ html += td.format('center', rate) # test rate
+ html += td.format('center nowrap', '<br>'.join(links)) # links
+ html += '</tr>\n'
+ num += 1
+
+ # flush the data to file
+ hf = open(htmlfile, 'w')
+ hf.write(html+'</table>\n'+extra+'</body>\n</html>\n')
+ hf.close()
+ return issues
+
def ordinal(value):
suffix = 'th'
if value < 10 or value > 19:
@@ -3771,7 +4268,7 @@ def createHTML(testruns, testfail):
if(tTotal == 0):
doError('No timeline data')
if(len(data.tLow) > 0):
- low_time = '|'.join(data.tLow)
+ low_time = '+'.join(data.tLow)
if sysvals.suspendmode == 'command':
run_time = '%.0f'%((data.end-data.start)*1000)
if sysvals.testcommand:
@@ -3837,7 +4334,7 @@ def createHTML(testruns, testfail):
for group in data.devicegroups:
devlist = []
for phase in group:
- for devname in data.tdevlist[phase]:
+ for devname in sorted(data.tdevlist[phase]):
d = DevItem(data.testnumber, phase, data.dmesg[phase]['list'][devname])
devlist.append(d)
if d.isa('kth'):
@@ -3916,7 +4413,7 @@ def createHTML(testruns, testfail):
for b in phases[dir]:
# draw the devices for this phase
phaselist = data.dmesg[b]['list']
- for d in data.tdevlist[b]:
+ for d in sorted(data.tdevlist[b]):
name = d
drv = ''
dev = phaselist[d]
@@ -3999,7 +4496,7 @@ def createHTML(testruns, testfail):
for word in phase.split('_'):
id += word[0]
order = '%.2f' % ((p['order'] * pdelta) + pmargin)
- name = string.replace(phase, '_', ' &nbsp;')
+ name = phase.replace('_', ' &nbsp;')
devtl.html += devtl.html_legend.format(order, p['color'], name, id)
devtl.html += '</div>\n'
@@ -4588,6 +5085,7 @@ def setRuntimeSuspend(before=True):
def executeSuspend():
pm = ProcessMonitor()
tp = sysvals.tpath
+ wifi = sysvals.checkWifi()
testdata = []
battery = True if getBattery() else False
# run these commands to prepare the system for suspend
@@ -4621,6 +5119,7 @@ def executeSuspend():
pprint('SUSPEND START')
else:
pprint('SUSPEND START (press a key to resume)')
+ sysvals.mcelog(True)
bat1 = getBattery() if battery else False
# set rtcwake
if(sysvals.rtcwake):
@@ -4652,13 +5151,19 @@ def executeSuspend():
pf = open(sysvals.diskpowerfile, 'w')
pf.write(sysvals.diskmode)
pf.close()
- pf = open(sysvals.powerfile, 'w')
- pf.write(mode)
- # execution will pause here
- try:
- pf.close()
- except Exception as e:
- tdata['error'] = str(e)
+ if mode == 'freeze' and sysvals.haveTurbostat():
+ # execution will pause here
+ turbo = sysvals.turbostat()
+ if turbo:
+ tdata['turbo'] = turbo
+ else:
+ pf = open(sysvals.powerfile, 'w')
+ pf.write(mode)
+ # execution will pause here
+ try:
+ pf.close()
+ except Exception as e:
+ tdata['error'] = str(e)
if(sysvals.rtcwake):
sysvals.rtcWakeAlarmOff()
# postdelay delay
@@ -4672,9 +5177,14 @@ def executeSuspend():
sysvals.fsetVal('RESUME COMPLETE', 'trace_marker')
if(sysvals.suspendmode == 'mem' or sysvals.suspendmode == 'command'):
tdata['fw'] = getFPDT(False)
+ mcelog = sysvals.mcelog()
+ if mcelog:
+ tdata['mcelog'] = mcelog
bat2 = getBattery() if battery else False
if battery and bat1 and bat2:
tdata['bat'] = (bat1, bat2)
+ if 'device' in wifi and 'ip' in wifi:
+ tdata['wifi'] = (wifi, sysvals.checkWifi())
testdata.append(tdata)
# stop ftrace
if(sysvals.usecallgraph or sysvals.usetraceevents):
@@ -4693,7 +5203,8 @@ def executeSuspend():
op.write(line)
op.close()
sysvals.fsetVal('', 'trace')
- devProps()
+ sysvals.platforminfo()
+ return testdata
def readFile(file):
if os.path.islink(file):
@@ -4708,9 +5219,9 @@ def readFile(file):
# The time string, e.g. "1901m16s"
def ms2nice(val):
val = int(val)
- h = val / 3600000
- m = (val / 60000) % 60
- s = (val / 1000) % 60
+ h = val // 3600000
+ m = (val // 60000) % 60
+ s = (val // 1000) % 60
if h > 0:
return '%d:%02d:%02d' % (h, m, s)
if m > 0:
@@ -4780,130 +5291,9 @@ def deviceInfo(output=''):
ms2nice(power['runtime_active_time']), \
ms2nice(power['runtime_suspended_time']))
for i in sorted(lines):
- print lines[i]
+ print(lines[i])
return res
-# Function: devProps
-# Description:
-# Retrieve a list of properties for all devices in the trace log
-def devProps(data=0):
- props = dict()
-
- if data:
- idx = data.index(': ') + 2
- if idx >= len(data):
- return
- devlist = data[idx:].split(';')
- for dev in devlist:
- f = dev.split(',')
- if len(f) < 3:
- continue
- dev = f[0]
- props[dev] = DevProps()
- props[dev].altname = f[1]
- if int(f[2]):
- props[dev].async = True
- else:
- props[dev].async = False
- sysvals.devprops = props
- if sysvals.suspendmode == 'command' and 'testcommandstring' in props:
- sysvals.testcommand = props['testcommandstring'].altname
- return
-
- if(os.path.exists(sysvals.ftracefile) == False):
- doError('%s does not exist' % sysvals.ftracefile)
-
- # first get the list of devices we need properties for
- msghead = 'Additional data added by AnalyzeSuspend'
- alreadystamped = False
- tp = TestProps()
- tf = sysvals.openlog(sysvals.ftracefile, 'r')
- for line in tf:
- if msghead in line:
- alreadystamped = True
- continue
- # determine the trace data type (required for further parsing)
- m = re.match(tp.tracertypefmt, line)
- if(m):
- tp.setTracerType(m.group('t'))
- continue
- # parse only valid lines, if this is not one move on
- m = re.match(tp.ftrace_line_fmt, line)
- if(not m or 'device_pm_callback_start' not in line):
- continue
- m = re.match('.*: (?P<drv>.*) (?P<d>.*), parent: *(?P<p>.*), .*', m.group('msg'));
- if(not m):
- continue
- dev = m.group('d')
- if dev not in props:
- props[dev] = DevProps()
- tf.close()
-
- if not alreadystamped and sysvals.suspendmode == 'command':
- out = '#\n# '+msghead+'\n# Device Properties: '
- out += 'testcommandstring,%s,0;' % (sysvals.testcommand)
- with sysvals.openlog(sysvals.ftracefile, 'a') as fp:
- fp.write(out+'\n')
- sysvals.devprops = props
- return
-
- # now get the syspath for each of our target devices
- for dirname, dirnames, filenames in os.walk('/sys/devices'):
- if(re.match('.*/power', dirname) and 'async' in filenames):
- dev = dirname.split('/')[-2]
- if dev in props and (not props[dev].syspath or len(dirname) < len(props[dev].syspath)):
- props[dev].syspath = dirname[:-6]
-
- # now fill in the properties for our target devices
- for dev in props:
- dirname = props[dev].syspath
- if not dirname or not os.path.exists(dirname):
- continue
- with open(dirname+'/power/async') as fp:
- text = fp.read()
- props[dev].async = False
- if 'enabled' in text:
- props[dev].async = True
- fields = os.listdir(dirname)
- if 'product' in fields:
- with open(dirname+'/product') as fp:
- props[dev].altname = fp.read()
- elif 'name' in fields:
- with open(dirname+'/name') as fp:
- props[dev].altname = fp.read()
- elif 'model' in fields:
- with open(dirname+'/model') as fp:
- props[dev].altname = fp.read()
- elif 'description' in fields:
- with open(dirname+'/description') as fp:
- props[dev].altname = fp.read()
- elif 'id' in fields:
- with open(dirname+'/id') as fp:
- props[dev].altname = fp.read()
- elif 'idVendor' in fields and 'idProduct' in fields:
- idv, idp = '', ''
- with open(dirname+'/idVendor') as fp:
- idv = fp.read().strip()
- with open(dirname+'/idProduct') as fp:
- idp = fp.read().strip()
- props[dev].altname = '%s:%s' % (idv, idp)
-
- if props[dev].altname:
- out = props[dev].altname.strip().replace('\n', ' ')
- out = out.replace(',', ' ')
- out = out.replace(';', ' ')
- props[dev].altname = out
-
- # and now write the data to the ftrace file
- if not alreadystamped:
- out = '#\n# '+msghead+'\n# Device Properties: '
- for dev in sorted(props):
- out += props[dev].out(dev)
- with sysvals.openlog(sysvals.ftracefile, 'a') as fp:
- fp.write(out+'\n')
-
- sysvals.devprops = props
-
# Function: getModes
# Description:
# Determine the supported power modes on this system
@@ -4913,12 +5303,12 @@ def getModes():
modes = []
if(os.path.exists(sysvals.powerfile)):
fp = open(sysvals.powerfile, 'r')
- modes = string.split(fp.read())
+ modes = fp.read().split()
fp.close()
if(os.path.exists(sysvals.mempowerfile)):
deep = False
fp = open(sysvals.mempowerfile, 'r')
- for m in string.split(fp.read()):
+ for m in fp.read().split():
memmode = m.strip('[]')
if memmode == 'deep':
deep = True
@@ -4929,7 +5319,7 @@ def getModes():
modes.remove('mem')
if('disk' in modes and os.path.exists(sysvals.diskpowerfile)):
fp = open(sysvals.diskpowerfile, 'r')
- for m in string.split(fp.read()):
+ for m in fp.read().split():
modes.append('disk-%s' % m.strip('[]'))
fp.close()
return modes
@@ -4992,25 +5382,26 @@ def dmidecode(mempath, fatal=False):
continue
# read in the memory for scanning
- fp = open(mempath, 'rb')
try:
+ fp = open(mempath, 'rb')
fp.seek(memaddr)
buf = fp.read(memsize)
except:
if(fatal):
doError('DMI table is unreachable, sorry')
else:
+ pprint('WARNING: /dev/mem is not readable, ignoring DMI data')
return out
fp.close()
# search for either an SM table or DMI table
i = base = length = num = 0
while(i < memsize):
- if buf[i:i+4] == '_SM_' and i < memsize - 16:
+ if buf[i:i+4] == b'_SM_' and i < memsize - 16:
length = struct.unpack('H', buf[i+22:i+24])[0]
base, num = struct.unpack('IH', buf[i+24:i+30])
break
- elif buf[i:i+5] == '_DMI_':
+ elif buf[i:i+5] == b'_DMI_':
length = struct.unpack('H', buf[i+6:i+8])[0]
base, num = struct.unpack('IH', buf[i+8:i+14])
break
@@ -5022,14 +5413,15 @@ def dmidecode(mempath, fatal=False):
return out
# read in the SM or DMI table
- fp = open(mempath, 'rb')
try:
+ fp = open(mempath, 'rb')
fp.seek(base)
buf = fp.read(length)
except:
if(fatal):
doError('DMI table is unreachable, sorry')
else:
+ pprint('WARNING: /dev/mem is not readable, ignoring DMI data')
return out
fp.close()
@@ -5042,15 +5434,15 @@ def dmidecode(mempath, fatal=False):
if 0 == struct.unpack('H', buf[n:n+2])[0]:
break
n += 1
- data = buf[i+size:n+2].split('\0')
+ data = buf[i+size:n+2].split(b'\0')
for name in info:
itype, idxadr = info[name]
if itype == type:
- idx = struct.unpack('B', buf[i+idxadr])[0]
+ idx = struct.unpack('B', buf[i+idxadr:i+idxadr+1])[0]
if idx > 0 and idx < len(data) - 1:
- s = data[idx-1].strip()
- if s and s.lower() != 'to be filled by o.e.m.':
- out[name] = data[idx-1]
+ s = data[idx-1].decode('utf-8')
+ if s.strip() and s.strip().lower() != 'to be filled by o.e.m.':
+ out[name] = s
i = n + 2
count += 1
return out
@@ -5075,7 +5467,7 @@ def getBattery():
return (ac, charge)
def displayControl(cmd):
- xset, ret = 'xset -d :0.0 {0}', 0
+ xset, ret = 'timeout 10 xset -d :0.0 {0}', 0
if sysvals.sudouser:
xset = 'sudo -u %s %s' % (sysvals.sudouser, xset)
if cmd == 'init':
@@ -5099,7 +5491,7 @@ def displayControl(cmd):
fp = Popen(xset.format('q').split(' '), stdout=PIPE).stdout
ret = 'unknown'
for line in fp:
- m = re.match('[\s]*Monitor is (?P<m>.*)', line)
+ m = re.match('[\s]*Monitor is (?P<m>.*)', ascii(line))
if(m and len(m.group('m')) >= 2):
out = m.group('m').lower()
ret = out[3:] if out[0:2] == 'in' else out
@@ -5161,10 +5553,11 @@ def getFPDT(output):
' OEM Revision : %u\n'\
' Creator ID : %s\n'\
' Creator Revision : 0x%x\n'\
- '' % (table[0], table[0], table[1], table[2], table[3],
- table[4], table[5], table[6], table[7], table[8]))
+ '' % (ascii(table[0]), ascii(table[0]), table[1], table[2],
+ table[3], ascii(table[4]), ascii(table[5]), table[6],
+ ascii(table[7]), table[8]))
- if(table[0] != 'FPDT'):
+ if(table[0] != b'FPDT'):
if(output):
doError('Invalid FPDT table')
return False
@@ -5173,7 +5566,11 @@ def getFPDT(output):
i = 0
fwData = [0, 0]
records = buf[36:]
- fp = open(sysvals.mempath, 'rb')
+ try:
+ fp = open(sysvals.mempath, 'rb')
+ except:
+ pprint('WARNING: /dev/mem is not readable, ignoring the FPDT data')
+ return False
while(i < len(records)):
header = struct.unpack('HBB', records[i:i+4])
if(header[0] not in rectype):
@@ -5192,8 +5589,8 @@ def getFPDT(output):
return [0, 0]
rechead = struct.unpack('4sI', first)
recdata = fp.read(rechead[1]-8)
- if(rechead[0] == 'FBPT'):
- record = struct.unpack('HBBIQQQQQ', recdata)
+ if(rechead[0] == b'FBPT'):
+ record = struct.unpack('HBBIQQQQQ', recdata[:48])
if(output):
pprint('%s (%s)\n'\
' Reset END : %u ns\n'\
@@ -5201,11 +5598,11 @@ def getFPDT(output):
' OS Loader StartImage Start : %u ns\n'\
' ExitBootServices Entry : %u ns\n'\
' ExitBootServices Exit : %u ns'\
- '' % (rectype[header[0]], rechead[0], record[4], record[5],
+ '' % (rectype[header[0]], ascii(rechead[0]), record[4], record[5],
record[6], record[7], record[8]))
- elif(rechead[0] == 'S3PT'):
+ elif(rechead[0] == b'S3PT'):
if(output):
- pprint('%s (%s)' % (rectype[header[0]], rechead[0]))
+ pprint('%s (%s)' % (rectype[header[0]], ascii(rechead[0])))
j = 0
while(j < len(recdata)):
prechead = struct.unpack('HBB', recdata[j:j+4])
@@ -5290,13 +5687,14 @@ def statusCheck(probecheck=False):
pprint(' is ftrace supported: %s' % res)
# check if kprobes are available
- res = sysvals.colorText('NO')
- sysvals.usekprobes = sysvals.verifyKprobes()
- if(sysvals.usekprobes):
- res = 'YES'
- else:
- sysvals.usedevsrc = False
- pprint(' are kprobes supported: %s' % res)
+ if sysvals.usekprobes:
+ res = sysvals.colorText('NO')
+ sysvals.usekprobes = sysvals.verifyKprobes()
+ if(sysvals.usekprobes):
+ res = 'YES'
+ else:
+ sysvals.usedevsrc = False
+ pprint(' are kprobes supported: %s' % res)
# what data source are we using
res = 'DMESG'
@@ -5350,7 +5748,7 @@ def doError(msg, help=False):
def getArgInt(name, args, min, max, main=True):
if main:
try:
- arg = args.next()
+ arg = next(args)
except:
doError(name+': no argument supplied', True)
else:
@@ -5369,7 +5767,7 @@ def getArgInt(name, args, min, max, main=True):
def getArgFloat(name, args, min, max, main=True):
if main:
try:
- arg = args.next()
+ arg = next(args)
except:
doError(name+': no argument supplied', True)
else:
@@ -5384,6 +5782,8 @@ def getArgFloat(name, args, min, max, main=True):
def processData(live=False):
pprint('PROCESSING DATA')
+ sysvals.vprint('usetraceevents=%s, usetracemarkers=%s, usekprobes=%s' % \
+ (sysvals.usetraceevents, sysvals.usetracemarkers, sysvals.usekprobes))
error = ''
if(sysvals.usetraceevents):
testruns, error = parseTraceLog(live)
@@ -5396,14 +5796,46 @@ def processData(live=False):
parseKernelLog(data)
if(sysvals.ftracefile and (sysvals.usecallgraph or sysvals.usetraceevents)):
appendIncompleteTraceLog(testruns)
+ shown = ['bios', 'biosdate', 'cpu', 'host', 'kernel', 'man', 'memfr',
+ 'memsz', 'mode', 'numcpu', 'plat', 'time']
+ sysvals.vprint('System Info:')
+ for key in sorted(sysvals.stamp):
+ if key in shown:
+ sysvals.vprint(' %-8s : %s' % (key.upper(), sysvals.stamp[key]))
+ if sysvals.kparams:
+ sysvals.vprint('Kparams:\n %s' % sysvals.kparams)
sysvals.vprint('Command:\n %s' % sysvals.cmdline)
for data in testruns:
+ if data.mcelog:
+ sysvals.vprint('MCELOG Data:')
+ for line in data.mcelog.split('\n'):
+ sysvals.vprint(' %s' % line)
+ if data.turbostat:
+ idx, s = 0, 'Turbostat:\n '
+ for val in data.turbostat.split('|'):
+ idx += len(val) + 1
+ if idx >= 80:
+ idx = 0
+ s += '\n '
+ s += val + ' '
+ sysvals.vprint(s)
if data.battery:
a1, c1, a2, c2 = data.battery
s = 'Battery:\n Before - AC: %s, Charge: %d\n After - AC: %s, Charge: %d' % \
(a1, int(c1), a2, int(c2))
sysvals.vprint(s)
+ if data.wifi:
+ w = data.wifi.replace('|', ' ').split(',')
+ s = 'Wifi:\n Before %s\n After %s' % \
+ (w[0], w[1])
+ sysvals.vprint(s)
data.printDetails()
+ if len(sysvals.platinfo) > 0:
+ sysvals.vprint('\nPlatform Info:')
+ for info in sysvals.platinfo:
+ sysvals.vprint(info[0]+' - '+info[1])
+ sysvals.vprint(info[2])
+ sysvals.vprint('')
if sysvals.cgdump:
for data in testruns:
data.debugPrint()
@@ -5426,12 +5858,15 @@ def processData(live=False):
# Function: rerunTest
# Description:
# generate an output from an existing set of ftrace/dmesg logs
-def rerunTest():
+def rerunTest(htmlfile=''):
if sysvals.ftracefile:
doesTraceLogHaveTraceEvents()
if not sysvals.dmesgfile and not sysvals.usetraceevents:
doError('recreating this html output requires a dmesg file')
- sysvals.setOutputFile()
+ if htmlfile:
+ sysvals.htmlfile = htmlfile
+ else:
+ sysvals.setOutputFile()
if os.path.exists(sysvals.htmlfile):
if not os.path.isfile(sysvals.htmlfile):
doError('a directory already exists with this name: %s' % sysvals.htmlfile)
@@ -5450,14 +5885,18 @@ def runTest(n=0):
sysvals.initTestOutput('suspend')
# execute the test
- executeSuspend()
+ testdata = executeSuspend()
sysvals.cleanupFtrace()
if sysvals.skiphtml:
sysvals.sudoUserchown(sysvals.testdir)
return
- testruns, stamp = processData(True)
- for data in testruns:
- del data
+ if not testdata[0]['error']:
+ testruns, stamp = processData(True)
+ for data in testruns:
+ del data
+ else:
+ stamp = testdata[0]
+
sysvals.sudoUserchown(sysvals.testdir)
sysvals.outputResult(stamp, n)
if 'error' in stamp:
@@ -5487,10 +5926,13 @@ def find_in_html(html, start, end, firstonly=True):
return ''
return out
-def data_from_html(file, outpath, devlist=False):
+def data_from_html(file, outpath, issues, fulldetail=False):
html = open(file, 'r').read()
+ sysvals.htmlfile = os.path.relpath(file, outpath)
+ # extract general info
suspend = find_in_html(html, 'Kernel Suspend', 'ms')
resume = find_in_html(html, 'Kernel Resume', 'ms')
+ sysinfo = find_in_html(html, '<div class="stamp sysinfo">', '</div>')
line = find_in_html(html, '<div class="stamp">', '</div>')
stmp = line.split()
if not suspend or not resume or len(stmp) != 8:
@@ -5499,6 +5941,7 @@ def data_from_html(file, outpath, devlist=False):
dt = datetime.strptime(' '.join(stmp[3:]), '%B %d %Y, %I:%M:%S %p')
except:
return False
+ sysvals.hostname = stmp[0]
tstr = dt.strftime('%Y/%m/%d %H:%M:%S')
error = find_in_html(html, '<table class="testfail"><tr><td>', '</td>')
if error:
@@ -5509,13 +5952,45 @@ def data_from_html(file, outpath, devlist=False):
result = 'fail'
else:
result = 'pass'
+ # extract error info
ilist = []
- e = find_in_html(html, 'class="err"[\w=":;\.%\- ]*>', '&rarr;</div>', False)
- for i in list(set(e)):
- ilist.append('%sx%d' % (i, e.count(i)) if e.count(i) > 1 else i)
+ extra = dict()
+ log = find_in_html(html, '<div id="dmesglog" style="display:none;">',
+ '</div>').strip()
+ if log:
+ d = Data(0)
+ d.end = 999999999
+ d.dmesgtext = log.split('\n')
+ msglist = d.extractErrorInfo()
+ for msg in msglist:
+ sysvals.errorSummary(issues, msg)
+ if stmp[2] == 'freeze':
+ extra = d.turbostatInfo()
+ elist = dict()
+ for dir in d.errorinfo:
+ for err in d.errorinfo[dir]:
+ if err[0] not in elist:
+ elist[err[0]] = 0
+ elist[err[0]] += 1
+ for i in elist:
+ ilist.append('%sx%d' % (i, elist[i]) if elist[i] > 1 else i)
low = find_in_html(html, 'freeze time: <b>', ' ms</b>')
if low and '|' in low:
- ilist.append('FREEZEx%d' % len(low.split('|')))
+ issue = 'FREEZEx%d' % len(low.split('|'))
+ match = [i for i in issues if i['match'] == issue]
+ if len(match) > 0:
+ match[0]['count'] += 1
+ if sysvals.hostname not in match[0]['urls']:
+ match[0]['urls'][sysvals.hostname] = [sysvals.htmlfile]
+ elif sysvals.htmlfile not in match[0]['urls'][sysvals.hostname]:
+ match[0]['urls'][sysvals.hostname].append(sysvals.htmlfile)
+ else:
+ issues.append({
+ 'match': issue, 'count': 1, 'line': issue,
+ 'urls': {sysvals.hostname: [sysvals.htmlfile]},
+ })
+ ilist.append(issue)
+ # extract device info
devices = dict()
for line in html.split('\n'):
m = re.match(' *<div id=\"[a,0-9]*\" *title=\"(?P<title>.*)\" class=\"thread.*', line)
@@ -5527,82 +6002,98 @@ def data_from_html(file, outpath, devlist=False):
name, time, phase = m.group('n'), m.group('t'), m.group('p')
if ' async' in name or ' sync' in name:
name = ' '.join(name.split(' ')[:-1])
- d = phase.split('_')[0]
+ if phase.startswith('suspend'):
+ d = 'suspend'
+ elif phase.startswith('resume'):
+ d = 'resume'
+ else:
+ continue
if d not in devices:
devices[d] = dict()
if name not in devices[d]:
devices[d][name] = 0.0
devices[d][name] += float(time)
- worst = {'suspend': {'name':'', 'time': 0.0},
- 'resume': {'name':'', 'time': 0.0}}
- for d in devices:
- if d not in worst:
- worst[d] = dict()
- dev = devices[d]
- if len(dev.keys()) > 0:
- n = sorted(dev, key=dev.get, reverse=True)[0]
+ # create worst device info
+ worst = dict()
+ for d in ['suspend', 'resume']:
+ worst[d] = {'name':'', 'time': 0.0}
+ dev = devices[d] if d in devices else 0
+ if dev and len(dev.keys()) > 0:
+ n = sorted(dev, key=lambda k:(dev[k], k), reverse=True)[0]
worst[d]['name'], worst[d]['time'] = n, dev[n]
data = {
'mode': stmp[2],
'host': stmp[0],
'kernel': stmp[1],
+ 'sysinfo': sysinfo,
'time': tstr,
'result': result,
'issues': ' '.join(ilist),
'suspend': suspend,
'resume': resume,
+ 'devlist': devices,
'sus_worst': worst['suspend']['name'],
'sus_worsttime': worst['suspend']['time'],
'res_worst': worst['resume']['name'],
'res_worsttime': worst['resume']['time'],
- 'url': os.path.relpath(file, outpath),
+ 'url': sysvals.htmlfile,
}
- if devlist:
- data['devlist'] = devices
+ for key in extra:
+ data[key] = extra[key]
+ if fulldetail:
+ data['funclist'] = find_in_html(html, '<div title="', '" class="traceevent"', False)
return data
+def genHtml(subdir, force=False):
+ for dirname, dirnames, filenames in os.walk(subdir):
+ sysvals.dmesgfile = sysvals.ftracefile = sysvals.htmlfile = ''
+ for filename in filenames:
+ if(re.match('.*_dmesg.txt', filename)):
+ sysvals.dmesgfile = os.path.join(dirname, filename)
+ elif(re.match('.*_ftrace.txt', filename)):
+ sysvals.ftracefile = os.path.join(dirname, filename)
+ sysvals.setOutputFile()
+ if sysvals.ftracefile and sysvals.htmlfile and \
+ (force or not os.path.exists(sysvals.htmlfile)):
+ pprint('FTRACE: %s' % sysvals.ftracefile)
+ if sysvals.dmesgfile:
+ pprint('DMESG : %s' % sysvals.dmesgfile)
+ rerunTest()
+
# Function: runSummary
# Description:
# create a summary of tests in a sub-directory
def runSummary(subdir, local=True, genhtml=False):
inpath = os.path.abspath(subdir)
outpath = os.path.abspath('.') if local else inpath
- pprint('Generating a summary of folder "%s"' % inpath)
+ pprint('Generating a summary of folder:\n %s' % inpath)
if genhtml:
- for dirname, dirnames, filenames in os.walk(subdir):
- sysvals.dmesgfile = sysvals.ftracefile = sysvals.htmlfile = ''
- for filename in filenames:
- if(re.match('.*_dmesg.txt', filename)):
- sysvals.dmesgfile = os.path.join(dirname, filename)
- elif(re.match('.*_ftrace.txt', filename)):
- sysvals.ftracefile = os.path.join(dirname, filename)
- sysvals.setOutputFile()
- if sysvals.ftracefile and sysvals.htmlfile and \
- not os.path.exists(sysvals.htmlfile):
- pprint('FTRACE: %s' % sysvals.ftracefile)
- if sysvals.dmesgfile:
- pprint('DMESG : %s' % sysvals.dmesgfile)
- rerunTest()
+ genHtml(subdir)
+ issues = []
testruns = []
desc = {'host':[],'mode':[],'kernel':[]}
for dirname, dirnames, filenames in os.walk(subdir):
for filename in filenames:
if(not re.match('.*.html', filename)):
continue
- data = data_from_html(os.path.join(dirname, filename), outpath)
+ data = data_from_html(os.path.join(dirname, filename), outpath, issues)
if(not data):
continue
testruns.append(data)
for key in desc:
if data[key] not in desc[key]:
desc[key].append(data[key])
- outfile = os.path.join(outpath, 'summary.html')
- pprint('Summary file: %s' % outfile)
+ pprint('Summary files:')
if len(desc['host']) == len(desc['mode']) == len(desc['kernel']) == 1:
title = '%s %s %s' % (desc['host'][0], desc['kernel'][0], desc['mode'][0])
else:
title = inpath
- createHTMLSummarySimple(testruns, outfile, title)
+ createHTMLSummarySimple(testruns, os.path.join(outpath, 'summary.html'), title)
+ pprint(' summary.html - tabular list of test data found')
+ createHTMLDeviceSummary(testruns, os.path.join(outpath, 'summary-devices.html'), title)
+ pprint(' summary-devices.html - kernel device list sorted by total execution time')
+ createHTMLIssuesSummary(testruns, issues, os.path.join(outpath, 'summary-issues.html'), title)
+ pprint(' summary-issues.html - kernel issues found sorted by frequency')
# Function: checkArgBool
# Description:
@@ -5619,7 +6110,7 @@ def checkArgBool(name, value):
# Description:
# Configure the script via the info in a config file
def configFromFile(file):
- Config = ConfigParser.ConfigParser()
+ Config = configparser.ConfigParser()
Config.read(file)
sections = Config.sections()
@@ -5847,6 +6338,7 @@ def printHelp():
' default: suspend-{date}-{time}\n'\
' -rtcwake t Wakeup t seconds after suspend, set t to "off" to disable (default: 15)\n'\
' -addlogs Add the dmesg and ftrace logs to the html output\n'\
+ ' -noturbostat Dont use turbostat in freeze mode (default: disabled)\n'\
' -srgap Add a visible gap in the timeline between sus/res (default: disabled)\n'\
' -skiphtml Run the test and capture the trace logs, but skip the timeline (default: disabled)\n'\
' -result fn Export a results table to a text file for parsing.\n'\
@@ -5868,6 +6360,7 @@ def printHelp():
' be created in a new subdirectory with a summary page.\n'\
' [debug]\n'\
' -f Use ftrace to create device callgraphs (default: disabled)\n'\
+ ' -ftop Use ftrace on the top level call: "%s" (default: disabled)\n'\
' -maxdepth N limit the callgraph data to N call levels (default: 0=all)\n'\
' -expandcg pre-expand the callgraph data in the html output (default: disabled)\n'\
' -fadd file Add functions to be graphed in the timeline from a list in a text file\n'\
@@ -5887,6 +6380,7 @@ def printHelp():
' -status Test to see if the system is enabled to run this tool\n'\
' -fpdt Print out the contents of the ACPI Firmware Performance Data Table\n'\
' -battery Print out battery info (if available)\n'\
+ ' -wifi Print out wifi connection info (if wireless-tools and device exists)\n'\
' -x<mode> Test xset by toggling the given mode (on/off/standby/suspend)\n'\
' -sysinfo Print out system info extracted from BIOS\n'\
' -devinfo Print out the pm settings of all devices which support runtime suspend\n'\
@@ -5896,7 +6390,7 @@ def printHelp():
' [redo]\n'\
' -ftrace ftracefile Create HTML output using ftrace input (used with -dmesg)\n'\
' -dmesg dmesgfile Create HTML output using dmesg (used with -ftrace)\n'\
- '' % (sysvals.title, sysvals.version, sysvals.suspendmode))
+ '' % (sysvals.title, sysvals.version, sysvals.suspendmode, sysvals.ftopfunc))
return True
# ----------------- MAIN --------------------
@@ -5906,7 +6400,7 @@ if __name__ == '__main__':
cmd = ''
simplecmds = ['-sysinfo', '-modes', '-fpdt', '-flist', '-flistall',
'-devinfo', '-status', '-battery', '-xon', '-xoff', '-xstandby',
- '-xsuspend', '-xinit', '-xreset', '-xstat']
+ '-xsuspend', '-xinit', '-xreset', '-xstat', '-wifi']
if '-f' in sys.argv:
sysvals.cgskip = sysvals.configFile('cgskip.txt')
# loop through the command line arguments
@@ -5914,7 +6408,7 @@ if __name__ == '__main__':
for arg in args:
if(arg == '-m'):
try:
- val = args.next()
+ val = next(args)
except:
doError('No mode supplied', True)
if val == 'command' and not sysvals.testcommand:
@@ -5938,6 +6432,10 @@ if __name__ == '__main__':
sysvals.postdelay = getArgInt('-postdelay', args, 0, 60000)
elif(arg == '-f'):
sysvals.usecallgraph = True
+ elif(arg == '-ftop'):
+ sysvals.usecallgraph = True
+ sysvals.ftop = True
+ sysvals.usekprobes = False
elif(arg == '-skiphtml'):
sysvals.skiphtml = True
elif(arg == '-cgdump'):
@@ -5948,10 +6446,14 @@ if __name__ == '__main__':
genhtml = True
elif(arg == '-addlogs'):
sysvals.dmesglog = sysvals.ftracelog = True
+ elif(arg == '-nologs'):
+ sysvals.dmesglog = sysvals.ftracelog = False
elif(arg == '-addlogdmesg'):
sysvals.dmesglog = True
elif(arg == '-addlogftrace'):
sysvals.ftracelog = True
+ elif(arg == '-noturbostat'):
+ sysvals.tstat = False
elif(arg == '-verbose'):
sysvals.verbose = True
elif(arg == '-proc'):
@@ -5964,7 +6466,7 @@ if __name__ == '__main__':
sysvals.gzip = True
elif(arg == '-rs'):
try:
- val = args.next()
+ val = next(args)
except:
doError('-rs requires "enable" or "disable"', True)
if val.lower() in switchvalues:
@@ -5976,7 +6478,7 @@ if __name__ == '__main__':
doError('invalid option: %s, use "enable/disable" or "on/off"' % val, True)
elif(arg == '-display'):
try:
- val = args.next()
+ val = next(args)
except:
doError('-display requires an mode value', True)
disopt = ['on', 'off', 'standby', 'suspend']
@@ -5987,7 +6489,7 @@ if __name__ == '__main__':
sysvals.max_graph_depth = getArgInt('-maxdepth', args, 0, 1000)
elif(arg == '-rtcwake'):
try:
- val = args.next()
+ val = next(args)
except:
doError('No rtcwake time supplied', True)
if val.lower() in switchoff:
@@ -6007,7 +6509,7 @@ if __name__ == '__main__':
sysvals.cgtest = getArgInt('-cgtest', args, 0, 1)
elif(arg == '-cgphase'):
try:
- val = args.next()
+ val = next(args)
except:
doError('No phase name supplied', True)
d = Data(0)
@@ -6017,13 +6519,19 @@ if __name__ == '__main__':
sysvals.cgphase = val
elif(arg == '-cgfilter'):
try:
- val = args.next()
+ val = next(args)
except:
doError('No callgraph functions supplied', True)
sysvals.setCallgraphFilter(val)
+ elif(arg == '-skipkprobe'):
+ try:
+ val = next(args)
+ except:
+ doError('No kprobe functions supplied', True)
+ sysvals.skipKprobes(val)
elif(arg == '-cgskip'):
try:
- val = args.next()
+ val = next(args)
except:
doError('No file supplied', True)
if val.lower() in switchoff:
@@ -6038,7 +6546,7 @@ if __name__ == '__main__':
sysvals.callloopmaxlen = getArgFloat('-callloop-maxlen', args, 0.0, 1.0)
elif(arg == '-cmd'):
try:
- val = args.next()
+ val = next(args)
except:
doError('No command string supplied', True)
sysvals.testcommand = val
@@ -6053,13 +6561,13 @@ if __name__ == '__main__':
sysvals.multitest['delay'] = getArgInt('-multi n d (delay between tests)', args, 0, 3600)
elif(arg == '-o'):
try:
- val = args.next()
+ val = next(args)
except:
doError('No subdirectory name supplied', True)
sysvals.outdir = sysvals.setOutputFolder(val)
elif(arg == '-config'):
try:
- val = args.next()
+ val = next(args)
except:
doError('No text file supplied', True)
file = sysvals.configFile(val)
@@ -6068,7 +6576,7 @@ if __name__ == '__main__':
configFromFile(file)
elif(arg == '-fadd'):
try:
- val = args.next()
+ val = next(args)
except:
doError('No text file supplied', True)
file = sysvals.configFile(val)
@@ -6077,7 +6585,7 @@ if __name__ == '__main__':
sysvals.addFtraceFilterFunctions(file)
elif(arg == '-dmesg'):
try:
- val = args.next()
+ val = next(args)
except:
doError('No dmesg file supplied', True)
sysvals.notestrun = True
@@ -6086,7 +6594,7 @@ if __name__ == '__main__':
doError('%s does not exist' % sysvals.dmesgfile)
elif(arg == '-ftrace'):
try:
- val = args.next()
+ val = next(args)
except:
doError('No ftrace file supplied', True)
sysvals.notestrun = True
@@ -6095,7 +6603,7 @@ if __name__ == '__main__':
doError('%s does not exist' % sysvals.ftracefile)
elif(arg == '-summary'):
try:
- val = args.next()
+ val = next(args)
except:
doError('No directory supplied', True)
cmd = 'summary'
@@ -6105,13 +6613,13 @@ if __name__ == '__main__':
doError('%s is not accesible' % val)
elif(arg == '-filter'):
try:
- val = args.next()
+ val = next(args)
except:
doError('No devnames supplied', True)
sysvals.setDeviceFilter(val)
elif(arg == '-result'):
try:
- val = args.next()
+ val = next(args)
except:
doError('No result file supplied', True)
sysvals.result = val
@@ -6159,7 +6667,7 @@ if __name__ == '__main__':
elif(cmd == 'devinfo'):
deviceInfo()
elif(cmd == 'modes'):
- print getModes()
+ pprint(getModes())
elif(cmd == 'flist'):
sysvals.getFtraceFilterFunctions(True)
elif(cmd == 'flistall'):
@@ -6171,11 +6679,18 @@ if __name__ == '__main__':
ret = displayControl(cmd[1:])
elif(cmd == 'xstat'):
pprint('Display Status: %s' % displayControl('stat').upper())
+ elif(cmd == 'wifi'):
+ out = sysvals.checkWifi()
+ if 'device' not in out:
+ pprint('WIFI interface not found')
+ else:
+ for key in sorted(out):
+ pprint('%6s: %s' % (key.upper(), out[key]))
sys.exit(ret)
# if instructed, re-analyze existing data files
if(sysvals.notestrun):
- stamp = rerunTest()
+ stamp = rerunTest(sysvals.outdir)
sysvals.outputResult(stamp)
sys.exit(0)
@@ -6212,7 +6727,7 @@ if __name__ == '__main__':
s = 'suspend-x%d' % sysvals.multitest['count']
sysvals.outdir = datetime.now().strftime(s+'-%y%m%d-%H%M%S')
if not os.path.isdir(sysvals.outdir):
- os.mkdir(sysvals.outdir)
+ os.makedirs(sysvals.outdir)
for i in range(sysvals.multitest['count']):
if(i != 0):
pprint('Waiting %d seconds...' % (sysvals.multitest['delay']))
diff --git a/tools/power/x86/intel-speed-select/.gitignore b/tools/power/x86/intel-speed-select/.gitignore
new file mode 100644
index 000000000000..f61145925ce9
--- /dev/null
+++ b/tools/power/x86/intel-speed-select/.gitignore
@@ -0,0 +1,2 @@
+include/
+intel-speed-select
diff --git a/tools/power/x86/intel-speed-select/Build b/tools/power/x86/intel-speed-select/Build
new file mode 100644
index 000000000000..b61456d75190
--- /dev/null
+++ b/tools/power/x86/intel-speed-select/Build
@@ -0,0 +1 @@
+intel-speed-select-y += isst-config.o isst-core.o isst-display.o
diff --git a/tools/power/x86/intel-speed-select/Makefile b/tools/power/x86/intel-speed-select/Makefile
new file mode 100644
index 000000000000..12c6939dca2a
--- /dev/null
+++ b/tools/power/x86/intel-speed-select/Makefile
@@ -0,0 +1,56 @@
+# SPDX-License-Identifier: GPL-2.0
+include ../../../scripts/Makefile.include
+
+bindir ?= /usr/bin
+
+ifeq ($(srctree),)
+srctree := $(patsubst %/,%,$(dir $(CURDIR)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+srctree := $(patsubst %/,%,$(dir $(srctree)))
+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
+
+ALL_TARGETS := intel-speed-select
+ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS))
+
+all: $(ALL_PROGRAMS)
+
+export srctree OUTPUT CC LD CFLAGS
+include $(srctree)/tools/build/Makefile.include
+
+#
+# We need the following to be outside of kernel tree
+#
+$(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
+
+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 $@
+
+clean:
+ rm -f $(ALL_PROGRAMS)
+ rm -rf $(OUTPUT)include/linux/isst_if.h
+ find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete
+
+install: $(ALL_PROGRAMS)
+ install -d -m 755 $(DESTDIR)$(bindir); \
+ for program in $(ALL_PROGRAMS); do \
+ install $$program $(DESTDIR)$(bindir); \
+ done
+
+FORCE:
+
+.PHONY: all install clean FORCE prepare
diff --git a/tools/power/x86/intel-speed-select/isst-config.c b/tools/power/x86/intel-speed-select/isst-config.c
new file mode 100644
index 000000000000..944183f9ed5a
--- /dev/null
+++ b/tools/power/x86/intel-speed-select/isst-config.c
@@ -0,0 +1,2344 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel Speed Select -- Enumerate and control features
+ * Copyright (c) 2019 Intel Corporation.
+ */
+
+#include <linux/isst_if.h>
+
+#include "isst.h"
+
+struct process_cmd_struct {
+ char *feature;
+ char *command;
+ void (*process_fn)(int arg);
+ int arg;
+};
+
+static const char *version_str = "v1.1";
+static const int supported_api_ver = 1;
+static struct isst_if_platform_info isst_platform_info;
+static char *progname;
+static int debug_flag;
+static FILE *outf;
+
+static int cpu_model;
+static int cpu_stepping;
+
+#define MAX_CPUS_IN_ONE_REQ 64
+static short max_target_cpus;
+static unsigned short target_cpus[MAX_CPUS_IN_ONE_REQ];
+
+static int topo_max_cpus;
+static size_t present_cpumask_size;
+static cpu_set_t *present_cpumask;
+static size_t target_cpumask_size;
+static cpu_set_t *target_cpumask;
+static int tdp_level = 0xFF;
+static int fact_bucket = 0xFF;
+static int fact_avx = 0xFF;
+static unsigned long long fact_trl;
+static int out_format_json;
+static int cmd_help;
+static int force_online_offline;
+static int auto_mode;
+
+/* clos related */
+static int current_clos = -1;
+static int clos_epp = -1;
+static int clos_prop_prio = -1;
+static int clos_min = -1;
+static int clos_max = -1;
+static int clos_desired = -1;
+static int clos_priority_type;
+
+struct _cpu_map {
+ unsigned short core_id;
+ unsigned short pkg_id;
+ unsigned short die_id;
+ unsigned short punit_cpu;
+ unsigned short punit_cpu_core;
+};
+struct _cpu_map *cpu_map;
+
+void debug_printf(const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+
+ if (debug_flag)
+ vprintf(format, args);
+
+ va_end(args);
+}
+
+
+int is_clx_n_platform(void)
+{
+ if (cpu_model == 0x55)
+ if (cpu_stepping == 0x6 || cpu_stepping == 0x7)
+ return 1;
+ return 0;
+}
+
+static int update_cpu_model(void)
+{
+ unsigned int ebx, ecx, edx;
+ unsigned int fms, family;
+
+ __cpuid(1, fms, ebx, ecx, edx);
+ family = (fms >> 8) & 0xf;
+ cpu_model = (fms >> 4) & 0xf;
+ if (family == 6 || family == 0xf)
+ cpu_model += ((fms >> 16) & 0xf) << 4;
+
+ cpu_stepping = fms & 0xf;
+ /* only three CascadeLake-N models are supported */
+ if (is_clx_n_platform()) {
+ FILE *fp;
+ size_t n = 0;
+ char *line = NULL;
+ int ret = 1;
+
+ fp = fopen("/proc/cpuinfo", "r");
+ if (!fp)
+ err(-1, "cannot open /proc/cpuinfo\n");
+
+ while (getline(&line, &n, fp) > 0) {
+ if (strstr(line, "model name")) {
+ if (strstr(line, "6252N") ||
+ strstr(line, "6230N") ||
+ strstr(line, "5218N"))
+ ret = 0;
+ break;
+ }
+ }
+ free(line);
+ fclose(fp);
+ return ret;
+ }
+ return 0;
+}
+
+/* Open a file, and exit on failure */
+static FILE *fopen_or_exit(const char *path, const char *mode)
+{
+ FILE *filep = fopen(path, mode);
+
+ if (!filep)
+ err(1, "%s: open failed", path);
+
+ return filep;
+}
+
+/* Parse a file containing a single int */
+static int parse_int_file(int fatal, const char *fmt, ...)
+{
+ va_list args;
+ char path[PATH_MAX];
+ FILE *filep;
+ int value;
+
+ va_start(args, fmt);
+ vsnprintf(path, sizeof(path), fmt, args);
+ va_end(args);
+ if (fatal) {
+ filep = fopen_or_exit(path, "r");
+ } else {
+ filep = fopen(path, "r");
+ if (!filep)
+ return -1;
+ }
+ if (fscanf(filep, "%d", &value) != 1)
+ err(1, "%s: failed to parse number from file", path);
+ fclose(filep);
+
+ return value;
+}
+
+int cpufreq_sysfs_present(void)
+{
+ DIR *dir;
+
+ dir = opendir("/sys/devices/system/cpu/cpu0/cpufreq");
+ if (dir) {
+ closedir(dir);
+ return 1;
+ }
+
+ return 0;
+}
+
+int out_format_is_json(void)
+{
+ return out_format_json;
+}
+
+int get_physical_package_id(int cpu)
+{
+ return parse_int_file(
+ 0, "/sys/devices/system/cpu/cpu%d/topology/physical_package_id",
+ cpu);
+}
+
+int get_physical_core_id(int cpu)
+{
+ return parse_int_file(
+ 0, "/sys/devices/system/cpu/cpu%d/topology/core_id", cpu);
+}
+
+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 (ret < 0)
+ ret = 0;
+
+ return ret;
+}
+
+int get_cpufreq_base_freq(int cpu)
+{
+ return parse_int_file(0, "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency", cpu);
+}
+
+int get_topo_max_cpus(void)
+{
+ return topo_max_cpus;
+}
+
+static void set_cpu_online_offline(int cpu, int state)
+{
+ char buffer[128];
+ int fd, ret;
+
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/cpu%d/online", cpu);
+
+ fd = open(buffer, O_WRONLY);
+ if (fd < 0)
+ err(-1, "%s open failed", buffer);
+
+ if (state)
+ ret = write(fd, "1\n", 2);
+ else
+ ret = write(fd, "0\n", 2);
+
+ if (ret == -1)
+ perror("Online/Offline: Operation failed\n");
+
+ 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)
+{
+ int max_packages[MAX_PACKAGE_COUNT * MAX_PACKAGE_COUNT];
+ int pkg_index = 0, i;
+
+ memset(max_packages, 0xff, sizeof(max_packages));
+ for (i = 0; i < topo_max_cpus; ++i) {
+ int j, online, pkg_id, die_id = 0, skip = 0;
+
+ if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
+ continue;
+ if (i)
+ online = parse_int_file(
+ 1, "/sys/devices/system/cpu/cpu%d/online", i);
+ else
+ online =
+ 1; /* online entry for CPU 0 needs some special configs */
+
+ die_id = get_physical_die_id(i);
+ if (die_id < 0)
+ die_id = 0;
+ pkg_id = get_physical_package_id(i);
+ /* Create an unique id for package, die combination to store */
+ pkg_id = (MAX_PACKAGE_COUNT * pkg_id + die_id);
+
+ for (j = 0; j < pkg_index; ++j) {
+ if (max_packages[j] == pkg_id) {
+ skip = 1;
+ break;
+ }
+ }
+
+ if (!skip && online && callback) {
+ callback(i, 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 *arg2, void *arg3, void *arg4)
+{
+ int i;
+
+ for (i = 0; i < topo_max_cpus; ++i) {
+ int online;
+
+ if (!CPU_ISSET_S(i, target_cpumask_size, target_cpumask))
+ continue;
+ if (i)
+ online = parse_int_file(
+ 1, "/sys/devices/system/cpu/cpu%d/online", i);
+ else
+ online =
+ 1; /* online entry for CPU 0 needs some special configs */
+
+ if (online && callback)
+ callback(i, arg1, arg2, arg3, arg4);
+ }
+}
+
+#define BITMASK_SIZE 32
+static void set_max_cpu_num(void)
+{
+ FILE *filep;
+ unsigned long dummy;
+
+ topo_max_cpus = 0;
+ filep = fopen_or_exit(
+ "/sys/devices/system/cpu/cpu0/topology/thread_siblings", "r");
+ 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);
+}
+
+size_t alloc_cpu_set(cpu_set_t **cpu_set)
+{
+ cpu_set_t *_cpu_set;
+ size_t size;
+
+ _cpu_set = CPU_ALLOC((topo_max_cpus + 1));
+ if (_cpu_set == NULL)
+ err(3, "CPU_ALLOC");
+ size = CPU_ALLOC_SIZE((topo_max_cpus + 1));
+ CPU_ZERO_S(size, _cpu_set);
+
+ *cpu_set = _cpu_set;
+ return size;
+}
+
+void free_cpu_set(cpu_set_t *cpu_set)
+{
+ CPU_FREE(cpu_set);
+}
+
+static int cpu_cnt[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE];
+static long long core_mask[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE];
+static void set_cpu_present_cpu_mask(void)
+{
+ size_t size;
+ DIR *dir;
+ int i;
+
+ size = alloc_cpu_set(&present_cpumask);
+ present_cpumask_size = size;
+ for (i = 0; i < topo_max_cpus; ++i) {
+ char buffer[256];
+
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/cpu%d", i);
+ dir = opendir(buffer);
+ if (dir) {
+ int pkg_id, die_id;
+
+ CPU_SET_S(i, size, present_cpumask);
+ die_id = get_physical_die_id(i);
+ if (die_id < 0)
+ die_id = 0;
+
+ pkg_id = get_physical_package_id(i);
+ if (pkg_id < 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 cnt = 0;
+
+ if (pkg_id < MAX_PACKAGE_COUNT && die_id < MAX_DIE_PER_PACKAGE) {
+ int i;
+
+ for (i = 0; i < sizeof(long long) * 8; ++i) {
+ if (core_mask[pkg_id][die_id] & (1ULL << i))
+ cnt++;
+ }
+ }
+
+ 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;
+}
+
+static void set_cpu_target_cpu_mask(void)
+{
+ 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;
+
+ CPU_SET_S(target_cpus[i], size, target_cpumask);
+ }
+}
+
+static void create_cpu_map(void)
+{
+ const char *pathname = "/dev/isst_interface";
+ int i, fd = 0;
+ struct isst_if_cpu_maps map;
+
+ cpu_map = malloc(sizeof(*cpu_map) * topo_max_cpus);
+ if (!cpu_map)
+ err(3, "cpumap");
+
+ fd = open(pathname, O_RDWR);
+ if (fd < 0)
+ err(-1, "%s open failed", pathname);
+
+ for (i = 0; i < topo_max_cpus; ++i) {
+ if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
+ 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) {
+ perror("ISST_IF_GET_PHY_ID");
+ fprintf(outf, "Error: map logical_cpu:%d\n",
+ 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
+
+ debug_printf(
+ "map logical_cpu:%d core: %d die:%d pkg:%d punit_cpu:%d punit_core:%d\n",
+ i, cpu_map[i].core_id, cpu_map[i].die_id,
+ cpu_map[i].pkg_id, cpu_map[i].punit_cpu,
+ cpu_map[i].punit_cpu_core);
+ }
+
+ if (fd)
+ close(fd);
+}
+
+int find_logical_cpu(int pkg_id, int die_id, int punit_core_id)
+{
+ int i;
+
+ 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;
+ }
+
+ return -EINVAL;
+}
+
+void set_cpu_mask_from_punit_coremask(int cpu, 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)) {
+ 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 &&
+ cpu_map[j].punit_cpu_core == i) {
+ CPU_SET_S(j, core_cpumask_size,
+ core_cpumask);
+ ++cnt;
+ }
+ }
+ }
+ }
+
+ *cpu_cnt = cnt;
+}
+
+int find_phy_core_num(int logical_cpu)
+{
+ if (logical_cpu < topo_max_cpus)
+ return cpu_map[logical_cpu].punit_cpu_core;
+
+ return -EINVAL;
+}
+
+static int isst_send_mmio_command(unsigned int cpu, unsigned int reg, int write,
+ unsigned int *value)
+{
+ struct isst_if_io_regs io_regs;
+ const char *pathname = "/dev/isst_interface";
+ int cmd;
+ int fd;
+
+ debug_printf("mmio_cmd cpu:%d reg:%d write:%d\n", cpu, reg, write);
+
+ fd = open(pathname, O_RDWR);
+ if (fd < 0)
+ err(-1, "%s open failed", pathname);
+
+ io_regs.req_count = 1;
+ io_regs.io_reg[0].logical_cpu = cpu;
+ io_regs.io_reg[0].reg = reg;
+ cmd = ISST_IF_IO_CMD;
+ if (write) {
+ io_regs.io_reg[0].read_write = 1;
+ io_regs.io_reg[0].value = *value;
+ } else {
+ io_regs.io_reg[0].read_write = 0;
+ }
+
+ if (ioctl(fd, cmd, &io_regs) == -1) {
+ perror("ISST_IF_IO_CMD");
+ fprintf(outf, "Error: mmio_cmd cpu:%d reg:%x read_write:%x\n",
+ cpu, reg, write);
+ } else {
+ if (!write)
+ *value = io_regs.io_reg[0].value;
+
+ debug_printf(
+ "mmio_cmd response: cpu:%d reg:%x rd_write:%x resp:%x\n",
+ cpu, reg, write, *value);
+ }
+
+ close(fd);
+
+ return 0;
+}
+
+int isst_send_mbox_command(unsigned int cpu, unsigned char command,
+ unsigned char sub_command, unsigned int parameter,
+ unsigned int req_data, unsigned int *resp)
+{
+ const char *pathname = "/dev/isst_interface";
+ int fd;
+ 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) {
+ unsigned int value;
+ int write = 0;
+ int clos_id, core_id, ret = 0;
+
+ debug_printf("CPU %d\n", cpu);
+
+ if (parameter & BIT(MBOX_CMD_WRITE_BIT)) {
+ value = req_data;
+ write = 1;
+ }
+
+ switch (sub_command) {
+ case CLOS_PQR_ASSOC:
+ core_id = parameter & 0xff;
+ ret = isst_send_mmio_command(
+ cpu, PQR_ASSOC_OFFSET + core_id * 4, write,
+ &value);
+ if (!ret && !write)
+ *resp = value;
+ break;
+ case CLOS_PM_CLOS:
+ clos_id = parameter & 0x03;
+ ret = isst_send_mmio_command(
+ cpu, PM_CLOS_OFFSET + clos_id * 4, write,
+ &value);
+ if (!ret && !write)
+ *resp = value;
+ break;
+ case CLOS_STATUS:
+ break;
+ default:
+ break;
+ }
+ return ret;
+ }
+
+ mbox_cmds.cmd_count = 1;
+ mbox_cmds.mbox_cmd[0].logical_cpu = cpu;
+ mbox_cmds.mbox_cmd[0].command = command;
+ mbox_cmds.mbox_cmd[0].sub_command = sub_command;
+ mbox_cmds.mbox_cmd[0].parameter = parameter;
+ mbox_cmds.mbox_cmd[0].req_data = req_data;
+
+ 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);
+ }
+
+ close(fd);
+
+ return 0;
+}
+
+int isst_send_msr_command(unsigned int cpu, unsigned int msr, int write,
+ unsigned long long *req_resp)
+{
+ struct isst_if_msr_cmds msr_cmds;
+ const char *pathname = "/dev/isst_interface";
+ int fd;
+
+ fd = open(pathname, O_RDWR);
+ if (fd < 0)
+ err(-1, "%s open failed", pathname);
+
+ msr_cmds.cmd_count = 1;
+ msr_cmds.msr_cmd[0].logical_cpu = cpu;
+ msr_cmds.msr_cmd[0].msr = msr;
+ msr_cmds.msr_cmd[0].read_write = write;
+ if (write)
+ msr_cmds.msr_cmd[0].data = *req_resp;
+
+ if (ioctl(fd, ISST_IF_MSR_COMMAND, &msr_cmds) == -1) {
+ perror("ISST_IF_MSR_COMMAD");
+ fprintf(outf, "Error: msr_cmd cpu:%d msr:%x read_write:%d\n",
+ cpu, msr, write);
+ } else {
+ if (!write)
+ *req_resp = msr_cmds.msr_cmd[0].data;
+
+ debug_printf(
+ "msr_cmd response: cpu:%d msr:%x rd_write:%x resp:%llx %llx\n",
+ cpu, msr, write, *req_resp, msr_cmds.msr_cmd[0].data);
+ }
+
+ close(fd);
+
+ return 0;
+}
+
+static int isst_fill_platform_info(void)
+{
+ const char *pathname = "/dev/isst_interface";
+ int fd;
+
+ fd = open(pathname, O_RDWR);
+ if (fd < 0)
+ err(-1, "%s open failed", pathname);
+
+ if (ioctl(fd, ISST_IF_GET_PLATFORM_INFO, &isst_platform_info) == -1) {
+ perror("ISST_IF_GET_PLATFORM_INFO");
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+
+ if (isst_platform_info.api_version > supported_api_ver) {
+ printf("Incompatible API versions; Upgrade of tool is required\n");
+ return -1;
+ }
+ return 0;
+}
+
+static void isst_print_platform_information(void)
+{
+ struct isst_if_platform_info platform_info;
+ const char *pathname = "/dev/isst_interface";
+ int fd;
+
+ fd = open(pathname, O_RDWR);
+ if (fd < 0)
+ err(-1, "%s open failed", pathname);
+
+ if (ioctl(fd, ISST_IF_GET_PLATFORM_INFO, &platform_info) == -1) {
+ perror("ISST_IF_GET_PLATFORM_INFO");
+ } else {
+ fprintf(outf, "Platform: API version : %d\n",
+ platform_info.api_version);
+ fprintf(outf, "Platform: Driver version : %d\n",
+ platform_info.driver_version);
+ fprintf(outf, "Platform: mbox supported : %d\n",
+ platform_info.mbox_supported);
+ fprintf(outf, "Platform: mmio supported : %d\n",
+ platform_info.mmio_supported);
+ }
+
+ close(fd);
+
+ exit(0);
+}
+
+static void exec_on_get_ctdp_cpu(int cpu, void *arg1, void *arg2, void *arg3,
+ void *arg4)
+{
+ int (*fn_ptr)(int cpu, void *arg);
+ int ret;
+
+ fn_ptr = arg1;
+ ret = fn_ptr(cpu, arg2);
+ if (ret)
+ perror("get_tdp_*");
+ else
+ isst_ctdp_display_core_info(cpu, outf, arg3,
+ *(unsigned int *)arg4);
+}
+
+#define _get_tdp_level(desc, suffix, object, help) \
+ static void get_tdp_##object(int arg) \
+ { \
+ struct isst_pkg_ctdp ctdp; \
+\
+ if (cmd_help) { \
+ fprintf(stderr, \
+ "Print %s [No command arguments are required]\n", \
+ help); \
+ exit(0); \
+ } \
+ isst_ctdp_display_information_start(outf); \
+ if (max_target_cpus) \
+ for_each_online_target_cpu_in_set( \
+ exec_on_get_ctdp_cpu, isst_get_ctdp_##suffix, \
+ &ctdp, desc, &ctdp.object); \
+ else \
+ for_each_online_package_in_set(exec_on_get_ctdp_cpu, \
+ isst_get_ctdp_##suffix, \
+ &ctdp, desc, \
+ &ctdp.object); \
+ 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-current_level", levels, current_level,
+ "Current TDP Level");
+_get_tdp_level("get-lock-status", levels, locked, "TDP lock status");
+
+struct isst_pkg_ctdp clx_n_pkg_dev;
+
+static int clx_n_get_base_ratio(void)
+{
+ FILE *fp;
+ char *begin, *end, *line = NULL;
+ char number[5];
+ float value = 0;
+ size_t n = 0;
+
+ fp = fopen("/proc/cpuinfo", "r");
+ if (!fp)
+ err(-1, "cannot open /proc/cpuinfo\n");
+
+ while (getline(&line, &n, fp) > 0) {
+ if (strstr(line, "model name")) {
+ /* this is true for CascadeLake-N */
+ begin = strstr(line, "@ ") + 2;
+ end = strstr(line, "GHz");
+ strncpy(number, begin, end - begin);
+ value = atof(number) * 10;
+ break;
+ }
+ }
+ free(line);
+ fclose(fp);
+
+ return (int)(value);
+}
+
+static int clx_n_config(int cpu)
+{
+ int i, ret, pkg_id, die_id;
+ unsigned long cpu_bf;
+ 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;
+ ctdp_level->core_cpumask_size =
+ alloc_cpu_set(&ctdp_level->core_cpumask);
+
+ /* find the frequency base ratio */
+ ctdp_level->tdp_ratio = clx_n_get_base_ratio();
+ if (ctdp_level->tdp_ratio == 0) {
+ debug_printf("CLX: cn base ratio is zero\n");
+ ret = -1;
+ goto error_ret;
+ }
+
+ /* find the high and low priority frequencies */
+ 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))
+ continue;
+
+ CPU_SET_S(i, ctdp_level->core_cpumask_size,
+ ctdp_level->core_cpumask);
+
+ cpu_bf = parse_int_file(1,
+ "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency",
+ i);
+ if (cpu_bf > pbf_info->p1_high)
+ pbf_info->p1_high = cpu_bf;
+ if (cpu_bf < pbf_info->p1_low)
+ pbf_info->p1_low = cpu_bf;
+ }
+
+ if (pbf_info->p1_high == ~0UL) {
+ debug_printf("CLX: maximum base frequency not set\n");
+ ret = -1;
+ goto error_ret;
+ }
+
+ if (pbf_info->p1_low == 0) {
+ debug_printf("CLX: minimum base frequency not set\n");
+ ret = -1;
+ goto error_ret;
+ }
+
+ /* convert frequencies back to ratios */
+ pbf_info->p1_high = pbf_info->p1_high / 100000;
+ pbf_info->p1_low = pbf_info->p1_low / 100000;
+
+ /* create high priority cpu mask */
+ pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask);
+ 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))
+ continue;
+
+ cpu_bf = parse_int_file(1,
+ "/sys/devices/system/cpu/cpu%d/cpufreq/base_frequency",
+ i);
+ cpu_bf = cpu_bf / 100000;
+ if (cpu_bf == pbf_info->p1_high)
+ CPU_SET_S(i, pbf_info->core_cpumask_size,
+ pbf_info->core_cpumask);
+ }
+
+ /* extra ctdp & pbf struct parameters */
+ ctdp_level->processed = 1;
+ ctdp_level->pbf_support = 1; /* PBF is always supported and enabled */
+ ctdp_level->pbf_enabled = 1;
+ ctdp_level->fact_support = 0; /* FACT is never supported */
+ ctdp_level->fact_enabled = 0;
+
+ return 0;
+
+error_ret:
+ free_cpu_set(ctdp_level->core_cpumask);
+ return ret;
+}
+
+static void dump_clx_n_config_for_cpu(int cpu, void *arg1, void *arg2,
+ void *arg3, void *arg4)
+{
+ int ret;
+
+ ret = clx_n_config(cpu);
+ if (ret) {
+ perror("isst_get_process_ctdp");
+ } 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);
+ 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,
+ 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);
+ if (ret) {
+ perror("isst_get_process_ctdp");
+ } else {
+ isst_ctdp_display_information(cpu, outf, tdp_level, &pkg_dev);
+ isst_get_process_ctdp_complete(cpu, &pkg_dev);
+ }
+}
+
+static void dump_isst_config(int arg)
+{
+ void *fn;
+
+ if (cmd_help) {
+ fprintf(stderr,
+ "Print Intel(R) Speed Select Technology Performance profile configuration\n");
+ fprintf(stderr,
+ "including base frequency and turbo frequency configurations\n");
+ fprintf(stderr, "Optional: -l|--level : Specify tdp level\n");
+ fprintf(stderr,
+ "\tIf no arguments, dump information for all TDP levels\n");
+ exit(0);
+ }
+
+ if (!is_clx_n_platform())
+ fn = dump_isst_config_for_cpu;
+ else
+ fn = dump_clx_n_config_for_cpu;
+
+ isst_ctdp_display_information_start(outf);
+
+ if (max_target_cpus)
+ for_each_online_target_cpu_in_set(fn, NULL, NULL, NULL, NULL);
+ else
+ for_each_online_package_in_set(fn, NULL, NULL, NULL, NULL);
+
+ isst_ctdp_display_information_end(outf);
+}
+
+static void set_tdp_level_for_cpu(int cpu, 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);
+ if (force_online_offline) {
+ struct isst_pkg_ctdp_level_info ctdp_level;
+ int pkg_id = get_physical_package_id(cpu);
+ int die_id = get_physical_die_id(cpu);
+
+ fprintf(stderr, "Option is set to online/offline\n");
+ ctdp_level.core_cpumask_size =
+ alloc_cpu_set(&ctdp_level.core_cpumask);
+ isst_get_coremask_info(cpu, tdp_level, &ctdp_level);
+ if (ctdp_level.cpu_count) {
+ int i, max_cpus = get_topo_max_cpus();
+ for (i = 0; i < max_cpus; ++i) {
+ if (pkg_id != get_physical_package_id(i) || die_id != get_physical_die_id(i))
+ continue;
+ if (CPU_ISSET_S(i, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask)) {
+ fprintf(stderr, "online cpu %d\n", i);
+ set_cpu_online_offline(i, 1);
+ } else {
+ fprintf(stderr, "offline cpu %d\n", i);
+ set_cpu_online_offline(i, 0);
+ }
+ }
+ }
+ }
+ }
+}
+
+static void set_tdp_level(int arg)
+{
+ if (cmd_help) {
+ fprintf(stderr, "Set Config TDP level\n");
+ fprintf(stderr,
+ "\t Arguments: -l|--level : Specify tdp level\n");
+ fprintf(stderr,
+ "\t Optional Arguments: -o | online : online/offline for the tdp level\n");
+ exit(0);
+ }
+
+ if (tdp_level == 0xff) {
+ fprintf(outf, "Invalid command: specify tdp_level\n");
+ exit(1);
+ }
+ isst_ctdp_display_information_start(outf);
+ if (max_target_cpus)
+ for_each_online_target_cpu_in_set(set_tdp_level_for_cpu, NULL,
+ NULL, NULL, NULL);
+ else
+ for_each_online_package_in_set(set_tdp_level_for_cpu, NULL,
+ NULL, NULL, NULL);
+ isst_ctdp_display_information_end(outf);
+}
+
+static void clx_n_dump_pbf_config_for_cpu(int cpu, void *arg1, void *arg2,
+ void *arg3, void *arg4)
+{
+ int ret;
+
+ ret = clx_n_config(cpu);
+ if (ret) {
+ perror("isst_get_process_ctdp");
+ } 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);
+ 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,
+ void *arg4)
+{
+ struct isst_pbf_info pbf_info;
+ int ret;
+
+ ret = isst_get_pbf_info(cpu, tdp_level, &pbf_info);
+ if (ret) {
+ perror("isst_get_pbf_info");
+ } else {
+ isst_pbf_display_information(cpu, outf, tdp_level, &pbf_info);
+ isst_get_pbf_info_complete(&pbf_info);
+ }
+}
+
+static void dump_pbf_config(int arg)
+{
+ void *fn;
+
+ if (cmd_help) {
+ fprintf(stderr,
+ "Print Intel(R) Speed Select Technology base frequency configuration for a TDP level\n");
+ fprintf(stderr,
+ "\tArguments: -l|--level : Specify tdp level\n");
+ exit(0);
+ }
+
+ if (tdp_level == 0xff) {
+ fprintf(outf, "Invalid command: specify tdp_level\n");
+ exit(1);
+ }
+
+ if (!is_clx_n_platform())
+ fn = dump_pbf_config_for_cpu;
+ else
+ fn = clx_n_dump_pbf_config_for_cpu;
+
+ isst_ctdp_display_information_start(outf);
+
+ if (max_target_cpus)
+ for_each_online_target_cpu_in_set(fn, NULL, NULL, NULL, NULL);
+ else
+ for_each_online_package_in_set(fn, NULL, NULL, NULL, NULL);
+
+ isst_ctdp_display_information_end(outf);
+}
+
+static int set_clos_param(int cpu, 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);
+ if (ret) {
+ perror("isst_pm_get_clos");
+ 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);
+ if (ret) {
+ perror("isst_pm_set_clos");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int set_cpufreq_scaling_min_max(int cpu, int max, int freq)
+{
+ char buffer[128], freq_str[16];
+ int fd, ret, len;
+
+ if (max)
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu);
+ else
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu);
+
+ fd = open(buffer, O_WRONLY);
+ if (fd < 0)
+ return fd;
+
+ snprintf(freq_str, sizeof(freq_str), "%d", freq);
+ len = strlen(freq_str);
+ ret = write(fd, freq_str, len);
+ if (ret == -1) {
+ close(fd);
+ return ret;
+ }
+ close(fd);
+
+ return 0;
+}
+
+static int set_clx_pbf_cpufreq_scaling_min_max(int cpu)
+{
+ 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 ret;
+
+ ret = clx_n_config(cpu);
+ if (ret) {
+ perror("set_clx_pbf_cpufreq_scaling_min_max");
+ return ret;
+ }
+
+ ctdp_level = &clx_n_pkg_dev.ctdp_level[0];
+ pbf_info = &ctdp_level->pbf_info;
+ 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))
+ continue;
+
+ if (CPU_ISSET_S(i, pbf_info->core_cpumask_size,
+ pbf_info->core_cpumask))
+ freq = freq_high;
+ else
+ freq = freq_low;
+
+ set_cpufreq_scaling_min_max(i, 1, freq);
+ set_cpufreq_scaling_min_max(i, 0, freq);
+ }
+
+ return 0;
+}
+
+static int set_cpufreq_scaling_min_max_from_cpuinfo(int cpu, int cpuinfo_max, int scaling_max)
+{
+ char buffer[128], min_freq[16];
+ int fd, ret, len;
+
+ if (!CPU_ISSET_S(cpu, present_cpumask_size, present_cpumask))
+ return -1;
+
+ if (cpuinfo_max)
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_max_freq", cpu);
+ else
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/cpu%d/cpufreq/cpuinfo_min_freq", cpu);
+
+ fd = open(buffer, O_RDONLY);
+ if (fd < 0)
+ return fd;
+
+ len = read(fd, min_freq, sizeof(min_freq));
+ close(fd);
+
+ if (len < 0)
+ return len;
+
+ if (scaling_max)
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu);
+ else
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu);
+
+ fd = open(buffer, O_WRONLY);
+ if (fd < 0)
+ return fd;
+
+ len = strlen(min_freq);
+ ret = write(fd, min_freq, len);
+ if (ret == -1) {
+ close(fd);
+ return ret;
+ }
+ close(fd);
+
+ return 0;
+}
+
+static void set_scaling_min_to_cpuinfo_max(int cpu)
+{
+ int i, pkg_id, die_id;
+
+ 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))
+ continue;
+
+ set_cpufreq_scaling_min_max_from_cpuinfo(i, 1, 0);
+ }
+}
+
+static void set_scaling_min_to_cpuinfo_min(int cpu)
+{
+ int i, pkg_id, die_id;
+
+ 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))
+ continue;
+
+ set_cpufreq_scaling_min_max_from_cpuinfo(i, 0, 0);
+ }
+}
+
+static void set_scaling_max_to_cpuinfo_max(int cpu)
+{
+ int i, pkg_id, die_id;
+
+ 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))
+ continue;
+
+ set_cpufreq_scaling_min_max_from_cpuinfo(i, 1, 1);
+ }
+}
+
+static int set_core_priority_and_min(int cpu, int mask_size,
+ cpu_set_t *cpu_mask, int min_high,
+ int min_low)
+{
+ int pkg_id, die_id, ret, i;
+
+ if (!CPU_COUNT_S(mask_size, cpu_mask))
+ return -1;
+
+ ret = set_clos_param(cpu, 0, 0, 0, min_high, 0xff);
+ if (ret)
+ return ret;
+
+ ret = set_clos_param(cpu, 1, 15, 15, min_low, 0xff);
+ if (ret)
+ return ret;
+
+ ret = set_clos_param(cpu, 2, 15, 15, min_low, 0xff);
+ if (ret)
+ return ret;
+
+ ret = set_clos_param(cpu, 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;
+
+ if (pkg_id != get_physical_package_id(i) ||
+ die_id != get_physical_die_id(i))
+ continue;
+
+ if (CPU_ISSET_S(i, mask_size, cpu_mask))
+ clos = 0;
+ else
+ clos = 3;
+
+ debug_printf("Associate cpu: %d clos: %d\n", i, clos);
+ ret = isst_clos_associate(i, clos);
+ if (ret) {
+ perror("isst_clos_associate");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int set_pbf_core_power(int cpu)
+{
+ struct isst_pbf_info pbf_info;
+ struct isst_pkg_ctdp pkg_dev;
+ int ret;
+
+ ret = isst_get_ctdp_levels(cpu, &pkg_dev);
+ if (ret) {
+ perror("isst_get_ctdp_levels");
+ return ret;
+ }
+ debug_printf("Current_level: %d\n", pkg_dev.current_level);
+
+ ret = isst_get_pbf_info(cpu, pkg_dev.current_level, &pbf_info);
+ if (ret) {
+ perror("isst_get_pbf_info");
+ 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,
+ pbf_info.core_cpumask,
+ pbf_info.p1_high, pbf_info.p1_low);
+ if (ret) {
+ perror("set_core_priority_and_min");
+ return ret;
+ }
+
+ ret = isst_pm_qos_config(cpu, 1, 1);
+ if (ret) {
+ perror("isst_pm_qos_config");
+ return ret;
+ }
+
+ return 0;
+}
+
+static void set_pbf_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
+ void *arg4)
+{
+ int ret;
+ int status = *(int *)arg4;
+
+ if (is_clx_n_platform()) {
+ if (status) {
+ ret = 0;
+ if (auto_mode)
+ set_clx_pbf_cpufreq_scaling_min_max(cpu);
+
+ } else {
+ ret = -1;
+ if (auto_mode) {
+ set_scaling_max_to_cpuinfo_max(cpu);
+ set_scaling_min_to_cpuinfo_min(cpu);
+ }
+ }
+ goto disp_result;
+ }
+
+ if (auto_mode) {
+ if (status) {
+ ret = set_pbf_core_power(cpu);
+ if (ret)
+ goto disp_result;
+ } else {
+ isst_pm_qos_config(cpu, 0, 0);
+ }
+ }
+
+ ret = isst_set_pbf_fact_status(cpu, 1, status);
+ if (ret) {
+ perror("isst_set_pbf");
+ if (auto_mode)
+ isst_pm_qos_config(cpu, 0, 0);
+ } else {
+ if (auto_mode) {
+ if (status)
+ set_scaling_min_to_cpuinfo_max(cpu);
+ else
+ set_scaling_min_to_cpuinfo_min(cpu);
+ }
+ }
+
+disp_result:
+ if (status)
+ isst_display_result(cpu, outf, "base-freq", "enable",
+ ret);
+ else
+ isst_display_result(cpu, outf, "base-freq", "disable",
+ ret);
+}
+
+static void set_pbf_enable(int arg)
+{
+ int enable = arg;
+
+ if (cmd_help) {
+ if (enable) {
+ fprintf(stderr,
+ "Enable Intel Speed Select Technology base frequency feature\n");
+ fprintf(stderr,
+ "\tOptional Arguments: -a|--auto : Use priority of cores to set core-power associations\n");
+ } else {
+
+ fprintf(stderr,
+ "Disable Intel Speed Select Technology base frequency feature\n");
+ fprintf(stderr,
+ "\tOptional Arguments: -a|--auto : Also disable core-power associations\n");
+ }
+ exit(0);
+ }
+
+ isst_ctdp_display_information_start(outf);
+ if (max_target_cpus)
+ for_each_online_target_cpu_in_set(set_pbf_for_cpu, NULL, NULL,
+ NULL, &enable);
+ else
+ for_each_online_package_in_set(set_pbf_for_cpu, NULL, NULL,
+ NULL, &enable);
+ isst_ctdp_display_information_end(outf);
+}
+
+static void dump_fact_config_for_cpu(int cpu, 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,
+ fact_avx, &fact_info);
+}
+
+static void dump_fact_config(int arg)
+{
+ if (cmd_help) {
+ fprintf(stderr,
+ "Print complete Intel Speed Select Technology turbo frequency configuration for a TDP level. Other arguments are optional.\n");
+ fprintf(stderr,
+ "\tArguments: -l|--level : Specify tdp level\n");
+ fprintf(stderr,
+ "\tArguments: -b|--bucket : Bucket index to dump\n");
+ fprintf(stderr,
+ "\tArguments: -r|--trl-type : Specify trl type: sse|avx2|avx512\n");
+ exit(0);
+ }
+
+ if (tdp_level == 0xff) {
+ fprintf(outf, "Invalid command: specify tdp_level\n");
+ exit(1);
+ }
+
+ isst_ctdp_display_information_start(outf);
+ if (max_target_cpus)
+ for_each_online_target_cpu_in_set(dump_fact_config_for_cpu,
+ NULL, NULL, NULL, NULL);
+ else
+ for_each_online_package_in_set(dump_fact_config_for_cpu, NULL,
+ NULL, NULL, NULL);
+ isst_ctdp_display_information_end(outf);
+}
+
+static void set_fact_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
+ void *arg4)
+{
+ int ret;
+ int status = *(int *)arg4;
+
+ if (auto_mode) {
+ if (status) {
+ ret = isst_pm_qos_config(cpu, 1, 1);
+ if (ret)
+ goto disp_results;
+ } else {
+ isst_pm_qos_config(cpu, 0, 0);
+ }
+ }
+
+ ret = isst_set_pbf_fact_status(cpu, 0, status);
+ if (ret) {
+ perror("isst_set_fact");
+ if (auto_mode)
+ isst_pm_qos_config(cpu, 0, 0);
+
+ goto disp_results;
+ }
+
+ /* Set TRL */
+ if (status) {
+ struct isst_pkg_ctdp pkg_dev;
+
+ ret = isst_get_ctdp_levels(cpu, &pkg_dev);
+ if (!ret)
+ ret = isst_set_trl(cpu, fact_trl);
+ if (ret && auto_mode)
+ isst_pm_qos_config(cpu, 0, 0);
+ }
+
+disp_results:
+ if (status) {
+ isst_display_result(cpu, outf, "turbo-freq", "enable", 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);
+ }
+}
+
+static void set_fact_enable(int arg)
+{
+ int i, ret, enable = arg;
+
+ if (cmd_help) {
+ if (enable) {
+ fprintf(stderr,
+ "Enable Intel Speed Select Technology Turbo frequency feature\n");
+ fprintf(stderr,
+ "Optional: -t|--trl : Specify turbo ratio limit\n");
+ fprintf(stderr,
+ "\tOptional Arguments: -a|--auto : Designate specified target CPUs with");
+ fprintf(stderr,
+ "-C|--cpu option as as high priority using core-power feature\n");
+ } else {
+ fprintf(stderr,
+ "Disable Intel Speed Select Technology turbo frequency feature\n");
+ fprintf(stderr,
+ "Optional: -t|--trl : Specify turbo ratio limit\n");
+ fprintf(stderr,
+ "\tOptional Arguments: -a|--auto : Also disable core-power associations\n");
+ }
+ exit(0);
+ }
+
+ isst_ctdp_display_information_start(outf);
+ if (max_target_cpus)
+ for_each_online_target_cpu_in_set(set_fact_for_cpu, NULL, NULL,
+ NULL, &enable);
+ else
+ for_each_online_package_in_set(set_fact_for_cpu, NULL, NULL,
+ NULL, &enable);
+ isst_ctdp_display_information_end(outf);
+
+ if (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
+ * in the present_cpu_mask.
+ */
+ for (i = 0; i < get_topo_max_cpus(); ++i) {
+ char buffer[128], sibling_list[128], *cpu_str;
+ int fd, len;
+
+ if (!CPU_ISSET_S(i, target_cpumask_size, target_cpumask))
+ continue;
+
+ snprintf(buffer, sizeof(buffer),
+ "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", i);
+
+ fd = open(buffer, O_RDONLY);
+ if (fd < 0)
+ continue;
+
+ len = read(fd, sibling_list, sizeof(sibling_list));
+ close(fd);
+
+ if (len < 0)
+ continue;
+
+ cpu_str = strtok(sibling_list, ",");
+ while (cpu_str != NULL) {
+ int cpu;
+
+ sscanf(cpu_str, "%d", &cpu);
+ CPU_SET_S(cpu, target_cpumask_size, target_cpumask);
+ cpu_str = strtok(NULL, ",");
+ }
+ }
+
+ for (i = 0; i < get_topo_max_cpus(); ++i) {
+ int clos;
+
+ if (!CPU_ISSET_S(i, present_cpumask_size, present_cpumask))
+ continue;
+
+ ret = set_clos_param(i, 0, 0, 0, 0, 0xff);
+ if (ret)
+ goto error_disp;
+
+ ret = set_clos_param(i, 1, 15, 15, 0, 0xff);
+ if (ret)
+ goto error_disp;
+
+ ret = set_clos_param(i, 2, 15, 15, 0, 0xff);
+ if (ret)
+ goto error_disp;
+
+ ret = set_clos_param(i, 3, 15, 15, 0, 0xff);
+ if (ret)
+ goto error_disp;
+
+ if (CPU_ISSET_S(i, target_cpumask_size, target_cpumask))
+ clos = 0;
+ else
+ clos = 3;
+
+ debug_printf("Associate cpu: %d clos: %d\n", i, clos);
+ ret = isst_clos_associate(i, clos);
+ if (ret)
+ goto error_disp;
+ }
+ isst_display_result(i, outf, "turbo-freq --auto", "enable", 0);
+ }
+
+ return;
+
+error_disp:
+ isst_display_result(i, outf, "turbo-freq --auto", "enable", ret);
+
+}
+
+static void enable_clos_qos_config(int cpu, 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 (ret)
+ perror("isst_pm_qos_config");
+
+ if (status)
+ isst_display_result(cpu, outf, "core-power", "enable",
+ ret);
+ else
+ isst_display_result(cpu, outf, "core-power", "disable",
+ ret);
+}
+
+static void set_clos_enable(int arg)
+{
+ int enable = arg;
+
+ if (cmd_help) {
+ 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");
+ } else {
+ fprintf(stderr,
+ "Disable core-power: [No command arguments are required]\n");
+ }
+ exit(0);
+ }
+
+ if (enable && cpufreq_sysfs_present()) {
+ fprintf(stderr,
+ "cpufreq subsystem and core-power enable will interfere with each other!\n");
+ }
+
+ isst_ctdp_display_information_start(outf);
+ if (max_target_cpus)
+ for_each_online_target_cpu_in_set(enable_clos_qos_config, NULL,
+ NULL, NULL, &enable);
+ else
+ for_each_online_package_in_set(enable_clos_qos_config, NULL,
+ NULL, NULL, &enable);
+ isst_ctdp_display_information_end(outf);
+}
+
+static void dump_clos_config_for_cpu(int cpu, 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);
+ if (ret)
+ perror("isst_pm_get_clos");
+ else
+ isst_clos_display_information(cpu, outf, current_clos,
+ &clos_config);
+}
+
+static void dump_clos_config(int arg)
+{
+ if (cmd_help) {
+ fprintf(stderr,
+ "Print Intel Speed Select Technology core power configuration\n");
+ fprintf(stderr,
+ "\tArguments: [-c | --clos]: Specify clos id\n");
+ exit(0);
+ }
+ if (current_clos < 0 || current_clos > 3) {
+ fprintf(stderr, "Invalid clos id\n");
+ exit(0);
+ }
+
+ isst_ctdp_display_information_start(outf);
+ if (max_target_cpus)
+ for_each_online_target_cpu_in_set(dump_clos_config_for_cpu,
+ NULL, NULL, NULL, NULL);
+ else
+ for_each_online_package_in_set(dump_clos_config_for_cpu, NULL,
+ NULL, NULL, NULL);
+ isst_ctdp_display_information_end(outf);
+}
+
+static void get_clos_info_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
+ void *arg4)
+{
+ int enable, ret, prio_type;
+
+ ret = isst_clos_get_clos_information(cpu, &enable, &prio_type);
+ if (ret)
+ perror("isst_clos_get_info");
+ else
+ isst_clos_display_clos_information(cpu, outf, enable, prio_type);
+}
+
+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");
+ exit(0);
+ }
+
+ isst_ctdp_display_information_start(outf);
+ for_each_online_target_cpu_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,
+ 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);
+ if (ret)
+ perror("isst_set_clos");
+ else
+ isst_display_result(cpu, outf, "core-power", "config", ret);
+}
+
+static void set_clos_config(int arg)
+{
+ if (cmd_help) {
+ fprintf(stderr,
+ "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");
+ 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");
+ exit(0);
+ }
+ if (clos_epp < 0 || clos_epp > 0x0F) {
+ fprintf(stderr, "clos epp is not specified, default: 0\n");
+ clos_epp = 0;
+ }
+ if (clos_prop_prio < 0 || clos_prop_prio > 0x0F) {
+ fprintf(stderr,
+ "clos frequency weight is not specified, default: 0\n");
+ clos_prop_prio = 0;
+ }
+ if (clos_min < 0) {
+ fprintf(stderr, "clos min is not specified, default: 0\n");
+ clos_min = 0;
+ }
+ if (clos_max < 0) {
+ fprintf(stderr, "clos max is not specified, default: 25500 MHz\n");
+ clos_max = 0xff;
+ }
+ if (clos_desired < 0) {
+ fprintf(stderr, "clos desired is not specified, default: 0\n");
+ clos_desired = 0x00;
+ }
+
+ isst_ctdp_display_information_start(outf);
+ if (max_target_cpus)
+ for_each_online_target_cpu_in_set(set_clos_config_for_cpu, NULL,
+ NULL, NULL, NULL);
+ else
+ for_each_online_package_in_set(set_clos_config_for_cpu, NULL,
+ NULL, NULL, NULL);
+ isst_ctdp_display_information_end(outf);
+}
+
+static void set_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
+ void *arg4)
+{
+ int ret;
+
+ ret = isst_clos_associate(cpu, current_clos);
+ if (ret)
+ perror("isst_clos_associate");
+ else
+ isst_display_result(cpu, outf, "core-power", "assoc", ret);
+}
+
+static void set_clos_assoc(int arg)
+{
+ if (cmd_help) {
+ fprintf(stderr, "Associate a clos id to a CPU\n");
+ fprintf(stderr,
+ "\tSpecify targeted clos id with [--clos|-c]\n");
+ exit(0);
+ }
+
+ if (current_clos < 0 || current_clos > 3) {
+ fprintf(stderr, "Invalid clos id\n");
+ 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");
+ }
+}
+
+static void get_clos_assoc_for_cpu(int cpu, void *arg1, void *arg2, void *arg3,
+ void *arg4)
+{
+ int clos, ret;
+
+ ret = isst_clos_get_assoc_status(cpu, &clos);
+ if (ret)
+ perror("isst_clos_get_assoc_status");
+ else
+ isst_clos_display_assoc_information(cpu, outf, clos);
+}
+
+static void get_clos_assoc(int arg)
+{
+ if (cmd_help) {
+ fprintf(stderr, "Get associate clos id to a CPU\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");
+ exit(0);
+ }
+
+ isst_ctdp_display_information_start(outf);
+ for_each_online_target_cpu_in_set(get_clos_assoc_for_cpu, NULL,
+ NULL, NULL, NULL);
+ 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 },
+ { "base-freq", "enable", set_pbf_enable, 1 },
+ { "base-freq", "disable", set_pbf_enable, 0 },
+ { NULL, NULL, NULL, 0 }
+};
+
+static struct process_cmd_struct isst_cmds[] = {
+ { "perf-profile", "get-lock-status", get_tdp_locked, 0 },
+ { "perf-profile", "get-config-levels", get_tdp_levels, 0 },
+ { "perf-profile", "get-config-version", get_tdp_version, 0 },
+ { "perf-profile", "get-config-enabled", get_tdp_enabled, 0 },
+ { "perf-profile", "get-config-current-level", get_tdp_current_level,
+ 0 },
+ { "perf-profile", "set-config-level", set_tdp_level, 0 },
+ { "perf-profile", "info", dump_isst_config, 0 },
+ { "base-freq", "info", dump_pbf_config, 0 },
+ { "base-freq", "enable", set_pbf_enable, 1 },
+ { "base-freq", "disable", set_pbf_enable, 0 },
+ { "turbo-freq", "info", dump_fact_config, 0 },
+ { "turbo-freq", "enable", set_fact_enable, 1 },
+ { "turbo-freq", "disable", set_fact_enable, 0 },
+ { "core-power", "info", dump_clos_info, 0 },
+ { "core-power", "enable", set_clos_enable, 1 },
+ { "core-power", "disable", set_clos_enable, 0 },
+ { "core-power", "config", set_clos_config, 0 },
+ { "core-power", "get-config", dump_clos_config, 0 },
+ { "core-power", "assoc", set_clos_assoc, 0 },
+ { "core-power", "get-assoc", get_clos_assoc, 0 },
+ { NULL, NULL, NULL }
+};
+
+/*
+ * parse cpuset with following syntax
+ * 1,2,4..6,8-10 and set bits in cpu_subset
+ */
+void parse_cpu_command(char *optarg)
+{
+ unsigned int start, end;
+ char *next;
+
+ next = optarg;
+
+ while (next && *next) {
+ if (*next == '-') /* no negative cpu numbers */
+ goto error;
+
+ start = strtoul(next, &next, 10);
+
+ if (max_target_cpus < MAX_CPUS_IN_ONE_REQ)
+ target_cpus[max_target_cpus++] = start;
+
+ if (*next == '\0')
+ break;
+
+ if (*next == ',') {
+ next += 1;
+ continue;
+ }
+
+ if (*next == '-') {
+ next += 1; /* start range */
+ } else if (*next == '.') {
+ next += 1;
+ if (*next == '.')
+ next += 1; /* start range */
+ else
+ goto error;
+ }
+
+ end = strtoul(next, &next, 10);
+ if (end <= start)
+ goto error;
+
+ while (++start <= end) {
+ if (max_target_cpus < MAX_CPUS_IN_ONE_REQ)
+ target_cpus[max_target_cpus++] = start;
+ }
+
+ if (*next == ',')
+ next += 1;
+ else if (*next != '\0')
+ goto error;
+ }
+
+#ifdef DEBUG
+ {
+ int i;
+
+ for (i = 0; i < max_target_cpus; ++i)
+ printf("cpu [%d] in arg\n", target_cpus[i]);
+ }
+#endif
+ return;
+
+error:
+ fprintf(stderr, "\"--cpu %s\" malformed\n", optarg);
+ exit(-1);
+}
+
+static void parse_cmd_args(int argc, int start, char **argv)
+{
+ int opt;
+ int option_index;
+
+ static struct option long_options[] = {
+ { "bucket", required_argument, 0, 'b' },
+ { "level", required_argument, 0, 'l' },
+ { "online", required_argument, 0, 'o' },
+ { "trl-type", required_argument, 0, 'r' },
+ { "trl", required_argument, 0, 't' },
+ { "help", no_argument, 0, 'h' },
+ { "clos", required_argument, 0, 'c' },
+ { "desired", required_argument, 0, 'd' },
+ { "epp", required_argument, 0, 'e' },
+ { "min", required_argument, 0, 'n' },
+ { "max", required_argument, 0, 'm' },
+ { "priority", required_argument, 0, 'p' },
+ { "weight", required_argument, 0, 'w' },
+ { "auto", no_argument, 0, 'a' },
+ { 0, 0, 0, 0 }
+ };
+
+ option_index = start;
+
+ optind = start + 1;
+ while ((opt = getopt_long(argc, argv, "b:l:t:c:d:e:n:m:p:w:hoa",
+ long_options, &option_index)) != -1) {
+ switch (opt) {
+ case 'a':
+ auto_mode = 1;
+ break;
+ case 'b':
+ fact_bucket = atoi(optarg);
+ break;
+ case 'h':
+ cmd_help = 1;
+ break;
+ case 'l':
+ tdp_level = atoi(optarg);
+ break;
+ case 'o':
+ force_online_offline = 1;
+ break;
+ case 't':
+ sscanf(optarg, "0x%llx", &fact_trl);
+ break;
+ case 'r':
+ if (!strncmp(optarg, "sse", 3)) {
+ fact_avx = 0x01;
+ } else if (!strncmp(optarg, "avx2", 4)) {
+ fact_avx = 0x02;
+ } else if (!strncmp(optarg, "avx512", 4)) {
+ fact_avx = 0x04;
+ } else {
+ fprintf(outf, "Invalid sse,avx options\n");
+ exit(1);
+ }
+ break;
+ /* CLOS related */
+ case 'c':
+ current_clos = atoi(optarg);
+ break;
+ case 'd':
+ clos_desired = atoi(optarg);
+ clos_desired /= DISP_FREQ_MULTIPLIER;
+ break;
+ case 'e':
+ clos_epp = atoi(optarg);
+ break;
+ case 'n':
+ clos_min = atoi(optarg);
+ clos_min /= DISP_FREQ_MULTIPLIER;
+ break;
+ case 'm':
+ clos_max = atoi(optarg);
+ clos_max /= DISP_FREQ_MULTIPLIER;
+ break;
+ case 'p':
+ clos_priority_type = atoi(optarg);
+ break;
+ case 'w':
+ clos_prop_prio = atoi(optarg);
+ break;
+ default:
+ printf("no match\n");
+ }
+ }
+}
+
+static void isst_help(void)
+{
+ printf("perf-profile:\tAn architectural mechanism that allows multiple optimized \n\
+ performance profiles per system via static and/or dynamic\n\
+ adjustment of core count, workload, Tjmax, and\n\
+ TDP, etc.\n");
+ printf("\nCommands : For feature=perf-profile\n");
+ printf("\tinfo\n");
+
+ if (!is_clx_n_platform()) {
+ printf("\tget-lock-status\n");
+ printf("\tget-config-levels\n");
+ printf("\tget-config-version\n");
+ printf("\tget-config-enabled\n");
+ printf("\tget-config-current-level\n");
+ printf("\tset-config-level\n");
+ }
+}
+
+static void pbf_help(void)
+{
+ printf("base-freq:\tEnables users to increase guaranteed base frequency\n\
+ on certain cores (high priority cores) in exchange for lower\n\
+ base frequency on remaining cores (low priority cores).\n");
+ printf("\tcommand : info\n");
+ printf("\tcommand : enable\n");
+ printf("\tcommand : disable\n");
+}
+
+static void fact_help(void)
+{
+ printf("turbo-freq:\tEnables the ability to set different turbo ratio\n\
+ limits to cores based on priority.\n");
+ printf("\nCommand: For feature=turbo-freq\n");
+ printf("\tcommand : info\n");
+ printf("\tcommand : enable\n");
+ printf("\tcommand : disable\n");
+}
+
+static void core_power_help(void)
+{
+ printf("core-power:\tInterface that allows user to define per core/tile\n\
+ priority.\n");
+ printf("\nCommands : For feature=core-power\n");
+ printf("\tinfo\n");
+ printf("\tenable\n");
+ printf("\tdisable\n");
+ printf("\tconfig\n");
+ printf("\tget-config\n");
+ printf("\tassoc\n");
+ printf("\tget-assoc\n");
+}
+
+struct process_cmd_help_struct {
+ char *feature;
+ void (*process_fn)(void);
+};
+
+static struct process_cmd_help_struct isst_help_cmds[] = {
+ { "perf-profile", isst_help },
+ { "base-freq", pbf_help },
+ { "turbo-freq", fact_help },
+ { "core-power", core_power_help },
+ { NULL, NULL }
+};
+
+static struct process_cmd_help_struct clx_n_help_cmds[] = {
+ { "perf-profile", isst_help },
+ { "base-freq", pbf_help },
+ { NULL, NULL }
+};
+
+void process_command(int argc, char **argv,
+ struct process_cmd_help_struct *help_cmds,
+ struct process_cmd_struct *cmds)
+{
+ int i = 0, matched = 0;
+ char *feature = argv[optind];
+ char *cmd = argv[optind + 1];
+
+ if (!feature || !cmd)
+ return;
+
+ debug_printf("feature name [%s] command [%s]\n", feature, cmd);
+ if (!strcmp(cmd, "-h") || !strcmp(cmd, "--help")) {
+ while (help_cmds[i].feature) {
+ if (!strcmp(help_cmds[i].feature, feature)) {
+ help_cmds[i].process_fn();
+ exit(0);
+ }
+ ++i;
+ }
+ }
+
+ if (!is_clx_n_platform())
+ create_cpu_map();
+
+ i = 0;
+ while (cmds[i].feature) {
+ if (!strcmp(cmds[i].feature, feature) &&
+ !strcmp(cmds[i].command, cmd)) {
+ parse_cmd_args(argc, optind + 1, argv);
+ cmds[i].process_fn(cmds[i].arg);
+ matched = 1;
+ break;
+ }
+ ++i;
+ }
+
+ if (!matched)
+ fprintf(stderr, "Invalid command\n");
+}
+
+static void usage(void)
+{
+ printf("Intel(R) Speed Select Technology\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("\nFor help on each feature, use -h|--help\n");
+ printf("\tFor example: intel-speed-select perf-profile -h\n");
+
+ printf("\nFor additional help on each command for a feature, use --h|--help\n");
+ printf("\tFor example: intel-speed-select perf-profile get-lock-status -h\n");
+ printf("\t\t This will print help for the command \"get-lock-status\" for the feature \"perf-profile\"\n");
+
+ printf("\nOPTIONS\n");
+ printf("\t[-c|--cpu] : logical cpu number\n");
+ 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[-h|--help] : Print help\n");
+ printf("\t[-i|--info] : Print platform information\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[-v|--version] : Print version\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");
+ 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;
+ int option_index = 0;
+ int ret;
+
+ static struct option long_options[] = {
+ { "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' },
+ { "out", required_argument, 0, 'o' },
+ { "version", no_argument, 0, 'v' },
+ { 0, 0, 0, 0 }
+ };
+
+ progname = argv[0];
+ while ((opt = getopt_long_only(argc, argv, "+c:df:hio:v", long_options,
+ &option_index)) != -1) {
+ switch (opt) {
+ case 'c':
+ parse_cpu_command(optarg);
+ break;
+ case 'd':
+ debug_flag = 1;
+ printf("Debug Mode ON\n");
+ break;
+ case 'f':
+ if (!strncmp(optarg, "json", 4))
+ out_format_json = 1;
+ break;
+ case 'h':
+ usage();
+ break;
+ case 'i':
+ isst_print_platform_information();
+ break;
+ case 'o':
+ if (outf)
+ fclose(outf);
+ outf = fopen_or_exit(optarg, "w");
+ break;
+ case 'v':
+ print_version();
+ break;
+ default:
+ usage();
+ }
+ }
+
+ if (geteuid() != 0) {
+ fprintf(stderr, "Must run as root\n");
+ exit(0);
+ }
+
+ if (optind > (argc - 2)) {
+ fprintf(stderr, "Feature name and|or command not specified\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);
+ set_max_cpu_num();
+ set_cpu_present_cpu_mask();
+ set_cpu_target_cpu_mask();
+
+ if (!is_clx_n_platform()) {
+ ret = isst_fill_platform_info();
+ if (ret)
+ goto out;
+ process_command(argc, argv, isst_help_cmds, isst_cmds);
+ } else {
+ process_command(argc, argv, clx_n_help_cmds, clx_n_cmds);
+ }
+out:
+ free_cpu_set(present_cpumask);
+ free_cpu_set(target_cpumask);
+}
+
+int main(int argc, char **argv)
+{
+ outf = stderr;
+ cmdline(argc, argv);
+ return 0;
+}
diff --git a/tools/power/x86/intel-speed-select/isst-core.c b/tools/power/x86/intel-speed-select/isst-core.c
new file mode 100644
index 000000000000..d14c7bcd327a
--- /dev/null
+++ b/tools/power/x86/intel-speed-select/isst-core.c
@@ -0,0 +1,900 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel Speed Select -- Enumerate and control features
+ * Copyright (c) 2019 Intel Corporation.
+ */
+
+#include "isst.h"
+
+int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev)
+{
+ unsigned int resp;
+ int ret;
+
+ ret = isst_send_mbox_command(cpu, CONFIG_TDP,
+ CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp);
+ if (ret) {
+ pkg_dev->levels = 0;
+ pkg_dev->locked = 1;
+ pkg_dev->current_level = 0;
+ pkg_dev->version = 0;
+ pkg_dev->enabled = 0;
+ return 0;
+ }
+
+ debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", cpu, resp);
+
+ pkg_dev->version = resp & 0xff;
+ pkg_dev->levels = (resp >> 8) & 0xff;
+ pkg_dev->current_level = (resp >> 16) & 0xff;
+ pkg_dev->locked = !!(resp & BIT(24));
+ pkg_dev->enabled = !!(resp & BIT(31));
+
+ return 0;
+}
+
+int isst_get_ctdp_control(int cpu, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ unsigned int resp;
+ int ret;
+
+ ret = isst_send_mbox_command(cpu, CONFIG_TDP,
+ CONFIG_TDP_GET_TDP_CONTROL, 0,
+ config_index, &resp);
+ if (ret)
+ return ret;
+
+ ctdp_level->fact_support = resp & BIT(0);
+ ctdp_level->pbf_support = !!(resp & BIT(1));
+ ctdp_level->fact_enabled = !!(resp & BIT(16));
+ ctdp_level->pbf_enabled = !!(resp & BIT(17));
+
+ debug_printf(
+ "cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
+ cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support,
+ ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
+
+ return 0;
+}
+
+int isst_get_tdp_info(int cpu, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ unsigned int resp;
+ int ret;
+
+ ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_INFO,
+ 0, config_index, &resp);
+ if (ret)
+ 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,
+ ctdp_level->pkg_tdp);
+ return 0;
+}
+
+int isst_get_pwr_info(int cpu, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ unsigned int resp;
+ int ret;
+
+ ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_PWR_INFO,
+ 0, config_index, &resp);
+ if (ret)
+ return ret;
+
+ ctdp_level->pkg_max_power = resp & GENMASK(14, 0);
+ ctdp_level->pkg_min_power = (resp & GENMASK(30, 16)) >> 16;
+
+ debug_printf(
+ "cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO resp:%x pkg_max_power:%d pkg_min_power:%d\n",
+ cpu, config_index, resp, ctdp_level->pkg_max_power,
+ ctdp_level->pkg_min_power);
+
+ return 0;
+}
+
+void isst_get_uncore_p0_p1_info(int cpu, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ unsigned int resp;
+ int ret;
+ ret = isst_send_mbox_command(cpu, CONFIG_TDP,
+ CONFIG_TDP_GET_UNCORE_P0_P1_INFO, 0,
+ config_index, &resp);
+ if (ret) {
+ ctdp_level->uncore_p0 = 0;
+ ctdp_level->uncore_p1 = 0;
+ return;
+ }
+
+ ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
+ ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
+ debug_printf(
+ "cpu:%d ctdp:%d CONFIG_TDP_GET_UNCORE_P0_P1_INFO resp:%x uncore p0:%d uncore p1:%d\n",
+ cpu, config_index, resp, ctdp_level->uncore_p0,
+ ctdp_level->uncore_p1);
+}
+
+void isst_get_p1_info(int cpu, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ unsigned int resp;
+ int ret;
+ ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_P1_INFO, 0,
+ config_index, &resp);
+ if (ret) {
+ ctdp_level->sse_p1 = 0;
+ ctdp_level->avx2_p1 = 0;
+ ctdp_level->avx512_p1 = 0;
+ return;
+ }
+
+ ctdp_level->sse_p1 = resp & GENMASK(7, 0);
+ ctdp_level->avx2_p1 = (resp & GENMASK(15, 8)) >> 8;
+ ctdp_level->avx512_p1 = (resp & GENMASK(23, 16)) >> 16;
+ debug_printf(
+ "cpu:%d ctdp:%d CONFIG_TDP_GET_P1_INFO resp:%x sse_p1:%d avx2_p1:%d avx512_p1:%d\n",
+ cpu, config_index, resp, ctdp_level->sse_p1,
+ ctdp_level->avx2_p1, ctdp_level->avx512_p1);
+}
+
+void isst_get_uncore_mem_freq(int cpu, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ unsigned int resp;
+ int ret;
+ ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_MEM_FREQ,
+ 0, config_index, &resp);
+ if (ret) {
+ ctdp_level->mem_freq = 0;
+ return;
+ }
+
+ ctdp_level->mem_freq = resp & GENMASK(7, 0);
+ debug_printf(
+ "cpu:%d ctdp:%d CONFIG_TDP_GET_MEM_FREQ resp:%x uncore mem_freq:%d\n",
+ cpu, config_index, resp, ctdp_level->mem_freq);
+}
+
+int isst_get_tjmax_info(int cpu, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ unsigned int resp;
+ int ret;
+
+ ret = isst_send_mbox_command(cpu, CONFIG_TDP, CONFIG_TDP_GET_TJMAX_INFO,
+ 0, config_index, &resp);
+ if (ret)
+ return ret;
+
+ ctdp_level->t_proc_hot = resp & GENMASK(7, 0);
+
+ debug_printf(
+ "cpu:%d ctdp:%d CONFIG_TDP_GET_TJMAX_INFO resp:%x t_proc_hot:%d\n",
+ cpu, config_index, resp, ctdp_level->t_proc_hot);
+
+ return 0;
+}
+
+int isst_get_coremask_info(int cpu, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level)
+{
+ unsigned int resp;
+ int i, ret;
+
+ ctdp_level->cpu_count = 0;
+ for (i = 0; i < 2; ++i) {
+ unsigned long long mask;
+ int cpu_count = 0;
+
+ ret = isst_send_mbox_command(cpu, CONFIG_TDP,
+ CONFIG_TDP_GET_CORE_MASK, 0,
+ (i << 8) | config_index, &resp);
+ if (ret)
+ return ret;
+
+ debug_printf(
+ "cpu:%d ctdp:%d mask:%d CONFIG_TDP_GET_CORE_MASK resp:%x\n",
+ cpu, config_index, i, resp);
+
+ mask = (unsigned long long)resp << (32 * i);
+ set_cpu_mask_from_punit_coremask(cpu, mask,
+ ctdp_level->core_cpumask_size,
+ ctdp_level->core_cpumask,
+ &cpu_count);
+ ctdp_level->cpu_count += cpu_count;
+ debug_printf("cpu:%d ctdp:%d mask:%d cpu count:%d\n", cpu,
+ config_index, i, ctdp_level->cpu_count);
+ }
+
+ return 0;
+}
+
+int isst_get_get_trl_from_msr(int cpu, int *trl)
+{
+ unsigned long long msr_trl;
+ int ret;
+
+ ret = isst_send_msr_command(cpu, 0x1AD, 0, &msr_trl);
+ if (ret)
+ return ret;
+
+ trl[0] = msr_trl & GENMASK(7, 0);
+ trl[1] = (msr_trl & GENMASK(15, 8)) >> 8;
+ trl[2] = (msr_trl & GENMASK(23, 16)) >> 16;
+ trl[3] = (msr_trl & GENMASK(31, 24)) >> 24;
+ trl[4] = (msr_trl & GENMASK(39, 32)) >> 32;
+ trl[5] = (msr_trl & GENMASK(47, 40)) >> 40;
+ trl[6] = (msr_trl & GENMASK(55, 48)) >> 48;
+ trl[7] = (msr_trl & GENMASK(63, 56)) >> 56;
+
+ return 0;
+}
+
+int isst_get_get_trl(int cpu, int level, int avx_level, int *trl)
+{
+ unsigned int req, resp;
+ int ret;
+
+ req = level | (avx_level << 16);
+ ret = isst_send_mbox_command(cpu, CONFIG_TDP,
+ CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
+ &resp);
+ if (ret)
+ return ret;
+
+ debug_printf(
+ "cpu:%d CONFIG_TDP_GET_TURBO_LIMIT_RATIOS req:%x resp:%x\n",
+ cpu, req, resp);
+
+ trl[0] = resp & GENMASK(7, 0);
+ trl[1] = (resp & GENMASK(15, 8)) >> 8;
+ trl[2] = (resp & GENMASK(23, 16)) >> 16;
+ trl[3] = (resp & GENMASK(31, 24)) >> 24;
+
+ req = level | BIT(8) | (avx_level << 16);
+ ret = isst_send_mbox_command(cpu, CONFIG_TDP,
+ CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
+ &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CONFIG_TDP_GET_TURBO_LIMIT req:%x resp:%x\n", cpu,
+ req, resp);
+
+ trl[4] = resp & GENMASK(7, 0);
+ trl[5] = (resp & GENMASK(15, 8)) >> 8;
+ trl[6] = (resp & GENMASK(23, 16)) >> 16;
+ trl[7] = (resp & GENMASK(31, 24)) >> 24;
+
+ return 0;
+}
+
+int isst_get_trl_bucket_info(int cpu, unsigned long long *buckets_info)
+{
+ int ret;
+
+ debug_printf("cpu:%d bucket info via MSR\n", cpu);
+
+ *buckets_info = 0;
+
+ ret = isst_send_msr_command(cpu, 0x1ae, 0, buckets_info);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d bucket info via MSR successful 0x%llx\n", cpu,
+ *buckets_info);
+
+ return 0;
+}
+
+int isst_set_tdp_level_msr(int cpu, int tdp_level)
+{
+ unsigned long long level = tdp_level;
+ int ret;
+
+ debug_printf("cpu: tdp_level via MSR %d\n", cpu, tdp_level);
+
+ if (isst_get_config_tdp_lock_status(cpu)) {
+ debug_printf("cpu: tdp_locked %d\n", cpu);
+ return -1;
+ }
+
+ if (tdp_level > 2)
+ return -1; /* invalid value */
+
+ ret = isst_send_msr_command(cpu, 0x64b, 1, &level);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu: tdp_level via MSR successful %d\n", cpu, tdp_level);
+
+ return 0;
+}
+
+int isst_set_tdp_level(int cpu, int tdp_level)
+{
+ unsigned int resp;
+ int ret;
+
+ 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);
+
+ return 0;
+}
+
+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;
+
+ pbf_info->core_cpumask_size = alloc_cpu_set(&pbf_info->core_cpumask);
+
+ core_cnt = get_core_count(get_physical_package_id(cpu), get_physical_die_id(cpu));
+ max = core_cnt > 32 ? 2 : 1;
+
+ for (i = 0; i < max; ++i) {
+ unsigned long long mask;
+ int count;
+
+ ret = isst_send_mbox_command(cpu, CONFIG_TDP,
+ CONFIG_TDP_PBF_GET_CORE_MASK_INFO,
+ 0, (i << 8) | level, &resp);
+ if (ret)
+ break;
+
+ debug_printf(
+ "cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n",
+ cpu, resp);
+
+ mask = (unsigned long long)resp << (32 * i);
+ set_cpu_mask_from_punit_coremask(cpu, mask,
+ pbf_info->core_cpumask_size,
+ pbf_info->core_cpumask,
+ &count);
+ }
+
+ req = level;
+ ret = isst_send_mbox_command(cpu, CONFIG_TDP,
+ CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO, 0, req,
+ &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO resp:%x\n", cpu,
+ resp);
+
+ pbf_info->p1_low = resp & 0xff;
+ pbf_info->p1_high = (resp & GENMASK(15, 8)) >> 8;
+
+ req = level;
+ ret = isst_send_mbox_command(
+ cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TDP_INFO, 0, req, &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TDP_INFO resp:%x\n", cpu, resp);
+
+ pbf_info->tdp = resp & 0xffff;
+
+ req = level;
+ ret = isst_send_mbox_command(
+ cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TJ_MAX_INFO, 0, req, &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TJ_MAX_INFO resp:%x\n", cpu,
+ resp);
+ pbf_info->t_control = (resp >> 8) & 0xff;
+ pbf_info->t_prochot = resp & 0xff;
+
+ return 0;
+}
+
+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)
+{
+ struct isst_pkg_ctdp pkg_dev;
+ struct isst_pkg_ctdp_level_info ctdp_level;
+ int current_level;
+ unsigned int req = 0, resp;
+ int ret;
+
+ ret = isst_get_ctdp_levels(cpu, &pkg_dev);
+ if (ret)
+ debug_printf("cpu:%d No support for dynamic ISST\n", cpu);
+
+ current_level = pkg_dev.current_level;
+
+ ret = isst_get_ctdp_control(cpu, current_level, &ctdp_level);
+ if (ret)
+ return ret;
+
+ if (pbf) {
+ if (ctdp_level.fact_enabled)
+ req = BIT(16);
+
+ if (enable)
+ req |= BIT(17);
+ else
+ req &= ~BIT(17);
+ } else {
+ if (ctdp_level.pbf_enabled)
+ req = BIT(17);
+
+ if (enable)
+ req |= BIT(16);
+ else
+ req &= ~BIT(16);
+ }
+
+ ret = isst_send_mbox_command(cpu, CONFIG_TDP,
+ CONFIG_TDP_SET_TDP_CONTROL, 0, req, &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CONFIG_TDP_SET_TDP_CONTROL pbf/fact:%d req:%x\n",
+ cpu, pbf, req);
+
+ return 0;
+}
+
+int isst_get_fact_bucket_info(int cpu, int level,
+ struct isst_fact_bucket_info *bucket_info)
+{
+ unsigned int resp;
+ int i, k, ret;
+
+ for (i = 0; i < 2; ++i) {
+ int j;
+
+ ret = isst_send_mbox_command(
+ cpu, CONFIG_TDP,
+ CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES, 0,
+ (i << 8) | level, &resp);
+ if (ret)
+ return ret;
+
+ debug_printf(
+ "cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES index:%d level:%d resp:%x\n",
+ cpu, i, level, resp);
+
+ for (j = 0; j < 4; ++j) {
+ bucket_info[j + (i * 4)].high_priority_cores_count =
+ (resp >> (j * 8)) & 0xff;
+ }
+ }
+
+ for (k = 0; k < 3; ++k) {
+ for (i = 0; i < 2; ++i) {
+ int j;
+
+ ret = isst_send_mbox_command(
+ cpu, CONFIG_TDP,
+ CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS, 0,
+ (k << 16) | (i << 8) | level, &resp);
+ if (ret)
+ return ret;
+
+ debug_printf(
+ "cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS index:%d level:%d avx:%d resp:%x\n",
+ cpu, i, level, k, resp);
+
+ for (j = 0; j < 4; ++j) {
+ switch (k) {
+ case 0:
+ bucket_info[j + (i * 4)].sse_trl =
+ (resp >> (j * 8)) & 0xff;
+ break;
+ case 1:
+ bucket_info[j + (i * 4)].avx_trl =
+ (resp >> (j * 8)) & 0xff;
+ break;
+ case 2:
+ bucket_info[j + (i * 4)].avx512_trl =
+ (resp >> (j * 8)) & 0xff;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+int isst_get_fact_info(int cpu, int level, struct isst_fact_info *fact_info)
+{
+ unsigned int resp;
+ int ret;
+
+ ret = isst_send_mbox_command(cpu, CONFIG_TDP,
+ CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO, 0,
+ level, &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO resp:%x\n",
+ cpu, resp);
+
+ fact_info->lp_clipping_ratio_license_sse = resp & 0xff;
+ fact_info->lp_clipping_ratio_license_avx2 = (resp >> 8) & 0xff;
+ fact_info->lp_clipping_ratio_license_avx512 = (resp >> 16) & 0xff;
+
+ ret = isst_get_fact_bucket_info(cpu, level, fact_info->bucket_info);
+
+ return ret;
+}
+
+int isst_set_trl(int cpu, unsigned long long trl)
+{
+ int ret;
+
+ if (!trl)
+ trl = 0xFFFFFFFFFFFFFFFFULL;
+
+ ret = isst_send_msr_command(cpu, 0x1AD, 1, &trl);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+int isst_set_trl_from_current_tdp(int cpu, unsigned long long trl)
+{
+ unsigned long long msr_trl;
+ int ret;
+
+ if (trl) {
+ msr_trl = trl;
+ } else {
+ struct isst_pkg_ctdp pkg_dev;
+ int trl[8];
+ int i;
+
+ ret = isst_get_ctdp_levels(cpu, &pkg_dev);
+ if (ret)
+ return ret;
+
+ ret = isst_get_get_trl(cpu, pkg_dev.current_level, 0, trl);
+ if (ret)
+ return ret;
+
+ msr_trl = 0;
+ for (i = 0; i < 8; ++i) {
+ unsigned long long _trl = trl[i];
+
+ msr_trl |= (_trl << (i * 8));
+ }
+ }
+ ret = isst_send_msr_command(cpu, 0x1AD, 1, &msr_trl);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+/* Return 1 if locked */
+int isst_get_config_tdp_lock_status(int cpu)
+{
+ unsigned long long tdp_control = 0;
+ int ret;
+
+ ret = isst_send_msr_command(cpu, 0x64b, 0, &tdp_control);
+ if (ret)
+ return ret;
+
+ ret = !!(tdp_control & BIT(31));
+
+ return ret;
+}
+
+void isst_get_process_ctdp_complete(int cpu, struct isst_pkg_ctdp *pkg_dev)
+{
+ int i;
+
+ if (!pkg_dev->processed)
+ return;
+
+ for (i = 0; i < pkg_dev->levels; ++i) {
+ struct isst_pkg_ctdp_level_info *ctdp_level;
+
+ ctdp_level = &pkg_dev->ctdp_level[i];
+ if (ctdp_level->pbf_support)
+ free_cpu_set(ctdp_level->pbf_info.core_cpumask);
+ free_cpu_set(ctdp_level->core_cpumask);
+ }
+}
+
+int isst_get_process_ctdp(int cpu, int tdp_level, struct isst_pkg_ctdp *pkg_dev)
+{
+ int i, ret;
+
+ if (pkg_dev->processed)
+ return 0;
+
+ ret = isst_get_ctdp_levels(cpu, 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,
+ pkg_dev->levels);
+
+ 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,
+ 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);
+
+ ret = isst_get_ctdp_control(cpu, i, ctdp_level);
+ if (ret)
+ continue;
+
+ pkg_dev->processed = 1;
+ ctdp_level->processed = 1;
+
+ if (ctdp_level->pbf_support) {
+ ret = isst_get_pbf_info(cpu, i, &ctdp_level->pbf_info);
+ if (!ret)
+ ctdp_level->pbf_found = 1;
+ }
+
+ if (ctdp_level->fact_support) {
+ ret = isst_get_fact_info(cpu, i,
+ &ctdp_level->fact_info);
+ if (ret)
+ return ret;
+ }
+
+ if (!pkg_dev->enabled) {
+ int freq;
+
+ freq = get_cpufreq_base_freq(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);
+ continue;
+ }
+
+ ret = isst_get_tdp_info(cpu, i, ctdp_level);
+ if (ret)
+ return ret;
+
+ ret = isst_get_pwr_info(cpu, i, ctdp_level);
+ if (ret)
+ return ret;
+
+ ret = isst_get_tjmax_info(cpu, 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);
+ if (ret)
+ return ret;
+
+ ret = isst_get_trl_bucket_info(cpu, &ctdp_level->buckets_info);
+ if (ret)
+ return ret;
+
+ ret = isst_get_get_trl(cpu, i, 0,
+ ctdp_level->trl_sse_active_cores);
+ if (ret)
+ return ret;
+
+ ret = isst_get_get_trl(cpu, i, 1,
+ ctdp_level->trl_avx_active_cores);
+ if (ret)
+ return ret;
+
+ ret = isst_get_get_trl(cpu, i, 2,
+ ctdp_level->trl_avx_512_active_cores);
+ if (ret)
+ return ret;
+
+ isst_get_uncore_p0_p1_info(cpu, i, ctdp_level);
+ isst_get_p1_info(cpu, i, ctdp_level);
+ isst_get_uncore_mem_freq(cpu, i, ctdp_level);
+ }
+
+ return 0;
+}
+
+int isst_clos_get_clos_information(int cpu, int *enable, int *type)
+{
+ unsigned int resp;
+ int ret;
+
+ ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
+ &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", cpu, resp);
+
+ if (resp & BIT(1))
+ *enable = 1;
+ else
+ *enable = 0;
+
+ if (resp & BIT(2))
+ *type = 1;
+ else
+ *type = 0;
+
+ return 0;
+}
+
+int isst_pm_qos_config(int cpu, int enable_clos, int priority_type)
+{
+ unsigned int req, resp;
+ int ret;
+
+ if (!enable_clos) {
+ struct isst_pkg_ctdp pkg_dev;
+ struct isst_pkg_ctdp_level_info ctdp_level;
+
+ ret = isst_get_ctdp_levels(cpu, &pkg_dev);
+ if (ret) {
+ debug_printf("isst_get_ctdp_levels\n");
+ return ret;
+ }
+
+ ret = isst_get_ctdp_control(cpu, pkg_dev.current_level,
+ &ctdp_level);
+ if (ret)
+ return ret;
+
+ if (ctdp_level.fact_enabled) {
+ debug_printf("Turbo-freq feature must be disabled first\n");
+ return -EINVAL;
+ }
+ }
+
+ ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
+ &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", cpu, resp);
+
+ req = resp;
+
+ if (enable_clos)
+ req = req | BIT(1);
+ else
+ req = req & ~BIT(1);
+
+ if (priority_type)
+ req = req | BIT(2);
+ else
+ req = req & ~BIT(2);
+
+ ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG,
+ BIT(MBOX_CMD_WRITE_BIT), req, &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CLOS_PM_QOS_CONFIG priority type:%d req:%x\n", cpu,
+ priority_type, req);
+
+ return 0;
+}
+
+int isst_pm_get_clos(int cpu, int clos, struct isst_clos_config *clos_config)
+{
+ unsigned int resp;
+ int ret;
+
+ ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_CLOS, clos, 0,
+ &resp);
+ if (ret)
+ return ret;
+
+ clos_config->pkg_id = get_physical_package_id(cpu);
+ clos_config->die_id = get_physical_die_id(cpu);
+
+ clos_config->epp = resp & 0x0f;
+ clos_config->clos_prop_prio = (resp >> 4) & 0x0f;
+ clos_config->clos_min = (resp >> 8) & 0xff;
+ clos_config->clos_max = (resp >> 16) & 0xff;
+ clos_config->clos_desired = (resp >> 24) & 0xff;
+
+ return 0;
+}
+
+int isst_set_clos(int cpu, int clos, struct isst_clos_config *clos_config)
+{
+ unsigned int req, resp;
+ unsigned int param;
+ int ret;
+
+ req = clos_config->epp & 0x0f;
+ req |= (clos_config->clos_prop_prio & 0x0f) << 4;
+ req |= (clos_config->clos_min & 0xff) << 8;
+ req |= (clos_config->clos_max & 0xff) << 16;
+ req |= (clos_config->clos_desired & 0xff) << 24;
+
+ param = BIT(MBOX_CMD_WRITE_BIT) | clos;
+
+ ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PM_CLOS, param, req,
+ &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CLOS_PM_CLOS param:%x req:%x\n", cpu, param, req);
+
+ return 0;
+}
+
+int isst_clos_get_assoc_status(int cpu, int *clos_id)
+{
+ unsigned int resp;
+ unsigned int param;
+ int core_id, ret;
+
+ core_id = find_phy_core_num(cpu);
+ param = core_id;
+
+ ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 0,
+ &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x resp:%x\n", cpu, param,
+ resp);
+ *clos_id = (resp >> 16) & 0x03;
+
+ return 0;
+}
+
+int isst_clos_associate(int cpu, 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);
+ param = BIT(MBOX_CMD_WRITE_BIT) | core_id;
+
+ ret = isst_send_mbox_command(cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param,
+ req, &resp);
+ if (ret)
+ return ret;
+
+ debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x req:%x\n", cpu, param,
+ req);
+
+ return 0;
+}
diff --git a/tools/power/x86/intel-speed-select/isst-display.c b/tools/power/x86/intel-speed-select/isst-display.c
new file mode 100644
index 000000000000..040dd09d5eee
--- /dev/null
+++ b/tools/power/x86/intel-speed-select/isst-display.c
@@ -0,0 +1,654 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Intel dynamic_speed_select -- Enumerate and control features
+ * Copyright (c) 2019 Intel Corporation.
+ */
+
+#include "isst.h"
+
+static void printcpulist(int str_len, char *str, int mask_size,
+ cpu_set_t *cpu_mask)
+{
+ int i, first, curr_index, index;
+
+ if (!CPU_COUNT_S(mask_size, cpu_mask)) {
+ snprintf(str, str_len, "none");
+ return;
+ }
+
+ curr_index = 0;
+ first = 1;
+ for (i = 0; i < get_topo_max_cpus(); ++i) {
+ if (!CPU_ISSET_S(i, mask_size, cpu_mask))
+ continue;
+ if (!first) {
+ index = snprintf(&str[curr_index],
+ str_len - curr_index, ",");
+ curr_index += index;
+ }
+ index = snprintf(&str[curr_index], str_len - curr_index, "%d",
+ i);
+ curr_index += index;
+ first = 0;
+ }
+}
+
+static void printcpumask(int str_len, char *str, int mask_size,
+ cpu_set_t *cpu_mask)
+{
+ int i, max_cpus = get_topo_max_cpus();
+ unsigned int *mask;
+ int size, index, curr_index;
+
+ size = max_cpus / (sizeof(unsigned int) * 8);
+ if (max_cpus % (sizeof(unsigned int) * 8))
+ size++;
+
+ mask = calloc(size, sizeof(unsigned int));
+ if (!mask)
+ return;
+
+ for (i = 0; i < max_cpus; ++i) {
+ int mask_index, bit_index;
+
+ if (!CPU_ISSET_S(i, mask_size, cpu_mask))
+ continue;
+
+ mask_index = i / (sizeof(unsigned int) * 8);
+ bit_index = i % (sizeof(unsigned int) * 8);
+ mask[mask_index] |= BIT(bit_index);
+ }
+
+ curr_index = 0;
+ for (i = size - 1; i >= 0; --i) {
+ index = snprintf(&str[curr_index], str_len - curr_index, "%08x",
+ mask[i]);
+ curr_index += index;
+ if (i) {
+ strncat(&str[curr_index], ",", str_len - curr_index);
+ curr_index++;
+ }
+ }
+
+ free(mask);
+}
+
+static void format_and_print_txt(FILE *outf, int level, char *header,
+ char *value)
+{
+ char *spaces = " ";
+ static char delimiters[256];
+ int i, j = 0;
+
+ if (!level)
+ return;
+
+ if (level == 1) {
+ strcpy(delimiters, " ");
+ } else {
+ for (i = 0; i < level - 1; ++i)
+ j += snprintf(&delimiters[j], sizeof(delimiters) - j,
+ "%s", spaces);
+ }
+
+ if (header && value) {
+ fprintf(outf, "%s", delimiters);
+ fprintf(outf, "%s:%s\n", header, value);
+ } else if (header) {
+ fprintf(outf, "%s", delimiters);
+ fprintf(outf, "%s\n", header);
+ }
+}
+
+static int last_level;
+static void format_and_print(FILE *outf, int level, char *header, char *value)
+{
+ char *spaces = " ";
+ static char delimiters[256];
+ int i;
+
+ if (!out_format_is_json()) {
+ format_and_print_txt(outf, level, header, value);
+ return;
+ }
+
+ if (level == 0) {
+ if (header)
+ fprintf(outf, "{");
+ else
+ fprintf(outf, "\n}\n");
+
+ } else {
+ int j = 0;
+
+ for (i = 0; i < level; ++i)
+ j += snprintf(&delimiters[j], sizeof(delimiters) - j,
+ "%s", spaces);
+
+ if (last_level == level)
+ fprintf(outf, ",\n");
+
+ if (value) {
+ if (last_level != level)
+ fprintf(outf, "\n");
+
+ fprintf(outf, "%s\"%s\": ", delimiters, header);
+ fprintf(outf, "\"%s\"", value);
+ } else {
+ for (i = last_level - 1; i >= level; --i) {
+ int k = 0;
+
+ for (j = i; j > 0; --j)
+ k += snprintf(&delimiters[k],
+ sizeof(delimiters) - k,
+ "%s", spaces);
+ if (i == level && header)
+ fprintf(outf, "\n%s},", delimiters);
+ else
+ fprintf(outf, "\n%s}", delimiters);
+ }
+ if (abs(last_level - level) < 3)
+ fprintf(outf, "\n");
+ if (header)
+ fprintf(outf, "%s\"%s\": {", delimiters,
+ header);
+ }
+ }
+
+ last_level = level;
+}
+
+static void print_package_info(int cpu, FILE *outf)
+{
+ char header[256];
+
+ 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);
+}
+
+static void _isst_pbf_display_information(int cpu, FILE *outf, int level,
+ struct isst_pbf_info *pbf_info,
+ int disp_level)
+{
+ char header[256];
+ char value[256];
+
+ snprintf(header, sizeof(header), "speed-select-base-freq");
+ format_and_print(outf, disp_level, header, NULL);
+
+ snprintf(header, sizeof(header), "high-priority-base-frequency(MHz)");
+ snprintf(value, sizeof(value), "%d",
+ pbf_info->p1_high * DISP_FREQ_MULTIPLIER);
+ format_and_print(outf, disp_level + 1, header, value);
+
+ snprintf(header, sizeof(header), "high-priority-cpu-mask");
+ printcpumask(sizeof(value), value, pbf_info->core_cpumask_size,
+ pbf_info->core_cpumask);
+ format_and_print(outf, disp_level + 1, header, value);
+
+ snprintf(header, sizeof(header), "high-priority-cpu-list");
+ printcpulist(sizeof(value), value,
+ pbf_info->core_cpumask_size,
+ pbf_info->core_cpumask);
+ format_and_print(outf, disp_level + 1, header, value);
+
+ snprintf(header, sizeof(header), "low-priority-base-frequency(MHz)");
+ snprintf(value, sizeof(value), "%d",
+ pbf_info->p1_low * DISP_FREQ_MULTIPLIER);
+ format_and_print(outf, disp_level + 1, header, value);
+
+ if (is_clx_n_platform())
+ return;
+
+ snprintf(header, sizeof(header), "tjunction-temperature(C)");
+ snprintf(value, sizeof(value), "%d", pbf_info->t_prochot);
+ format_and_print(outf, disp_level + 1, header, value);
+
+ snprintf(header, sizeof(header), "thermal-design-power(W)");
+ snprintf(value, sizeof(value), "%d", pbf_info->tdp);
+ format_and_print(outf, disp_level + 1, header, value);
+}
+
+static void _isst_fact_display_information(int cpu, FILE *outf, int level,
+ int fact_bucket, int fact_avx,
+ struct isst_fact_info *fact_info,
+ int base_level)
+{
+ struct isst_fact_bucket_info *bucket_info = fact_info->bucket_info;
+ char header[256];
+ char value[256];
+ int j;
+
+ snprintf(header, sizeof(header), "speed-select-turbo-freq");
+ format_and_print(outf, base_level, header, NULL);
+ 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;
+
+ snprintf(header, sizeof(header), "bucket-%d", j);
+ format_and_print(outf, base_level + 1, header, NULL);
+
+ snprintf(header, sizeof(header), "high-priority-cores-count");
+ snprintf(value, sizeof(value), "%d",
+ bucket_info[j].high_priority_cores_count);
+ format_and_print(outf, base_level + 2, header, value);
+
+ if (fact_avx & 0x01) {
+ snprintf(header, sizeof(header),
+ "high-priority-max-frequency(MHz)");
+ snprintf(value, sizeof(value), "%d",
+ bucket_info[j].sse_trl * DISP_FREQ_MULTIPLIER);
+ format_and_print(outf, base_level + 2, header, value);
+ }
+
+ if (fact_avx & 0x02) {
+ snprintf(header, sizeof(header),
+ "high-priority-max-avx2-frequency(MHz)");
+ snprintf(value, sizeof(value), "%d",
+ bucket_info[j].avx_trl * DISP_FREQ_MULTIPLIER);
+ format_and_print(outf, base_level + 2, header, value);
+ }
+
+ if (fact_avx & 0x04) {
+ snprintf(header, sizeof(header),
+ "high-priority-max-avx512-frequency(MHz)");
+ snprintf(value, sizeof(value), "%d",
+ bucket_info[j].avx512_trl *
+ DISP_FREQ_MULTIPLIER);
+ format_and_print(outf, base_level + 2, header, value);
+ }
+ }
+ snprintf(header, sizeof(header),
+ "speed-select-turbo-freq-clip-frequencies");
+ format_and_print(outf, base_level + 1, header, NULL);
+ snprintf(header, sizeof(header), "low-priority-max-frequency(MHz)");
+ snprintf(value, sizeof(value), "%d",
+ fact_info->lp_clipping_ratio_license_sse *
+ DISP_FREQ_MULTIPLIER);
+ format_and_print(outf, base_level + 2, header, value);
+ snprintf(header, sizeof(header),
+ "low-priority-max-avx2-frequency(MHz)");
+ snprintf(value, sizeof(value), "%d",
+ fact_info->lp_clipping_ratio_license_avx2 *
+ DISP_FREQ_MULTIPLIER);
+ format_and_print(outf, base_level + 2, header, value);
+ snprintf(header, sizeof(header),
+ "low-priority-max-avx512-frequency(MHz)");
+ snprintf(value, sizeof(value), "%d",
+ fact_info->lp_clipping_ratio_license_avx512 *
+ DISP_FREQ_MULTIPLIER);
+ format_and_print(outf, base_level + 2, header, value);
+}
+
+void isst_ctdp_display_core_info(int cpu, FILE *outf, char *prefix,
+ unsigned int val)
+{
+ char header[256];
+ char value[256];
+
+ 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(value, sizeof(value), "%u", val);
+ format_and_print(outf, 4, prefix, value);
+
+ format_and_print(outf, 1, NULL, NULL);
+}
+
+void isst_ctdp_display_information(int cpu, FILE *outf, int tdp_level,
+ struct isst_pkg_ctdp *pkg_dev)
+{
+ char header[256];
+ char value[256];
+ int i, base_level = 1;
+
+ if (pkg_dev->processed)
+ print_package_info(cpu, outf);
+
+ for (i = 0; i <= pkg_dev->levels; ++i) {
+ struct isst_pkg_ctdp_level_info *ctdp_level;
+ int j;
+
+ ctdp_level = &pkg_dev->ctdp_level[i];
+ if (!ctdp_level->processed)
+ continue;
+
+ snprintf(header, sizeof(header), "perf-profile-level-%d",
+ ctdp_level->level);
+ format_and_print(outf, base_level + 3, header, NULL);
+
+ snprintf(header, sizeof(header), "cpu-count");
+ j = get_cpu_count(get_physical_die_id(cpu),
+ get_physical_die_id(cpu));
+ snprintf(value, sizeof(value), "%d", j);
+ format_and_print(outf, base_level + 4, 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);
+
+ 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);
+ }
+
+ 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);
+
+ 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);
+
+ 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);
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ snprintf(header, sizeof(header),
+ "speed-select-turbo-freq");
+ if (ctdp_level->fact_support) {
+ if (ctdp_level->fact_enabled)
+ snprintf(value, sizeof(value), "enabled");
+ else
+ snprintf(value, sizeof(value), "disabled");
+ } else
+ snprintf(value, sizeof(value), "unsupported");
+ format_and_print(outf, base_level + 4, header, value);
+
+ snprintf(header, sizeof(header),
+ "speed-select-base-freq");
+ if (ctdp_level->pbf_support) {
+ if (ctdp_level->pbf_enabled)
+ snprintf(value, sizeof(value), "enabled");
+ else
+ snprintf(value, sizeof(value), "disabled");
+ } else
+ snprintf(value, sizeof(value), "unsupported");
+ format_and_print(outf, base_level + 4, header, value);
+
+ if (is_clx_n_platform()) {
+ if (ctdp_level->pbf_support)
+ _isst_pbf_display_information(cpu, outf,
+ tdp_level,
+ &ctdp_level->pbf_info,
+ base_level + 4);
+ 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);
+ }
+
+ 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);
+ }
+
+ snprintf(header, sizeof(header), "turbo-ratio-limits-sse");
+ format_and_print(outf, base_level + 4, header, NULL);
+ for (j = 0; j < 8; ++j) {
+ snprintf(header, sizeof(header), "bucket-%d", j);
+ format_and_print(outf, base_level + 5, 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);
+
+ 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);
+ }
+
+ 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);
+ for (j = 0; j < 8; ++j) {
+ snprintf(header, sizeof(header), "bucket-%d", j);
+ format_and_print(outf, base_level + 5, 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);
+
+ 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);
+ }
+ }
+
+ 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);
+ for (j = 0; j < 8; ++j) {
+ snprintf(header, sizeof(header), "bucket-%d", j);
+ format_and_print(outf, base_level + 5, 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);
+
+ 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);
+ }
+ }
+
+ if (ctdp_level->pbf_support)
+ _isst_pbf_display_information(cpu, outf, i,
+ &ctdp_level->pbf_info,
+ base_level + 4);
+ if (ctdp_level->fact_support)
+ _isst_fact_display_information(cpu, outf, i, 0xff, 0xff,
+ &ctdp_level->fact_info,
+ base_level + 4);
+ }
+
+ format_and_print(outf, 1, NULL, NULL);
+}
+
+void isst_ctdp_display_information_start(FILE *outf)
+{
+ last_level = 0;
+ format_and_print(outf, 0, "start", NULL);
+}
+
+void isst_ctdp_display_information_end(FILE *outf)
+{
+ format_and_print(outf, 0, NULL, NULL);
+}
+
+void isst_pbf_display_information(int cpu, 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);
+ format_and_print(outf, 1, NULL, NULL);
+}
+
+void isst_fact_display_information(int cpu, 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);
+ format_and_print(outf, 1, NULL, NULL);
+}
+
+void isst_clos_display_information(int cpu, FILE *outf, int clos,
+ struct isst_clos_config *clos_config)
+{
+ char header[256];
+ char value[256];
+
+ 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), "core-power");
+ format_and_print(outf, 4, header, NULL);
+
+ snprintf(header, sizeof(header), "clos");
+ snprintf(value, sizeof(value), "%d", clos);
+ format_and_print(outf, 5, header, value);
+
+ snprintf(header, sizeof(header), "epp");
+ snprintf(value, sizeof(value), "%d", clos_config->epp);
+ format_and_print(outf, 5, 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);
+
+ 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);
+
+ 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);
+
+ 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, 1, NULL, NULL);
+}
+
+void isst_clos_display_clos_information(int cpu, FILE *outf,
+ int clos_enable, int type)
+{
+ char header[256];
+ char value[256];
+
+ 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), "core-power");
+ format_and_print(outf, 4, header, NULL);
+
+ snprintf(header, sizeof(header), "enable-status");
+ snprintf(value, sizeof(value), "%d", clos_enable);
+ format_and_print(outf, 5, header, value);
+
+ snprintf(header, sizeof(header), "priority-type");
+ snprintf(value, sizeof(value), "%d", type);
+ format_and_print(outf, 5, header, value);
+
+ format_and_print(outf, 1, NULL, NULL);
+}
+
+void isst_clos_display_assoc_information(int cpu, FILE *outf, int clos)
+{
+ char header[256];
+ char value[256];
+
+ 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), "get-assoc");
+ format_and_print(outf, 4, header, NULL);
+
+ snprintf(header, sizeof(header), "clos");
+ snprintf(value, sizeof(value), "%d", clos);
+ format_and_print(outf, 5, header, value);
+
+ format_and_print(outf, 1, NULL, NULL);
+}
+
+void isst_display_result(int cpu, FILE *outf, char *feature, char *cmd,
+ int result)
+{
+ char header[256];
+ char value[256];
+
+ 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);
+ 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, 1, NULL, NULL);
+}
diff --git a/tools/power/x86/intel-speed-select/isst.h b/tools/power/x86/intel-speed-select/isst.h
new file mode 100644
index 000000000000..cdf0f8a6dbbf
--- /dev/null
+++ b/tools/power/x86/intel-speed-select/isst.h
@@ -0,0 +1,245 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Intel Speed Select -- Enumerate and control features
+ * Copyright (c) 2019 Intel Corporation.
+ */
+
+#ifndef _ISST_H_
+#define _ISST_H_
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sched.h>
+#include <sys/stat.h>
+#include <sys/resource.h>
+#include <getopt.h>
+#include <err.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <cpuid.h>
+#include <dirent.h>
+#include <errno.h>
+
+#include <stdarg.h>
+#include <sys/ioctl.h>
+
+#define BIT(x) (1 << (x))
+#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))))
+
+#define CONFIG_TDP 0x7f
+#define CONFIG_TDP_GET_LEVELS_INFO 0x00
+#define CONFIG_TDP_GET_TDP_CONTROL 0x01
+#define CONFIG_TDP_SET_TDP_CONTROL 0x02
+#define CONFIG_TDP_GET_TDP_INFO 0x03
+#define CONFIG_TDP_GET_PWR_INFO 0x04
+#define CONFIG_TDP_GET_TJMAX_INFO 0x05
+#define CONFIG_TDP_GET_CORE_MASK 0x06
+#define CONFIG_TDP_GET_TURBO_LIMIT_RATIOS 0x07
+#define CONFIG_TDP_SET_LEVEL 0x08
+#define CONFIG_TDP_GET_UNCORE_P0_P1_INFO 0X09
+#define CONFIG_TDP_GET_P1_INFO 0x0a
+#define CONFIG_TDP_GET_MEM_FREQ 0x0b
+
+#define CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES 0x10
+#define CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS 0x11
+#define CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO 0x12
+
+#define CONFIG_TDP_PBF_GET_CORE_MASK_INFO 0x20
+#define CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO 0x21
+#define CONFIG_TDP_PBF_GET_TJ_MAX_INFO 0x22
+#define CONFIG_TDP_PBF_GET_TDP_INFO 0X23
+
+#define CONFIG_CLOS 0xd0
+#define CLOS_PQR_ASSOC 0x00
+#define CLOS_PM_CLOS 0x01
+#define CLOS_PM_QOS_CONFIG 0x02
+#define CLOS_STATUS 0x03
+
+#define MBOX_CMD_WRITE_BIT 0x08
+
+#define PM_QOS_INFO_OFFSET 0x00
+#define PM_QOS_CONFIG_OFFSET 0x04
+#define PM_CLOS_OFFSET 0x08
+#define PQR_ASSOC_OFFSET 0x20
+
+#define DISP_FREQ_MULTIPLIER 100
+
+struct isst_clos_config {
+ int pkg_id;
+ int die_id;
+ unsigned char epp;
+ unsigned char clos_prop_prio;
+ unsigned char clos_min;
+ unsigned char clos_max;
+ unsigned char clos_desired;
+};
+
+struct isst_fact_bucket_info {
+ int high_priority_cores_count;
+ int sse_trl;
+ int avx_trl;
+ int avx512_trl;
+};
+
+struct isst_pbf_info {
+ int pbf_acticated;
+ int pbf_available;
+ size_t core_cpumask_size;
+ cpu_set_t *core_cpumask;
+ int p1_high;
+ int p1_low;
+ int t_control;
+ int t_prochot;
+ int tdp;
+};
+
+#define ISST_TRL_MAX_ACTIVE_CORES 8
+#define ISST_FACT_MAX_BUCKETS 8
+struct isst_fact_info {
+ int lp_clipping_ratio_license_sse;
+ int lp_clipping_ratio_license_avx2;
+ int lp_clipping_ratio_license_avx512;
+ struct isst_fact_bucket_info bucket_info[ISST_FACT_MAX_BUCKETS];
+};
+
+struct isst_pkg_ctdp_level_info {
+ int processed;
+ int control_cpu;
+ int pkg_id;
+ int die_id;
+ int level;
+ int fact_support;
+ int pbf_support;
+ int fact_enabled;
+ int pbf_enabled;
+ int tdp_ratio;
+ int active;
+ int tdp_control;
+ int pkg_tdp;
+ int pkg_min_power;
+ int pkg_max_power;
+ int fact;
+ int t_proc_hot;
+ int uncore_p0;
+ int uncore_p1;
+ int sse_p1;
+ int avx2_p1;
+ int avx512_p1;
+ int mem_freq;
+ size_t core_cpumask_size;
+ cpu_set_t *core_cpumask;
+ int cpu_count;
+ unsigned long long buckets_info;
+ int trl_sse_active_cores[ISST_TRL_MAX_ACTIVE_CORES];
+ int trl_avx_active_cores[ISST_TRL_MAX_ACTIVE_CORES];
+ int trl_avx_512_active_cores[ISST_TRL_MAX_ACTIVE_CORES];
+ int kobj_bucket_index;
+ int active_bucket;
+ int fact_max_index;
+ int fact_max_config;
+ int pbf_found;
+ int pbf_active;
+ struct isst_pbf_info pbf_info;
+ struct isst_fact_info fact_info;
+};
+
+#define ISST_MAX_TDP_LEVELS (4 + 1) /* +1 for base config */
+struct isst_pkg_ctdp {
+ int locked;
+ int version;
+ int processed;
+ int levels;
+ int current_level;
+ int enabled;
+ struct isst_pkg_ctdp_level_info ctdp_level[ISST_MAX_TDP_LEVELS];
+};
+
+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);
+
+/* Common interfaces */
+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 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,
+ unsigned long long core_mask,
+ size_t core_cpumask_size,
+ cpu_set_t *core_cpumask,
+ int *cpu_cnt);
+
+extern int isst_send_mbox_command(unsigned int cpu, unsigned char command,
+ unsigned char sub_command,
+ unsigned int write,
+ unsigned int req_data, unsigned int *resp);
+
+extern int isst_send_msr_command(unsigned int cpu, unsigned int command,
+ int write, unsigned long long *req_resp);
+
+extern int isst_get_ctdp_levels(int cpu, struct isst_pkg_ctdp *pkg_dev);
+extern int isst_get_coremask_info(int cpu, int config_index,
+ struct isst_pkg_ctdp_level_info *ctdp_level);
+extern int isst_get_process_ctdp(int cpu, int tdp_level,
+ struct isst_pkg_ctdp *pkg_dev);
+extern void isst_get_process_ctdp_complete(int cpu,
+ struct isst_pkg_ctdp *pkg_dev);
+extern void isst_ctdp_display_information(int cpu, 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_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,
+ 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,
+ 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,
+ struct isst_fact_info *fact_info);
+extern int isst_get_fact_bucket_info(int cpu, int level,
+ struct isst_fact_bucket_info *bucket_info);
+extern void isst_fact_display_information(int cpu, FILE *outf, int level,
+ 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_pm_qos_config(int cpu, int enable_clos, int priority_type);
+extern int isst_pm_get_clos(int cpu, int clos,
+ struct isst_clos_config *clos_config);
+extern int isst_set_clos(int cpu, 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,
+ 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_display_result(int cpu, 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 is_clx_n_platform(void);
+extern int get_cpufreq_base_freq(int cpu);
+#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 2fa3c5757bcb..2d6d342b148f 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,5 @@
#!/usr/bin/python
+# SPDX-License-Identifier: GPL-2.0-only
# -*- coding: utf-8 -*-
#
""" This utility can be used to debug and tune the performance of the
diff --git a/tools/power/x86/turbostat/Makefile b/tools/power/x86/turbostat/Makefile
index 1598b4fa0b11..13f1e8b9ac52 100644
--- a/tools/power/x86/turbostat/Makefile
+++ b/tools/power/x86/turbostat/Makefile
@@ -9,9 +9,10 @@ ifeq ("$(origin O)", "command line")
endif
turbostat : turbostat.c
-override CFLAGS += -Wall
+override CFLAGS += -O2 -Wall -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_FORTIFY_SOURCE=2
%: %.c
@mkdir -p $(BUILD_OUTPUT)
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index c7727be9719f..5d0fddda842c 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -1,22 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* turbostat -- show CPU frequency and C-state residency
* on modern Intel and AMD processors.
*
* Copyright (c) 2013 Intel Corporation.
* Len Brown <len.brown@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/
#define _GNU_SOURCE
@@ -51,7 +39,6 @@ FILE *outf;
int *fd_percpu;
struct timeval interval_tv = {5, 0};
struct timespec interval_ts = {5, 0};
-struct timespec one_msec = {0, 1000000};
unsigned int num_iterations;
unsigned int debug;
unsigned int quiet;
@@ -72,6 +59,7 @@ unsigned int do_irtl_hsw;
unsigned int units = 1000000; /* MHz etc */
unsigned int genuine_intel;
unsigned int authentic_amd;
+unsigned int hygon_genuine;
unsigned int max_level, max_extended_level;
unsigned int has_invariant_tsc;
unsigned int do_nhm_platform_info;
@@ -112,6 +100,7 @@ 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;
#define RAPL_PKG (1 << 0)
/* 0x610 MSR_PKG_POWER_LIMIT */
@@ -178,6 +167,7 @@ size_t cpu_present_setsize, cpu_affinity_setsize, cpu_subset_size;
struct thread_data {
struct timeval tv_begin;
struct timeval tv_end;
+ struct timeval tv_delta;
unsigned long long tsc;
unsigned long long aperf;
unsigned long long mperf;
@@ -518,6 +508,7 @@ unsigned long long bic_enabled = (0xFFFFFFFFFFFFFFFFULL & ~BIC_DISABLED_BY_DEFAU
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)
@@ -861,7 +852,6 @@ int dump_counters(struct thread_data *t, struct core_data *c,
outp += sprintf(outp, "pc8: %016llX\n", p->pc8);
outp += sprintf(outp, "pc9: %016llX\n", p->pc9);
outp += sprintf(outp, "pc10: %016llX\n", p->pc10);
- 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);
@@ -923,7 +913,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 = tv_delta.tv_sec + 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;
@@ -1299,6 +1289,14 @@ delta_core(struct core_data *new, struct core_data *old)
}
}
+int soft_c1_residency_display(int bic)
+{
+ if (!DO_BIC(BIC_CPU_c1) || use_c1_residency_msr)
+ return 0;
+
+ return DO_BIC_READ(bic);
+}
+
/*
* old = new - old
*/
@@ -1321,6 +1319,7 @@ delta_thread(struct thread_data *new, struct thread_data *old,
* over-write old w/ new so we can print end of interval values
*/
+ timersub(&new->tv_begin, &old->tv_begin, &old->tv_delta);
old->tv_begin = new->tv_begin;
old->tv_end = new->tv_end;
@@ -1334,7 +1333,8 @@ 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)) {
+ 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;
@@ -1416,6 +1416,8 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data
t->tv_begin.tv_usec = 0;
t->tv_end.tv_sec = 0;
t->tv_end.tv_usec = 0;
+ t->tv_delta.tv_sec = 0;
+ t->tv_delta.tv_usec = 0;
t->tsc = 0;
t->aperf = 0;
@@ -1585,6 +1587,9 @@ void compute_average(struct thread_data *t, struct core_data *c,
for_all_cpus(sum_counters, t, c, p);
+ /* Use the global time delta for the average. */
+ average.threads.tv_delta = tv_delta;
+
average.threads.tsc /= topo.num_cpus;
average.threads.aperf /= topo.num_cpus;
average.threads.mperf /= topo.num_cpus;
@@ -1726,7 +1731,7 @@ void get_apic_id(struct thread_data *t)
if (!DO_BIC(BIC_X2APIC))
return;
- if (authentic_amd) {
+ if (authentic_amd || hygon_genuine) {
unsigned int topology_extensions;
if (max_extended_level < 0x8000001e)
@@ -1774,19 +1779,20 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
struct msr_counter *mp;
int i;
- gettimeofday(&t->tv_begin, (struct timezone *)NULL);
-
if (cpu_migrate(cpu)) {
fprintf(outf, "Could not migrate to CPU %d\n", cpu);
return -1;
}
+ gettimeofday(&t->tv_begin, (struct timezone *)NULL);
+
if (first_counter_read)
get_apic_id(t);
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)) {
+ 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;
/*
@@ -1863,20 +1869,20 @@ retry:
if (!(t->flags & CPU_IS_FIRST_THREAD_IN_CORE))
goto done;
- if (DO_BIC(BIC_CPU_c3)) {
+ if (DO_BIC(BIC_CPU_c3) || soft_c1_residency_display(BIC_CPU_c3)) {
if (get_msr(cpu, MSR_CORE_C3_RESIDENCY, &c->c3))
return -6;
}
- if (DO_BIC(BIC_CPU_c6) && !do_knl_cstates) {
+ if ((DO_BIC(BIC_CPU_c6) || soft_c1_residency_display(BIC_CPU_c6)) && !do_knl_cstates) {
if (get_msr(cpu, MSR_CORE_C6_RESIDENCY, &c->c6))
return -7;
- } else if (do_knl_cstates) {
+ } else if (do_knl_cstates || soft_c1_residency_display(BIC_CPU_c6)) {
if (get_msr(cpu, MSR_KNL_CORE_C6_RESIDENCY, &c->c6))
return -7;
}
- if (DO_BIC(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;
@@ -2162,7 +2168,7 @@ int has_turbo_ratio_group_limits(int family, int model)
switch (model) {
case INTEL_FAM6_ATOM_GOLDMONT:
case INTEL_FAM6_SKYLAKE_X:
- case INTEL_FAM6_ATOM_GOLDMONT_X:
+ case INTEL_FAM6_ATOM_GOLDMONT_D:
return 1;
}
return 0;
@@ -2924,6 +2930,7 @@ int snapshot_cpu_lpi_us(void)
if (retval != 1) {
fprintf(stderr, "Disabling Low Power Idle CPU output\n");
BIC_NOT_PRESENT(BIC_CPU_LPI);
+ fclose(fp);
return -1;
}
@@ -2950,6 +2957,7 @@ int snapshot_sys_lpi_us(void)
if (retval != 1) {
fprintf(stderr, "Disabling Low Power Idle System output\n");
BIC_NOT_PRESENT(BIC_SYS_LPI);
+ fclose(fp);
return -1;
}
fclose(fp);
@@ -2997,8 +3005,6 @@ static void signal_handler (int signal)
fprintf(stderr, "SIGUSR1\n");
break;
}
- /* make sure this manually-invoked interval is at least 1ms long */
- nanosleep(&one_msec, NULL);
}
void setup_signal_handler(void)
@@ -3017,29 +3023,38 @@ void setup_signal_handler(void)
void do_sleep(void)
{
- struct timeval select_timeout;
+ struct timeval tout;
+ struct timespec rest;
fd_set readfds;
int retval;
FD_ZERO(&readfds);
FD_SET(0, &readfds);
- if (!isatty(fileno(stdin))) {
+ if (ignore_stdin) {
nanosleep(&interval_ts, NULL);
return;
}
- select_timeout = interval_tv;
- retval = select(1, &readfds, NULL, NULL, &select_timeout);
+ tout = interval_tv;
+ retval = select(1, &readfds, NULL, NULL, &tout);
if (retval == 1) {
switch (getc(stdin)) {
case 'q':
exit_requested = 1;
break;
+ case EOF:
+ /*
+ * 'stdin' is a pipe closed on the other end. There
+ * won't be any further input.
+ */
+ ignore_stdin = 1;
+ /* Sleep the rest of the time */
+ rest.tv_sec = (tout.tv_sec + tout.tv_usec / 1000000);
+ rest.tv_nsec = (tout.tv_usec % 1000000) * 1000;
+ nanosleep(&rest, NULL);
}
- /* make sure this manually-invoked interval is at least 1ms long */
- nanosleep(&one_msec, NULL);
}
}
@@ -3219,14 +3234,15 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
pkg_cstate_limits = snb_pkg_cstate_limits;
has_misc_feature_control = 1;
break;
- case INTEL_FAM6_HASWELL_CORE: /* HSW */
+ case INTEL_FAM6_HASWELL: /* HSW */
+ case INTEL_FAM6_HASWELL_G: /* HSW */
case INTEL_FAM6_HASWELL_X: /* HSX */
- case INTEL_FAM6_HASWELL_GT3E: /* HSW */
- case INTEL_FAM6_BROADWELL_CORE: /* BDW */
- case INTEL_FAM6_BROADWELL_GT3E: /* BDW */
+ case INTEL_FAM6_HASWELL_L: /* HSW */
+ case INTEL_FAM6_BROADWELL: /* BDW */
+ case INTEL_FAM6_BROADWELL_G: /* BDW */
case INTEL_FAM6_BROADWELL_X: /* BDX */
- case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */
- case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */
+ case INTEL_FAM6_SKYLAKE_L: /* SKL */
+ case INTEL_FAM6_CANNONLAKE_L: /* CNL */
pkg_cstate_limits = hsw_pkg_cstate_limits;
has_misc_feature_control = 1;
break;
@@ -3236,7 +3252,7 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
break;
case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */
no_MSR_MISC_PWR_MGMT = 1;
- case INTEL_FAM6_ATOM_SILVERMONT_X: /* AVN */
+ case INTEL_FAM6_ATOM_SILVERMONT_D: /* AVN */
pkg_cstate_limits = slv_pkg_cstate_limits;
break;
case INTEL_FAM6_ATOM_AIRMONT: /* AMT */
@@ -3248,7 +3264,7 @@ int probe_nhm_msrs(unsigned int family, unsigned int model)
break;
case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
- case INTEL_FAM6_ATOM_GOLDMONT_X: /* DNV */
+ case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */
pkg_cstate_limits = glm_pkg_cstate_limits;
break;
default:
@@ -3291,7 +3307,7 @@ int is_dnv(unsigned int family, unsigned int model)
return 0;
switch (model) {
- case INTEL_FAM6_ATOM_GOLDMONT_X:
+ case INTEL_FAM6_ATOM_GOLDMONT_D:
return 1;
}
return 0;
@@ -3415,14 +3431,15 @@ int has_config_tdp(unsigned int family, unsigned int model)
switch (model) {
case INTEL_FAM6_IVYBRIDGE: /* IVB */
- case INTEL_FAM6_HASWELL_CORE: /* HSW */
+ case INTEL_FAM6_HASWELL: /* HSW */
case INTEL_FAM6_HASWELL_X: /* HSX */
- case INTEL_FAM6_HASWELL_GT3E: /* HSW */
- case INTEL_FAM6_BROADWELL_CORE: /* BDW */
- case INTEL_FAM6_BROADWELL_GT3E: /* BDW */
+ 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_MOBILE: /* SKL */
- case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */
+ case INTEL_FAM6_SKYLAKE_L: /* SKL */
+ case INTEL_FAM6_CANNONLAKE_L: /* CNL */
case INTEL_FAM6_SKYLAKE_X: /* SKX */
case INTEL_FAM6_XEON_PHI_KNL: /* Knights Landing */
@@ -3804,7 +3821,7 @@ double get_tdp_intel(unsigned int model)
switch (model) {
case INTEL_FAM6_ATOM_SILVERMONT:
- case INTEL_FAM6_ATOM_SILVERMONT_X:
+ case INTEL_FAM6_ATOM_SILVERMONT_D:
return 30.0;
default:
return 135.0;
@@ -3815,6 +3832,7 @@ 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;
@@ -3852,10 +3870,11 @@ void rapl_probe_intel(unsigned int family, unsigned int model)
switch (model) {
case INTEL_FAM6_SANDYBRIDGE:
case INTEL_FAM6_IVYBRIDGE:
- case INTEL_FAM6_HASWELL_CORE: /* HSW */
- case INTEL_FAM6_HASWELL_GT3E: /* HSW */
- case INTEL_FAM6_BROADWELL_CORE: /* BDW */
- case INTEL_FAM6_BROADWELL_GT3E: /* BDW */
+ case INTEL_FAM6_HASWELL: /* HSW */
+ case INTEL_FAM6_HASWELL_L: /* HSW */
+ case INTEL_FAM6_HASWELL_G: /* HSW */
+ case INTEL_FAM6_BROADWELL: /* BDW */
+ case INTEL_FAM6_BROADWELL_G: /* BDW */
do_rapl = RAPL_PKG | RAPL_CORES | RAPL_CORE_POLICY | RAPL_GFX | RAPL_PKG_POWER_INFO;
if (rapl_joules) {
BIC_PRESENT(BIC_Pkg_J);
@@ -3875,8 +3894,8 @@ void rapl_probe_intel(unsigned int family, unsigned int model)
else
BIC_PRESENT(BIC_PkgWatt);
break;
- case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */
- case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */
+ 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;
BIC_PRESENT(BIC_PKG__);
BIC_PRESENT(BIC_RAM__);
@@ -3923,7 +3942,7 @@ void rapl_probe_intel(unsigned int family, unsigned int model)
}
break;
case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */
- case INTEL_FAM6_ATOM_SILVERMONT_X: /* AVN */
+ case INTEL_FAM6_ATOM_SILVERMONT_D: /* AVN */
do_rapl = RAPL_PKG | RAPL_CORES;
if (rapl_joules) {
BIC_PRESENT(BIC_Pkg_J);
@@ -3933,7 +3952,7 @@ void rapl_probe_intel(unsigned int family, unsigned int model)
BIC_PRESENT(BIC_CorWatt);
}
break;
- case INTEL_FAM6_ATOM_GOLDMONT_X: /* DNV */
+ 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;
BIC_PRESENT(BIC_PKG__);
BIC_PRESENT(BIC_RAM__);
@@ -3994,6 +4013,7 @@ void rapl_probe_amd(unsigned int family, unsigned int model)
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);
@@ -4014,7 +4034,7 @@ void rapl_probe_amd(unsigned int family, unsigned int model)
rapl_energy_units = ldexp(1.0, -(msr >> 8 & 0x1f));
rapl_power_units = ldexp(1.0, -(msr & 0xf));
- tdp = get_tdp_amd(model);
+ tdp = get_tdp_amd(family);
rapl_joule_counter_range = 0xFFFFFFFF * rapl_energy_units / tdp;
if (!quiet)
@@ -4030,7 +4050,7 @@ void rapl_probe(unsigned int family, unsigned int model)
{
if (genuine_intel)
rapl_probe_intel(family, model);
- if (authentic_amd)
+ if (authentic_amd || hygon_genuine)
rapl_probe_amd(family, model);
}
@@ -4043,8 +4063,9 @@ void perf_limit_reasons_probe(unsigned int family, unsigned int model)
return;
switch (model) {
- case INTEL_FAM6_HASWELL_CORE: /* HSW */
- case INTEL_FAM6_HASWELL_GT3E: /* HSW */
+ case INTEL_FAM6_HASWELL: /* HSW */
+ case INTEL_FAM6_HASWELL_L: /* HSW */
+ case INTEL_FAM6_HASWELL_G: /* HSW */
do_gfx_perf_limit_reasons = 1;
case INTEL_FAM6_HASWELL_X: /* HSX */
do_core_perf_limit_reasons = 1;
@@ -4259,27 +4280,28 @@ int has_snb_msrs(unsigned int family, unsigned int model)
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_CORE: /* HSW */
- case INTEL_FAM6_HASWELL_X: /* HSW */
- case INTEL_FAM6_HASWELL_GT3E: /* HSW */
- case INTEL_FAM6_BROADWELL_CORE: /* BDW */
- case INTEL_FAM6_BROADWELL_GT3E: /* BDW */
- case INTEL_FAM6_BROADWELL_X: /* BDX */
- case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */
- case INTEL_FAM6_CANNONLAKE_MOBILE: /* 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_ATOM_GOLDMONT: /* BXT */
case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
- case INTEL_FAM6_ATOM_GOLDMONT_X: /* DNV */
+ case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */
return 1;
}
return 0;
}
/*
- * HSW adds support for additional MSRs:
+ * HSW ULT added support for C8/C9/C10 MSRs:
*
* MSR_PKG_C8_RESIDENCY 0x00000630
* MSR_PKG_C9_RESIDENCY 0x00000631
@@ -4290,16 +4312,16 @@ int has_snb_msrs(unsigned int family, unsigned int model)
* MSR_PKGC10_IRTL 0x00000635
*
*/
-int has_hsw_msrs(unsigned int family, unsigned int model)
+int has_c8910_msrs(unsigned int family, unsigned int model)
{
if (!genuine_intel)
return 0;
switch (model) {
- case INTEL_FAM6_HASWELL_CORE:
- case INTEL_FAM6_BROADWELL_CORE: /* BDW */
- case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */
- case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */
+ case INTEL_FAM6_HASWELL_L: /* HSW */
+ case INTEL_FAM6_BROADWELL: /* BDW */
+ case INTEL_FAM6_SKYLAKE_L: /* SKL */
+ case INTEL_FAM6_CANNONLAKE_L: /* CNL */
case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
return 1;
@@ -4321,8 +4343,8 @@ int has_skl_msrs(unsigned int family, unsigned int model)
return 0;
switch (model) {
- case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */
- case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */
+ case INTEL_FAM6_SKYLAKE_L: /* SKL */
+ case INTEL_FAM6_CANNONLAKE_L: /* CNL */
return 1;
}
return 0;
@@ -4334,7 +4356,7 @@ int is_slm(unsigned int family, unsigned int model)
return 0;
switch (model) {
case INTEL_FAM6_ATOM_SILVERMONT: /* BYT */
- case INTEL_FAM6_ATOM_SILVERMONT_X: /* AVN */
+ case INTEL_FAM6_ATOM_SILVERMONT_D: /* AVN */
return 1;
}
return 0;
@@ -4357,7 +4379,7 @@ int is_cnl(unsigned int family, unsigned int model)
return 0;
switch (model) {
- case INTEL_FAM6_CANNONLAKE_MOBILE: /* CNL */
+ case INTEL_FAM6_CANNONLAKE_L: /* CNL */
return 1;
}
@@ -4580,21 +4602,22 @@ unsigned int intel_model_duplicates(unsigned int model)
case INTEL_FAM6_XEON_PHI_KNM:
return INTEL_FAM6_XEON_PHI_KNL;
- case INTEL_FAM6_HASWELL_ULT:
- return INTEL_FAM6_HASWELL_CORE;
-
case INTEL_FAM6_BROADWELL_X:
- case INTEL_FAM6_BROADWELL_XEON_D: /* BDX-DE */
+ case INTEL_FAM6_BROADWELL_D: /* BDX-DE */
return INTEL_FAM6_BROADWELL_X;
- case INTEL_FAM6_SKYLAKE_MOBILE:
- case INTEL_FAM6_SKYLAKE_DESKTOP:
- case INTEL_FAM6_KABYLAKE_MOBILE:
- case INTEL_FAM6_KABYLAKE_DESKTOP:
- return INTEL_FAM6_SKYLAKE_MOBILE;
+ case INTEL_FAM6_SKYLAKE_L:
+ case INTEL_FAM6_SKYLAKE:
+ case INTEL_FAM6_KABYLAKE_L:
+ case INTEL_FAM6_KABYLAKE:
+ return INTEL_FAM6_SKYLAKE_L;
+
+ case INTEL_FAM6_ICELAKE_L:
+ case INTEL_FAM6_ICELAKE_NNPI:
+ return INTEL_FAM6_CANNONLAKE_L;
- case INTEL_FAM6_ICELAKE_MOBILE:
- return INTEL_FAM6_CANNONLAKE_MOBILE;
+ case INTEL_FAM6_ATOM_TREMONT_D:
+ return INTEL_FAM6_ATOM_GOLDMONT_D;
}
return model;
}
@@ -4612,6 +4635,8 @@ void process_cpuid()
genuine_intel = 1;
else if (ebx == 0x68747541 && ecx == 0x444d4163 && edx == 0x69746e65)
authentic_amd = 1;
+ else if (ebx == 0x6f677948 && ecx == 0x656e6975 && edx == 0x6e65476e)
+ hygon_genuine = 1;
if (!quiet)
fprintf(outf, "CPUID(0): %.4s%.4s%.4s ",
@@ -4743,10 +4768,10 @@ void process_cpuid()
if (crystal_hz == 0)
switch(model) {
- case INTEL_FAM6_SKYLAKE_MOBILE: /* SKL */
+ case INTEL_FAM6_SKYLAKE_L: /* SKL */
crystal_hz = 24000000; /* 24.0 MHz */
break;
- case INTEL_FAM6_ATOM_GOLDMONT_X: /* DNV */
+ case INTEL_FAM6_ATOM_GOLDMONT_D: /* DNV */
crystal_hz = 25000000; /* 25.0 MHz */
break;
case INTEL_FAM6_ATOM_GOLDMONT: /* BXT */
@@ -4832,12 +4857,12 @@ void process_cpuid()
BIC_NOT_PRESENT(BIC_CPU_c7);
BIC_NOT_PRESENT(BIC_Pkgpc7);
}
- if (has_hsw_msrs(family, model)) {
+ if (has_c8910_msrs(family, model)) {
BIC_PRESENT(BIC_Pkgpc8);
BIC_PRESENT(BIC_Pkgpc9);
BIC_PRESENT(BIC_Pkgpc10);
}
- do_irtl_hsw = has_hsw_msrs(family, model);
+ do_irtl_hsw = has_c8910_msrs(family, model);
if (has_skl_msrs(family, model)) {
BIC_PRESENT(BIC_Totl_c0);
BIC_PRESENT(BIC_Any_c0);
@@ -5135,7 +5160,7 @@ int initialize_counters(int cpu_id)
void allocate_output_buffer()
{
- output_buffer = calloc(1, (1 + topo.num_cpus) * 1024);
+ output_buffer = calloc(1, (1 + topo.num_cpus) * 2048);
outp = output_buffer;
if (outp == NULL)
err(-1, "calloc output buffer");
@@ -5281,7 +5306,7 @@ int get_and_dump_counters(void)
}
void print_version() {
- fprintf(outf, "turbostat version 19.03.20"
+ fprintf(outf, "turbostat version 19.08.31"
" - Len Brown <lenb@kernel.org>\n");
}
diff --git a/tools/power/x86/x86_energy_perf_policy/Makefile b/tools/power/x86/x86_energy_perf_policy/Makefile
index ae7a0e09b722..666b325a62a2 100644
--- a/tools/power/x86/x86_energy_perf_policy/Makefile
+++ b/tools/power/x86/x86_energy_perf_policy/Makefile
@@ -9,8 +9,9 @@ ifeq ("$(origin O)", "command line")
endif
x86_energy_perf_policy : x86_energy_perf_policy.c
-override CFLAGS += -Wall
+override CFLAGS += -O2 -Wall -I../../../include
override CFLAGS += -DMSRHEADER='"../../../../arch/x86/include/asm/msr-index.h"'
+override CFLAGS += -D_FORTIFY_SOURCE=2
%: %.c
@mkdir -p $(BUILD_OUTPUT)
diff --git a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8 b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8
index 17db1c3af4d0..78c6361898b1 100644
--- a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8
+++ b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.8
@@ -40,7 +40,7 @@ in the same processor package.
Hardware P-States (HWP) are effectively an expansion of hardware
P-state control from the opportunistic turbo-mode P-state range
to include the entire range of available P-states.
-On Broadwell Xeon, the initial HWP implementation, EBP influenced HWP.
+On Broadwell Xeon, the initial HWP implementation, EPB influenced HWP.
That influence was removed in subsequent generations,
where it was moved to the
Energy_Performance_Preference (EPP) field in
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 65bbe627a425..3fe1eed900d4 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
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* x86_energy_perf_policy -- set the energy versus performance
* policy preference bias on recent X86 processors.
@@ -5,8 +6,6 @@
/*
* Copyright (c) 2010 - 2017 Intel Corporation.
* Len Brown <len.brown@intel.com>
- *
- * This program is released under GPL v2
*/
#define _GNU_SOURCE
@@ -546,7 +545,7 @@ void cmdline(int argc, char **argv)
progname = argv[0];
- while ((opt = getopt_long_only(argc, argv, "+a:c:dD:E:e:f:m:M:rt:u:vw",
+ while ((opt = getopt_long_only(argc, argv, "+a:c:dD:E:e:f:m:M:rt:u:vw:",
long_options, &option_index)) != -1) {
switch (opt) {
case 'a':
@@ -1260,6 +1259,15 @@ void probe_dev_msr(void)
if (system("/sbin/modprobe msr > /dev/null 2>&1"))
err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" ");
}
+
+static void get_cpuid_or_exit(unsigned int leaf,
+ unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx)
+{
+ if (!__get_cpuid(leaf, eax, ebx, ecx, edx))
+ errx(1, "Processor not supported\n");
+}
+
/*
* early_cpuid()
* initialize turbo_is_enabled, has_hwp, has_epb
@@ -1267,15 +1275,10 @@ void probe_dev_msr(void)
*/
void early_cpuid(void)
{
- unsigned int eax, ebx, ecx, edx, max_level;
+ unsigned int eax, ebx, ecx, edx;
unsigned int fms, family, model;
- __get_cpuid(0, &max_level, &ebx, &ecx, &edx);
-
- if (max_level < 6)
- errx(1, "Processor not supported\n");
-
- __get_cpuid(1, &fms, &ebx, &ecx, &edx);
+ get_cpuid_or_exit(1, &fms, &ebx, &ecx, &edx);
family = (fms >> 8) & 0xf;
model = (fms >> 4) & 0xf;
if (family == 6 || family == 0xf)
@@ -1289,7 +1292,7 @@ void early_cpuid(void)
bdx_highest_ratio = msr & 0xFF;
}
- __get_cpuid(0x6, &eax, &ebx, &ecx, &edx);
+ get_cpuid_or_exit(0x6, &eax, &ebx, &ecx, &edx);
turbo_is_enabled = (eax >> 1) & 1;
has_hwp = (eax >> 7) & 1;
has_epb = (ecx >> 3) & 1;
@@ -1307,7 +1310,7 @@ void parse_cpuid(void)
eax = ebx = ecx = edx = 0;
- __get_cpuid(0, &max_level, &ebx, &ecx, &edx);
+ get_cpuid_or_exit(0, &max_level, &ebx, &ecx, &edx);
if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e)
genuine_intel = 1;
@@ -1316,7 +1319,7 @@ void parse_cpuid(void)
fprintf(stderr, "CPUID(0): %.4s%.4s%.4s ",
(char *)&ebx, (char *)&edx, (char *)&ecx);
- __get_cpuid(1, &fms, &ebx, &ecx, &edx);
+ get_cpuid_or_exit(1, &fms, &ebx, &ecx, &edx);
family = (fms >> 8) & 0xf;
model = (fms >> 4) & 0xf;
stepping = fms & 0xf;
@@ -1341,7 +1344,7 @@ void parse_cpuid(void)
errx(1, "CPUID: no MSR");
- __get_cpuid(0x6, &eax, &ebx, &ecx, &edx);
+ get_cpuid_or_exit(0x6, &eax, &ebx, &ecx, &edx);
/* turbo_is_enabled already set */
/* has_hwp already set */
has_hwp_notify = eax & (1 << 8);
OpenPOWER on IntegriCloud