12025cf9eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2af5d3aabSBorislav Petkov /*
3af5d3aabSBorislav Petkov * BTS PMU driver for perf
4af5d3aabSBorislav Petkov * Copyright (c) 2013-2014, Intel Corporation.
5af5d3aabSBorislav Petkov */
6af5d3aabSBorislav Petkov
7af5d3aabSBorislav Petkov #undef DEBUG
8af5d3aabSBorislav Petkov
9af5d3aabSBorislav Petkov #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
10af5d3aabSBorislav Petkov
11af5d3aabSBorislav Petkov #include <linux/bitops.h>
12af5d3aabSBorislav Petkov #include <linux/types.h>
13af5d3aabSBorislav Petkov #include <linux/slab.h>
14af5d3aabSBorislav Petkov #include <linux/debugfs.h>
15af5d3aabSBorislav Petkov #include <linux/device.h>
16af5d3aabSBorislav Petkov #include <linux/coredump.h>
17af5d3aabSBorislav Petkov
1887dfb311SMasahiro Yamada #include <linux/sizes.h>
19af5d3aabSBorislav Petkov #include <asm/perf_event.h>
20af5d3aabSBorislav Petkov
2127f6d22bSBorislav Petkov #include "../perf_event.h"
22af5d3aabSBorislav Petkov
23af5d3aabSBorislav Petkov struct bts_ctx {
24af5d3aabSBorislav Petkov struct perf_output_handle handle;
25af5d3aabSBorislav Petkov struct debug_store ds_back;
26a9a94401SAlexander Shishkin int state;
27a9a94401SAlexander Shishkin };
28a9a94401SAlexander Shishkin
29a9a94401SAlexander Shishkin /* BTS context states: */
30a9a94401SAlexander Shishkin enum {
31a9a94401SAlexander Shishkin /* no ongoing AUX transactions */
32a9a94401SAlexander Shishkin BTS_STATE_STOPPED = 0,
33a9a94401SAlexander Shishkin /* AUX transaction is on, BTS tracing is disabled */
34a9a94401SAlexander Shishkin BTS_STATE_INACTIVE,
35a9a94401SAlexander Shishkin /* AUX transaction is on, BTS tracing is running */
36a9a94401SAlexander Shishkin BTS_STATE_ACTIVE,
37af5d3aabSBorislav Petkov };
38af5d3aabSBorislav Petkov
39af5d3aabSBorislav Petkov static DEFINE_PER_CPU(struct bts_ctx, bts_ctx);
40af5d3aabSBorislav Petkov
41af5d3aabSBorislav Petkov #define BTS_RECORD_SIZE 24
42af5d3aabSBorislav Petkov #define BTS_SAFETY_MARGIN 4080
43af5d3aabSBorislav Petkov
44af5d3aabSBorislav Petkov struct bts_phys {
45af5d3aabSBorislav Petkov struct page *page;
46af5d3aabSBorislav Petkov unsigned long size;
47af5d3aabSBorislav Petkov unsigned long offset;
48af5d3aabSBorislav Petkov unsigned long displacement;
49af5d3aabSBorislav Petkov };
50af5d3aabSBorislav Petkov
51af5d3aabSBorislav Petkov struct bts_buffer {
52af5d3aabSBorislav Petkov size_t real_size; /* multiple of BTS_RECORD_SIZE */
53af5d3aabSBorislav Petkov unsigned int nr_pages;
54af5d3aabSBorislav Petkov unsigned int nr_bufs;
55af5d3aabSBorislav Petkov unsigned int cur_buf;
56af5d3aabSBorislav Petkov bool snapshot;
57af5d3aabSBorislav Petkov local_t data_size;
58af5d3aabSBorislav Petkov local_t head;
59af5d3aabSBorislav Petkov unsigned long end;
60af5d3aabSBorislav Petkov void **data_pages;
618ac7571aSGustavo A. R. Silva struct bts_phys buf[];
62af5d3aabSBorislav Petkov };
63af5d3aabSBorislav Petkov
64b45e4c45SColin Ian King static struct pmu bts_pmu;
65af5d3aabSBorislav Petkov
buf_nr_pages(struct page * page)66ff61541cSAlexander Shishkin static int buf_nr_pages(struct page *page)
67ff61541cSAlexander Shishkin {
68ff61541cSAlexander Shishkin if (!PagePrivate(page))
69ff61541cSAlexander Shishkin return 1;
70ff61541cSAlexander Shishkin
71ff61541cSAlexander Shishkin return 1 << page_private(page);
72ff61541cSAlexander Shishkin }
73ff61541cSAlexander Shishkin
buf_size(struct page * page)74af5d3aabSBorislav Petkov static size_t buf_size(struct page *page)
75af5d3aabSBorislav Petkov {
76ff61541cSAlexander Shishkin return buf_nr_pages(page) * PAGE_SIZE;
77af5d3aabSBorislav Petkov }
78af5d3aabSBorislav Petkov
79af5d3aabSBorislav Petkov static void *
bts_buffer_setup_aux(struct perf_event * event,void ** pages,int nr_pages,bool overwrite)8084001866SMathieu Poirier bts_buffer_setup_aux(struct perf_event *event, void **pages,
8184001866SMathieu Poirier int nr_pages, bool overwrite)
82af5d3aabSBorislav Petkov {
83af5d3aabSBorislav Petkov struct bts_buffer *buf;
84af5d3aabSBorislav Petkov struct page *page;
8584001866SMathieu Poirier int cpu = event->cpu;
86af5d3aabSBorislav Petkov int node = (cpu == -1) ? cpu : cpu_to_node(cpu);
87af5d3aabSBorislav Petkov unsigned long offset;
88af5d3aabSBorislav Petkov size_t size = nr_pages << PAGE_SHIFT;
89af5d3aabSBorislav Petkov int pg, nbuf, pad;
90af5d3aabSBorislav Petkov
91af5d3aabSBorislav Petkov /* count all the high order buffers */
92af5d3aabSBorislav Petkov for (pg = 0, nbuf = 0; pg < nr_pages;) {
93af5d3aabSBorislav Petkov page = virt_to_page(pages[pg]);
94ff61541cSAlexander Shishkin pg += buf_nr_pages(page);
95af5d3aabSBorislav Petkov nbuf++;
96af5d3aabSBorislav Petkov }
97af5d3aabSBorislav Petkov
98af5d3aabSBorislav Petkov /*
99af5d3aabSBorislav Petkov * to avoid interrupts in overwrite mode, only allow one physical
100af5d3aabSBorislav Petkov */
101af5d3aabSBorislav Petkov if (overwrite && nbuf > 1)
102af5d3aabSBorislav Petkov return NULL;
103af5d3aabSBorislav Petkov
104af5d3aabSBorislav Petkov buf = kzalloc_node(offsetof(struct bts_buffer, buf[nbuf]), GFP_KERNEL, node);
105af5d3aabSBorislav Petkov if (!buf)
106af5d3aabSBorislav Petkov return NULL;
107af5d3aabSBorislav Petkov
108af5d3aabSBorislav Petkov buf->nr_pages = nr_pages;
109af5d3aabSBorislav Petkov buf->nr_bufs = nbuf;
110af5d3aabSBorislav Petkov buf->snapshot = overwrite;
111af5d3aabSBorislav Petkov buf->data_pages = pages;
112af5d3aabSBorislav Petkov buf->real_size = size - size % BTS_RECORD_SIZE;
113af5d3aabSBorislav Petkov
114af5d3aabSBorislav Petkov for (pg = 0, nbuf = 0, offset = 0, pad = 0; nbuf < buf->nr_bufs; nbuf++) {
115af5d3aabSBorislav Petkov unsigned int __nr_pages;
116af5d3aabSBorislav Petkov
117af5d3aabSBorislav Petkov page = virt_to_page(pages[pg]);
118ff61541cSAlexander Shishkin __nr_pages = buf_nr_pages(page);
119af5d3aabSBorislav Petkov buf->buf[nbuf].page = page;
120af5d3aabSBorislav Petkov buf->buf[nbuf].offset = offset;
121af5d3aabSBorislav Petkov buf->buf[nbuf].displacement = (pad ? BTS_RECORD_SIZE - pad : 0);
122af5d3aabSBorislav Petkov buf->buf[nbuf].size = buf_size(page) - buf->buf[nbuf].displacement;
123af5d3aabSBorislav Petkov pad = buf->buf[nbuf].size % BTS_RECORD_SIZE;
124af5d3aabSBorislav Petkov buf->buf[nbuf].size -= pad;
125af5d3aabSBorislav Petkov
126af5d3aabSBorislav Petkov pg += __nr_pages;
127af5d3aabSBorislav Petkov offset += __nr_pages << PAGE_SHIFT;
128af5d3aabSBorislav Petkov }
129af5d3aabSBorislav Petkov
130af5d3aabSBorislav Petkov return buf;
131af5d3aabSBorislav Petkov }
132af5d3aabSBorislav Petkov
bts_buffer_free_aux(void * data)133af5d3aabSBorislav Petkov static void bts_buffer_free_aux(void *data)
134af5d3aabSBorislav Petkov {
135af5d3aabSBorislav Petkov kfree(data);
136af5d3aabSBorislav Petkov }
137af5d3aabSBorislav Petkov
bts_buffer_offset(struct bts_buffer * buf,unsigned int idx)138af5d3aabSBorislav Petkov static unsigned long bts_buffer_offset(struct bts_buffer *buf, unsigned int idx)
139af5d3aabSBorislav Petkov {
140af5d3aabSBorislav Petkov return buf->buf[idx].offset + buf->buf[idx].displacement;
141af5d3aabSBorislav Petkov }
142af5d3aabSBorislav Petkov
143af5d3aabSBorislav Petkov static void
bts_config_buffer(struct bts_buffer * buf)144af5d3aabSBorislav Petkov bts_config_buffer(struct bts_buffer *buf)
145af5d3aabSBorislav Petkov {
146af5d3aabSBorislav Petkov int cpu = raw_smp_processor_id();
147af5d3aabSBorislav Petkov struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
148af5d3aabSBorislav Petkov struct bts_phys *phys = &buf->buf[buf->cur_buf];
149af5d3aabSBorislav Petkov unsigned long index, thresh = 0, end = phys->size;
150af5d3aabSBorislav Petkov struct page *page = phys->page;
151af5d3aabSBorislav Petkov
152af5d3aabSBorislav Petkov index = local_read(&buf->head);
153af5d3aabSBorislav Petkov
154af5d3aabSBorislav Petkov if (!buf->snapshot) {
155af5d3aabSBorislav Petkov if (buf->end < phys->offset + buf_size(page))
156af5d3aabSBorislav Petkov end = buf->end - phys->offset - phys->displacement;
157af5d3aabSBorislav Petkov
158af5d3aabSBorislav Petkov index -= phys->offset + phys->displacement;
159af5d3aabSBorislav Petkov
160af5d3aabSBorislav Petkov if (end - index > BTS_SAFETY_MARGIN)
161af5d3aabSBorislav Petkov thresh = end - BTS_SAFETY_MARGIN;
162af5d3aabSBorislav Petkov else if (end - index > BTS_RECORD_SIZE)
163af5d3aabSBorislav Petkov thresh = end - BTS_RECORD_SIZE;
164af5d3aabSBorislav Petkov else
165af5d3aabSBorislav Petkov thresh = end;
166af5d3aabSBorislav Petkov }
167af5d3aabSBorislav Petkov
168af5d3aabSBorislav Petkov ds->bts_buffer_base = (u64)(long)page_address(page) + phys->displacement;
169af5d3aabSBorislav Petkov ds->bts_index = ds->bts_buffer_base + index;
170af5d3aabSBorislav Petkov ds->bts_absolute_maximum = ds->bts_buffer_base + end;
171af5d3aabSBorislav Petkov ds->bts_interrupt_threshold = !buf->snapshot
172af5d3aabSBorislav Petkov ? ds->bts_buffer_base + thresh
173af5d3aabSBorislav Petkov : ds->bts_absolute_maximum + BTS_RECORD_SIZE;
174af5d3aabSBorislav Petkov }
175af5d3aabSBorislav Petkov
bts_buffer_pad_out(struct bts_phys * phys,unsigned long head)176af5d3aabSBorislav Petkov static void bts_buffer_pad_out(struct bts_phys *phys, unsigned long head)
177af5d3aabSBorislav Petkov {
178af5d3aabSBorislav Petkov unsigned long index = head - phys->offset;
179af5d3aabSBorislav Petkov
180af5d3aabSBorislav Petkov memset(page_address(phys->page) + index, 0, phys->size - index);
181af5d3aabSBorislav Petkov }
182af5d3aabSBorislav Petkov
bts_update(struct bts_ctx * bts)183af5d3aabSBorislav Petkov static void bts_update(struct bts_ctx *bts)
184af5d3aabSBorislav Petkov {
185af5d3aabSBorislav Petkov int cpu = raw_smp_processor_id();
186af5d3aabSBorislav Petkov struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds;
187af5d3aabSBorislav Petkov struct bts_buffer *buf = perf_get_aux(&bts->handle);
188af5d3aabSBorislav Petkov unsigned long index = ds->bts_index - ds->bts_buffer_base, old, head;
189af5d3aabSBorislav Petkov
190af5d3aabSBorislav Petkov if (!buf)
191af5d3aabSBorislav Petkov return;
192af5d3aabSBorislav Petkov
193af5d3aabSBorislav Petkov head = index + bts_buffer_offset(buf, buf->cur_buf);
194af5d3aabSBorislav Petkov old = local_xchg(&buf->head, head);
195af5d3aabSBorislav Petkov
196af5d3aabSBorislav Petkov if (!buf->snapshot) {
197af5d3aabSBorislav Petkov if (old == head)
198af5d3aabSBorislav Petkov return;
199af5d3aabSBorislav Petkov
200af5d3aabSBorislav Petkov if (ds->bts_index >= ds->bts_absolute_maximum)
201f4c0b0aaSWill Deacon perf_aux_output_flag(&bts->handle,
202f4c0b0aaSWill Deacon PERF_AUX_FLAG_TRUNCATED);
203af5d3aabSBorislav Petkov
204af5d3aabSBorislav Petkov /*
205af5d3aabSBorislav Petkov * old and head are always in the same physical buffer, so we
206af5d3aabSBorislav Petkov * can subtract them to get the data size.
207af5d3aabSBorislav Petkov */
208af5d3aabSBorislav Petkov local_add(head - old, &buf->data_size);
209af5d3aabSBorislav Petkov } else {
210af5d3aabSBorislav Petkov local_set(&buf->data_size, head);
211af5d3aabSBorislav Petkov }
212*41100833SLeo Yan
213*41100833SLeo Yan /*
214*41100833SLeo Yan * Since BTS is coherent, just add compiler barrier to ensure
215*41100833SLeo Yan * BTS updating is ordered against bts::handle::event.
216*41100833SLeo Yan */
217*41100833SLeo Yan barrier();
218af5d3aabSBorislav Petkov }
219af5d3aabSBorislav Petkov
220981a4cb3SAlexander Shishkin static int
221981a4cb3SAlexander Shishkin bts_buffer_reset(struct bts_buffer *buf, struct perf_output_handle *handle);
222981a4cb3SAlexander Shishkin
223a9a94401SAlexander Shishkin /*
224a9a94401SAlexander Shishkin * Ordering PMU callbacks wrt themselves and the PMI is done by means
225a9a94401SAlexander Shishkin * of bts::state, which:
226a9a94401SAlexander Shishkin * - is set when bts::handle::event is valid, that is, between
227a9a94401SAlexander Shishkin * perf_aux_output_begin() and perf_aux_output_end();
228a9a94401SAlexander Shishkin * - is zero otherwise;
229a9a94401SAlexander Shishkin * - is ordered against bts::handle::event with a compiler barrier.
230a9a94401SAlexander Shishkin */
231a9a94401SAlexander Shishkin
__bts_event_start(struct perf_event * event)232af5d3aabSBorislav Petkov static void __bts_event_start(struct perf_event *event)
233af5d3aabSBorislav Petkov {
234af5d3aabSBorislav Petkov struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
235af5d3aabSBorislav Petkov struct bts_buffer *buf = perf_get_aux(&bts->handle);
236af5d3aabSBorislav Petkov u64 config = 0;
237af5d3aabSBorislav Petkov
238af5d3aabSBorislav Petkov if (!buf->snapshot)
239af5d3aabSBorislav Petkov config |= ARCH_PERFMON_EVENTSEL_INT;
240af5d3aabSBorislav Petkov if (!event->attr.exclude_kernel)
241af5d3aabSBorislav Petkov config |= ARCH_PERFMON_EVENTSEL_OS;
242af5d3aabSBorislav Petkov if (!event->attr.exclude_user)
243af5d3aabSBorislav Petkov config |= ARCH_PERFMON_EVENTSEL_USR;
244af5d3aabSBorislav Petkov
245af5d3aabSBorislav Petkov bts_config_buffer(buf);
246af5d3aabSBorislav Petkov
247af5d3aabSBorislav Petkov /*
248af5d3aabSBorislav Petkov * local barrier to make sure that ds configuration made it
249a9a94401SAlexander Shishkin * before we enable BTS and bts::state goes ACTIVE
250af5d3aabSBorislav Petkov */
251af5d3aabSBorislav Petkov wmb();
252af5d3aabSBorislav Petkov
253a9a94401SAlexander Shishkin /* INACTIVE/STOPPED -> ACTIVE */
254a9a94401SAlexander Shishkin WRITE_ONCE(bts->state, BTS_STATE_ACTIVE);
255a9a94401SAlexander Shishkin
256af5d3aabSBorislav Petkov intel_pmu_enable_bts(config);
257981a4cb3SAlexander Shishkin
258af5d3aabSBorislav Petkov }
259af5d3aabSBorislav Petkov
bts_event_start(struct perf_event * event,int flags)260af5d3aabSBorislav Petkov static void bts_event_start(struct perf_event *event, int flags)
261af5d3aabSBorislav Petkov {
262981a4cb3SAlexander Shishkin struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
263af5d3aabSBorislav Petkov struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
264981a4cb3SAlexander Shishkin struct bts_buffer *buf;
265981a4cb3SAlexander Shishkin
266981a4cb3SAlexander Shishkin buf = perf_aux_output_begin(&bts->handle, event);
267981a4cb3SAlexander Shishkin if (!buf)
268981a4cb3SAlexander Shishkin goto fail_stop;
269981a4cb3SAlexander Shishkin
270981a4cb3SAlexander Shishkin if (bts_buffer_reset(buf, &bts->handle))
271981a4cb3SAlexander Shishkin goto fail_end_stop;
272981a4cb3SAlexander Shishkin
273981a4cb3SAlexander Shishkin bts->ds_back.bts_buffer_base = cpuc->ds->bts_buffer_base;
274981a4cb3SAlexander Shishkin bts->ds_back.bts_absolute_maximum = cpuc->ds->bts_absolute_maximum;
275981a4cb3SAlexander Shishkin bts->ds_back.bts_interrupt_threshold = cpuc->ds->bts_interrupt_threshold;
276981a4cb3SAlexander Shishkin
2778d4e6c4cSAlexander Shishkin perf_event_itrace_started(event);
278981a4cb3SAlexander Shishkin event->hw.state = 0;
279af5d3aabSBorislav Petkov
280af5d3aabSBorislav Petkov __bts_event_start(event);
281af5d3aabSBorislav Petkov
282981a4cb3SAlexander Shishkin return;
283981a4cb3SAlexander Shishkin
284981a4cb3SAlexander Shishkin fail_end_stop:
285f4c0b0aaSWill Deacon perf_aux_output_end(&bts->handle, 0);
286981a4cb3SAlexander Shishkin
287981a4cb3SAlexander Shishkin fail_stop:
288981a4cb3SAlexander Shishkin event->hw.state = PERF_HES_STOPPED;
289af5d3aabSBorislav Petkov }
290af5d3aabSBorislav Petkov
__bts_event_stop(struct perf_event * event,int state)291a9a94401SAlexander Shishkin static void __bts_event_stop(struct perf_event *event, int state)
292af5d3aabSBorislav Petkov {
293a9a94401SAlexander Shishkin struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
294a9a94401SAlexander Shishkin
295a9a94401SAlexander Shishkin /* ACTIVE -> INACTIVE(PMI)/STOPPED(->stop()) */
296a9a94401SAlexander Shishkin WRITE_ONCE(bts->state, state);
297a9a94401SAlexander Shishkin
298af5d3aabSBorislav Petkov /*
299af5d3aabSBorislav Petkov * No extra synchronization is mandated by the documentation to have
300af5d3aabSBorislav Petkov * BTS data stores globally visible.
301af5d3aabSBorislav Petkov */
302af5d3aabSBorislav Petkov intel_pmu_disable_bts();
303af5d3aabSBorislav Petkov }
304af5d3aabSBorislav Petkov
bts_event_stop(struct perf_event * event,int flags)305af5d3aabSBorislav Petkov static void bts_event_stop(struct perf_event *event, int flags)
306af5d3aabSBorislav Petkov {
307981a4cb3SAlexander Shishkin struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
308af5d3aabSBorislav Petkov struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
309a9a94401SAlexander Shishkin struct bts_buffer *buf = NULL;
310a9a94401SAlexander Shishkin int state = READ_ONCE(bts->state);
311af5d3aabSBorislav Petkov
312a9a94401SAlexander Shishkin if (state == BTS_STATE_ACTIVE)
313a9a94401SAlexander Shishkin __bts_event_stop(event, BTS_STATE_STOPPED);
314af5d3aabSBorislav Petkov
315a9a94401SAlexander Shishkin if (state != BTS_STATE_STOPPED)
316a9a94401SAlexander Shishkin buf = perf_get_aux(&bts->handle);
317a9a94401SAlexander Shishkin
318a9a94401SAlexander Shishkin event->hw.state |= PERF_HES_STOPPED;
319af5d3aabSBorislav Petkov
320981a4cb3SAlexander Shishkin if (flags & PERF_EF_UPDATE) {
321af5d3aabSBorislav Petkov bts_update(bts);
322981a4cb3SAlexander Shishkin
323981a4cb3SAlexander Shishkin if (buf) {
324981a4cb3SAlexander Shishkin if (buf->snapshot)
325981a4cb3SAlexander Shishkin bts->handle.head =
326981a4cb3SAlexander Shishkin local_xchg(&buf->data_size,
327981a4cb3SAlexander Shishkin buf->nr_pages << PAGE_SHIFT);
328f4c0b0aaSWill Deacon perf_aux_output_end(&bts->handle,
329f4c0b0aaSWill Deacon local_xchg(&buf->data_size, 0));
330981a4cb3SAlexander Shishkin }
331981a4cb3SAlexander Shishkin
332981a4cb3SAlexander Shishkin cpuc->ds->bts_index = bts->ds_back.bts_buffer_base;
333981a4cb3SAlexander Shishkin cpuc->ds->bts_buffer_base = bts->ds_back.bts_buffer_base;
334981a4cb3SAlexander Shishkin cpuc->ds->bts_absolute_maximum = bts->ds_back.bts_absolute_maximum;
335981a4cb3SAlexander Shishkin cpuc->ds->bts_interrupt_threshold = bts->ds_back.bts_interrupt_threshold;
336981a4cb3SAlexander Shishkin }
337af5d3aabSBorislav Petkov }
338af5d3aabSBorislav Petkov
intel_bts_enable_local(void)339af5d3aabSBorislav Petkov void intel_bts_enable_local(void)
340af5d3aabSBorislav Petkov {
341af5d3aabSBorislav Petkov struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
342a9a94401SAlexander Shishkin int state = READ_ONCE(bts->state);
343af5d3aabSBorislav Petkov
344a9a94401SAlexander Shishkin /*
345a9a94401SAlexander Shishkin * Here we transition from INACTIVE to ACTIVE;
346a9a94401SAlexander Shishkin * if we instead are STOPPED from the interrupt handler,
347a9a94401SAlexander Shishkin * stay that way. Can't be ACTIVE here though.
348a9a94401SAlexander Shishkin */
349a9a94401SAlexander Shishkin if (WARN_ON_ONCE(state == BTS_STATE_ACTIVE))
350a9a94401SAlexander Shishkin return;
351a9a94401SAlexander Shishkin
352a9a94401SAlexander Shishkin if (state == BTS_STATE_STOPPED)
353a9a94401SAlexander Shishkin return;
354a9a94401SAlexander Shishkin
355a9a94401SAlexander Shishkin if (bts->handle.event)
356af5d3aabSBorislav Petkov __bts_event_start(bts->handle.event);
357af5d3aabSBorislav Petkov }
358af5d3aabSBorislav Petkov
intel_bts_disable_local(void)359af5d3aabSBorislav Petkov void intel_bts_disable_local(void)
360af5d3aabSBorislav Petkov {
361af5d3aabSBorislav Petkov struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
362af5d3aabSBorislav Petkov
363a9a94401SAlexander Shishkin /*
364a9a94401SAlexander Shishkin * Here we transition from ACTIVE to INACTIVE;
365a9a94401SAlexander Shishkin * do nothing for STOPPED or INACTIVE.
366a9a94401SAlexander Shishkin */
367a9a94401SAlexander Shishkin if (READ_ONCE(bts->state) != BTS_STATE_ACTIVE)
368a9a94401SAlexander Shishkin return;
369a9a94401SAlexander Shishkin
370af5d3aabSBorislav Petkov if (bts->handle.event)
371a9a94401SAlexander Shishkin __bts_event_stop(bts->handle.event, BTS_STATE_INACTIVE);
372af5d3aabSBorislav Petkov }
373af5d3aabSBorislav Petkov
374af5d3aabSBorislav Petkov static int
bts_buffer_reset(struct bts_buffer * buf,struct perf_output_handle * handle)375af5d3aabSBorislav Petkov bts_buffer_reset(struct bts_buffer *buf, struct perf_output_handle *handle)
376af5d3aabSBorislav Petkov {
377af5d3aabSBorislav Petkov unsigned long head, space, next_space, pad, gap, skip, wakeup;
378af5d3aabSBorislav Petkov unsigned int next_buf;
379af5d3aabSBorislav Petkov struct bts_phys *phys, *next_phys;
380af5d3aabSBorislav Petkov int ret;
381af5d3aabSBorislav Petkov
382af5d3aabSBorislav Petkov if (buf->snapshot)
383af5d3aabSBorislav Petkov return 0;
384af5d3aabSBorislav Petkov
385af5d3aabSBorislav Petkov head = handle->head & ((buf->nr_pages << PAGE_SHIFT) - 1);
386af5d3aabSBorislav Petkov
387af5d3aabSBorislav Petkov phys = &buf->buf[buf->cur_buf];
388af5d3aabSBorislav Petkov space = phys->offset + phys->displacement + phys->size - head;
389af5d3aabSBorislav Petkov pad = space;
390af5d3aabSBorislav Petkov if (space > handle->size) {
391af5d3aabSBorislav Petkov space = handle->size;
392af5d3aabSBorislav Petkov space -= space % BTS_RECORD_SIZE;
393af5d3aabSBorislav Petkov }
394af5d3aabSBorislav Petkov if (space <= BTS_SAFETY_MARGIN) {
395af5d3aabSBorislav Petkov /* See if next phys buffer has more space */
396af5d3aabSBorislav Petkov next_buf = buf->cur_buf + 1;
397af5d3aabSBorislav Petkov if (next_buf >= buf->nr_bufs)
398af5d3aabSBorislav Petkov next_buf = 0;
399af5d3aabSBorislav Petkov next_phys = &buf->buf[next_buf];
400af5d3aabSBorislav Petkov gap = buf_size(phys->page) - phys->displacement - phys->size +
401af5d3aabSBorislav Petkov next_phys->displacement;
402af5d3aabSBorislav Petkov skip = pad + gap;
403af5d3aabSBorislav Petkov if (handle->size >= skip) {
404af5d3aabSBorislav Petkov next_space = next_phys->size;
405af5d3aabSBorislav Petkov if (next_space + skip > handle->size) {
406af5d3aabSBorislav Petkov next_space = handle->size - skip;
407af5d3aabSBorislav Petkov next_space -= next_space % BTS_RECORD_SIZE;
408af5d3aabSBorislav Petkov }
409af5d3aabSBorislav Petkov if (next_space > space || !space) {
410af5d3aabSBorislav Petkov if (pad)
411af5d3aabSBorislav Petkov bts_buffer_pad_out(phys, head);
412af5d3aabSBorislav Petkov ret = perf_aux_output_skip(handle, skip);
413af5d3aabSBorislav Petkov if (ret)
414af5d3aabSBorislav Petkov return ret;
415af5d3aabSBorislav Petkov /* Advance to next phys buffer */
416af5d3aabSBorislav Petkov phys = next_phys;
417af5d3aabSBorislav Petkov space = next_space;
418af5d3aabSBorislav Petkov head = phys->offset + phys->displacement;
419af5d3aabSBorislav Petkov /*
420af5d3aabSBorislav Petkov * After this, cur_buf and head won't match ds
421af5d3aabSBorislav Petkov * anymore, so we must not be racing with
422af5d3aabSBorislav Petkov * bts_update().
423af5d3aabSBorislav Petkov */
424af5d3aabSBorislav Petkov buf->cur_buf = next_buf;
425af5d3aabSBorislav Petkov local_set(&buf->head, head);
426af5d3aabSBorislav Petkov }
427af5d3aabSBorislav Petkov }
428af5d3aabSBorislav Petkov }
429af5d3aabSBorislav Petkov
430af5d3aabSBorislav Petkov /* Don't go far beyond wakeup watermark */
431af5d3aabSBorislav Petkov wakeup = BTS_SAFETY_MARGIN + BTS_RECORD_SIZE + handle->wakeup -
432af5d3aabSBorislav Petkov handle->head;
433af5d3aabSBorislav Petkov if (space > wakeup) {
434af5d3aabSBorislav Petkov space = wakeup;
435af5d3aabSBorislav Petkov space -= space % BTS_RECORD_SIZE;
436af5d3aabSBorislav Petkov }
437af5d3aabSBorislav Petkov
438af5d3aabSBorislav Petkov buf->end = head + space;
439af5d3aabSBorislav Petkov
440af5d3aabSBorislav Petkov /*
441af5d3aabSBorislav Petkov * If we have no space, the lost notification would have been sent when
442af5d3aabSBorislav Petkov * we hit absolute_maximum - see bts_update()
443af5d3aabSBorislav Petkov */
444af5d3aabSBorislav Petkov if (!space)
445af5d3aabSBorislav Petkov return -ENOSPC;
446af5d3aabSBorislav Petkov
447af5d3aabSBorislav Petkov return 0;
448af5d3aabSBorislav Petkov }
449af5d3aabSBorislav Petkov
intel_bts_interrupt(void)450af5d3aabSBorislav Petkov int intel_bts_interrupt(void)
451af5d3aabSBorislav Petkov {
4524d4c4741SAlexander Shishkin struct debug_store *ds = this_cpu_ptr(&cpu_hw_events)->ds;
453af5d3aabSBorislav Petkov struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
454af5d3aabSBorislav Petkov struct perf_event *event = bts->handle.event;
455af5d3aabSBorislav Petkov struct bts_buffer *buf;
456af5d3aabSBorislav Petkov s64 old_head;
4574d4c4741SAlexander Shishkin int err = -ENOSPC, handled = 0;
4584d4c4741SAlexander Shishkin
4594d4c4741SAlexander Shishkin /*
4604d4c4741SAlexander Shishkin * The only surefire way of knowing if this NMI is ours is by checking
4614d4c4741SAlexander Shishkin * the write ptr against the PMI threshold.
4624d4c4741SAlexander Shishkin */
463f1e1c9e5SSebastian Andrzej Siewior if (ds && (ds->bts_index >= ds->bts_interrupt_threshold))
4644d4c4741SAlexander Shishkin handled = 1;
465af5d3aabSBorislav Petkov
466a9a94401SAlexander Shishkin /*
467a9a94401SAlexander Shishkin * this is wrapped in intel_bts_enable_local/intel_bts_disable_local,
468a9a94401SAlexander Shishkin * so we can only be INACTIVE or STOPPED
469a9a94401SAlexander Shishkin */
470a9a94401SAlexander Shishkin if (READ_ONCE(bts->state) == BTS_STATE_STOPPED)
4714d4c4741SAlexander Shishkin return handled;
472af5d3aabSBorislav Petkov
473af5d3aabSBorislav Petkov buf = perf_get_aux(&bts->handle);
4744d4c4741SAlexander Shishkin if (!buf)
4754d4c4741SAlexander Shishkin return handled;
4764d4c4741SAlexander Shishkin
477af5d3aabSBorislav Petkov /*
478af5d3aabSBorislav Petkov * Skip snapshot counters: they don't use the interrupt, but
479af5d3aabSBorislav Petkov * there's no other way of telling, because the pointer will
480af5d3aabSBorislav Petkov * keep moving
481af5d3aabSBorislav Petkov */
4824d4c4741SAlexander Shishkin if (buf->snapshot)
483af5d3aabSBorislav Petkov return 0;
484af5d3aabSBorislav Petkov
485af5d3aabSBorislav Petkov old_head = local_read(&buf->head);
486af5d3aabSBorislav Petkov bts_update(bts);
487af5d3aabSBorislav Petkov
488af5d3aabSBorislav Petkov /* no new data */
489af5d3aabSBorislav Petkov if (old_head == local_read(&buf->head))
4904d4c4741SAlexander Shishkin return handled;
491af5d3aabSBorislav Petkov
492f4c0b0aaSWill Deacon perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0));
493af5d3aabSBorislav Petkov
494af5d3aabSBorislav Petkov buf = perf_aux_output_begin(&bts->handle, event);
495a9a94401SAlexander Shishkin if (buf)
496af5d3aabSBorislav Petkov err = bts_buffer_reset(buf, &bts->handle);
497a9a94401SAlexander Shishkin
498a9a94401SAlexander Shishkin if (err) {
499a9a94401SAlexander Shishkin WRITE_ONCE(bts->state, BTS_STATE_STOPPED);
500a9a94401SAlexander Shishkin
501a9a94401SAlexander Shishkin if (buf) {
502a9a94401SAlexander Shishkin /*
503a9a94401SAlexander Shishkin * BTS_STATE_STOPPED should be visible before
504a9a94401SAlexander Shishkin * cleared handle::event
505a9a94401SAlexander Shishkin */
506a9a94401SAlexander Shishkin barrier();
507f4c0b0aaSWill Deacon perf_aux_output_end(&bts->handle, 0);
508a9a94401SAlexander Shishkin }
509a9a94401SAlexander Shishkin }
510af5d3aabSBorislav Petkov
511af5d3aabSBorislav Petkov return 1;
512af5d3aabSBorislav Petkov }
513af5d3aabSBorislav Petkov
bts_event_del(struct perf_event * event,int mode)514af5d3aabSBorislav Petkov static void bts_event_del(struct perf_event *event, int mode)
515af5d3aabSBorislav Petkov {
516af5d3aabSBorislav Petkov bts_event_stop(event, PERF_EF_UPDATE);
517af5d3aabSBorislav Petkov }
518af5d3aabSBorislav Petkov
bts_event_add(struct perf_event * event,int mode)519af5d3aabSBorislav Petkov static int bts_event_add(struct perf_event *event, int mode)
520af5d3aabSBorislav Petkov {
521af5d3aabSBorislav Petkov struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
522af5d3aabSBorislav Petkov struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
523af5d3aabSBorislav Petkov struct hw_perf_event *hwc = &event->hw;
524af5d3aabSBorislav Petkov
525af5d3aabSBorislav Petkov event->hw.state = PERF_HES_STOPPED;
526af5d3aabSBorislav Petkov
527af5d3aabSBorislav Petkov if (test_bit(INTEL_PMC_IDX_FIXED_BTS, cpuc->active_mask))
528af5d3aabSBorislav Petkov return -EBUSY;
529af5d3aabSBorislav Petkov
530af5d3aabSBorislav Petkov if (bts->handle.event)
531af5d3aabSBorislav Petkov return -EBUSY;
532af5d3aabSBorislav Petkov
533af5d3aabSBorislav Petkov if (mode & PERF_EF_START) {
534af5d3aabSBorislav Petkov bts_event_start(event, 0);
535981a4cb3SAlexander Shishkin if (hwc->state & PERF_HES_STOPPED)
536981a4cb3SAlexander Shishkin return -EINVAL;
537af5d3aabSBorislav Petkov }
538af5d3aabSBorislav Petkov
539af5d3aabSBorislav Petkov return 0;
540af5d3aabSBorislav Petkov }
541af5d3aabSBorislav Petkov
bts_event_destroy(struct perf_event * event)542af5d3aabSBorislav Petkov static void bts_event_destroy(struct perf_event *event)
543af5d3aabSBorislav Petkov {
544af5d3aabSBorislav Petkov x86_release_hardware();
545af5d3aabSBorislav Petkov x86_del_exclusive(x86_lbr_exclusive_bts);
546af5d3aabSBorislav Petkov }
547af5d3aabSBorislav Petkov
bts_event_init(struct perf_event * event)548af5d3aabSBorislav Petkov static int bts_event_init(struct perf_event *event)
549af5d3aabSBorislav Petkov {
550af5d3aabSBorislav Petkov int ret;
551af5d3aabSBorislav Petkov
552af5d3aabSBorislav Petkov if (event->attr.type != bts_pmu.type)
553af5d3aabSBorislav Petkov return -ENOENT;
554af5d3aabSBorislav Petkov
555af5d3aabSBorislav Petkov /*
556af5d3aabSBorislav Petkov * BTS leaks kernel addresses even when CPL0 tracing is
557af5d3aabSBorislav Petkov * disabled, so disallow intel_bts driver for unprivileged
558af5d3aabSBorislav Petkov * users on paranoid systems since it provides trace data
559af5d3aabSBorislav Petkov * to the user in a zero-copy fashion.
560af5d3aabSBorislav Petkov */
561da97e184SJoel Fernandes (Google) if (event->attr.exclude_kernel) {
562da97e184SJoel Fernandes (Google) ret = perf_allow_kernel(&event->attr);
563da97e184SJoel Fernandes (Google) if (ret)
564da97e184SJoel Fernandes (Google) return ret;
565da97e184SJoel Fernandes (Google) }
566af5d3aabSBorislav Petkov
5672eece390SAlexander Shishkin if (x86_add_exclusive(x86_lbr_exclusive_bts))
5682eece390SAlexander Shishkin return -EBUSY;
5692eece390SAlexander Shishkin
570af5d3aabSBorislav Petkov ret = x86_reserve_hardware();
571af5d3aabSBorislav Petkov if (ret) {
572af5d3aabSBorislav Petkov x86_del_exclusive(x86_lbr_exclusive_bts);
573af5d3aabSBorislav Petkov return ret;
574af5d3aabSBorislav Petkov }
575af5d3aabSBorislav Petkov
576af5d3aabSBorislav Petkov event->destroy = bts_event_destroy;
577af5d3aabSBorislav Petkov
578af5d3aabSBorislav Petkov return 0;
579af5d3aabSBorislav Petkov }
580af5d3aabSBorislav Petkov
bts_event_read(struct perf_event * event)581af5d3aabSBorislav Petkov static void bts_event_read(struct perf_event *event)
582af5d3aabSBorislav Petkov {
583af5d3aabSBorislav Petkov }
584af5d3aabSBorislav Petkov
bts_init(void)585af5d3aabSBorislav Petkov static __init int bts_init(void)
586af5d3aabSBorislav Petkov {
587af5d3aabSBorislav Petkov if (!boot_cpu_has(X86_FEATURE_DTES64) || !x86_pmu.bts)
588af5d3aabSBorislav Petkov return -ENODEV;
589af5d3aabSBorislav Petkov
59099a9dc98SPeter Zijlstra if (boot_cpu_has(X86_FEATURE_PTI)) {
59199a9dc98SPeter Zijlstra /*
59299a9dc98SPeter Zijlstra * BTS hardware writes through a virtual memory map we must
59399a9dc98SPeter Zijlstra * either use the kernel physical map, or the user mapping of
59499a9dc98SPeter Zijlstra * the AUX buffer.
59599a9dc98SPeter Zijlstra *
59699a9dc98SPeter Zijlstra * However, since this driver supports per-CPU and per-task inherit
597a97673a1SIngo Molnar * we cannot use the user mapping since it will not be available
59899a9dc98SPeter Zijlstra * if we're not running the owning process.
59999a9dc98SPeter Zijlstra *
600163b0991SIngo Molnar * With PTI we can't use the kernel map either, because its not
60199a9dc98SPeter Zijlstra * there when we run userspace.
60299a9dc98SPeter Zijlstra *
60399a9dc98SPeter Zijlstra * For now, disable this driver when using PTI.
60499a9dc98SPeter Zijlstra */
60599a9dc98SPeter Zijlstra return -ENODEV;
60699a9dc98SPeter Zijlstra }
60799a9dc98SPeter Zijlstra
60808b90f06SAlexander Shishkin bts_pmu.capabilities = PERF_PMU_CAP_AUX_NO_SG | PERF_PMU_CAP_ITRACE |
60908b90f06SAlexander Shishkin PERF_PMU_CAP_EXCLUSIVE;
610af5d3aabSBorislav Petkov bts_pmu.task_ctx_nr = perf_sw_context;
611af5d3aabSBorislav Petkov bts_pmu.event_init = bts_event_init;
612af5d3aabSBorislav Petkov bts_pmu.add = bts_event_add;
613af5d3aabSBorislav Petkov bts_pmu.del = bts_event_del;
614af5d3aabSBorislav Petkov bts_pmu.start = bts_event_start;
615af5d3aabSBorislav Petkov bts_pmu.stop = bts_event_stop;
616af5d3aabSBorislav Petkov bts_pmu.read = bts_event_read;
617af5d3aabSBorislav Petkov bts_pmu.setup_aux = bts_buffer_setup_aux;
618af5d3aabSBorislav Petkov bts_pmu.free_aux = bts_buffer_free_aux;
619af5d3aabSBorislav Petkov
620af5d3aabSBorislav Petkov return perf_pmu_register(&bts_pmu, "intel_bts", -1);
621af5d3aabSBorislav Petkov }
622af5d3aabSBorislav Petkov arch_initcall(bts_init);
623