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

perf parse-events: Make legacy events lower priority than sysfs/JSON

The perf tool has previously made legacy events the priority so with
or without a PMU the legacy event would be opened:

$ perf stat -e cpu-cycles,cpu/cpu-cycles/ true
Using CPUID GenuineIntel-6-8D-1
intel_pt default config: tsc,mtc,mtc_period=3,psb_period=3,pt,branch
Attempting to add event pmu 'cpu' with 'cpu-cycles,' that may result in non-fatal errors
After aliases, add event pmu 'cpu' with 'cpu-cycles,' that may result in non-fatal errors
Control descriptor is not initialized
------------------------------------------------------------
perf_event_attr:
type 0 (PERF_TYPE_HARDWARE)
size 136
config 0 (PERF_COUNT_HW_CPU_CYCLES)
sample_type IDENTIFIER
read_format TOTAL_TIME_ENABLED|TOTAL_TIME_RUNNING
disabled 1
inherit 1
enable_on_exec 1
exclude_guest 1
------------------------------------------------------------
sys_perf_event_open: pid 833967 cpu -1 group_fd -1 flags 0x8 = 3
------------------------------------------------------------
perf_event_attr:
type 0 (PERF_TYPE_HARDWARE)
size 136
config 0 (PERF_COUNT_HW_CPU_CYCLES)
sample_type IDENTIFIER
read_format TOTAL_TIME_ENABLED|TOTAL_TIME_RUNNING
disabled 1
inherit 1
enable_on_exec 1
exclude_guest 1
------------------------------------------------------------
...

Fixes to make hybrid/BIG.little PMUs behave correctly, ie as core PMUs
capable of opening legacy events on each, removing hard coded "cpu_core"
and "cpu_atom" Intel PMU names, etc. caused a behavioral difference on
Apple/ARM due to latent issues in the PMU driver reported in:
https://lore.kernel.org/lkml/08f1f185-e259-4014-9ca4-6411d5c1bc65@marcan.st/

As part of that report Mark Rutland <mark.rutland@arm.com> requested
that legacy events not be higher in priority when a PMU is specified
reversing what has until this change been perf's default behavior. With
this change the above becomes:

$ perf stat -e cpu-cycles,cpu/cpu-cycles/ true
Using CPUID GenuineIntel-6-8D-1
Attempt to add: cpu/cpu-cycles=0/
..after resolving event: cpu/event=0x3c/
Control descriptor is not initialized
------------------------------------------------------------
perf_event_attr:
type 0 (PERF_TYPE_HARDWARE)
size 136
config 0 (PERF_COUNT_HW_CPU_CYCLES)
sample_type IDENTIFIER
read_format TOTAL_TIME_ENABLED|TOTAL_TIME_RUNNING
disabled 1
inherit 1
enable_on_exec 1
exclude_guest 1
------------------------------------------------------------
sys_perf_event_open: pid 827628 cpu -1 group_fd -1 flags 0x8 = 3
------------------------------------------------------------
perf_event_attr:
type 4 (PERF_TYPE_RAW)
size 136
config 0x3c
sample_type IDENTIFIER
read_format TOTAL_TIME_ENABLED|TOTAL_TIME_RUNNING
disabled 1
inherit 1
enable_on_exec 1
exclude_guest 1
------------------------------------------------------------
...

So the second event has become a raw event as
/sys/devices/cpu/events/cpu-cycles exists.

A fix was necessary to config_term_pmu in parse-events.c as check_alias
expansion needs to happen after config_term_pmu, and config_term_pmu may
need calling a second time because of this.

config_term_pmu is updated to not use the legacy event when the PMU has
such a named event (either from JSON or sysfs).

The bulk of this change is updating all of the parse-events test
expectations so that if a sysfs/JSON event exists for a PMU the test
doesn't fail - a further sign, if it were needed, that the legacy event
priority was a known and tested behavior of the perf tool.

Reported-by: Hector Martin <marcan@marcan.st>
Signed-off-by: Ian Rogers <irogers@google.com>
Tested-by: Hector Martin <marcan@marcan.st>
Tested-by: Marc Zyngier <maz@kernel.org>
Acked-by: Mark Rutland <mark.rutland@arm.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20231123042922.834425-1-irogers@google.com
[ Initialize the 'alias_rewrote_terms' variable to false to address a clang warning ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
a24d9d9d a4271827

+231 -88
+185 -71
tools/perf/tests/parse-events.c
··· 162 162 return TEST_OK; 163 163 } 164 164 165 + 166 + static int assert_hw(struct perf_evsel *evsel, enum perf_hw_id id, const char *name) 167 + { 168 + struct perf_pmu *pmu; 169 + 170 + if (evsel->attr.type == PERF_TYPE_HARDWARE) { 171 + TEST_ASSERT_VAL("wrong config", test_perf_config(evsel, id)); 172 + return 0; 173 + } 174 + pmu = perf_pmus__find_by_type(evsel->attr.type); 175 + 176 + TEST_ASSERT_VAL("unexpected PMU type", pmu); 177 + TEST_ASSERT_VAL("PMU missing event", perf_pmu__have_event(pmu, name)); 178 + return 0; 179 + } 180 + 165 181 static int test__checkevent_symbolic_name(struct evlist *evlist) 166 182 { 167 183 struct perf_evsel *evsel; ··· 185 169 TEST_ASSERT_VAL("wrong number of entries", 0 != evlist->core.nr_entries); 186 170 187 171 perf_evlist__for_each_evsel(&evlist->core, evsel) { 188 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); 189 - TEST_ASSERT_VAL("wrong config", 190 - test_perf_config(evsel, PERF_COUNT_HW_INSTRUCTIONS)); 172 + int ret = assert_hw(evsel, PERF_COUNT_HW_INSTRUCTIONS, "instructions"); 173 + 174 + if (ret) 175 + return ret; 191 176 } 177 + 192 178 return TEST_OK; 193 179 } 194 180 ··· 201 183 TEST_ASSERT_VAL("wrong number of entries", 0 != evlist->core.nr_entries); 202 184 203 185 perf_evlist__for_each_evsel(&evlist->core, evsel) { 204 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type); 205 - TEST_ASSERT_VAL("wrong config", test_perf_config(evsel, PERF_COUNT_HW_CPU_CYCLES)); 186 + int ret = assert_hw(evsel, PERF_COUNT_HW_CPU_CYCLES, "cycles"); 187 + 188 + if (ret) 189 + return ret; 206 190 /* 207 191 * The period value gets configured within evlist__config, 208 192 * while this test executes only parse events method. ··· 881 861 evlist__nr_groups(evlist) == num_core_entries()); 882 862 883 863 for (int i = 0; i < num_core_entries(); i++) { 864 + int ret; 865 + 884 866 /* instructions:k */ 885 867 evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); 886 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 887 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_INSTRUCTIONS)); 868 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_INSTRUCTIONS, "instructions"); 869 + if (ret) 870 + return ret; 871 + 888 872 TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); 889 873 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); 890 874 TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); ··· 902 878 903 879 /* cycles:upp */ 904 880 evsel = evsel__next(evsel); 905 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 906 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES)); 881 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); 882 + if (ret) 883 + return ret; 884 + 907 885 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 908 886 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); 909 887 TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); ··· 933 907 TEST_ASSERT_VAL("wrong number of groups", 1 == evlist__nr_groups(evlist)); 934 908 935 909 evlist__for_each_entry(evlist, evsel) { 910 + int ret; 911 + 936 912 if (evsel->core.attr.type == PERF_TYPE_SOFTWARE) { 937 913 /* faults + :ku modifier */ 938 914 leader = evsel; ··· 967 939 continue; 968 940 } 969 941 /* cycles:k */ 970 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 971 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES)); 942 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); 943 + if (ret) 944 + return ret; 945 + 972 946 TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); 973 947 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); 974 948 TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); ··· 987 957 static int test__group3(struct evlist *evlist __maybe_unused) 988 958 { 989 959 struct evsel *evsel, *group1_leader = NULL, *group2_leader = NULL; 960 + int ret; 990 961 991 962 TEST_ASSERT_VAL("wrong number of entries", 992 963 evlist->core.nr_entries == (3 * perf_pmus__num_core_pmus() + 2)); ··· 1076 1045 continue; 1077 1046 } 1078 1047 /* instructions:u */ 1079 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1080 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_INSTRUCTIONS)); 1048 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_INSTRUCTIONS, "instructions"); 1049 + if (ret) 1050 + return ret; 1051 + 1081 1052 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1082 1053 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); 1083 1054 TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); ··· 1103 1070 num_core_entries() == evlist__nr_groups(evlist)); 1104 1071 1105 1072 for (int i = 0; i < num_core_entries(); i++) { 1073 + int ret; 1074 + 1106 1075 /* cycles:u + p */ 1107 1076 evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); 1108 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1109 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES)); 1077 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); 1078 + if (ret) 1079 + return ret; 1080 + 1110 1081 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1111 1082 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); 1112 1083 TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); ··· 1126 1089 1127 1090 /* instructions:kp + p */ 1128 1091 evsel = evsel__next(evsel); 1129 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1130 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_INSTRUCTIONS)); 1092 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_INSTRUCTIONS, "instructions"); 1093 + if (ret) 1094 + return ret; 1095 + 1131 1096 TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); 1132 1097 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); 1133 1098 TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); ··· 1147 1108 static int test__group5(struct evlist *evlist __maybe_unused) 1148 1109 { 1149 1110 struct evsel *evsel = NULL, *leader; 1111 + int ret; 1150 1112 1151 1113 TEST_ASSERT_VAL("wrong number of entries", 1152 1114 evlist->core.nr_entries == (5 * num_core_entries())); ··· 1157 1117 for (int i = 0; i < num_core_entries(); i++) { 1158 1118 /* cycles + G */ 1159 1119 evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); 1160 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1161 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES)); 1120 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); 1121 + if (ret) 1122 + return ret; 1123 + 1162 1124 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1163 1125 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); 1164 1126 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); ··· 1175 1133 1176 1134 /* instructions + G */ 1177 1135 evsel = evsel__next(evsel); 1178 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1179 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_INSTRUCTIONS)); 1136 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_INSTRUCTIONS, "instructions"); 1137 + if (ret) 1138 + return ret; 1139 + 1180 1140 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1181 1141 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); 1182 1142 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); ··· 1192 1148 for (int i = 0; i < num_core_entries(); i++) { 1193 1149 /* cycles:G */ 1194 1150 evsel = leader = evsel__next(evsel); 1195 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1196 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES)); 1151 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); 1152 + if (ret) 1153 + return ret; 1154 + 1197 1155 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1198 1156 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); 1199 1157 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); ··· 1210 1164 1211 1165 /* instructions:G */ 1212 1166 evsel = evsel__next(evsel); 1213 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1214 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_INSTRUCTIONS)); 1167 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_INSTRUCTIONS, "instructions"); 1168 + if (ret) 1169 + return ret; 1170 + 1215 1171 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1216 1172 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); 1217 1173 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); ··· 1226 1178 for (int i = 0; i < num_core_entries(); i++) { 1227 1179 /* cycles */ 1228 1180 evsel = evsel__next(evsel); 1229 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1230 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES)); 1181 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); 1182 + if (ret) 1183 + return ret; 1184 + 1231 1185 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1232 1186 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); 1233 1187 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); ··· 1251 1201 evlist__nr_groups(evlist) == num_core_entries()); 1252 1202 1253 1203 for (int i = 0; i < num_core_entries(); i++) { 1204 + int ret; 1205 + 1254 1206 /* cycles + :H group modifier */ 1255 1207 evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); 1256 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1257 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES)); 1208 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); 1209 + if (ret) 1210 + return ret; 1211 + 1258 1212 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1259 1213 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); 1260 1214 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); ··· 1272 1218 1273 1219 /* cache-misses:G + :H group modifier */ 1274 1220 evsel = evsel__next(evsel); 1275 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1276 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CACHE_MISSES)); 1221 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_CACHE_MISSES, "cache-misses"); 1222 + if (ret) 1223 + return ret; 1224 + 1277 1225 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1278 1226 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); 1279 1227 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); ··· 1298 1242 evlist__nr_groups(evlist) == num_core_entries()); 1299 1243 1300 1244 for (int i = 0; i < num_core_entries(); i++) { 1245 + int ret; 1246 + 1301 1247 /* cycles + :G group modifier */ 1302 1248 evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); 1303 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1304 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES)); 1249 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); 1250 + if (ret) 1251 + return ret; 1252 + 1305 1253 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1306 1254 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); 1307 1255 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); ··· 1319 1259 1320 1260 /* cache-misses:H + :G group modifier */ 1321 1261 evsel = evsel__next(evsel); 1322 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1323 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CACHE_MISSES)); 1262 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_CACHE_MISSES, "cache-misses"); 1263 + if (ret) 1264 + return ret; 1265 + 1324 1266 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1325 1267 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); 1326 1268 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); ··· 1345 1283 evlist__nr_groups(evlist) == num_core_entries()); 1346 1284 1347 1285 for (int i = 0; i < num_core_entries(); i++) { 1286 + int ret; 1287 + 1348 1288 /* cycles:G + :u group modifier */ 1349 1289 evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); 1350 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1351 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES)); 1290 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); 1291 + if (ret) 1292 + return ret; 1293 + 1352 1294 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1353 1295 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); 1354 1296 TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); ··· 1366 1300 1367 1301 /* cache-misses:H + :u group modifier */ 1368 1302 evsel = evsel__next(evsel); 1369 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1370 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CACHE_MISSES)); 1303 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_CACHE_MISSES, "cache-misses"); 1304 + if (ret) 1305 + return ret; 1306 + 1371 1307 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1372 1308 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); 1373 1309 TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); ··· 1392 1324 evlist__nr_groups(evlist) == num_core_entries()); 1393 1325 1394 1326 for (int i = 0; i < num_core_entries(); i++) { 1327 + int ret; 1328 + 1395 1329 /* cycles:G + :uG group modifier */ 1396 1330 evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); 1397 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1398 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES)); 1331 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); 1332 + if (ret) 1333 + return ret; 1334 + 1399 1335 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1400 1336 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); 1401 1337 TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); ··· 1413 1341 1414 1342 /* cache-misses:H + :uG group modifier */ 1415 1343 evsel = evsel__next(evsel); 1416 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1417 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CACHE_MISSES)); 1344 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_CACHE_MISSES, "cache-misses"); 1345 + if (ret) 1346 + return ret; 1347 + 1418 1348 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1419 1349 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); 1420 1350 TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); ··· 1437 1363 evlist->core.nr_entries == (3 * num_core_entries())); 1438 1364 1439 1365 for (int i = 0; i < num_core_entries(); i++) { 1366 + int ret; 1367 + 1440 1368 /* cycles - sampling group leader */ 1441 1369 evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); 1442 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1443 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES)); 1370 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); 1371 + if (ret) 1372 + return ret; 1373 + 1444 1374 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1445 1375 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); 1446 1376 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); ··· 1457 1379 1458 1380 /* cache-misses - not sampling */ 1459 1381 evsel = evsel__next(evsel); 1460 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1461 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CACHE_MISSES)); 1382 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_CACHE_MISSES, "cache-misses"); 1383 + if (ret) 1384 + return ret; 1385 + 1462 1386 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1463 1387 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); 1464 1388 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); ··· 1472 1392 1473 1393 /* branch-misses - not sampling */ 1474 1394 evsel = evsel__next(evsel); 1475 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1476 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_BRANCH_MISSES)); 1395 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_BRANCH_MISSES, "branch-misses"); 1396 + if (ret) 1397 + return ret; 1398 + 1477 1399 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1478 1400 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->core.attr.exclude_kernel); 1479 1401 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->core.attr.exclude_hv); ··· 1497 1415 evlist->core.nr_entries == (2 * num_core_entries())); 1498 1416 1499 1417 for (int i = 0; i < num_core_entries(); i++) { 1418 + int ret; 1419 + 1500 1420 /* instructions - sampling group leader */ 1501 1421 evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); 1502 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1503 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_INSTRUCTIONS)); 1422 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_INSTRUCTIONS, "instructions"); 1423 + if (ret) 1424 + return ret; 1425 + 1504 1426 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1505 1427 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); 1506 1428 TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); ··· 1517 1431 1518 1432 /* branch-misses - not sampling */ 1519 1433 evsel = evsel__next(evsel); 1520 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1521 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_BRANCH_MISSES)); 1434 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_BRANCH_MISSES, "branch-misses"); 1435 + if (ret) 1436 + return ret; 1437 + 1522 1438 TEST_ASSERT_VAL("wrong exclude_user", !evsel->core.attr.exclude_user); 1523 1439 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); 1524 1440 TEST_ASSERT_VAL("wrong exclude_hv", evsel->core.attr.exclude_hv); ··· 1560 1472 evlist->core.nr_entries == (3 * num_core_entries())); 1561 1473 1562 1474 for (int i = 0; i < num_core_entries(); i++) { 1475 + int ret; 1476 + 1563 1477 /* cycles - group leader */ 1564 1478 evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); 1565 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1566 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES)); 1479 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); 1480 + if (ret) 1481 + return ret; 1482 + 1567 1483 TEST_ASSERT_VAL("wrong group name", !evsel->group_name); 1568 1484 TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 1569 1485 /* TODO: The group modifier is not copied to the split group leader. */ ··· 1576 1484 1577 1485 /* cache-misses - can not be pinned, but will go on with the leader */ 1578 1486 evsel = evsel__next(evsel); 1579 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1580 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CACHE_MISSES)); 1487 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_CACHE_MISSES, "cache-misses"); 1488 + if (ret) 1489 + return ret; 1490 + 1581 1491 TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned); 1582 1492 1583 1493 /* branch-misses - ditto */ 1584 1494 evsel = evsel__next(evsel); 1585 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_BRANCH_MISSES)); 1495 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_BRANCH_MISSES, "branch-misses"); 1496 + if (ret) 1497 + return ret; 1498 + 1586 1499 TEST_ASSERT_VAL("wrong pinned", !evsel->core.attr.pinned); 1587 1500 } 1588 1501 return TEST_OK; ··· 1614 1517 evlist->core.nr_entries == 3 * num_core_entries()); 1615 1518 1616 1519 for (int i = 0; i < num_core_entries(); i++) { 1520 + int ret; 1521 + 1617 1522 /* cycles - group leader */ 1618 1523 evsel = leader = (i == 0 ? evlist__first(evlist) : evsel__next(evsel)); 1619 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1620 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES)); 1524 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); 1525 + if (ret) 1526 + return ret; 1527 + 1621 1528 TEST_ASSERT_VAL("wrong group name", !evsel->group_name); 1622 1529 TEST_ASSERT_VAL("wrong leader", evsel__has_leader(evsel, leader)); 1623 1530 /* TODO: The group modifier is not copied to the split group leader. */ ··· 1630 1529 1631 1530 /* cache-misses - can not be pinned, but will go on with the leader */ 1632 1531 evsel = evsel__next(evsel); 1633 - TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->core.attr.type); 1634 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CACHE_MISSES)); 1532 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_CACHE_MISSES, "cache-misses"); 1533 + if (ret) 1534 + return ret; 1535 + 1635 1536 TEST_ASSERT_VAL("wrong exclusive", !evsel->core.attr.exclusive); 1636 1537 1637 1538 /* branch-misses - ditto */ 1638 1539 evsel = evsel__next(evsel); 1639 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_BRANCH_MISSES)); 1540 + ret = assert_hw(&evsel->core, PERF_COUNT_HW_BRANCH_MISSES, "branch-misses"); 1541 + if (ret) 1542 + return ret; 1543 + 1640 1544 TEST_ASSERT_VAL("wrong exclusive", !evsel->core.attr.exclusive); 1641 1545 } 1642 1546 return TEST_OK; ··· 1783 1677 static int test__sym_event_slash(struct evlist *evlist) 1784 1678 { 1785 1679 struct evsel *evsel = evlist__first(evlist); 1680 + int ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); 1786 1681 1787 - TEST_ASSERT_VAL("wrong type", evsel->core.attr.type == PERF_TYPE_HARDWARE); 1788 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES)); 1682 + if (ret) 1683 + return ret; 1684 + 1789 1685 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->core.attr.exclude_kernel); 1790 1686 return TEST_OK; 1791 1687 } ··· 1795 1687 static int test__sym_event_dc(struct evlist *evlist) 1796 1688 { 1797 1689 struct evsel *evsel = evlist__first(evlist); 1690 + int ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); 1798 1691 1799 - TEST_ASSERT_VAL("wrong type", evsel->core.attr.type == PERF_TYPE_HARDWARE); 1800 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES)); 1692 + if (ret) 1693 + return ret; 1694 + 1801 1695 TEST_ASSERT_VAL("wrong exclude_user", evsel->core.attr.exclude_user); 1802 1696 return TEST_OK; 1803 1697 } ··· 1807 1697 static int test__term_equal_term(struct evlist *evlist) 1808 1698 { 1809 1699 struct evsel *evsel = evlist__first(evlist); 1700 + int ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); 1810 1701 1811 - TEST_ASSERT_VAL("wrong type", evsel->core.attr.type == PERF_TYPE_HARDWARE); 1812 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES)); 1702 + if (ret) 1703 + return ret; 1704 + 1813 1705 TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "name") == 0); 1814 1706 return TEST_OK; 1815 1707 } ··· 1819 1707 static int test__term_equal_legacy(struct evlist *evlist) 1820 1708 { 1821 1709 struct evsel *evsel = evlist__first(evlist); 1710 + int ret = assert_hw(&evsel->core, PERF_COUNT_HW_CPU_CYCLES, "cycles"); 1822 1711 1823 - TEST_ASSERT_VAL("wrong type", evsel->core.attr.type == PERF_TYPE_HARDWARE); 1824 - TEST_ASSERT_VAL("wrong config", test_config(evsel, PERF_COUNT_HW_CPU_CYCLES)); 1712 + if (ret) 1713 + return ret; 1714 + 1825 1715 TEST_ASSERT_VAL("wrong name setting", strcmp(evsel->name, "l1d") == 0); 1826 1716 return TEST_OK; 1827 1717 }
+38 -14
tools/perf/util/parse-events.c
··· 976 976 struct parse_events_error *err) 977 977 { 978 978 if (term->type_term == PARSE_EVENTS__TERM_TYPE_LEGACY_CACHE) { 979 - const struct perf_pmu *pmu = perf_pmus__find_by_type(attr->type); 979 + struct perf_pmu *pmu = perf_pmus__find_by_type(attr->type); 980 980 981 981 if (!pmu) { 982 982 char *err_str; ··· 986 986 err_str, /*help=*/NULL); 987 987 return -EINVAL; 988 988 } 989 - if (perf_pmu__supports_legacy_cache(pmu)) { 989 + /* 990 + * Rewrite the PMU event to a legacy cache one unless the PMU 991 + * doesn't support legacy cache events or the event is present 992 + * within the PMU. 993 + */ 994 + if (perf_pmu__supports_legacy_cache(pmu) && 995 + !perf_pmu__have_event(pmu, term->config)) { 990 996 attr->type = PERF_TYPE_HW_CACHE; 991 997 return parse_events__decode_legacy_cache(term->config, pmu->type, 992 998 &attr->config); 993 - } else 999 + } else { 994 1000 term->type_term = PARSE_EVENTS__TERM_TYPE_USER; 1001 + term->no_value = true; 1002 + } 995 1003 } 996 1004 if (term->type_term == PARSE_EVENTS__TERM_TYPE_HARDWARE) { 997 - const struct perf_pmu *pmu = perf_pmus__find_by_type(attr->type); 1005 + struct perf_pmu *pmu = perf_pmus__find_by_type(attr->type); 998 1006 999 1007 if (!pmu) { 1000 1008 char *err_str; ··· 1012 1004 err_str, /*help=*/NULL); 1013 1005 return -EINVAL; 1014 1006 } 1015 - attr->type = PERF_TYPE_HARDWARE; 1016 - attr->config = term->val.num; 1017 - if (perf_pmus__supports_extended_type()) 1018 - attr->config |= (__u64)pmu->type << PERF_PMU_TYPE_SHIFT; 1007 + /* 1008 + * If the PMU has a sysfs or json event prefer it over 1009 + * legacy. ARM requires this. 1010 + */ 1011 + if (perf_pmu__have_event(pmu, term->config)) { 1012 + term->type_term = PARSE_EVENTS__TERM_TYPE_USER; 1013 + term->no_value = true; 1014 + } else { 1015 + attr->type = PERF_TYPE_HARDWARE; 1016 + attr->config = term->val.num; 1017 + if (perf_pmus__supports_extended_type()) 1018 + attr->config |= (__u64)pmu->type << PERF_PMU_TYPE_SHIFT; 1019 + } 1019 1020 return 0; 1020 1021 } 1021 1022 if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER || ··· 1398 1381 YYLTYPE *loc = loc_; 1399 1382 LIST_HEAD(config_terms); 1400 1383 struct parse_events_terms parsed_terms; 1384 + bool alias_rewrote_terms = false; 1401 1385 1402 1386 pmu = parse_state->fake_pmu ?: perf_pmus__find(name); 1403 1387 ··· 1451 1433 return evsel ? 0 : -ENOMEM; 1452 1434 } 1453 1435 1454 - if (!parse_state->fake_pmu && perf_pmu__check_alias(pmu, &parsed_terms, &info, err)) { 1436 + /* Configure attr/terms with a known PMU, this will set hardcoded terms. */ 1437 + if (config_attr(&attr, &parsed_terms, parse_state->error, config_term_pmu)) { 1438 + parse_events_terms__exit(&parsed_terms); 1439 + return -EINVAL; 1440 + } 1441 + 1442 + /* Look for event names in the terms and rewrite into format based terms. */ 1443 + if (!parse_state->fake_pmu && perf_pmu__check_alias(pmu, &parsed_terms, 1444 + &info, &alias_rewrote_terms, err)) { 1455 1445 parse_events_terms__exit(&parsed_terms); 1456 1446 return -EINVAL; 1457 1447 } ··· 1473 1447 strbuf_release(&sb); 1474 1448 } 1475 1449 1476 - /* 1477 - * Configure hardcoded terms first, no need to check 1478 - * return value when called with fail == 0 ;) 1479 - */ 1480 - if (config_attr(&attr, &parsed_terms, parse_state->error, config_term_pmu)) { 1450 + /* Configure attr/terms again if an alias was expanded. */ 1451 + if (alias_rewrote_terms && 1452 + config_attr(&attr, &parsed_terms, parse_state->error, config_term_pmu)) { 1481 1453 parse_events_terms__exit(&parsed_terms); 1482 1454 return -EINVAL; 1483 1455 }
+6 -2
tools/perf/util/pmu.c
··· 1494 1494 * defined for the alias 1495 1495 */ 1496 1496 int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_terms, 1497 - struct perf_pmu_info *info, struct parse_events_error *err) 1497 + struct perf_pmu_info *info, bool *rewrote_terms, 1498 + struct parse_events_error *err) 1498 1499 { 1499 1500 struct parse_events_term *term, *h; 1500 1501 struct perf_pmu_alias *alias; 1501 1502 int ret; 1502 1503 1504 + *rewrote_terms = false; 1503 1505 info->per_pkg = false; 1504 1506 1505 1507 /* ··· 1523 1521 NULL); 1524 1522 return ret; 1525 1523 } 1526 - 1524 + *rewrote_terms = true; 1527 1525 ret = check_info_data(pmu, alias, info, err, term->err_term); 1528 1526 if (ret) 1529 1527 return ret; ··· 1617 1615 1618 1616 bool perf_pmu__have_event(struct perf_pmu *pmu, const char *name) 1619 1617 { 1618 + if (!name) 1619 + return false; 1620 1620 if (perf_pmu__find_alias(pmu, name, /*load=*/ true) != NULL) 1621 1621 return true; 1622 1622 if (pmu->cpu_aliases_added || !pmu->events_table)
+2 -1
tools/perf/util/pmu.h
··· 201 201 __u64 perf_pmu__format_bits(struct perf_pmu *pmu, const char *name); 202 202 int perf_pmu__format_type(struct perf_pmu *pmu, const char *name); 203 203 int perf_pmu__check_alias(struct perf_pmu *pmu, struct parse_events_terms *head_terms, 204 - struct perf_pmu_info *info, struct parse_events_error *err); 204 + struct perf_pmu_info *info, bool *rewrote_terms, 205 + struct parse_events_error *err); 205 206 int perf_pmu__find_event(struct perf_pmu *pmu, const char *event, void *state, pmu_event_callback cb); 206 207 207 208 int perf_pmu__format_parse(struct perf_pmu *pmu, int dirfd, bool eager_load);