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

Merge branch 'perfcounters-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'perfcounters-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (49 commits)
perfcounter: Handle some IO return values
perf_counter: Push perf_sample_data through the swcounter code
perf_counter tools: Define and use our own u64, s64 etc. definitions
perf_counter: Close race in perf_lock_task_context()
perf_counter, x86: Improve interactions with fast-gup
perf_counter: Simplify and fix task migration counting
perf_counter tools: Add a data file header
perf_counter: Update userspace callchain sampling uses
perf_counter: Make callchain samples extensible
perf report: Filter to parent set by default
perf_counter tools: Handle lost events
perf_counter: Add event overlow handling
fs: Provide empty .set_page_dirty() aop for anon inodes
perf_counter: tools: Makefile tweaks for 64-bit powerpc
perf_counter: powerpc: Add processor back-end for MPC7450 family
perf_counter: powerpc: Make powerpc perf_counter code safe for 32-bit kernels
perf_counter: powerpc: Change how processor-specific back-ends get selected
perf_counter: powerpc: Use unsigned long for register and constraint values
perf_counter: powerpc: Enable use of software counters on 32-bit powerpc
perf_counter tools: Add and use isprint()
...

+2327 -898
+1
arch/powerpc/Kconfig
··· 126 126 select HAVE_OPROFILE 127 127 select HAVE_SYSCALL_WRAPPERS if PPC64 128 128 select GENERIC_ATOMIC64 if PPC32 129 + select HAVE_PERF_COUNTERS 129 130 130 131 config EARLY_PRINTK 131 132 bool
+4 -2
arch/powerpc/include/asm/hw_irq.h
··· 131 131 struct irq_chip; 132 132 133 133 #ifdef CONFIG_PERF_COUNTERS 134 + 135 + #ifdef CONFIG_PPC64 134 136 static inline unsigned long test_perf_counter_pending(void) 135 137 { 136 138 unsigned long x; ··· 156 154 "r" (0), 157 155 "i" (offsetof(struct paca_struct, perf_counter_pending))); 158 156 } 157 + #endif /* CONFIG_PPC64 */ 159 158 160 - #else 159 + #else /* CONFIG_PERF_COUNTERS */ 161 160 162 161 static inline unsigned long test_perf_counter_pending(void) 163 162 { 164 163 return 0; 165 164 } 166 165 167 - static inline void set_perf_counter_pending(void) {} 168 166 static inline void clear_perf_counter_pending(void) {} 169 167 #endif /* CONFIG_PERF_COUNTERS */ 170 168
+31 -21
arch/powerpc/include/asm/perf_counter.h
··· 10 10 */ 11 11 #include <linux/types.h> 12 12 13 + #include <asm/hw_irq.h> 14 + 13 15 #define MAX_HWCOUNTERS 8 14 16 #define MAX_EVENT_ALTERNATIVES 8 15 17 #define MAX_LIMITED_HWCOUNTERS 2 ··· 21 19 * describe the PMU on a particular POWER-family CPU. 22 20 */ 23 21 struct power_pmu { 24 - int n_counter; 25 - int max_alternatives; 26 - u64 add_fields; 27 - u64 test_adder; 28 - int (*compute_mmcr)(u64 events[], int n_ev, 29 - unsigned int hwc[], u64 mmcr[]); 30 - int (*get_constraint)(u64 event, u64 *mskp, u64 *valp); 31 - int (*get_alternatives)(u64 event, unsigned int flags, 32 - u64 alt[]); 33 - void (*disable_pmc)(unsigned int pmc, u64 mmcr[]); 34 - int (*limited_pmc_event)(u64 event); 35 - u32 flags; 36 - int n_generic; 37 - int *generic_events; 38 - int (*cache_events)[PERF_COUNT_HW_CACHE_MAX] 22 + const char *name; 23 + int n_counter; 24 + int max_alternatives; 25 + unsigned long add_fields; 26 + unsigned long test_adder; 27 + int (*compute_mmcr)(u64 events[], int n_ev, 28 + unsigned int hwc[], unsigned long mmcr[]); 29 + int (*get_constraint)(u64 event, unsigned long *mskp, 30 + unsigned long *valp); 31 + int (*get_alternatives)(u64 event, unsigned int flags, 32 + u64 alt[]); 33 + void (*disable_pmc)(unsigned int pmc, unsigned long mmcr[]); 34 + int (*limited_pmc_event)(u64 event); 35 + u32 flags; 36 + int n_generic; 37 + int *generic_events; 38 + int (*cache_events)[PERF_COUNT_HW_CACHE_MAX] 39 39 [PERF_COUNT_HW_CACHE_OP_MAX] 40 40 [PERF_COUNT_HW_CACHE_RESULT_MAX]; 41 41 }; 42 - 43 - extern struct power_pmu *ppmu; 44 42 45 43 /* 46 44 * Values for power_pmu.flags ··· 55 53 #define PPMU_LIMITED_PMC_REQD 2 /* have to put this on a limited PMC */ 56 54 #define PPMU_ONLY_COUNT_RUN 4 /* only counting in run state */ 57 55 56 + extern int register_power_pmu(struct power_pmu *); 57 + 58 58 struct pt_regs; 59 59 extern unsigned long perf_misc_flags(struct pt_regs *regs); 60 - #define perf_misc_flags(regs) perf_misc_flags(regs) 61 - 62 60 extern unsigned long perf_instruction_pointer(struct pt_regs *regs); 63 61 64 62 /* 65 - * The power_pmu.get_constraint function returns a 64-bit value and 66 - * a 64-bit mask that express the constraints between this event and 63 + * Only override the default definitions in include/linux/perf_counter.h 64 + * if we have hardware PMU support. 65 + */ 66 + #ifdef CONFIG_PPC_PERF_CTRS 67 + #define perf_misc_flags(regs) perf_misc_flags(regs) 68 + #endif 69 + 70 + /* 71 + * The power_pmu.get_constraint function returns a 32/64-bit value and 72 + * a 32/64-bit mask that express the constraints between this event and 67 73 * other events. 68 74 * 69 75 * The value and mask are divided up into (non-overlapping) bitfields
+5 -3
arch/powerpc/kernel/Makefile
··· 97 97 98 98 obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o 99 99 obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o 100 - obj-$(CONFIG_PERF_COUNTERS) += perf_counter.o power4-pmu.o ppc970-pmu.o \ 101 - power5-pmu.o power5+-pmu.o power6-pmu.o \ 102 - power7-pmu.o 100 + obj-$(CONFIG_PPC_PERF_CTRS) += perf_counter.o 101 + obj64-$(CONFIG_PPC_PERF_CTRS) += power4-pmu.o ppc970-pmu.o power5-pmu.o \ 102 + power5+-pmu.o power6-pmu.o power7-pmu.o 103 + obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450-pmu.o 103 104 104 105 obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o 105 106 ··· 109 108 endif 110 109 111 110 obj-$(CONFIG_PPC64) += $(obj64-y) 111 + obj-$(CONFIG_PPC32) += $(obj32-y) 112 112 113 113 ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),) 114 114 obj-y += ppc_save_regs.o
+417
arch/powerpc/kernel/mpc7450-pmu.c
··· 1 + /* 2 + * Performance counter support for MPC7450-family processors. 3 + * 4 + * Copyright 2008-2009 Paul Mackerras, IBM Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public License 8 + * as published by the Free Software Foundation; either version 9 + * 2 of the License, or (at your option) any later version. 10 + */ 11 + #include <linux/string.h> 12 + #include <linux/perf_counter.h> 13 + #include <linux/string.h> 14 + #include <asm/reg.h> 15 + #include <asm/cputable.h> 16 + 17 + #define N_COUNTER 6 /* Number of hardware counters */ 18 + #define MAX_ALT 3 /* Maximum number of event alternative codes */ 19 + 20 + /* 21 + * Bits in event code for MPC7450 family 22 + */ 23 + #define PM_THRMULT_MSKS 0x40000 24 + #define PM_THRESH_SH 12 25 + #define PM_THRESH_MSK 0x3f 26 + #define PM_PMC_SH 8 27 + #define PM_PMC_MSK 7 28 + #define PM_PMCSEL_MSK 0x7f 29 + 30 + /* 31 + * Classify events according to how specific their PMC requirements are. 32 + * Result is: 33 + * 0: can go on any PMC 34 + * 1: can go on PMCs 1-4 35 + * 2: can go on PMCs 1,2,4 36 + * 3: can go on PMCs 1 or 2 37 + * 4: can only go on one PMC 38 + * -1: event code is invalid 39 + */ 40 + #define N_CLASSES 5 41 + 42 + static int mpc7450_classify_event(u32 event) 43 + { 44 + int pmc; 45 + 46 + pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; 47 + if (pmc) { 48 + if (pmc > N_COUNTER) 49 + return -1; 50 + return 4; 51 + } 52 + event &= PM_PMCSEL_MSK; 53 + if (event <= 1) 54 + return 0; 55 + if (event <= 7) 56 + return 1; 57 + if (event <= 13) 58 + return 2; 59 + if (event <= 22) 60 + return 3; 61 + return -1; 62 + } 63 + 64 + /* 65 + * Events using threshold and possible threshold scale: 66 + * code scale? name 67 + * 11e N PM_INSTQ_EXCEED_CYC 68 + * 11f N PM_ALTV_IQ_EXCEED_CYC 69 + * 128 Y PM_DTLB_SEARCH_EXCEED_CYC 70 + * 12b Y PM_LD_MISS_EXCEED_L1_CYC 71 + * 220 N PM_CQ_EXCEED_CYC 72 + * 30c N PM_GPR_RB_EXCEED_CYC 73 + * 30d ? PM_FPR_IQ_EXCEED_CYC ? 74 + * 311 Y PM_ITLB_SEARCH_EXCEED 75 + * 410 N PM_GPR_IQ_EXCEED_CYC 76 + */ 77 + 78 + /* 79 + * Return use of threshold and threshold scale bits: 80 + * 0 = uses neither, 1 = uses threshold, 2 = uses both 81 + */ 82 + static int mpc7450_threshold_use(u32 event) 83 + { 84 + int pmc, sel; 85 + 86 + pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; 87 + sel = event & PM_PMCSEL_MSK; 88 + switch (pmc) { 89 + case 1: 90 + if (sel == 0x1e || sel == 0x1f) 91 + return 1; 92 + if (sel == 0x28 || sel == 0x2b) 93 + return 2; 94 + break; 95 + case 2: 96 + if (sel == 0x20) 97 + return 1; 98 + break; 99 + case 3: 100 + if (sel == 0xc || sel == 0xd) 101 + return 1; 102 + if (sel == 0x11) 103 + return 2; 104 + break; 105 + case 4: 106 + if (sel == 0x10) 107 + return 1; 108 + break; 109 + } 110 + return 0; 111 + } 112 + 113 + /* 114 + * Layout of constraint bits: 115 + * 33222222222211111111110000000000 116 + * 10987654321098765432109876543210 117 + * |< >< > < > < ><><><><><><> 118 + * TS TV G4 G3 G2P6P5P4P3P2P1 119 + * 120 + * P1 - P6 121 + * 0 - 11: Count of events needing PMC1 .. PMC6 122 + * 123 + * G2 124 + * 12 - 14: Count of events needing PMC1 or PMC2 125 + * 126 + * G3 127 + * 16 - 18: Count of events needing PMC1, PMC2 or PMC4 128 + * 129 + * G4 130 + * 20 - 23: Count of events needing PMC1, PMC2, PMC3 or PMC4 131 + * 132 + * TV 133 + * 24 - 29: Threshold value requested 134 + * 135 + * TS 136 + * 30: Threshold scale value requested 137 + */ 138 + 139 + static u32 pmcbits[N_COUNTER][2] = { 140 + { 0x00844002, 0x00111001 }, /* PMC1 mask, value: P1,G2,G3,G4 */ 141 + { 0x00844008, 0x00111004 }, /* PMC2: P2,G2,G3,G4 */ 142 + { 0x00800020, 0x00100010 }, /* PMC3: P3,G4 */ 143 + { 0x00840080, 0x00110040 }, /* PMC4: P4,G3,G4 */ 144 + { 0x00000200, 0x00000100 }, /* PMC5: P5 */ 145 + { 0x00000800, 0x00000400 } /* PMC6: P6 */ 146 + }; 147 + 148 + static u32 classbits[N_CLASSES - 1][2] = { 149 + { 0x00000000, 0x00000000 }, /* class 0: no constraint */ 150 + { 0x00800000, 0x00100000 }, /* class 1: G4 */ 151 + { 0x00040000, 0x00010000 }, /* class 2: G3 */ 152 + { 0x00004000, 0x00001000 }, /* class 3: G2 */ 153 + }; 154 + 155 + static int mpc7450_get_constraint(u64 event, unsigned long *maskp, 156 + unsigned long *valp) 157 + { 158 + int pmc, class; 159 + u32 mask, value; 160 + int thresh, tuse; 161 + 162 + class = mpc7450_classify_event(event); 163 + if (class < 0) 164 + return -1; 165 + if (class == 4) { 166 + pmc = ((unsigned int)event >> PM_PMC_SH) & PM_PMC_MSK; 167 + mask = pmcbits[pmc - 1][0]; 168 + value = pmcbits[pmc - 1][1]; 169 + } else { 170 + mask = classbits[class][0]; 171 + value = classbits[class][1]; 172 + } 173 + 174 + tuse = mpc7450_threshold_use(event); 175 + if (tuse) { 176 + thresh = ((unsigned int)event >> PM_THRESH_SH) & PM_THRESH_MSK; 177 + mask |= 0x3f << 24; 178 + value |= thresh << 24; 179 + if (tuse == 2) { 180 + mask |= 0x40000000; 181 + if ((unsigned int)event & PM_THRMULT_MSKS) 182 + value |= 0x40000000; 183 + } 184 + } 185 + 186 + *maskp = mask; 187 + *valp = value; 188 + return 0; 189 + } 190 + 191 + static const unsigned int event_alternatives[][MAX_ALT] = { 192 + { 0x217, 0x317 }, /* PM_L1_DCACHE_MISS */ 193 + { 0x418, 0x50f, 0x60f }, /* PM_SNOOP_RETRY */ 194 + { 0x502, 0x602 }, /* PM_L2_HIT */ 195 + { 0x503, 0x603 }, /* PM_L3_HIT */ 196 + { 0x504, 0x604 }, /* PM_L2_ICACHE_MISS */ 197 + { 0x505, 0x605 }, /* PM_L3_ICACHE_MISS */ 198 + { 0x506, 0x606 }, /* PM_L2_DCACHE_MISS */ 199 + { 0x507, 0x607 }, /* PM_L3_DCACHE_MISS */ 200 + { 0x50a, 0x623 }, /* PM_LD_HIT_L3 */ 201 + { 0x50b, 0x624 }, /* PM_ST_HIT_L3 */ 202 + { 0x50d, 0x60d }, /* PM_L2_TOUCH_HIT */ 203 + { 0x50e, 0x60e }, /* PM_L3_TOUCH_HIT */ 204 + { 0x512, 0x612 }, /* PM_INT_LOCAL */ 205 + { 0x513, 0x61d }, /* PM_L2_MISS */ 206 + { 0x514, 0x61e }, /* PM_L3_MISS */ 207 + }; 208 + 209 + /* 210 + * Scan the alternatives table for a match and return the 211 + * index into the alternatives table if found, else -1. 212 + */ 213 + static int find_alternative(u32 event) 214 + { 215 + int i, j; 216 + 217 + for (i = 0; i < ARRAY_SIZE(event_alternatives); ++i) { 218 + if (event < event_alternatives[i][0]) 219 + break; 220 + for (j = 0; j < MAX_ALT && event_alternatives[i][j]; ++j) 221 + if (event == event_alternatives[i][j]) 222 + return i; 223 + } 224 + return -1; 225 + } 226 + 227 + static int mpc7450_get_alternatives(u64 event, unsigned int flags, u64 alt[]) 228 + { 229 + int i, j, nalt = 1; 230 + u32 ae; 231 + 232 + alt[0] = event; 233 + nalt = 1; 234 + i = find_alternative((u32)event); 235 + if (i >= 0) { 236 + for (j = 0; j < MAX_ALT; ++j) { 237 + ae = event_alternatives[i][j]; 238 + if (ae && ae != (u32)event) 239 + alt[nalt++] = ae; 240 + } 241 + } 242 + return nalt; 243 + } 244 + 245 + /* 246 + * Bitmaps of which PMCs each class can use for classes 0 - 3. 247 + * Bit i is set if PMC i+1 is usable. 248 + */ 249 + static const u8 classmap[N_CLASSES] = { 250 + 0x3f, 0x0f, 0x0b, 0x03, 0 251 + }; 252 + 253 + /* Bit position and width of each PMCSEL field */ 254 + static const int pmcsel_shift[N_COUNTER] = { 255 + 6, 0, 27, 22, 17, 11 256 + }; 257 + static const u32 pmcsel_mask[N_COUNTER] = { 258 + 0x7f, 0x3f, 0x1f, 0x1f, 0x1f, 0x3f 259 + }; 260 + 261 + /* 262 + * Compute MMCR0/1/2 values for a set of events. 263 + */ 264 + static int mpc7450_compute_mmcr(u64 event[], int n_ev, 265 + unsigned int hwc[], unsigned long mmcr[]) 266 + { 267 + u8 event_index[N_CLASSES][N_COUNTER]; 268 + int n_classevent[N_CLASSES]; 269 + int i, j, class, tuse; 270 + u32 pmc_inuse = 0, pmc_avail; 271 + u32 mmcr0 = 0, mmcr1 = 0, mmcr2 = 0; 272 + u32 ev, pmc, thresh; 273 + 274 + if (n_ev > N_COUNTER) 275 + return -1; 276 + 277 + /* First pass: count usage in each class */ 278 + for (i = 0; i < N_CLASSES; ++i) 279 + n_classevent[i] = 0; 280 + for (i = 0; i < n_ev; ++i) { 281 + class = mpc7450_classify_event(event[i]); 282 + if (class < 0) 283 + return -1; 284 + j = n_classevent[class]++; 285 + event_index[class][j] = i; 286 + } 287 + 288 + /* Second pass: allocate PMCs from most specific event to least */ 289 + for (class = N_CLASSES - 1; class >= 0; --class) { 290 + for (i = 0; i < n_classevent[class]; ++i) { 291 + ev = event[event_index[class][i]]; 292 + if (class == 4) { 293 + pmc = (ev >> PM_PMC_SH) & PM_PMC_MSK; 294 + if (pmc_inuse & (1 << (pmc - 1))) 295 + return -1; 296 + } else { 297 + /* Find a suitable PMC */ 298 + pmc_avail = classmap[class] & ~pmc_inuse; 299 + if (!pmc_avail) 300 + return -1; 301 + pmc = ffs(pmc_avail); 302 + } 303 + pmc_inuse |= 1 << (pmc - 1); 304 + 305 + tuse = mpc7450_threshold_use(ev); 306 + if (tuse) { 307 + thresh = (ev >> PM_THRESH_SH) & PM_THRESH_MSK; 308 + mmcr0 |= thresh << 16; 309 + if (tuse == 2 && (ev & PM_THRMULT_MSKS)) 310 + mmcr2 = 0x80000000; 311 + } 312 + ev &= pmcsel_mask[pmc - 1]; 313 + ev <<= pmcsel_shift[pmc - 1]; 314 + if (pmc <= 2) 315 + mmcr0 |= ev; 316 + else 317 + mmcr1 |= ev; 318 + hwc[event_index[class][i]] = pmc - 1; 319 + } 320 + } 321 + 322 + if (pmc_inuse & 1) 323 + mmcr0 |= MMCR0_PMC1CE; 324 + if (pmc_inuse & 0x3e) 325 + mmcr0 |= MMCR0_PMCnCE; 326 + 327 + /* Return MMCRx values */ 328 + mmcr[0] = mmcr0; 329 + mmcr[1] = mmcr1; 330 + mmcr[2] = mmcr2; 331 + return 0; 332 + } 333 + 334 + /* 335 + * Disable counting by a PMC. 336 + * Note that the pmc argument is 0-based here, not 1-based. 337 + */ 338 + static void mpc7450_disable_pmc(unsigned int pmc, unsigned long mmcr[]) 339 + { 340 + if (pmc <= 1) 341 + mmcr[0] &= ~(pmcsel_mask[pmc] << pmcsel_shift[pmc]); 342 + else 343 + mmcr[1] &= ~(pmcsel_mask[pmc] << pmcsel_shift[pmc]); 344 + } 345 + 346 + static int mpc7450_generic_events[] = { 347 + [PERF_COUNT_HW_CPU_CYCLES] = 1, 348 + [PERF_COUNT_HW_INSTRUCTIONS] = 2, 349 + [PERF_COUNT_HW_CACHE_MISSES] = 0x217, /* PM_L1_DCACHE_MISS */ 350 + [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x122, /* PM_BR_CMPL */ 351 + [PERF_COUNT_HW_BRANCH_MISSES] = 0x41c, /* PM_BR_MPRED */ 352 + }; 353 + 354 + #define C(x) PERF_COUNT_HW_CACHE_##x 355 + 356 + /* 357 + * Table of generalized cache-related events. 358 + * 0 means not supported, -1 means nonsensical, other values 359 + * are event codes. 360 + */ 361 + static int mpc7450_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = { 362 + [C(L1D)] = { /* RESULT_ACCESS RESULT_MISS */ 363 + [C(OP_READ)] = { 0, 0x225 }, 364 + [C(OP_WRITE)] = { 0, 0x227 }, 365 + [C(OP_PREFETCH)] = { 0, 0 }, 366 + }, 367 + [C(L1I)] = { /* RESULT_ACCESS RESULT_MISS */ 368 + [C(OP_READ)] = { 0x129, 0x115 }, 369 + [C(OP_WRITE)] = { -1, -1 }, 370 + [C(OP_PREFETCH)] = { 0x634, 0 }, 371 + }, 372 + [C(LL)] = { /* RESULT_ACCESS RESULT_MISS */ 373 + [C(OP_READ)] = { 0, 0 }, 374 + [C(OP_WRITE)] = { 0, 0 }, 375 + [C(OP_PREFETCH)] = { 0, 0 }, 376 + }, 377 + [C(DTLB)] = { /* RESULT_ACCESS RESULT_MISS */ 378 + [C(OP_READ)] = { 0, 0x312 }, 379 + [C(OP_WRITE)] = { -1, -1 }, 380 + [C(OP_PREFETCH)] = { -1, -1 }, 381 + }, 382 + [C(ITLB)] = { /* RESULT_ACCESS RESULT_MISS */ 383 + [C(OP_READ)] = { 0, 0x223 }, 384 + [C(OP_WRITE)] = { -1, -1 }, 385 + [C(OP_PREFETCH)] = { -1, -1 }, 386 + }, 387 + [C(BPU)] = { /* RESULT_ACCESS RESULT_MISS */ 388 + [C(OP_READ)] = { 0x122, 0x41c }, 389 + [C(OP_WRITE)] = { -1, -1 }, 390 + [C(OP_PREFETCH)] = { -1, -1 }, 391 + }, 392 + }; 393 + 394 + struct power_pmu mpc7450_pmu = { 395 + .name = "MPC7450 family", 396 + .n_counter = N_COUNTER, 397 + .max_alternatives = MAX_ALT, 398 + .add_fields = 0x00111555ul, 399 + .test_adder = 0x00301000ul, 400 + .compute_mmcr = mpc7450_compute_mmcr, 401 + .get_constraint = mpc7450_get_constraint, 402 + .get_alternatives = mpc7450_get_alternatives, 403 + .disable_pmc = mpc7450_disable_pmc, 404 + .n_generic = ARRAY_SIZE(mpc7450_generic_events), 405 + .generic_events = mpc7450_generic_events, 406 + .cache_events = &mpc7450_cache_events, 407 + }; 408 + 409 + static int init_mpc7450_pmu(void) 410 + { 411 + if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc/7450")) 412 + return -ENODEV; 413 + 414 + return register_power_pmu(&mpc7450_pmu); 415 + } 416 + 417 + arch_initcall(init_mpc7450_pmu);
+149 -106
arch/powerpc/kernel/perf_counter.c
··· 29 29 struct perf_counter *counter[MAX_HWCOUNTERS]; 30 30 u64 events[MAX_HWCOUNTERS]; 31 31 unsigned int flags[MAX_HWCOUNTERS]; 32 - u64 mmcr[3]; 32 + unsigned long mmcr[3]; 33 33 struct perf_counter *limited_counter[MAX_LIMITED_HWCOUNTERS]; 34 34 u8 limited_hwidx[MAX_LIMITED_HWCOUNTERS]; 35 35 }; ··· 45 45 * then we need to use the FCHV bit to ignore kernel events. 46 46 */ 47 47 static unsigned int freeze_counters_kernel = MMCR0_FCS; 48 + 49 + /* 50 + * 32-bit doesn't have MMCRA but does have an MMCR2, 51 + * and a few other names are different. 52 + */ 53 + #ifdef CONFIG_PPC32 54 + 55 + #define MMCR0_FCHV 0 56 + #define MMCR0_PMCjCE MMCR0_PMCnCE 57 + 58 + #define SPRN_MMCRA SPRN_MMCR2 59 + #define MMCRA_SAMPLE_ENABLE 0 60 + 61 + static inline unsigned long perf_ip_adjust(struct pt_regs *regs) 62 + { 63 + return 0; 64 + } 65 + static inline void perf_set_pmu_inuse(int inuse) { } 66 + static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp) { } 67 + static inline u32 perf_get_misc_flags(struct pt_regs *regs) 68 + { 69 + return 0; 70 + } 71 + static inline void perf_read_regs(struct pt_regs *regs) { } 72 + static inline int perf_intr_is_nmi(struct pt_regs *regs) 73 + { 74 + return 0; 75 + } 76 + 77 + #endif /* CONFIG_PPC32 */ 78 + 79 + /* 80 + * Things that are specific to 64-bit implementations. 81 + */ 82 + #ifdef CONFIG_PPC64 83 + 84 + static inline unsigned long perf_ip_adjust(struct pt_regs *regs) 85 + { 86 + unsigned long mmcra = regs->dsisr; 87 + 88 + if ((mmcra & MMCRA_SAMPLE_ENABLE) && !(ppmu->flags & PPMU_ALT_SIPR)) { 89 + unsigned long slot = (mmcra & MMCRA_SLOT) >> MMCRA_SLOT_SHIFT; 90 + if (slot > 1) 91 + return 4 * (slot - 1); 92 + } 93 + return 0; 94 + } 95 + 96 + static inline void perf_set_pmu_inuse(int inuse) 97 + { 98 + get_lppaca()->pmcregs_in_use = inuse; 99 + } 100 + 101 + /* 102 + * The user wants a data address recorded. 103 + * If we're not doing instruction sampling, give them the SDAR 104 + * (sampled data address). If we are doing instruction sampling, then 105 + * only give them the SDAR if it corresponds to the instruction 106 + * pointed to by SIAR; this is indicated by the [POWER6_]MMCRA_SDSYNC 107 + * bit in MMCRA. 108 + */ 109 + static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp) 110 + { 111 + unsigned long mmcra = regs->dsisr; 112 + unsigned long sdsync = (ppmu->flags & PPMU_ALT_SIPR) ? 113 + POWER6_MMCRA_SDSYNC : MMCRA_SDSYNC; 114 + 115 + if (!(mmcra & MMCRA_SAMPLE_ENABLE) || (mmcra & sdsync)) 116 + *addrp = mfspr(SPRN_SDAR); 117 + } 118 + 119 + static inline u32 perf_get_misc_flags(struct pt_regs *regs) 120 + { 121 + unsigned long mmcra = regs->dsisr; 122 + 123 + if (TRAP(regs) != 0xf00) 124 + return 0; /* not a PMU interrupt */ 125 + 126 + if (ppmu->flags & PPMU_ALT_SIPR) { 127 + if (mmcra & POWER6_MMCRA_SIHV) 128 + return PERF_EVENT_MISC_HYPERVISOR; 129 + return (mmcra & POWER6_MMCRA_SIPR) ? 130 + PERF_EVENT_MISC_USER : PERF_EVENT_MISC_KERNEL; 131 + } 132 + if (mmcra & MMCRA_SIHV) 133 + return PERF_EVENT_MISC_HYPERVISOR; 134 + return (mmcra & MMCRA_SIPR) ? PERF_EVENT_MISC_USER : 135 + PERF_EVENT_MISC_KERNEL; 136 + } 137 + 138 + /* 139 + * Overload regs->dsisr to store MMCRA so we only need to read it once 140 + * on each interrupt. 141 + */ 142 + static inline void perf_read_regs(struct pt_regs *regs) 143 + { 144 + regs->dsisr = mfspr(SPRN_MMCRA); 145 + } 146 + 147 + /* 148 + * If interrupts were soft-disabled when a PMU interrupt occurs, treat 149 + * it as an NMI. 150 + */ 151 + static inline int perf_intr_is_nmi(struct pt_regs *regs) 152 + { 153 + return !regs->softe; 154 + } 155 + 156 + #endif /* CONFIG_PPC64 */ 48 157 49 158 static void perf_counter_interrupt(struct pt_regs *regs); 50 159 ··· 187 78 case 6: 188 79 val = mfspr(SPRN_PMC6); 189 80 break; 81 + #ifdef CONFIG_PPC64 190 82 case 7: 191 83 val = mfspr(SPRN_PMC7); 192 84 break; 193 85 case 8: 194 86 val = mfspr(SPRN_PMC8); 195 87 break; 88 + #endif /* CONFIG_PPC64 */ 196 89 default: 197 90 printk(KERN_ERR "oops trying to read PMC%d\n", idx); 198 91 val = 0; ··· 226 115 case 6: 227 116 mtspr(SPRN_PMC6, val); 228 117 break; 118 + #ifdef CONFIG_PPC64 229 119 case 7: 230 120 mtspr(SPRN_PMC7, val); 231 121 break; 232 122 case 8: 233 123 mtspr(SPRN_PMC8, val); 234 124 break; 125 + #endif /* CONFIG_PPC64 */ 235 126 default: 236 127 printk(KERN_ERR "oops trying to write PMC%d\n", idx); 237 128 } ··· 248 135 static int power_check_constraints(u64 event[], unsigned int cflags[], 249 136 int n_ev) 250 137 { 251 - u64 mask, value, nv; 138 + unsigned long mask, value, nv; 252 139 u64 alternatives[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES]; 253 - u64 amasks[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES]; 254 - u64 avalues[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES]; 255 - u64 smasks[MAX_HWCOUNTERS], svalues[MAX_HWCOUNTERS]; 140 + unsigned long amasks[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES]; 141 + unsigned long avalues[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES]; 142 + unsigned long smasks[MAX_HWCOUNTERS], svalues[MAX_HWCOUNTERS]; 256 143 int n_alt[MAX_HWCOUNTERS], choice[MAX_HWCOUNTERS]; 257 144 int i, j; 258 - u64 addf = ppmu->add_fields; 259 - u64 tadd = ppmu->test_adder; 145 + unsigned long addf = ppmu->add_fields; 146 + unsigned long tadd = ppmu->test_adder; 260 147 261 148 if (n_ev > ppmu->n_counter) 262 149 return -1; ··· 396 283 397 284 static void power_pmu_read(struct perf_counter *counter) 398 285 { 399 - long val, delta, prev; 286 + s64 val, delta, prev; 400 287 401 288 if (!counter->hw.idx) 402 289 return; ··· 516 403 void hw_perf_disable(void) 517 404 { 518 405 struct cpu_hw_counters *cpuhw; 519 - unsigned long ret; 520 406 unsigned long flags; 521 407 522 408 local_irq_save(flags); 523 409 cpuhw = &__get_cpu_var(cpu_hw_counters); 524 410 525 - ret = cpuhw->disabled; 526 - if (!ret) { 411 + if (!cpuhw->disabled) { 527 412 cpuhw->disabled = 1; 528 413 cpuhw->n_added = 0; 529 414 ··· 590 479 mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE); 591 480 mtspr(SPRN_MMCR1, cpuhw->mmcr[1]); 592 481 if (cpuhw->n_counters == 0) 593 - get_lppaca()->pmcregs_in_use = 0; 482 + perf_set_pmu_inuse(0); 594 483 goto out_enable; 595 484 } 596 485 ··· 623 512 * bit set and set the hardware counters to their initial values. 624 513 * Then unfreeze the counters. 625 514 */ 626 - get_lppaca()->pmcregs_in_use = 1; 515 + perf_set_pmu_inuse(1); 627 516 mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE); 628 517 mtspr(SPRN_MMCR1, cpuhw->mmcr[1]); 629 518 mtspr(SPRN_MMCR0, (cpuhw->mmcr[0] & ~(MMCR0_PMC1CE | MMCR0_PMCjCE)) ··· 1024 913 case PERF_TYPE_RAW: 1025 914 ev = counter->attr.config; 1026 915 break; 916 + default: 917 + return ERR_PTR(-EINVAL); 1027 918 } 1028 919 counter->hw.config_base = ev; 1029 920 counter->hw.idx = 0; ··· 1120 1007 * things if requested. Note that interrupts are hard-disabled 1121 1008 * here so there is no possibility of being interrupted. 1122 1009 */ 1123 - static void record_and_restart(struct perf_counter *counter, long val, 1010 + static void record_and_restart(struct perf_counter *counter, unsigned long val, 1124 1011 struct pt_regs *regs, int nmi) 1125 1012 { 1126 1013 u64 period = counter->hw.sample_period; 1127 1014 s64 prev, delta, left; 1128 1015 int record = 0; 1129 - u64 addr, mmcra, sdsync; 1130 1016 1131 1017 /* we don't have to worry about interrupts here */ 1132 1018 prev = atomic64_read(&counter->hw.prev_count); ··· 1145 1033 left = period; 1146 1034 record = 1; 1147 1035 } 1148 - if (left < 0x80000000L) 1149 - val = 0x80000000L - left; 1036 + if (left < 0x80000000LL) 1037 + val = 0x80000000LL - left; 1150 1038 } 1151 1039 1152 1040 /* ··· 1159 1047 .period = counter->hw.last_period, 1160 1048 }; 1161 1049 1162 - if (counter->attr.sample_type & PERF_SAMPLE_ADDR) { 1163 - /* 1164 - * The user wants a data address recorded. 1165 - * If we're not doing instruction sampling, 1166 - * give them the SDAR (sampled data address). 1167 - * If we are doing instruction sampling, then only 1168 - * give them the SDAR if it corresponds to the 1169 - * instruction pointed to by SIAR; this is indicated 1170 - * by the [POWER6_]MMCRA_SDSYNC bit in MMCRA. 1171 - */ 1172 - mmcra = regs->dsisr; 1173 - sdsync = (ppmu->flags & PPMU_ALT_SIPR) ? 1174 - POWER6_MMCRA_SDSYNC : MMCRA_SDSYNC; 1175 - if (!(mmcra & MMCRA_SAMPLE_ENABLE) || (mmcra & sdsync)) 1176 - data.addr = mfspr(SPRN_SDAR); 1177 - } 1050 + if (counter->attr.sample_type & PERF_SAMPLE_ADDR) 1051 + perf_get_data_addr(regs, &data.addr); 1052 + 1178 1053 if (perf_counter_overflow(counter, nmi, &data)) { 1179 1054 /* 1180 1055 * Interrupts are coming too fast - throttle them ··· 1187 1088 */ 1188 1089 unsigned long perf_misc_flags(struct pt_regs *regs) 1189 1090 { 1190 - unsigned long mmcra; 1091 + u32 flags = perf_get_misc_flags(regs); 1191 1092 1192 - if (TRAP(regs) != 0xf00) { 1193 - /* not a PMU interrupt */ 1194 - return user_mode(regs) ? PERF_EVENT_MISC_USER : 1195 - PERF_EVENT_MISC_KERNEL; 1196 - } 1197 - 1198 - mmcra = regs->dsisr; 1199 - if (ppmu->flags & PPMU_ALT_SIPR) { 1200 - if (mmcra & POWER6_MMCRA_SIHV) 1201 - return PERF_EVENT_MISC_HYPERVISOR; 1202 - return (mmcra & POWER6_MMCRA_SIPR) ? PERF_EVENT_MISC_USER : 1203 - PERF_EVENT_MISC_KERNEL; 1204 - } 1205 - if (mmcra & MMCRA_SIHV) 1206 - return PERF_EVENT_MISC_HYPERVISOR; 1207 - return (mmcra & MMCRA_SIPR) ? PERF_EVENT_MISC_USER : 1208 - PERF_EVENT_MISC_KERNEL; 1093 + if (flags) 1094 + return flags; 1095 + return user_mode(regs) ? PERF_EVENT_MISC_USER : 1096 + PERF_EVENT_MISC_KERNEL; 1209 1097 } 1210 1098 1211 1099 /* ··· 1201 1115 */ 1202 1116 unsigned long perf_instruction_pointer(struct pt_regs *regs) 1203 1117 { 1204 - unsigned long mmcra; 1205 1118 unsigned long ip; 1206 - unsigned long slot; 1207 1119 1208 1120 if (TRAP(regs) != 0xf00) 1209 1121 return regs->nip; /* not a PMU interrupt */ 1210 1122 1211 - ip = mfspr(SPRN_SIAR); 1212 - mmcra = regs->dsisr; 1213 - if ((mmcra & MMCRA_SAMPLE_ENABLE) && !(ppmu->flags & PPMU_ALT_SIPR)) { 1214 - slot = (mmcra & MMCRA_SLOT) >> MMCRA_SLOT_SHIFT; 1215 - if (slot > 1) 1216 - ip += 4 * (slot - 1); 1217 - } 1123 + ip = mfspr(SPRN_SIAR) + perf_ip_adjust(regs); 1218 1124 return ip; 1219 1125 } 1220 1126 ··· 1218 1140 int i; 1219 1141 struct cpu_hw_counters *cpuhw = &__get_cpu_var(cpu_hw_counters); 1220 1142 struct perf_counter *counter; 1221 - long val; 1143 + unsigned long val; 1222 1144 int found = 0; 1223 1145 int nmi; 1224 1146 ··· 1226 1148 freeze_limited_counters(cpuhw, mfspr(SPRN_PMC5), 1227 1149 mfspr(SPRN_PMC6)); 1228 1150 1229 - /* 1230 - * Overload regs->dsisr to store MMCRA so we only need to read it once. 1231 - */ 1232 - regs->dsisr = mfspr(SPRN_MMCRA); 1151 + perf_read_regs(regs); 1233 1152 1234 - /* 1235 - * If interrupts were soft-disabled when this PMU interrupt 1236 - * occurred, treat it as an NMI. 1237 - */ 1238 - nmi = !regs->softe; 1153 + nmi = perf_intr_is_nmi(regs); 1239 1154 if (nmi) 1240 1155 nmi_enter(); 1241 1156 else ··· 1285 1214 cpuhw->mmcr[0] = MMCR0_FC; 1286 1215 } 1287 1216 1288 - extern struct power_pmu power4_pmu; 1289 - extern struct power_pmu ppc970_pmu; 1290 - extern struct power_pmu power5_pmu; 1291 - extern struct power_pmu power5p_pmu; 1292 - extern struct power_pmu power6_pmu; 1293 - extern struct power_pmu power7_pmu; 1294 - 1295 - static int init_perf_counters(void) 1217 + int register_power_pmu(struct power_pmu *pmu) 1296 1218 { 1297 - unsigned long pvr; 1219 + if (ppmu) 1220 + return -EBUSY; /* something's already registered */ 1298 1221 1299 - /* XXX should get this from cputable */ 1300 - pvr = mfspr(SPRN_PVR); 1301 - switch (PVR_VER(pvr)) { 1302 - case PV_POWER4: 1303 - case PV_POWER4p: 1304 - ppmu = &power4_pmu; 1305 - break; 1306 - case PV_970: 1307 - case PV_970FX: 1308 - case PV_970MP: 1309 - ppmu = &ppc970_pmu; 1310 - break; 1311 - case PV_POWER5: 1312 - ppmu = &power5_pmu; 1313 - break; 1314 - case PV_POWER5p: 1315 - ppmu = &power5p_pmu; 1316 - break; 1317 - case 0x3e: 1318 - ppmu = &power6_pmu; 1319 - break; 1320 - case 0x3f: 1321 - ppmu = &power7_pmu; 1322 - break; 1323 - } 1222 + ppmu = pmu; 1223 + pr_info("%s performance monitor hardware support registered\n", 1224 + pmu->name); 1324 1225 1226 + #ifdef MSR_HV 1325 1227 /* 1326 1228 * Use FCHV to ignore kernel events if MSR.HV is set. 1327 1229 */ 1328 1230 if (mfmsr() & MSR_HV) 1329 1231 freeze_counters_kernel = MMCR0_FCHV; 1232 + #endif /* CONFIG_PPC64 */ 1330 1233 1331 1234 return 0; 1332 1235 } 1333 - 1334 - arch_initcall(init_perf_counters);
+53 -36
arch/powerpc/kernel/power4-pmu.c
··· 10 10 */ 11 11 #include <linux/kernel.h> 12 12 #include <linux/perf_counter.h> 13 + #include <linux/string.h> 13 14 #include <asm/reg.h> 15 + #include <asm/cputable.h> 14 16 15 17 /* 16 18 * Bits in event code for POWER4 ··· 181 179 */ 182 180 183 181 static struct unitinfo { 184 - u64 value, mask; 185 - int unit; 186 - int lowerbit; 182 + unsigned long value, mask; 183 + int unit; 184 + int lowerbit; 187 185 } p4_unitinfo[16] = { 188 - [PM_FPU] = { 0x44000000000000ull, 0x88000000000000ull, PM_FPU, 0 }, 189 - [PM_ISU1] = { 0x20080000000000ull, 0x88000000000000ull, PM_ISU1, 0 }, 186 + [PM_FPU] = { 0x44000000000000ul, 0x88000000000000ul, PM_FPU, 0 }, 187 + [PM_ISU1] = { 0x20080000000000ul, 0x88000000000000ul, PM_ISU1, 0 }, 190 188 [PM_ISU1_ALT] = 191 - { 0x20080000000000ull, 0x88000000000000ull, PM_ISU1, 0 }, 192 - [PM_IFU] = { 0x02200000000000ull, 0x08820000000000ull, PM_IFU, 41 }, 189 + { 0x20080000000000ul, 0x88000000000000ul, PM_ISU1, 0 }, 190 + [PM_IFU] = { 0x02200000000000ul, 0x08820000000000ul, PM_IFU, 41 }, 193 191 [PM_IFU_ALT] = 194 - { 0x02200000000000ull, 0x08820000000000ull, PM_IFU, 41 }, 195 - [PM_IDU0] = { 0x10100000000000ull, 0x80840000000000ull, PM_IDU0, 1 }, 196 - [PM_ISU2] = { 0x10140000000000ull, 0x80840000000000ull, PM_ISU2, 0 }, 197 - [PM_LSU0] = { 0x01400000000000ull, 0x08800000000000ull, PM_LSU0, 0 }, 198 - [PM_LSU1] = { 0x00000000000000ull, 0x00010000000000ull, PM_LSU1, 40 }, 199 - [PM_GPS] = { 0x00000000000000ull, 0x00000000000000ull, PM_GPS, 0 } 192 + { 0x02200000000000ul, 0x08820000000000ul, PM_IFU, 41 }, 193 + [PM_IDU0] = { 0x10100000000000ul, 0x80840000000000ul, PM_IDU0, 1 }, 194 + [PM_ISU2] = { 0x10140000000000ul, 0x80840000000000ul, PM_ISU2, 0 }, 195 + [PM_LSU0] = { 0x01400000000000ul, 0x08800000000000ul, PM_LSU0, 0 }, 196 + [PM_LSU1] = { 0x00000000000000ul, 0x00010000000000ul, PM_LSU1, 40 }, 197 + [PM_GPS] = { 0x00000000000000ul, 0x00000000000000ul, PM_GPS, 0 } 200 198 }; 201 199 202 200 static unsigned char direct_marked_event[8] = { ··· 251 249 return (mask >> (byte * 8 + bit)) & 1; 252 250 } 253 251 254 - static int p4_get_constraint(u64 event, u64 *maskp, u64 *valp) 252 + static int p4_get_constraint(u64 event, unsigned long *maskp, 253 + unsigned long *valp) 255 254 { 256 255 int pmc, byte, unit, lower, sh; 257 - u64 mask = 0, value = 0; 256 + unsigned long mask = 0, value = 0; 258 257 int grp = -1; 259 258 260 259 pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; ··· 285 282 value |= p4_unitinfo[unit].value; 286 283 sh = p4_unitinfo[unit].lowerbit; 287 284 if (sh > 1) 288 - value |= (u64)lower << sh; 285 + value |= (unsigned long)lower << sh; 289 286 else if (lower != sh) 290 287 return -1; 291 288 unit = p4_unitinfo[unit].unit; 292 289 293 290 /* Set byte lane select field */ 294 291 mask |= 0xfULL << (28 - 4 * byte); 295 - value |= (u64)unit << (28 - 4 * byte); 292 + value |= (unsigned long)unit << (28 - 4 * byte); 296 293 } 297 294 if (grp == 0) { 298 295 /* increment PMC1/2/5/6 field */ ··· 356 353 } 357 354 358 355 static int p4_compute_mmcr(u64 event[], int n_ev, 359 - unsigned int hwc[], u64 mmcr[]) 356 + unsigned int hwc[], unsigned long mmcr[]) 360 357 { 361 - u64 mmcr0 = 0, mmcr1 = 0, mmcra = 0; 358 + unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0; 362 359 unsigned int pmc, unit, byte, psel, lower; 363 360 unsigned int ttm, grp; 364 361 unsigned int pmc_inuse = 0; ··· 432 429 return -1; 433 430 434 431 /* Set TTMxSEL fields. Note, units 1-3 => TTM0SEL codes 0-2 */ 435 - mmcr1 |= (u64)(unituse[3] * 2 + unituse[2]) << MMCR1_TTM0SEL_SH; 436 - mmcr1 |= (u64)(unituse[7] * 3 + unituse[6] * 2) << MMCR1_TTM1SEL_SH; 437 - mmcr1 |= (u64)unituse[9] << MMCR1_TTM2SEL_SH; 432 + mmcr1 |= (unsigned long)(unituse[3] * 2 + unituse[2]) 433 + << MMCR1_TTM0SEL_SH; 434 + mmcr1 |= (unsigned long)(unituse[7] * 3 + unituse[6] * 2) 435 + << MMCR1_TTM1SEL_SH; 436 + mmcr1 |= (unsigned long)unituse[9] << MMCR1_TTM2SEL_SH; 438 437 439 438 /* Set TTCxSEL fields. */ 440 439 if (unitlower & 0xe) ··· 461 456 ttm = unit - 1; /* 2->1, 3->2 */ 462 457 else 463 458 ttm = unit >> 2; 464 - mmcr1 |= (u64)ttm << (MMCR1_TD_CP_DBG0SEL_SH - 2*byte); 459 + mmcr1 |= (unsigned long)ttm 460 + << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte); 465 461 } 466 462 } 467 463 ··· 525 519 return 0; 526 520 } 527 521 528 - static void p4_disable_pmc(unsigned int pmc, u64 mmcr[]) 522 + static void p4_disable_pmc(unsigned int pmc, unsigned long mmcr[]) 529 523 { 530 524 /* 531 525 * Setting the PMCxSEL field to 0 disables PMC x. ··· 589 583 }, 590 584 }; 591 585 592 - struct power_pmu power4_pmu = { 593 - .n_counter = 8, 594 - .max_alternatives = 5, 595 - .add_fields = 0x0000001100005555ull, 596 - .test_adder = 0x0011083300000000ull, 597 - .compute_mmcr = p4_compute_mmcr, 598 - .get_constraint = p4_get_constraint, 599 - .get_alternatives = p4_get_alternatives, 600 - .disable_pmc = p4_disable_pmc, 601 - .n_generic = ARRAY_SIZE(p4_generic_events), 602 - .generic_events = p4_generic_events, 603 - .cache_events = &power4_cache_events, 586 + static struct power_pmu power4_pmu = { 587 + .name = "POWER4/4+", 588 + .n_counter = 8, 589 + .max_alternatives = 5, 590 + .add_fields = 0x0000001100005555ul, 591 + .test_adder = 0x0011083300000000ul, 592 + .compute_mmcr = p4_compute_mmcr, 593 + .get_constraint = p4_get_constraint, 594 + .get_alternatives = p4_get_alternatives, 595 + .disable_pmc = p4_disable_pmc, 596 + .n_generic = ARRAY_SIZE(p4_generic_events), 597 + .generic_events = p4_generic_events, 598 + .cache_events = &power4_cache_events, 604 599 }; 600 + 601 + static int init_power4_pmu(void) 602 + { 603 + if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power4")) 604 + return -ENODEV; 605 + 606 + return register_power_pmu(&power4_pmu); 607 + } 608 + 609 + arch_initcall(init_power4_pmu);
+56 -39
arch/powerpc/kernel/power5+-pmu.c
··· 10 10 */ 11 11 #include <linux/kernel.h> 12 12 #include <linux/perf_counter.h> 13 + #include <linux/string.h> 13 14 #include <asm/reg.h> 15 + #include <asm/cputable.h> 14 16 15 17 /* 16 18 * Bits in event code for POWER5+ (POWER5 GS) and POWER5++ (POWER5 GS DD3) ··· 128 126 }; 129 127 130 128 /* Masks and values for using events from the various units */ 131 - static u64 unit_cons[PM_LASTUNIT+1][2] = { 132 - [PM_FPU] = { 0x3200000000ull, 0x0100000000ull }, 133 - [PM_ISU0] = { 0x0200000000ull, 0x0080000000ull }, 134 - [PM_ISU1] = { 0x3200000000ull, 0x3100000000ull }, 135 - [PM_IFU] = { 0x3200000000ull, 0x2100000000ull }, 136 - [PM_IDU] = { 0x0e00000000ull, 0x0040000000ull }, 137 - [PM_GRS] = { 0x0e00000000ull, 0x0c40000000ull }, 129 + static unsigned long unit_cons[PM_LASTUNIT+1][2] = { 130 + [PM_FPU] = { 0x3200000000ul, 0x0100000000ul }, 131 + [PM_ISU0] = { 0x0200000000ul, 0x0080000000ul }, 132 + [PM_ISU1] = { 0x3200000000ul, 0x3100000000ul }, 133 + [PM_IFU] = { 0x3200000000ul, 0x2100000000ul }, 134 + [PM_IDU] = { 0x0e00000000ul, 0x0040000000ul }, 135 + [PM_GRS] = { 0x0e00000000ul, 0x0c40000000ul }, 138 136 }; 139 137 140 - static int power5p_get_constraint(u64 event, u64 *maskp, u64 *valp) 138 + static int power5p_get_constraint(u64 event, unsigned long *maskp, 139 + unsigned long *valp) 141 140 { 142 141 int pmc, byte, unit, sh; 143 142 int bit, fmask; 144 - u64 mask = 0, value = 0; 143 + unsigned long mask = 0, value = 0; 145 144 146 145 pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; 147 146 if (pmc) { ··· 174 171 bit = event & 7; 175 172 fmask = (bit == 6)? 7: 3; 176 173 sh = grsel_shift[bit]; 177 - mask |= (u64)fmask << sh; 178 - value |= (u64)((event >> PM_GRS_SH) & fmask) << sh; 174 + mask |= (unsigned long)fmask << sh; 175 + value |= (unsigned long)((event >> PM_GRS_SH) & fmask) 176 + << sh; 179 177 } 180 178 /* Set byte lane select field */ 181 - mask |= 0xfULL << (24 - 4 * byte); 182 - value |= (u64)unit << (24 - 4 * byte); 179 + mask |= 0xfUL << (24 - 4 * byte); 180 + value |= (unsigned long)unit << (24 - 4 * byte); 183 181 } 184 182 if (pmc < 5) { 185 183 /* need a counter from PMC1-4 set */ 186 - mask |= 0x8000000000000ull; 187 - value |= 0x1000000000000ull; 184 + mask |= 0x8000000000000ul; 185 + value |= 0x1000000000000ul; 188 186 } 189 187 *maskp = mask; 190 188 *valp = value; ··· 456 452 } 457 453 458 454 static int power5p_compute_mmcr(u64 event[], int n_ev, 459 - unsigned int hwc[], u64 mmcr[]) 455 + unsigned int hwc[], unsigned long mmcr[]) 460 456 { 461 - u64 mmcr1 = 0; 462 - u64 mmcra = 0; 457 + unsigned long mmcr1 = 0; 458 + unsigned long mmcra = 0; 463 459 unsigned int pmc, unit, byte, psel; 464 460 unsigned int ttm; 465 461 int i, isbus, bit, grsel; ··· 521 517 continue; 522 518 if (ttmuse++) 523 519 return -1; 524 - mmcr1 |= (u64)i << MMCR1_TTM0SEL_SH; 520 + mmcr1 |= (unsigned long)i << MMCR1_TTM0SEL_SH; 525 521 } 526 522 ttmuse = 0; 527 523 for (; i <= PM_GRS; ++i) { ··· 529 525 continue; 530 526 if (ttmuse++) 531 527 return -1; 532 - mmcr1 |= (u64)(i & 3) << MMCR1_TTM1SEL_SH; 528 + mmcr1 |= (unsigned long)(i & 3) << MMCR1_TTM1SEL_SH; 533 529 } 534 530 if (ttmuse > 1) 535 531 return -1; ··· 544 540 unit = PM_ISU0_ALT; 545 541 } else if (unit == PM_LSU1 + 1) { 546 542 /* select lower word of LSU1 for this byte */ 547 - mmcr1 |= 1ull << (MMCR1_TTM3SEL_SH + 3 - byte); 543 + mmcr1 |= 1ul << (MMCR1_TTM3SEL_SH + 3 - byte); 548 544 } 549 545 ttm = unit >> 2; 550 - mmcr1 |= (u64)ttm << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte); 546 + mmcr1 |= (unsigned long)ttm 547 + << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte); 551 548 } 552 549 553 550 /* Second pass: assign PMCs, set PMCxSEL and PMCx_ADDER_SEL fields */ ··· 573 568 if (isbus && (byte & 2) && 574 569 (psel == 8 || psel == 0x10 || psel == 0x28)) 575 570 /* add events on higher-numbered bus */ 576 - mmcr1 |= 1ull << (MMCR1_PMC1_ADDER_SEL_SH - pmc); 571 + mmcr1 |= 1ul << (MMCR1_PMC1_ADDER_SEL_SH - pmc); 577 572 } else { 578 573 /* Instructions or run cycles on PMC5/6 */ 579 574 --pmc; ··· 581 576 if (isbus && unit == PM_GRS) { 582 577 bit = psel & 7; 583 578 grsel = (event[i] >> PM_GRS_SH) & PM_GRS_MSK; 584 - mmcr1 |= (u64)grsel << grsel_shift[bit]; 579 + mmcr1 |= (unsigned long)grsel << grsel_shift[bit]; 585 580 } 586 581 if (power5p_marked_instr_event(event[i])) 587 582 mmcra |= MMCRA_SAMPLE_ENABLE; ··· 604 599 return 0; 605 600 } 606 601 607 - static void power5p_disable_pmc(unsigned int pmc, u64 mmcr[]) 602 + static void power5p_disable_pmc(unsigned int pmc, unsigned long mmcr[]) 608 603 { 609 604 if (pmc <= 3) 610 605 mmcr[1] &= ~(0x7fUL << MMCR1_PMCSEL_SH(pmc)); ··· 659 654 }, 660 655 }; 661 656 662 - struct power_pmu power5p_pmu = { 663 - .n_counter = 6, 664 - .max_alternatives = MAX_ALT, 665 - .add_fields = 0x7000000000055ull, 666 - .test_adder = 0x3000040000000ull, 667 - .compute_mmcr = power5p_compute_mmcr, 668 - .get_constraint = power5p_get_constraint, 669 - .get_alternatives = power5p_get_alternatives, 670 - .disable_pmc = power5p_disable_pmc, 671 - .limited_pmc_event = power5p_limited_pmc_event, 672 - .flags = PPMU_LIMITED_PMC5_6, 673 - .n_generic = ARRAY_SIZE(power5p_generic_events), 674 - .generic_events = power5p_generic_events, 675 - .cache_events = &power5p_cache_events, 657 + static struct power_pmu power5p_pmu = { 658 + .name = "POWER5+/++", 659 + .n_counter = 6, 660 + .max_alternatives = MAX_ALT, 661 + .add_fields = 0x7000000000055ul, 662 + .test_adder = 0x3000040000000ul, 663 + .compute_mmcr = power5p_compute_mmcr, 664 + .get_constraint = power5p_get_constraint, 665 + .get_alternatives = power5p_get_alternatives, 666 + .disable_pmc = power5p_disable_pmc, 667 + .limited_pmc_event = power5p_limited_pmc_event, 668 + .flags = PPMU_LIMITED_PMC5_6, 669 + .n_generic = ARRAY_SIZE(power5p_generic_events), 670 + .generic_events = power5p_generic_events, 671 + .cache_events = &power5p_cache_events, 676 672 }; 673 + 674 + static int init_power5p_pmu(void) 675 + { 676 + if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5+") 677 + && strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5++")) 678 + return -ENODEV; 679 + 680 + return register_power_pmu(&power5p_pmu); 681 + } 682 + 683 + arch_initcall(init_power5p_pmu);
+57 -41
arch/powerpc/kernel/power5-pmu.c
··· 10 10 */ 11 11 #include <linux/kernel.h> 12 12 #include <linux/perf_counter.h> 13 + #include <linux/string.h> 13 14 #include <asm/reg.h> 15 + #include <asm/cputable.h> 14 16 15 17 /* 16 18 * Bits in event code for POWER5 (not POWER5++) ··· 132 130 }; 133 131 134 132 /* Masks and values for using events from the various units */ 135 - static u64 unit_cons[PM_LASTUNIT+1][2] = { 136 - [PM_FPU] = { 0xc0002000000000ull, 0x00001000000000ull }, 137 - [PM_ISU0] = { 0x00002000000000ull, 0x00000800000000ull }, 138 - [PM_ISU1] = { 0xc0002000000000ull, 0xc0001000000000ull }, 139 - [PM_IFU] = { 0xc0002000000000ull, 0x80001000000000ull }, 140 - [PM_IDU] = { 0x30002000000000ull, 0x00000400000000ull }, 141 - [PM_GRS] = { 0x30002000000000ull, 0x30000400000000ull }, 133 + static unsigned long unit_cons[PM_LASTUNIT+1][2] = { 134 + [PM_FPU] = { 0xc0002000000000ul, 0x00001000000000ul }, 135 + [PM_ISU0] = { 0x00002000000000ul, 0x00000800000000ul }, 136 + [PM_ISU1] = { 0xc0002000000000ul, 0xc0001000000000ul }, 137 + [PM_IFU] = { 0xc0002000000000ul, 0x80001000000000ul }, 138 + [PM_IDU] = { 0x30002000000000ul, 0x00000400000000ul }, 139 + [PM_GRS] = { 0x30002000000000ul, 0x30000400000000ul }, 142 140 }; 143 141 144 - static int power5_get_constraint(u64 event, u64 *maskp, u64 *valp) 142 + static int power5_get_constraint(u64 event, unsigned long *maskp, 143 + unsigned long *valp) 145 144 { 146 145 int pmc, byte, unit, sh; 147 146 int bit, fmask; 148 - u64 mask = 0, value = 0; 147 + unsigned long mask = 0, value = 0; 149 148 int grp = -1; 150 149 151 150 pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; ··· 181 178 bit = event & 7; 182 179 fmask = (bit == 6)? 7: 3; 183 180 sh = grsel_shift[bit]; 184 - mask |= (u64)fmask << sh; 185 - value |= (u64)((event >> PM_GRS_SH) & fmask) << sh; 181 + mask |= (unsigned long)fmask << sh; 182 + value |= (unsigned long)((event >> PM_GRS_SH) & fmask) 183 + << sh; 186 184 } 187 185 /* 188 186 * Bus events on bytes 0 and 2 can be counted ··· 192 188 if (!pmc) 193 189 grp = byte & 1; 194 190 /* Set byte lane select field */ 195 - mask |= 0xfULL << (24 - 4 * byte); 196 - value |= (u64)unit << (24 - 4 * byte); 191 + mask |= 0xfUL << (24 - 4 * byte); 192 + value |= (unsigned long)unit << (24 - 4 * byte); 197 193 } 198 194 if (grp == 0) { 199 195 /* increment PMC1/2 field */ 200 - mask |= 0x200000000ull; 201 - value |= 0x080000000ull; 196 + mask |= 0x200000000ul; 197 + value |= 0x080000000ul; 202 198 } else if (grp == 1) { 203 199 /* increment PMC3/4 field */ 204 - mask |= 0x40000000ull; 205 - value |= 0x10000000ull; 200 + mask |= 0x40000000ul; 201 + value |= 0x10000000ul; 206 202 } 207 203 if (pmc < 5) { 208 204 /* need a counter from PMC1-4 set */ 209 - mask |= 0x8000000000000ull; 210 - value |= 0x1000000000000ull; 205 + mask |= 0x8000000000000ul; 206 + value |= 0x1000000000000ul; 211 207 } 212 208 *maskp = mask; 213 209 *valp = value; ··· 387 383 } 388 384 389 385 static int power5_compute_mmcr(u64 event[], int n_ev, 390 - unsigned int hwc[], u64 mmcr[]) 386 + unsigned int hwc[], unsigned long mmcr[]) 391 387 { 392 - u64 mmcr1 = 0; 393 - u64 mmcra = 0; 388 + unsigned long mmcr1 = 0; 389 + unsigned long mmcra = 0; 394 390 unsigned int pmc, unit, byte, psel; 395 391 unsigned int ttm, grp; 396 392 int i, isbus, bit, grsel; ··· 461 457 continue; 462 458 if (ttmuse++) 463 459 return -1; 464 - mmcr1 |= (u64)i << MMCR1_TTM0SEL_SH; 460 + mmcr1 |= (unsigned long)i << MMCR1_TTM0SEL_SH; 465 461 } 466 462 ttmuse = 0; 467 463 for (; i <= PM_GRS; ++i) { ··· 469 465 continue; 470 466 if (ttmuse++) 471 467 return -1; 472 - mmcr1 |= (u64)(i & 3) << MMCR1_TTM1SEL_SH; 468 + mmcr1 |= (unsigned long)(i & 3) << MMCR1_TTM1SEL_SH; 473 469 } 474 470 if (ttmuse > 1) 475 471 return -1; ··· 484 480 unit = PM_ISU0_ALT; 485 481 } else if (unit == PM_LSU1 + 1) { 486 482 /* select lower word of LSU1 for this byte */ 487 - mmcr1 |= 1ull << (MMCR1_TTM3SEL_SH + 3 - byte); 483 + mmcr1 |= 1ul << (MMCR1_TTM3SEL_SH + 3 - byte); 488 484 } 489 485 ttm = unit >> 2; 490 - mmcr1 |= (u64)ttm << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte); 486 + mmcr1 |= (unsigned long)ttm 487 + << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte); 491 488 } 492 489 493 490 /* Second pass: assign PMCs, set PMCxSEL and PMCx_ADDER_SEL fields */ ··· 518 513 --pmc; 519 514 if ((psel == 8 || psel == 0x10) && isbus && (byte & 2)) 520 515 /* add events on higher-numbered bus */ 521 - mmcr1 |= 1ull << (MMCR1_PMC1_ADDER_SEL_SH - pmc); 516 + mmcr1 |= 1ul << (MMCR1_PMC1_ADDER_SEL_SH - pmc); 522 517 } else { 523 518 /* Instructions or run cycles on PMC5/6 */ 524 519 --pmc; ··· 526 521 if (isbus && unit == PM_GRS) { 527 522 bit = psel & 7; 528 523 grsel = (event[i] >> PM_GRS_SH) & PM_GRS_MSK; 529 - mmcr1 |= (u64)grsel << grsel_shift[bit]; 524 + mmcr1 |= (unsigned long)grsel << grsel_shift[bit]; 530 525 } 531 526 if (power5_marked_instr_event(event[i])) 532 527 mmcra |= MMCRA_SAMPLE_ENABLE; ··· 546 541 return 0; 547 542 } 548 543 549 - static void power5_disable_pmc(unsigned int pmc, u64 mmcr[]) 544 + static void power5_disable_pmc(unsigned int pmc, unsigned long mmcr[]) 550 545 { 551 546 if (pmc <= 3) 552 547 mmcr[1] &= ~(0x7fUL << MMCR1_PMCSEL_SH(pmc)); ··· 601 596 }, 602 597 }; 603 598 604 - struct power_pmu power5_pmu = { 605 - .n_counter = 6, 606 - .max_alternatives = MAX_ALT, 607 - .add_fields = 0x7000090000555ull, 608 - .test_adder = 0x3000490000000ull, 609 - .compute_mmcr = power5_compute_mmcr, 610 - .get_constraint = power5_get_constraint, 611 - .get_alternatives = power5_get_alternatives, 612 - .disable_pmc = power5_disable_pmc, 613 - .n_generic = ARRAY_SIZE(power5_generic_events), 614 - .generic_events = power5_generic_events, 615 - .cache_events = &power5_cache_events, 599 + static struct power_pmu power5_pmu = { 600 + .name = "POWER5", 601 + .n_counter = 6, 602 + .max_alternatives = MAX_ALT, 603 + .add_fields = 0x7000090000555ul, 604 + .test_adder = 0x3000490000000ul, 605 + .compute_mmcr = power5_compute_mmcr, 606 + .get_constraint = power5_get_constraint, 607 + .get_alternatives = power5_get_alternatives, 608 + .disable_pmc = power5_disable_pmc, 609 + .n_generic = ARRAY_SIZE(power5_generic_events), 610 + .generic_events = power5_generic_events, 611 + .cache_events = &power5_cache_events, 616 612 }; 613 + 614 + static int init_power5_pmu(void) 615 + { 616 + if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5")) 617 + return -ENODEV; 618 + 619 + return register_power_pmu(&power5_pmu); 620 + } 621 + 622 + arch_initcall(init_power5_pmu);
+43 -29
arch/powerpc/kernel/power6-pmu.c
··· 10 10 */ 11 11 #include <linux/kernel.h> 12 12 #include <linux/perf_counter.h> 13 + #include <linux/string.h> 13 14 #include <asm/reg.h> 15 + #include <asm/cputable.h> 14 16 15 17 /* 16 18 * Bits in event code for POWER6 ··· 43 41 #define MMCR1_NESTSEL_SH 45 44 42 #define MMCR1_NESTSEL_MSK 0x7 45 43 #define MMCR1_NESTSEL(m) (((m) >> MMCR1_NESTSEL_SH) & MMCR1_NESTSEL_MSK) 46 - #define MMCR1_PMC1_LLA ((u64)1 << 44) 47 - #define MMCR1_PMC1_LLA_VALUE ((u64)1 << 39) 48 - #define MMCR1_PMC1_ADDR_SEL ((u64)1 << 35) 44 + #define MMCR1_PMC1_LLA (1ul << 44) 45 + #define MMCR1_PMC1_LLA_VALUE (1ul << 39) 46 + #define MMCR1_PMC1_ADDR_SEL (1ul << 35) 49 47 #define MMCR1_PMC1SEL_SH 24 50 48 #define MMCR1_PMCSEL_SH(n) (MMCR1_PMC1SEL_SH - (n) * 8) 51 49 #define MMCR1_PMCSEL_MSK 0xff ··· 175 173 * Assign PMC numbers and compute MMCR1 value for a set of events 176 174 */ 177 175 static int p6_compute_mmcr(u64 event[], int n_ev, 178 - unsigned int hwc[], u64 mmcr[]) 176 + unsigned int hwc[], unsigned long mmcr[]) 179 177 { 180 - u64 mmcr1 = 0; 181 - u64 mmcra = 0; 178 + unsigned long mmcr1 = 0; 179 + unsigned long mmcra = 0; 182 180 int i; 183 181 unsigned int pmc, ev, b, u, s, psel; 184 182 unsigned int ttmset = 0; ··· 217 215 /* check for conflict on this byte of event bus */ 218 216 if ((ttmset & (1 << b)) && MMCR1_TTMSEL(mmcr1, b) != u) 219 217 return -1; 220 - mmcr1 |= (u64)u << MMCR1_TTMSEL_SH(b); 218 + mmcr1 |= (unsigned long)u << MMCR1_TTMSEL_SH(b); 221 219 ttmset |= 1 << b; 222 220 if (u == 5) { 223 221 /* Nest events have a further mux */ ··· 226 224 MMCR1_NESTSEL(mmcr1) != s) 227 225 return -1; 228 226 ttmset |= 0x10; 229 - mmcr1 |= (u64)s << MMCR1_NESTSEL_SH; 227 + mmcr1 |= (unsigned long)s << MMCR1_NESTSEL_SH; 230 228 } 231 229 if (0x30 <= psel && psel <= 0x3d) { 232 230 /* these need the PMCx_ADDR_SEL bits */ ··· 245 243 if (power6_marked_instr_event(event[i])) 246 244 mmcra |= MMCRA_SAMPLE_ENABLE; 247 245 if (pmc < 4) 248 - mmcr1 |= (u64)psel << MMCR1_PMCSEL_SH(pmc); 246 + mmcr1 |= (unsigned long)psel << MMCR1_PMCSEL_SH(pmc); 249 247 } 250 248 mmcr[0] = 0; 251 249 if (pmc_inuse & 1) ··· 267 265 * 20-23, 24-27, 28-31 ditto for bytes 1, 2, 3 268 266 * 32-34 select field: nest (subunit) event selector 269 267 */ 270 - static int p6_get_constraint(u64 event, u64 *maskp, u64 *valp) 268 + static int p6_get_constraint(u64 event, unsigned long *maskp, 269 + unsigned long *valp) 271 270 { 272 271 int pmc, byte, sh, subunit; 273 - u64 mask = 0, value = 0; 272 + unsigned long mask = 0, value = 0; 274 273 275 274 pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; 276 275 if (pmc) { ··· 285 282 byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK; 286 283 sh = byte * 4 + (16 - PM_UNIT_SH); 287 284 mask |= PM_UNIT_MSKS << sh; 288 - value |= (u64)(event & PM_UNIT_MSKS) << sh; 285 + value |= (unsigned long)(event & PM_UNIT_MSKS) << sh; 289 286 if ((event & PM_UNIT_MSKS) == (5 << PM_UNIT_SH)) { 290 287 subunit = (event >> PM_SUBUNIT_SH) & PM_SUBUNIT_MSK; 291 - mask |= (u64)PM_SUBUNIT_MSK << 32; 292 - value |= (u64)subunit << 32; 288 + mask |= (unsigned long)PM_SUBUNIT_MSK << 32; 289 + value |= (unsigned long)subunit << 32; 293 290 } 294 291 } 295 292 if (pmc <= 4) { ··· 461 458 return nalt; 462 459 } 463 460 464 - static void p6_disable_pmc(unsigned int pmc, u64 mmcr[]) 461 + static void p6_disable_pmc(unsigned int pmc, unsigned long mmcr[]) 465 462 { 466 463 /* Set PMCxSEL to 0 to disable PMCx */ 467 464 if (pmc <= 3) ··· 518 515 }, 519 516 }; 520 517 521 - struct power_pmu power6_pmu = { 522 - .n_counter = 6, 523 - .max_alternatives = MAX_ALT, 524 - .add_fields = 0x1555, 525 - .test_adder = 0x3000, 526 - .compute_mmcr = p6_compute_mmcr, 527 - .get_constraint = p6_get_constraint, 528 - .get_alternatives = p6_get_alternatives, 529 - .disable_pmc = p6_disable_pmc, 530 - .limited_pmc_event = p6_limited_pmc_event, 531 - .flags = PPMU_LIMITED_PMC5_6 | PPMU_ALT_SIPR, 532 - .n_generic = ARRAY_SIZE(power6_generic_events), 533 - .generic_events = power6_generic_events, 534 - .cache_events = &power6_cache_events, 518 + static struct power_pmu power6_pmu = { 519 + .name = "POWER6", 520 + .n_counter = 6, 521 + .max_alternatives = MAX_ALT, 522 + .add_fields = 0x1555, 523 + .test_adder = 0x3000, 524 + .compute_mmcr = p6_compute_mmcr, 525 + .get_constraint = p6_get_constraint, 526 + .get_alternatives = p6_get_alternatives, 527 + .disable_pmc = p6_disable_pmc, 528 + .limited_pmc_event = p6_limited_pmc_event, 529 + .flags = PPMU_LIMITED_PMC5_6 | PPMU_ALT_SIPR, 530 + .n_generic = ARRAY_SIZE(power6_generic_events), 531 + .generic_events = power6_generic_events, 532 + .cache_events = &power6_cache_events, 535 533 }; 534 + 535 + static int init_power6_pmu(void) 536 + { 537 + if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power6")) 538 + return -ENODEV; 539 + 540 + return register_power_pmu(&power6_pmu); 541 + } 542 + 543 + arch_initcall(init_power6_pmu);
+39 -22
arch/powerpc/kernel/power7-pmu.c
··· 10 10 */ 11 11 #include <linux/kernel.h> 12 12 #include <linux/perf_counter.h> 13 + #include <linux/string.h> 13 14 #include <asm/reg.h> 15 + #include <asm/cputable.h> 14 16 15 17 /* 16 18 * Bits in event code for POWER7 ··· 73 71 * 0-9: Count of events needing PMC1..PMC5 74 72 */ 75 73 76 - static int power7_get_constraint(u64 event, u64 *maskp, u64 *valp) 74 + static int power7_get_constraint(u64 event, unsigned long *maskp, 75 + unsigned long *valp) 77 76 { 78 77 int pmc, sh; 79 - u64 mask = 0, value = 0; 78 + unsigned long mask = 0, value = 0; 80 79 81 80 pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; 82 81 if (pmc) { ··· 227 224 } 228 225 229 226 static int power7_compute_mmcr(u64 event[], int n_ev, 230 - unsigned int hwc[], u64 mmcr[]) 227 + unsigned int hwc[], unsigned long mmcr[]) 231 228 { 232 - u64 mmcr1 = 0; 233 - u64 mmcra = 0; 229 + unsigned long mmcr1 = 0; 230 + unsigned long mmcra = 0; 234 231 unsigned int pmc, unit, combine, l2sel, psel; 235 232 unsigned int pmc_inuse = 0; 236 233 int i; ··· 268 265 --pmc; 269 266 } 270 267 if (pmc <= 3) { 271 - mmcr1 |= (u64) unit << (MMCR1_TTM0SEL_SH - 4 * pmc); 272 - mmcr1 |= (u64) combine << (MMCR1_PMC1_COMBINE_SH - pmc); 268 + mmcr1 |= (unsigned long) unit 269 + << (MMCR1_TTM0SEL_SH - 4 * pmc); 270 + mmcr1 |= (unsigned long) combine 271 + << (MMCR1_PMC1_COMBINE_SH - pmc); 273 272 mmcr1 |= psel << MMCR1_PMCSEL_SH(pmc); 274 273 if (unit == 6) /* L2 events */ 275 - mmcr1 |= (u64) l2sel << MMCR1_L2SEL_SH; 274 + mmcr1 |= (unsigned long) l2sel 275 + << MMCR1_L2SEL_SH; 276 276 } 277 277 if (power7_marked_instr_event(event[i])) 278 278 mmcra |= MMCRA_SAMPLE_ENABLE; ··· 293 287 return 0; 294 288 } 295 289 296 - static void power7_disable_pmc(unsigned int pmc, u64 mmcr[]) 290 + static void power7_disable_pmc(unsigned int pmc, unsigned long mmcr[]) 297 291 { 298 292 if (pmc <= 3) 299 - mmcr[1] &= ~(0xffULL << MMCR1_PMCSEL_SH(pmc)); 293 + mmcr[1] &= ~(0xffUL << MMCR1_PMCSEL_SH(pmc)); 300 294 } 301 295 302 296 static int power7_generic_events[] = { ··· 348 342 }, 349 343 }; 350 344 351 - struct power_pmu power7_pmu = { 352 - .n_counter = 6, 353 - .max_alternatives = MAX_ALT + 1, 354 - .add_fields = 0x1555ull, 355 - .test_adder = 0x3000ull, 356 - .compute_mmcr = power7_compute_mmcr, 357 - .get_constraint = power7_get_constraint, 358 - .get_alternatives = power7_get_alternatives, 359 - .disable_pmc = power7_disable_pmc, 360 - .n_generic = ARRAY_SIZE(power7_generic_events), 361 - .generic_events = power7_generic_events, 362 - .cache_events = &power7_cache_events, 345 + static struct power_pmu power7_pmu = { 346 + .name = "POWER7", 347 + .n_counter = 6, 348 + .max_alternatives = MAX_ALT + 1, 349 + .add_fields = 0x1555ul, 350 + .test_adder = 0x3000ul, 351 + .compute_mmcr = power7_compute_mmcr, 352 + .get_constraint = power7_get_constraint, 353 + .get_alternatives = power7_get_alternatives, 354 + .disable_pmc = power7_disable_pmc, 355 + .n_generic = ARRAY_SIZE(power7_generic_events), 356 + .generic_events = power7_generic_events, 357 + .cache_events = &power7_cache_events, 363 358 }; 359 + 360 + static int init_power7_pmu(void) 361 + { 362 + if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power7")) 363 + return -ENODEV; 364 + 365 + return register_power_pmu(&power7_pmu); 366 + } 367 + 368 + arch_initcall(init_power7_pmu);
+40 -23
arch/powerpc/kernel/ppc970-pmu.c
··· 10 10 */ 11 11 #include <linux/string.h> 12 12 #include <linux/perf_counter.h> 13 + #include <linux/string.h> 13 14 #include <asm/reg.h> 15 + #include <asm/cputable.h> 14 16 15 17 /* 16 18 * Bits in event code for PPC970 ··· 185 183 } 186 184 187 185 /* Masks and values for using events from the various units */ 188 - static u64 unit_cons[PM_LASTUNIT+1][2] = { 186 + static unsigned long unit_cons[PM_LASTUNIT+1][2] = { 189 187 [PM_FPU] = { 0xc80000000000ull, 0x040000000000ull }, 190 188 [PM_VPU] = { 0xc80000000000ull, 0xc40000000000ull }, 191 189 [PM_ISU] = { 0x080000000000ull, 0x020000000000ull }, ··· 194 192 [PM_STS] = { 0x380000000000ull, 0x310000000000ull }, 195 193 }; 196 194 197 - static int p970_get_constraint(u64 event, u64 *maskp, u64 *valp) 195 + static int p970_get_constraint(u64 event, unsigned long *maskp, 196 + unsigned long *valp) 198 197 { 199 198 int pmc, byte, unit, sh, spcsel; 200 - u64 mask = 0, value = 0; 199 + unsigned long mask = 0, value = 0; 201 200 int grp = -1; 202 201 203 202 pmc = (event >> PM_PMC_SH) & PM_PMC_MSK; ··· 225 222 grp = byte & 1; 226 223 /* Set byte lane select field */ 227 224 mask |= 0xfULL << (28 - 4 * byte); 228 - value |= (u64)unit << (28 - 4 * byte); 225 + value |= (unsigned long)unit << (28 - 4 * byte); 229 226 } 230 227 if (grp == 0) { 231 228 /* increment PMC1/2/5/6 field */ ··· 239 236 spcsel = (event >> PM_SPCSEL_SH) & PM_SPCSEL_MSK; 240 237 if (spcsel) { 241 238 mask |= 3ull << 48; 242 - value |= (u64)spcsel << 48; 239 + value |= (unsigned long)spcsel << 48; 243 240 } 244 241 *maskp = mask; 245 242 *valp = value; ··· 260 257 } 261 258 262 259 static int p970_compute_mmcr(u64 event[], int n_ev, 263 - unsigned int hwc[], u64 mmcr[]) 260 + unsigned int hwc[], unsigned long mmcr[]) 264 261 { 265 - u64 mmcr0 = 0, mmcr1 = 0, mmcra = 0; 262 + unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0; 266 263 unsigned int pmc, unit, byte, psel; 267 264 unsigned int ttm, grp; 268 265 unsigned int pmc_inuse = 0; ··· 323 320 continue; 324 321 ttm = unitmap[i]; 325 322 ++ttmuse[(ttm >> 2) & 1]; 326 - mmcr1 |= (u64)(ttm & ~4) << MMCR1_TTM1SEL_SH; 323 + mmcr1 |= (unsigned long)(ttm & ~4) << MMCR1_TTM1SEL_SH; 327 324 } 328 325 /* Check only one unit per TTMx */ 329 326 if (ttmuse[0] > 1 || ttmuse[1] > 1) ··· 343 340 if (unit == PM_LSU1L && byte >= 2) 344 341 mmcr1 |= 1ull << (MMCR1_TTM3SEL_SH + 3 - byte); 345 342 } 346 - mmcr1 |= (u64)ttm << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte); 343 + mmcr1 |= (unsigned long)ttm 344 + << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte); 347 345 } 348 346 349 347 /* Second pass: assign PMCs, set PMCxSEL and PMCx_ADDER_SEL fields */ ··· 390 386 for (pmc = 0; pmc < 2; ++pmc) 391 387 mmcr0 |= pmcsel[pmc] << (MMCR0_PMC1SEL_SH - 7 * pmc); 392 388 for (; pmc < 8; ++pmc) 393 - mmcr1 |= (u64)pmcsel[pmc] << (MMCR1_PMC3SEL_SH - 5 * (pmc - 2)); 389 + mmcr1 |= (unsigned long)pmcsel[pmc] 390 + << (MMCR1_PMC3SEL_SH - 5 * (pmc - 2)); 394 391 if (pmc_inuse & 1) 395 392 mmcr0 |= MMCR0_PMC1CE; 396 393 if (pmc_inuse & 0xfe) ··· 406 401 return 0; 407 402 } 408 403 409 - static void p970_disable_pmc(unsigned int pmc, u64 mmcr[]) 404 + static void p970_disable_pmc(unsigned int pmc, unsigned long mmcr[]) 410 405 { 411 406 int shift, i; 412 407 ··· 472 467 }, 473 468 }; 474 469 475 - struct power_pmu ppc970_pmu = { 476 - .n_counter = 8, 477 - .max_alternatives = 2, 478 - .add_fields = 0x001100005555ull, 479 - .test_adder = 0x013300000000ull, 480 - .compute_mmcr = p970_compute_mmcr, 481 - .get_constraint = p970_get_constraint, 482 - .get_alternatives = p970_get_alternatives, 483 - .disable_pmc = p970_disable_pmc, 484 - .n_generic = ARRAY_SIZE(ppc970_generic_events), 485 - .generic_events = ppc970_generic_events, 486 - .cache_events = &ppc970_cache_events, 470 + static struct power_pmu ppc970_pmu = { 471 + .name = "PPC970/FX/MP", 472 + .n_counter = 8, 473 + .max_alternatives = 2, 474 + .add_fields = 0x001100005555ull, 475 + .test_adder = 0x013300000000ull, 476 + .compute_mmcr = p970_compute_mmcr, 477 + .get_constraint = p970_get_constraint, 478 + .get_alternatives = p970_get_alternatives, 479 + .disable_pmc = p970_disable_pmc, 480 + .n_generic = ARRAY_SIZE(ppc970_generic_events), 481 + .generic_events = ppc970_generic_events, 482 + .cache_events = &ppc970_cache_events, 487 483 }; 484 + 485 + static int init_ppc970_pmu(void) 486 + { 487 + if (strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/970") 488 + && strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/970MP")) 489 + return -ENODEV; 490 + 491 + return register_power_pmu(&ppc970_pmu); 492 + } 493 + 494 + arch_initcall(init_ppc970_pmu);
+25
arch/powerpc/kernel/time.c
··· 53 53 #include <linux/posix-timers.h> 54 54 #include <linux/irq.h> 55 55 #include <linux/delay.h> 56 + #include <linux/perf_counter.h> 56 57 57 58 #include <asm/io.h> 58 59 #include <asm/processor.h> ··· 526 525 } 527 526 #endif /* CONFIG_PPC_ISERIES */ 528 527 528 + #if defined(CONFIG_PERF_COUNTERS) && defined(CONFIG_PPC32) 529 + DEFINE_PER_CPU(u8, perf_counter_pending); 530 + 531 + void set_perf_counter_pending(void) 532 + { 533 + get_cpu_var(perf_counter_pending) = 1; 534 + set_dec(1); 535 + put_cpu_var(perf_counter_pending); 536 + } 537 + 538 + #define test_perf_counter_pending() __get_cpu_var(perf_counter_pending) 539 + #define clear_perf_counter_pending() __get_cpu_var(perf_counter_pending) = 0 540 + 541 + #else /* CONFIG_PERF_COUNTERS && CONFIG_PPC32 */ 542 + 543 + #define test_perf_counter_pending() 0 544 + #define clear_perf_counter_pending() 545 + 546 + #endif /* CONFIG_PERF_COUNTERS && CONFIG_PPC32 */ 547 + 529 548 /* 530 549 * For iSeries shared processors, we have to let the hypervisor 531 550 * set the hardware decrementer. We set a virtual decrementer ··· 572 551 set_dec(DECREMENTER_MAX); 573 552 574 553 #ifdef CONFIG_PPC32 554 + if (test_perf_counter_pending()) { 555 + clear_perf_counter_pending(); 556 + perf_counter_do_pending(); 557 + } 575 558 if (atomic_read(&ppc_n_lost_interrupts) != 0) 576 559 do_IRQ(regs); 577 560 #endif
+11 -1
arch/powerpc/platforms/Kconfig.cputype
··· 1 1 config PPC64 2 2 bool "64-bit kernel" 3 3 default n 4 - select HAVE_PERF_COUNTERS 4 + select PPC_HAVE_PMU_SUPPORT 5 5 help 6 6 This option selects whether a 32-bit or a 64-bit kernel 7 7 will be built. ··· 78 78 config 6xx 79 79 def_bool y 80 80 depends on PPC32 && PPC_BOOK3S 81 + select PPC_HAVE_PMU_SUPPORT 81 82 82 83 config POWER3 83 84 bool ··· 246 245 IBM POWER5-based machines. 247 246 248 247 If in doubt, say Y here. 248 + 249 + config PPC_HAVE_PMU_SUPPORT 250 + bool 251 + 252 + config PPC_PERF_CTRS 253 + def_bool y 254 + depends on PERF_COUNTERS && PPC_HAVE_PMU_SUPPORT 255 + help 256 + This enables the powerpc-specific perf_counter back-end. 249 257 250 258 config SMP 251 259 depends on PPC_STD_MMU || FSL_BOOKE
-5
arch/x86/include/asm/perf_counter.h
··· 84 84 #define MSR_ARCH_PERFMON_FIXED_CTR2 0x30b 85 85 #define X86_PMC_IDX_FIXED_BUS_CYCLES (X86_PMC_IDX_FIXED + 2) 86 86 87 - extern void set_perf_counter_pending(void); 88 - 89 - #define clear_perf_counter_pending() do { } while (0) 90 - #define test_perf_counter_pending() (0) 91 - 92 87 #ifdef CONFIG_PERF_COUNTERS 93 88 extern void init_hw_perf_counters(void); 94 89 extern void perf_counters_lapic_init(void);
+6 -2
arch/x86/include/asm/pgtable_32.h
··· 49 49 #endif 50 50 51 51 #if defined(CONFIG_HIGHPTE) 52 + #define __KM_PTE \ 53 + (in_nmi() ? KM_NMI_PTE : \ 54 + in_irq() ? KM_IRQ_PTE : \ 55 + KM_PTE0) 52 56 #define pte_offset_map(dir, address) \ 53 - ((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), KM_PTE0) + \ 57 + ((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), __KM_PTE) + \ 54 58 pte_index((address))) 55 59 #define pte_offset_map_nested(dir, address) \ 56 60 ((pte_t *)kmap_atomic_pte(pmd_page(*(dir)), KM_PTE1) + \ 57 61 pte_index((address))) 58 - #define pte_unmap(pte) kunmap_atomic((pte), KM_PTE0) 62 + #define pte_unmap(pte) kunmap_atomic((pte), __KM_PTE) 59 63 #define pte_unmap_nested(pte) kunmap_atomic((pte), KM_PTE1) 60 64 #else 61 65 #define pte_offset_map(dir, address) \
+6 -1
arch/x86/include/asm/uaccess.h
··· 25 25 #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) 26 26 27 27 #define KERNEL_DS MAKE_MM_SEG(-1UL) 28 - #define USER_DS MAKE_MM_SEG(PAGE_OFFSET) 28 + 29 + #ifdef CONFIG_X86_32 30 + # define USER_DS MAKE_MM_SEG(PAGE_OFFSET) 31 + #else 32 + # define USER_DS MAKE_MM_SEG(__VIRTUAL_MASK) 33 + #endif 29 34 30 35 #define get_ds() (KERNEL_DS) 31 36 #define get_fs() (current_thread_info()->addr_limit)
+76 -66
arch/x86/kernel/cpu/perf_counter.c
··· 19 19 #include <linux/kdebug.h> 20 20 #include <linux/sched.h> 21 21 #include <linux/uaccess.h> 22 + #include <linux/highmem.h> 22 23 23 24 #include <asm/apic.h> 24 25 #include <asm/stacktrace.h> ··· 390 389 return event & CORE_EVNTSEL_MASK; 391 390 } 392 391 393 - static const u64 amd_0f_hw_cache_event_ids 392 + static const u64 amd_hw_cache_event_ids 394 393 [PERF_COUNT_HW_CACHE_MAX] 395 394 [PERF_COUNT_HW_CACHE_OP_MAX] 396 395 [PERF_COUNT_HW_CACHE_RESULT_MAX] = 397 396 { 398 397 [ C(L1D) ] = { 399 398 [ C(OP_READ) ] = { 400 - [ C(RESULT_ACCESS) ] = 0, 401 - [ C(RESULT_MISS) ] = 0, 399 + [ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses */ 400 + [ C(RESULT_MISS) ] = 0x0041, /* Data Cache Misses */ 402 401 }, 403 402 [ C(OP_WRITE) ] = { 404 - [ C(RESULT_ACCESS) ] = 0, 403 + [ C(RESULT_ACCESS) ] = 0x0042, /* Data Cache Refills from L2 */ 405 404 [ C(RESULT_MISS) ] = 0, 406 405 }, 407 406 [ C(OP_PREFETCH) ] = { 408 - [ C(RESULT_ACCESS) ] = 0, 409 - [ C(RESULT_MISS) ] = 0, 407 + [ C(RESULT_ACCESS) ] = 0x0267, /* Data Prefetcher :attempts */ 408 + [ C(RESULT_MISS) ] = 0x0167, /* Data Prefetcher :cancelled */ 410 409 }, 411 410 }, 412 411 [ C(L1I ) ] = { ··· 419 418 [ C(RESULT_MISS) ] = -1, 420 419 }, 421 420 [ C(OP_PREFETCH) ] = { 422 - [ C(RESULT_ACCESS) ] = 0, 421 + [ C(RESULT_ACCESS) ] = 0x014B, /* Prefetch Instructions :Load */ 423 422 [ C(RESULT_MISS) ] = 0, 424 423 }, 425 424 }, 426 425 [ C(LL ) ] = { 427 426 [ C(OP_READ) ] = { 428 - [ C(RESULT_ACCESS) ] = 0, 429 - [ C(RESULT_MISS) ] = 0, 427 + [ C(RESULT_ACCESS) ] = 0x037D, /* Requests to L2 Cache :IC+DC */ 428 + [ C(RESULT_MISS) ] = 0x037E, /* L2 Cache Misses : IC+DC */ 430 429 }, 431 430 [ C(OP_WRITE) ] = { 432 - [ C(RESULT_ACCESS) ] = 0, 431 + [ C(RESULT_ACCESS) ] = 0x017F, /* L2 Fill/Writeback */ 433 432 [ C(RESULT_MISS) ] = 0, 434 433 }, 435 434 [ C(OP_PREFETCH) ] = { ··· 439 438 }, 440 439 [ C(DTLB) ] = { 441 440 [ C(OP_READ) ] = { 442 - [ C(RESULT_ACCESS) ] = 0, 443 - [ C(RESULT_MISS) ] = 0, 441 + [ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses */ 442 + [ C(RESULT_MISS) ] = 0x0046, /* L1 DTLB and L2 DLTB Miss */ 444 443 }, 445 444 [ C(OP_WRITE) ] = { 446 445 [ C(RESULT_ACCESS) ] = 0, ··· 1224 1223 if (!intel_pmu_save_and_restart(counter)) 1225 1224 continue; 1226 1225 1226 + data.period = counter->hw.last_period; 1227 + 1227 1228 if (perf_counter_overflow(counter, 1, &data)) 1228 1229 intel_pmu_disable_counter(&counter->hw, bit); 1229 1230 } ··· 1462 1459 1463 1460 static int amd_pmu_init(void) 1464 1461 { 1462 + /* Performance-monitoring supported from K7 and later: */ 1463 + if (boot_cpu_data.x86 < 6) 1464 + return -ENODEV; 1465 + 1465 1466 x86_pmu = amd_pmu; 1466 1467 1467 - switch (boot_cpu_data.x86) { 1468 - case 0x0f: 1469 - case 0x10: 1470 - case 0x11: 1471 - memcpy(hw_cache_event_ids, amd_0f_hw_cache_event_ids, 1472 - sizeof(hw_cache_event_ids)); 1468 + /* Events are common for all AMDs */ 1469 + memcpy(hw_cache_event_ids, amd_hw_cache_event_ids, 1470 + sizeof(hw_cache_event_ids)); 1473 1471 1474 - pr_cont("AMD Family 0f/10/11 events, "); 1475 - break; 1476 - } 1477 1472 return 0; 1478 1473 } 1479 1474 ··· 1555 1554 */ 1556 1555 1557 1556 static inline 1558 - void callchain_store(struct perf_callchain_entry *entry, unsigned long ip) 1557 + void callchain_store(struct perf_callchain_entry *entry, u64 ip) 1559 1558 { 1560 - if (entry->nr < MAX_STACK_DEPTH) 1559 + if (entry->nr < PERF_MAX_STACK_DEPTH) 1561 1560 entry->ip[entry->nr++] = ip; 1562 1561 } 1563 1562 ··· 1578 1577 1579 1578 static int backtrace_stack(void *data, char *name) 1580 1579 { 1581 - /* Don't bother with IRQ stacks for now */ 1582 - return -1; 1580 + /* Process all stacks: */ 1581 + return 0; 1583 1582 } 1584 1583 1585 1584 static void backtrace_address(void *data, unsigned long addr, int reliable) ··· 1597 1596 .address = backtrace_address, 1598 1597 }; 1599 1598 1599 + #include "../dumpstack.h" 1600 + 1600 1601 static void 1601 1602 perf_callchain_kernel(struct pt_regs *regs, struct perf_callchain_entry *entry) 1602 1603 { 1603 - unsigned long bp; 1604 - char *stack; 1605 - int nr = entry->nr; 1604 + callchain_store(entry, PERF_CONTEXT_KERNEL); 1605 + callchain_store(entry, regs->ip); 1606 1606 1607 - callchain_store(entry, instruction_pointer(regs)); 1608 - 1609 - stack = ((char *)regs + sizeof(struct pt_regs)); 1610 - #ifdef CONFIG_FRAME_POINTER 1611 - bp = frame_pointer(regs); 1612 - #else 1613 - bp = 0; 1614 - #endif 1615 - 1616 - dump_trace(NULL, regs, (void *)stack, bp, &backtrace_ops, entry); 1617 - 1618 - entry->kernel = entry->nr - nr; 1607 + dump_trace(NULL, regs, NULL, 0, &backtrace_ops, entry); 1619 1608 } 1620 1609 1610 + /* 1611 + * best effort, GUP based copy_from_user() that assumes IRQ or NMI context 1612 + */ 1613 + static unsigned long 1614 + copy_from_user_nmi(void *to, const void __user *from, unsigned long n) 1615 + { 1616 + unsigned long offset, addr = (unsigned long)from; 1617 + int type = in_nmi() ? KM_NMI : KM_IRQ0; 1618 + unsigned long size, len = 0; 1619 + struct page *page; 1620 + void *map; 1621 + int ret; 1621 1622 1622 - struct stack_frame { 1623 - const void __user *next_fp; 1624 - unsigned long return_address; 1625 - }; 1623 + do { 1624 + ret = __get_user_pages_fast(addr, 1, 0, &page); 1625 + if (!ret) 1626 + break; 1627 + 1628 + offset = addr & (PAGE_SIZE - 1); 1629 + size = min(PAGE_SIZE - offset, n - len); 1630 + 1631 + map = kmap_atomic(page, type); 1632 + memcpy(to, map+offset, size); 1633 + kunmap_atomic(map, type); 1634 + put_page(page); 1635 + 1636 + len += size; 1637 + to += size; 1638 + addr += size; 1639 + 1640 + } while (len < n); 1641 + 1642 + return len; 1643 + } 1626 1644 1627 1645 static int copy_stack_frame(const void __user *fp, struct stack_frame *frame) 1628 1646 { 1629 - int ret; 1647 + unsigned long bytes; 1630 1648 1631 - if (!access_ok(VERIFY_READ, fp, sizeof(*frame))) 1632 - return 0; 1649 + bytes = copy_from_user_nmi(frame, fp, sizeof(*frame)); 1633 1650 1634 - ret = 1; 1635 - pagefault_disable(); 1636 - if (__copy_from_user_inatomic(frame, fp, sizeof(*frame))) 1637 - ret = 0; 1638 - pagefault_enable(); 1639 - 1640 - return ret; 1651 + return bytes == sizeof(*frame); 1641 1652 } 1642 1653 1643 1654 static void ··· 1657 1644 { 1658 1645 struct stack_frame frame; 1659 1646 const void __user *fp; 1660 - int nr = entry->nr; 1661 1647 1662 - regs = (struct pt_regs *)current->thread.sp0 - 1; 1663 - fp = (void __user *)regs->bp; 1648 + if (!user_mode(regs)) 1649 + regs = task_pt_regs(current); 1664 1650 1651 + fp = (void __user *)regs->bp; 1652 + 1653 + callchain_store(entry, PERF_CONTEXT_USER); 1665 1654 callchain_store(entry, regs->ip); 1666 1655 1667 - while (entry->nr < MAX_STACK_DEPTH) { 1668 - frame.next_fp = NULL; 1656 + while (entry->nr < PERF_MAX_STACK_DEPTH) { 1657 + frame.next_frame = NULL; 1669 1658 frame.return_address = 0; 1670 1659 1671 1660 if (!copy_stack_frame(fp, &frame)) 1672 1661 break; 1673 1662 1674 - if ((unsigned long)fp < user_stack_pointer(regs)) 1663 + if ((unsigned long)fp < regs->sp) 1675 1664 break; 1676 1665 1677 1666 callchain_store(entry, frame.return_address); 1678 - fp = frame.next_fp; 1667 + fp = frame.next_frame; 1679 1668 } 1680 - 1681 - entry->user = entry->nr - nr; 1682 1669 } 1683 1670 1684 1671 static void ··· 1714 1701 entry = &__get_cpu_var(irq_entry); 1715 1702 1716 1703 entry->nr = 0; 1717 - entry->hv = 0; 1718 - entry->kernel = 0; 1719 - entry->user = 0; 1720 1704 1721 1705 perf_do_callchain(regs, entry); 1722 1706
+57 -1
arch/x86/mm/gup.c
··· 14 14 static inline pte_t gup_get_pte(pte_t *ptep) 15 15 { 16 16 #ifndef CONFIG_X86_PAE 17 - return *ptep; 17 + return ACCESS_ONCE(*ptep); 18 18 #else 19 19 /* 20 20 * With get_user_pages_fast, we walk down the pagetables without taking ··· 217 217 } while (pudp++, addr = next, addr != end); 218 218 219 219 return 1; 220 + } 221 + 222 + /* 223 + * Like get_user_pages_fast() except its IRQ-safe in that it won't fall 224 + * back to the regular GUP. 225 + */ 226 + int __get_user_pages_fast(unsigned long start, int nr_pages, int write, 227 + struct page **pages) 228 + { 229 + struct mm_struct *mm = current->mm; 230 + unsigned long addr, len, end; 231 + unsigned long next; 232 + unsigned long flags; 233 + pgd_t *pgdp; 234 + int nr = 0; 235 + 236 + start &= PAGE_MASK; 237 + addr = start; 238 + len = (unsigned long) nr_pages << PAGE_SHIFT; 239 + end = start + len; 240 + if (unlikely(!access_ok(write ? VERIFY_WRITE : VERIFY_READ, 241 + (void __user *)start, len))) 242 + return 0; 243 + 244 + /* 245 + * XXX: batch / limit 'nr', to avoid large irq off latency 246 + * needs some instrumenting to determine the common sizes used by 247 + * important workloads (eg. DB2), and whether limiting the batch size 248 + * will decrease performance. 249 + * 250 + * It seems like we're in the clear for the moment. Direct-IO is 251 + * the main guy that batches up lots of get_user_pages, and even 252 + * they are limited to 64-at-a-time which is not so many. 253 + */ 254 + /* 255 + * This doesn't prevent pagetable teardown, but does prevent 256 + * the pagetables and pages from being freed on x86. 257 + * 258 + * So long as we atomically load page table pointers versus teardown 259 + * (which we do on x86, with the above PAE exception), we can follow the 260 + * address down to the the page and take a ref on it. 261 + */ 262 + local_irq_save(flags); 263 + pgdp = pgd_offset(mm, addr); 264 + do { 265 + pgd_t pgd = *pgdp; 266 + 267 + next = pgd_addr_end(addr, end); 268 + if (pgd_none(pgd)) 269 + break; 270 + if (!gup_pud_range(pgd, addr, next, write, pages, &nr)) 271 + break; 272 + } while (pgdp++, addr = next, addr != end); 273 + local_irq_restore(flags); 274 + 275 + return nr; 220 276 } 221 277 222 278 /**
+15
fs/anon_inodes.c
··· 52 52 .d_delete = anon_inodefs_delete_dentry, 53 53 }; 54 54 55 + /* 56 + * nop .set_page_dirty method so that people can use .page_mkwrite on 57 + * anon inodes. 58 + */ 59 + static int anon_set_page_dirty(struct page *page) 60 + { 61 + return 0; 62 + }; 63 + 64 + static const struct address_space_operations anon_aops = { 65 + .set_page_dirty = anon_set_page_dirty, 66 + }; 67 + 55 68 /** 56 69 * anon_inode_getfd - creates a new file instance by hooking it up to an 57 70 * anonymous inode, and a dentry that describe the "class" ··· 163 150 return ERR_PTR(-ENOMEM); 164 151 165 152 inode->i_fop = &anon_inode_fops; 153 + 154 + inode->i_mapping->a_ops = &anon_aops; 166 155 167 156 /* 168 157 * Mark the inode dirty from the very beginning,
+4 -1
include/asm-generic/kmap_types.h
··· 24 24 D(13) KM_SYNC_ICACHE, 25 25 D(14) KM_SYNC_DCACHE, 26 26 D(15) KM_UML_USERCOPY, /* UML specific, for copy_*_user - used in do_op_one_page */ 27 - D(16) KM_TYPE_NR 27 + D(16) KM_IRQ_PTE, 28 + D(17) KM_NMI, 29 + D(18) KM_NMI_PTE, 30 + D(19) KM_TYPE_NR 28 31 }; 29 32 30 33 #undef D
+6
include/linux/mm.h
··· 854 854 unsigned long end, unsigned long newflags); 855 855 856 856 /* 857 + * doesn't attempt to fault and will return short. 858 + */ 859 + int __get_user_pages_fast(unsigned long start, int nr_pages, int write, 860 + struct page **pages); 861 + 862 + /* 857 863 * A callback you can register to apply pressure to ageable caches. 858 864 * 859 865 * 'shrink' is passed a count 'nr_to_scan' and a 'gfpmask'. It should
+49 -30
include/linux/perf_counter.h
··· 236 236 /* 237 237 * Control data for the mmap() data buffer. 238 238 * 239 - * User-space reading this value should issue an rmb(), on SMP capable 240 - * platforms, after reading this value -- see perf_counter_wakeup(). 239 + * User-space reading the @data_head value should issue an rmb(), on 240 + * SMP capable platforms, after reading this value -- see 241 + * perf_counter_wakeup(). 242 + * 243 + * When the mapping is PROT_WRITE the @data_tail value should be 244 + * written by userspace to reflect the last read data. In this case 245 + * the kernel will not over-write unread data. 241 246 */ 242 247 __u64 data_head; /* head in the data section */ 248 + __u64 data_tail; /* user-space written tail */ 243 249 }; 244 250 245 251 #define PERF_EVENT_MISC_CPUMODE_MASK (3 << 0) ··· 278 272 * }; 279 273 */ 280 274 PERF_EVENT_MMAP = 1, 275 + 276 + /* 277 + * struct { 278 + * struct perf_event_header header; 279 + * u64 id; 280 + * u64 lost; 281 + * }; 282 + */ 283 + PERF_EVENT_LOST = 2, 281 284 282 285 /* 283 286 * struct { ··· 328 313 329 314 /* 330 315 * When header.misc & PERF_EVENT_MISC_OVERFLOW the event_type field 331 - * will be PERF_RECORD_* 316 + * will be PERF_SAMPLE_* 332 317 * 333 318 * struct { 334 319 * struct perf_event_header header; 335 320 * 336 - * { u64 ip; } && PERF_RECORD_IP 337 - * { u32 pid, tid; } && PERF_RECORD_TID 338 - * { u64 time; } && PERF_RECORD_TIME 339 - * { u64 addr; } && PERF_RECORD_ADDR 340 - * { u64 config; } && PERF_RECORD_CONFIG 341 - * { u32 cpu, res; } && PERF_RECORD_CPU 321 + * { u64 ip; } && PERF_SAMPLE_IP 322 + * { u32 pid, tid; } && PERF_SAMPLE_TID 323 + * { u64 time; } && PERF_SAMPLE_TIME 324 + * { u64 addr; } && PERF_SAMPLE_ADDR 325 + * { u64 config; } && PERF_SAMPLE_CONFIG 326 + * { u32 cpu, res; } && PERF_SAMPLE_CPU 342 327 * 343 328 * { u64 nr; 344 - * { u64 id, val; } cnt[nr]; } && PERF_RECORD_GROUP 329 + * { u64 id, val; } cnt[nr]; } && PERF_SAMPLE_GROUP 345 330 * 346 - * { u16 nr, 347 - * hv, 348 - * kernel, 349 - * user; 350 - * u64 ips[nr]; } && PERF_RECORD_CALLCHAIN 331 + * { u64 nr, 332 + * u64 ips[nr]; } && PERF_SAMPLE_CALLCHAIN 351 333 * }; 352 334 */ 335 + }; 336 + 337 + enum perf_callchain_context { 338 + PERF_CONTEXT_HV = (__u64)-32, 339 + PERF_CONTEXT_KERNEL = (__u64)-128, 340 + PERF_CONTEXT_USER = (__u64)-512, 341 + 342 + PERF_CONTEXT_GUEST = (__u64)-2048, 343 + PERF_CONTEXT_GUEST_KERNEL = (__u64)-2176, 344 + PERF_CONTEXT_GUEST_USER = (__u64)-2560, 345 + 346 + PERF_CONTEXT_MAX = (__u64)-4095, 353 347 }; 354 348 355 349 #ifdef __KERNEL__ ··· 379 355 #include <linux/fs.h> 380 356 #include <linux/pid_namespace.h> 381 357 #include <asm/atomic.h> 358 + 359 + #define PERF_MAX_STACK_DEPTH 255 360 + 361 + struct perf_callchain_entry { 362 + __u64 nr; 363 + __u64 ip[PERF_MAX_STACK_DEPTH]; 364 + }; 382 365 383 366 struct task_struct; 384 367 ··· 445 414 struct perf_mmap_data { 446 415 struct rcu_head rcu_head; 447 416 int nr_pages; /* nr of data pages */ 417 + int writable; /* are we writable */ 448 418 int nr_locked; /* nr pages mlocked */ 449 419 450 420 atomic_t poll; /* POLL_ for wakeups */ ··· 455 423 atomic_long_t done_head; /* completed head */ 456 424 457 425 atomic_t lock; /* concurrent writes */ 458 - 459 426 atomic_t wakeup; /* needs a wakeup */ 427 + atomic_t lost; /* nr records lost */ 460 428 461 429 struct perf_counter_mmap_page *user_page; 462 430 void *data_pages[0]; ··· 636 604 extern int perf_counter_init_task(struct task_struct *child); 637 605 extern void perf_counter_exit_task(struct task_struct *child); 638 606 extern void perf_counter_free_task(struct task_struct *task); 607 + extern void set_perf_counter_pending(void); 639 608 extern void perf_counter_do_pending(void); 640 609 extern void perf_counter_print_debug(void); 641 610 extern void __perf_disable(void); ··· 682 649 extern void perf_counter_comm(struct task_struct *tsk); 683 650 extern void perf_counter_fork(struct task_struct *tsk); 684 651 685 - extern void perf_counter_task_migration(struct task_struct *task, int cpu); 686 - 687 - #define MAX_STACK_DEPTH 255 688 - 689 - struct perf_callchain_entry { 690 - u16 nr; 691 - u16 hv; 692 - u16 kernel; 693 - u16 user; 694 - u64 ip[MAX_STACK_DEPTH]; 695 - }; 696 - 697 652 extern struct perf_callchain_entry *perf_callchain(struct pt_regs *regs); 698 653 699 654 extern int sysctl_perf_counter_paranoid; ··· 722 701 static inline void perf_counter_comm(struct task_struct *tsk) { } 723 702 static inline void perf_counter_fork(struct task_struct *tsk) { } 724 703 static inline void perf_counter_init(void) { } 725 - static inline void perf_counter_task_migration(struct task_struct *task, 726 - int cpu) { } 727 704 #endif 728 705 729 706 #endif /* __KERNEL__ */
+182 -138
kernel/perf_counter.c
··· 124 124 125 125 static void get_ctx(struct perf_counter_context *ctx) 126 126 { 127 - atomic_inc(&ctx->refcount); 127 + WARN_ON(!atomic_inc_not_zero(&ctx->refcount)); 128 128 } 129 129 130 130 static void free_ctx(struct rcu_head *head) ··· 175 175 spin_unlock_irqrestore(&ctx->lock, *flags); 176 176 goto retry; 177 177 } 178 + 179 + if (!atomic_inc_not_zero(&ctx->refcount)) { 180 + spin_unlock_irqrestore(&ctx->lock, *flags); 181 + ctx = NULL; 182 + } 178 183 } 179 184 rcu_read_unlock(); 180 185 return ctx; ··· 198 193 ctx = perf_lock_task_context(task, &flags); 199 194 if (ctx) { 200 195 ++ctx->pin_count; 201 - get_ctx(ctx); 202 196 spin_unlock_irqrestore(&ctx->lock, flags); 203 197 } 204 198 return ctx; ··· 1287 1283 if (!interrupts) { 1288 1284 perf_disable(); 1289 1285 counter->pmu->disable(counter); 1290 - atomic_set(&hwc->period_left, 0); 1286 + atomic64_set(&hwc->period_left, 0); 1291 1287 counter->pmu->enable(counter); 1292 1288 perf_enable(); 1293 1289 } ··· 1463 1459 put_ctx(parent_ctx); 1464 1460 ctx->parent_ctx = NULL; /* no longer a clone */ 1465 1461 } 1466 - /* 1467 - * Get an extra reference before dropping the lock so that 1468 - * this context won't get freed if the task exits. 1469 - */ 1470 - get_ctx(ctx); 1471 1462 spin_unlock_irqrestore(&ctx->lock, flags); 1472 1463 } 1473 1464 ··· 1552 1553 static ssize_t 1553 1554 perf_read_hw(struct perf_counter *counter, char __user *buf, size_t count) 1554 1555 { 1555 - u64 values[3]; 1556 + u64 values[4]; 1556 1557 int n; 1557 1558 1558 1559 /* ··· 1619 1620 perf_counter_update_userpage(counter); 1620 1621 } 1621 1622 1622 - static void perf_counter_for_each_sibling(struct perf_counter *counter, 1623 - void (*func)(struct perf_counter *)) 1624 - { 1625 - struct perf_counter_context *ctx = counter->ctx; 1626 - struct perf_counter *sibling; 1627 - 1628 - WARN_ON_ONCE(ctx->parent_ctx); 1629 - mutex_lock(&ctx->mutex); 1630 - counter = counter->group_leader; 1631 - 1632 - func(counter); 1633 - list_for_each_entry(sibling, &counter->sibling_list, list_entry) 1634 - func(sibling); 1635 - mutex_unlock(&ctx->mutex); 1636 - } 1637 - 1638 1623 /* 1639 1624 * Holding the top-level counter's child_mutex means that any 1640 1625 * descendant process that has inherited this counter will block ··· 1641 1658 static void perf_counter_for_each(struct perf_counter *counter, 1642 1659 void (*func)(struct perf_counter *)) 1643 1660 { 1644 - struct perf_counter *child; 1661 + struct perf_counter_context *ctx = counter->ctx; 1662 + struct perf_counter *sibling; 1645 1663 1646 - WARN_ON_ONCE(counter->ctx->parent_ctx); 1647 - mutex_lock(&counter->child_mutex); 1648 - perf_counter_for_each_sibling(counter, func); 1649 - list_for_each_entry(child, &counter->child_list, child_list) 1650 - perf_counter_for_each_sibling(child, func); 1651 - mutex_unlock(&counter->child_mutex); 1664 + WARN_ON_ONCE(ctx->parent_ctx); 1665 + mutex_lock(&ctx->mutex); 1666 + counter = counter->group_leader; 1667 + 1668 + perf_counter_for_each_child(counter, func); 1669 + func(counter); 1670 + list_for_each_entry(sibling, &counter->sibling_list, list_entry) 1671 + perf_counter_for_each_child(counter, func); 1672 + mutex_unlock(&ctx->mutex); 1652 1673 } 1653 1674 1654 1675 static int perf_counter_period(struct perf_counter *counter, u64 __user *arg) ··· 1793 1806 struct perf_mmap_data *data; 1794 1807 int ret = VM_FAULT_SIGBUS; 1795 1808 1809 + if (vmf->flags & FAULT_FLAG_MKWRITE) { 1810 + if (vmf->pgoff == 0) 1811 + ret = 0; 1812 + return ret; 1813 + } 1814 + 1796 1815 rcu_read_lock(); 1797 1816 data = rcu_dereference(counter->data); 1798 1817 if (!data) ··· 1812 1819 if ((unsigned)nr > data->nr_pages) 1813 1820 goto unlock; 1814 1821 1822 + if (vmf->flags & FAULT_FLAG_WRITE) 1823 + goto unlock; 1824 + 1815 1825 vmf->page = virt_to_page(data->data_pages[nr]); 1816 1826 } 1827 + 1817 1828 get_page(vmf->page); 1829 + vmf->page->mapping = vma->vm_file->f_mapping; 1830 + vmf->page->index = vmf->pgoff; 1831 + 1818 1832 ret = 0; 1819 1833 unlock: 1820 1834 rcu_read_unlock(); ··· 1874 1874 return -ENOMEM; 1875 1875 } 1876 1876 1877 + static void perf_mmap_free_page(unsigned long addr) 1878 + { 1879 + struct page *page = virt_to_page(addr); 1880 + 1881 + page->mapping = NULL; 1882 + __free_page(page); 1883 + } 1884 + 1877 1885 static void __perf_mmap_data_free(struct rcu_head *rcu_head) 1878 1886 { 1879 1887 struct perf_mmap_data *data; ··· 1889 1881 1890 1882 data = container_of(rcu_head, struct perf_mmap_data, rcu_head); 1891 1883 1892 - free_page((unsigned long)data->user_page); 1884 + perf_mmap_free_page((unsigned long)data->user_page); 1893 1885 for (i = 0; i < data->nr_pages; i++) 1894 - free_page((unsigned long)data->data_pages[i]); 1886 + perf_mmap_free_page((unsigned long)data->data_pages[i]); 1887 + 1895 1888 kfree(data); 1896 1889 } 1897 1890 ··· 1929 1920 } 1930 1921 1931 1922 static struct vm_operations_struct perf_mmap_vmops = { 1932 - .open = perf_mmap_open, 1933 - .close = perf_mmap_close, 1934 - .fault = perf_mmap_fault, 1923 + .open = perf_mmap_open, 1924 + .close = perf_mmap_close, 1925 + .fault = perf_mmap_fault, 1926 + .page_mkwrite = perf_mmap_fault, 1935 1927 }; 1936 1928 1937 1929 static int perf_mmap(struct file *file, struct vm_area_struct *vma) ··· 1946 1936 long user_extra, extra; 1947 1937 int ret = 0; 1948 1938 1949 - if (!(vma->vm_flags & VM_SHARED) || (vma->vm_flags & VM_WRITE)) 1939 + if (!(vma->vm_flags & VM_SHARED)) 1950 1940 return -EINVAL; 1951 1941 1952 1942 vma_size = vma->vm_end - vma->vm_start; ··· 2005 1995 atomic_long_add(user_extra, &user->locked_vm); 2006 1996 vma->vm_mm->locked_vm += extra; 2007 1997 counter->data->nr_locked = extra; 1998 + if (vma->vm_flags & VM_WRITE) 1999 + counter->data->writable = 1; 2000 + 2008 2001 unlock: 2009 2002 mutex_unlock(&counter->mmap_mutex); 2010 2003 2011 - vma->vm_flags &= ~VM_MAYWRITE; 2012 2004 vma->vm_flags |= VM_RESERVED; 2013 2005 vma->vm_ops = &perf_mmap_vmops; 2014 2006 ··· 2187 2175 unsigned long head; 2188 2176 unsigned long offset; 2189 2177 int nmi; 2190 - int overflow; 2178 + int sample; 2191 2179 int locked; 2192 2180 unsigned long flags; 2193 2181 }; 2182 + 2183 + static bool perf_output_space(struct perf_mmap_data *data, 2184 + unsigned int offset, unsigned int head) 2185 + { 2186 + unsigned long tail; 2187 + unsigned long mask; 2188 + 2189 + if (!data->writable) 2190 + return true; 2191 + 2192 + mask = (data->nr_pages << PAGE_SHIFT) - 1; 2193 + /* 2194 + * Userspace could choose to issue a mb() before updating the tail 2195 + * pointer. So that all reads will be completed before the write is 2196 + * issued. 2197 + */ 2198 + tail = ACCESS_ONCE(data->user_page->data_tail); 2199 + smp_rmb(); 2200 + 2201 + offset = (offset - tail) & mask; 2202 + head = (head - tail) & mask; 2203 + 2204 + if ((int)(head - offset) < 0) 2205 + return false; 2206 + 2207 + return true; 2208 + } 2194 2209 2195 2210 static void perf_output_wakeup(struct perf_output_handle *handle) 2196 2211 { ··· 2309 2270 local_irq_restore(handle->flags); 2310 2271 } 2311 2272 2312 - static int perf_output_begin(struct perf_output_handle *handle, 2313 - struct perf_counter *counter, unsigned int size, 2314 - int nmi, int overflow) 2315 - { 2316 - struct perf_mmap_data *data; 2317 - unsigned int offset, head; 2318 - 2319 - /* 2320 - * For inherited counters we send all the output towards the parent. 2321 - */ 2322 - if (counter->parent) 2323 - counter = counter->parent; 2324 - 2325 - rcu_read_lock(); 2326 - data = rcu_dereference(counter->data); 2327 - if (!data) 2328 - goto out; 2329 - 2330 - handle->data = data; 2331 - handle->counter = counter; 2332 - handle->nmi = nmi; 2333 - handle->overflow = overflow; 2334 - 2335 - if (!data->nr_pages) 2336 - goto fail; 2337 - 2338 - perf_output_lock(handle); 2339 - 2340 - do { 2341 - offset = head = atomic_long_read(&data->head); 2342 - head += size; 2343 - } while (atomic_long_cmpxchg(&data->head, offset, head) != offset); 2344 - 2345 - handle->offset = offset; 2346 - handle->head = head; 2347 - 2348 - if ((offset >> PAGE_SHIFT) != (head >> PAGE_SHIFT)) 2349 - atomic_set(&data->wakeup, 1); 2350 - 2351 - return 0; 2352 - 2353 - fail: 2354 - perf_output_wakeup(handle); 2355 - out: 2356 - rcu_read_unlock(); 2357 - 2358 - return -ENOSPC; 2359 - } 2360 - 2361 2273 static void perf_output_copy(struct perf_output_handle *handle, 2362 2274 const void *buf, unsigned int len) 2363 2275 { ··· 2348 2358 #define perf_output_put(handle, x) \ 2349 2359 perf_output_copy((handle), &(x), sizeof(x)) 2350 2360 2361 + static int perf_output_begin(struct perf_output_handle *handle, 2362 + struct perf_counter *counter, unsigned int size, 2363 + int nmi, int sample) 2364 + { 2365 + struct perf_mmap_data *data; 2366 + unsigned int offset, head; 2367 + int have_lost; 2368 + struct { 2369 + struct perf_event_header header; 2370 + u64 id; 2371 + u64 lost; 2372 + } lost_event; 2373 + 2374 + /* 2375 + * For inherited counters we send all the output towards the parent. 2376 + */ 2377 + if (counter->parent) 2378 + counter = counter->parent; 2379 + 2380 + rcu_read_lock(); 2381 + data = rcu_dereference(counter->data); 2382 + if (!data) 2383 + goto out; 2384 + 2385 + handle->data = data; 2386 + handle->counter = counter; 2387 + handle->nmi = nmi; 2388 + handle->sample = sample; 2389 + 2390 + if (!data->nr_pages) 2391 + goto fail; 2392 + 2393 + have_lost = atomic_read(&data->lost); 2394 + if (have_lost) 2395 + size += sizeof(lost_event); 2396 + 2397 + perf_output_lock(handle); 2398 + 2399 + do { 2400 + offset = head = atomic_long_read(&data->head); 2401 + head += size; 2402 + if (unlikely(!perf_output_space(data, offset, head))) 2403 + goto fail; 2404 + } while (atomic_long_cmpxchg(&data->head, offset, head) != offset); 2405 + 2406 + handle->offset = offset; 2407 + handle->head = head; 2408 + 2409 + if ((offset >> PAGE_SHIFT) != (head >> PAGE_SHIFT)) 2410 + atomic_set(&data->wakeup, 1); 2411 + 2412 + if (have_lost) { 2413 + lost_event.header.type = PERF_EVENT_LOST; 2414 + lost_event.header.misc = 0; 2415 + lost_event.header.size = sizeof(lost_event); 2416 + lost_event.id = counter->id; 2417 + lost_event.lost = atomic_xchg(&data->lost, 0); 2418 + 2419 + perf_output_put(handle, lost_event); 2420 + } 2421 + 2422 + return 0; 2423 + 2424 + fail: 2425 + atomic_inc(&data->lost); 2426 + perf_output_unlock(handle); 2427 + out: 2428 + rcu_read_unlock(); 2429 + 2430 + return -ENOSPC; 2431 + } 2432 + 2351 2433 static void perf_output_end(struct perf_output_handle *handle) 2352 2434 { 2353 2435 struct perf_counter *counter = handle->counter; ··· 2427 2365 2428 2366 int wakeup_events = counter->attr.wakeup_events; 2429 2367 2430 - if (handle->overflow && wakeup_events) { 2368 + if (handle->sample && wakeup_events) { 2431 2369 int events = atomic_inc_return(&data->events); 2432 2370 if (events >= wakeup_events) { 2433 2371 atomic_sub(wakeup_events, &data->events); ··· 3032 2970 } 3033 2971 3034 2972 /* 3035 - * Generic counter overflow handling. 2973 + * Generic counter overflow handling, sampling. 3036 2974 */ 3037 2975 3038 2976 int perf_counter_overflow(struct perf_counter *counter, int nmi, ··· 3171 3109 } 3172 3110 3173 3111 static void perf_swcounter_overflow(struct perf_counter *counter, 3174 - int nmi, struct pt_regs *regs, u64 addr) 3112 + int nmi, struct perf_sample_data *data) 3175 3113 { 3176 - struct perf_sample_data data = { 3177 - .regs = regs, 3178 - .addr = addr, 3179 - .period = counter->hw.last_period, 3180 - }; 3114 + data->period = counter->hw.last_period; 3181 3115 3182 3116 perf_swcounter_update(counter); 3183 3117 perf_swcounter_set_period(counter); 3184 - if (perf_counter_overflow(counter, nmi, &data)) 3118 + if (perf_counter_overflow(counter, nmi, data)) 3185 3119 /* soft-disable the counter */ 3186 3120 ; 3187 - 3188 3121 } 3189 3122 3190 3123 static int perf_swcounter_is_counting(struct perf_counter *counter) ··· 3244 3187 } 3245 3188 3246 3189 static void perf_swcounter_add(struct perf_counter *counter, u64 nr, 3247 - int nmi, struct pt_regs *regs, u64 addr) 3190 + int nmi, struct perf_sample_data *data) 3248 3191 { 3249 3192 int neg = atomic64_add_negative(nr, &counter->hw.count); 3250 3193 3251 - if (counter->hw.sample_period && !neg && regs) 3252 - perf_swcounter_overflow(counter, nmi, regs, addr); 3194 + if (counter->hw.sample_period && !neg && data->regs) 3195 + perf_swcounter_overflow(counter, nmi, data); 3253 3196 } 3254 3197 3255 3198 static void perf_swcounter_ctx_event(struct perf_counter_context *ctx, 3256 - enum perf_type_id type, u32 event, 3257 - u64 nr, int nmi, struct pt_regs *regs, 3258 - u64 addr) 3199 + enum perf_type_id type, 3200 + u32 event, u64 nr, int nmi, 3201 + struct perf_sample_data *data) 3259 3202 { 3260 3203 struct perf_counter *counter; 3261 3204 ··· 3264 3207 3265 3208 rcu_read_lock(); 3266 3209 list_for_each_entry_rcu(counter, &ctx->event_list, event_entry) { 3267 - if (perf_swcounter_match(counter, type, event, regs)) 3268 - perf_swcounter_add(counter, nr, nmi, regs, addr); 3210 + if (perf_swcounter_match(counter, type, event, data->regs)) 3211 + perf_swcounter_add(counter, nr, nmi, data); 3269 3212 } 3270 3213 rcu_read_unlock(); 3271 3214 } ··· 3284 3227 return &cpuctx->recursion[0]; 3285 3228 } 3286 3229 3287 - static void __perf_swcounter_event(enum perf_type_id type, u32 event, 3288 - u64 nr, int nmi, struct pt_regs *regs, 3289 - u64 addr) 3230 + static void do_perf_swcounter_event(enum perf_type_id type, u32 event, 3231 + u64 nr, int nmi, 3232 + struct perf_sample_data *data) 3290 3233 { 3291 3234 struct perf_cpu_context *cpuctx = &get_cpu_var(perf_cpu_context); 3292 3235 int *recursion = perf_swcounter_recursion_context(cpuctx); ··· 3299 3242 barrier(); 3300 3243 3301 3244 perf_swcounter_ctx_event(&cpuctx->ctx, type, event, 3302 - nr, nmi, regs, addr); 3245 + nr, nmi, data); 3303 3246 rcu_read_lock(); 3304 3247 /* 3305 3248 * doesn't really matter which of the child contexts the ··· 3307 3250 */ 3308 3251 ctx = rcu_dereference(current->perf_counter_ctxp); 3309 3252 if (ctx) 3310 - perf_swcounter_ctx_event(ctx, type, event, nr, nmi, regs, addr); 3253 + perf_swcounter_ctx_event(ctx, type, event, nr, nmi, data); 3311 3254 rcu_read_unlock(); 3312 3255 3313 3256 barrier(); ··· 3320 3263 void 3321 3264 perf_swcounter_event(u32 event, u64 nr, int nmi, struct pt_regs *regs, u64 addr) 3322 3265 { 3323 - __perf_swcounter_event(PERF_TYPE_SOFTWARE, event, nr, nmi, regs, addr); 3266 + struct perf_sample_data data = { 3267 + .regs = regs, 3268 + .addr = addr, 3269 + }; 3270 + 3271 + do_perf_swcounter_event(PERF_TYPE_SOFTWARE, event, nr, nmi, &data); 3324 3272 } 3325 3273 3326 3274 static void perf_swcounter_read(struct perf_counter *counter) ··· 3466 3404 .read = task_clock_perf_counter_read, 3467 3405 }; 3468 3406 3469 - /* 3470 - * Software counter: cpu migrations 3471 - */ 3472 - void perf_counter_task_migration(struct task_struct *task, int cpu) 3473 - { 3474 - struct perf_cpu_context *cpuctx = &per_cpu(perf_cpu_context, cpu); 3475 - struct perf_counter_context *ctx; 3476 - 3477 - perf_swcounter_ctx_event(&cpuctx->ctx, PERF_TYPE_SOFTWARE, 3478 - PERF_COUNT_SW_CPU_MIGRATIONS, 3479 - 1, 1, NULL, 0); 3480 - 3481 - ctx = perf_pin_task_context(task); 3482 - if (ctx) { 3483 - perf_swcounter_ctx_event(ctx, PERF_TYPE_SOFTWARE, 3484 - PERF_COUNT_SW_CPU_MIGRATIONS, 3485 - 1, 1, NULL, 0); 3486 - perf_unpin_context(ctx); 3487 - } 3488 - } 3489 - 3490 3407 #ifdef CONFIG_EVENT_PROFILE 3491 3408 void perf_tpcounter_event(int event_id) 3492 3409 { 3493 - struct pt_regs *regs = get_irq_regs(); 3410 + struct perf_sample_data data = { 3411 + .regs = get_irq_regs(); 3412 + .addr = 0, 3413 + }; 3494 3414 3495 - if (!regs) 3496 - regs = task_pt_regs(current); 3415 + if (!data.regs) 3416 + data.regs = task_pt_regs(current); 3497 3417 3498 - __perf_swcounter_event(PERF_TYPE_TRACEPOINT, event_id, 1, 1, regs, 0); 3418 + do_perf_swcounter_event(PERF_TYPE_TRACEPOINT, event_id, 1, 1, &data); 3499 3419 } 3500 3420 EXPORT_SYMBOL_GPL(perf_tpcounter_event); 3501 3421
+2 -1
kernel/sched.c
··· 1978 1978 if (task_hot(p, old_rq->clock, NULL)) 1979 1979 schedstat_inc(p, se.nr_forced2_migrations); 1980 1980 #endif 1981 - perf_counter_task_migration(p, new_cpu); 1981 + perf_swcounter_event(PERF_COUNT_SW_CPU_MIGRATIONS, 1982 + 1, 1, NULL, 0); 1982 1983 } 1983 1984 p->se.vruntime -= old_cfsrq->min_vruntime - 1984 1985 new_cfsrq->min_vruntime;
+8 -2
tools/perf/Makefile
··· 157 157 uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not') 158 158 uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not') 159 159 160 + # If we're on a 64-bit kernel, use -m64 161 + ifneq ($(patsubst %64,%,$(uname_M)),$(uname_M)) 162 + M64 := -m64 163 + endif 164 + 160 165 # CFLAGS and LDFLAGS are for the users to override from the command line. 161 166 162 - CFLAGS = -ggdb3 -Wall -Werror -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -O6 163 - LDFLAGS = -lpthread -lrt -lelf 167 + CFLAGS = $(M64) -ggdb3 -Wall -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement -Werror -O6 168 + LDFLAGS = -lpthread -lrt -lelf -lm 164 169 ALL_CFLAGS = $(CFLAGS) 165 170 ALL_LDFLAGS = $(LDFLAGS) 166 171 STRIP ?= strip ··· 290 285 291 286 LIB_H += ../../include/linux/perf_counter.h 292 287 LIB_H += perf.h 288 + LIB_H += types.h 293 289 LIB_H += util/list.h 294 290 LIB_H += util/rbtree.h 295 291 LIB_H += util/levenshtein.h
+214 -48
tools/perf/builtin-annotate.c
··· 25 25 #define SHOW_USER 2 26 26 #define SHOW_HV 4 27 27 28 + #define MIN_GREEN 0.5 29 + #define MIN_RED 5.0 30 + 31 + 28 32 static char const *input_name = "perf.data"; 29 33 static char *vmlinux = "vmlinux"; 30 34 ··· 43 39 44 40 static int verbose; 45 41 42 + static int print_line; 43 + 46 44 static unsigned long page_size; 47 45 static unsigned long mmap_window = 32; 48 46 49 47 struct ip_event { 50 48 struct perf_event_header header; 51 - __u64 ip; 52 - __u32 pid, tid; 49 + u64 ip; 50 + u32 pid, tid; 53 51 }; 54 52 55 53 struct mmap_event { 56 54 struct perf_event_header header; 57 - __u32 pid, tid; 58 - __u64 start; 59 - __u64 len; 60 - __u64 pgoff; 55 + u32 pid, tid; 56 + u64 start; 57 + u64 len; 58 + u64 pgoff; 61 59 char filename[PATH_MAX]; 62 60 }; 63 61 64 62 struct comm_event { 65 63 struct perf_event_header header; 66 - __u32 pid, tid; 64 + u32 pid, tid; 67 65 char comm[16]; 68 66 }; 69 67 70 68 struct fork_event { 71 69 struct perf_event_header header; 72 - __u32 pid, ppid; 70 + u32 pid, ppid; 73 71 }; 74 72 75 73 struct period_event { 76 74 struct perf_event_header header; 77 - __u64 time; 78 - __u64 id; 79 - __u64 sample_period; 75 + u64 time; 76 + u64 id; 77 + u64 sample_period; 80 78 }; 81 79 82 80 typedef union event_union { ··· 89 83 struct fork_event fork; 90 84 struct period_event period; 91 85 } event_t; 86 + 87 + 88 + struct sym_ext { 89 + struct rb_node node; 90 + double percent; 91 + char *path; 92 + }; 92 93 93 94 static LIST_HEAD(dsos); 94 95 static struct dso *kernel_dso; ··· 158 145 dso__fprintf(pos, fp); 159 146 } 160 147 161 - static struct symbol *vdso__find_symbol(struct dso *dso, __u64 ip) 148 + static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) 162 149 { 163 150 return dso__find_symbol(kernel_dso, ip); 164 151 } ··· 191 178 192 179 struct map { 193 180 struct list_head node; 194 - __u64 start; 195 - __u64 end; 196 - __u64 pgoff; 197 - __u64 (*map_ip)(struct map *, __u64); 181 + u64 start; 182 + u64 end; 183 + u64 pgoff; 184 + u64 (*map_ip)(struct map *, u64); 198 185 struct dso *dso; 199 186 }; 200 187 201 - static __u64 map__map_ip(struct map *map, __u64 ip) 188 + static u64 map__map_ip(struct map *map, u64 ip) 202 189 { 203 190 return ip - map->start + map->pgoff; 204 191 } 205 192 206 - static __u64 vdso__map_ip(struct map *map, __u64 ip) 193 + static u64 vdso__map_ip(struct map *map, u64 ip) 207 194 { 208 195 return ip; 209 196 } ··· 386 373 return 0; 387 374 } 388 375 389 - static struct map *thread__find_map(struct thread *self, __u64 ip) 376 + static struct map *thread__find_map(struct thread *self, u64 ip) 390 377 { 391 378 struct map *pos; 392 379 ··· 427 414 struct map *map; 428 415 struct dso *dso; 429 416 struct symbol *sym; 430 - __u64 ip; 417 + u64 ip; 431 418 char level; 432 419 433 420 uint32_t count; ··· 532 519 if (self->dso) 533 520 return fprintf(fp, "%-25s", self->dso->name); 534 521 535 - return fprintf(fp, "%016llx ", (__u64)self->ip); 522 + return fprintf(fp, "%016llx ", (u64)self->ip); 536 523 } 537 524 538 525 static struct sort_entry sort_dso = { ··· 546 533 static int64_t 547 534 sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) 548 535 { 549 - __u64 ip_l, ip_r; 536 + u64 ip_l, ip_r; 550 537 551 538 if (left->sym == right->sym) 552 539 return 0; ··· 563 550 size_t ret = 0; 564 551 565 552 if (verbose) 566 - ret += fprintf(fp, "%#018llx ", (__u64)self->ip); 553 + ret += fprintf(fp, "%#018llx ", (u64)self->ip); 567 554 568 555 if (self->sym) { 569 556 ret += fprintf(fp, "[%c] %s", 570 557 self->dso == kernel_dso ? 'k' : '.', self->sym->name); 571 558 } else { 572 - ret += fprintf(fp, "%#016llx", (__u64)self->ip); 559 + ret += fprintf(fp, "%#016llx", (u64)self->ip); 573 560 } 574 561 575 562 return ret; ··· 660 647 /* 661 648 * collect histogram counts 662 649 */ 663 - static void hist_hit(struct hist_entry *he, __u64 ip) 650 + static void hist_hit(struct hist_entry *he, u64 ip) 664 651 { 665 652 unsigned int sym_size, offset; 666 653 struct symbol *sym = he->sym; ··· 689 676 690 677 static int 691 678 hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, 692 - struct symbol *sym, __u64 ip, char level) 679 + struct symbol *sym, u64 ip, char level) 693 680 { 694 681 struct rb_node **p = &hist.rb_node; 695 682 struct rb_node *parent = NULL; ··· 861 848 int show = 0; 862 849 struct dso *dso = NULL; 863 850 struct thread *thread = threads__findnew(event->ip.pid); 864 - __u64 ip = event->ip.ip; 851 + u64 ip = event->ip.ip; 865 852 struct map *map = NULL; 866 853 867 854 dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n", ··· 1043 1030 return 0; 1044 1031 } 1045 1032 1033 + static char *get_color(double percent) 1034 + { 1035 + char *color = PERF_COLOR_NORMAL; 1036 + 1037 + /* 1038 + * We color high-overhead entries in red, mid-overhead 1039 + * entries in green - and keep the low overhead places 1040 + * normal: 1041 + */ 1042 + if (percent >= MIN_RED) 1043 + color = PERF_COLOR_RED; 1044 + else { 1045 + if (percent > MIN_GREEN) 1046 + color = PERF_COLOR_GREEN; 1047 + } 1048 + return color; 1049 + } 1050 + 1046 1051 static int 1047 - parse_line(FILE *file, struct symbol *sym, __u64 start, __u64 len) 1052 + parse_line(FILE *file, struct symbol *sym, u64 start, u64 len) 1048 1053 { 1049 1054 char *line = NULL, *tmp, *tmp2; 1055 + static const char *prev_line; 1056 + static const char *prev_color; 1050 1057 unsigned int offset; 1051 1058 size_t line_len; 1052 - __u64 line_ip; 1059 + u64 line_ip; 1053 1060 int ret; 1054 1061 char *c; 1055 1062 ··· 1106 1073 } 1107 1074 1108 1075 if (line_ip != -1) { 1076 + const char *path = NULL; 1109 1077 unsigned int hits = 0; 1110 1078 double percent = 0.0; 1111 - char *color = PERF_COLOR_NORMAL; 1079 + char *color; 1080 + struct sym_ext *sym_ext = sym->priv; 1112 1081 1113 1082 offset = line_ip - start; 1114 1083 if (offset < len) 1115 1084 hits = sym->hist[offset]; 1116 1085 1117 - if (sym->hist_sum) 1086 + if (offset < len && sym_ext) { 1087 + path = sym_ext[offset].path; 1088 + percent = sym_ext[offset].percent; 1089 + } else if (sym->hist_sum) 1118 1090 percent = 100.0 * hits / sym->hist_sum; 1119 1091 1092 + color = get_color(percent); 1093 + 1120 1094 /* 1121 - * We color high-overhead entries in red, mid-overhead 1122 - * entries in green - and keep the low overhead places 1123 - * normal: 1095 + * Also color the filename and line if needed, with 1096 + * the same color than the percentage. Don't print it 1097 + * twice for close colored ip with the same filename:line 1124 1098 */ 1125 - if (percent >= 5.0) 1126 - color = PERF_COLOR_RED; 1127 - else { 1128 - if (percent > 0.5) 1129 - color = PERF_COLOR_GREEN; 1099 + if (path) { 1100 + if (!prev_line || strcmp(prev_line, path) 1101 + || color != prev_color) { 1102 + color_fprintf(stdout, color, " %s", path); 1103 + prev_line = path; 1104 + prev_color = color; 1105 + } 1130 1106 } 1131 1107 1132 1108 color_fprintf(stdout, color, " %7.2f", percent); ··· 1151 1109 return 0; 1152 1110 } 1153 1111 1112 + static struct rb_root root_sym_ext; 1113 + 1114 + static void insert_source_line(struct sym_ext *sym_ext) 1115 + { 1116 + struct sym_ext *iter; 1117 + struct rb_node **p = &root_sym_ext.rb_node; 1118 + struct rb_node *parent = NULL; 1119 + 1120 + while (*p != NULL) { 1121 + parent = *p; 1122 + iter = rb_entry(parent, struct sym_ext, node); 1123 + 1124 + if (sym_ext->percent > iter->percent) 1125 + p = &(*p)->rb_left; 1126 + else 1127 + p = &(*p)->rb_right; 1128 + } 1129 + 1130 + rb_link_node(&sym_ext->node, parent, p); 1131 + rb_insert_color(&sym_ext->node, &root_sym_ext); 1132 + } 1133 + 1134 + static void free_source_line(struct symbol *sym, int len) 1135 + { 1136 + struct sym_ext *sym_ext = sym->priv; 1137 + int i; 1138 + 1139 + if (!sym_ext) 1140 + return; 1141 + 1142 + for (i = 0; i < len; i++) 1143 + free(sym_ext[i].path); 1144 + free(sym_ext); 1145 + 1146 + sym->priv = NULL; 1147 + root_sym_ext = RB_ROOT; 1148 + } 1149 + 1150 + /* Get the filename:line for the colored entries */ 1151 + static void 1152 + get_source_line(struct symbol *sym, u64 start, int len, char *filename) 1153 + { 1154 + int i; 1155 + char cmd[PATH_MAX * 2]; 1156 + struct sym_ext *sym_ext; 1157 + 1158 + if (!sym->hist_sum) 1159 + return; 1160 + 1161 + sym->priv = calloc(len, sizeof(struct sym_ext)); 1162 + if (!sym->priv) 1163 + return; 1164 + 1165 + sym_ext = sym->priv; 1166 + 1167 + for (i = 0; i < len; i++) { 1168 + char *path = NULL; 1169 + size_t line_len; 1170 + u64 offset; 1171 + FILE *fp; 1172 + 1173 + sym_ext[i].percent = 100.0 * sym->hist[i] / sym->hist_sum; 1174 + if (sym_ext[i].percent <= 0.5) 1175 + continue; 1176 + 1177 + offset = start + i; 1178 + sprintf(cmd, "addr2line -e %s %016llx", filename, offset); 1179 + fp = popen(cmd, "r"); 1180 + if (!fp) 1181 + continue; 1182 + 1183 + if (getline(&path, &line_len, fp) < 0 || !line_len) 1184 + goto next; 1185 + 1186 + sym_ext[i].path = malloc(sizeof(char) * line_len + 1); 1187 + if (!sym_ext[i].path) 1188 + goto next; 1189 + 1190 + strcpy(sym_ext[i].path, path); 1191 + insert_source_line(&sym_ext[i]); 1192 + 1193 + next: 1194 + pclose(fp); 1195 + } 1196 + } 1197 + 1198 + static void print_summary(char *filename) 1199 + { 1200 + struct sym_ext *sym_ext; 1201 + struct rb_node *node; 1202 + 1203 + printf("\nSorted summary for file %s\n", filename); 1204 + printf("----------------------------------------------\n\n"); 1205 + 1206 + if (RB_EMPTY_ROOT(&root_sym_ext)) { 1207 + printf(" Nothing higher than %1.1f%%\n", MIN_GREEN); 1208 + return; 1209 + } 1210 + 1211 + node = rb_first(&root_sym_ext); 1212 + while (node) { 1213 + double percent; 1214 + char *color; 1215 + char *path; 1216 + 1217 + sym_ext = rb_entry(node, struct sym_ext, node); 1218 + percent = sym_ext->percent; 1219 + color = get_color(percent); 1220 + path = sym_ext->path; 1221 + 1222 + color_fprintf(stdout, color, " %7.2f %s", percent, path); 1223 + node = rb_next(node); 1224 + } 1225 + } 1226 + 1154 1227 static void annotate_sym(struct dso *dso, struct symbol *sym) 1155 1228 { 1156 1229 char *filename = dso->name; 1157 - __u64 start, end, len; 1230 + u64 start, end, len; 1158 1231 char command[PATH_MAX*2]; 1159 1232 FILE *file; 1160 1233 ··· 1278 1121 if (dso == kernel_dso) 1279 1122 filename = vmlinux; 1280 1123 1281 - printf("\n------------------------------------------------\n"); 1282 - printf(" Percent | Source code & Disassembly of %s\n", filename); 1283 - printf("------------------------------------------------\n"); 1284 - 1285 - if (verbose >= 2) 1286 - printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name); 1287 - 1288 1124 start = sym->obj_start; 1289 1125 if (!start) 1290 1126 start = sym->start; ··· 1285 1135 end = start + sym->end - sym->start + 1; 1286 1136 len = sym->end - sym->start; 1287 1137 1288 - sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", (__u64)start, (__u64)end, filename); 1138 + if (print_line) { 1139 + get_source_line(sym, start, len, filename); 1140 + print_summary(filename); 1141 + } 1142 + 1143 + printf("\n\n------------------------------------------------\n"); 1144 + printf(" Percent | Source code & Disassembly of %s\n", filename); 1145 + printf("------------------------------------------------\n"); 1146 + 1147 + if (verbose >= 2) 1148 + printf("annotating [%p] %30s : [%p] %30s\n", dso, dso->name, sym, sym->name); 1149 + 1150 + sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", (u64)start, (u64)end, filename); 1289 1151 1290 1152 if (verbose >= 3) 1291 1153 printf("doing: %s\n", command); ··· 1312 1150 } 1313 1151 1314 1152 pclose(file); 1153 + if (print_line) 1154 + free_source_line(sym, len); 1315 1155 } 1316 1156 1317 1157 static void find_annotations(void) ··· 1472 1308 OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, 1473 1309 "dump raw trace in ASCII"), 1474 1310 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), 1311 + OPT_BOOLEAN('l', "print-line", &print_line, 1312 + "print matching source lines (may be slow)"), 1475 1313 OPT_END() 1476 1314 }; 1477 1315
+103 -60
tools/perf/builtin-record.c
··· 37 37 static int inherit = 1; 38 38 static int force = 0; 39 39 static int append_file = 0; 40 + static int call_graph = 0; 40 41 static int verbose = 0; 41 42 42 43 static long samples; 43 44 static struct timeval last_read; 44 45 static struct timeval this_read; 45 46 46 - static __u64 bytes_written; 47 + static u64 bytes_written; 47 48 48 49 static struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS]; 49 50 50 51 static int nr_poll; 51 52 static int nr_cpu; 52 53 54 + static int file_new = 1; 55 + static struct perf_file_header file_header; 56 + 53 57 struct mmap_event { 54 58 struct perf_event_header header; 55 - __u32 pid; 56 - __u32 tid; 57 - __u64 start; 58 - __u64 len; 59 - __u64 pgoff; 59 + u32 pid; 60 + u32 tid; 61 + u64 start; 62 + u64 len; 63 + u64 pgoff; 60 64 char filename[PATH_MAX]; 61 65 }; 62 66 63 67 struct comm_event { 64 68 struct perf_event_header header; 65 - __u32 pid; 66 - __u32 tid; 69 + u32 pid; 70 + u32 tid; 67 71 char comm[16]; 68 72 }; 69 73 ··· 81 77 82 78 static struct mmap_data mmap_array[MAX_NR_CPUS][MAX_COUNTERS]; 83 79 84 - static unsigned int mmap_read_head(struct mmap_data *md) 80 + static unsigned long mmap_read_head(struct mmap_data *md) 85 81 { 86 82 struct perf_counter_mmap_page *pc = md->base; 87 - int head; 83 + long head; 88 84 89 85 head = pc->data_head; 90 86 rmb(); 91 87 92 88 return head; 89 + } 90 + 91 + static void mmap_write_tail(struct mmap_data *md, unsigned long tail) 92 + { 93 + struct perf_counter_mmap_page *pc = md->base; 94 + 95 + /* 96 + * ensure all reads are done before we write the tail out. 97 + */ 98 + /* mb(); */ 99 + pc->data_tail = tail; 100 + } 101 + 102 + static void write_output(void *buf, size_t size) 103 + { 104 + while (size) { 105 + int ret = write(output, buf, size); 106 + 107 + if (ret < 0) 108 + die("failed to write"); 109 + 110 + size -= ret; 111 + buf += ret; 112 + 113 + bytes_written += ret; 114 + } 93 115 } 94 116 95 117 static void mmap_read(struct mmap_data *md) ··· 138 108 * In either case, truncate and restart at head. 139 109 */ 140 110 diff = head - old; 141 - if (diff > md->mask / 2 || diff < 0) { 111 + if (diff < 0) { 142 112 struct timeval iv; 143 113 unsigned long msecs; 144 114 ··· 166 136 size = md->mask + 1 - (old & md->mask); 167 137 old += size; 168 138 169 - while (size) { 170 - int ret = write(output, buf, size); 171 - 172 - if (ret < 0) 173 - die("failed to write"); 174 - 175 - size -= ret; 176 - buf += ret; 177 - 178 - bytes_written += ret; 179 - } 139 + write_output(buf, size); 180 140 } 181 141 182 142 buf = &data[old & md->mask]; 183 143 size = head - old; 184 144 old += size; 185 145 186 - while (size) { 187 - int ret = write(output, buf, size); 188 - 189 - if (ret < 0) 190 - die("failed to write"); 191 - 192 - size -= ret; 193 - buf += ret; 194 - 195 - bytes_written += ret; 196 - } 146 + write_output(buf, size); 197 147 198 148 md->prev = old; 149 + mmap_write_tail(md, old); 199 150 } 200 151 201 152 static volatile int done = 0; ··· 202 191 struct comm_event comm_ev; 203 192 char filename[PATH_MAX]; 204 193 char bf[BUFSIZ]; 205 - int fd, ret; 194 + int fd; 206 195 size_t size; 207 196 char *field, *sep; 208 197 DIR *tasks; ··· 212 201 213 202 fd = open(filename, O_RDONLY); 214 203 if (fd < 0) { 215 - fprintf(stderr, "couldn't open %s\n", filename); 216 - exit(EXIT_FAILURE); 204 + /* 205 + * We raced with a task exiting - just return: 206 + */ 207 + if (verbose) 208 + fprintf(stderr, "couldn't open %s\n", filename); 209 + return; 217 210 } 218 211 if (read(fd, bf, sizeof(bf)) < 0) { 219 212 fprintf(stderr, "couldn't read %s\n", filename); ··· 238 223 239 224 comm_ev.pid = pid; 240 225 comm_ev.header.type = PERF_EVENT_COMM; 241 - size = ALIGN(size, sizeof(__u64)); 226 + size = ALIGN(size, sizeof(u64)); 242 227 comm_ev.header.size = sizeof(comm_ev) - (sizeof(comm_ev.comm) - size); 243 228 244 229 if (!full) { 245 230 comm_ev.tid = pid; 246 231 247 - ret = write(output, &comm_ev, comm_ev.header.size); 248 - if (ret < 0) { 249 - perror("failed to write"); 250 - exit(-1); 251 - } 232 + write_output(&comm_ev, comm_ev.header.size); 252 233 return; 253 234 } 254 235 ··· 259 248 260 249 comm_ev.tid = pid; 261 250 262 - ret = write(output, &comm_ev, comm_ev.header.size); 263 - if (ret < 0) { 264 - perror("failed to write"); 265 - exit(-1); 266 - } 251 + write_output(&comm_ev, comm_ev.header.size); 267 252 } 268 253 closedir(tasks); 269 254 return; ··· 279 272 280 273 fp = fopen(filename, "r"); 281 274 if (fp == NULL) { 282 - fprintf(stderr, "couldn't open %s\n", filename); 283 - exit(EXIT_FAILURE); 275 + /* 276 + * We raced with a task exiting - just return: 277 + */ 278 + if (verbose) 279 + fprintf(stderr, "couldn't open %s\n", filename); 280 + return; 284 281 } 285 282 while (1) { 286 283 char bf[BUFSIZ], *pbf = bf; ··· 315 304 size = strlen(execname); 316 305 execname[size - 1] = '\0'; /* Remove \n */ 317 306 memcpy(mmap_ev.filename, execname, size); 318 - size = ALIGN(size, sizeof(__u64)); 307 + size = ALIGN(size, sizeof(u64)); 319 308 mmap_ev.len -= mmap_ev.start; 320 309 mmap_ev.header.size = (sizeof(mmap_ev) - 321 310 (sizeof(mmap_ev.filename) - size)); 322 311 mmap_ev.pid = pid; 323 312 mmap_ev.tid = pid; 324 313 325 - if (write(output, &mmap_ev, mmap_ev.header.size) < 0) { 326 - perror("failed to write"); 327 - exit(-1); 328 - } 314 + write_output(&mmap_ev, mmap_ev.header.size); 329 315 } 330 316 } 331 317 ··· 359 351 int track = 1; 360 352 361 353 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 354 + 362 355 if (freq) { 363 356 attr->sample_type |= PERF_SAMPLE_PERIOD; 364 357 attr->freq = 1; 365 358 attr->sample_freq = freq; 366 359 } 360 + 361 + if (call_graph) 362 + attr->sample_type |= PERF_SAMPLE_CALLCHAIN; 363 + 364 + if (file_new) { 365 + file_header.sample_type = attr->sample_type; 366 + } else { 367 + if (file_header.sample_type != attr->sample_type) { 368 + fprintf(stderr, "incompatible append\n"); 369 + exit(-1); 370 + } 371 + } 372 + 367 373 attr->mmap = track; 368 374 attr->comm = track; 369 375 attr->inherit = (cpu < 0) && inherit; ··· 432 410 mmap_array[nr_cpu][counter].prev = 0; 433 411 mmap_array[nr_cpu][counter].mask = mmap_pages*page_size - 1; 434 412 mmap_array[nr_cpu][counter].base = mmap(NULL, (mmap_pages+1)*page_size, 435 - PROT_READ, MAP_SHARED, fd[nr_cpu][counter], 0); 413 + PROT_READ|PROT_WRITE, MAP_SHARED, fd[nr_cpu][counter], 0); 436 414 if (mmap_array[nr_cpu][counter].base == MAP_FAILED) { 437 415 error("failed to mmap with %d (%s)\n", errno, strerror(errno)); 438 416 exit(-1); ··· 457 435 nr_cpu++; 458 436 } 459 437 438 + static void atexit_header(void) 439 + { 440 + file_header.data_size += bytes_written; 441 + 442 + if (pwrite(output, &file_header, sizeof(file_header), 0) == -1) 443 + perror("failed to write on file headers"); 444 + } 445 + 460 446 static int __cmd_record(int argc, const char **argv) 461 447 { 462 448 int i, counter; ··· 478 448 assert(nr_cpus <= MAX_NR_CPUS); 479 449 assert(nr_cpus >= 0); 480 450 451 + atexit(sig_atexit); 452 + signal(SIGCHLD, sig_handler); 453 + signal(SIGINT, sig_handler); 454 + 481 455 if (!stat(output_name, &st) && !force && !append_file) { 482 456 fprintf(stderr, "Error, output file %s exists, use -A to append or -f to overwrite.\n", 483 457 output_name); ··· 490 456 491 457 flags = O_CREAT|O_RDWR; 492 458 if (append_file) 493 - flags |= O_APPEND; 459 + file_new = 0; 494 460 else 495 461 flags |= O_TRUNC; 496 462 ··· 500 466 exit(-1); 501 467 } 502 468 469 + if (!file_new) { 470 + if (read(output, &file_header, sizeof(file_header)) == -1) { 471 + perror("failed to read file headers"); 472 + exit(-1); 473 + } 474 + 475 + lseek(output, file_header.data_size, SEEK_CUR); 476 + } 477 + 478 + atexit(atexit_header); 479 + 503 480 if (!system_wide) { 504 481 open_counters(-1, target_pid != -1 ? target_pid : getpid()); 505 482 } else for (i = 0; i < nr_cpus; i++) 506 483 open_counters(i, target_pid); 507 - 508 - atexit(sig_atexit); 509 - signal(SIGCHLD, sig_handler); 510 - signal(SIGINT, sig_handler); 511 484 512 485 if (target_pid == -1 && argc) { 513 486 pid = fork(); ··· 596 555 "profile at this frequency"), 597 556 OPT_INTEGER('m', "mmap-pages", &mmap_pages, 598 557 "number of mmap data pages"), 558 + OPT_BOOLEAN('g', "call-graph", &call_graph, 559 + "do call-graph (stack chain/backtrace) recording"), 599 560 OPT_BOOLEAN('v', "verbose", &verbose, 600 561 "be more verbose (show counter open errors, etc)"), 601 562 OPT_END()
+352 -87
tools/perf/builtin-report.c
··· 36 36 37 37 static int dump_trace = 0; 38 38 #define dprintf(x...) do { if (dump_trace) printf(x); } while (0) 39 + #define cdprintf(x...) do { if (dump_trace) color_fprintf(stdout, color, x); } while (0) 39 40 40 41 static int verbose; 42 + #define eprintf(x...) do { if (verbose) fprintf(stderr, x); } while (0) 43 + 41 44 static int full_paths; 42 45 43 46 static unsigned long page_size; 44 47 static unsigned long mmap_window = 32; 45 48 49 + static char default_parent_pattern[] = "^sys_|^do_page_fault"; 50 + static char *parent_pattern = default_parent_pattern; 51 + static regex_t parent_regex; 52 + 53 + static int exclude_other = 1; 54 + 46 55 struct ip_event { 47 56 struct perf_event_header header; 48 - __u64 ip; 49 - __u32 pid, tid; 50 - __u64 period; 57 + u64 ip; 58 + u32 pid, tid; 59 + unsigned char __more_data[]; 60 + }; 61 + 62 + struct ip_callchain { 63 + u64 nr; 64 + u64 ips[0]; 51 65 }; 52 66 53 67 struct mmap_event { 54 68 struct perf_event_header header; 55 - __u32 pid, tid; 56 - __u64 start; 57 - __u64 len; 58 - __u64 pgoff; 69 + u32 pid, tid; 70 + u64 start; 71 + u64 len; 72 + u64 pgoff; 59 73 char filename[PATH_MAX]; 60 74 }; 61 75 62 76 struct comm_event { 63 77 struct perf_event_header header; 64 - __u32 pid, tid; 78 + u32 pid, tid; 65 79 char comm[16]; 66 80 }; 67 81 68 82 struct fork_event { 69 83 struct perf_event_header header; 70 - __u32 pid, ppid; 84 + u32 pid, ppid; 71 85 }; 72 86 73 87 struct period_event { 74 88 struct perf_event_header header; 75 - __u64 time; 76 - __u64 id; 77 - __u64 sample_period; 89 + u64 time; 90 + u64 id; 91 + u64 sample_period; 92 + }; 93 + 94 + struct lost_event { 95 + struct perf_event_header header; 96 + u64 id; 97 + u64 lost; 78 98 }; 79 99 80 100 typedef union event_union { ··· 104 84 struct comm_event comm; 105 85 struct fork_event fork; 106 86 struct period_event period; 87 + struct lost_event lost; 107 88 } event_t; 108 89 109 90 static LIST_HEAD(dsos); ··· 140 119 141 120 nr = dso__load(dso, NULL, verbose); 142 121 if (nr < 0) { 143 - if (verbose) 144 - fprintf(stderr, "Failed to open: %s\n", name); 122 + eprintf("Failed to open: %s\n", name); 145 123 goto out_delete_dso; 146 124 } 147 - if (!nr && verbose) { 148 - fprintf(stderr, 149 - "No symbols found in: %s, maybe install a debug package?\n", 150 - name); 151 - } 125 + if (!nr) 126 + eprintf("No symbols found in: %s, maybe install a debug package?\n", name); 152 127 153 128 dsos__add(dso); 154 129 ··· 163 146 dso__fprintf(pos, fp); 164 147 } 165 148 166 - static struct symbol *vdso__find_symbol(struct dso *dso, __u64 ip) 149 + static struct symbol *vdso__find_symbol(struct dso *dso, u64 ip) 167 150 { 168 151 return dso__find_symbol(kernel_dso, ip); 169 152 } ··· 210 193 211 194 struct map { 212 195 struct list_head node; 213 - __u64 start; 214 - __u64 end; 215 - __u64 pgoff; 216 - __u64 (*map_ip)(struct map *, __u64); 196 + u64 start; 197 + u64 end; 198 + u64 pgoff; 199 + u64 (*map_ip)(struct map *, u64); 217 200 struct dso *dso; 218 201 }; 219 202 220 - static __u64 map__map_ip(struct map *map, __u64 ip) 203 + static u64 map__map_ip(struct map *map, u64 ip) 221 204 { 222 205 return ip - map->start + map->pgoff; 223 206 } 224 207 225 - static __u64 vdso__map_ip(struct map *map, __u64 ip) 208 + static u64 vdso__map_ip(struct map *map, u64 ip) 226 209 { 227 210 return ip; 228 211 } ··· 429 412 return 0; 430 413 } 431 414 432 - static struct map *thread__find_map(struct thread *self, __u64 ip) 415 + static struct map *thread__find_map(struct thread *self, u64 ip) 433 416 { 434 417 struct map *pos; 435 418 ··· 470 453 struct map *map; 471 454 struct dso *dso; 472 455 struct symbol *sym; 473 - __u64 ip; 456 + struct symbol *parent; 457 + u64 ip; 474 458 char level; 475 459 476 - __u64 count; 460 + u64 count; 477 461 }; 478 462 479 463 /* ··· 490 472 int64_t (*collapse)(struct hist_entry *, struct hist_entry *); 491 473 size_t (*print)(FILE *fp, struct hist_entry *); 492 474 }; 475 + 476 + static int64_t cmp_null(void *l, void *r) 477 + { 478 + if (!l && !r) 479 + return 0; 480 + else if (!l) 481 + return -1; 482 + else 483 + return 1; 484 + } 493 485 494 486 /* --sort pid */ 495 487 ··· 535 507 char *comm_l = left->thread->comm; 536 508 char *comm_r = right->thread->comm; 537 509 538 - if (!comm_l || !comm_r) { 539 - if (!comm_l && !comm_r) 540 - return 0; 541 - else if (!comm_l) 542 - return -1; 543 - else 544 - return 1; 545 - } 510 + if (!comm_l || !comm_r) 511 + return cmp_null(comm_l, comm_r); 546 512 547 513 return strcmp(comm_l, comm_r); 548 514 } ··· 562 540 struct dso *dso_l = left->dso; 563 541 struct dso *dso_r = right->dso; 564 542 565 - if (!dso_l || !dso_r) { 566 - if (!dso_l && !dso_r) 567 - return 0; 568 - else if (!dso_l) 569 - return -1; 570 - else 571 - return 1; 572 - } 543 + if (!dso_l || !dso_r) 544 + return cmp_null(dso_l, dso_r); 573 545 574 546 return strcmp(dso_l->name, dso_r->name); 575 547 } ··· 574 558 if (self->dso) 575 559 return fprintf(fp, "%-25s", self->dso->name); 576 560 577 - return fprintf(fp, "%016llx ", (__u64)self->ip); 561 + return fprintf(fp, "%016llx ", (u64)self->ip); 578 562 } 579 563 580 564 static struct sort_entry sort_dso = { ··· 588 572 static int64_t 589 573 sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) 590 574 { 591 - __u64 ip_l, ip_r; 575 + u64 ip_l, ip_r; 592 576 593 577 if (left->sym == right->sym) 594 578 return 0; ··· 605 589 size_t ret = 0; 606 590 607 591 if (verbose) 608 - ret += fprintf(fp, "%#018llx ", (__u64)self->ip); 592 + ret += fprintf(fp, "%#018llx ", (u64)self->ip); 609 593 610 594 if (self->sym) { 611 595 ret += fprintf(fp, "[%c] %s", 612 596 self->dso == kernel_dso ? 'k' : '.', self->sym->name); 613 597 } else { 614 - ret += fprintf(fp, "%#016llx", (__u64)self->ip); 598 + ret += fprintf(fp, "%#016llx", (u64)self->ip); 615 599 } 616 600 617 601 return ret; ··· 623 607 .print = sort__sym_print, 624 608 }; 625 609 610 + /* --sort parent */ 611 + 612 + static int64_t 613 + sort__parent_cmp(struct hist_entry *left, struct hist_entry *right) 614 + { 615 + struct symbol *sym_l = left->parent; 616 + struct symbol *sym_r = right->parent; 617 + 618 + if (!sym_l || !sym_r) 619 + return cmp_null(sym_l, sym_r); 620 + 621 + return strcmp(sym_l->name, sym_r->name); 622 + } 623 + 624 + static size_t 625 + sort__parent_print(FILE *fp, struct hist_entry *self) 626 + { 627 + size_t ret = 0; 628 + 629 + ret += fprintf(fp, "%-20s", self->parent ? self->parent->name : "[other]"); 630 + 631 + return ret; 632 + } 633 + 634 + static struct sort_entry sort_parent = { 635 + .header = "Parent symbol ", 636 + .cmp = sort__parent_cmp, 637 + .print = sort__parent_print, 638 + }; 639 + 626 640 static int sort__need_collapse = 0; 641 + static int sort__has_parent = 0; 627 642 628 643 struct sort_dimension { 629 644 char *name; ··· 667 620 { .name = "comm", .entry = &sort_comm, }, 668 621 { .name = "dso", .entry = &sort_dso, }, 669 622 { .name = "symbol", .entry = &sort_sym, }, 623 + { .name = "parent", .entry = &sort_parent, }, 670 624 }; 671 625 672 626 static LIST_HEAD(hist_entry__sort_list); ··· 687 639 688 640 if (sd->entry->collapse) 689 641 sort__need_collapse = 1; 642 + 643 + if (sd->entry == &sort_parent) { 644 + int ret = regcomp(&parent_regex, parent_pattern, REG_EXTENDED); 645 + if (ret) { 646 + char err[BUFSIZ]; 647 + 648 + regerror(ret, &parent_regex, err, sizeof(err)); 649 + fprintf(stderr, "Invalid regex: %s\n%s", 650 + parent_pattern, err); 651 + exit(-1); 652 + } 653 + sort__has_parent = 1; 654 + } 690 655 691 656 list_add_tail(&sd->entry->list, &hist_entry__sort_list); 692 657 sd->taken = 1; ··· 745 684 } 746 685 747 686 static size_t 748 - hist_entry__fprintf(FILE *fp, struct hist_entry *self, __u64 total_samples) 687 + hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples) 749 688 { 750 689 struct sort_entry *se; 751 690 size_t ret; 691 + 692 + if (exclude_other && !self->parent) 693 + return 0; 752 694 753 695 if (total_samples) { 754 696 double percent = self->count * 100.0 / total_samples; ··· 775 711 ret = fprintf(fp, "%12Ld ", self->count); 776 712 777 713 list_for_each_entry(se, &hist_entry__sort_list, list) { 714 + if (exclude_other && (se == &sort_parent)) 715 + continue; 716 + 778 717 fprintf(fp, " "); 779 718 ret += se->print(fp, self); 780 719 } ··· 788 721 } 789 722 790 723 /* 724 + * 725 + */ 726 + 727 + static struct symbol * 728 + resolve_symbol(struct thread *thread, struct map **mapp, 729 + struct dso **dsop, u64 *ipp) 730 + { 731 + struct dso *dso = dsop ? *dsop : NULL; 732 + struct map *map = mapp ? *mapp : NULL; 733 + uint64_t ip = *ipp; 734 + 735 + if (!thread) 736 + return NULL; 737 + 738 + if (dso) 739 + goto got_dso; 740 + 741 + if (map) 742 + goto got_map; 743 + 744 + map = thread__find_map(thread, ip); 745 + if (map != NULL) { 746 + if (mapp) 747 + *mapp = map; 748 + got_map: 749 + ip = map->map_ip(map, ip); 750 + *ipp = ip; 751 + 752 + dso = map->dso; 753 + } else { 754 + /* 755 + * If this is outside of all known maps, 756 + * and is a negative address, try to look it 757 + * up in the kernel dso, as it might be a 758 + * vsyscall (which executes in user-mode): 759 + */ 760 + if ((long long)ip < 0) 761 + dso = kernel_dso; 762 + } 763 + dprintf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); 764 + 765 + if (dsop) 766 + *dsop = dso; 767 + 768 + if (!dso) 769 + return NULL; 770 + got_dso: 771 + return dso->find_symbol(dso, ip); 772 + } 773 + 774 + static int call__match(struct symbol *sym) 775 + { 776 + if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0)) 777 + return 1; 778 + 779 + return 0; 780 + } 781 + 782 + /* 791 783 * collect histogram counts 792 784 */ 793 785 794 786 static int 795 787 hist_entry__add(struct thread *thread, struct map *map, struct dso *dso, 796 - struct symbol *sym, __u64 ip, char level, __u64 count) 788 + struct symbol *sym, u64 ip, struct ip_callchain *chain, 789 + char level, u64 count) 797 790 { 798 791 struct rb_node **p = &hist.rb_node; 799 792 struct rb_node *parent = NULL; ··· 866 739 .ip = ip, 867 740 .level = level, 868 741 .count = count, 742 + .parent = NULL, 869 743 }; 870 744 int cmp; 745 + 746 + if (sort__has_parent && chain) { 747 + u64 context = PERF_CONTEXT_MAX; 748 + int i; 749 + 750 + for (i = 0; i < chain->nr; i++) { 751 + u64 ip = chain->ips[i]; 752 + struct dso *dso = NULL; 753 + struct symbol *sym; 754 + 755 + if (ip >= PERF_CONTEXT_MAX) { 756 + context = ip; 757 + continue; 758 + } 759 + 760 + switch (context) { 761 + case PERF_CONTEXT_KERNEL: 762 + dso = kernel_dso; 763 + break; 764 + default: 765 + break; 766 + } 767 + 768 + sym = resolve_symbol(thread, NULL, &dso, &ip); 769 + 770 + if (sym && call__match(sym)) { 771 + entry.parent = sym; 772 + break; 773 + } 774 + } 775 + } 871 776 872 777 while (*p != NULL) { 873 778 parent = *p; ··· 1032 873 } 1033 874 } 1034 875 1035 - static size_t output__fprintf(FILE *fp, __u64 total_samples) 876 + static size_t output__fprintf(FILE *fp, u64 total_samples) 1036 877 { 1037 878 struct hist_entry *pos; 1038 879 struct sort_entry *se; ··· 1041 882 1042 883 fprintf(fp, "\n"); 1043 884 fprintf(fp, "#\n"); 1044 - fprintf(fp, "# (%Ld samples)\n", (__u64)total_samples); 885 + fprintf(fp, "# (%Ld samples)\n", (u64)total_samples); 1045 886 fprintf(fp, "#\n"); 1046 887 1047 888 fprintf(fp, "# Overhead"); 1048 - list_for_each_entry(se, &hist_entry__sort_list, list) 889 + list_for_each_entry(se, &hist_entry__sort_list, list) { 890 + if (exclude_other && (se == &sort_parent)) 891 + continue; 1049 892 fprintf(fp, " %s", se->header); 893 + } 1050 894 fprintf(fp, "\n"); 1051 895 1052 896 fprintf(fp, "# ........"); 1053 897 list_for_each_entry(se, &hist_entry__sort_list, list) { 1054 898 int i; 899 + 900 + if (exclude_other && (se == &sort_parent)) 901 + continue; 1055 902 1056 903 fprintf(fp, " "); 1057 904 for (i = 0; i < strlen(se->header); i++) ··· 1072 907 ret += hist_entry__fprintf(fp, pos, total_samples); 1073 908 } 1074 909 1075 - if (!strcmp(sort_order, default_sort_order)) { 910 + if (sort_order == default_sort_order && 911 + parent_pattern == default_parent_pattern) { 1076 912 fprintf(fp, "#\n"); 1077 913 fprintf(fp, "# (For more details, try: perf report --sort comm,dso,symbol)\n"); 1078 914 fprintf(fp, "#\n"); ··· 1098 932 total_mmap = 0, 1099 933 total_comm = 0, 1100 934 total_fork = 0, 1101 - total_unknown = 0; 935 + total_unknown = 0, 936 + total_lost = 0; 937 + 938 + static int validate_chain(struct ip_callchain *chain, event_t *event) 939 + { 940 + unsigned int chain_size; 941 + 942 + chain_size = event->header.size; 943 + chain_size -= (unsigned long)&event->ip.__more_data - (unsigned long)event; 944 + 945 + if (chain->nr*sizeof(u64) > chain_size) 946 + return -1; 947 + 948 + return 0; 949 + } 1102 950 1103 951 static int 1104 952 process_overflow_event(event_t *event, unsigned long offset, unsigned long head) ··· 1121 941 int show = 0; 1122 942 struct dso *dso = NULL; 1123 943 struct thread *thread = threads__findnew(event->ip.pid); 1124 - __u64 ip = event->ip.ip; 1125 - __u64 period = 1; 944 + u64 ip = event->ip.ip; 945 + u64 period = 1; 1126 946 struct map *map = NULL; 947 + void *more_data = event->ip.__more_data; 948 + struct ip_callchain *chain = NULL; 1127 949 1128 - if (event->header.type & PERF_SAMPLE_PERIOD) 1129 - period = event->ip.period; 950 + if (event->header.type & PERF_SAMPLE_PERIOD) { 951 + period = *(u64 *)more_data; 952 + more_data += sizeof(u64); 953 + } 1130 954 1131 955 dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p period: %Ld\n", 1132 956 (void *)(offset + head), ··· 1140 956 (void *)(long)ip, 1141 957 (long long)period); 1142 958 959 + if (event->header.type & PERF_SAMPLE_CALLCHAIN) { 960 + int i; 961 + 962 + chain = (void *)more_data; 963 + 964 + dprintf("... chain: nr:%Lu\n", chain->nr); 965 + 966 + if (validate_chain(chain, event) < 0) { 967 + eprintf("call-chain problem with event, skipping it.\n"); 968 + return 0; 969 + } 970 + 971 + if (dump_trace) { 972 + for (i = 0; i < chain->nr; i++) 973 + dprintf("..... %2d: %016Lx\n", i, chain->ips[i]); 974 + } 975 + } 976 + 1143 977 dprintf(" ... thread: %s:%d\n", thread->comm, thread->pid); 1144 978 1145 979 if (thread == NULL) { 1146 - fprintf(stderr, "problem processing %d event, skipping it.\n", 980 + eprintf("problem processing %d event, skipping it.\n", 1147 981 event->header.type); 1148 982 return -1; 1149 983 } ··· 1179 977 show = SHOW_USER; 1180 978 level = '.'; 1181 979 1182 - map = thread__find_map(thread, ip); 1183 - if (map != NULL) { 1184 - ip = map->map_ip(map, ip); 1185 - dso = map->dso; 1186 - } else { 1187 - /* 1188 - * If this is outside of all known maps, 1189 - * and is a negative address, try to look it 1190 - * up in the kernel dso, as it might be a 1191 - * vsyscall (which executes in user-mode): 1192 - */ 1193 - if ((long long)ip < 0) 1194 - dso = kernel_dso; 1195 - } 1196 - dprintf(" ...... dso: %s\n", dso ? dso->name : "<not found>"); 1197 - 1198 980 } else { 1199 981 show = SHOW_HV; 1200 982 level = 'H'; ··· 1186 1000 } 1187 1001 1188 1002 if (show & show_mask) { 1189 - struct symbol *sym = NULL; 1003 + struct symbol *sym = resolve_symbol(thread, &map, &dso, &ip); 1190 1004 1191 - if (dso) 1192 - sym = dso->find_symbol(dso, ip); 1193 - 1194 - if (hist_entry__add(thread, map, dso, sym, ip, level, period)) { 1195 - fprintf(stderr, 1196 - "problem incrementing symbol count, skipping event\n"); 1005 + if (hist_entry__add(thread, map, dso, sym, ip, chain, level, period)) { 1006 + eprintf("problem incrementing symbol count, skipping event\n"); 1197 1007 return -1; 1198 1008 } 1199 1009 } ··· 1278 1096 } 1279 1097 1280 1098 static int 1099 + process_lost_event(event_t *event, unsigned long offset, unsigned long head) 1100 + { 1101 + dprintf("%p [%p]: PERF_EVENT_LOST: id:%Ld: lost:%Ld\n", 1102 + (void *)(offset + head), 1103 + (void *)(long)(event->header.size), 1104 + event->lost.id, 1105 + event->lost.lost); 1106 + 1107 + total_lost += event->lost.lost; 1108 + 1109 + return 0; 1110 + } 1111 + 1112 + static void trace_event(event_t *event) 1113 + { 1114 + unsigned char *raw_event = (void *)event; 1115 + char *color = PERF_COLOR_BLUE; 1116 + int i, j; 1117 + 1118 + if (!dump_trace) 1119 + return; 1120 + 1121 + dprintf("."); 1122 + cdprintf("\n. ... raw event: size %d bytes\n", event->header.size); 1123 + 1124 + for (i = 0; i < event->header.size; i++) { 1125 + if ((i & 15) == 0) { 1126 + dprintf("."); 1127 + cdprintf(" %04x: ", i); 1128 + } 1129 + 1130 + cdprintf(" %02x", raw_event[i]); 1131 + 1132 + if (((i & 15) == 15) || i == event->header.size-1) { 1133 + cdprintf(" "); 1134 + for (j = 0; j < 15-(i & 15); j++) 1135 + cdprintf(" "); 1136 + for (j = 0; j < (i & 15); j++) { 1137 + if (isprint(raw_event[i-15+j])) 1138 + cdprintf("%c", raw_event[i-15+j]); 1139 + else 1140 + cdprintf("."); 1141 + } 1142 + cdprintf("\n"); 1143 + } 1144 + } 1145 + dprintf(".\n"); 1146 + } 1147 + 1148 + static int 1281 1149 process_event(event_t *event, unsigned long offset, unsigned long head) 1282 1150 { 1151 + trace_event(event); 1152 + 1283 1153 if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) 1284 1154 return process_overflow_event(event, offset, head); 1285 1155 ··· 1347 1113 1348 1114 case PERF_EVENT_PERIOD: 1349 1115 return process_period_event(event, offset, head); 1116 + 1117 + case PERF_EVENT_LOST: 1118 + return process_lost_event(event, offset, head); 1119 + 1350 1120 /* 1351 1121 * We dont process them right now but they are fine: 1352 1122 */ ··· 1366 1128 return 0; 1367 1129 } 1368 1130 1131 + static struct perf_file_header file_header; 1132 + 1369 1133 static int __cmd_report(void) 1370 1134 { 1371 1135 int ret, rc = EXIT_FAILURE; 1372 1136 unsigned long offset = 0; 1373 - unsigned long head = 0; 1137 + unsigned long head = sizeof(file_header); 1374 1138 struct stat stat; 1375 1139 event_t *event; 1376 1140 uint32_t size; ··· 1398 1158 if (!stat.st_size) { 1399 1159 fprintf(stderr, "zero-sized file, nothing to do!\n"); 1400 1160 exit(0); 1161 + } 1162 + 1163 + if (read(input, &file_header, sizeof(file_header)) == -1) { 1164 + perror("failed to read file headers"); 1165 + exit(-1); 1166 + } 1167 + 1168 + if (sort__has_parent && 1169 + !(file_header.sample_type & PERF_SAMPLE_CALLCHAIN)) { 1170 + fprintf(stderr, "selected --sort parent, but no callchain data\n"); 1171 + exit(-1); 1401 1172 } 1402 1173 1403 1174 if (load_kernel() < 0) { ··· 1455 1204 1456 1205 size = event->header.size; 1457 1206 1458 - dprintf("%p [%p]: event: %d\n", 1207 + dprintf("\n%p [%p]: event: %d\n", 1459 1208 (void *)(offset + head), 1460 1209 (void *)(long)event->header.size, 1461 1210 event->header.type); ··· 1482 1231 1483 1232 head += size; 1484 1233 1234 + if (offset + head >= sizeof(file_header) + file_header.data_size) 1235 + goto done; 1236 + 1485 1237 if (offset + head < stat.st_size) 1486 1238 goto more; 1487 1239 1240 + done: 1488 1241 rc = EXIT_SUCCESS; 1489 1242 close(input); 1490 1243 ··· 1496 1241 dprintf(" mmap events: %10ld\n", total_mmap); 1497 1242 dprintf(" comm events: %10ld\n", total_comm); 1498 1243 dprintf(" fork events: %10ld\n", total_fork); 1244 + dprintf(" lost events: %10ld\n", total_lost); 1499 1245 dprintf(" unknown events: %10ld\n", total_unknown); 1500 1246 1501 1247 if (dump_trace) ··· 1529 1273 "dump raw trace in ASCII"), 1530 1274 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), 1531 1275 OPT_STRING('s', "sort", &sort_order, "key[,key2...]", 1532 - "sort by key(s): pid, comm, dso, symbol. Default: pid,symbol"), 1276 + "sort by key(s): pid, comm, dso, symbol, parent"), 1533 1277 OPT_BOOLEAN('P', "full-paths", &full_paths, 1534 1278 "Don't shorten the pathnames taking into account the cwd"), 1279 + OPT_STRING('p', "parent", &parent_pattern, "regex", 1280 + "regex filter to identify parent, see: '--sort parent'"), 1281 + OPT_BOOLEAN('x', "exclude-other", &exclude_other, 1282 + "Only display entries with parent-match"), 1535 1283 OPT_END() 1536 1284 }; 1537 1285 ··· 1563 1303 argc = parse_options(argc, argv, options, report_usage, 0); 1564 1304 1565 1305 setup_sorting(); 1306 + 1307 + if (parent_pattern != default_parent_pattern) 1308 + sort_dimension__add("parent"); 1309 + else 1310 + exclude_other = 0; 1566 1311 1567 1312 /* 1568 1313 * Any (unrecognized) arguments left?
+232 -78
tools/perf/builtin-stat.c
··· 43 43 #include "util/parse-events.h" 44 44 45 45 #include <sys/prctl.h> 46 + #include <math.h> 46 47 47 48 static struct perf_counter_attr default_attrs[MAX_COUNTERS] = { 48 49 ··· 80 79 10000, 81 80 }; 82 81 83 - static __u64 event_res[MAX_COUNTERS][3]; 84 - static __u64 event_scaled[MAX_COUNTERS]; 82 + #define MAX_RUN 100 85 83 86 - static __u64 runtime_nsecs; 87 - static __u64 walltime_nsecs; 88 - static __u64 runtime_cycles; 84 + static int run_count = 1; 85 + static int run_idx = 0; 86 + 87 + static u64 event_res[MAX_RUN][MAX_COUNTERS][3]; 88 + static u64 event_scaled[MAX_RUN][MAX_COUNTERS]; 89 + 90 + //static u64 event_hist[MAX_RUN][MAX_COUNTERS][3]; 91 + 92 + 93 + static u64 runtime_nsecs[MAX_RUN]; 94 + static u64 walltime_nsecs[MAX_RUN]; 95 + static u64 runtime_cycles[MAX_RUN]; 96 + 97 + static u64 event_res_avg[MAX_COUNTERS][3]; 98 + static u64 event_res_noise[MAX_COUNTERS][3]; 99 + 100 + static u64 event_scaled_avg[MAX_COUNTERS]; 101 + 102 + static u64 runtime_nsecs_avg; 103 + static u64 runtime_nsecs_noise; 104 + 105 + static u64 walltime_nsecs_avg; 106 + static u64 walltime_nsecs_noise; 107 + 108 + static u64 runtime_cycles_avg; 109 + static u64 runtime_cycles_noise; 89 110 90 111 static void create_perf_stat_counter(int counter) 91 112 { ··· 158 135 */ 159 136 static void read_counter(int counter) 160 137 { 161 - __u64 *count, single_count[3]; 138 + u64 *count, single_count[3]; 162 139 ssize_t res; 163 140 int cpu, nv; 164 141 int scaled; 165 142 166 - count = event_res[counter]; 143 + count = event_res[run_idx][counter]; 167 144 168 145 count[0] = count[1] = count[2] = 0; 169 146 ··· 172 149 if (fd[cpu][counter] < 0) 173 150 continue; 174 151 175 - res = read(fd[cpu][counter], single_count, nv * sizeof(__u64)); 176 - assert(res == nv * sizeof(__u64)); 152 + res = read(fd[cpu][counter], single_count, nv * sizeof(u64)); 153 + assert(res == nv * sizeof(u64)); 154 + close(fd[cpu][counter]); 155 + fd[cpu][counter] = -1; 177 156 178 157 count[0] += single_count[0]; 179 158 if (scale) { ··· 187 162 scaled = 0; 188 163 if (scale) { 189 164 if (count[2] == 0) { 190 - event_scaled[counter] = -1; 165 + event_scaled[run_idx][counter] = -1; 191 166 count[0] = 0; 192 167 return; 193 168 } 194 169 195 170 if (count[2] < count[1]) { 196 - event_scaled[counter] = 1; 171 + event_scaled[run_idx][counter] = 1; 197 172 count[0] = (unsigned long long) 198 173 ((double)count[0] * count[1] / count[2] + 0.5); 199 174 } ··· 203 178 */ 204 179 if (attrs[counter].type == PERF_TYPE_SOFTWARE && 205 180 attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) 206 - runtime_nsecs = count[0]; 181 + runtime_nsecs[run_idx] = count[0]; 207 182 if (attrs[counter].type == PERF_TYPE_HARDWARE && 208 183 attrs[counter].config == PERF_COUNT_HW_CPU_CYCLES) 209 - runtime_cycles = count[0]; 184 + runtime_cycles[run_idx] = count[0]; 210 185 } 211 186 212 - /* 213 - * Print out the results of a single counter: 214 - */ 215 - static void print_counter(int counter) 216 - { 217 - __u64 *count; 218 - int scaled; 219 - 220 - count = event_res[counter]; 221 - scaled = event_scaled[counter]; 222 - 223 - if (scaled == -1) { 224 - fprintf(stderr, " %14s %-20s\n", 225 - "<not counted>", event_name(counter)); 226 - return; 227 - } 228 - 229 - if (nsec_counter(counter)) { 230 - double msecs = (double)count[0] / 1000000; 231 - 232 - fprintf(stderr, " %14.6f %-20s", 233 - msecs, event_name(counter)); 234 - if (attrs[counter].type == PERF_TYPE_SOFTWARE && 235 - attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) { 236 - 237 - if (walltime_nsecs) 238 - fprintf(stderr, " # %11.3f CPU utilization factor", 239 - (double)count[0] / (double)walltime_nsecs); 240 - } 241 - } else { 242 - fprintf(stderr, " %14Ld %-20s", 243 - count[0], event_name(counter)); 244 - if (runtime_nsecs) 245 - fprintf(stderr, " # %11.3f M/sec", 246 - (double)count[0]/runtime_nsecs*1000.0); 247 - if (runtime_cycles && 248 - attrs[counter].type == PERF_TYPE_HARDWARE && 249 - attrs[counter].config == PERF_COUNT_HW_INSTRUCTIONS) { 250 - 251 - fprintf(stderr, " # %1.3f per cycle", 252 - (double)count[0] / (double)runtime_cycles); 253 - } 254 - } 255 - if (scaled) 256 - fprintf(stderr, " (scaled from %.2f%%)", 257 - (double) count[2] / count[1] * 100); 258 - fprintf(stderr, "\n"); 259 - } 260 - 261 - static int do_perf_stat(int argc, const char **argv) 187 + static int run_perf_stat(int argc, const char **argv) 262 188 { 263 189 unsigned long long t0, t1; 190 + int status = 0; 264 191 int counter; 265 - int status; 266 192 int pid; 267 - int i; 268 193 269 194 if (!system_wide) 270 195 nr_cpus = 1; ··· 238 263 } 239 264 } 240 265 241 - while (wait(&status) >= 0) 242 - ; 266 + wait(&status); 243 267 244 268 prctl(PR_TASK_PERF_COUNTERS_DISABLE); 245 269 t1 = rdclock(); 246 270 247 - walltime_nsecs = t1 - t0; 271 + walltime_nsecs[run_idx] = t1 - t0; 272 + 273 + for (counter = 0; counter < nr_counters; counter++) 274 + read_counter(counter); 275 + 276 + return WEXITSTATUS(status); 277 + } 278 + 279 + static void print_noise(u64 *count, u64 *noise) 280 + { 281 + if (run_count > 1) 282 + fprintf(stderr, " ( +- %7.3f%% )", 283 + (double)noise[0]/(count[0]+1)*100.0); 284 + } 285 + 286 + static void nsec_printout(int counter, u64 *count, u64 *noise) 287 + { 288 + double msecs = (double)count[0] / 1000000; 289 + 290 + fprintf(stderr, " %14.6f %-20s", msecs, event_name(counter)); 291 + 292 + if (attrs[counter].type == PERF_TYPE_SOFTWARE && 293 + attrs[counter].config == PERF_COUNT_SW_TASK_CLOCK) { 294 + 295 + if (walltime_nsecs_avg) 296 + fprintf(stderr, " # %10.3f CPUs ", 297 + (double)count[0] / (double)walltime_nsecs_avg); 298 + } 299 + print_noise(count, noise); 300 + } 301 + 302 + static void abs_printout(int counter, u64 *count, u64 *noise) 303 + { 304 + fprintf(stderr, " %14Ld %-20s", count[0], event_name(counter)); 305 + 306 + if (runtime_cycles_avg && 307 + attrs[counter].type == PERF_TYPE_HARDWARE && 308 + attrs[counter].config == PERF_COUNT_HW_INSTRUCTIONS) { 309 + 310 + fprintf(stderr, " # %10.3f IPC ", 311 + (double)count[0] / (double)runtime_cycles_avg); 312 + } else { 313 + if (runtime_nsecs_avg) { 314 + fprintf(stderr, " # %10.3f M/sec", 315 + (double)count[0]/runtime_nsecs_avg*1000.0); 316 + } 317 + } 318 + print_noise(count, noise); 319 + } 320 + 321 + /* 322 + * Print out the results of a single counter: 323 + */ 324 + static void print_counter(int counter) 325 + { 326 + u64 *count, *noise; 327 + int scaled; 328 + 329 + count = event_res_avg[counter]; 330 + noise = event_res_noise[counter]; 331 + scaled = event_scaled_avg[counter]; 332 + 333 + if (scaled == -1) { 334 + fprintf(stderr, " %14s %-20s\n", 335 + "<not counted>", event_name(counter)); 336 + return; 337 + } 338 + 339 + if (nsec_counter(counter)) 340 + nsec_printout(counter, count, noise); 341 + else 342 + abs_printout(counter, count, noise); 343 + 344 + if (scaled) 345 + fprintf(stderr, " (scaled from %.2f%%)", 346 + (double) count[2] / count[1] * 100); 347 + 348 + fprintf(stderr, "\n"); 349 + } 350 + 351 + /* 352 + * normalize_noise noise values down to stddev: 353 + */ 354 + static void normalize_noise(u64 *val) 355 + { 356 + double res; 357 + 358 + res = (double)*val / (run_count * sqrt((double)run_count)); 359 + 360 + *val = (u64)res; 361 + } 362 + 363 + static void update_avg(const char *name, int idx, u64 *avg, u64 *val) 364 + { 365 + *avg += *val; 366 + 367 + if (verbose > 1) 368 + fprintf(stderr, "debug: %20s[%d]: %Ld\n", name, idx, *val); 369 + } 370 + /* 371 + * Calculate the averages and noises: 372 + */ 373 + static void calc_avg(void) 374 + { 375 + int i, j; 376 + 377 + if (verbose > 1) 378 + fprintf(stderr, "\n"); 379 + 380 + for (i = 0; i < run_count; i++) { 381 + update_avg("runtime", 0, &runtime_nsecs_avg, runtime_nsecs + i); 382 + update_avg("walltime", 0, &walltime_nsecs_avg, walltime_nsecs + i); 383 + update_avg("runtime_cycles", 0, &runtime_cycles_avg, runtime_cycles + i); 384 + 385 + for (j = 0; j < nr_counters; j++) { 386 + update_avg("counter/0", j, 387 + event_res_avg[j]+0, event_res[i][j]+0); 388 + update_avg("counter/1", j, 389 + event_res_avg[j]+1, event_res[i][j]+1); 390 + update_avg("counter/2", j, 391 + event_res_avg[j]+2, event_res[i][j]+2); 392 + update_avg("scaled", j, 393 + event_scaled_avg + j, event_scaled[i]+j); 394 + } 395 + } 396 + runtime_nsecs_avg /= run_count; 397 + walltime_nsecs_avg /= run_count; 398 + runtime_cycles_avg /= run_count; 399 + 400 + for (j = 0; j < nr_counters; j++) { 401 + event_res_avg[j][0] /= run_count; 402 + event_res_avg[j][1] /= run_count; 403 + event_res_avg[j][2] /= run_count; 404 + } 405 + 406 + for (i = 0; i < run_count; i++) { 407 + runtime_nsecs_noise += 408 + abs((s64)(runtime_nsecs[i] - runtime_nsecs_avg)); 409 + walltime_nsecs_noise += 410 + abs((s64)(walltime_nsecs[i] - walltime_nsecs_avg)); 411 + runtime_cycles_noise += 412 + abs((s64)(runtime_cycles[i] - runtime_cycles_avg)); 413 + 414 + for (j = 0; j < nr_counters; j++) { 415 + event_res_noise[j][0] += 416 + abs((s64)(event_res[i][j][0] - event_res_avg[j][0])); 417 + event_res_noise[j][1] += 418 + abs((s64)(event_res[i][j][1] - event_res_avg[j][1])); 419 + event_res_noise[j][2] += 420 + abs((s64)(event_res[i][j][2] - event_res_avg[j][2])); 421 + } 422 + } 423 + 424 + normalize_noise(&runtime_nsecs_noise); 425 + normalize_noise(&walltime_nsecs_noise); 426 + normalize_noise(&runtime_cycles_noise); 427 + 428 + for (j = 0; j < nr_counters; j++) { 429 + normalize_noise(&event_res_noise[j][0]); 430 + normalize_noise(&event_res_noise[j][1]); 431 + normalize_noise(&event_res_noise[j][2]); 432 + } 433 + } 434 + 435 + static void print_stat(int argc, const char **argv) 436 + { 437 + int i, counter; 438 + 439 + calc_avg(); 248 440 249 441 fflush(stdout); 250 442 ··· 421 279 for (i = 1; i < argc; i++) 422 280 fprintf(stderr, " %s", argv[i]); 423 281 424 - fprintf(stderr, "\':\n"); 425 - fprintf(stderr, "\n"); 426 - 427 - for (counter = 0; counter < nr_counters; counter++) 428 - read_counter(counter); 282 + fprintf(stderr, "\'"); 283 + if (run_count > 1) 284 + fprintf(stderr, " (%d runs)", run_count); 285 + fprintf(stderr, ":\n\n"); 429 286 430 287 for (counter = 0; counter < nr_counters; counter++) 431 288 print_counter(counter); 432 289 433 290 434 291 fprintf(stderr, "\n"); 435 - fprintf(stderr, " Wall-clock time elapsed: %12.6f msecs\n", 436 - (double)(t1-t0)/1e6); 292 + fprintf(stderr, " %14.9f seconds time elapsed.\n", 293 + (double)walltime_nsecs_avg/1e9); 437 294 fprintf(stderr, "\n"); 438 - 439 - return 0; 440 295 } 441 296 442 297 static volatile int signr = -1; ··· 471 332 "scale/normalize counters"), 472 333 OPT_BOOLEAN('v', "verbose", &verbose, 473 334 "be more verbose (show counter open errors, etc)"), 335 + OPT_INTEGER('r', "repeat", &run_count, 336 + "repeat command and print average + stddev (max: 100)"), 474 337 OPT_END() 475 338 }; 476 339 477 340 int cmd_stat(int argc, const char **argv, const char *prefix) 478 341 { 342 + int status; 343 + 479 344 page_size = sysconf(_SC_PAGE_SIZE); 480 345 481 346 memcpy(attrs, default_attrs, sizeof(attrs)); 482 347 483 348 argc = parse_options(argc, argv, options, stat_usage, 0); 484 349 if (!argc) 350 + usage_with_options(stat_usage, options); 351 + if (run_count <= 0 || run_count > MAX_RUN) 485 352 usage_with_options(stat_usage, options); 486 353 487 354 if (!nr_counters) ··· 508 363 signal(SIGALRM, skip_signal); 509 364 signal(SIGABRT, skip_signal); 510 365 511 - return do_perf_stat(argc, argv); 366 + status = 0; 367 + for (run_idx = 0; run_idx < run_count; run_idx++) { 368 + if (run_count != 1 && verbose) 369 + fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx+1); 370 + status = run_perf_stat(argc, argv); 371 + } 372 + 373 + print_stat(argc, argv); 374 + 375 + return status; 512 376 }
+12 -12
tools/perf/builtin-top.c
··· 54 54 55 55 static int default_interval = 100000; 56 56 57 - static __u64 count_filter = 5; 57 + static u64 count_filter = 5; 58 58 static int print_entries = 15; 59 59 60 60 static int target_pid = -1; ··· 79 79 * Symbols 80 80 */ 81 81 82 - static __u64 min_ip; 83 - static __u64 max_ip = -1ll; 82 + static u64 min_ip; 83 + static u64 max_ip = -1ll; 84 84 85 85 struct sym_entry { 86 86 struct rb_node rb_node; ··· 194 194 100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec))); 195 195 196 196 if (nr_counters == 1) { 197 - printf("%Ld", attrs[0].sample_period); 197 + printf("%Ld", (u64)attrs[0].sample_period); 198 198 if (freq) 199 199 printf("Hz "); 200 200 else ··· 372 372 /* 373 373 * Binary search in the histogram table and record the hit: 374 374 */ 375 - static void record_ip(__u64 ip, int counter) 375 + static void record_ip(u64 ip, int counter) 376 376 { 377 377 struct symbol *sym = dso__find_symbol(kernel_dso, ip); 378 378 ··· 392 392 samples--; 393 393 } 394 394 395 - static void process_event(__u64 ip, int counter) 395 + static void process_event(u64 ip, int counter) 396 396 { 397 397 samples++; 398 398 ··· 463 463 for (; old != head;) { 464 464 struct ip_event { 465 465 struct perf_event_header header; 466 - __u64 ip; 467 - __u32 pid, target_pid; 466 + u64 ip; 467 + u32 pid, target_pid; 468 468 }; 469 469 struct mmap_event { 470 470 struct perf_event_header header; 471 - __u32 pid, target_pid; 472 - __u64 start; 473 - __u64 len; 474 - __u64 pgoff; 471 + u32 pid, target_pid; 472 + u64 start; 473 + u64 len; 474 + u64 pgoff; 475 475 char filename[PATH_MAX]; 476 476 }; 477 477
+7
tools/perf/perf.h
··· 19 19 #include <sys/syscall.h> 20 20 21 21 #include "../../include/linux/perf_counter.h" 22 + #include "types.h" 22 23 23 24 /* 24 25 * prctl(PR_TASK_PERF_COUNTERS_DISABLE) will (cheaply) disable all ··· 65 64 66 65 #define MAX_COUNTERS 256 67 66 #define MAX_NR_CPUS 256 67 + 68 + struct perf_file_header { 69 + u64 version; 70 + u64 sample_type; 71 + u64 data_size; 72 + }; 68 73 69 74 #endif
+17
tools/perf/types.h
··· 1 + #ifndef _PERF_TYPES_H 2 + #define _PERF_TYPES_H 3 + 4 + /* 5 + * We define u64 as unsigned long long for every architecture 6 + * so that we can print it with %Lx without getting warnings. 7 + */ 8 + typedef unsigned long long u64; 9 + typedef signed long long s64; 10 + typedef unsigned int u32; 11 + typedef signed int s32; 12 + typedef unsigned short u16; 13 + typedef signed short s16; 14 + typedef unsigned char u8; 15 + typedef signed char s8; 16 + 17 + #endif /* _PERF_TYPES_H */
+11 -6
tools/perf/util/ctype.c
··· 11 11 D = GIT_DIGIT, 12 12 G = GIT_GLOB_SPECIAL, /* *, ?, [, \\ */ 13 13 R = GIT_REGEX_SPECIAL, /* $, (, ), +, ., ^, {, | * */ 14 + P = GIT_PRINT_EXTRA, /* printable - alpha - digit - glob - regex */ 15 + 16 + PS = GIT_SPACE | GIT_PRINT_EXTRA, 14 17 }; 15 18 16 19 unsigned char sane_ctype[256] = { 20 + /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 21 + 17 22 0, 0, 0, 0, 0, 0, 0, 0, 0, S, S, 0, 0, S, 0, 0, /* 0.. 15 */ 18 23 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 16.. 31 */ 19 - S, 0, 0, 0, R, 0, 0, 0, R, R, G, R, 0, 0, R, 0, /* 32.. 47 */ 20 - D, D, D, D, D, D, D, D, D, D, 0, 0, 0, 0, 0, G, /* 48.. 63 */ 21 - 0, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 64.. 79 */ 22 - A, A, A, A, A, A, A, A, A, A, A, G, G, 0, R, 0, /* 80.. 95 */ 23 - 0, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 96..111 */ 24 - A, A, A, A, A, A, A, A, A, A, A, R, R, 0, 0, 0, /* 112..127 */ 24 + PS,P, P, P, R, P, P, P, R, R, G, R, P, P, R, P, /* 32.. 47 */ 25 + D, D, D, D, D, D, D, D, D, D, P, P, P, P, P, G, /* 48.. 63 */ 26 + P, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 64.. 79 */ 27 + A, A, A, A, A, A, A, A, A, A, A, G, G, P, R, P, /* 80.. 95 */ 28 + P, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, /* 96..111 */ 29 + A, A, A, A, A, A, A, A, A, A, A, R, R, P, P, 0, /* 112..127 */ 25 30 /* Nothing in the 128.. range */ 26 31 };
+7 -7
tools/perf/util/parse-events.c
··· 13 13 struct perf_counter_attr attrs[MAX_COUNTERS]; 14 14 15 15 struct event_symbol { 16 - __u8 type; 17 - __u64 config; 16 + u8 type; 17 + u64 config; 18 18 char *symbol; 19 19 }; 20 20 ··· 63 63 }; 64 64 65 65 static char *sw_event_names[] = { 66 - "cpu-clock-ticks", 67 - "task-clock-ticks", 66 + "cpu-clock-msecs", 67 + "task-clock-msecs", 68 68 "page-faults", 69 69 "context-switches", 70 70 "CPU-migrations", ··· 96 96 97 97 char *event_name(int counter) 98 98 { 99 - __u64 config = attrs[counter].config; 99 + u64 config = attrs[counter].config; 100 100 int type = attrs[counter].type; 101 101 static char buf[32]; 102 102 ··· 112 112 return "unknown-hardware"; 113 113 114 114 case PERF_TYPE_HW_CACHE: { 115 - __u8 cache_type, cache_op, cache_result; 115 + u8 cache_type, cache_op, cache_result; 116 116 static char name[100]; 117 117 118 118 cache_type = (config >> 0) & 0xff; ··· 202 202 */ 203 203 static int parse_event_symbols(const char *str, struct perf_counter_attr *attr) 204 204 { 205 - __u64 config, id; 205 + u64 config, id; 206 206 int type; 207 207 unsigned int i; 208 208 const char *sep, *pstr;
+1 -1
tools/perf/util/string.c
··· 15 15 * While we find nice hex chars, build a long_val. 16 16 * Return number of chars processed. 17 17 */ 18 - int hex2u64(const char *ptr, __u64 *long_val) 18 + int hex2u64(const char *ptr, u64 *long_val) 19 19 { 20 20 const char *p = ptr; 21 21 *long_val = 0;
+2 -2
tools/perf/util/string.h
··· 1 1 #ifndef _PERF_STRING_H_ 2 2 #define _PERF_STRING_H_ 3 3 4 - #include <linux/types.h> 4 + #include "../types.h" 5 5 6 - int hex2u64(const char *ptr, __u64 *val); 6 + int hex2u64(const char *ptr, u64 *val); 7 7 8 8 #endif
+10 -10
tools/perf/util/symbol.c
··· 9 9 10 10 const char *sym_hist_filter; 11 11 12 - static struct symbol *symbol__new(__u64 start, __u64 len, 12 + static struct symbol *symbol__new(u64 start, u64 len, 13 13 const char *name, unsigned int priv_size, 14 - __u64 obj_start, int verbose) 14 + u64 obj_start, int verbose) 15 15 { 16 16 size_t namelen = strlen(name) + 1; 17 17 struct symbol *self = calloc(1, priv_size + sizeof(*self) + namelen); ··· 21 21 22 22 if (verbose >= 2) 23 23 printf("new symbol: %016Lx [%08lx]: %s, hist: %p, obj_start: %p\n", 24 - (__u64)start, (unsigned long)len, name, self->hist, (void *)(unsigned long)obj_start); 24 + (u64)start, (unsigned long)len, name, self->hist, (void *)(unsigned long)obj_start); 25 25 26 26 self->obj_start= obj_start; 27 27 self->hist = NULL; 28 28 self->hist_sum = 0; 29 29 30 30 if (sym_hist_filter && !strcmp(name, sym_hist_filter)) 31 - self->hist = calloc(sizeof(__u64), len); 31 + self->hist = calloc(sizeof(u64), len); 32 32 33 33 if (priv_size) { 34 34 memset(self, 0, priv_size); ··· 89 89 { 90 90 struct rb_node **p = &self->syms.rb_node; 91 91 struct rb_node *parent = NULL; 92 - const __u64 ip = sym->start; 92 + const u64 ip = sym->start; 93 93 struct symbol *s; 94 94 95 95 while (*p != NULL) { ··· 104 104 rb_insert_color(&sym->rb_node, &self->syms); 105 105 } 106 106 107 - struct symbol *dso__find_symbol(struct dso *self, __u64 ip) 107 + struct symbol *dso__find_symbol(struct dso *self, u64 ip) 108 108 { 109 109 struct rb_node *n; 110 110 ··· 151 151 goto out_failure; 152 152 153 153 while (!feof(file)) { 154 - __u64 start; 154 + u64 start; 155 155 struct symbol *sym; 156 156 int line_len, len; 157 157 char symbol_type; ··· 232 232 goto out_failure; 233 233 234 234 while (!feof(file)) { 235 - __u64 start, size; 235 + u64 start, size; 236 236 struct symbol *sym; 237 237 int line_len, len; 238 238 ··· 353 353 { 354 354 uint32_t nr_rel_entries, idx; 355 355 GElf_Sym sym; 356 - __u64 plt_offset; 356 + u64 plt_offset; 357 357 GElf_Shdr shdr_plt; 358 358 struct symbol *f; 359 359 GElf_Shdr shdr_rel_plt; ··· 523 523 524 524 elf_symtab__for_each_symbol(syms, nr_syms, index, sym) { 525 525 struct symbol *f; 526 - __u64 obj_start; 526 + u64 obj_start; 527 527 528 528 if (!elf_sym__is_function(&sym)) 529 529 continue;
+9 -7
tools/perf/util/symbol.h
··· 2 2 #define _PERF_SYMBOL_ 1 3 3 4 4 #include <linux/types.h> 5 + #include "../types.h" 5 6 #include "list.h" 6 7 #include "rbtree.h" 7 8 8 9 struct symbol { 9 10 struct rb_node rb_node; 10 - __u64 start; 11 - __u64 end; 12 - __u64 obj_start; 13 - __u64 hist_sum; 14 - __u64 *hist; 11 + u64 start; 12 + u64 end; 13 + u64 obj_start; 14 + u64 hist_sum; 15 + u64 *hist; 16 + void *priv; 15 17 char name[0]; 16 18 }; 17 19 ··· 21 19 struct list_head node; 22 20 struct rb_root syms; 23 21 unsigned int sym_priv_size; 24 - struct symbol *(*find_symbol)(struct dso *, __u64 ip); 22 + struct symbol *(*find_symbol)(struct dso *, u64 ip); 25 23 char name[0]; 26 24 }; 27 25 ··· 37 35 return ((void *)sym) - self->sym_priv_size; 38 36 } 39 37 40 - struct symbol *dso__find_symbol(struct dso *self, __u64 ip); 38 + struct symbol *dso__find_symbol(struct dso *self, u64 ip); 41 39 42 40 int dso__load_kernel(struct dso *self, const char *vmlinux, 43 41 symbol_filter_t filter, int verbose);
+8 -10
tools/perf/util/util.h
··· 100 100 #include <iconv.h> 101 101 #endif 102 102 103 - #ifndef NO_OPENSSL 104 - #include <openssl/ssl.h> 105 - #include <openssl/err.h> 106 - #endif 107 - 108 103 /* On most systems <limits.h> would have given us this, but 109 104 * not on some systems (e.g. GNU/Hurd). 110 105 */ ··· 327 332 #undef tolower 328 333 #undef toupper 329 334 extern unsigned char sane_ctype[256]; 330 - #define GIT_SPACE 0x01 331 - #define GIT_DIGIT 0x02 332 - #define GIT_ALPHA 0x04 333 - #define GIT_GLOB_SPECIAL 0x08 334 - #define GIT_REGEX_SPECIAL 0x10 335 + #define GIT_SPACE 0x01 336 + #define GIT_DIGIT 0x02 337 + #define GIT_ALPHA 0x04 338 + #define GIT_GLOB_SPECIAL 0x08 339 + #define GIT_REGEX_SPECIAL 0x10 340 + #define GIT_PRINT_EXTRA 0x20 341 + #define GIT_PRINT 0x3E 335 342 #define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0) 336 343 #define isascii(x) (((x) & ~0x7f) == 0) 337 344 #define isspace(x) sane_istest(x,GIT_SPACE) 338 345 #define isdigit(x) sane_istest(x,GIT_DIGIT) 339 346 #define isalpha(x) sane_istest(x,GIT_ALPHA) 340 347 #define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT) 348 + #define isprint(x) sane_istest(x,GIT_PRINT) 341 349 #define is_glob_special(x) sane_istest(x,GIT_GLOB_SPECIAL) 342 350 #define is_regex_special(x) sane_istest(x,GIT_GLOB_SPECIAL | GIT_REGEX_SPECIAL) 343 351 #define tolower(x) sane_case((unsigned char)(x), 0x20)