0203-x86-events-intel-ds-Map-debug-buffers-in-cpu_entry_a.patch 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. From 68338a3b7267b4fc346630b2d82a3599b5fbf54e Mon Sep 17 00:00:00 2001
  2. From: Hugh Dickins <[email protected]>
  3. Date: Mon, 4 Dec 2017 15:07:50 +0100
  4. Subject: [PATCH 203/231] x86/events/intel/ds: Map debug buffers in
  5. cpu_entry_area
  6. MIME-Version: 1.0
  7. Content-Type: text/plain; charset=UTF-8
  8. Content-Transfer-Encoding: 8bit
  9. CVE-2017-5754
  10. The BTS and PEBS buffers both have their virtual addresses programmed into
  11. the hardware. This means that any access to them is performed via the page
  12. tables. The times that the hardware accesses these are entirely dependent
  13. on how the performance monitoring hardware events are set up. In other
  14. words, there is no way for the kernel to tell when the hardware might
  15. access these buffers.
  16. To avoid perf crashes, place 'debug_store' allocate pages and map them into
  17. the cpu_entry_area.
  18. The PEBS fixup buffer does not need this treatment.
  19. [ tglx: Got rid of the kaiser_add_mapping() complication ]
  20. Signed-off-by: Hugh Dickins <[email protected]>
  21. Signed-off-by: Dave Hansen <[email protected]>
  22. Signed-off-by: Thomas Gleixner <[email protected]>
  23. Cc: Andy Lutomirski <[email protected]>
  24. Cc: Boris Ostrovsky <[email protected]>
  25. Cc: Borislav Petkov <[email protected]>
  26. Cc: Brian Gerst <[email protected]>
  27. Cc: David Laight <[email protected]>
  28. Cc: Denys Vlasenko <[email protected]>
  29. Cc: Eduardo Valentin <[email protected]>
  30. Cc: Greg KH <[email protected]>
  31. Cc: H. Peter Anvin <[email protected]>
  32. Cc: Josh Poimboeuf <[email protected]>
  33. Cc: Juergen Gross <[email protected]>
  34. Cc: Linus Torvalds <[email protected]>
  35. Cc: Peter Zijlstra <[email protected]>
  36. Cc: Will Deacon <[email protected]>
  37. Cc: [email protected]
  38. Cc: [email protected]
  39. Cc: [email protected]
  40. Signed-off-by: Ingo Molnar <[email protected]>
  41. (cherry picked from commit c1961a4631daef4aeabee8e368b1b13e8f173c91)
  42. Signed-off-by: Andy Whitcroft <[email protected]>
  43. Signed-off-by: Kleber Sacilotto de Souza <[email protected]>
  44. (cherry picked from commit 569dedbb62e16e3268f006dcf745b8d27690ef91)
  45. Signed-off-by: Fabian Grünbichler <[email protected]>
  46. ---
  47. arch/x86/events/perf_event.h | 2 +
  48. arch/x86/events/intel/ds.c | 125 +++++++++++++++++++++++++++----------------
  49. 2 files changed, 82 insertions(+), 45 deletions(-)
  50. diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
  51. index 308bc14f58af..eb0876475f18 100644
  52. --- a/arch/x86/events/perf_event.h
  53. +++ b/arch/x86/events/perf_event.h
  54. @@ -199,6 +199,8 @@ struct cpu_hw_events {
  55. * Intel DebugStore bits
  56. */
  57. struct debug_store *ds;
  58. + void *ds_pebs_vaddr;
  59. + void *ds_bts_vaddr;
  60. u64 pebs_enabled;
  61. int n_pebs;
  62. int n_large_pebs;
  63. diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c
  64. index 21a4ed789ec0..85df1f12c49e 100644
  65. --- a/arch/x86/events/intel/ds.c
  66. +++ b/arch/x86/events/intel/ds.c
  67. @@ -2,6 +2,7 @@
  68. #include <linux/types.h>
  69. #include <linux/slab.h>
  70. +#include <asm/cpu_entry_area.h>
  71. #include <asm/perf_event.h>
  72. #include <asm/insn.h>
  73. @@ -279,17 +280,52 @@ void fini_debug_store_on_cpu(int cpu)
  74. static DEFINE_PER_CPU(void *, insn_buffer);
  75. -static int alloc_pebs_buffer(int cpu)
  76. +static void ds_update_cea(void *cea, void *addr, size_t size, pgprot_t prot)
  77. {
  78. - struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
  79. + phys_addr_t pa;
  80. + size_t msz = 0;
  81. +
  82. + pa = virt_to_phys(addr);
  83. + for (; msz < size; msz += PAGE_SIZE, pa += PAGE_SIZE, cea += PAGE_SIZE)
  84. + cea_set_pte(cea, pa, prot);
  85. +}
  86. +
  87. +static void ds_clear_cea(void *cea, size_t size)
  88. +{
  89. + size_t msz = 0;
  90. +
  91. + for (; msz < size; msz += PAGE_SIZE, cea += PAGE_SIZE)
  92. + cea_set_pte(cea, 0, PAGE_NONE);
  93. +}
  94. +
  95. +static void *dsalloc_pages(size_t size, gfp_t flags, int cpu)
  96. +{
  97. + unsigned int order = get_order(size);
  98. int node = cpu_to_node(cpu);
  99. - int max;
  100. - void *buffer, *ibuffer;
  101. + struct page *page;
  102. +
  103. + page = __alloc_pages_node(node, flags | __GFP_ZERO, order);
  104. + return page ? page_address(page) : NULL;
  105. +}
  106. +
  107. +static void dsfree_pages(const void *buffer, size_t size)
  108. +{
  109. + if (buffer)
  110. + free_pages((unsigned long)buffer, get_order(size));
  111. +}
  112. +
  113. +static int alloc_pebs_buffer(int cpu)
  114. +{
  115. + struct cpu_hw_events *hwev = per_cpu_ptr(&cpu_hw_events, cpu);
  116. + struct debug_store *ds = hwev->ds;
  117. + size_t bsiz = x86_pmu.pebs_buffer_size;
  118. + int max, node = cpu_to_node(cpu);
  119. + void *buffer, *ibuffer, *cea;
  120. if (!x86_pmu.pebs)
  121. return 0;
  122. - buffer = kzalloc_node(x86_pmu.pebs_buffer_size, GFP_KERNEL, node);
  123. + buffer = dsalloc_pages(bsiz, GFP_KERNEL, cpu);
  124. if (unlikely(!buffer))
  125. return -ENOMEM;
  126. @@ -300,25 +336,27 @@ static int alloc_pebs_buffer(int cpu)
  127. if (x86_pmu.intel_cap.pebs_format < 2) {
  128. ibuffer = kzalloc_node(PEBS_FIXUP_SIZE, GFP_KERNEL, node);
  129. if (!ibuffer) {
  130. - kfree(buffer);
  131. + dsfree_pages(buffer, bsiz);
  132. return -ENOMEM;
  133. }
  134. per_cpu(insn_buffer, cpu) = ibuffer;
  135. }
  136. -
  137. - max = x86_pmu.pebs_buffer_size / x86_pmu.pebs_record_size;
  138. -
  139. - ds->pebs_buffer_base = (u64)(unsigned long)buffer;
  140. + hwev->ds_pebs_vaddr = buffer;
  141. + /* Update the cpu entry area mapping */
  142. + cea = &get_cpu_entry_area(cpu)->cpu_debug_buffers.pebs_buffer;
  143. + ds->pebs_buffer_base = (unsigned long) cea;
  144. + ds_update_cea(cea, buffer, bsiz, PAGE_KERNEL);
  145. ds->pebs_index = ds->pebs_buffer_base;
  146. - ds->pebs_absolute_maximum = ds->pebs_buffer_base +
  147. - max * x86_pmu.pebs_record_size;
  148. -
  149. + max = x86_pmu.pebs_record_size * (bsiz / x86_pmu.pebs_record_size);
  150. + ds->pebs_absolute_maximum = ds->pebs_buffer_base + max;
  151. return 0;
  152. }
  153. static void release_pebs_buffer(int cpu)
  154. {
  155. - struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
  156. + struct cpu_hw_events *hwev = per_cpu_ptr(&cpu_hw_events, cpu);
  157. + struct debug_store *ds = hwev->ds;
  158. + void *cea;
  159. if (!ds || !x86_pmu.pebs)
  160. return;
  161. @@ -326,73 +364,70 @@ static void release_pebs_buffer(int cpu)
  162. kfree(per_cpu(insn_buffer, cpu));
  163. per_cpu(insn_buffer, cpu) = NULL;
  164. - kfree((void *)(unsigned long)ds->pebs_buffer_base);
  165. + /* Clear the fixmap */
  166. + cea = &get_cpu_entry_area(cpu)->cpu_debug_buffers.pebs_buffer;
  167. + ds_clear_cea(cea, x86_pmu.pebs_buffer_size);
  168. ds->pebs_buffer_base = 0;
  169. + dsfree_pages(hwev->ds_pebs_vaddr, x86_pmu.pebs_buffer_size);
  170. + hwev->ds_pebs_vaddr = NULL;
  171. }
  172. static int alloc_bts_buffer(int cpu)
  173. {
  174. - struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
  175. - int node = cpu_to_node(cpu);
  176. - int max, thresh;
  177. - void *buffer;
  178. + struct cpu_hw_events *hwev = per_cpu_ptr(&cpu_hw_events, cpu);
  179. + struct debug_store *ds = hwev->ds;
  180. + void *buffer, *cea;
  181. + int max;
  182. if (!x86_pmu.bts)
  183. return 0;
  184. - buffer = kzalloc_node(BTS_BUFFER_SIZE, GFP_KERNEL | __GFP_NOWARN, node);
  185. + buffer = dsalloc_pages(BTS_BUFFER_SIZE, GFP_KERNEL | __GFP_NOWARN, cpu);
  186. if (unlikely(!buffer)) {
  187. WARN_ONCE(1, "%s: BTS buffer allocation failure\n", __func__);
  188. return -ENOMEM;
  189. }
  190. -
  191. - max = BTS_BUFFER_SIZE / BTS_RECORD_SIZE;
  192. - thresh = max / 16;
  193. -
  194. - ds->bts_buffer_base = (u64)(unsigned long)buffer;
  195. + hwev->ds_bts_vaddr = buffer;
  196. + /* Update the fixmap */
  197. + cea = &get_cpu_entry_area(cpu)->cpu_debug_buffers.bts_buffer;
  198. + ds->bts_buffer_base = (unsigned long) cea;
  199. + ds_update_cea(cea, buffer, BTS_BUFFER_SIZE, PAGE_KERNEL);
  200. ds->bts_index = ds->bts_buffer_base;
  201. - ds->bts_absolute_maximum = ds->bts_buffer_base +
  202. - max * BTS_RECORD_SIZE;
  203. - ds->bts_interrupt_threshold = ds->bts_absolute_maximum -
  204. - thresh * BTS_RECORD_SIZE;
  205. -
  206. + max = BTS_RECORD_SIZE * (BTS_BUFFER_SIZE / BTS_RECORD_SIZE);
  207. + ds->bts_absolute_maximum = ds->bts_buffer_base + max;
  208. + ds->bts_interrupt_threshold = ds->bts_absolute_maximum - (max / 16);
  209. return 0;
  210. }
  211. static void release_bts_buffer(int cpu)
  212. {
  213. - struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
  214. + struct cpu_hw_events *hwev = per_cpu_ptr(&cpu_hw_events, cpu);
  215. + struct debug_store *ds = hwev->ds;
  216. + void *cea;
  217. if (!ds || !x86_pmu.bts)
  218. return;
  219. - kfree((void *)(unsigned long)ds->bts_buffer_base);
  220. + /* Clear the fixmap */
  221. + cea = &get_cpu_entry_area(cpu)->cpu_debug_buffers.bts_buffer;
  222. + ds_clear_cea(cea, BTS_BUFFER_SIZE);
  223. ds->bts_buffer_base = 0;
  224. + dsfree_pages(hwev->ds_bts_vaddr, BTS_BUFFER_SIZE);
  225. + hwev->ds_bts_vaddr = NULL;
  226. }
  227. static int alloc_ds_buffer(int cpu)
  228. {
  229. - int node = cpu_to_node(cpu);
  230. - struct debug_store *ds;
  231. -
  232. - ds = kzalloc_node(sizeof(*ds), GFP_KERNEL, node);
  233. - if (unlikely(!ds))
  234. - return -ENOMEM;
  235. + struct debug_store *ds = &get_cpu_entry_area(cpu)->cpu_debug_store;
  236. + memset(ds, 0, sizeof(*ds));
  237. per_cpu(cpu_hw_events, cpu).ds = ds;
  238. -
  239. return 0;
  240. }
  241. static void release_ds_buffer(int cpu)
  242. {
  243. - struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
  244. -
  245. - if (!ds)
  246. - return;
  247. -
  248. per_cpu(cpu_hw_events, cpu).ds = NULL;
  249. - kfree(ds);
  250. }
  251. void release_ds_buffers(void)
  252. --
  253. 2.14.2