summaryrefslogtreecommitdiff
path: root/samples/workqueue
diff options
context:
space:
mode:
authorLi, Yifan <yifan2.li@intel.com>2026-08-14 11:10:08 +0800
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2026-08-20 23:11:52 +0200
commita8b842366f8ff469fe0fc700ba53770ded847ea9 (patch)
tree542d20df1adb343573302dc69f150de72300c046 /samples/workqueue
parenta5778046a02570fd23bdf0b48dce330237d1996c (diff)
downloadlinux-stable-a8b842366f8ff469fe0fc700ba53770ded847ea9.tar.gz
linux-stable-a8b842366f8ff469fe0fc700ba53770ded847ea9.zip
powercap: intel_rapl: Sign-extend the PMU delta on counter wraparound
The RAPL PMU misreports energy when the hardware energy counter overflows and wraps back to zero. perf event counts are defined to increase monotonically, but a single wraparound makes the PMU event count jump backwards by nearly the full counter range, and consumers that take the difference of two reads in unsigned arithmetic then underflow and report an absurd value. On a Panther Lake system (energy unit 61.035 uJ, counter range 262144 J) the package counter wraps every ~2.9 hours at 25 W, and turbostat prints one bogus sample per wraparound, per domain: PkgTmp PkgWatt CorWatt GFXWatt RAMWatt SysWatt 44 24.97 16.30 3.90 1.87 2145386370.35 43 2145240612.10 16.13 4.02 1.91 40.46 The RAPL energy counters are 32-bit wide on every register interface: MSR, MMIO and TPMI all describe ENERGY_COUNTER with a GENMASK(31, 0) mask. rapl_read_data_raw() applies that mask, so event_read_counter() returns the counter zero-extended in a u64. rapl_event_update() then computes delta = new_raw_count - prev_raw_count; without reducing the result modulo 2^32. While the counter does not wrap this is correct, but once the hardware counter wraps, new_raw_count < prev_raw_count and delta becomes (true_delta - 2^32), a large negative value. Declaring delta as s64 only makes that value representable; it does not correct it. That bogus delta is scaled and added to event->count, which is where the backwards jump comes from. Fix it the way arch/x86/events/rapl.c has done since the RAPL PMU was first introduced: shift both values up so that the 64-bit subtraction reduces modulo 2^32, then shift the difference back down with an arithmetic shift to sign-extend it. This is correct as long as at most one wraparound happens between two updates, which the existing overflow hrtimer already guarantees: its period is half of the counter range at the 200 W reference used in rapl_package_add_pmu_locked(). The problem has been present since the powercap RAPL PMU was added, but only affected TPMI RAPL until commit 748d6ba43afd ("powercap: intel_rapl: Enable MSR-based RAPL PMU support") routed MSR RAPL through the same PMU, which exposed it on client platforms such as Panther Lake. Fixes: 575024a8aa7c ("powercap: intel_rapl: Introduce APIs for PMU support") Reported-by: Jyoti, Anand B <anand.b.jyoti@intel.com> Signed-off-by: Li, Yifan <yifan2.li@intel.com> Signed-off-by: Gao Jianfeng <jianfeng.gao@intel.com> Tested-by: Jyoti, Anand B <anand.b.jyoti@intel.com> Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Reviewed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> Link: https://patch.msgid.link/20260814031008.750911-1-yifan2.li@intel.com Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'samples/workqueue')
0 files changed, 0 insertions, 0 deletions