diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2011-05-23 05:08:15 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-07-01 05:06:37 -0400 |
commit | b79e8941fb9af07d810da91b4e29da2bba331b6e (patch) | |
tree | 8bb9c7ec132d185dc79f9a05274c1535d3634762 | |
parent | ee89cbc2d48150c7c0e9f2aaac00afde99af098c (diff) |
perf, intel: Try alternative OFFCORE encodings
Since the OFFCORE registers are fully symmetric, try the other one
when the specified one is already in use.
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1306141897.18455.8.camel@twins
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 5 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel.c | 44 |
2 files changed, 41 insertions, 8 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 583f3113436d..c53d433c3dde 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -327,9 +327,12 @@ struct x86_pmu { | |||
327 | * Extra registers for events | 327 | * Extra registers for events |
328 | */ | 328 | */ |
329 | struct extra_reg *extra_regs; | 329 | struct extra_reg *extra_regs; |
330 | bool regs_no_ht_sharing; | 330 | unsigned int er_flags; |
331 | }; | 331 | }; |
332 | 332 | ||
333 | #define ERF_NO_HT_SHARING 1 | ||
334 | #define ERF_HAS_RSP_1 2 | ||
335 | |||
333 | static struct x86_pmu x86_pmu __read_mostly; | 336 | static struct x86_pmu x86_pmu __read_mostly; |
334 | 337 | ||
335 | static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { | 338 | static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { |
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index a674ae45a472..5c448622468c 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c | |||
@@ -1018,6 +1018,29 @@ intel_bts_constraints(struct perf_event *event) | |||
1018 | return NULL; | 1018 | return NULL; |
1019 | } | 1019 | } |
1020 | 1020 | ||
1021 | static bool intel_try_alt_er(struct perf_event *event, int orig_idx) | ||
1022 | { | ||
1023 | if (!(x86_pmu.er_flags & ERF_HAS_RSP_1)) | ||
1024 | return false; | ||
1025 | |||
1026 | if (event->hw.extra_reg.idx == EXTRA_REG_RSP_0) { | ||
1027 | event->hw.config &= ~INTEL_ARCH_EVENT_MASK; | ||
1028 | event->hw.config |= 0x01bb; | ||
1029 | event->hw.extra_reg.idx = EXTRA_REG_RSP_1; | ||
1030 | event->hw.extra_reg.reg = MSR_OFFCORE_RSP_1; | ||
1031 | } else if (event->hw.extra_reg.idx == EXTRA_REG_RSP_1) { | ||
1032 | event->hw.config &= ~INTEL_ARCH_EVENT_MASK; | ||
1033 | event->hw.config |= 0x01b7; | ||
1034 | event->hw.extra_reg.idx = EXTRA_REG_RSP_0; | ||
1035 | event->hw.extra_reg.reg = MSR_OFFCORE_RSP_0; | ||
1036 | } | ||
1037 | |||
1038 | if (event->hw.extra_reg.idx == orig_idx) | ||
1039 | return false; | ||
1040 | |||
1041 | return true; | ||
1042 | } | ||
1043 | |||
1021 | /* | 1044 | /* |
1022 | * manage allocation of shared extra msr for certain events | 1045 | * manage allocation of shared extra msr for certain events |
1023 | * | 1046 | * |
@@ -1027,16 +1050,19 @@ intel_bts_constraints(struct perf_event *event) | |||
1027 | */ | 1050 | */ |
1028 | static struct event_constraint * | 1051 | static struct event_constraint * |
1029 | __intel_shared_reg_get_constraints(struct cpu_hw_events *cpuc, | 1052 | __intel_shared_reg_get_constraints(struct cpu_hw_events *cpuc, |
1030 | struct hw_perf_event_extra *reg) | 1053 | struct perf_event *event) |
1031 | { | 1054 | { |
1032 | struct event_constraint *c = &emptyconstraint; | 1055 | struct event_constraint *c = &emptyconstraint; |
1056 | struct hw_perf_event_extra *reg = &event->hw.extra_reg; | ||
1033 | struct er_account *era; | 1057 | struct er_account *era; |
1034 | unsigned long flags; | 1058 | unsigned long flags; |
1059 | int orig_idx = reg->idx; | ||
1035 | 1060 | ||
1036 | /* already allocated shared msr */ | 1061 | /* already allocated shared msr */ |
1037 | if (reg->alloc) | 1062 | if (reg->alloc) |
1038 | return &unconstrained; | 1063 | return &unconstrained; |
1039 | 1064 | ||
1065 | again: | ||
1040 | era = &cpuc->shared_regs->regs[reg->idx]; | 1066 | era = &cpuc->shared_regs->regs[reg->idx]; |
1041 | /* | 1067 | /* |
1042 | * we use spin_lock_irqsave() to avoid lockdep issues when | 1068 | * we use spin_lock_irqsave() to avoid lockdep issues when |
@@ -1065,6 +1091,9 @@ __intel_shared_reg_get_constraints(struct cpu_hw_events *cpuc, | |||
1065 | * the regular event constraint table. | 1091 | * the regular event constraint table. |
1066 | */ | 1092 | */ |
1067 | c = &unconstrained; | 1093 | c = &unconstrained; |
1094 | } else if (intel_try_alt_er(event, orig_idx)) { | ||
1095 | raw_spin_unlock(&era->lock); | ||
1096 | goto again; | ||
1068 | } | 1097 | } |
1069 | raw_spin_unlock_irqrestore(&era->lock, flags); | 1098 | raw_spin_unlock_irqrestore(&era->lock, flags); |
1070 | 1099 | ||
@@ -1099,11 +1128,10 @@ intel_shared_regs_constraints(struct cpu_hw_events *cpuc, | |||
1099 | struct perf_event *event) | 1128 | struct perf_event *event) |
1100 | { | 1129 | { |
1101 | struct event_constraint *c = NULL; | 1130 | struct event_constraint *c = NULL; |
1102 | struct hw_perf_event_extra *xreg; | ||
1103 | 1131 | ||
1104 | xreg = &event->hw.extra_reg; | 1132 | if (event->hw.extra_reg.idx != EXTRA_REG_NONE) |
1105 | if (xreg->idx != EXTRA_REG_NONE) | 1133 | c = __intel_shared_reg_get_constraints(cpuc, event); |
1106 | c = __intel_shared_reg_get_constraints(cpuc, xreg); | 1134 | |
1107 | return c; | 1135 | return c; |
1108 | } | 1136 | } |
1109 | 1137 | ||
@@ -1264,7 +1292,7 @@ static void intel_pmu_cpu_starting(int cpu) | |||
1264 | */ | 1292 | */ |
1265 | intel_pmu_lbr_reset(); | 1293 | intel_pmu_lbr_reset(); |
1266 | 1294 | ||
1267 | if (!cpuc->shared_regs || x86_pmu.regs_no_ht_sharing) | 1295 | if (!cpuc->shared_regs || (x86_pmu.er_flags & ERF_NO_HT_SHARING)) |
1268 | return; | 1296 | return; |
1269 | 1297 | ||
1270 | for_each_cpu(i, topology_thread_cpumask(cpu)) { | 1298 | for_each_cpu(i, topology_thread_cpumask(cpu)) { |
@@ -1489,6 +1517,7 @@ static __init int intel_pmu_init(void) | |||
1489 | x86_pmu.enable_all = intel_pmu_nhm_enable_all; | 1517 | x86_pmu.enable_all = intel_pmu_nhm_enable_all; |
1490 | x86_pmu.pebs_constraints = intel_westmere_pebs_event_constraints; | 1518 | x86_pmu.pebs_constraints = intel_westmere_pebs_event_constraints; |
1491 | x86_pmu.extra_regs = intel_westmere_extra_regs; | 1519 | x86_pmu.extra_regs = intel_westmere_extra_regs; |
1520 | x86_pmu.er_flags |= ERF_HAS_RSP_1; | ||
1492 | 1521 | ||
1493 | /* UOPS_ISSUED.STALLED_CYCLES */ | 1522 | /* UOPS_ISSUED.STALLED_CYCLES */ |
1494 | intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x180010e; | 1523 | intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x180010e; |
@@ -1508,7 +1537,8 @@ static __init int intel_pmu_init(void) | |||
1508 | x86_pmu.pebs_constraints = intel_snb_pebs_events; | 1537 | x86_pmu.pebs_constraints = intel_snb_pebs_events; |
1509 | x86_pmu.extra_regs = intel_snb_extra_regs; | 1538 | x86_pmu.extra_regs = intel_snb_extra_regs; |
1510 | /* all extra regs are per-cpu when HT is on */ | 1539 | /* all extra regs are per-cpu when HT is on */ |
1511 | x86_pmu.regs_no_ht_sharing = true; | 1540 | x86_pmu.er_flags |= ERF_HAS_RSP_1; |
1541 | x86_pmu.er_flags |= ERF_NO_HT_SHARING; | ||
1512 | 1542 | ||
1513 | /* UOPS_ISSUED.ANY,c=1,i=1 to count stall cycles */ | 1543 | /* UOPS_ISSUED.ANY,c=1,i=1 to count stall cycles */ |
1514 | intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x180010e; | 1544 | intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x180010e; |