perfmon: prune bundles by available pmu counters
[vpp.git] / src / plugins / perfmon / perfmon.c
index 411a07d..1569036 100644 (file)
@@ -324,11 +324,37 @@ perfmon_stop (vlib_main_t *vm)
   return 0;
 }
 
+static_always_inline u8
+is_enough_counters (perfmon_bundle_t *b)
+{
+  struct
+  {
+    u8 general;
+    u8 fixed;
+  } bl = { 0, 0 }, cpu = { 0, 0 };
+
+  /* how many does this uarch support */
+  if (!clib_get_pmu_counter_count (&cpu.fixed, &cpu.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++;
+
+  return cpu.general >= bl.general && cpu.fixed >= bl.fixed;
+}
+
 static_always_inline u8
 is_bundle_supported (perfmon_bundle_t *b)
 {
   perfmon_cpu_supports_t *supports = b->cpu_supports;
 
+  if (!is_enough_counters (b))
+    return 0;
+
   if (!b->cpu_supports)
     return 1;
 
@@ -372,13 +398,6 @@ perfmon_init (vlib_main_t *vm)
       clib_error_t *err;
       uword *p;
 
-      if (!is_bundle_supported (b))
-       {
-         log_debug ("skipping bundle '%s' - not supported", b->name);
-         b = b->next;
-         continue;
-       }
-
       if (hash_get_mem (pm->bundle_by_name, b->name) != 0)
        clib_panic ("duplicate bundle name '%s'", b->name);
 
@@ -391,6 +410,13 @@ perfmon_init (vlib_main_t *vm)
        }
 
       b->src = (perfmon_source_t *) p[0];
+      if (!is_bundle_supported (b))
+       {
+         log_debug ("skipping bundle '%s' - not supported", b->name);
+         b = b->next;
+         continue;
+       }
+
       if (b->init_fn && ((err = (b->init_fn) (vm, b))))
        {
          log_warn ("skipping bundle '%s' - %U", b->name, format_clib_error,