Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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
...

+357 -120
+6 -6
arch/x86/include/asm/uaccess.h
··· 33 33 #define segment_eq(a, b) ((a).seg == (b).seg) 34 34 35 35 #define user_addr_max() (current_thread_info()->addr_limit.seg) 36 - #define __addr_ok(addr) \ 37 - ((unsigned long __force)(addr) < \ 38 - (current_thread_info()->addr_limit.seg)) 36 + #define __addr_ok(addr) \ 37 + ((unsigned long __force)(addr) < user_addr_max()) 39 38 40 39 /* 41 40 * Test whether a block of memory is a valid user space address. ··· 46 47 * This needs 33-bit (65-bit for x86_64) arithmetic. We have a carry... 47 48 */ 48 49 49 - #define __range_not_ok(addr, size) \ 50 + #define __range_not_ok(addr, size, limit) \ 50 51 ({ \ 51 52 unsigned long flag, roksum; \ 52 53 __chk_user_ptr(addr); \ 53 54 asm("add %3,%1 ; sbb %0,%0 ; cmp %1,%4 ; sbb $0,%0" \ 54 55 : "=&r" (flag), "=r" (roksum) \ 55 56 : "1" (addr), "g" ((long)(size)), \ 56 - "rm" (current_thread_info()->addr_limit.seg)); \ 57 + "rm" (limit)); \ 57 58 flag; \ 58 59 }) 59 60 ··· 76 77 * checks that the pointer is in the user space range - after calling 77 78 * this function, memory access functions may still return -EFAULT. 78 79 */ 79 - #define access_ok(type, addr, size) (likely(__range_not_ok(addr, size) == 0)) 80 + #define access_ok(type, addr, size) \ 81 + (likely(__range_not_ok(addr, size, user_addr_max()) == 0)) 80 82 81 83 /* 82 84 * The exception table consists of pairs of addresses relative to the
+9 -2
arch/x86/kernel/cpu/perf_event.c
··· 1496 1496 if (!cpuc->shared_regs) 1497 1497 goto error; 1498 1498 } 1499 + cpuc->is_fake = 1; 1499 1500 return cpuc; 1500 1501 error: 1501 1502 free_fake_cpuc(cpuc); ··· 1757 1756 dump_trace(NULL, regs, NULL, 0, &backtrace_ops, entry); 1758 1757 } 1759 1758 1759 + static inline int 1760 + valid_user_frame(const void __user *fp, unsigned long size) 1761 + { 1762 + return (__range_not_ok(fp, size, TASK_SIZE) == 0); 1763 + } 1764 + 1760 1765 #ifdef CONFIG_COMPAT 1761 1766 1762 1767 #include <asm/compat.h> ··· 1787 1780 if (bytes != sizeof(frame)) 1788 1781 break; 1789 1782 1790 - if (fp < compat_ptr(regs->sp)) 1783 + if (!valid_user_frame(fp, sizeof(frame))) 1791 1784 break; 1792 1785 1793 1786 perf_callchain_store(entry, frame.return_address); ··· 1833 1826 if (bytes != sizeof(frame)) 1834 1827 break; 1835 1828 1836 - if ((unsigned long)fp < regs->sp) 1829 + if (!valid_user_frame(fp, sizeof(frame))) 1837 1830 break; 1838 1831 1839 1832 perf_callchain_store(entry, frame.return_address);
+2
arch/x86/kernel/cpu/perf_event.h
··· 117 117 struct perf_event *event_list[X86_PMC_IDX_MAX]; /* in enabled order */ 118 118 119 119 unsigned int group_flag; 120 + int is_fake; 120 121 121 122 /* 122 123 * Intel DebugStore bits ··· 365 364 int pebs_record_size; 366 365 void (*drain_pebs)(struct pt_regs *regs); 367 366 struct event_constraint *pebs_constraints; 367 + void (*pebs_aliases)(struct perf_event *event); 368 368 369 369 /* 370 370 * Intel LBR
+108 -37
arch/x86/kernel/cpu/perf_event_intel.c
··· 1119 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 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) { 1128 - event->hw.config &= ~INTEL_ARCH_EVENT_MASK; 1129 - event->hw.config |= 0x01bb; 1130 - event->hw.extra_reg.idx = EXTRA_REG_RSP_1; 1131 - event->hw.extra_reg.reg = MSR_OFFCORE_RSP_1; 1132 - } else if (event->hw.extra_reg.idx == EXTRA_REG_RSP_1) { 1127 + if (idx == EXTRA_REG_RSP_0) 1128 + return EXTRA_REG_RSP_1; 1129 + 1130 + if (idx == EXTRA_REG_RSP_1) 1131 + return EXTRA_REG_RSP_0; 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 1141 event->hw.config &= ~INTEL_ARCH_EVENT_MASK; 1134 1142 event->hw.config |= 0x01b7; 1135 - event->hw.extra_reg.idx = EXTRA_REG_RSP_0; 1136 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 /* ··· 1163 1157 struct event_constraint *c = &emptyconstraint; 1164 1158 struct er_account *era; 1165 1159 unsigned long flags; 1166 - int orig_idx = reg->idx; 1160 + int idx = reg->idx; 1167 1161 1168 - /* already allocated shared msr */ 1169 - if (reg->alloc) 1162 + /* 1163 + * reg->alloc can be set due to existing state, so for fake cpuc we 1164 + * need to ignore this, otherwise we might fail to allocate proper fake 1165 + * state for this extra reg constraint. Also see the comment below. 1166 + */ 1167 + if (reg->alloc && !cpuc->is_fake) 1170 1168 return NULL; /* call x86_get_event_constraint() */ 1171 1169 1172 1170 again: 1173 - era = &cpuc->shared_regs->regs[reg->idx]; 1171 + era = &cpuc->shared_regs->regs[idx]; 1174 1172 /* 1175 1173 * we use spin_lock_irqsave() to avoid lockdep issues when 1176 1174 * passing a fake cpuc ··· 1183 1173 1184 1174 if (!atomic_read(&era->ref) || era->config == reg->config) { 1185 1175 1176 + /* 1177 + * If its a fake cpuc -- as per validate_{group,event}() we 1178 + * shouldn't touch event state and we can avoid doing so 1179 + * since both will only call get_event_constraints() once 1180 + * on each event, this avoids the need for reg->alloc. 1181 + * 1182 + * Not doing the ER fixup will only result in era->reg being 1183 + * wrong, but since we won't actually try and program hardware 1184 + * this isn't a problem either. 1185 + */ 1186 + if (!cpuc->is_fake) { 1187 + if (idx != reg->idx) 1188 + intel_fixup_er(event, idx); 1189 + 1190 + /* 1191 + * x86_schedule_events() can call get_event_constraints() 1192 + * multiple times on events in the case of incremental 1193 + * scheduling(). reg->alloc ensures we only do the ER 1194 + * allocation once. 1195 + */ 1196 + reg->alloc = 1; 1197 + } 1198 + 1186 1199 /* lock in msr value */ 1187 1200 era->config = reg->config; 1188 1201 era->reg = reg->reg; ··· 1213 1180 /* one more user */ 1214 1181 atomic_inc(&era->ref); 1215 1182 1216 - /* no need to reallocate during incremental event scheduling */ 1217 - reg->alloc = 1; 1218 - 1219 1183 /* 1220 1184 * need to call x86_get_event_constraint() 1221 1185 * to check if associated event has constraints 1222 1186 */ 1223 1187 c = NULL; 1224 - } else if (intel_try_alt_er(event, orig_idx)) { 1225 - raw_spin_unlock_irqrestore(&era->lock, flags); 1226 - goto again; 1188 + } else { 1189 + idx = intel_alt_er(idx); 1190 + if (idx != reg->idx) { 1191 + raw_spin_unlock_irqrestore(&era->lock, flags); 1192 + goto again; 1193 + } 1227 1194 } 1228 1195 raw_spin_unlock_irqrestore(&era->lock, flags); 1229 1196 ··· 1237 1204 struct er_account *era; 1238 1205 1239 1206 /* 1240 - * only put constraint if extra reg was actually 1241 - * allocated. Also takes care of event which do 1242 - * not use an extra shared reg 1207 + * Only put constraint if extra reg was actually allocated. Also takes 1208 + * care of event which do not use an extra shared reg. 1209 + * 1210 + * Also, if this is a fake cpuc we shouldn't touch any event state 1211 + * (reg->alloc) and we don't care about leaving inconsistent cpuc state 1212 + * either since it'll be thrown out. 1243 1213 */ 1244 - if (!reg->alloc) 1214 + if (!reg->alloc || cpuc->is_fake) 1245 1215 return; 1246 1216 1247 1217 era = &cpuc->shared_regs->regs[reg->idx]; ··· 1336 1300 intel_put_shared_regs_event_constraints(cpuc, event); 1337 1301 } 1338 1302 1339 - static int intel_pmu_hw_config(struct perf_event *event) 1303 + static void intel_pebs_aliases_core2(struct perf_event *event) 1340 1304 { 1341 - int ret = x86_pmu_hw_config(event); 1342 - 1343 - if (ret) 1344 - return ret; 1345 - 1346 - if (event->attr.precise_ip && 1347 - (event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) { 1305 + if ((event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) { 1348 1306 /* 1349 1307 * Use an alternative encoding for CPU_CLK_UNHALTED.THREAD_P 1350 1308 * (0x003c) so that we can use it with PEBS. ··· 1359 1329 */ 1360 1330 u64 alt_config = X86_CONFIG(.event=0xc0, .inv=1, .cmask=16); 1361 1331 1332 + alt_config |= (event->hw.config & ~X86_RAW_EVENT_MASK); 1333 + event->hw.config = alt_config; 1334 + } 1335 + } 1336 + 1337 + static void intel_pebs_aliases_snb(struct perf_event *event) 1338 + { 1339 + if ((event->hw.config & X86_RAW_EVENT_MASK) == 0x003c) { 1340 + /* 1341 + * Use an alternative encoding for CPU_CLK_UNHALTED.THREAD_P 1342 + * (0x003c) so that we can use it with PEBS. 1343 + * 1344 + * The regular CPU_CLK_UNHALTED.THREAD_P event (0x003c) isn't 1345 + * PEBS capable. However we can use UOPS_RETIRED.ALL 1346 + * (0x01c2), which is a PEBS capable event, to get the same 1347 + * count. 1348 + * 1349 + * UOPS_RETIRED.ALL counts the number of cycles that retires 1350 + * CNTMASK micro-ops. By setting CNTMASK to a value (16) 1351 + * larger than the maximum number of micro-ops that can be 1352 + * retired per cycle (4) and then inverting the condition, we 1353 + * count all cycles that retire 16 or less micro-ops, which 1354 + * is every cycle. 1355 + * 1356 + * Thereby we gain a PEBS capable cycle counter. 1357 + */ 1358 + u64 alt_config = X86_CONFIG(.event=0xc2, .umask=0x01, .inv=1, .cmask=16); 1362 1359 1363 1360 alt_config |= (event->hw.config & ~X86_RAW_EVENT_MASK); 1364 1361 event->hw.config = alt_config; 1365 1362 } 1363 + } 1364 + 1365 + static int intel_pmu_hw_config(struct perf_event *event) 1366 + { 1367 + int ret = x86_pmu_hw_config(event); 1368 + 1369 + if (ret) 1370 + return ret; 1371 + 1372 + if (event->attr.precise_ip && x86_pmu.pebs_aliases) 1373 + x86_pmu.pebs_aliases(event); 1366 1374 1367 1375 if (intel_pmu_needs_lbr_smpl(event)) { 1368 1376 ret = intel_pmu_setup_lbr_filter(event); ··· 1675 1607 .max_period = (1ULL << 31) - 1, 1676 1608 .get_event_constraints = intel_get_event_constraints, 1677 1609 .put_event_constraints = intel_put_event_constraints, 1610 + .pebs_aliases = intel_pebs_aliases_core2, 1678 1611 1679 1612 .format_attrs = intel_arch3_formats_attr, 1680 1613 ··· 1909 1840 break; 1910 1841 1911 1842 case 42: /* SandyBridge */ 1912 - x86_add_quirk(intel_sandybridge_quirk); 1913 1843 case 45: /* SandyBridge, "Romely-EP" */ 1844 + x86_add_quirk(intel_sandybridge_quirk); 1845 + case 58: /* IvyBridge */ 1914 1846 memcpy(hw_cache_event_ids, snb_hw_cache_event_ids, 1915 1847 sizeof(hw_cache_event_ids)); 1916 1848 ··· 1919 1849 1920 1850 x86_pmu.event_constraints = intel_snb_event_constraints; 1921 1851 x86_pmu.pebs_constraints = intel_snb_pebs_event_constraints; 1852 + x86_pmu.pebs_aliases = intel_pebs_aliases_snb; 1922 1853 x86_pmu.extra_regs = intel_snb_extra_regs; 1923 1854 /* all extra regs are per-cpu when HT is on */ 1924 1855 x86_pmu.er_flags |= ERF_HAS_RSP_1;
+1 -8
arch/x86/kernel/cpu/perf_event_intel_ds.c
··· 400 400 INTEL_EVENT_CONSTRAINT(0xc4, 0xf), /* BR_INST_RETIRED.* */ 401 401 INTEL_EVENT_CONSTRAINT(0xc5, 0xf), /* BR_MISP_RETIRED.* */ 402 402 INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.* */ 403 - INTEL_UEVENT_CONSTRAINT(0x11d0, 0xf), /* MEM_UOP_RETIRED.STLB_MISS_LOADS */ 404 - INTEL_UEVENT_CONSTRAINT(0x12d0, 0xf), /* MEM_UOP_RETIRED.STLB_MISS_STORES */ 405 - INTEL_UEVENT_CONSTRAINT(0x21d0, 0xf), /* MEM_UOP_RETIRED.LOCK_LOADS */ 406 - INTEL_UEVENT_CONSTRAINT(0x22d0, 0xf), /* MEM_UOP_RETIRED.LOCK_STORES */ 407 - INTEL_UEVENT_CONSTRAINT(0x41d0, 0xf), /* MEM_UOP_RETIRED.SPLIT_LOADS */ 408 - INTEL_UEVENT_CONSTRAINT(0x42d0, 0xf), /* MEM_UOP_RETIRED.SPLIT_STORES */ 409 - INTEL_UEVENT_CONSTRAINT(0x81d0, 0xf), /* MEM_UOP_RETIRED.ANY_LOADS */ 410 - INTEL_UEVENT_CONSTRAINT(0x82d0, 0xf), /* MEM_UOP_RETIRED.ANY_STORES */ 403 + INTEL_EVENT_CONSTRAINT(0xd0, 0xf), /* MEM_UOP_RETIRED.* */ 411 404 INTEL_EVENT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */ 412 405 INTEL_EVENT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */ 413 406 INTEL_UEVENT_CONSTRAINT(0x02d4, 0xf), /* MEM_LOAD_UOPS_MISC_RETIRED.LLC_MISS */
+4
arch/x86/lib/usercopy.c
··· 8 8 #include <linux/module.h> 9 9 10 10 #include <asm/word-at-a-time.h> 11 + #include <linux/sched.h> 11 12 12 13 /* 13 14 * best effort, GUP based copy_from_user() that is NMI-safe ··· 21 20 struct page *page; 22 21 void *map; 23 22 int ret; 23 + 24 + if (__range_not_ok(from, n, TASK_SIZE) == 0) 25 + return len; 24 26 25 27 do { 26 28 ret = __get_user_pages_fast(addr, 1, 0, &page);
+4 -4
arch/x86/lib/x86-opcode-map.txt
··· 28 28 # - (66): the last prefix is 0x66 29 29 # - (F3): the last prefix is 0xF3 30 30 # - (F2): the last prefix is 0xF2 31 - # 31 + # - (!F3) : the last prefix is not 0xF3 (including non-last prefix case) 32 32 33 33 Table: one byte opcode 34 34 Referrer: ··· 515 515 b5: LGS Gv,Mp 516 516 b6: MOVZX Gv,Eb 517 517 b7: MOVZX Gv,Ew 518 - b8: JMPE | POPCNT Gv,Ev (F3) 518 + b8: JMPE (!F3) | POPCNT Gv,Ev (F3) 519 519 b9: Grp10 (1A) 520 520 ba: Grp8 Ev,Ib (1A) 521 521 bb: BTC Ev,Gv 522 - bc: BSF Gv,Ev | TZCNT Gv,Ev (F3) 523 - bd: BSR Gv,Ev | LZCNT Gv,Ev (F3) 522 + bc: BSF Gv,Ev (!F3) | TZCNT Gv,Ev (F3) 523 + bd: BSR Gv,Ev (!F3) | LZCNT Gv,Ev (F3) 524 524 be: MOVSX Gv,Eb 525 525 bf: MOVSX Gv,Ew 526 526 # 0x0f 0xc0-0xcf
+9 -5
arch/x86/tools/gen-insn-attr-x86.awk
··· 66 66 rex_expr = "^REX(\\.[XRWB]+)*" 67 67 fpu_expr = "^ESC" # TODO 68 68 69 - lprefix1_expr = "\\(66\\)" 69 + lprefix1_expr = "\\((66|!F3)\\)" 70 70 lprefix2_expr = "\\(F3\\)" 71 - lprefix3_expr = "\\(F2\\)" 71 + lprefix3_expr = "\\((F2|!F3)\\)" 72 + lprefix_expr = "\\((66|F2|F3)\\)" 72 73 max_lprefix = 4 73 74 74 75 # All opcodes starting with lower-case 'v' or with (v1) superscript ··· 334 333 if (match(ext, lprefix1_expr)) { 335 334 lptable1[idx] = add_flags(lptable1[idx],flags) 336 335 variant = "INAT_VARIANT" 337 - } else if (match(ext, lprefix2_expr)) { 336 + } 337 + if (match(ext, lprefix2_expr)) { 338 338 lptable2[idx] = add_flags(lptable2[idx],flags) 339 339 variant = "INAT_VARIANT" 340 - } else if (match(ext, lprefix3_expr)) { 340 + } 341 + if (match(ext, lprefix3_expr)) { 341 342 lptable3[idx] = add_flags(lptable3[idx],flags) 342 343 variant = "INAT_VARIANT" 343 - } else { 344 + } 345 + if (!match(ext, lprefix_expr)){ 344 346 table[idx] = add_flags(table[idx],flags) 345 347 } 346 348 }
+2 -2
include/linux/perf_event.h
··· 555 555 PERF_RECORD_MAX, /* non-ABI */ 556 556 }; 557 557 558 + #define PERF_MAX_STACK_DEPTH 127 559 + 558 560 enum perf_callchain_context { 559 561 PERF_CONTEXT_HV = (__u64)-32, 560 562 PERF_CONTEXT_KERNEL = (__u64)-128, ··· 610 608 #include <linux/atomic.h> 611 609 #include <linux/sysfs.h> 612 610 #include <asm/local.h> 613 - 614 - #define PERF_MAX_STACK_DEPTH 255 615 611 616 612 struct perf_callchain_entry { 617 613 __u64 nr;
-1
kernel/events/core.c
··· 3181 3181 event = event->group_leader; 3182 3182 3183 3183 perf_event_for_each_child(event, func); 3184 - func(event); 3185 3184 list_for_each_entry(sibling, &event->sibling_list, group_entry) 3186 3185 perf_event_for_each_child(sibling, func); 3187 3186 mutex_unlock(&ctx->mutex);
+2
tools/perf/MANIFEST
··· 1 1 tools/perf 2 + tools/scripts 3 + tools/lib/traceevent 2 4 include/linux/const.h 3 5 include/linux/perf_event.h 4 6 include/linux/rbtree.h
+2 -2
tools/perf/builtin-report.c
··· 152 152 153 153 if (symbol_conf.use_callchain) { 154 154 err = callchain_append(he->callchain, 155 - &evsel->hists.callchain_cursor, 155 + &callchain_cursor, 156 156 sample->period); 157 157 if (err) 158 158 return err; ··· 162 162 * so we don't allocated the extra space needed because the stdio 163 163 * code will not use it. 164 164 */ 165 - if (al->sym != NULL && use_browser > 0) { 165 + if (he->ms.sym != NULL && use_browser > 0) { 166 166 struct annotation *notes = symbol__annotation(he->ms.sym); 167 167 168 168 assert(evsel != NULL);
+4 -4
tools/perf/builtin-stat.c
··· 1129 1129 return 0; 1130 1130 1131 1131 if (!evsel_list->nr_entries) { 1132 - if (perf_evlist__add_attrs_array(evsel_list, default_attrs) < 0) 1132 + if (perf_evlist__add_default_attrs(evsel_list, default_attrs) < 0) 1133 1133 return -1; 1134 1134 } 1135 1135 ··· 1139 1139 return 0; 1140 1140 1141 1141 /* Append detailed run extra attributes: */ 1142 - if (perf_evlist__add_attrs_array(evsel_list, detailed_attrs) < 0) 1142 + if (perf_evlist__add_default_attrs(evsel_list, detailed_attrs) < 0) 1143 1143 return -1; 1144 1144 1145 1145 if (detailed_run < 2) 1146 1146 return 0; 1147 1147 1148 1148 /* Append very detailed run extra attributes: */ 1149 - if (perf_evlist__add_attrs_array(evsel_list, very_detailed_attrs) < 0) 1149 + if (perf_evlist__add_default_attrs(evsel_list, very_detailed_attrs) < 0) 1150 1150 return -1; 1151 1151 1152 1152 if (detailed_run < 3) 1153 1153 return 0; 1154 1154 1155 1155 /* Append very, very detailed run extra attributes: */ 1156 - return perf_evlist__add_attrs_array(evsel_list, very_very_detailed_attrs); 1156 + return perf_evlist__add_default_attrs(evsel_list, very_very_detailed_attrs); 1157 1157 } 1158 1158 1159 1159 int cmd_stat(int argc, const char **argv, const char *prefix __used)
+1 -1
tools/perf/builtin-top.c
··· 787 787 } 788 788 789 789 if (symbol_conf.use_callchain) { 790 - err = callchain_append(he->callchain, &evsel->hists.callchain_cursor, 790 + err = callchain_append(he->callchain, &callchain_cursor, 791 791 sample->period); 792 792 if (err) 793 793 return;
+4 -3
tools/perf/design.txt
··· 409 409 prctl. When a counter is disabled, it doesn't count or generate 410 410 events but does continue to exist and maintain its count value. 411 411 412 - An individual counter or counter group can be enabled with 412 + An individual counter can be enabled with 413 413 414 - ioctl(fd, PERF_EVENT_IOC_ENABLE); 414 + ioctl(fd, PERF_EVENT_IOC_ENABLE, 0); 415 415 416 416 or disabled with 417 417 418 - ioctl(fd, PERF_EVENT_IOC_DISABLE); 418 + ioctl(fd, PERF_EVENT_IOC_DISABLE, 0); 419 419 420 + For a counter group, pass PERF_IOC_FLAG_GROUP as the third argument. 420 421 Enabling or disabling the leader of a group enables or disables the 421 422 whole group; that is, while the group leader is disabled, none of the 422 423 counters in the group will count. Enabling or disabling a member of a
+1 -1
tools/perf/ui/browsers/annotate.c
··· 668 668 "q/ESC/CTRL+C Exit\n\n" 669 669 "-> Go to target\n" 670 670 "<- Exit\n" 671 - "h Cycle thru hottest instructions\n" 671 + "H Cycle thru hottest instructions\n" 672 672 "j Toggle showing jump to target arrows\n" 673 673 "J Toggle showing number of jump sources on targets\n" 674 674 "n Search next string\n"
+1 -1
tools/perf/util/PERF-VERSION-GEN
··· 12 12 # First check if there is a .git to get the version from git describe 13 13 # otherwise try to get the version from the kernel makefile 14 14 if test -d ../../.git -o -f ../../.git && 15 - VN=$(git describe --abbrev=4 HEAD 2>/dev/null) && 15 + VN=$(git describe --match 'v[0-9].[0-9]*' --abbrev=4 HEAD 2>/dev/null) && 16 16 case "$VN" in 17 17 *$LF*) (exit 1) ;; 18 18 v[0-9]*)
+2
tools/perf/util/callchain.c
··· 18 18 #include "util.h" 19 19 #include "callchain.h" 20 20 21 + __thread struct callchain_cursor callchain_cursor; 22 + 21 23 bool ip_callchain__valid(struct ip_callchain *chain, 22 24 const union perf_event *event) 23 25 {
+2
tools/perf/util/callchain.h
··· 76 76 struct callchain_cursor_node *curr; 77 77 }; 78 78 79 + extern __thread struct callchain_cursor callchain_cursor; 80 + 79 81 static inline void callchain_init(struct callchain_root *root) 80 82 { 81 83 INIT_LIST_HEAD(&root->node.siblings);
+15 -2
tools/perf/util/evlist.c
··· 159 159 return -1; 160 160 } 161 161 162 + int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, 163 + struct perf_event_attr *attrs, size_t nr_attrs) 164 + { 165 + size_t i; 166 + 167 + for (i = 0; i < nr_attrs; i++) 168 + event_attr_init(attrs + i); 169 + 170 + return perf_evlist__add_attrs(evlist, attrs, nr_attrs); 171 + } 172 + 162 173 static int trace_event__id(const char *evname) 163 174 { 164 175 char *filename, *colon; ··· 274 263 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 275 264 list_for_each_entry(pos, &evlist->entries, node) { 276 265 for (thread = 0; thread < evlist->threads->nr; thread++) 277 - ioctl(FD(pos, cpu, thread), PERF_EVENT_IOC_DISABLE); 266 + ioctl(FD(pos, cpu, thread), 267 + PERF_EVENT_IOC_DISABLE, 0); 278 268 } 279 269 } 280 270 } ··· 288 276 for (cpu = 0; cpu < evlist->cpus->nr; cpu++) { 289 277 list_for_each_entry(pos, &evlist->entries, node) { 290 278 for (thread = 0; thread < evlist->threads->nr; thread++) 291 - ioctl(FD(pos, cpu, thread), PERF_EVENT_IOC_ENABLE); 279 + ioctl(FD(pos, cpu, thread), 280 + PERF_EVENT_IOC_ENABLE, 0); 292 281 } 293 282 } 294 283 }
+4
tools/perf/util/evlist.h
··· 54 54 int perf_evlist__add_default(struct perf_evlist *evlist); 55 55 int perf_evlist__add_attrs(struct perf_evlist *evlist, 56 56 struct perf_event_attr *attrs, size_t nr_attrs); 57 + int __perf_evlist__add_default_attrs(struct perf_evlist *evlist, 58 + struct perf_event_attr *attrs, size_t nr_attrs); 57 59 int perf_evlist__add_tracepoints(struct perf_evlist *evlist, 58 60 const char *tracepoints[], size_t nr_tracepoints); 59 61 int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist, ··· 64 62 65 63 #define perf_evlist__add_attrs_array(evlist, array) \ 66 64 perf_evlist__add_attrs(evlist, array, ARRAY_SIZE(array)) 65 + #define perf_evlist__add_default_attrs(evlist, array) \ 66 + __perf_evlist__add_default_attrs(evlist, array, ARRAY_SIZE(array)) 67 67 68 68 #define perf_evlist__add_tracepoints_array(evlist, array) \ 69 69 perf_evlist__add_tracepoints(evlist, array, ARRAY_SIZE(array))
+22 -7
tools/perf/util/evsel.c
··· 494 494 } 495 495 496 496 static int perf_event__parse_id_sample(const union perf_event *event, u64 type, 497 - struct perf_sample *sample) 497 + struct perf_sample *sample, 498 + bool swapped) 498 499 { 499 500 const u64 *array = event->sample.array; 501 + union u64_swap u; 500 502 501 503 array += ((event->header.size - 502 504 sizeof(event->header)) / sizeof(u64)) - 1; 503 505 504 506 if (type & PERF_SAMPLE_CPU) { 505 - u32 *p = (u32 *)array; 506 - sample->cpu = *p; 507 + u.val64 = *array; 508 + if (swapped) { 509 + /* undo swap of u64, then swap on individual u32s */ 510 + u.val64 = bswap_64(u.val64); 511 + u.val32[0] = bswap_32(u.val32[0]); 512 + } 513 + 514 + sample->cpu = u.val32[0]; 507 515 array--; 508 516 } 509 517 ··· 531 523 } 532 524 533 525 if (type & PERF_SAMPLE_TID) { 534 - u32 *p = (u32 *)array; 535 - sample->pid = p[0]; 536 - sample->tid = p[1]; 526 + u.val64 = *array; 527 + if (swapped) { 528 + /* undo swap of u64, then swap on individual u32s */ 529 + u.val64 = bswap_64(u.val64); 530 + u.val32[0] = bswap_32(u.val32[0]); 531 + u.val32[1] = bswap_32(u.val32[1]); 532 + } 533 + 534 + sample->pid = u.val32[0]; 535 + sample->tid = u.val32[1]; 537 536 } 538 537 539 538 return 0; ··· 577 562 if (event->header.type != PERF_RECORD_SAMPLE) { 578 563 if (!sample_id_all) 579 564 return 0; 580 - return perf_event__parse_id_sample(event, type, data); 565 + return perf_event__parse_id_sample(event, type, data, swapped); 581 566 } 582 567 583 568 array = event->sample.array;
+4 -3
tools/perf/util/hist.c
··· 378 378 * collapse the histogram 379 379 */ 380 380 381 - static bool hists__collapse_insert_entry(struct hists *hists, 381 + static bool hists__collapse_insert_entry(struct hists *hists __used, 382 382 struct rb_root *root, 383 383 struct hist_entry *he) 384 384 { ··· 397 397 iter->period += he->period; 398 398 iter->nr_events += he->nr_events; 399 399 if (symbol_conf.use_callchain) { 400 - callchain_cursor_reset(&hists->callchain_cursor); 401 - callchain_merge(&hists->callchain_cursor, iter->callchain, 400 + callchain_cursor_reset(&callchain_cursor); 401 + callchain_merge(&callchain_cursor, 402 + iter->callchain, 402 403 he->callchain); 403 404 } 404 405 hist_entry__free(he);
-2
tools/perf/util/hist.h
··· 67 67 struct events_stats stats; 68 68 u64 event_stream; 69 69 u16 col_len[HISTC_NR_COLS]; 70 - /* Best would be to reuse the session callchain cursor */ 71 - struct callchain_cursor callchain_cursor; 72 70 }; 73 71 74 72 struct hist_entry *__hists__add_entry(struct hists *self,
+4
tools/perf/util/pager.c
··· 57 57 } 58 58 if (!pager) 59 59 pager = getenv("PAGER"); 60 + if (!pager) { 61 + if (!access("/usr/bin/pager", X_OK)) 62 + pager = "/usr/bin/pager"; 63 + } 60 64 if (!pager) 61 65 pager = "less"; 62 66 else if (!*pager || !strcmp(pager, "cat"))
+2 -6
tools/perf/util/probe-event.c
··· 2164 2164 2165 2165 error: 2166 2166 if (kfd >= 0) { 2167 - if (namelist) 2168 - strlist__delete(namelist); 2169 - 2167 + strlist__delete(namelist); 2170 2168 close(kfd); 2171 2169 } 2172 2170 2173 2171 if (ufd >= 0) { 2174 - if (unamelist) 2175 - strlist__delete(unamelist); 2176 - 2172 + strlist__delete(unamelist); 2177 2173 close(ufd); 2178 2174 } 2179 2175
+76 -21
tools/perf/util/session.c
··· 288 288 return bi; 289 289 } 290 290 291 - int machine__resolve_callchain(struct machine *self, struct perf_evsel *evsel, 291 + int machine__resolve_callchain(struct machine *self, 292 + struct perf_evsel *evsel __used, 292 293 struct thread *thread, 293 294 struct ip_callchain *chain, 294 295 struct symbol **parent) ··· 298 297 unsigned int i; 299 298 int err; 300 299 301 - callchain_cursor_reset(&evsel->hists.callchain_cursor); 300 + callchain_cursor_reset(&callchain_cursor); 301 + 302 + if (chain->nr > PERF_MAX_STACK_DEPTH) { 303 + pr_warning("corrupted callchain. skipping...\n"); 304 + return 0; 305 + } 302 306 303 307 for (i = 0; i < chain->nr; i++) { 304 308 u64 ip; ··· 323 317 case PERF_CONTEXT_USER: 324 318 cpumode = PERF_RECORD_MISC_USER; break; 325 319 default: 326 - break; 320 + pr_debug("invalid callchain context: " 321 + "%"PRId64"\n", (s64) ip); 322 + /* 323 + * It seems the callchain is corrupted. 324 + * Discard all. 325 + */ 326 + callchain_cursor_reset(&callchain_cursor); 327 + return 0; 327 328 } 328 329 continue; 329 330 } ··· 346 333 break; 347 334 } 348 335 349 - err = callchain_cursor_append(&evsel->hists.callchain_cursor, 336 + err = callchain_cursor_append(&callchain_cursor, 350 337 ip, al.map, al.sym); 351 338 if (err) 352 339 return err; ··· 454 441 } 455 442 } 456 443 457 - static void perf_event__all64_swap(union perf_event *event) 444 + static void swap_sample_id_all(union perf_event *event, void *data) 445 + { 446 + void *end = (void *) event + event->header.size; 447 + int size = end - data; 448 + 449 + BUG_ON(size % sizeof(u64)); 450 + mem_bswap_64(data, size); 451 + } 452 + 453 + static void perf_event__all64_swap(union perf_event *event, 454 + bool sample_id_all __used) 458 455 { 459 456 struct perf_event_header *hdr = &event->header; 460 457 mem_bswap_64(hdr + 1, event->header.size - sizeof(*hdr)); 461 458 } 462 459 463 - static void perf_event__comm_swap(union perf_event *event) 460 + static void perf_event__comm_swap(union perf_event *event, bool sample_id_all) 464 461 { 465 462 event->comm.pid = bswap_32(event->comm.pid); 466 463 event->comm.tid = bswap_32(event->comm.tid); 464 + 465 + if (sample_id_all) { 466 + void *data = &event->comm.comm; 467 + 468 + data += ALIGN(strlen(data) + 1, sizeof(u64)); 469 + swap_sample_id_all(event, data); 470 + } 467 471 } 468 472 469 - static void perf_event__mmap_swap(union perf_event *event) 473 + static void perf_event__mmap_swap(union perf_event *event, 474 + bool sample_id_all) 470 475 { 471 476 event->mmap.pid = bswap_32(event->mmap.pid); 472 477 event->mmap.tid = bswap_32(event->mmap.tid); 473 478 event->mmap.start = bswap_64(event->mmap.start); 474 479 event->mmap.len = bswap_64(event->mmap.len); 475 480 event->mmap.pgoff = bswap_64(event->mmap.pgoff); 481 + 482 + if (sample_id_all) { 483 + void *data = &event->mmap.filename; 484 + 485 + data += ALIGN(strlen(data) + 1, sizeof(u64)); 486 + swap_sample_id_all(event, data); 487 + } 476 488 } 477 489 478 - static void perf_event__task_swap(union perf_event *event) 490 + static void perf_event__task_swap(union perf_event *event, bool sample_id_all) 479 491 { 480 492 event->fork.pid = bswap_32(event->fork.pid); 481 493 event->fork.tid = bswap_32(event->fork.tid); 482 494 event->fork.ppid = bswap_32(event->fork.ppid); 483 495 event->fork.ptid = bswap_32(event->fork.ptid); 484 496 event->fork.time = bswap_64(event->fork.time); 497 + 498 + if (sample_id_all) 499 + swap_sample_id_all(event, &event->fork + 1); 485 500 } 486 501 487 - static void perf_event__read_swap(union perf_event *event) 502 + static void perf_event__read_swap(union perf_event *event, bool sample_id_all) 488 503 { 489 504 event->read.pid = bswap_32(event->read.pid); 490 505 event->read.tid = bswap_32(event->read.tid); ··· 520 479 event->read.time_enabled = bswap_64(event->read.time_enabled); 521 480 event->read.time_running = bswap_64(event->read.time_running); 522 481 event->read.id = bswap_64(event->read.id); 482 + 483 + if (sample_id_all) 484 + swap_sample_id_all(event, &event->read + 1); 523 485 } 524 486 525 487 static u8 revbyte(u8 b) ··· 574 530 swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64)); 575 531 } 576 532 577 - static void perf_event__hdr_attr_swap(union perf_event *event) 533 + static void perf_event__hdr_attr_swap(union perf_event *event, 534 + bool sample_id_all __used) 578 535 { 579 536 size_t size; 580 537 ··· 586 541 mem_bswap_64(event->attr.id, size); 587 542 } 588 543 589 - static void perf_event__event_type_swap(union perf_event *event) 544 + static void perf_event__event_type_swap(union perf_event *event, 545 + bool sample_id_all __used) 590 546 { 591 547 event->event_type.event_type.event_id = 592 548 bswap_64(event->event_type.event_type.event_id); 593 549 } 594 550 595 - static void perf_event__tracing_data_swap(union perf_event *event) 551 + static void perf_event__tracing_data_swap(union perf_event *event, 552 + bool sample_id_all __used) 596 553 { 597 554 event->tracing_data.size = bswap_32(event->tracing_data.size); 598 555 } 599 556 600 - typedef void (*perf_event__swap_op)(union perf_event *event); 557 + typedef void (*perf_event__swap_op)(union perf_event *event, 558 + bool sample_id_all); 601 559 602 560 static perf_event__swap_op perf_event__swap_ops[] = { 603 561 [PERF_RECORD_MMAP] = perf_event__mmap_swap, ··· 1034 986 } 1035 987 } 1036 988 989 + static void event_swap(union perf_event *event, bool sample_id_all) 990 + { 991 + perf_event__swap_op swap; 992 + 993 + swap = perf_event__swap_ops[event->header.type]; 994 + if (swap) 995 + swap(event, sample_id_all); 996 + } 997 + 1037 998 static int perf_session__process_event(struct perf_session *session, 1038 999 union perf_event *event, 1039 1000 struct perf_tool *tool, ··· 1051 994 struct perf_sample sample; 1052 995 int ret; 1053 996 1054 - if (session->header.needs_swap && 1055 - perf_event__swap_ops[event->header.type]) 1056 - perf_event__swap_ops[event->header.type](event); 997 + if (session->header.needs_swap) 998 + event_swap(event, session->sample_id_all); 1057 999 1058 1000 if (event->header.type >= PERF_RECORD_HEADER_MAX) 1059 1001 return -EINVAL; ··· 1484 1428 int print_sym, int print_dso, int print_symoffset) 1485 1429 { 1486 1430 struct addr_location al; 1487 - struct callchain_cursor *cursor = &evsel->hists.callchain_cursor; 1488 1431 struct callchain_cursor_node *node; 1489 1432 1490 1433 if (perf_event__preprocess_sample(event, machine, &al, sample, ··· 1501 1446 error("Failed to resolve callchain. Skipping\n"); 1502 1447 return; 1503 1448 } 1504 - callchain_cursor_commit(cursor); 1449 + callchain_cursor_commit(&callchain_cursor); 1505 1450 1506 1451 while (1) { 1507 - node = callchain_cursor_current(cursor); 1452 + node = callchain_cursor_current(&callchain_cursor); 1508 1453 if (!node) 1509 1454 break; 1510 1455 ··· 1515 1460 } 1516 1461 if (print_dso) { 1517 1462 printf(" ("); 1518 - map__fprintf_dsoname(al.map, stdout); 1463 + map__fprintf_dsoname(node->map, stdout); 1519 1464 printf(")"); 1520 1465 } 1521 1466 printf("\n"); 1522 1467 1523 - callchain_cursor_advance(cursor); 1468 + callchain_cursor_advance(&callchain_cursor); 1524 1469 } 1525 1470 1526 1471 } else {
+36 -2
tools/perf/util/symbol.c
··· 323 323 dso->sorted_by_name = 0; 324 324 dso->has_build_id = 0; 325 325 dso->kernel = DSO_TYPE_USER; 326 + dso->needs_swap = DSO_SWAP__UNSET; 326 327 INIT_LIST_HEAD(&dso->node); 327 328 } 328 329 ··· 1157 1156 return -1; 1158 1157 } 1159 1158 1159 + static int dso__swap_init(struct dso *dso, unsigned char eidata) 1160 + { 1161 + static unsigned int const endian = 1; 1162 + 1163 + dso->needs_swap = DSO_SWAP__NO; 1164 + 1165 + switch (eidata) { 1166 + case ELFDATA2LSB: 1167 + /* We are big endian, DSO is little endian. */ 1168 + if (*(unsigned char const *)&endian != 1) 1169 + dso->needs_swap = DSO_SWAP__YES; 1170 + break; 1171 + 1172 + case ELFDATA2MSB: 1173 + /* We are little endian, DSO is big endian. */ 1174 + if (*(unsigned char const *)&endian != 0) 1175 + dso->needs_swap = DSO_SWAP__YES; 1176 + break; 1177 + 1178 + default: 1179 + pr_err("unrecognized DSO data encoding %d\n", eidata); 1180 + return -EINVAL; 1181 + } 1182 + 1183 + return 0; 1184 + } 1185 + 1160 1186 static int dso__load_sym(struct dso *dso, struct map *map, const char *name, 1161 1187 int fd, symbol_filter_t filter, int kmodule, 1162 1188 int want_symtab) ··· 1214 1186 pr_debug("%s: cannot get elf header.\n", __func__); 1215 1187 goto out_elf_end; 1216 1188 } 1189 + 1190 + if (dso__swap_init(dso, ehdr.e_ident[EI_DATA])) 1191 + goto out_elf_end; 1217 1192 1218 1193 /* Always reject images with a mismatched build-id: */ 1219 1194 if (dso->has_build_id) { ··· 1303 1272 if (opdsec && sym.st_shndx == opdidx) { 1304 1273 u32 offset = sym.st_value - opdshdr.sh_addr; 1305 1274 u64 *opd = opddata->d_buf + offset; 1306 - sym.st_value = *opd; 1275 + sym.st_value = DSO__SWAP(dso, u64, *opd); 1307 1276 sym.st_shndx = elf_addr_to_index(elf, sym.st_value); 1308 1277 } 1309 1278 ··· 2817 2786 2818 2787 struct map *dso__new_map(const char *name) 2819 2788 { 2789 + struct map *map = NULL; 2820 2790 struct dso *dso = dso__new(name); 2821 - struct map *map = map__new2(0, dso, MAP__FUNCTION); 2791 + 2792 + if (dso) 2793 + map = map__new2(0, dso, MAP__FUNCTION); 2822 2794 2823 2795 return map; 2824 2796 }
+30
tools/perf/util/symbol.h
··· 9 9 #include <linux/list.h> 10 10 #include <linux/rbtree.h> 11 11 #include <stdio.h> 12 + #include <byteswap.h> 12 13 13 14 #ifdef HAVE_CPLUS_DEMANGLE 14 15 extern char *cplus_demangle(const char *, int); ··· 161 160 DSO_TYPE_GUEST_KERNEL 162 161 }; 163 162 163 + enum dso_swap_type { 164 + DSO_SWAP__UNSET, 165 + DSO_SWAP__NO, 166 + DSO_SWAP__YES, 167 + }; 168 + 164 169 struct dso { 165 170 struct list_head node; 166 171 struct rb_root symbols[MAP__NR_TYPES]; 167 172 struct rb_root symbol_names[MAP__NR_TYPES]; 168 173 enum dso_kernel_type kernel; 174 + enum dso_swap_type needs_swap; 169 175 u8 adjust_symbols:1; 170 176 u8 has_build_id:1; 171 177 u8 hit:1; ··· 189 181 u16 short_name_len; 190 182 char name[0]; 191 183 }; 184 + 185 + #define DSO__SWAP(dso, type, val) \ 186 + ({ \ 187 + type ____r = val; \ 188 + BUG_ON(dso->needs_swap == DSO_SWAP__UNSET); \ 189 + if (dso->needs_swap == DSO_SWAP__YES) { \ 190 + switch (sizeof(____r)) { \ 191 + case 2: \ 192 + ____r = bswap_16(val); \ 193 + break; \ 194 + case 4: \ 195 + ____r = bswap_32(val); \ 196 + break; \ 197 + case 8: \ 198 + ____r = bswap_64(val); \ 199 + break; \ 200 + default: \ 201 + BUG_ON(1); \ 202 + } \ 203 + } \ 204 + ____r; \ 205 + }) 192 206 193 207 struct dso *dso__new(const char *name); 194 208 void dso__delete(struct dso *dso);