forked from Minki/linux
perf powerpc: Fix gap between kernel end and module start
Running "perf mem report" in TUI mode fails with ENOMEM message in powerpc: failed to process sample Running with debug and verbose options points that issue is while allocating memory for sample histograms. The error path is: symbol__inc_addr_samples() -> __symbol__inc_addr_samples() -> annotated_source__histogram() symbol__inc_addr_samples() calls annotated_source__alloc_histograms () to allocate memory for sample histograms using calloc(). Here calloc() fails since the size of symbol is huge. The size of a symbol is calculated as difference between its start and end address. Example histogram allocation that fails is: sym->name is _end sym->start is 0xc0000000027a0000 sym->end is 0xc008000003890000 symbol__size(sym) is 0x80000010f0000 In the above case, the difference between sym->start (0xc0000000027a0000) and sym->end (0xc008000003890000) is huge. This is same problem as in s390 and arm64 which are fixed in commits:b9c0a64901
("perf annotate: Fix s390 gap between kernel end and module start")78886f3ed3
("perf symbols: Fix arm64 gap between kernel start and module end") When this symbol was read first, its start and end address was set to address which matches with data from /proc/kallsyms. After symbol__new(): symbol__new: _end 0xc0000000027a0000-0xc0000000027a0000 From /proc/kallsyms: ... c000000002799370 b backtrace_flag c000000002799378 B radix_tree_node_cachep c000000002799380 B __bss_stop c0000000027a0000 B _end c008000003890000 t icmp_checkentry [ip_tables] c008000003890038 t ipt_alloc_initial_table [ip_tables] c008000003890468 T ipt_do_table [ip_tables] c008000003890de8 T ipt_unregister_table_pre_exit [ip_tables] ... Perf calls function symbols__fixup_end() which sets the end of symbol to 0xc008000003890000, which is the next address and this is the start address of first module (icmp_checkentry in above) which will make the huge symbol size of 0x80000010f0000. After symbols__fixup_end: symbols__fixup_end: sym->name: _end sym->start: 0xc0000000027a0000 sym->end: 0xc008000003890000 On powerpc, kernel text segment is located at 0xc000000000000000 whereas the modules are located at very high memory addresses, 0xc00800000xxxxxxx. Since the gap between end of kernel text segment and beginning of first module's address is high, histogram allocation using calloc fails. Fix this by detecting the kernel's last symbol and limiting the range of last kernel symbol to pagesize. Signed-off-by: Athira Rajeev<atrajeev@linux.vnet.ibm.com> Acked-by: Jiri Olsa <jolsa@redhat.com> Tested-By: Kajol Jain <kjain@linux.ibm.com> Cc: Madhavan Srinivasan <maddy@linux.ibm.com> Cc: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/1609208054-1566-1-git-send-email-atrajeev@linux.vnet.ibm.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
67dec92693
commit
557c3eadb7
@ -1,4 +1,5 @@
|
||||
perf-y += header.o
|
||||
perf-y += machine.o
|
||||
perf-y += kvm-stat.o
|
||||
perf-y += perf_regs.o
|
||||
perf-y += mem-events.o
|
||||
|
24
tools/perf/arch/powerpc/util/machine.c
Normal file
24
tools/perf/arch/powerpc/util/machine.c
Normal file
@ -0,0 +1,24 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <internal/lib.h> // page_size
|
||||
#include "debug.h"
|
||||
#include "symbol.h"
|
||||
|
||||
/* On powerpc kernel text segment start at memory addresses, 0xc000000000000000
|
||||
* whereas the modules are located at very high memory addresses,
|
||||
* for example 0xc00800000xxxxxxx. The gap between end of kernel text segment
|
||||
* and beginning of first module's text segment is very high.
|
||||
* Therefore do not fill this gap and do not assign it to the kernel dso map.
|
||||
*/
|
||||
|
||||
void arch__symbols__fixup_end(struct symbol *p, struct symbol *c)
|
||||
{
|
||||
if (strchr(p->name, '[') == NULL && strchr(c->name, '['))
|
||||
/* Limit the range of last kernel symbol */
|
||||
p->end += page_size;
|
||||
else
|
||||
p->end = c->start;
|
||||
pr_debug4("%s sym:%s end:%#lx\n", __func__, p->name, p->end);
|
||||
}
|
Loading…
Reference in New Issue
Block a user