Commit 56edab31 authored by Linus Torvalds's avatar Linus Torvalds

Merge branches 'perf-urgent-for-linus' and 'perf-core-for-linus' of...

Merge branches 'perf-urgent-for-linus' and 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf fixes from Ingo Molnar:

 - Leftover AMD PMU driver fix fix from the end of the v3.4
   stabilization cycle.

 - Late tools/perf/ changes that missed the first round:
    * endianness fixes
    * event parsing improvements
    * libtraceevent fixes factored out from trace-cmd
    * perl scripting engine fixes related to libtraceevent,
    * testcase improvements
    * perf inject / pipe mode fixes
    * plus a kernel side fix

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  perf/x86: Update event scheduling constraints for AMD family 15h models

* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  Revert "sched, perf: Use a single callback into the scheduler"
  perf evlist: Show event attribute details
  perf tools: Bump default sample freq to 4 kHz
  perf buildid-list: Work better with pipe mode
  perf tools: Fix piped mode read code
  perf inject: Fix broken perf inject -b
  perf tools: rename HEADER_TRACE_INFO to HEADER_TRACING_DATA
  perf tools: Add union u64_swap type for swapping u64 data
  perf tools: Carry perf_event_attr bitfield throught different endians
  perf record: Fix documentation for branch stack sampling
  perf target: Add cpu flag to sample_type if target has cpu
  perf tools: Always try to build libtraceevent
  perf tools: Rename libparsevent to libtraceevent in Makefile
  perf script: Rename struct event to struct event_format in perl engine
  perf script: Explicitly handle known default print arg type
  perf tools: Add hardcoded name term for pmu events
  perf tools: Separate 'mem:' event scanner bits
  perf tools: Use allocated list for each parsed event
  perf tools: Add support for displaying event parser debug info
  perf test: Move parse event automated tests to separated object
...@@ -496,6 +496,7 @@ static __initconst const struct x86_pmu amd_pmu = { ...@@ -496,6 +496,7 @@ static __initconst const struct x86_pmu amd_pmu = {
* 0x023 DE PERF_CTL[2:0] * 0x023 DE PERF_CTL[2:0]
* 0x02D LS PERF_CTL[3] * 0x02D LS PERF_CTL[3]
* 0x02E LS PERF_CTL[3,0] * 0x02E LS PERF_CTL[3,0]
* 0x031 LS PERF_CTL[2:0] (**)
* 0x043 CU PERF_CTL[2:0] * 0x043 CU PERF_CTL[2:0]
* 0x045 CU PERF_CTL[2:0] * 0x045 CU PERF_CTL[2:0]
* 0x046 CU PERF_CTL[2:0] * 0x046 CU PERF_CTL[2:0]
...@@ -509,10 +510,12 @@ static __initconst const struct x86_pmu amd_pmu = { ...@@ -509,10 +510,12 @@ static __initconst const struct x86_pmu amd_pmu = {
* 0x0DD LS PERF_CTL[5:0] * 0x0DD LS PERF_CTL[5:0]
* 0x0DE LS PERF_CTL[5:0] * 0x0DE LS PERF_CTL[5:0]
* 0x0DF LS PERF_CTL[5:0] * 0x0DF LS PERF_CTL[5:0]
* 0x1C0 EX PERF_CTL[5:3]
* 0x1D6 EX PERF_CTL[5:0] * 0x1D6 EX PERF_CTL[5:0]
* 0x1D8 EX PERF_CTL[5:0] * 0x1D8 EX PERF_CTL[5:0]
* *
* (*) depending on the umask all FPU counters may be used * (*) depending on the umask all FPU counters may be used
* (**) only one unitmask enabled at a time
*/ */
static struct event_constraint amd_f15_PMC0 = EVENT_CONSTRAINT(0, 0x01, 0); static struct event_constraint amd_f15_PMC0 = EVENT_CONSTRAINT(0, 0x01, 0);
...@@ -562,6 +565,12 @@ amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *ev ...@@ -562,6 +565,12 @@ amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *ev
return &amd_f15_PMC3; return &amd_f15_PMC3;
case 0x02E: case 0x02E:
return &amd_f15_PMC30; return &amd_f15_PMC30;
case 0x031:
if (hweight_long(hwc->config & ARCH_PERFMON_EVENTSEL_UMASK) <= 1)
return &amd_f15_PMC20;
return &emptyconstraint;
case 0x1C0:
return &amd_f15_PMC53;
default: default:
return &amd_f15_PMC50; return &amd_f15_PMC50;
} }
......
...@@ -1084,8 +1084,10 @@ extern void perf_pmu_unregister(struct pmu *pmu); ...@@ -1084,8 +1084,10 @@ extern void perf_pmu_unregister(struct pmu *pmu);
extern int perf_num_counters(void); extern int perf_num_counters(void);
extern const char *perf_pmu_name(void); extern const char *perf_pmu_name(void);
extern void __perf_event_task_sched(struct task_struct *prev, extern void __perf_event_task_sched_in(struct task_struct *prev,
struct task_struct *next); struct task_struct *task);
extern void __perf_event_task_sched_out(struct task_struct *prev,
struct task_struct *next);
extern int perf_event_init_task(struct task_struct *child); extern int perf_event_init_task(struct task_struct *child);
extern void perf_event_exit_task(struct task_struct *child); extern void perf_event_exit_task(struct task_struct *child);
extern void perf_event_free_task(struct task_struct *task); extern void perf_event_free_task(struct task_struct *task);
...@@ -1205,13 +1207,20 @@ perf_sw_event(u32 event_id, u64 nr, struct pt_regs *regs, u64 addr) ...@@ -1205,13 +1207,20 @@ perf_sw_event(u32 event_id, u64 nr, struct pt_regs *regs, u64 addr)
extern struct static_key_deferred perf_sched_events; extern struct static_key_deferred perf_sched_events;
static inline void perf_event_task_sched(struct task_struct *prev, static inline void perf_event_task_sched_in(struct task_struct *prev,
struct task_struct *task) struct task_struct *task)
{
if (static_key_false(&perf_sched_events.key))
__perf_event_task_sched_in(prev, task);
}
static inline void perf_event_task_sched_out(struct task_struct *prev,
struct task_struct *next)
{ {
perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, NULL, 0); perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, NULL, 0);
if (static_key_false(&perf_sched_events.key)) if (static_key_false(&perf_sched_events.key))
__perf_event_task_sched(prev, task); __perf_event_task_sched_out(prev, next);
} }
extern void perf_event_mmap(struct vm_area_struct *vma); extern void perf_event_mmap(struct vm_area_struct *vma);
...@@ -1286,8 +1295,11 @@ extern void perf_event_disable(struct perf_event *event); ...@@ -1286,8 +1295,11 @@ extern void perf_event_disable(struct perf_event *event);
extern void perf_event_task_tick(void); extern void perf_event_task_tick(void);
#else #else
static inline void static inline void
perf_event_task_sched(struct task_struct *prev, perf_event_task_sched_in(struct task_struct *prev,
struct task_struct *task) { } struct task_struct *task) { }
static inline void
perf_event_task_sched_out(struct task_struct *prev,
struct task_struct *next) { }
static inline int perf_event_init_task(struct task_struct *child) { return 0; } static inline int perf_event_init_task(struct task_struct *child) { return 0; }
static inline void perf_event_exit_task(struct task_struct *child) { } static inline void perf_event_exit_task(struct task_struct *child) { }
static inline void perf_event_free_task(struct task_struct *task) { } static inline void perf_event_free_task(struct task_struct *task) { }
......
...@@ -2039,8 +2039,8 @@ static void perf_event_context_sched_out(struct task_struct *task, int ctxn, ...@@ -2039,8 +2039,8 @@ static void perf_event_context_sched_out(struct task_struct *task, int ctxn,
* accessing the event control register. If a NMI hits, then it will * accessing the event control register. If a NMI hits, then it will
* not restart the event. * not restart the event.
*/ */
static void __perf_event_task_sched_out(struct task_struct *task, void __perf_event_task_sched_out(struct task_struct *task,
struct task_struct *next) struct task_struct *next)
{ {
int ctxn; int ctxn;
...@@ -2279,8 +2279,8 @@ static void perf_branch_stack_sched_in(struct task_struct *prev, ...@@ -2279,8 +2279,8 @@ static void perf_branch_stack_sched_in(struct task_struct *prev,
* accessing the event control register. If a NMI hits, then it will * accessing the event control register. If a NMI hits, then it will
* keep the event running. * keep the event running.
*/ */
static void __perf_event_task_sched_in(struct task_struct *prev, void __perf_event_task_sched_in(struct task_struct *prev,
struct task_struct *task) struct task_struct *task)
{ {
struct perf_event_context *ctx; struct perf_event_context *ctx;
int ctxn; int ctxn;
...@@ -2305,12 +2305,6 @@ static void __perf_event_task_sched_in(struct task_struct *prev, ...@@ -2305,12 +2305,6 @@ static void __perf_event_task_sched_in(struct task_struct *prev,
perf_branch_stack_sched_in(prev, task); perf_branch_stack_sched_in(prev, task);
} }
void __perf_event_task_sched(struct task_struct *prev, struct task_struct *next)
{
__perf_event_task_sched_out(prev, next);
__perf_event_task_sched_in(prev, next);
}
static u64 perf_calculate_period(struct perf_event *event, u64 nsec, u64 count) static u64 perf_calculate_period(struct perf_event *event, u64 nsec, u64 count)
{ {
u64 frequency = event->attr.sample_freq; u64 frequency = event->attr.sample_freq;
......
...@@ -1912,7 +1912,7 @@ prepare_task_switch(struct rq *rq, struct task_struct *prev, ...@@ -1912,7 +1912,7 @@ prepare_task_switch(struct rq *rq, struct task_struct *prev,
struct task_struct *next) struct task_struct *next)
{ {
sched_info_switch(prev, next); sched_info_switch(prev, next);
perf_event_task_sched(prev, next); perf_event_task_sched_out(prev, next);
fire_sched_out_preempt_notifiers(prev, next); fire_sched_out_preempt_notifiers(prev, next);
prepare_lock_switch(rq, next); prepare_lock_switch(rq, next);
prepare_arch_switch(next); prepare_arch_switch(next);
...@@ -1955,6 +1955,13 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev) ...@@ -1955,6 +1955,13 @@ static void finish_task_switch(struct rq *rq, struct task_struct *prev)
*/ */
prev_state = prev->state; prev_state = prev->state;
finish_arch_switch(prev); finish_arch_switch(prev);
#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
local_irq_disable();
#endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */
perf_event_task_sched_in(prev, current);
#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
local_irq_enable();
#endif /* __ARCH_WANT_INTERRUPTS_ON_CTXSW */
finish_lock_switch(rq, prev); finish_lock_switch(rq, prev);
finish_arch_post_lock_switch(); finish_arch_post_lock_switch();
......
...@@ -20,6 +20,14 @@ OPTIONS ...@@ -20,6 +20,14 @@ OPTIONS
--input=:: --input=::
Input file name. (default: perf.data unless stdin is a fifo) Input file name. (default: perf.data unless stdin is a fifo)
-F::
--freq=::
Show just the sample frequency used for each event.
-v::
--verbose=::
Show all fields.
SEE ALSO SEE ALSO
-------- --------
linkperf:perf-record[1], linkperf:perf-list[1], linkperf:perf-record[1], linkperf:perf-list[1],
......
...@@ -168,7 +168,7 @@ following filters are defined: ...@@ -168,7 +168,7 @@ following filters are defined:
- any: any type of branches - any: any type of branches
- any_call: any function call or system call - any_call: any function call or system call
- any_ret: any function return or system call return - any_ret: any function return or system call return
- any_ind: any indirect branch - ind_call: any indirect branch
- u: only when the branch target is at the user level - u: only when the branch target is at the user level
- k: only when the branch target is in the kernel - k: only when the branch target is in the kernel
- hv: only when the target is at the hypervisor level - hv: only when the target is at the hypervisor level
......
...@@ -83,7 +83,13 @@ ifndef PERF_DEBUG ...@@ -83,7 +83,13 @@ ifndef PERF_DEBUG
CFLAGS_OPTIMIZE = -O6 CFLAGS_OPTIMIZE = -O6
endif endif
CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) ifdef PARSER_DEBUG
PARSER_DEBUG_BISON := -t
PARSER_DEBUG_FLEX := -d
PARSER_DEBUG_CFLAGS := -DPARSER_DEBUG
endif
CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) $(PARSER_DEBUG_CFLAGS)
EXTLIBS = -lpthread -lrt -lelf -lm EXTLIBS = -lpthread -lrt -lelf -lm
ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
ALL_LDFLAGS = $(LDFLAGS) ALL_LDFLAGS = $(LDFLAGS)
...@@ -149,7 +155,7 @@ endif ...@@ -149,7 +155,7 @@ endif
### --- END CONFIGURATION SECTION --- ### --- END CONFIGURATION SECTION ---
BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)/util -I$(EVENT_PARSE_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)/util -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
BASIC_LDFLAGS = BASIC_LDFLAGS =
# Guard against environment variables # Guard against environment variables
...@@ -178,16 +184,16 @@ $(OUTPUT)python/perf.so: $(PYRF_OBJS) $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) ...@@ -178,16 +184,16 @@ $(OUTPUT)python/perf.so: $(PYRF_OBJS) $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
EVENT_PARSE_DIR = ../lib/traceevent/ TRACE_EVENT_DIR = ../lib/traceevent/
ifeq ("$(origin O)", "command line") ifeq ("$(origin O)", "command line")
EP_PATH=$(OUTPUT)/ TE_PATH=$(OUTPUT)/
else else
EP_PATH=$(EVENT_PARSE_DIR)/ TE_PATH=$(TRACE_EVENT_DIR)/
endif endif
LIBPARSEVENT = $(EP_PATH)libtraceevent.a LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
EP_LIB := -L$(EP_PATH) -ltraceevent TE_LIB := -L$(TE_PATH) -ltraceevent
# #
# Single 'perf' binary right now: # Single 'perf' binary right now:
...@@ -216,10 +222,10 @@ FLEX = flex ...@@ -216,10 +222,10 @@ FLEX = flex
BISON= bison BISON= bison
$(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-flex.c: util/parse-events.l
$(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c
$(OUTPUT)util/parse-events-bison.c: util/parse-events.y $(OUTPUT)util/parse-events-bison.c: util/parse-events.y
$(QUIET_BISON)$(BISON) -v util/parse-events.y -d -o $(OUTPUT)util/parse-events-bison.c $(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c
$(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-flex.c: util/pmu.l
$(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c
...@@ -311,7 +317,7 @@ LIB_H += util/cpumap.h ...@@ -311,7 +317,7 @@ LIB_H += util/cpumap.h
LIB_H += util/top.h LIB_H += util/top.h
LIB_H += $(ARCH_INCLUDE) LIB_H += $(ARCH_INCLUDE)
LIB_H += util/cgroup.h LIB_H += util/cgroup.h
LIB_H += $(EVENT_PARSE_DIR)event-parse.h LIB_H += $(TRACE_EVENT_DIR)event-parse.h
LIB_H += util/target.h LIB_H += util/target.h
LIB_OBJS += $(OUTPUT)util/abspath.o LIB_OBJS += $(OUTPUT)util/abspath.o
...@@ -332,6 +338,7 @@ LIB_OBJS += $(OUTPUT)util/help.o ...@@ -332,6 +338,7 @@ LIB_OBJS += $(OUTPUT)util/help.o
LIB_OBJS += $(OUTPUT)util/levenshtein.o LIB_OBJS += $(OUTPUT)util/levenshtein.o
LIB_OBJS += $(OUTPUT)util/parse-options.o LIB_OBJS += $(OUTPUT)util/parse-options.o
LIB_OBJS += $(OUTPUT)util/parse-events.o LIB_OBJS += $(OUTPUT)util/parse-events.o
LIB_OBJS += $(OUTPUT)util/parse-events-test.o
LIB_OBJS += $(OUTPUT)util/path.o LIB_OBJS += $(OUTPUT)util/path.o
LIB_OBJS += $(OUTPUT)util/rbtree.o LIB_OBJS += $(OUTPUT)util/rbtree.o
LIB_OBJS += $(OUTPUT)util/bitmap.o LIB_OBJS += $(OUTPUT)util/bitmap.o
...@@ -410,7 +417,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o ...@@ -410,7 +417,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
BUILTIN_OBJS += $(OUTPUT)builtin-test.o BUILTIN_OBJS += $(OUTPUT)builtin-test.o
BUILTIN_OBJS += $(OUTPUT)builtin-inject.o BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
PERFLIBS = $(LIB_FILE) $(LIBPARSEVENT) PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT)
# Files needed for the python binding, perf.so # Files needed for the python binding, perf.so
# pyrf is just an internal name needed for all those wrappers. # pyrf is just an internal name needed for all those wrappers.
...@@ -819,9 +826,9 @@ $(sort $(dir $(DIRECTORY_DEPS))): ...@@ -819,9 +826,9 @@ $(sort $(dir $(DIRECTORY_DEPS))):
$(LIB_FILE): $(LIB_OBJS) $(LIB_FILE): $(LIB_OBJS)
$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS) $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
# libparsevent.a # libtraceevent.a
$(LIBPARSEVENT): $(LIBTRACEEVENT):
make -C $(EVENT_PARSE_DIR) $(COMMAND_O) libtraceevent.a $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) $(COMMAND_O) libtraceevent.a
help: help:
@echo 'Perf make targets:' @echo 'Perf make targets:'
...@@ -969,6 +976,6 @@ clean: ...@@ -969,6 +976,6 @@ clean:
$(RM) $(OUTPUT)util/*-{bison,flex}* $(RM) $(OUTPUT)util/*-{bison,flex}*
$(python-clean) $(python-clean)
.PHONY: all install clean strip .PHONY: all install clean strip $(LIBTRACEEVENT)
.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell .PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
.PHONY: .FORCE-PERF-VERSION-FILE TAGS tags cscope .FORCE-PERF-CFLAGS .PHONY: .FORCE-PERF-VERSION-FILE TAGS tags cscope .FORCE-PERF-CFLAGS
...@@ -84,7 +84,11 @@ static int perf_session__list_build_ids(void) ...@@ -84,7 +84,11 @@ static int perf_session__list_build_ids(void)
if (filename__fprintf_build_id(session->filename, stdout)) if (filename__fprintf_build_id(session->filename, stdout))
goto out; goto out;
if (with_hits) /*
* in pipe-mode, the only way to get the buildids is to parse
* the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID
*/
if (with_hits || session->fd_pipe)
perf_session__process_events(session, &build_id__mark_dso_hit_ops); perf_session__process_events(session, &build_id__mark_dso_hit_ops);
perf_session__fprintf_dsos_buildid(session, stdout, with_hits); perf_session__fprintf_dsos_buildid(session, stdout, with_hits);
......
...@@ -15,9 +15,40 @@ ...@@ -15,9 +15,40 @@
#include "util/parse-options.h" #include "util/parse-options.h"
#include "util/session.h" #include "util/session.h"
static const char *input_name; struct perf_attr_details {
bool freq;
bool verbose;
};
static int comma_printf(bool *first, const char *fmt, ...)
{
va_list args;
int ret = 0;
if (!*first) {
ret += printf(",");
} else {
ret += printf(":");
*first = false;
}
va_start(args, fmt);
ret += vprintf(fmt, args);
va_end(args);
return ret;
}
static int __if_print(bool *first, const char *field, u64 value)
{
if (value == 0)
return 0;
return comma_printf(first, " %s: %" PRIu64, field, value);
}
#define if_print(field) __if_print(&first, #field, pos->attr.field)
static int __cmd_evlist(void) static int __cmd_evlist(const char *input_name, struct perf_attr_details *details)
{ {
struct perf_session *session; struct perf_session *session;
struct perf_evsel *pos; struct perf_evsel *pos;
...@@ -26,8 +57,52 @@ static int __cmd_evlist(void) ...@@ -26,8 +57,52 @@ static int __cmd_evlist(void)
if (session == NULL) if (session == NULL)
return -ENOMEM; return -ENOMEM;
list_for_each_entry(pos, &session->evlist->entries, node) list_for_each_entry(pos, &session->evlist->entries, node) {
printf("%s\n", event_name(pos)); bool first = true;
printf("%s", event_name(pos));
if (details->verbose || details->freq) {
comma_printf(&first, " sample_freq=%" PRIu64,
(u64)pos->attr.sample_freq);
}
if (details->verbose) {
if_print(type);
if_print(config);
if_print(config1);
if_print(config2);
if_print(size);
if_print(sample_type);
if_print(read_format);
if_print(disabled);
if_print(inherit);
if_print(pinned);
if_print(exclusive);
if_print(exclude_user);
if_print(exclude_kernel);
if_print(exclude_hv);
if_print(exclude_idle);
if_print(mmap);
if_print(comm);
if_print(freq);
if_print(inherit_stat);
if_print(enable_on_exec);
if_print(task);
if_print(watermark);
if_print(precise_ip);
if_print(mmap_data);
if_print(sample_id_all);
if_print(exclude_host);
if_print(exclude_guest);
if_print(__reserved_1);
if_print(wakeup_events);
if_print(bp_type);
if_print(branch_sample_type);
}
putchar('\n');
}
perf_session__delete(session); perf_session__delete(session);
return 0; return 0;
...@@ -38,17 +113,23 @@ static const char * const evlist_usage[] = { ...@@ -38,17 +113,23 @@ static const char * const evlist_usage[] = {
NULL NULL
}; };
static const struct option options[] = {
OPT_STRING('i', "input", &input_name, "file",
"input file name"),
OPT_END()
};
int cmd_evlist(int argc, const char **argv, const char *prefix __used) int cmd_evlist(int argc, const char **argv, const char *prefix __used)
{ {
struct perf_attr_details details = { .verbose = false, };
const char *input_name;
const struct option options[] = {
OPT_STRING('i', "input", &input_name, "file",
"Input file name"),
OPT_BOOLEAN('F', "freq", &details.freq,
"Show the sample frequency"),
OPT_BOOLEAN('v', "verbose", &details.verbose,
"Show all event attr details"),
OPT_END()
};
argc = parse_options(argc, argv, options, evlist_usage, 0); argc = parse_options(argc, argv, options, evlist_usage, 0);
if (argc) if (argc)
usage_with_options(evlist_usage, options); usage_with_options(evlist_usage, options);
return __cmd_evlist(); return __cmd_evlist(input_name, &details);
} }
...@@ -60,6 +60,11 @@ static int perf_event__repipe_tracing_data_synth(union perf_event *event, ...@@ -60,6 +60,11 @@ static int perf_event__repipe_tracing_data_synth(union perf_event *event,
static int perf_event__repipe_attr(union perf_event *event, static int perf_event__repipe_attr(union perf_event *event,
struct perf_evlist **pevlist __used) struct perf_evlist **pevlist __used)
{ {
int ret;
ret = perf_event__process_attr(event, pevlist);
if (ret)
return ret;
return perf_event__repipe_synth(NULL, event, NULL); return perf_event__repipe_synth(NULL, event, NULL);
} }
......
...@@ -396,7 +396,7 @@ static void perf_record__mmap_read_all(struct perf_record *rec) ...@@ -396,7 +396,7 @@ static void perf_record__mmap_read_all(struct perf_record *rec)
perf_record__mmap_read(rec, &rec->evlist->mmap[i]); perf_record__mmap_read(rec, &rec->evlist->mmap[i]);
} }
if (perf_header__has_feat(&rec->session->header, HEADER_TRACE_INFO)) if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA))
write_output(rec, &finished_round_event, sizeof(finished_round_event)); write_output(rec, &finished_round_event, sizeof(finished_round_event));
} }
...@@ -478,7 +478,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) ...@@ -478,7 +478,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
perf_header__clear_feat(&session->header, HEADER_BUILD_ID); perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
if (!have_tracepoints(&evsel_list->entries)) if (!have_tracepoints(&evsel_list->entries))
perf_header__clear_feat(&session->header, HEADER_TRACE_INFO); perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
if (!rec->opts.branch_stack) if (!rec->opts.branch_stack)
perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
...@@ -753,7 +753,7 @@ static struct perf_record record = { ...@@ -753,7 +753,7 @@ static struct perf_record record = {
.mmap_pages = UINT_MAX, .mmap_pages = UINT_MAX,
.user_freq = UINT_MAX, .user_freq = UINT_MAX,
.user_interval = ULLONG_MAX, .user_interval = ULLONG_MAX,
.freq = 1000, .freq = 4000,
.target = { .target = {
.uses_mmap = true, .uses_mmap = true,
}, },
......
This diff is collapsed.
...@@ -900,6 +900,9 @@ static void perf_top__start_counters(struct perf_top *top) ...@@ -900,6 +900,9 @@ static void perf_top__start_counters(struct perf_top *top)
attr->read_format |= PERF_FORMAT_ID; attr->read_format |= PERF_FORMAT_ID;
} }
if (perf_target__has_cpu(&top->target))
attr->sample_type |= PERF_SAMPLE_CPU;
if (symbol_conf.use_callchain) if (symbol_conf.use_callchain)
attr->sample_type |= PERF_SAMPLE_CALLCHAIN; attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
...@@ -1159,7 +1162,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) ...@@ -1159,7 +1162,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
struct perf_top top = { struct perf_top top = {
.count_filter = 5, .count_filter = 5,
.delay_secs = 2, .delay_secs = 2,
.freq = 1000, /* 1 KHz */ .freq = 4000, /* 4 KHz */
.mmap_pages = 128, .mmap_pages = 128,
.sym_pcnt_filter = 5, .sym_pcnt_filter = 5,
.target = { .target = {
......
...@@ -65,6 +65,8 @@ struct perf_tool build_id__mark_dso_hit_ops = { ...@@ -65,6 +65,8 @@ struct perf_tool build_id__mark_dso_hit_ops = {
.mmap = perf_event__process_mmap, .mmap = perf_event__process_mmap,
.fork = perf_event__process_task, .fork = perf_event__process_task,
.exit = perf_event__exit_del_thread, .exit = perf_event__exit_del_thread,
.attr = perf_event__process_attr,
.build_id = perf_event__process_build_id,
}; };
char *dso__build_id_filename(struct dso *self, char *bf, size_t size) char *dso__build_id_filename(struct dso *self, char *bf, size_t size)
......
...@@ -108,7 +108,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts, ...@@ -108,7 +108,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
if (opts->call_graph) if (opts->call_graph)
attr->sample_type |= PERF_SAMPLE_CALLCHAIN; attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
if (opts->target.system_wide) if (perf_target__has_cpu(&opts->target))
attr->sample_type |= PERF_SAMPLE_CPU; attr->sample_type |= PERF_SAMPLE_CPU;
if (opts->period) if (opts->period)
...@@ -462,10 +462,7 @@ int perf_event__parse_sample(const union perf_event *event, u64 type, ...@@ -462,10 +462,7 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
* used for cross-endian analysis. See git commit 65014ab3 * used for cross-endian analysis. See git commit 65014ab3
* for why this goofiness is needed. * for why this goofiness is needed.
*/ */
union { union u64_swap u;
u64 val64;
u32 val32[2];
} u;
memset(data, 0, sizeof(*data)); memset(data, 0, sizeof(*data));
data->cpu = data->pid = data->tid = -1; data->cpu = data->pid = data->tid = -1;
...@@ -608,10 +605,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, ...@@ -608,10 +605,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
* used for cross-endian analysis. See git commit 65014ab3 * used for cross-endian analysis. See git commit 65014ab3
* for why this goofiness is needed. * for why this goofiness is needed.
*/ */
union { union u64_swap u;
u64 val64;
u32 val32[2];
} u;
array = event->sample.array; array = event->sample.array;
......
...@@ -437,7 +437,7 @@ static bool perf_session__read_build_ids(struct perf_session *session, bool with ...@@ -437,7 +437,7 @@ static bool perf_session__read_build_ids(struct perf_session *session, bool with
return ret; return ret;
} }
static int write_trace_info(int fd, struct perf_header *h __used, static int write_tracing_data(int fd, struct perf_header *h __used,
struct perf_evlist *evlist) struct perf_evlist *evlist)
{ {
return read_tracing_data(fd, &evlist->entries); return read_tracing_data(fd, &evlist->entries);
...@@ -1472,7 +1472,7 @@ static int perf_header__read_build_ids(struct perf_header *header, ...@@ -1472,7 +1472,7 @@ static int perf_header__read_build_ids(struct perf_header *header,
return err; return err;
} }
static int process_trace_info(struct perf_file_section *section __unused, static int process_tracing_data(struct perf_file_section *section __unused,
struct perf_header *ph __unused, struct perf_header *ph __unused,
int feat __unused, int fd) int feat __unused, int fd)
{ {
...@@ -1508,11 +1508,11 @@ struct feature_ops { ...@@ -1508,11 +1508,11 @@ struct feature_ops {
.full_only = true } .full_only = true }
/* feature_ops not implemented: */ /* feature_ops not implemented: */
#define print_trace_info NULL #define print_tracing_data NULL
#define print_build_id NULL #define print_build_id NULL
static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
FEAT_OPP(HEADER_TRACE_INFO, trace_info), FEAT_OPP(HEADER_TRACING_DATA, tracing_data),
FEAT_OPP(HEADER_BUILD_ID, build_id), FEAT_OPP(HEADER_BUILD_ID, build_id),
FEAT_OPA(HEADER_HOSTNAME, hostname), FEAT_OPA(HEADER_HOSTNAME, hostname),
FEAT_OPA(HEADER_OSRELEASE, osrelease), FEAT_OPA(HEADER_OSRELEASE, osrelease),
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
enum { enum {
HEADER_RESERVED = 0, /* always cleared */ HEADER_RESERVED = 0, /* always cleared */
HEADER_FIRST_FEATURE = 1, HEADER_FIRST_FEATURE = 1,
HEADER_TRACE_INFO = 1, HEADER_TRACING_DATA = 1,
HEADER_BUILD_ID, HEADER_BUILD_ID,
HEADER_HOSTNAME, HEADER_HOSTNAME,
......
This diff is collapsed.
...@@ -23,8 +23,10 @@ struct event_symbol { ...@@ -23,8 +23,10 @@ struct event_symbol {
const char *alias; const char *alias;
}; };
int parse_events_parse(struct list_head *list, struct list_head *list_tmp, #ifdef PARSER_DEBUG
int *idx); extern int parse_events_debug;
#endif
int parse_events_parse(struct list_head *list, int *idx);
#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x #define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x #define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
...@@ -355,20 +357,30 @@ const char *__event_name(int type, u64 config) ...@@ -355,20 +357,30 @@ const char *__event_name(int type, u64 config)
return "unknown"; return "unknown";
} }
static int add_event(struct list_head *list, int *idx, static int add_event(struct list_head **_list, int *idx,
struct perf_event_attr *attr, char *name) struct perf_event_attr *attr, char *name)
{ {
struct perf_evsel *evsel; struct perf_evsel *evsel;
struct list_head *list = *_list;
if (!list) {
list = malloc(sizeof(*list));
if (!list)
return -ENOMEM;
INIT_LIST_HEAD(list);
}
event_attr_init(attr); event_attr_init(attr);
evsel = perf_evsel__new(attr, (*idx)++); evsel = perf_evsel__new(attr, (*idx)++);
if (!evsel) if (!evsel) {
free(list);
return -ENOMEM; return -ENOMEM;
}
list_add_tail(&evsel->node, list);
evsel->name = strdup(name); evsel->name = strdup(name);
list_add_tail(&evsel->node, list);
*_list = list;
return 0; return 0;
} }
...@@ -390,7 +402,7 @@ static int parse_aliases(char *str, const char *names[][MAX_ALIASES], int size) ...@@ -390,7 +402,7 @@ static int parse_aliases(char *str, const char *names[][MAX_ALIASES], int size)
return -1; return -1;
} }
int parse_events_add_cache(struct list_head *list, int *idx, int parse_events_add_cache(struct list_head **list, int *idx,
char *type, char *op_result1, char *op_result2) char *type, char *op_result1, char *op_result2)
{ {
struct perf_event_attr attr; struct perf_event_attr attr;
...@@ -451,7 +463,7 @@ int parse_events_add_cache(struct list_head *list, int *idx, ...@@ -451,7 +463,7 @@ int parse_events_add_cache(struct list_head *list, int *idx,
return add_event(list, idx, &attr, name); return add_event(list, idx, &attr, name);
} }
static int add_tracepoint(struct list_head *list, int *idx, static int add_tracepoint(struct list_head **list, int *idx,
char *sys_name, char *evt_name) char *sys_name, char *evt_name)
{ {
struct perf_event_attr attr; struct perf_event_attr attr;
...@@ -488,7 +500,7 @@ static int add_tracepoint(struct list_head *list, int *idx, ...@@ -488,7 +500,7 @@ static int add_tracepoint(struct list_head *list, int *idx,
return add_event(list, idx, &attr, name); return add_event(list, idx, &attr, name);
} }
static int add_tracepoint_multi(struct list_head *list, int *idx, static int add_tracepoint_multi(struct list_head **list, int *idx,
char *sys_name, char *evt_name) char *sys_name, char *evt_name)
{ {
char evt_path[MAXPATHLEN]; char evt_path[MAXPATHLEN];
...@@ -519,7 +531,7 @@ static int add_tracepoint_multi(struct list_head *list, int *idx, ...@@ -519,7 +531,7 @@ static int add_tracepoint_multi(struct list_head *list, int *idx,
return ret; return ret;
} }
int parse_events_add_tracepoint(struct list_head *list, int *idx, int parse_events_add_tracepoint(struct list_head **list, int *idx,
char *sys, char *event) char *sys, char *event)
{ {
int ret; int ret;
...@@ -563,7 +575,7 @@ parse_breakpoint_type(const char *type, struct perf_event_attr *attr) ...@@ -563,7 +575,7 @@ parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
return 0; return 0;
} }
int parse_events_add_breakpoint(struct list_head *list, int *idx, int parse_events_add_breakpoint(struct list_head **list, int *idx,
void *ptr, char *type) void *ptr, char *type)
{ {
struct perf_event_attr attr; struct perf_event_attr attr;
...@@ -622,6 +634,9 @@ do { \ ...@@ -622,6 +634,9 @@ do { \
* attr->branch_sample_type = term->val.num; * attr->branch_sample_type = term->val.num;
*/ */
break; break;
case PARSE_EVENTS__TERM_TYPE_NAME:
CHECK_TYPE_VAL(STR);
break;
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -642,7 +657,7 @@ static int config_attr(struct perf_event_attr *attr, ...@@ -642,7 +657,7 @@ static int config_attr(struct perf_event_attr *attr,
return 0; return 0;
} }
int parse_events_add_numeric(struct list_head *list, int *idx, int parse_events_add_numeric(struct list_head **list, int *idx,
unsigned long type, unsigned long config, unsigned long type, unsigned long config,
struct list_head *head_config) struct list_head *head_config)
{ {
...@@ -660,7 +675,24 @@ int parse_events_add_numeric(struct list_head *list, int *idx, ...@@ -660,7 +675,24 @@ int parse_events_add_numeric(struct list_head *list, int *idx,
(char *) __event_name(type, config)); (char *) __event_name(type, config));
} }
int parse_events_add_pmu(struct list_head *list, int *idx, static int parse_events__is_name_term(struct parse_events__term *term)
{
return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME;
}
static char *pmu_event_name(struct perf_event_attr *attr,
struct list_head *head_terms)
{
struct parse_events__term *term;
list_for_each_entry(term, head_terms, list)
if (parse_events__is_name_term(term))
return term->val.str;
return (char *) __event_name(PERF_TYPE_RAW, attr->config);
}
int parse_events_add_pmu(struct list_head **list, int *idx,
char *name, struct list_head *head_config) char *name, struct list_head *head_config)
{ {
struct perf_event_attr attr; struct perf_event_attr attr;
...@@ -681,7 +713,8 @@ int parse_events_add_pmu(struct list_head *list, int *idx, ...@@ -681,7 +713,8 @@ int parse_events_add_pmu(struct list_head *list, int *idx,
if (perf_pmu__config(pmu, &attr, head_config)) if (perf_pmu__config(pmu, &attr, head_config))
return -EINVAL; return -EINVAL;
return add_event(list, idx, &attr, (char *) "pmu"); return add_event(list, idx, &attr,
pmu_event_name(&attr, head_config));
} }
void parse_events_update_lists(struct list_head *list_event, void parse_events_update_lists(struct list_head *list_event,
...@@ -693,7 +726,7 @@ void parse_events_update_lists(struct list_head *list_event, ...@@ -693,7 +726,7 @@ void parse_events_update_lists(struct list_head *list_event,
* list, for next event definition. * list, for next event definition.
*/ */
list_splice_tail(list_event, list_all); list_splice_tail(list_event, list_all);
INIT_LIST_HEAD(list_event); free(list_event);
} }
int parse_events_modifier(struct list_head *list, char *str) int parse_events_modifier(struct list_head *list, char *str)
...@@ -768,10 +801,14 @@ int parse_events(struct perf_evlist *evlist, const char *str, int unset __used) ...@@ -768,10 +801,14 @@ int parse_events(struct perf_evlist *evlist, const char *str, int unset __used)
buffer = parse_events__scan_string(str); buffer = parse_events__scan_string(str);
ret = parse_events_parse(&list, &list_tmp, &idx); #ifdef PARSER_DEBUG
parse_events_debug = 1;
#endif
ret = parse_events_parse(&list, &idx);
parse_events__flush_buffer(buffer); parse_events__flush_buffer(buffer);
parse_events__delete_buffer(buffer); parse_events__delete_buffer(buffer);
parse_events_lex_destroy();
if (!ret) { if (!ret) {
int entries = idx - evlist->nr_entries; int entries = idx - evlist->nr_entries;
......
...@@ -4,7 +4,9 @@ ...@@ -4,7 +4,9 @@
* Parse symbolic events/counts passed in as options: * Parse symbolic events/counts passed in as options:
*/ */
#include <linux/list.h>
#include <stdbool.h> #include <stdbool.h>
#include "types.h"
#include "../../../include/linux/perf_event.h" #include "../../../include/linux/perf_event.h"
#include "types.h" #include "types.h"
...@@ -45,6 +47,7 @@ enum { ...@@ -45,6 +47,7 @@ enum {
PARSE_EVENTS__TERM_TYPE_CONFIG, PARSE_EVENTS__TERM_TYPE_CONFIG,
PARSE_EVENTS__TERM_TYPE_CONFIG1, PARSE_EVENTS__TERM_TYPE_CONFIG1,
PARSE_EVENTS__TERM_TYPE_CONFIG2, PARSE_EVENTS__TERM_TYPE_CONFIG2,
PARSE_EVENTS__TERM_TYPE_NAME,
PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD,
PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE,
}; };
...@@ -66,26 +69,23 @@ int parse_events__term_num(struct parse_events__term **_term, ...@@ -66,26 +69,23 @@ int parse_events__term_num(struct parse_events__term **_term,
int parse_events__term_str(struct parse_events__term **_term, int parse_events__term_str(struct parse_events__term **_term,
int type_term, char *config, char *str); int type_term, char *config, char *str);
void parse_events__free_terms(struct list_head *terms); void parse_events__free_terms(struct list_head *terms);
int parse_events_modifier(struct list_head *list __used, char *str __used); int parse_events_modifier(struct list_head *list, char *str);
int parse_events_add_tracepoint(struct list_head *list, int *idx, int parse_events_add_tracepoint(struct list_head **list, int *idx,
char *sys, char *event); char *sys, char *event);
int parse_events_add_raw(struct perf_evlist *evlist, unsigned long config, int parse_events_add_numeric(struct list_head **list, int *idx,
unsigned long config1, unsigned long config2,
char *mod);
int parse_events_add_numeric(struct list_head *list, int *idx,
unsigned long type, unsigned long config, unsigned long type, unsigned long config,
struct list_head *head_config); struct list_head *head_config);
int parse_events_add_cache(struct list_head *list, int *idx, int parse_events_add_cache(struct list_head **list, int *idx,
char *type, char *op_result1, char *op_result2); char *type, char *op_result1, char *op_result2);
int parse_events_add_breakpoint(struct list_head *list, int *idx, int parse_events_add_breakpoint(struct list_head **list, int *idx,
void *ptr, char *type); void *ptr, char *type);
int parse_events_add_pmu(struct list_head *list, int *idx, int parse_events_add_pmu(struct list_head **list, int *idx,
char *pmu , struct list_head *head_config); char *pmu , struct list_head *head_config);
void parse_events_update_lists(struct list_head *list_event, void parse_events_update_lists(struct list_head *list_event,
struct list_head *list_all); struct list_head *list_all);
void parse_events_error(struct list_head *list_all, void parse_events_error(struct list_head *list_all,
struct list_head *list_event,
int *idx, char const *msg); int *idx, char const *msg);
int parse_events__test(void);
void print_events(const char *event_glob); void print_events(const char *event_glob);
void print_events_type(u8 type); void print_events_type(u8 type);
......
%option prefix="parse_events_" %option prefix="parse_events_"
%option stack
%{ %{
#include <errno.h> #include <errno.h>
...@@ -50,6 +51,8 @@ static int term(int type) ...@@ -50,6 +51,8 @@ static int term(int type)
%} %}
%x mem
num_dec [0-9]+ num_dec [0-9]+
num_hex 0x[a-fA-F0-9]+ num_hex 0x[a-fA-F0-9]+
num_raw_hex [a-fA-F0-9]+ num_raw_hex [a-fA-F0-9]+
...@@ -102,16 +105,16 @@ misses|miss { return str(PE_NAME_CACHE_OP_RESULT); } ...@@ -102,16 +105,16 @@ misses|miss { return str(PE_NAME_CACHE_OP_RESULT); }
config { return term(PARSE_EVENTS__TERM_TYPE_CONFIG); } config { return term(PARSE_EVENTS__TERM_TYPE_CONFIG); }
config1 { return term(PARSE_EVENTS__TERM_TYPE_CONFIG1); } config1 { return term(PARSE_EVENTS__TERM_TYPE_CONFIG1); }
config2 { return term(PARSE_EVENTS__TERM_TYPE_CONFIG2); } config2 { return term(PARSE_EVENTS__TERM_TYPE_CONFIG2); }
name { return term(PARSE_EVENTS__TERM_TYPE_NAME); }
period { return term(PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); } period { return term(PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
branch_type { return term(PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } branch_type { return term(PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
mem: { return PE_PREFIX_MEM; } mem: { BEGIN(mem); return PE_PREFIX_MEM; }
r{num_raw_hex} { return raw(); } r{num_raw_hex} { return raw(); }
{num_dec} { return value(10); } {num_dec} { return value(10); }
{num_hex} { return value(16); } {num_hex} { return value(16); }
{modifier_event} { return str(PE_MODIFIER_EVENT); } {modifier_event} { return str(PE_MODIFIER_EVENT); }
{modifier_bp} { return str(PE_MODIFIER_BP); }
{name} { return str(PE_NAME); } {name} { return str(PE_NAME); }
"/" { return '/'; } "/" { return '/'; }
- { return '-'; } - { return '-'; }
...@@ -119,6 +122,25 @@ r{num_raw_hex} { return raw(); } ...@@ -119,6 +122,25 @@ r{num_raw_hex} { return raw(); }
: { return ':'; } : { return ':'; }
= { return '='; } = { return '='; }
<mem>{
{modifier_bp} { return str(PE_MODIFIER_BP); }
: { return ':'; }
{num_dec} { return value(10); }
{num_hex} { return value(16); }
/*
* We need to separate 'mem:' scanner part, in order to get specific
* modifier bits parsed out. Otherwise we would need to handle PE_NAME
* and we'd need to parse it manually. During the escape from <mem>
* state we need to put the escaping char back, so we dont miss it.
*/
. { unput(*parse_events_text); BEGIN(INITIAL); }
/*
* We destroy the scanner after reaching EOF,
* but anyway just to be sure get back to INIT state.
*/
<<EOF>> { BEGIN(INITIAL); }
}
%% %%
int parse_events_wrap(void) int parse_events_wrap(void)
......
%name-prefix "parse_events_" %name-prefix "parse_events_"
%parse-param {struct list_head *list_all} %parse-param {struct list_head *list_all}
%parse-param {struct list_head *list_event}
%parse-param {int *idx} %parse-param {int *idx}
%{ %{
...@@ -41,6 +40,14 @@ do { \ ...@@ -41,6 +40,14 @@ do { \
%type <str> PE_MODIFIER_BP %type <str> PE_MODIFIER_BP
%type <head> event_config %type <head> event_config
%type <term> event_term %type <term> event_term
%type <head> event_pmu
%type <head> event_legacy_symbol
%type <head> event_legacy_cache
%type <head> event_legacy_mem
%type <head> event_legacy_tracepoint
%type <head> event_legacy_numeric
%type <head> event_legacy_raw
%type <head> event_def
%union %union
{ {
...@@ -62,13 +69,13 @@ event_def PE_MODIFIER_EVENT ...@@ -62,13 +69,13 @@ event_def PE_MODIFIER_EVENT
* (there could be more events added for multiple tracepoint * (there could be more events added for multiple tracepoint
* definitions via '*?'. * definitions via '*?'.
*/ */
ABORT_ON(parse_events_modifier(list_event, $2)); ABORT_ON(parse_events_modifier($1, $2));
parse_events_update_lists(list_event, list_all); parse_events_update_lists($1, list_all);
} }
| |
event_def event_def
{ {
parse_events_update_lists(list_event, list_all); parse_events_update_lists($1, list_all);
} }
event_def: event_pmu | event_def: event_pmu |
...@@ -82,71 +89,102 @@ event_def: event_pmu | ...@@ -82,71 +89,102 @@ event_def: event_pmu |
event_pmu: event_pmu:
PE_NAME '/' event_config '/' PE_NAME '/' event_config '/'
{ {
ABORT_ON(parse_events_add_pmu(list_event, idx, $1, $3)); struct list_head *list = NULL;
ABORT_ON(parse_events_add_pmu(&list, idx, $1, $3));
parse_events__free_terms($3); parse_events__free_terms($3);
$$ = list;
} }
event_legacy_symbol: event_legacy_symbol:
PE_VALUE_SYM '/' event_config '/' PE_VALUE_SYM '/' event_config '/'
{ {
struct list_head *list = NULL;
int type = $1 >> 16; int type = $1 >> 16;
int config = $1 & 255; int config = $1 & 255;
ABORT_ON(parse_events_add_numeric(list_event, idx, type, config, $3)); ABORT_ON(parse_events_add_numeric(&list, idx, type, config, $3));
parse_events__free_terms($3); parse_events__free_terms($3);
$$ = list;
} }
| |
PE_VALUE_SYM sep_slash_dc PE_VALUE_SYM sep_slash_dc
{ {
struct list_head *list = NULL;
int type = $1 >> 16; int type = $1 >> 16;
int config = $1 & 255; int config = $1 & 255;
ABORT_ON(parse_events_add_numeric(list_event, idx, type, config, NULL)); ABORT_ON(parse_events_add_numeric(&list, idx, type, config, NULL));
$$ = list;
} }
event_legacy_cache: event_legacy_cache:
PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT
{ {
ABORT_ON(parse_events_add_cache(list_event, idx, $1, $3, $5)); struct list_head *list = NULL;
ABORT_ON(parse_events_add_cache(&list, idx, $1, $3, $5));
$$ = list;
} }
| |
PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT
{ {
ABORT_ON(parse_events_add_cache(list_event, idx, $1, $3, NULL)); struct list_head *list = NULL;
ABORT_ON(parse_events_add_cache(&list, idx, $1, $3, NULL));
$$ = list;
} }
| |
PE_NAME_CACHE_TYPE PE_NAME_CACHE_TYPE
{ {
ABORT_ON(parse_events_add_cache(list_event, idx, $1, NULL, NULL)); struct list_head *list = NULL;
ABORT_ON(parse_events_add_cache(&list, idx, $1, NULL, NULL));
$$ = list;
} }
event_legacy_mem: event_legacy_mem:
PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
{ {
ABORT_ON(parse_events_add_breakpoint(list_event, idx, (void *) $2, $4)); struct list_head *list = NULL;
ABORT_ON(parse_events_add_breakpoint(&list, idx, (void *) $2, $4));
$$ = list;
} }
| |
PE_PREFIX_MEM PE_VALUE sep_dc PE_PREFIX_MEM PE_VALUE sep_dc
{ {
ABORT_ON(parse_events_add_breakpoint(list_event, idx, (void *) $2, NULL)); struct list_head *list = NULL;
ABORT_ON(parse_events_add_breakpoint(&list, idx, (void *) $2, NULL));
$$ = list;
} }
event_legacy_tracepoint: event_legacy_tracepoint:
PE_NAME ':' PE_NAME PE_NAME ':' PE_NAME
{ {
ABORT_ON(parse_events_add_tracepoint(list_event, idx, $1, $3)); struct list_head *list = NULL;
ABORT_ON(parse_events_add_tracepoint(&list, idx, $1, $3));
$$ = list;
} }
event_legacy_numeric: event_legacy_numeric:
PE_VALUE ':' PE_VALUE PE_VALUE ':' PE_VALUE
{ {
ABORT_ON(parse_events_add_numeric(list_event, idx, $1, $3, NULL)); struct list_head *list = NULL;
ABORT_ON(parse_events_add_numeric(&list, idx, $1, $3, NULL));
$$ = list;
} }
event_legacy_raw: event_legacy_raw:
PE_RAW PE_RAW
{ {
ABORT_ON(parse_events_add_numeric(list_event, idx, PERF_TYPE_RAW, $1, NULL)); struct list_head *list = NULL;
ABORT_ON(parse_events_add_numeric(&list, idx, PERF_TYPE_RAW, $1, NULL));
$$ = list;
} }
event_config: event_config:
...@@ -199,6 +237,14 @@ PE_NAME ...@@ -199,6 +237,14 @@ PE_NAME
$$ = term; $$ = term;
} }
| |
PE_TERM '=' PE_NAME
{
struct parse_events__term *term;
ABORT_ON(parse_events__term_str(&term, $1, NULL, $3));
$$ = term;
}
|
PE_TERM '=' PE_VALUE PE_TERM '=' PE_VALUE
{ {
struct parse_events__term *term; struct parse_events__term *term;
...@@ -222,7 +268,6 @@ sep_slash_dc: '/' | ':' | ...@@ -222,7 +268,6 @@ sep_slash_dc: '/' | ':' |
%% %%
void parse_events_error(struct list_head *list_all __used, void parse_events_error(struct list_head *list_all __used,
struct list_head *list_event __used,
int *idx __used, int *idx __used,
char const *msg __used) char const *msg __used)
{ {
......
...@@ -258,9 +258,9 @@ static int pmu_config_term(struct list_head *formats, ...@@ -258,9 +258,9 @@ static int pmu_config_term(struct list_head *formats,
static int pmu_config(struct list_head *formats, struct perf_event_attr *attr, static int pmu_config(struct list_head *formats, struct perf_event_attr *attr,
struct list_head *head_terms) struct list_head *head_terms)
{ {
struct parse_events__term *term, *h; struct parse_events__term *term;
list_for_each_entry_safe(term, h, head_terms, list) list_for_each_entry(term, head_terms, list)
if (pmu_config_term(formats, attr, term)) if (pmu_config_term(formats, attr, term))
return -EINVAL; return -EINVAL;
......
...@@ -56,7 +56,7 @@ INTERP my_perl; ...@@ -56,7 +56,7 @@ INTERP my_perl;
#define FTRACE_MAX_EVENT \ #define FTRACE_MAX_EVENT \
((1 << (sizeof(unsigned short) * 8)) - 1) ((1 << (sizeof(unsigned short) * 8)) - 1)
struct event *events[FTRACE_MAX_EVENT]; struct event_format *events[FTRACE_MAX_EVENT];
extern struct scripting_context *scripting_context; extern struct scripting_context *scripting_context;
...@@ -181,7 +181,7 @@ static void define_flag_field(const char *ev_name, ...@@ -181,7 +181,7 @@ static void define_flag_field(const char *ev_name,
LEAVE; LEAVE;
} }
static void define_event_symbols(struct event *event, static void define_event_symbols(struct event_format *event,
const char *ev_name, const char *ev_name,
struct print_arg *args) struct print_arg *args)
{ {
...@@ -209,6 +209,8 @@ static void define_event_symbols(struct event *event, ...@@ -209,6 +209,8 @@ static void define_event_symbols(struct event *event,
define_symbolic_values(args->symbol.symbols, ev_name, define_symbolic_values(args->symbol.symbols, ev_name,
cur_field_name); cur_field_name);
break; break;
case PRINT_BSTRING:
case PRINT_DYNAMIC_ARRAY:
case PRINT_STRING: case PRINT_STRING:
break; break;
case PRINT_TYPE: case PRINT_TYPE:
...@@ -220,7 +222,9 @@ static void define_event_symbols(struct event *event, ...@@ -220,7 +222,9 @@ static void define_event_symbols(struct event *event,
define_event_symbols(event, ev_name, args->op.left); define_event_symbols(event, ev_name, args->op.left);
define_event_symbols(event, ev_name, args->op.right); define_event_symbols(event, ev_name, args->op.right);
break; break;
case PRINT_FUNC:
default: default:
pr_err("Unsupported print arg type\n");
/* we should warn... */ /* we should warn... */
return; return;
} }
...@@ -229,10 +233,10 @@ static void define_event_symbols(struct event *event, ...@@ -229,10 +233,10 @@ static void define_event_symbols(struct event *event,
define_event_symbols(event, ev_name, args->next); define_event_symbols(event, ev_name, args->next);
} }
static inline struct event *find_cache_event(int type) static inline struct event_format *find_cache_event(int type)
{ {
static char ev_name[256]; static char ev_name[256];
struct event *event; struct event_format *event;
if (events[type]) if (events[type])
return events[type]; return events[type];
...@@ -258,7 +262,7 @@ static void perl_process_tracepoint(union perf_event *pevent __unused, ...@@ -258,7 +262,7 @@ static void perl_process_tracepoint(union perf_event *pevent __unused,
static char handler[256]; static char handler[256];
unsigned long long val; unsigned long long val;
unsigned long s, ns; unsigned long s, ns;
struct event *event; struct event_format *event;
int type; int type;
int pid; int pid;
int cpu = sample->cpu; int cpu = sample->cpu;
...@@ -446,7 +450,7 @@ static int perl_stop_script(void) ...@@ -446,7 +450,7 @@ static int perl_stop_script(void)
static int perl_generate_script(const char *outfile) static int perl_generate_script(const char *outfile)
{ {
struct event *event = NULL; struct event_format *event = NULL;
struct format_field *f; struct format_field *f;
char fname[PATH_MAX]; char fname[PATH_MAX];
int not_first, count; int not_first, count;
......
...@@ -481,6 +481,38 @@ static void perf_event__read_swap(union perf_event *event) ...@@ -481,6 +481,38 @@ static void perf_event__read_swap(union perf_event *event)
event->read.id = bswap_64(event->read.id); event->read.id = bswap_64(event->read.id);
} }
static u8 revbyte(u8 b)
{
int rev = (b >> 4) | ((b & 0xf) << 4);
rev = ((rev & 0xcc) >> 2) | ((rev & 0x33) << 2);
rev = ((rev & 0xaa) >> 1) | ((rev & 0x55) << 1);
return (u8) rev;
}
/*
* XXX this is hack in attempt to carry flags bitfield
* throught endian village. ABI says:
*
* Bit-fields are allocated from right to left (least to most significant)
* on little-endian implementations and from left to right (most to least
* significant) on big-endian implementations.
*
* The above seems to be byte specific, so we need to reverse each
* byte of the bitfield. 'Internet' also says this might be implementation
* specific and we probably need proper fix and carry perf_event_attr
* bitfield flags in separate data file FEAT_ section. Thought this seems
* to work for now.
*/
static void swap_bitfield(u8 *p, unsigned len)
{
unsigned i;
for (i = 0; i < len; i++) {
*p = revbyte(*p);
p++;
}
}
/* exported for swapping attributes in file header */ /* exported for swapping attributes in file header */
void perf_event__attr_swap(struct perf_event_attr *attr) void perf_event__attr_swap(struct perf_event_attr *attr)
{ {
...@@ -494,6 +526,8 @@ void perf_event__attr_swap(struct perf_event_attr *attr) ...@@ -494,6 +526,8 @@ void perf_event__attr_swap(struct perf_event_attr *attr)
attr->bp_type = bswap_32(attr->bp_type); attr->bp_type = bswap_32(attr->bp_type);
attr->bp_addr = bswap_64(attr->bp_addr); attr->bp_addr = bswap_64(attr->bp_addr);
attr->bp_len = bswap_64(attr->bp_len); attr->bp_len = bswap_64(attr->bp_len);
swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64));
} }
static void perf_event__hdr_attr_swap(union perf_event *event) static void perf_event__hdr_attr_swap(union perf_event *event)
...@@ -1064,8 +1098,9 @@ volatile int session_done; ...@@ -1064,8 +1098,9 @@ volatile int session_done;
static int __perf_session__process_pipe_events(struct perf_session *self, static int __perf_session__process_pipe_events(struct perf_session *self,
struct perf_tool *tool) struct perf_tool *tool)
{ {
union perf_event event; union perf_event *event;
uint32_t size; uint32_t size, cur_size = 0;
void *buf = NULL;
int skip = 0; int skip = 0;
u64 head; u64 head;
int err; int err;
...@@ -1074,8 +1109,14 @@ static int __perf_session__process_pipe_events(struct perf_session *self, ...@@ -1074,8 +1109,14 @@ static int __perf_session__process_pipe_events(struct perf_session *self,
perf_tool__fill_defaults(tool); perf_tool__fill_defaults(tool);
head = 0; head = 0;
cur_size = sizeof(union perf_event);
buf = malloc(cur_size);
if (!buf)
return -errno;
more: more:
err = readn(self->fd, &event, sizeof(struct perf_event_header)); event = buf;
err = readn(self->fd, event, sizeof(struct perf_event_header));
if (err <= 0) { if (err <= 0) {
if (err == 0) if (err == 0)
goto done; goto done;
...@@ -1085,13 +1126,23 @@ static int __perf_session__process_pipe_events(struct perf_session *self, ...@@ -1085,13 +1126,23 @@ static int __perf_session__process_pipe_events(struct perf_session *self,
} }
if (self->header.needs_swap) if (self->header.needs_swap)
perf_event_header__bswap(&event.header); perf_event_header__bswap(&event->header);
size = event.header.size; size = event->header.size;
if (size == 0) if (size == 0)
size = 8; size = 8;
p = &event; if (size > cur_size) {
void *new = realloc(buf, size);
if (!new) {
pr_err("failed to allocate memory to read event\n");
goto out_err;
}
buf = new;
cur_size = size;
event = buf;
}
p = event;
p += sizeof(struct perf_event_header); p += sizeof(struct perf_event_header);
if (size - sizeof(struct perf_event_header)) { if (size - sizeof(struct perf_event_header)) {
...@@ -1107,9 +1158,9 @@ static int __perf_session__process_pipe_events(struct perf_session *self, ...@@ -1107,9 +1158,9 @@ static int __perf_session__process_pipe_events(struct perf_session *self,
} }
} }
if ((skip = perf_session__process_event(self, &event, tool, head)) < 0) { if ((skip = perf_session__process_event(self, event, tool, head)) < 0) {
pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
head, event.header.size, event.header.type); head, event->header.size, event->header.type);
err = -EINVAL; err = -EINVAL;
goto out_err; goto out_err;
} }
...@@ -1124,6 +1175,7 @@ static int __perf_session__process_pipe_events(struct perf_session *self, ...@@ -1124,6 +1175,7 @@ static int __perf_session__process_pipe_events(struct perf_session *self,
done: done:
err = 0; err = 0;
out_err: out_err:
free(buf);
perf_session__warn_about_errors(self, tool); perf_session__warn_about_errors(self, tool);
perf_session_free_sample_buffers(self); perf_session_free_sample_buffers(self);
return err; return err;
......
...@@ -16,4 +16,9 @@ typedef signed short s16; ...@@ -16,4 +16,9 @@ typedef signed short s16;
typedef unsigned char u8; typedef unsigned char u8;
typedef signed char s8; typedef signed char s8;
union u64_swap {
u64 val64;
u32 val32[2];
};
#endif /* __PERF_TYPES_H */ #endif /* __PERF_TYPES_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment