In some cases, an event may be created without needing a counter
allocation. For example, an lbr event may be created by the host
only to help save/restore the lbr stack on the vCPU context switching.

This patch adds a "no_counter" attr boolean to let the callers
explicitly tell the perf core that no counter is needed.

Signed-off-by: Wei Wang <wei.w.w...@intel.com>
---
 arch/x86/events/core.c          | 12 ++++++++++++
 include/linux/perf_event.h      |  5 +++++
 include/uapi/linux/perf_event.h |  3 ++-
 3 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index 374a197..c09f03b 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -410,6 +410,9 @@ int x86_setup_perfctr(struct perf_event *event)
        struct hw_perf_event *hwc = &event->hw;
        u64 config;
 
+       if (is_no_counter_event(event))
+               return 0;
+
        if (!is_sampling_event(event)) {
                hwc->sample_period = x86_pmu.max_period;
                hwc->last_period = hwc->sample_period;
@@ -1209,6 +1212,12 @@ static int x86_pmu_add(struct perf_event *event, int 
flags)
        hwc = &event->hw;
 
        n0 = cpuc->n_events;
+
+       if (is_no_counter_event(event)) {
+               n = n0;
+               goto done_collect;
+       }
+
        ret = n = collect_events(cpuc, event, false);
        if (ret < 0)
                goto out;
@@ -1387,6 +1396,9 @@ static void x86_pmu_del(struct perf_event *event, int 
flags)
        if (cpuc->txn_flags & PERF_PMU_TXN_ADD)
                goto do_del;
 
+       if (is_no_counter_event(event))
+               goto do_del;
+
        /*
         * Not a TXN, therefore cleanup properly.
         */
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 53c500f..e58a997 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -1009,6 +1009,11 @@ static inline bool is_sampling_event(struct perf_event 
*event)
        return event->attr.sample_period != 0;
 }
 
+static inline bool is_no_counter_event(struct perf_event *event)
+{
+       return event->attr.no_counter;
+}
+
 /*
  * Return 1 for a software event, 0 for a hardware event
  */
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 9de8780..ec97a70 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -372,7 +372,8 @@ struct perf_event_attr {
                                context_switch :  1, /* context switch data */
                                write_backward :  1, /* Write ring buffer from 
end to beginning */
                                namespaces     :  1, /* include namespaces data 
*/
-                               __reserved_1   : 35;
+                               no_counter     :  1, /* no counter allocation */
+                               __reserved_1   : 34;
 
        union {
                __u32           wakeup_events;    /* wakeup every n events */
-- 
2.7.4

Reply via email to