}
 
        if (evsel->fd == NULL &&
-           perf_evsel__alloc_fd(evsel, cpus->nr, threads->nr) < 0)
+           perf_evsel__alloc_fd(evsel, perf_cpu_map__nr(cpus), threads->nr) < 0)
                return -ENOMEM;
 
        perf_cpu_map__for_each_cpu(cpu, idx, cpus) {
 {
        int err = 0, i;
 
-       for (i = 0; i < evsel->cpus->nr && !err; i++)
+       for (i = 0; i < perf_cpu_map__nr(evsel->cpus) && !err; i++)
                err = perf_evsel__run_ioctl(evsel,
                                     PERF_EVENT_IOC_SET_FILTER,
                                     (void *)filter, i);
 
 
        /* default to the number of CPUs */
        if (!nthreads)
-               nthreads = cpu->nr;
+               nthreads = perf_cpu_map__nr(cpu);
 
        worker = calloc(nthreads, sizeof(*worker));
        if (!worker)
 
 
        /* default to the number of CPUs and leave one for the writer pthread */
        if (!nthreads)
-               nthreads = cpu->nr - 1;
+               nthreads = perf_cpu_map__nr(cpu) - 1;
 
        worker = calloc(nthreads, sizeof(*worker));
        if (!worker) {
 
        int cnt = 0;
 
        evlist__for_each_entry(evlist, evsel)
-               cnt += evsel->core.threads->nr * evsel->core.cpus->nr;
+               cnt += evsel->core.threads->nr * perf_cpu_map__nr(evsel->core.cpus);
 
        return cnt;
 }
 
        init_stats(&time_stats);
 
-       printf("  Number of cpus:\t%d\n", evlist->core.cpus->nr);
+       printf("  Number of cpus:\t%d\n", perf_cpu_map__nr(evlist->core.cpus));
        printf("  Number of threads:\t%d\n", evlist->core.threads->nr);
        printf("  Number of events:\t%d (%d fds)\n",
                evlist->core.nr_entries, evlist__count_evsel_fds(evlist));
 
        }
 
        if (!params.nthreads) /* default to the number of CPUs */
-               params.nthreads = cpu->nr;
+               params.nthreads = perf_cpu_map__nr(cpu);
 
        worker = calloc(params.nthreads, sizeof(*worker));
        if (!worker)
 
        }
 
        if (!params.nthreads)
-               params.nthreads = cpu->nr;
+               params.nthreads = perf_cpu_map__nr(cpu);
 
        worker = calloc(params.nthreads, sizeof(*worker));
        if (!worker)
 
        }
 
        if (!params.nthreads)
-               params.nthreads = cpu->nr;
+               params.nthreads = perf_cpu_map__nr(cpu);
 
        worker = calloc(params.nthreads, sizeof(*worker));
        if (!worker)
 
                err(EXIT_FAILURE, "calloc");
 
        if (!params.nthreads)
-               params.nthreads = cpu->nr;
+               params.nthreads = perf_cpu_map__nr(cpu);
 
        /* some sanity checks */
        if (params.nwakes > params.nthreads ||
 
        }
 
        if (!params.nthreads)
-               params.nthreads = cpu->nr;
+               params.nthreads = perf_cpu_map__nr(cpu);
 
        worker = calloc(params.nthreads, sizeof(*worker));
        if (!worker)
 
        int ret;
        int last_cpu;
 
-       last_cpu = perf_cpu_map__cpu(cpumap, cpumap->nr - 1).cpu;
+       last_cpu = perf_cpu_map__cpu(cpumap, perf_cpu_map__nr(cpumap) - 1).cpu;
        mask_size = last_cpu / 4 + 2; /* one more byte for EOS */
        mask_size += last_cpu / 32; /* ',' is needed for every 32th cpus */
 
 
        if (!a->core.cpus || !b->core.cpus)
                return false;
 
-       if (a->core.cpus->nr != b->core.cpus->nr)
+       if (perf_cpu_map__nr(a->core.cpus) != perf_cpu_map__nr(b->core.cpus))
                return false;
 
-       for (int i = 0; i < a->core.cpus->nr; i++) {
-               if (a->core.cpus->map[i].cpu != b->core.cpus->map[i].cpu)
+       for (int i = 0; i < perf_cpu_map__nr(a->core.cpus); i++) {
+               if (perf_cpu_map__cpu(a->core.cpus, i).cpu !=
+                   perf_cpu_map__cpu(b->core.cpus, i).cpu)
                        return false;
        }
 
 
        bm = bitmap_zalloc(nbits);
 
        if (map && bm) {
-               for (i = 0; i < map->nr; i++)
-                       set_bit(map->map[i].cpu, bm);
+               for (i = 0; i < perf_cpu_map__nr(map); i++)
+                       set_bit(perf_cpu_map__cpu(map, i).cpu, bm);
        }
 
        if (map)
 
 
        TEST_ASSERT_VAL("wrong id", ev->id == 123);
        TEST_ASSERT_VAL("wrong type", ev->type == PERF_EVENT_UPDATE__CPUS);
-       TEST_ASSERT_VAL("wrong cpus", map->nr == 3);
-       TEST_ASSERT_VAL("wrong cpus", map->map[0].cpu == 1);
-       TEST_ASSERT_VAL("wrong cpus", map->map[1].cpu == 2);
-       TEST_ASSERT_VAL("wrong cpus", map->map[2].cpu == 3);
+       TEST_ASSERT_VAL("wrong cpus", perf_cpu_map__nr(map) == 3);
+       TEST_ASSERT_VAL("wrong cpus", perf_cpu_map__cpu(map, 0).cpu == 1);
+       TEST_ASSERT_VAL("wrong cpus", perf_cpu_map__cpu(map, 1).cpu == 2);
+       TEST_ASSERT_VAL("wrong cpus", perf_cpu_map__cpu(map, 2).cpu == 3);
        perf_cpu_map__put(map);
        return 0;
 }
 
 {
        struct perf_cpu_map *map = perf_cpu_map__new(str);
        unsigned long *bm = NULL;
-       int i;
 
        bm = bitmap_zalloc(nbits);
 
        if (map && bm) {
-               for (i = 0; i < map->nr; i++) {
-                       set_bit(map->map[i].cpu, bm);
-               }
+               struct perf_cpu cpu;
+               int i;
+
+               perf_cpu_map__for_each_cpu(cpu, i, map)
+                       set_bit(cpu.cpu, bm);
        }
 
        if (map)
 
        }
 
        CPU_ZERO(&cpu_set);
-       CPU_SET(cpus->map[0].cpu, &cpu_set);
+       CPU_SET(perf_cpu_map__cpu(cpus, 0).cpu, &cpu_set);
        sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
        if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
                pr_debug("sched_setaffinity() failed on CPU %d: %s ",
-                        cpus->map[0].cpu, str_error_r(errno, sbuf, sizeof(sbuf)));
+                        perf_cpu_map__cpu(cpus, 0).cpu,
+                        str_error_r(errno, sbuf, sizeof(sbuf)));
                goto out_free_cpus;
        }
 
 
        }
 
        // Test that CPU ID contains socket, die, core and CPU
-       for (i = 0; i < map->nr; i++) {
+       for (i = 0; i < perf_cpu_map__nr(map); i++) {
                id = aggr_cpu_id__cpu(perf_cpu_map__cpu(map, i), NULL);
-               TEST_ASSERT_VAL("Cpu map - CPU ID doesn't match", map->map[i].cpu == id.cpu.cpu);
+               TEST_ASSERT_VAL("Cpu map - CPU ID doesn't match",
+                               perf_cpu_map__cpu(map, i).cpu == id.cpu.cpu);
 
                TEST_ASSERT_VAL("Cpu map - Core ID doesn't match",
-                       session->header.env.cpu[map->map[i].cpu].core_id == id.core);
+                       session->header.env.cpu[perf_cpu_map__cpu(map, i).cpu].core_id == id.core);
                TEST_ASSERT_VAL("Cpu map - Socket ID doesn't match",
-                       session->header.env.cpu[map->map[i].cpu].socket_id == id.socket);
+                       session->header.env.cpu[perf_cpu_map__cpu(map, i).cpu].socket_id ==
+                       id.socket);
 
                TEST_ASSERT_VAL("Cpu map - Die ID doesn't match",
-                       session->header.env.cpu[map->map[i].cpu].die_id == id.die);
+                       session->header.env.cpu[perf_cpu_map__cpu(map, i).cpu].die_id == id.die);
                TEST_ASSERT_VAL("Cpu map - Node ID is set", id.node == -1);
                TEST_ASSERT_VAL("Cpu map - Thread is set", id.thread == -1);
        }
 
        // Test that core ID contains socket, die and core
-       for (i = 0; i < map->nr; i++) {
+       for (i = 0; i < perf_cpu_map__nr(map); i++) {
                id = aggr_cpu_id__core(perf_cpu_map__cpu(map, i), NULL);
                TEST_ASSERT_VAL("Core map - Core ID doesn't match",
-                       session->header.env.cpu[map->map[i].cpu].core_id == id.core);
+                       session->header.env.cpu[perf_cpu_map__cpu(map, i).cpu].core_id == id.core);
 
                TEST_ASSERT_VAL("Core map - Socket ID doesn't match",
-                       session->header.env.cpu[map->map[i].cpu].socket_id == id.socket);
+                       session->header.env.cpu[perf_cpu_map__cpu(map, i).cpu].socket_id ==
+                       id.socket);
 
                TEST_ASSERT_VAL("Core map - Die ID doesn't match",
-                       session->header.env.cpu[map->map[i].cpu].die_id == id.die);
+                       session->header.env.cpu[perf_cpu_map__cpu(map, i).cpu].die_id == id.die);
                TEST_ASSERT_VAL("Core map - Node ID is set", id.node == -1);
                TEST_ASSERT_VAL("Core map - Thread is set", id.thread == -1);
        }
 
        // Test that die ID contains socket and die
-       for (i = 0; i < map->nr; i++) {
+       for (i = 0; i < perf_cpu_map__nr(map); i++) {
                id = aggr_cpu_id__die(perf_cpu_map__cpu(map, i), NULL);
                TEST_ASSERT_VAL("Die map - Socket ID doesn't match",
-                       session->header.env.cpu[map->map[i].cpu].socket_id == id.socket);
+                       session->header.env.cpu[perf_cpu_map__cpu(map, i).cpu].socket_id ==
+                       id.socket);
 
                TEST_ASSERT_VAL("Die map - Die ID doesn't match",
-                       session->header.env.cpu[map->map[i].cpu].die_id == id.die);
+                       session->header.env.cpu[perf_cpu_map__cpu(map, i).cpu].die_id == id.die);
 
                TEST_ASSERT_VAL("Die map - Node ID is set", id.node == -1);
                TEST_ASSERT_VAL("Die map - Core is set", id.core == -1);
        }
 
        // Test that socket ID contains only socket
-       for (i = 0; i < map->nr; i++) {
+       for (i = 0; i < perf_cpu_map__nr(map); i++) {
                id = aggr_cpu_id__socket(perf_cpu_map__cpu(map, i), NULL);
                TEST_ASSERT_VAL("Socket map - Socket ID doesn't match",
-                       session->header.env.cpu[map->map[i].cpu].socket_id == id.socket);
+                       session->header.env.cpu[perf_cpu_map__cpu(map, i).cpu].socket_id ==
+                       id.socket);
 
                TEST_ASSERT_VAL("Socket map - Node ID is set", id.node == -1);
                TEST_ASSERT_VAL("Socket map - Die ID is set", id.die == -1);
        }
 
        // Test that node ID contains only node
-       for (i = 0; i < map->nr; i++) {
+       for (i = 0; i < perf_cpu_map__nr(map); i++) {
                id = aggr_cpu_id__node(perf_cpu_map__cpu(map, i), NULL);
                TEST_ASSERT_VAL("Node map - Node ID doesn't match",
-                       cpu__get_node(map->map[i]) == id.node);
+                               cpu__get_node(perf_cpu_map__cpu(map, i)) == id.node);
                TEST_ASSERT_VAL("Node map - Socket is set", id.socket == -1);
                TEST_ASSERT_VAL("Node map - Die ID is set", id.die == -1);
                TEST_ASSERT_VAL("Node map - Core is set", id.core == -1);
 
        mp->idx = idx;
 
        if (per_cpu) {
-               mp->cpu = evlist->core.cpus->map[idx];
+               mp->cpu = perf_cpu_map__cpu(evlist->core.cpus, idx);
                if (evlist->core.threads)
                        mp->tid = perf_thread_map__pid(evlist->core.threads, 0);
                else
 
        struct perf_cpu_map *cpus = evsel__cpus(evsel);
        int nthreads = perf_thread_map__nr(evsel->core.threads);
 
-       evsel->counts = perf_counts__new(cpus ? cpus->nr : 1, nthreads);
+       evsel->counts = perf_counts__new(perf_cpu_map__nr(cpus), nthreads);
        return evsel->counts != NULL ? 0 : -ENOMEM;
 }
 
 
  */
 static inline bool cpu_map__is_dummy(struct perf_cpu_map *cpus)
 {
-       return cpus->nr == 1 && cpus->map[0].cpu == -1;
+       return perf_cpu_map__nr(cpus) == 1 && perf_cpu_map__cpu(cpus, 0).cpu == -1;
 }
 
 /**
 
        if (!node_map)
                goto out;
 
-       nr = (u32) node_map->nr;
+       nr = (u32) perf_cpu_map__nr(node_map);
 
        tp = zalloc(sizeof(*tp) + sizeof(tp->nodes[0])*nr);
        if (!tp)
        tp->nr = nr;
 
        for (i = 0; i < nr; i++) {
-               if (load_numa_node(&tp->nodes[i], node_map->map[i].cpu)) {
+               if (load_numa_node(&tp->nodes[i], perf_cpu_map__cpu(node_map, i).cpu)) {
                        numa_topology__delete(tp);
                        tp = NULL;
                        break;
 
 
                events_nr++;
 
-               if (matched_cpus->nr > 0 && (unmatched_cpus->nr > 0 ||
-                   matched_cpus->nr < cpus->nr ||
-                   matched_cpus->nr < pmu->cpus->nr)) {
+               if (perf_cpu_map__nr(matched_cpus) > 0 &&
+                   (perf_cpu_map__nr(unmatched_cpus) > 0 ||
+                    perf_cpu_map__nr(matched_cpus) < perf_cpu_map__nr(cpus) ||
+                    perf_cpu_map__nr(matched_cpus) < perf_cpu_map__nr(pmu->cpus))) {
                        perf_cpu_map__put(evsel->core.cpus);
                        perf_cpu_map__put(evsel->core.own_cpus);
                        evsel->core.cpus = perf_cpu_map__get(matched_cpus);
                        evsel->core.own_cpus = perf_cpu_map__get(matched_cpus);
 
-                       if (unmatched_cpus->nr > 0) {
+                       if (perf_cpu_map__nr(unmatched_cpus) > 0) {
                                cpu_map__snprint(matched_cpus, buf1, sizeof(buf1));
                                pr_warning("WARNING: use %s in '%s' for '%s', skip other cpus in list.\n",
                                           buf1, pmu->name, evsel->name);
                        }
                }
 
-               if (matched_cpus->nr == 0) {
+               if (perf_cpu_map__nr(matched_cpus) == 0) {
                        evlist__remove(evlist, evsel);
                        evsel__delete(evsel);
 
 
                nthreads = threads->nr;
 
        if (evsel->core.fd == NULL &&
-           perf_evsel__alloc_fd(&evsel->core, cpus->nr, nthreads) < 0)
+           perf_evsel__alloc_fd(&evsel->core, perf_cpu_map__nr(cpus), nthreads) < 0)
                return -ENOMEM;
 
        evsel->open_flags = PERF_FLAG_FD_CLOEXEC;
                        test_attr__ready();
 
                        pr_debug2_peo("sys_perf_event_open: pid %d  cpu %d  group_fd %d  flags %#lx",
-                               pid, cpus->map[idx].cpu, group_fd, evsel->open_flags);
+                               pid, perf_cpu_map__cpu(cpus, idx).cpu, group_fd, evsel->open_flags);
 
-                       fd = sys_perf_event_open(&evsel->core.attr, pid, cpus->map[idx].cpu,
+                       fd = sys_perf_event_open(&evsel->core.attr, pid,
+                                               perf_cpu_map__cpu(cpus, idx).cpu,
                                                group_fd, evsel->open_flags);
 
                        FD(evsel, idx, thread) = fd;
                        bpf_counter__install_pe(evsel, idx, fd);
 
                        if (unlikely(test_attr__enabled)) {
-                               test_attr__open(&evsel->core.attr, pid, cpus->map[idx],
+                               test_attr__open(&evsel->core.attr, pid,
+                                               perf_cpu_map__cpu(cpus, idx),
                                                fd, group_fd, evsel->open_flags);
                        }
 
        if (evsel__precise_ip_fallback(evsel))
                goto retry_open;
 
-       if (evsel__ignore_missing_thread(evsel, cpus->nr, idx, threads, thread, err)) {
+       if (evsel__ignore_missing_thread(evsel, perf_cpu_map__nr(cpus),
+                                        idx, threads, thread, err)) {
                /* We just removed 1 thread, so lower the upper nthreads limit. */
                nthreads--;
 
 int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus,
                struct perf_thread_map *threads)
 {
-       return evsel__open_cpu(evsel, cpus, threads, 0, cpus ? cpus->nr : 1);
+       return evsel__open_cpu(evsel, cpus, threads, 0, perf_cpu_map__nr(cpus));
 }
 
 void evsel__close(struct evsel *evsel)
 int evsel__open_per_cpu(struct evsel *evsel, struct perf_cpu_map *cpus, int cpu_map_idx)
 {
        if (cpu_map_idx == -1)
-               return evsel__open_cpu(evsel, cpus, NULL, 0,
-                                       cpus ? cpus->nr : 1);
+               return evsel__open_cpu(evsel, cpus, NULL, 0, perf_cpu_map__nr(cpus));
 
        return evsel__open_cpu(evsel, cpus, NULL, cpu_map_idx, cpu_map_idx + 1);
 }
        struct perf_cpu_map *cpus = evsel->core.cpus;
        struct perf_thread_map *threads = evsel->core.threads;
 
-       if (perf_evsel__alloc_id(&evsel->core, cpus->nr, threads->nr))
+       if (perf_evsel__alloc_id(&evsel->core, perf_cpu_map__nr(cpus), threads->nr))
                return -ENOMEM;
 
        return store_evsel_ids(evsel, evlist);
 
 #include <perf/evsel.h>
 #include "symbol_conf.h"
 #include <internal/cpumap.h>
+#include <perf/cpumap.h>
 
 struct bpf_object;
 struct cgroup;
 
 static inline int evsel__nr_cpus(struct evsel *evsel)
 {
-       return evsel__cpus(evsel)->nr;
+       return perf_cpu_map__nr(evsel__cpus(evsel));
 }
 
 void evsel__compute_deltas(struct evsel *evsel, int cpu, int thread,
 
 
        nr_cpus = perf_cpu_map__nr(cpu_map);
        for (idx = 0; idx < nr_cpus; idx++) {
-               cpu = cpu_map->map[idx]; /* map c index to online cpu index */
+               cpu = perf_cpu_map__cpu(cpu_map, idx); /* map c index to online cpu index */
                if (cpu__get_node(cpu) == node)
                        set_bit(cpu.cpu, mask->bits);
        }
 
        cpus = perf_cpu_map__new(NULL);
        if (!cpus)
                return false;
-       cpu = cpus->map[0];
+       cpu = perf_cpu_map__cpu(cpus, 0);
        perf_cpu_map__put(cpus);
 
        do {
        if (!cpus)
                return false;
 
-       cpu = cpus->map[0];
+       cpu = perf_cpu_map__cpu(cpus, 0);
        perf_cpu_map__put(cpus);
 
        fd = sys_perf_event_open(&attr, -1, cpu.cpu, -1, 0);
 
        if (opts->group)
                evlist__set_leader(evlist);
 
-       if (evlist->core.cpus->map[0].cpu < 0)
+       if (perf_cpu_map__cpu(evlist->core.cpus, 0).cpu < 0)
                opts->no_inherit = true;
 
        use_comm_exec = perf_can_comm_exec();
                struct perf_cpu_map *cpus = perf_cpu_map__new(NULL);
 
                if (cpus)
-                       cpu =  cpus->map[0];
+                       cpu =  perf_cpu_map__cpu(cpus, 0);
 
                perf_cpu_map__put(cpus);
        } else {
-               cpu = evlist->core.cpus->map[0];
+               cpu = perf_cpu_map__cpu(evlist->core.cpus, 0);
        }
 
        while (1) {
 
        }
 
        for (thread = 0; thread < threads->nr; thread++) {
-               for (cpu = 0; cpu < cpus->nr; cpu++) {
-                       process_stat(counter, cpus->map[cpu],
+               for (cpu = 0; cpu < perf_cpu_map__nr(cpus); cpu++) {
+                       process_stat(counter, perf_cpu_map__cpu(cpus, cpu),
                                     perf_thread_map__pid(threads, thread), tstamp,
                                     perf_counts(counter->counts, cpu, thread));
                }
 
                return -1;
        }
 
-       for (i = 0; i < map->nr; i++) {
-               struct perf_cpu cpu = map->map[i];
+       for (i = 0; i < perf_cpu_map__nr(map); i++) {
+               struct perf_cpu cpu = perf_cpu_map__cpu(map, i);
 
                if (cpu.cpu >= nr_cpus) {
                        pr_err("Requested CPU %d too large. "
 
        if (!m)
                return -1;
 
-       for (i = 0; i < m->nr; i++) {
-               c = m->map[i];
+       for (i = 0; i < perf_cpu_map__nr(m); i++) {
+               c = perf_cpu_map__cpu(m, i);
                if (c.cpu >= nr_cpus) {
                        ret = -1;
                        break;
 
 static void synthesize_cpus(struct cpu_map_entries *cpus,
                            struct perf_cpu_map *map)
 {
-       int i;
+       int i, map_nr = perf_cpu_map__nr(map);
 
-       cpus->nr = map->nr;
+       cpus->nr = map_nr;
 
-       for (i = 0; i < map->nr; i++)
-               cpus->cpu[i] = map->map[i].cpu;
+       for (i = 0; i < map_nr; i++)
+               cpus->cpu[i] = perf_cpu_map__cpu(map, i).cpu;
 }
 
 static void synthesize_mask(struct perf_record_record_cpu_map *mask,
        mask->nr = BITS_TO_LONGS(max);
        mask->long_size = sizeof(long);
 
-       for (i = 0; i < map->nr; i++)
-               set_bit(map->map[i].cpu, mask->mask);
+       for (i = 0; i < perf_cpu_map__nr(map); i++)
+               set_bit(perf_cpu_map__cpu(map, i).cpu, mask->mask);
 }
 
 static size_t cpus_size(struct perf_cpu_map *map)
 {
-       return sizeof(struct cpu_map_entries) + map->nr * sizeof(u16);
+       return sizeof(struct cpu_map_entries) + perf_cpu_map__nr(map) * sizeof(u16);
 }
 
 static size_t mask_size(struct perf_cpu_map *map, int *max)
 
        *max = 0;
 
-       for (i = 0; i < map->nr; i++) {
+       for (i = 0; i < perf_cpu_map__nr(map); i++) {
                /* bit position of the cpu is + 1 */
-               int bit = map->map[i].cpu + 1;
+               int bit = perf_cpu_map__cpu(map, i).cpu + 1;
 
                if (bit > *max)
                        *max = bit;
 
 
        if (target->cpu_list)
                ret += SNPRINTF(bf + ret, size - ret, ", CPU%s: %s)",
-                               top->evlist->core.cpus->nr > 1 ? "s" : "",
+                               perf_cpu_map__nr(top->evlist->core.cpus) > 1 ? "s" : "",
                                target->cpu_list);
        else {
                if (target->tid)
                        ret += SNPRINTF(bf + ret, size - ret, ")");
                else
                        ret += SNPRINTF(bf + ret, size - ret, ", %d CPU%s)",
-                                       top->evlist->core.cpus->nr,
-                                       top->evlist->core.cpus->nr > 1 ? "s" : "");
+                                       perf_cpu_map__nr(top->evlist->core.cpus),
+                                       perf_cpu_map__nr(top->evlist->core.cpus) > 1 ? "s" : "");
        }
 
        perf_top__reset_sample_counters(top);