evsel->priv = NULL;
 }
 
+static inline struct cpu_map *perf_evsel__cpus(struct perf_evsel *evsel)
+{
+       return (evsel->cpus && !target.cpu_list) ? evsel->cpus : evsel_list->cpus;
+}
+
+static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel)
+{
+       return perf_evsel__cpus(evsel)->nr;
+}
+
 static struct stats runtime_nsecs_stats[MAX_NR_CPUS];
 static struct stats runtime_cycles_stats[MAX_NR_CPUS];
 static struct stats runtime_stalled_cycles_front_stats[MAX_NR_CPUS];
                evsel->attr.exclude_guest = evsel->attr.exclude_host = 0;
 
        if (perf_target__has_cpu(&target)) {
-               ret = perf_evsel__open_per_cpu(evsel, evsel_list->cpus);
+               ret = perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
                if (ret)
                        goto check_ret;
                return 0;
        u64 *count = counter->counts->aggr.values;
        int i;
 
-       if (__perf_evsel__read(counter, evsel_list->cpus->nr,
+       if (__perf_evsel__read(counter, perf_evsel__nr_cpus(counter),
                               evsel_list->threads->nr, scale) < 0)
                return -1;
 
        u64 *count;
        int cpu;
 
-       for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) {
+       for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
                if (__perf_evsel__read_on_cpu(counter, cpu, 0, scale) < 0)
                        return -1;
 
        if (no_aggr) {
                list_for_each_entry(counter, &evsel_list->entries, node) {
                        read_counter(counter);
-                       perf_evsel__close_fd(counter, evsel_list->cpus->nr, 1);
+                       perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter), 1);
                }
        } else {
                list_for_each_entry(counter, &evsel_list->entries, node) {
                        read_counter_aggr(counter);
-                       perf_evsel__close_fd(counter, evsel_list->cpus->nr,
+                       perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter),
                                             evsel_list->threads->nr);
                }
        }
        if (no_aggr)
                sprintf(cpustr, "CPU%*d%s",
                        csv_output ? 0 : -4,
-                       evsel_list->cpus->map[cpu], csv_sep);
+                       perf_evsel__cpus(evsel)->map[cpu], csv_sep);
 
        fprintf(output, fmt, cpustr, msecs, csv_sep, perf_evsel__name(evsel));
 
        if (no_aggr)
                sprintf(cpustr, "CPU%*d%s",
                        csv_output ? 0 : -4,
-                       evsel_list->cpus->map[cpu], csv_sep);
+                       perf_evsel__cpus(evsel)->map[cpu], csv_sep);
        else
                cpu = 0;
 
        u64 ena, run, val;
        int cpu;
 
-       for (cpu = 0; cpu < evsel_list->cpus->nr; cpu++) {
+       for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
                val = counter->counts->cpu[cpu].val;
                ena = counter->counts->cpu[cpu].ena;
                run = counter->counts->cpu[cpu].run;
                if (run == 0 || ena == 0) {
                        fprintf(output, "CPU%*d%s%*s%s%*s",
                                csv_output ? 0 : -4,
-                               evsel_list->cpus->map[cpu], csv_sep,
+                               perf_evsel__cpus(counter)->map[cpu], csv_sep,
                                csv_output ? 0 : 18,
                                counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
                                csv_sep,
 
        list_for_each_entry(pos, &evsel_list->entries, node) {
                if (perf_evsel__alloc_stat_priv(pos) < 0 ||
-                   perf_evsel__alloc_counts(pos, evsel_list->cpus->nr) < 0)
+                   perf_evsel__alloc_counts(pos, perf_evsel__nr_cpus(pos)) < 0)
                        goto out_free_fd;
        }
 
 
        return cpus;
 }
 
-static struct cpu_map *cpu_map__read_all_cpu_map(void)
+struct cpu_map *cpu_map__read(FILE *file)
 {
        struct cpu_map *cpus = NULL;
-       FILE *onlnf;
        int nr_cpus = 0;
        int *tmp_cpus = NULL, *tmp;
        int max_entries = 0;
        int n, cpu, prev;
        char sep;
 
-       onlnf = fopen("/sys/devices/system/cpu/online", "r");
-       if (!onlnf)
-               return cpu_map__default_new();
-
        sep = 0;
        prev = -1;
        for (;;) {
-               n = fscanf(onlnf, "%u%c", &cpu, &sep);
+               n = fscanf(file, "%u%c", &cpu, &sep);
                if (n <= 0)
                        break;
                if (prev >= 0) {
                cpus = cpu_map__default_new();
 out_free_tmp:
        free(tmp_cpus);
+       return cpus;
+}
+
+static struct cpu_map *cpu_map__read_all_cpu_map(void)
+{
+       struct cpu_map *cpus = NULL;
+       FILE *onlnf;
+
+       onlnf = fopen("/sys/devices/system/cpu/online", "r");
+       if (!onlnf)
+               return cpu_map__default_new();
+
+       cpus = cpu_map__read(onlnf);
        fclose(onlnf);
        return cpus;
 }
 
        return "unknown";
 }
 
-static int add_event(struct list_head **_list, int *idx,
-                    struct perf_event_attr *attr, char *name)
+
+
+static int __add_event(struct list_head **_list, int *idx,
+                      struct perf_event_attr *attr,
+                      char *name, struct cpu_map *cpus)
 {
        struct perf_evsel *evsel;
        struct list_head *list = *_list;
                return -ENOMEM;
        }
 
+       evsel->cpus = cpus;
        if (name)
                evsel->name = strdup(name);
        list_add_tail(&evsel->node, list);
        return 0;
 }
 
+static int add_event(struct list_head **_list, int *idx,
+                    struct perf_event_attr *attr, char *name)
+{
+       return __add_event(_list, idx, attr, name, NULL);
+}
+
 static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
 {
        int i, j;
        if (perf_pmu__config(pmu, &attr, head_config))
                return -EINVAL;
 
-       return add_event(list, idx, &attr,
-                        pmu_event_name(head_config));
+       return __add_event(list, idx, &attr, pmu_event_name(head_config),
+                          pmu->cpus);
 }
 
 int parse_events__modifier_group(struct list_head *list,
 
 #include "util.h"
 #include "pmu.h"
 #include "parse-events.h"
+#include "cpumap.h"
 
 #define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
 
        closedir(dir);
 }
 
+static struct cpu_map *pmu_cpumask(char *name)
+{
+       struct stat st;
+       char path[PATH_MAX];
+       const char *sysfs;
+       FILE *file;
+       struct cpu_map *cpus;
+
+       sysfs = sysfs_find_mountpoint();
+       if (!sysfs)
+               return NULL;
+
+       snprintf(path, PATH_MAX,
+                "%s/bus/event_source/devices/%s/cpumask", sysfs, name);
+
+       if (stat(path, &st) < 0)
+               return NULL;
+
+       file = fopen(path, "r");
+       if (!file)
+               return NULL;
+
+       cpus = cpu_map__read(file);
+       fclose(file);
+       return cpus;
+}
+
 static struct perf_pmu *pmu_lookup(char *name)
 {
        struct perf_pmu *pmu;
        if (!pmu)
                return NULL;
 
+       pmu->cpus = pmu_cpumask(name);
+
        pmu_aliases(name, &aliases);
 
        INIT_LIST_HEAD(&pmu->format);