Skip to content

Commit 6855dc4

Browse files
ahunter6acmel
authored andcommitted
x86: Add entry trampolines to kcore
Without program headers for PTI entry trampoline pages, the trampoline virtual addresses do not map to anything. Example before: sudo gdb --quiet vmlinux /proc/kcore Reading symbols from vmlinux...done. [New process 1] Core was generated by `BOOT_IMAGE=/boot/vmlinuz-4.16.0 root=UUID=a6096b83-b763-4101-807e-f33daff63233'. #0 0x0000000000000000 in irq_stack_union () (gdb) x /21ib 0xfffffe0000006000 0xfffffe0000006000: Cannot access memory at address 0xfffffe0000006000 (gdb) quit After: sudo gdb --quiet vmlinux /proc/kcore [sudo] password for ahunter: Reading symbols from vmlinux...done. [New process 1] Core was generated by `BOOT_IMAGE=/boot/vmlinuz-4.16.0-fix-4-00005-gd6e65a8b4072 root=UUID=a6096b83-b7'. #0 0x0000000000000000 in irq_stack_union () (gdb) x /21ib 0xfffffe0000006000 0xfffffe0000006000: swapgs 0xfffffe0000006003: mov %rsp,-0x3e12(%rip) # 0xfffffe00000021f8 0xfffffe000000600a: xchg %ax,%ax 0xfffffe000000600c: mov %cr3,%rsp 0xfffffe000000600f: bts $0x3f,%rsp 0xfffffe0000006014: and $0xffffffffffffe7ff,%rsp 0xfffffe000000601b: mov %rsp,%cr3 0xfffffe000000601e: mov -0x3019(%rip),%rsp # 0xfffffe000000300c 0xfffffe0000006025: pushq $0x2b 0xfffffe0000006027: pushq -0x3e35(%rip) # 0xfffffe00000021f8 0xfffffe000000602d: push %r11 0xfffffe000000602f: pushq $0x33 0xfffffe0000006031: push %rcx 0xfffffe0000006032: push %rdi 0xfffffe0000006033: mov $0xffffffff91a00010,%rdi 0xfffffe000000603a: callq 0xfffffe0000006046 0xfffffe000000603f: pause 0xfffffe0000006041: lfence 0xfffffe0000006044: jmp 0xfffffe000000603f 0xfffffe0000006046: mov %rdi,(%rsp) 0xfffffe000000604a: retq (gdb) quit In addition, 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). Notes by PeterZ: This also adds the KCORE_REMAP functionality. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Acked-by: Andi Kleen <ak@linux.intel.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Andy Lutomirski <luto@kernel.org> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Joerg Roedel <joro@8bytes.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: x86@kernel.org Link: http://lkml.kernel.org/r/1528289651-4113-4-git-send-email-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
1 parent d83212d commit 6855dc4

File tree

3 files changed

+28
-2
lines changed

3 files changed

+28
-2
lines changed

arch/x86/mm/cpu_entry_area.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <linux/spinlock.h>
44
#include <linux/percpu.h>
55
#include <linux/kallsyms.h>
6+
#include <linux/kcore.h>
67

78
#include <asm/cpu_entry_area.h>
89
#include <asm/pgtable.h>
@@ -14,6 +15,7 @@ static DEFINE_PER_CPU_PAGE_ALIGNED(struct entry_stack_page, entry_stack_storage)
1415
#ifdef CONFIG_X86_64
1516
static DEFINE_PER_CPU_PAGE_ALIGNED(char, exception_stacks
1617
[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ]);
18+
static DEFINE_PER_CPU(struct kcore_list, kcore_entry_trampoline);
1719
#endif
1820

1921
struct cpu_entry_area *get_cpu_entry_area(int cpu)
@@ -147,6 +149,14 @@ static void __init setup_cpu_entry_area(int cpu)
147149

148150
cea_set_pte(&get_cpu_entry_area(cpu)->entry_trampoline,
149151
__pa_symbol(_entry_trampoline), PAGE_KERNEL_RX);
152+
/*
153+
* The cpu_entry_area alias addresses are not in the kernel binary
154+
* so they do not show up in /proc/kcore normally. This adds entries
155+
* for them manually.
156+
*/
157+
kclist_add_remap(&per_cpu(kcore_entry_trampoline, cpu),
158+
_entry_trampoline,
159+
&get_cpu_entry_area(cpu)->entry_trampoline, PAGE_SIZE);
150160
#endif
151161
percpu_setup_debug_store(cpu);
152162
}

fs/proc/kcore.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,8 +383,11 @@ static void elf_kcore_store_hdr(char *bufp, int nphdr, int dataoff)
383383
phdr->p_type = PT_LOAD;
384384
phdr->p_flags = PF_R|PF_W|PF_X;
385385
phdr->p_offset = kc_vaddr_to_offset(m->addr) + dataoff;
386-
phdr->p_vaddr = (size_t)m->addr;
387-
if (m->type == KCORE_RAM || m->type == KCORE_TEXT)
386+
if (m->type == KCORE_REMAP)
387+
phdr->p_vaddr = (size_t)m->vaddr;
388+
else
389+
phdr->p_vaddr = (size_t)m->addr;
390+
if (m->type == KCORE_RAM || m->type == KCORE_TEXT || m->type == KCORE_REMAP)
388391
phdr->p_paddr = __pa(m->addr);
389392
else
390393
phdr->p_paddr = (elf_addr_t)-1;

include/linux/kcore.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ enum kcore_type {
1212
KCORE_VMEMMAP,
1313
KCORE_USER,
1414
KCORE_OTHER,
15+
KCORE_REMAP,
1516
};
1617

1718
struct kcore_list {
1819
struct list_head list;
1920
unsigned long addr;
21+
unsigned long vaddr;
2022
size_t size;
2123
int type;
2224
};
@@ -36,11 +38,22 @@ struct vmcoredd_node {
3638

3739
#ifdef CONFIG_PROC_KCORE
3840
extern void kclist_add(struct kcore_list *, void *, size_t, int type);
41+
static inline
42+
void kclist_add_remap(struct kcore_list *m, void *addr, void *vaddr, size_t sz)
43+
{
44+
m->vaddr = (unsigned long)vaddr;
45+
kclist_add(m, addr, sz, KCORE_REMAP);
46+
}
3947
#else
4048
static inline
4149
void kclist_add(struct kcore_list *new, void *addr, size_t size, int type)
4250
{
4351
}
52+
53+
static inline
54+
void kclist_add_remap(struct kcore_list *m, void *addr, void *vaddr, size_t sz)
55+
{
56+
}
4457
#endif
4558

4659
#endif /* _LINUX_KCORE_H */

0 commit comments

Comments
 (0)