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>
This commit is contained in:
committed by
Ingo Molnar
parent
dc86cabe4b
commit
747b50aaf7
@@ -769,7 +769,7 @@ static int reserve_bts_hardware(void)
|
|||||||
int cpu, err = 0;
|
int cpu, err = 0;
|
||||||
|
|
||||||
if (!bts_available())
|
if (!bts_available())
|
||||||
return -EOPNOTSUPP;
|
return 0;
|
||||||
|
|
||||||
get_online_cpus();
|
get_online_cpus();
|
||||||
|
|
||||||
@@ -914,7 +914,7 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
|
|||||||
if (!reserve_pmc_hardware())
|
if (!reserve_pmc_hardware())
|
||||||
err = -EBUSY;
|
err = -EBUSY;
|
||||||
else
|
else
|
||||||
reserve_bts_hardware();
|
err = reserve_bts_hardware();
|
||||||
}
|
}
|
||||||
if (!err)
|
if (!err)
|
||||||
atomic_inc(&active_counters);
|
atomic_inc(&active_counters);
|
||||||
@@ -979,6 +979,13 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
|
|||||||
if (config == -1LL)
|
if (config == -1LL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Branch tracing:
|
||||||
|
*/
|
||||||
|
if ((attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS) &&
|
||||||
|
(hwc->sample_period == 1) && !bts_available())
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
hwc->config |= config;
|
hwc->config |= config;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1355,19 +1362,9 @@ static int x86_pmu_enable(struct perf_counter *counter)
|
|||||||
|
|
||||||
idx = fixed_mode_idx(counter, hwc);
|
idx = fixed_mode_idx(counter, hwc);
|
||||||
if (idx == X86_PMC_IDX_FIXED_BTS) {
|
if (idx == X86_PMC_IDX_FIXED_BTS) {
|
||||||
/*
|
/* BTS is already occupied. */
|
||||||
* Try to use BTS for branch tracing. If that is not
|
|
||||||
* available, try to get a generic counter.
|
|
||||||
*/
|
|
||||||
if (unlikely(!cpuc->ds))
|
|
||||||
goto try_generic;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Try to get the fixed counter, if that is already taken
|
|
||||||
* then try to get a generic counter:
|
|
||||||
*/
|
|
||||||
if (test_and_set_bit(idx, cpuc->used_mask))
|
if (test_and_set_bit(idx, cpuc->used_mask))
|
||||||
goto try_generic;
|
return -EAGAIN;
|
||||||
|
|
||||||
hwc->config_base = 0;
|
hwc->config_base = 0;
|
||||||
hwc->counter_base = 0;
|
hwc->counter_base = 0;
|
||||||
|
Reference in New Issue
Block a user