diff options
author | Thomas Richter <tmricht@linux.ibm.com> | 2019-07-24 08:27:03 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2019-08-08 14:41:25 -0400 |
commit | b9c0a64901d5bdec6eafd38d1dc8fa0e2974fccb (patch) | |
tree | a3ad811e38b86f47f7d65ebd62a917c185ae5825 /tools | |
parent | 12a6d2940b5f02b4b9f71ce098e3bb02bc24a9ea (diff) |
perf annotate: Fix s390 gap between kernel end and module start
During execution of command 'perf top' the error message:
Not enough memory for annotating '__irf_end' symbol!)
is emitted from this call sequence:
__cmd_top
perf_top__mmap_read
perf_top__mmap_read_idx
perf_event__process_sample
hist_entry_iter__add
hist_iter__top_callback
perf_top__record_precise_ip
hist_entry__inc_addr_samples
symbol__inc_addr_samples
symbol__get_annotation
symbol__alloc_hist
In this function the size of symbol __irf_end is calculated. The size of
a symbol is the difference between its start and end address.
When the symbol was read the first time, its start and end was set to:
symbol__new: __irf_end 0xe954d0-0xe954d0
which is correct and maps with /proc/kallsyms:
root@s8360046:~/linux-4.15.0/tools/perf# fgrep _irf_end /proc/kallsyms
0000000000e954d0 t __irf_end
root@s8360046:~/linux-4.15.0/tools/perf#
In function symbol__alloc_hist() the end of symbol __irf_end is
symbol__alloc_hist sym:__irf_end start:0xe954d0 end:0x3ff80045a8
which is identical with the first module entry in /proc/kallsyms
This results in a symbol size of __irf_req for histogram analyses of
70334140059072 bytes and a malloc() for this requested size fails.
The root cause of this is function
__dso__load_kallsyms()
+-> symbols__fixup_end()
Function symbols__fixup_end() enlarges the last symbol in the kallsyms
map:
# fgrep __irf_end /proc/kallsyms
0000000000e954d0 t __irf_end
#
to the start address of the first module:
# cat /proc/kallsyms | sort | egrep ' [tT] '
....
0000000000e952d0 T __security_initcall_end
0000000000e954d0 T __initramfs_size
0000000000e954d0 t __irf_end
000003ff800045a8 T fc_get_event_number [scsi_transport_fc]
000003ff800045d0 t store_fc_vport_disable [scsi_transport_fc]
000003ff800046a8 T scsi_is_fc_rport [scsi_transport_fc]
000003ff800046d0 t fc_target_setup [scsi_transport_fc]
On s390 the kernel is located around memory address 0x200, 0x10000 or
0x100000, depending on linux version. Modules however start some- where
around 0x3ff xxxx xxxx.
This is different than x86 and produces a large gap for which histogram
allocation fails.
Fix this by detecting the kernel's last symbol and do no adjustment for
it. Introduce a weak function and handle s390 specifics.
Reported-by: Klaus Theurich <klaus.theurich@de.ibm.com>
Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Acked-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Hendrik Brueckner <brueckner@linux.ibm.com>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Cc: stable@vger.kernel.org
Link: http://lkml.kernel.org/r/20190724122703.3996-2-tmricht@linux.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/arch/s390/util/machine.c | 17 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 7 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 1 |
3 files changed, 24 insertions, 1 deletions
diff --git a/tools/perf/arch/s390/util/machine.c b/tools/perf/arch/s390/util/machine.c index de26b1441a48..c8c86a0c9b79 100644 --- a/tools/perf/arch/s390/util/machine.c +++ b/tools/perf/arch/s390/util/machine.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include "machine.h" | 6 | #include "machine.h" |
7 | #include "api/fs/fs.h" | 7 | #include "api/fs/fs.h" |
8 | #include "debug.h" | 8 | #include "debug.h" |
9 | #include "symbol.h" | ||
9 | 10 | ||
10 | int arch__fix_module_text_start(u64 *start, u64 *size, const char *name) | 11 | int arch__fix_module_text_start(u64 *start, u64 *size, const char *name) |
11 | { | 12 | { |
@@ -33,3 +34,19 @@ int arch__fix_module_text_start(u64 *start, u64 *size, const char *name) | |||
33 | 34 | ||
34 | return 0; | 35 | return 0; |
35 | } | 36 | } |
37 | |||
38 | /* On s390 kernel text segment start is located at very low memory addresses, | ||
39 | * for example 0x10000. Modules are located at very high memory addresses, | ||
40 | * for example 0x3ff xxxx xxxx. The gap between end of kernel text segment | ||
41 | * and beginning of first module's text segment is very big. | ||
42 | * Therefore do not fill this gap and do not assign it to the kernel dso map. | ||
43 | */ | ||
44 | void arch__symbols__fixup_end(struct symbol *p, struct symbol *c) | ||
45 | { | ||
46 | if (strchr(p->name, '[') == NULL && strchr(c->name, '[')) | ||
47 | /* Last kernel symbol mapped to end of page */ | ||
48 | p->end = roundup(p->end, page_size); | ||
49 | else | ||
50 | p->end = c->start; | ||
51 | pr_debug4("%s sym:%s end:%#lx\n", __func__, p->name, p->end); | ||
52 | } | ||
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 173f3378aaa0..4efde7879474 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -92,6 +92,11 @@ static int prefix_underscores_count(const char *str) | |||
92 | return tail - str; | 92 | return tail - str; |
93 | } | 93 | } |
94 | 94 | ||
95 | void __weak arch__symbols__fixup_end(struct symbol *p, struct symbol *c) | ||
96 | { | ||
97 | p->end = c->start; | ||
98 | } | ||
99 | |||
95 | const char * __weak arch__normalize_symbol_name(const char *name) | 100 | const char * __weak arch__normalize_symbol_name(const char *name) |
96 | { | 101 | { |
97 | return name; | 102 | return name; |
@@ -218,7 +223,7 @@ void symbols__fixup_end(struct rb_root_cached *symbols) | |||
218 | curr = rb_entry(nd, struct symbol, rb_node); | 223 | curr = rb_entry(nd, struct symbol, rb_node); |
219 | 224 | ||
220 | if (prev->end == prev->start && prev->end != curr->start) | 225 | if (prev->end == prev->start && prev->end != curr->start) |
221 | prev->end = curr->start; | 226 | arch__symbols__fixup_end(prev, curr); |
222 | } | 227 | } |
223 | 228 | ||
224 | /* Last entry */ | 229 | /* Last entry */ |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 12755b42ea93..183f630cb5f1 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -288,6 +288,7 @@ const char *arch__normalize_symbol_name(const char *name); | |||
288 | #define SYMBOL_A 0 | 288 | #define SYMBOL_A 0 |
289 | #define SYMBOL_B 1 | 289 | #define SYMBOL_B 1 |
290 | 290 | ||
291 | void arch__symbols__fixup_end(struct symbol *p, struct symbol *c); | ||
291 | int arch__compare_symbol_names(const char *namea, const char *nameb); | 292 | int arch__compare_symbol_names(const char *namea, const char *nameb); |
292 | int arch__compare_symbol_names_n(const char *namea, const char *nameb, | 293 | int arch__compare_symbol_names_n(const char *namea, const char *nameb, |
293 | unsigned int n); | 294 | unsigned int n); |