summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRay Kinsella <mdr@ashroe.eu>2022-01-28 05:01:52 +0000
committerDamjan Marion <dmarion@me.com>2022-01-30 15:08:18 +0000
commit7e8aeb876b3bf21075621e40c3c1aa2fa2874dfb (patch)
tree992beb415bdc81f07f30cec95c5b411347a4f635
parent0a0e711cce0f29012ceb6bcde732c072415c2f96 (diff)
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 <mdr@ashroe.eu> Change-Id: Ic938f8266fd04d7731afbd02e261c61ef22a8522
-rw-r--r--src/plugins/perfmon/intel/core.c19
-rw-r--r--src/plugins/perfmon/perfmon.c28
-rw-r--r--src/plugins/perfmon/perfmon.h12
3 files changed, 41 insertions, 18 deletions
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
@@ -27,6 +27,14 @@
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,
PERFMON_BUNDLE_TYPE_NODE,
PERFMON_BUNDLE_TYPE_THREAD,
@@ -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;