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 | |
| 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')
| -rw-r--r-- | arch/x86/include/asm/uaccess.h | 12 | ||||
| -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 | ||||
| -rw-r--r-- | arch/x86/lib/usercopy.c | 4 | ||||
| -rw-r--r-- | arch/x86/lib/x86-opcode-map.txt | 8 | ||||
| -rw-r--r-- | arch/x86/tools/gen-insn-attr-x86.awk | 14 |
8 files changed, 143 insertions, 62 deletions
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index 04cd6882308e..e1f3a17034fc 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h | |||
| @@ -33,9 +33,8 @@ | |||
| 33 | #define segment_eq(a, b) ((a).seg == (b).seg) | 33 | #define segment_eq(a, b) ((a).seg == (b).seg) |
| 34 | 34 | ||
| 35 | #define user_addr_max() (current_thread_info()->addr_limit.seg) | 35 | #define user_addr_max() (current_thread_info()->addr_limit.seg) |
| 36 | #define __addr_ok(addr) \ | 36 | #define __addr_ok(addr) \ |
| 37 | ((unsigned long __force)(addr) < \ | 37 | ((unsigned long __force)(addr) < user_addr_max()) |
| 38 | (current_thread_info()->addr_limit.seg)) | ||
| 39 | 38 | ||
| 40 | /* | 39 | /* |
| 41 | * Test whether a block of memory is a valid user space address. | 40 | * Test whether a block of memory is a valid user space address. |
| @@ -47,14 +46,14 @@ | |||
| 47 | * This needs 33-bit (65-bit for x86_64) arithmetic. We have a carry... | 46 | * This needs 33-bit (65-bit for x86_64) arithmetic. We have a carry... |
| 48 | */ | 47 | */ |
| 49 | 48 | ||
| 50 | #define __range_not_ok(addr, size) \ | 49 | #define __range_not_ok(addr, size, limit) \ |
| 51 | ({ \ | 50 | ({ \ |
| 52 | unsigned long flag, roksum; \ | 51 | unsigned long flag, roksum; \ |
| 53 | __chk_user_ptr(addr); \ | 52 | __chk_user_ptr(addr); \ |
| 54 | asm("add %3,%1 ; sbb %0,%0 ; cmp %1,%4 ; sbb $0,%0" \ | 53 | asm("add %3,%1 ; sbb %0,%0 ; cmp %1,%4 ; sbb $0,%0" \ |
| 55 | : "=&r" (flag), "=r" (roksum) \ | 54 | : "=&r" (flag), "=r" (roksum) \ |
| 56 | : "1" (addr), "g" ((long)(size)), \ | 55 | : "1" (addr), "g" ((long)(size)), \ |
| 57 | "rm" (current_thread_info()->addr_limit.seg)); \ | 56 | "rm" (limit)); \ |
| 58 | flag; \ | 57 | flag; \ |
| 59 | }) | 58 | }) |
| 60 | 59 | ||
| @@ -77,7 +76,8 @@ | |||
| 77 | * checks that the pointer is in the user space range - after calling | 76 | * checks that the pointer is in the user space range - after calling |
| 78 | * this function, memory access functions may still return -EFAULT. | 77 | * this function, memory access functions may still return -EFAULT. |
| 79 | */ | 78 | */ |
| 80 | #define access_ok(type, addr, size) (likely(__range_not_ok(addr, size) == 0)) | 79 | #define access_ok(type, addr, size) \ |
| 80 | (likely(__range_not_ok(addr, size, user_addr_max()) == 0)) | ||
| 81 | 81 | ||
| 82 | /* | 82 | /* |
| 83 | * The exception table consists of pairs of addresses relative to the | 83 | * The exception table consists of pairs of addresses relative to the |
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; | ||
