mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] perf/x86/msr: add support for MSR_IA32_THERM_STATUS
@ 2018-01-05 16:18 Stephane Eranian
  2018-01-06 11:53 ` [tip:perf/core] perf/x86/msr: Add " tip-bot for Stephane Eranian
  2018-01-06 11:54 ` [tip:perf/core] perf/x86/msr: Clean up the code tip-bot for Ingo Molnar
  0 siblings, 2 replies; 3+ messages in thread
From: Stephane Eranian @ 2018-01-05 16:18 UTC (permalink / raw)
  To: linux-kernel; +Cc: acme, peterz, mingo, ak, kan.liang

This patch adds support for the Digital Readout provided by the
IA32_THERM_STATUS MSR (0x19C) on Intel X86 processors. The readout
shows the number of degrees Celcius to the TCC (critical temperature)
supported by the processor. Thus, the larger, the better.

The perf_event support is provided via the msr PMU. The new
logical event is called cpu_thermal_margin. It comes with a unit and
snapshot files. The event shows the current temprature distance (margin).
It is not an accumulating event. The unit is degree C. The event
is provided per logical CPU to make things simpler but it is the
same for both hyper-threads sharing a physical core.

$ perf stat -I 1000 -a -A -e msr/cpu_thermal_margin/

This will print the temperature for all logical CPUs.
             time CPU                counts unit events
     1.000123741 CPU0                    38 C    msr/cpu_thermal_margin/
     1.000161837 CPU1                    37 C    msr/cpu_thermal_margin/
     1.000187906 CPU2                    36 C    msr/cpu_thermal_margin/
     1.000189046 CPU3                    39 C    msr/cpu_thermal_margin/
     1.000283044 CPU4                    40 C    msr/cpu_thermal_margin/
     1.000344297 CPU5                    40 C    msr/cpu_thermal_margin/
     1.000365832 CPU6                    39 C    msr/cpu_thermal_margin/
     ...

In case the temperature margin cannot be read, the reported value would be -1.

Works on all processors supporting the Digital Readout (dtherm in cpuinfo)

Signed-off-by: Stephane Eranian <eranian@google.com>

---
 arch/x86/events/msr.c | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/arch/x86/events/msr.c b/arch/x86/events/msr.c
index 14efaa0e8684..0be15b9b2376 100644
--- a/arch/x86/events/msr.c
+++ b/arch/x86/events/msr.c
@@ -10,7 +10,9 @@ enum perf_msr_id {
 	PERF_MSR_SMI			= 4,
 	PERF_MSR_PTSC			= 5,
 	PERF_MSR_IRPERF			= 6,
-
+	PERF_MSR_THERM			= 7,
+	PERF_MSR_THERM_SNAP		= 8,
+	PERF_MSR_THERM_UNIT		= 9,
 	PERF_MSR_EVENT_MAX,
 };
 
@@ -29,6 +31,12 @@ static bool test_irperf(int idx)
 	return boot_cpu_has(X86_FEATURE_IRPERF);
 }
 
+static bool test_therm_status(int idx)
+{
+	return boot_cpu_has(X86_FEATURE_DTHERM);
+}
+
+
 static bool test_intel(int idx)
 {
 	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
@@ -102,6 +110,9 @@ PMU_EVENT_ATTR_STRING(pperf,  evattr_pperf,  "event=0x03");
 PMU_EVENT_ATTR_STRING(smi,    evattr_smi,    "event=0x04");
 PMU_EVENT_ATTR_STRING(ptsc,   evattr_ptsc,   "event=0x05");
 PMU_EVENT_ATTR_STRING(irperf, evattr_irperf, "event=0x06");
+PMU_EVENT_ATTR_STRING(cpu_thermal_margin, evattr_therm, "event=0x07");
+PMU_EVENT_ATTR_STRING(cpu_thermal_margin.snapshot, evattr_therm_snap, "1");
+PMU_EVENT_ATTR_STRING(cpu_thermal_margin.unit, evattr_therm_unit, "C");
 
 static struct perf_msr msr[] = {
 	[PERF_MSR_TSC]    = { 0,		&evattr_tsc,	NULL,		 },
@@ -111,6 +122,9 @@ static struct perf_msr msr[] = {
 	[PERF_MSR_SMI]    = { MSR_SMI_COUNT,	&evattr_smi,	test_intel,	 },
 	[PERF_MSR_PTSC]   = { MSR_F15H_PTSC,	&evattr_ptsc,	test_ptsc,	 },
 	[PERF_MSR_IRPERF] = { MSR_F17H_IRPERF,	&evattr_irperf,	test_irperf,	 },
+	[PERF_MSR_THERM] = { MSR_IA32_THERM_STATUS, &evattr_therm,	     test_therm_status, },
+	[PERF_MSR_THERM_SNAP] = { MSR_IA32_THERM_STATUS, &evattr_therm_snap, test_therm_status, },
+	[PERF_MSR_THERM_UNIT] = { MSR_IA32_THERM_STATUS, &evattr_therm_unit, test_therm_status, },
 };
 
 static struct attribute *events_attrs[PERF_MSR_EVENT_MAX + 1] = {
@@ -193,10 +207,15 @@ static void msr_event_update(struct perf_event *event)
 		goto again;
 
 	delta = now - prev;
-	if (unlikely(event->hw.event_base == MSR_SMI_COUNT))
+	if (unlikely(event->hw.event_base == MSR_SMI_COUNT)) {
 		delta = sign_extend64(delta, 31);
-
-	local64_add(delta, &event->count);
+		local64_add(delta, &event->count);
+	} else if (unlikely(event->hw.event_base == MSR_IA32_THERM_STATUS)) {
+		/* if valid, extract digital readout, other set to -1 */
+		now = now & (1ULL << 31) ? (now >> 16) & 0x3f :  -1;
+		local64_set(&event->count, now);
+	} else
+		local64_add(delta, &event->count);
 }
 
 static void msr_event_start(struct perf_event *event, int flags)
-- 
2.7.4

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [tip:perf/core] perf/x86/msr: Add support for MSR_IA32_THERM_STATUS
  2018-01-05 16:18 [PATCH] perf/x86/msr: add support for MSR_IA32_THERM_STATUS Stephane Eranian
@ 2018-01-06 11:53 ` tip-bot for Stephane Eranian
  2018-01-06 11:54 ` [tip:perf/core] perf/x86/msr: Clean up the code tip-bot for Ingo Molnar
  1 sibling, 0 replies; 3+ messages in thread
From: tip-bot for Stephane Eranian @ 2018-01-06 11:53 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, jolsa, tglx, torvalds, peterz, acme,
	alexander.shishkin, hpa, mingo, eranian, vincent.weaver

Commit-ID:  9ae21dd66b970b5e3192a636353d75ede0529338
Gitweb:     https://git.kernel.org/tip/9ae21dd66b970b5e3192a636353d75ede0529338
Author:     Stephane Eranian <eranian@google.com>
AuthorDate: Fri, 5 Jan 2018 08:18:52 -0800
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Sat, 6 Jan 2018 12:17:39 +0100

perf/x86/msr: Add support for MSR_IA32_THERM_STATUS

This patch adds support for the Digital Readout provided by the
IA32_THERM_STATUS MSR (0x19C) on Intel X86 processors. The readout
shows the number of degrees Celcius to the TCC (critical temperature)
supported by the processor. Thus, the larger, the better.

The perf_event support is provided via the msr PMU. The new
logical event is called cpu_thermal_margin. It comes with a unit and
snapshot files. The event shows the current temprature distance (margin).
It is not an accumulating event. The unit is degrees C. The event
is provided per logical CPU to make things simpler but it is the
same for both hyper-threads sharing a physical core.

$ perf stat -I 1000 -a -A -e msr/cpu_thermal_margin/

This will print the temperature for all logical CPUs.
             time CPU                counts unit events
     1.000123741 CPU0                    38 C    msr/cpu_thermal_margin/
     1.000161837 CPU1                    37 C    msr/cpu_thermal_margin/
     1.000187906 CPU2                    36 C    msr/cpu_thermal_margin/
     1.000189046 CPU3                    39 C    msr/cpu_thermal_margin/
     1.000283044 CPU4                    40 C    msr/cpu_thermal_margin/
     1.000344297 CPU5                    40 C    msr/cpu_thermal_margin/
     1.000365832 CPU6                    39 C    msr/cpu_thermal_margin/
     ...

In case the temperature margin cannot be read, the reported value would be -1.

Works on all processors supporting the Digital Readout (dtherm in cpuinfo)

Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Cc: kan.liang@intel.com
Link: http://lkml.kernel.org/r/1515169132-3980-1-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/events/msr.c | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/arch/x86/events/msr.c b/arch/x86/events/msr.c
index 14efaa0..0be15b9 100644
--- a/arch/x86/events/msr.c
+++ b/arch/x86/events/msr.c
@@ -10,7 +10,9 @@ enum perf_msr_id {
 	PERF_MSR_SMI			= 4,
 	PERF_MSR_PTSC			= 5,
 	PERF_MSR_IRPERF			= 6,
-
+	PERF_MSR_THERM			= 7,
+	PERF_MSR_THERM_SNAP		= 8,
+	PERF_MSR_THERM_UNIT		= 9,
 	PERF_MSR_EVENT_MAX,
 };
 
@@ -29,6 +31,12 @@ static bool test_irperf(int idx)
 	return boot_cpu_has(X86_FEATURE_IRPERF);
 }
 
+static bool test_therm_status(int idx)
+{
+	return boot_cpu_has(X86_FEATURE_DTHERM);
+}
+
+
 static bool test_intel(int idx)
 {
 	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
@@ -102,6 +110,9 @@ PMU_EVENT_ATTR_STRING(pperf,  evattr_pperf,  "event=0x03");
 PMU_EVENT_ATTR_STRING(smi,    evattr_smi,    "event=0x04");
 PMU_EVENT_ATTR_STRING(ptsc,   evattr_ptsc,   "event=0x05");
 PMU_EVENT_ATTR_STRING(irperf, evattr_irperf, "event=0x06");
+PMU_EVENT_ATTR_STRING(cpu_thermal_margin, evattr_therm, "event=0x07");
+PMU_EVENT_ATTR_STRING(cpu_thermal_margin.snapshot, evattr_therm_snap, "1");
+PMU_EVENT_ATTR_STRING(cpu_thermal_margin.unit, evattr_therm_unit, "C");
 
 static struct perf_msr msr[] = {
 	[PERF_MSR_TSC]    = { 0,		&evattr_tsc,	NULL,		 },
@@ -111,6 +122,9 @@ static struct perf_msr msr[] = {
 	[PERF_MSR_SMI]    = { MSR_SMI_COUNT,	&evattr_smi,	test_intel,	 },
 	[PERF_MSR_PTSC]   = { MSR_F15H_PTSC,	&evattr_ptsc,	test_ptsc,	 },
 	[PERF_MSR_IRPERF] = { MSR_F17H_IRPERF,	&evattr_irperf,	test_irperf,	 },
+	[PERF_MSR_THERM] = { MSR_IA32_THERM_STATUS, &evattr_therm,	     test_therm_status, },
+	[PERF_MSR_THERM_SNAP] = { MSR_IA32_THERM_STATUS, &evattr_therm_snap, test_therm_status, },
+	[PERF_MSR_THERM_UNIT] = { MSR_IA32_THERM_STATUS, &evattr_therm_unit, test_therm_status, },
 };
 
 static struct attribute *events_attrs[PERF_MSR_EVENT_MAX + 1] = {
@@ -193,10 +207,15 @@ again:
 		goto again;
 
 	delta = now - prev;
-	if (unlikely(event->hw.event_base == MSR_SMI_COUNT))
+	if (unlikely(event->hw.event_base == MSR_SMI_COUNT)) {
 		delta = sign_extend64(delta, 31);
-
-	local64_add(delta, &event->count);
+		local64_add(delta, &event->count);
+	} else if (unlikely(event->hw.event_base == MSR_IA32_THERM_STATUS)) {
+		/* if valid, extract digital readout, other set to -1 */
+		now = now & (1ULL << 31) ? (now >> 16) & 0x3f :  -1;
+		local64_set(&event->count, now);
+	} else
+		local64_add(delta, &event->count);
 }
 
 static void msr_event_start(struct perf_event *event, int flags)

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [tip:perf/core] perf/x86/msr: Clean up the code
  2018-01-05 16:18 [PATCH] perf/x86/msr: add support for MSR_IA32_THERM_STATUS Stephane Eranian
  2018-01-06 11:53 ` [tip:perf/core] perf/x86/msr: Add " tip-bot for Stephane Eranian
@ 2018-01-06 11:54 ` tip-bot for Ingo Molnar
  1 sibling, 0 replies; 3+ messages in thread
From: tip-bot for Ingo Molnar @ 2018-01-06 11:54 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: jolsa, linux-kernel, mingo, hpa, acme, tglx, peterz,
	alexander.shishkin, torvalds, eranian, vincent.weaver

Commit-ID:  9128d3ed9de3882c83b927eb553d5d44c84505f5
Gitweb:     https://git.kernel.org/tip/9128d3ed9de3882c83b927eb553d5d44c84505f5
Author:     Ingo Molnar <mingo@kernel.org>
AuthorDate: Fri, 5 Jan 2018 08:18:52 -0800
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Sat, 6 Jan 2018 12:18:40 +0100

perf/x86/msr: Clean up the code

Recent changes made a bit of an inconsistent mess out of arch/x86/events/msr.c,
fix it:

 - re-align the initialization tables to be vertically aligned and readable again

 - harmonize comment style in terms of punctuation, capitalization and spelling

 - use curly braces for multi-condition branches

 - remove extra newlines

 - simplify the code a bit

Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Cc: kan.liang@intel.com
Link: http://lkml.kernel.org/r/1515169132-3980-1-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/events/msr.c | 61 ++++++++++++++++++++++++---------------------------
 1 file changed, 29 insertions(+), 32 deletions(-)

diff --git a/arch/x86/events/msr.c b/arch/x86/events/msr.c
index 0be15b9..18e2628 100644
--- a/arch/x86/events/msr.c
+++ b/arch/x86/events/msr.c
@@ -36,7 +36,6 @@ static bool test_therm_status(int idx)
 	return boot_cpu_has(X86_FEATURE_DTHERM);
 }
 
-
 static bool test_intel(int idx)
 {
 	if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
@@ -103,28 +102,28 @@ struct perf_msr {
 	bool	(*test)(int idx);
 };
 
-PMU_EVENT_ATTR_STRING(tsc,    evattr_tsc,    "event=0x00");
-PMU_EVENT_ATTR_STRING(aperf,  evattr_aperf,  "event=0x01");
-PMU_EVENT_ATTR_STRING(mperf,  evattr_mperf,  "event=0x02");
-PMU_EVENT_ATTR_STRING(pperf,  evattr_pperf,  "event=0x03");
-PMU_EVENT_ATTR_STRING(smi,    evattr_smi,    "event=0x04");
-PMU_EVENT_ATTR_STRING(ptsc,   evattr_ptsc,   "event=0x05");
-PMU_EVENT_ATTR_STRING(irperf, evattr_irperf, "event=0x06");
-PMU_EVENT_ATTR_STRING(cpu_thermal_margin, evattr_therm, "event=0x07");
-PMU_EVENT_ATTR_STRING(cpu_thermal_margin.snapshot, evattr_therm_snap, "1");
-PMU_EVENT_ATTR_STRING(cpu_thermal_margin.unit, evattr_therm_unit, "C");
+PMU_EVENT_ATTR_STRING(tsc,				evattr_tsc,		"event=0x00"	);
+PMU_EVENT_ATTR_STRING(aperf,				evattr_aperf,		"event=0x01"	);
+PMU_EVENT_ATTR_STRING(mperf,				evattr_mperf,		"event=0x02"	);
+PMU_EVENT_ATTR_STRING(pperf,				evattr_pperf,		"event=0x03"	);
+PMU_EVENT_ATTR_STRING(smi,				evattr_smi,		"event=0x04"	);
+PMU_EVENT_ATTR_STRING(ptsc,				evattr_ptsc,		"event=0x05"	);
+PMU_EVENT_ATTR_STRING(irperf,				evattr_irperf,		"event=0x06"	);
+PMU_EVENT_ATTR_STRING(cpu_thermal_margin,		evattr_therm,		"event=0x07"	);
+PMU_EVENT_ATTR_STRING(cpu_thermal_margin.snapshot,	evattr_therm_snap,	"1"		);
+PMU_EVENT_ATTR_STRING(cpu_thermal_margin.unit,		evattr_therm_unit,	"C"		);
 
 static struct perf_msr msr[] = {
-	[PERF_MSR_TSC]    = { 0,		&evattr_tsc,	NULL,		 },
-	[PERF_MSR_APERF]  = { MSR_IA32_APERF,	&evattr_aperf,	test_aperfmperf, },
-	[PERF_MSR_MPERF]  = { MSR_IA32_MPERF,	&evattr_mperf,	test_aperfmperf, },
-	[PERF_MSR_PPERF]  = { MSR_PPERF,	&evattr_pperf,	test_intel,	 },
-	[PERF_MSR_SMI]    = { MSR_SMI_COUNT,	&evattr_smi,	test_intel,	 },
-	[PERF_MSR_PTSC]   = { MSR_F15H_PTSC,	&evattr_ptsc,	test_ptsc,	 },
-	[PERF_MSR_IRPERF] = { MSR_F17H_IRPERF,	&evattr_irperf,	test_irperf,	 },
-	[PERF_MSR_THERM] = { MSR_IA32_THERM_STATUS, &evattr_therm,	     test_therm_status, },
-	[PERF_MSR_THERM_SNAP] = { MSR_IA32_THERM_STATUS, &evattr_therm_snap, test_therm_status, },
-	[PERF_MSR_THERM_UNIT] = { MSR_IA32_THERM_STATUS, &evattr_therm_unit, test_therm_status, },
+	[PERF_MSR_TSC]		= { 0,				&evattr_tsc,		NULL,			},
+	[PERF_MSR_APERF]	= { MSR_IA32_APERF,		&evattr_aperf,		test_aperfmperf,	},
+	[PERF_MSR_MPERF]	= { MSR_IA32_MPERF,		&evattr_mperf,		test_aperfmperf,	},
+	[PERF_MSR_PPERF]	= { MSR_PPERF,			&evattr_pperf,		test_intel,		},
+	[PERF_MSR_SMI]		= { MSR_SMI_COUNT,		&evattr_smi,		test_intel,		},
+	[PERF_MSR_PTSC]		= { MSR_F15H_PTSC,		&evattr_ptsc,		test_ptsc,		},
+	[PERF_MSR_IRPERF]	= { MSR_F17H_IRPERF,		&evattr_irperf,		test_irperf,		},
+	[PERF_MSR_THERM]	= { MSR_IA32_THERM_STATUS,	&evattr_therm,		test_therm_status,	},
+	[PERF_MSR_THERM_SNAP]	= { MSR_IA32_THERM_STATUS,	&evattr_therm_snap,	test_therm_status,	},
+	[PERF_MSR_THERM_UNIT]	= { MSR_IA32_THERM_STATUS,	&evattr_therm_unit,	test_therm_status,	},
 };
 
 static struct attribute *events_attrs[PERF_MSR_EVENT_MAX + 1] = {
@@ -175,9 +174,9 @@ static int msr_event_init(struct perf_event *event)
 	if (!msr[cfg].attr)
 		return -EINVAL;
 
-	event->hw.idx = -1;
-	event->hw.event_base = msr[cfg].msr;
-	event->hw.config = cfg;
+	event->hw.idx		= -1;
+	event->hw.event_base	= msr[cfg].msr;
+	event->hw.config	= cfg;
 
 	return 0;
 }
@@ -198,7 +197,7 @@ static void msr_event_update(struct perf_event *event)
 	u64 prev, now;
 	s64 delta;
 
-	/* Careful, an NMI might modify the previous event value. */
+	/* Careful, an NMI might modify the previous event value: */
 again:
 	prev = local64_read(&event->hw.prev_count);
 	now = msr_read_counter(event);
@@ -211,18 +210,18 @@ again:
 		delta = sign_extend64(delta, 31);
 		local64_add(delta, &event->count);
 	} else if (unlikely(event->hw.event_base == MSR_IA32_THERM_STATUS)) {
-		/* if valid, extract digital readout, other set to -1 */
+		/* If valid, extract digital readout, otherwise set to -1: */
 		now = now & (1ULL << 31) ? (now >> 16) & 0x3f :  -1;
 		local64_set(&event->count, now);
-	} else
+	} else {
 		local64_add(delta, &event->count);
+	}
 }
 
 static void msr_event_start(struct perf_event *event, int flags)
 {
-	u64 now;
+	u64 now = msr_read_counter(event);
 
-	now = msr_read_counter(event);
 	local64_set(&event->hw.prev_count, now);
 }
 
@@ -269,9 +268,7 @@ static int __init msr_init(void)
 	for (i = PERF_MSR_TSC + 1; i < PERF_MSR_EVENT_MAX; i++) {
 		u64 val;
 
-		/*
-		 * Virt sucks arse; you cannot tell if a R/O MSR is present :/
-		 */
+		/* Virt sucks; you cannot tell if a R/O MSR is present :/ */
 		if (!msr[i].test(i) || rdmsrl_safe(msr[i].msr, &val))
 			msr[i].attr = NULL;
 	}

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2018-01-06 12:00 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-05 16:18 [PATCH] perf/x86/msr: add support for MSR_IA32_THERM_STATUS Stephane Eranian
2018-01-06 11:53 ` [tip:perf/core] perf/x86/msr: Add " tip-bot for Stephane Eranian
2018-01-06 11:54 ` [tip:perf/core] perf/x86/msr: Clean up the code tip-bot for Ingo Molnar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome