diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-08 12:14:46 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-06-08 12:14:46 -0400 |
| commit | 106544d81d88069c2df66ebdee42a4ba8fcd25e9 (patch) | |
| tree | 9a6233100699c28fafde9eaa1751de7ddc173f58 /arch/x86/kernel | |
| parent | 03d8f5408235bfd2781142458e0c0671530e74e7 (diff) | |
| parent | db0dc75d6403b6663c0eab4c6ccb672eb9b2ed72 (diff) | |
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Ingo Molnar:
"A bit larger than what I'd wish for - half of it is due to hw driver
updates to Intel Ivy-Bridge which info got recently released,
cycles:pp should work there now too, amongst other things. (but we
are generally making exceptions for hardware enablement of this type.)
There are also callchain fixes in it - responding to mostly
theoretical (but valid) concerns. The tooling side sports perf.data
endianness/portability fixes which did not make it for the merge
window - and various other fixes as well."
* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (26 commits)
perf/x86: Check user address explicitly in copy_from_user_nmi()
perf/x86: Check if user fp is valid
perf: Limit callchains to 127
perf/x86: Allow multiple stacks
perf/x86: Update SNB PEBS constraints
perf/x86: Enable/Add IvyBridge hardware support
perf/x86: Implement cycles:p for SNB/IVB
perf/x86: Fix Intel shared extra MSR allocation
x86/decoder: Fix bsr/bsf/jmpe decoding with operand-size prefix
perf: Remove duplicate invocation on perf_event_for_each
perf uprobes: Remove unnecessary check before strlist__delete
perf symbols: Check for valid dso before creating map
perf evsel: Fix 32 bit values endianity swap for sample_id_all header
perf session: Handle endianity swap on sample_id_all header data
perf symbols: Handle different endians properly during symbol load
perf evlist: Pass third argument to ioctl explicitly
perf tools: Update ioctl documentation for PERF_IOC_FLAG_GROUP
perf tools: Make --version show kernel version instead of pull req tag
perf tools: Check if callchain is corrupted
perf callchain: Make callchain cursors TLS
...
Diffstat (limited to 'arch/x86/kernel')
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 11 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event.h | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel.c | 145 | ||||
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event_intel_ds.c | 9 |
4 files changed, 120 insertions, 47 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index e049d6da0183..c4706cf9c011 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
| @@ -1496,6 +1496,7 @@ static struct cpu_hw_events *allocate_fake_cpuc(void) | |||
| 1496 | if (!cpuc->shared_regs) | 1496 | if (!cpuc->shared_regs) |
| 1497 | goto error; | 1497 | goto error; |
| 1498 | } | 1498 | } |
| 1499 | cpuc->is_fake = 1; | ||
| 1499 | return cpuc; | 1500 | return cpuc; |
| 1500 | error: | 1501 | error: |
| 1501 | free_fake_cpuc(cpuc); | 1502 | free_fake_cpuc(cpuc); |
| @@ -1756,6 +1757,12 @@ perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs) | |||
| 1756 | dump_trace(NULL, regs, NULL, 0, &backtrace_ops, entry); | 1757 | dump_trace(NULL, regs, NULL, 0, &backtrace_ops, entry); |
| 1757 | } | 1758 | } |
| 1758 | 1759 | ||
| 1760 | static inline int | ||
| 1761 | valid_user_frame(const void __user *fp, unsigned long size) | ||
| 1762 | { | ||
| 1763 | return (__range_not_ok(fp, size, TASK_SIZE) == 0); | ||
| 1764 | } | ||
| 1765 | |||
| 1759 | #ifdef CONFIG_COMPAT | 1766 | #ifdef CONFIG_COMPAT |
| 1760 | 1767 | ||
| 1761 | #include <asm/compat.h> | 1768 | #include <asm/compat.h> |
| @@ -1780,7 +1787,7 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry) | |||
| 1780 | if (bytes != sizeof(frame)) | 1787 | if (bytes != sizeof(frame)) |
| 1781 | break; | 1788 | break; |
| 1782 | 1789 | ||
| 1783 | if (fp < compat_ptr(regs->sp)) | 1790 | if (!valid_user_frame(fp, sizeof(frame))) |
| 1784 | break; | 1791 | break; |
| 1785 | 1792 | ||
| 1786 | perf_callchain_store(entry, frame.return_address); | 1793 | perf_callchain_store(entry, frame.return_address); |
| @@ -1826,7 +1833,7 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) | |||
| 1826 | if (bytes != sizeof(frame)) | 1833 | if (bytes != sizeof(frame)) |
| 1827 | break; | 1834 | break; |
| 1828 | 1835 | ||
| 1829 | if ((unsigned long)fp < regs->sp) | 1836 | if (!valid_user_frame(fp, sizeof(frame))) |
| 1830 | break; | 1837 | break; |
| 1831 | 1838 | ||
| 1832 | perf_callchain_store(entry, frame.return_address); | 1839 | perf_callchain_store(entry, frame.return_address); |
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index 6638aaf54493..7241e2fc3c17 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h | |||
| @@ -117,6 +117,7 @@ struct cpu_hw_events { | |||
| 117 | struct perf_event *event_list[X86_PMC_IDX_MAX]; /* in enabled order */ | 117 | struct perf_event *event_list[X86_PMC_IDX_MAX]; /* in enabled order */ |
| 118 | 118 | ||
| 119 | unsigned int group_flag; | 119 | unsigned int group_flag; |
| 120 | int is_fake; | ||
| 120 | 121 | ||
| 121 | /* | 122 | /* |
| 122 | * Intel DebugStore bits | 123 | * Intel DebugStore bits |
| @@ -364,6 +365,7 @@ struct x86_pmu { | |||
| 364 | int pebs_record_size; | 365 | int pebs_record_size; |
| 365 | void (*drain_pebs)(struct pt_regs *regs); | 366 | void (*drain_pebs)(struct pt_regs *regs); |
| 366 | struct event_constraint *pebs_constraints; | 367 | struct event_constraint *pebs_constraints; |
| 368 | void (*pebs_aliases)(struct perf_event *event); | ||
| 367 | 369 | ||
| 368 | /* | 370 | /* |
| 369 | * Intel LBR | 371 | * Intel LBR |
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 166546ec6aef..187c294bc658 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c | |||
| @@ -1119,27 +1119,33 @@ intel_bts_constraints(struct perf_event *event) | |||
| 1119 | return NULL; | 1119 | return NULL; |
| 1120 | } | 1120 | } |
| 1121 | 1121 | ||
| 1122 | static bool intel_try_alt_er(struct perf_event *event, int orig_idx) | 1122 | static int intel_alt_er(int idx) |
| 1123 | { | 1123 | { |
| 1124 | if (!(x86_pmu.er_flags & ERF_HAS_RSP_1)) | 1124 | if (!(x86_pmu.er_flags & ERF_HAS_RSP_1)) |
| 1125 | return false; | 1125 | return idx; |
| 1126 | 1126 | ||
| 1127 | if (event->hw.extra_reg.idx == EXTRA_REG_RSP_0) { | 1127 | if (idx == EXTRA_REG_RSP_0) |
| 1128 | event->hw.config &= ~INTEL_ARCH_EVENT_MASK; | 1128 | return EXTRA_REG_RSP_1; |
| 1129 | event->hw.config |= 0x01bb; | 1129 | |
| 1130 | event->hw.extra_reg.idx = EXTRA_REG_RSP_1; | 1130 | if (idx == EXTRA_REG_RSP_1) |
| 1131 | event->hw.extra_reg.reg = MSR_OFFCORE_RSP_1; | 1131 | return EXTRA_REG_RSP_0; |
| 1132 | } else if (event->hw.extra_reg.idx == EXTRA_REG_RSP_1) { | 1132 | |
| 1133 | return idx; | ||
| 1134 | } | ||
| 1135 | |||
| 1136 | static void intel_fixup_er(struct perf_event *event, int idx) | ||
| 1137 | { | ||
| 1138 | event->hw.extra_reg.idx = idx; | ||
| 1139 | |||
| 1140 | if (idx == EXTRA_REG_RSP_0) { | ||
| 1133 | event->hw.config &= ~INTEL_ARCH_EVENT_MASK; | 1141 | event->hw.config &= ~INTEL_ARCH_EVENT_MASK; |
| 1134 | event->hw.config |= 0x01b7; | 1142 | event->hw.config |= 0x01b7; |
| 1135 | event->hw.extra_reg.idx = EXTRA_REG_RSP_0; | ||
| 1136 | event->hw.extra_reg.reg = MSR_OFFCORE_RSP_0; | 1143 | event->hw.extra_reg.reg = MSR_OFFCORE_RSP_0; |
| 1144 | } else if (idx == EXTRA_REG_RSP_1) { | ||
| 1145 | event->hw.config &= ~INTEL_ARCH_EVENT_MASK; | ||
| 1146 | event->hw.config |= 0x01bb; | ||
| 1147 | event->hw.extra_reg.reg = MSR_OFFCORE_RSP_1; | ||
| 1137 | } | 1148 | } |
| 1138 | |||
| 1139 | if (event->hw.extra_reg.idx == orig_idx) | ||
| 1140 | return false; | ||
| 1141 | |||
| 1142 | return true; | ||
| 1143 | } | 1149 | } |
| 1144 | 1150 | ||
| 1145 | /* | 1151 | /* |
| @@ -1157,14 +1163,18 @@ __intel_shared_reg_get_constraints(struct cpu_hw_events *cpuc, | |||
| 1157 | struct event_constraint *c = &emptyconstraint; | 1163 | struct event_constraint *c = &emptyconstraint; |
| 1158 | struct er_account *era; | 1164 | struct er_account *era; |
| 1159 | unsigned long flags; | 1165 | unsigned long flags; |
| 1160 | int orig_idx = reg->idx; | 1166 | int idx = reg->idx; |
| 1161 | 1167 | ||
| 1162 | /* already allocated shared msr */ | 1168 | /* |
| 1163 | if (reg->alloc) | 1169 | * reg->alloc can be set due to existing state, so for fake cpuc we |
| 1170 | * need to ignore this, otherwise we might fail to allocate proper fake | ||
| 1171 | * state for this extra reg constraint. Also see the comment below. | ||
| 1172 | */ | ||
| 1173 | if (reg->alloc && !cpuc->is_fake) | ||
| 1164 | return NULL; /* call x86_get_event_constraint() */ | 1174 | return NULL; /* call x86_get_event_constraint() */ |
| 1165 | 1175 | ||
| 1166 | again: | 1176 | again: |
| 1167 | era = &cpuc->shared_regs->regs[reg->idx]; | 1177 | era = &cpuc->shared_regs->regs[idx]; |
| 1168 | /* | 1178 | /* |
| 1169 | * we use spin_lock_irqsave() to avoid lockdep issues when | 1179 | * we use spin_lock_irqsave() to avoid lockdep issues when |
| 1170 | * passing a fake cpuc | 1180 | * passing a fake cpuc |
| @@ -1173,6 +1183,29 @@ again: | |||
| 1173 | 1183 | ||
| 1174 | if (!atomic_read(&era->ref) || era->config == reg->config) { | 1184 | if (!atomic_read(&era->ref) || era->config == reg->config) { |
| 1175 | 1185 | ||
| 1186 | /* | ||
| 1187 | * If its a fake cpuc -- as per validate_{group,event}() we | ||
| 1188 | * shouldn't touch event state and we can avoid doing so | ||
| 1189 | * since both will only call get_event_constraints() once | ||
| 1190 | * on each event, this avoids the need for reg->alloc. | ||
| 1191 | * | ||
| 1192 | * Not doing the ER fixup will only result in era->reg being | ||
| 1193 | * wrong, but since we won't actually try and program hardware | ||
| 1194 | * this isn't a problem either. | ||
| 1195 | */ | ||
| 1196 | if (!cpuc->is_fake) { | ||
