From 7e8aeb876b3bf21075621e40c3c1aa2fa2874dfb Mon Sep 17 00:00:00 2001 From: Ray Kinsella Date: Fri, 28 Jan 2022 05:01:52 +0000 Subject: perfmon: fix init of bundles with pseudo events Previously Linux pseudo events were being counted as multiple fixed events, such that a bundle with pseudo events could exceed the number of available fixed counters. Reworked to ignore pseudo events in the accounting for the moment. Type: fix Fixes: 0024e53ad Signed-off-by: Ray Kinsella Change-Id: Ic938f8266fd04d7731afbd02e261c61ef22a8522 --- src/plugins/perfmon/intel/core.c | 19 ++++++++++++++----- src/plugins/perfmon/perfmon.c | 28 +++++++++++++++++----------- src/plugins/perfmon/perfmon.h | 12 ++++++++++-- 3 files changed, 41 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/plugins/perfmon/intel/core.c b/src/plugins/perfmon/intel/core.c index d985d049712..08a27b6a73f 100644 --- a/src/plugins/perfmon/intel/core.c +++ b/src/plugins/perfmon/intel/core.c @@ -77,13 +77,22 @@ intel_core_init (vlib_main_t *vm, perfmon_source_t *src) return 0; } -u8 -intel_core_is_fixed (u32 event) +perfmon_event_type_t +intel_core_get_event_type (u32 event) { u64 config = events[event].config; u8 eventcode = (config & 0xFF); - - return !eventcode ? 1 : 0; + u8 umask = ((config >> 8) & 0xFF); + + if (!eventcode) /* is fixed or pseudo */ + { + if (umask >= 0x80) /* is pseudo */ + return PERFMON_EVENT_TYPE_PSEUDO; + else /* is fixed */ + return PERFMON_EVENT_TYPE_FIXED; + } + else + return PERFMON_EVENT_TYPE_GENERAL; } PERFMON_REGISTER_SOURCE (intel_core) = { @@ -92,6 +101,6 @@ PERFMON_REGISTER_SOURCE (intel_core) = { .events = events, .n_events = ARRAY_LEN (events), .init_fn = intel_core_init, - .is_fixed = intel_core_is_fixed, + .get_event_type = intel_core_get_event_type, .format_config = format_intel_core_config, }; diff --git a/src/plugins/perfmon/perfmon.c b/src/plugins/perfmon/perfmon.c index 594a98759c8..b0c46b8edfc 100644 --- a/src/plugins/perfmon/perfmon.c +++ b/src/plugins/perfmon/perfmon.c @@ -327,24 +327,30 @@ perfmon_stop (vlib_main_t *vm) static_always_inline u8 is_enough_counters (perfmon_bundle_t *b) { - struct - { - u8 general; - u8 fixed; - } bl = { 0, 0 }, cpu = { 0, 0 }; + u8 bl[PERFMON_EVENT_TYPE_MAX]; + u8 cpu[PERFMON_EVENT_TYPE_MAX]; + + clib_memset (&bl, 0, sizeof (bl)); + clib_memset (&cpu, 0, sizeof (cpu)); /* how many does this uarch support */ - if (!clib_get_pmu_counter_count (&cpu.fixed, &cpu.general)) + if (!clib_get_pmu_counter_count (&cpu[PERFMON_EVENT_TYPE_FIXED], + &cpu[PERFMON_EVENT_TYPE_GENERAL])) return 0; /* how many does the bundle require */ for (u16 i = 0; i < b->n_events; i++) - if (b->src->is_fixed && b->src->is_fixed (b->events[i])) - bl.fixed++; - else - bl.general++; + { + /* if source allows us to identify events, otherwise assume general */ + if (b->src->get_event_type) + bl[b->src->get_event_type (b->events[i])]++; + else + bl[PERFMON_EVENT_TYPE_GENERAL]++; + } - return cpu.general >= bl.general && cpu.fixed >= bl.fixed; + /* consciously ignoring pseudo events here */ + return cpu[PERFMON_EVENT_TYPE_GENERAL] >= bl[PERFMON_EVENT_TYPE_GENERAL] && + cpu[PERFMON_EVENT_TYPE_FIXED] >= bl[PERFMON_EVENT_TYPE_FIXED]; } static_always_inline u8 diff --git a/src/plugins/perfmon/perfmon.h b/src/plugins/perfmon/perfmon.h index c7f43145943..fa15ef63aca 100644 --- a/src/plugins/perfmon/perfmon.h +++ b/src/plugins/perfmon/perfmon.h @@ -25,6 +25,14 @@ #define PERF_MAX_EVENTS 12 /* 4 fixed and 8 programable on ICX */ +typedef enum +{ + PERFMON_EVENT_TYPE_GENERAL, + PERFMON_EVENT_TYPE_FIXED, + PERFMON_EVENT_TYPE_PSEUDO, + PERFMON_EVENT_TYPE_MAX, +} perfmon_event_type_t; + typedef enum { PERFMON_BUNDLE_TYPE_UNKNOWN, @@ -82,7 +90,7 @@ extern vlib_node_function_t *perfmon_dispatch_wrappers[PERF_MAX_EVENTS + 1]; typedef clib_error_t *(perfmon_source_init_fn_t) (vlib_main_t *vm, struct perfmon_source *); -typedef u8 (perfmon_source_is_fixed) (u32 event); +typedef perfmon_event_type_t (perfmon_source_get_event_type) (u32 event); typedef struct perfmon_source { @@ -93,7 +101,7 @@ typedef struct perfmon_source u32 n_events; perfmon_instance_type_t *instances_by_type; format_function_t *format_config; - perfmon_source_is_fixed *is_fixed; + perfmon_source_get_event_type *get_event_type; perfmon_source_init_fn_t *init_fn; } perfmon_source_t; -- cgit 1.2.3-korg