Commit d072b89d authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-core-for-mingo-2' of...

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

Pull perf tooling changes from Arnaldo Carvalho de Melo:

New features:

 - Port 'perf kvm stat' to PowerPC (Hemant Kumar)

Infrastructure changes:

 - Use the 'feature-dump' target to do the feature checks just once and then
   add code to reuse that in the tests/make makefile, speeding up the
   'make -C tools/perf build-test' target (Wang Nan)

 - Reduce the number of tests the 'build-test' target do to those that don't
   pollute the source tree (Arnaldo Carvalho de Melo)

 - Improve the output of the build tests a bit by aligning the name of the
   tests, more can be done to filter out uninteresting info in the output
   (Arnaldo Carvalho de Melo)

 - Add perf_evlist pointer to *info_priv_size(), more prep work for
   supporting the coresight architecture (Mathieu Poirier)

 - Improve the 'perf test bp_signal' test (Wang Nan)

 - Check environment before starting the BPF 'perf test', so that we can just
   'Skip' older kernels instead of 'FAIL'ing them (Wang Nan)

 - Fix cpumode of synthesized buildid event (Wang Nan)
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 402e8db5 814568db
...@@ -119,6 +119,14 @@ ifeq ($(feature-all), 1) ...@@ -119,6 +119,14 @@ ifeq ($(feature-all), 1)
# test-all.c passed - just set all the core feature flags to 1: # test-all.c passed - just set all the core feature flags to 1:
# #
$(foreach feat,$(FEATURE_TESTS),$(call feature_set,$(feat))) $(foreach feat,$(FEATURE_TESTS),$(call feature_set,$(feat)))
#
# test-all.c does not comprise these tests, so we need to
# for this case to get features proper values
#
$(call feature_check,compile-32)
$(call feature_check,compile-x32)
$(call feature_check,bionic)
$(call feature_check,libbabeltrace)
else else
$(foreach feat,$(FEATURE_TESTS),$(call feature_check,$(feat))) $(foreach feat,$(FEATURE_TESTS),$(call feature_check,$(feat)))
endif endif
......
#include <stdio.h>
int main(void) int main(void)
{ {
printf("Hello World!\n");
return 0; return 0;
} }
...@@ -75,10 +75,17 @@ clean: ...@@ -75,10 +75,17 @@ clean:
$(make) $(make)
# #
# The build-test target is not really parallel, don't print the jobs info: # The build-test target is not really parallel, don't print the jobs info,
# it also uses only the tests/make targets that don't pollute the source
# repository, i.e. that uses O= or builds the tarpkg outside the source
# repo directories.
#
# For a full test, use:
#
# make -C tools/perf -f tests/make
# #
build-test: build-test:
@$(MAKE) SHUF=1 -f tests/make --no-print-directory @$(MAKE) SHUF=1 -f tests/make REUSE_FEATURES_DUMP=1 MK=Makefile --no-print-directory tarpkg out
# #
# All other targets get passed through: # All other targets get passed through:
......
ifndef NO_DWARF ifndef NO_DWARF
PERF_HAVE_DWARF_REGS := 1 PERF_HAVE_DWARF_REGS := 1
endif endif
HAVE_KVM_STAT_SUPPORT := 1
libperf-y += header.o libperf-y += header.o
libperf-y += sym-handling.o libperf-y += sym-handling.o
libperf-y += kvm-stat.o
libperf-$(CONFIG_DWARF) += dwarf-regs.o libperf-$(CONFIG_DWARF) += dwarf-regs.o
libperf-$(CONFIG_DWARF) += skip-callchain-idx.o libperf-$(CONFIG_DWARF) += skip-callchain-idx.o
#ifndef ARCH_PERF_BOOK3S_HV_HCALLS_H
#define ARCH_PERF_BOOK3S_HV_HCALLS_H
/*
* PowerPC HCALL codes : hcall code to name mapping
*/
#define kvm_trace_symbol_hcall \
{0x4, "H_REMOVE"}, \
{0x8, "H_ENTER"}, \
{0xc, "H_READ"}, \
{0x10, "H_CLEAR_MOD"}, \
{0x14, "H_CLEAR_REF"}, \
{0x18, "H_PROTECT"}, \
{0x1c, "H_GET_TCE"}, \
{0x20, "H_PUT_TCE"}, \
{0x24, "H_SET_SPRG0"}, \
{0x28, "H_SET_DABR"}, \
{0x2c, "H_PAGE_INIT"}, \
{0x30, "H_SET_ASR"}, \
{0x34, "H_ASR_ON"}, \
{0x38, "H_ASR_OFF"}, \
{0x3c, "H_LOGICAL_CI_LOAD"}, \
{0x40, "H_LOGICAL_CI_STORE"}, \
{0x44, "H_LOGICAL_CACHE_LOAD"}, \
{0x48, "H_LOGICAL_CACHE_STORE"}, \
{0x4c, "H_LOGICAL_ICBI"}, \
{0x50, "H_LOGICAL_DCBF"}, \
{0x54, "H_GET_TERM_CHAR"}, \
{0x58, "H_PUT_TERM_CHAR"}, \
{0x5c, "H_REAL_TO_LOGICAL"}, \
{0x60, "H_HYPERVISOR_DATA"}, \
{0x64, "H_EOI"}, \
{0x68, "H_CPPR"}, \
{0x6c, "H_IPI"}, \
{0x70, "H_IPOLL"}, \
{0x74, "H_XIRR"}, \
{0x78, "H_MIGRATE_DMA"}, \
{0x7c, "H_PERFMON"}, \
{0xdc, "H_REGISTER_VPA"}, \
{0xe0, "H_CEDE"}, \
{0xe4, "H_CONFER"}, \
{0xe8, "H_PROD"}, \
{0xec, "H_GET_PPP"}, \
{0xf0, "H_SET_PPP"}, \
{0xf4, "H_PURR"}, \
{0xf8, "H_PIC"}, \
{0xfc, "H_REG_CRQ"}, \
{0x100, "H_FREE_CRQ"}, \
{0x104, "H_VIO_SIGNAL"}, \
{0x108, "H_SEND_CRQ"}, \
{0x110, "H_COPY_RDMA"}, \
{0x114, "H_REGISTER_LOGICAL_LAN"}, \
{0x118, "H_FREE_LOGICAL_LAN"}, \
{0x11c, "H_ADD_LOGICAL_LAN_BUFFER"}, \
{0x120, "H_SEND_LOGICAL_LAN"}, \
{0x124, "H_BULK_REMOVE"}, \
{0x130, "H_MULTICAST_CTRL"}, \
{0x134, "H_SET_XDABR"}, \
{0x138, "H_STUFF_TCE"}, \
{0x13c, "H_PUT_TCE_INDIRECT"}, \
{0x14c, "H_CHANGE_LOGICAL_LAN_MAC"}, \
{0x150, "H_VTERM_PARTNER_INFO"}, \
{0x154, "H_REGISTER_VTERM"}, \
{0x158, "H_FREE_VTERM"}, \
{0x15c, "H_RESET_EVENTS"}, \
{0x160, "H_ALLOC_RESOURCE"}, \
{0x164, "H_FREE_RESOURCE"}, \
{0x168, "H_MODIFY_QP"}, \
{0x16c, "H_QUERY_QP"}, \
{0x170, "H_REREGISTER_PMR"}, \
{0x174, "H_REGISTER_SMR"}, \
{0x178, "H_QUERY_MR"}, \
{0x17c, "H_QUERY_MW"}, \
{0x180, "H_QUERY_HCA"}, \
{0x184, "H_QUERY_PORT"}, \
{0x188, "H_MODIFY_PORT"}, \
{0x18c, "H_DEFINE_AQP1"}, \
{0x190, "H_GET_TRACE_BUFFER"}, \
{0x194, "H_DEFINE_AQP0"}, \
{0x198, "H_RESIZE_MR"}, \
{0x19c, "H_ATTACH_MCQP"}, \
{0x1a0, "H_DETACH_MCQP"}, \
{0x1a4, "H_CREATE_RPT"}, \
{0x1a8, "H_REMOVE_RPT"}, \
{0x1ac, "H_REGISTER_RPAGES"}, \
{0x1b0, "H_DISABLE_AND_GETC"}, \
{0x1b4, "H_ERROR_DATA"}, \
{0x1b8, "H_GET_HCA_INFO"}, \
{0x1bc, "H_GET_PERF_COUNT"}, \
{0x1c0, "H_MANAGE_TRACE"}, \
{0x1d4, "H_FREE_LOGICAL_LAN_BUFFER"}, \
{0x1d8, "H_POLL_PENDING"}, \
{0x1e4, "H_QUERY_INT_STATE"}, \
{0x244, "H_ILLAN_ATTRIBUTES"}, \
{0x250, "H_MODIFY_HEA_QP"}, \
{0x254, "H_QUERY_HEA_QP"}, \
{0x258, "H_QUERY_HEA"}, \
{0x25c, "H_QUERY_HEA_PORT"}, \
{0x260, "H_MODIFY_HEA_PORT"}, \
{0x264, "H_REG_BCMC"}, \
{0x268, "H_DEREG_BCMC"}, \
{0x26c, "H_REGISTER_HEA_RPAGES"}, \
{0x270, "H_DISABLE_AND_GET_HEA"}, \
{0x274, "H_GET_HEA_INFO"}, \
{0x278, "H_ALLOC_HEA_RESOURCE"}, \
{0x284, "H_ADD_CONN"}, \
{0x288, "H_DEL_CONN"}, \
{0x298, "H_JOIN"}, \
{0x2a4, "H_VASI_STATE"}, \
{0x2b0, "H_ENABLE_CRQ"}, \
{0x2b8, "H_GET_EM_PARMS"}, \
{0x2d0, "H_SET_MPP"}, \
{0x2d4, "H_GET_MPP"}, \
{0x2ec, "H_HOME_NODE_ASSOCIATIVITY"}, \
{0x2f4, "H_BEST_ENERGY"}, \
{0x2fc, "H_XIRR_X"}, \
{0x300, "H_RANDOM"}, \
{0x304, "H_COP"}, \
{0x314, "H_GET_MPP_X"}, \
{0x31c, "H_SET_MODE"}, \
{0xf000, "H_RTAS"} \
#endif
#ifndef ARCH_PERF_BOOK3S_HV_EXITS_H
#define ARCH_PERF_BOOK3S_HV_EXITS_H
/*
* PowerPC Interrupt vectors : exit code to name mapping
*/
#define kvm_trace_symbol_exit \
{0x0, "RETURN_TO_HOST"}, \
{0x100, "SYSTEM_RESET"}, \
{0x200, "MACHINE_CHECK"}, \
{0x300, "DATA_STORAGE"}, \
{0x380, "DATA_SEGMENT"}, \
{0x400, "INST_STORAGE"}, \
{0x480, "INST_SEGMENT"}, \
{0x500, "EXTERNAL"}, \
{0x501, "EXTERNAL_LEVEL"}, \
{0x502, "EXTERNAL_HV"}, \
{0x600, "ALIGNMENT"}, \
{0x700, "PROGRAM"}, \
{0x800, "FP_UNAVAIL"}, \
{0x900, "DECREMENTER"}, \
{0x980, "HV_DECREMENTER"}, \
{0xc00, "SYSCALL"}, \
{0xd00, "TRACE"}, \
{0xe00, "H_DATA_STORAGE"}, \
{0xe20, "H_INST_STORAGE"}, \
{0xe40, "H_EMUL_ASSIST"}, \
{0xf00, "PERFMON"}, \
{0xf20, "ALTIVEC"}, \
{0xf40, "VSX"}
#endif
#include "util/kvm-stat.h"
#include "util/parse-events.h"
#include "util/debug.h"
#include "book3s_hv_exits.h"
#include "book3s_hcalls.h"
#define NR_TPS 4
const char *vcpu_id_str = "vcpu_id";
const int decode_str_len = 40;
const char *kvm_entry_trace = "kvm_hv:kvm_guest_enter";
const char *kvm_exit_trace = "kvm_hv:kvm_guest_exit";
define_exit_reasons_table(hv_exit_reasons, kvm_trace_symbol_exit);
define_exit_reasons_table(hcall_reasons, kvm_trace_symbol_hcall);
/* Tracepoints specific to ppc_book3s_hv */
const char *ppc_book3s_hv_kvm_tp[] = {
"kvm_hv:kvm_guest_enter",
"kvm_hv:kvm_guest_exit",
"kvm_hv:kvm_hcall_enter",
"kvm_hv:kvm_hcall_exit",
NULL,
};
/* 1 extra placeholder for NULL */
const char *kvm_events_tp[NR_TPS + 1];
const char *kvm_exit_reason;
static void hcall_event_get_key(struct perf_evsel *evsel,
struct perf_sample *sample,
struct event_key *key)
{
key->info = 0;
key->key = perf_evsel__intval(evsel, sample, "req");
}
static const char *get_hcall_exit_reason(u64 exit_code)
{
struct exit_reasons_table *tbl = hcall_reasons;
while (tbl->reason != NULL) {
if (tbl->exit_code == exit_code)
return tbl->reason;
tbl++;
}
pr_debug("Unknown hcall code: %lld\n",
(unsigned long long)exit_code);
return "UNKNOWN";
}
static bool hcall_event_end(struct perf_evsel *evsel,
struct perf_sample *sample __maybe_unused,
struct event_key *key __maybe_unused)
{
return (!strcmp(evsel->name, kvm_events_tp[3]));
}
static bool hcall_event_begin(struct perf_evsel *evsel,
struct perf_sample *sample, struct event_key *key)
{
if (!strcmp(evsel->name, kvm_events_tp[2])) {
hcall_event_get_key(evsel, sample, key);
return true;
}
return false;
}
static void hcall_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
struct event_key *key,
char *decode)
{
const char *hcall_reason = get_hcall_exit_reason(key->key);
scnprintf(decode, decode_str_len, "%s", hcall_reason);
}
static struct kvm_events_ops hcall_events = {
.is_begin_event = hcall_event_begin,
.is_end_event = hcall_event_end,
.decode_key = hcall_event_decode_key,
.name = "HCALL-EVENT",
};
static struct kvm_events_ops exit_events = {
.is_begin_event = exit_event_begin,
.is_end_event = exit_event_end,
.decode_key = exit_event_decode_key,
.name = "VM-EXIT"
};
struct kvm_reg_events_ops kvm_reg_events_ops[] = {
{ .name = "vmexit", .ops = &exit_events },
{ .name = "hcall", .ops = &hcall_events },
{ NULL, NULL },
};
const char * const kvm_skip_events[] = {
NULL,
};
static int is_tracepoint_available(const char *str, struct perf_evlist *evlist)
{
struct parse_events_error err;
int ret;
err.str = NULL;
ret = parse_events(evlist, str, &err);
if (err.str)
pr_err("%s : %s\n", str, err.str);
return ret;
}
static int ppc__setup_book3s_hv(struct perf_kvm_stat *kvm,
struct perf_evlist *evlist)
{
const char **events_ptr;
int i, nr_tp = 0, err = -1;
/* Check for book3s_hv tracepoints */
for (events_ptr = ppc_book3s_hv_kvm_tp; *events_ptr; events_ptr++) {
err = is_tracepoint_available(*events_ptr, evlist);
if (err)
return -1;
nr_tp++;
}
for (i = 0; i < nr_tp; i++)
kvm_events_tp[i] = ppc_book3s_hv_kvm_tp[i];
kvm_events_tp[i] = NULL;
kvm_exit_reason = "trap";
kvm->exit_reasons = hv_exit_reasons;
kvm->exit_reasons_isa = "HV";
return 0;
}
/* Wrapper to setup kvm tracepoints */
static int ppc__setup_kvm_tp(struct perf_kvm_stat *kvm)
{
struct perf_evlist *evlist = perf_evlist__new();
if (evlist == NULL)
return -ENOMEM;
/* Right now, only supported on book3s_hv */
return ppc__setup_book3s_hv(kvm, evlist);
}
int setup_kvm_events_tp(struct perf_kvm_stat *kvm)
{
return ppc__setup_kvm_tp(kvm);
}
int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid __maybe_unused)
{
int ret;
ret = ppc__setup_kvm_tp(kvm);
if (ret) {
kvm->exit_reasons = NULL;
kvm->exit_reasons_isa = NULL;
}
return ret;
}
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
*/ */
#include "../../util/kvm-stat.h" #include "../../util/kvm-stat.h"
#include <asm/kvm_perf.h> #include <asm/sie.h>
define_exit_reasons_table(sie_exit_reasons, sie_intercept_code); define_exit_reasons_table(sie_exit_reasons, sie_intercept_code);
define_exit_reasons_table(sie_icpt_insn_codes, icpt_insn_codes); define_exit_reasons_table(sie_icpt_insn_codes, icpt_insn_codes);
...@@ -18,6 +18,12 @@ define_exit_reasons_table(sie_sigp_order_codes, sigp_order_codes); ...@@ -18,6 +18,12 @@ define_exit_reasons_table(sie_sigp_order_codes, sigp_order_codes);
define_exit_reasons_table(sie_diagnose_codes, diagnose_codes); define_exit_reasons_table(sie_diagnose_codes, diagnose_codes);
define_exit_reasons_table(sie_icpt_prog_codes, icpt_prog_codes); define_exit_reasons_table(sie_icpt_prog_codes, icpt_prog_codes);
const char *vcpu_id_str = "id";
const int decode_str_len = 40;
const char *kvm_exit_reason = "icptcode";
const char *kvm_entry_trace = "kvm:kvm_s390_sie_enter";
const char *kvm_exit_trace = "kvm:kvm_s390_sie_exit";
static void event_icpt_insn_get_key(struct perf_evsel *evsel, static void event_icpt_insn_get_key(struct perf_evsel *evsel,
struct perf_sample *sample, struct perf_sample *sample,
struct event_key *key) struct event_key *key)
...@@ -73,7 +79,7 @@ static struct kvm_events_ops exit_events = { ...@@ -73,7 +79,7 @@ static struct kvm_events_ops exit_events = {
.name = "VM-EXIT" .name = "VM-EXIT"
}; };
const char * const kvm_events_tp[] = { const char *kvm_events_tp[] = {
"kvm:kvm_s390_sie_enter", "kvm:kvm_s390_sie_enter",
"kvm:kvm_s390_sie_exit", "kvm:kvm_s390_sie_exit",
"kvm:kvm_s390_intercept_instruction", "kvm:kvm_s390_intercept_instruction",
......
...@@ -60,7 +60,9 @@ struct branch { ...@@ -60,7 +60,9 @@ struct branch {
u64 misc; u64 misc;
}; };
static size_t intel_bts_info_priv_size(struct auxtrace_record *itr __maybe_unused) static size_t
intel_bts_info_priv_size(struct auxtrace_record *itr __maybe_unused,
struct perf_evlist *evlist __maybe_unused)
{ {
return INTEL_BTS_AUXTRACE_PRIV_SIZE; return INTEL_BTS_AUXTRACE_PRIV_SIZE;
} }
......
...@@ -273,7 +273,9 @@ intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu) ...@@ -273,7 +273,9 @@ intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu)
return attr; return attr;
} }
static size_t intel_pt_info_priv_size(struct auxtrace_record *itr __maybe_unused) static size_t
intel_pt_info_priv_size(struct auxtrace_record *itr __maybe_unused,
struct perf_evlist *evlist __maybe_unused)
{ {
return INTEL_PT_AUXTRACE_PRIV_SIZE; return INTEL_PT_AUXTRACE_PRIV_SIZE;
} }
......
#include "../../util/kvm-stat.h" #include "../../util/kvm-stat.h"
#include <asm/kvm_perf.h> #include <asm/svm.h>
#include <asm/vmx.h>
#include <asm/kvm.h>
define_exit_reasons_table(vmx_exit_reasons, VMX_EXIT_REASONS); define_exit_reasons_table(vmx_exit_reasons, VMX_EXIT_REASONS);
define_exit_reasons_table(svm_exit_reasons, SVM_EXIT_REASONS); define_exit_reasons_table(svm_exit_reasons, SVM_EXIT_REASONS);
...@@ -11,6 +13,12 @@ static struct kvm_events_ops exit_events = { ...@@ -11,6 +13,12 @@ static struct kvm_events_ops exit_events = {
.name = "VM-EXIT" .name = "VM-EXIT"
}; };
const char *vcpu_id_str = "vcpu_id";
const int decode_str_len = 20;
const char *kvm_exit_reason = "exit_reason";
const char *kvm_entry_trace = "kvm:kvm_entry";
const char *kvm_exit_trace = "kvm:kvm_exit";
/* /*
* For the mmio events, we treat: * For the mmio events, we treat:
* the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry * the time of MMIO write: kvm_mmio(KVM_TRACE_MMIO_WRITE...) -> kvm_entry
...@@ -65,7 +73,7 @@ static void mmio_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused, ...@@ -65,7 +73,7 @@ static void mmio_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
struct event_key *key, struct event_key *key,
char *decode) char *decode)
{ {
scnprintf(decode, DECODE_STR_LEN, "%#lx:%s", scnprintf(decode, decode_str_len, "%#lx:%s",
(unsigned long)key->key, (unsigned long)key->key,
key->info == KVM_TRACE_MMIO_WRITE ? "W" : "R"); key->info == KVM_TRACE_MMIO_WRITE ? "W" : "R");
} }
...@@ -109,7 +117,7 @@ static void ioport_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused, ...@@ -109,7 +117,7 @@ static void ioport_event_decode_key(struct perf_kvm_stat *kvm __maybe_unused,
struct event_key *key, struct event_key *key,
char *decode) char *decode)
{ {
scnprintf(decode, DECODE_STR_LEN, "%#llx:%s", scnprintf(decode, decode_str_len, "%#llx:%s",
(unsigned long long)key->key, (unsigned long long)key->key,
key->info ? "POUT" : "PIN"); key->info ? "POUT" : "PIN");
} }
...@@ -121,7 +129,7 @@ static struct kvm_events_ops ioport_events = { ...@@ -121,7 +129,7 @@ static struct kvm_events_ops ioport_events = {
.name = "IO Port Access" .name = "IO Port Access"
}; };
const char * const kvm_events_tp[] = { const char *kvm_events_tp[] = {
"kvm:kvm_entry", "kvm:kvm_entry",
"kvm:kvm_exit", "kvm:kvm_exit",
"kvm:kvm_mmio", "kvm:kvm_mmio",
......
...@@ -38,19 +38,7 @@ static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid) ...@@ -38,19 +38,7 @@ static int build_id_cache__kcore_buildid(const char *proc_dir, char *sbuildid)
static int build_id_cache__kcore_dir(char *dir, size_t sz) static int build_id_cache__kcore_dir(char *dir, size_t sz)
{ {
struct timeval tv; return fetch_current_timestamp(dir, sz);
struct tm tm;
char dt[32];
if (gettimeofday(&tv, NULL) || !localtime_r(&tv.tv_sec, &tm))
return -1;
if (!strftime(dt, sizeof(dt), "%Y%m%d%H%M%S", &tm))
return -1;
scnprintf(dir, sz, "%s%02u", dt, (unsigned)tv.tv_usec / 10000);
return 0;
} }
static bool same_kallsyms_reloc(const char *from_dir, char *to_dir) static bool same_kallsyms_reloc(const char *from_dir, char *to_dir)
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include <math.h> #include <math.h>
#ifdef HAVE_KVM_STAT_SUPPORT #ifdef HAVE_KVM_STAT_SUPPORT
#include <asm/kvm_perf.h>
#include "util/kvm-stat.h" #include "util/kvm-stat.h"
void exit_event_get_key(struct perf_evsel *evsel, void exit_event_get_key(struct perf_evsel *evsel,
...@@ -38,12 +37,12 @@ void exit_event_get_key(struct perf_evsel *evsel, ...@@ -38,12 +37,12 @@ void exit_event_get_key(struct perf_evsel *evsel,
struct event_key *key) struct event_key *key)
{ {
key->info = 0; key->info = 0;
key->key = perf_evsel__intval(evsel, sample, KVM_EXIT_REASON); key->key = perf_evsel__intval(evsel, sample, kvm_exit_reason);
} }
bool kvm_exit_event(struct perf_evsel *evsel) bool kvm_exit_event(struct perf_evsel *evsel)
{ {
return !strcmp(evsel->name, KVM_EXIT_TRACE); return !strcmp(evsel->name, kvm_exit_trace);
} }
bool exit_event_begin(struct perf_evsel *evsel, bool exit_event_begin(struct perf_evsel *evsel,
...@@ -59,7 +58,7 @@ bool exit_event_begin(struct perf_evsel *evsel, ...@@ -59,7 +58,7 @@ bool exit_event_begin(struct perf_evsel *evsel,
bool kvm_entry_event(struct perf_evsel *evsel) bool kvm_entry_event(struct perf_evsel *evsel)
{ {
return !strcmp(evsel->name, KVM_ENTRY_TRACE); return !strcmp(evsel->name, kvm_entry_trace);
} }
bool exit_event_end(struct perf_evsel *evsel, bool exit_event_end(struct perf_evsel *evsel,
...@@ -91,7 +90,7 @@ void exit_event_decode_key(struct perf_kvm_stat *kvm, ...@@ -91,7 +90,7 @@ void exit_event_decode_key(struct perf_kvm_stat *kvm,
const char *exit_reason = get_exit_reason(kvm, key->exit_reasons, const char *exit_reason = get_exit_reason(kvm, key->exit_reasons,
key->key); key->key);
scnprintf(decode, DECODE_STR_LEN, "%s", exit_reason); scnprintf(decode, decode_str_len, "%s", exit_reason);
} }
static bool register_kvm_events_ops(struct perf_kvm_stat *kvm) static bool register_kvm_events_ops(struct perf_kvm_stat *kvm)
...@@ -357,7 +356,7 @@ static bool handle_end_event(struct perf_kvm_stat *kvm, ...@@ -357,7 +356,7 @@ static bool handle_end_event(struct perf_kvm_stat *kvm,
time_diff = sample->time - time_begin; time_diff = sample->time - time_begin;
if (kvm->duration && time_diff > kvm->duration) { if (kvm->duration && time_diff > kvm->duration) {
char decode[DECODE_STR_LEN]; char decode[decode_str_len];
kvm->events_ops->decode_key(kvm, &event->key, decode); kvm->events_ops->decode_key(kvm, &event->key, decode);
if (!skip_event(decode)) { if (!skip_event(decode)) {
...@@ -385,7 +384,8 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread, ...@@ -385,7 +384,8 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
return NULL; return NULL;
} }
vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample, VCPU_ID); vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample,
vcpu_id_str);
thread__set_priv(thread, vcpu_record); thread__set_priv(thread, vcpu_record);
} }
...@@ -574,7 +574,7 @@ static void show_timeofday(void) ...@@ -574,7 +574,7 @@ static void show_timeofday(void)
static void print_result(struct perf_kvm_stat *kvm) static void print_result(struct perf_kvm_stat *kvm)
{ {
char decode[DECODE_STR_LEN]; char decode[decode_str_len];
struct kvm_event *event; struct kvm_event *event;
int vcpu = kvm->trace_vcpu; int vcpu = kvm->trace_vcpu;
...@@ -585,7 +585,7 @@ static void print_result(struct perf_kvm_stat *kvm) ...@@ -585,7 +585,7 @@ static void print_result(struct perf_kvm_stat *kvm)
pr_info("\n\n"); pr_info("\n\n");
print_vcpu_info(kvm); print_vcpu_info(kvm);
pr_info("%*s ", DECODE_STR_LEN, kvm->events_ops->name); pr_info("%*s ", decode_str_len, kvm->events_ops->name);
pr_info("%10s ", "Samples"); pr_info("%10s ", "Samples");
pr_info("%9s ", "Samples%"); pr_info("%9s ", "Samples%");
...@@ -604,7 +604,7 @@ static void print_result(struct perf_kvm_stat *kvm) ...@@ -604,7 +604,7 @@ static void print_result(struct perf_kvm_stat *kvm)
min = get_event_min(event, vcpu); min = get_event_min(event, vcpu);
kvm->events_ops->decode_key(kvm, &event->key, decode); kvm->events_ops->decode_key(kvm, &event->key, decode);
pr_info("%*s ", DECODE_STR_LEN, decode); pr_info("%*s ", decode_str_len, decode);
pr_info("%10llu ", (unsigned long long)ecount); pr_info("%10llu ", (unsigned long long)ecount);
pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100); pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100);
pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100); pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100);
...@@ -1132,6 +1132,11 @@ static int kvm_events_report_vcpu(struct perf_kvm_stat *kvm) ...@@ -1132,6 +1132,11 @@ static int kvm_events_report_vcpu(struct perf_kvm_stat *kvm)
_p; \ _p; \
}) })
int __weak setup_kvm_events_tp(struct perf_kvm_stat *kvm __maybe_unused)
{
return 0;
}
static int static int
kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv) kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
{ {
...@@ -1148,7 +1153,14 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv) ...@@ -1148,7 +1153,14 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
NULL NULL
}; };
const char * const *events_tp; const char * const *events_tp;
int ret;
events_tp_size = 0; events_tp_size = 0;
ret = setup_kvm_events_tp(kvm);
if (ret < 0) {
pr_err("Unable to setup the kvm tracepoints\n");
return ret;
}
for (events_tp = kvm_events_tp; *events_tp; events_tp++) for (events_tp = kvm_events_tp; *events_tp; events_tp++)
events_tp_size++; events_tp_size++;
...@@ -1377,6 +1389,12 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, ...@@ -1377,6 +1389,12 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
/* /*
* generate the event list * generate the event list
*/ */
err = setup_kvm_events_tp(kvm);
if (err < 0) {
pr_err("Unable to setup the kvm tracepoints\n");
return err;
}
kvm->evlist = kvm_live_event_list(); kvm->evlist = kvm_live_event_list();
if (kvm->evlist == NULL) { if (kvm->evlist == NULL) {
err = -1; err = -1;
......
...@@ -49,7 +49,9 @@ struct record { ...@@ -49,7 +49,9 @@ struct record {
const char *progname; const char *progname;
int realtime_prio; int realtime_prio;
bool no_buildid; bool no_buildid;
bool no_buildid_set;
bool no_buildid_cache; bool no_buildid_cache;
bool no_buildid_cache_set;
bool buildid_all; bool buildid_all;
unsigned long long samples; unsigned long long samples;
}; };
...@@ -1097,9 +1099,11 @@ struct option __record_options[] = { ...@@ -1097,9 +1099,11 @@ struct option __record_options[] = {
OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"), OPT_BOOLEAN('P', "period", &record.opts.period, "Record the sample period"),
OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples, OPT_BOOLEAN('n', "no-samples", &record.opts.no_samples,
"don't sample"), "don't sample"),
OPT_BOOLEAN('N', "no-buildid-cache", &record.no_buildid_cache, OPT_BOOLEAN_SET('N', "no-buildid-cache", &record.no_buildid_cache,
&record.no_buildid_cache_set,
"do not update the buildid cache"), "do not update the buildid cache"),
OPT_BOOLEAN('B', "no-buildid", &record.no_buildid, OPT_BOOLEAN_SET('B', "no-buildid", &record.no_buildid,
&record.no_buildid_set,
"do not collect buildids in perf.data"), "do not collect buildids in perf.data"),
OPT_CALLBACK('G', "cgroup", &record.evlist, "name", OPT_CALLBACK('G', "cgroup", &record.evlist, "name",
"monitor event in cgroup name only", "monitor event in cgroup name only",
......
...@@ -61,50 +61,45 @@ endif ...@@ -61,50 +61,45 @@ endif
ifeq ($(LIBUNWIND_LIBS),) ifeq ($(LIBUNWIND_LIBS),)
NO_LIBUNWIND := 1 NO_LIBUNWIND := 1
else endif
# #
# For linking with debug library, run like: # For linking with debug library, run like:
# #
# make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/ # make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/
# #
ifdef LIBUNWIND_DIR ifdef LIBUNWIND_DIR
LIBUNWIND_CFLAGS = -I$(LIBUNWIND_DIR)/include LIBUNWIND_CFLAGS = -I$(LIBUNWIND_DIR)/include
LIBUNWIND_LDFLAGS = -L$(LIBUNWIND_DIR)/lib LIBUNWIND_LDFLAGS = -L$(LIBUNWIND_DIR)/lib
endif
LIBUNWIND_LDFLAGS += $(LIBUNWIND_LIBS)
# Set per-feature check compilation flags
FEATURE_CHECK_CFLAGS-libunwind = $(LIBUNWIND_CFLAGS)
FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS)
FEATURE_CHECK_CFLAGS-libunwind-debug-frame = $(LIBUNWIND_CFLAGS)
FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS)
endif endif
LIBUNWIND_LDFLAGS += $(LIBUNWIND_LIBS)
# Set per-feature check compilation flags
FEATURE_CHECK_CFLAGS-libunwind = $(LIBUNWIND_CFLAGS)
FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS)
FEATURE_CHECK_CFLAGS-libunwind-debug-frame = $(LIBUNWIND_CFLAGS)
FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS)
ifeq ($(NO_PERF_REGS),0) ifeq ($(NO_PERF_REGS),0)
CFLAGS += -DHAVE_PERF_REGS_SUPPORT CFLAGS += -DHAVE_PERF_REGS_SUPPORT
endif endif
ifndef NO_LIBELF # for linking with debug library, run like:
# for linking with debug library, run like: # make DEBUG=1 LIBDW_DIR=/opt/libdw/
# make DEBUG=1 LIBDW_DIR=/opt/libdw/ ifdef LIBDW_DIR
ifdef LIBDW_DIR
LIBDW_CFLAGS := -I$(LIBDW_DIR)/include LIBDW_CFLAGS := -I$(LIBDW_DIR)/include
LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
endif
FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS)
FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw
endif endif
FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS)
FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw
ifdef LIBBABELTRACE # for linking with debug library, run like:
# for linking with debug library, run like: # make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/
# make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/ ifdef LIBBABELTRACE_DIR
ifdef LIBBABELTRACE_DIR
LIBBABELTRACE_CFLAGS := -I$(LIBBABELTRACE_DIR)/include LIBBABELTRACE_CFLAGS := -I$(LIBBABELTRACE_DIR)/include
LIBBABELTRACE_LDFLAGS := -L$(LIBBABELTRACE_DIR)/lib LIBBABELTRACE_LDFLAGS := -L$(LIBBABELTRACE_DIR)/lib
endif
FEATURE_CHECK_CFLAGS-libbabeltrace := $(LIBBABELTRACE_CFLAGS)
FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf
endif endif
FEATURE_CHECK_CFLAGS-libbabeltrace := $(LIBBABELTRACE_CFLAGS)
FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf
FEATURE_CHECK_CFLAGS-bpf = -I. -I$(srctree)/tools/include -I$(srctree)/arch/$(ARCH)/include/uapi -I$(srctree)/include/uapi FEATURE_CHECK_CFLAGS-bpf = -I. -I$(srctree)/tools/include -I$(srctree)/arch/$(ARCH)/include/uapi -I$(srctree)/include/uapi
# include ARCH specific config # include ARCH specific config
...@@ -145,28 +140,26 @@ ifdef PARSER_DEBUG ...@@ -145,28 +140,26 @@ ifdef PARSER_DEBUG
$(call detected_var,PARSER_DEBUG_FLEX) $(call detected_var,PARSER_DEBUG_FLEX)
endif endif
ifndef NO_LIBPYTHON # Try different combinations to accommodate systems that only have
# Try different combinations to accommodate systems that only have # python[2][-config] in weird combinations but always preferring
# python[2][-config] in weird combinations but always preferring # python2 and python2-config as per pep-0394. If we catch a
# python2 and python2-config as per pep-0394. If we catch a # python[-config] in version 3, the version check will kill it.
# python[-config] in version 3, the version check will kill it. PYTHON2 := $(if $(call get-executable,python2),python2,python)
PYTHON2 := $(if $(call get-executable,python2),python2,python) override PYTHON := $(call get-executable-or-default,PYTHON,$(PYTHON2))
override PYTHON := $(call get-executable-or-default,PYTHON,$(PYTHON2)) PYTHON2_CONFIG := \
PYTHON2_CONFIG := \
$(if $(call get-executable,$(PYTHON)-config),$(PYTHON)-config,python-config) $(if $(call get-executable,$(PYTHON)-config),$(PYTHON)-config,python-config)
override PYTHON_CONFIG := \ override PYTHON_CONFIG := \
$(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON2_CONFIG)) $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON2_CONFIG))
PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG)) PYTHON_CONFIG_SQ := $(call shell-sq,$(PYTHON_CONFIG))
PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null) PYTHON_EMBED_LDOPTS := $(shell $(PYTHON_CONFIG_SQ) --ldflags 2>/dev/null)
PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null) PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
FEATURE_CHECK_CFLAGS-libpython := $(PYTHON_EMBED_CCOPTS) FEATURE_CHECK_CFLAGS-libpython := $(PYTHON_EMBED_CCOPTS)
FEATURE_CHECK_LDFLAGS-libpython := $(PYTHON_EMBED_LDOPTS) FEATURE_CHECK_LDFLAGS-libpython := $(PYTHON_EMBED_LDOPTS)
FEATURE_CHECK_CFLAGS-libpython-version := $(PYTHON_EMBED_CCOPTS) FEATURE_CHECK_CFLAGS-libpython-version := $(PYTHON_EMBED_CCOPTS)
FEATURE_CHECK_LDFLAGS-libpython-version := $(PYTHON_EMBED_LDOPTS) FEATURE_CHECK_LDFLAGS-libpython-version := $(PYTHON_EMBED_LDOPTS)
endif
CFLAGS += -fno-omit-frame-pointer CFLAGS += -fno-omit-frame-pointer
CFLAGS += -ggdb3 CFLAGS += -ggdb3
......
...@@ -29,14 +29,59 @@ ...@@ -29,14 +29,59 @@
static int fd1; static int fd1;
static int fd2; static int fd2;
static int fd3;
static int overflows; static int overflows;
static int overflows_2;
volatile long the_var;
/*
* Use ASM to ensure watchpoint and breakpoint can be triggered
* at one instruction.
*/
#if defined (__x86_64__)
extern void __test_function(volatile long *ptr);
asm (
".globl __test_function\n"
"__test_function:\n"
"incq (%rdi)\n"
"ret\n");
#elif defined (__aarch64__)
extern void __test_function(volatile long *ptr);
asm (
".globl __test_function\n"
"__test_function:\n"
"str x30, [x0]\n"
"ret\n");
#else
static void __test_function(volatile long *ptr)
{
*ptr = 0x1234;
}
#endif
__attribute__ ((noinline)) __attribute__ ((noinline))
static int test_function(void) static int test_function(void)
{ {
__test_function(&the_var);
the_var++;
return time(NULL); return time(NULL);
} }
static void sig_handler_2(int signum __maybe_unused,
siginfo_t *oh __maybe_unused,
void *uc __maybe_unused)
{
overflows_2++;
if (overflows_2 > 10) {
ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
}
}
static void sig_handler(int signum __maybe_unused, static void sig_handler(int signum __maybe_unused,
siginfo_t *oh __maybe_unused, siginfo_t *oh __maybe_unused,
void *uc __maybe_unused) void *uc __maybe_unused)
...@@ -54,10 +99,11 @@ static void sig_handler(int signum __maybe_unused, ...@@ -54,10 +99,11 @@ static void sig_handler(int signum __maybe_unused,
*/ */
ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0); ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0); ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
} }
} }
static int bp_event(void *fn, int setup_signal) static int __event(bool is_x, void *addr, int signal)
{ {
struct perf_event_attr pe; struct perf_event_attr pe;
int fd; int fd;
...@@ -67,8 +113,8 @@ static int bp_event(void *fn, int setup_signal) ...@@ -67,8 +113,8 @@ static int bp_event(void *fn, int setup_signal)
pe.size = sizeof(struct perf_event_attr); pe.size = sizeof(struct perf_event_attr);
pe.config = 0; pe.config = 0;
pe.bp_type = HW_BREAKPOINT_X; pe.bp_type = is_x ? HW_BREAKPOINT_X : HW_BREAKPOINT_W;
pe.bp_addr = (unsigned long) fn; pe.bp_addr = (unsigned long) addr;
pe.bp_len = sizeof(long); pe.bp_len = sizeof(long);
pe.sample_period = 1; pe.sample_period = 1;
...@@ -86,17 +132,25 @@ static int bp_event(void *fn, int setup_signal) ...@@ -86,17 +132,25 @@ static int bp_event(void *fn, int setup_signal)
return TEST_FAIL; return TEST_FAIL;
} }
if (setup_signal) {
fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC); fcntl(fd, F_SETFL, O_RDWR|O_NONBLOCK|O_ASYNC);
fcntl(fd, F_SETSIG, SIGIO); fcntl(fd, F_SETSIG, signal);
fcntl(fd, F_SETOWN, getpid()); fcntl(fd, F_SETOWN, getpid());
}
ioctl(fd, PERF_EVENT_IOC_RESET, 0); ioctl(fd, PERF_EVENT_IOC_RESET, 0);
return fd; return fd;
} }
static int bp_event(void *addr, int signal)
{
return __event(true, addr, signal);
}
static int wp_event(void *addr, int signal)
{
return __event(false, addr, signal);
}
static long long bp_count(int fd) static long long bp_count(int fd)
{ {
long long count; long long count;
...@@ -114,7 +168,7 @@ static long long bp_count(int fd) ...@@ -114,7 +168,7 @@ static long long bp_count(int fd)
int test__bp_signal(int subtest __maybe_unused) int test__bp_signal(int subtest __maybe_unused)
{ {
struct sigaction sa; struct sigaction sa;
long long count1, count2; long long count1, count2, count3;
/* setup SIGIO signal handler */ /* setup SIGIO signal handler */
memset(&sa, 0, sizeof(struct sigaction)); memset(&sa, 0, sizeof(struct sigaction));
...@@ -126,21 +180,52 @@ int test__bp_signal(int subtest __maybe_unused) ...@@ -126,21 +180,52 @@ int test__bp_signal(int subtest __maybe_unused)
return TEST_FAIL; return TEST_FAIL;
} }
sa.sa_sigaction = (void *) sig_handler_2;
if (sigaction(SIGUSR1, &sa, NULL) < 0) {
pr_debug("failed setting up signal handler 2\n");
return TEST_FAIL;
}
/* /*
* We create following events: * We create following events:
* *
* fd1 - breakpoint event on test_function with SIGIO * fd1 - breakpoint event on __test_function with SIGIO
* signal configured. We should get signal * signal configured. We should get signal
* notification each time the breakpoint is hit * notification each time the breakpoint is hit
* *
* fd2 - breakpoint event on sig_handler without SIGIO * fd2 - breakpoint event on sig_handler with SIGUSR1
* configured. We should get SIGUSR1 each time when
* breakpoint is hit
*
* fd3 - watchpoint event on __test_function with SIGIO
* configured. * configured.
* *
* Following processing should happen: * Following processing should happen:
* - execute test_function * Exec: Action: Result:
* - fd1 event breakpoint hit -> count1 == 1 * incq (%rdi) - fd1 event breakpoint hit -> count1 == 1
* - SIGIO is delivered -> overflows == 1 * - SIGIO is delivered
* - fd2 event breakpoint hit -> count2 == 1 * sig_handler - fd2 event breakpoint hit -> count2 == 1
* - SIGUSR1 is delivered
* sig_handler_2 -> overflows_2 == 1 (nested signal)
* sys_rt_sigreturn - return from sig_handler_2
* overflows++ -> overflows = 1
* sys_rt_sigreturn - return from sig_handler
* incq (%rdi) - fd3 event watchpoint hit -> count3 == 1 (wp and bp in one insn)
* - SIGIO is delivered
* sig_handler - fd2 event breakpoint hit -> count2 == 2
* - SIGUSR1 is delivered
* sig_handler_2 -> overflows_2 == 2 (nested signal)
* sys_rt_sigreturn - return from sig_handler_2
* overflows++ -> overflows = 2
* sys_rt_sigreturn - return from sig_handler
* the_var++ - fd3 event watchpoint hit -> count3 == 2 (standalone watchpoint)
* - SIGIO is delivered
* sig_handler - fd2 event breakpoint hit -> count2 == 3
* - SIGUSR1 is delivered
* sig_handler_2 -> overflows_2 == 3 (nested signal)
* sys_rt_sigreturn - return from sig_handler_2
* overflows++ -> overflows == 3
* sys_rt_sigreturn - return from sig_handler
* *
* The test case check following error conditions: * The test case check following error conditions:
* - we get stuck in signal handler because of debug * - we get stuck in signal handler because of debug
...@@ -152,11 +237,13 @@ int test__bp_signal(int subtest __maybe_unused) ...@@ -152,11 +237,13 @@ int test__bp_signal(int subtest __maybe_unused)
* *
*/ */
fd1 = bp_event(test_function, 1); fd1 = bp_event(__test_function, SIGIO);
fd2 = bp_event(sig_handler, 0); fd2 = bp_event(sig_handler, SIGUSR1);
fd3 = wp_event((void *)&the_var, SIGIO);
ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0); ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0);
ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0); ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0);
ioctl(fd3, PERF_EVENT_IOC_ENABLE, 0);
/* /*
* Kick off the test by trigering 'fd1' * Kick off the test by trigering 'fd1'
...@@ -166,15 +253,18 @@ int test__bp_signal(int subtest __maybe_unused) ...@@ -166,15 +253,18 @@ int test__bp_signal(int subtest __maybe_unused)
ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0); ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0);
ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0); ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0);
ioctl(fd3, PERF_EVENT_IOC_DISABLE, 0);
count1 = bp_count(fd1); count1 = bp_count(fd1);
count2 = bp_count(fd2); count2 = bp_count(fd2);
count3 = bp_count(fd3);
close(fd1); close(fd1);
close(fd2); close(fd2);
close(fd3);
pr_debug("count1 %lld, count2 %lld, overflow %d\n", pr_debug("count1 %lld, count2 %lld, count3 %lld, overflow %d, overflows_2 %d\n",
count1, count2, overflows); count1, count2, count3, overflows, overflows_2);
if (count1 != 1) { if (count1 != 1) {
if (count1 == 11) if (count1 == 11)
...@@ -183,12 +273,18 @@ int test__bp_signal(int subtest __maybe_unused) ...@@ -183,12 +273,18 @@ int test__bp_signal(int subtest __maybe_unused)
pr_debug("failed: wrong count for bp1%lld\n", count1); pr_debug("failed: wrong count for bp1%lld\n", count1);
} }
if (overflows != 1) if (overflows != 3)
pr_debug("failed: wrong overflow hit\n"); pr_debug("failed: wrong overflow hit\n");
if (count2 != 1) if (overflows_2 != 3)
pr_debug("failed: wrong overflow_2 hit\n");
if (count2 != 3)
pr_debug("failed: wrong count for bp2\n"); pr_debug("failed: wrong count for bp2\n");
return count1 == 1 && overflows == 1 && count2 == 1 ? if (count3 != 2)
pr_debug("failed: wrong count for bp3\n");
return count1 == 1 && overflows == 3 && count2 == 3 && overflows_2 == 3 && count3 == 2 ?
TEST_OK : TEST_FAIL; TEST_OK : TEST_FAIL;
} }
#include <stdio.h> #include <stdio.h>
#include <sys/epoll.h> #include <sys/epoll.h>
#include <util/util.h>
#include <util/bpf-loader.h> #include <util/bpf-loader.h>
#include <util/evlist.h> #include <util/evlist.h>
#include <linux/bpf.h>
#include <linux/filter.h>
#include <bpf/bpf.h>
#include "tests.h" #include "tests.h"
#include "llvm.h" #include "llvm.h"
#include "debug.h" #include "debug.h"
...@@ -243,6 +247,36 @@ const char *test__bpf_subtest_get_desc(int i) ...@@ -243,6 +247,36 @@ const char *test__bpf_subtest_get_desc(int i)
return bpf_testcase_table[i].desc; return bpf_testcase_table[i].desc;
} }
static int check_env(void)
{
int err;
unsigned int kver_int;
char license[] = "GPL";
struct bpf_insn insns[] = {
BPF_MOV64_IMM(BPF_REG_0, 1),
BPF_EXIT_INSN(),
};
err = fetch_kernel_version(&kver_int, NULL, 0);
if (err) {
pr_debug("Unable to get kernel version\n");
return err;
}
err = bpf_load_program(BPF_PROG_TYPE_KPROBE, insns,
sizeof(insns) / sizeof(insns[0]),
license, kver_int, NULL, 0);
if (err < 0) {
pr_err("Missing basic BPF support, skip this test: %s\n",
strerror(errno));
return err;
}
close(err);
return 0;
}
int test__bpf(int i) int test__bpf(int i)
{ {
int err; int err;
...@@ -255,6 +289,9 @@ int test__bpf(int i) ...@@ -255,6 +289,9 @@ int test__bpf(int i)
return TEST_SKIP; return TEST_SKIP;
} }
if (check_env())
return TEST_SKIP;
err = __test__bpf(i); err = __test__bpf(i);
return err; return err;
} }
......
...@@ -15,6 +15,7 @@ else ...@@ -15,6 +15,7 @@ else
PERF := . PERF := .
PERF_O := $(PERF) PERF_O := $(PERF)
O_OPT := O_OPT :=
FULL_O := $(shell readlink -f $(PERF_O) || echo $(PERF_O))
ifneq ($(O),) ifneq ($(O),)
FULL_O := $(shell readlink -f $(O) || echo $(O)) FULL_O := $(shell readlink -f $(O) || echo $(O))
...@@ -260,6 +261,8 @@ run := $(shell shuf -e $(run)) ...@@ -260,6 +261,8 @@ run := $(shell shuf -e $(run))
run_O := $(shell shuf -e $(run_O)) run_O := $(shell shuf -e $(run_O))
endif endif
max_width := $(shell echo $(run_O) | sed 's/ /\n/g' | wc -L)
ifdef DEBUG ifdef DEBUG
d := $(info run $(run)) d := $(info run $(run))
d := $(info run_O $(run_O)) d := $(info run_O $(run_O))
...@@ -273,7 +276,7 @@ $(run): ...@@ -273,7 +276,7 @@ $(run):
$(call clean) $(call clean)
@TMP_DEST=$$(mktemp -d); \ @TMP_DEST=$$(mktemp -d); \
cmd="cd $(PERF) && make -f $(MK) $(PARALLEL_OPT) $(O_OPT) DESTDIR=$$TMP_DEST $($@)"; \ cmd="cd $(PERF) && make -f $(MK) $(PARALLEL_OPT) $(O_OPT) DESTDIR=$$TMP_DEST $($@)"; \
echo "- $@: $$cmd" && echo $$cmd > $@ && \ printf "%*.*s: %s\n" $(max_width) $(max_width) "$@" "$$cmd" && echo $$cmd > $@ && \
( eval $$cmd ) >> $@ 2>&1; \ ( eval $$cmd ) >> $@ 2>&1; \
echo " test: $(call test,$@)" >> $@ 2>&1; \ echo " test: $(call test,$@)" >> $@ 2>&1; \
$(call test,$@) && \ $(call test,$@) && \
...@@ -284,7 +287,7 @@ $(run_O): ...@@ -284,7 +287,7 @@ $(run_O):
@TMP_O=$$(mktemp -d); \ @TMP_O=$$(mktemp -d); \
TMP_DEST=$$(mktemp -d); \ TMP_DEST=$$(mktemp -d); \
cmd="cd $(PERF) && make -f $(MK) $(PARALLEL_OPT) O=$$TMP_O DESTDIR=$$TMP_DEST $($(patsubst %_O,%,$@))"; \ cmd="cd $(PERF) && make -f $(MK) $(PARALLEL_OPT) O=$$TMP_O DESTDIR=$$TMP_DEST $($(patsubst %_O,%,$@))"; \
echo "- $@: $$cmd" && echo $$cmd > $@ && \ printf "%*.*s: %s\n" $(max_width) $(max_width) "$@" "$$cmd" && echo $$cmd > $@ && \
( eval $$cmd ) >> $@ 2>&1 && \ ( eval $$cmd ) >> $@ 2>&1 && \
echo " test: $(call test_O,$@)" >> $@ 2>&1; \ echo " test: $(call test_O,$@)" >> $@ 2>&1; \
$(call test_O,$@) && \ $(call test_O,$@) && \
...@@ -313,11 +316,43 @@ make_kernelsrc_tools: ...@@ -313,11 +316,43 @@ make_kernelsrc_tools:
(make -C ../../tools $(PARALLEL_OPT) $(K_O_OPT) perf) > $@ 2>&1 && \ (make -C ../../tools $(PARALLEL_OPT) $(K_O_OPT) perf) > $@ 2>&1 && \
test -x $(KERNEL_O)/tools/perf/perf && rm -f $@ || (cat $@ ; false) test -x $(KERNEL_O)/tools/perf/perf && rm -f $@ || (cat $@ ; false)
FEATURES_DUMP_FILE := $(FULL_O)/BUILD_TEST_FEATURE_DUMP
FEATURES_DUMP_FILE_STATIC := $(FULL_O)/BUILD_TEST_FEATURE_DUMP_STATIC
all: $(run) $(run_O) tarpkg make_kernelsrc make_kernelsrc_tools all: $(run) $(run_O) tarpkg make_kernelsrc make_kernelsrc_tools
@echo OK @echo OK
@rm -f $(FEATURES_DUMP_FILE) $(FEATURES_DUMP_FILE_STATIC)
out: $(run_O) out: $(run_O)
@echo OK @echo OK
@rm -f $(FEATURES_DUMP_FILE) $(FEATURES_DUMP_FILE_STATIC)
ifeq ($(REUSE_FEATURES_DUMP),1)
$(FEATURES_DUMP_FILE):
$(call clean)
@cmd="cd $(PERF) && make FEATURE_DUMP_COPY=$@ $(O_OPT) feature-dump"; \
echo "- $@: $$cmd" && echo $$cmd && \
( eval $$cmd ) > /dev/null 2>&1
$(FEATURES_DUMP_FILE_STATIC):
$(call clean)
@cmd="cd $(PERF) && make FEATURE_DUMP_COPY=$@ $(O_OPT) LDFLAGS='-static' feature-dump"; \
echo "- $@: $$cmd" && echo $$cmd && \
( eval $$cmd ) > /dev/null 2>&1
# Add feature dump dependency for run/run_O targets
$(foreach t,$(run) $(run_O),$(eval \
$(t): $(if $(findstring make_static,$(t)),\
$(FEATURES_DUMP_FILE_STATIC),\
$(FEATURES_DUMP_FILE))))
# Append 'FEATURES_DUMP=' option to all test cases. For example:
# make_no_libbpf: NO_LIBBPF=1 --> NO_LIBBPF=1 FEATURES_DUMP=/a/b/BUILD_TEST_FEATURE_DUMP
# make_static: LDFLAGS=-static --> LDFLAGS=-static FEATURES_DUMP=/a/b/BUILD_TEST_FEATURE_DUMP_STATIC
$(foreach t,$(run),$(if $(findstring make_static,$(t)),\
$(eval $(t) := $($(t)) FEATURES_DUMP=$(FEATURES_DUMP_FILE_STATIC)),\
$(eval $(t) := $($(t)) FEATURES_DUMP=$(FEATURES_DUMP_FILE))))
endif
.PHONY: all $(run) $(run_O) tarpkg clean make_kernelsrc make_kernelsrc_tools .PHONY: all $(run) $(run_O) tarpkg clean make_kernelsrc make_kernelsrc_tools
endif # ifndef MK endif # ifndef MK
...@@ -478,10 +478,11 @@ void auxtrace_heap__pop(struct auxtrace_heap *heap) ...@@ -478,10 +478,11 @@ void auxtrace_heap__pop(struct auxtrace_heap *heap)
heap_array[last].ordinal); heap_array[last].ordinal);
} }
size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr) size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr,
struct perf_evlist *evlist)
{ {
if (itr) if (itr)
return itr->info_priv_size(itr); return itr->info_priv_size(itr, evlist);
return 0; return 0;
} }
...@@ -852,7 +853,7 @@ int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr, ...@@ -852,7 +853,7 @@ int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,
int err; int err;
pr_debug2("Synthesizing auxtrace information\n"); pr_debug2("Synthesizing auxtrace information\n");
priv_size = auxtrace_record__info_priv_size(itr); priv_size = auxtrace_record__info_priv_size(itr, session->evlist);
ev = zalloc(sizeof(struct auxtrace_info_event) + priv_size); ev = zalloc(sizeof(struct auxtrace_info_event) + priv_size);
if (!ev) if (!ev)
return -ENOMEM; return -ENOMEM;
......
...@@ -293,7 +293,8 @@ struct auxtrace_record { ...@@ -293,7 +293,8 @@ struct auxtrace_record {
int (*recording_options)(struct auxtrace_record *itr, int (*recording_options)(struct auxtrace_record *itr,
struct perf_evlist *evlist, struct perf_evlist *evlist,
struct record_opts *opts); struct record_opts *opts);
size_t (*info_priv_size)(struct auxtrace_record *itr); size_t (*info_priv_size)(struct auxtrace_record *itr,
struct perf_evlist *evlist);
int (*info_fill)(struct auxtrace_record *itr, int (*info_fill)(struct auxtrace_record *itr,
struct perf_session *session, struct perf_session *session,
struct auxtrace_info_event *auxtrace_info, struct auxtrace_info_event *auxtrace_info,
...@@ -429,7 +430,8 @@ int auxtrace_parse_snapshot_options(struct auxtrace_record *itr, ...@@ -429,7 +430,8 @@ int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,
int auxtrace_record__options(struct auxtrace_record *itr, int auxtrace_record__options(struct auxtrace_record *itr,
struct perf_evlist *evlist, struct perf_evlist *evlist,
struct record_opts *opts); struct record_opts *opts);
size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr); size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr,
struct perf_evlist *evlist);
int auxtrace_record__info_fill(struct auxtrace_record *itr, int auxtrace_record__info_fill(struct auxtrace_record *itr,
struct perf_session *session, struct perf_session *session,
struct auxtrace_info_event *auxtrace_info, struct auxtrace_info_event *auxtrace_info,
......
...@@ -211,6 +211,7 @@ static int machine__write_buildid_table(struct machine *machine, int fd) ...@@ -211,6 +211,7 @@ static int machine__write_buildid_table(struct machine *machine, int fd)
dsos__for_each_with_build_id(pos, &machine->dsos.head) { dsos__for_each_with_build_id(pos, &machine->dsos.head) {
const char *name; const char *name;
size_t name_len; size_t name_len;
bool in_kernel = false;
if (!pos->hit) if (!pos->hit)
continue; continue;
...@@ -227,8 +228,11 @@ static int machine__write_buildid_table(struct machine *machine, int fd) ...@@ -227,8 +228,11 @@ static int machine__write_buildid_table(struct machine *machine, int fd)
name_len = pos->long_name_len + 1; name_len = pos->long_name_len + 1;
} }
in_kernel = pos->kernel ||
is_kernel_module(name,
PERF_RECORD_MISC_CPUMODE_UNKNOWN);
err = write_buildid(name, name_len, pos->build_id, machine->pid, err = write_buildid(name, name_len, pos->build_id, machine->pid,
pos->kernel ? kmisc : umisc, fd); in_kernel ? kmisc : umisc, fd);
if (err) if (err)
break; break;
} }
......
...@@ -122,6 +122,7 @@ void exit_event_decode_key(struct perf_kvm_stat *kvm, ...@@ -122,6 +122,7 @@ void exit_event_decode_key(struct perf_kvm_stat *kvm,
bool kvm_exit_event(struct perf_evsel *evsel); bool kvm_exit_event(struct perf_evsel *evsel);
bool kvm_entry_event(struct perf_evsel *evsel); bool kvm_entry_event(struct perf_evsel *evsel);
int setup_kvm_events_tp(struct perf_kvm_stat *kvm);
#define define_exit_reasons_table(name, symbols) \ #define define_exit_reasons_table(name, symbols) \
static struct exit_reasons_table name[] = { \ static struct exit_reasons_table name[] = { \
...@@ -133,8 +134,13 @@ bool kvm_entry_event(struct perf_evsel *evsel); ...@@ -133,8 +134,13 @@ bool kvm_entry_event(struct perf_evsel *evsel);
*/ */
int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid); int cpu_isa_init(struct perf_kvm_stat *kvm, const char *cpuid);
extern const char * const kvm_events_tp[]; extern const char *kvm_events_tp[];
extern struct kvm_reg_events_ops kvm_reg_events_ops[]; extern struct kvm_reg_events_ops kvm_reg_events_ops[];
extern const char * const kvm_skip_events[]; extern const char * const kvm_skip_events[];
extern const char *vcpu_id_str;
extern const int decode_str_len;
extern const char *kvm_exit_reason;
extern const char *kvm_entry_trace;
extern const char *kvm_exit_trace;
#endif /* __PERF_KVM_STAT_H */ #endif /* __PERF_KVM_STAT_H */
...@@ -701,3 +701,20 @@ bool is_regular_file(const char *file) ...@@ -701,3 +701,20 @@ bool is_regular_file(const char *file)
return S_ISREG(st.st_mode); return S_ISREG(st.st_mode);
} }
int fetch_current_timestamp(char *buf, size_t sz)
{
struct timeval tv;
struct tm tm;
char dt[32];
if (gettimeofday(&tv, NULL) || !localtime_r(&tv.tv_sec, &tm))
return -1;
if (!strftime(dt, sizeof(dt), "%Y%m%d%H%M%S", &tm))
return -1;
scnprintf(buf, sz, "%s%02u", dt, (unsigned)tv.tv_usec / 10000);
return 0;
}
...@@ -344,5 +344,6 @@ int fetch_kernel_version(unsigned int *puint, ...@@ -344,5 +344,6 @@ int fetch_kernel_version(unsigned int *puint,
const char *perf_tip(const char *dirpath); const char *perf_tip(const char *dirpath);
bool is_regular_file(const char *file); bool is_regular_file(const char *file);
int fetch_current_timestamp(char *buf, size_t sz);
#endif /* GIT_COMPAT_UTIL_H */ #endif /* GIT_COMPAT_UTIL_H */
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