Skip to content

Commit 10043e0

Browse files
KAGA-KOKOIngo Molnar
authored andcommitted
x86/cpu_entry_area: Add debugstore entries to cpu_entry_area
The Intel PEBS/BTS debug store is a design trainwreck as it expects virtual addresses which must be visible in any execution context. So it is required to make these mappings visible to user space when kernel page table isolation is active. Provide enough room for the buffer mappings in the cpu_entry_area so the buffers are available in the user space visible page tables. At the point where the kernel side entry area is populated there is no buffer available yet, but the kernel PMD must be populated. To achieve this set the entries for these buffers to non present. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: Andy Lutomirski <luto@kernel.org> Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: David Laight <David.Laight@aculab.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: Eduardo Valentin <eduval@amazon.com> Cc: Greg KH <gregkh@linuxfoundation.org> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Juergen Gross <jgross@suse.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Will Deacon <will.deacon@arm.com> Cc: aliguori@amazon.com Cc: daniel.gruss@iaik.tugraz.at Cc: hughd@google.com Cc: keescook@google.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent 4b6bbe9 commit 10043e0

File tree

5 files changed

+81
-21
lines changed

5 files changed

+81
-21
lines changed

arch/x86/events/intel/ds.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88

99
#include "../perf_event.h"
1010

11+
/* Waste a full page so it can be mapped into the cpu_entry_area */
12+
DEFINE_PER_CPU_PAGE_ALIGNED(struct debug_store, cpu_debug_store);
13+
1114
/* The size of a BTS record in bytes: */
1215
#define BTS_RECORD_SIZE 24
1316

14-
#define BTS_BUFFER_SIZE (PAGE_SIZE << 4)
15-
#define PEBS_BUFFER_SIZE (PAGE_SIZE << 4)
1617
#define PEBS_FIXUP_SIZE PAGE_SIZE
1718

1819
/*

arch/x86/events/perf_event.h

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
#include <linux/perf_event.h>
1616

17+
#include <asm/intel_ds.h>
18+
1719
/* To enable MSR tracing please use the generic trace points. */
1820

1921
/*
@@ -77,8 +79,6 @@ struct amd_nb {
7779
struct event_constraint event_constraints[X86_PMC_IDX_MAX];
7880
};
7981

80-
/* The maximal number of PEBS events: */
81-
#define MAX_PEBS_EVENTS 8
8282
#define PEBS_COUNTER_MASK ((1ULL << MAX_PEBS_EVENTS) - 1)
8383

8484
/*
@@ -95,23 +95,6 @@ struct amd_nb {
9595
PERF_SAMPLE_TRANSACTION | PERF_SAMPLE_PHYS_ADDR | \
9696
PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER)
9797

98-
/*
99-
* A debug store configuration.
100-
*
101-
* We only support architectures that use 64bit fields.
102-
*/
103-
struct debug_store {
104-
u64 bts_buffer_base;
105-
u64 bts_index;
106-
u64 bts_absolute_maximum;
107-
u64 bts_interrupt_threshold;
108-
u64 pebs_buffer_base;
109-
u64 pebs_index;
110-
u64 pebs_absolute_maximum;
111-
u64 pebs_interrupt_threshold;
112-
u64 pebs_event_reset[MAX_PEBS_EVENTS];
113-
};
114-
11598
#define PEBS_REGS \
11699
(PERF_REG_X86_AX | \
117100
PERF_REG_X86_BX | \

arch/x86/include/asm/cpu_entry_area.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include <linux/percpu-defs.h>
77
#include <asm/processor.h>
8+
#include <asm/intel_ds.h>
89

910
/*
1011
* cpu_entry_area is a percpu region that contains things needed by the CPU
@@ -40,6 +41,18 @@ struct cpu_entry_area {
4041
*/
4142
char exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + DEBUG_STKSZ];
4243
#endif
44+
#ifdef CONFIG_CPU_SUP_INTEL
45+
/*
46+
* Per CPU debug store for Intel performance monitoring. Wastes a
47+
* full page at the moment.
48+
*/
49+
struct debug_store cpu_debug_store;
50+
/*
51+
* The actual PEBS/BTS buffers must be mapped to user space
52+
* Reserve enough fixmap PTEs.
53+
*/
54+
struct debug_store_buffers cpu_debug_buffers;
55+
#endif
4356
};
4457

4558
#define CPU_ENTRY_AREA_SIZE (sizeof(struct cpu_entry_area))

arch/x86/include/asm/intel_ds.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#ifndef _ASM_INTEL_DS_H
2+
#define _ASM_INTEL_DS_H
3+
4+
#include <linux/percpu-defs.h>
5+
6+
#define BTS_BUFFER_SIZE (PAGE_SIZE << 4)
7+
#define PEBS_BUFFER_SIZE (PAGE_SIZE << 4)
8+
9+
/* The maximal number of PEBS events: */
10+
#define MAX_PEBS_EVENTS 8
11+
12+
/*
13+
* A debug store configuration.
14+
*
15+
* We only support architectures that use 64bit fields.
16+
*/
17+
struct debug_store {
18+
u64 bts_buffer_base;
19+
u64 bts_index;
20+
u64 bts_absolute_maximum;
21+
u64 bts_interrupt_threshold;
22+
u64 pebs_buffer_base;
23+
u64 pebs_index;
24+
u64 pebs_absolute_maximum;
25+
u64 pebs_interrupt_threshold;
26+
u64 pebs_event_reset[MAX_PEBS_EVENTS];
27+
} __aligned(PAGE_SIZE);
28+
29+
DECLARE_PER_CPU_PAGE_ALIGNED(struct debug_store, cpu_debug_store);
30+
31+
struct debug_store_buffers {
32+
char bts_buffer[BTS_BUFFER_SIZE];
33+
char pebs_buffer[PEBS_BUFFER_SIZE];
34+
};
35+
36+
#endif

arch/x86/mm/cpu_entry_area.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,32 @@ cea_map_percpu_pages(void *cea_vaddr, void *ptr, int pages, pgprot_t prot)
3838
cea_set_pte(cea_vaddr, per_cpu_ptr_to_phys(ptr), prot);
3939
}
4040

41+
static void percpu_setup_debug_store(int cpu)
42+
{
43+
#ifdef CONFIG_CPU_SUP_INTEL
44+
int npages;
45+
void *cea;
46+
47+
if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
48+
return;
49+
50+
cea = &get_cpu_entry_area(cpu)->cpu_debug_store;
51+
npages = sizeof(struct debug_store) / PAGE_SIZE;
52+
BUILD_BUG_ON(sizeof(struct debug_store) % PAGE_SIZE != 0);
53+
cea_map_percpu_pages(cea, &per_cpu(cpu_debug_store, cpu), npages,
54+
PAGE_KERNEL);
55+
56+
cea = &get_cpu_entry_area(cpu)->cpu_debug_buffers;
57+
/*
58+
* Force the population of PMDs for not yet allocated per cpu
59+
* memory like debug store buffers.
60+
*/
61+
npages = sizeof(struct debug_store_buffers) / PAGE_SIZE;
62+
for (; npages; npages--, cea += PAGE_SIZE)
63+
cea_set_pte(cea, 0, PAGE_NONE);
64+
#endif
65+
}
66+
4167
/* Setup the fixmap mappings only once per-processor */
4268
static void __init setup_cpu_entry_area(int cpu)
4369
{
@@ -109,6 +135,7 @@ static void __init setup_cpu_entry_area(int cpu)
109135
cea_set_pte(&get_cpu_entry_area(cpu)->entry_trampoline,
110136
__pa_symbol(_entry_trampoline), PAGE_KERNEL_RX);
111137
#endif
138+
percpu_setup_debug_store(cpu);
112139
}
113140

114141
static __init void setup_cpu_entry_area_ptes(void)

0 commit comments

Comments
 (0)