#include "pmu.h"
 #include "print-events.h"
 
-static LIST_HEAD(pmus);
+static LIST_HEAD(core_pmus);
+static LIST_HEAD(other_pmus);
 
 void perf_pmus__destroy(void)
 {
        struct perf_pmu *pmu, *tmp;
 
-       list_for_each_entry_safe(pmu, tmp, &pmus, list) {
+       list_for_each_entry_safe(pmu, tmp, &core_pmus, list) {
+               list_del(&pmu->list);
+
+               perf_pmu__delete(pmu);
+       }
+       list_for_each_entry_safe(pmu, tmp, &other_pmus, list) {
                list_del(&pmu->list);
 
                perf_pmu__delete(pmu);
 {
        struct perf_pmu *pmu;
 
-       list_for_each_entry(pmu, &pmus, list) {
+       list_for_each_entry(pmu, &core_pmus, list) {
+               if (!strcmp(pmu->name, name) ||
+                   (pmu->alias_name && !strcmp(pmu->alias_name, name)))
+                       return pmu;
+       }
+       list_for_each_entry(pmu, &other_pmus, list) {
                if (!strcmp(pmu->name, name) ||
                    (pmu->alias_name && !strcmp(pmu->alias_name, name)))
                        return pmu;
                return pmu;
 
        dirfd = perf_pmu__event_source_devices_fd();
-       pmu = perf_pmu__lookup(&pmus, dirfd, name);
+       pmu = perf_pmu__lookup(is_pmu_core(name) ? &core_pmus : &other_pmus, dirfd, name);
        close(dirfd);
 
        return pmu;
        if (pmu)
                return pmu;
 
-       return perf_pmu__lookup(&pmus, dirfd, name);
+       return perf_pmu__lookup(is_pmu_core(name) ? &core_pmus : &other_pmus, dirfd, name);
 }
 
 /* Add all pmus in sysfs to pmu list: */
        while ((dent = readdir(dir))) {
                if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
                        continue;
-               /* add to static LIST_HEAD(pmus): */
+               /* add to static LIST_HEAD(core_pmus) or LIST_HEAD(other_pmus): */
                perf_pmu__find2(fd, dent->d_name);
        }
 
 {
        struct perf_pmu *pmu;
 
-       list_for_each_entry(pmu, &pmus, list)
+       list_for_each_entry(pmu, &core_pmus, list) {
                if (pmu->type == type)
                        return pmu;
-
+       }
+       list_for_each_entry(pmu, &other_pmus, list) {
+               if (pmu->type == type)
+                       return pmu;
+       }
        return NULL;
 }
 
+/*
+ * pmu iterator: If pmu is NULL, we start at the begin, otherwise return the
+ * next pmu. Returns NULL on end.
+ */
 struct perf_pmu *perf_pmus__scan(struct perf_pmu *pmu)
 {
-       /*
-        * pmu iterator: If pmu is NULL, we start at the begin,
-        * otherwise return the next pmu. Returns NULL on end.
-        */
+       bool use_core_pmus = !pmu || pmu->is_core;
+
        if (!pmu) {
                pmu_read_sysfs();
-               pmu = list_prepare_entry(pmu, &pmus, list);
+               pmu = list_prepare_entry(pmu, &core_pmus, list);
+       }
+       if (use_core_pmus) {
+               list_for_each_entry_continue(pmu, &core_pmus, list)
+                       return pmu;
+
+               pmu = NULL;
+               pmu = list_prepare_entry(pmu, &other_pmus, list);
        }
-       list_for_each_entry_continue(pmu, &pmus, list)
+       list_for_each_entry_continue(pmu, &other_pmus, list)
                return pmu;
        return NULL;
 }