Re: [patch 43/60] x86/fixmap: Add debugstore entries to cpu_entry_area

2017-12-07 Thread Borislav Petkov
On Mon, Dec 04, 2017 at 03:07:49PM +0100, Thomas Gleixner wrote:
> From: Thomas Gleixner 
> 
> The intel PEBS/BTS debug store is a design trainwreck as is expects virtual
> addresses which must be visible in any execution context.

Sure, what can possibly go wrong?! :-\

> 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 fixmap.
> 
> At the point where the kernel side fixmap is populated there is no buffer
> available yet, but the kernel PMD must be populated. To achieve this set
> the fixmap entries for these buffers to non present.
> 
> Signed-off-by: Thomas Gleixner 
> ---
>  arch/x86/events/intel/ds.c  |5 +++--
>  arch/x86/events/perf_event.h|   21 ++---
>  arch/x86/include/asm/fixmap.h   |   13 +
>  arch/x86/include/asm/intel_ds.h |   36 
>  arch/x86/kernel/cpu/common.c|   21 +
>  5 files changed, 75 insertions(+), 21 deletions(-)

...

> @@ -592,6 +603,16 @@ static void __init setup_cpu_entry_area(
>   __set_fixmap(get_cpu_entry_area_index(cpu, entry_trampoline),
>__pa_symbol(_entry_trampoline), PAGE_KERNEL_RX);
>  #endif
> +
> +#ifdef CONFIG_CPU_SUP_INTEL
> + BUILD_BUG_ON(sizeof(struct debug_store) % PAGE_SIZE != 0);
> + set_percpu_fixmap_pages(get_cpu_entry_area_index(cpu, cpu_debug_store),
> + _cpu(cpu_debug_store, cpu),
> + sizeof(struct debug_store) / PAGE_SIZE,
> + PAGE_KERNEL);
> + set_percpu_fixmap_ptes(get_cpu_entry_area_index(cpu, cpu_debug_buffers),
> +sizeof(struct debug_store_buffers) / PAGE_SIZE);
> +#endif

I guess we can do that additionally, so as not to setup the mappings on
distro kernels running !INTEL:

---
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 1364a8f378f8..5cfb68090a24 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -606,12 +606,16 @@ static void __init setup_cpu_entry_area(int cpu)
 
 #ifdef CONFIG_CPU_SUP_INTEL
BUILD_BUG_ON(sizeof(struct debug_store) % PAGE_SIZE != 0);
-   set_percpu_fixmap_pages(get_cpu_entry_area_index(cpu, cpu_debug_store),
-   _cpu(cpu_debug_store, cpu),
-   sizeof(struct debug_store) / PAGE_SIZE,
-   PAGE_KERNEL);
-   set_percpu_fixmap_ptes(get_cpu_entry_area_index(cpu, cpu_debug_buffers),
-  sizeof(struct debug_store_buffers) / PAGE_SIZE);
+
+   if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
+   set_percpu_fixmap_pages(get_cpu_entry_area_index(cpu, 
cpu_debug_store),
+   _cpu(cpu_debug_store, cpu),
+   sizeof(struct debug_store) / PAGE_SIZE,
+   PAGE_KERNEL);
+
+   set_percpu_fixmap_ptes(get_cpu_entry_area_index(cpu, 
cpu_debug_buffers),
+  sizeof(struct debug_store_buffers) / 
PAGE_SIZE);
+   }
 #endif
 }

-- 
Regards/Gruss,
Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 
(AG Nürnberg)
-- 


Re: [patch 43/60] x86/fixmap: Add debugstore entries to cpu_entry_area

2017-12-07 Thread Borislav Petkov
On Mon, Dec 04, 2017 at 03:07:49PM +0100, Thomas Gleixner wrote:
> From: Thomas Gleixner 
> 
> The intel PEBS/BTS debug store is a design trainwreck as is expects virtual
> addresses which must be visible in any execution context.

Sure, what can possibly go wrong?! :-\

> 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 fixmap.
> 
> At the point where the kernel side fixmap is populated there is no buffer
> available yet, but the kernel PMD must be populated. To achieve this set
> the fixmap entries for these buffers to non present.
> 
> Signed-off-by: Thomas Gleixner 
> ---
>  arch/x86/events/intel/ds.c  |5 +++--
>  arch/x86/events/perf_event.h|   21 ++---
>  arch/x86/include/asm/fixmap.h   |   13 +
>  arch/x86/include/asm/intel_ds.h |   36 
>  arch/x86/kernel/cpu/common.c|   21 +
>  5 files changed, 75 insertions(+), 21 deletions(-)

...

> @@ -592,6 +603,16 @@ static void __init setup_cpu_entry_area(
>   __set_fixmap(get_cpu_entry_area_index(cpu, entry_trampoline),
>__pa_symbol(_entry_trampoline), PAGE_KERNEL_RX);
>  #endif
> +
> +#ifdef CONFIG_CPU_SUP_INTEL
> + BUILD_BUG_ON(sizeof(struct debug_store) % PAGE_SIZE != 0);
> + set_percpu_fixmap_pages(get_cpu_entry_area_index(cpu, cpu_debug_store),
> + _cpu(cpu_debug_store, cpu),
> + sizeof(struct debug_store) / PAGE_SIZE,
> + PAGE_KERNEL);
> + set_percpu_fixmap_ptes(get_cpu_entry_area_index(cpu, cpu_debug_buffers),
> +sizeof(struct debug_store_buffers) / PAGE_SIZE);
> +#endif

I guess we can do that additionally, so as not to setup the mappings on
distro kernels running !INTEL:

---
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 1364a8f378f8..5cfb68090a24 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -606,12 +606,16 @@ static void __init setup_cpu_entry_area(int cpu)
 
 #ifdef CONFIG_CPU_SUP_INTEL
BUILD_BUG_ON(sizeof(struct debug_store) % PAGE_SIZE != 0);
-   set_percpu_fixmap_pages(get_cpu_entry_area_index(cpu, cpu_debug_store),
-   _cpu(cpu_debug_store, cpu),
-   sizeof(struct debug_store) / PAGE_SIZE,
-   PAGE_KERNEL);
-   set_percpu_fixmap_ptes(get_cpu_entry_area_index(cpu, cpu_debug_buffers),
-  sizeof(struct debug_store_buffers) / PAGE_SIZE);
+
+   if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) {
+   set_percpu_fixmap_pages(get_cpu_entry_area_index(cpu, 
cpu_debug_store),
+   _cpu(cpu_debug_store, cpu),
+   sizeof(struct debug_store) / PAGE_SIZE,
+   PAGE_KERNEL);
+
+   set_percpu_fixmap_ptes(get_cpu_entry_area_index(cpu, 
cpu_debug_buffers),
+  sizeof(struct debug_store_buffers) / 
PAGE_SIZE);
+   }
 #endif
 }

-- 
Regards/Gruss,
Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 
(AG Nürnberg)
-- 


[patch 43/60] x86/fixmap: Add debugstore entries to cpu_entry_area

2017-12-04 Thread Thomas Gleixner
From: Thomas Gleixner 

The intel PEBS/BTS debug store is a design trainwreck as is 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 fixmap.

At the point where the kernel side fixmap is populated there is no buffer
available yet, but the kernel PMD must be populated. To achieve this set
the fixmap entries for these buffers to non present.

Signed-off-by: Thomas Gleixner 
---
 arch/x86/events/intel/ds.c  |5 +++--
 arch/x86/events/perf_event.h|   21 ++---
 arch/x86/include/asm/fixmap.h   |   13 +
 arch/x86/include/asm/intel_ds.h |   36 
 arch/x86/kernel/cpu/common.c|   21 +
 5 files changed, 75 insertions(+), 21 deletions(-)

--- a/arch/x86/events/intel/ds.c
+++ b/arch/x86/events/intel/ds.c
@@ -8,11 +8,12 @@
 
 #include "../perf_event.h"
 
+/* Waste a full page so it can be mapped into the cpu_entry_area */
+DEFINE_PER_CPU_PAGE_ALIGNED(struct debug_store, cpu_debug_store);
+
 /* The size of a BTS record in bytes: */
 #define BTS_RECORD_SIZE24
 
-#define BTS_BUFFER_SIZE(PAGE_SIZE << 4)
-#define PEBS_BUFFER_SIZE   (PAGE_SIZE << 4)
 #define PEBS_FIXUP_SIZEPAGE_SIZE
 
 /*
--- a/arch/x86/events/perf_event.h
+++ b/arch/x86/events/perf_event.h
@@ -14,6 +14,8 @@
 
 #include 
 
+#include 
+
 /* To enable MSR tracing please use the generic trace points. */
 
 /*
@@ -77,8 +79,6 @@ struct amd_nb {
struct event_constraint event_constraints[X86_PMC_IDX_MAX];
 };
 
-/* The maximal number of PEBS events: */
-#define MAX_PEBS_EVENTS8
 #define PEBS_COUNTER_MASK  ((1ULL << MAX_PEBS_EVENTS) - 1)
 
 /*
@@ -95,23 +95,6 @@ struct amd_nb {
PERF_SAMPLE_TRANSACTION | PERF_SAMPLE_PHYS_ADDR | \
PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER)
 
-/*
- * A debug store configuration.
- *
- * We only support architectures that use 64bit fields.
- */
-struct debug_store {
-   u64 bts_buffer_base;
-   u64 bts_index;
-   u64 bts_absolute_maximum;
-   u64 bts_interrupt_threshold;
-   u64 pebs_buffer_base;
-   u64 pebs_index;
-   u64 pebs_absolute_maximum;
-   u64 pebs_interrupt_threshold;
-   u64 pebs_event_reset[MAX_PEBS_EVENTS];
-};
-
 #define PEBS_REGS \
(PERF_REG_X86_AX | \
 PERF_REG_X86_BX | \
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #ifdef CONFIG_X86_32
 #include 
 #include 
@@ -78,6 +79,18 @@ struct cpu_entry_area {
 */
char exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + 
DEBUG_STKSZ];
 #endif
+#ifdef CONFIG_CPU_SUP_INTEL
+   /*
+* Per CPU debug store for Intel performance monitoring. Wastes a
+* full page at the moment.
+*/
+   struct debug_store cpu_debug_store;
+   /*
+* The actual PEBS/BTS buffers must be mapped to user space
+* Reserve enough fixmap PTEs.
+*/
+   struct debug_store_buffers cpu_debug_buffers;
+#endif
 };
 
 #define CPU_ENTRY_AREA_PAGES (sizeof(struct cpu_entry_area) / PAGE_SIZE)
--- /dev/null
+++ b/arch/x86/include/asm/intel_ds.h
@@ -0,0 +1,36 @@
+#ifndef _ASM_INTEL_DS_H
+#define _ASM_INTEL_DS_H
+
+#include 
+
+#define BTS_BUFFER_SIZE(PAGE_SIZE << 4)
+#define PEBS_BUFFER_SIZE   (PAGE_SIZE << 4)
+
+/* The maximal number of PEBS events: */
+#define MAX_PEBS_EVENTS8
+
+/*
+ * A debug store configuration.
+ *
+ * We only support architectures that use 64bit fields.
+ */
+struct debug_store {
+   u64 bts_buffer_base;
+   u64 bts_index;
+   u64 bts_absolute_maximum;
+   u64 bts_interrupt_threshold;
+   u64 pebs_buffer_base;
+   u64 pebs_index;
+   u64 pebs_absolute_maximum;
+   u64 pebs_interrupt_threshold;
+   u64 pebs_event_reset[MAX_PEBS_EVENTS];
+} __aligned(PAGE_SIZE);
+
+DECLARE_PER_CPU_PAGE_ALIGNED(struct debug_store, cpu_debug_store);
+
+struct debug_store_buffers {
+   charbts_buffer[BTS_BUFFER_SIZE];
+   charpebs_buffer[PEBS_BUFFER_SIZE];
+};
+
+#endif
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -514,6 +515,16 @@ static DEFINE_PER_CPU_PAGE_ALIGNED(char,
 static DEFINE_PER_CPU_PAGE_ALIGNED(struct SYSENTER_stack_page,
   SYSENTER_stack_storage);
 
+/*
+ * Force the population of PMDs for not yet allocated per cpu
+ * memory like debug store buffers.
+ */
+static void __init 

[patch 43/60] x86/fixmap: Add debugstore entries to cpu_entry_area

2017-12-04 Thread Thomas Gleixner
From: Thomas Gleixner 

The intel PEBS/BTS debug store is a design trainwreck as is 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 fixmap.

At the point where the kernel side fixmap is populated there is no buffer
available yet, but the kernel PMD must be populated. To achieve this set
the fixmap entries for these buffers to non present.

Signed-off-by: Thomas Gleixner 
---
 arch/x86/events/intel/ds.c  |5 +++--
 arch/x86/events/perf_event.h|   21 ++---
 arch/x86/include/asm/fixmap.h   |   13 +
 arch/x86/include/asm/intel_ds.h |   36 
 arch/x86/kernel/cpu/common.c|   21 +
 5 files changed, 75 insertions(+), 21 deletions(-)

--- a/arch/x86/events/intel/ds.c
+++ b/arch/x86/events/intel/ds.c
@@ -8,11 +8,12 @@
 
 #include "../perf_event.h"
 
+/* Waste a full page so it can be mapped into the cpu_entry_area */
+DEFINE_PER_CPU_PAGE_ALIGNED(struct debug_store, cpu_debug_store);
+
 /* The size of a BTS record in bytes: */
 #define BTS_RECORD_SIZE24
 
-#define BTS_BUFFER_SIZE(PAGE_SIZE << 4)
-#define PEBS_BUFFER_SIZE   (PAGE_SIZE << 4)
 #define PEBS_FIXUP_SIZEPAGE_SIZE
 
 /*
--- a/arch/x86/events/perf_event.h
+++ b/arch/x86/events/perf_event.h
@@ -14,6 +14,8 @@
 
 #include 
 
+#include 
+
 /* To enable MSR tracing please use the generic trace points. */
 
 /*
@@ -77,8 +79,6 @@ struct amd_nb {
struct event_constraint event_constraints[X86_PMC_IDX_MAX];
 };
 
-/* The maximal number of PEBS events: */
-#define MAX_PEBS_EVENTS8
 #define PEBS_COUNTER_MASK  ((1ULL << MAX_PEBS_EVENTS) - 1)
 
 /*
@@ -95,23 +95,6 @@ struct amd_nb {
PERF_SAMPLE_TRANSACTION | PERF_SAMPLE_PHYS_ADDR | \
PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER)
 
-/*
- * A debug store configuration.
- *
- * We only support architectures that use 64bit fields.
- */
-struct debug_store {
-   u64 bts_buffer_base;
-   u64 bts_index;
-   u64 bts_absolute_maximum;
-   u64 bts_interrupt_threshold;
-   u64 pebs_buffer_base;
-   u64 pebs_index;
-   u64 pebs_absolute_maximum;
-   u64 pebs_interrupt_threshold;
-   u64 pebs_event_reset[MAX_PEBS_EVENTS];
-};
-
 #define PEBS_REGS \
(PERF_REG_X86_AX | \
 PERF_REG_X86_BX | \
--- a/arch/x86/include/asm/fixmap.h
+++ b/arch/x86/include/asm/fixmap.h
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #ifdef CONFIG_X86_32
 #include 
 #include 
@@ -78,6 +79,18 @@ struct cpu_entry_area {
 */
char exception_stacks[(N_EXCEPTION_STACKS - 1) * EXCEPTION_STKSZ + 
DEBUG_STKSZ];
 #endif
+#ifdef CONFIG_CPU_SUP_INTEL
+   /*
+* Per CPU debug store for Intel performance monitoring. Wastes a
+* full page at the moment.
+*/
+   struct debug_store cpu_debug_store;
+   /*
+* The actual PEBS/BTS buffers must be mapped to user space
+* Reserve enough fixmap PTEs.
+*/
+   struct debug_store_buffers cpu_debug_buffers;
+#endif
 };
 
 #define CPU_ENTRY_AREA_PAGES (sizeof(struct cpu_entry_area) / PAGE_SIZE)
--- /dev/null
+++ b/arch/x86/include/asm/intel_ds.h
@@ -0,0 +1,36 @@
+#ifndef _ASM_INTEL_DS_H
+#define _ASM_INTEL_DS_H
+
+#include 
+
+#define BTS_BUFFER_SIZE(PAGE_SIZE << 4)
+#define PEBS_BUFFER_SIZE   (PAGE_SIZE << 4)
+
+/* The maximal number of PEBS events: */
+#define MAX_PEBS_EVENTS8
+
+/*
+ * A debug store configuration.
+ *
+ * We only support architectures that use 64bit fields.
+ */
+struct debug_store {
+   u64 bts_buffer_base;
+   u64 bts_index;
+   u64 bts_absolute_maximum;
+   u64 bts_interrupt_threshold;
+   u64 pebs_buffer_base;
+   u64 pebs_index;
+   u64 pebs_absolute_maximum;
+   u64 pebs_interrupt_threshold;
+   u64 pebs_event_reset[MAX_PEBS_EVENTS];
+} __aligned(PAGE_SIZE);
+
+DECLARE_PER_CPU_PAGE_ALIGNED(struct debug_store, cpu_debug_store);
+
+struct debug_store_buffers {
+   charbts_buffer[BTS_BUFFER_SIZE];
+   charpebs_buffer[PEBS_BUFFER_SIZE];
+};
+
+#endif
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -514,6 +515,16 @@ static DEFINE_PER_CPU_PAGE_ALIGNED(char,
 static DEFINE_PER_CPU_PAGE_ALIGNED(struct SYSENTER_stack_page,
   SYSENTER_stack_storage);
 
+/*
+ * Force the population of PMDs for not yet allocated per cpu
+ * memory like debug store buffers.
+ */
+static void __init set_percpu_fixmap_ptes(int idx, int pages)
+{
+