[PATCH 5/5] cpupowerutils: Introduce -b/-t --boost/--turbo cpufreq-info param

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Prints out this by default (also works with --cpu X param):
  Analyzing Boost Capabilities on CPU 0:
  Supported: yes
  Active: yes

With activation one has to be careful...
On AMD, it's enough if any of the CPUs shows "Active: no" and boost mode
is not active (cmp with powernow-k8 kernel code).

Not exactly sure how this works on Intel,
Intel 64 and IA-32 Architectures Software Developerâs Manual
Volume 3A, System Programming Guide, Part 1
14.3.2.2 OS Control of Opportunistic Processor Performance Operation
says:
------
The DISENAGE bit in IA32_PERF_CTL (..) is not shared between logical
processors in a physical package.
------
So it sounds as if boost mode can get disabled on every processor
socket, or even more fine grained?

Possible further enhancements:
   cpufreq-set --turbo_active (or similar)
to enable/disable turbo/boost mode.

For AMD there already is:
/sys/devices/system/cpu/cpu0/cpufreq/cpb
but this could all get handled in userspace and this recently introduced
interface could get removed again.
Then enabling/disabling could all be done on CPU 0 which cannot be taken
offline.
  -> To be discussed.

For Intel, some input about which other cores are affected by disabling
boost mode on a specific core is needed.
  -> To be discussed.

Potentially dangerous is if cores get offlined while boost mode got disbled,
then the userspace tool would not be able to enable it again.
But as this stuff is meant for debugging and performance measuring only,
it should be enough to document this a bit in a manpage...


Signed-off-by: Thomas Renninger <trenn@xxxxxxx>
CC: Dominik Brodowski <linux@xxxxxxxxxxxxxxxxxxxx>
CC: cpufreq@xxxxxxxxxxxxxxx
CC: Borislav Petkov <borislav.petkov@xxxxxxx>
CC: Len Brown <len.brown@xxxxxxxxx>
---
 lib/cpufreq.c        |   37 +++++++++++++++++++++++++++++++++++++
 lib/cpufreq.h        |    8 ++++++++
 lib/msr.c            |   37 +++++++++++++++++++++++++++++++++++++
 lib/msr.h            |    5 +++++
 utils/cpufreq-info.c |   29 ++++++++++++++++++++++++++++-
 5 files changed, 115 insertions(+), 1 deletions(-)

diff --git a/lib/cpufreq.c b/lib/cpufreq.c
index ae7d8c5..0b5fe9f 100644
--- a/lib/cpufreq.c
+++ b/lib/cpufreq.c
@@ -12,6 +12,8 @@
 
 #include "cpufreq.h"
 #include "sysfs.h"
+#include "cpuid.h"
+#include "msr.h"
 
 int cpufreq_cpu_exists(unsigned int cpu)
 {
@@ -188,3 +190,38 @@ unsigned long cpufreq_get_transitions(unsigned int cpu) {
 
 	return (ret);
 }
+
+int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active)
+{
+	struct cpupower_cpu_info cpu_info;
+	int ret;
+
+	*support = *active = 0;
+
+	ret = get_cpu_info(0, &cpu_info);
+	if (ret)
+		return ret;
+
+	if (cpu_info.vendor == X86_VENDOR_INTEL) {
+		ret = msr_intel_has_boost_support(cpu);
+		if (ret <= 0)
+			return ret;
+		*support = ret;
+		ret = msr_intel_boost_is_active(cpu);
+		if (ret <= 0)
+			return ret;
+		*active = ret;
+	} else if (cpu_info.vendor == X86_VENDOR_AMD) {
+		if (cpu_info.ext_cpuid_level < 0x80000007)
+			return 0;
+		if ((cpuid_edx(0x80000007) >> 9) & 0x1)
+			*support = 1;
+		else
+			return 0;
+		ret = msr_amd_boost_is_active(cpu);
+		if (ret <= 0)
+			return ret;
+		*active = ret;
+	}
+	return 0;
+}
diff --git a/lib/cpufreq.h b/lib/cpufreq.h
index 03be906..506b6fc 100644
--- a/lib/cpufreq.h
+++ b/lib/cpufreq.h
@@ -208,6 +208,14 @@ extern int cpufreq_modify_policy_governor(unsigned int cpu, char *governor);
 
 extern int cpufreq_set_frequency(unsigned int cpu, unsigned long target_frequency);
 
+/* get boost mode support/activation
+ *
+ * Check whether Intel's "Turbo Boost Technology" or AMD's
+ * "Dynamic Speed Boost Technology" is supported and if, whether it's activated
+ */
+extern int cpufreq_has_boost_support(unsigned int cpu, int *support, int *active);
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/msr.c b/lib/msr.c
index bccea8d..9921ff1 100644
--- a/lib/msr.c
+++ b/lib/msr.c
@@ -18,6 +18,8 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#define MSR_IA32_MISC_ENABLES	0x1a0
+
 
 /* General X86 MSRs */
 #define MSR_IA32_APERF		0x000000E8
@@ -25,9 +27,11 @@
 
 /* AMD specific MSRs */
 #define MSR_FIDVID_STATUS	0xc0010042
+#define MSR_K7_HWCR		0xc0010015
 
 /* Intel specific MSRs */
 #define MSR_IA32_PERF_STATUS	0x198
+#define MSR_IA32_MISC_ENABLES	0x1a0
 
 /* AMD specific bits */
 #define AMD_S_HI_CURRENT_VID	0x0000001f
@@ -123,8 +127,41 @@ int msr_amd_get_fidvid(unsigned int cpu, uint32_t *fid, uint32_t *vid)
 	return 0;
 }
 
+int msr_amd_boost_is_active(unsigned int cpu)
+{
+	uint64_t k7_hwcr;
+	int ret;
+
+	ret = read_msr(cpu, MSR_K7_HWCR, &k7_hwcr);
+	if (ret)
+		return ret;
+	return !((k7_hwcr >> 25) & 0x1);
+}
+
 /* Intel X86 MSRs **********************************/
 int msr_intel_get_perf_status(unsigned int cpu, uint64_t perf_status)
 {
        return read_msr(cpu, MSR_IA32_PERF_STATUS, &perf_status);
 }
+
+int msr_intel_has_boost_support(unsigned int cpu)
+{
+	uint64_t misc_enables;
+	int ret;
+
+	ret = read_msr(cpu, MSR_IA32_MISC_ENABLES, &misc_enables);
+	if (ret)
+		return ret;
+	return (misc_enables >> 38) & 0x1;
+}
+
+int msr_intel_boost_is_active(unsigned int cpu)
+{
+	uint64_t perf_status;
+	int ret;
+
+	ret = read_msr(cpu, MSR_IA32_PERF_STATUS, &perf_status);
+	if (ret)
+		return ret;
+	return (perf_status >> 32) & 0x1;
+}
diff --git a/lib/msr.h b/lib/msr.h
index 8b1755e..6b743ce 100644
--- a/lib/msr.h
+++ b/lib/msr.h
@@ -3,3 +3,8 @@ extern int msr_get_aperf(unsigned int cpu, uint64_t *aperf);
 
 extern int msr_amd_get_fidvid(unsigned int cpu, uint32_t *fid, uint32_t *vid);
 extern int msr_intel_get_perf_status(unsigned int cpu, uint64_t perf_status);
+
+extern int msr_intel_has_boost_support(unsigned int cpu);
+extern int msr_intel_boost_is_active(unsigned int cpu);
+
+extern int msr_amd_boost_is_active(unsigned int cpu);
diff --git a/utils/cpufreq-info.c b/utils/cpufreq-info.c
index 38d906a..be0c9e3 100644
--- a/utils/cpufreq-info.c
+++ b/utils/cpufreq-info.c
@@ -16,6 +16,7 @@
 #include <getopt.h>
 
 #include "cpufreq.h"
+#include "cpuid.h"
 
 
 #define _(String) gettext (String)
@@ -286,6 +287,24 @@ static void debug_output(unsigned int cpu, unsigned int all) {
 		debug_output_one(cpu);
 }
 
+/* --boost / -b */
+
+static int get_boost_mode(unsigned int cpu) {
+	int support, active, ret;
+
+	ret = cpufreq_has_boost_support(cpu, &support, &active);
+	if (ret) {
+		printf(gettext ("Error while evaluating Boost Capabilities"
+				" on CPU %d:\n"), cpu);
+		return ret;
+	}
+
+      	printf(gettext ("Analyzing Boost Capabilities on CPU %d:\n"), cpu);
+	printf("Supported: %s\n", support ? "yes" : "no");
+	printf("Active: %s\n", active ? "yes" : "no");
+
+	return 0;
+}
 
 /* --freq / -f */
 
@@ -473,6 +492,8 @@ static void print_help(void) {
 static struct option info_opts[] = {
 	{ .name="cpu",		.has_arg=required_argument,	.flag=NULL,	.val='c'},
 	{ .name="debug",	.has_arg=no_argument,		.flag=NULL,	.val='e'},
+	{ .name="turbo",	.has_arg=no_argument,		.flag=NULL,	.val='t'},
+	{ .name="boost",	.has_arg=no_argument,		.flag=NULL,	.val='b'},
 	{ .name="freq",		.has_arg=no_argument,		.flag=NULL,	.val='f'},
 	{ .name="hwfreq",	.has_arg=no_argument,		.flag=NULL,	.val='w'},
 	{ .name="hwlimits",	.has_arg=no_argument,		.flag=NULL,	.val='l'},
@@ -501,7 +522,7 @@ int main(int argc, char **argv) {
 	textdomain (PACKAGE);
 
 	do {
-		ret = getopt_long(argc, argv, "c:hoefwldpgrasmy", info_opts, NULL);
+		ret = getopt_long(argc, argv, "c:hoefwldpgrasmytb", info_opts, NULL);
 		switch (ret) {
 		case '?':
 			output_param = '?';
@@ -514,6 +535,8 @@ int main(int argc, char **argv) {
 		case -1:
 			cont = 0;
 			break;
+		case 't':
+		case 'b':
 		case 'o':
 		case 'a':
 		case 'r':
@@ -587,6 +610,10 @@ int main(int argc, char **argv) {
 		print_header();
 		print_help();
 		break;
+	case 't':
+	case 'b':
+		get_boost_mode(cpu);
+		break;
 	case 'o':
 		proc_cpufreq_output();
 		break;
-- 
1.6.4.2

--
To unsubscribe from this list: send the line "unsubscribe cpufreq" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Devel]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Forum]     [Linux SCSI]

  Powered by Linux