aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2018-05-31 06:37:07 -0400
committerIngo Molnar <mingo@kernel.org>2018-05-31 06:37:07 -0400
commit6497bbc35ac5efce3bccd31d3719bae020282da6 (patch)
treec99f566cf166cced1961140ea30249e9babaded2
parent786b71f5b754273ccef6d9462e52062b3e1f9877 (diff)
parent18a7057420f8b67f15d17087bf5c0863db752c8b (diff)
Merge tag 'perf-urgent-for-mingo-4.17-20180531' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
Pull perf/urgent fixes from Arnaldo Carvalho de Melo: - Fix 'perf test Session topology' segfault on s390 (Thomas Richter) - Fix NULL return handling in bpf__prepare_load() (YueHaibing) - Fix indexing on Coresight ETM packet queue decoder (Mathieu Poirier) - Fix perf.data format description of NRCPUS header (Arnaldo Carvalho de Melo) - Update perf.data documentation section on cpu topology - Handle uncore event aliases in small groups properly (Kan Liang) - Add missing perf_sample.addr into python sample dictionary (Leo Yan) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/perf/Documentation/perf.data-file-format.txt10
-rw-r--r--tools/perf/tests/topology.c30
-rw-r--r--tools/perf/util/bpf-loader.c6
-rw-r--r--tools/perf/util/cs-etm-decoder/cs-etm-decoder.c12
-rw-r--r--tools/perf/util/evsel.h1
-rw-r--r--tools/perf/util/parse-events.c130
-rw-r--r--tools/perf/util/parse-events.h7
-rw-r--r--tools/perf/util/parse-events.y8
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c2
9 files changed, 185 insertions, 21 deletions
diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt
index d00f0d51cab8..dfb218feaad9 100644
--- a/tools/perf/Documentation/perf.data-file-format.txt
+++ b/tools/perf/Documentation/perf.data-file-format.txt
@@ -111,8 +111,8 @@ A perf_header_string with the CPU architecture (uname -m)
111A structure defining the number of CPUs. 111A structure defining the number of CPUs.
112 112
113struct nr_cpus { 113struct nr_cpus {
114 uint32_t nr_cpus_online;
115 uint32_t nr_cpus_available; /* CPUs not yet onlined */ 114 uint32_t nr_cpus_available; /* CPUs not yet onlined */
115 uint32_t nr_cpus_online;
116}; 116};
117 117
118 HEADER_CPUDESC = 8, 118 HEADER_CPUDESC = 8,
@@ -153,10 +153,18 @@ struct {
153 HEADER_CPU_TOPOLOGY = 13, 153 HEADER_CPU_TOPOLOGY = 13,
154 154
155String lists defining the core and CPU threads topology. 155String lists defining the core and CPU threads topology.
156The string lists are followed by a variable length array
157which contains core_id and socket_id of each cpu.
158The number of entries can be determined by the size of the
159section minus the sizes of both string lists.
156 160
157struct { 161struct {
158 struct perf_header_string_list cores; /* Variable length */ 162 struct perf_header_string_list cores; /* Variable length */
159 struct perf_header_string_list threads; /* Variable length */ 163 struct perf_header_string_list threads; /* Variable length */
164 struct {
165 uint32_t core_id;
166 uint32_t socket_id;
167 } cpus[nr]; /* Variable length records */
160}; 168};
161 169
162Example: 170Example:
diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c
index 17cb1bb3448c..40e30a26b23c 100644
--- a/tools/perf/tests/topology.c
+++ b/tools/perf/tests/topology.c
@@ -70,6 +70,27 @@ static int check_cpu_topology(char *path, struct cpu_map *map)
70 session = perf_session__new(&data, false, NULL); 70 session = perf_session__new(&data, false, NULL);
71 TEST_ASSERT_VAL("can't get session", session); 71 TEST_ASSERT_VAL("can't get session", session);
72 72
73 /* On platforms with large numbers of CPUs process_cpu_topology()
74 * might issue an error while reading the perf.data file section
75 * HEADER_CPU_TOPOLOGY and the cpu_topology_map pointed to by member
76 * cpu is a NULL pointer.
77 * Example: On s390
78 * CPU 0 is on core_id 0 and physical_package_id 6
79 * CPU 1 is on core_id 1 and physical_package_id 3
80 *
81 * Core_id and physical_package_id are platform and architecture
82 * dependend and might have higher numbers than the CPU id.
83 * This actually depends on the configuration.
84 *
85 * In this case process_cpu_topology() prints error message:
86 * "socket_id number is too big. You may need to upgrade the
87 * perf tool."
88 *
89 * This is the reason why this test might be skipped.
90 */
91 if (!session->header.env.cpu)
92 return TEST_SKIP;
93
73 for (i = 0; i < session->header.env.nr_cpus_avail; i++) { 94 for (i = 0; i < session->header.env.nr_cpus_avail; i++) {
74 if (!cpu_map__has(map, i)) 95 if (!cpu_map__has(map, i))
75 continue; 96 continue;
@@ -95,7 +116,7 @@ int test__session_topology(struct test *test __maybe_unused, int subtest __maybe
95{ 116{
96 char path[PATH_MAX]; 117 char path[PATH_MAX];
97 struct cpu_map *map; 118 struct cpu_map *map;
98 int ret = -1; 119 int ret = TEST_FAIL;
99 120
100 TEST_ASSERT_VAL("can't get templ file", !get_temp(path)); 121 TEST_ASSERT_VAL("can't get templ file", !get_temp(path));
101 122
@@ -110,12 +131,9 @@ int test__session_topology(struct test *test __maybe_unused, int subtest __maybe
110 goto free_path; 131 goto free_path;
111 } 132 }
112 133
113 if (check_cpu_topology(path, map)) 134 ret = check_cpu_topology(path, map);
114 goto free_map;
115 ret = 0;
116
117free_map:
118 cpu_map__put(map); 135 cpu_map__put(map);
136
119free_path: 137free_path:
120 unlink(path); 138 unlink(path);
121 return ret; 139 return ret;
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index af7ad814b2c3..cee658733e2c 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -66,7 +66,7 @@ bpf__prepare_load_buffer(void *obj_buf, size_t obj_buf_sz, const char *name)
66 } 66 }
67 67
68 obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, name); 68 obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, name);
69 if (IS_ERR(obj)) { 69 if (IS_ERR_OR_NULL(obj)) {
70 pr_debug("bpf: failed to load buffer\n"); 70 pr_debug("bpf: failed to load buffer\n");
71 return ERR_PTR(-EINVAL); 71 return ERR_PTR(-EINVAL);
72 } 72 }
@@ -102,14 +102,14 @@ struct bpf_object *bpf__prepare_load(const char *filename, bool source)
102 pr_debug("bpf: successfull builtin compilation\n"); 102 pr_debug("bpf: successfull builtin compilation\n");
103 obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename); 103 obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename);
104 104
105 if (!IS_ERR(obj) && llvm_param.dump_obj) 105 if (!IS_ERR_OR_NULL(obj) && llvm_param.dump_obj)
106 llvm__dump_obj(filename, obj_buf, obj_buf_sz); 106 llvm__dump_obj(filename, obj_buf, obj_buf_sz);
107 107
108 free(obj_buf); 108 free(obj_buf);
109 } else 109 } else
110 obj = bpf_object__open(filename); 110 obj = bpf_object__open(filename);
111 111
112 if (IS_ERR(obj)) { 112 if (IS_ERR_OR_NULL(obj)) {
113 pr_debug("bpf: failed to load %s\n", filename); 113 pr_debug("bpf: failed to load %s\n", filename);
114 return obj; 114 return obj;
115 } 115 }
diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
index c8b98fa22997..4d5fc374e730 100644
--- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
+++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
@@ -96,11 +96,19 @@ int cs_etm_decoder__get_packet(struct cs_etm_decoder *decoder,
96 /* Nothing to do, might as well just return */ 96 /* Nothing to do, might as well just return */
97 if (decoder->packet_count == 0) 97 if (decoder->packet_count == 0)
98 return 0; 98 return 0;
99 /*
100 * The queueing process in function cs_etm_decoder__buffer_packet()
101 * increments the tail *before* using it. This is somewhat counter
102 * intuitive but it has the advantage of centralizing tail management
103 * at a single location. Because of that we need to follow the same
104 * heuristic with the head, i.e we increment it before using its
105 * value. Otherwise the first element of the packet queue is not
106 * used.
107 */
108 decoder->head = (decoder->head + 1) & (MAX_BUFFER - 1);
99 109
100 *packet = decoder->packet_buffer[decoder->head]; 110 *packet = decoder->packet_buffer[decoder->head];
101 111
102 decoder->head = (decoder->head + 1) & (MAX_BUFFER - 1);
103
104 decoder->packet_count--; 112 decoder->packet_count--;
105 113
106 return 1; 114 return 1;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 92ec009a292d..b13f5f234c8f 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -127,6 +127,7 @@ struct perf_evsel {
127 bool precise_max; 127 bool precise_max;
128 bool ignore_missing_thread; 128 bool ignore_missing_thread;
129 bool forced_leader; 129 bool forced_leader;
130 bool use_uncore_alias;
130 /* parse modifier helper */ 131 /* parse modifier helper */
131 int exclude_GH; 132 int exclude_GH;
132 int nr_members; 133 int nr_members;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index b8b8a9558d32..2fc4ee8b86c1 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1219,13 +1219,16 @@ int parse_events_add_numeric(struct parse_events_state *parse_state,
1219 1219
1220int parse_events_add_pmu(struct parse_events_state *parse_state, 1220int parse_events_add_pmu(struct parse_events_state *parse_state,
1221 struct list_head *list, char *name, 1221 struct list_head *list, char *name,
1222 struct list_head *head_config, bool auto_merge_stats) 1222 struct list_head *head_config,
1223 bool auto_merge_stats,
1224 bool use_alias)
1223{ 1225{
1224 struct perf_event_attr attr; 1226 struct perf_event_attr attr;
1225 struct perf_pmu_info info; 1227 struct perf_pmu_info info;
1226 struct perf_pmu *pmu; 1228 struct perf_pmu *pmu;
1227 struct perf_evsel *evsel; 1229 struct perf_evsel *evsel;
1228 struct parse_events_error *err = parse_state->error; 1230 struct parse_events_error *err = parse_state->error;
1231 bool use_uncore_alias;
1229 LIST_HEAD(config_terms); 1232 LIST_HEAD(config_terms);
1230 1233
1231 pmu = perf_pmu__find(name); 1234 pmu = perf_pmu__find(name);
@@ -1244,11 +1247,14 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
1244 memset(&attr, 0, sizeof(attr)); 1247 memset(&attr, 0, sizeof(attr));
1245 } 1248 }
1246 1249
1250 use_uncore_alias = (pmu->is_uncore && use_alias);
1251
1247 if (!head_config) { 1252 if (!head_config) {
1248 attr.type = pmu->type; 1253 attr.type = pmu->type;
1249 evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu, NULL, auto_merge_stats); 1254 evsel = __add_event(list, &parse_state->idx, &attr, NULL, pmu, NULL, auto_merge_stats);
1250 if (evsel) { 1255 if (evsel) {
1251 evsel->pmu_name = name; 1256 evsel->pmu_name = name;
1257 evsel->use_uncore_alias = use_uncore_alias;
1252 return 0; 1258 return 0;
1253 } else { 1259 } else {
1254 return -ENOMEM; 1260 return -ENOMEM;
@@ -1282,6 +1288,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
1282 evsel->metric_expr = info.metric_expr; 1288 evsel->metric_expr = info.metric_expr;
1283 evsel->metric_name = info.metric_name; 1289 evsel->metric_name = info.metric_name;
1284 evsel->pmu_name = name; 1290 evsel->pmu_name = name;
1291 evsel->use_uncore_alias = use_uncore_alias;
1285 } 1292 }
1286 1293
1287 return evsel ? 0 : -ENOMEM; 1294 return evsel ? 0 : -ENOMEM;
@@ -1317,7 +1324,8 @@ int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
1317 list_add_tail(&term->list, head); 1324 list_add_tail(&term->list, head);
1318 1325
1319 if (!parse_events_add_pmu(parse_state, list, 1326 if (!parse_events_add_pmu(parse_state, list,
1320 pmu->name, head, true)) { 1327 pmu->name, head,
1328 true, true)) {
1321 pr_debug("%s -> %s/%s/\n", str, 1329 pr_debug("%s -> %s/%s/\n", str,
1322 pmu->name, alias->str); 1330 pmu->name, alias->str);
1323 ok++; 1331 ok++;
@@ -1339,7 +1347,120 @@ int parse_events__modifier_group(struct list_head *list,
1339 return parse_events__modifier_event(list, event_mod, true); 1347 return parse_events__modifier_event(list, event_mod, true);
1340} 1348}
1341 1349
1342void parse_events__set_leader(char *name, struct list_head *list) 1350/*
1351 * Check if the two uncore PMUs are from the same uncore block
1352 * The format of the uncore PMU name is uncore_#blockname_#pmuidx
1353 */
1354static bool is_same_uncore_block(const char *pmu_name_a, const char *pmu_name_b)
1355{
1356 char *end_a, *end_b;
1357
1358 end_a = strrchr(pmu_name_a, '_');
1359 end_b = strrchr(pmu_name_b, '_');
1360
1361 if (!end_a || !end_b)
1362 return false;
1363
1364 if ((end_a - pmu_name_a) != (end_b - pmu_name_b))
1365 return false;
1366
1367 return (strncmp(pmu_name_a, pmu_name_b, end_a - pmu_name_a) == 0);
1368}
1369
1370static int
1371parse_events__set_leader_for_uncore_aliase(char *name, struct list_head *list,
1372 struct parse_events_state *parse_state)
1373{
1374 struct perf_evsel *evsel, *leader;
1375 uintptr_t *leaders;
1376 bool is_leader = true;
1377 int i, nr_pmu = 0, total_members, ret = 0;
1378
1379 leader = list_first_entry(list, struct perf_evsel, node);
1380 evsel = list_last_entry(list, struct perf_evsel, node);
1381 total_members = evsel->idx - leader->idx + 1;
1382
1383 leaders = calloc(total_members, sizeof(uintptr_t));
1384 if (WARN_ON(!leaders))
1385 return 0;
1386
1387 /*
1388 * Going through the whole group and doing sanity check.
1389 * All members must use alias, and be from the same uncore block.
1390 * Also, storing the leader events in an array.
1391 */
1392 __evlist__for_each_entry(list, evsel) {
1393
1394 /* Only split the uncore group which members use alias */
1395 if (!evsel->use_uncore_alias)
1396 goto out;
1397
1398 /* The events must be from the same uncore block */
1399 if (!is_same_uncore_block(leader->pmu_name, evsel->pmu_name))
1400 goto out;
1401
1402 if (!is_leader)
1403 continue;
1404 /*
1405 * If the event's PMU name starts to repeat, it must be a new
1406 * event. That can be used to distinguish the leader from
1407 * other members, even they have the same event name.
1408 */
1409 if ((leader != evsel) && (leader->pmu_name == evsel->pmu_name)) {
1410 is_leader = false;
1411 continue;
1412 }
1413 /* The name is always alias name */
1414 WARN_ON(strcmp(leader->name, evsel->name));
1415
1416 /* Store the leader event for each PMU */
1417 leaders[nr_pmu++] = (uintptr_t) evsel;
1418 }
1419
1420 /* only one event alias */
1421 if (nr_pmu == total_members) {
1422 parse_state->nr_groups--;
1423 goto handled;
1424 }
1425
1426 /*
1427 * An uncore event alias is a joint name which means the same event
1428 * runs on all PMUs of a block.
1429 * Perf doesn't support mixed events from different PMUs in the same
1430 * group. The big group has to be split into multiple small groups
1431 * which only include the events from the same PMU.
1432 *
1433 * Here the uncore event aliases must be from the same uncore block.
1434 * The number of PMUs must be same for each alias. The number of new
1435 * small groups equals to the number of PMUs.
1436 * Setting the leader event for corresponding members in each group.
1437 */
1438 i = 0;
1439 __evlist__for_each_entry(list, evsel) {
1440 if (i >= nr_pmu)
1441 i = 0;
1442 evsel->leader = (struct perf_evsel *) leaders[i++];
1443 }
1444
1445 /* The number of members and group name are same for each group */
1446 for (i = 0; i < nr_pmu; i++) {
1447 evsel = (struct perf_evsel *) leaders[i];
1448 evsel->nr_members = total_members / nr_pmu;
1449 evsel->group_name = name ? strdup(name) : NULL;
1450 }
1451
1452 /* Take the new small groups into account */
1453 parse_state->nr_groups += nr_pmu - 1;
1454
1455handled:
1456 ret = 1;
1457out:
1458 free(leaders);
1459 return ret;
1460}
1461
1462void parse_events__set_leader(char *name, struct list_head *list,
1463 struct parse_events_state *parse_state)
1343{ 1464{
1344 struct perf_evsel *leader; 1465 struct perf_evsel *leader;
1345 1466
@@ -1348,6 +1469,9 @@ void parse_events__set_leader(char *name, struct list_head *list)
1348 return; 1469 return;
1349 } 1470 }
1350 1471
1472 if (parse_events__set_leader_for_uncore_aliase(name, list, parse_state))
1473 return;
1474
1351 __perf_evlist__set_leader(list); 1475 __perf_evlist__set_leader(list);
1352 leader = list_entry(list->next, struct perf_evsel, node); 1476 leader = list_entry(list->next, struct perf_evsel, node);
1353 leader->group_name = name ? strdup(name) : NULL; 1477 leader->group_name = name ? strdup(name) : NULL;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index 5015cfd58277..4473dac27aee 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -167,7 +167,9 @@ int parse_events_add_breakpoint(struct list_head *list, int *idx,
167 void *ptr, char *type, u64 len); 167 void *ptr, char *type, u64 len);
168int parse_events_add_pmu(struct parse_events_state *parse_state, 168int parse_events_add_pmu(struct parse_events_state *parse_state,
169 struct list_head *list, char *name, 169 struct list_head *list, char *name,
170 struct list_head *head_config, bool auto_merge_stats); 170 struct list_head *head_config,
171 bool auto_merge_stats,
172 bool use_alias);
171 173
172int parse_events_multi_pmu_add(struct parse_events_state *parse_state, 174int parse_events_multi_pmu_add(struct parse_events_state *parse_state,
173 char *str, 175 char *str,
@@ -178,7 +180,8 @@ int parse_events_copy_term_list(struct list_head *old,
178 180
179enum perf_pmu_event_symbol_type 181enum perf_pmu_event_symbol_type
180perf_pmu__parse_check(const char *name); 182perf_pmu__parse_check(const char *name);
181void parse_events__set_leader(char *name, struct list_head *list); 183void parse_events__set_leader(char *name, struct list_head *list,
184 struct parse_events_state *parse_state);
182void parse_events_update_lists(struct list_head *list_event, 185void parse_events_update_lists(struct list_head *list_event,
183 struct list_head *list_all); 186 struct list_head *list_all);
184void parse_events_evlist_error(struct parse_events_state *parse_state, 187void parse_events_evlist_error(struct parse_events_state *parse_state,
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 7afeb80cc39e..e37608a87dba 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -161,7 +161,7 @@ PE_NAME '{' events '}'
161 struct list_head *list = $3; 161 struct list_head *list = $3;
162 162
163 inc_group_count(list, _parse_state); 163 inc_group_count(list, _parse_state);
164 parse_events__set_leader($1, list); 164 parse_events__set_leader($1, list, _parse_state);
165 $$ = list; 165 $$ = list;
166} 166}
167| 167|
@@ -170,7 +170,7 @@ PE_NAME '{' events '}'
170 struct list_head *list = $2; 170 struct list_head *list = $2;
171 171
172 inc_group_count(list, _parse_state); 172 inc_group_count(list, _parse_state);
173 parse_events__set_leader(NULL, list); 173 parse_events__set_leader(NULL, list, _parse_state);
174 $$ = list; 174 $$ = list;
175} 175}
176 176
@@ -232,7 +232,7 @@ PE_NAME opt_event_config
232 YYABORT; 232 YYABORT;
233 233
234 ALLOC_LIST(list); 234 ALLOC_LIST(list);
235 if (parse_events_add_pmu(_parse_state, list, $1, $2, false)) { 235 if (parse_events_add_pmu(_parse_state, list, $1, $2, false, false)) {
236 struct perf_pmu *pmu = NULL; 236 struct perf_pmu *pmu = NULL;
237 int ok = 0; 237 int ok = 0;
238 char *pattern; 238 char *pattern;
@@ -251,7 +251,7 @@ PE_NAME opt_event_config
251 free(pattern); 251 free(pattern);
252 YYABORT; 252 YYABORT;
253 } 253 }
254 if (!parse_events_add_pmu(_parse_state, list, pmu->name, terms, true)) 254 if (!parse_events_add_pmu(_parse_state, list, pmu->name, terms, true, false))
255 ok++; 255 ok++;
256 parse_events_terms__delete(terms); 256 parse_events_terms__delete(terms);
257 } 257 }
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 10dd5fce082b..7f8afacd08ee 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -531,6 +531,8 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample,
531 PyLong_FromUnsignedLongLong(sample->period)); 531 PyLong_FromUnsignedLongLong(sample->period));
532 pydict_set_item_string_decref(dict_sample, "phys_addr", 532 pydict_set_item_string_decref(dict_sample, "phys_addr",
533 PyLong_FromUnsignedLongLong(sample->phys_addr)); 533 PyLong_FromUnsignedLongLong(sample->phys_addr));
534 pydict_set_item_string_decref(dict_sample, "addr",
535 PyLong_FromUnsignedLongLong(sample->addr));
534 set_sample_read_in_dict(dict_sample, sample, evsel); 536 set_sample_read_in_dict(dict_sample, sample, evsel);
535 pydict_set_item_string_decref(dict, "sample", dict_sample); 537 pydict_set_item_string_decref(dict, "sample", dict_sample);
536 538