mirror of
https://github.com/torvalds/linux
synced 2024-11-05 18:23:50 +00:00
perf map: Simplify map_ip/unmap_ip and make 'struct map' smaller
When mapping an IP it is either an identity mapping or a DSO relative mapping, so a single bit is required in the struct to identify this. The current code uses function pointers, adding 2 pointers per map and also pushing the size of a map beyond 1 cache line. Switch to using a byte to identify the mapping type (as well as priv and erange_warned), to avoid any masking. Change struct maps's layout to avoid holes. Before: ``` struct map { u64 start; /* 0 8 */ u64 end; /* 8 8 */ _Bool erange_warned:1; /* 16: 0 1 */ _Bool priv:1; /* 16: 1 1 */ /* XXX 6 bits hole, try to pack */ /* XXX 3 bytes hole, try to pack */ u32 prot; /* 20 4 */ u64 pgoff; /* 24 8 */ u64 reloc; /* 32 8 */ u64 (*map_ip)(const struct map *, u64); /* 40 8 */ u64 (*unmap_ip)(const struct map *, u64); /* 48 8 */ struct dso * dso; /* 56 8 */ /* --- cacheline 1 boundary (64 bytes) --- */ refcount_t refcnt; /* 64 4 */ u32 flags; /* 68 4 */ /* size: 72, cachelines: 2, members: 12 */ /* sum members: 68, holes: 1, sum holes: 3 */ /* sum bitfield members: 2 bits, bit holes: 1, sum bit holes: 6 bits */ /* last cacheline: 8 bytes */ }; ``` After: ``` struct map { u64 start; /* 0 8 */ u64 end; /* 8 8 */ u64 pgoff; /* 16 8 */ u64 reloc; /* 24 8 */ struct dso * dso; /* 32 8 */ refcount_t refcnt; /* 40 4 */ u32 prot; /* 44 4 */ u32 flags; /* 48 4 */ enum mapping_type mapping_type:8; /* 52: 0 4 */ /* Bitfield combined with next fields */ _Bool erange_warned; /* 53 1 */ _Bool priv; /* 54 1 */ /* size: 56, cachelines: 1, members: 11 */ /* padding: 1 */ /* last cacheline: 56 bytes */ }; ``` Signed-off-by: Ian Rogers <irogers@google.com> Acked-by: Namhyung Kim <namhyung@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Athira Jajeev <atrajeev@linux.vnet.ibm.com> Cc: Changbin Du <changbin.du@huawei.com> Cc: Colin Ian King <colin.i.king@gmail.com> Cc: Dmitrii Dolgov <9erthalion6@gmail.com> Cc: German Gomez <german.gomez@arm.com> Cc: Guilherme Amadio <amadio@gentoo.org> Cc: Huacai Chen <chenhuacai@kernel.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: James Clark <james.clark@arm.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: K Prateek Nayak <kprateek.nayak@amd.com> Cc: Kajol Jain <kjain@linux.ibm.com> Cc: Kan Liang <kan.liang@linux.intel.com> Cc: Leo Yan <leo.yan@linaro.org> Cc: Li Dong <lidong@vivo.com> Cc: Liam Howlett <liam.howlett@oracle.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Masami Hiramatsu (Google) <mhiramat@kernel.org> Cc: Miguel Ojeda <ojeda@kernel.org> Cc: Ming Wang <wangming01@loongson.cn> Cc: Nick Terrell <terrelln@fb.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ravi Bangoria <ravi.bangoria@amd.com> Cc: Sandipan Das <sandipan.das@amd.com> Cc: Sean Christopherson <seanjc@google.com> Cc: Steinar H. Gunderson <sesse@google.com> Cc: Vincent Whitchurch <vincent.whitchurch@axis.com> Cc: Wenyu Liu <liuwenyu7@huawei.com> Cc: Yang Jihong <yangjihong1@huawei.com> Link: https://lore.kernel.org/r/20231127220902.1315692-13-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
407a3898d7
commit
9fa688ea34
5 changed files with 50 additions and 68 deletions
|
@ -1359,8 +1359,7 @@ __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
|
|||
if (machine->vmlinux_map == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
map__set_map_ip(machine->vmlinux_map, identity__map_ip);
|
||||
map__set_unmap_ip(machine->vmlinux_map, identity__map_ip);
|
||||
map__set_mapping_type(machine->vmlinux_map, MAPPING_TYPE__IDENTITY);
|
||||
return maps__insert(machine__kernel_maps(machine), machine->vmlinux_map);
|
||||
}
|
||||
|
||||
|
|
|
@ -109,8 +109,7 @@ void map__init(struct map *map, u64 start, u64 end, u64 pgoff, struct dso *dso)
|
|||
map__set_pgoff(map, pgoff);
|
||||
map__set_reloc(map, 0);
|
||||
map__set_dso(map, dso__get(dso));
|
||||
map__set_map_ip(map, map__dso_map_ip);
|
||||
map__set_unmap_ip(map, map__dso_unmap_ip);
|
||||
map__set_mapping_type(map, MAPPING_TYPE__DSO);
|
||||
map__set_erange_warned(map, false);
|
||||
refcount_set(map__refcnt(map), 1);
|
||||
}
|
||||
|
@ -172,7 +171,7 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
|
|||
map__init(result, start, start + len, pgoff, dso);
|
||||
|
||||
if (anon || no_dso) {
|
||||
map->map_ip = map->unmap_ip = identity__map_ip;
|
||||
map->mapping_type = MAPPING_TYPE__IDENTITY;
|
||||
|
||||
/*
|
||||
* Set memory without DSO as loaded. All map__find_*
|
||||
|
@ -630,18 +629,3 @@ struct maps *map__kmaps(struct map *map)
|
|||
}
|
||||
return kmap->kmaps;
|
||||
}
|
||||
|
||||
u64 map__dso_map_ip(const struct map *map, u64 ip)
|
||||
{
|
||||
return ip - map__start(map) + map__pgoff(map);
|
||||
}
|
||||
|
||||
u64 map__dso_unmap_ip(const struct map *map, u64 ip)
|
||||
{
|
||||
return ip + map__start(map) - map__pgoff(map);
|
||||
}
|
||||
|
||||
u64 identity__map_ip(const struct map *map __maybe_unused, u64 ip)
|
||||
{
|
||||
return ip;
|
||||
}
|
||||
|
|
|
@ -16,23 +16,25 @@ struct dso;
|
|||
struct maps;
|
||||
struct machine;
|
||||
|
||||
enum mapping_type {
|
||||
/* map__map_ip/map__unmap_ip are given as offsets in the DSO. */
|
||||
MAPPING_TYPE__DSO,
|
||||
/* map__map_ip/map__unmap_ip are just the given ip value. */
|
||||
MAPPING_TYPE__IDENTITY,
|
||||
};
|
||||
|
||||
DECLARE_RC_STRUCT(map) {
|
||||
u64 start;
|
||||
u64 end;
|
||||
bool erange_warned:1;
|
||||
bool priv:1;
|
||||
u32 prot;
|
||||
u64 pgoff;
|
||||
u64 reloc;
|
||||
|
||||
/* ip -> dso rip */
|
||||
u64 (*map_ip)(const struct map *, u64);
|
||||
/* dso rip -> ip */
|
||||
u64 (*unmap_ip)(const struct map *, u64);
|
||||
|
||||
struct dso *dso;
|
||||
refcount_t refcnt;
|
||||
u32 prot;
|
||||
u32 flags;
|
||||
enum mapping_type mapping_type:8;
|
||||
bool erange_warned;
|
||||
bool priv;
|
||||
};
|
||||
|
||||
struct kmap;
|
||||
|
@ -41,38 +43,11 @@ struct kmap *__map__kmap(struct map *map);
|
|||
struct kmap *map__kmap(struct map *map);
|
||||
struct maps *map__kmaps(struct map *map);
|
||||
|
||||
/* ip -> dso rip */
|
||||
u64 map__dso_map_ip(const struct map *map, u64 ip);
|
||||
/* dso rip -> ip */
|
||||
u64 map__dso_unmap_ip(const struct map *map, u64 ip);
|
||||
/* Returns ip */
|
||||
u64 identity__map_ip(const struct map *map __maybe_unused, u64 ip);
|
||||
|
||||
static inline struct dso *map__dso(const struct map *map)
|
||||
{
|
||||
return RC_CHK_ACCESS(map)->dso;
|
||||
}
|
||||
|
||||
static inline u64 map__map_ip(const struct map *map, u64 ip)
|
||||
{
|
||||
return RC_CHK_ACCESS(map)->map_ip(map, ip);
|
||||
}
|
||||
|
||||
static inline u64 map__unmap_ip(const struct map *map, u64 ip)
|
||||
{
|
||||
return RC_CHK_ACCESS(map)->unmap_ip(map, ip);
|
||||
}
|
||||
|
||||
static inline void *map__map_ip_ptr(struct map *map)
|
||||
{
|
||||
return RC_CHK_ACCESS(map)->map_ip;
|
||||
}
|
||||
|
||||
static inline void* map__unmap_ip_ptr(struct map *map)
|
||||
{
|
||||
return RC_CHK_ACCESS(map)->unmap_ip;
|
||||
}
|
||||
|
||||
static inline u64 map__start(const struct map *map)
|
||||
{
|
||||
return RC_CHK_ACCESS(map)->start;
|
||||
|
@ -123,6 +98,34 @@ static inline size_t map__size(const struct map *map)
|
|||
return map__end(map) - map__start(map);
|
||||
}
|
||||
|
||||
/* ip -> dso rip */
|
||||
static inline u64 map__dso_map_ip(const struct map *map, u64 ip)
|
||||
{
|
||||
return ip - map__start(map) + map__pgoff(map);
|
||||
}
|
||||
|
||||
/* dso rip -> ip */
|
||||
static inline u64 map__dso_unmap_ip(const struct map *map, u64 ip)
|
||||
{
|
||||
return ip + map__start(map) - map__pgoff(map);
|
||||
}
|
||||
|
||||
static inline u64 map__map_ip(const struct map *map, u64 ip)
|
||||
{
|
||||
if ((RC_CHK_ACCESS(map)->mapping_type) == MAPPING_TYPE__DSO)
|
||||
return map__dso_map_ip(map, ip);
|
||||
else
|
||||
return ip;
|
||||
}
|
||||
|
||||
static inline u64 map__unmap_ip(const struct map *map, u64 ip)
|
||||
{
|
||||
if ((RC_CHK_ACCESS(map)->mapping_type) == MAPPING_TYPE__DSO)
|
||||
return map__dso_unmap_ip(map, ip);
|
||||
else
|
||||
return ip;
|
||||
}
|
||||
|
||||
/* rip/ip <-> addr suitable for passing to `objdump --start-address=` */
|
||||
u64 map__rip_2objdump(struct map *map, u64 rip);
|
||||
|
||||
|
@ -294,13 +297,13 @@ static inline void map__set_dso(struct map *map, struct dso *dso)
|
|||
RC_CHK_ACCESS(map)->dso = dso;
|
||||
}
|
||||
|
||||
static inline void map__set_map_ip(struct map *map, u64 (*map_ip)(const struct map *map, u64 ip))
|
||||
static inline void map__set_mapping_type(struct map *map, enum mapping_type type)
|
||||
{
|
||||
RC_CHK_ACCESS(map)->map_ip = map_ip;
|
||||
RC_CHK_ACCESS(map)->mapping_type = type;
|
||||
}
|
||||
|
||||
static inline void map__set_unmap_ip(struct map *map, u64 (*unmap_ip)(const struct map *map, u64 rip))
|
||||
static inline enum mapping_type map__mapping_type(struct map *map)
|
||||
{
|
||||
RC_CHK_ACCESS(map)->unmap_ip = unmap_ip;
|
||||
return RC_CHK_ACCESS(map)->mapping_type;
|
||||
}
|
||||
#endif /* __PERF_MAP_H */
|
||||
|
|
|
@ -1392,8 +1392,7 @@ static int dso__process_kernel_symbol(struct dso *dso, struct map *map,
|
|||
map__set_start(map, shdr->sh_addr + ref_reloc(kmap));
|
||||
map__set_end(map, map__start(map) + shdr->sh_size);
|
||||
map__set_pgoff(map, shdr->sh_offset);
|
||||
map__set_map_ip(map, map__dso_map_ip);
|
||||
map__set_unmap_ip(map, map__dso_unmap_ip);
|
||||
map__set_mapping_type(map, MAPPING_TYPE__DSO);
|
||||
/* Ensure maps are correctly ordered */
|
||||
if (kmaps) {
|
||||
int err;
|
||||
|
@ -1455,8 +1454,7 @@ static int dso__process_kernel_symbol(struct dso *dso, struct map *map,
|
|||
map__set_end(curr_map, map__start(curr_map) + shdr->sh_size);
|
||||
map__set_pgoff(curr_map, shdr->sh_offset);
|
||||
} else {
|
||||
map__set_map_ip(curr_map, identity__map_ip);
|
||||
map__set_unmap_ip(curr_map, identity__map_ip);
|
||||
map__set_mapping_type(curr_map, MAPPING_TYPE__IDENTITY);
|
||||
}
|
||||
curr_dso->symtab_type = dso->symtab_type;
|
||||
if (maps__insert(kmaps, curr_map))
|
||||
|
|
|
@ -956,8 +956,7 @@ static int maps__split_kallsyms(struct maps *kmaps, struct dso *dso, u64 delta,
|
|||
return -1;
|
||||
}
|
||||
|
||||
map__set_map_ip(curr_map, identity__map_ip);
|
||||
map__set_unmap_ip(curr_map, identity__map_ip);
|
||||
map__set_mapping_type(curr_map, MAPPING_TYPE__IDENTITY);
|
||||
if (maps__insert(kmaps, curr_map)) {
|
||||
dso__put(ndso);
|
||||
return -1;
|
||||
|
@ -1475,8 +1474,7 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
|
|||
map__set_start(map, map__start(new_map));
|
||||
map__set_end(map, map__end(new_map));
|
||||
map__set_pgoff(map, map__pgoff(new_map));
|
||||
map__set_map_ip(map, map__map_ip_ptr(new_map));
|
||||
map__set_unmap_ip(map, map__unmap_ip_ptr(new_map));
|
||||
map__set_mapping_type(map, map__mapping_type(new_map));
|
||||
/* Ensure maps are correctly ordered */
|
||||
map_ref = map__get(map);
|
||||
maps__remove(kmaps, map_ref);
|
||||
|
|
Loading…
Reference in a new issue