Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf tests: Use function to add missing maps lock

Switch loop macro maps__for_each_entry to maps__for_each_map function
that takes a callback. The function holds the maps lock, which should
be held during iteration.

Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Athira Rajeev <atrajeev@linux.vnet.ibm.com>
Cc: Changbin Du <changbin.du@huawei.com>
Cc: Colin Ian King <colin.i.king@gmail.com>
Cc: Dmitrii Dolgov <9erthalion6@gmail.com>
Cc: German Gomez <german.gomez@arm.com>
Cc: Guilherme Amadio <amadio@gentoo.org>
Cc: Huacai Chen <chenhuacai@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: K Prateek Nayak <kprateek.nayak@amd.com>
Cc: Kajol Jain <kjain@linux.ibm.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Li Dong <lidong@vivo.com>
Cc: Liam Howlett <liam.howlett@oracle.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Miguel Ojeda <ojeda@kernel.org>
Cc: Ming Wang <wangming01@loongson.cn>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Nick Terrell <terrelln@fb.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Cc: Sandipan Das <sandipan.das@amd.com>
Cc: Sean Christopherson <seanjc@google.com>
Cc: Steinar H. Gunderson <sesse@google.com>
Cc: Vincent Whitchurch <vincent.whitchurch@axis.com>
Cc: Wenyu Liu <liuwenyu7@huawei.com>
Cc: Yang Jihong <yangjihong1@huawei.com>
Link: https://lore.kernel.org/r/20231207011722.1220634-6-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
b1928ca9 431be14b

+136 -106
+38 -23
tools/perf/tests/maps.c
··· 14 14 u64 end; 15 15 }; 16 16 17 + struct check_maps_cb_args { 18 + struct map_def *merged; 19 + unsigned int i; 20 + }; 21 + 22 + static int check_maps_cb(struct map *map, void *data) 23 + { 24 + struct check_maps_cb_args *args = data; 25 + struct map_def *merged = &args->merged[args->i]; 26 + 27 + if (map__start(map) != merged->start || 28 + map__end(map) != merged->end || 29 + strcmp(map__dso(map)->name, merged->name) || 30 + refcount_read(map__refcnt(map)) != 1) { 31 + return 1; 32 + } 33 + args->i++; 34 + return 0; 35 + } 36 + 37 + static int failed_cb(struct map *map, void *data __maybe_unused) 38 + { 39 + pr_debug("\tstart: %" PRIu64 " end: %" PRIu64 " name: '%s' refcnt: %d\n", 40 + map__start(map), 41 + map__end(map), 42 + map__dso(map)->name, 43 + refcount_read(map__refcnt(map))); 44 + 45 + return 0; 46 + } 47 + 17 48 static int check_maps(struct map_def *merged, unsigned int size, struct maps *maps) 18 49 { 19 - struct map_rb_node *rb_node; 20 - unsigned int i = 0; 21 50 bool failed = false; 22 51 23 52 if (maps__nr_maps(maps) != size) { 24 53 pr_debug("Expected %d maps, got %d", size, maps__nr_maps(maps)); 25 54 failed = true; 26 55 } else { 27 - maps__for_each_entry(maps, rb_node) { 28 - struct map *map = rb_node->map; 29 - 30 - if (map__start(map) != merged[i].start || 31 - map__end(map) != merged[i].end || 32 - strcmp(map__dso(map)->name, merged[i].name) || 33 - refcount_read(map__refcnt(map)) != 1) { 34 - failed = true; 35 - } 36 - i++; 37 - } 56 + struct check_maps_cb_args args = { 57 + .merged = merged, 58 + .i = 0, 59 + }; 60 + failed = maps__for_each_map(maps, check_maps_cb, &args); 38 61 } 39 62 if (failed) { 40 63 pr_debug("Expected:\n"); 41 - for (i = 0; i < size; i++) { 64 + for (unsigned int i = 0; i < size; i++) { 42 65 pr_debug("\tstart: %" PRIu64 " end: %" PRIu64 " name: '%s' refcnt: 1\n", 43 66 merged[i].start, merged[i].end, merged[i].name); 44 67 } 45 68 pr_debug("Got:\n"); 46 - maps__for_each_entry(maps, rb_node) { 47 - struct map *map = rb_node->map; 48 - 49 - pr_debug("\tstart: %" PRIu64 " end: %" PRIu64 " name: '%s' refcnt: %d\n", 50 - map__start(map), 51 - map__end(map), 52 - map__dso(map)->name, 53 - refcount_read(map__refcnt(map))); 54 - } 69 + maps__for_each_map(maps, failed_cb, NULL); 55 70 } 56 71 return failed ? TEST_FAIL : TEST_OK; 57 72 }
+98 -83
tools/perf/tests/vmlinux-kallsyms.c
··· 112 112 return false; 113 113 } 114 114 115 + struct test__vmlinux_matches_kallsyms_cb_args { 116 + struct machine kallsyms; 117 + struct map *vmlinux_map; 118 + bool header_printed; 119 + }; 120 + 121 + static int test__vmlinux_matches_kallsyms_cb1(struct map *map, void *data) 122 + { 123 + struct test__vmlinux_matches_kallsyms_cb_args *args = data; 124 + struct dso *dso = map__dso(map); 125 + /* 126 + * If it is the kernel, kallsyms is always "[kernel.kallsyms]", while 127 + * the kernel will have the path for the vmlinux file being used, so use 128 + * the short name, less descriptive but the same ("[kernel]" in both 129 + * cases. 130 + */ 131 + struct map *pair = maps__find_by_name(args->kallsyms.kmaps, 132 + (dso->kernel ? dso->short_name : dso->name)); 133 + 134 + if (pair) 135 + map__set_priv(pair, 1); 136 + else { 137 + if (!args->header_printed) { 138 + pr_info("WARN: Maps only in vmlinux:\n"); 139 + args->header_printed = true; 140 + } 141 + map__fprintf(map, stderr); 142 + } 143 + return 0; 144 + } 145 + 146 + static int test__vmlinux_matches_kallsyms_cb2(struct map *map, void *data) 147 + { 148 + struct test__vmlinux_matches_kallsyms_cb_args *args = data; 149 + struct map *pair; 150 + u64 mem_start = map__unmap_ip(args->vmlinux_map, map__start(map)); 151 + u64 mem_end = map__unmap_ip(args->vmlinux_map, map__end(map)); 152 + 153 + pair = maps__find(args->kallsyms.kmaps, mem_start); 154 + if (pair == NULL || map__priv(pair)) 155 + return 0; 156 + 157 + if (map__start(pair) == mem_start) { 158 + struct dso *dso = map__dso(map); 159 + 160 + if (!args->header_printed) { 161 + pr_info("WARN: Maps in vmlinux with a different name in kallsyms:\n"); 162 + args->header_printed = true; 163 + } 164 + 165 + pr_info("WARN: %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as", 166 + map__start(map), map__end(map), map__pgoff(map), dso->name); 167 + if (mem_end != map__end(pair)) 168 + pr_info(":\nWARN: *%" PRIx64 "-%" PRIx64 " %" PRIx64, 169 + map__start(pair), map__end(pair), map__pgoff(pair)); 170 + pr_info(" %s\n", dso->name); 171 + map__set_priv(pair, 1); 172 + } 173 + return 0; 174 + } 175 + 176 + static int test__vmlinux_matches_kallsyms_cb3(struct map *map, void *data) 177 + { 178 + struct test__vmlinux_matches_kallsyms_cb_args *args = data; 179 + 180 + if (!map__priv(map)) { 181 + if (!args->header_printed) { 182 + pr_info("WARN: Maps only in kallsyms:\n"); 183 + args->header_printed = true; 184 + } 185 + map__fprintf(map, stderr); 186 + } 187 + return 0; 188 + } 189 + 115 190 static int test__vmlinux_matches_kallsyms(struct test_suite *test __maybe_unused, 116 191 int subtest __maybe_unused) 117 192 { 118 193 int err = TEST_FAIL; 119 194 struct rb_node *nd; 120 195 struct symbol *sym; 121 - struct map *kallsyms_map, *vmlinux_map; 122 - struct map_rb_node *rb_node; 123 - struct machine kallsyms, vmlinux; 196 + struct map *kallsyms_map; 197 + struct machine vmlinux; 124 198 struct maps *maps; 125 199 u64 mem_start, mem_end; 126 - bool header_printed; 200 + struct test__vmlinux_matches_kallsyms_cb_args args; 127 201 128 202 /* 129 203 * Step 1: ··· 205 131 * Init the machines that will hold kernel, modules obtained from 206 132 * both vmlinux + .ko files and from /proc/kallsyms split by modules. 207 133 */ 208 - machine__init(&kallsyms, "", HOST_KERNEL_ID); 134 + machine__init(&args.kallsyms, "", HOST_KERNEL_ID); 209 135 machine__init(&vmlinux, "", HOST_KERNEL_ID); 210 136 211 137 maps = machine__kernel_maps(&vmlinux); ··· 217 143 * load /proc/kallsyms. Also create the modules maps from /proc/modules 218 144 * and find the .ko files that match them in /lib/modules/`uname -r`/. 219 145 */ 220 - if (machine__create_kernel_maps(&kallsyms) < 0) { 146 + if (machine__create_kernel_maps(&args.kallsyms) < 0) { 221 147 pr_debug("machine__create_kernel_maps failed"); 222 148 err = TEST_SKIP; 223 149 goto out; ··· 234 160 * be compacted against the list of modules found in the "vmlinux" 235 161 * code and with the one got from /proc/modules from the "kallsyms" code. 236 162 */ 237 - if (machine__load_kallsyms(&kallsyms, "/proc/kallsyms") <= 0) { 163 + if (machine__load_kallsyms(&args.kallsyms, "/proc/kallsyms") <= 0) { 238 164 pr_debug("machine__load_kallsyms failed"); 239 165 err = TEST_SKIP; 240 166 goto out; ··· 248 174 * to see if the running kernel was relocated by checking if it has the 249 175 * same value in the vmlinux file we load. 250 176 */ 251 - kallsyms_map = machine__kernel_map(&kallsyms); 177 + kallsyms_map = machine__kernel_map(&args.kallsyms); 252 178 253 179 /* 254 180 * Step 5: ··· 260 186 goto out; 261 187 } 262 188 263 - vmlinux_map = machine__kernel_map(&vmlinux); 189 + args.vmlinux_map = machine__kernel_map(&vmlinux); 264 190 265 191 /* 266 192 * Step 6: ··· 287 213 * in the kallsyms dso. For the ones that are in both, check its names and 288 214 * end addresses too. 289 215 */ 290 - map__for_each_symbol(vmlinux_map, sym, nd) { 216 + map__for_each_symbol(args.vmlinux_map, sym, nd) { 291 217 struct symbol *pair, *first_pair; 292 218 293 219 sym = rb_entry(nd, struct symbol, rb_node); ··· 295 221 if (sym->start == sym->end) 296 222 continue; 297 223 298 - mem_start = map__unmap_ip(vmlinux_map, sym->start); 299 - mem_end = map__unmap_ip(vmlinux_map, sym->end); 224 + mem_start = map__unmap_ip(args.vmlinux_map, sym->start); 225 + mem_end = map__unmap_ip(args.vmlinux_map, sym->end); 300 226 301 - first_pair = machine__find_kernel_symbol(&kallsyms, mem_start, NULL); 227 + first_pair = machine__find_kernel_symbol(&args.kallsyms, mem_start, NULL); 302 228 pair = first_pair; 303 229 304 230 if (pair && UM(pair->start) == mem_start) { ··· 327 253 */ 328 254 continue; 329 255 } else { 330 - pair = machine__find_kernel_symbol_by_name(&kallsyms, sym->name, NULL); 256 + pair = machine__find_kernel_symbol_by_name(&args.kallsyms, 257 + sym->name, NULL); 331 258 if (pair) { 332 259 if (UM(pair->start) == mem_start) 333 260 goto next_pair; ··· 342 267 343 268 continue; 344 269 } 345 - } else if (mem_start == map__end(kallsyms.vmlinux_map)) { 270 + } else if (mem_start == map__end(args.kallsyms.vmlinux_map)) { 346 271 /* 347 272 * Ignore aliases to _etext, i.e. to the end of the kernel text area, 348 273 * such as __indirect_thunk_end. ··· 364 289 if (verbose <= 0) 365 290 goto out; 366 291 367 - header_printed = false; 292 + args.header_printed = false; 293 + maps__for_each_map(maps, test__vmlinux_matches_kallsyms_cb1, &args); 368 294 369 - maps__for_each_entry(maps, rb_node) { 370 - struct map *map = rb_node->map; 371 - struct dso *dso = map__dso(map); 372 - /* 373 - * If it is the kernel, kallsyms is always "[kernel.kallsyms]", while 374 - * the kernel will have the path for the vmlinux file being used, 375 - * so use the short name, less descriptive but the same ("[kernel]" in 376 - * both cases. 377 - */ 378 - struct map *pair = maps__find_by_name(kallsyms.kmaps, (dso->kernel ? 379 - dso->short_name : 380 - dso->name)); 381 - if (pair) { 382 - map__set_priv(pair, 1); 383 - } else { 384 - if (!header_printed) { 385 - pr_info("WARN: Maps only in vmlinux:\n"); 386 - header_printed = true; 387 - } 388 - map__fprintf(map, stderr); 389 - } 390 - } 295 + args.header_printed = false; 296 + maps__for_each_map(maps, test__vmlinux_matches_kallsyms_cb2, &args); 391 297 392 - header_printed = false; 298 + args.header_printed = false; 299 + maps = machine__kernel_maps(&args.kallsyms); 300 + maps__for_each_map(maps, test__vmlinux_matches_kallsyms_cb3, &args); 393 301 394 - maps__for_each_entry(maps, rb_node) { 395 - struct map *pair, *map = rb_node->map; 396 - 397 - mem_start = map__unmap_ip(vmlinux_map, map__start(map)); 398 - mem_end = map__unmap_ip(vmlinux_map, map__end(map)); 399 - 400 - pair = maps__find(kallsyms.kmaps, mem_start); 401 - if (pair == NULL || map__priv(pair)) 402 - continue; 403 - 404 - if (map__start(pair) == mem_start) { 405 - struct dso *dso = map__dso(map); 406 - 407 - if (!header_printed) { 408 - pr_info("WARN: Maps in vmlinux with a different name in kallsyms:\n"); 409 - header_printed = true; 410 - } 411 - 412 - pr_info("WARN: %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as", 413 - map__start(map), map__end(map), map__pgoff(map), dso->name); 414 - if (mem_end != map__end(pair)) 415 - pr_info(":\nWARN: *%" PRIx64 "-%" PRIx64 " %" PRIx64, 416 - map__start(pair), map__end(pair), map__pgoff(pair)); 417 - pr_info(" %s\n", dso->name); 418 - map__set_priv(pair, 1); 419 - } 420 - } 421 - 422 - header_printed = false; 423 - 424 - maps = machine__kernel_maps(&kallsyms); 425 - 426 - maps__for_each_entry(maps, rb_node) { 427 - struct map *map = rb_node->map; 428 - 429 - if (!map__priv(map)) { 430 - if (!header_printed) { 431 - pr_info("WARN: Maps only in kallsyms:\n"); 432 - header_printed = true; 433 - } 434 - map__fprintf(map, stderr); 435 - } 436 - } 437 302 out: 438 - machine__exit(&kallsyms); 303 + machine__exit(&args.kallsyms); 439 304 machine__exit(&vmlinux); 440 305 return err; 441 306 }