Commit 5925fa68 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'perf-tools-fixes-for-v5.9-2020-09-16' of...

Merge tag 'perf-tools-fixes-for-v5.9-2020-09-16' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux

Pull perf tools fixes from Arnaldo Carvalho de Melo:

 - Set PERF_SAMPLE_PERIOD if attr->freq is set.

 - Remove trailing commas from AMD JSON vendor event files.

 - Don't clear event's period if set by a event definition term.

 - Leader sampling shouldn't clear sample period in 'perf test'.

 - Fix the "signal" test inline assembly when built with DEBUG=1.

 - Fix memory leaks detected by ASAN, some in normal paths, some in
   error paths.

 - Fix 2 memory sanitizer warnings in 'perf bench'.

 - Fix the ratio comments of miss-events in 'perf stat'.

 - Prevent override of attr->sample_period for libpfm4 events.

 - Sync kvm.h and in.h headers with the kernel sources.

* tag 'perf-tools-fixes-for-v5.9-2020-09-16' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux:
  perf stat: Fix the ratio comments of miss-events
  perf test: Free formats for perf pmu parse test
  perf metric: Do not free metric when failed to resolve
  perf metric: Free metric when it failed to resolve
  perf metric: Release expr_parse_ctx after testing
  perf test: Fix memory leaks in parse-metric test
  perf parse-event: Fix memory leak in evsel->unit
  perf evlist: Fix cpu/thread map leak
  perf metric: Fix some memory leaks - part 2
  perf metric: Fix some memory leaks
  perf test: Free aliases for PMU event map aliases test
  perf vendor events amd: Remove trailing commas
  perf test: Leader sampling shouldn't clear sample period
  perf record: Don't clear event's period if set by a term
  tools headers UAPI: update linux/in.h copy
  tools headers UAPI: Sync kvm.h headers with the kernel sources
  perf record: Prevent override of attr->sample_period for libpfm4 events
  perf record: Set PERF_RECORD_PERIOD if attr->freq is set.
  perf bench: Fix 2 memory sanitizer warnings
  perf test: Fix the "signal" test inline assembly
parents 05da40eb ce9c13f3
...@@ -135,7 +135,7 @@ struct in_addr { ...@@ -135,7 +135,7 @@ struct in_addr {
* this socket to prevent accepting spoofed ones. * this socket to prevent accepting spoofed ones.
*/ */
#define IP_PMTUDISC_INTERFACE 4 #define IP_PMTUDISC_INTERFACE 4
/* weaker version of IP_PMTUDISC_INTERFACE, which allos packets to get /* weaker version of IP_PMTUDISC_INTERFACE, which allows packets to get
* fragmented if they exeed the interface mtu * fragmented if they exeed the interface mtu
*/ */
#define IP_PMTUDISC_OMIT 5 #define IP_PMTUDISC_OMIT 5
......
...@@ -790,9 +790,10 @@ struct kvm_ppc_resize_hpt { ...@@ -790,9 +790,10 @@ struct kvm_ppc_resize_hpt {
#define KVM_VM_PPC_HV 1 #define KVM_VM_PPC_HV 1
#define KVM_VM_PPC_PR 2 #define KVM_VM_PPC_PR 2
/* on MIPS, 0 forces trap & emulate, 1 forces VZ ASE */ /* on MIPS, 0 indicates auto, 1 forces VZ ASE, 2 forces trap & emulate */
#define KVM_VM_MIPS_TE 0 #define KVM_VM_MIPS_AUTO 0
#define KVM_VM_MIPS_VZ 1 #define KVM_VM_MIPS_VZ 1
#define KVM_VM_MIPS_TE 2
#define KVM_S390_SIE_PAGE_OFFSET 1 #define KVM_S390_SIE_PAGE_OFFSET 1
...@@ -1035,6 +1036,7 @@ struct kvm_ppc_resize_hpt { ...@@ -1035,6 +1036,7 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_LAST_CPU 184 #define KVM_CAP_LAST_CPU 184
#define KVM_CAP_SMALLER_MAXPHYADDR 185 #define KVM_CAP_SMALLER_MAXPHYADDR 185
#define KVM_CAP_S390_DIAG318 186 #define KVM_CAP_S390_DIAG318 186
#define KVM_CAP_STEAL_TIME 187
#ifdef KVM_CAP_IRQ_ROUTING #ifdef KVM_CAP_IRQ_ROUTING
......
...@@ -66,11 +66,10 @@ static void fdpair(int fds[2]) ...@@ -66,11 +66,10 @@ static void fdpair(int fds[2])
/* Block until we're ready to go */ /* Block until we're ready to go */
static void ready(int ready_out, int wakefd) static void ready(int ready_out, int wakefd)
{ {
char dummy;
struct pollfd pollfd = { .fd = wakefd, .events = POLLIN }; struct pollfd pollfd = { .fd = wakefd, .events = POLLIN };
/* Tell them we're ready. */ /* Tell them we're ready. */
if (write(ready_out, &dummy, 1) != 1) if (write(ready_out, "R", 1) != 1)
err(EXIT_FAILURE, "CLIENT: ready write"); err(EXIT_FAILURE, "CLIENT: ready write");
/* Wait for "GO" signal */ /* Wait for "GO" signal */
...@@ -85,6 +84,7 @@ static void *sender(struct sender_context *ctx) ...@@ -85,6 +84,7 @@ static void *sender(struct sender_context *ctx)
unsigned int i, j; unsigned int i, j;
ready(ctx->ready_out, ctx->wakefd); ready(ctx->ready_out, ctx->wakefd);
memset(data, 'S', sizeof(data));
/* Now pump to every receiver. */ /* Now pump to every receiver. */
for (i = 0; i < nr_loops; i++) { for (i = 0; i < nr_loops; i++) {
......
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
{ {
"EventName": "ex_ret_brn_ind_misp", "EventName": "ex_ret_brn_ind_misp",
"EventCode": "0xca", "EventCode": "0xca",
"BriefDescription": "Retired Indirect Branch Instructions Mispredicted.", "BriefDescription": "Retired Indirect Branch Instructions Mispredicted."
}, },
{ {
"EventName": "ex_ret_mmx_fp_instr.sse_instr", "EventName": "ex_ret_mmx_fp_instr.sse_instr",
......
...@@ -125,6 +125,6 @@ ...@@ -125,6 +125,6 @@
{ {
"EventName": "ex_ret_fus_brnch_inst", "EventName": "ex_ret_fus_brnch_inst",
"EventCode": "0x1d0", "EventCode": "0x1d0",
"BriefDescription": "Retired Fused Instructions. The number of fuse-branch instructions retired per cycle. The number of events logged per cycle can vary from 0-8.", "BriefDescription": "Retired Fused Instructions. The number of fuse-branch instructions retired per cycle. The number of events logged per cycle can vary from 0-8."
} }
] ]
...@@ -49,6 +49,7 @@ Following tests are defined (with perf commands): ...@@ -49,6 +49,7 @@ Following tests are defined (with perf commands):
perf record --call-graph fp kill (test-record-graph-fp) perf record --call-graph fp kill (test-record-graph-fp)
perf record --group -e cycles,instructions kill (test-record-group) perf record --group -e cycles,instructions kill (test-record-group)
perf record -e '{cycles,instructions}' kill (test-record-group1) perf record -e '{cycles,instructions}' kill (test-record-group1)
perf record -e '{cycles/period=1/,instructions/period=2/}:S' kill (test-record-group2)
perf record -D kill (test-record-no-delay) perf record -D kill (test-record-no-delay)
perf record -i kill (test-record-no-inherit) perf record -i kill (test-record-no-inherit)
perf record -n kill (test-record-no-samples) perf record -n kill (test-record-no-samples)
......
[config]
command = record
args = --no-bpf-event -e '{cycles/period=1234000/,instructions/period=6789000/}:S' kill >/dev/null 2>&1
ret = 1
[event-1:base-record]
fd=1
group_fd=-1
config=0|1
sample_period=1234000
sample_type=87
read_format=12
inherit=0
freq=0
[event-2:base-record]
fd=2
group_fd=1
config=0|1
sample_period=6789000
sample_type=87
read_format=12
disabled=0
inherit=0
mmap=0
comm=0
freq=0
enable_on_exec=0
task=0
...@@ -45,10 +45,13 @@ volatile long the_var; ...@@ -45,10 +45,13 @@ volatile long the_var;
#if defined (__x86_64__) #if defined (__x86_64__)
extern void __test_function(volatile long *ptr); extern void __test_function(volatile long *ptr);
asm ( asm (
".pushsection .text;"
".globl __test_function\n" ".globl __test_function\n"
".type __test_function, @function;"
"__test_function:\n" "__test_function:\n"
"incq (%rdi)\n" "incq (%rdi)\n"
"ret\n"); "ret\n"
".popsection\n");
#else #else
static void __test_function(volatile long *ptr) static void __test_function(volatile long *ptr)
{ {
......
...@@ -153,8 +153,10 @@ static int __compute_metric(const char *name, struct value *vals, ...@@ -153,8 +153,10 @@ static int __compute_metric(const char *name, struct value *vals,
return -ENOMEM; return -ENOMEM;
cpus = perf_cpu_map__new("0"); cpus = perf_cpu_map__new("0");
if (!cpus) if (!cpus) {
evlist__delete(evlist);
return -ENOMEM; return -ENOMEM;
}
perf_evlist__set_maps(&evlist->core, cpus, NULL); perf_evlist__set_maps(&evlist->core, cpus, NULL);
...@@ -163,10 +165,11 @@ static int __compute_metric(const char *name, struct value *vals, ...@@ -163,10 +165,11 @@ static int __compute_metric(const char *name, struct value *vals,
false, false, false, false,
&metric_events); &metric_events);
if (err) if (err)
return err; goto out;
if (perf_evlist__alloc_stats(evlist, false)) err = perf_evlist__alloc_stats(evlist, false);
return -1; if (err)
goto out;
/* Load the runtime stats with given numbers for events. */ /* Load the runtime stats with given numbers for events. */
runtime_stat__init(&st); runtime_stat__init(&st);
...@@ -178,13 +181,14 @@ static int __compute_metric(const char *name, struct value *vals, ...@@ -178,13 +181,14 @@ static int __compute_metric(const char *name, struct value *vals,
if (name2 && ratio2) if (name2 && ratio2)
*ratio2 = compute_single(&metric_events, evlist, &st, name2); *ratio2 = compute_single(&metric_events, evlist, &st, name2);
out:
/* ... clenup. */ /* ... clenup. */
metricgroup__rblist_exit(&metric_events); metricgroup__rblist_exit(&metric_events);
runtime_stat__exit(&st); runtime_stat__exit(&st);
perf_evlist__free_stats(evlist); perf_evlist__free_stats(evlist);
perf_cpu_map__put(cpus); perf_cpu_map__put(cpus);
evlist__delete(evlist); evlist__delete(evlist);
return 0; return err;
} }
static int compute_metric(const char *name, struct value *vals, double *ratio) static int compute_metric(const char *name, struct value *vals, double *ratio)
......
...@@ -274,6 +274,7 @@ static int __test__pmu_event_aliases(char *pmu_name, int *count) ...@@ -274,6 +274,7 @@ static int __test__pmu_event_aliases(char *pmu_name, int *count)
int res = 0; int res = 0;
bool use_uncore_table; bool use_uncore_table;
struct pmu_events_map *map = __test_pmu_get_events_map(); struct pmu_events_map *map = __test_pmu_get_events_map();
struct perf_pmu_alias *a, *tmp;
if (!map) if (!map)
return -1; return -1;
...@@ -347,6 +348,10 @@ static int __test__pmu_event_aliases(char *pmu_name, int *count) ...@@ -347,6 +348,10 @@ static int __test__pmu_event_aliases(char *pmu_name, int *count)
pmu_name, alias->name); pmu_name, alias->name);
} }
list_for_each_entry_safe(a, tmp, &aliases, list) {
list_del(&a->list);
perf_pmu_free_alias(a);
}
free(pmu); free(pmu);
return res; return res;
} }
......
...@@ -173,6 +173,7 @@ int test__pmu(struct test *test __maybe_unused, int subtest __maybe_unused) ...@@ -173,6 +173,7 @@ int test__pmu(struct test *test __maybe_unused, int subtest __maybe_unused)
ret = 0; ret = 0;
} while (0); } while (0);
perf_pmu__del_formats(&formats);
test_format_dir_put(format); test_format_dir_put(format);
return ret; return ret;
} }
...@@ -946,6 +946,10 @@ int perf_evlist__create_maps(struct evlist *evlist, struct target *target) ...@@ -946,6 +946,10 @@ int perf_evlist__create_maps(struct evlist *evlist, struct target *target)
perf_evlist__set_maps(&evlist->core, cpus, threads); perf_evlist__set_maps(&evlist->core, cpus, threads);
/* as evlist now has references, put count here */
perf_cpu_map__put(cpus);
perf_thread_map__put(threads);
return 0; return 0;
out_delete_threads: out_delete_threads:
...@@ -1273,11 +1277,12 @@ static int perf_evlist__create_syswide_maps(struct evlist *evlist) ...@@ -1273,11 +1277,12 @@ static int perf_evlist__create_syswide_maps(struct evlist *evlist)
goto out_put; goto out_put;
perf_evlist__set_maps(&evlist->core, cpus, threads); perf_evlist__set_maps(&evlist->core, cpus, threads);
out:
return err; perf_thread_map__put(threads);
out_put: out_put:
perf_cpu_map__put(cpus); perf_cpu_map__put(cpus);
goto out; out:
return err;
} }
int evlist__open(struct evlist *evlist) int evlist__open(struct evlist *evlist)
......
...@@ -976,16 +976,20 @@ void evsel__config(struct evsel *evsel, struct record_opts *opts, ...@@ -976,16 +976,20 @@ void evsel__config(struct evsel *evsel, struct record_opts *opts,
* We default some events to have a default interval. But keep * We default some events to have a default interval. But keep
* it a weak assumption overridable by the user. * it a weak assumption overridable by the user.
*/ */
if (!attr->sample_period || (opts->user_freq != UINT_MAX || if (!attr->sample_period) {
opts->user_interval != ULLONG_MAX)) {
if (opts->freq) { if (opts->freq) {
evsel__set_sample_bit(evsel, PERIOD);
attr->freq = 1; attr->freq = 1;
attr->sample_freq = opts->freq; attr->sample_freq = opts->freq;
} else { } else {
attr->sample_period = opts->default_interval; attr->sample_period = opts->default_interval;
} }
} }
/*
* If attr->freq was set (here or earlier), ask for period
* to be sampled.
*/
if (attr->freq)
evsel__set_sample_bit(evsel, PERIOD);
if (opts->no_samples) if (opts->no_samples)
attr->sample_freq = 0; attr->sample_freq = 0;
......
...@@ -85,6 +85,7 @@ static void metric_event_delete(struct rblist *rblist __maybe_unused, ...@@ -85,6 +85,7 @@ static void metric_event_delete(struct rblist *rblist __maybe_unused,
list_for_each_entry_safe(expr, tmp, &me->head, nd) { list_for_each_entry_safe(expr, tmp, &me->head, nd) {
free(expr->metric_refs); free(expr->metric_refs);
free(expr->metric_events);
free(expr); free(expr);
} }
...@@ -316,6 +317,7 @@ static int metricgroup__setup_events(struct list_head *groups, ...@@ -316,6 +317,7 @@ static int metricgroup__setup_events(struct list_head *groups,
if (!metric_refs) { if (!metric_refs) {
ret = -ENOMEM; ret = -ENOMEM;
free(metric_events); free(metric_events);
free(expr);
break; break;
} }
...@@ -530,6 +532,9 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter, ...@@ -530,6 +532,9 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter,
continue; continue;
strlist__add(me->metrics, s); strlist__add(me->metrics, s);
} }
if (!raw)
free(s);
} }
free(omg); free(omg);
} }
...@@ -667,7 +672,6 @@ static int __add_metric(struct list_head *metric_list, ...@@ -667,7 +672,6 @@ static int __add_metric(struct list_head *metric_list,
m->has_constraint = metric_no_group || metricgroup__has_constraint(pe); m->has_constraint = metric_no_group || metricgroup__has_constraint(pe);
INIT_LIST_HEAD(&m->metric_refs); INIT_LIST_HEAD(&m->metric_refs);
m->metric_refs_cnt = 0; m->metric_refs_cnt = 0;
*mp = m;
parent = expr_ids__alloc(ids); parent = expr_ids__alloc(ids);
if (!parent) { if (!parent) {
...@@ -680,6 +684,7 @@ static int __add_metric(struct list_head *metric_list, ...@@ -680,6 +684,7 @@ static int __add_metric(struct list_head *metric_list,
free(m); free(m);
return -ENOMEM; return -ENOMEM;
} }
*mp = m;
} else { } else {
/* /*
* We got here for the referenced metric, via the * We got here for the referenced metric, via the
...@@ -714,8 +719,11 @@ static int __add_metric(struct list_head *metric_list, ...@@ -714,8 +719,11 @@ static int __add_metric(struct list_head *metric_list,
* all the metric's IDs and add it to the parent context. * all the metric's IDs and add it to the parent context.
*/ */
if (expr__find_other(pe->metric_expr, NULL, &m->pctx, runtime) < 0) { if (expr__find_other(pe->metric_expr, NULL, &m->pctx, runtime) < 0) {
expr__ctx_clear(&m->pctx); if (m->metric_refs_cnt == 0) {
free(m); expr__ctx_clear(&m->pctx);
free(m);
*mp = NULL;
}
return -EINVAL; return -EINVAL;
} }
...@@ -934,7 +942,7 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, ...@@ -934,7 +942,7 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group,
ret = add_metric(&list, pe, metric_no_group, &m, NULL, &ids); ret = add_metric(&list, pe, metric_no_group, &m, NULL, &ids);
if (ret) if (ret)
return ret; goto out;
/* /*
* Process any possible referenced metrics * Process any possible referenced metrics
...@@ -943,12 +951,14 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, ...@@ -943,12 +951,14 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group,
ret = resolve_metric(metric_no_group, ret = resolve_metric(metric_no_group,
&list, map, &ids); &list, map, &ids);
if (ret) if (ret)
return ret; goto out;
} }
/* End of pmu events. */ /* End of pmu events. */
if (!has_match) if (!has_match) {
return -EINVAL; ret = -EINVAL;
goto out;
}
list_for_each_entry(m, &list, nd) { list_for_each_entry(m, &list, nd) {
if (events->len > 0) if (events->len > 0)
...@@ -963,9 +973,14 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group, ...@@ -963,9 +973,14 @@ static int metricgroup__add_metric(const char *metric, bool metric_no_group,
} }
} }
out:
/*
* add to metric_list so that they can be released
* even if it's failed
*/
list_splice(&list, metric_list); list_splice(&list, metric_list);
expr_ids__exit(&ids); expr_ids__exit(&ids);
return 0; return ret;
} }
static int metricgroup__add_metric_list(const char *list, bool metric_no_group, static int metricgroup__add_metric_list(const char *list, bool metric_no_group,
...@@ -1040,7 +1055,7 @@ static int parse_groups(struct evlist *perf_evlist, const char *str, ...@@ -1040,7 +1055,7 @@ static int parse_groups(struct evlist *perf_evlist, const char *str,
ret = metricgroup__add_metric_list(str, metric_no_group, ret = metricgroup__add_metric_list(str, metric_no_group,
&extra_events, &metric_list, map); &extra_events, &metric_list, map);
if (ret) if (ret)
return ret; goto out;
pr_debug("adding %s\n", extra_events.buf); pr_debug("adding %s\n", extra_events.buf);
bzero(&parse_error, sizeof(parse_error)); bzero(&parse_error, sizeof(parse_error));
ret = __parse_events(perf_evlist, extra_events.buf, &parse_error, fake_pmu); ret = __parse_events(perf_evlist, extra_events.buf, &parse_error, fake_pmu);
...@@ -1048,11 +1063,11 @@ static int parse_groups(struct evlist *perf_evlist, const char *str, ...@@ -1048,11 +1063,11 @@ static int parse_groups(struct evlist *perf_evlist, const char *str,
parse_events_print_error(&parse_error, extra_events.buf); parse_events_print_error(&parse_error, extra_events.buf);
goto out; goto out;
} }
strbuf_release(&extra_events);
ret = metricgroup__setup_events(&metric_list, metric_no_merge, ret = metricgroup__setup_events(&metric_list, metric_no_merge,
perf_evlist, metric_events); perf_evlist, metric_events);
out: out:
metricgroup__free_metrics(&metric_list); metricgroup__free_metrics(&metric_list);
strbuf_release(&extra_events);
return ret; return ret;
} }
......
...@@ -411,7 +411,7 @@ static int add_event_tool(struct list_head *list, int *idx, ...@@ -411,7 +411,7 @@ static int add_event_tool(struct list_head *list, int *idx,
return -ENOMEM; return -ENOMEM;
evsel->tool_event = tool_event; evsel->tool_event = tool_event;
if (tool_event == PERF_TOOL_DURATION_TIME) if (tool_event == PERF_TOOL_DURATION_TIME)
evsel->unit = strdup("ns"); evsel->unit = "ns";
return 0; return 0;
} }
......
...@@ -274,7 +274,7 @@ static void perf_pmu_update_alias(struct perf_pmu_alias *old, ...@@ -274,7 +274,7 @@ static void perf_pmu_update_alias(struct perf_pmu_alias *old,
} }
/* Delete an alias entry. */ /* Delete an alias entry. */
static void perf_pmu_free_alias(struct perf_pmu_alias *newalias) void perf_pmu_free_alias(struct perf_pmu_alias *newalias)
{ {
zfree(&newalias->name); zfree(&newalias->name);
zfree(&newalias->desc); zfree(&newalias->desc);
...@@ -1354,6 +1354,17 @@ void perf_pmu__set_format(unsigned long *bits, long from, long to) ...@@ -1354,6 +1354,17 @@ void perf_pmu__set_format(unsigned long *bits, long from, long to)
set_bit(b, bits); set_bit(b, bits);
} }
void perf_pmu__del_formats(struct list_head *formats)
{
struct perf_pmu_format *fmt, *tmp;
list_for_each_entry_safe(fmt, tmp, formats, list) {
list_del(&fmt->list);
free(fmt->name);
free(fmt);
}
}
static int sub_non_neg(int a, int b) static int sub_non_neg(int a, int b)
{ {
if (b > a) if (b > a)
......
...@@ -94,6 +94,7 @@ int perf_pmu__new_format(struct list_head *list, char *name, ...@@ -94,6 +94,7 @@ int perf_pmu__new_format(struct list_head *list, char *name,
int config, unsigned long *bits); int config, unsigned long *bits);
void perf_pmu__set_format(unsigned long *bits, long from, long to); void perf_pmu__set_format(unsigned long *bits, long from, long to);
int perf_pmu__format_parse(char *dir, struct list_head *head); int perf_pmu__format_parse(char *dir, struct list_head *head);
void perf_pmu__del_formats(struct list_head *formats);
struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu); struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
...@@ -113,6 +114,7 @@ void pmu_add_cpu_aliases_map(struct list_head *head, struct perf_pmu *pmu, ...@@ -113,6 +114,7 @@ void pmu_add_cpu_aliases_map(struct list_head *head, struct perf_pmu *pmu,
struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu); struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu);
bool pmu_uncore_alias_match(const char *pmu_name, const char *name); bool pmu_uncore_alias_match(const char *pmu_name, const char *name);
void perf_pmu_free_alias(struct perf_pmu_alias *alias);
int perf_pmu__convert_scale(const char *scale, char **end, double *sval); int perf_pmu__convert_scale(const char *scale, char **end, double *sval);
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#include "debug.h" #include "debug.h"
#include "evlist.h" #include "evlist.h"
#include "evsel.h" #include "evsel.h"
#include "evsel_config.h"
#include "parse-events.h" #include "parse-events.h"
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
...@@ -33,11 +34,24 @@ static struct evsel *evsel__read_sampler(struct evsel *evsel, struct evlist *evl ...@@ -33,11 +34,24 @@ static struct evsel *evsel__read_sampler(struct evsel *evsel, struct evlist *evl
return leader; return leader;
} }
static u64 evsel__config_term_mask(struct evsel *evsel)
{
struct evsel_config_term *term;
struct list_head *config_terms = &evsel->config_terms;
u64 term_types = 0;
list_for_each_entry(term, config_terms, list) {
term_types |= 1 << term->type;
}
return term_types;
}
static void evsel__config_leader_sampling(struct evsel *evsel, struct evlist *evlist) static void evsel__config_leader_sampling(struct evsel *evsel, struct evlist *evlist)
{ {
struct perf_event_attr *attr = &evsel->core.attr; struct perf_event_attr *attr = &evsel->core.attr;
struct evsel *leader = evsel->leader; struct evsel *leader = evsel->leader;
struct evsel *read_sampler; struct evsel *read_sampler;
u64 term_types, freq_mask;
if (!leader->sample_read) if (!leader->sample_read)
return; return;
...@@ -47,16 +61,20 @@ static void evsel__config_leader_sampling(struct evsel *evsel, struct evlist *ev ...@@ -47,16 +61,20 @@ static void evsel__config_leader_sampling(struct evsel *evsel, struct evlist *ev
if (evsel == read_sampler) if (evsel == read_sampler)
return; return;
term_types = evsel__config_term_mask(evsel);
/* /*
* Disable sampling for all group members other than the leader in * Disable sampling for all group members except those with explicit
* case the leader 'leads' the sampling, except when the leader is an * config terms or the leader. In the case of an AUX area event, the 2nd
* AUX area event, in which case the 2nd event in the group is the one * event in the group is the one that 'leads' the sampling.
* that 'leads' the sampling.
*/ */
attr->freq = 0; freq_mask = (1 << EVSEL__CONFIG_TERM_FREQ) | (1 << EVSEL__CONFIG_TERM_PERIOD);
attr->sample_freq = 0; if ((term_types & freq_mask) == 0) {
attr->sample_period = 0; attr->freq = 0;
attr->write_backward = 0; attr->sample_freq = 0;
attr->sample_period = 0;
}
if ((term_types & (1 << EVSEL__CONFIG_TERM_OVERWRITE)) == 0)
attr->write_backward = 0;
/* /*
* We don't get a sample for slave events, we make them when delivering * We don't get a sample for slave events, we make them when delivering
......
...@@ -517,7 +517,7 @@ static void print_l1_dcache_misses(struct perf_stat_config *config, ...@@ -517,7 +517,7 @@ static void print_l1_dcache_misses(struct perf_stat_config *config,
color = get_ratio_color(GRC_CACHE_MISSES, ratio); color = get_ratio_color(GRC_CACHE_MISSES, ratio);
out->print_metric(config, out->ctx, color, "%7.2f%%", "of all L1-dcache hits", ratio); out->print_metric(config, out->ctx, color, "%7.2f%%", "of all L1-dcache accesses", ratio);
} }
static void print_l1_icache_misses(struct perf_stat_config *config, static void print_l1_icache_misses(struct perf_stat_config *config,
...@@ -538,7 +538,7 @@ static void print_l1_icache_misses(struct perf_stat_config *config, ...@@ -538,7 +538,7 @@ static void print_l1_icache_misses(struct perf_stat_config *config,
ratio = avg / total * 100.0; ratio = avg / total * 100.0;
color = get_ratio_color(GRC_CACHE_MISSES, ratio); color = get_ratio_color(GRC_CACHE_MISSES, ratio);
out->print_metric(config, out->ctx, color, "%7.2f%%", "of all L1-icache hits", ratio); out->print_metric(config, out->ctx, color, "%7.2f%%", "of all L1-icache accesses", ratio);
} }
static void print_dtlb_cache_misses(struct perf_stat_config *config, static void print_dtlb_cache_misses(struct perf_stat_config *config,
...@@ -558,7 +558,7 @@ static void print_dtlb_cache_misses(struct perf_stat_config *config, ...@@ -558,7 +558,7 @@ static void print_dtlb_cache_misses(struct perf_stat_config *config,
ratio = avg / total * 100.0; ratio = avg / total * 100.0;
color = get_ratio_color(GRC_CACHE_MISSES, ratio); color = get_ratio_color(GRC_CACHE_MISSES, ratio);
out->print_metric(config, out->ctx, color, "%7.2f%%", "of all dTLB cache hits", ratio); out->print_metric(config, out->ctx, color, "%7.2f%%", "of all dTLB cache accesses", ratio);
} }
static void print_itlb_cache_misses(struct perf_stat_config *config, static void print_itlb_cache_misses(struct perf_stat_config *config,
...@@ -578,7 +578,7 @@ static void print_itlb_cache_misses(struct perf_stat_config *config, ...@@ -578,7 +578,7 @@ static void print_itlb_cache_misses(struct perf_stat_config *config,
ratio = avg / total * 100.0; ratio = avg / total * 100.0;
color = get_ratio_color(GRC_CACHE_MISSES, ratio); color = get_ratio_color(GRC_CACHE_MISSES, ratio);
out->print_metric(config, out->ctx, color, "%7.2f%%", "of all iTLB cache hits", ratio); out->print_metric(config, out->ctx, color, "%7.2f%%", "of all iTLB cache accesses", ratio);
} }
static void print_ll_cache_misses(struct perf_stat_config *config, static void print_ll_cache_misses(struct perf_stat_config *config,
...@@ -598,7 +598,7 @@ static void print_ll_cache_misses(struct perf_stat_config *config, ...@@ -598,7 +598,7 @@ static void print_ll_cache_misses(struct perf_stat_config *config,
ratio = avg / total * 100.0; ratio = avg / total * 100.0;
color = get_ratio_color(GRC_CACHE_MISSES, ratio); color = get_ratio_color(GRC_CACHE_MISSES, ratio);
out->print_metric(config, out->ctx, color, "%7.2f%%", "of all LL-cache hits", ratio); out->print_metric(config, out->ctx, color, "%7.2f%%", "of all LL-cache accesses", ratio);
} }
/* /*
...@@ -853,14 +853,16 @@ static void generic_metric(struct perf_stat_config *config, ...@@ -853,14 +853,16 @@ static void generic_metric(struct perf_stat_config *config,
double test_generic_metric(struct metric_expr *mexp, int cpu, struct runtime_stat *st) double test_generic_metric(struct metric_expr *mexp, int cpu, struct runtime_stat *st)
{ {
struct expr_parse_ctx pctx; struct expr_parse_ctx pctx;
double ratio; double ratio = 0.0;
if (prepare_metric(mexp->metric_events, mexp->metric_refs, &pctx, cpu, st) < 0) if (prepare_metric(mexp->metric_events, mexp->metric_refs, &pctx, cpu, st) < 0)
return 0.; goto out;
if (expr__parse(&ratio, &pctx, mexp->metric_expr, 1)) if (expr__parse(&ratio, &pctx, mexp->metric_expr, 1))
return 0.; ratio = 0.0;
out:
expr__ctx_clear(&pctx);
return ratio; return ratio;
} }
...@@ -918,7 +920,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config, ...@@ -918,7 +920,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
if (runtime_stat_n(st, STAT_L1_DCACHE, ctx, cpu) != 0) if (runtime_stat_n(st, STAT_L1_DCACHE, ctx, cpu) != 0)
print_l1_dcache_misses(config, cpu, evsel, avg, out, st); print_l1_dcache_misses(config, cpu, evsel, avg, out, st);
else else
print_metric(config, ctxp, NULL, NULL, "of all L1-dcache hits", 0); print_metric(config, ctxp, NULL, NULL, "of all L1-dcache accesses", 0);
} else if ( } else if (
evsel->core.attr.type == PERF_TYPE_HW_CACHE && evsel->core.attr.type == PERF_TYPE_HW_CACHE &&
evsel->core.attr.config == ( PERF_COUNT_HW_CACHE_L1I | evsel->core.attr.config == ( PERF_COUNT_HW_CACHE_L1I |
...@@ -928,7 +930,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config, ...@@ -928,7 +930,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
if (runtime_stat_n(st, STAT_L1_ICACHE, ctx, cpu) != 0) if (runtime_stat_n(st, STAT_L1_ICACHE, ctx, cpu) != 0)
print_l1_icache_misses(config, cpu, evsel, avg, out, st); print_l1_icache_misses(config, cpu, evsel, avg, out, st);
else else
print_metric(config, ctxp, NULL, NULL, "of all L1-icache hits", 0); print_metric(config, ctxp, NULL, NULL, "of all L1-icache accesses", 0);
} else if ( } else if (
evsel->core.attr.type == PERF_TYPE_HW_CACHE && evsel->core.attr.type == PERF_TYPE_HW_CACHE &&
evsel->core.attr.config == ( PERF_COUNT_HW_CACHE_DTLB | evsel->core.attr.config == ( PERF_COUNT_HW_CACHE_DTLB |
...@@ -938,7 +940,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config, ...@@ -938,7 +940,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
if (runtime_stat_n(st, STAT_DTLB_CACHE, ctx, cpu) != 0) if (runtime_stat_n(st, STAT_DTLB_CACHE, ctx, cpu) != 0)
print_dtlb_cache_misses(config, cpu, evsel, avg, out, st); print_dtlb_cache_misses(config, cpu, evsel, avg, out, st);
else else
print_metric(config, ctxp, NULL, NULL, "of all dTLB cache hits", 0); print_metric(config, ctxp, NULL, NULL, "of all dTLB cache accesses", 0);
} else if ( } else if (
evsel->core.attr.type == PERF_TYPE_HW_CACHE && evsel->core.attr.type == PERF_TYPE_HW_CACHE &&
evsel->core.attr.config == ( PERF_COUNT_HW_CACHE_ITLB | evsel->core.attr.config == ( PERF_COUNT_HW_CACHE_ITLB |
...@@ -948,7 +950,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config, ...@@ -948,7 +950,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
if (runtime_stat_n(st, STAT_ITLB_CACHE, ctx, cpu) != 0) if (runtime_stat_n(st, STAT_ITLB_CACHE, ctx, cpu) != 0)
print_itlb_cache_misses(config, cpu, evsel, avg, out, st); print_itlb_cache_misses(config, cpu, evsel, avg, out, st);
else else
print_metric(config, ctxp, NULL, NULL, "of all iTLB cache hits", 0); print_metric(config, ctxp, NULL, NULL, "of all iTLB cache accesses", 0);
} else if ( } else if (
evsel->core.attr.type == PERF_TYPE_HW_CACHE && evsel->core.attr.type == PERF_TYPE_HW_CACHE &&
evsel->core.attr.config == ( PERF_COUNT_HW_CACHE_LL | evsel->core.attr.config == ( PERF_COUNT_HW_CACHE_LL |
...@@ -958,7 +960,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config, ...@@ -958,7 +960,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
if (runtime_stat_n(st, STAT_LL_CACHE, ctx, cpu) != 0) if (runtime_stat_n(st, STAT_LL_CACHE, ctx, cpu) != 0)
print_ll_cache_misses(config, cpu, evsel, avg, out, st); print_ll_cache_misses(config, cpu, evsel, avg, out, st);
else else
print_metric(config, ctxp, NULL, NULL, "of all LL-cache hits", 0); print_metric(config, ctxp, NULL, NULL, "of all LL-cache accesses", 0);
} else if (evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)) { } else if (evsel__match(evsel, HARDWARE, HW_CACHE_MISSES)) {
total = runtime_stat_avg(st, STAT_CACHEREFS, ctx, cpu); total = runtime_stat_avg(st, STAT_CACHEREFS, ctx, cpu);
......
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