diff options
author | markus.t.metzger@intel.com <markus.t.metzger@intel.com> | 2009-09-02 10:04:46 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-09-04 03:26:39 -0400 |
commit | 747b50aaf728987732e6ff3ba10aba4acc4e0277 (patch) | |
tree | dd1b75f7d14b8bf7dff2519058516be69e70c356 /arch/x86/kernel/cpu/perf_counter.c | |
parent | dc86cabe4b242446ea9aa8492c727e1220817898 (diff) |
x86, perf_counter, bts: Fail if BTS is not available
Reserve PERF_COUNT_HW_BRANCH_INSTRUCTIONS with sample_period ==
1 for BTS tracing and fail, if BTS is not available.
Signed-off-by: Markus Metzger <markus.t.metzger@intel.com>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <20090902140612.943801000@intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/cpu/perf_counter.c')
-rw-r--r-- | arch/x86/kernel/cpu/perf_counter.c | 25 |
1 files changed, 11 insertions, 14 deletions
diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c index 396e35db705..2f41874ffb8 100644 --- a/arch/x86/kernel/cpu/perf_counter.c +++ b/arch/x86/kernel/cpu/perf_counter.c | |||
@@ -769,7 +769,7 @@ static int reserve_bts_hardware(void) | |||
769 | int cpu, err = 0; | 769 | int cpu, err = 0; |
770 | 770 | ||
771 | if (!bts_available()) | 771 | if (!bts_available()) |
772 | return -EOPNOTSUPP; | 772 | return 0; |
773 | 773 | ||
774 | get_online_cpus(); | 774 | get_online_cpus(); |
775 | 775 | ||
@@ -914,7 +914,7 @@ static int __hw_perf_counter_init(struct perf_counter *counter) | |||
914 | if (!reserve_pmc_hardware()) | 914 | if (!reserve_pmc_hardware()) |
915 | err = -EBUSY; | 915 | err = -EBUSY; |
916 | else | 916 | else |
917 | reserve_bts_hardware(); | 917 | err = reserve_bts_hardware(); |
918 | } | 918 | } |
919 | if (!err) | 919 | if (!err) |
920 | atomic_inc(&active_counters); | 920 | atomic_inc(&active_counters); |
@@ -979,6 +979,13 @@ static int __hw_perf_counter_init(struct perf_counter *counter) | |||
979 | if (config == -1LL) | 979 | if (config == -1LL) |
980 | return -EINVAL; | 980 | return -EINVAL; |
981 | 981 | ||
982 | /* | ||
983 | * Branch tracing: | ||
984 | */ | ||
985 | if ((attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS) && | ||
986 | (hwc->sample_period == 1) && !bts_available()) | ||
987 | return -EOPNOTSUPP; | ||
988 | |||
982 | hwc->config |= config; | 989 | hwc->config |= config; |
983 | 990 | ||
984 | return 0; | 991 | return 0; |
@@ -1355,19 +1362,9 @@ static int x86_pmu_enable(struct perf_counter *counter) | |||
1355 | 1362 | ||
1356 | idx = fixed_mode_idx(counter, hwc); | 1363 | idx = fixed_mode_idx(counter, hwc); |
1357 | if (idx == X86_PMC_IDX_FIXED_BTS) { | 1364 | if (idx == X86_PMC_IDX_FIXED_BTS) { |
1358 | /* | 1365 | /* BTS is already occupied. */ |
1359 | * Try to use BTS for branch tracing. If that is not | ||
1360 | * available, try to get a generic counter. | ||
1361 | */ | ||
1362 | if (unlikely(!cpuc->ds)) | ||
1363 | goto try_generic; | ||
1364 | |||
1365 | /* | ||
1366 | * Try to get the fixed counter, if that is already taken | ||
1367 | * then try to get a generic counter: | ||
1368 | */ | ||
1369 | if (test_and_set_bit(idx, cpuc->used_mask)) | 1366 | if (test_and_set_bit(idx, cpuc->used_mask)) |
1370 | goto try_generic; | 1367 | return -EAGAIN; |
1371 | 1368 | ||
1372 | hwc->config_base = 0; | 1369 | hwc->config_base = 0; |
1373 | hwc->counter_base = 0; | 1370 | hwc->counter_base = 0; |