You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
perf/core improvements and fixes: - Preparatory patches to use hw events in PMU syntax, from Jiri Olsa - Remaining backport of trace-cmd's libparseevent, from Namhyung Kim - Fix libtraceevent 'clean' make target, from Namhyung Kim - Teach ctags about libtraceevent error codes, from Namhyung Kim - Fix libtraceevent dependency files usage, from Namhyung Kim - Support hex number pretty printing in libtraceevent, fixing kvm output, from Namhyung Kim - Kill some die() usage in libtraceevent, from Namhyung Kim - Improve support for hw breakpoints parsing/pretty printing/testing, from Jiri Olsa - Clarify perf bench option naming, from Hitoshi Mitake - Look for ".note" ELF notes too, used in the kernel vdso, from Jiri Olsa - Fix internal PMU list usage, removing leak, from Robert Richter Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
@@ -250,8 +250,12 @@ endef
|
||||
all_objs := $(sort $(ALL_OBJS))
|
||||
all_deps := $(all_objs:%.o=.%.d)
|
||||
|
||||
# let .d file also depends on the source and header files
|
||||
define check_deps
|
||||
$(CC) -M $(CFLAGS) $< > $@;
|
||||
@set -e; $(RM) $@; \
|
||||
$(CC) -M $(CFLAGS) $< > $@.$$$$; \
|
||||
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
|
||||
$(RM) $@.$$$$
|
||||
endef
|
||||
|
||||
$(gui_deps): ks_version.h
|
||||
@@ -270,11 +274,13 @@ endif
|
||||
|
||||
tags: force
|
||||
$(RM) tags
|
||||
find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px
|
||||
find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \
|
||||
--regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/'
|
||||
|
||||
TAGS: force
|
||||
$(RM) TAGS
|
||||
find . -name '*.[ch]' | xargs etags
|
||||
find . -name '*.[ch]' | xargs etags \
|
||||
--regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/'
|
||||
|
||||
define do_install
|
||||
$(print_install) \
|
||||
@@ -290,7 +296,7 @@ install_lib: all_cmd install_plugins install_python
|
||||
install: install_lib
|
||||
|
||||
clean:
|
||||
$(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES).*.d
|
||||
$(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d
|
||||
$(RM) tags TAGS
|
||||
|
||||
endif # skip-makefile
|
||||
|
||||
+303
-112
File diff suppressed because it is too large
Load Diff
@@ -226,6 +226,11 @@ struct print_arg_symbol {
|
||||
struct print_flag_sym *symbols;
|
||||
};
|
||||
|
||||
struct print_arg_hex {
|
||||
struct print_arg *field;
|
||||
struct print_arg *size;
|
||||
};
|
||||
|
||||
struct print_arg_dynarray {
|
||||
struct format_field *field;
|
||||
struct print_arg *index;
|
||||
@@ -253,6 +258,7 @@ enum print_arg_type {
|
||||
PRINT_FIELD,
|
||||
PRINT_FLAGS,
|
||||
PRINT_SYMBOL,
|
||||
PRINT_HEX,
|
||||
PRINT_TYPE,
|
||||
PRINT_STRING,
|
||||
PRINT_BSTRING,
|
||||
@@ -270,6 +276,7 @@ struct print_arg {
|
||||
struct print_arg_typecast typecast;
|
||||
struct print_arg_flags flags;
|
||||
struct print_arg_symbol symbol;
|
||||
struct print_arg_hex hex;
|
||||
struct print_arg_func func;
|
||||
struct print_arg_string string;
|
||||
struct print_arg_op op;
|
||||
|
||||
@@ -96,7 +96,7 @@ static enum event_type read_token(char **tok)
|
||||
(strcmp(token, "=") == 0 || strcmp(token, "!") == 0) &&
|
||||
pevent_peek_char() == '~') {
|
||||
/* append it */
|
||||
*tok = malloc(3);
|
||||
*tok = malloc_or_die(3);
|
||||
sprintf(*tok, "%c%c", *token, '~');
|
||||
free_token(token);
|
||||
/* Now remove the '~' from the buffer */
|
||||
@@ -148,17 +148,11 @@ add_filter_type(struct event_filter *filter, int id)
|
||||
if (filter_type)
|
||||
return filter_type;
|
||||
|
||||
if (!filter->filters)
|
||||
filter->event_filters =
|
||||
malloc_or_die(sizeof(*filter->event_filters));
|
||||
else {
|
||||
filter->event_filters =
|
||||
realloc(filter->event_filters,
|
||||
sizeof(*filter->event_filters) *
|
||||
(filter->filters + 1));
|
||||
if (!filter->event_filters)
|
||||
die("Could not allocate filter");
|
||||
}
|
||||
filter->event_filters = realloc(filter->event_filters,
|
||||
sizeof(*filter->event_filters) *
|
||||
(filter->filters + 1));
|
||||
if (!filter->event_filters)
|
||||
die("Could not allocate filter");
|
||||
|
||||
for (i = 0; i < filter->filters; i++) {
|
||||
if (filter->event_filters[i].event_id > id)
|
||||
@@ -1480,7 +1474,7 @@ void pevent_filter_clear_trivial(struct event_filter *filter,
|
||||
{
|
||||
struct filter_type *filter_type;
|
||||
int count = 0;
|
||||
int *ids;
|
||||
int *ids = NULL;
|
||||
int i;
|
||||
|
||||
if (!filter->filters)
|
||||
@@ -1504,10 +1498,8 @@ void pevent_filter_clear_trivial(struct event_filter *filter,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (count)
|
||||
ids = realloc(ids, sizeof(*ids) * (count + 1));
|
||||
else
|
||||
ids = malloc(sizeof(*ids));
|
||||
|
||||
ids = realloc(ids, sizeof(*ids) * (count + 1));
|
||||
if (!ids)
|
||||
die("Can't allocate ids");
|
||||
ids[count++] = filter_type->event_id;
|
||||
@@ -1710,18 +1702,43 @@ static int test_num(struct event_format *event,
|
||||
|
||||
static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record)
|
||||
{
|
||||
const char *val = record->data + arg->str.field->offset;
|
||||
struct event_format *event;
|
||||
struct pevent *pevent;
|
||||
unsigned long long addr;
|
||||
const char *val = NULL;
|
||||
char hex[64];
|
||||
|
||||
/*
|
||||
* We need to copy the data since we can't be sure the field
|
||||
* is null terminated.
|
||||
*/
|
||||
if (*(val + arg->str.field->size - 1)) {
|
||||
/* copy it */
|
||||
memcpy(arg->str.buffer, val, arg->str.field->size);
|
||||
/* the buffer is already NULL terminated */
|
||||
val = arg->str.buffer;
|
||||
/* If the field is not a string convert it */
|
||||
if (arg->str.field->flags & FIELD_IS_STRING) {
|
||||
val = record->data + arg->str.field->offset;
|
||||
|
||||
/*
|
||||
* We need to copy the data since we can't be sure the field
|
||||
* is null terminated.
|
||||
*/
|
||||
if (*(val + arg->str.field->size - 1)) {
|
||||
/* copy it */
|
||||
memcpy(arg->str.buffer, val, arg->str.field->size);
|
||||
/* the buffer is already NULL terminated */
|
||||
val = arg->str.buffer;
|
||||
}
|
||||
|
||||
} else {
|
||||
event = arg->str.field->event;
|
||||
pevent = event->pevent;
|
||||
addr = get_value(event, arg->str.field, record);
|
||||
|
||||
if (arg->str.field->flags & (FIELD_IS_POINTER | FIELD_IS_LONG))
|
||||
/* convert to a kernel symbol */
|
||||
val = pevent_find_function(pevent, addr);
|
||||
|
||||
if (val == NULL) {
|
||||
/* just use the hex of the string name */
|
||||
snprintf(hex, 64, "0x%llx", addr);
|
||||
val = hex;
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -2001,11 +2018,13 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
|
||||
char *lstr;
|
||||
char *rstr;
|
||||
char *op;
|
||||
char *str;
|
||||
char *str = NULL;
|
||||
int len;
|
||||
|
||||
lstr = arg_to_str(filter, arg->exp.left);
|
||||
rstr = arg_to_str(filter, arg->exp.right);
|
||||
if (!lstr || !rstr)
|
||||
goto out;
|
||||
|
||||
switch (arg->exp.type) {
|
||||
case FILTER_EXP_ADD:
|
||||
@@ -2045,6 +2064,7 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
|
||||
len = strlen(op) + strlen(lstr) + strlen(rstr) + 4;
|
||||
str = malloc_or_die(len);
|
||||
snprintf(str, len, "%s %s %s", lstr, op, rstr);
|
||||
out:
|
||||
free(lstr);
|
||||
free(rstr);
|
||||
|
||||
@@ -2061,6 +2081,8 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
|
||||
|
||||
lstr = arg_to_str(filter, arg->num.left);
|
||||
rstr = arg_to_str(filter, arg->num.right);
|
||||
if (!lstr || !rstr)
|
||||
goto out;
|
||||
|
||||
switch (arg->num.type) {
|
||||
case FILTER_CMP_EQ:
|
||||
@@ -2097,6 +2119,7 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
free(lstr);
|
||||
free(rstr);
|
||||
return str;
|
||||
@@ -2247,7 +2270,12 @@ int pevent_filter_compare(struct event_filter *filter1, struct event_filter *fil
|
||||
/* The best way to compare complex filters is with strings */
|
||||
str1 = arg_to_str(filter1, filter_type1->filter);
|
||||
str2 = arg_to_str(filter2, filter_type2->filter);
|
||||
result = strcmp(str1, str2) != 0;
|
||||
if (str1 && str2)
|
||||
result = strcmp(str1, str2) != 0;
|
||||
else
|
||||
/* bail out if allocation fails */
|
||||
result = 1;
|
||||
|
||||
free(str1);
|
||||
free(str2);
|
||||
if (result)
|
||||
|
||||
@@ -144,7 +144,7 @@ On x86-64, x86-64-unrolled, x86-64-movsq and x86-64-movsb are supported.
|
||||
Repeat memcpy invocation this number of times.
|
||||
|
||||
-c::
|
||||
--clock::
|
||||
--cycle::
|
||||
Use perf's cpu-cycles event instead of gettimeofday syscall.
|
||||
|
||||
-o::
|
||||
@@ -176,7 +176,7 @@ On x86-64, x86-64-unrolled, x86-64-stosq and x86-64-stosb are supported.
|
||||
Repeat memset invocation this number of times.
|
||||
|
||||
-c::
|
||||
--clock::
|
||||
--cycle::
|
||||
Use perf's cpu-cycles event instead of gettimeofday syscall.
|
||||
|
||||
-o::
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
static const char *length_str = "1MB";
|
||||
static const char *routine = "default";
|
||||
static int iterations = 1;
|
||||
static bool use_clock;
|
||||
static int clock_fd;
|
||||
static bool use_cycle;
|
||||
static int cycle_fd;
|
||||
static bool only_prefault;
|
||||
static bool no_prefault;
|
||||
|
||||
@@ -37,7 +37,7 @@ static const struct option options[] = {
|
||||
"Specify routine to copy"),
|
||||
OPT_INTEGER('i', "iterations", &iterations,
|
||||
"repeat memcpy() invocation this number of times"),
|
||||
OPT_BOOLEAN('c', "clock", &use_clock,
|
||||
OPT_BOOLEAN('c', "cycle", &use_cycle,
|
||||
"Use cycles event instead of gettimeofday() for measuring"),
|
||||
OPT_BOOLEAN('o', "only-prefault", &only_prefault,
|
||||
"Show only the result with page faults before memcpy()"),
|
||||
@@ -76,27 +76,27 @@ static const char * const bench_mem_memcpy_usage[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct perf_event_attr clock_attr = {
|
||||
static struct perf_event_attr cycle_attr = {
|
||||
.type = PERF_TYPE_HARDWARE,
|
||||
.config = PERF_COUNT_HW_CPU_CYCLES
|
||||
};
|
||||
|
||||
static void init_clock(void)
|
||||
static void init_cycle(void)
|
||||
{
|
||||
clock_fd = sys_perf_event_open(&clock_attr, getpid(), -1, -1, 0);
|
||||
cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0);
|
||||
|
||||
if (clock_fd < 0 && errno == ENOSYS)
|
||||
if (cycle_fd < 0 && errno == ENOSYS)
|
||||
die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
|
||||
else
|
||||
BUG_ON(clock_fd < 0);
|
||||
BUG_ON(cycle_fd < 0);
|
||||
}
|
||||
|
||||
static u64 get_clock(void)
|
||||
static u64 get_cycle(void)
|
||||
{
|
||||
int ret;
|
||||
u64 clk;
|
||||
|
||||
ret = read(clock_fd, &clk, sizeof(u64));
|
||||
ret = read(cycle_fd, &clk, sizeof(u64));
|
||||
BUG_ON(ret != sizeof(u64));
|
||||
|
||||
return clk;
|
||||
@@ -119,9 +119,9 @@ static void alloc_mem(void **dst, void **src, size_t length)
|
||||
die("memory allocation failed - maybe length is too large?\n");
|
||||
}
|
||||
|
||||
static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault)
|
||||
static u64 do_memcpy_cycle(memcpy_t fn, size_t len, bool prefault)
|
||||
{
|
||||
u64 clock_start = 0ULL, clock_end = 0ULL;
|
||||
u64 cycle_start = 0ULL, cycle_end = 0ULL;
|
||||
void *src = NULL, *dst = NULL;
|
||||
int i;
|
||||
|
||||
@@ -130,14 +130,14 @@ static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault)
|
||||
if (prefault)
|
||||
fn(dst, src, len);
|
||||
|
||||
clock_start = get_clock();
|
||||
cycle_start = get_cycle();
|
||||
for (i = 0; i < iterations; ++i)
|
||||
fn(dst, src, len);
|
||||
clock_end = get_clock();
|
||||
cycle_end = get_cycle();
|
||||
|
||||
free(src);
|
||||
free(dst);
|
||||
return clock_end - clock_start;
|
||||
return cycle_end - cycle_start;
|
||||
}
|
||||
|
||||
static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)
|
||||
@@ -182,17 +182,17 @@ int bench_mem_memcpy(int argc, const char **argv,
|
||||
int i;
|
||||
size_t len;
|
||||
double result_bps[2];
|
||||
u64 result_clock[2];
|
||||
u64 result_cycle[2];
|
||||
|
||||
argc = parse_options(argc, argv, options,
|
||||
bench_mem_memcpy_usage, 0);
|
||||
|
||||
if (use_clock)
|
||||
init_clock();
|
||||
if (use_cycle)
|
||||
init_cycle();
|
||||
|
||||
len = (size_t)perf_atoll((char *)length_str);
|
||||
|
||||
result_clock[0] = result_clock[1] = 0ULL;
|
||||
result_cycle[0] = result_cycle[1] = 0ULL;
|
||||
result_bps[0] = result_bps[1] = 0.0;
|
||||
|
||||
if ((s64)len <= 0) {
|
||||
@@ -223,11 +223,11 @@ int bench_mem_memcpy(int argc, const char **argv,
|
||||
|
||||
if (!only_prefault && !no_prefault) {
|
||||
/* show both of results */
|
||||
if (use_clock) {
|
||||
result_clock[0] =
|
||||
do_memcpy_clock(routines[i].fn, len, false);
|
||||
result_clock[1] =
|
||||
do_memcpy_clock(routines[i].fn, len, true);
|
||||
if (use_cycle) {
|
||||
result_cycle[0] =
|
||||
do_memcpy_cycle(routines[i].fn, len, false);
|
||||
result_cycle[1] =
|
||||
do_memcpy_cycle(routines[i].fn, len, true);
|
||||
} else {
|
||||
result_bps[0] =
|
||||
do_memcpy_gettimeofday(routines[i].fn,
|
||||
@@ -237,9 +237,9 @@ int bench_mem_memcpy(int argc, const char **argv,
|
||||
len, true);
|
||||
}
|
||||
} else {
|
||||
if (use_clock) {
|
||||
result_clock[pf] =
|
||||
do_memcpy_clock(routines[i].fn,
|
||||
if (use_cycle) {
|
||||
result_cycle[pf] =
|
||||
do_memcpy_cycle(routines[i].fn,
|
||||
len, only_prefault);
|
||||
} else {
|
||||
result_bps[pf] =
|
||||
@@ -251,12 +251,12 @@ int bench_mem_memcpy(int argc, const char **argv,
|
||||
switch (bench_format) {
|
||||
case BENCH_FORMAT_DEFAULT:
|
||||
if (!only_prefault && !no_prefault) {
|
||||
if (use_clock) {
|
||||
printf(" %14lf Clock/Byte\n",
|
||||
(double)result_clock[0]
|
||||
if (use_cycle) {
|
||||
printf(" %14lf Cycle/Byte\n",
|
||||
(double)result_cycle[0]
|
||||
/ (double)len);
|
||||
printf(" %14lf Clock/Byte (with prefault)\n",
|
||||
(double)result_clock[1]
|
||||
printf(" %14lf Cycle/Byte (with prefault)\n",
|
||||
(double)result_cycle[1]
|
||||
/ (double)len);
|
||||
} else {
|
||||
print_bps(result_bps[0]);
|
||||
@@ -265,9 +265,9 @@ int bench_mem_memcpy(int argc, const char **argv,
|
||||
printf(" (with prefault)\n");
|
||||
}
|
||||
} else {
|
||||
if (use_clock) {
|
||||
printf(" %14lf Clock/Byte",
|
||||
(double)result_clock[pf]
|
||||
if (use_cycle) {
|
||||
printf(" %14lf Cycle/Byte",
|
||||
(double)result_cycle[pf]
|
||||
/ (double)len);
|
||||
} else
|
||||
print_bps(result_bps[pf]);
|
||||
@@ -277,17 +277,17 @@ int bench_mem_memcpy(int argc, const char **argv,
|
||||
break;
|
||||
case BENCH_FORMAT_SIMPLE:
|
||||
if (!only_prefault && !no_prefault) {
|
||||
if (use_clock) {
|
||||
if (use_cycle) {
|
||||
printf("%lf %lf\n",
|
||||
(double)result_clock[0] / (double)len,
|
||||
(double)result_clock[1] / (double)len);
|
||||
(double)result_cycle[0] / (double)len,
|
||||
(double)result_cycle[1] / (double)len);
|
||||
} else {
|
||||
printf("%lf %lf\n",
|
||||
result_bps[0], result_bps[1]);
|
||||
}
|
||||
} else {
|
||||
if (use_clock) {
|
||||
printf("%lf\n", (double)result_clock[pf]
|
||||
if (use_cycle) {
|
||||
printf("%lf\n", (double)result_cycle[pf]
|
||||
/ (double)len);
|
||||
} else
|
||||
printf("%lf\n", result_bps[pf]);
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
static const char *length_str = "1MB";
|
||||
static const char *routine = "default";
|
||||
static int iterations = 1;
|
||||
static bool use_clock;
|
||||
static int clock_fd;
|
||||
static bool use_cycle;
|
||||
static int cycle_fd;
|
||||
static bool only_prefault;
|
||||
static bool no_prefault;
|
||||
|
||||
@@ -37,7 +37,7 @@ static const struct option options[] = {
|
||||
"Specify routine to set"),
|
||||
OPT_INTEGER('i', "iterations", &iterations,
|
||||
"repeat memset() invocation this number of times"),
|
||||
OPT_BOOLEAN('c', "clock", &use_clock,
|
||||
OPT_BOOLEAN('c', "cycle", &use_cycle,
|
||||
"Use cycles event instead of gettimeofday() for measuring"),
|
||||
OPT_BOOLEAN('o', "only-prefault", &only_prefault,
|
||||
"Show only the result with page faults before memset()"),
|
||||
@@ -76,27 +76,27 @@ static const char * const bench_mem_memset_usage[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct perf_event_attr clock_attr = {
|
||||
static struct perf_event_attr cycle_attr = {
|
||||
.type = PERF_TYPE_HARDWARE,
|
||||
.config = PERF_COUNT_HW_CPU_CYCLES
|
||||
};
|
||||
|
||||
static void init_clock(void)
|
||||
static void init_cycle(void)
|
||||
{
|
||||
clock_fd = sys_perf_event_open(&clock_attr, getpid(), -1, -1, 0);
|
||||
cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0);
|
||||
|
||||
if (clock_fd < 0 && errno == ENOSYS)
|
||||
if (cycle_fd < 0 && errno == ENOSYS)
|
||||
die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
|
||||
else
|
||||
BUG_ON(clock_fd < 0);
|
||||
BUG_ON(cycle_fd < 0);
|
||||
}
|
||||
|
||||
static u64 get_clock(void)
|
||||
static u64 get_cycle(void)
|
||||
{
|
||||
int ret;
|
||||
u64 clk;
|
||||
|
||||
ret = read(clock_fd, &clk, sizeof(u64));
|
||||
ret = read(cycle_fd, &clk, sizeof(u64));
|
||||
BUG_ON(ret != sizeof(u64));
|
||||
|
||||
return clk;
|
||||
@@ -115,9 +115,9 @@ static void alloc_mem(void **dst, size_t length)
|
||||
die("memory allocation failed - maybe length is too large?\n");
|
||||
}
|
||||
|
||||
static u64 do_memset_clock(memset_t fn, size_t len, bool prefault)
|
||||
static u64 do_memset_cycle(memset_t fn, size_t len, bool prefault)
|
||||
{
|
||||
u64 clock_start = 0ULL, clock_end = 0ULL;
|
||||
u64 cycle_start = 0ULL, cycle_end = 0ULL;
|
||||
void *dst = NULL;
|
||||
int i;
|
||||
|
||||
@@ -126,13 +126,13 @@ static u64 do_memset_clock(memset_t fn, size_t len, bool prefault)
|
||||
if (prefault)
|
||||
fn(dst, -1, len);
|
||||
|
||||
clock_start = get_clock();
|
||||
cycle_start = get_cycle();
|
||||
for (i = 0; i < iterations; ++i)
|
||||
fn(dst, i, len);
|
||||
clock_end = get_clock();
|
||||
cycle_end = get_cycle();
|
||||
|
||||
free(dst);
|
||||
return clock_end - clock_start;
|
||||
return cycle_end - cycle_start;
|
||||
}
|
||||
|
||||
static double do_memset_gettimeofday(memset_t fn, size_t len, bool prefault)
|
||||
@@ -176,17 +176,17 @@ int bench_mem_memset(int argc, const char **argv,
|
||||
int i;
|
||||
size_t len;
|
||||
double result_bps[2];
|
||||
u64 result_clock[2];
|
||||
u64 result_cycle[2];
|
||||
|
||||
argc = parse_options(argc, argv, options,
|
||||
bench_mem_memset_usage, 0);
|
||||
|
||||
if (use_clock)
|
||||
init_clock();
|
||||
if (use_cycle)
|
||||
init_cycle();
|
||||
|
||||
len = (size_t)perf_atoll((char *)length_str);
|
||||
|
||||
result_clock[0] = result_clock[1] = 0ULL;
|
||||
result_cycle[0] = result_cycle[1] = 0ULL;
|
||||
result_bps[0] = result_bps[1] = 0.0;
|
||||
|
||||
if ((s64)len <= 0) {
|
||||
@@ -217,11 +217,11 @@ int bench_mem_memset(int argc, const char **argv,
|
||||
|
||||
if (!only_prefault && !no_prefault) {
|
||||
/* show both of results */
|
||||
if (use_clock) {
|
||||
result_clock[0] =
|
||||
do_memset_clock(routines[i].fn, len, false);
|
||||
result_clock[1] =
|
||||
do_memset_clock(routines[i].fn, len, true);
|
||||
if (use_cycle) {
|
||||
result_cycle[0] =
|
||||
do_memset_cycle(routines[i].fn, len, false);
|
||||
result_cycle[1] =
|
||||
do_memset_cycle(routines[i].fn, len, true);
|
||||
} else {
|
||||
result_bps[0] =
|
||||
do_memset_gettimeofday(routines[i].fn,
|
||||
@@ -231,9 +231,9 @@ int bench_mem_memset(int argc, const char **argv,
|
||||
len, true);
|
||||
}
|
||||
} else {
|
||||
if (use_clock) {
|
||||
result_clock[pf] =
|
||||
do_memset_clock(routines[i].fn,
|
||||
if (use_cycle) {
|
||||
result_cycle[pf] =
|
||||
do_memset_cycle(routines[i].fn,
|
||||
len, only_prefault);
|
||||
} else {
|
||||
result_bps[pf] =
|
||||
@@ -245,12 +245,12 @@ int bench_mem_memset(int argc, const char **argv,
|
||||
switch (bench_format) {
|
||||
case BENCH_FORMAT_DEFAULT:
|
||||
if (!only_prefault && !no_prefault) {
|
||||
if (use_clock) {
|
||||
printf(" %14lf Clock/Byte\n",
|
||||
(double)result_clock[0]
|
||||
if (use_cycle) {
|
||||
printf(" %14lf Cycle/Byte\n",
|
||||
(double)result_cycle[0]
|
||||
/ (double)len);
|
||||
printf(" %14lf Clock/Byte (with prefault)\n ",
|
||||
(double)result_clock[1]
|
||||
printf(" %14lf Cycle/Byte (with prefault)\n ",
|
||||
(double)result_cycle[1]
|
||||
/ (double)len);
|
||||
} else {
|
||||
print_bps(result_bps[0]);
|
||||
@@ -259,9 +259,9 @@ int bench_mem_memset(int argc, const char **argv,
|
||||
printf(" (with prefault)\n");
|
||||
}
|
||||
} else {
|
||||
if (use_clock) {
|
||||
printf(" %14lf Clock/Byte",
|
||||
(double)result_clock[pf]
|
||||
if (use_cycle) {
|
||||
printf(" %14lf Cycle/Byte",
|
||||
(double)result_cycle[pf]
|
||||
/ (double)len);
|
||||
} else
|
||||
print_bps(result_bps[pf]);
|
||||
@@ -271,17 +271,17 @@ int bench_mem_memset(int argc, const char **argv,
|
||||
break;
|
||||
case BENCH_FORMAT_SIMPLE:
|
||||
if (!only_prefault && !no_prefault) {
|
||||
if (use_clock) {
|
||||
if (use_cycle) {
|
||||
printf("%lf %lf\n",
|
||||
(double)result_clock[0] / (double)len,
|
||||
(double)result_clock[1] / (double)len);
|
||||
(double)result_cycle[0] / (double)len,
|
||||
(double)result_cycle[1] / (double)len);
|
||||
} else {
|
||||
printf("%lf %lf\n",
|
||||
result_bps[0], result_bps[1]);
|
||||
}
|
||||
} else {
|
||||
if (use_clock) {
|
||||
printf("%lf\n", (double)result_clock[pf]
|
||||
if (use_cycle) {
|
||||
printf("%lf\n", (double)result_cycle[pf]
|
||||
/ (double)len);
|
||||
} else
|
||||
printf("%lf\n", result_bps[pf]);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "cpumap.h"
|
||||
#include "thread_map.h"
|
||||
#include "target.h"
|
||||
#include "../../../include/linux/hw_breakpoint.h"
|
||||
|
||||
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
|
||||
#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
|
||||
@@ -152,6 +153,31 @@ static int perf_evsel__sw_name(struct perf_evsel *evsel, char *bf, size_t size)
|
||||
return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
|
||||
}
|
||||
|
||||
static int __perf_evsel__bp_name(char *bf, size_t size, u64 addr, u64 type)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = scnprintf(bf, size, "mem:0x%" PRIx64 ":", addr);
|
||||
|
||||
if (type & HW_BREAKPOINT_R)
|
||||
r += scnprintf(bf + r, size - r, "r");
|
||||
|
||||
if (type & HW_BREAKPOINT_W)
|
||||
r += scnprintf(bf + r, size - r, "w");
|
||||
|
||||
if (type & HW_BREAKPOINT_X)
|
||||
r += scnprintf(bf + r, size - r, "x");
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int perf_evsel__bp_name(struct perf_evsel *evsel, char *bf, size_t size)
|
||||
{
|
||||
struct perf_event_attr *attr = &evsel->attr;
|
||||
int r = __perf_evsel__bp_name(bf, size, attr->bp_addr, attr->bp_type);
|
||||
return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
|
||||
}
|
||||
|
||||
const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
|
||||
[PERF_EVSEL__MAX_ALIASES] = {
|
||||
{ "L1-dcache", "l1-d", "l1d", "L1-data", },
|
||||
@@ -285,6 +311,10 @@ const char *perf_evsel__name(struct perf_evsel *evsel)
|
||||
scnprintf(bf, sizeof(bf), "%s", "unknown tracepoint");
|
||||
break;
|
||||
|
||||
case PERF_TYPE_BREAKPOINT:
|
||||
perf_evsel__bp_name(evsel, bf, sizeof(bf));
|
||||
break;
|
||||
|
||||
default:
|
||||
scnprintf(bf, sizeof(bf), "%s", "unknown attr type");
|
||||
break;
|
||||
|
||||
@@ -108,4 +108,14 @@ int eprintf(int level,
|
||||
#define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__)
|
||||
#define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__)
|
||||
|
||||
/*
|
||||
* This looks more complex than it should be. But we need to
|
||||
* get the type for the ~ right in round_down (it needs to be
|
||||
* as wide as the result!), and we want to evaluate the macro
|
||||
* arguments just once each.
|
||||
*/
|
||||
#define __round_mask(x, y) ((__typeof__(x))((y)-1))
|
||||
#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
|
||||
#define round_down(x, y) ((x) & ~__round_mask(x, y))
|
||||
|
||||
#endif
|
||||
|
||||
@@ -181,6 +181,22 @@ static int test__checkevent_breakpoint_w(struct perf_evlist *evlist)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist)
|
||||
{
|
||||
struct perf_evsel *evsel = list_entry(evlist->entries.next,
|
||||
struct perf_evsel, node);
|
||||
|
||||
TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
|
||||
TEST_ASSERT_VAL("wrong type",
|
||||
PERF_TYPE_BREAKPOINT == evsel->attr.type);
|
||||
TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
|
||||
TEST_ASSERT_VAL("wrong bp_type",
|
||||
(HW_BREAKPOINT_R|HW_BREAKPOINT_W) == evsel->attr.bp_type);
|
||||
TEST_ASSERT_VAL("wrong bp_len",
|
||||
HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist)
|
||||
{
|
||||
struct perf_evsel *evsel = list_entry(evlist->entries.next,
|
||||
@@ -309,6 +325,8 @@ static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
|
||||
TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
|
||||
TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
|
||||
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
|
||||
TEST_ASSERT_VAL("wrong name",
|
||||
!strcmp(perf_evsel__name(evsel), "mem:0x0:rw:u"));
|
||||
|
||||
return test__checkevent_breakpoint(evlist);
|
||||
}
|
||||
@@ -322,6 +340,8 @@ static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist)
|
||||
TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
|
||||
TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
|
||||
TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
|
||||
TEST_ASSERT_VAL("wrong name",
|
||||
!strcmp(perf_evsel__name(evsel), "mem:0x0:x:k"));
|
||||
|
||||
return test__checkevent_breakpoint_x(evlist);
|
||||
}
|
||||
@@ -335,6 +355,8 @@ static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist)
|
||||
TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
|
||||
TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
|
||||
TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
|
||||
TEST_ASSERT_VAL("wrong name",
|
||||
!strcmp(perf_evsel__name(evsel), "mem:0x0:r:hp"));
|
||||
|
||||
return test__checkevent_breakpoint_r(evlist);
|
||||
}
|
||||
@@ -348,10 +370,27 @@ static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist)
|
||||
TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
|
||||
TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
|
||||
TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
|
||||
TEST_ASSERT_VAL("wrong name",
|
||||
!strcmp(perf_evsel__name(evsel), "mem:0x0:w:up"));
|
||||
|
||||
return test__checkevent_breakpoint_w(evlist);
|
||||
}
|
||||
|
||||
static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist)
|
||||
{
|
||||
struct perf_evsel *evsel = list_entry(evlist->entries.next,
|
||||
struct perf_evsel, node);
|
||||
|
||||
TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
|
||||
TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
|
||||
TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
|
||||
TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
|
||||
TEST_ASSERT_VAL("wrong name",
|
||||
!strcmp(perf_evsel__name(evsel), "mem:0x0:rw:kp"));
|
||||
|
||||
return test__checkevent_breakpoint_rw(evlist);
|
||||
}
|
||||
|
||||
static int test__checkevent_pmu(struct perf_evlist *evlist)
|
||||
{
|
||||
|
||||
@@ -585,10 +624,16 @@ static struct test__event_st test__events[] = {
|
||||
.name = "instructions:H",
|
||||
.check = test__checkevent_exclude_guest_modifier,
|
||||
},
|
||||
[26] = {
|
||||
.name = "mem:0:rw",
|
||||
.check = test__checkevent_breakpoint_rw,
|
||||
},
|
||||
[27] = {
|
||||
.name = "mem:0:rw:kp",
|
||||
.check = test__checkevent_breakpoint_rw_modifier,
|
||||
},
|
||||
};
|
||||
|
||||
#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st))
|
||||
|
||||
static struct test__event_st test__events_pmu[] = {
|
||||
[0] = {
|
||||
.name = "cpu/config=10,config1,config2=3,period=1000/u",
|
||||
@@ -600,9 +645,6 @@ static struct test__event_st test__events_pmu[] = {
|
||||
},
|
||||
};
|
||||
|
||||
#define TEST__EVENTS_PMU_CNT (sizeof(test__events_pmu) / \
|
||||
sizeof(struct test__event_st))
|
||||
|
||||
struct test__term {
|
||||
const char *str;
|
||||
__u32 type;
|
||||
@@ -718,21 +760,17 @@ int parse_events__test(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
do {
|
||||
ret = test_events(test__events, TEST__EVENTS_CNT);
|
||||
if (ret)
|
||||
break;
|
||||
#define TEST_EVENTS(tests) \
|
||||
do { \
|
||||
ret = test_events(tests, ARRAY_SIZE(tests)); \
|
||||
if (ret) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
if (test_pmu()) {
|
||||
ret = test_events(test__events_pmu,
|
||||
TEST__EVENTS_PMU_CNT);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
TEST_EVENTS(test__events);
|
||||
|
||||
ret = test_terms(test__terms, TEST__TERMS_CNT);
|
||||
if (test_pmu())
|
||||
TEST_EVENTS(test__events_pmu);
|
||||
|
||||
} while (0);
|
||||
|
||||
return ret;
|
||||
return test_terms(test__terms, ARRAY_SIZE(test__terms));
|
||||
}
|
||||
|
||||
+130
-62
@@ -19,8 +19,6 @@
|
||||
#define MAX_NAME_LEN 100
|
||||
|
||||
struct event_symbol {
|
||||
u8 type;
|
||||
u64 config;
|
||||
const char *symbol;
|
||||
const char *alias;
|
||||
};
|
||||
@@ -30,30 +28,86 @@ extern int parse_events_debug;
|
||||
#endif
|
||||
int parse_events_parse(void *data, void *scanner);
|
||||
|
||||
#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
|
||||
#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
|
||||
static struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
|
||||
[PERF_COUNT_HW_CPU_CYCLES] = {
|
||||
.symbol = "cpu-cycles",
|
||||
.alias = "cycles",
|
||||
},
|
||||
[PERF_COUNT_HW_INSTRUCTIONS] = {
|
||||
.symbol = "instructions",
|
||||
.alias = "",
|
||||
},
|
||||
[PERF_COUNT_HW_CACHE_REFERENCES] = {
|
||||
.symbol = "cache-references",
|
||||
.alias = "",
|
||||
},
|
||||
[PERF_COUNT_HW_CACHE_MISSES] = {
|
||||
.symbol = "cache-misses",
|
||||
.alias = "",
|
||||
},
|
||||
[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = {
|
||||
.symbol = "branch-instructions",
|
||||
.alias = "branches",
|
||||
},
|
||||
[PERF_COUNT_HW_BRANCH_MISSES] = {
|
||||
.symbol = "branch-misses",
|
||||
.alias = "",
|
||||
},
|
||||
[PERF_COUNT_HW_BUS_CYCLES] = {
|
||||
.symbol = "bus-cycles",
|
||||
.alias = "",
|
||||
},
|
||||
[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = {
|
||||
.symbol = "stalled-cycles-frontend",
|
||||
.alias = "idle-cycles-frontend",
|
||||
},
|
||||
[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = {
|
||||
.symbol = "stalled-cycles-backend",
|
||||
.alias = "idle-cycles-backend",
|
||||
},
|
||||
[PERF_COUNT_HW_REF_CPU_CYCLES] = {
|
||||
.symbol = "ref-cycles",
|
||||
.alias = "",
|
||||
},
|
||||
};
|
||||
|
||||
static struct event_symbol event_symbols[] = {
|
||||
{ CHW(CPU_CYCLES), "cpu-cycles", "cycles" },
|
||||
{ CHW(STALLED_CYCLES_FRONTEND), "stalled-cycles-frontend", "idle-cycles-frontend" },
|
||||
{ CHW(STALLED_CYCLES_BACKEND), "stalled-cycles-backend", "idle-cycles-backend" },
|
||||
{ CHW(INSTRUCTIONS), "instructions", "" },
|
||||
{ CHW(CACHE_REFERENCES), "cache-references", "" },
|
||||
{ CHW(CACHE_MISSES), "cache-misses", "" },
|
||||
{ CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" },
|
||||
{ CHW(BRANCH_MISSES), "branch-misses", "" },
|
||||
{ CHW(BUS_CYCLES), "bus-cycles", "" },
|
||||
{ CHW(REF_CPU_CYCLES), "ref-cycles", "" },
|
||||
|
||||
{ CSW(CPU_CLOCK), "cpu-clock", "" },
|
||||
{ CSW(TASK_CLOCK), "task-clock", "" },
|
||||
{ CSW(PAGE_FAULTS), "page-faults", "faults" },
|
||||
{ CSW(PAGE_FAULTS_MIN), "minor-faults", "" },
|
||||
{ CSW(PAGE_FAULTS_MAJ), "major-faults", "" },
|
||||
{ CSW(CONTEXT_SWITCHES), "context-switches", "cs" },
|
||||
{ CSW(CPU_MIGRATIONS), "cpu-migrations", "migrations" },
|
||||
{ CSW(ALIGNMENT_FAULTS), "alignment-faults", "" },
|
||||
{ CSW(EMULATION_FAULTS), "emulation-faults", "" },
|
||||
static struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
|
||||
[PERF_COUNT_SW_CPU_CLOCK] = {
|
||||
.symbol = "cpu-clock",
|
||||
.alias = "",
|
||||
},
|
||||
[PERF_COUNT_SW_TASK_CLOCK] = {
|
||||
.symbol = "task-clock",
|
||||
.alias = "",
|
||||
},
|
||||
[PERF_COUNT_SW_PAGE_FAULTS] = {
|
||||
.symbol = "page-faults",
|
||||
.alias = "faults",
|
||||
},
|
||||
[PERF_COUNT_SW_CONTEXT_SWITCHES] = {
|
||||
.symbol = "context-switches",
|
||||
.alias = "cs",
|
||||
},
|
||||
[PERF_COUNT_SW_CPU_MIGRATIONS] = {
|
||||
.symbol = "cpu-migrations",
|
||||
.alias = "migrations",
|
||||
},
|
||||
[PERF_COUNT_SW_PAGE_FAULTS_MIN] = {
|
||||
.symbol = "minor-faults",
|
||||
.alias = "",
|
||||
},
|
||||
[PERF_COUNT_SW_PAGE_FAULTS_MAJ] = {
|
||||
.symbol = "major-faults",
|
||||
.alias = "",
|
||||
},
|
||||
[PERF_COUNT_SW_ALIGNMENT_FAULTS] = {
|
||||
.symbol = "alignment-faults",
|
||||
.alias = "",
|
||||
},
|
||||
[PERF_COUNT_SW_EMULATION_FAULTS] = {
|
||||
.symbol = "emulation-faults",
|
||||
.alias = "",
|
||||
},
|
||||
};
|
||||
|
||||
#define __PERF_EVENT_FIELD(config, name) \
|
||||
@@ -383,21 +437,31 @@ parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
|
||||
if (!type || !type[i])
|
||||
break;
|
||||
|
||||
#define CHECK_SET_TYPE(bit) \
|
||||
do { \
|
||||
if (attr->bp_type & bit) \
|
||||
return -EINVAL; \
|
||||
else \
|
||||
attr->bp_type |= bit; \
|
||||
} while (0)
|
||||
|
||||
switch (type[i]) {
|
||||
case 'r':
|
||||
attr->bp_type |= HW_BREAKPOINT_R;
|
||||
CHECK_SET_TYPE(HW_BREAKPOINT_R);
|
||||
break;
|
||||
case 'w':
|
||||
attr->bp_type |= HW_BREAKPOINT_W;
|
||||
CHECK_SET_TYPE(HW_BREAKPOINT_W);
|
||||
break;
|
||||
case 'x':
|
||||
attr->bp_type |= HW_BREAKPOINT_X;
|
||||
CHECK_SET_TYPE(HW_BREAKPOINT_X);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
#undef CHECK_SET_TYPE
|
||||
|
||||
if (!attr->bp_type) /* Default */
|
||||
attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
|
||||
|
||||
@@ -408,7 +472,6 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
|
||||
void *ptr, char *type)
|
||||
{
|
||||
struct perf_event_attr attr;
|
||||
char name[MAX_NAME_LEN];
|
||||
|
||||
memset(&attr, 0, sizeof(attr));
|
||||
attr.bp_addr = (unsigned long) ptr;
|
||||
@@ -427,8 +490,7 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
|
||||
|
||||
attr.type = PERF_TYPE_BREAKPOINT;
|
||||
|
||||
snprintf(name, MAX_NAME_LEN, "mem:%p:%s", ptr, type ? type : "rw");
|
||||
return add_event(list, idx, &attr, name);
|
||||
return add_event(list, idx, &attr, NULL);
|
||||
}
|
||||
|
||||
static int config_term(struct perf_event_attr *attr,
|
||||
@@ -816,16 +878,13 @@ int is_valid_tracepoint(const char *event_string)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void print_events_type(u8 type)
|
||||
static void __print_events_type(u8 type, struct event_symbol *syms,
|
||||
unsigned max)
|
||||
{
|
||||
struct event_symbol *syms = event_symbols;
|
||||
unsigned int i;
|
||||
char name[64];
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
|
||||
if (type != syms->type)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < max ; i++, syms++) {
|
||||
if (strlen(syms->alias))
|
||||
snprintf(name, sizeof(name), "%s OR %s",
|
||||
syms->symbol, syms->alias);
|
||||
@@ -837,6 +896,14 @@ void print_events_type(u8 type)
|
||||
}
|
||||
}
|
||||
|
||||
void print_events_type(u8 type)
|
||||
{
|
||||
if (type == PERF_TYPE_SOFTWARE)
|
||||
__print_events_type(type, event_symbols_sw, PERF_COUNT_SW_MAX);
|
||||
else
|
||||
__print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX);
|
||||
}
|
||||
|
||||
int print_hwcache_events(const char *event_glob)
|
||||
{
|
||||
unsigned int type, op, i, printed = 0;
|
||||
@@ -864,26 +931,13 @@ int print_hwcache_events(const char *event_glob)
|
||||
return printed;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print the help text for the event symbols:
|
||||
*/
|
||||
void print_events(const char *event_glob)
|
||||
static void print_symbol_events(const char *event_glob, unsigned type,
|
||||
struct event_symbol *syms, unsigned max)
|
||||
{
|
||||
unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0;
|
||||
struct event_symbol *syms = event_symbols;
|
||||
unsigned i, printed = 0;
|
||||
char name[MAX_NAME_LEN];
|
||||
|
||||
printf("\n");
|
||||
printf("List of pre-defined events (to be used in -e):\n");
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
|
||||
type = syms->type;
|
||||
|
||||
if (type != prev_type && printed) {
|
||||
printf("\n");
|
||||
printed = 0;
|
||||
ntypes_printed++;
|
||||
}
|
||||
for (i = 0; i < max; i++, syms++) {
|
||||
|
||||
if (event_glob != NULL &&
|
||||
!(strglobmatch(syms->symbol, event_glob) ||
|
||||
@@ -894,17 +948,31 @@ void print_events(const char *event_glob)
|
||||
snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
|
||||
else
|
||||
strncpy(name, syms->symbol, MAX_NAME_LEN);
|
||||
printf(" %-50s [%s]\n", name,
|
||||
event_type_descriptors[type]);
|
||||
|
||||
prev_type = type;
|
||||
++printed;
|
||||
printf(" %-50s [%s]\n", name, event_type_descriptors[type]);
|
||||
|
||||
printed++;
|
||||
}
|
||||
|
||||
if (ntypes_printed) {
|
||||
printed = 0;
|
||||
if (printed)
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print the help text for the event symbols:
|
||||
*/
|
||||
void print_events(const char *event_glob)
|
||||
{
|
||||
|
||||
printf("\n");
|
||||
printf("List of pre-defined events (to be used in -e):\n");
|
||||
|
||||
print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
|
||||
event_symbols_hw, PERF_COUNT_HW_MAX);
|
||||
|
||||
print_symbol_events(event_glob, PERF_TYPE_SOFTWARE,
|
||||
event_symbols_sw, PERF_COUNT_SW_MAX);
|
||||
|
||||
print_hwcache_events(event_glob);
|
||||
|
||||
if (event_glob != NULL)
|
||||
|
||||
@@ -56,7 +56,7 @@ static int sym(yyscan_t scanner, int type, int config)
|
||||
YYSTYPE *yylval = parse_events_get_lval(scanner);
|
||||
|
||||
yylval->num = (type << 16) + config;
|
||||
return PE_VALUE_SYM;
|
||||
return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW;
|
||||
}
|
||||
|
||||
static int term(yyscan_t scanner, int type)
|
||||
@@ -76,7 +76,7 @@ num_hex 0x[a-fA-F0-9]+
|
||||
num_raw_hex [a-fA-F0-9]+
|
||||
name [a-zA-Z_*?][a-zA-Z0-9_*?]*
|
||||
modifier_event [ukhpGH]{1,8}
|
||||
modifier_bp [rwx]
|
||||
modifier_bp [rwx]{1,3}
|
||||
|
||||
%%
|
||||
|
||||
@@ -152,6 +152,7 @@ r{num_raw_hex} { return raw(yyscanner); }
|
||||
, { return ','; }
|
||||
: { return ':'; }
|
||||
= { return '='; }
|
||||
\n { }
|
||||
|
||||
<mem>{
|
||||
{modifier_bp} { return str(yyscanner, PE_MODIFIER_BP); }
|
||||
|
||||
@@ -26,14 +26,15 @@ do { \
|
||||
%}
|
||||
|
||||
%token PE_START_EVENTS PE_START_TERMS
|
||||
%token PE_VALUE PE_VALUE_SYM PE_RAW PE_TERM
|
||||
%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
|
||||
%token PE_NAME
|
||||
%token PE_MODIFIER_EVENT PE_MODIFIER_BP
|
||||
%token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
|
||||
%token PE_PREFIX_MEM PE_PREFIX_RAW
|
||||
%token PE_ERROR
|
||||
%type <num> PE_VALUE
|
||||
%type <num> PE_VALUE_SYM
|
||||
%type <num> PE_VALUE_SYM_HW
|
||||
%type <num> PE_VALUE_SYM_SW
|
||||
%type <num> PE_RAW
|
||||
%type <num> PE_TERM
|
||||
%type <str> PE_NAME
|
||||
@@ -41,6 +42,7 @@ do { \
|
||||
%type <str> PE_NAME_CACHE_OP_RESULT
|
||||
%type <str> PE_MODIFIER_EVENT
|
||||
%type <str> PE_MODIFIER_BP
|
||||
%type <num> value_sym
|
||||
%type <head> event_config
|
||||
%type <term> event_term
|
||||
%type <head> event_pmu
|
||||
@@ -109,8 +111,13 @@ PE_NAME '/' event_config '/'
|
||||
$$ = list;
|
||||
}
|
||||
|
||||
value_sym:
|
||||
PE_VALUE_SYM_HW
|
||||
|
|
||||
PE_VALUE_SYM_SW
|
||||
|
||||
event_legacy_symbol:
|
||||
PE_VALUE_SYM '/' event_config '/'
|
||||
value_sym '/' event_config '/'
|
||||
{
|
||||
struct parse_events_data__events *data = _data;
|
||||
struct list_head *list = NULL;
|
||||
@@ -123,7 +130,7 @@ PE_VALUE_SYM '/' event_config '/'
|
||||
$$ = list;
|
||||
}
|
||||
|
|
||||
PE_VALUE_SYM sep_slash_dc
|
||||
value_sym sep_slash_dc
|
||||
{
|
||||
struct parse_events_data__events *data = _data;
|
||||
struct list_head *list = NULL;
|
||||
|
||||
@@ -72,7 +72,7 @@ static int pmu_format(char *name, struct list_head *format)
|
||||
"%s/bus/event_source/devices/%s/format", sysfs, name);
|
||||
|
||||
if (stat(path, &st) < 0)
|
||||
return -1;
|
||||
return 0; /* no error if format does not exist */
|
||||
|
||||
if (pmu_format_parse(path, format))
|
||||
return -1;
|
||||
@@ -252,6 +252,7 @@ static struct perf_pmu *pmu_lookup(char *name)
|
||||
list_splice(&aliases, &pmu->aliases);
|
||||
pmu->name = strdup(name);
|
||||
pmu->type = type;
|
||||
list_add_tail(&pmu->list, &pmus);
|
||||
return pmu;
|
||||
}
|
||||
|
||||
|
||||
@@ -209,6 +209,10 @@ static void define_event_symbols(struct event_format *event,
|
||||
define_symbolic_values(args->symbol.symbols, ev_name,
|
||||
cur_field_name);
|
||||
break;
|
||||
case PRINT_HEX:
|
||||
define_event_symbols(event, ev_name, args->hex.field);
|
||||
define_event_symbols(event, ev_name, args->hex.size);
|
||||
break;
|
||||
case PRINT_BSTRING:
|
||||
case PRINT_DYNAMIC_ARRAY:
|
||||
case PRINT_STRING:
|
||||
|
||||
@@ -166,6 +166,10 @@ static void define_event_symbols(struct event_format *event,
|
||||
define_values(PRINT_SYMBOL, args->symbol.symbols, ev_name,
|
||||
cur_field_name);
|
||||
break;
|
||||
case PRINT_HEX:
|
||||
define_event_symbols(event, ev_name, args->hex.field);
|
||||
define_event_symbols(event, ev_name, args->hex.size);
|
||||
break;
|
||||
case PRINT_STRING:
|
||||
break;
|
||||
case PRINT_TYPE:
|
||||
|
||||
@@ -1478,14 +1478,31 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size)
|
||||
goto out;
|
||||
}
|
||||
|
||||
sec = elf_section_by_name(elf, &ehdr, &shdr,
|
||||
".note.gnu.build-id", NULL);
|
||||
if (sec == NULL) {
|
||||
/*
|
||||
* Check following sections for notes:
|
||||
* '.note.gnu.build-id'
|
||||
* '.notes'
|
||||
* '.note' (VDSO specific)
|
||||
*/
|
||||
do {
|
||||
sec = elf_section_by_name(elf, &ehdr, &shdr,
|
||||
".note.gnu.build-id", NULL);
|
||||
if (sec)
|
||||
break;
|
||||
|
||||
sec = elf_section_by_name(elf, &ehdr, &shdr,
|
||||
".notes", NULL);
|
||||
if (sec == NULL)
|
||||
goto out;
|
||||
}
|
||||
if (sec)
|
||||
break;
|
||||
|
||||
sec = elf_section_by_name(elf, &ehdr, &shdr,
|
||||
".note", NULL);
|
||||
if (sec)
|
||||
break;
|
||||
|
||||
return err;
|
||||
|
||||
} while (0);
|
||||
|
||||
data = elf_getdata(sec, NULL);
|
||||
if (data == NULL)
|
||||
|
||||
Reference in New Issue
Block a user