Commit 8b98436a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'perf-tools-fixes-for-v5.16-2021-11-19' of...

Merge tag 'perf-tools-fixes-for-v5.16-2021-11-19' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux

Pull perf tools fixes from Arnaldo Carvalho de Melo:

 - Fix the 'local_weight', 'weight' (memory access latency),
   'local_ins_lat', 'ins_lat' (instruction latency) and 'pstage_cyc'
   (pipeline stage cycles) sort key sample aggregation.

 - Fix 'perf test' entry for watchpoints on s/390.

 - Fix branch_stack entry endianness check in the 'perf test' sample
   parsing test.

 - Fix ARM SPE handling on 'perf inject'.

 - Fix memory leaks detected with ASan.

 - Fix build on arm64 related to reallocarray() availability.

 - Sync copies of kernel headers: cpufeatures, kvm, MIPS syscalltable
   (futex_waitv).

* tag 'perf-tools-fixes-for-v5.16-2021-11-19' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux:
  perf evsel: Fix memory leaks relating to unit
  perf report: Fix memory leaks around perf_tip()
  perf hist: Fix memory leak of a perf_hpp_fmt
  tools headers UAPI: Sync MIPS syscall table file changed by new futex_waitv syscall
  tools build: Fix removal of feature-sync-compare-and-swap feature detection
  perf inject: Fix ARM SPE handling
  perf bench: Fix two memory leaks detected with ASan
  perf test sample-parsing: Fix branch_stack entry endianness check
  tools headers UAPI: Sync x86's asm/kvm.h with the kernel sources
  perf sort: Fix the 'p_stage_cyc' sort key behavior
  perf sort: Fix the 'ins_lat' sort key behavior
  perf sort: Fix the 'weight' sort key behavior
  perf tools: Set COMPAT_NEED_REALLOCARRAY for CONFIG_AUXTRACE=1
  perf tests wp: Remove unused functions on s390
  tools headers UAPI: Sync linux/kvm.h with the kernel sources
  tools headers cpufeatures: Sync with the kernel sources
parents 9539ba43 b194c9cd
...@@ -277,6 +277,7 @@ ...@@ -277,6 +277,7 @@
#define X86_FEATURE_XSAVEC (10*32+ 1) /* XSAVEC instruction */ #define X86_FEATURE_XSAVEC (10*32+ 1) /* XSAVEC instruction */
#define X86_FEATURE_XGETBV1 (10*32+ 2) /* XGETBV with ECX = 1 instruction */ #define X86_FEATURE_XGETBV1 (10*32+ 2) /* XGETBV with ECX = 1 instruction */
#define X86_FEATURE_XSAVES (10*32+ 3) /* XSAVES/XRSTORS instructions */ #define X86_FEATURE_XSAVES (10*32+ 3) /* XSAVES/XRSTORS instructions */
#define X86_FEATURE_XFD (10*32+ 4) /* "" eXtended Feature Disabling */
/* /*
* Extended auxiliary flags: Linux defined - for features scattered in various * Extended auxiliary flags: Linux defined - for features scattered in various
...@@ -298,6 +299,7 @@ ...@@ -298,6 +299,7 @@
/* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */ /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */
#define X86_FEATURE_AVX_VNNI (12*32+ 4) /* AVX VNNI instructions */ #define X86_FEATURE_AVX_VNNI (12*32+ 4) /* AVX VNNI instructions */
#define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* AVX512 BFLOAT16 instructions */ #define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* AVX512 BFLOAT16 instructions */
#define X86_FEATURE_AMX_TILE (18*32+24) /* AMX tile Support */
/* AMD-defined CPU features, CPUID level 0x80000008 (EBX), word 13 */ /* AMD-defined CPU features, CPUID level 0x80000008 (EBX), word 13 */
#define X86_FEATURE_CLZERO (13*32+ 0) /* CLZERO instruction */ #define X86_FEATURE_CLZERO (13*32+ 0) /* CLZERO instruction */
......
...@@ -504,4 +504,8 @@ struct kvm_pmu_event_filter { ...@@ -504,4 +504,8 @@ struct kvm_pmu_event_filter {
#define KVM_PMU_EVENT_ALLOW 0 #define KVM_PMU_EVENT_ALLOW 0
#define KVM_PMU_EVENT_DENY 1 #define KVM_PMU_EVENT_DENY 1
/* for KVM_{GET,SET,HAS}_DEVICE_ATTR */
#define KVM_VCPU_TSC_CTRL 0 /* control group for the timestamp counter (TSC) */
#define KVM_VCPU_TSC_OFFSET 0 /* attribute for the TSC offset */
#endif /* _ASM_X86_KVM_H */ #endif /* _ASM_X86_KVM_H */
...@@ -200,7 +200,6 @@ int main(int argc, char *argv[]) ...@@ -200,7 +200,6 @@ int main(int argc, char *argv[])
main_test_timerfd(); main_test_timerfd();
main_test_stackprotector_all(); main_test_stackprotector_all();
main_test_libdw_dwarf_unwind(); main_test_libdw_dwarf_unwind();
main_test_sync_compare_and_swap(argc, argv);
main_test_zlib(); main_test_zlib();
main_test_pthread_attr_setaffinity_np(); main_test_pthread_attr_setaffinity_np();
main_test_pthread_barrier(); main_test_pthread_barrier();
......
...@@ -269,6 +269,7 @@ struct kvm_xen_exit { ...@@ -269,6 +269,7 @@ struct kvm_xen_exit {
#define KVM_EXIT_AP_RESET_HOLD 32 #define KVM_EXIT_AP_RESET_HOLD 32
#define KVM_EXIT_X86_BUS_LOCK 33 #define KVM_EXIT_X86_BUS_LOCK 33
#define KVM_EXIT_XEN 34 #define KVM_EXIT_XEN 34
#define KVM_EXIT_RISCV_SBI 35
/* For KVM_EXIT_INTERNAL_ERROR */ /* For KVM_EXIT_INTERNAL_ERROR */
/* Emulate instruction failed. */ /* Emulate instruction failed. */
...@@ -397,13 +398,23 @@ struct kvm_run { ...@@ -397,13 +398,23 @@ struct kvm_run {
* "ndata" is correct, that new fields are enumerated in "flags", * "ndata" is correct, that new fields are enumerated in "flags",
* and that each flag enumerates fields that are 64-bit aligned * and that each flag enumerates fields that are 64-bit aligned
* and sized (so that ndata+internal.data[] is valid/accurate). * and sized (so that ndata+internal.data[] is valid/accurate).
*
* Space beyond the defined fields may be used to store arbitrary
* debug information relating to the emulation failure. It is
* accounted for in "ndata" but the format is unspecified and is
* not represented in "flags". Any such information is *not* ABI!
*/ */
struct { struct {
__u32 suberror; __u32 suberror;
__u32 ndata; __u32 ndata;
__u64 flags; __u64 flags;
__u8 insn_size; union {
__u8 insn_bytes[15]; struct {
__u8 insn_size;
__u8 insn_bytes[15];
};
};
/* Arbitrary debug data may follow. */
} emulation_failure; } emulation_failure;
/* KVM_EXIT_OSI */ /* KVM_EXIT_OSI */
struct { struct {
...@@ -469,6 +480,13 @@ struct kvm_run { ...@@ -469,6 +480,13 @@ struct kvm_run {
} msr; } msr;
/* KVM_EXIT_XEN */ /* KVM_EXIT_XEN */
struct kvm_xen_exit xen; struct kvm_xen_exit xen;
/* KVM_EXIT_RISCV_SBI */
struct {
unsigned long extension_id;
unsigned long function_id;
unsigned long args[6];
unsigned long ret[2];
} riscv_sbi;
/* Fix the size of the union. */ /* Fix the size of the union. */
char padding[256]; char padding[256];
}; };
...@@ -1112,6 +1130,7 @@ struct kvm_ppc_resize_hpt { ...@@ -1112,6 +1130,7 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_BINARY_STATS_FD 203 #define KVM_CAP_BINARY_STATS_FD 203
#define KVM_CAP_EXIT_ON_EMULATION_FAILURE 204 #define KVM_CAP_EXIT_ON_EMULATION_FAILURE 204
#define KVM_CAP_ARM_MTE 205 #define KVM_CAP_ARM_MTE 205
#define KVM_CAP_VM_MOVE_ENC_CONTEXT_FROM 206
#ifdef KVM_CAP_IRQ_ROUTING #ifdef KVM_CAP_IRQ_ROUTING
...@@ -1223,11 +1242,16 @@ struct kvm_irqfd { ...@@ -1223,11 +1242,16 @@ struct kvm_irqfd {
/* Do not use 1, KVM_CHECK_EXTENSION returned it before we had flags. */ /* Do not use 1, KVM_CHECK_EXTENSION returned it before we had flags. */
#define KVM_CLOCK_TSC_STABLE 2 #define KVM_CLOCK_TSC_STABLE 2
#define KVM_CLOCK_REALTIME (1 << 2)
#define KVM_CLOCK_HOST_TSC (1 << 3)
struct kvm_clock_data { struct kvm_clock_data {
__u64 clock; __u64 clock;
__u32 flags; __u32 flags;
__u32 pad[9]; __u32 pad0;
__u64 realtime;
__u64 host_tsc;
__u32 pad[4];
}; };
/* For KVM_CAP_SW_TLB */ /* For KVM_CAP_SW_TLB */
......
...@@ -1010,6 +1010,9 @@ ifndef NO_AUXTRACE ...@@ -1010,6 +1010,9 @@ ifndef NO_AUXTRACE
ifndef NO_AUXTRACE ifndef NO_AUXTRACE
$(call detected,CONFIG_AUXTRACE) $(call detected,CONFIG_AUXTRACE)
CFLAGS += -DHAVE_AUXTRACE_SUPPORT CFLAGS += -DHAVE_AUXTRACE_SUPPORT
ifeq ($(feature-reallocarray), 0)
CFLAGS += -DCOMPAT_NEED_REALLOCARRAY
endif
endif endif
endif endif
......
...@@ -363,3 +363,4 @@ ...@@ -363,3 +363,4 @@
446 n64 landlock_restrict_self sys_landlock_restrict_self 446 n64 landlock_restrict_self sys_landlock_restrict_self
# 447 reserved for memfd_secret # 447 reserved for memfd_secret
448 n64 process_mrelease sys_process_mrelease 448 n64 process_mrelease sys_process_mrelease
449 n64 futex_waitv sys_futex_waitv
...@@ -223,6 +223,8 @@ static unsigned int group(pthread_t *pth, ...@@ -223,6 +223,8 @@ static unsigned int group(pthread_t *pth,
snd_ctx->out_fds[i] = fds[1]; snd_ctx->out_fds[i] = fds[1];
if (!thread_mode) if (!thread_mode)
close(fds[0]); close(fds[0]);
free(ctx);
} }
/* Now we have all the fds, fork the senders */ /* Now we have all the fds, fork the senders */
...@@ -239,6 +241,8 @@ static unsigned int group(pthread_t *pth, ...@@ -239,6 +241,8 @@ static unsigned int group(pthread_t *pth,
for (i = 0; i < num_fds; i++) for (i = 0; i < num_fds; i++)
close(snd_ctx->out_fds[i]); close(snd_ctx->out_fds[i]);
free(snd_ctx);
/* Return number of children to reap */ /* Return number of children to reap */
return num_fds * 2; return num_fds * 2;
} }
......
...@@ -619,14 +619,17 @@ static int report__browse_hists(struct report *rep) ...@@ -619,14 +619,17 @@ static int report__browse_hists(struct report *rep)
int ret; int ret;
struct perf_session *session = rep->session; struct perf_session *session = rep->session;
struct evlist *evlist = session->evlist; struct evlist *evlist = session->evlist;
const char *help = perf_tip(system_path(TIPDIR)); char *help = NULL, *path = NULL;
if (help == NULL) { path = system_path(TIPDIR);
if (perf_tip(&help, path) || help == NULL) {
/* fallback for people who don't install perf ;-) */ /* fallback for people who don't install perf ;-) */
help = perf_tip(DOCDIR); free(path);
if (help == NULL) path = system_path(DOCDIR);
help = "Cannot load tips.txt file, please install perf!"; if (perf_tip(&help, path) || help == NULL)
help = strdup("Cannot load tips.txt file, please install perf!");
} }
free(path);
switch (use_browser) { switch (use_browser) {
case 1: case 1:
...@@ -651,7 +654,7 @@ static int report__browse_hists(struct report *rep) ...@@ -651,7 +654,7 @@ static int report__browse_hists(struct report *rep)
ret = evlist__tty_browse_hists(evlist, rep, help); ret = evlist__tty_browse_hists(evlist, rep, help);
break; break;
} }
free(help);
return ret; return ret;
} }
......
...@@ -88,7 +88,6 @@ static int test__event_update(struct test_suite *test __maybe_unused, int subtes ...@@ -88,7 +88,6 @@ static int test__event_update(struct test_suite *test __maybe_unused, int subtes
struct evsel *evsel; struct evsel *evsel;
struct event_name tmp; struct event_name tmp;
struct evlist *evlist = evlist__new_default(); struct evlist *evlist = evlist__new_default();
char *unit = strdup("KRAVA");
TEST_ASSERT_VAL("failed to get evlist", evlist); TEST_ASSERT_VAL("failed to get evlist", evlist);
...@@ -99,7 +98,8 @@ static int test__event_update(struct test_suite *test __maybe_unused, int subtes ...@@ -99,7 +98,8 @@ static int test__event_update(struct test_suite *test __maybe_unused, int subtes
perf_evlist__id_add(&evlist->core, &evsel->core, 0, 0, 123); perf_evlist__id_add(&evlist->core, &evsel->core, 0, 0, 123);
evsel->unit = unit; free((char *)evsel->unit);
evsel->unit = strdup("KRAVA");
TEST_ASSERT_VAL("failed to synthesize attr update unit", TEST_ASSERT_VAL("failed to synthesize attr update unit",
!perf_event__synthesize_event_update_unit(NULL, evsel, process_event_unit)); !perf_event__synthesize_event_update_unit(NULL, evsel, process_event_unit));
...@@ -119,7 +119,6 @@ static int test__event_update(struct test_suite *test __maybe_unused, int subtes ...@@ -119,7 +119,6 @@ static int test__event_update(struct test_suite *test __maybe_unused, int subtes
TEST_ASSERT_VAL("failed to synthesize attr update cpus", TEST_ASSERT_VAL("failed to synthesize attr update cpus",
!perf_event__synthesize_event_update_cpus(&tmp.tool, evsel, process_event_cpus)); !perf_event__synthesize_event_update_cpus(&tmp.tool, evsel, process_event_cpus));
free(unit);
evlist__delete(evlist); evlist__delete(evlist);
return 0; return 0;
} }
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
* These are based on the input value (213) specified * These are based on the input value (213) specified
* in branch_stack variable. * in branch_stack variable.
*/ */
#define BS_EXPECTED_BE 0xa00d000000000000 #define BS_EXPECTED_BE 0xa000d00000000000
#define BS_EXPECTED_LE 0xd5000000 #define BS_EXPECTED_LE 0xd5000000
#define FLAG(s) s->branch_stack->entries[i].flags #define FLAG(s) s->branch_stack->entries[i].flags
......
...@@ -21,6 +21,7 @@ do { \ ...@@ -21,6 +21,7 @@ do { \
volatile u64 data1; volatile u64 data1;
volatile u8 data2[3]; volatile u8 data2[3];
#ifndef __s390x__
static int wp_read(int fd, long long *count, int size) static int wp_read(int fd, long long *count, int size)
{ {
int ret = read(fd, count, size); int ret = read(fd, count, size);
...@@ -48,7 +49,6 @@ static void get__perf_event_attr(struct perf_event_attr *attr, int wp_type, ...@@ -48,7 +49,6 @@ static void get__perf_event_attr(struct perf_event_attr *attr, int wp_type,
attr->exclude_hv = 1; attr->exclude_hv = 1;
} }
#ifndef __s390x__
static int __event(int wp_type, void *wp_addr, unsigned long wp_len) static int __event(int wp_type, void *wp_addr, unsigned long wp_len)
{ {
int fd; int fd;
......
...@@ -535,6 +535,18 @@ struct perf_hpp_list perf_hpp_list = { ...@@ -535,6 +535,18 @@ struct perf_hpp_list perf_hpp_list = {
#undef __HPP_SORT_ACC_FN #undef __HPP_SORT_ACC_FN
#undef __HPP_SORT_RAW_FN #undef __HPP_SORT_RAW_FN
static void fmt_free(struct perf_hpp_fmt *fmt)
{
/*
* At this point fmt should be completely
* unhooked, if not it's a bug.
*/
BUG_ON(!list_empty(&fmt->list));
BUG_ON(!list_empty(&fmt->sort_list));
if (fmt->free)
fmt->free(fmt);
}
void perf_hpp__init(void) void perf_hpp__init(void)
{ {
...@@ -598,9 +610,10 @@ void perf_hpp_list__prepend_sort_field(struct perf_hpp_list *list, ...@@ -598,9 +610,10 @@ void perf_hpp_list__prepend_sort_field(struct perf_hpp_list *list,
list_add(&format->sort_list, &list->sorts); list_add(&format->sort_list, &list->sorts);
} }
void perf_hpp__column_unregister(struct perf_hpp_fmt *format) static void perf_hpp__column_unregister(struct perf_hpp_fmt *format)
{ {
list_del_init(&format->list); list_del_init(&format->list);
fmt_free(format);
} }
void perf_hpp__cancel_cumulate(void) void perf_hpp__cancel_cumulate(void)
...@@ -672,19 +685,6 @@ void perf_hpp__append_sort_keys(struct perf_hpp_list *list) ...@@ -672,19 +685,6 @@ void perf_hpp__append_sort_keys(struct perf_hpp_list *list)
} }
static void fmt_free(struct perf_hpp_fmt *fmt)
{
/*
* At this point fmt should be completely
* unhooked, if not it's a bug.
*/
BUG_ON(!list_empty(&fmt->list));
BUG_ON(!list_empty(&fmt->sort_list));
if (fmt->free)
fmt->free(fmt);
}
void perf_hpp__reset_output_field(struct perf_hpp_list *list) void perf_hpp__reset_output_field(struct perf_hpp_list *list)
{ {
struct perf_hpp_fmt *fmt, *tmp; struct perf_hpp_fmt *fmt, *tmp;
......
...@@ -51,6 +51,7 @@ struct arm_spe { ...@@ -51,6 +51,7 @@ struct arm_spe {
u8 timeless_decoding; u8 timeless_decoding;
u8 data_queued; u8 data_queued;
u64 sample_type;
u8 sample_flc; u8 sample_flc;
u8 sample_llc; u8 sample_llc;
u8 sample_tlb; u8 sample_tlb;
...@@ -287,6 +288,12 @@ static void arm_spe_prep_sample(struct arm_spe *spe, ...@@ -287,6 +288,12 @@ static void arm_spe_prep_sample(struct arm_spe *spe,
event->sample.header.size = sizeof(struct perf_event_header); event->sample.header.size = sizeof(struct perf_event_header);
} }
static int arm_spe__inject_event(union perf_event *event, struct perf_sample *sample, u64 type)
{
event->header.size = perf_event__sample_event_size(sample, type, 0);
return perf_event__synthesize_sample(event, type, 0, sample);
}
static inline int static inline int
arm_spe_deliver_synth_event(struct arm_spe *spe, arm_spe_deliver_synth_event(struct arm_spe *spe,
struct arm_spe_queue *speq __maybe_unused, struct arm_spe_queue *speq __maybe_unused,
...@@ -295,6 +302,12 @@ arm_spe_deliver_synth_event(struct arm_spe *spe, ...@@ -295,6 +302,12 @@ arm_spe_deliver_synth_event(struct arm_spe *spe,
{ {
int ret; int ret;
if (spe->synth_opts.inject) {
ret = arm_spe__inject_event(event, sample, spe->sample_type);
if (ret)
return ret;
}
ret = perf_session__deliver_synth_event(spe->session, event, sample); ret = perf_session__deliver_synth_event(spe->session, event, sample);
if (ret) if (ret)
pr_err("ARM SPE: failed to deliver event, error %d\n", ret); pr_err("ARM SPE: failed to deliver event, error %d\n", ret);
...@@ -986,6 +999,8 @@ arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session) ...@@ -986,6 +999,8 @@ arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session)
else else
attr.sample_type |= PERF_SAMPLE_TIME; attr.sample_type |= PERF_SAMPLE_TIME;
spe->sample_type = attr.sample_type;
attr.exclude_user = evsel->core.attr.exclude_user; attr.exclude_user = evsel->core.attr.exclude_user;
attr.exclude_kernel = evsel->core.attr.exclude_kernel; attr.exclude_kernel = evsel->core.attr.exclude_kernel;
attr.exclude_hv = evsel->core.attr.exclude_hv; attr.exclude_hv = evsel->core.attr.exclude_hv;
......
...@@ -241,7 +241,7 @@ void evsel__init(struct evsel *evsel, ...@@ -241,7 +241,7 @@ void evsel__init(struct evsel *evsel,
{ {
perf_evsel__init(&evsel->core, attr, idx); perf_evsel__init(&evsel->core, attr, idx);
evsel->tracking = !idx; evsel->tracking = !idx;
evsel->unit = ""; evsel->unit = strdup("");
evsel->scale = 1.0; evsel->scale = 1.0;
evsel->max_events = ULONG_MAX; evsel->max_events = ULONG_MAX;
evsel->evlist = NULL; evsel->evlist = NULL;
...@@ -276,13 +276,8 @@ struct evsel *evsel__new_idx(struct perf_event_attr *attr, int idx) ...@@ -276,13 +276,8 @@ struct evsel *evsel__new_idx(struct perf_event_attr *attr, int idx)
} }
if (evsel__is_clock(evsel)) { if (evsel__is_clock(evsel)) {
/* free((char *)evsel->unit);
* The evsel->unit points to static alias->unit evsel->unit = strdup("msec");
* so it's ok to use static string in here.
*/
static const char *unit = "msec";
evsel->unit = unit;
evsel->scale = 1e-6; evsel->scale = 1e-6;
} }
...@@ -420,7 +415,11 @@ struct evsel *evsel__clone(struct evsel *orig) ...@@ -420,7 +415,11 @@ struct evsel *evsel__clone(struct evsel *orig)
evsel->max_events = orig->max_events; evsel->max_events = orig->max_events;
evsel->tool_event = orig->tool_event; evsel->tool_event = orig->tool_event;
evsel->unit = orig->unit; free((char *)evsel->unit);
evsel->unit = strdup(orig->unit);
if (evsel->unit == NULL)
goto out_err;
evsel->scale = orig->scale; evsel->scale = orig->scale;
evsel->snapshot = orig->snapshot; evsel->snapshot = orig->snapshot;
evsel->per_pkg = orig->per_pkg; evsel->per_pkg = orig->per_pkg;
...@@ -1441,6 +1440,7 @@ void evsel__exit(struct evsel *evsel) ...@@ -1441,6 +1440,7 @@ void evsel__exit(struct evsel *evsel)
zfree(&evsel->group_name); zfree(&evsel->group_name);
zfree(&evsel->name); zfree(&evsel->name);
zfree(&evsel->pmu_name); zfree(&evsel->pmu_name);
zfree(&evsel->unit);
zfree(&evsel->metric_id); zfree(&evsel->metric_id);
evsel__zero_per_pkg(evsel); evsel__zero_per_pkg(evsel);
hashmap__free(evsel->per_pkg_mask); hashmap__free(evsel->per_pkg_mask);
......
...@@ -4257,9 +4257,11 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused, ...@@ -4257,9 +4257,11 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
switch (ev->type) { switch (ev->type) {
case PERF_EVENT_UPDATE__UNIT: case PERF_EVENT_UPDATE__UNIT:
free((char *)evsel->unit);
evsel->unit = strdup(ev->data); evsel->unit = strdup(ev->data);
break; break;
case PERF_EVENT_UPDATE__NAME: case PERF_EVENT_UPDATE__NAME:
free(evsel->name);
evsel->name = strdup(ev->data); evsel->name = strdup(ev->data);
break; break;
case PERF_EVENT_UPDATE__SCALE: case PERF_EVENT_UPDATE__SCALE:
...@@ -4268,11 +4270,11 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused, ...@@ -4268,11 +4270,11 @@ int perf_event__process_event_update(struct perf_tool *tool __maybe_unused,
break; break;
case PERF_EVENT_UPDATE__CPUS: case PERF_EVENT_UPDATE__CPUS:
ev_cpus = (struct perf_record_event_update_cpus *)ev->data; ev_cpus = (struct perf_record_event_update_cpus *)ev->data;
map = cpu_map__new_data(&ev_cpus->cpus); map = cpu_map__new_data(&ev_cpus->cpus);
if (map) if (map) {
perf_cpu_map__put(evsel->core.own_cpus);
evsel->core.own_cpus = map; evsel->core.own_cpus = map;
else } else
pr_err("failed to get event_update cpus\n"); pr_err("failed to get event_update cpus\n");
default: default:
break; break;
......
...@@ -289,15 +289,10 @@ static long hist_time(unsigned long htime) ...@@ -289,15 +289,10 @@ static long hist_time(unsigned long htime)
return htime; return htime;
} }
static void he_stat__add_period(struct he_stat *he_stat, u64 period, static void he_stat__add_period(struct he_stat *he_stat, u64 period)
u64 weight, u64 ins_lat, u64 p_stage_cyc)
{ {
he_stat->period += period; he_stat->period += period;
he_stat->weight += weight;
he_stat->nr_events += 1; he_stat->nr_events += 1;
he_stat->ins_lat += ins_lat;
he_stat->p_stage_cyc += p_stage_cyc;
} }
static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src) static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src)
...@@ -308,9 +303,6 @@ static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src) ...@@ -308,9 +303,6 @@ static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src)
dest->period_guest_sys += src->period_guest_sys; dest->period_guest_sys += src->period_guest_sys;
dest->period_guest_us += src->period_guest_us; dest->period_guest_us += src->period_guest_us;
dest->nr_events += src->nr_events; dest->nr_events += src->nr_events;
dest->weight += src->weight;
dest->ins_lat += src->ins_lat;
dest->p_stage_cyc += src->p_stage_cyc;
} }
static void he_stat__decay(struct he_stat *he_stat) static void he_stat__decay(struct he_stat *he_stat)
...@@ -598,9 +590,6 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists, ...@@ -598,9 +590,6 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,
struct hist_entry *he; struct hist_entry *he;
int64_t cmp; int64_t cmp;
u64 period = entry->stat.period; u64 period = entry->stat.period;
u64 weight = entry->stat.weight;
u64 ins_lat = entry->stat.ins_lat;
u64 p_stage_cyc = entry->stat.p_stage_cyc;
bool leftmost = true; bool leftmost = true;
p = &hists->entries_in->rb_root.rb_node; p = &hists->entries_in->rb_root.rb_node;
...@@ -619,11 +608,11 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists, ...@@ -619,11 +608,11 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,
if (!cmp) { if (!cmp) {
if (sample_self) { if (sample_self) {
he_stat__add_period(&he->stat, period, weight, ins_lat, p_stage_cyc); he_stat__add_period(&he->stat, period);
hist_entry__add_callchain_period(he, period); hist_entry__add_callchain_period(he, period);
} }
if (symbol_conf.cumulate_callchain) if (symbol_conf.cumulate_callchain)
he_stat__add_period(he->stat_acc, period, weight, ins_lat, p_stage_cyc); he_stat__add_period(he->stat_acc, period);
/* /*
* This mem info was allocated from sample__resolve_mem * This mem info was allocated from sample__resolve_mem
...@@ -733,9 +722,6 @@ __hists__add_entry(struct hists *hists, ...@@ -733,9 +722,6 @@ __hists__add_entry(struct hists *hists,
.stat = { .stat = {
.nr_events = 1, .nr_events = 1,
.period = sample->period, .period = sample->period,
.weight = sample->weight,
.ins_lat = sample->ins_lat,
.p_stage_cyc = sample->p_stage_cyc,
}, },
.parent = sym_parent, .parent = sym_parent,
.filtered = symbol__parent_filter(sym_parent) | al->filtered, .filtered = symbol__parent_filter(sym_parent) | al->filtered,
...@@ -748,6 +734,9 @@ __hists__add_entry(struct hists *hists, ...@@ -748,6 +734,9 @@ __hists__add_entry(struct hists *hists,
.raw_size = sample->raw_size, .raw_size = sample->raw_size,
.ops = ops, .ops = ops,
.time = hist_time(sample->time), .time = hist_time(sample->time),
.weight = sample->weight,
.ins_lat = sample->ins_lat,
.p_stage_cyc = sample->p_stage_cyc,
}, *he = hists__findnew_entry(hists, &entry, al, sample_self); }, *he = hists__findnew_entry(hists, &entry, al, sample_self);
if (!hists->has_callchains && he && he->callchain_size != 0) if (!hists->has_callchains && he && he->callchain_size != 0)
......
...@@ -369,7 +369,6 @@ enum { ...@@ -369,7 +369,6 @@ enum {
}; };
void perf_hpp__init(void); void perf_hpp__init(void);
void perf_hpp__column_unregister(struct perf_hpp_fmt *format);
void perf_hpp__cancel_cumulate(void); void perf_hpp__cancel_cumulate(void);
void perf_hpp__setup_output_field(struct perf_hpp_list *list); void perf_hpp__setup_output_field(struct perf_hpp_list *list);
void perf_hpp__reset_output_field(struct perf_hpp_list *list); void perf_hpp__reset_output_field(struct perf_hpp_list *list);
......
...@@ -402,8 +402,10 @@ static int add_event_tool(struct list_head *list, int *idx, ...@@ -402,8 +402,10 @@ static int add_event_tool(struct list_head *list, int *idx,
if (!evsel) if (!evsel)
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 = "ns"; free((char *)evsel->unit);
evsel->unit = strdup("ns");
}
return 0; return 0;
} }
...@@ -1630,7 +1632,8 @@ int parse_events_add_pmu(struct parse_events_state *parse_state, ...@@ -1630,7 +1632,8 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
if (parse_state->fake_pmu) if (parse_state->fake_pmu)
return 0; return 0;
evsel->unit = info.unit; free((char *)evsel->unit);
evsel->unit = strdup(info.unit);
evsel->scale = info.scale; evsel->scale = info.scale;
evsel->per_pkg = info.per_pkg; evsel->per_pkg = info.per_pkg;
evsel->snapshot = info.snapshot; evsel->snapshot = info.snapshot;
......
...@@ -1325,88 +1325,68 @@ struct sort_entry sort_mispredict = { ...@@ -1325,88 +1325,68 @@ struct sort_entry sort_mispredict = {
.se_width_idx = HISTC_MISPREDICT, .se_width_idx = HISTC_MISPREDICT,
}; };
static u64 he_weight(struct hist_entry *he)
{
return he->stat.nr_events ? he->stat.weight / he->stat.nr_events : 0;
}
static int64_t static int64_t
sort__local_weight_cmp(struct hist_entry *left, struct hist_entry *right) sort__weight_cmp(struct hist_entry *left, struct hist_entry *right)
{ {
return he_weight(left) - he_weight(right); return left->weight - right->weight;
} }
static int hist_entry__local_weight_snprintf(struct hist_entry *he, char *bf, static int hist_entry__local_weight_snprintf(struct hist_entry *he, char *bf,
size_t size, unsigned int width) size_t size, unsigned int width)
{ {
return repsep_snprintf(bf, size, "%-*llu", width, he_weight(he)); return repsep_snprintf(bf, size, "%-*llu", width, he->weight);
} }
struct sort_entry sort_local_weight = { struct sort_entry sort_local_weight = {
.se_header = "Local Weight", .se_header = "Local Weight",
.se_cmp = sort__local_weight_cmp, .se_cmp = sort__weight_cmp,
.se_snprintf = hist_entry__local_weight_snprintf, .se_snprintf = hist_entry__local_weight_snprintf,
.se_width_idx = HISTC_LOCAL_WEIGHT, .se_width_idx = HISTC_LOCAL_WEIGHT,
}; };
static int64_t
sort__global_weight_cmp(struct hist_entry *left, struct hist_entry *right)
{
return left->stat.weight - right->stat.weight;
}
static int hist_entry__global_weight_snprintf(struct hist_entry *he, char *bf, static int hist_entry__global_weight_snprintf(struct hist_entry *he, char *bf,
size_t size, unsigned int width) size_t size, unsigned int width)
{ {
return repsep_snprintf(bf, size, "%-*llu", width, he->stat.weight); return repsep_snprintf(bf, size, "%-*llu", width,
he->weight * he->stat.nr_events);
} }
struct sort_entry sort_global_weight = { struct sort_entry sort_global_weight = {
.se_header = "Weight", .se_header = "Weight",
.se_cmp = sort__global_weight_cmp, .se_cmp = sort__weight_cmp,
.se_snprintf = hist_entry__global_weight_snprintf, .se_snprintf = hist_entry__global_weight_snprintf,
.se_width_idx = HISTC_GLOBAL_WEIGHT, .se_width_idx = HISTC_GLOBAL_WEIGHT,
}; };
static u64 he_ins_lat(struct hist_entry *he)
{
return he->stat.nr_events ? he->stat.ins_lat / he->stat.nr_events : 0;
}
static int64_t static int64_t
sort__local_ins_lat_cmp(struct hist_entry *left, struct hist_entry *right) sort__ins_lat_cmp(struct hist_entry *left, struct hist_entry *right)
{ {
return he_ins_lat(left) - he_ins_lat(right); return left->ins_lat - right->ins_lat;
} }
static int hist_entry__local_ins_lat_snprintf(struct hist_entry *he, char *bf, static int hist_entry__local_ins_lat_snprintf(struct hist_entry *he, char *bf,
size_t size, unsigned int width) size_t size, unsigned int width)
{ {
return repsep_snprintf(bf, size, "%-*u", width, he_ins_lat(he)); return repsep_snprintf(bf, size, "%-*u", width, he->ins_lat);
} }
struct sort_entry sort_local_ins_lat = { struct sort_entry sort_local_ins_lat = {
.se_header = "Local INSTR Latency", .se_header = "Local INSTR Latency",
.se_cmp = sort__local_ins_lat_cmp, .se_cmp = sort__ins_lat_cmp,
.se_snprintf = hist_entry__local_ins_lat_snprintf, .se_snprintf = hist_entry__local_ins_lat_snprintf,
.se_width_idx = HISTC_LOCAL_INS_LAT, .se_width_idx = HISTC_LOCAL_INS_LAT,
}; };
static int64_t
sort__global_ins_lat_cmp(struct hist_entry *left, struct hist_entry *right)
{
return left->stat.ins_lat - right->stat.ins_lat;
}
static int hist_entry__global_ins_lat_snprintf(struct hist_entry *he, char *bf, static int hist_entry__global_ins_lat_snprintf(struct hist_entry *he, char *bf,
size_t size, unsigned int width) size_t size, unsigned int width)
{ {
return repsep_snprintf(bf, size, "%-*u", width, he->stat.ins_lat); return repsep_snprintf(bf, size, "%-*u", width,
he->ins_lat * he->stat.nr_events);
} }
struct sort_entry sort_global_ins_lat = { struct sort_entry sort_global_ins_lat = {
.se_header = "INSTR Latency", .se_header = "INSTR Latency",
.se_cmp = sort__global_ins_lat_cmp, .se_cmp = sort__ins_lat_cmp,
.se_snprintf = hist_entry__global_ins_lat_snprintf, .se_snprintf = hist_entry__global_ins_lat_snprintf,
.se_width_idx = HISTC_GLOBAL_INS_LAT, .se_width_idx = HISTC_GLOBAL_INS_LAT,
}; };
...@@ -1414,13 +1394,13 @@ struct sort_entry sort_global_ins_lat = { ...@@ -1414,13 +1394,13 @@ struct sort_entry sort_global_ins_lat = {
static int64_t static int64_t
sort__global_p_stage_cyc_cmp(struct hist_entry *left, struct hist_entry *right) sort__global_p_stage_cyc_cmp(struct hist_entry *left, struct hist_entry *right)
{ {
return left->stat.p_stage_cyc - right->stat.p_stage_cyc; return left->p_stage_cyc - right->p_stage_cyc;
} }
static int hist_entry__p_stage_cyc_snprintf(struct hist_entry *he, char *bf, static int hist_entry__p_stage_cyc_snprintf(struct hist_entry *he, char *bf,
size_t size, unsigned int width) size_t size, unsigned int width)
{ {
return repsep_snprintf(bf, size, "%-*u", width, he->stat.p_stage_cyc); return repsep_snprintf(bf, size, "%-*u", width, he->p_stage_cyc);
} }
struct sort_entry sort_p_stage_cyc = { struct sort_entry sort_p_stage_cyc = {
......
...@@ -49,9 +49,6 @@ struct he_stat { ...@@ -49,9 +49,6 @@ struct he_stat {
u64 period_us; u64 period_us;
u64 period_guest_sys; u64 period_guest_sys;
u64 period_guest_us; u64 period_guest_us;
u64 weight;
u64 ins_lat;
u64 p_stage_cyc;
u32 nr_events; u32 nr_events;
}; };
...@@ -109,6 +106,9 @@ struct hist_entry { ...@@ -109,6 +106,9 @@ struct hist_entry {
s32 socket; s32 socket;
s32 cpu; s32 cpu;
u64 code_page_size; u64 code_page_size;
u64 weight;
u64 ins_lat;
u64 p_stage_cyc;
u8 cpumode; u8 cpumode;
u8 depth; u8 depth;
......
...@@ -379,32 +379,32 @@ fetch_kernel_version(unsigned int *puint, char *str, ...@@ -379,32 +379,32 @@ fetch_kernel_version(unsigned int *puint, char *str,
return 0; return 0;
} }
const char *perf_tip(const char *dirpath) int perf_tip(char **strp, const char *dirpath)
{ {
struct strlist *tips; struct strlist *tips;
struct str_node *node; struct str_node *node;
char *tip = NULL;
struct strlist_config conf = { struct strlist_config conf = {
.dirname = dirpath, .dirname = dirpath,
.file_only = true, .file_only = true,
}; };
int ret = 0;
*strp = NULL;
tips = strlist__new("tips.txt", &conf); tips = strlist__new("tips.txt", &conf);
if (tips == NULL) if (tips == NULL)
return errno == ENOENT ? NULL : return -errno;
"Tip: check path of tips.txt or get more memory! ;-p";
if (strlist__nr_entries(tips) == 0) if (strlist__nr_entries(tips) == 0)
goto out; goto out;
node = strlist__entry(tips, random() % strlist__nr_entries(tips)); node = strlist__entry(tips, random() % strlist__nr_entries(tips));
if (asprintf(&tip, "Tip: %s", node->s) < 0) if (asprintf(strp, "Tip: %s", node->s) < 0)
tip = (char *)"Tip: get more memory! ;-)"; ret = -ENOMEM;
out: out:
strlist__delete(tips); strlist__delete(tips);
return tip; return ret;
} }
char *perf_exe(char *buf, int len) char *perf_exe(char *buf, int len)
......
...@@ -39,7 +39,7 @@ int fetch_kernel_version(unsigned int *puint, ...@@ -39,7 +39,7 @@ int fetch_kernel_version(unsigned int *puint,
#define KVER_FMT "%d.%d.%d" #define KVER_FMT "%d.%d.%d"
#define KVER_PARAM(x) KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x) #define KVER_PARAM(x) KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x)
const char *perf_tip(const char *dirpath); int perf_tip(char **strp, const char *dirpath);
#ifndef HAVE_SCHED_GETCPU_SUPPORT #ifndef HAVE_SCHED_GETCPU_SUPPORT
int sched_getcpu(void); int sched_getcpu(void);
......
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