xref: /linux/arch/x86/events/intel/bts.c (revision 3a39d672e7f48b8d6b91a09afa4b55352773b4b5)
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