Commit 754fe00f authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-core-for-mingo-4.15-20171117' of...

Merge tag 'perf-core-for-mingo-4.15-20171117' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

- Optimize sample parsing for ordering events, where we don't need to parse
  all the PERF_SAMPLE_ bits, just the ones leading to the timestamp needed
  to reorder events (Jiri Olsa)

- Use a dummy event to ask for PERF_RECORD_{MMAP,COMM,EXEC} with
  'perf record --delay', when the events asked by the user will only be
  enabled after the workload is started and the requested delay passes,
  so we need to add the dummy event and have it .enabled_on_exec. This
  then allows us to resolve symbols for the DSO executable MMAPs setup
  while we wait for the delay (Arnaldo Carvalho de Melo)

- Synchronize kcmp.h and prctl.h ABI headers wrt SPDX tags (Arnaldo Carvalho de Melo)

- Generalize the annotation code to support other source information
  besides objdump/DWARF obtained ones, starting with python scripts,
  that will is slated to be merged soon (Jiri Olsa)

- Advance the source code lines to right after the column with the
  address in asm lines (Jiri Olsa)

- Fix terminal dimensions resizing signal handling in 'perf top --stdio' (Jiri Olsa)

- Improve error messages for PMU events (Kim Phillips)

- Fix 'perf record' -c/-F options for cpu event aliases (Andi Kleen)

- Enable type checking for perf_evsel_config_term types (Andi Kleen)

- Call machine__exit() at 'perf trace' exit, so as to remove temporary
  files related to VDSO (Andrei Vagin)

- Add "reject" option to parse-events.l, fixing the build with newer
  flex releases. Noticed with flex 2.6.4 on Alpine Linux 3.6 and Edge (Jiri Olsa)

- Document some missing perf.data headers (Andi Kleen)

- Allow printing period for non freq mod groups (Andi Kleen)

- Do not warn the user about kernel.kptr_restrict when not sampling the
  kernel (Arnaldo Carvalho de Melo)

- Fix bug in 'perf help' introduced during conversion to strstart() (Namhyung Kim)

- Do not truncate ASM instruction mnemonics at 6 characters in the annotation
  output, PowerPC has long ones (Ravi Bangoria)

- Document some missing command line options (Sihyeon Jang)

- Update POWER9 vendor event tables (Sukadev Bhattiprolu)

- Fix 'perf test' shell entries on s390x, where the 'openat' syscall
  is used instead of 'open' in one of the tests and

- No need to use overwrite mmap mode in 'perf test', those tests
  do not generate massive amount of events to fill the ring buffer (Wang Nan)

- Add missing command line options (mostly --force/-f) to the man pages (Sihyeon Jang)
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents b29c6ef7 05d3f1a1
......@@ -6640,6 +6640,7 @@ static void perf_event_namespaces_output(struct perf_event *event,
struct perf_namespaces_event *namespaces_event = data;
struct perf_output_handle handle;
struct perf_sample_data sample;
u16 header_size = namespaces_event->event_id.header.size;
int ret;
if (!perf_event_namespaces_match(event))
......@@ -6650,7 +6651,7 @@ static void perf_event_namespaces_output(struct perf_event *event,
ret = perf_output_begin(&handle, event,
namespaces_event->event_id.header.size);
if (ret)
return;
goto out;
namespaces_event->event_id.pid = perf_event_pid(event,
namespaces_event->task);
......@@ -6662,6 +6663,8 @@ static void perf_event_namespaces_output(struct perf_event *event,
perf_event__output_id_sample(event, &handle, &sample);
perf_output_end(&handle);
out:
namespaces_event->event_id.header.size = header_size;
}
static void perf_fill_ns_link_info(struct perf_ns_link_info *ns_link_info,
......
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _UAPI_LINUX_KCMP_H
#define _UAPI_LINUX_KCMP_H
......
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _LINUX_PRCTL_H
#define _LINUX_PRCTL_H
......
......@@ -24,6 +24,9 @@ OPTIONS
-a::
--add=::
Add specified file to the cache.
-f::
--force::
Don't complain, do it.
-k::
--kcore::
Add specified kcore file to the cache. For the current host that is
......
......@@ -20,6 +20,10 @@ OPTIONS
--input=::
Input file name. (default: perf.data unless stdin is a fifo)
-f::
--force::
Don't complain, do it.
-F::
--freq=::
Show just the sample frequency used for each event.
......
......@@ -60,6 +60,10 @@ include::itrace.txt[]
found in the jitdumps files captured in the input perf.data file. Use this option
if you are monitoring environment using JIT runtimes, such as Java, DART or V8.
-f::
--force::
Don't complain, do it.
SEE ALSO
--------
linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1]
......@@ -42,6 +42,10 @@ COMMON OPTIONS
--dump-raw-trace::
Dump raw trace in ASCII.
-f::
--force::
Don't complan, do it.
REPORT OPTIONS
--------------
......
......@@ -74,6 +74,10 @@ OPTIONS
--dump-raw-trace=::
Display verbose dump of the sched data.
-f::
--force::
Don't complain, do it.
OPTIONS for 'perf sched map'
----------------------------
......
......@@ -50,7 +50,9 @@ TIMECHART OPTIONS
-p::
--process::
Select the processes to display, by name or PID
-f::
--force::
Don't complain, do it.
--symfs=<directory>::
Look for files with symbols relative to this directory.
-n::
......
......@@ -268,6 +268,12 @@ INTERACTIVE PROMPTING KEYS
[S]::
Stop annotation, return to full profile display.
[K]::
Hide kernel symbols.
[U]::
Hide user symbols.
[z]::
Toggle event count zeroing across display updates.
......
......@@ -86,18 +86,18 @@ comma-separated list with no space: 0,1. Ranges of CPUs are specified with -: 0-
In per-thread mode with inheritance mode on (default), Events are captured only when
the thread executes on the designated CPUs. Default is to monitor all CPUs.
--duration:
--duration::
Show only events that had a duration greater than N.M ms.
--sched:
--sched::
Accrue thread runtime and provide a summary at the end of the session.
-i
--input
-i::
--input::
Process events from a given perf data file.
-T
--time
-T::
--time::
Print full timestamp rather time relative to first sample.
--comm::
......@@ -117,6 +117,10 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
Show tool stats such as number of times fd->pathname was discovered thru
hooking the open syscall return + vfs_getname or via reading /proc/pid/fd, etc.
-f::
--force::
Don't complain, do it.
-F=[all|min|maj]::
--pf=[all|min|maj]::
Trace pagefaults. Optionally, you can specify whether you want minor,
......
......@@ -238,6 +238,29 @@ struct auxtrace_index {
struct auxtrace_index_entry entries[PERF_AUXTRACE_INDEX_ENTRY_COUNT];
};
HEADER_STAT = 19,
This is merely a flag signifying that the data section contains data
recorded from perf stat record.
HEADER_CACHE = 20,
Description of the cache hierarchy. Based on the Linux sysfs format
in /sys/devices/system/cpu/cpu*/cache/
u32 version Currently always 1
u32 number_of_cache_levels
struct {
u32 level;
u32 line_size;
u32 sets;
u32 ways;
struct perf_header_string type;
struct perf_header_string size;
struct perf_header_string map;
}[number_of_cache_levels];
other bits are reserved and should ignored for now
HEADER_FEAT_BITS = 256,
......
......@@ -579,7 +579,7 @@ else
PERL_EMBED_LDOPTS = $(shell perl -MExtUtils::Embed -e ldopts 2>/dev/null)
PERL_EMBED_LDFLAGS = $(call strip-libs,$(PERL_EMBED_LDOPTS))
PERL_EMBED_LIBADD = $(call grep-libs,$(PERL_EMBED_LDOPTS))
PERL_EMBED_CCOPTS = `perl -MExtUtils::Embed -e ccopts 2>/dev/null`
PERL_EMBED_CCOPTS = $(shell perl -MExtUtils::Embed -e ccopts 2>/dev/null)
FLAGS_PERL_EMBED=$(PERL_EMBED_CCOPTS) $(PERL_EMBED_LDOPTS)
ifneq ($(feature-libperl), 1)
......
......@@ -325,8 +325,8 @@ int cmd_buildid_cache(int argc, const char **argv)
"file", "kcore file to add"),
OPT_STRING('r', "remove", &remove_name_list_str, "file list",
"file(s) to remove"),
OPT_STRING('p', "purge", &purge_name_list_str, "path list",
"path(s) to remove (remove old caches too)"),
OPT_STRING('p', "purge", &purge_name_list_str, "file list",
"file(s) to remove (remove old caches too)"),
OPT_STRING('M', "missing", &missing_filename, "file",
"to find missing build ids in the cache"),
OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
......
......@@ -2224,9 +2224,9 @@ static int perf_c2c__browse_cacheline(struct hist_entry *he)
struct hist_browser *browser;
int key = -1;
const char help[] =
" ENTER Togle callchains (if present) \n"
" n Togle Node details info \n"
" s Togle full lenght of symbol and source line columns \n"
" ENTER Toggle callchains (if present) \n"
" n Toggle Node details info \n"
" s Toggle full length of symbol and source line columns \n"
" q Return back to cacheline list \n";
/* Display compact version first. */
......@@ -2303,7 +2303,7 @@ static int perf_c2c__hists_browse(struct hists *hists)
int key = -1;
const char help[] =
" d Display cacheline details \n"
" ENTER Togle callchains (if present) \n"
" ENTER Toggle callchains (if present) \n"
" q Quit \n";
browser = perf_c2c_browser__new(hists);
......
......@@ -284,7 +284,7 @@ static int perf_help_config(const char *var, const char *value, void *cb)
add_man_viewer(value);
return 0;
}
if (!strstarts(var, "man."))
if (strstarts(var, "man."))
return add_man_viewer_info(var, value);
return 0;
......@@ -314,7 +314,7 @@ static const char *cmd_to_page(const char *perf_cmd)
if (!perf_cmd)
return "perf";
else if (!strstarts(perf_cmd, "perf"))
else if (strstarts(perf_cmd, "perf"))
return perf_cmd;
return asprintf(&s, "perf-%s", perf_cmd) < 0 ? NULL : s;
......
......@@ -741,20 +741,20 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
u64 *mmap_time)
{
union perf_event *event;
struct perf_sample sample;
u64 timestamp;
s64 n = 0;
int err;
*mmap_time = ULLONG_MAX;
while ((event = perf_evlist__mmap_read(kvm->evlist, idx)) != NULL) {
err = perf_evlist__parse_sample(kvm->evlist, event, &sample);
err = perf_evlist__parse_sample_timestamp(kvm->evlist, event, &timestamp);
if (err) {
perf_evlist__mmap_consume(kvm->evlist, idx);
pr_err("Failed to parse sample\n");
return -1;
}
err = perf_session__queue_event(kvm->session, event, &sample, 0);
err = perf_session__queue_event(kvm->session, event, timestamp, 0);
/*
* FIXME: Here we can't consume the event, as perf_session__queue_event will
* point to it, and it'll get possibly overwritten by the kernel.
......@@ -768,7 +768,7 @@ static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
/* save time stamp of our first sample for this mmap */
if (n == 0)
*mmap_time = sample.time;
*mmap_time = timestamp;
/* limit events per mmap handled all at once */
n++;
......
......@@ -339,6 +339,22 @@ static int record__open(struct record *rec)
struct perf_evsel_config_term *err_term;
int rc = 0;
/*
* For initial_delay we need to add a dummy event so that we can track
* PERF_RECORD_MMAP while we wait for the initial delay to enable the
* real events, the ones asked by the user.
*/
if (opts->initial_delay) {
if (perf_evlist__add_dummy(evlist))
return -ENOMEM;
pos = perf_evlist__first(evlist);
pos->tracking = 0;
pos = perf_evlist__last(evlist);
pos->tracking = 1;
pos->attr.enable_on_exec = 1;
}
perf_evlist__config(evlist, opts, &callchain_param);
evlist__for_each_entry(evlist, pos) {
......@@ -749,17 +765,19 @@ static int record__synthesize(struct record *rec, bool tail)
goto out;
}
err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
machine);
WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n"
"Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
"Check /proc/kallsyms permission or run as root.\n");
err = perf_event__synthesize_modules(tool, process_synthesized_event,
machine);
WARN_ONCE(err < 0, "Couldn't record kernel module information.\n"
"Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
"Check /proc/modules permission or run as root.\n");
if (!perf_evlist__exclude_kernel(rec->evlist)) {
err = perf_event__synthesize_kernel_mmap(tool, process_synthesized_event,
machine);
WARN_ONCE(err < 0, "Couldn't record kernel reference relocation symbol\n"
"Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
"Check /proc/kallsyms permission or run as root.\n");
err = perf_event__synthesize_modules(tool, process_synthesized_event,
machine);
WARN_ONCE(err < 0, "Couldn't record kernel module information.\n"
"Symbol resolution may be skewed if relocation was used (e.g. kexec).\n"
"Check /proc/modules permission or run as root.\n");
}
if (perf_guest) {
machines__process_guests(&session->machines,
......@@ -1693,7 +1711,7 @@ int cmd_record(int argc, const char **argv)
err = -ENOMEM;
if (symbol_conf.kptr_restrict)
if (symbol_conf.kptr_restrict && !perf_evlist__exclude_kernel(rec->evlist))
pr_warning(
"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
"check /proc/sys/kernel/kptr_restrict.\n\n"
......
......@@ -441,6 +441,9 @@ static void report__warn_kptr_restrict(const struct report *rep)
struct map *kernel_map = machine__kernel_map(&rep->session->machines.host);
struct kmap *kernel_kmap = kernel_map ? map__kmap(kernel_map) : NULL;
if (perf_evlist__exclude_kernel(rep->session->evlist))
return;
if (kernel_map == NULL ||
(kernel_map->dso->hit &&
(kernel_kmap->ref_reloc_sym == NULL ||
......
......@@ -423,11 +423,6 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
PERF_OUTPUT_CPU, allow_user_set))
return -EINVAL;
if (PRINT_FIELD(PERIOD) &&
perf_evsel__check_stype(evsel, PERF_SAMPLE_PERIOD, "PERIOD",
PERF_OUTPUT_PERIOD))
return -EINVAL;
if (PRINT_FIELD(IREGS) &&
perf_evsel__check_stype(evsel, PERF_SAMPLE_REGS_INTR, "IREGS",
PERF_OUTPUT_IREGS))
......@@ -1955,6 +1950,16 @@ static int perf_script__fopen_per_event_dump(struct perf_script *script)
struct perf_evsel *evsel;
evlist__for_each_entry(script->session->evlist, evsel) {
/*
* Already setup? I.e. we may be called twice in cases like
* Intel PT, one for the intel_pt// and dummy events, then
* for the evsels syntheized from the auxtrace info.
*
* Ses perf_script__process_auxtrace_info.
*/
if (evsel->priv != NULL)
continue;
evsel->priv = perf_evsel_script__new(evsel, script->session->data);
if (evsel->priv == NULL)
goto out_err_fclose;
......@@ -2838,6 +2843,25 @@ int process_cpu_map_event(struct perf_tool *tool __maybe_unused,
return set_maps(script);
}
#ifdef HAVE_AUXTRACE_SUPPORT
static int perf_script__process_auxtrace_info(struct perf_tool *tool,
union perf_event *event,
struct perf_session *session)
{
int ret = perf_event__process_auxtrace_info(tool, event, session);
if (ret == 0) {
struct perf_script *script = container_of(tool, struct perf_script, tool);
ret = perf_script__setup_per_event_dump(script);
}
return ret;
}
#else
#define perf_script__process_auxtrace_info 0
#endif
int cmd_script(int argc, const char **argv)
{
bool show_full_info = false;
......@@ -2866,7 +2890,7 @@ int cmd_script(int argc, const char **argv)
.feature = perf_event__process_feature,
.build_id = perf_event__process_build_id,
.id_index = perf_event__process_id_index,
.auxtrace_info = perf_event__process_auxtrace_info,
.auxtrace_info = perf_script__process_auxtrace_info,
.auxtrace = perf_event__process_auxtrace,
.auxtrace_error = perf_event__process_auxtrace_error,
.stat = perf_event__process_stat_event,
......
......@@ -77,6 +77,7 @@
#include "sane_ctype.h"
static volatile int done;
static volatile int resize;
#define HEADER_LINE_NR 5
......@@ -85,17 +86,20 @@ static void perf_top__update_print_entries(struct perf_top *top)
top->print_entries = top->winsize.ws_row - HEADER_LINE_NR;
}
static void perf_top__sig_winch(int sig __maybe_unused,
siginfo_t *info __maybe_unused, void *arg)
static void winch_sig(int sig __maybe_unused)
{
struct perf_top *top = arg;
resize = 1;
}
static void perf_top__resize(struct perf_top *top)
{
get_term_dimensions(&top->winsize);
perf_top__update_print_entries(top);
}
static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
{
struct perf_evsel *evsel = hists_to_evsel(he->hists);
struct symbol *sym;
struct annotation *notes;
struct map *map;
......@@ -134,7 +138,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
return err;
}
err = symbol__disassemble(sym, map, NULL, 0, NULL, NULL);
err = symbol__annotate(sym, map, evsel, 0, NULL, NULL);
if (err == 0) {
out_assign:
top->sym_filter_entry = he;
......@@ -226,6 +230,7 @@ static void perf_top__record_precise_ip(struct perf_top *top,
static void perf_top__show_details(struct perf_top *top)
{
struct hist_entry *he = top->sym_filter_entry;
struct perf_evsel *evsel = hists_to_evsel(he->hists);
struct annotation *notes;
struct symbol *symbol;
int more;
......@@ -238,6 +243,8 @@ static void perf_top__show_details(struct perf_top *top)
pthread_mutex_lock(&notes->lock);
symbol__calc_percent(symbol, evsel);
if (notes->src == NULL)
goto out_unlock;
......@@ -409,7 +416,7 @@ static void perf_top__print_mapped_keys(struct perf_top *top)
fprintf(stdout, "\t[S] stop annotation.\n");
fprintf(stdout,
"\t[K] hide kernel_symbols symbols. \t(%s)\n",
"\t[K] hide kernel symbols. \t(%s)\n",
top->hide_kernel_symbols ? "yes" : "no");
fprintf(stdout,
"\t[U] hide user symbols. \t(%s)\n",
......@@ -473,12 +480,8 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
case 'e':
prompt_integer(&top->print_entries, "Enter display entries (lines)");
if (top->print_entries == 0) {
struct sigaction act = {
.sa_sigaction = perf_top__sig_winch,
.sa_flags = SA_SIGINFO,
};
perf_top__sig_winch(SIGWINCH, NULL, top);
sigaction(SIGWINCH, &act, NULL);
perf_top__resize(top);
signal(SIGWINCH, winch_sig);
} else {
signal(SIGWINCH, SIG_DFL);
}
......@@ -732,14 +735,16 @@ static void perf_event__process_sample(struct perf_tool *tool,
if (!machine->kptr_restrict_warned &&
symbol_conf.kptr_restrict &&
al.cpumode == PERF_RECORD_MISC_KERNEL) {
ui__warning(
if (!perf_evlist__exclude_kernel(top->session->evlist)) {
ui__warning(
"Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n"
"Check /proc/sys/kernel/kptr_restrict.\n\n"
"Kernel%s samples will not be resolved.\n",
al.map && !RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION]) ?
" modules" : "");
if (use_browser <= 0)
sleep(5);
if (use_browser <= 0)
sleep(5);
}
machine->kptr_restrict_warned = true;
}
......@@ -1030,6 +1035,11 @@ static int __cmd_top(struct perf_top *top)
if (hits == top->samples)
ret = perf_evlist__poll(top->evlist, 100);
if (resize) {
perf_top__resize(top);
resize = 0;
}
}
ret = 0;
......@@ -1352,12 +1362,8 @@ int cmd_top(int argc, const char **argv)
get_term_dimensions(&top.winsize);
if (top.print_entries == 0) {
struct sigaction act = {
.sa_sigaction = perf_top__sig_winch,
.sa_flags = SA_SIGINFO,
};
perf_top__update_print_entries(&top);
sigaction(SIGWINCH, &act, NULL);
signal(SIGWINCH, winch_sig);
}
status = __cmd_top(&top);
......
......@@ -1152,12 +1152,14 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
if (trace->host == NULL)
return -ENOMEM;
if (trace_event__register_resolver(trace->host, trace__machine__resolve_kernel_addr) < 0)
return -errno;
err = trace_event__register_resolver(trace->host, trace__machine__resolve_kernel_addr);
if (err < 0)
goto out;
err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
evlist->threads, trace__tool_process, false,
trace->opts.proc_map_timeout, 1);
out:
if (err)
symbol__exit();
......
......@@ -124,11 +124,6 @@
"EventName": "PM_CMPLU_STALL_LARX",
"BriefDescription": "Finish stall because the NTF instruction was a larx waiting to be satisfied"
},
{,
"EventCode": "0x3006C",
"EventName": "PM_RUN_CYC_SMT2_MODE",
"BriefDescription": "Cycles in which this thread's run latch is set and the core is in SMT2 mode"
},
{,
"EventCode": "0x1C058",
"EventName": "PM_DTLB_MISS_16G",
......
[
{,
"EventCode": "0x3E15C",
"EventName": "PM_MRK_L2_TM_ST_ABORT_SISTER",
"BriefDescription": "TM marked store abort for this thread"
},
{,
"EventCode": "0x25044",
"EventName": "PM_IPTEG_FROM_L31_MOD",
......@@ -369,4 +364,4 @@
"EventName": "PM_IPTEG_FROM_L31_ECO_MOD",
"BriefDescription": "A Page Table Entry was loaded into the TLB with Modified (M) data from another core's ECO L3 on the same chip due to a instruction side request"
}
]
]
\ No newline at end of file
[
{,
"EventCode": "0x3C052",
"EventName": "PM_DATA_SYS_PUMP_MPRED",
"BriefDescription": "Final Pump Scope (system) mispredicted. Either the original scope was too small (Chip/Group) or the original scope was System and it should have been smaller. Counts for a demand load"
},
{,
"EventCode": "0x3013E",
"EventName": "PM_MRK_STALL_CMPLU_CYC",
......@@ -254,6 +249,11 @@
"EventName": "PM_RADIX_PWC_L1_PDE_FROM_L3",
"BriefDescription": "A Page Directory Entry was reloaded to a level 1 page walk cache from the core's L3 data cache"
},
{,
"EventCode": "0x3C052",
"EventName": "PM_DATA_SYS_PUMP_MPRED",
"BriefDescription": "Final Pump Scope (system) mispredicted. Either the original scope was too small (Chip/Group) or the original scope was System and it should have been smaller. Counts for a demand load"
},
{,
"EventCode": "0x4D142",
"EventName": "PM_MRK_DATA_FROM_L3",
......@@ -434,21 +434,6 @@
"EventName": "PM_ITLB_MISS",
"BriefDescription": "ITLB Reloaded. Counts 1 per ITLB miss for HPT but multiple for radix depending on number of levels traveresed"
},
{,
"EventCode": "0x2D024",
"EventName": "PM_RADIX_PWC_L2_HIT",
"BriefDescription": "A radix translation attempt missed in the TLB but hit on both the first and second levels of page walk cache."
},
{,
"EventCode": "0x3F056",
"EventName": "PM_RADIX_PWC_L3_HIT",
"BriefDescription": "A radix translation attempt missed in the TLB but hit on the first, second, and third levels of page walk cache."
},
{,
"EventCode": "0x4E014",
"EventName": "PM_TM_TX_PASS_RUN_INST",
"BriefDescription": "Run instructions spent in successful transactions"
},
{,
"EventCode": "0x1E044",
"EventName": "PM_DPTEG_FROM_L3_NO_CONFLICT",
......@@ -644,4 +629,4 @@
"EventName": "PM_MRK_BR_MPRED_CMPL",
"BriefDescription": "Marked Branch Mispredicted"
}
]
]
\ No newline at end of file
......@@ -124,6 +124,11 @@
"EventName": "PM_PMC5_OVERFLOW",
"BriefDescription": "Overflow from counter 5"
},
{,
"EventCode": "0x4505E",
"EventName": "PM_FLOP_CMPL",
"BriefDescription": "Floating Point Operation Finished"
},
{,
"EventCode": "0x2C018",
"EventName": "PM_CMPLU_STALL_DMISS_L21_L31",
......@@ -389,11 +394,6 @@
"EventName": "PM_ICT_NOSLOT_BR_MPRED",
"BriefDescription": "Ict empty for this thread due to branch mispred"
},
{,
"EventCode": "0x3405E",
"EventName": "PM_IFETCH_THROTTLE",
"BriefDescription": "Cycles in which Instruction fetch throttle was active."
},
{,
"EventCode": "0x1F148",
"EventName": "PM_MRK_DPTEG_FROM_ON_CHIP_CACHE",
......@@ -422,7 +422,7 @@
{,
"EventCode": "0xD0A8",
"EventName": "PM_DSLB_MISS",
"BriefDescription": "Data SLB Miss - Total of all segment sizes"
"BriefDescription": "gate_and(sd_pc_c0_comp_valid AND sd_pc_c0_comp_thread(0:1)=tid,sd_pc_c0_comp_ppc_count(0:3)) + gate_and(sd_pc_c1_comp_valid AND sd_pc_c1_comp_thread(0:1)=tid,sd_pc_c1_comp_ppc_count(0:3))"
},
{,
"EventCode": "0x4C058",
......@@ -549,4 +549,4 @@
"EventName": "PM_MRK_DATA_FROM_L21_SHR_CYC",
"BriefDescription": "Duration in cycles to reload with Shared (S) data from another core's L2 on the same chip due to a marked load"
}
]
]
\ No newline at end of file
......@@ -119,4 +119,4 @@
"EventName": "PM_1FLOP_CMPL",
"BriefDescription": "one flop (fadd, fmul, fsub, fcmp, fsel, fabs, fnabs, fres, fsqrte, fneg) operation completed"
}
]
]
\ No newline at end of file
......@@ -89,11 +89,6 @@
"EventName": "PM_STCX_FAIL",
"BriefDescription": "stcx failed"
},
{,
"EventCode": "0x20112",
"EventName": "PM_MRK_NTF_FIN",
"BriefDescription": "Marked next to finish instruction finished"
},
{,
"EventCode": "0x300F0",
"EventName": "PM_ST_MISS_L1",
......
......@@ -124,6 +124,12 @@ static int store_event(struct perf_event_attr *attr, pid_t pid, int cpu,
WRITE_ASS(exclude_guest, "d");
WRITE_ASS(exclude_callchain_kernel, "d");
WRITE_ASS(exclude_callchain_user, "d");
WRITE_ASS(mmap2, "d");
WRITE_ASS(comm_exec, "d");
WRITE_ASS(context_switch, "d");
WRITE_ASS(write_backward, "d");
WRITE_ASS(namespaces, "d");
WRITE_ASS(use_clockid, "d");
WRITE_ASS(wakeup_events, PRIu32);
WRITE_ASS(bp_type, PRIu32);
WRITE_ASS(config1, "llu");
......
......@@ -59,7 +59,7 @@ static int do_test(struct perf_evlist *evlist, int mmap_pages,
int err;
char sbuf[STRERR_BUFSIZE];
err = perf_evlist__mmap(evlist, mmap_pages, true);
err = perf_evlist__mmap(evlist, mmap_pages, false);
if (err < 0) {
pr_debug("perf_evlist__mmap: %s\n",
str_error_r(errno, sbuf, sizeof(sbuf)));
......
......@@ -94,7 +94,7 @@ int test__basic_mmap(struct test *test __maybe_unused, int subtest __maybe_unuse
expected_nr_events[i] = 1 + rand() % 127;
}
if (perf_evlist__mmap(evlist, 128, true) < 0) {
if (perf_evlist__mmap(evlist, 128, false) < 0) {
pr_debug("failed to mmap events: %d (%s)\n", errno,
str_error_r(errno, sbuf, sizeof(sbuf)));
goto out_delete_evlist;
......
......@@ -10,8 +10,8 @@
. $(dirname $0)/lib/probe.sh
ld=$(realpath /lib64/ld*.so.* | uniq)
libc=$(echo $ld | sed 's/ld/libc/g')
libc=$(grep -w libc /proc/self/maps | head -1 | sed -r 's/.*[[:space:]](\/.*)/\1/g')
nm -g $libc 2>/dev/null | fgrep -q inet_pton || exit 254
trace_libc_inet_pton_backtrace() {
idx=0
......@@ -37,6 +37,9 @@ trace_libc_inet_pton_backtrace() {
done
}
# Check for IPv6 interface existence
ip a sh lo | fgrep -q inet6 || exit 2
skip_if_no_perf_probe && \
perf probe -q $libc inet_pton && \
trace_libc_inet_pton_backtrace
......
......@@ -17,8 +17,10 @@ skip_if_no_perf_probe || exit 2
file=$(mktemp /tmp/temporary_file.XXXXX)
trace_open_vfs_getname() {
perf trace -e open touch $file 2>&1 | \
egrep " +[0-9]+\.[0-9]+ +\( +[0-9]+\.[0-9]+ ms\): +touch\/[0-9]+ open\(filename: +${file}, +flags: CREAT\|NOCTTY\|NONBLOCK\|WRONLY, +mode: +IRUGO\|IWUGO\) += +[0-9]+$"
test "$(uname -m)" = s390x && { svc="openat"; txt="dfd: +CWD, +"; }
perf trace -e ${svc:-open} touch $file 2>&1 | \
egrep " +[0-9]+\.[0-9]+ +\( +[0-9]+\.[0-9]+ ms\): +touch\/[0-9]+ ${svc:-open}\(${txt}filename: +${file}, +flags: CREAT\|NOCTTY\|NONBLOCK\|WRONLY, +mode: +IRUGO\|IWUGO\) += +[0-9]+$"
}
......
......@@ -78,7 +78,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
goto out_delete_evlist;
}
err = perf_evlist__mmap(evlist, 128, true);
err = perf_evlist__mmap(evlist, 128, false);
if (err < 0) {
pr_debug("failed to mmap event: %d (%s)\n", errno,
str_error_r(errno, sbuf, sizeof(sbuf)));
......
......@@ -97,7 +97,7 @@ int test__task_exit(struct test *test __maybe_unused, int subtest __maybe_unused
goto out_delete_evlist;
}
if (perf_evlist__mmap(evlist, 128, true) < 0) {
if (perf_evlist__mmap(evlist, 128, false) < 0) {
pr_debug("failed to mmap events: %d (%s)\n", errno,
str_error_r(errno, sbuf, sizeof(sbuf)));
goto out_delete_evlist;
......
This diff is collapsed.
......@@ -31,14 +31,14 @@ static int perf_gtk__get_percent(char *buf, size_t size, struct symbol *sym,
strcpy(buf, "");
if (dl->offset == (s64) -1)
if (dl->al.offset == (s64) -1)
return 0;
symhist = annotation__histogram(symbol__annotation(sym), evidx);
if (!symbol_conf.event_group && !symhist->addr[dl->offset].nr_samples)
if (!symbol_conf.event_group && !symhist->addr[dl->al.offset].nr_samples)
return 0;
percent = 100.0 * symhist->addr[dl->offset].nr_samples / symhist->nr_samples;
percent = 100.0 * symhist->addr[dl->al.offset].nr_samples / symhist->nr_samples;
markup = perf_gtk__get_percent_color(percent);
if (markup)
......@@ -57,16 +57,16 @@ static int perf_gtk__get_offset(char *buf, size_t size, struct symbol *sym,
strcpy(buf, "");
if (dl->offset == (s64) -1)
if (dl->al.offset == (s64) -1)
return 0;
return scnprintf(buf, size, "%"PRIx64, start + dl->offset);
return scnprintf(buf, size, "%"PRIx64, start + dl->al.offset);
}
static int perf_gtk__get_line(char *buf, size_t size, struct disasm_line *dl)
{
int ret = 0;
char *line = g_markup_escape_text(dl->line, -1);
char *line = g_markup_escape_text(dl->al.line, -1);
const char *markup = "<span fgcolor='gray'>";
strcpy(buf, "");
......@@ -74,7 +74,7 @@ static int perf_gtk__get_line(char *buf, size_t size, struct disasm_line *dl)
if (!line)
return 0;
if (dl->offset != (s64) -1)
if (dl->al.offset != (s64) -1)
markup = NULL;
if (markup)
......@@ -119,7 +119,7 @@ static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym,
gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(store));
g_object_unref(GTK_TREE_MODEL(store));
list_for_each_entry(pos, &notes->src->source, node) {
list_for_each_entry(pos, &notes->src->source, al.node) {
GtkTreeIter iter;
int ret = 0;
......@@ -148,8 +148,8 @@ static int perf_gtk__annotate_symbol(GtkWidget *window, struct symbol *sym,
gtk_container_add(GTK_CONTAINER(window), view);
list_for_each_entry_safe(pos, n, &notes->src->source, node) {
list_del(&pos->node);
list_for_each_entry_safe(pos, n, &notes->src->source, al.node) {
list_del(&pos->al.node);
disasm_line__free(pos);
}
......@@ -169,8 +169,7 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map,
if (map->dso->annotate_warned)
return -1;
err = symbol__disassemble(sym, map, perf_evsel__env_arch(evsel),
0, NULL, NULL);
err = symbol__annotate(sym, map, evsel, 0, NULL, NULL);
if (err) {
char msg[BUFSIZ];
symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
......@@ -178,6 +177,8 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map,
return -1;
}
symbol__calc_percent(sym, evsel);
if (perf_gtk__is_active_context(pgctx)) {
window = pgctx->main_window;
notebook = pgctx->notebook;
......
This diff is collapsed.
......@@ -59,33 +59,55 @@ bool ins__is_fused(struct arch *arch, const char *ins1, const char *ins2);
struct annotation;
struct sym_hist_entry {
u64 nr_samples;
u64 period;
};
struct annotation_data {
double percent;
double percent_sum;
struct sym_hist_entry he;
};
struct annotation_line {
struct list_head node;
struct rb_node rb_node;
s64 offset;
char *line;
int line_nr;
float ipc;
u64 cycles;
size_t privsize;
char *path;
int samples_nr;
struct annotation_data samples[0];
};
struct disasm_line {
struct list_head node;
s64 offset;
char *line;
struct ins ins;
int line_nr;
float ipc;
u64 cycles;
struct ins_operands ops;
struct ins ins;
struct ins_operands ops;
/* This needs to be at the end. */
struct annotation_line al;
};
static inline struct disasm_line *disasm_line(struct annotation_line *al)
{
return al ? container_of(al, struct disasm_line, al) : NULL;
}
static inline bool disasm_line__has_offset(const struct disasm_line *dl)
{
return dl->ops.target.offset_avail;
}
struct sym_hist_entry {
u64 nr_samples;
u64 period;
};
void disasm_line__free(struct disasm_line *dl);
struct disasm_line *disasm__get_next_ip_line(struct list_head *head, struct disasm_line *pos);
struct annotation_line *
annotation_line__next(struct annotation_line *pos, struct list_head *head);
int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw);
size_t disasm__fprintf(struct list_head *head, FILE *fp);
double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
s64 end, const char **path, struct sym_hist_entry *sample);
void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel);
struct sym_hist {
u64 nr_samples;
......@@ -104,19 +126,6 @@ struct cyc_hist {
u16 reset;
};
struct source_line_samples {
double percent;
double percent_sum;
u64 nr;
};
struct source_line {
struct rb_node node;
char *path;
int nr_pcnt;
struct source_line_samples samples[1];
};
/** struct annotated_source - symbols with hits have this attached as in sannotation
*
* @histogram: Array of addr hit histograms per event being monitored
......@@ -132,7 +141,6 @@ struct source_line {
*/
struct annotated_source {
struct list_head source;
struct source_line *lines;
int nr_histograms;
size_t sizeof_sym_hist;
struct cyc_hist *cycles_hist;
......@@ -169,9 +177,9 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, struct perf_sample *samp
int symbol__alloc_hist(struct symbol *sym);
void symbol__annotate_zero_histograms(struct symbol *sym);
int symbol__disassemble(struct symbol *sym, struct map *map,
const char *arch_name, size_t privsize,
struct arch **parch, char *cpuid);
int symbol__annotate(struct symbol *sym, struct map *map,
struct perf_evsel *evsel, size_t privsize,
struct arch **parch, char *cpuid);
enum symbol_disassemble_errno {
SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0,
......@@ -198,7 +206,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
int min_pcnt, int max_lines, int context);
void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
void disasm__purge(struct list_head *head);
void annotated_source__purge(struct annotated_source *as);
bool ui__has_annotation(void);
......
......@@ -257,7 +257,7 @@ int perf_evlist__add_dummy(struct perf_evlist *evlist)
.config = PERF_COUNT_SW_DUMMY,
.size = sizeof(attr), /* to capture ABI version */
};
struct perf_evsel *evsel = perf_evsel__new(&attr);
struct perf_evsel *evsel = perf_evsel__new_idx(&attr, evlist->nr_entries);
if (evsel == NULL)
return -ENOMEM;
......@@ -1582,6 +1582,17 @@ int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *even
return perf_evsel__parse_sample(evsel, event, sample);
}
int perf_evlist__parse_sample_timestamp(struct perf_evlist *evlist,
union perf_event *event,
u64 *timestamp)
{
struct perf_evsel *evsel = perf_evlist__event2evsel(evlist, event);
if (!evsel)
return -EFAULT;
return perf_evsel__parse_sample_timestamp(evsel, event, timestamp);
}
size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
{
struct perf_evsel *evsel;
......@@ -1786,3 +1797,15 @@ void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist,
state_err:
return;
}
bool perf_evlist__exclude_kernel(struct perf_evlist *evlist)
{
struct perf_evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
if (!evsel->attr.exclude_kernel)
return false;
}
return true;
}
......@@ -205,6 +205,10 @@ u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist);
int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
struct perf_sample *sample);
int perf_evlist__parse_sample_timestamp(struct perf_evlist *evlist,
union perf_event *event,
u64 *timestamp);
bool perf_evlist__valid_sample_type(struct perf_evlist *evlist);
bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist);
bool perf_evlist__valid_read_format(struct perf_evlist *evlist);
......@@ -312,4 +316,6 @@ perf_evlist__find_evsel_by_str(struct perf_evlist *evlist, const char *str);
struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
union perf_event *event);
bool perf_evlist__exclude_kernel(struct perf_evlist *evlist);
#endif /* __PERF_EVLIST_H */
......@@ -733,12 +733,16 @@ static void apply_config_terms(struct perf_evsel *evsel,
list_for_each_entry(term, config_terms, list) {
switch (term->type) {
case PERF_EVSEL__CONFIG_TERM_PERIOD:
attr->sample_period = term->val.period;
attr->freq = 0;
if (!(term->weak && opts->user_interval != ULLONG_MAX)) {
attr->sample_period = term->val.period;
attr->freq = 0;
}
break;
case PERF_EVSEL__CONFIG_TERM_FREQ:
attr->sample_freq = term->val.freq;
attr->freq = 1;
if (!(term->weak && opts->user_freq != UINT_MAX)) {
attr->sample_freq = term->val.freq;
attr->freq = 1;
}
break;
case PERF_EVSEL__CONFIG_TERM_TIME:
if (term->val.time)
......@@ -775,6 +779,8 @@ static void apply_config_terms(struct perf_evsel *evsel,
case PERF_EVSEL__CONFIG_TERM_OVERWRITE:
attr->write_backward = term->val.overwrite ? 1 : 0;
break;
case PERF_EVSEL__CONFIG_TERM_DRV_CFG:
BUG_ON(1);
default:
break;
}
......@@ -1371,7 +1377,7 @@ perf_evsel__process_group_data(struct perf_evsel *leader,
static int
perf_evsel__read_group(struct perf_evsel *leader, int cpu, int thread)
{
struct perf_stat_evsel *ps = leader->priv;
struct perf_stat_evsel *ps = leader->stats;
u64 read_format = leader->attr.read_format;
int size = perf_evsel__read_size(leader);
u64 *data = ps->group_data;
......@@ -1956,6 +1962,20 @@ static inline bool overflow(const void *endp, u16 max_size, const void *offset,
#define OVERFLOW_CHECK_u64(offset) \
OVERFLOW_CHECK(offset, sizeof(u64), sizeof(u64))
static int
perf_event__check_size(union perf_event *event, unsigned int sample_size)
{
/*
* The evsel's sample_size is based on PERF_SAMPLE_MASK which includes
* up to PERF_SAMPLE_PERIOD. After that overflow() must be used to
* check the format does not go past the end of the event.
*/
if (sample_size + sizeof(event->header) > event->header.size)
return -EFAULT;
return 0;
}
int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
struct perf_sample *data)
{
......@@ -1977,6 +1997,8 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
data->stream_id = data->id = data->time = -1ULL;
data->period = evsel->attr.sample_period;
data->cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
data->id = -1ULL;
data->data_src = PERF_MEM_DATA_SRC_NONE;
if (event->header.type != PERF_RECORD_SAMPLE) {
if (!evsel->attr.sample_id_all)
......@@ -1986,15 +2008,9 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
array = event->sample.array;
/*
* The evsel's sample_size is based on PERF_SAMPLE_MASK which includes
* up to PERF_SAMPLE_PERIOD. After that overflow() must be used to
* check the format does not go past the end of the event.
*/
if (evsel->sample_size + sizeof(event->header) > event->header.size)
if (perf_event__check_size(event, evsel->sample_size))
return -EFAULT;
data->id = -1ULL;
if (type & PERF_SAMPLE_IDENTIFIER) {
data->id = *array;
array++;
......@@ -2024,7 +2040,6 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
array++;
}
data->addr = 0;
if (type & PERF_SAMPLE_ADDR) {
data->addr = *array;
array++;
......@@ -2188,14 +2203,12 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
array++;
}
data->data_src = PERF_MEM_DATA_SRC_NONE;
if (type & PERF_SAMPLE_DATA_SRC) {
OVERFLOW_CHECK_u64(array);
data->data_src = *array;
array++;
}
data->transaction = 0;
if (type & PERF_SAMPLE_TRANSACTION) {
OVERFLOW_CHECK_u64(array);
data->transaction = *array;
......@@ -2228,6 +2241,50 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
return 0;
}
int perf_evsel__parse_sample_timestamp(struct perf_evsel *evsel,
union perf_event *event,
u64 *timestamp)
{
u64 type = evsel->attr.sample_type;
const u64 *array;
if (!(type & PERF_SAMPLE_TIME))
return -1;
if (event->header.type != PERF_RECORD_SAMPLE) {
struct perf_sample data = {
.time = -1ULL,
};
if (!evsel->attr.sample_id_all)
return -1;
if (perf_evsel__parse_id_sample(evsel, event, &data))
return -1;
*timestamp = data.time;
return 0;
}
array = event->sample.array;
if (perf_event__check_size(event, evsel->sample_size))
return -EFAULT;
if (type & PERF_SAMPLE_IDENTIFIER)
array++;
if (type & PERF_SAMPLE_IP)
array++;
if (type & PERF_SAMPLE_TID)
array++;
if (type & PERF_SAMPLE_TIME)
*timestamp = *array;
return 0;
}
size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
u64 read_format)
{
......@@ -2739,8 +2796,9 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
break;
case EOPNOTSUPP:
if (evsel->attr.sample_period != 0)
return scnprintf(msg, size, "%s",
"PMU Hardware doesn't support sampling/overflow-interrupts.");
return scnprintf(msg, size,
"%s: PMU Hardware doesn't support sampling/overflow-interrupts. Try 'perf stat'",
perf_evsel__name(evsel));
if (evsel->attr.precise_ip)
return scnprintf(msg, size, "%s",
"\'precise\' request may not be supported. Try removing 'p' modifier.");
......
......@@ -38,7 +38,7 @@ struct cgroup_sel;
* It is allocated within event parsing and attached to
* perf_evsel::config_terms list head.
*/
enum {
enum term_type {
PERF_EVSEL__CONFIG_TERM_PERIOD,
PERF_EVSEL__CONFIG_TERM_FREQ,
PERF_EVSEL__CONFIG_TERM_TIME,
......@@ -49,12 +49,11 @@ enum {
PERF_EVSEL__CONFIG_TERM_OVERWRITE,
PERF_EVSEL__CONFIG_TERM_DRV_CFG,
PERF_EVSEL__CONFIG_TERM_BRANCH,
PERF_EVSEL__CONFIG_TERM_MAX,
};
struct perf_evsel_config_term {
struct list_head list;
int type;
enum term_type type;
union {
u64 period;
u64 freq;
......@@ -67,6 +66,7 @@ struct perf_evsel_config_term {
bool overwrite;
char *branch;
} val;
bool weak;
};
struct perf_stat_evsel;
......@@ -338,6 +338,10 @@ static inline int perf_evsel__read_on_cpu_scaled(struct perf_evsel *evsel,
int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
struct perf_sample *sample);
int perf_evsel__parse_sample_timestamp(struct perf_evsel *evsel,
union perf_event *event,
u64 *timestamp);
static inline struct perf_evsel *perf_evsel__next(struct perf_evsel *evsel)
{
return list_entry(evsel->node.next, struct perf_evsel, node);
......
......@@ -172,6 +172,9 @@ void machine__exit(struct machine *machine)
{
int i;
if (machine == NULL)
return;
machine__destroy_kernel_maps(machine);
map_groups__exit(&machine->kmaps);
dsos__exit(&machine->dsos);
......@@ -2201,7 +2204,7 @@ int thread__resolve_callchain(struct thread *thread,
{
int ret = 0;
callchain_cursor_reset(&callchain_cursor);
callchain_cursor_reset(cursor);
if (callchain_param.order == ORDER_CALLEE) {
ret = thread__resolve_callchain_sample(thread, cursor,
......
......@@ -157,9 +157,8 @@ void ordered_events__delete(struct ordered_events *oe, struct ordered_event *eve
}
int ordered_events__queue(struct ordered_events *oe, union perf_event *event,
struct perf_sample *sample, u64 file_offset)
u64 timestamp, u64 file_offset)
{
u64 timestamp = sample->time;
struct ordered_event *oevent;
if (!timestamp || timestamp == ~0ULL)
......
......@@ -45,7 +45,7 @@ struct ordered_events {
};
int ordered_events__queue(struct ordered_events *oe, union perf_event *event,
struct perf_sample *sample, u64 file_offset);
u64 timestamp, u64 file_offset);
void ordered_events__delete(struct ordered_events *oe, struct ordered_event *event);
int ordered_events__flush(struct ordered_events *oe, enum oe_flush how);
void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t deliver);
......
......@@ -1116,6 +1116,7 @@ do { \
INIT_LIST_HEAD(&__t->list); \
__t->type = PERF_EVSEL__CONFIG_TERM_ ## __type; \
__t->val.__name = __val; \
__t->weak = term->weak; \
list_add_tail(&__t->list, head_terms); \
} while (0)
......@@ -2410,6 +2411,7 @@ static int new_term(struct parse_events_term **_term,
*term = *temp;
INIT_LIST_HEAD(&term->list);
term->weak = false;
switch (term->type_val) {
case PARSE_EVENTS__TERM_TYPE_NUM:
......
......@@ -101,6 +101,9 @@ struct parse_events_term {
/* error string indexes for within parsed string */
int err_term;
int err_val;
/* Coming from implicit alias */
bool weak;
};
struct parse_events_error {
......
......@@ -405,6 +405,11 @@ static int pmu_alias_terms(struct perf_pmu_alias *alias,
parse_events_terms__purge(&list);
return ret;
}
/*
* Weak terms don't override command line options,
* which we don't want for implicit terms in aliases.
*/
cloned->weak = true;
list_add_tail(&cloned->list, &list);
}
list_splice(&list, terms);
......
......@@ -27,7 +27,6 @@
static int perf_session__deliver_event(struct perf_session *session,
union perf_event *event,
struct perf_sample *sample,
struct perf_tool *tool,
u64 file_offset);
......@@ -107,17 +106,10 @@ static void perf_session__set_comm_exec(struct perf_session *session)
static int ordered_events__deliver_event(struct ordered_events *oe,
struct ordered_event *event)
{
struct perf_sample sample;
struct perf_session *session = container_of(oe, struct perf_session,
ordered_events);
int ret = perf_evlist__parse_sample(session->evlist, event->event, &sample);
if (ret) {
pr_err("Can't parse sample, err = %d\n", ret);
return ret;
}
return perf_session__deliver_event(session, event->event, &sample,
return perf_session__deliver_event(session, event->event,
session->tool, event->file_offset);
}
......@@ -873,9 +865,9 @@ static int process_finished_round(struct perf_tool *tool __maybe_unused,
}
int perf_session__queue_event(struct perf_session *s, union perf_event *event,
struct perf_sample *sample, u64 file_offset)
u64 timestamp, u64 file_offset)
{
return ordered_events__queue(&s->ordered_events, event, sample, file_offset);
return ordered_events__queue(&s->ordered_events, event, timestamp, file_offset);
}
static void callchain__lbr_callstack_printf(struct perf_sample *sample)
......@@ -1328,20 +1320,26 @@ static int machines__deliver_event(struct machines *machines,
static int perf_session__deliver_event(struct perf_session *session,
union perf_event *event,
struct perf_sample *sample,
struct perf_tool *tool,
u64 file_offset)
{
struct perf_sample sample;
int ret;
ret = auxtrace__process_event(session, event, sample, tool);
ret = perf_evlist__parse_sample(session->evlist, event, &sample);
if (ret) {
pr_err("Can't parse sample, err = %d\n", ret);
return ret;
}
ret = auxtrace__process_event(session, event, &sample, tool);
if (ret < 0)
return ret;
if (ret > 0)
return 0;
return machines__deliver_event(&session->machines, session->evlist,
event, sample, tool, file_offset);
event, &sample, tool, file_offset);
}
static s64 perf_session__process_user_event(struct perf_session *session,
......@@ -1495,7 +1493,6 @@ static s64 perf_session__process_event(struct perf_session *session,
{
struct perf_evlist *evlist = session->evlist;
struct perf_tool *tool = session->tool;
struct perf_sample sample;
int ret;
if (session->header.needs_swap)
......@@ -1509,21 +1506,19 @@ static s64 perf_session__process_event(struct perf_session *session,
if (event->header.type >= PERF_RECORD_USER_TYPE_START)
return perf_session__process_user_event(session, event, file_offset);
/*
* For all kernel events we get the sample data
*/
ret = perf_evlist__parse_sample(evlist, event, &sample);
if (ret)
return ret;
if (tool->ordered_events) {
ret = perf_session__queue_event(session, event, &sample, file_offset);
u64 timestamp;
ret = perf_evlist__parse_sample_timestamp(evlist, event, &timestamp);
if (ret)
return ret;
ret = perf_session__queue_event(session, event, timestamp, file_offset);
if (ret != -ETIME)
return ret;
}
return perf_session__deliver_event(session, event, &sample, tool,
file_offset);
return perf_session__deliver_event(session, event, tool, file_offset);
}
void perf_event_header__bswap(struct perf_event_header *hdr)
......
......@@ -53,7 +53,7 @@ int perf_session__peek_event(struct perf_session *session, off_t file_offset,
int perf_session__process_events(struct perf_session *session);
int perf_session__queue_event(struct perf_session *s, union perf_event *event,
struct perf_sample *sample, u64 file_offset);
u64 timestamp, u64 file_offset);
void perf_tool__fill_defaults(struct perf_tool *tool);
......
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