aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-03-18 13:38:34 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-03-18 13:38:34 -0400
commit619297855aa16646246ea4b1f6e05f1b2455c808 (patch)
treea07fe1b24c372f5eabf244555db41fdf574c1205
parente16b396ce314b2bcdfe6c173fe075bf8e3432368 (diff)
parent1ef1d1c2353967e2d61ecaddf76edfd058a778b4 (diff)
Merge branch 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (30 commits) trace, filters: Initialize the match variable in process_ops() properly trace, documentation: Fix branch profiling location in debugfs oprofile, s390: Cleanups oprofile, s390: Remove hwsampler_files.c and merge it into init.c perf: Fix tear-down of inherited group events perf: Reorder & optimize perf_event_context to remove alignment padding on 64 bit builds perf: Handle stopped state with tracepoints perf: Fix the software events state check perf, powerpc: Handle events that raise an exception without overflowing perf, x86: Use INTEL_*_CONSTRAINT() for all PEBS event constraints perf, x86: Clean up SandyBridge PEBS events perf lock: Fix sorting by wait_min perf tools: Version incorrect with some versions of grep perf evlist: New command to list the names of events present in a perf.data file perf script: Add support for H/W and S/W events perf script: Add support for dumping symbols perf script: Support custom field selection for output perf script: Move printing of 'common' data from print_event and rename perf tracing: Remove print_graph_cpu and print_graph_proc from trace-event-parse perf script: Change process_event prototype ...
-rw-r--r--arch/powerpc/include/asm/reg.h1
-rw-r--r--arch/powerpc/kernel/perf_event.c24
-rw-r--r--arch/s390/oprofile/Makefile2
-rw-r--r--arch/s390/oprofile/hwsampler.c1256
-rw-r--r--arch/s390/oprofile/hwsampler.h113
-rw-r--r--arch/s390/oprofile/init.c165
-rw-r--r--arch/x86/kernel/cpu/perf_event.c2
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_ds.c112
-rw-r--r--drivers/oprofile/cpu_buffer.c24
-rw-r--r--drivers/oprofile/timer_int.c4
-rw-r--r--include/linux/oprofile.h7
-rw-r--r--include/linux/perf_event.h2
-rw-r--r--kernel/perf_event.c17
-rw-r--r--kernel/trace/Kconfig4
-rw-r--r--kernel/trace/trace_events_filter.c2
-rw-r--r--tools/perf/Documentation/perf-evlist.txt26
-rw-r--r--tools/perf/Documentation/perf-script.txt22
-rw-r--r--tools/perf/Makefile1
-rw-r--r--tools/perf/builtin-evlist.c54
-rw-r--r--tools/perf/builtin-lock.c13
-rw-r--r--tools/perf/builtin-script.c300
-rw-r--r--tools/perf/builtin-stat.c8
-rw-r--r--tools/perf/builtin-top.c20
-rw-r--r--tools/perf/builtin.h1
-rw-r--r--tools/perf/command-list.txt1
-rw-r--r--tools/perf/perf.c1
-rwxr-xr-xtools/perf/util/PERF-VERSION-GEN8
-rw-r--r--tools/perf/util/annotate.c2
-rw-r--r--tools/perf/util/parse-events.c22
-rw-r--r--tools/perf/util/parse-events.h1
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c11
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c11
-rw-r--r--tools/perf/util/session.c61
-rw-r--r--tools/perf/util/session.h4
-rw-r--r--tools/perf/util/symbol.c64
-rw-r--r--tools/perf/util/symbol.h31
-rw-r--r--tools/perf/util/top.c6
-rw-r--r--tools/perf/util/top.h4
-rw-r--r--tools/perf/util/trace-event-parse.c110
-rw-r--r--tools/perf/util/trace-event-scripting.c9
-rw-r--r--tools/perf/util/trace-event.h10
41 files changed, 2240 insertions, 296 deletions
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 1bc6a12f3725..7e4abebe76c0 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -892,6 +892,7 @@
892#define PV_970 0x0039 892#define PV_970 0x0039
893#define PV_POWER5 0x003A 893#define PV_POWER5 0x003A
894#define PV_POWER5p 0x003B 894#define PV_POWER5p 0x003B
895#define PV_POWER7 0x003F
895#define PV_970FX 0x003C 896#define PV_970FX 0x003C
896#define PV_630 0x0040 897#define PV_630 0x0040
897#define PV_630p 0x0041 898#define PV_630p 0x0041
diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c
index ab6f6beadb57..97e0ae414940 100644
--- a/arch/powerpc/kernel/perf_event.c
+++ b/arch/powerpc/kernel/perf_event.c
@@ -1269,6 +1269,28 @@ unsigned long perf_instruction_pointer(struct pt_regs *regs)
1269 return ip; 1269 return ip;
1270} 1270}
1271 1271
1272static bool pmc_overflow(unsigned long val)
1273{
1274 if ((int)val < 0)
1275 return true;
1276
1277 /*
1278 * Events on POWER7 can roll back if a speculative event doesn't
1279 * eventually complete. Unfortunately in some rare cases they will
1280 * raise a performance monitor exception. We need to catch this to
1281 * ensure we reset the PMC. In all cases the PMC will be 256 or less
1282 * cycles from overflow.
1283 *
1284 * We only do this if the first pass fails to find any overflowing
1285 * PMCs because a user might set a period of less than 256 and we
1286 * don't want to mistakenly reset them.
1287 */
1288 if (__is_processor(PV_POWER7) && ((0x80000000 - val) <= 256))
1289 return true;
1290
1291 return false;
1292}
1293
1272/* 1294/*
1273 * Performance monitor interrupt stuff 1295 * Performance monitor interrupt stuff
1274 */ 1296 */
@@ -1316,7 +1338,7 @@ static void perf_event_interrupt(struct pt_regs *regs)
1316 if (is_limited_pmc(i + 1)) 1338 if (is_limited_pmc(i + 1))
1317 continue; 1339 continue;
1318 val = read_pmc(i + 1); 1340 val = read_pmc(i + 1);
1319 if ((int)val < 0) 1341 if (pmc_overflow(val))
1320 write_pmc(i + 1, 0); 1342 write_pmc(i + 1, 0);
1321 } 1343 }
1322 } 1344 }
diff --git a/arch/s390/oprofile/Makefile b/arch/s390/oprofile/Makefile
index 537b2d840e69..d698cddcfbdd 100644
--- a/arch/s390/oprofile/Makefile
+++ b/arch/s390/oprofile/Makefile
@@ -6,4 +6,4 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
6 oprofilefs.o oprofile_stats.o \ 6 oprofilefs.o oprofile_stats.o \
7 timer_int.o ) 7 timer_int.o )
8 8
9oprofile-y := $(DRIVER_OBJS) init.o backtrace.o 9oprofile-y := $(DRIVER_OBJS) init.o backtrace.o hwsampler.o
diff --git a/arch/s390/oprofile/hwsampler.c b/arch/s390/oprofile/hwsampler.c
new file mode 100644
index 000000000000..3d48f4db246d
--- /dev/null
+++ b/arch/s390/oprofile/hwsampler.c
@@ -0,0 +1,1256 @@
1/**
2 * arch/s390/oprofile/hwsampler.c
3 *
4 * Copyright IBM Corp. 2010
5 * Author: Heinz Graalfs <graalfs@de.ibm.com>
6 */
7
8#include <linux/kernel.h>
9#include <linux/module.h>
10#include <linux/smp.h>
11#include <linux/errno.h>
12#include <linux/workqueue.h>
13#include <linux/interrupt.h>
14#include <linux/notifier.h>
15#include <linux/cpu.h>
16#include <linux/semaphore.h>
17#include <linux/oom.h>
18#include <linux/oprofile.h>
19
20#include <asm/lowcore.h>
21#include <asm/s390_ext.h>
22
23#include "hwsampler.h"
24
25#define MAX_NUM_SDB 511
26#define MIN_NUM_SDB 1
27
28#define ALERT_REQ_MASK 0x4000000000000000ul
29#define BUFFER_FULL_MASK 0x8000000000000000ul
30
31#define EI_IEA (1 << 31) /* invalid entry address */
32#define EI_ISE (1 << 30) /* incorrect SDBT entry */
33#define EI_PRA (1 << 29) /* program request alert */
34#define EI_SACA (1 << 23) /* sampler authorization change alert */
35#define EI_LSDA (1 << 22) /* loss of sample data alert */
36
37DECLARE_PER_CPU(struct hws_cpu_buffer, sampler_cpu_buffer);
38
39struct hws_execute_parms {
40 void *buffer;
41 signed int rc;
42};
43
44DEFINE_PER_CPU(struct hws_cpu_buffer, sampler_cpu_buffer);
45EXPORT_PER_CPU_SYMBOL(sampler_cpu_buffer);
46
47static DEFINE_MUTEX(hws_sem);
48static DEFINE_MUTEX(hws_sem_oom);
49
50static unsigned char hws_flush_all;
51static unsigned int hws_oom;
52static struct workqueue_struct *hws_wq;
53
54static unsigned int hws_state;
55enum {
56 HWS_INIT = 1,
57 HWS_DEALLOCATED,
58 HWS_STOPPED,
59 HWS_STARTED,
60 HWS_STOPPING };
61
62/* set to 1 if called by kernel during memory allocation */
63static unsigned char oom_killer_was_active;
64/* size of SDBT and SDB as of allocate API */
65static unsigned long num_sdbt = 100;
66static unsigned long num_sdb = 511;
67/* sampling interval (machine cycles) */
68static unsigned long interval;
69
70static unsigned long min_sampler_rate;
71static unsigned long max_sampler_rate;
72
73static int ssctl(void *buffer)
74{
75 int cc;
76
77 /* set in order to detect a program check */
78 cc = 1;
79
80 asm volatile(
81 "0: .insn s,0xB2870000,0(%1)\n"
82 "1: ipm %0\n"
83 " srl %0,28\n"
84 "2:\n"
85 EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
86 : "+d" (cc), "+a" (buffer)
87 : "m" (*((struct hws_ssctl_request_block *)buffer))
88 : "cc", "memory");
89
90 return cc ? -EINVAL : 0 ;
91}
92
93static int qsi(void *buffer)
94{
95 int cc;
96 cc = 1;
97
98 asm volatile(
99 "0: .insn s,0xB2860000,0(%1)\n"
100 "1: lhi %0,0\n"
101 "2:\n"
102 EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
103 : "=d" (cc), "+a" (buffer)
104 : "m" (*((struct hws_qsi_info_block *)buffer))
105 : "cc", "memory");
106
107 return cc ? -EINVAL : 0;
108}
109
110static void execute_qsi(void *parms)
111{
112 struct hws_execute_parms *ep = parms;
113
114 ep->rc = qsi(ep->buffer);
115}
116
117static void execute_ssctl(void *parms)
118{
119 struct hws_execute_parms *ep = parms;
120
121 ep->rc = ssctl(ep->buffer);
122}
123
124static int smp_ctl_ssctl_stop(int cpu)
125{
126 int rc;
127 struct hws_execute_parms ep;
128 struct hws_cpu_buffer *cb;
129
130 cb = &per_cpu(sampler_cpu_buffer, cpu);
131
132 cb->ssctl.es = 0;
133 cb->ssctl.cs = 0;
134
135 ep.buffer = &cb->ssctl;
136 smp_call_function_single(cpu, execute_ssctl, &ep, 1);
137 rc = ep.rc;
138 if (rc) {
139 printk(KERN_ERR "hwsampler: CPU %d CPUMF SSCTL failed.\n", cpu);
140 dump_stack();
141 }
142
143 ep.buffer = &cb->qsi;
144 smp_call_function_single(cpu, execute_qsi, &ep, 1);
145
146 if (cb->qsi.es || cb->qsi.cs) {
147 printk(KERN_EMERG "CPUMF sampling did not stop properly.\n");
148 dump_stack();
149 }
150
151 return rc;
152}
153
154static int smp_ctl_ssctl_deactivate(int cpu)
155{
156 int rc;
157 struct hws_execute_parms ep;
158 struct hws_cpu_buffer *cb;
159
160 cb = &per_cpu(sampler_cpu_buffer, cpu);
161
162 cb->ssctl.es = 1;
163 cb->ssctl.cs = 0;
164
165 ep.buffer = &cb->ssctl;
166 smp_call_function_single(cpu, execute_ssctl, &ep, 1);
167 rc = ep.rc;
168 if (rc)
169 printk(KERN_ERR "hwsampler: CPU %d CPUMF SSCTL failed.\n", cpu);
170
171 ep.buffer = &cb->qsi;
172 smp_call_function_single(cpu, execute_qsi, &ep, 1);
173
174 if (cb->qsi.cs)
175 printk(KERN_EMERG "CPUMF sampling was not set inactive.\n");
176
177 return rc;
178}
179
180static int smp_ctl_ssctl_enable_activate(int cpu, unsigned long interval)
181{
182 int rc;
183 struct hws_execute_parms ep;
184 struct hws_cpu_buffer *cb;
185
186 cb = &per_cpu(sampler_cpu_buffer, cpu);
187
188 cb->ssctl.h = 1;
189 cb->ssctl.tear = cb->first_sdbt;
190 cb->ssctl.dear = *(unsigned long *) cb->first_sdbt;
191 cb->ssctl.interval = interval;
192 cb->ssctl.es = 1;
193 cb->ssctl.cs = 1;
194
195 ep.buffer = &cb->ssctl;
196 smp_call_function_single(cpu, execute_ssctl, &ep, 1);
197 rc = ep.rc;
198 if (rc)
199 printk(KERN_ERR "hwsampler: CPU %d CPUMF SSCTL failed.\n", cpu);
200
201 ep.buffer = &cb->qsi;
202 smp_call_function_single(cpu, execute_qsi, &ep, 1);
203 if (ep.rc)
204 printk(KERN_ERR "hwsampler: CPU %d CPUMF QSI failed.\n", cpu);
205
206 return rc;
207}
208
209static int smp_ctl_qsi(int cpu)
210{
211 struct hws_execute_parms ep;
212 struct hws_cpu_buffer *cb;
213
214 cb = &per_cpu(sampler_cpu_buffer, cpu);
215
216 ep.buffer = &cb->qsi;
217 smp_call_function_single(cpu, execute_qsi, &ep, 1);
218
219 return ep.rc;
220}
221
222static inline unsigned long *trailer_entry_ptr(unsigned long v)
223{
224 void *ret;
225
226 ret = (void *)v;
227 ret += PAGE_SIZE;
228 ret -= sizeof(struct hws_trailer_entry);
229
230 return (unsigned long *) ret;
231}
232
233/* prototypes for external interrupt handler and worker */
234static void hws_ext_handler(unsigned int ext_int_code,
235 unsigned int param32, unsigned long param64);
236
237static void worker(struct work_struct *work);
238
239static void add_samples_to_oprofile(unsigned cpu, unsigned long *,
240 unsigned long *dear);
241
242static void init_all_cpu_buffers(void)
243{
244 int cpu;
245 struct hws_cpu_buffer *cb;
246
247 for_each_online_cpu(cpu) {
248 cb = &per_cpu(sampler_cpu_buffer, cpu);
249 memset(cb, 0, sizeof(struct hws_cpu_buffer));
250 }
251}
252
253static int is_link_entry(unsigned long *s)
254{
255 return *s & 0x1ul ? 1 : 0;
256}
257
258static unsigned long *get_next_sdbt(unsigned long *s)
259{
260 return (unsigned long *) (*s & ~0x1ul);
261}
262
263static int prepare_cpu_buffers(void)
264{
265 int cpu;
266 int rc;
267 struct hws_cpu_buffer *cb;
268
269 rc = 0;
270 for_each_online_cpu(cpu) {
271 cb = &per_cpu(sampler_cpu_buffer, cpu);
272 atomic_set(&cb->ext_params, 0);
273 cb->worker_entry = 0;
274 cb->sample_overflow = 0;
275 cb->req_alert = 0;
276 cb->incorrect_sdbt_entry = 0;
277 cb->invalid_entry_address = 0;
278 cb->loss_of_sample_data = 0;
279 cb->sample_auth_change_alert = 0;
280 cb->finish = 0;
281 cb->oom = 0;
282 cb->stop_mode = 0;
283 }
284
285 return rc;
286}
287
288/*
289 * allocate_sdbt() - allocate sampler memory
290 * @cpu: the cpu for which sampler memory is allocated
291 *
292 * A 4K page is allocated for each requested SDBT.
293 * A maximum of 511 4K pages are allocated for the SDBs in each of the SDBTs.
294 * Set ALERT_REQ mask in each SDBs trailer.
295 * Returns zero if successful, <0 otherwise.
296 */
297static int allocate_sdbt(int cpu)
298{
299 int j, k, rc;
300 unsigned long *sdbt;
301 unsigned long sdb;
302 unsigned long *tail;
303 unsigned long *trailer;
304 struct hws_cpu_buffer *cb;
305
306 cb = &per_cpu(sampler_cpu_buffer, cpu);
307
308 if (cb->first_sdbt)
309 return -EINVAL;
310
311 sdbt = NULL;
312 tail = sdbt;
313
314 for (j = 0; j < num_sdbt; j++) {
315 sdbt = (unsigned long *)get_zeroed_page(GFP_KERNEL);
316
317 mutex_lock(&hws_sem_oom);
318 /* OOM killer might have been activated */
319 barrier();
320 if (oom_killer_was_active || !sdbt) {
321 if (sdbt)
322 free_page((unsigned long)sdbt);
323
324 goto allocate_sdbt_error;
325 }
326 if (cb->first_sdbt == 0)
327 cb->first_sdbt = (unsigned long)sdbt;
328
329 /* link current page to tail of chain */
330 if (tail)
331 *tail = (unsigned long)(void *)sdbt + 1;
332
333 mutex_unlock(&hws_sem_oom);
334
335 for (k = 0; k < num_sdb; k++) {
336 /* get and set SDB page */
337 sdb = get_zeroed_page(GFP_KERNEL);
338
339 mutex_lock(&hws_sem_oom);
340 /* OOM killer might have been activated */
341 barrier();
342 if (oom_killer_was_active || !sdb) {
343 if (sdb)
344 free_page(sdb);
345
346 goto allocate_sdbt_error;
347 }
348 *sdbt = sdb;
349 trailer = trailer_entry_ptr(*sdbt);
350 *trailer = ALERT_REQ_MASK;
351 sdbt++;
352 mutex_unlock(&hws_sem_oom);
353 }
354 tail = sdbt;
355 }
356 mutex_lock(&hws_sem_oom);
357 if (oom_killer_was_active)
358 goto allocate_sdbt_error;
359
360 rc = 0;
361 if (tail)
362 *tail = (unsigned long)
363 ((void *)cb->first_sdbt) + 1;
364
365allocate_sdbt_exit:
366 mutex_unlock(&hws_sem_oom);
367 return rc;
368
369allocate_sdbt_error:
370 rc = -ENOMEM;
371 goto allocate_sdbt_exit;
372}
373
374/*
375 * deallocate_sdbt() - deallocate all sampler memory
376 *
377 * For each online CPU all SDBT trees are deallocated.
378 * Returns the number of freed pages.
379 */
380static int deallocate_sdbt(void)
381{
382 int cpu;
383 int counter;
384
385 counter = 0;
386
387 for_each_online_cpu(cpu) {
388 unsigned long start;
389 unsigned long sdbt;
390 unsigned long *curr;
391 struct hws_cpu_buffer *cb;
392
393 cb = &per_cpu(sampler_cpu_buffer, cpu);
394
395 if (!cb->first_sdbt)
396 continue;
397
398 sdbt = cb->first_sdbt;
399 curr = (unsigned long *) sdbt;
400 start = sdbt;
401
402 /* we'll free the SDBT after all SDBs are processed... */
403 while (1) {
404 if (!*curr || !sdbt)
405 break;
406
407 /* watch for link entry reset if found */
408 if (is_link_entry(curr)) {
409 curr = get_next_sdbt(curr);
410 if (sdbt)
411 free_page(sdbt);
412
413 /* we are done if we reach the start */
414 if ((unsigned long) curr == start)
415 break;
416 else
417 sdbt = (unsigned long) curr;
418 } else {
419 /* process SDB pointer */
420 if (*curr) {
421 free_page(*curr);
422 curr++;
423 }
424 }
425 counter++;
426 }
427 cb->first_sdbt = 0;
428 }
429 return counter;
430}
431
432static int start_sampling(int cpu)
433{
434 int rc;
435 struct hws_cpu_buffer *cb;
436
437 cb = &per_cpu(sampler_cpu_buffer, cpu);
438 rc = smp_ctl_ssctl_enable_activate(cpu, interval);
439 if (rc) {
440 printk(KERN_INFO "hwsampler: CPU %d ssctl failed.\n", cpu);
441 goto start_exit;
442 }
443
444 rc = -EINVAL;
445 if (!cb->qsi.es) {
446 printk(KERN_INFO "hwsampler: CPU %d ssctl not enabled.\n", cpu);
447 goto start_exit;
448 }
449
450 if (!cb->qsi.cs) {
451 printk(KERN_INFO "hwsampler: CPU %d ssctl not active.\n", cpu);
452 goto start_exit;
453 }
454
455 printk(KERN_INFO
456 "hwsampler: CPU %d, CPUMF Sampling started, interval %lu.\n",
457 cpu, interval);
458
459 rc = 0;
460
461start_exit:
462 return rc;
463}
464
465static int stop_sampling(int cpu)
466{
467 unsigned long v;
468 int rc;
469 struct hws_cpu_buffer *cb;
470
471 rc = smp_ctl_qsi(cpu);
472 WARN_ON(rc);
473
474 cb = &per_cpu(sampler_cpu_buffer, cpu);
475 if (!rc && !cb->qsi.es)
476 printk(KERN_INFO "hwsampler: CPU %d, already stopped.\n", cpu);
477
478 rc = smp_ctl_ssctl_stop(cpu);
479 if (rc) {
480 printk(KERN_INFO "hwsampler: CPU %d, ssctl stop error %d.\n",
481 cpu, rc);
482 goto stop_exit;
483 }
484
485 printk(KERN_INFO "hwsampler: CPU %d, CPUMF Sampling stopped.\n", cpu);
486
487stop_exit:
488 v = cb->req_alert;
489 if (v)
490 printk(KERN_ERR "hwsampler: CPU %d CPUMF Request alert,"
491 " count=%lu.\n", cpu, v);
492
493 v = cb->loss_of_sample_data;
494 if (v)
495 printk(KERN_ERR "hwsampler: CPU %d CPUMF Loss of sample data,"
496 " count=%lu.\n", cpu, v);
497
498 v = cb->invalid_entry_address;
499 if (v)
500 printk(KERN_ERR "hwsampler: CPU %d CPUMF Invalid entry address,"
501 " count=%lu.\n", cpu, v);
502
503 v = cb->incorrect_sdbt_entry;
504 if (v)
505 printk(KERN_ERR
506 "hwsampler: CPU %d CPUMF Incorrect SDBT address,"
507 " count=%lu.\n", cpu, v);
508
509 v = cb->sample_auth_change_alert;
510 if (v)
511 printk(KERN_ERR
512 "hwsampler: CPU %d CPUMF Sample authorization change,"
513 " count=%lu.\n", cpu, v);
514
515 return rc;
516}
517
518static int check_hardware_prerequisites(void)
519{
520 unsigned long long facility_bits[2];
521
522 memcpy(facility_bits, S390_lowcore.stfle_fac_list, 32);
523 if (!(facility_bits[1] & (1ULL << 59)))
524 return -EOPNOTSUPP;
525
526 return 0;
527}
528/*
529 * hws_oom_callback() - the OOM callback function
530 *
531 * In case the callback is invoked during memory allocation for the
532 * hw sampler, all obtained memory is deallocated and a flag is set
533 * so main sampler memory allocation can exit with a failure code.
534 * In case the callback is invoked during sampling the hw sampler
535 * is deactivated for all CPUs.
536 */
537static int hws_oom_callback(struct notifier_block *nfb,
538 unsigned long dummy, void *parm)
539{
540 unsigned long *freed;
541 int cpu;
542 struct hws_cpu_buffer *cb;
543
544 freed = parm;
545
546 mutex_lock(&hws_sem_oom);
547
548 if (hws_state == HWS_DEALLOCATED) {
549 /* during memory allocation */
550 if (oom_killer_was_active == 0) {
551 oom_killer_was_active = 1;
552 *freed += deallocate_sdbt();
553 }
554 } else {
555 int i;
556 cpu = get_cpu();
557 cb = &per_cpu(sampler_cpu_buffer, cpu);
558
559 if (!cb->oom) {
560 for_each_online_cpu(i) {
561 smp_ctl_ssctl_deactivate(i);
562 cb->oom = 1;
563 }
564 cb->finish = 1;
565
566 printk(KERN_INFO
567 "hwsampler: CPU %d, OOM notify during CPUMF Sampling.\n",
568 cpu);
569 }
570 }
571
572 mutex_unlock(&hws_sem_oom);
573
574 return NOTIFY_OK;
575}
576
577static struct notifier_block hws_oom_notifier = {
578 .notifier_call = hws_oom_callback
579};
580
581static int hws_cpu_callback(struct notifier_block *nfb,
582 unsigned long action, void *hcpu)
583{
584 /* We do not have sampler space available for all possible CPUs.
585 All CPUs should be online when hw sampling is activated. */
586 return NOTIFY_BAD;
587}
588
589static struct notifier_block hws_cpu_notifier = {
590 .notifier_call = hws_cpu_callback
591};
592
593/**
594 * hwsampler_deactivate() - set hardware sampling temporarily inactive
595 * @cpu: specifies the CPU to be set inactive.
596 *
597 * Returns 0 on success, !0 on failure.
598 */
599int hwsampler_deactivate(unsigned int cpu)
600{
601 /*
602 * Deactivate hw sampling temporarily and flush the buffer
603 * by pushing all the pending samples to oprofile buffer.
604 *
605 * This function can be called under one of the following conditions:
606 * Memory unmap, task is exiting.
607 */
608 int rc;
609 struct hws_cpu_buffer *cb;
610
611 rc = 0;
612 mutex_lock(&hws_sem);
613
614 cb = &per_cpu(sampler_cpu_buffer, cpu);
615 if (hws_state == HWS_STARTED) {
616 rc = smp_ctl_qsi(cpu);
617 WARN_ON(rc);
618 if (cb->qsi.cs) {
619 rc = smp_ctl_ssctl_deactivate(cpu);
620 if (rc) {
621 printk(KERN_INFO
622 "hwsampler: CPU %d, CPUMF Deactivation failed.\n", cpu);
623 cb->finish = 1;
624 hws_state = HWS_STOPPING;
625 } else {
626 hws_flush_all = 1;
627 /* Add work to queue to read pending samples.*/
628 queue_work_on(cpu, hws_wq, &cb->worker);
629 }
630 }
631 }
632 mutex_unlock(&hws_sem);
633
634 if (hws_wq)
635 flush_workqueue(hws_wq);
636
637 return rc;
638}
639
640/**
641 * hwsampler_activate() - activate/resume hardware sampling which was deactivated
642 * @cpu: specifies the CPU to be set active.
643 *
644 * Returns 0 on success, !0 on failure.
645 */
646int hwsampler_activate(unsigned int cpu)
647{
648 /*
649 * Re-activate hw sampling. This should be called in pair with
650 * hwsampler_deactivate().
651 */
652 int rc;
653 struct hws_cpu_buffer *cb;
654
655 rc = 0;
656 mutex_lock(&hws_sem);
657
658 cb = &per_cpu(sampler_cpu_buffer, cpu);
659 if (hws_state == HWS_STARTED) {
660 rc = smp_ctl_qsi(cpu);
661 WARN_ON(rc);
662 if (!cb->qsi.cs) {
663 hws_flush_all = 0;
664 rc = smp_ctl_ssctl_enable_activate(cpu, interval);
665 if (rc) {
666 printk(KERN_ERR
667 "CPU %d, CPUMF activate sampling failed.\n",
668 cpu);
669 }
670 }
671 }
672
673 mutex_unlock(&hws_sem);
674
675 return rc;
676}
677
678static void hws_ext_handler(unsigned int ext_int_code,
679 unsigned int param32, unsigned long param64)
680{
681 int cpu;
682 struct hws_cpu_buffer *cb;
683
684 cpu = smp_processor_id();
685 cb = &per_cpu(sampler_cpu_buffer, cpu);
686
687 atomic_xchg(
688 &cb->ext_params,
689 atomic_read(&cb->ext_params)
690 | S390_lowcore.ext_params);
691
692 if (hws_wq)
693 queue_work(hws_wq, &cb->worker);
694}
695
696static int check_qsi_on_setup(void)
697{
698 int rc;
699 unsigned int cpu;
700 struct hws_cpu_buffer *cb;
701
702 for_each_online_cpu(cpu) {
703 cb = &per_cpu(sampler_cpu_buffer, cpu);
704 rc = smp_ctl_qsi(cpu);
705 WARN_ON(rc);
706 if (rc)
707 return -EOPNOTSUPP;
708
709 if (!cb->qsi.as) {
710 printk(KERN_INFO "hwsampler: CPUMF sampling is not authorized.\n");
711 return -EINVAL;
712 }
713
714 if (cb->qsi.es) {
715 printk(KERN_WARNING "hwsampler: CPUMF is still enabled.\n");
716 rc = smp_ctl_ssctl_stop(cpu);
717 if (rc)
718 return -EINVAL;
719
720 printk(KERN_INFO
721 "CPU %d, CPUMF Sampling stopped now.\n", cpu);
722 }
723 }
724 return 0;
725}
726
727static int check_qsi_on_start(void)
728{
729 unsigned int cpu;
730 int rc;
731 struct hws_cpu_buffer *cb;
732
733 for_each_online_cpu(cpu) {
734 cb = &per_cpu(sampler_cpu_buffer, cpu);
735 rc = smp_ctl_qsi(cpu);
736 WARN_ON(rc);
737
738 if (!cb->qsi.as)
739 return -EINVAL;
740
741 if (cb->qsi.es)
742 return -EINVAL;
743
744 if (cb->qsi.cs)
745 return -EINVAL;
746 }
747 return 0;
748}
749
750static void worker_on_start(unsigned int cpu)
751{
752 struct hws_cpu_buffer *cb;
753
754 cb = &per_cpu(sampler_cpu_buffer, cpu);
755 cb->worker_entry = cb->first_sdbt;
756}
757
758static int worker_check_error(unsigned int cpu, int ext_params)
759{
760 int rc;
761 unsigned long *sdbt;
762 struct hws_cpu_buffer *cb;
763
764 rc = 0;
765 cb = &per_cpu(sampler_cpu_buffer, cpu);
766 sdbt = (unsigned long *) cb->worker_entry;
767
768 if (!sdbt || !*sdbt)
769 return -EINVAL;
770
771 if (ext_params & EI_IEA)
772 cb->req_alert++;
773
774 if (ext_params & EI_LSDA)
775 cb->loss_of_sample_data++;
776
777 if (ext_params & EI_IEA) {
778 cb->invalid_entry_address++;
779 rc = -EINVAL;
780 }
781
782 if (ext_params & EI_ISE) {
783 cb->incorrect_sdbt_entry++;
784 rc = -EINVAL;
785 }
786
787 if (ext_params & EI_SACA) {
788 cb->sample_auth_change_alert++;
789 rc = -EINVAL;
790 }
791
792 return rc;
793}
794
795static void worker_on_finish(unsigned int cpu)
796{
797 int rc, i;
798 struct hws_cpu_buffer *cb;
799
800 cb = &per_cpu(sampler_cpu_buffer, cpu);
801
802 if (cb->finish) {
803 rc = smp_ctl_qsi(cpu);
804 WARN_ON(rc);
805 if (cb->qsi.es) {
806 printk(KERN_INFO
807 "hwsampler: CPU %d, CPUMF Stop/Deactivate sampling.\n",
808 cpu);
809 rc = smp_ctl_ssctl_stop(cpu);
810 if (rc)
811 printk(KERN_INFO
812 "hwsampler: CPU %d, CPUMF Deactivation failed.\n",
813 cpu);
814
815 for_each_online_cpu(i) {
816 if (i == cpu)
817 continue;
818 if (!cb->finish) {
819 cb->finish = 1;
820 queue_work_on(i, hws_wq,
821 &cb->worker);
822 }
823 }
824 }
825 }
826}
827
828static void worker_on_interrupt(unsigned int cpu)
829{
830 unsigned long *sdbt;
831 unsigned char done;
832 struct hws_cpu_buffer *cb;
833
834 cb = &per_cpu(sampler_cpu_buffer, cpu);
835
836 sdbt = (unsigned long *) cb->worker_entry;
837
838 done = 0;
839 /* do not proceed if stop was entered,
840 * forget the buffers not yet processed */
841 while (!done && !cb->stop_mode) {
842 unsigned long *trailer;
843 struct hws_trailer_entry *te;
844 unsigned long *dear = 0;
845
846 trailer = trailer_entry_ptr(*sdbt);
847 /* leave loop if no more work to do */
848 if (!(*trailer & BUFFER_FULL_MASK)) {
849 done = 1;
850 if (!hws_flush_all)
851 continue;
852 }
853
854 te = (struct hws_trailer_entry *)trailer;
855 cb->sample_overflow += te->overflow;
856
857 add_samples_to_oprofile(cpu, sdbt, dear);
858
859 /* reset trailer */
860 xchg((unsigned char *) te, 0x40);
861
862 /* advance to next sdb slot in current sdbt */
863 sdbt++;
864 /* in case link bit is set use address w/o link bit */
865 if (is_link_entry(sdbt))
866 sdbt = get_next_sdbt(sdbt);
867
868 cb->worker_entry = (unsigned long)sdbt;
869 }
870}
871
872static void add_samples_to_oprofile(unsigned int cpu, unsigned long *sdbt,
873 unsigned long *dear)
874{
875 struct hws_data_entry *sample_data_ptr;
876 unsigned long *trailer;
877
878 trailer = trailer_entry_ptr(*sdbt);
879 if (dear) {
880 if (dear > trailer)
881 return;
882 trailer = dear;
883 }
884
885 sample_data_ptr = (struct hws_data_entry *)(*sdbt);
886
887 while ((unsigned long *)sample_data_ptr < trailer) {
888 struct pt_regs *regs = NULL;
889 struct task_struct *tsk = NULL;
890
891 /*
892 * Check sampling mode, 1 indicates basic (=customer) sampling
893 * mode.
894 */
895 if (sample_data_ptr->def != 1) {
896 /* sample slot is not yet written */
897 break;
898 } else {
899 /* make sure we don't use it twice,
900 * the next time the sampler will set it again */
901 sample_data_ptr->def = 0;
902 }
903
904 /* Get pt_regs. */
905 if (sample_data_ptr->P == 1) {
906 /* userspace sample */
907 unsigned int pid = sample_data_ptr->prim_asn;
908 rcu_read_lock();
909 tsk = pid_task(find_vpid(pid), PIDTYPE_PID);
910 if (tsk)
911 regs = task_pt_regs(tsk);
912 rcu_read_unlock();
913 } else {
914 /* kernelspace sample */
915 regs = task_pt_regs(current);
916 }
917
918 mutex_lock(&hws_sem);
919 oprofile_add_ext_hw_sample(sample_data_ptr->ia, regs, 0,
920 !sample_data_ptr->P, tsk);
921 mutex_unlock(&hws_sem);
922
923 sample_data_ptr++;
924 }
925}
926
927static void worker(struct work_struct *work)
928{
929 unsigned int cpu;
930 int ext_params;
931 struct hws_cpu_buffer *cb;
932
933 cb = container_of(work, struct hws_cpu_buffer, worker);
934 cpu = smp_processor_id();
935 ext_params = atomic_xchg(&cb->ext_params, 0);
936
937 if (!cb->worker_entry)
938 worker_on_start(cpu);
939
940 if (worker_check_error(cpu, ext_params))
941 return;
942
943 if (!cb->finish)
944 worker_on_interrupt(cpu);
945
946 if (cb->finish)
947 worker_on_finish(cpu);
948}
949
950/**
951 * hwsampler_allocate() - allocate memory for the hardware sampler
952 * @sdbt: number of SDBTs per online CPU (must be > 0)
953 * @sdb: number of SDBs per SDBT (minimum 1, maximum 511)
954 *
955 * Returns 0 on success, !0 on failure.
956 */
957int hwsampler_allocate(unsigned long sdbt, unsigned long sdb)
958{
959 int cpu, rc;
960 mutex_lock(&hws_sem);
961
962 rc = -EINVAL;
963 if (hws_state != HWS_DEALLOCATED)
964 goto allocate_exit;
965
966 if (sdbt < 1)
967 goto allocate_exit;
968
969 if (sdb > MAX_NUM_SDB || sdb < MIN_NUM_SDB)
970 goto allocate_exit;
971
972 num_sdbt = sdbt;
973 num_sdb = sdb;
974
975 oom_killer_was_active = 0;
976 register_oom_notifier(&hws_oom_notifier);
977
978 for_each_online_cpu(cpu) {
979 if (allocate_sdbt(cpu)) {
980 unregister_oom_notifier(&hws_oom_notifier);
981 goto allocate_error;
982 }
983 }
984 unregister_oom_notifier(&hws_oom_notifier);
985 if (oom_killer_was_active)
986 goto allocate_error;
987
988 hws_state = HWS_STOPPED;
989 rc = 0;
990
991allocate_exit:
992 mutex_unlock(&hws_sem);
993 return rc;
994
995allocate_error:
996 rc = -ENOMEM;
997 printk(KERN_ERR "hwsampler: CPUMF Memory allocation failed.\n");
998 goto allocate_exit;
999}
1000
1001/**
1002 * hwsampler_deallocate() - deallocate hardware sampler memory
1003 *
1004 * Returns 0 on success, !0 on failure.
1005 */
1006int hwsampler_deallocate()
1007{
1008 int rc;
1009
1010 mutex_lock(&hws_sem);
1011
1012 rc = -EINVAL;
1013 if (hws_state != HWS_STOPPED)
1014 goto deallocate_exit;
1015
1016 smp_ctl_clear_bit(0, 5); /* set bit 58 CR0 off */
1017 deallocate_sdbt();
1018
1019 hws_state = HWS_DEALLOCATED;
1020 rc = 0;
1021
1022deallocate_exit:
1023 mutex_unlock(&hws_sem);
1024
1025 return rc;
1026}
1027
1028long hwsampler_query_min_interval(void)
1029{
1030 if (min_sampler_rate)
1031 return min_sampler_rate;
1032 else
1033 return -EINVAL;
1034}
1035
1036long hwsampler_query_max_interval(void)
1037{
1038 if (max_sampler_rate)
1039 return max_sampler_rate;
1040 else
1041 return -EINVAL;
1042}
1043
1044unsigned long hwsampler_get_sample_overflow_count(unsigned int cpu)
1045{
1046 struct hws_cpu_buffer *cb;
1047
1048 cb = &per_cpu(sampler_cpu_buffer, cpu);
1049
1050 return cb->sample_overflow;
1051}
1052
1053int hwsampler_setup()
1054{
1055 int rc;
1056 int cpu;
1057 struct hws_cpu_buffer *cb;
1058
1059 mutex_lock(&hws_sem);
1060
1061 rc = -EINVAL;
1062 if (hws_state)
1063 goto setup_exit;
1064
1065 hws_state = HWS_INIT;
1066
1067 init_all_cpu_buffers();
1068
1069 rc = check_hardware_prerequisites();
1070 if (rc)
1071 goto setup_exit;
1072
1073 rc = check_qsi_on_setup();
1074 if (rc)
1075 goto setup_exit;
1076
1077 rc = -EINVAL;
1078 hws_wq = create_workqueue("hwsampler");
1079 if (!hws_wq)
1080 goto setup_exit;
1081
1082 register_cpu_notifier(&hws_cpu_notifier);
1083
1084 for_each_online_cpu(cpu) {
1085 cb = &per_cpu(sampler_cpu_buffer, cpu);
1086 INIT_WORK(&cb->worker, worker);
1087 rc = smp_ctl_qsi(cpu);
1088 WARN_ON(rc);
1089 if (min_sampler_rate != cb->qsi.min_sampl_rate) {
1090 if (min_sampler_rate) {
1091 printk(KERN_WARNING
1092 "hwsampler: different min sampler rate values.\n");
1093 if (min_sampler_rate < cb->qsi.min_sampl_rate)
1094 min_sampler_rate =
1095 cb->qsi.min_sampl_rate;
1096 } else
1097 min_sampler_rate = cb->qsi.min_sampl_rate;
1098 }
1099 if (max_sampler_rate != cb->qsi.max_sampl_rate) {
1100 if (max_sampler_rate) {
1101 printk(KERN_WARNING
1102 "hwsampler: different max sampler rate values.\n");
1103 if (max_sampler_rate > cb->qsi.max_sampl_rate)
1104 max_sampler_rate =
1105 cb->qsi.max_sampl_rate;
1106 } else
1107 max_sampler_rate = cb->qsi.max_sampl_rate;
1108 }
1109 }
1110 register_external_interrupt(0x1407, hws_ext_handler);
1111
1112 hws_state = HWS_DEALLOCATED;
1113 rc = 0;
1114
1115setup_exit:
1116 mutex_unlock(&hws_sem);
1117 return rc;
1118}
1119
1120int hwsampler_shutdown()
1121{
1122 int rc;
1123
1124 mutex_lock(&hws_sem);
1125
1126 rc = -EINVAL;
1127 if (hws_state == HWS_DEALLOCATED || hws_state == HWS_STOPPED) {
1128 mutex_unlock(&hws_sem);
1129
1130 if (hws_wq)
1131 flush_workqueue(hws_wq);
1132
1133 mutex_lock(&hws_sem);
1134
1135 if (hws_state == HWS_STOPPED) {
1136 smp_ctl_clear_bit(0, 5); /* set bit 58 CR0 off */
1137 deallocate_sdbt();
1138 }
1139 if (hws_wq) {
1140 destroy_workqueue(hws_wq);
1141 hws_wq = NULL;
1142 }
1143
1144 unregister_external_interrupt(0x1407, hws_ext_handler);
1145 hws_state = HWS_INIT;
1146 rc = 0;
1147 }
1148 mutex_unlock(&hws_sem);
1149
1150 unregister_cpu_notifier(&hws_cpu_notifier);
1151
1152 return rc;
1153}
1154
1155/**
1156 * hwsampler_start_all() - start hardware sampling on all online CPUs
1157 * @rate: specifies the used interval when samples are taken
1158 *
1159 * Returns 0 on success, !0 on failure.
1160 */
1161int hwsampler_start_all(unsigned long rate)
1162{
1163 int rc, cpu;
1164
1165 mutex_lock(&hws_sem);
1166
1167 hws_oom = 0;
1168
1169 rc = -EINVAL;
1170 if (hws_state != HWS_STOPPED)
1171 goto start_all_exit;
1172
1173 interval = rate;
1174
1175 /* fail if rate is not valid */
1176 if (interval < min_sampler_rate || interval > max_sampler_rate)
1177 goto start_all_exit;
1178
1179 rc = check_qsi_on_start();
1180 if (rc)
1181 goto start_all_exit;
1182
1183 rc = prepare_cpu_buffers();
1184 if (rc)
1185 goto start_all_exit;
1186
1187 for_each_online_cpu(cpu) {
1188 rc = start_sampling(cpu);
1189 if (rc)
1190 break;
1191 }
1192 if (rc) {
1193 for_each_online_cpu(cpu) {
1194 stop_sampling(cpu);
1195 }
1196 goto start_all_exit;
1197 }
1198 hws_state = HWS_STARTED;
1199 rc = 0;
1200
1201start_all_exit:
1202 mutex_unlock(&hws_sem);
1203
1204 if (rc)
1205 return rc;
1206
1207 register_oom_notifier(&hws_oom_notifier);
1208 hws_oom = 1;
1209 hws_flush_all = 0;
1210 /* now let them in, 1407 CPUMF external interrupts */
1211 smp_ctl_set_bit(0, 5); /* set CR0 bit 58 */
1212
1213 return 0;
1214}
1215
1216/**
1217 * hwsampler_stop_all() - stop hardware sampling on all online CPUs
1218 *
1219 * Returns 0 on success, !0 on failure.
1220 */
1221int hwsampler_stop_all()
1222{
1223 int tmp_rc, rc, cpu;
1224 struct hws_cpu_buffer *cb;
1225
1226 mutex_lock(&hws_sem);
1227
1228 rc = 0;
1229 if (hws_state == HWS_INIT) {
1230 mutex_unlock(&hws_sem);
1231 return rc;
1232 }
1233 hws_state = HWS_STOPPING;
1234 mutex_unlock(&hws_sem);
1235
1236 for_each_online_cpu(cpu) {
1237 cb = &per_cpu(sampler_cpu_buffer, cpu);
1238 cb->stop_mode = 1;
1239 tmp_rc = stop_sampling(cpu);
1240 if (tmp_rc)
1241 rc = tmp_rc;
1242 }
1243
1244 if (hws_wq)
1245 flush_workqueue(hws_wq);
1246
1247 mutex_lock(&hws_sem);
1248 if (hws_oom) {
1249 unregister_oom_notifier(&hws_oom_notifier);
1250 hws_oom = 0;
1251 }
1252 hws_state = HWS_STOPPED;
1253 mutex_unlock(&hws_sem);
1254
1255 return rc;
1256}
diff --git a/arch/s390/oprofile/hwsampler.h b/arch/s390/oprofile/hwsampler.h
new file mode 100644
index 000000000000..8c72b59316b5
--- /dev/null
+++ b/arch/s390/oprofile/hwsampler.h
@@ -0,0 +1,113 @@
1/*
2 * CPUMF HW sampler functions and internal structures
3 *
4 * Copyright IBM Corp. 2010
5 * Author(s): Heinz Graalfs <graalfs@de.ibm.com>
6 */
7
8#ifndef HWSAMPLER_H_
9#define HWSAMPLER_H_
10
11#include <linux/workqueue.h>
12
13struct hws_qsi_info_block /* QUERY SAMPLING information block */
14{ /* Bit(s) */
15 unsigned int b0_13:14; /* 0-13: zeros */
16 unsigned int as:1; /* 14: sampling authorisation control*/
17 unsigned int b15_21:7; /* 15-21: zeros */
18 unsigned int es:1; /* 22: sampling enable control */
19 unsigned int b23_29:7; /* 23-29: zeros */
20 unsigned int cs:1; /* 30: sampling activation control */
21 unsigned int:1; /* 31: reserved */
22 unsigned int bsdes:16; /* 4-5: size of sampling entry */
23 unsigned int:16; /* 6-7: reserved */
24 unsigned long min_sampl_rate; /* 8-15: minimum sampling interval */
25 unsigned long max_sampl_rate; /* 16-23: maximum sampling interval*/
26 unsigned long tear; /* 24-31: TEAR contents */
27 unsigned long dear; /* 32-39: DEAR contents */
28 unsigned int rsvrd0; /* 40-43: reserved */
29 unsigned int cpu_speed; /* 44-47: CPU speed */
30 unsigned long long rsvrd1; /* 48-55: reserved */
31 unsigned long long rsvrd2; /* 56-63: reserved */
32};
33
34struct hws_ssctl_request_block /* SET SAMPLING CONTROLS req block */
35{ /* bytes 0 - 7 Bit(s) */
36 unsigned int s:1; /* 0: maximum buffer indicator */
37 unsigned int h:1; /* 1: part. level reserved for VM use*/
38 unsigned long b2_53:52; /* 2-53: zeros */
39 unsigned int es:1; /* 54: sampling enable control */
40 unsigned int b55_61:7; /* 55-61: - zeros */
41 unsigned int cs:1; /* 62: sampling activation control */
42 unsigned int b63:1; /* 63: zero */
43 unsigned long interval; /* 8-15: sampling interval */
44 unsigned long tear; /* 16-23: TEAR contents */
45 unsigned long dear; /* 24-31: DEAR contents */
46 /* 32-63: */
47 unsigned long rsvrd1; /* reserved */
48 unsigned long rsvrd2; /* reserved */
49 unsigned long rsvrd3; /* reserved */
50 unsigned long rsvrd4; /* reserved */
51};
52
53struct hws_cpu_buffer {
54 unsigned long first_sdbt; /* @ of 1st SDB-Table for this CP*/
55 unsigned long worker_entry;
56 unsigned long sample_overflow; /* taken from SDB ... */
57 struct hws_qsi_info_block qsi;
58 struct hws_ssctl_request_block ssctl;
59 struct work_struct worker;
60 atomic_t ext_params;
61 unsigned long req_alert;
62 unsigned long loss_of_sample_data;
63 unsigned long invalid_entry_address;
64 unsigned long incorrect_sdbt_entry;
65 unsigned long sample_auth_change_alert;
66 unsigned int finish:1;
67 unsigned int oom:1;
68 unsigned int stop_mode:1;
69};
70
71struct hws_data_entry {
72 unsigned int def:16; /* 0-15 Data Entry Format */
73 unsigned int R:4; /* 16-19 reserved */
74 unsigned int U:4; /* 20-23 Number of unique instruct. */
75 unsigned int z:2; /* zeros */
76 unsigned int T:1; /* 26 PSW DAT mode */
77 unsigned int W:1; /* 27 PSW wait state */
78 unsigned int P:1; /* 28 PSW Problem state */
79 unsigned int AS:2; /* 29-30 PSW address-space control */
80 unsigned int I:1; /* 31 entry valid or invalid */
81 unsigned int:16;
82 unsigned int prim_asn:16; /* primary ASN */
83 unsigned long long ia; /* Instruction Address */
84 unsigned long long lpp; /* Logical-Partition Program Param. */
85 unsigned long long vpp; /* Virtual-Machine Program Param. */
86};
87
88struct hws_trailer_entry {
89 unsigned int f:1; /* 0 - Block Full Indicator */
90 unsigned int a:1; /* 1 - Alert request control */
91 unsigned long:62; /* 2 - 63: Reserved */
92 unsigned long overflow; /* 64 - sample Overflow count */
93 unsigned long timestamp; /* 16 - time-stamp */
94 unsigned long timestamp1; /* */
95 unsigned long reserved1; /* 32 -Reserved */
96 unsigned long reserved2; /* */
97 unsigned long progusage1; /* 48 - reserved for programming use */
98 unsigned long progusage2; /* */
99};
100
101int hwsampler_setup(void);
102int hwsampler_shutdown(void);
103int hwsampler_allocate(unsigned long sdbt, unsigned long sdb);
104int hwsampler_deallocate(void);
105long hwsampler_query_min_interval(void);
106long hwsampler_query_max_interval(void);
107int hwsampler_start_all(unsigned long interval);
108int hwsampler_stop_all(void);
109int hwsampler_deactivate(unsigned int cpu);
110int hwsampler_activate(unsigned int cpu);
111unsigned long hwsampler_get_sample_overflow_count(unsigned int cpu);
112
113#endif /*HWSAMPLER_H_*/
diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c
index 7a995113b918..16c76def4a9d 100644
--- a/arch/s390/oprofile/init.c
+++ b/arch/s390/oprofile/init.c
@@ -4,23 +4,182 @@
4 * S390 Version 4 * S390 Version
5 * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation 5 * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
6 * Author(s): Thomas Spatzier (tspat@de.ibm.com) 6 * Author(s): Thomas Spatzier (tspat@de.ibm.com)
7 * Author(s): Mahesh Salgaonkar (mahesh@linux.vnet.ibm.com)
8 * Author(s): Heinz Graalfs (graalfs@linux.vnet.ibm.com)
7 * 9 *
8 * @remark Copyright 2002 OProfile authors 10 * @remark Copyright 2002-2011 OProfile authors
9 */ 11 */
10 12
11#include <linux/oprofile.h> 13#include <linux/oprofile.h>
12#include <linux/init.h> 14#include <linux/init.h>
13#include <linux/errno.h> 15#include <linux/errno.h>
16#include <linux/oprofile.h>
17#include <linux/errno.h>
18#include <linux/fs.h>
19
20#include "../../../drivers/oprofile/oprof.h"
21#include "hwsampler.h"
22
23#define DEFAULT_INTERVAL 4096
24
25#define DEFAULT_SDBT_BLOCKS 1
26#define DEFAULT_SDB_BLOCKS 511
27
28static unsigned long oprofile_hw_interval = DEFAULT_INTERVAL;
29static unsigned long oprofile_min_interval;
30static unsigned long oprofile_max_interval;
31
32static unsigned long oprofile_sdbt_blocks = DEFAULT_SDBT_BLOCKS;
33static unsigned long oprofile_sdb_blocks = DEFAULT_SDB_BLOCKS;
14 34
35static int hwsampler_file;
36static int hwsampler_running; /* start_mutex must be held to change */
37
38static struct oprofile_operations timer_ops;
15 39
16extern void s390_backtrace(struct pt_regs * const regs, unsigned int depth); 40extern void s390_backtrace(struct pt_regs * const regs, unsigned int depth);
17 41
18int __init oprofile_arch_init(struct oprofile_operations* ops) 42static int oprofile_hwsampler_start(void)
43{
44 int retval;
45
46 hwsampler_running = hwsampler_file;
47
48 if (!hwsampler_running)
49 return timer_ops.start();
50
51 retval = hwsampler_allocate(oprofile_sdbt_blocks, oprofile_sdb_blocks);
52 if (retval)
53 return retval;
54
55 retval = hwsampler_start_all(oprofile_hw_interval);
56 if (retval)
57 hwsampler_deallocate();
58
59 return retval;
60}
61
62static void oprofile_hwsampler_stop(void)
63{
64 if (!hwsampler_running) {
65 timer_ops.stop();
66 return;
67 }
68
69 hwsampler_stop_all();
70 hwsampler_deallocate();
71 return;
72}
73
74static ssize_t hwsampler_read(struct file *file, char __user *buf,
75 size_t count, loff_t *offset)
76{
77 return oprofilefs_ulong_to_user(hwsampler_file, buf, count, offset);
78}
79
80static ssize_t hwsampler_write(struct file *file, char const __user *buf,
81 size_t count, loff_t *offset)
82{
83 unsigned long val;
84 int retval;
85
86 if (*offset)
87 return -EINVAL;
88
89 retval = oprofilefs_ulong_from_user(&val, buf, count);
90 if (retval)
91 return retval;
92
93 if (oprofile_started)
94 /*
95 * save to do without locking as we set
96 * hwsampler_running in start() when start_mutex is
97 * held
98 */
99 return -EBUSY;
100
101 hwsampler_file = val;
102
103 return count;
104}
105
106static const struct file_operations hwsampler_fops = {
107 .read = hwsampler_read,
108 .write = hwsampler_write,
109};
110
111static int oprofile_create_hwsampling_files(struct super_block *sb,
112 struct dentry *root)
113{
114 struct dentry *hw_dir;
115
116 /* reinitialize default values */
117 hwsampler_file = 1;
118
119 hw_dir = oprofilefs_mkdir(sb, root, "hwsampling");
120 if (!hw_dir)
121 return -EINVAL;
122
123 oprofilefs_create_file(sb, hw_dir, "hwsampler", &hwsampler_fops);
124 oprofilefs_create_ulong(sb, hw_dir, "hw_interval",
125 &oprofile_hw_interval);
126 oprofilefs_create_ro_ulong(sb, hw_dir, "hw_min_interval",
127 &oprofile_min_interval);
128 oprofilefs_create_ro_ulong(sb, hw_dir, "hw_max_interval",
129 &oprofile_max_interval);
130 oprofilefs_create_ulong(sb, hw_dir, "hw_sdbt_blocks",
131 &oprofile_sdbt_blocks);
132
133 return 0;
134}
135
136static int oprofile_hwsampler_init(struct oprofile_operations *ops)
137{
138 if (hwsampler_setup())
139 return -ENODEV;
140
141 /*
142 * create hwsampler files only if hwsampler_setup() succeeds.
143 */
144 oprofile_min_interval = hwsampler_query_min_interval();
145 if (oprofile_min_interval < 0) {
146 oprofile_min_interval = 0;
147 return -ENODEV;
148 }
149 oprofile_max_interval = hwsampler_query_max_interval();
150 if (oprofile_max_interval < 0) {
151 oprofile_max_interval = 0;
152 return -ENODEV;
153 }
154
155 if (oprofile_timer_init(ops))
156 return -ENODEV;
157
158 printk(KERN_INFO "oprofile: using hardware sampling\n");
159
160 memcpy(&timer_ops, ops, sizeof(timer_ops));
161
162 ops->start = oprofile_hwsampler_start;
163 ops->stop = oprofile_hwsampler_stop;
164 ops->create_files = oprofile_create_hwsampling_files;
165
166 return 0;
167}
168
169static void oprofile_hwsampler_exit(void)
170{
171 oprofile_timer_exit();
172 hwsampler_shutdown();
173}
174
175int __init oprofile_arch_init(struct oprofile_operations *ops)
19{ 176{
20 ops->backtrace = s390_backtrace; 177 ops->backtrace = s390_backtrace;
21 return -ENODEV; 178
179 return oprofile_hwsampler_init(ops);
22} 180}
23 181
24void oprofile_arch_exit(void) 182void oprofile_arch_exit(void)
25{ 183{
184 oprofile_hwsampler_exit();
26} 185}
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 26604188aa49..e8dbe179587f 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -178,8 +178,6 @@ struct cpu_hw_events {
178 */ 178 */
179#define INTEL_UEVENT_CONSTRAINT(c, n) \ 179#define INTEL_UEVENT_CONSTRAINT(c, n) \
180 EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK) 180 EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK)
181#define PEBS_EVENT_CONSTRAINT(c, n) \
182 INTEL_UEVENT_CONSTRAINT(c, n)
183 181
184#define EVENT_CONSTRAINT_END \ 182#define EVENT_CONSTRAINT_END \
185 EVENT_CONSTRAINT(0, 0, 0) 183 EVENT_CONSTRAINT(0, 0, 0)
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
index b95c66ae4a2a..bab491b8ee25 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -362,87 +362,69 @@ static int intel_pmu_drain_bts_buffer(void)
362 * PEBS 362 * PEBS
363 */ 363 */
364static struct event_constraint intel_core2_pebs_event_constraints[] = { 364static struct event_constraint intel_core2_pebs_event_constraints[] = {
365 PEBS_EVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */ 365 INTEL_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */
366 PEBS_EVENT_CONSTRAINT(0xfec1, 0x1), /* X87_OPS_RETIRED.ANY */ 366 INTEL_UEVENT_CONSTRAINT(0xfec1, 0x1), /* X87_OPS_RETIRED.ANY */
367 PEBS_EVENT_CONSTRAINT(0x00c5, 0x1), /* BR_INST_RETIRED.MISPRED */ 367 INTEL_UEVENT_CONSTRAINT(0x00c5, 0x1), /* BR_INST_RETIRED.MISPRED */
368 PEBS_EVENT_CONSTRAINT(0x1fc7, 0x1), /* SIMD_INST_RETURED.ANY */ 368 INTEL_UEVENT_CONSTRAINT(0x1fc7, 0x1), /* SIMD_INST_RETURED.ANY */
369 INTEL_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED.* */ 369 INTEL_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED.* */
370 EVENT_CONSTRAINT_END 370 EVENT_CONSTRAINT_END
371}; 371};
372 372
373static struct event_constraint intel_atom_pebs_event_constraints[] = { 373static struct event_constraint intel_atom_pebs_event_constraints[] = {
374 PEBS_EVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */ 374 INTEL_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */
375 PEBS_EVENT_CONSTRAINT(0x00c5, 0x1), /* MISPREDICTED_BRANCH_RETIRED */ 375 INTEL_UEVENT_CONSTRAINT(0x00c5, 0x1), /* MISPREDICTED_BRANCH_RETIRED */
376 INTEL_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED.* */ 376 INTEL_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED.* */
377 EVENT_CONSTRAINT_END 377 EVENT_CONSTRAINT_END
378}; 378};
379 379
380static struct event_constraint intel_nehalem_pebs_event_constraints[] = { 380static struct event_constraint intel_nehalem_pebs_event_constraints[] = {
381 INTEL_EVENT_CONSTRAINT(0x0b, 0xf), /* MEM_INST_RETIRED.* */ 381 INTEL_EVENT_CONSTRAINT(0x0b, 0xf), /* MEM_INST_RETIRED.* */
382 INTEL_EVENT_CONSTRAINT(0x0f, 0xf), /* MEM_UNCORE_RETIRED.* */ 382 INTEL_EVENT_CONSTRAINT(0x0f, 0xf), /* MEM_UNCORE_RETIRED.* */
383 PEBS_EVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */ 383 INTEL_UEVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */
384 INTEL_EVENT_CONSTRAINT(0xc0, 0xf), /* INST_RETIRED.ANY */ 384 INTEL_EVENT_CONSTRAINT(0xc0, 0xf), /* INST_RETIRED.ANY */
385 INTEL_EVENT_CONSTRAINT(0xc2, 0xf), /* UOPS_RETIRED.* */ 385 INTEL_EVENT_CONSTRAINT(0xc2, 0xf), /* UOPS_RETIRED.* */
386 INTEL_EVENT_CONSTRAINT(0xc4, 0xf), /* BR_INST_RETIRED.* */ 386 INTEL_EVENT_CONSTRAINT(0xc4, 0xf), /* BR_INST_RETIRED.* */
387 PEBS_EVENT_CONSTRAINT(0x02c5, 0xf), /* BR_MISP_RETIRED.NEAR_CALL */ 387 INTEL_UEVENT_CONSTRAINT(0x02c5, 0xf), /* BR_MISP_RETIRED.NEAR_CALL */
388 INTEL_EVENT_CONSTRAINT(0xc7, 0xf), /* SSEX_UOPS_RETIRED.* */ 388 INTEL_EVENT_CONSTRAINT(0xc7, 0xf), /* SSEX_UOPS_RETIRED.* */
389 PEBS_EVENT_CONSTRAINT(0x20c8, 0xf), /* ITLB_MISS_RETIRED */ 389 INTEL_UEVENT_CONSTRAINT(0x20c8, 0xf), /* ITLB_MISS_RETIRED */
390 INTEL_EVENT_CONSTRAINT(0xcb, 0xf), /* MEM_LOAD_RETIRED.* */ 390 INTEL_EVENT_CONSTRAINT(0xcb, 0xf), /* MEM_LOAD_RETIRED.* */
391 INTEL_EVENT_CONSTRAINT(0xf7, 0xf), /* FP_ASSIST.* */ 391 INTEL_EVENT_CONSTRAINT(0xf7, 0xf), /* FP_ASSIST.* */
392 EVENT_CONSTRAINT_END 392 EVENT_CONSTRAINT_END
393}; 393};
394 394
395static struct event_constraint intel_westmere_pebs_event_constraints[] = { 395static struct event_constraint intel_westmere_pebs_event_constraints[] = {
396 INTEL_EVENT_CONSTRAINT(0x0b, 0xf), /* MEM_INST_RETIRED.* */ 396 INTEL_EVENT_CONSTRAINT(0x0b, 0xf), /* MEM_INST_RETIRED.* */
397 INTEL_EVENT_CONSTRAINT(0x0f, 0xf), /* MEM_UNCORE_RETIRED.* */ 397 INTEL_EVENT_CONSTRAINT(0x0f, 0xf), /* MEM_UNCORE_RETIRED.* */
398 PEBS_EVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */ 398 INTEL_UEVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */
399 INTEL_EVENT_CONSTRAINT(0xc0, 0xf), /* INSTR_RETIRED.* */ 399 INTEL_EVENT_CONSTRAINT(0xc0, 0xf), /* INSTR_RETIRED.* */
400 INTEL_EVENT_CONSTRAINT(0xc2, 0xf), /* UOPS_RETIRED.* */ 400 INTEL_EVENT_CONSTRAINT(0xc2, 0xf), /* UOPS_RETIRED.* */
401 401 INTEL_EVENT_CONSTRAINT(0xc4, 0xf), /* BR_INST_RETIRED.* */
402 INTEL_EVENT_CONSTRAINT(0xc4, 0xf), /* BR_INST_RETIRED.* */ 402 INTEL_EVENT_CONSTRAINT(0xc5, 0xf), /* BR_MISP_RETIRED.* */
403 INTEL_EVENT_CONSTRAINT(0xc5, 0xf), /* BR_MISP_RETIRED.* */ 403 INTEL_EVENT_CONSTRAINT(0xc7, 0xf), /* SSEX_UOPS_RETIRED.* */
404 INTEL_EVENT_CONSTRAINT(0xc7, 0xf), /* SSEX_UOPS_RETIRED.* */ 404 INTEL_UEVENT_CONSTRAINT(0x20c8, 0xf), /* ITLB_MISS_RETIRED */
405 PEBS_EVENT_CONSTRAINT(0x20c8, 0xf), /* ITLB_MISS_RETIRED */ 405 INTEL_EVENT_CONSTRAINT(0xcb, 0xf), /* MEM_LOAD_RETIRED.* */
406 INTEL_EVENT_CONSTRAINT(0xcb, 0xf), /* MEM_LOAD_RETIRED.* */ 406 INTEL_EVENT_CONSTRAINT(0xf7, 0xf), /* FP_ASSIST.* */
407 INTEL_EVENT_CONSTRAINT(0xf7, 0xf), /* FP_ASSIST.* */
408 EVENT_CONSTRAINT_END 407 EVENT_CONSTRAINT_END
409}; 408};
410 409
411static struct event_constraint intel_snb_pebs_events[] = { 410static struct event_constraint intel_snb_pebs_events[] = {
412 PEBS_EVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */ 411 INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
413 PEBS_EVENT_CONSTRAINT(0x01c2, 0xf), /* UOPS_RETIRED.ALL */ 412 INTEL_UEVENT_CONSTRAINT(0x01c2, 0xf), /* UOPS_RETIRED.ALL */
414 PEBS_EVENT_CONSTRAINT(0x02c2, 0xf), /* UOPS_RETIRED.RETIRE_SLOTS */ 413 INTEL_UEVENT_CONSTRAINT(0x02c2, 0xf), /* UOPS_RETIRED.RETIRE_SLOTS */
415 PEBS_EVENT_CONSTRAINT(0x01c4, 0xf), /* BR_INST_RETIRED.CONDITIONAL */ 414 INTEL_EVENT_CONSTRAINT(0xc4, 0xf), /* BR_INST_RETIRED.* */
416 PEBS_EVENT_CONSTRAINT(0x02c4, 0xf), /* BR_INST_RETIRED.NEAR_CALL */ 415 INTEL_EVENT_CONSTRAINT(0xc5, 0xf), /* BR_MISP_RETIRED.* */
417 PEBS_EVENT_CONSTRAINT(0x04c4, 0xf), /* BR_INST_RETIRED.ALL_BRANCHES */ 416 INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.* */
418 PEBS_EVENT_CONSTRAINT(0x08c4, 0xf), /* BR_INST_RETIRED.NEAR_RETURN */ 417 INTEL_UEVENT_CONSTRAINT(0x11d0, 0xf), /* MEM_UOP_RETIRED.STLB_MISS_LOADS */
419 PEBS_EVENT_CONSTRAINT(0x10c4, 0xf), /* BR_INST_RETIRED.NOT_TAKEN */ 418 INTEL_UEVENT_CONSTRAINT(0x12d0, 0xf), /* MEM_UOP_RETIRED.STLB_MISS_STORES */
420 PEBS_EVENT_CONSTRAINT(0x20c4, 0xf), /* BR_INST_RETIRED.NEAR_TAKEN */ 419 INTEL_UEVENT_CONSTRAINT(0x21d0, 0xf), /* MEM_UOP_RETIRED.LOCK_LOADS */
421 PEBS_EVENT_CONSTRAINT(0x40c4, 0xf), /* BR_INST_RETIRED.FAR_BRANCH */ 420 INTEL_UEVENT_CONSTRAINT(0x22d0, 0xf), /* MEM_UOP_RETIRED.LOCK_STORES */
422 PEBS_EVENT_CONSTRAINT(0x01c5, 0xf), /* BR_MISP_RETIRED.CONDITIONAL */ 421 INTEL_UEVENT_CONSTRAINT(0x41d0, 0xf), /* MEM_UOP_RETIRED.SPLIT_LOADS */
423 PEBS_EVENT_CONSTRAINT(0x02c5, 0xf), /* BR_MISP_RETIRED.NEAR_CALL */ 422 INTEL_UEVENT_CONSTRAINT(0x42d0, 0xf), /* MEM_UOP_RETIRED.SPLIT_STORES */
424 PEBS_EVENT_CONSTRAINT(0x04c5, 0xf), /* BR_MISP_RETIRED.ALL_BRANCHES */ 423 INTEL_UEVENT_CONSTRAINT(0x81d0, 0xf), /* MEM_UOP_RETIRED.ANY_LOADS */
425 PEBS_EVENT_CONSTRAINT(0x10c5, 0xf), /* BR_MISP_RETIRED.NOT_TAKEN */ 424 INTEL_UEVENT_CONSTRAINT(0x82d0, 0xf), /* MEM_UOP_RETIRED.ANY_STORES */
426 PEBS_EVENT_CONSTRAINT(0x20c5, 0xf), /* BR_MISP_RETIRED.TAKEN */ 425 INTEL_EVENT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */
427 PEBS_EVENT_CONSTRAINT(0x01cd, 0x8), /* MEM_TRANS_RETIRED.LOAD_LATENCY */ 426 INTEL_EVENT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
428 PEBS_EVENT_CONSTRAINT(0x02cd, 0x8), /* MEM_TRANS_RETIRED.PRECISE_STORE */ 427 INTEL_UEVENT_CONSTRAINT(0x02d4, 0xf), /* MEM_LOAD_UOPS_MISC_RETIRED.LLC_MISS */
429 PEBS_EVENT_CONSTRAINT(0x11d0, 0xf), /* MEM_UOP_RETIRED.STLB_MISS_LOADS */
430 PEBS_EVENT_CONSTRAINT(0x12d0, 0xf), /* MEM_UOP_RETIRED.STLB_MISS_STORES */
431 PEBS_EVENT_CONSTRAINT(0x21d0, 0xf), /* MEM_UOP_RETIRED.LOCK_LOADS */
432 PEBS_EVENT_CONSTRAINT(0x22d0, 0xf), /* MEM_UOP_RETIRED.LOCK_STORES */
433 PEBS_EVENT_CONSTRAINT(0x41d0, 0xf), /* MEM_UOP_RETIRED.SPLIT_LOADS */
434 PEBS_EVENT_CONSTRAINT(0x42d0, 0xf), /* MEM_UOP_RETIRED.SPLIT_STORES */
435 PEBS_EVENT_CONSTRAINT(0x81d0, 0xf), /* MEM_UOP_RETIRED.ANY_LOADS */
436 PEBS_EVENT_CONSTRAINT(0x82d0, 0xf), /* MEM_UOP_RETIRED.ANY_STORES */
437 PEBS_EVENT_CONSTRAINT(0x01d1, 0xf), /* MEM_LOAD_UOPS_RETIRED.L1_HIT */
438 PEBS_EVENT_CONSTRAINT(0x02d1, 0xf), /* MEM_LOAD_UOPS_RETIRED.L2_HIT */
439 PEBS_EVENT_CONSTRAINT(0x04d1, 0xf), /* MEM_LOAD_UOPS_RETIRED.LLC_HIT */
440 PEBS_EVENT_CONSTRAINT(0x40d1, 0xf), /* MEM_LOAD_UOPS_RETIRED.HIT_LFB */
441 PEBS_EVENT_CONSTRAINT(0x01d2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_MISS */
442 PEBS_EVENT_CONSTRAINT(0x02d2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HIT */
443 PEBS_EVENT_CONSTRAINT(0x04d2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_HITM */
444 PEBS_EVENT_CONSTRAINT(0x08d2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.XSNP_NONE */
445 PEBS_EVENT_CONSTRAINT(0x02d4, 0xf), /* MEM_LOAD_UOPS_MISC_RETIRED.LLC_MISS */
446 EVENT_CONSTRAINT_END 428 EVENT_CONSTRAINT_END
447}; 429};
448 430
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c
index 59f55441e075..b8ef8ddcc292 100644
--- a/drivers/oprofile/cpu_buffer.c
+++ b/drivers/oprofile/cpu_buffer.c
@@ -258,8 +258,10 @@ op_add_sample(struct oprofile_cpu_buffer *cpu_buf,
258 */ 258 */
259static int 259static int
260log_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc, 260log_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc,
261 unsigned long backtrace, int is_kernel, unsigned long event) 261 unsigned long backtrace, int is_kernel, unsigned long event,
262 struct task_struct *task)
262{ 263{
264 struct task_struct *tsk = task ? task : current;
263 cpu_buf->sample_received++; 265 cpu_buf->sample_received++;
264 266
265 if (pc == ESCAPE_CODE) { 267 if (pc == ESCAPE_CODE) {
@@ -267,7 +269,7 @@ log_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc,
267 return 0; 269 return 0;
268 } 270 }
269 271
270 if (op_add_code(cpu_buf, backtrace, is_kernel, current)) 272 if (op_add_code(cpu_buf, backtrace, is_kernel, tsk))
271 goto fail; 273 goto fail;
272 274
273 if (op_add_sample(cpu_buf, pc, event)) 275 if (op_add_sample(cpu_buf, pc, event))
@@ -292,7 +294,8 @@ static inline void oprofile_end_trace(struct oprofile_cpu_buffer *cpu_buf)
292 294
293static inline void 295static inline void
294__oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs, 296__oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
295 unsigned long event, int is_kernel) 297 unsigned long event, int is_kernel,
298 struct task_struct *task)
296{ 299{
297 struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(op_cpu_buffer); 300 struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(op_cpu_buffer);
298 unsigned long backtrace = oprofile_backtrace_depth; 301 unsigned long backtrace = oprofile_backtrace_depth;
@@ -301,7 +304,7 @@ __oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
301 * if log_sample() fail we can't backtrace since we lost the 304 * if log_sample() fail we can't backtrace since we lost the
302 * source of this event 305 * source of this event
303 */ 306 */
304 if (!log_sample(cpu_buf, pc, backtrace, is_kernel, event)) 307 if (!log_sample(cpu_buf, pc, backtrace, is_kernel, event, task))
305 /* failed */ 308 /* failed */
306 return; 309 return;
307 310
@@ -313,10 +316,17 @@ __oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
313 oprofile_end_trace(cpu_buf); 316 oprofile_end_trace(cpu_buf);
314} 317}
315 318
319void oprofile_add_ext_hw_sample(unsigned long pc, struct pt_regs * const regs,
320 unsigned long event, int is_kernel,
321 struct task_struct *task)
322{
323 __oprofile_add_ext_sample(pc, regs, event, is_kernel, task);
324}
325
316void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs, 326void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
317 unsigned long event, int is_kernel) 327 unsigned long event, int is_kernel)
318{ 328{
319 __oprofile_add_ext_sample(pc, regs, event, is_kernel); 329 __oprofile_add_ext_sample(pc, regs, event, is_kernel, NULL);
320} 330}
321 331
322void oprofile_add_sample(struct pt_regs * const regs, unsigned long event) 332void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
@@ -332,7 +342,7 @@ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
332 pc = ESCAPE_CODE; /* as this causes an early return. */ 342 pc = ESCAPE_CODE; /* as this causes an early return. */
333 } 343 }
334 344
335 __oprofile_add_ext_sample(pc, regs, event, is_kernel); 345 __oprofile_add_ext_sample(pc, regs, event, is_kernel, NULL);
336} 346}
337 347
338/* 348/*
@@ -403,7 +413,7 @@ int oprofile_write_commit(struct op_entry *entry)
403void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event) 413void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event)
404{ 414{
405 struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(op_cpu_buffer); 415 struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(op_cpu_buffer);
406 log_sample(cpu_buf, pc, 0, is_kernel, event); 416 log_sample(cpu_buf, pc, 0, is_kernel, event, NULL);
407} 417}
408 418
409void oprofile_add_trace(unsigned long pc) 419void oprofile_add_trace(unsigned long pc)
diff --git a/drivers/oprofile/timer_int.c b/drivers/oprofile/timer_int.c
index 010725117dbb..3ef44624f510 100644
--- a/drivers/oprofile/timer_int.c
+++ b/drivers/oprofile/timer_int.c
@@ -97,7 +97,7 @@ static struct notifier_block __refdata oprofile_cpu_notifier = {
97 .notifier_call = oprofile_cpu_notify, 97 .notifier_call = oprofile_cpu_notify,
98}; 98};
99 99
100int __init oprofile_timer_init(struct oprofile_operations *ops) 100int oprofile_timer_init(struct oprofile_operations *ops)
101{ 101{
102 int rc; 102 int rc;
103 103
@@ -113,7 +113,7 @@ int __init oprofile_timer_init(struct oprofile_operations *ops)
113 return 0; 113 return 0;
114} 114}
115 115
116void __exit oprofile_timer_exit(void) 116void oprofile_timer_exit(void)
117{ 117{
118 unregister_hotcpu_notifier(&oprofile_cpu_notifier); 118 unregister_hotcpu_notifier(&oprofile_cpu_notifier);
119} 119}
diff --git a/include/linux/oprofile.h b/include/linux/oprofile.h
index 1ca64113efe8..7f5cfd3b37dd 100644
--- a/include/linux/oprofile.h
+++ b/include/linux/oprofile.h
@@ -106,6 +106,13 @@ void oprofile_add_sample(struct pt_regs * const regs, unsigned long event);
106void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs, 106void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
107 unsigned long event, int is_kernel); 107 unsigned long event, int is_kernel);
108 108
109/**
110 * Add an hardware sample.
111 */
112void oprofile_add_ext_hw_sample(unsigned long pc, struct pt_regs * const regs,
113 unsigned long event, int is_kernel,
114 struct task_struct *task);
115
109/* Use this instead when the PC value is not from the regs. Doesn't 116/* Use this instead when the PC value is not from the regs. Doesn't
110 * backtrace. */ 117 * backtrace. */
111void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event); 118void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event);
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 614615b8d42b..f495c0147240 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -878,8 +878,8 @@ enum perf_event_context_type {
878 * Used as a container for task events and CPU events as well: 878 * Used as a container for task events and CPU events as well:
879 */ 879 */
880struct perf_event_context { 880struct perf_event_context {
881 enum perf_event_context_type type;
882 struct pmu *pmu; 881 struct pmu *pmu;
882 enum perf_event_context_type type;
883 /* 883 /*
884 * Protect the states of the events in the list, 884 * Protect the states of the events in the list,
885 * nr_active, and the list: 885 * nr_active, and the list:
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index ed253aa24ba4..3472bb1a070c 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -5122,7 +5122,7 @@ static int perf_exclude_event(struct perf_event *event,
5122 struct pt_regs *regs) 5122 struct pt_regs *regs)
5123{ 5123{
5124 if (event->hw.state & PERF_HES_STOPPED) 5124 if (event->hw.state & PERF_HES_STOPPED)
5125 return 0; 5125 return 1;
5126 5126
5127 if (regs) { 5127 if (regs) {
5128 if (event->attr.exclude_user && user_mode(regs)) 5128 if (event->attr.exclude_user && user_mode(regs))
@@ -5478,6 +5478,8 @@ static int perf_tp_event_match(struct perf_event *event,
5478 struct perf_sample_data *data, 5478 struct perf_sample_data *data,
5479 struct pt_regs *regs) 5479 struct pt_regs *regs)
5480{ 5480{
5481 if (event->hw.state & PERF_HES_STOPPED)
5482 return 0;
5481 /* 5483 /*
5482 * All tracepoints are from kernel-space. 5484 * All tracepoints are from kernel-space.
5483 */ 5485 */
@@ -6720,17 +6722,20 @@ __perf_event_exit_task(struct perf_event *child_event,
6720 struct perf_event_context *child_ctx, 6722 struct perf_event_context *child_ctx,
6721 struct task_struct *child) 6723 struct task_struct *child)
6722{ 6724{
6723 struct perf_event *parent_event; 6725 if (child_event->parent) {
6726 raw_spin_lock_irq(&child_ctx->lock);
6727 perf_group_detach(child_event);
6728 raw_spin_unlock_irq(&child_ctx->lock);
6729 }
6724 6730
6725 perf_remove_from_context(child_event); 6731 perf_remove_from_context(child_event);
6726 6732
6727 parent_event = child_event->parent;
6728 /* 6733 /*
6729 * It can happen that parent exits first, and has events 6734 * It can happen that the parent exits first, and has events
6730 * that are still around due to the child reference. These 6735 * that are still around due to the child reference. These
6731 * events need to be zapped - but otherwise linger. 6736 * events need to be zapped.
6732 */ 6737 */
6733 if (parent_event) { 6738 if (child_event->parent) {
6734 sync_child_event(child_event, child); 6739 sync_child_event(child_event, child);
6735 free_event(child_event); 6740 free_event(child_event);
6736 } 6741 }
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index 14674dce77a6..61d7d59f4a1a 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -275,7 +275,7 @@ config PROFILE_ANNOTATED_BRANCHES
275 This tracer profiles all the the likely and unlikely macros 275 This tracer profiles all the the likely and unlikely macros
276 in the kernel. It will display the results in: 276 in the kernel. It will display the results in:
277 277
278 /sys/kernel/debug/tracing/profile_annotated_branch 278 /sys/kernel/debug/tracing/trace_stat/branch_annotated
279 279
280 Note: this will add a significant overhead; only turn this 280 Note: this will add a significant overhead; only turn this
281 on if you need to profile the system's use of these macros. 281 on if you need to profile the system's use of these macros.
@@ -288,7 +288,7 @@ config PROFILE_ALL_BRANCHES
288 taken in the kernel is recorded whether it hit or miss. 288 taken in the kernel is recorded whether it hit or miss.
289 The results will be displayed in: 289 The results will be displayed in:
290 290
291 /sys/kernel/debug/tracing/profile_branch 291 /sys/kernel/debug/tracing/trace_stat/branch_all
292 292
293 This option also enables the likely/unlikely profiler. 293 This option also enables the likely/unlikely profiler.
294 294
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 3249b4f77ef0..8008ddcfbf20 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -391,8 +391,8 @@ static int process_ops(struct filter_pred *preds,
391 struct filter_pred *op, void *rec) 391 struct filter_pred *op, void *rec)
392{ 392{
393 struct filter_pred *pred; 393 struct filter_pred *pred;
394 int match = 0;
394 int type; 395 int type;
395 int match;
396 int i; 396 int i;
397 397
398 /* 398 /*
diff --git a/tools/perf/Documentation/perf-evlist.txt b/tools/perf/Documentation/perf-evlist.txt
new file mode 100644
index 000000000000..0cada9e053dc
--- /dev/null
+++ b/tools/perf/Documentation/perf-evlist.txt
@@ -0,0 +1,26 @@
1perf-evlist(1)
2==============
3
4NAME
5----
6perf-evlist - List the event names in a perf.data file
7
8SYNOPSIS
9--------
10[verse]
11'perf evlist <options>'
12
13DESCRIPTION
14-----------
15This command displays the names of events sampled in a perf.data file.
16
17OPTIONS
18-------
19-i::
20--input=::
21 Input file name. (default: perf.data)
22
23SEE ALSO
24--------
25linkperf:perf-record[1], linkperf:perf-list[1],
26linkperf:perf-report[1]
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 29ad94293cd2..66f040b30729 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -112,6 +112,28 @@ OPTIONS
112--debug-mode:: 112--debug-mode::
113 Do various checks like samples ordering and lost events. 113 Do various checks like samples ordering and lost events.
114 114
115-f::
116--fields
117 Comma separated list of fields to print. Options are:
118 comm, tid, pid, time, cpu, event, trace, sym. Field
119 list must be prepended with the type, trace, sw or hw,
120 to indicate to which event type the field list applies.
121 e.g., -f sw:comm,tid,time,sym and -f trace:time,cpu,trace
122
123-k::
124--vmlinux=<file>::
125 vmlinux pathname
126
127--kallsyms=<file>::
128 kallsyms pathname
129
130--symfs=<directory>::
131 Look for files with symbols relative to this directory.
132
133-G::
134--hide-call-graph::
135 When printing symbols do not display call chain.
136
115SEE ALSO 137SEE ALSO
116-------- 138--------
117linkperf:perf-record[1], linkperf:perf-script-perl[1], 139linkperf:perf-record[1], linkperf:perf-script-perl[1],
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 9b8421805c5c..158c30e8210c 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -338,6 +338,7 @@ endif
338BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o 338BUILTIN_OBJS += $(OUTPUT)bench/mem-memcpy.o
339 339
340BUILTIN_OBJS += $(OUTPUT)builtin-diff.o 340BUILTIN_OBJS += $(OUTPUT)builtin-diff.o
341BUILTIN_OBJS += $(OUTPUT)builtin-evlist.o
341BUILTIN_OBJS += $(OUTPUT)builtin-help.o 342BUILTIN_OBJS += $(OUTPUT)builtin-help.o
342BUILTIN_OBJS += $(OUTPUT)builtin-sched.o 343BUILTIN_OBJS += $(OUTPUT)builtin-sched.o
343BUILTIN_OBJS += $(OUTPUT)builtin-buildid-list.o 344BUILTIN_OBJS += $(OUTPUT)builtin-buildid-list.o
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
new file mode 100644
index 000000000000..4c5e9e04a41f
--- /dev/null
+++ b/tools/perf/builtin-evlist.c
@@ -0,0 +1,54 @@
1/*
2 * Builtin evlist command: Show the list of event selectors present
3 * in a perf.data file.
4 */
5#include "builtin.h"
6
7#include "util/util.h"
8
9#include <linux/list.h>
10
11#include "perf.h"
12#include "util/evlist.h"
13#include "util/evsel.h"
14#include "util/parse-events.h"
15#include "util/parse-options.h"
16#include "util/session.h"
17
18static char const *input_name = "perf.data";
19
20static int __cmd_evlist(void)
21{
22 struct perf_session *session;
23 struct perf_evsel *pos;
24
25 session = perf_session__new(input_name, O_RDONLY, 0, false, NULL);
26 if (session == NULL)
27 return -ENOMEM;
28
29 list_for_each_entry(pos, &session->evlist->entries, node)
30 printf("%s\n", event_name(pos));
31
32 perf_session__delete(session);
33 return 0;
34}
35
36static const char * const evlist_usage[] = {
37 "perf evlist [<options>]",
38 NULL
39};
40
41static const struct option options[] = {
42 OPT_STRING('i', "input", &input_name, "file",
43 "input file name"),
44 OPT_END()
45};
46
47int cmd_evlist(int argc, const char **argv, const char *prefix __used)
48{
49 argc = parse_options(argc, argv, options, evlist_usage, 0);
50 if (argc)
51 usage_with_options(evlist_usage, options);
52
53 return __cmd_evlist();
54}
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 2e93f99b1480..7a2a79d2cf2c 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -202,9 +202,20 @@ static struct thread_stat *thread_stat_findnew_first(u32 tid)
202SINGLE_KEY(nr_acquired) 202SINGLE_KEY(nr_acquired)
203SINGLE_KEY(nr_contended) 203SINGLE_KEY(nr_contended)
204SINGLE_KEY(wait_time_total) 204SINGLE_KEY(wait_time_total)
205SINGLE_KEY(wait_time_min)
206SINGLE_KEY(wait_time_max) 205SINGLE_KEY(wait_time_max)
207 206
207static int lock_stat_key_wait_time_min(struct lock_stat *one,
208 struct lock_stat *two)
209{
210 u64 s1 = one->wait_time_min;
211 u64 s2 = two->wait_time_min;
212 if (s1 == ULLONG_MAX)
213 s1 = 0;
214 if (s2 == ULLONG_MAX)
215 s2 = 0;
216 return s1 > s2;
217}
218
208struct lock_key { 219struct lock_key {
209 /* 220 /*
210 * name: the value for specify by user 221 * name: the value for specify by user
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 5f40df635dcb..9f5fc5492141 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -12,6 +12,8 @@
12#include "util/trace-event.h" 12#include "util/trace-event.h"
13#include "util/parse-options.h" 13#include "util/parse-options.h"
14#include "util/util.h" 14#include "util/util.h"
15#include "util/evlist.h"
16#include "util/evsel.h"
15 17
16static char const *script_name; 18static char const *script_name;
17static char const *generate_script_lang; 19static char const *generate_script_lang;
@@ -19,6 +21,183 @@ static bool debug_mode;
19static u64 last_timestamp; 21static u64 last_timestamp;
20static u64 nr_unordered; 22static u64 nr_unordered;
21extern const struct option record_options[]; 23extern const struct option record_options[];
24static bool no_callchain;
25
26enum perf_output_field {
27 PERF_OUTPUT_COMM = 1U << 0,
28 PERF_OUTPUT_TID = 1U << 1,
29 PERF_OUTPUT_PID = 1U << 2,
30 PERF_OUTPUT_TIME = 1U << 3,
31 PERF_OUTPUT_CPU = 1U << 4,
32 PERF_OUTPUT_EVNAME = 1U << 5,
33 PERF_OUTPUT_TRACE = 1U << 6,
34 PERF_OUTPUT_SYM = 1U << 7,
35};
36
37struct output_option {
38 const char *str;
39 enum perf_output_field field;
40} all_output_options[] = {
41 {.str = "comm", .field = PERF_OUTPUT_COMM},
42 {.str = "tid", .field = PERF_OUTPUT_TID},
43 {.str = "pid", .field = PERF_OUTPUT_PID},
44 {.str = "time", .field = PERF_OUTPUT_TIME},
45 {.str = "cpu", .field = PERF_OUTPUT_CPU},
46 {.str = "event", .field = PERF_OUTPUT_EVNAME},
47 {.str = "trace", .field = PERF_OUTPUT_TRACE},
48 {.str = "sym", .field = PERF_OUTPUT_SYM},
49};
50
51/* default set to maintain compatibility with current format */
52static u64 output_fields[PERF_TYPE_MAX] = {
53 [PERF_TYPE_HARDWARE] = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | \
54 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | \
55 PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
56
57 [PERF_TYPE_SOFTWARE] = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | \
58 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | \
59 PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
60
61 [PERF_TYPE_TRACEPOINT] = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | \
62 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | \
63 PERF_OUTPUT_EVNAME | PERF_OUTPUT_TRACE,
64};
65
66static bool output_set_by_user;
67
68#define PRINT_FIELD(x) (output_fields[attr->type] & PERF_OUTPUT_##x)
69
70static int perf_session__check_attr(struct perf_session *session,
71 struct perf_event_attr *attr)
72{
73 if (PRINT_FIELD(TRACE) &&
74 !perf_session__has_traces(session, "record -R"))
75 return -EINVAL;
76
77 if (PRINT_FIELD(SYM)) {
78 if (!(session->sample_type & PERF_SAMPLE_IP)) {
79 pr_err("Samples do not contain IP data.\n");
80 return -EINVAL;
81 }
82 if (!no_callchain &&
83 !(session->sample_type & PERF_SAMPLE_CALLCHAIN))
84 symbol_conf.use_callchain = false;
85 }
86
87 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
88 !(session->sample_type & PERF_SAMPLE_TID)) {
89 pr_err("Samples do not contain TID/PID data.\n");
90 return -EINVAL;
91 }
92
93 if (PRINT_FIELD(TIME) &&
94 !(session->sample_type & PERF_SAMPLE_TIME)) {
95 pr_err("Samples do not contain timestamps.\n");
96 return -EINVAL;
97 }
98
99 if (PRINT_FIELD(CPU) &&
100 !(session->sample_type & PERF_SAMPLE_CPU)) {
101 pr_err("Samples do not contain cpu.\n");
102 return -EINVAL;
103 }
104
105 return 0;
106}
107
108static void print_sample_start(struct perf_sample *sample,
109 struct thread *thread,
110 struct perf_event_attr *attr)
111{
112 int type;
113 struct event *event;
114 const char *evname = NULL;
115 unsigned long secs;
116 unsigned long usecs;
117 unsigned long long nsecs;
118
119 if (PRINT_FIELD(COMM)) {
120 if (latency_format)
121 printf("%8.8s ", thread->comm);
122 else if (PRINT_FIELD(SYM) && symbol_conf.use_callchain)
123 printf("%s ", thread->comm);
124 else
125 printf("%16s ", thread->comm);
126 }
127
128 if (PRINT_FIELD(PID) && PRINT_FIELD(TID))
129 printf("%5d/%-5d ", sample->pid, sample->tid);
130 else if (PRINT_FIELD(PID))
131 printf("%5d ", sample->pid);
132 else if (PRINT_FIELD(TID))
133 printf("%5d ", sample->tid);
134
135 if (PRINT_FIELD(CPU)) {
136 if (latency_format)
137 printf("%3d ", sample->cpu);
138 else
139 printf("[%03d] ", sample->cpu);
140 }
141
142 if (PRINT_FIELD(TIME)) {
143 nsecs = sample->time;
144 secs = nsecs / NSECS_PER_SEC;
145 nsecs -= secs * NSECS_PER_SEC;
146 usecs = nsecs / NSECS_PER_USEC;
147 printf("%5lu.%06lu: ", secs, usecs);
148 }
149
150 if (PRINT_FIELD(EVNAME)) {
151 if (attr->type == PERF_TYPE_TRACEPOINT) {
152 type = trace_parse_common_type(sample->raw_data);
153 event = trace_find_event(type);
154 if (event)
155 evname = event->name;
156 } else
157 evname = __event_name(attr->type, attr->config);
158
159 printf("%s: ", evname ? evname : "(unknown)");
160 }
161}
162
163static void process_event(union perf_event *event __unused,
164 struct perf_sample *sample,
165 struct perf_session *session,
166 struct thread *thread)
167{
168 struct perf_event_attr *attr;
169 struct perf_evsel *evsel;
170
171 evsel = perf_evlist__id2evsel(session->evlist, sample->id);
172 if (evsel == NULL) {
173 pr_err("Invalid data. Contains samples with id not in "
174 "its header!\n");
175 return;
176 }
177 attr = &evsel->attr;
178
179 if (output_fields[attr->type] == 0)
180 return;
181
182 if (perf_session__check_attr(session, attr) < 0)
183 return;
184
185 print_sample_start(sample, thread, attr);
186
187 if (PRINT_FIELD(TRACE))
188 print_trace_event(sample->cpu, sample->raw_data,
189 sample->raw_size);
190
191 if (PRINT_FIELD(SYM)) {
192 if (!symbol_conf.use_callchain)
193 printf(" ");
194 else
195 printf("\n");
196 perf_session__print_symbols(event, sample, session);
197 }
198
199 printf("\n");
200}
22 201
23static int default_start_script(const char *script __unused, 202static int default_start_script(const char *script __unused,
24 int argc __unused, 203 int argc __unused,
@@ -40,7 +219,7 @@ static int default_generate_script(const char *outfile __unused)
40static struct scripting_ops default_scripting_ops = { 219static struct scripting_ops default_scripting_ops = {
41 .start_script = default_start_script, 220 .start_script = default_start_script,
42 .stop_script = default_stop_script, 221 .stop_script = default_stop_script,
43 .process_event = print_event, 222 .process_event = process_event,
44 .generate_script = default_generate_script, 223 .generate_script = default_generate_script,
45}; 224};
46 225
@@ -75,26 +254,17 @@ static int process_sample_event(union perf_event *event,
75 return -1; 254 return -1;
76 } 255 }
77 256
78 if (session->sample_type & PERF_SAMPLE_RAW) { 257 if (debug_mode) {
79 if (debug_mode) { 258 if (sample->time < last_timestamp) {
80 if (sample->time < last_timestamp) { 259 pr_err("Samples misordered, previous: %" PRIu64
81 pr_err("Samples misordered, previous: %" PRIu64 260 " this: %" PRIu64 "\n", last_timestamp,
82 " this: %" PRIu64 "\n", last_timestamp, 261 sample->time);
83 sample->time); 262 nr_unordered++;
84 nr_unordered++;
85 }
86 last_timestamp = sample->time;
87 return 0;
88 } 263 }
89 /* 264 last_timestamp = sample->time;
90 * FIXME: better resolve from pid from the struct trace_entry 265 return 0;
91 * field, although it should be the same than this perf
92 * event pid
93 */
94 scripting_ops->process_event(sample->cpu, sample->raw_data,
95 sample->raw_size,
96 sample->time, thread->comm);
97 } 266 }
267 scripting_ops->process_event(event, sample, session, thread);
98 268
99 session->hists.stats.total_period += sample->period; 269 session->hists.stats.total_period += sample->period;
100 return 0; 270 return 0;
@@ -102,7 +272,10 @@ static int process_sample_event(union perf_event *event,
102 272
103static struct perf_event_ops event_ops = { 273static struct perf_event_ops event_ops = {
104 .sample = process_sample_event, 274 .sample = process_sample_event,
275 .mmap = perf_event__process_mmap,
105 .comm = perf_event__process_comm, 276 .comm = perf_event__process_comm,
277 .exit = perf_event__process_task,
278 .fork = perf_event__process_task,
106 .attr = perf_event__process_attr, 279 .attr = perf_event__process_attr,
107 .event_type = perf_event__process_event_type, 280 .event_type = perf_event__process_event_type,
108 .tracing_data = perf_event__process_tracing_data, 281 .tracing_data = perf_event__process_tracing_data,
@@ -280,6 +453,68 @@ static int parse_scriptname(const struct option *opt __used,
280 return 0; 453 return 0;
281} 454}
282 455
456static int parse_output_fields(const struct option *opt __used,
457 const char *arg, int unset __used)
458{
459 char *tok;
460 int i, imax = sizeof(all_output_options) / sizeof(struct output_option);
461 int rc = 0;
462 char *str = strdup(arg);
463 int type = -1;
464
465 if (!str)
466 return -ENOMEM;
467
468 tok = strtok(str, ":");
469 if (!tok) {
470 fprintf(stderr,
471 "Invalid field string - not prepended with type.");
472 return -EINVAL;
473 }
474
475 /* first word should state which event type user
476 * is specifying the fields
477 */
478 if (!strcmp(tok, "hw"))
479 type = PERF_TYPE_HARDWARE;
480 else if (!strcmp(tok, "sw"))
481 type = PERF_TYPE_SOFTWARE;
482 else if (!strcmp(tok, "trace"))
483 type = PERF_TYPE_TRACEPOINT;
484 else {
485 fprintf(stderr, "Invalid event type in field string.");
486 return -EINVAL;
487 }
488
489 output_fields[type] = 0;
490 while (1) {
491 tok = strtok(NULL, ",");
492 if (!tok)
493 break;
494 for (i = 0; i < imax; ++i) {
495 if (strcmp(tok, all_output_options[i].str) == 0) {
496 output_fields[type] |= all_output_options[i].field;
497 break;
498 }
499 }
500 if (i == imax) {
501 fprintf(stderr, "Invalid field requested.");
502 rc = -EINVAL;
503 break;
504 }
505 }
506
507 if (output_fields[type] == 0) {
508 pr_debug("No fields requested for %s type. "
509 "Events will not be displayed\n", event_type(type));
510 }
511
512 output_set_by_user = true;
513
514 free(str);
515 return rc;
516}
517
283/* Helper function for filesystems that return a dent->d_type DT_UNKNOWN */ 518/* Helper function for filesystems that return a dent->d_type DT_UNKNOWN */
284static int is_directory(const char *base_path, const struct dirent *dent) 519static int is_directory(const char *base_path, const struct dirent *dent)
285{ 520{
@@ -592,6 +827,17 @@ static const struct option options[] = {
592 "input file name"), 827 "input file name"),
593 OPT_BOOLEAN('d', "debug-mode", &debug_mode, 828 OPT_BOOLEAN('d', "debug-mode", &debug_mode,
594 "do various checks like samples ordering and lost events"), 829 "do various checks like samples ordering and lost events"),
830 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
831 "file", "vmlinux pathname"),
832 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
833 "file", "kallsyms pathname"),
834 OPT_BOOLEAN('G', "hide-call-graph", &no_callchain,
835 "When printing symbols do not display call chain"),
836 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
837 "Look for files with symbols relative to this directory"),
838 OPT_CALLBACK('f', "fields", NULL, "str",
839 "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace. Fields: comm,tid,pid,time,cpu,event,trace,sym",
840 parse_output_fields),
595 841
596 OPT_END() 842 OPT_END()
597}; 843};
@@ -772,14 +1018,22 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
772 if (session == NULL) 1018 if (session == NULL)
773 return -ENOMEM; 1019 return -ENOMEM;
774 1020
775 if (strcmp(input_name, "-") && 1021 if (!no_callchain)
776 !perf_session__has_traces(session, "record -R")) 1022 symbol_conf.use_callchain = true;
777 return -EINVAL; 1023 else
1024 symbol_conf.use_callchain = false;
778 1025
779 if (generate_script_lang) { 1026 if (generate_script_lang) {
780 struct stat perf_stat; 1027 struct stat perf_stat;
1028 int input;
1029
1030 if (output_set_by_user) {
1031 fprintf(stderr,
1032 "custom fields not supported for generated scripts");
1033 return -1;
1034 }
781 1035
782 int input = open(input_name, O_RDONLY); 1036 input = open(input_name, O_RDONLY);
783 if (input < 0) { 1037 if (input < 0) {
784 perror("failed to open file"); 1038 perror("failed to open file");
785 exit(-1); 1039 exit(-1);
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 21c025222496..e2109f9b43eb 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -333,6 +333,12 @@ static int run_perf_stat(int argc __used, const char **argv)
333 } 333 }
334 } 334 }
335 335
336 if (perf_evlist__set_filters(evsel_list)) {
337 error("failed to set filter with %d (%s)\n", errno,
338 strerror(errno));
339 return -1;
340 }
341
336 /* 342 /*
337 * Enable counters and exec the command: 343 * Enable counters and exec the command:
338 */ 344 */
@@ -634,6 +640,8 @@ static const struct option options[] = {
634 OPT_CALLBACK('e', "event", &evsel_list, "event", 640 OPT_CALLBACK('e', "event", &evsel_list, "event",
635 "event selector. use 'perf list' to list available events", 641 "event selector. use 'perf list' to list available events",
636 parse_events), 642 parse_events),
643 OPT_CALLBACK(0, "filter", &evsel_list, "filter",
644 "event filter", parse_filter),
637 OPT_BOOLEAN('i', "no-inherit", &no_inherit, 645 OPT_BOOLEAN('i', "no-inherit", &no_inherit,
638 "child tasks do not inherit counters"), 646 "child tasks do not inherit counters"),
639 OPT_INTEGER('p', "pid", &target_pid, 647 OPT_INTEGER('p', "pid", &target_pid,
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 80c9e062bd5b..70f1075cc5b0 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -152,7 +152,7 @@ static int parse_source(struct sym_entry *syme)
152 /* 152 /*
153 * We can't annotate with just /proc/kallsyms 153 * We can't annotate with just /proc/kallsyms
154 */ 154 */
155 if (map->dso->origin == DSO__ORIG_KERNEL) { 155 if (map->dso->symtab_type == SYMTAB__KALLSYMS) {
156 pr_err("Can't annotate %s: No vmlinux file was found in the " 156 pr_err("Can't annotate %s: No vmlinux file was found in the "
157 "path\n", sym->name); 157 "path\n", sym->name);
158 sleep(1); 158 sleep(1);
@@ -515,24 +515,25 @@ static void handle_keypress(struct perf_session *session, int c)
515 break; 515 break;
516 case 'E': 516 case 'E':
517 if (top.evlist->nr_entries > 1) { 517 if (top.evlist->nr_entries > 1) {
518 int counter;
518 fprintf(stderr, "\nAvailable events:"); 519 fprintf(stderr, "\nAvailable events:");
519 520
520 list_for_each_entry(top.sym_evsel, &top.evlist->entries, node) 521 list_for_each_entry(top.sym_evsel, &top.evlist->entries, node)
521 fprintf(stderr, "\n\t%d %s", top.sym_evsel->idx, event_name(top.sym_evsel)); 522 fprintf(stderr, "\n\t%d %s", top.sym_evsel->idx, event_name(top.sym_evsel));
522 523
523 prompt_integer(&top.sym_counter, "Enter details event counter"); 524 prompt_integer(&counter, "Enter details event counter");
524 525
525 if (top.sym_counter >= top.evlist->nr_entries) { 526 if (counter >= top.evlist->nr_entries) {
526 top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node); 527 top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node);
527 top.sym_counter = 0;
528 fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(top.sym_evsel)); 528 fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(top.sym_evsel));
529 sleep(1); 529 sleep(1);
530 break; 530 break;
531 } 531 }
532 list_for_each_entry(top.sym_evsel, &top.evlist->entries, node) 532 list_for_each_entry(top.sym_evsel, &top.evlist->entries, node)
533 if (top.sym_evsel->idx == top.sym_counter) 533 if (top.sym_evsel->idx == counter)
534 break; 534 break;
535 } else top.sym_counter = 0; 535 } else
536 top.sym_evsel = list_entry(top.evlist->entries.next, struct perf_evsel, node);
536 break; 537 break;
537 case 'f': 538 case 'f':
538 prompt_integer(&top.count_filter, "Enter display event count filter"); 539 prompt_integer(&top.count_filter, "Enter display event count filter");
@@ -675,7 +676,7 @@ static int symbol_filter(struct map *map, struct symbol *sym)
675 676
676 for (i = 0; skip_symbols[i]; i++) { 677 for (i = 0; skip_symbols[i]; i++) {
677 if (!strcmp(skip_symbols[i], name)) { 678 if (!strcmp(skip_symbols[i], name)) {
678 syme->skip = 1; 679 sym->ignore = true;
679 break; 680 break;
680 } 681 }
681 } 682 }
@@ -768,7 +769,7 @@ static void perf_event__process_sample(const union perf_event *event,
768 struct symbol *sym = sym_entry__symbol(top.sym_filter_entry); 769 struct symbol *sym = sym_entry__symbol(top.sym_filter_entry);
769 770
770 pr_err("Can't annotate %s", sym->name); 771 pr_err("Can't annotate %s", sym->name);
771 if (top.sym_filter_entry->map->dso->origin == DSO__ORIG_KERNEL) { 772 if (top.sym_filter_entry->map->dso->symtab_type == SYMTAB__KALLSYMS) {
772 pr_err(": No vmlinux file was found in the path:\n"); 773 pr_err(": No vmlinux file was found in the path:\n");
773 machine__fprintf_vmlinux_path(machine, stderr); 774 machine__fprintf_vmlinux_path(machine, stderr);
774 } else 775 } else
@@ -778,10 +779,9 @@ static void perf_event__process_sample(const union perf_event *event,
778 } 779 }
779 780
780 syme = symbol__priv(al.sym); 781 syme = symbol__priv(al.sym);
781 if (!syme->skip) { 782 if (!al.sym->ignore) {
782 struct perf_evsel *evsel; 783 struct perf_evsel *evsel;
783 784
784 syme->origin = origin;
785 evsel = perf_evlist__id2evsel(top.evlist, sample->id); 785 evsel = perf_evlist__id2evsel(top.evlist, sample->id);
786 assert(evsel != NULL); 786 assert(evsel != NULL);
787 syme->count[evsel->idx]++; 787 syme->count[evsel->idx]++;
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index c7798c7f24ed..4702e2443a8e 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -19,6 +19,7 @@ extern int cmd_bench(int argc, const char **argv, const char *prefix);
19extern int cmd_buildid_cache(int argc, const char **argv, const char *prefix); 19extern int cmd_buildid_cache(int argc, const char **argv, const char *prefix);
20extern int cmd_buildid_list(int argc, const char **argv, const char *prefix); 20extern int cmd_buildid_list(int argc, const char **argv, const char *prefix);
21extern int cmd_diff(int argc, const char **argv, const char *prefix); 21extern int cmd_diff(int argc, const char **argv, const char *prefix);
22extern int cmd_evlist(int argc, const char **argv, const char *prefix);
22extern int cmd_help(int argc, const char **argv, const char *prefix); 23extern int cmd_help(int argc, const char **argv, const char *prefix);
23extern int cmd_sched(int argc, const char **argv, const char *prefix); 24extern int cmd_sched(int argc, const char **argv, const char *prefix);
24extern int cmd_list(int argc, const char **argv, const char *prefix); 25extern int cmd_list(int argc, const char **argv, const char *prefix);
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index 16b5088cf8f4..d695fe40fbff 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -8,6 +8,7 @@ perf-bench mainporcelain common
8perf-buildid-cache mainporcelain common 8perf-buildid-cache mainporcelain common
9perf-buildid-list mainporcelain common 9perf-buildid-list mainporcelain common
10perf-diff mainporcelain common 10perf-diff mainporcelain common
11perf-evlist mainporcelain common
11perf-inject mainporcelain common 12perf-inject mainporcelain common
12perf-list mainporcelain common 13perf-list mainporcelain common
13perf-sched mainporcelain common 14perf-sched mainporcelain common
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 595d0f4a7103..ec635b7cc8ea 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -313,6 +313,7 @@ static void handle_internal_command(int argc, const char **argv)
313 { "buildid-cache", cmd_buildid_cache, 0 }, 313 { "buildid-cache", cmd_buildid_cache, 0 },
314 { "buildid-list", cmd_buildid_list, 0 }, 314 { "buildid-list", cmd_buildid_list, 0 },
315 { "diff", cmd_diff, 0 }, 315 { "diff", cmd_diff, 0 },
316 { "evlist", cmd_evlist, 0 },
316 { "help", cmd_help, 0 }, 317 { "help", cmd_help, 0 },
317 { "list", cmd_list, 0 }, 318 { "list", cmd_list, 0 },
318 { "record", cmd_record, 0 }, 319 { "record", cmd_record, 0 },
diff --git a/tools/perf/util/PERF-VERSION-GEN b/tools/perf/util/PERF-VERSION-GEN
index 97d76562a1a0..26d4d3fd6deb 100755
--- a/tools/perf/util/PERF-VERSION-GEN
+++ b/tools/perf/util/PERF-VERSION-GEN
@@ -23,10 +23,10 @@ if test -d ../../.git -o -f ../../.git &&
23then 23then
24 VN=$(echo "$VN" | sed -e 's/-/./g'); 24 VN=$(echo "$VN" | sed -e 's/-/./g');
25else 25else
26 eval `grep '^VERSION\s*=' ../../Makefile|tr -d ' '` 26 eval $(grep '^VERSION[[:space:]]*=' ../../Makefile|tr -d ' ')
27 eval `grep '^PATCHLEVEL\s*=' ../../Makefile|tr -d ' '` 27 eval $(grep '^PATCHLEVEL[[:space:]]*=' ../../Makefile|tr -d ' ')
28 eval `grep '^SUBLEVEL\s*=' ../../Makefile|tr -d ' '` 28 eval $(grep '^SUBLEVEL[[:space:]]*=' ../../Makefile|tr -d ' ')
29 eval `grep '^EXTRAVERSION\s*=' ../../Makefile|tr -d ' '` 29 eval $(grep '^EXTRAVERSION[[:space:]]*=' ../../Makefile|tr -d ' ')
30 30
31 VN="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}${EXTRAVERSION}" 31 VN="${VERSION}.${PATCHLEVEL}.${SUBLEVEL}${EXTRAVERSION}"
32fi 32fi
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 0d0830c98cd7..e01af2b1a469 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -294,7 +294,7 @@ fallback:
294 free_filename = false; 294 free_filename = false;
295 } 295 }
296 296
297 if (dso->origin == DSO__ORIG_KERNEL) { 297 if (dso->symtab_type == SYMTAB__KALLSYMS) {
298 char bf[BUILD_ID_SIZE * 2 + 16] = " with build id "; 298 char bf[BUILD_ID_SIZE * 2 + 16] = " with build id ";
299 char *build_id_msg = NULL; 299 char *build_id_msg = NULL;
300 300
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 54a7e2634d58..952b4ae3d954 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -263,6 +263,28 @@ static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
263 return name; 263 return name;
264} 264}
265 265
266const char *event_type(int type)
267{
268 switch (type) {
269 case PERF_TYPE_HARDWARE:
270 return "hardware";
271
272 case PERF_TYPE_SOFTWARE:
273 return "software";
274
275 case PERF_TYPE_TRACEPOINT:
276 return "tracepoint";
277
278 case PERF_TYPE_HW_CACHE:
279 return "hardware-cache";
280
281 default:
282 break;
283 }
284
285 return "unknown";
286}
287
266const char *event_name(struct perf_evsel *evsel) 288const char *event_name(struct perf_evsel *evsel)
267{ 289{
268 u64 config = evsel->attr.config; 290 u64 config = evsel->attr.config;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 212f88e07a9c..746d3fcbfc2a 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -20,6 +20,7 @@ struct tracepoint_path {
20extern struct tracepoint_path *tracepoint_id_to_path(u64 config); 20extern struct tracepoint_path *tracepoint_id_to_path(u64 config);
21extern bool have_tracepoints(struct list_head *evlist); 21extern bool have_tracepoints(struct list_head *evlist);
22 22
23const char *event_type(int type);
23const char *event_name(struct perf_evsel *event); 24const char *event_name(struct perf_evsel *event);
24extern const char *__event_name(int type, u64 config); 25extern const char *__event_name(int type, u64 config);
25 26
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 93680818e244..621427212e86 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -245,9 +245,10 @@ static inline struct event *find_cache_event(int type)
245 return event; 245 return event;
246} 246}
247 247
248static void perl_process_event(int cpu, void *data, 248static void perl_process_event(union perf_event *pevent __unused,
249 int size __unused, 249 struct perf_sample *sample,
250 unsigned long long nsecs, char *comm) 250 struct perf_session *session __unused,
251 struct thread *thread)
251{ 252{
252 struct format_field *field; 253 struct format_field *field;
253 static char handler[256]; 254 static char handler[256];
@@ -256,6 +257,10 @@ static void perl_process_event(int cpu, void *data,
256 struct event *event; 257 struct event *event;
257 int type; 258 int type;
258 int pid; 259 int pid;
260 int cpu = sample->cpu;
261 void *data = sample->raw_data;
262 unsigned long long nsecs = sample->time;
263 char *comm = thread->comm;
259 264
260 dSP; 265 dSP;
261 266
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 2040b8538527..1b85d6055159 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -204,9 +204,10 @@ static inline struct event *find_cache_event(int type)
204 return event; 204 return event;
205} 205}
206 206
207static void python_process_event(int cpu, void *data, 207static void python_process_event(union perf_event *pevent __unused,
208 int size __unused, 208 struct perf_sample *sample,
209 unsigned long long nsecs, char *comm) 209 struct perf_session *session __unused,
210 struct thread *thread)
210{ 211{
211 PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; 212 PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
212 static char handler_name[256]; 213 static char handler_name[256];
@@ -217,6 +218,10 @@ static void python_process_event(int cpu, void *data,
217 unsigned n = 0; 218 unsigned n = 0;
218 int type; 219 int type;
219 int pid; 220 int pid;
221 int cpu = sample->cpu;
222 void *data = sample->raw_data;
223 unsigned long long nsecs = sample->time;
224 char *comm = thread->comm;
220 225
221 t = PyTuple_New(MAX_FIELDS); 226 t = PyTuple_New(MAX_FIELDS);
222 if (!t) 227 if (!t)
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index f26639fa0fb3..c68cf40764f9 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1134,3 +1134,64 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1134 1134
1135 return ret; 1135 return ret;
1136} 1136}
1137
1138void perf_session__print_symbols(union perf_event *event,
1139 struct perf_sample *sample,
1140 struct perf_session *session)
1141{
1142 struct addr_location al;
1143 const char *symname, *dsoname;
1144 struct callchain_cursor *cursor = &session->callchain_cursor;
1145 struct callchain_cursor_node *node;
1146
1147 if (perf_event__preprocess_sample(event, session, &al, sample,
1148 NULL) < 0) {
1149 error("problem processing %d event, skipping it.\n",
1150 event->header.type);
1151 return;
1152 }
1153
1154 if (symbol_conf.use_callchain && sample->callchain) {
1155
1156 if (perf_session__resolve_callchain(session, al.thread,
1157 sample->callchain, NULL) != 0) {
1158 if (verbose)
1159 error("Failed to resolve callchain. Skipping\n");
1160 return;
1161 }
1162 callchain_cursor_commit(cursor);
1163
1164 while (1) {
1165 node = callchain_cursor_current(cursor);
1166 if (!node)
1167 break;
1168
1169 if (node->sym && node->sym->name)
1170 symname = node->sym->name;
1171 else
1172 symname = "";
1173
1174 if (node->map && node->map->dso && node->map->dso->name)
1175 dsoname = node->map->dso->name;
1176 else
1177 dsoname = "";
1178
1179 printf("\t%16" PRIx64 " %s (%s)\n", node->ip, symname, dsoname);
1180
1181 callchain_cursor_advance(cursor);
1182 }
1183
1184 } else {
1185 if (al.sym && al.sym->name)
1186 symname = al.sym->name;
1187 else
1188 symname = "";
1189
1190 if (al.map && al.map->dso && al.map->dso->name)
1191 dsoname = al.map->dso->name;
1192 else
1193 dsoname = "";
1194
1195 printf("%16" PRIx64 " %s (%s)", al.addr, symname, dsoname);
1196 }
1197}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index b5b148b0aaca..0b3c9afecaa9 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -159,4 +159,8 @@ static inline int perf_session__parse_sample(struct perf_session *session,
159 session->sample_id_all, sample); 159 session->sample_id_all, sample);
160} 160}
161 161
162void perf_session__print_symbols(union perf_event *event,
163 struct perf_sample *sample,
164 struct perf_session *session);
165
162#endif /* __PERF_SESSION_H */ 166#endif /* __PERF_SESSION_H */
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 00014e32c288..651dbfe7f4f3 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -207,7 +207,7 @@ struct dso *dso__new(const char *name)
207 dso__set_short_name(self, self->name); 207 dso__set_short_name(self, self->name);
208 for (i = 0; i < MAP__NR_TYPES; ++i) 208 for (i = 0; i < MAP__NR_TYPES; ++i)
209 self->symbols[i] = self->symbol_names[i] = RB_ROOT; 209 self->symbols[i] = self->symbol_names[i] = RB_ROOT;
210 self->origin = DSO__ORIG_NOT_FOUND; 210 self->symtab_type = SYMTAB__NOT_FOUND;
211 self->loaded = 0; 211 self->loaded = 0;
212 self->sorted_by_name = 0; 212 self->sorted_by_name = 0;
213 self->has_build_id = 0; 213 self->has_build_id = 0;
@@ -680,9 +680,9 @@ int dso__load_kallsyms(struct dso *self, const char *filename,
680 return -1; 680 return -1;
681 681
682 if (self->kernel == DSO_TYPE_GUEST_KERNEL) 682 if (self->kernel == DSO_TYPE_GUEST_KERNEL)
683 self->origin = DSO__ORIG_GUEST_KERNEL; 683 self->symtab_type = SYMTAB__GUEST_KALLSYMS;
684 else 684 else
685 self->origin = DSO__ORIG_KERNEL; 685 self->symtab_type = SYMTAB__KALLSYMS;
686 686
687 return dso__split_kallsyms(self, map, filter); 687 return dso__split_kallsyms(self, map, filter);
688} 688}
@@ -1204,7 +1204,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
1204 } 1204 }
1205 curr_map->map_ip = identity__map_ip; 1205 curr_map->map_ip = identity__map_ip;
1206 curr_map->unmap_ip = identity__map_ip; 1206 curr_map->unmap_ip = identity__map_ip;
1207 curr_dso->origin = self->origin; 1207 curr_dso->symtab_type = self->symtab_type;
1208 map_groups__insert(kmap->kmaps, curr_map); 1208 map_groups__insert(kmap->kmaps, curr_map);
1209 dsos__add(&self->node, curr_dso); 1209 dsos__add(&self->node, curr_dso);
1210 dso__set_loaded(curr_dso, map->type); 1210 dso__set_loaded(curr_dso, map->type);
@@ -1430,21 +1430,21 @@ out:
1430char dso__symtab_origin(const struct dso *self) 1430char dso__symtab_origin(const struct dso *self)
1431{ 1431{
1432 static const char origin[] = { 1432 static const char origin[] = {
1433 [DSO__ORIG_KERNEL] = 'k', 1433 [SYMTAB__KALLSYMS] = 'k',
1434 [DSO__ORIG_JAVA_JIT] = 'j', 1434 [SYMTAB__JAVA_JIT] = 'j',
1435 [DSO__ORIG_BUILD_ID_CACHE] = 'B', 1435 [SYMTAB__BUILD_ID_CACHE] = 'B',
1436 [DSO__ORIG_FEDORA] = 'f', 1436 [SYMTAB__FEDORA_DEBUGINFO] = 'f',
1437 [DSO__ORIG_UBUNTU] = 'u', 1437 [SYMTAB__UBUNTU_DEBUGINFO] = 'u',
1438 [DSO__ORIG_BUILDID] = 'b', 1438 [SYMTAB__BUILDID_DEBUGINFO] = 'b',
1439 [DSO__ORIG_DSO] = 'd', 1439 [SYMTAB__SYSTEM_PATH_DSO] = 'd',
1440 [DSO__ORIG_KMODULE] = 'K', 1440 [SYMTAB__SYSTEM_PATH_KMODULE] = 'K',
1441 [DSO__ORIG_GUEST_KERNEL] = 'g', 1441 [SYMTAB__GUEST_KALLSYMS] = 'g',
1442 [DSO__ORIG_GUEST_KMODULE] = 'G', 1442 [SYMTAB__GUEST_KMODULE] = 'G',
1443 }; 1443 };
1444 1444
1445 if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND) 1445 if (self == NULL || self->symtab_type == SYMTAB__NOT_FOUND)
1446 return '!'; 1446 return '!';
1447 return origin[self->origin]; 1447 return origin[self->symtab_type];
1448} 1448}
1449 1449
1450int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) 1450int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
@@ -1477,8 +1477,8 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1477 1477
1478 if (strncmp(self->name, "/tmp/perf-", 10) == 0) { 1478 if (strncmp(self->name, "/tmp/perf-", 10) == 0) {
1479 ret = dso__load_perf_map(self, map, filter); 1479 ret = dso__load_perf_map(self, map, filter);
1480 self->origin = ret > 0 ? DSO__ORIG_JAVA_JIT : 1480 self->symtab_type = ret > 0 ? SYMTAB__JAVA_JIT :
1481 DSO__ORIG_NOT_FOUND; 1481 SYMTAB__NOT_FOUND;
1482 return ret; 1482 return ret;
1483 } 1483 }
1484 1484
@@ -1486,26 +1486,26 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1486 * On the first pass, only load images if they have a full symtab. 1486 * On the first pass, only load images if they have a full symtab.
1487 * Failing that, do a second pass where we accept .dynsym also 1487 * Failing that, do a second pass where we accept .dynsym also
1488 */ 1488 */
1489 for (self->origin = DSO__ORIG_BUILD_ID_CACHE, want_symtab = 1; 1489 for (self->symtab_type = SYMTAB__BUILD_ID_CACHE, want_symtab = 1;
1490 self->origin != DSO__ORIG_NOT_FOUND; 1490 self->symtab_type != SYMTAB__NOT_FOUND;
1491 self->origin++) { 1491 self->symtab_type++) {
1492 switch (self->origin) { 1492 switch (self->symtab_type) {
1493 case DSO__ORIG_BUILD_ID_CACHE: 1493 case SYMTAB__BUILD_ID_CACHE:
1494 /* skip the locally configured cache if a symfs is given */ 1494 /* skip the locally configured cache if a symfs is given */
1495 if (symbol_conf.symfs[0] || 1495 if (symbol_conf.symfs[0] ||
1496 (dso__build_id_filename(self, name, size) == NULL)) { 1496 (dso__build_id_filename(self, name, size) == NULL)) {
1497 continue; 1497 continue;
1498 } 1498 }
1499 break; 1499 break;
1500 case DSO__ORIG_FEDORA: 1500 case SYMTAB__FEDORA_DEBUGINFO:
1501 snprintf(name, size, "%s/usr/lib/debug%s.debug", 1501 snprintf(name, size, "%s/usr/lib/debug%s.debug",
1502 symbol_conf.symfs, self->long_name); 1502 symbol_conf.symfs, self->long_name);
1503 break; 1503 break;
1504 case DSO__ORIG_UBUNTU: 1504 case SYMTAB__UBUNTU_DEBUGINFO:
1505 snprintf(name, size, "%s/usr/lib/debug%s", 1505 snprintf(name, size, "%s/usr/lib/debug%s",
1506 symbol_conf.symfs, self->long_name); 1506 symbol_conf.symfs, self->long_name);
1507 break; 1507 break;
1508 case DSO__ORIG_BUILDID: { 1508 case SYMTAB__BUILDID_DEBUGINFO: {
1509 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 1509 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
1510 1510
1511 if (!self->has_build_id) 1511 if (!self->has_build_id)
@@ -1519,11 +1519,11 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1519 symbol_conf.symfs, build_id_hex, build_id_hex + 2); 1519 symbol_conf.symfs, build_id_hex, build_id_hex + 2);
1520 } 1520 }
1521 break; 1521 break;
1522 case DSO__ORIG_DSO: 1522 case SYMTAB__SYSTEM_PATH_DSO:
1523 snprintf(name, size, "%s%s", 1523 snprintf(name, size, "%s%s",
1524 symbol_conf.symfs, self->long_name); 1524 symbol_conf.symfs, self->long_name);
1525 break; 1525 break;
1526 case DSO__ORIG_GUEST_KMODULE: 1526 case SYMTAB__GUEST_KMODULE:
1527 if (map->groups && machine) 1527 if (map->groups && machine)
1528 root_dir = machine->root_dir; 1528 root_dir = machine->root_dir;
1529 else 1529 else
@@ -1532,7 +1532,7 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1532 root_dir, self->long_name); 1532 root_dir, self->long_name);
1533 break; 1533 break;
1534 1534
1535 case DSO__ORIG_KMODULE: 1535 case SYMTAB__SYSTEM_PATH_KMODULE:
1536 snprintf(name, size, "%s%s", symbol_conf.symfs, 1536 snprintf(name, size, "%s%s", symbol_conf.symfs,
1537 self->long_name); 1537 self->long_name);
1538 break; 1538 break;
@@ -1544,7 +1544,7 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1544 */ 1544 */
1545 if (want_symtab) { 1545 if (want_symtab) {
1546 want_symtab = 0; 1546 want_symtab = 0;
1547 self->origin = DSO__ORIG_BUILD_ID_CACHE; 1547 self->symtab_type = SYMTAB__BUILD_ID_CACHE;
1548 } else 1548 } else
1549 continue; 1549 continue;
1550 } 1550 }
@@ -1757,9 +1757,9 @@ struct map *machine__new_module(struct machine *self, u64 start,
1757 return NULL; 1757 return NULL;
1758 1758
1759 if (machine__is_host(self)) 1759 if (machine__is_host(self))
1760 dso->origin = DSO__ORIG_KMODULE; 1760 dso->symtab_type = SYMTAB__SYSTEM_PATH_KMODULE;
1761 else 1761 else
1762 dso->origin = DSO__ORIG_GUEST_KMODULE; 1762 dso->symtab_type = SYMTAB__GUEST_KMODULE;
1763 map_groups__insert(&self->kmaps, map); 1763 map_groups__insert(&self->kmaps, map);
1764 return map; 1764 return map;
1765} 1765}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 4d7ed09fe332..713b0b40cc4a 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -48,12 +48,17 @@ char *strxfrchar(char *s, char from, char to);
48 48
49#define BUILD_ID_SIZE 20 49#define BUILD_ID_SIZE 20
50 50
51/** struct symbol - symtab entry
52 *
53 * @ignore - resolvable but tools ignore it (e.g. idle routines)
54 */
51struct symbol { 55struct symbol {
52 struct rb_node rb_node; 56 struct rb_node rb_node;
53 u64 start; 57 u64 start;
54 u64 end; 58 u64 end;
55 u16 namelen; 59 u16 namelen;
56 u8 binding; 60 u8 binding;
61 bool ignore;
57 char name[0]; 62 char name[0];
58}; 63};
59 64
@@ -137,7 +142,7 @@ struct dso {
137 u8 annotate_warned:1; 142 u8 annotate_warned:1;
138 u8 sname_alloc:1; 143 u8 sname_alloc:1;
139 u8 lname_alloc:1; 144 u8 lname_alloc:1;
140 unsigned char origin; 145 unsigned char symtab_type;
141 u8 sorted_by_name; 146 u8 sorted_by_name;
142 u8 loaded; 147 u8 loaded;
143 u8 build_id[BUILD_ID_SIZE]; 148 u8 build_id[BUILD_ID_SIZE];
@@ -188,18 +193,18 @@ size_t dso__fprintf_buildid(struct dso *self, FILE *fp);
188size_t dso__fprintf_symbols_by_name(struct dso *self, enum map_type type, FILE *fp); 193size_t dso__fprintf_symbols_by_name(struct dso *self, enum map_type type, FILE *fp);
189size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp); 194size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp);
190 195
191enum dso_origin { 196enum symtab_type {
192 DSO__ORIG_KERNEL = 0, 197 SYMTAB__KALLSYMS = 0,
193 DSO__ORIG_GUEST_KERNEL, 198 SYMTAB__GUEST_KALLSYMS,
194 DSO__ORIG_JAVA_JIT, 199 SYMTAB__JAVA_JIT,
195 DSO__ORIG_BUILD_ID_CACHE, 200 SYMTAB__BUILD_ID_CACHE,
196 DSO__ORIG_FEDORA, 201 SYMTAB__FEDORA_DEBUGINFO,
197 DSO__ORIG_UBUNTU, 202 SYMTAB__UBUNTU_DEBUGINFO,
198 DSO__ORIG_BUILDID, 203 SYMTAB__BUILDID_DEBUGINFO,
199 DSO__ORIG_DSO, 204 SYMTAB__SYSTEM_PATH_DSO,
200 DSO__ORIG_GUEST_KMODULE, 205 SYMTAB__GUEST_KMODULE,
201 DSO__ORIG_KMODULE, 206 SYMTAB__SYSTEM_PATH_KMODULE,
202 DSO__ORIG_NOT_FOUND, 207 SYMTAB__NOT_FOUND,
203}; 208};
204 209
205char dso__symtab_origin(const struct dso *self); 210char dso__symtab_origin(const struct dso *self);
diff --git a/tools/perf/util/top.c b/tools/perf/util/top.c
index 75cfe4d45119..a11f60735a18 100644
--- a/tools/perf/util/top.c
+++ b/tools/perf/util/top.c
@@ -171,7 +171,7 @@ float perf_top__decay_samples(struct perf_top *top, struct rb_root *root)
171{ 171{
172 struct sym_entry *syme, *n; 172 struct sym_entry *syme, *n;
173 float sum_ksamples = 0.0; 173 float sum_ksamples = 0.0;
174 int snap = !top->display_weighted ? top->sym_counter : 0, j; 174 int snap = !top->display_weighted ? top->sym_evsel->idx : 0, j;
175 175
176 /* Sort the active symbols */ 176 /* Sort the active symbols */
177 pthread_mutex_lock(&top->active_symbols_lock); 177 pthread_mutex_lock(&top->active_symbols_lock);
@@ -184,9 +184,9 @@ float perf_top__decay_samples(struct perf_top *top, struct rb_root *root)
184 if (syme->snap_count != 0) { 184 if (syme->snap_count != 0) {
185 185
186 if ((top->hide_user_symbols && 186 if ((top->hide_user_symbols &&
187 syme->origin == PERF_RECORD_MISC_USER) || 187 syme->map->dso->kernel == DSO_TYPE_USER) ||
188 (top->hide_kernel_symbols && 188 (top->hide_kernel_symbols &&
189 syme->origin == PERF_RECORD_MISC_KERNEL)) { 189 syme->map->dso->kernel == DSO_TYPE_KERNEL)) {
190 perf_top__remove_active_sym(top, syme); 190 perf_top__remove_active_sym(top, syme);
191 continue; 191 continue;
192 } 192 }
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 96d1cb78af01..bfbf95bcc603 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -16,8 +16,6 @@ struct sym_entry {
16 struct list_head node; 16 struct list_head node;
17 unsigned long snap_count; 17 unsigned long snap_count;
18 double weight; 18 double weight;
19 int skip;
20 u8 origin;
21 struct map *map; 19 struct map *map;
22 unsigned long count[0]; 20 unsigned long count[0];
23}; 21};
@@ -41,7 +39,7 @@ struct perf_top {
41 u64 exact_samples; 39 u64 exact_samples;
42 u64 guest_us_samples, guest_kernel_samples; 40 u64 guest_us_samples, guest_kernel_samples;
43 int print_entries, count_filter, delay_secs; 41 int print_entries, count_filter, delay_secs;
44 int display_weighted, freq, rb_entries, sym_counter; 42 int display_weighted, freq, rb_entries;
45 pid_t target_pid, target_tid; 43 pid_t target_pid, target_tid;
46 bool hide_kernel_symbols, hide_user_symbols, zero; 44 bool hide_kernel_symbols, hide_user_symbols, zero;
47 const char *cpu_list; 45 const char *cpu_list;
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index d8e622dd738a..0a7ed5b5e281 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -2643,68 +2643,13 @@ static void print_lat_fmt(void *data, int size __unused)
2643 printf("."); 2643 printf(".");
2644 2644
2645 if (lock_depth < 0) 2645 if (lock_depth < 0)
2646 printf("."); 2646 printf(". ");
2647 else 2647 else
2648 printf("%d", lock_depth); 2648 printf("%d ", lock_depth);
2649} 2649}
2650 2650
2651/* taken from Linux, written by Frederic Weisbecker */
2652static void print_graph_cpu(int cpu)
2653{
2654 int i;
2655 int log10_this = log10_cpu(cpu);
2656 int log10_all = log10_cpu(cpus);
2657
2658
2659 /*
2660 * Start with a space character - to make it stand out
2661 * to the right a bit when trace output is pasted into
2662 * email:
2663 */
2664 printf(" ");
2665
2666 /*
2667 * Tricky - we space the CPU field according to the max
2668 * number of online CPUs. On a 2-cpu system it would take
2669 * a maximum of 1 digit - on a 128 cpu system it would
2670 * take up to 3 digits:
2671 */
2672 for (i = 0; i < log10_all - log10_this; i++)
2673 printf(" ");
2674
2675 printf("%d) ", cpu);
2676}
2677
2678#define TRACE_GRAPH_PROCINFO_LENGTH 14
2679#define TRACE_GRAPH_INDENT 2 2651#define TRACE_GRAPH_INDENT 2
2680 2652
2681static void print_graph_proc(int pid, const char *comm)
2682{
2683 /* sign + log10(MAX_INT) + '\0' */
2684 char pid_str[11];
2685 int spaces = 0;
2686 int len;
2687 int i;
2688
2689 sprintf(pid_str, "%d", pid);
2690
2691 /* 1 stands for the "-" character */
2692 len = strlen(comm) + strlen(pid_str) + 1;
2693
2694 if (len < TRACE_GRAPH_PROCINFO_LENGTH)
2695 spaces = TRACE_GRAPH_PROCINFO_LENGTH - len;
2696
2697 /* First spaces to align center */
2698 for (i = 0; i < spaces / 2; i++)
2699 printf(" ");
2700
2701 printf("%s-%s", comm, pid_str);
2702
2703 /* Last spaces to align center */
2704 for (i = 0; i < spaces - (spaces / 2); i++)
2705 printf(" ");
2706}
2707
2708static struct record * 2653static struct record *
2709get_return_for_leaf(int cpu, int cur_pid, unsigned long long cur_func, 2654get_return_for_leaf(int cpu, int cur_pid, unsigned long long cur_func,
2710 struct record *next) 2655 struct record *next)
@@ -2876,21 +2821,13 @@ static void print_graph_nested(struct event *event, void *data)
2876 2821
2877static void 2822static void
2878pretty_print_func_ent(void *data, int size, struct event *event, 2823pretty_print_func_ent(void *data, int size, struct event *event,
2879 int cpu, int pid, const char *comm, 2824 int cpu, int pid)
2880 unsigned long secs, unsigned long usecs)
2881{ 2825{
2882 struct format_field *field; 2826 struct format_field *field;
2883 struct record *rec; 2827 struct record *rec;
2884 void *copy_data; 2828 void *copy_data;
2885 unsigned long val; 2829 unsigned long val;
2886 2830
2887 printf("%5lu.%06lu | ", secs, usecs);
2888
2889 print_graph_cpu(cpu);
2890 print_graph_proc(pid, comm);
2891
2892 printf(" | ");
2893
2894 if (latency_format) { 2831 if (latency_format) {
2895 print_lat_fmt(data, size); 2832 print_lat_fmt(data, size);
2896 printf(" | "); 2833 printf(" | ");
@@ -2923,22 +2860,13 @@ out_free:
2923} 2860}
2924 2861
2925static void 2862static void
2926pretty_print_func_ret(void *data, int size __unused, struct event *event, 2863pretty_print_func_ret(void *data, int size __unused, struct event *event)
2927 int cpu, int pid, const char *comm,
2928 unsigned long secs, unsigned long usecs)
2929{ 2864{
2930 unsigned long long rettime, calltime; 2865 unsigned long long rettime, calltime;
2931 unsigned long long duration, depth; 2866 unsigned long long duration, depth;
2932 struct format_field *field; 2867 struct format_field *field;
2933 int i; 2868 int i;
2934 2869
2935 printf("%5lu.%06lu | ", secs, usecs);
2936
2937 print_graph_cpu(cpu);
2938 print_graph_proc(pid, comm);
2939
2940 printf(" | ");
2941
2942 if (latency_format) { 2870 if (latency_format) {
2943 print_lat_fmt(data, size); 2871 print_lat_fmt(data, size);
2944 printf(" | "); 2872 printf(" | ");
@@ -2976,31 +2904,21 @@ pretty_print_func_ret(void *data, int size __unused, struct event *event,
2976 2904
2977static void 2905static void
2978pretty_print_func_graph(void *data, int size, struct event *event, 2906pretty_print_func_graph(void *data, int size, struct event *event,
2979 int cpu, int pid, const char *comm, 2907 int cpu, int pid)
2980 unsigned long secs, unsigned long usecs)
2981{ 2908{
2982 if (event->flags & EVENT_FL_ISFUNCENT) 2909 if (event->flags & EVENT_FL_ISFUNCENT)
2983 pretty_print_func_ent(data, size, event, 2910 pretty_print_func_ent(data, size, event, cpu, pid);
2984 cpu, pid, comm, secs, usecs);
2985 else if (event->flags & EVENT_FL_ISFUNCRET) 2911 else if (event->flags & EVENT_FL_ISFUNCRET)
2986 pretty_print_func_ret(data, size, event, 2912 pretty_print_func_ret(data, size, event);
2987 cpu, pid, comm, secs, usecs);
2988 printf("\n"); 2913 printf("\n");
2989} 2914}
2990 2915
2991void print_event(int cpu, void *data, int size, unsigned long long nsecs, 2916void print_trace_event(int cpu, void *data, int size)
2992 char *comm)
2993{ 2917{
2994 struct event *event; 2918 struct event *event;
2995 unsigned long secs;
2996 unsigned long usecs;
2997 int type; 2919 int type;
2998 int pid; 2920 int pid;
2999 2921
3000 secs = nsecs / NSECS_PER_SEC;
3001 nsecs -= secs * NSECS_PER_SEC;
3002 usecs = nsecs / NSECS_PER_USEC;
3003
3004 type = trace_parse_common_type(data); 2922 type = trace_parse_common_type(data);
3005 2923
3006 event = trace_find_event(type); 2924 event = trace_find_event(type);
@@ -3012,17 +2930,10 @@ void print_event(int cpu, void *data, int size, unsigned long long nsecs,
3012 pid = trace_parse_common_pid(data); 2930 pid = trace_parse_common_pid(data);
3013 2931
3014 if (event->flags & (EVENT_FL_ISFUNCENT | EVENT_FL_ISFUNCRET)) 2932 if (event->flags & (EVENT_FL_ISFUNCENT | EVENT_FL_ISFUNCRET))
3015 return pretty_print_func_graph(data, size, event, cpu, 2933 return pretty_print_func_graph(data, size, event, cpu, pid);
3016 pid, comm, secs, usecs);
3017 2934
3018 if (latency_format) { 2935 if (latency_format)
3019 printf("%8.8s-%-5d %3d",
3020 comm, pid, cpu);
3021 print_lat_fmt(data, size); 2936 print_lat_fmt(data, size);
3022 } else
3023 printf("%16s-%-5d [%03d]", comm, pid, cpu);
3024
3025 printf(" %5lu.%06lu: %s: ", secs, usecs, event->name);
3026 2937
3027 if (event->flags & EVENT_FL_FAILED) { 2938 if (event->flags & EVENT_FL_FAILED) {
3028 printf("EVENT '%s' FAILED TO PARSE\n", 2939 printf("EVENT '%s' FAILED TO PARSE\n",
@@ -3031,7 +2942,6 @@ void print_event(int cpu, void *data, int size, unsigned long long nsecs,
3031 } 2942 }
3032 2943
3033 pretty_print(data, size, event); 2944 pretty_print(data, size, event);
3034 printf("\n");
3035} 2945}
3036 2946
3037static void print_fields(struct print_flag_sym *field) 2947static void print_fields(struct print_flag_sym *field)
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index f7af2fca965d..66f4b78737ab 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -36,11 +36,10 @@ static int stop_script_unsupported(void)
36 return 0; 36 return 0;
37} 37}
38 38
39static void process_event_unsupported(int cpu __unused, 39static void process_event_unsupported(union perf_event *event __unused,
40 void *data __unused, 40 struct perf_sample *sample __unused,
41 int size __unused, 41 struct perf_session *session __unused,
42 unsigned long long nsecs __unused, 42 struct thread *thread __unused)
43 char *comm __unused)
44{ 43{
45} 44}
46 45
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index b5f12ca24d99..b04da5722437 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -3,6 +3,7 @@
3 3
4#include <stdbool.h> 4#include <stdbool.h>
5#include "parse-events.h" 5#include "parse-events.h"
6#include "session.h"
6 7
7#define __unused __attribute__((unused)) 8#define __unused __attribute__((unused))
8 9
@@ -176,8 +177,7 @@ void print_printk(void);
176 177
177int parse_ftrace_file(char *buf, unsigned long size); 178int parse_ftrace_file(char *buf, unsigned long size);
178int parse_event_file(char *buf, unsigned long size, char *sys); 179int parse_event_file(char *buf, unsigned long size, char *sys);
179void print_event(int cpu, void *data, int size, unsigned long long nsecs, 180void print_trace_event(int cpu, void *data, int size);
180 char *comm);
181 181
182extern int file_bigendian; 182extern int file_bigendian;
183extern int host_bigendian; 183extern int host_bigendian;
@@ -278,8 +278,10 @@ struct scripting_ops {
278 const char *name; 278 const char *name;
279 int (*start_script) (const char *script, int argc, const char **argv); 279 int (*start_script) (const char *script, int argc, const char **argv);
280 int (*stop_script) (void); 280 int (*stop_script) (void);
281 void (*process_event) (int cpu, void *data, int size, 281 void (*process_event) (union perf_event *event,
282 unsigned long long nsecs, char *comm); 282 struct perf_sample *sample,
283 struct perf_session *session,
284 struct thread *thread);
283 int (*generate_script) (const char *outfile); 285 int (*generate_script) (const char *outfile);
284}; 286};
285 287