}
 
 static atomic_t active_events;
+static atomic_t pmc_refcount;
 static DEFINE_MUTEX(pmc_reserve_mutex);
 
 #ifdef CONFIG_X86_LOCAL_APIC
 static void hw_perf_event_destroy(struct perf_event *event)
 {
        x86_release_hardware();
+       atomic_dec(&active_events);
 }
 
 void hw_perf_lbr_event_destroy(struct perf_event *event)
 {
        int err = 0;
 
-       if (!atomic_inc_not_zero(&active_events)) {
+       if (!atomic_inc_not_zero(&pmc_refcount)) {
                mutex_lock(&pmc_reserve_mutex);
-               if (atomic_read(&active_events) == 0) {
+               if (atomic_read(&pmc_refcount) == 0) {
                        if (!reserve_pmc_hardware())
                                err = -EBUSY;
                        else
                                reserve_ds_buffers();
                }
                if (!err)
-                       atomic_inc(&active_events);
+                       atomic_inc(&pmc_refcount);
                mutex_unlock(&pmc_reserve_mutex);
        }
 
 
 void x86_release_hardware(void)
 {
-       if (atomic_dec_and_mutex_lock(&active_events, &pmc_reserve_mutex)) {
+       if (atomic_dec_and_mutex_lock(&pmc_refcount, &pmc_reserve_mutex)) {
                release_pmc_hardware();
                release_ds_buffers();
                mutex_unlock(&pmc_reserve_mutex);
 
 out:
        mutex_unlock(&pmc_reserve_mutex);
+
+       /*
+        * Assuming that all exclusive events will share the PMI handler
+        * (which checks active_events for whether there is work to do),
+        * we can bump active_events counter right here, except for
+        * x86_lbr_exclusive_lbr events that go through x86_pmu_event_init()
+        * path, which already bumps active_events for them.
+        */
+       if (!ret && what != x86_lbr_exclusive_lbr)
+               atomic_inc(&active_events);
+
        return ret;
 }
 
 void x86_del_exclusive(unsigned int what)
 {
        atomic_dec(&x86_pmu.lbr_exclusive[what]);
+       atomic_dec(&active_events);
 }
 
 int x86_setup_perfctr(struct perf_event *event)
        if (err)
                return err;
 
+       atomic_inc(&active_events);
        event->destroy = hw_perf_event_destroy;
 
        event->hw.idx = -1;
        u64 finish_clock;
        int ret;
 
+       /*
+        * All PMUs/events that share this PMI handler should make sure to
+        * increment active_events for their events.
+        */
        if (!atomic_read(&active_events))
                return NMI_DONE;