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

Configure Feed

Select the types of activity you want to include in your feed.

perf evlist: Improve default event for s390

Frame pointer callchains are not supported on s390 and dwarf
callchains are only supported on software events.

Switch the default event from the hardware 'cycles' event to the
software 'cpu-clock' or 'task-clock' on s390 if callchains are
enabled. Move some of the target initialization earlier in builtin-top
and builtin-record, so it is ready for use by evlist__new_default.

If frame pointer callchains are requested on s390 show a
warning. Modify the '-g' option of `perf top` and `perf record` to
default to dwarf callchains on s390.

Signed-off-by: Ian Rogers <irogers@google.com>
Tested-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>

authored by

Ian Rogers and committed by
Namhyung Kim
ca76fb67 c006753c

+64 -35
+11 -7
tools/perf/builtin-record.c
··· 55 55 #include "asm/bug.h" 56 56 #include "perf.h" 57 57 #include "cputopo.h" 58 + #include "dwarf-regs.h" 58 59 59 60 #include <errno.h> 60 61 #include <inttypes.h> ··· 2996 2995 return 0; 2997 2996 } 2998 2997 2999 - return record_opts__parse_callchain(opt->value, &callchain_param, "fp", unset); 2998 + return record_opts__parse_callchain(opt->value, &callchain_param, 2999 + EM_HOST != EM_S390 ? "fp" : "dwarf", 3000 + unset); 3000 3001 } 3001 3002 3002 3003 ··· 4098 4095 4099 4096 perf_debuginfod_setup(&record.debuginfod); 4100 4097 4101 - /* Make system wide (-a) the default target. */ 4102 - if (!argc && target__none(&rec->opts.target)) 4098 + /* 4099 + * Use system wide (-a) for the default target (ie. when no 4100 + * workload). User ID filtering also implies system-wide. 4101 + */ 4102 + if ((!argc && target__none(&rec->opts.target)) || rec->uid_str) 4103 4103 rec->opts.target.system_wide = true; 4104 4104 4105 4105 if (nr_cgroups && !rec->opts.target.system_wide) { ··· 4280 4274 record.opts.tail_synthesize = true; 4281 4275 4282 4276 if (rec->evlist->core.nr_entries == 0) { 4283 - struct evlist *def_evlist = evlist__new_default(); 4277 + struct evlist *def_evlist = evlist__new_default(&rec->opts.target, 4278 + callchain_param.enabled); 4284 4279 4285 4280 if (!def_evlist) 4286 4281 goto out; ··· 4310 4303 err = parse_uid_filter(rec->evlist, uid); 4311 4304 if (err) 4312 4305 goto out; 4313 - 4314 - /* User ID filtering implies system wide. */ 4315 - rec->opts.target.system_wide = true; 4316 4306 } 4317 4307 4318 4308 /* Enable ignoring missing threads when -p option is defined. */
+12 -11
tools/perf/builtin-top.c
··· 56 56 #include "util/debug.h" 57 57 #include "util/ordered-events.h" 58 58 #include "util/pfm.h" 59 + #include "dwarf-regs.h" 59 60 60 61 #include <assert.h> 61 62 #include <elf.h> ··· 1421 1420 return 0; 1422 1421 } 1423 1422 1424 - return parse_callchain_opt(opt, "fp", unset); 1423 + return parse_callchain_opt(opt, EM_HOST != EM_S390 ? "fp" : "dwarf", unset); 1425 1424 } 1426 1425 1427 1426 ··· 1706 1705 if (annotate_check_args() < 0) 1707 1706 goto out_delete_evlist; 1708 1707 1708 + status = target__validate(target); 1709 + if (status) { 1710 + target__strerror(target, status, errbuf, BUFSIZ); 1711 + ui__warning("%s\n", errbuf); 1712 + } 1713 + 1714 + if (target__none(target)) 1715 + target->system_wide = true; 1716 + 1709 1717 if (!top.evlist->core.nr_entries) { 1710 - struct evlist *def_evlist = evlist__new_default(); 1718 + struct evlist *def_evlist = evlist__new_default(target, callchain_param.enabled); 1711 1719 1712 1720 if (!def_evlist) 1713 1721 goto out_delete_evlist; ··· 1809 1799 goto out_delete_evlist; 1810 1800 } 1811 1801 1812 - status = target__validate(target); 1813 - if (status) { 1814 - target__strerror(target, status, errbuf, BUFSIZ); 1815 - ui__warning("%s\n", errbuf); 1816 - } 1817 - 1818 1802 if (top.uid_str) { 1819 1803 uid_t uid = parse_uid(top.uid_str); 1820 1804 ··· 1821 1817 if (status) 1822 1818 goto out_delete_evlist; 1823 1819 } 1824 - 1825 - if (target__none(target)) 1826 - target->system_wide = true; 1827 1820 1828 1821 if (evlist__create_maps(top.evlist, target) < 0) { 1829 1822 ui__error("Couldn't create thread/CPU maps: %s\n",
+3 -1
tools/perf/tests/event_update.c
··· 8 8 #include "header.h" 9 9 #include "machine.h" 10 10 #include "util/synthetic-events.h" 11 + #include "target.h" 11 12 #include "tool.h" 12 13 #include "tests.h" 13 14 #include "debug.h" ··· 82 81 { 83 82 struct evsel *evsel; 84 83 struct event_name tmp; 85 - struct evlist *evlist = evlist__new_default(); 84 + struct target target = {}; 85 + struct evlist *evlist = evlist__new_default(&target, /*sample_callchains=*/false); 86 86 87 87 TEST_ASSERT_VAL("failed to get evlist", evlist); 88 88
+3 -1
tools/perf/tests/expand-cgroup.c
··· 8 8 #include "parse-events.h" 9 9 #include "pmu-events/pmu-events.h" 10 10 #include "pfm.h" 11 + #include "target.h" 11 12 #include <subcmd/parse-options.h> 12 13 #include <stdio.h> 13 14 #include <stdlib.h> ··· 100 99 static int expand_default_events(void) 101 100 { 102 101 int ret; 103 - struct evlist *evlist = evlist__new_default(); 102 + struct target target = {}; 103 + struct evlist *evlist = evlist__new_default(&target, /*sample_callchains=*/false); 104 104 105 105 TEST_ASSERT_VAL("failed to get evlist", evlist); 106 106
+5 -2
tools/perf/tests/perf-record.c
··· 84 84 CPU_ZERO_S(cpu_mask_size, cpu_mask); 85 85 86 86 perf_sample__init(&sample, /*all=*/false); 87 - if (evlist == NULL) /* Fallback for kernels lacking PERF_COUNT_SW_DUMMY */ 88 - evlist = evlist__new_default(); 87 + if (evlist == NULL) { /* Fallback for kernels lacking PERF_COUNT_SW_DUMMY */ 88 + struct target target = {}; 89 + 90 + evlist = evlist__new_default(&target, /*sample_callchains=*/false); 91 + } 89 92 90 93 if (evlist == NULL) { 91 94 pr_debug("Not enough memory to create evlist\n");
+3 -1
tools/perf/tests/topology.c
··· 9 9 #include "evlist.h" 10 10 #include "debug.h" 11 11 #include "pmus.h" 12 + #include "target.h" 12 13 #include <linux/err.h> 13 14 14 15 #define TEMPL "/tmp/perf-test-XXXXXX" ··· 38 37 .path = path, 39 38 .mode = PERF_DATA_MODE_WRITE, 40 39 }; 40 + struct target target = {}; 41 41 42 42 session = perf_session__new(&data, NULL); 43 43 TEST_ASSERT_VAL("can't get session", !IS_ERR(session)); 44 44 45 - session->evlist = evlist__new_default(); 45 + session->evlist = evlist__new_default(&target, /*sample_callchains=*/false); 46 46 TEST_ASSERT_VAL("can't get evlist", session->evlist); 47 47 session->evlist->session = session; 48 48
+21 -11
tools/perf/util/evlist.c
··· 13 13 #include "util/mmap.h" 14 14 #include "thread_map.h" 15 15 #include "target.h" 16 + #include "dwarf-regs.h" 16 17 #include "evlist.h" 17 18 #include "evsel.h" 18 19 #include "record.h" ··· 99 98 return evlist; 100 99 } 101 100 102 - struct evlist *evlist__new_default(void) 101 + struct evlist *evlist__new_default(const struct target *target, bool sample_callchains) 103 102 { 104 103 struct evlist *evlist = evlist__new(); 105 104 bool can_profile_kernel; 106 105 struct perf_pmu *pmu = NULL; 106 + struct evsel *evsel; 107 + char buf[256]; 108 + int err; 107 109 108 110 if (!evlist) 109 111 return NULL; 110 112 111 113 can_profile_kernel = perf_event_paranoid_check(1); 112 114 113 - while ((pmu = perf_pmus__scan_core(pmu)) != NULL) { 114 - char buf[256]; 115 - int err; 116 - 117 - snprintf(buf, sizeof(buf), "%s/cycles/%s", pmu->name, 115 + if (EM_HOST == EM_S390 && sample_callchains) { 116 + snprintf(buf, sizeof(buf), "software/%s/%s", 117 + target__has_cpu(target) ? "cpu-clock" : "task-clock", 118 118 can_profile_kernel ? "P" : "Pu"); 119 119 err = parse_event(evlist, buf); 120 - if (err) { 121 - evlist__delete(evlist); 122 - return NULL; 120 + if (err) 121 + goto out_err; 122 + } else { 123 + while ((pmu = perf_pmus__scan_core(pmu)) != NULL) { 124 + snprintf(buf, sizeof(buf), "%s/cycles/%s", pmu->name, 125 + can_profile_kernel ? "P" : "Pu"); 126 + err = parse_event(evlist, buf); 127 + if (err) 128 + goto out_err; 123 129 } 124 130 } 125 131 132 + /* If there is only 1 event a sample identifier isn't necessary. */ 126 133 if (evlist->core.nr_entries > 1) { 127 - struct evsel *evsel; 128 - 129 134 evlist__for_each_entry(evlist, evsel) 130 135 evsel__set_sample_id(evsel, /*can_sample_identifier=*/false); 131 136 } 132 137 133 138 return evlist; 139 + out_err: 140 + evlist__delete(evlist); 141 + return NULL; 134 142 } 135 143 136 144 struct evlist *evlist__new_dummy(void)
+1 -1
tools/perf/util/evlist.h
··· 104 104 }; 105 105 106 106 struct evlist *evlist__new(void); 107 - struct evlist *evlist__new_default(void); 107 + struct evlist *evlist__new_default(const struct target *target, bool sample_callchains); 108 108 struct evlist *evlist__new_dummy(void); 109 109 void evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus, 110 110 struct perf_thread_map *threads);
+5
tools/perf/util/evsel.c
··· 1021 1021 bool function = evsel__is_function_event(evsel); 1022 1022 struct perf_event_attr *attr = &evsel->core.attr; 1023 1023 1024 + if (EM_HOST == EM_S390 && param->record_mode == CALLCHAIN_FP) { 1025 + pr_warning_once( 1026 + "Framepointer unwinding lacks kernel support. Use '--call-graph dwarf'\n"); 1027 + } 1028 + 1024 1029 evsel__set_sample_bit(evsel, CALLCHAIN); 1025 1030 1026 1031 attr->sample_max_stack = param->max_stack;