aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/cpu/perf_event.c5
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_ds.c58
2 files changed, 47 insertions, 16 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index f369c53315a5..61e78f651060 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -238,6 +238,7 @@ struct x86_pmu {
238 * Intel DebugStore bits 238 * Intel DebugStore bits
239 */ 239 */
240 int bts, pebs; 240 int bts, pebs;
241 int bts_active, pebs_active;
241 int pebs_record_size; 242 int pebs_record_size;
242 void (*drain_pebs)(struct pt_regs *regs); 243 void (*drain_pebs)(struct pt_regs *regs);
243 struct event_constraint *pebs_constraints; 244 struct event_constraint *pebs_constraints;
@@ -478,7 +479,7 @@ static int x86_setup_perfctr(struct perf_event *event)
478 if ((attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS) && 479 if ((attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS) &&
479 (hwc->sample_period == 1)) { 480 (hwc->sample_period == 1)) {
480 /* BTS is not supported by this architecture. */ 481 /* BTS is not supported by this architecture. */
481 if (!x86_pmu.bts) 482 if (!x86_pmu.bts_active)
482 return -EOPNOTSUPP; 483 return -EOPNOTSUPP;
483 484
484 /* BTS is currently only allowed for user-mode. */ 485 /* BTS is currently only allowed for user-mode. */
@@ -497,7 +498,7 @@ static int x86_pmu_hw_config(struct perf_event *event)
497 int precise = 0; 498 int precise = 0;
498 499
499 /* Support for constant skid */ 500 /* Support for constant skid */
500 if (x86_pmu.pebs) { 501 if (x86_pmu.pebs_active) {
501 precise++; 502 precise++;
502 503
503 /* Support for IP fixup */ 504 /* Support for IP fixup */
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
index 3c86f4d2f02d..05c7db68277b 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -193,36 +193,66 @@ static void release_ds_buffers(void)
193 193
194static int reserve_ds_buffers(void) 194static int reserve_ds_buffers(void)
195{ 195{
196 int cpu, err = 0; 196 int bts_err = 0, pebs_err = 0;
197 int cpu;
198
199 x86_pmu.bts_active = 0;
200 x86_pmu.pebs_active = 0;
197 201
198 if (!x86_pmu.bts && !x86_pmu.pebs) 202 if (!x86_pmu.bts && !x86_pmu.pebs)
199 return 0; 203 return 0;
200 204
205 if (!x86_pmu.bts)
206 bts_err = 1;
207
208 if (!x86_pmu.pebs)
209 pebs_err = 1;
210
201 get_online_cpus(); 211 get_online_cpus();
202 212
203 for_each_possible_cpu(cpu) { 213 for_each_possible_cpu(cpu) {
204 if (alloc_ds_buffer(cpu)) 214 if (alloc_ds_buffer(cpu)) {
205 break; 215 bts_err = 1;
216 pebs_err = 1;
217 }
206 218
207 if (alloc_bts_buffer(cpu)) 219 if (!bts_err && alloc_bts_buffer(cpu))
208 break; 220 bts_err = 1;
221
222 if (!pebs_err && alloc_pebs_buffer(cpu))
223 pebs_err = 1;
209 224
210 if (alloc_pebs_buffer(cpu)) 225 if (bts_err && pebs_err)
211 break; 226 break;
227 }
228
229 if (bts_err) {
230 for_each_possible_cpu(cpu)
231 release_bts_buffer(cpu);
232 }
212 233
213 err = 0; 234 if (pebs_err) {
235 for_each_possible_cpu(cpu)
236 release_pebs_buffer(cpu);
214 } 237 }
215 238
216 if (err) 239 if (bts_err && pebs_err) {
217 release_ds_buffers(); 240 for_each_possible_cpu(cpu)
218 else { 241 release_ds_buffer(cpu);
242 } else {
243 if (x86_pmu.bts && !bts_err)
244 x86_pmu.bts_active = 1;
245
246 if (x86_pmu.pebs && !pebs_err)
247 x86_pmu.pebs_active = 1;
248
219 for_each_online_cpu(cpu) 249 for_each_online_cpu(cpu)
220 init_debug_store_on_cpu(cpu); 250 init_debug_store_on_cpu(cpu);
221 } 251 }
222 252
223 put_online_cpus(); 253 put_online_cpus();
224 254
225 return err; 255 return 0;
226} 256}
227 257
228/* 258/*
@@ -287,7 +317,7 @@ static int intel_pmu_drain_bts_buffer(void)
287 if (!event) 317 if (!event)
288 return 0; 318 return 0;
289 319
290 if (!ds) 320 if (!x86_pmu.bts_active)
291 return 0; 321 return 0;
292 322
293 at = (struct bts_record *)(unsigned long)ds->bts_buffer_base; 323 at = (struct bts_record *)(unsigned long)ds->bts_buffer_base;
@@ -557,7 +587,7 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs)
557 struct pebs_record_core *at, *top; 587 struct pebs_record_core *at, *top;
558 int n; 588 int n;
559 589
560 if (!ds || !x86_pmu.pebs) 590 if (!x86_pmu.pebs_active)
561 return; 591 return;
562 592
563 at = (struct pebs_record_core *)(unsigned long)ds->pebs_buffer_base; 593 at = (struct pebs_record_core *)(unsigned long)ds->pebs_buffer_base;
@@ -599,7 +629,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
599 u64 status = 0; 629 u64 status = 0;
600 int bit, n; 630 int bit, n;
601 631
602 if (!ds || !x86_pmu.pebs) 632 if (!x86_pmu.pebs_active)
603 return; 633 return;
604 634
605 at = (struct pebs_record_nhm *)(unsigned long)ds->pebs_buffer_base; 635 at = (struct pebs_record_nhm *)(unsigned long)ds->pebs_buffer_base;