linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Thomas Richter <tmricht@linux.ibm.com>
To: linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org,
	acme@kernel.org
Cc: brueckner@linux.vnet.ibm.com, heiko.carstens@de.ibm.com,
	Thomas Richter <tmricht@linux.ibm.com>
Subject: [PATCH 2/3] perf record: Fix kallsym map size for s390
Date: Wed, 22 May 2019 16:46:00 +0200	[thread overview]
Message-ID: <20190522144601.50763-3-tmricht@linux.ibm.com> (raw)
In-Reply-To: <20190522144601.50763-1-tmricht@linux.ibm.com>

On s390 command

   [root@m35lp76 perf]#./perf record -e cycles -- find ~

creates a perf.data file with a strange PERF_RECORD_MMAP for kallsyms:

   [root@m35lp76 perf]# ./perf report -D | fgrep kernel.kallsyms
   0 0x128 [0x50]: PERF_RECORD_MMAP -1/0:
            [0x100000(0x3ff7ff027f0) @ 0x100000]: x [kernel.kallsyms]_text
   [root@m35lp76 perf]#

The size of the kernel is 0x3ff7ff027f0 bytes which is simply wrong.
It is the difference between the kernel's _end symbol and the first module:

  [root@m35lp76 perf]# cat /proc/kallsyms |sort| les
  0000000002472000 B __bss_stop
  0000000002472000 B _end
  000003ff800027f0 T qdio_stop_irq        [qdio]
  000003ff80002898 t qdio_do_eqbs [qdio]

The root cause is the following function sequence:
  cmd__record
    __cmd_record
      perf_session__new
        perf_session__create_kernel_maps
          machine__create_kernel_maps
            machine__get_running_kernel_start
            machine__update_kernel_mmap
            machine__set_kernel_mmap;

Machine__get_running_kernel_start() searches /proc/kallsyms for the
start symbol and then calls machine__update_kernel_mmap() with ~0ULL
for the kernel's end address.
It relies on machine__set_kernel_mmap() to find the next map, which is
usually a module and then uses the first module's start address as
kernel end address.
This works nicely on x86 and similar plattforms but not on s390.

On s390 the kernel starts at address 0x10000 and modules are loaded
at kernel virtual address space somewhere around 0x3ff xxxx xxxx,
leaving a huge gap.

To fix this function machine__create_kernel_maps() also searches for
symbol _end as BSS symbol and if this symbol is found, use this
symbol's address a kernel end in machine__update_kernel_mmap().
Otherwise fall back to the previous method and use the first
kernel module's load address (as before).

Output before:
  [root@m35lp76 perf]# ./perf record -e cycles -- find ~
  [root@m35lp76 perf]# ./perf report -D | fgrep kernel.kallsyms
  0 0x128 [0x50]: PERF_RECORD_MMAP -1/0:
                [0x100000(0x3ff7ff027f0) @ 0x100000]:
                x [kernel.kallsyms]_text
  [root@m35lp76 perf]#

Output after:
  [root@m35lp76 perf]# ./perf record -e cycles -- find ~
  [root@m35lp76 perf]# ./perf report -D | fgrep kernel.kallsyms
  0 0x128 [0x50]: PERF_RECORD_MMAP -1/0:
                [0x100000(0x2372000) @ 0x100000]:
                x [kernel.kallsyms]_text
  [root@m35lp76 perf]#

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Hendrik Brueckner <brueckner@linux.ibm.com>
---
 tools/perf/util/event.c   |  4 ++--
 tools/perf/util/machine.c | 29 +++++++++++++++++++++++------
 2 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index d1ad6c419724..96b4cbdb655e 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -876,11 +876,11 @@ static int find_symbol_cb(void *arg, const char *name, char type,
 	/*
 	 * Must be a function or at least an alias, as in PARISC64, where "_text" is
 	 * an 'A' to the same address as "_stext".
+	 * When searching for symbol _end allow symbol type 'B'.
 	 */
 	if (!(kallsyms__is_function(type) ||
-	      type == 'A') || strcmp(name, args->name))
+	      type == 'A' || type == 'B') || strcmp(name, args->name))
 		return 0;
-
 	args->start = start;
 	return 1;
 }
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 28a9541c4835..c278c1fe6dd3 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -918,13 +918,18 @@ void machine__get_kallsyms_filename(struct machine *machine, char *buf,
 }
 
 const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL};
+static const char *const ref_sym_endnames[] = {"_end", NULL};
 
 /* Figure out the start address of kernel map from /proc/kallsyms.
  * Returns the name of the start symbol in *symbol_name. Pass in NULL as
  * symbol_name if it's not that important.
+ *
+ * Get kernel end address for kernel map from /proc/kallsyms by
+ * searching for symbol _end.
  */
 static int machine__get_running_kernel_start(struct machine *machine,
-					     const char **symbol_name, u64 *start)
+					     const char **symbol_name,
+					     u64 *start, u64 *kernel_end)
 {
 	char filename[PATH_MAX];
 	int i, err = -1;
@@ -949,6 +954,16 @@ static int machine__get_running_kernel_start(struct machine *machine,
 		*symbol_name = name;
 
 	*start = addr;
+
+	/* Get kernel end address and store it when found */
+	for (i = 0; (name = ref_sym_endnames[i]) != NULL; i++) {
+		err = kallsyms__get_function_start(filename, name, &addr);
+		if (!err) {
+			*kernel_end = addr;
+			break;
+		}
+	}
+
 	return 0;
 }
 
@@ -1441,7 +1456,7 @@ int machine__create_kernel_maps(struct machine *machine)
 	struct dso *kernel = machine__get_kernel(machine);
 	const char *name = NULL;
 	struct map *map;
-	u64 addr = 0;
+	u64 addr = 0, e_addr = 0;
 	int ret;
 
 	if (kernel == NULL)
@@ -1460,7 +1475,7 @@ int machine__create_kernel_maps(struct machine *machine)
 				 "continuing anyway...\n", machine->pid);
 	}
 
-	if (!machine__get_running_kernel_start(machine, &name, &addr)) {
+	if (!machine__get_running_kernel_start(machine, &name, &addr, &e_addr)) {
 		if (name &&
 		    map__set_kallsyms_ref_reloc_sym(machine->vmlinux_map, name, addr)) {
 			machine__destroy_kernel_maps(machine);
@@ -1472,15 +1487,17 @@ int machine__create_kernel_maps(struct machine *machine)
 		 * we have a real start address now, so re-order the kmaps
 		 * assume it's the last in the kmaps
 		 */
-		machine__update_kernel_mmap(machine, addr, ~0ULL);
+		machine__update_kernel_mmap(machine, addr, e_addr ?: ~0ULL);
 	}
 
 	if (machine__create_extra_kernel_maps(machine, kernel))
 		pr_debug("Problems creating extra kernel maps, continuing anyway...\n");
 
-	/* update end address of the kernel map using adjacent module address */
+	/* update end address of the kernel map using adjacent module address
+	 * only when the kernel end could not be determined.
+	 */
 	map = map__next(machine__kernel_map(machine));
-	if (map)
+	if (!e_addr && map)
 		machine__set_kernel_mmap(machine, addr, map->start);
 out_put:
 	dso__put(kernel);
-- 
2.19.1


  parent reply	other threads:[~2019-05-22 14:46 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-22 14:45 [PATCH 0/3] Fix OOM in perf report on s390 Thomas Richter
2019-05-22 14:45 ` [PATCH 1/3] perf report: Fix OOM error in TUI mode " Thomas Richter
2019-05-22 18:08   ` Arnaldo Carvalho de Melo
2019-05-23  8:12     ` Thomas-Mich Richter
2019-05-22 14:46 ` Thomas Richter [this message]
2019-05-22 14:46 ` [PATCH 3/3] perf record: Fix s390 missing module symbol and warning for non-root users Thomas Richter
2019-05-22 18:03   ` Arnaldo Carvalho de Melo
2019-05-28 21:30   ` [tip:perf/urgent] " tip-bot for Thomas Richter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190522144601.50763-3-tmricht@linux.ibm.com \
    --to=tmricht@linux.ibm.com \
    --cc=acme@kernel.org \
    --cc=brueckner@linux.vnet.ibm.com \
    --cc=heiko.carstens@de.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).