Skip to content

Commit a8ce99b

Browse files
ahunter6acmel
authored andcommitted
perf machine: Synthesize and process mmap events for x86 PTI entry trampolines
Like the kernel text, the location of x86 PTI entry trampolines must be recorded in the perf.data file. Like the kernel, synthesize a mmap event for that, and add processing for it. Signed-off-by: Adrian Hunter <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Andi Kleen <[email protected]> Cc: Andy Lutomirski <[email protected]> Cc: Dave Hansen <[email protected]> Cc: H. Peter Anvin <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Joerg Roedel <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: [email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 1c5aae7 commit a8ce99b

File tree

5 files changed

+140
-7
lines changed

5 files changed

+140
-7
lines changed

tools/perf/arch/x86/util/Build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ libperf-y += kvm-stat.o
55
libperf-y += perf_regs.o
66
libperf-y += group.o
77
libperf-y += machine.o
8+
libperf-y += event.o
89

910
libperf-$(CONFIG_DWARF) += dwarf-regs.o
1011
libperf-$(CONFIG_BPF_PROLOGUE) += dwarf-regs.o

tools/perf/arch/x86/util/event.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
#include <linux/types.h>
3+
#include <linux/string.h>
4+
5+
#include "../../util/machine.h"
6+
#include "../../util/tool.h"
7+
#include "../../util/map.h"
8+
#include "../../util/util.h"
9+
#include "../../util/debug.h"
10+
11+
#if defined(__x86_64__)
12+
13+
int perf_event__synthesize_extra_kmaps(struct perf_tool *tool,
14+
perf_event__handler_t process,
15+
struct machine *machine)
16+
{
17+
int rc = 0;
18+
struct map *pos;
19+
struct map_groups *kmaps = &machine->kmaps;
20+
struct maps *maps = &kmaps->maps;
21+
union perf_event *event = zalloc(sizeof(event->mmap) +
22+
machine->id_hdr_size);
23+
24+
if (!event) {
25+
pr_debug("Not enough memory synthesizing mmap event "
26+
"for extra kernel maps\n");
27+
return -1;
28+
}
29+
30+
for (pos = maps__first(maps); pos; pos = map__next(pos)) {
31+
struct kmap *kmap;
32+
size_t size;
33+
34+
if (!__map__is_extra_kernel_map(pos))
35+
continue;
36+
37+
kmap = map__kmap(pos);
38+
39+
size = sizeof(event->mmap) - sizeof(event->mmap.filename) +
40+
PERF_ALIGN(strlen(kmap->name) + 1, sizeof(u64)) +
41+
machine->id_hdr_size;
42+
43+
memset(event, 0, size);
44+
45+
event->mmap.header.type = PERF_RECORD_MMAP;
46+
47+
/*
48+
* kernel uses 0 for user space maps, see kernel/perf_event.c
49+
* __perf_event_mmap
50+
*/
51+
if (machine__is_host(machine))
52+
event->header.misc = PERF_RECORD_MISC_KERNEL;
53+
else
54+
event->header.misc = PERF_RECORD_MISC_GUEST_KERNEL;
55+
56+
event->mmap.header.size = size;
57+
58+
event->mmap.start = pos->start;
59+
event->mmap.len = pos->end - pos->start;
60+
event->mmap.pgoff = pos->pgoff;
61+
event->mmap.pid = machine->pid;
62+
63+
strlcpy(event->mmap.filename, kmap->name, PATH_MAX);
64+
65+
if (perf_tool__process_synth_event(tool, event, machine,
66+
process) != 0) {
67+
rc = -1;
68+
break;
69+
}
70+
}
71+
72+
free(event);
73+
return rc;
74+
}
75+
76+
#endif

tools/perf/util/event.c

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,10 @@ static const char *perf_ns__name(unsigned int id)
8888
return perf_ns__names[id];
8989
}
9090

91-
static int perf_tool__process_synth_event(struct perf_tool *tool,
92-
union perf_event *event,
93-
struct machine *machine,
94-
perf_event__handler_t process)
91+
int perf_tool__process_synth_event(struct perf_tool *tool,
92+
union perf_event *event,
93+
struct machine *machine,
94+
perf_event__handler_t process)
9595
{
9696
struct perf_sample synth_sample = {
9797
.pid = -1,
@@ -888,9 +888,16 @@ int kallsyms__get_function_start(const char *kallsyms_filename,
888888
return 0;
889889
}
890890

891-
int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
892-
perf_event__handler_t process,
893-
struct machine *machine)
891+
int __weak perf_event__synthesize_extra_kmaps(struct perf_tool *tool __maybe_unused,
892+
perf_event__handler_t process __maybe_unused,
893+
struct machine *machine __maybe_unused)
894+
{
895+
return 0;
896+
}
897+
898+
static int __perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
899+
perf_event__handler_t process,
900+
struct machine *machine)
894901
{
895902
size_t size;
896903
struct map *map = machine__kernel_map(machine);
@@ -943,6 +950,19 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
943950
return err;
944951
}
945952

953+
int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
954+
perf_event__handler_t process,
955+
struct machine *machine)
956+
{
957+
int err;
958+
959+
err = __perf_event__synthesize_kernel_mmap(tool, process, machine);
960+
if (err < 0)
961+
return err;
962+
963+
return perf_event__synthesize_extra_kmaps(tool, process, machine);
964+
}
965+
946966
int perf_event__synthesize_thread_map2(struct perf_tool *tool,
947967
struct thread_map *threads,
948968
perf_event__handler_t process,

tools/perf/util/event.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,10 @@ int perf_event__process_exit(struct perf_tool *tool,
750750
union perf_event *event,
751751
struct perf_sample *sample,
752752
struct machine *machine);
753+
int perf_tool__process_synth_event(struct perf_tool *tool,
754+
union perf_event *event,
755+
struct machine *machine,
756+
perf_event__handler_t process);
753757
int perf_event__process(struct perf_tool *tool,
754758
union perf_event *event,
755759
struct perf_sample *sample,
@@ -796,6 +800,10 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
796800
bool mmap_data,
797801
unsigned int proc_map_timeout);
798802

803+
int perf_event__synthesize_extra_kmaps(struct perf_tool *tool,
804+
perf_event__handler_t process,
805+
struct machine *machine);
806+
799807
size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp);
800808
size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp);
801809
size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp);

tools/perf/util/machine.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,6 +1387,32 @@ static bool machine__uses_kcore(struct machine *machine)
13871387
return false;
13881388
}
13891389

1390+
static bool perf_event__is_extra_kernel_mmap(struct machine *machine,
1391+
union perf_event *event)
1392+
{
1393+
return machine__is(machine, "x86_64") &&
1394+
is_entry_trampoline(event->mmap.filename);
1395+
}
1396+
1397+
static int machine__process_extra_kernel_map(struct machine *machine,
1398+
union perf_event *event)
1399+
{
1400+
struct map *kernel_map = machine__kernel_map(machine);
1401+
struct dso *kernel = kernel_map ? kernel_map->dso : NULL;
1402+
struct extra_kernel_map xm = {
1403+
.start = event->mmap.start,
1404+
.end = event->mmap.start + event->mmap.len,
1405+
.pgoff = event->mmap.pgoff,
1406+
};
1407+
1408+
if (kernel == NULL)
1409+
return -1;
1410+
1411+
strlcpy(xm.name, event->mmap.filename, KMAP_NAME_LEN);
1412+
1413+
return machine__create_extra_kernel_map(machine, kernel, &xm);
1414+
}
1415+
13901416
static int machine__process_kernel_mmap_event(struct machine *machine,
13911417
union perf_event *event)
13921418
{
@@ -1490,6 +1516,8 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
14901516
*/
14911517
dso__load(kernel, machine__kernel_map(machine));
14921518
}
1519+
} else if (perf_event__is_extra_kernel_mmap(machine, event)) {
1520+
return machine__process_extra_kernel_map(machine, event);
14931521
}
14941522
return 0;
14951523
out_problem:

0 commit comments

Comments
 (0)