1 // SPDX-License-Identifier: GPL-2.0 2 #include "math.h" 3 #include "parse-events.h" 4 #include "pmu.h" 5 #include "pmus.h" 6 #include "tests.h" 7 #include <errno.h> 8 #include <stdio.h> 9 #include <linux/kernel.h> 10 #include <linux/zalloc.h> 11 #include "debug.h" 12 #include "../pmu-events/pmu-events.h" 13 #include <perf/evlist.h> 14 #include "util/evlist.h" 15 #include "util/expr.h" 16 #include "util/hashmap.h" 17 #include "util/parse-events.h" 18 #include "metricgroup.h" 19 #include "stat.h" 20 21 struct perf_pmu_test_event { 22 /* used for matching against events from generated pmu-events.c */ 23 struct pmu_event event; 24 25 /* 26 * Note: For when PublicDescription does not exist in the JSON, we 27 * will have no long_desc in pmu_event.long_desc, but long_desc may 28 * be set in the alias. 29 */ 30 const char *alias_long_desc; 31 32 /* PMU which we should match against */ 33 const char *matching_pmu; 34 }; 35 36 struct perf_pmu_test_pmu { 37 const char *pmu_name; 38 bool pmu_is_uncore; 39 const char *pmu_id; 40 struct perf_pmu_test_event const *aliases[10]; 41 }; 42 43 static const struct perf_pmu_test_event bp_l1_btb_correct = { 44 .event = { 45 .pmu = "default_core", 46 .name = "bp_l1_btb_correct", 47 .event = "event=0x8a", 48 .desc = "L1 BTB Correction", 49 .topic = "branch", 50 }, 51 }; 52 53 static const struct perf_pmu_test_event bp_l2_btb_correct = { 54 .event = { 55 .pmu = "default_core", 56 .name = "bp_l2_btb_correct", 57 .event = "event=0x8b", 58 .desc = "L2 BTB Correction", 59 .topic = "branch", 60 }, 61 }; 62 63 static const struct perf_pmu_test_event segment_reg_loads_any = { 64 .event = { 65 .pmu = "default_core", 66 .name = "segment_reg_loads.any", 67 .event = "event=6,period=200000,umask=0x80", 68 .desc = "Number of segment register loads", 69 .topic = "other", 70 }, 71 }; 72 73 static const struct perf_pmu_test_event dispatch_blocked_any = { 74 .event = { 75 .pmu = "default_core", 76 .name = "dispatch_blocked.any", 77 .event = "event=9,period=200000,umask=0x20", 78 .desc = "Memory cluster signals to block micro-op dispatch for any reason", 79 .topic = "other", 80 }, 81 }; 82 83 static const struct perf_pmu_test_event eist_trans = { 84 .event = { 85 .pmu = "default_core", 86 .name = "eist_trans", 87 .event = "event=0x3a,period=200000", 88 .desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions", 89 .topic = "other", 90 }, 91 }; 92 93 static const struct perf_pmu_test_event l3_cache_rd = { 94 .event = { 95 .pmu = "default_core", 96 .name = "l3_cache_rd", 97 .event = "event=0x40", 98 .desc = "L3 cache access, read", 99 .long_desc = "Attributable Level 3 cache access, read", 100 .topic = "cache", 101 }, 102 .alias_long_desc = "Attributable Level 3 cache access, read", 103 }; 104 105 static const struct perf_pmu_test_event *core_events[] = { 106 &bp_l1_btb_correct, 107 &bp_l2_btb_correct, 108 &segment_reg_loads_any, 109 &dispatch_blocked_any, 110 &eist_trans, 111 &l3_cache_rd, 112 NULL 113 }; 114 115 static const struct perf_pmu_test_event uncore_hisi_ddrc_flux_wcmd = { 116 .event = { 117 .name = "uncore_hisi_ddrc.flux_wcmd", 118 .event = "event=2", 119 .desc = "DDRC write commands", 120 .topic = "uncore", 121 .pmu = "hisi_sccl,ddrc", 122 }, 123 .matching_pmu = "hisi_sccl1_ddrc2", 124 }; 125 126 static const struct perf_pmu_test_event unc_cbo_xsnp_response_miss_eviction = { 127 .event = { 128 .name = "unc_cbo_xsnp_response.miss_eviction", 129 .event = "event=0x22,umask=0x81", 130 .desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core", 131 .topic = "uncore", 132 .pmu = "uncore_cbox", 133 }, 134 .matching_pmu = "uncore_cbox_0", 135 }; 136 137 static const struct perf_pmu_test_event uncore_hyphen = { 138 .event = { 139 .name = "event-hyphen", 140 .event = "event=0xe0", 141 .desc = "UNC_CBO_HYPHEN", 142 .topic = "uncore", 143 .pmu = "uncore_cbox", 144 }, 145 .matching_pmu = "uncore_cbox_0", 146 }; 147 148 static const struct perf_pmu_test_event uncore_two_hyph = { 149 .event = { 150 .name = "event-two-hyph", 151 .event = "event=0xc0", 152 .desc = "UNC_CBO_TWO_HYPH", 153 .topic = "uncore", 154 .pmu = "uncore_cbox", 155 }, 156 .matching_pmu = "uncore_cbox_0", 157 }; 158 159 static const struct perf_pmu_test_event uncore_hisi_l3c_rd_hit_cpipe = { 160 .event = { 161 .name = "uncore_hisi_l3c.rd_hit_cpipe", 162 .event = "event=7", 163 .desc = "Total read hits", 164 .topic = "uncore", 165 .pmu = "hisi_sccl,l3c", 166 }, 167 .matching_pmu = "hisi_sccl3_l3c7", 168 }; 169 170 static const struct perf_pmu_test_event uncore_imc_free_running_cache_miss = { 171 .event = { 172 .name = "uncore_imc_free_running.cache_miss", 173 .event = "event=0x12", 174 .desc = "Total cache misses", 175 .topic = "uncore", 176 .pmu = "uncore_imc_free_running", 177 }, 178 .matching_pmu = "uncore_imc_free_running_0", 179 }; 180 181 static const struct perf_pmu_test_event uncore_imc_cache_hits = { 182 .event = { 183 .name = "uncore_imc.cache_hits", 184 .event = "event=0x34", 185 .desc = "Total cache hits", 186 .topic = "uncore", 187 .pmu = "uncore_imc", 188 }, 189 .matching_pmu = "uncore_imc_0", 190 }; 191 192 static const struct perf_pmu_test_event *uncore_events[] = { 193 &uncore_hisi_ddrc_flux_wcmd, 194 &unc_cbo_xsnp_response_miss_eviction, 195 &uncore_hyphen, 196 &uncore_two_hyph, 197 &uncore_hisi_l3c_rd_hit_cpipe, 198 &uncore_imc_free_running_cache_miss, 199 &uncore_imc_cache_hits, 200 NULL 201 }; 202 203 static const struct perf_pmu_test_event sys_ddr_pmu_write_cycles = { 204 .event = { 205 .name = "sys_ddr_pmu.write_cycles", 206 .event = "event=0x2b", 207 .desc = "ddr write-cycles event", 208 .topic = "uncore", 209 .pmu = "uncore_sys_ddr_pmu", 210 .compat = "v8", 211 }, 212 .matching_pmu = "uncore_sys_ddr_pmu0", 213 }; 214 215 static const struct perf_pmu_test_event sys_ccn_pmu_read_cycles = { 216 .event = { 217 .name = "sys_ccn_pmu.read_cycles", 218 .event = "config=0x2c", 219 .desc = "ccn read-cycles event", 220 .topic = "uncore", 221 .pmu = "uncore_sys_ccn_pmu", 222 .compat = "0x01", 223 }, 224 .matching_pmu = "uncore_sys_ccn_pmu4", 225 }; 226 227 static const struct perf_pmu_test_event sys_cmn_pmu_hnf_cache_miss = { 228 .event = { 229 .name = "sys_cmn_pmu.hnf_cache_miss", 230 .event = "eventid=1,type=5", 231 .desc = "Counts total cache misses in first lookup result (high priority)", 232 .topic = "uncore", 233 .pmu = "uncore_sys_cmn_pmu", 234 .compat = "(434|436|43c|43a).*", 235 }, 236 .matching_pmu = "uncore_sys_cmn_pmu0", 237 }; 238 239 static const struct perf_pmu_test_event *sys_events[] = { 240 &sys_ddr_pmu_write_cycles, 241 &sys_ccn_pmu_read_cycles, 242 &sys_cmn_pmu_hnf_cache_miss, 243 NULL 244 }; 245 246 static bool is_same(const char *reference, const char *test) 247 { 248 if (!reference && !test) 249 return true; 250 251 if (reference && !test) 252 return false; 253 254 if (!reference && test) 255 return false; 256 257 return !strcmp(reference, test); 258 } 259 260 static int compare_pmu_events(const struct pmu_event *e1, const struct pmu_event *e2) 261 { 262 if (!is_same(e1->name, e2->name)) { 263 pr_debug2("testing event e1 %s: mismatched name string, %s vs %s\n", 264 e1->name, e1->name, e2->name); 265 return -1; 266 } 267 268 if (!is_same(e1->compat, e2->compat)) { 269 pr_debug2("testing event e1 %s: mismatched compat string, %s vs %s\n", 270 e1->name, e1->compat, e2->compat); 271 return -1; 272 } 273 274 if (!is_same(e1->event, e2->event)) { 275 pr_debug2("testing event e1 %s: mismatched event, %s vs %s\n", 276 e1->name, e1->event, e2->event); 277 return -1; 278 } 279 280 if (!is_same(e1->desc, e2->desc)) { 281 pr_debug2("testing event e1 %s: mismatched desc, %s vs %s\n", 282 e1->name, e1->desc, e2->desc); 283 return -1; 284 } 285 286 if (!is_same(e1->topic, e2->topic)) { 287 pr_debug2("testing event e1 %s: mismatched topic, %s vs %s\n", 288 e1->name, e1->topic, e2->topic); 289 return -1; 290 } 291 292 if (!is_same(e1->long_desc, e2->long_desc)) { 293 pr_debug2("testing event e1 %s: mismatched long_desc, %s vs %s\n", 294 e1->name, e1->long_desc, e2->long_desc); 295 return -1; 296 } 297 298 if (!is_same(e1->pmu, e2->pmu)) { 299 pr_debug2("testing event e1 %s: mismatched pmu string, %s vs %s\n", 300 e1->name, e1->pmu, e2->pmu); 301 return -1; 302 } 303 304 if (!is_same(e1->unit, e2->unit)) { 305 pr_debug2("testing event e1 %s: mismatched unit, %s vs %s\n", 306 e1->name, e1->unit, e2->unit); 307 return -1; 308 } 309 310 if (e1->perpkg != e2->perpkg) { 311 pr_debug2("testing event e1 %s: mismatched perpkg, %d vs %d\n", 312 e1->name, e1->perpkg, e2->perpkg); 313 return -1; 314 } 315 316 if (e1->deprecated != e2->deprecated) { 317 pr_debug2("testing event e1 %s: mismatched deprecated, %d vs %d\n", 318 e1->name, e1->deprecated, e2->deprecated); 319 return -1; 320 } 321 322 return 0; 323 } 324 325 static int compare_alias_to_test_event(struct pmu_event_info *alias, 326 struct perf_pmu_test_event const *test_event, 327 char const *pmu_name) 328 { 329 struct pmu_event const *event = &test_event->event; 330 331 /* An alias was found, ensure everything is in order */ 332 if (!is_same(alias->name, event->name)) { 333 pr_debug("testing aliases PMU %s: mismatched name, %s vs %s\n", 334 pmu_name, alias->name, event->name); 335 return -1; 336 } 337 338 if (!is_same(alias->desc, event->desc)) { 339 pr_debug("testing aliases PMU %s: mismatched desc, %s vs %s\n", 340 pmu_name, alias->desc, event->desc); 341 return -1; 342 } 343 344 if (!is_same(alias->long_desc, test_event->alias_long_desc)) { 345 pr_debug("testing aliases PMU %s: mismatched long_desc, %s vs %s\n", 346 pmu_name, alias->long_desc, 347 test_event->alias_long_desc); 348 return -1; 349 } 350 351 if (!is_same(alias->topic, event->topic)) { 352 pr_debug("testing aliases PMU %s: mismatched topic, %s vs %s\n", 353 pmu_name, alias->topic, event->topic); 354 return -1; 355 } 356 357 if (!is_same(alias->str, test_event->event.event)) { 358 pr_debug("testing aliases PMU %s: mismatched str, %s vs %s\n", 359 pmu_name, alias->str, test_event->event.event); 360 return -1; 361 } 362 363 if (!is_same(alias->long_desc, test_event->alias_long_desc)) { 364 pr_debug("testing aliases PMU %s: mismatched long desc, %s vs %s\n", 365 pmu_name, alias->str, test_event->alias_long_desc); 366 return -1; 367 } 368 369 if (!is_same(alias->pmu_name, test_event->event.pmu) && 370 !is_same(alias->pmu_name, "default_core")) { 371 pr_debug("testing aliases PMU %s: mismatched pmu_name, %s vs %s\n", 372 pmu_name, alias->pmu_name, test_event->event.pmu); 373 return -1; 374 } 375 376 return 0; 377 } 378 379 static int test__pmu_event_table_core_callback(const struct pmu_event *pe, 380 const struct pmu_events_table *table __maybe_unused, 381 void *data) 382 { 383 int *map_events = data; 384 struct perf_pmu_test_event const **test_event_table; 385 bool found = false; 386 387 if (strcmp(pe->pmu, "default_core")) 388 test_event_table = &uncore_events[0]; 389 else 390 test_event_table = &core_events[0]; 391 392 for (; *test_event_table; test_event_table++) { 393 struct perf_pmu_test_event const *test_event = *test_event_table; 394 struct pmu_event const *event = &test_event->event; 395 396 if (strcmp(pe->name, event->name)) 397 continue; 398 found = true; 399 (*map_events)++; 400 401 if (compare_pmu_events(pe, event)) 402 return -1; 403 404 pr_debug("testing event table %s: pass\n", pe->name); 405 } 406 if (!found) { 407 pr_err("testing event table: could not find event %s\n", pe->name); 408 return -1; 409 } 410 return 0; 411 } 412 413 static int test__pmu_event_table_sys_callback(const struct pmu_event *pe, 414 const struct pmu_events_table *table __maybe_unused, 415 void *data) 416 { 417 int *map_events = data; 418 struct perf_pmu_test_event const **test_event_table; 419 bool found = false; 420 421 test_event_table = &sys_events[0]; 422 423 for (; *test_event_table; test_event_table++) { 424 struct perf_pmu_test_event const *test_event = *test_event_table; 425 struct pmu_event const *event = &test_event->event; 426 427 if (strcmp(pe->name, event->name)) 428 continue; 429 found = true; 430 (*map_events)++; 431 432 if (compare_pmu_events(pe, event)) 433 return TEST_FAIL; 434 435 pr_debug("testing sys event table %s: pass\n", pe->name); 436 } 437 if (!found) { 438 pr_debug("testing sys event table: could not find event %s\n", pe->name); 439 return TEST_FAIL; 440 } 441 return TEST_OK; 442 } 443 444 /* Verify generated events from pmu-events.c are as expected */ 445 static int test__pmu_event_table(struct test_suite *test __maybe_unused, 446 int subtest __maybe_unused) 447 { 448 const struct pmu_events_table *sys_event_table = 449 find_sys_events_table("pmu_events__test_soc_sys"); 450 const struct pmu_events_table *table = find_core_events_table("testarch", "testcpu"); 451 int map_events = 0, expected_events, err; 452 453 /* ignore 3x sentinels */ 454 expected_events = ARRAY_SIZE(core_events) + 455 ARRAY_SIZE(uncore_events) + 456 ARRAY_SIZE(sys_events) - 3; 457 458 if (!table || !sys_event_table) 459 return -1; 460 461 err = pmu_events_table__for_each_event(table, /*pmu=*/ NULL, 462 test__pmu_event_table_core_callback, 463 &map_events); 464 if (err) 465 return err; 466 467 err = pmu_events_table__for_each_event(sys_event_table, /*pmu=*/ NULL, 468 test__pmu_event_table_sys_callback, 469 &map_events); 470 if (err) 471 return err; 472 473 if (map_events != expected_events) { 474 pr_err("testing event table: found %d, but expected %d\n", 475 map_events, expected_events); 476 return TEST_FAIL; 477 } 478 479 return 0; 480 } 481 482 struct test_core_pmu_event_aliases_cb_args { 483 struct perf_pmu_test_event const *test_event; 484 int *count; 485 }; 486 487 static int test_core_pmu_event_aliases_cb(void *state, struct pmu_event_info *alias) 488 { 489 struct test_core_pmu_event_aliases_cb_args *args = state; 490 491 if (compare_alias_to_test_event(alias, args->test_event, alias->pmu->name)) 492 return -1; 493 (*args->count)++; 494 pr_debug2("testing aliases core PMU %s: matched event %s\n", 495 alias->pmu_name, alias->name); 496 return 0; 497 } 498 499 /* Verify aliases are as expected */ 500 static int __test_core_pmu_event_aliases(const char *pmu_name, int *count) 501 { 502 struct perf_pmu_test_event const **test_event_table; 503 struct perf_pmu *pmu; 504 int res = 0; 505 const struct pmu_events_table *table = find_core_events_table("testarch", "testcpu"); 506 507 if (!table) 508 return -1; 509 510 test_event_table = &core_events[0]; 511 512 pmu = zalloc(sizeof(*pmu)); 513 if (!pmu) 514 return -1; 515 516 if (perf_pmu__init(pmu, PERF_PMU_TYPE_FAKE, pmu_name) != 0) { 517 perf_pmu__delete(pmu); 518 return -1; 519 } 520 pmu->is_core = true; 521 522 pmu->events_table = table; 523 pmu_add_cpu_aliases_table(pmu, table); 524 pmu->cpu_aliases_added = true; 525 pmu->sysfs_aliases_loaded = true; 526 527 res = pmu_events_table__find_event(table, pmu, "bp_l1_btb_correct", NULL, NULL); 528 if (res != 0) { 529 pr_debug("Missing test event in test architecture"); 530 return res; 531 } 532 for (; *test_event_table; test_event_table++) { 533 struct perf_pmu_test_event test_event = **test_event_table; 534 struct pmu_event const *event = &test_event.event; 535 struct test_core_pmu_event_aliases_cb_args args = { 536 .test_event = &test_event, 537 .count = count, 538 }; 539 int err; 540 541 test_event.event.pmu = pmu_name; 542 err = perf_pmu__find_event(pmu, event->name, &args, 543 test_core_pmu_event_aliases_cb); 544 if (err) 545 res = err; 546 } 547 perf_pmu__delete(pmu); 548 549 return res; 550 } 551 552 static int __test_uncore_pmu_event_aliases(struct perf_pmu_test_pmu *test_pmu) 553 { 554 int alias_count = 0, to_match_count = 0, matched_count = 0; 555 struct perf_pmu_test_event const **table; 556 struct perf_pmu *pmu; 557 const struct pmu_events_table *events_table; 558 int res = 0; 559 560 events_table = find_core_events_table("testarch", "testcpu"); 561 if (!events_table) 562 return -1; 563 564 pmu = zalloc(sizeof(*pmu)); 565 if (!pmu) 566 return -1; 567 568 if (perf_pmu__init(pmu, PERF_PMU_TYPE_FAKE, test_pmu->pmu_name) != 0) { 569 perf_pmu__delete(pmu); 570 return -1; 571 } 572 pmu->is_uncore = test_pmu->pmu_is_uncore; 573 if (test_pmu->pmu_id) { 574 pmu->id = strdup(test_pmu->pmu_id); 575 if (!pmu->id) { 576 perf_pmu__delete(pmu); 577 return -1; 578 } 579 } 580 pmu->events_table = events_table; 581 pmu_add_cpu_aliases_table(pmu, events_table); 582 pmu->cpu_aliases_added = true; 583 pmu->sysfs_aliases_loaded = true; 584 pmu_add_sys_aliases(pmu); 585 586 /* Count how many aliases we generated */ 587 alias_count = perf_pmu__num_events(pmu); 588 589 /* Count how many aliases we expect from the known table */ 590 for (table = &test_pmu->aliases[0]; *table; table++) 591 to_match_count++; 592 593 if (alias_count != to_match_count) { 594 pr_debug("testing aliases uncore PMU %s: mismatch expected aliases (%d) vs found (%d)\n", 595 pmu->name, to_match_count, alias_count); 596 perf_pmu__delete(pmu); 597 return -1; 598 } 599 600 for (table = &test_pmu->aliases[0]; *table; table++) { 601 struct perf_pmu_test_event test_event = **table; 602 struct pmu_event const *event = &test_event.event; 603 int err; 604 struct test_core_pmu_event_aliases_cb_args args = { 605 .test_event = &test_event, 606 .count = &matched_count, 607 }; 608 609 if (strcmp(pmu->name, test_event.matching_pmu)) { 610 pr_debug("testing aliases uncore PMU %s: mismatched matching_pmu, %s vs %s\n", 611 pmu->name, test_event.matching_pmu, pmu->name); 612 perf_pmu__delete(pmu); 613 return -1; 614 } 615 616 err = perf_pmu__find_event(pmu, event->name, &args, 617 test_core_pmu_event_aliases_cb); 618 if (err) { 619 res = err; 620 pr_debug("testing aliases uncore PMU %s: could not match alias %s\n", 621 pmu->name, event->name); 622 perf_pmu__delete(pmu); 623 return -1; 624 } 625 } 626 627 if (alias_count != matched_count) { 628 pr_debug("testing aliases uncore PMU %s: mismatch found aliases (%d) vs matched (%d)\n", 629 pmu->name, matched_count, alias_count); 630 res = -1; 631 } 632 perf_pmu__delete(pmu); 633 return res; 634 } 635 636 static struct perf_pmu_test_pmu test_pmus[] = { 637 { 638 .pmu_name = "hisi_sccl1_ddrc2", 639 .pmu_is_uncore = 1, 640 .aliases = { 641 &uncore_hisi_ddrc_flux_wcmd, 642 }, 643 }, 644 { 645 .pmu_name = "uncore_cbox_0", 646 .pmu_is_uncore = 1, 647 .aliases = { 648 &unc_cbo_xsnp_response_miss_eviction, 649 &uncore_hyphen, 650 &uncore_two_hyph, 651 }, 652 }, 653 { 654 .pmu_name = "hisi_sccl3_l3c7", 655 .pmu_is_uncore = 1, 656 .aliases = { 657 &uncore_hisi_l3c_rd_hit_cpipe, 658 }, 659 }, 660 { 661 .pmu_name = "uncore_imc_free_running_0", 662 .pmu_is_uncore = 1, 663 .aliases = { 664 &uncore_imc_free_running_cache_miss, 665 }, 666 }, 667 { 668 .pmu_name = "uncore_imc_0", 669 .pmu_is_uncore = 1, 670 .aliases = { 671 &uncore_imc_cache_hits, 672 }, 673 }, 674 { 675 .pmu_name = "uncore_sys_ddr_pmu0", 676 .pmu_is_uncore = 1, 677 .pmu_id = "v8", 678 .aliases = { 679 &sys_ddr_pmu_write_cycles, 680 }, 681 }, 682 { 683 .pmu_name = "uncore_sys_ccn_pmu4", 684 .pmu_is_uncore = 1, 685 .pmu_id = "0x01", 686 .aliases = { 687 &sys_ccn_pmu_read_cycles, 688 }, 689 }, 690 { 691 .pmu_name = "uncore_sys_cmn_pmu0", 692 .pmu_is_uncore = 1, 693 .pmu_id = "43401", 694 .aliases = { 695 &sys_cmn_pmu_hnf_cache_miss, 696 }, 697 }, 698 { 699 .pmu_name = "uncore_sys_cmn_pmu0", 700 .pmu_is_uncore = 1, 701 .pmu_id = "43602", 702 .aliases = { 703 &sys_cmn_pmu_hnf_cache_miss, 704 }, 705 }, 706 { 707 .pmu_name = "uncore_sys_cmn_pmu0", 708 .pmu_is_uncore = 1, 709 .pmu_id = "43c03", 710 .aliases = { 711 &sys_cmn_pmu_hnf_cache_miss, 712 }, 713 }, 714 { 715 .pmu_name = "uncore_sys_cmn_pmu0", 716 .pmu_is_uncore = 1, 717 .pmu_id = "43a01", 718 .aliases = { 719 &sys_cmn_pmu_hnf_cache_miss, 720 }, 721 } 722 }; 723 724 /* Test that aliases generated are as expected */ 725 static int test__aliases(struct test_suite *test __maybe_unused, 726 int subtest __maybe_unused) 727 { 728 struct perf_pmu *pmu = NULL; 729 unsigned long i; 730 731 while ((pmu = perf_pmus__scan_core(pmu)) != NULL) { 732 int count = 0; 733 734 if (list_empty(&pmu->format)) { 735 pr_debug2("skipping testing core PMU %s\n", pmu->name); 736 continue; 737 } 738 739 if (__test_core_pmu_event_aliases(pmu->name, &count)) { 740 pr_debug("testing core PMU %s aliases: failed\n", pmu->name); 741 return -1; 742 } 743 744 if (count == 0) { 745 pr_debug("testing core PMU %s aliases: no events to match\n", 746 pmu->name); 747 return -1; 748 } 749 750 pr_debug("testing core PMU %s aliases: pass\n", pmu->name); 751 } 752 753 for (i = 0; i < ARRAY_SIZE(test_pmus); i++) { 754 int res; 755 756 res = __test_uncore_pmu_event_aliases(&test_pmus[i]); 757 if (res) 758 return res; 759 } 760 761 return 0; 762 } 763 764 static bool is_number(const char *str) 765 { 766 char *end_ptr; 767 double v; 768 769 errno = 0; 770 v = strtod(str, &end_ptr); 771 (void)v; // We're not interested in this value, only if it is valid 772 return errno == 0 && end_ptr != str; 773 } 774 775 static int check_parse_id(const char *id, struct parse_events_error *error) 776 { 777 struct evlist *evlist; 778 int ret; 779 char *dup, *cur; 780 781 /* Numbers are always valid. */ 782 if (is_number(id)) 783 return 0; 784 785 evlist = evlist__new(); 786 if (!evlist) 787 return -ENOMEM; 788 789 dup = strdup(id); 790 if (!dup) 791 return -ENOMEM; 792 793 for (cur = strchr(dup, '@') ; cur; cur = strchr(++cur, '@')) 794 *cur = '/'; 795 796 ret = __parse_events(evlist, dup, /*pmu_filter=*/NULL, error, /*fake_pmu=*/true, 797 /*warn_if_reordered=*/true, /*fake_tp=*/false); 798 free(dup); 799 800 evlist__delete(evlist); 801 return ret; 802 } 803 804 static int check_parse_fake(const char *id) 805 { 806 struct parse_events_error error; 807 int ret; 808 809 parse_events_error__init(&error); 810 ret = check_parse_id(id, &error); 811 parse_events_error__exit(&error); 812 return ret; 813 } 814 815 struct metric { 816 struct list_head list; 817 struct metric_ref metric_ref; 818 }; 819 820 static int test__parsing_callback(const struct pmu_metric *pm, 821 const struct pmu_metrics_table *table, 822 void *data) 823 { 824 int *failures = data; 825 int k; 826 struct evlist *evlist; 827 struct perf_cpu_map *cpus; 828 struct evsel *evsel; 829 int err = 0; 830 831 if (!pm->metric_expr) 832 return 0; 833 834 pr_debug("Found metric '%s'\n", pm->metric_name); 835 (*failures)++; 836 837 /* 838 * We need to prepare evlist for stat mode running on CPU 0 839 * because that's where all the stats are going to be created. 840 */ 841 evlist = evlist__new(); 842 if (!evlist) 843 return -ENOMEM; 844 845 cpus = perf_cpu_map__new("0"); 846 if (!cpus) { 847 evlist__delete(evlist); 848 return -ENOMEM; 849 } 850 851 perf_evlist__set_maps(&evlist->core, cpus, NULL); 852 853 err = metricgroup__parse_groups_test(evlist, table, pm->metric_name); 854 if (err) { 855 if (!strcmp(pm->metric_name, "M1") || !strcmp(pm->metric_name, "M2") || 856 !strcmp(pm->metric_name, "M3")) { 857 (*failures)--; 858 pr_debug("Expected broken metric %s skipping\n", pm->metric_name); 859 err = 0; 860 } 861 goto out_err; 862 } 863 864 err = evlist__alloc_stats(/*config=*/NULL, evlist, /*alloc_raw=*/false); 865 if (err) 866 goto out_err; 867 /* 868 * Add all ids with a made up value. The value may trigger divide by 869 * zero when subtracted and so try to make them unique. 870 */ 871 k = 1; 872 evlist__alloc_aggr_stats(evlist, 1); 873 evlist__for_each_entry(evlist, evsel) { 874 evsel->stats->aggr->counts.val = k; 875 k++; 876 } 877 evlist__for_each_entry(evlist, evsel) { 878 struct metric_event *me = metricgroup__lookup(&evlist->metric_events, evsel, false); 879 880 if (me != NULL) { 881 struct metric_expr *mexp; 882 883 list_for_each_entry (mexp, &me->head, nd) { 884 if (strcmp(mexp->metric_name, pm->metric_name)) 885 continue; 886 pr_debug("Result %f\n", test_generic_metric(mexp, 0)); 887 err = 0; 888 (*failures)--; 889 goto out_err; 890 } 891 } 892 } 893 pr_debug("Didn't find parsed metric %s", pm->metric_name); 894 err = 1; 895 out_err: 896 if (err) 897 pr_debug("Broken metric %s\n", pm->metric_name); 898 899 /* ... cleanup. */ 900 evlist__free_stats(evlist); 901 perf_cpu_map__put(cpus); 902 evlist__delete(evlist); 903 return err; 904 } 905 906 static int test__parsing(struct test_suite *test __maybe_unused, 907 int subtest __maybe_unused) 908 { 909 int failures = 0; 910 911 pmu_for_each_core_metric(test__parsing_callback, &failures); 912 pmu_for_each_sys_metric(test__parsing_callback, &failures); 913 914 return failures == 0 ? TEST_OK : TEST_FAIL; 915 } 916 917 struct test_metric { 918 const char *str; 919 }; 920 921 static struct test_metric metrics[] = { 922 { "(unc_p_power_state_occupancy.cores_c0 / unc_p_clockticks) * 100." }, 923 { "imx8_ddr0@read\\-cycles@ * 4 * 4", }, 924 { "imx8_ddr0@axid\\-read\\,axi_mask\\=0xffff\\,axi_id\\=0x0000@ * 4", }, 925 { "(cstate_pkg@c2\\-residency@ / msr@tsc@) * 100", }, 926 { "(imx8_ddr0@read\\-cycles@ + imx8_ddr0@write\\-cycles@)", }, 927 }; 928 929 static int metric_parse_fake(const char *metric_name, const char *str) 930 { 931 struct expr_parse_ctx *ctx; 932 struct hashmap_entry *cur; 933 double result; 934 int ret = -1; 935 size_t bkt; 936 int i; 937 938 pr_debug("parsing '%s': '%s'\n", metric_name, str); 939 940 ctx = expr__ctx_new(); 941 if (!ctx) { 942 pr_debug("expr__ctx_new failed"); 943 return TEST_FAIL; 944 } 945 ctx->sctx.is_test = true; 946 if (expr__find_ids(str, NULL, ctx) < 0) { 947 pr_err("expr__find_ids failed\n"); 948 return -1; 949 } 950 951 /* 952 * Add all ids with a made up value. The value may 953 * trigger divide by zero when subtracted and so try to 954 * make them unique. 955 */ 956 i = 1; 957 hashmap__for_each_entry(ctx->ids, cur, bkt) 958 expr__add_id_val(ctx, strdup(cur->pkey), i++); 959 960 hashmap__for_each_entry(ctx->ids, cur, bkt) { 961 if (check_parse_fake(cur->pkey)) { 962 pr_err("check_parse_fake failed\n"); 963 goto out; 964 } 965 } 966 967 ret = 0; 968 if (expr__parse(&result, ctx, str)) { 969 /* 970 * Parsing failed, make numbers go from large to small which can 971 * resolve divide by zero issues. 972 */ 973 i = 1024; 974 hashmap__for_each_entry(ctx->ids, cur, bkt) 975 expr__add_id_val(ctx, strdup(cur->pkey), i--); 976 if (expr__parse(&result, ctx, str)) { 977 pr_err("expr__parse failed for %s\n", metric_name); 978 /* The following have hard to avoid divide by zero. */ 979 if (!strcmp(metric_name, "tma_clears_resteers") || 980 !strcmp(metric_name, "tma_mispredicts_resteers")) 981 ret = 0; 982 else 983 ret = -1; 984 } 985 } 986 987 out: 988 expr__ctx_free(ctx); 989 return ret; 990 } 991 992 static int test__parsing_fake_callback(const struct pmu_metric *pm, 993 const struct pmu_metrics_table *table __maybe_unused, 994 void *data __maybe_unused) 995 { 996 return metric_parse_fake(pm->metric_name, pm->metric_expr); 997 } 998 999 /* 1000 * Parse all the metrics for current architecture, or all defined cpus via the 1001 * 'fake_pmu' in parse_events. 1002 */ 1003 static int test__parsing_fake(struct test_suite *test __maybe_unused, 1004 int subtest __maybe_unused) 1005 { 1006 int err = 0; 1007 1008 for (size_t i = 0; i < ARRAY_SIZE(metrics); i++) { 1009 err = metric_parse_fake("", metrics[i].str); 1010 if (err) 1011 return err; 1012 } 1013 1014 err = pmu_for_each_core_metric(test__parsing_fake_callback, NULL); 1015 if (err) 1016 return err; 1017 1018 return pmu_for_each_sys_metric(test__parsing_fake_callback, NULL); 1019 } 1020 1021 static int test__parsing_threshold_callback(const struct pmu_metric *pm, 1022 const struct pmu_metrics_table *table __maybe_unused, 1023 void *data __maybe_unused) 1024 { 1025 if (!pm->metric_threshold) 1026 return 0; 1027 return metric_parse_fake(pm->metric_name, pm->metric_threshold); 1028 } 1029 1030 static int test__parsing_threshold(struct test_suite *test __maybe_unused, 1031 int subtest __maybe_unused) 1032 { 1033 int err = 0; 1034 1035 err = pmu_for_each_core_metric(test__parsing_threshold_callback, NULL); 1036 if (err) 1037 return err; 1038 1039 return pmu_for_each_sys_metric(test__parsing_threshold_callback, NULL); 1040 } 1041 1042 static struct test_case pmu_events_tests[] = { 1043 TEST_CASE("PMU event table sanity", pmu_event_table), 1044 TEST_CASE("PMU event map aliases", aliases), 1045 TEST_CASE_REASON("Parsing of PMU event table metrics", parsing, 1046 "some metrics failed"), 1047 TEST_CASE("Parsing of PMU event table metrics with fake PMUs", parsing_fake), 1048 TEST_CASE("Parsing of metric thresholds with fake PMUs", parsing_threshold), 1049 { .name = NULL, } 1050 }; 1051 1052 struct test_suite suite__pmu_events = { 1053 .desc = "PMU JSON event tests", 1054 .test_cases = pmu_events_tests, 1055 }; 1056