]>
Commit | Line | Data |
---|---|---|
59d5af67 | 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
e4cdf2a5 FG |
2 | From: Peter Zijlstra <peterz@infradead.org> |
3 | Date: Thu, 4 Jan 2018 18:07:12 +0100 | |
59d5af67 FG |
4 | Subject: [PATCH] x86/events/intel/ds: Use the proper cache flush method for |
5 | mapping ds buffers | |
e4cdf2a5 FG |
6 | MIME-Version: 1.0 |
7 | Content-Type: text/plain; charset=UTF-8 | |
8 | Content-Transfer-Encoding: 8bit | |
9 | ||
10 | commit 42f3bdc5dd962a5958bc024c1e1444248a6b8b4a upstream. | |
11 | ||
12 | Thomas reported the following warning: | |
13 | ||
14 | BUG: using smp_processor_id() in preemptible [00000000] code: ovsdb-server/4498 | |
15 | caller is native_flush_tlb_single+0x57/0xc0 | |
16 | native_flush_tlb_single+0x57/0xc0 | |
17 | __set_pte_vaddr+0x2d/0x40 | |
18 | set_pte_vaddr+0x2f/0x40 | |
19 | cea_set_pte+0x30/0x40 | |
20 | ds_update_cea.constprop.4+0x4d/0x70 | |
21 | reserve_ds_buffers+0x159/0x410 | |
22 | x86_reserve_hardware+0x150/0x160 | |
23 | x86_pmu_event_init+0x3e/0x1f0 | |
24 | perf_try_init_event+0x69/0x80 | |
25 | perf_event_alloc+0x652/0x740 | |
26 | SyS_perf_event_open+0x3f6/0xd60 | |
27 | do_syscall_64+0x5c/0x190 | |
28 | ||
29 | set_pte_vaddr is used to map the ds buffers into the cpu entry area, but | |
30 | there are two problems with that: | |
31 | ||
32 | 1) The resulting flush is not supposed to be called in preemptible context | |
33 | ||
34 | 2) The cpu entry area is supposed to be per CPU, but the debug store | |
35 | buffers are mapped for all CPUs so these mappings need to be flushed | |
36 | globally. | |
37 | ||
38 | Add the necessary preemption protection across the mapping code and flush | |
39 | TLBs globally. | |
40 | ||
41 | Fixes: c1961a4631da ("x86/events/intel/ds: Map debug buffers in cpu_entry_area") | |
42 | Reported-by: Thomas Zeitlhofer <thomas.zeitlhofer+lkml@ze-it.at> | |
43 | Signed-off-by: Peter Zijlstra <peterz@infradead.org> | |
44 | Signed-off-by: Thomas Gleixner <tglx@linutronix.de> | |
45 | Tested-by: Thomas Zeitlhofer <thomas.zeitlhofer+lkml@ze-it.at> | |
46 | Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
47 | Cc: Hugh Dickins <hughd@google.com> | |
48 | Link: https://lkml.kernel.org/r/20180104170712.GB3040@hirez.programming.kicks-ass.net | |
49 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
50 | Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com> | |
51 | --- | |
52 | arch/x86/events/intel/ds.c | 16 ++++++++++++++++ | |
53 | 1 file changed, 16 insertions(+) | |
54 | ||
55 | diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c | |
56 | index 85df1f12c49e..1d236666ee0e 100644 | |
57 | --- a/arch/x86/events/intel/ds.c | |
58 | +++ b/arch/x86/events/intel/ds.c | |
59 | @@ -4,6 +4,7 @@ | |
60 | ||
61 | #include <asm/cpu_entry_area.h> | |
62 | #include <asm/perf_event.h> | |
63 | +#include <asm/tlbflush.h> | |
64 | #include <asm/insn.h> | |
65 | ||
66 | #include "../perf_event.h" | |
67 | @@ -282,20 +283,35 @@ static DEFINE_PER_CPU(void *, insn_buffer); | |
68 | ||
69 | static void ds_update_cea(void *cea, void *addr, size_t size, pgprot_t prot) | |
70 | { | |
71 | + unsigned long start = (unsigned long)cea; | |
72 | phys_addr_t pa; | |
73 | size_t msz = 0; | |
74 | ||
75 | pa = virt_to_phys(addr); | |
76 | + | |
77 | + preempt_disable(); | |
78 | for (; msz < size; msz += PAGE_SIZE, pa += PAGE_SIZE, cea += PAGE_SIZE) | |
79 | cea_set_pte(cea, pa, prot); | |
80 | + | |
81 | + /* | |
82 | + * This is a cross-CPU update of the cpu_entry_area, we must shoot down | |
83 | + * all TLB entries for it. | |
84 | + */ | |
85 | + flush_tlb_kernel_range(start, start + size); | |
86 | + preempt_enable(); | |
87 | } | |
88 | ||
89 | static void ds_clear_cea(void *cea, size_t size) | |
90 | { | |
91 | + unsigned long start = (unsigned long)cea; | |
92 | size_t msz = 0; | |
93 | ||
94 | + preempt_disable(); | |
95 | for (; msz < size; msz += PAGE_SIZE, cea += PAGE_SIZE) | |
96 | cea_set_pte(cea, 0, PAGE_NONE); | |
97 | + | |
98 | + flush_tlb_kernel_range(start, start + size); | |
99 | + preempt_enable(); | |
100 | } | |
101 | ||
102 | static void *dsalloc_pages(size_t size, gfp_t flags, int cpu) | |
103 | -- | |
104 | 2.14.2 | |
105 |