summaryrefslogtreecommitdiff
path: root/tools/lib
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-10-17 11:47:46 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2020-10-17 11:47:46 -0700
commit9d9af1007bc08971953ae915d88dc9bb21344b53 (patch)
tree02090da0b271c31f19d58d80f4cff19c8ef89971 /tools/lib
parenta1e16bc7d5f7ca3599d8a7f061841c93a563665e (diff)
parent744aec4df2c5b4d12af26a57d8858af2f59ef3d0 (diff)
Merge tag 'perf-tools-for-v5.10-2020-10-15' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux
Pull perf tools updates from Arnaldo Carvalho de Melo: - cgroup improvements for 'perf stat', allowing for compact specification of events and cgroups in the command line. - Support per thread topdown metrics in 'perf stat'. - Support sample-read topdown metric group in 'perf record' - Show start of latency in addition to its start in 'perf sched latency'. - Add min, max to 'perf script' futex-contention output, in addition to avg. - Allow usage of 'perf_event_attr->exclusive' attribute via the new ':e' event modifier. - Add 'snapshot' command to 'perf record --control', using it with Intel PT. - Support FIFO file names as alternative options to 'perf record --control'. - Introduce branch history "streams", to compare 'perf record' runs with 'perf diff' based on branch records and report hot streams. - Support PE executable symbol tables using libbfd, to profile, for instance, wine binaries. - Add filter support for option 'perf ftrace -F/--funcs'. - Allow configuring the 'disassembler_style' 'perf annotate' knob via 'perf config' - Update CascadelakeX and SkylakeX JSON vendor events files. - Add support for parsing perchip/percore JSON vendor events. - Add power9 hv_24x7 core level metric events. - Add L2 prefetch, ITLB instruction fetch hits JSON events for AMD zen1. - Enable Family 19h users by matching Zen2 AMD vendor events. - Use debuginfod in 'perf probe' when required debug files not found locally. - Display negative tid in non-sample events in 'perf script'. - Make GTK2 support opt-in - Add build test with GTK+ - Add missing -lzstd to the fast path feature detection - Add scripts to auto generate 'mmap', 'mremap' string<->id tables for use in 'perf trace'. - Show python test script in verbose mode. - Fix uncore metric expressions - Msan uninitialized use fixes. - Use condition variables in 'perf bench numa' - Autodetect python3 binary in systems without python2. - Support md5 build ids in addition to sha1. - Add build id 'perf test' regression test. - Fix printable strings in python3 scripts. - Fix off by ones in 'perf trace' in arches using libaudit. - Fix JSON event code for events referencing std arch events. - Introduce 'perf test' shell script for Arm CoreSight testing. - Add rdtsc() for Arm64 for used in the PERF_RECORD_TIME_CONV metadata event and in 'perf test tsc'. - 'perf c2c' improvements: Add "RMT Load Hit" metric, "Total Stores", fixes and documentation update. - Fix usage of reloc_sym in 'perf probe' when using both kallsyms and debuginfo files. - Do not print 'Metric Groups:' unnecessarily in 'perf list' - Refcounting fixes in the event parsing code. - Add expand cgroup event 'perf test' entry. - Fix out of bounds CPU map access when handling armv8_pmu events in 'perf stat'. - Add build-id injection 'perf bench' benchmark. - Enter namespace when reading build-id in 'perf inject'. - Do not load map/dso when injecting build-id speeding up the 'perf inject' process. - Add --buildid-all option to avoid processing all samples, just the mmap metadata events. - Add feature test to check if libbfd has buildid support - Add 'perf test' entry for PE binary format support. - Fix typos in power8 PMU vendor events JSON files. - Hide libtraceevent non API functions. * tag 'perf-tools-for-v5.10-2020-10-15' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux: (113 commits) perf c2c: Update documentation for metrics reorganization perf c2c: Add metrics "RMT Load Hit" perf c2c: Correct LLC load hit metrics perf c2c: Change header for LLC local hit perf c2c: Use more explicit headers for HITM perf c2c: Change header from "LLC Load Hitm" to "Load Hitm" perf c2c: Organize metrics based on memory hierarchy perf c2c: Display "Total Stores" as a standalone metrics perf c2c: Display the total numbers continuously perf bench: Use condition variables in numa. perf jevents: Fix event code for events referencing std arch events perf diff: Support hot streams comparison perf streams: Report hot streams perf streams: Calculate the sum of total streams hits perf streams: Link stream pair perf streams: Compare two streams perf streams: Get the evsel_streams by evsel_idx perf streams: Introduce branch history "streams" perf intel-pt: Improve PT documentation slightly perf tools: Add support for exclusive groups/events ...
Diffstat (limited to 'tools/lib')
-rw-r--r--tools/lib/perf/evlist.c3
-rw-r--r--tools/lib/perf/include/perf/event.h16
-rw-r--r--tools/lib/traceevent/event-parse-api.c8
-rw-r--r--tools/lib/traceevent/event-parse-local.h24
-rw-r--r--tools/lib/traceevent/event-parse.c125
-rw-r--r--tools/lib/traceevent/event-parse.h8
-rw-r--r--tools/lib/traceevent/event-plugin.c2
-rw-r--r--tools/lib/traceevent/parse-filter.c23
8 files changed, 101 insertions, 108 deletions
diff --git a/tools/lib/perf/evlist.c b/tools/lib/perf/evlist.c
index 2208444ecb44..cfcdbd7be066 100644
--- a/tools/lib/perf/evlist.c
+++ b/tools/lib/perf/evlist.c
@@ -45,6 +45,9 @@ static void __perf_evlist__propagate_maps(struct perf_evlist *evlist,
if (!evsel->own_cpus || evlist->has_user_cpus) {
perf_cpu_map__put(evsel->cpus);
evsel->cpus = perf_cpu_map__get(evlist->cpus);
+ } else if (!evsel->system_wide && perf_cpu_map__empty(evlist->cpus)) {
+ perf_cpu_map__put(evsel->cpus);
+ evsel->cpus = perf_cpu_map__get(evlist->cpus);
} else if (evsel->cpus != evsel->own_cpus) {
perf_cpu_map__put(evsel->cpus);
evsel->cpus = perf_cpu_map__get(evsel->own_cpus);
diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/perf/event.h
index 842028858d66..988c539bedb6 100644
--- a/tools/lib/perf/include/perf/event.h
+++ b/tools/lib/perf/include/perf/event.h
@@ -201,10 +201,20 @@ struct perf_record_header_tracing_data {
__u32 size;
};
+#define PERF_RECORD_MISC_BUILD_ID_SIZE (1 << 15)
+
struct perf_record_header_build_id {
struct perf_event_header header;
pid_t pid;
- __u8 build_id[24];
+ union {
+ __u8 build_id[24];
+ struct {
+ __u8 data[20];
+ __u8 size;
+ __u8 reserved1__;
+ __u16 reserved2__;
+ };
+ };
char filename[];
};
@@ -324,6 +334,10 @@ struct perf_record_time_conv {
__u64 time_shift;
__u64 time_mult;
__u64 time_zero;
+ __u64 time_cycles;
+ __u64 time_mask;
+ bool cap_user_time_zero;
+ bool cap_user_time_short;
};
struct perf_record_header_feature {
diff --git a/tools/lib/traceevent/event-parse-api.c b/tools/lib/traceevent/event-parse-api.c
index 4faf52a65791..f8361e45d446 100644
--- a/tools/lib/traceevent/event-parse-api.c
+++ b/tools/lib/traceevent/event-parse-api.c
@@ -92,7 +92,7 @@ bool tep_test_flag(struct tep_handle *tep, enum tep_flag flag)
return false;
}
-unsigned short tep_data2host2(struct tep_handle *tep, unsigned short data)
+__hidden unsigned short data2host2(struct tep_handle *tep, unsigned short data)
{
unsigned short swap;
@@ -105,7 +105,7 @@ unsigned short tep_data2host2(struct tep_handle *tep, unsigned short data)
return swap;
}
-unsigned int tep_data2host4(struct tep_handle *tep, unsigned int data)
+__hidden unsigned int data2host4(struct tep_handle *tep, unsigned int data)
{
unsigned int swap;
@@ -120,8 +120,8 @@ unsigned int tep_data2host4(struct tep_handle *tep, unsigned int data)
return swap;
}
-unsigned long long
-tep_data2host8(struct tep_handle *tep, unsigned long long data)
+__hidden unsigned long long
+data2host8(struct tep_handle *tep, unsigned long long data)
{
unsigned long long swap;
diff --git a/tools/lib/traceevent/event-parse-local.h b/tools/lib/traceevent/event-parse-local.h
index d805a920af6f..fd4bbcfbb849 100644
--- a/tools/lib/traceevent/event-parse-local.h
+++ b/tools/lib/traceevent/event-parse-local.h
@@ -15,6 +15,8 @@ struct event_handler;
struct func_resolver;
struct tep_plugins_dir;
+#define __hidden __attribute__((visibility ("hidden")))
+
struct tep_handle {
int ref_count;
@@ -102,12 +104,20 @@ struct tep_print_parse {
struct tep_print_arg *len_as_arg;
};
-void tep_free_event(struct tep_event *event);
-void tep_free_format_field(struct tep_format_field *field);
-void tep_free_plugin_paths(struct tep_handle *tep);
-
-unsigned short tep_data2host2(struct tep_handle *tep, unsigned short data);
-unsigned int tep_data2host4(struct tep_handle *tep, unsigned int data);
-unsigned long long tep_data2host8(struct tep_handle *tep, unsigned long long data);
+void free_tep_event(struct tep_event *event);
+void free_tep_format_field(struct tep_format_field *field);
+void free_tep_plugin_paths(struct tep_handle *tep);
+
+unsigned short data2host2(struct tep_handle *tep, unsigned short data);
+unsigned int data2host4(struct tep_handle *tep, unsigned int data);
+unsigned long long data2host8(struct tep_handle *tep, unsigned long long data);
+
+/* access to the internal parser */
+int peek_char(void);
+void init_input_buf(const char *buf, unsigned long long size);
+unsigned long long get_input_buf_ptr(void);
+const char *get_input_buf(void);
+enum tep_event_type read_token(char **tok);
+void free_token(char *tok);
#endif /* _PARSE_EVENTS_INT_H */
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 5acc18b32606..fe58843d047c 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -54,19 +54,26 @@ static int show_warning = 1;
warning(fmt, ##__VA_ARGS__); \
} while (0)
-static void init_input_buf(const char *buf, unsigned long long size)
+/**
+ * init_input_buf - init buffer for parsing
+ * @buf: buffer to parse
+ * @size: the size of the buffer
+ *
+ * Initializes the internal buffer that tep_read_token() will parse.
+ */
+__hidden void init_input_buf(const char *buf, unsigned long long size)
{
input_buf = buf;
input_buf_siz = size;
input_buf_ptr = 0;
}
-const char *tep_get_input_buf(void)
+__hidden const char *get_input_buf(void)
{
return input_buf;
}
-unsigned long long tep_get_input_buf_ptr(void)
+__hidden unsigned long long get_input_buf_ptr(void)
{
return input_buf_ptr;
}
@@ -100,26 +107,13 @@ process_defined_func(struct trace_seq *s, void *data, int size,
static void free_func_handle(struct tep_function_handler *func);
-/**
- * tep_buffer_init - init buffer for parsing
- * @buf: buffer to parse
- * @size: the size of the buffer
- *
- * For use with tep_read_token(), this initializes the internal
- * buffer that tep_read_token() will parse.
- */
-void tep_buffer_init(const char *buf, unsigned long long size)
-{
- init_input_buf(buf, size);
-}
-
void breakpoint(void)
{
static int x;
x++;
}
-struct tep_print_arg *alloc_arg(void)
+static struct tep_print_arg *alloc_arg(void)
{
return calloc(1, sizeof(struct tep_print_arg));
}
@@ -962,22 +956,17 @@ static int __read_char(void)
return input_buf[input_buf_ptr++];
}
-static int __peek_char(void)
-{
- if (input_buf_ptr >= input_buf_siz)
- return -1;
-
- return input_buf[input_buf_ptr];
-}
-
/**
- * tep_peek_char - peek at the next character that will be read
+ * peek_char - peek at the next character that will be read
*
* Returns the next character read, or -1 if end of buffer.
*/
-int tep_peek_char(void)
+__hidden int peek_char(void)
{
- return __peek_char();
+ if (input_buf_ptr >= input_buf_siz)
+ return -1;
+
+ return input_buf[input_buf_ptr];
}
static int extend_token(char **tok, char *buf, int size)
@@ -1033,7 +1022,7 @@ static enum tep_event_type __read_token(char **tok)
case TEP_EVENT_OP:
switch (ch) {
case '-':
- next_ch = __peek_char();
+ next_ch = peek_char();
if (next_ch == '>') {
buf[i++] = __read_char();
break;
@@ -1045,7 +1034,7 @@ static enum tep_event_type __read_token(char **tok)
case '>':
case '<':
last_ch = ch;
- ch = __peek_char();
+ ch = peek_char();
if (ch != last_ch)
goto test_equal;
buf[i++] = __read_char();
@@ -1068,7 +1057,7 @@ static enum tep_event_type __read_token(char **tok)
return type;
test_equal:
- ch = __peek_char();
+ ch = peek_char();
if (ch == '=')
buf[i++] = __read_char();
goto out;
@@ -1122,7 +1111,7 @@ static enum tep_event_type __read_token(char **tok)
break;
}
- while (get_type(__peek_char()) == type) {
+ while (get_type(peek_char()) == type) {
if (i == (BUFSIZ - 1)) {
buf[i] = 0;
tok_size += BUFSIZ;
@@ -1191,13 +1180,26 @@ static enum tep_event_type force_token(const char *str, char **tok)
return type;
}
-static void free_token(char *tok)
+/**
+ * free_token - free a token returned by tep_read_token
+ * @token: the token to free
+ */
+__hidden void free_token(char *tok)
{
if (tok)
free(tok);
}
-static enum tep_event_type read_token(char **tok)
+/**
+ * read_token - access to utilities to use the tep parser
+ * @tok: The token to return
+ *
+ * This will parse tokens from the string given by
+ * tep_init_data().
+ *
+ * Returns the token type.
+ */
+__hidden enum tep_event_type read_token(char **tok)
{
enum tep_event_type type;
@@ -1214,29 +1216,6 @@ static enum tep_event_type read_token(char **tok)
return TEP_EVENT_NONE;
}
-/**
- * tep_read_token - access to utilities to use the tep parser
- * @tok: The token to return
- *
- * This will parse tokens from the string given by
- * tep_init_data().
- *
- * Returns the token type.
- */
-enum tep_event_type tep_read_token(char **tok)
-{
- return read_token(tok);
-}
-
-/**
- * tep_free_token - free a token returned by tep_read_token
- * @token: the token to free
- */
-void tep_free_token(char *token)
-{
- free_token(token);
-}
-
/* no newline */
static enum tep_event_type read_token_item(char **tok)
{
@@ -3459,12 +3438,12 @@ unsigned long long tep_read_number(struct tep_handle *tep,
case 1:
return *(unsigned char *)ptr;
case 2:
- return tep_data2host2(tep, *(unsigned short *)ptr);
+ return data2host2(tep, *(unsigned short *)ptr);
case 4:
- return tep_data2host4(tep, *(unsigned int *)ptr);
+ return data2host4(tep, *(unsigned int *)ptr);
case 8:
memcpy(&val, (ptr), sizeof(unsigned long long));
- return tep_data2host8(tep, val);
+ return data2host8(tep, val);
default:
/* BUG! */
return 0;
@@ -4190,7 +4169,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
f = tep_find_any_field(event, arg->string.string);
arg->string.offset = f->offset;
}
- str_offset = tep_data2host4(tep, *(unsigned int *)(data + arg->string.offset));
+ str_offset = data2host4(tep, *(unsigned int *)(data + arg->string.offset));
str_offset &= 0xffff;
print_str_to_seq(s, format, len_arg, ((char *)data) + str_offset);
break;
@@ -4208,7 +4187,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
f = tep_find_any_field(event, arg->bitmask.bitmask);
arg->bitmask.offset = f->offset;
}
- bitmask_offset = tep_data2host4(tep, *(unsigned int *)(data + arg->bitmask.offset));
+ bitmask_offset = data2host4(tep, *(unsigned int *)(data + arg->bitmask.offset));
bitmask_size = bitmask_offset >> 16;
bitmask_offset &= 0xffff;
print_bitmask_to_seq(tep, s, format, len_arg,
@@ -6750,7 +6729,7 @@ static int find_event_handle(struct tep_handle *tep, struct tep_event *event)
}
/**
- * __tep_parse_format - parse the event format
+ * parse_format - parse the event format
* @buf: the buffer storing the event format string
* @size: the size of @buf
* @sys: the system the event belongs to
@@ -6762,9 +6741,9 @@ static int find_event_handle(struct tep_handle *tep, struct tep_event *event)
*
* /sys/kernel/debug/tracing/events/.../.../format
*/
-enum tep_errno __tep_parse_format(struct tep_event **eventp,
- struct tep_handle *tep, const char *buf,
- unsigned long size, const char *sys)
+static enum tep_errno parse_format(struct tep_event **eventp,
+ struct tep_handle *tep, const char *buf,
+ unsigned long size, const char *sys)
{
struct tep_event *event;
int ret;
@@ -6879,7 +6858,7 @@ __parse_event(struct tep_handle *tep,
const char *buf, unsigned long size,
const char *sys)
{
- int ret = __tep_parse_format(eventp, tep, buf, size, sys);
+ int ret = parse_format(eventp, tep, buf, size, sys);
struct tep_event *event = *eventp;
if (event == NULL)
@@ -6897,7 +6876,7 @@ __parse_event(struct tep_handle *tep,
return 0;
event_add_failed:
- tep_free_event(event);
+ free_tep_event(event);
return ret;
}
@@ -7490,7 +7469,7 @@ int tep_get_ref(struct tep_handle *tep)
return 0;
}
-void tep_free_format_field(struct tep_format_field *field)
+__hidden void free_tep_format_field(struct tep_format_field *field)
{
free(field->type);
if (field->alias != field->name)
@@ -7505,7 +7484,7 @@ static void free_format_fields(struct tep_format_field *field)
while (field) {
next = field->next;
- tep_free_format_field(field);
+ free_tep_format_field(field);
field = next;
}
}
@@ -7516,7 +7495,7 @@ static void free_formats(struct tep_format *format)
free_format_fields(format->fields);
}
-void tep_free_event(struct tep_event *event)
+__hidden void free_tep_event(struct tep_event *event)
{
free(event->name);
free(event->system);
@@ -7602,7 +7581,7 @@ void tep_free(struct tep_handle *tep)
}
for (i = 0; i < tep->nr_events; i++)
- tep_free_event(tep->events[i]);
+ free_tep_event(tep->events[i]);
while (tep->handlers) {
handle = tep->handlers;
@@ -7613,7 +7592,7 @@ void tep_free(struct tep_handle *tep)
free(tep->events);
free(tep->sort_events);
free(tep->func_resolver);
- tep_free_plugin_paths(tep);
+ free_tep_plugin_paths(tep);
free(tep);
}
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index c29b693e31ee..a67ad9a5b835 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -578,14 +578,6 @@ void tep_ref(struct tep_handle *tep);
void tep_unref(struct tep_handle *tep);
int tep_get_ref(struct tep_handle *tep);
-/* access to the internal parser */
-void tep_buffer_init(const char *buf, unsigned long long size);
-enum tep_event_type tep_read_token(char **tok);
-void tep_free_token(char *token);
-int tep_peek_char(void);
-const char *tep_get_input_buf(void);
-unsigned long long tep_get_input_buf_ptr(void);
-
/* for debugging */
void tep_print_funcs(struct tep_handle *tep);
void tep_print_printk(struct tep_handle *tep);
diff --git a/tools/lib/traceevent/event-plugin.c b/tools/lib/traceevent/event-plugin.c
index e7c2acb8680f..e7f93d5fe4fd 100644
--- a/tools/lib/traceevent/event-plugin.c
+++ b/tools/lib/traceevent/event-plugin.c
@@ -676,7 +676,7 @@ int tep_add_plugin_path(struct tep_handle *tep, char *path,
return 0;
}
-void tep_free_plugin_paths(struct tep_handle *tep)
+__hidden void free_tep_plugin_paths(struct tep_handle *tep)
{
struct tep_plugins_dir *dir;
diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c
index c271aeeb227d..368826bb5a57 100644
--- a/tools/lib/traceevent/parse-filter.c
+++ b/tools/lib/traceevent/parse-filter.c
@@ -38,8 +38,8 @@ static void show_error(char *error_buf, const char *fmt, ...)
int len;
int i;
- input = tep_get_input_buf();
- index = tep_get_input_buf_ptr();
+ input = get_input_buf();
+ index = get_input_buf_ptr();
len = input ? strlen(input) : 0;
if (len) {
@@ -57,25 +57,20 @@ static void show_error(char *error_buf, const char *fmt, ...)
va_end(ap);
}
-static void free_token(char *token)
-{
- tep_free_token(token);
-}
-
-static enum tep_event_type read_token(char **tok)
+static enum tep_event_type filter_read_token(char **tok)
{
enum tep_event_type type;
char *token = NULL;
do {
free_token(token);
- type = tep_read_token(&token);
+ type = read_token(&token);
} while (type == TEP_EVENT_NEWLINE || type == TEP_EVENT_SPACE);
/* If token is = or ! check to see if the next char is ~ */
if (token &&
(strcmp(token, "=") == 0 || strcmp(token, "!") == 0) &&
- tep_peek_char() == '~') {
+ peek_char() == '~') {
/* append it */
*tok = malloc(3);
if (*tok == NULL) {
@@ -85,7 +80,7 @@ static enum tep_event_type read_token(char **tok)
sprintf(*tok, "%c%c", *token, '~');
free_token(token);
/* Now remove the '~' from the buffer */
- tep_read_token(&token);
+ read_token(&token);
free_token(token);
} else
*tok = token;
@@ -959,7 +954,7 @@ process_filter(struct tep_event *event, struct tep_filter_arg **parg,
do {
free(token);
- type = read_token(&token);
+ type = filter_read_token(&token);
switch (type) {
case TEP_EVENT_SQUOTE:
case TEP_EVENT_DQUOTE:
@@ -1185,7 +1180,7 @@ process_event(struct tep_event *event, const char *filter_str,
{
int ret;
- tep_buffer_init(filter_str, strlen(filter_str));
+ init_input_buf(filter_str, strlen(filter_str));
ret = process_filter(event, parg, error_str, 0);
if (ret < 0)
@@ -1243,7 +1238,7 @@ filter_event(struct tep_event_filter *filter, struct tep_event *event,
static void filter_init_error_buf(struct tep_event_filter *filter)
{
/* clear buffer to reset show error */
- tep_buffer_init("", 0);
+ init_input_buf("", 0);
filter->error_buffer[0] = '\0';
}