diff options
author | Robert Richter <robert.richter@amd.com> | 2012-04-02 14:19:10 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-05-09 09:23:13 -0400 |
commit | 6accb9cf76080422d400a641d9068b6b2a2c216f (patch) | |
tree | 3774a7b43cb513761924209f5d51b1a497fcd3d2 /arch | |
parent | 7bf352384fda3f678a283928c6c5b2cd9da877e4 (diff) |
perf/x86-ibs: Fix frequency profiling
Fixing profiling at a fixed frequency, in this case the freq value and
sample period was setup incorrectly. Since sampling periods are
adjusted we also allow periods that have lower 4 bits set.
Another fix is the setup of the hw counter: If we modify
hwc->sample_period, we also need to update hwc->last_period and
hwc->period_left.
Signed-off-by: Robert Richter <robert.richter@amd.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1333390758-10893-5-git-send-email-robert.richter@amd.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_amd_ibs.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c index ebf169fe40ef..bc401bd9f14a 100644 --- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c +++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c | |||
@@ -162,9 +162,16 @@ static int perf_ibs_init(struct perf_event *event) | |||
162 | if (config & perf_ibs->cnt_mask) | 162 | if (config & perf_ibs->cnt_mask) |
163 | /* raw max_cnt may not be set */ | 163 | /* raw max_cnt may not be set */ |
164 | return -EINVAL; | 164 | return -EINVAL; |
165 | if (hwc->sample_period & 0x0f) | 165 | if (!event->attr.sample_freq && hwc->sample_period & 0x0f) |
166 | /* lower 4 bits can not be set in ibs max cnt */ | 166 | /* |
167 | * lower 4 bits can not be set in ibs max cnt, | ||
168 | * but allowing it in case we adjust the | ||
169 | * sample period to set a frequency. | ||
170 | */ | ||
167 | return -EINVAL; | 171 | return -EINVAL; |
172 | hwc->sample_period &= ~0x0FULL; | ||
173 | if (!hwc->sample_period) | ||
174 | hwc->sample_period = 0x10; | ||
168 | } else { | 175 | } else { |
169 | max_cnt = config & perf_ibs->cnt_mask; | 176 | max_cnt = config & perf_ibs->cnt_mask; |
170 | config &= ~perf_ibs->cnt_mask; | 177 | config &= ~perf_ibs->cnt_mask; |
@@ -175,6 +182,13 @@ static int perf_ibs_init(struct perf_event *event) | |||
175 | if (!hwc->sample_period) | 182 | if (!hwc->sample_period) |
176 | return -EINVAL; | 183 | return -EINVAL; |
177 | 184 | ||
185 | /* | ||
186 | * If we modify hwc->sample_period, we also need to update | ||
187 | * hwc->last_period and hwc->period_left. | ||
188 | */ | ||
189 | hwc->last_period = hwc->sample_period; | ||
190 | local64_set(&hwc->period_left, hwc->sample_period); | ||
191 | |||
178 | hwc->config_base = perf_ibs->msr; | 192 | hwc->config_base = perf_ibs->msr; |
179 | hwc->config = config; | 193 | hwc->config = config; |
180 | 194 | ||