[PATCH RFC 04/19] x86: kcore: Give entry trampolines all the same offset in kcore

From: Adrian Hunter
Date: Wed May 09 2018 - 07:45:26 EST


Entry trampolines all map to the same page. Represent that by giving the
corresponding program headers in kcore the same offset.

This has the benefit that, when perf tools uses /proc/kcore as a source for
kernel object code, samples from different CPU trampolines are aggregated
together. Note, such aggregation is normal for profiling i.e. people want
to profile the object code, not every different virtual address the object
code might be mapped to (across different processes for example).

Signed-off-by: Adrian Hunter <adrian.hunter@xxxxxxxxx>
---
arch/x86/mm/cpu_entry_area.c | 6 +++---
fs/proc/kcore.c | 7 +++++--
include/linux/kcore.h | 13 +++++++++++++
3 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/arch/x86/mm/cpu_entry_area.c b/arch/x86/mm/cpu_entry_area.c
index fb1fbc8538fa..faea80e9bbd2 100644
--- a/arch/x86/mm/cpu_entry_area.c
+++ b/arch/x86/mm/cpu_entry_area.c
@@ -149,9 +149,9 @@ static void __init setup_cpu_entry_area(int cpu)

cea_set_pte(&get_cpu_entry_area(cpu)->entry_trampoline,
__pa_symbol(_entry_trampoline), PAGE_KERNEL_RX);
- kclist_add(&per_cpu(kcore_entry_trampoline, cpu),
- &get_cpu_entry_area(cpu)->entry_trampoline, PAGE_SIZE,
- KCORE_TEXT);
+ kclist_add_remap(&per_cpu(kcore_entry_trampoline, cpu),
+ _entry_trampoline,
+ &get_cpu_entry_area(cpu)->entry_trampoline, PAGE_SIZE);
#endif
percpu_setup_debug_store(cpu);
}
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index d1e82761de81..b5e02b0379ca 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -374,8 +374,11 @@ static void elf_kcore_store_hdr(char *bufp, int nphdr, int dataoff)
phdr->p_type = PT_LOAD;
phdr->p_flags = PF_R|PF_W|PF_X;
phdr->p_offset = kc_vaddr_to_offset(m->addr) + dataoff;
- phdr->p_vaddr = (size_t)m->addr;
- if (m->type == KCORE_RAM || m->type == KCORE_TEXT)
+ if (m->type == KCORE_REMAP)
+ phdr->p_vaddr = (size_t)m->vaddr;
+ else
+ phdr->p_vaddr = (size_t)m->addr;
+ if (m->type == KCORE_RAM || m->type == KCORE_TEXT || m->type == KCORE_REMAP)
phdr->p_paddr = __pa(m->addr);
else
phdr->p_paddr = (elf_addr_t)-1;
diff --git a/include/linux/kcore.h b/include/linux/kcore.h
index 80db19d3a505..3a11ce51e137 100644
--- a/include/linux/kcore.h
+++ b/include/linux/kcore.h
@@ -12,11 +12,13 @@ enum kcore_type {
KCORE_VMEMMAP,
KCORE_USER,
KCORE_OTHER,
+ KCORE_REMAP,
};

struct kcore_list {
struct list_head list;
unsigned long addr;
+ unsigned long vaddr;
size_t size;
int type;
};
@@ -30,11 +32,22 @@ struct vmcore {

#ifdef CONFIG_PROC_KCORE
extern void kclist_add(struct kcore_list *, void *, size_t, int type);
+static inline
+void kclist_add_remap(struct kcore_list *m, void *addr, void *vaddr, size_t sz)
+{
+ m->vaddr = (unsigned long)vaddr;
+ kclist_add(m, addr, sz, KCORE_REMAP);
+}
#else
static inline
void kclist_add(struct kcore_list *new, void *addr, size_t size, int type)
{
}
+
+static inline
+void kclist_add_remap(struct kcore_list *m, void *addr, void *vaddr, size_t sz)
+{
+}
#endif

#endif /* _LINUX_KCORE_H */
--
1.9.1