aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorJan Stancek <jstancek@redhat.com>2017-02-17 06:10:26 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2017-02-17 10:56:35 -0500
commitda8a58b56c661681f9b2fd2fa59c6da3a5bac8d1 (patch)
tree6c3d7be2c88dd61e006831715244fccf951cf35f /tools/perf
parent43db2843a4a41cc8cdb6ab696639aeee1f4d5062 (diff)
perf tools: Replace _SC_NPROCESSORS_CONF with max_present_cpu in cpu_topology_map
There are 2 problems wrt. cpu_topology_map on systems with sparse CPUs: 1. offline/absent CPUs will have their socket_id and core_id set to -1 which triggers: "socket_id number is too big.You may need to upgrade the perf tool." 2. size of cpu_topology_map (perf_env.cpu[]) is allocated based on _SC_NPROCESSORS_CONF, but can be indexed with CPU ids going above. Users of perf_env.cpu[] are using CPU id as index. This can lead to read beyond what was allocated: ==19991== Invalid read of size 4 ==19991== at 0x490CEB: check_cpu_topology (topology.c:69) ==19991== by 0x490CEB: test_session_topology (topology.c:106) ... For example: _SC_NPROCESSORS_CONF == 16 available: 2 nodes (0-1) node 0 cpus: 0 6 8 10 16 22 24 26 node 0 size: 12004 MB node 0 free: 9470 MB node 1 cpus: 1 7 9 11 23 25 27 node 1 size: 12093 MB node 1 free: 9406 MB node distances: node 0 1 0: 10 20 1: 20 10 This patch changes HEADER_NRCPUS.nr_cpus_available from _SC_NPROCESSORS_CONF to max_present_cpu and updates any user of cpu_topology_map to iterate with nr_cpus_avail. As a consequence HEADER_CPU_TOPOLOGY core_id and socket_id lists get longer, but maintain compatibility with pre-patch state - index to cpu_topology_map is CPU id. perf test 36 -v 36: Session topology : --- start --- test child forked, pid 22211 templ file: /tmp/perf-test-gmdX5i CPU 0, core 0, socket 0 CPU 1, core 0, socket 1 CPU 6, core 10, socket 0 CPU 7, core 10, socket 1 CPU 8, core 1, socket 0 CPU 9, core 1, socket 1 CPU 10, core 9, socket 0 CPU 11, core 9, socket 1 CPU 16, core 0, socket 0 CPU 22, core 10, socket 0 CPU 23, core 10, socket 1 CPU 24, core 1, socket 0 CPU 25, core 1, socket 1 CPU 26, core 9, socket 0 CPU 27, core 9, socket 1 test child finished with 0 ---- end ---- Session topology: Ok Signed-off-by: Jan Stancek <jstancek@redhat.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/d7c05c6445fca74a8442c2c73cfffd349c52c44f.1487146877.git.jstancek@redhat.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/builtin-stat.c2
-rw-r--r--tools/perf/tests/topology.c4
-rw-r--r--tools/perf/util/env.c2
-rw-r--r--tools/perf/util/header.c16
4 files changed, 10 insertions, 14 deletions
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index f28719178b51..ca27a8a705ac 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1765,7 +1765,7 @@ static inline int perf_env__get_cpu(struct perf_env *env, struct cpu_map *map, i
1765 1765
1766 cpu = map->map[idx]; 1766 cpu = map->map[idx];
1767 1767
1768 if (cpu >= env->nr_cpus_online) 1768 if (cpu >= env->nr_cpus_avail)
1769 return -1; 1769 return -1;
1770 1770
1771 return cpu; 1771 return cpu;
diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c
index 98fe69ac553c..803f893550d6 100644
--- a/tools/perf/tests/topology.c
+++ b/tools/perf/tests/topology.c
@@ -65,7 +65,9 @@ static int check_cpu_topology(char *path, struct cpu_map *map)
65 session = perf_session__new(&file, false, NULL); 65 session = perf_session__new(&file, false, NULL);
66 TEST_ASSERT_VAL("can't get session", session); 66 TEST_ASSERT_VAL("can't get session", session);
67 67
68 for (i = 0; i < session->header.env.nr_cpus_online; i++) { 68 for (i = 0; i < session->header.env.nr_cpus_avail; i++) {
69 if (!cpu_map__has(map, i))
70 continue;
69 pr_debug("CPU %d, core %d, socket %d\n", i, 71 pr_debug("CPU %d, core %d, socket %d\n", i,
70 session->header.env.cpu[i].core_id, 72 session->header.env.cpu[i].core_id,
71 session->header.env.cpu[i].socket_id); 73 session->header.env.cpu[i].socket_id);
diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c
index bb964e86b09d..075fc77286bf 100644
--- a/tools/perf/util/env.c
+++ b/tools/perf/util/env.c
@@ -66,7 +66,7 @@ int perf_env__read_cpu_topology_map(struct perf_env *env)
66 return 0; 66 return 0;
67 67
68 if (env->nr_cpus_avail == 0) 68 if (env->nr_cpus_avail == 0)
69 env->nr_cpus_avail = sysconf(_SC_NPROCESSORS_CONF); 69 env->nr_cpus_avail = cpu__max_present_cpu();
70 70
71 nr_cpus = env->nr_cpus_avail; 71 nr_cpus = env->nr_cpus_avail;
72 if (nr_cpus == -1) 72 if (nr_cpus == -1)
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 1222f6c5e7b3..05714d548584 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -295,11 +295,7 @@ static int write_nrcpus(int fd, struct perf_header *h __maybe_unused,
295 u32 nrc, nra; 295 u32 nrc, nra;
296 int ret; 296 int ret;
297 297
298 nr = sysconf(_SC_NPROCESSORS_CONF); 298 nrc = cpu__max_present_cpu();
299 if (nr < 0)
300 return -1;
301
302 nrc = (u32)(nr & UINT_MAX);
303 299
304 nr = sysconf(_SC_NPROCESSORS_ONLN); 300 nr = sysconf(_SC_NPROCESSORS_ONLN);
305 if (nr < 0) 301 if (nr < 0)
@@ -513,9 +509,7 @@ static struct cpu_topo *build_cpu_topology(void)
513 int ret = -1; 509 int ret = -1;
514 struct cpu_map *map; 510 struct cpu_map *map;
515 511
516 ncpus = sysconf(_SC_NPROCESSORS_CONF); 512 ncpus = cpu__max_present_cpu();
517 if (ncpus < 0)
518 return NULL;
519 513
520 /* build online CPU map */ 514 /* build online CPU map */
521 map = cpu_map__new(NULL); 515 map = cpu_map__new(NULL);
@@ -1139,7 +1133,7 @@ static void print_cpu_topology(struct perf_header *ph, int fd __maybe_unused,
1139{ 1133{
1140 int nr, i; 1134 int nr, i;
1141 char *str; 1135 char *str;
1142 int cpu_nr = ph->env.nr_cpus_online; 1136 int cpu_nr = ph->env.nr_cpus_avail;
1143 1137
1144 nr = ph->env.nr_sibling_cores; 1138 nr = ph->env.nr_sibling_cores;
1145 str = ph->env.sibling_cores; 1139 str = ph->env.sibling_cores;
@@ -1794,7 +1788,7 @@ static int process_cpu_topology(struct perf_file_section *section,
1794 u32 nr, i; 1788 u32 nr, i;
1795 char *str; 1789 char *str;
1796 struct strbuf sb; 1790 struct strbuf sb;
1797 int cpu_nr = ph->env.nr_cpus_online; 1791 int cpu_nr = ph->env.nr_cpus_avail;
1798 u64 size = 0; 1792 u64 size = 0;
1799 1793
1800 ph->env.cpu = calloc(cpu_nr, sizeof(*ph->env.cpu)); 1794 ph->env.cpu = calloc(cpu_nr, sizeof(*ph->env.cpu));
@@ -1875,7 +1869,7 @@ static int process_cpu_topology(struct perf_file_section *section,
1875 if (ph->needs_swap) 1869 if (ph->needs_swap)
1876 nr = bswap_32(nr); 1870 nr = bswap_32(nr);
1877 1871
1878 if (nr > (u32)cpu_nr) { 1872 if (nr != (u32)-1 && nr > (u32)cpu_nr) {
1879 pr_debug("socket_id number is too big." 1873 pr_debug("socket_id number is too big."
1880 "You may need to upgrade the perf tool.\n"); 1874 "You may need to upgrade the perf tool.\n");
1881 goto free_cpu; 1875 goto free_cpu;