linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Zhang Rui <rui.zhang@intel.com>
To: linux-x86 <x86@kernel.org>, LKML <linux-kernel@vger.kernel.org>
Cc: peterz@infradead.org, mingo@redhat.com, acme@kernel.org,
	alexander.shishkin@linux.intel.com, jolsa@redhat.com,
	namhyung@kernel.org, tglx@linutronix.de, "Liang,
	Kan" <kan.liang@intel.com>
Subject: [PATCH] perf/rapl: restart perf rapl counter after resume
Date: Mon, 17 Jun 2019 21:41:37 +0800	[thread overview]
Message-ID: <1560778897.10723.6.camel@intel.com> (raw)

From b74a74f953f4c34818a58831b6eb468b42b17c62 Mon Sep 17 00:00:00 2001
From: Zhang Rui <rui.zhang@intel.com>
Date: Tue, 23 Apr 2019 16:26:50 +0800
Subject: [PATCH] perf/rapl: restart perf rapl counter after resume

After S3 suspend/resume, "perf stat -I 1000 -e power/energy-pkg/ -a"
reports an insane value for the very first sampling period after resume
as shown below.

    19.278989977               2.16 Joules power/energy-pkg/
    20.279373569               1.96 Joules power/energy-pkg/
    21.279765481               2.09 Joules power/energy-pkg/
    22.280305420               2.10 Joules power/energy-pkg/
    25.504782277   4,294,966,686.01 Joules power/energy-pkg/
    26.505114993               3.58 Joules power/energy-pkg/
    27.505471758               1.66 Joules power/energy-pkg/

Fix this by resetting the counter right after resume.

Kan, Liang proposed the prototype patch and I reworked it to use syscore
ops.

Signed-off-by: Zhang Rui <rui.zhang@intel.com>
Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
---
 arch/x86/events/intel/rapl.c | 84 +++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 76 insertions(+), 8 deletions(-)

diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c
index 26c03f5..6cff8fd 100644
--- a/arch/x86/events/intel/rapl.c
+++ b/arch/x86/events/intel/rapl.c
@@ -55,6 +55,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/perf_event.h>
+#include <linux/syscore_ops.h>
 #include <asm/cpu_device_id.h>
 #include <asm/intel-family.h>
 #include "../perf_event.h"
@@ -228,6 +229,32 @@ static u64 rapl_event_update(struct perf_event *event)
 	return new_raw_count;
 }
 
+static void rapl_pmu_update_all(struct rapl_pmu *pmu)
+{
+	struct perf_event *event;
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&pmu->lock, flags);
+
+	list_for_each_entry(event, &pmu->active_list, active_entry)
+		rapl_event_update(event);
+
+	raw_spin_unlock_irqrestore(&pmu->lock, flags);
+}
+
+static void rapl_pmu_restart_all(struct rapl_pmu *pmu)
+{
+	struct perf_event *event;
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&pmu->lock, flags);
+
+	list_for_each_entry(event, &pmu->active_list, active_entry)
+		local64_set(&event->hw.prev_count, rapl_read_counter(event));
+
+	raw_spin_unlock_irqrestore(&pmu->lock, flags);
+}
+
 static void rapl_start_hrtimer(struct rapl_pmu *pmu)
 {
        hrtimer_start(&pmu->hrtimer, pmu->timer_interval,
@@ -237,18 +264,11 @@ static void rapl_start_hrtimer(struct rapl_pmu *pmu)
 static enum hrtimer_restart rapl_hrtimer_handle(struct hrtimer *hrtimer)
 {
 	struct rapl_pmu *pmu = container_of(hrtimer, struct rapl_pmu, hrtimer);
-	struct perf_event *event;
-	unsigned long flags;
 
 	if (!pmu->n_active)
 		return HRTIMER_NORESTART;
 
-	raw_spin_lock_irqsave(&pmu->lock, flags);
-
-	list_for_each_entry(event, &pmu->active_list, active_entry)
-		rapl_event_update(event);
-
-	raw_spin_unlock_irqrestore(&pmu->lock, flags);
+	rapl_pmu_update_all(pmu);
 
 	hrtimer_forward_now(hrtimer, pmu->timer_interval);
 
@@ -698,6 +718,52 @@ static int __init init_rapl_pmus(void)
 	return 0;
 }
 
+
+#ifdef CONFIG_PM
+
+static int perf_rapl_suspend(void)
+{
+	int i;
+
+	get_online_cpus();
+	for (i = 0; i < rapl_pmus->maxpkg; i++)
+		rapl_pmu_update_all(rapl_pmus->pmus[i]);
+	put_online_cpus();
+	return 0;
+}
+
+static void perf_rapl_resume(void)
+{
+	int i;
+
+	get_online_cpus();
+	for (i = 0; i < rapl_pmus->maxpkg; i++)
+		rapl_pmu_restart_all(rapl_pmus->pmus[i]);
+	put_online_cpus();
+}
+
+static struct syscore_ops perf_rapl_syscore_ops = {
+	.resume = perf_rapl_resume,
+	.suspend = perf_rapl_suspend,
+};
+
+static void perf_rapl_pm_register(void)
+{
+	register_syscore_ops(&perf_rapl_syscore_ops);
+}
+
+static void perf_rapl_pm_unregister(void)
+{
+	unregister_syscore_ops(&perf_rapl_syscore_ops);
+}
+
+#else
+
+static inline void perf_rapl_pm_register(void) { }
+static inline void perf_rapl_pm_unregister(void) { }
+
+#endif
+
 #define X86_RAPL_MODEL_MATCH(model, init)	\
 	{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&init }
 
@@ -798,6 +864,7 @@ static int __init rapl_pmu_init(void)
 	apply_quirk = rapl_init->apply_quirk;
 	rapl_cntr_mask = rapl_init->cntr_mask;
 	rapl_pmu_events_group.attrs = rapl_init->attrs;
+	perf_rapl_pm_register();
 
 	ret = rapl_check_hw_unit(apply_quirk);
 	if (ret)
@@ -836,6 +903,7 @@ static void __exit intel_rapl_exit(void)
 {
 	cpuhp_remove_state_nocalls(CPUHP_AP_PERF_X86_RAPL_ONLINE);
 	perf_pmu_unregister(&rapl_pmus->pmu);
+	perf_rapl_pm_unregister();
 	cleanup_rapl_pmus();
 }
 module_exit(intel_rapl_exit);
-- 
2.7.4


             reply	other threads:[~2019-06-17 13:41 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-17 13:41 Zhang Rui [this message]
2019-06-20 12:50 ` [PATCH] perf/rapl: restart perf rapl counter after resume Peter Zijlstra
2019-06-20 14:33   ` Liang, Kan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1560778897.10723.6.camel@intel.com \
    --to=rui.zhang@intel.com \
    --cc=acme@kernel.org \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=jolsa@redhat.com \
    --cc=kan.liang@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=namhyung@kernel.org \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).