Skip to content

Commit b9c0a64

Browse files
Thomas Richteracmel
authored andcommitted
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 <[email protected]> Signed-off-by: Thomas Richter <[email protected]> Acked-by: Heiko Carstens <[email protected]> Cc: Hendrik Brueckner <[email protected]> Cc: Vasily Gorbik <[email protected]> Cc: [email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 12a6d29 commit b9c0a64

File tree

3 files changed

+24
-1
lines changed

3 files changed

+24
-1
lines changed

tools/perf/arch/s390/util/machine.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "machine.h"
77
#include "api/fs/fs.h"
88
#include "debug.h"
9+
#include "symbol.h"
910

1011
int arch__fix_module_text_start(u64 *start, u64 *size, const char *name)
1112
{
@@ -33,3 +34,19 @@ int arch__fix_module_text_start(u64 *start, u64 *size, const char *name)
3334

3435
return 0;
3536
}
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+
}

tools/perf/util/symbol.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ static int prefix_underscores_count(const char *str)
9292
return tail - str;
9393
}
9494

95+
void __weak arch__symbols__fixup_end(struct symbol *p, struct symbol *c)
96+
{
97+
p->end = c->start;
98+
}
99+
95100
const char * __weak arch__normalize_symbol_name(const char *name)
96101
{
97102
return name;
@@ -218,7 +223,7 @@ void symbols__fixup_end(struct rb_root_cached *symbols)
218223
curr = rb_entry(nd, struct symbol, rb_node);
219224

220225
if (prev->end == prev->start && prev->end != curr->start)
221-
prev->end = curr->start;
226+
arch__symbols__fixup_end(prev, curr);
222227
}
223228

224229
/* Last entry */

tools/perf/util/symbol.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ const char *arch__normalize_symbol_name(const char *name);
288288
#define SYMBOL_A 0
289289
#define SYMBOL_B 1
290290

291+
void arch__symbols__fixup_end(struct symbol *p, struct symbol *c);
291292
int arch__compare_symbol_names(const char *namea, const char *nameb);
292293
int arch__compare_symbol_names_n(const char *namea, const char *nameb,
293294
unsigned int n);

0 commit comments

Comments
 (0)