diff options
Diffstat (limited to 'tools/perf/util/machine.c')
-rw-r--r-- | tools/perf/util/machine.c | 66 |
1 files changed, 47 insertions, 19 deletions
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 355d23bcd443..dd7ab0731167 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -807,8 +807,8 @@ struct process_args { u64 start; }; -static void machine__get_kallsyms_filename(struct machine *machine, char *buf, - size_t bufsz) +void machine__get_kallsyms_filename(struct machine *machine, char *buf, + size_t bufsz) { if (machine__is_default_guest(machine)) scnprintf(buf, bufsz, "%s", symbol_conf.default_guest_kallsyms); @@ -851,17 +851,9 @@ static int machine__get_running_kernel_start(struct machine *machine, return 0; } -/* Kernel-space maps for symbols that are outside the main kernel map and module maps */ -struct extra_kernel_map { - u64 start; - u64 end; - u64 pgoff; - char name[KMAP_NAME_LEN]; -}; - -static int machine__create_extra_kernel_map(struct machine *machine, - struct dso *kernel, - struct extra_kernel_map *xm) +int machine__create_extra_kernel_map(struct machine *machine, + struct dso *kernel, + struct extra_kernel_map *xm) { struct kmap *kmap; struct map *map; @@ -923,9 +915,33 @@ static u64 find_entry_trampoline(struct dso *dso) int machine__map_x86_64_entry_trampolines(struct machine *machine, struct dso *kernel) { - u64 pgoff = find_entry_trampoline(kernel); + struct map_groups *kmaps = &machine->kmaps; + struct maps *maps = &kmaps->maps; int nr_cpus_avail, cpu; + bool found = false; + struct map *map; + u64 pgoff; + + /* + * In the vmlinux case, pgoff is a virtual address which must now be + * mapped to a vmlinux offset. + */ + for (map = maps__first(maps); map; map = map__next(map)) { + struct kmap *kmap = __map__kmap(map); + struct map *dest_map; + + if (!kmap || !is_entry_trampoline(kmap->name)) + continue; + + dest_map = map_groups__find(kmaps, map->pgoff); + if (dest_map != map) + map->pgoff = dest_map->map_ip(dest_map, map->pgoff); + found = true; + } + if (found || machine->trampolines_mapped) + return 0; + pgoff = find_entry_trampoline(kernel); if (!pgoff) return 0; @@ -948,6 +964,14 @@ int machine__map_x86_64_entry_trampolines(struct machine *machine, return -1; } + machine->trampolines_mapped = nr_cpus_avail; + + return 0; +} + +int __weak machine__create_extra_kernel_maps(struct machine *machine __maybe_unused, + struct dso *kernel __maybe_unused) +{ return 0; } @@ -1306,9 +1330,8 @@ int machine__create_kernel_maps(struct machine *machine) return -1; ret = __machine__create_kernel_maps(machine, kernel); - dso__put(kernel); if (ret < 0) - return -1; + goto out_put; if (symbol_conf.use_modules && machine__create_modules(machine) < 0) { if (machine__is_host(machine)) @@ -1323,7 +1346,8 @@ int machine__create_kernel_maps(struct machine *machine) if (name && map__set_kallsyms_ref_reloc_sym(machine->vmlinux_map, name, addr)) { machine__destroy_kernel_maps(machine); - return -1; + ret = -1; + goto out_put; } /* we have a real start address now, so re-order the kmaps */ @@ -1339,12 +1363,16 @@ int machine__create_kernel_maps(struct machine *machine) map__put(map); } + 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 */ map = map__next(machine__kernel_map(machine)); if (map) machine__set_kernel_mmap(machine, addr, map->start); - - return 0; +out_put: + dso__put(kernel); + return ret; } static bool machine__uses_kcore(struct machine *machine) |