summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorRavi Bangoria <ravi.bangoria@amd.com>2025-01-15 05:44:32 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-06-04 14:42:14 +0200
commit419988f4d0efb1a130bee837d8104c60b142e15f (patch)
treef969dea8e58a408379447410f53a35a39a703dd2 /arch
parent0cb6a1292aaef926d4587b9675cfa8e3eb626933 (diff)
downloadlinux-419988f4d0efb1a130bee837d8104c60b142e15f.tar.gz
linux-419988f4d0efb1a130bee837d8104c60b142e15f.tar.bz2
linux-419988f4d0efb1a130bee837d8104c60b142e15f.zip
perf/amd/ibs: Fix ->config to sample period calculation for OP PMU
[ Upstream commit 598bdf4fefff5af4ce6d26d16f7b2a20808fc4cb ] Instead of using standard perf_event_attr->freq=0 and ->sample_period fields, IBS event in 'sample period mode' can also be opened by setting period value directly in perf_event_attr->config in a MaxCnt bit-field format. IBS OP MaxCnt bits are defined as: (high bits) IbsOpCtl[26:20] = IbsOpMaxCnt[26:20] (low bits) IbsOpCtl[15:0] = IbsOpMaxCnt[19:4] Perf event sample period can be derived from MaxCnt bits as: sample_period = (high bits) | ((low_bits) << 4); However, current code just masks MaxCnt bits and shifts all of them, including high bits, which is incorrect. Fix it. Signed-off-by: Ravi Bangoria <ravi.bangoria@amd.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Namhyung Kim <namhyung@kernel.org> Link: https://lkml.kernel.org/r/20250115054438.1021-4-ravi.bangoria@amd.com Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/events/amd/ibs.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/arch/x86/events/amd/ibs.c b/arch/x86/events/amd/ibs.c
index 85731f121feb..fac3d97111b0 100644
--- a/arch/x86/events/amd/ibs.c
+++ b/arch/x86/events/amd/ibs.c
@@ -272,7 +272,7 @@ static int perf_ibs_init(struct perf_event *event)
{
struct hw_perf_event *hwc = &event->hw;
struct perf_ibs *perf_ibs;
- u64 max_cnt, config;
+ u64 config;
int ret;
perf_ibs = get_ibs_pmu(event->attr.type);
@@ -306,10 +306,19 @@ static int perf_ibs_init(struct perf_event *event)
if (!hwc->sample_period)
hwc->sample_period = 0x10;
} else {
- max_cnt = config & perf_ibs->cnt_mask;
+ u64 period = 0;
+
+ if (perf_ibs == &perf_ibs_op) {
+ period = (config & IBS_OP_MAX_CNT) << 4;
+ if (ibs_caps & IBS_CAPS_OPCNTEXT)
+ period |= config & IBS_OP_MAX_CNT_EXT_MASK;
+ } else {
+ period = (config & IBS_FETCH_MAX_CNT) << 4;
+ }
+
config &= ~perf_ibs->cnt_mask;
- event->attr.sample_period = max_cnt << 4;
- hwc->sample_period = event->attr.sample_period;
+ event->attr.sample_period = period;
+ hwc->sample_period = period;
}
if (!hwc->sample_period)