diff options
Diffstat (limited to 'tools/perf/arch/x86')
-rw-r--r-- | tools/perf/arch/x86/include/arch-tests.h | 1 | ||||
-rw-r--r-- | tools/perf/arch/x86/tests/Build | 2 | ||||
-rw-r--r-- | tools/perf/arch/x86/tests/arch-tests.c | 15 | ||||
-rw-r--r-- | tools/perf/arch/x86/tests/intel-pt-test.c (renamed from tools/perf/arch/x86/tests/intel-pt-pkt-decoder-test.c) | 154 | ||||
-rw-r--r-- | tools/perf/arch/x86/tests/sample-parsing.c | 1 | ||||
-rw-r--r-- | tools/perf/arch/x86/util/Build | 2 | ||||
-rw-r--r-- | tools/perf/arch/x86/util/event.c | 2 | ||||
-rw-r--r-- | tools/perf/arch/x86/util/intel-pt.c | 4 | ||||
-rw-r--r-- | tools/perf/arch/x86/util/iostat.c | 4 | ||||
-rw-r--r-- | tools/perf/arch/x86/util/tsc.c | 1 | ||||
-rw-r--r-- | tools/perf/arch/x86/util/unwind-libdw.c | 2 |
11 files changed, 181 insertions, 7 deletions
diff --git a/tools/perf/arch/x86/include/arch-tests.h b/tools/perf/arch/x86/include/arch-tests.h index 6a1a1b3c0827..902e9ea9b99e 100644 --- a/tools/perf/arch/x86/include/arch-tests.h +++ b/tools/perf/arch/x86/include/arch-tests.h @@ -8,6 +8,7 @@ struct test_suite; int test__rdpmc(struct test_suite *test, int subtest); int test__insn_x86(struct test_suite *test, int subtest); int test__intel_pt_pkt_decoder(struct test_suite *test, int subtest); +int test__intel_pt_hybrid_compat(struct test_suite *test, int subtest); int test__bp_modify(struct test_suite *test, int subtest); int test__x86_sample_parsing(struct test_suite *test, int subtest); diff --git a/tools/perf/arch/x86/tests/Build b/tools/perf/arch/x86/tests/Build index 70b5bcbc15df..6f4e8636c3bf 100644 --- a/tools/perf/arch/x86/tests/Build +++ b/tools/perf/arch/x86/tests/Build @@ -3,5 +3,5 @@ perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o perf-y += arch-tests.o perf-y += sample-parsing.o -perf-$(CONFIG_AUXTRACE) += insn-x86.o intel-pt-pkt-decoder-test.o +perf-$(CONFIG_AUXTRACE) += insn-x86.o intel-pt-test.o perf-$(CONFIG_X86_64) += bp-modify.o diff --git a/tools/perf/arch/x86/tests/arch-tests.c b/tools/perf/arch/x86/tests/arch-tests.c index 04018b8aa85b..aae6ea0fe52b 100644 --- a/tools/perf/arch/x86/tests/arch-tests.c +++ b/tools/perf/arch/x86/tests/arch-tests.c @@ -5,7 +5,18 @@ #ifdef HAVE_AUXTRACE_SUPPORT DEFINE_SUITE("x86 instruction decoder - new instructions", insn_x86); -DEFINE_SUITE("Intel PT packet decoder", intel_pt_pkt_decoder); + +static struct test_case intel_pt_tests[] = { + TEST_CASE("Intel PT packet decoder", intel_pt_pkt_decoder), + TEST_CASE("Intel PT hybrid CPU compatibility", intel_pt_hybrid_compat), + { .name = NULL, } +}; + +struct test_suite suite__intel_pt = { + .desc = "Intel PT", + .test_cases = intel_pt_tests, +}; + #endif #if defined(__x86_64__) DEFINE_SUITE("x86 bp modify", bp_modify); @@ -18,7 +29,7 @@ struct test_suite *arch_tests[] = { #endif #ifdef HAVE_AUXTRACE_SUPPORT &suite__insn_x86, - &suite__intel_pt_pkt_decoder, + &suite__intel_pt, #endif #if defined(__x86_64__) &suite__bp_modify, diff --git a/tools/perf/arch/x86/tests/intel-pt-pkt-decoder-test.c b/tools/perf/arch/x86/tests/intel-pt-test.c index 42237656f453..70b7f79396b1 100644 --- a/tools/perf/arch/x86/tests/intel-pt-pkt-decoder-test.c +++ b/tools/perf/arch/x86/tests/intel-pt-test.c @@ -1,12 +1,17 @@ // SPDX-License-Identifier: GPL-2.0 +#include <linux/compiler.h> +#include <linux/bits.h> #include <string.h> +#include <cpuid.h> +#include <sched.h> #include "intel-pt-decoder/intel-pt-pkt-decoder.h" #include "debug.h" #include "tests/tests.h" #include "arch-tests.h" +#include "cpumap.h" /** * struct test_data - Test data. @@ -313,3 +318,152 @@ int test__intel_pt_pkt_decoder(struct test_suite *test __maybe_unused, int subte return TEST_OK; } + +static int setaffinity(int cpu) +{ + cpu_set_t cpu_set; + + CPU_ZERO(&cpu_set); + CPU_SET(cpu, &cpu_set); + if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set)) { + pr_debug("sched_setaffinity() failed for CPU %d\n", cpu); + return -1; + } + return 0; +} + +#define INTEL_PT_ADDR_FILT_CNT_MASK GENMASK(2, 0) +#define INTEL_PT_SUBLEAF_CNT 2 +#define CPUID_REG_CNT 4 + +struct cpuid_result { + union { + struct { + unsigned int eax; + unsigned int ebx; + unsigned int ecx; + unsigned int edx; + }; + unsigned int reg[CPUID_REG_CNT]; + }; +}; + +struct pt_caps { + struct cpuid_result subleaf[INTEL_PT_SUBLEAF_CNT]; +}; + +static int get_pt_caps(int cpu, struct pt_caps *caps) +{ + struct cpuid_result r; + int i; + + if (setaffinity(cpu)) + return -1; + + memset(caps, 0, sizeof(*caps)); + + for (i = 0; i < INTEL_PT_SUBLEAF_CNT; i++) { + __get_cpuid_count(20, i, &r.eax, &r.ebx, &r.ecx, &r.edx); + pr_debug("CPU %d CPUID leaf 20 subleaf %d\n", cpu, i); + pr_debug("eax = 0x%08x\n", r.eax); + pr_debug("ebx = 0x%08x\n", r.ebx); + pr_debug("ecx = 0x%08x\n", r.ecx); + pr_debug("edx = 0x%08x\n", r.edx); + caps->subleaf[i] = r; + } + + return 0; +} + +static bool is_hydrid(void) +{ + unsigned int eax, ebx, ecx, edx = 0; + bool result; + + __get_cpuid_count(7, 0, &eax, &ebx, &ecx, &edx); + result = edx & BIT(15); + pr_debug("Is %shybrid : CPUID leaf 7 subleaf 0 edx %#x (bit-15 indicates hybrid)\n", + result ? "" : "not ", edx); + return result; +} + +static int compare_caps(int cpu, struct pt_caps *caps, struct pt_caps *caps0) +{ + struct pt_caps mask = { /* Mask of bits to check*/ + .subleaf = { + [0] = { + .ebx = GENMASK(8, 0), + .ecx = GENMASK(3, 0), + }, + [1] = { + .eax = GENMASK(31, 16), + .ebx = GENMASK(31, 0), + } + } + }; + unsigned int m, reg, reg0; + int ret = 0; + int i, j; + + for (i = 0; i < INTEL_PT_SUBLEAF_CNT; i++) { + for (j = 0; j < CPUID_REG_CNT; j++) { + m = mask.subleaf[i].reg[j]; + reg = m & caps->subleaf[i].reg[j]; + reg0 = m & caps0->subleaf[i].reg[j]; + if ((reg & reg0) != reg0) { + pr_debug("CPU %d subleaf %d reg %d FAIL %#x vs %#x\n", + cpu, i, j, reg, reg0); + ret = -1; + } + } + } + + m = INTEL_PT_ADDR_FILT_CNT_MASK; + reg = m & caps->subleaf[1].eax; + reg0 = m & caps0->subleaf[1].eax; + if (reg < reg0) { + pr_debug("CPU %d subleaf 1 reg 0 FAIL address filter count %#x vs %#x\n", + cpu, reg, reg0); + ret = -1; + } + + if (!ret) + pr_debug("CPU %d OK\n", cpu); + + return ret; +} + +int test__intel_pt_hybrid_compat(struct test_suite *test, int subtest) +{ + int max_cpu = cpu__max_cpu().cpu; + struct pt_caps last_caps; + struct pt_caps caps0; + int ret = TEST_OK; + int cpu; + + if (!is_hydrid()) { + test->test_cases[subtest].skip_reason = "not hybrid"; + return TEST_SKIP; + } + + if (get_pt_caps(0, &caps0)) + return TEST_FAIL; + + for (cpu = 1, last_caps = caps0; cpu < max_cpu; cpu++) { + struct pt_caps caps; + + if (get_pt_caps(cpu, &caps)) { + pr_debug("CPU %d not found\n", cpu); + continue; + } + if (!memcmp(&caps, &last_caps, sizeof(caps))) { + pr_debug("CPU %d same caps as previous CPU\n", cpu); + continue; + } + if (compare_caps(cpu, &caps, &caps0)) + ret = TEST_FAIL; + last_caps = caps; + } + + return ret; +} diff --git a/tools/perf/arch/x86/tests/sample-parsing.c b/tools/perf/arch/x86/tests/sample-parsing.c index bfbd3662b69e..690c7c07e90d 100644 --- a/tools/perf/arch/x86/tests/sample-parsing.c +++ b/tools/perf/arch/x86/tests/sample-parsing.c @@ -10,6 +10,7 @@ #include "event.h" #include "evsel.h" #include "debug.h" +#include "util/sample.h" #include "util/synthetic-events.h" #include "tests/tests.h" diff --git a/tools/perf/arch/x86/util/Build b/tools/perf/arch/x86/util/Build index dbeb04cb336e..195ccfdef7aa 100644 --- a/tools/perf/arch/x86/util/Build +++ b/tools/perf/arch/x86/util/Build @@ -1,7 +1,7 @@ perf-y += header.o perf-y += tsc.o perf-y += pmu.o -perf-y += kvm-stat.o +perf-$(CONFIG_LIBTRACEEVENT) += kvm-stat.o perf-y += perf_regs.o perf-y += topdown.o perf-y += machine.o diff --git a/tools/perf/arch/x86/util/event.c b/tools/perf/arch/x86/util/event.c index e670f3547581..a3acefe6d0c6 100644 --- a/tools/perf/arch/x86/util/event.c +++ b/tools/perf/arch/x86/util/event.c @@ -2,6 +2,7 @@ #include <linux/types.h> #include <linux/string.h> #include <linux/zalloc.h> +#include <stdlib.h> #include "../../../util/event.h" #include "../../../util/synthetic-events.h" @@ -9,6 +10,7 @@ #include "../../../util/tool.h" #include "../../../util/map.h" #include "../../../util/debug.h" +#include "util/sample.h" #if defined(__x86_64__) diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c index af102f471e9f..1e39a034cee9 100644 --- a/tools/perf/arch/x86/util/intel-pt.c +++ b/tools/perf/arch/x86/util/intel-pt.c @@ -418,6 +418,7 @@ static int intel_pt_info_fill(struct auxtrace_record *itr, return 0; } +#ifdef HAVE_LIBTRACEEVENT static int intel_pt_track_switches(struct evlist *evlist) { const char *sched_switch = "sched:sched_switch"; @@ -439,6 +440,7 @@ static int intel_pt_track_switches(struct evlist *evlist) return 0; } +#endif static void intel_pt_valid_str(char *str, size_t len, u64 valid) { @@ -829,6 +831,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, ptr->have_sched_switch = 2; } } else { +#ifdef HAVE_LIBTRACEEVENT err = intel_pt_track_switches(evlist); if (err == -EPERM) pr_debug2("Unable to select sched:sched_switch\n"); @@ -836,6 +839,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr, return err; else ptr->have_sched_switch = 1; +#endif } } diff --git a/tools/perf/arch/x86/util/iostat.c b/tools/perf/arch/x86/util/iostat.c index 404de795ec0b..7eb0a7b00b95 100644 --- a/tools/perf/arch/x86/util/iostat.c +++ b/tools/perf/arch/x86/util/iostat.c @@ -449,7 +449,7 @@ void iostat_print_metric(struct perf_stat_config *config, struct evsel *evsel, void iostat_print_counters(struct evlist *evlist, struct perf_stat_config *config, struct timespec *ts, - char *prefix, iostat_print_counter_t print_cnt_cb) + char *prefix, iostat_print_counter_t print_cnt_cb, void *arg) { void *perf_device = NULL; struct evsel *counter = evlist__first(evlist); @@ -464,7 +464,7 @@ void iostat_print_counters(struct evlist *evlist, iostat_prefix(evlist, config, prefix, ts); fprintf(config->output, "\n%s", prefix); } - print_cnt_cb(config, counter, prefix); + print_cnt_cb(config, counter, arg); } fputc('\n', config->output); } diff --git a/tools/perf/arch/x86/util/tsc.c b/tools/perf/arch/x86/util/tsc.c index eb2b5195bd02..9b99f48b923c 100644 --- a/tools/perf/arch/x86/util/tsc.c +++ b/tools/perf/arch/x86/util/tsc.c @@ -2,6 +2,7 @@ #include <linux/types.h> #include <math.h> #include <string.h> +#include <stdlib.h> #include "../../../util/debug.h" #include "../../../util/tsc.h" diff --git a/tools/perf/arch/x86/util/unwind-libdw.c b/tools/perf/arch/x86/util/unwind-libdw.c index eea2bf87232b..ef71e8bf80bf 100644 --- a/tools/perf/arch/x86/util/unwind-libdw.c +++ b/tools/perf/arch/x86/util/unwind-libdw.c @@ -2,7 +2,7 @@ #include <elfutils/libdwfl.h> #include "../../../util/unwind-libdw.h" #include "../../../util/perf_regs.h" -#include "../../../util/event.h" +#include "util/sample.h" bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg) { |