]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - kernel/perf_counter.c
perf_counters: allow users to count user, kernel and/or hypervisor events
[karo-tx-linux.git] / kernel / perf_counter.c
index 544193cbc47849263b5fbef8b03ca98cd0dbb56c..89d5e3fe9700e0bdac8963160ff0e8666949c2c4 100644 (file)
@@ -1567,11 +1567,25 @@ sw_perf_counter_init(struct perf_counter *counter)
 {
        const struct hw_perf_counter_ops *hw_ops = NULL;
 
+       /*
+        * Software counters (currently) can't in general distinguish
+        * between user, kernel and hypervisor events.
+        * However, context switches and cpu migrations are considered
+        * to be kernel events, and page faults are never hypervisor
+        * events.
+        */
        switch (counter->hw_event.type) {
        case PERF_COUNT_CPU_CLOCK:
-               hw_ops = &perf_ops_cpu_clock;
+               if (!(counter->hw_event.exclude_user ||
+                     counter->hw_event.exclude_kernel ||
+                     counter->hw_event.exclude_hv))
+                       hw_ops = &perf_ops_cpu_clock;
                break;
        case PERF_COUNT_TASK_CLOCK:
+               if (counter->hw_event.exclude_user ||
+                   counter->hw_event.exclude_kernel ||
+                   counter->hw_event.exclude_hv)
+                       break;
                /*
                 * If the user instantiates this as a per-cpu counter,
                 * use the cpu_clock counter instead.
@@ -1582,13 +1596,17 @@ sw_perf_counter_init(struct perf_counter *counter)
                        hw_ops = &perf_ops_cpu_clock;
                break;
        case PERF_COUNT_PAGE_FAULTS:
-               hw_ops = &perf_ops_page_faults;
+               if (!(counter->hw_event.exclude_user ||
+                     counter->hw_event.exclude_kernel))
+                       hw_ops = &perf_ops_page_faults;
                break;
        case PERF_COUNT_CONTEXT_SWITCHES:
-               hw_ops = &perf_ops_context_switches;
+               if (!counter->hw_event.exclude_kernel)
+                       hw_ops = &perf_ops_context_switches;
                break;
        case PERF_COUNT_CPU_MIGRATIONS:
-               hw_ops = &perf_ops_cpu_migrations;
+               if (!counter->hw_event.exclude_kernel)
+                       hw_ops = &perf_ops_cpu_migrations;
                break;
        default:
                break;