xref: /linux/kernel/trace/trace_remote.c (revision 96e43537af5461b26f50904c6055046ba65d742f)
1*96e43537SVincent Donnefort // SPDX-License-Identifier: GPL-2.0
2*96e43537SVincent Donnefort /*
3*96e43537SVincent Donnefort  * Copyright (C) 2025 - Google LLC
4*96e43537SVincent Donnefort  * Author: Vincent Donnefort <vdonnefort@google.com>
5*96e43537SVincent Donnefort  */
6*96e43537SVincent Donnefort 
7*96e43537SVincent Donnefort #include <linux/kstrtox.h>
8*96e43537SVincent Donnefort #include <linux/lockdep.h>
9*96e43537SVincent Donnefort #include <linux/mutex.h>
10*96e43537SVincent Donnefort #include <linux/tracefs.h>
11*96e43537SVincent Donnefort #include <linux/trace_remote.h>
12*96e43537SVincent Donnefort #include <linux/trace_seq.h>
13*96e43537SVincent Donnefort #include <linux/types.h>
14*96e43537SVincent Donnefort 
15*96e43537SVincent Donnefort #include "trace.h"
16*96e43537SVincent Donnefort 
17*96e43537SVincent Donnefort #define TRACEFS_DIR		"remotes"
18*96e43537SVincent Donnefort #define TRACEFS_MODE_WRITE	0640
19*96e43537SVincent Donnefort #define TRACEFS_MODE_READ	0440
20*96e43537SVincent Donnefort 
21*96e43537SVincent Donnefort struct trace_remote_iterator {
22*96e43537SVincent Donnefort 	struct trace_remote		*remote;
23*96e43537SVincent Donnefort 	struct trace_seq		seq;
24*96e43537SVincent Donnefort 	struct delayed_work		poll_work;
25*96e43537SVincent Donnefort 	unsigned long			lost_events;
26*96e43537SVincent Donnefort 	u64				ts;
27*96e43537SVincent Donnefort 	int				cpu;
28*96e43537SVincent Donnefort 	int				evt_cpu;
29*96e43537SVincent Donnefort };
30*96e43537SVincent Donnefort 
31*96e43537SVincent Donnefort struct trace_remote {
32*96e43537SVincent Donnefort 	struct trace_remote_callbacks	*cbs;
33*96e43537SVincent Donnefort 	void				*priv;
34*96e43537SVincent Donnefort 	struct trace_buffer		*trace_buffer;
35*96e43537SVincent Donnefort 	struct trace_buffer_desc	*trace_buffer_desc;
36*96e43537SVincent Donnefort 	unsigned long			trace_buffer_size;
37*96e43537SVincent Donnefort 	struct ring_buffer_remote	rb_remote;
38*96e43537SVincent Donnefort 	struct mutex			lock;
39*96e43537SVincent Donnefort 	unsigned int			nr_readers;
40*96e43537SVincent Donnefort 	unsigned int			poll_ms;
41*96e43537SVincent Donnefort 	bool				tracing_on;
42*96e43537SVincent Donnefort };
43*96e43537SVincent Donnefort 
44*96e43537SVincent Donnefort static bool trace_remote_loaded(struct trace_remote *remote)
45*96e43537SVincent Donnefort {
46*96e43537SVincent Donnefort 	return !!remote->trace_buffer;
47*96e43537SVincent Donnefort }
48*96e43537SVincent Donnefort 
49*96e43537SVincent Donnefort static int trace_remote_load(struct trace_remote *remote)
50*96e43537SVincent Donnefort {
51*96e43537SVincent Donnefort 	struct ring_buffer_remote *rb_remote = &remote->rb_remote;
52*96e43537SVincent Donnefort 	struct trace_buffer_desc *desc;
53*96e43537SVincent Donnefort 
54*96e43537SVincent Donnefort 	lockdep_assert_held(&remote->lock);
55*96e43537SVincent Donnefort 
56*96e43537SVincent Donnefort 	if (trace_remote_loaded(remote))
57*96e43537SVincent Donnefort 		return 0;
58*96e43537SVincent Donnefort 
59*96e43537SVincent Donnefort 	desc = remote->cbs->load_trace_buffer(remote->trace_buffer_size, remote->priv);
60*96e43537SVincent Donnefort 	if (IS_ERR(desc))
61*96e43537SVincent Donnefort 		return PTR_ERR(desc);
62*96e43537SVincent Donnefort 
63*96e43537SVincent Donnefort 	rb_remote->desc = desc;
64*96e43537SVincent Donnefort 	rb_remote->swap_reader_page = remote->cbs->swap_reader_page;
65*96e43537SVincent Donnefort 	rb_remote->priv = remote->priv;
66*96e43537SVincent Donnefort 	remote->trace_buffer = ring_buffer_alloc_remote(rb_remote);
67*96e43537SVincent Donnefort 	if (!remote->trace_buffer) {
68*96e43537SVincent Donnefort 		remote->cbs->unload_trace_buffer(desc, remote->priv);
69*96e43537SVincent Donnefort 		return -ENOMEM;
70*96e43537SVincent Donnefort 	}
71*96e43537SVincent Donnefort 
72*96e43537SVincent Donnefort 	remote->trace_buffer_desc = desc;
73*96e43537SVincent Donnefort 
74*96e43537SVincent Donnefort 	return 0;
75*96e43537SVincent Donnefort }
76*96e43537SVincent Donnefort 
77*96e43537SVincent Donnefort static void trace_remote_try_unload(struct trace_remote *remote)
78*96e43537SVincent Donnefort {
79*96e43537SVincent Donnefort 	lockdep_assert_held(&remote->lock);
80*96e43537SVincent Donnefort 
81*96e43537SVincent Donnefort 	if (!trace_remote_loaded(remote))
82*96e43537SVincent Donnefort 		return;
83*96e43537SVincent Donnefort 
84*96e43537SVincent Donnefort 	/* The buffer is being read or writable */
85*96e43537SVincent Donnefort 	if (remote->nr_readers || remote->tracing_on)
86*96e43537SVincent Donnefort 		return;
87*96e43537SVincent Donnefort 
88*96e43537SVincent Donnefort 	/* The buffer has readable data */
89*96e43537SVincent Donnefort 	if (!ring_buffer_empty(remote->trace_buffer))
90*96e43537SVincent Donnefort 		return;
91*96e43537SVincent Donnefort 
92*96e43537SVincent Donnefort 	ring_buffer_free(remote->trace_buffer);
93*96e43537SVincent Donnefort 	remote->trace_buffer = NULL;
94*96e43537SVincent Donnefort 	remote->cbs->unload_trace_buffer(remote->trace_buffer_desc, remote->priv);
95*96e43537SVincent Donnefort }
96*96e43537SVincent Donnefort 
97*96e43537SVincent Donnefort static int trace_remote_enable_tracing(struct trace_remote *remote)
98*96e43537SVincent Donnefort {
99*96e43537SVincent Donnefort 	int ret;
100*96e43537SVincent Donnefort 
101*96e43537SVincent Donnefort 	lockdep_assert_held(&remote->lock);
102*96e43537SVincent Donnefort 
103*96e43537SVincent Donnefort 	if (remote->tracing_on)
104*96e43537SVincent Donnefort 		return 0;
105*96e43537SVincent Donnefort 
106*96e43537SVincent Donnefort 	ret = trace_remote_load(remote);
107*96e43537SVincent Donnefort 	if (ret)
108*96e43537SVincent Donnefort 		return ret;
109*96e43537SVincent Donnefort 
110*96e43537SVincent Donnefort 	ret = remote->cbs->enable_tracing(true, remote->priv);
111*96e43537SVincent Donnefort 	if (ret) {
112*96e43537SVincent Donnefort 		trace_remote_try_unload(remote);
113*96e43537SVincent Donnefort 		return ret;
114*96e43537SVincent Donnefort 	}
115*96e43537SVincent Donnefort 
116*96e43537SVincent Donnefort 	remote->tracing_on = true;
117*96e43537SVincent Donnefort 
118*96e43537SVincent Donnefort 	return 0;
119*96e43537SVincent Donnefort }
120*96e43537SVincent Donnefort 
121*96e43537SVincent Donnefort static int trace_remote_disable_tracing(struct trace_remote *remote)
122*96e43537SVincent Donnefort {
123*96e43537SVincent Donnefort 	int ret;
124*96e43537SVincent Donnefort 
125*96e43537SVincent Donnefort 	lockdep_assert_held(&remote->lock);
126*96e43537SVincent Donnefort 
127*96e43537SVincent Donnefort 	if (!remote->tracing_on)
128*96e43537SVincent Donnefort 		return 0;
129*96e43537SVincent Donnefort 
130*96e43537SVincent Donnefort 	ret = remote->cbs->enable_tracing(false, remote->priv);
131*96e43537SVincent Donnefort 	if (ret)
132*96e43537SVincent Donnefort 		return ret;
133*96e43537SVincent Donnefort 
134*96e43537SVincent Donnefort 	ring_buffer_poll_remote(remote->trace_buffer, RING_BUFFER_ALL_CPUS);
135*96e43537SVincent Donnefort 	remote->tracing_on = false;
136*96e43537SVincent Donnefort 	trace_remote_try_unload(remote);
137*96e43537SVincent Donnefort 
138*96e43537SVincent Donnefort 	return 0;
139*96e43537SVincent Donnefort }
140*96e43537SVincent Donnefort 
141*96e43537SVincent Donnefort static ssize_t
142*96e43537SVincent Donnefort tracing_on_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
143*96e43537SVincent Donnefort {
144*96e43537SVincent Donnefort 	struct trace_remote *remote = filp->private_data;
145*96e43537SVincent Donnefort 	unsigned long val;
146*96e43537SVincent Donnefort 	int ret;
147*96e43537SVincent Donnefort 
148*96e43537SVincent Donnefort 	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
149*96e43537SVincent Donnefort 	if (ret)
150*96e43537SVincent Donnefort 		return ret;
151*96e43537SVincent Donnefort 
152*96e43537SVincent Donnefort 	guard(mutex)(&remote->lock);
153*96e43537SVincent Donnefort 
154*96e43537SVincent Donnefort 	ret = val ? trace_remote_enable_tracing(remote) : trace_remote_disable_tracing(remote);
155*96e43537SVincent Donnefort 	if (ret)
156*96e43537SVincent Donnefort 		return ret;
157*96e43537SVincent Donnefort 
158*96e43537SVincent Donnefort 	return cnt;
159*96e43537SVincent Donnefort }
160*96e43537SVincent Donnefort static int tracing_on_show(struct seq_file *s, void *unused)
161*96e43537SVincent Donnefort {
162*96e43537SVincent Donnefort 	struct trace_remote *remote = s->private;
163*96e43537SVincent Donnefort 
164*96e43537SVincent Donnefort 	seq_printf(s, "%d\n", remote->tracing_on);
165*96e43537SVincent Donnefort 
166*96e43537SVincent Donnefort 	return 0;
167*96e43537SVincent Donnefort }
168*96e43537SVincent Donnefort DEFINE_SHOW_STORE_ATTRIBUTE(tracing_on);
169*96e43537SVincent Donnefort 
170*96e43537SVincent Donnefort static ssize_t buffer_size_kb_write(struct file *filp, const char __user *ubuf, size_t cnt,
171*96e43537SVincent Donnefort 				    loff_t *ppos)
172*96e43537SVincent Donnefort {
173*96e43537SVincent Donnefort 	struct trace_remote *remote = filp->private_data;
174*96e43537SVincent Donnefort 	unsigned long val;
175*96e43537SVincent Donnefort 	int ret;
176*96e43537SVincent Donnefort 
177*96e43537SVincent Donnefort 	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
178*96e43537SVincent Donnefort 	if (ret)
179*96e43537SVincent Donnefort 		return ret;
180*96e43537SVincent Donnefort 
181*96e43537SVincent Donnefort 	/* KiB to Bytes */
182*96e43537SVincent Donnefort 	if (!val || check_shl_overflow(val, 10, &val))
183*96e43537SVincent Donnefort 		return -EINVAL;
184*96e43537SVincent Donnefort 
185*96e43537SVincent Donnefort 	guard(mutex)(&remote->lock);
186*96e43537SVincent Donnefort 
187*96e43537SVincent Donnefort 	if (trace_remote_loaded(remote))
188*96e43537SVincent Donnefort 		return -EBUSY;
189*96e43537SVincent Donnefort 
190*96e43537SVincent Donnefort 	remote->trace_buffer_size = val;
191*96e43537SVincent Donnefort 
192*96e43537SVincent Donnefort 	return cnt;
193*96e43537SVincent Donnefort }
194*96e43537SVincent Donnefort 
195*96e43537SVincent Donnefort static int buffer_size_kb_show(struct seq_file *s, void *unused)
196*96e43537SVincent Donnefort {
197*96e43537SVincent Donnefort 	struct trace_remote *remote = s->private;
198*96e43537SVincent Donnefort 
199*96e43537SVincent Donnefort 	seq_printf(s, "%lu (%s)\n", remote->trace_buffer_size >> 10,
200*96e43537SVincent Donnefort 		   trace_remote_loaded(remote) ? "loaded" : "unloaded");
201*96e43537SVincent Donnefort 
202*96e43537SVincent Donnefort 	return 0;
203*96e43537SVincent Donnefort }
204*96e43537SVincent Donnefort DEFINE_SHOW_STORE_ATTRIBUTE(buffer_size_kb);
205*96e43537SVincent Donnefort 
206*96e43537SVincent Donnefort static int trace_remote_get(struct trace_remote *remote, int cpu)
207*96e43537SVincent Donnefort {
208*96e43537SVincent Donnefort 	int ret;
209*96e43537SVincent Donnefort 
210*96e43537SVincent Donnefort 	if (remote->nr_readers == UINT_MAX)
211*96e43537SVincent Donnefort 		return -EBUSY;
212*96e43537SVincent Donnefort 
213*96e43537SVincent Donnefort 	ret = trace_remote_load(remote);
214*96e43537SVincent Donnefort 	if (ret)
215*96e43537SVincent Donnefort 		return ret;
216*96e43537SVincent Donnefort 
217*96e43537SVincent Donnefort 	remote->nr_readers++;
218*96e43537SVincent Donnefort 
219*96e43537SVincent Donnefort 	return 0;
220*96e43537SVincent Donnefort }
221*96e43537SVincent Donnefort 
222*96e43537SVincent Donnefort static void trace_remote_put(struct trace_remote *remote)
223*96e43537SVincent Donnefort {
224*96e43537SVincent Donnefort 	if (WARN_ON(!remote->nr_readers))
225*96e43537SVincent Donnefort 		return;
226*96e43537SVincent Donnefort 
227*96e43537SVincent Donnefort 	remote->nr_readers--;
228*96e43537SVincent Donnefort 	if (remote->nr_readers)
229*96e43537SVincent Donnefort 		return;
230*96e43537SVincent Donnefort 
231*96e43537SVincent Donnefort 	trace_remote_try_unload(remote);
232*96e43537SVincent Donnefort }
233*96e43537SVincent Donnefort 
234*96e43537SVincent Donnefort static void __poll_remote(struct work_struct *work)
235*96e43537SVincent Donnefort {
236*96e43537SVincent Donnefort 	struct delayed_work *dwork = to_delayed_work(work);
237*96e43537SVincent Donnefort 	struct trace_remote_iterator *iter;
238*96e43537SVincent Donnefort 
239*96e43537SVincent Donnefort 	iter = container_of(dwork, struct trace_remote_iterator, poll_work);
240*96e43537SVincent Donnefort 	ring_buffer_poll_remote(iter->remote->trace_buffer, iter->cpu);
241*96e43537SVincent Donnefort 	schedule_delayed_work((struct delayed_work *)work,
242*96e43537SVincent Donnefort 			      msecs_to_jiffies(iter->remote->poll_ms));
243*96e43537SVincent Donnefort }
244*96e43537SVincent Donnefort 
245*96e43537SVincent Donnefort static struct trace_remote_iterator *trace_remote_iter(struct trace_remote *remote, int cpu)
246*96e43537SVincent Donnefort {
247*96e43537SVincent Donnefort 	struct trace_remote_iterator *iter = NULL;
248*96e43537SVincent Donnefort 	int ret;
249*96e43537SVincent Donnefort 
250*96e43537SVincent Donnefort 	lockdep_assert_held(&remote->lock);
251*96e43537SVincent Donnefort 
252*96e43537SVincent Donnefort 
253*96e43537SVincent Donnefort 	ret = trace_remote_get(remote, cpu);
254*96e43537SVincent Donnefort 	if (ret)
255*96e43537SVincent Donnefort 		return ERR_PTR(ret);
256*96e43537SVincent Donnefort 
257*96e43537SVincent Donnefort 	/* Test the CPU */
258*96e43537SVincent Donnefort 	ret = ring_buffer_poll_remote(remote->trace_buffer, cpu);
259*96e43537SVincent Donnefort 	if (ret)
260*96e43537SVincent Donnefort 		goto err;
261*96e43537SVincent Donnefort 
262*96e43537SVincent Donnefort 	iter = kzalloc_obj(*iter);
263*96e43537SVincent Donnefort 	if (iter) {
264*96e43537SVincent Donnefort 		iter->remote = remote;
265*96e43537SVincent Donnefort 		iter->cpu = cpu;
266*96e43537SVincent Donnefort 		trace_seq_init(&iter->seq);
267*96e43537SVincent Donnefort 		INIT_DELAYED_WORK(&iter->poll_work, __poll_remote);
268*96e43537SVincent Donnefort 		schedule_delayed_work(&iter->poll_work, msecs_to_jiffies(remote->poll_ms));
269*96e43537SVincent Donnefort 
270*96e43537SVincent Donnefort 		return iter;
271*96e43537SVincent Donnefort 	}
272*96e43537SVincent Donnefort 	ret = -ENOMEM;
273*96e43537SVincent Donnefort 
274*96e43537SVincent Donnefort err:
275*96e43537SVincent Donnefort 	kfree(iter);
276*96e43537SVincent Donnefort 	trace_remote_put(remote);
277*96e43537SVincent Donnefort 
278*96e43537SVincent Donnefort 	return ERR_PTR(ret);
279*96e43537SVincent Donnefort }
280*96e43537SVincent Donnefort 
281*96e43537SVincent Donnefort static void trace_remote_iter_free(struct trace_remote_iterator *iter)
282*96e43537SVincent Donnefort {
283*96e43537SVincent Donnefort 	struct trace_remote *remote;
284*96e43537SVincent Donnefort 
285*96e43537SVincent Donnefort 	if (!iter)
286*96e43537SVincent Donnefort 		return;
287*96e43537SVincent Donnefort 
288*96e43537SVincent Donnefort 	remote = iter->remote;
289*96e43537SVincent Donnefort 
290*96e43537SVincent Donnefort 	lockdep_assert_held(&remote->lock);
291*96e43537SVincent Donnefort 
292*96e43537SVincent Donnefort 	kfree(iter);
293*96e43537SVincent Donnefort 	trace_remote_put(remote);
294*96e43537SVincent Donnefort }
295*96e43537SVincent Donnefort 
296*96e43537SVincent Donnefort static bool trace_remote_iter_read_event(struct trace_remote_iterator *iter)
297*96e43537SVincent Donnefort {
298*96e43537SVincent Donnefort 	struct trace_buffer *trace_buffer = iter->remote->trace_buffer;
299*96e43537SVincent Donnefort 	int cpu = iter->cpu;
300*96e43537SVincent Donnefort 
301*96e43537SVincent Donnefort 	if (cpu != RING_BUFFER_ALL_CPUS) {
302*96e43537SVincent Donnefort 		if (ring_buffer_empty_cpu(trace_buffer, cpu))
303*96e43537SVincent Donnefort 			return false;
304*96e43537SVincent Donnefort 
305*96e43537SVincent Donnefort 		if (!ring_buffer_peek(trace_buffer, cpu, &iter->ts, &iter->lost_events))
306*96e43537SVincent Donnefort 			return false;
307*96e43537SVincent Donnefort 
308*96e43537SVincent Donnefort 		iter->evt_cpu = cpu;
309*96e43537SVincent Donnefort 		return true;
310*96e43537SVincent Donnefort 	}
311*96e43537SVincent Donnefort 
312*96e43537SVincent Donnefort 	iter->ts = U64_MAX;
313*96e43537SVincent Donnefort 	for_each_possible_cpu(cpu) {
314*96e43537SVincent Donnefort 		unsigned long lost_events;
315*96e43537SVincent Donnefort 		u64 ts;
316*96e43537SVincent Donnefort 
317*96e43537SVincent Donnefort 		if (ring_buffer_empty_cpu(trace_buffer, cpu))
318*96e43537SVincent Donnefort 			continue;
319*96e43537SVincent Donnefort 
320*96e43537SVincent Donnefort 		if (!ring_buffer_peek(trace_buffer, cpu, &ts, &lost_events))
321*96e43537SVincent Donnefort 			continue;
322*96e43537SVincent Donnefort 
323*96e43537SVincent Donnefort 		if (ts >= iter->ts)
324*96e43537SVincent Donnefort 			continue;
325*96e43537SVincent Donnefort 
326*96e43537SVincent Donnefort 		iter->ts = ts;
327*96e43537SVincent Donnefort 		iter->evt_cpu = cpu;
328*96e43537SVincent Donnefort 		iter->lost_events = lost_events;
329*96e43537SVincent Donnefort 	}
330*96e43537SVincent Donnefort 
331*96e43537SVincent Donnefort 	return iter->ts != U64_MAX;
332*96e43537SVincent Donnefort }
333*96e43537SVincent Donnefort 
334*96e43537SVincent Donnefort static int trace_remote_iter_print_event(struct trace_remote_iterator *iter)
335*96e43537SVincent Donnefort {
336*96e43537SVincent Donnefort 	unsigned long usecs_rem;
337*96e43537SVincent Donnefort 	u64 ts = iter->ts;
338*96e43537SVincent Donnefort 
339*96e43537SVincent Donnefort 	if (iter->lost_events)
340*96e43537SVincent Donnefort 		trace_seq_printf(&iter->seq, "CPU:%d [LOST %lu EVENTS]\n",
341*96e43537SVincent Donnefort 				 iter->evt_cpu, iter->lost_events);
342*96e43537SVincent Donnefort 
343*96e43537SVincent Donnefort 	do_div(ts, 1000);
344*96e43537SVincent Donnefort 	usecs_rem = do_div(ts, USEC_PER_SEC);
345*96e43537SVincent Donnefort 
346*96e43537SVincent Donnefort 	trace_seq_printf(&iter->seq, "[%03d]\t%5llu.%06lu: ", iter->evt_cpu,
347*96e43537SVincent Donnefort 			 ts, usecs_rem);
348*96e43537SVincent Donnefort 
349*96e43537SVincent Donnefort 	return trace_seq_has_overflowed(&iter->seq) ? -EOVERFLOW : 0;
350*96e43537SVincent Donnefort }
351*96e43537SVincent Donnefort 
352*96e43537SVincent Donnefort static int trace_pipe_open(struct inode *inode, struct file *filp)
353*96e43537SVincent Donnefort {
354*96e43537SVincent Donnefort 	struct trace_remote *remote = inode->i_private;
355*96e43537SVincent Donnefort 	struct trace_remote_iterator *iter;
356*96e43537SVincent Donnefort 	int cpu = RING_BUFFER_ALL_CPUS;
357*96e43537SVincent Donnefort 
358*96e43537SVincent Donnefort 	if (inode->i_cdev)
359*96e43537SVincent Donnefort 		cpu = (long)inode->i_cdev - 1;
360*96e43537SVincent Donnefort 
361*96e43537SVincent Donnefort 	guard(mutex)(&remote->lock);
362*96e43537SVincent Donnefort 	iter = trace_remote_iter(remote, cpu);
363*96e43537SVincent Donnefort 	filp->private_data = iter;
364*96e43537SVincent Donnefort 
365*96e43537SVincent Donnefort 	return IS_ERR(iter) ? PTR_ERR(iter) : 0;
366*96e43537SVincent Donnefort }
367*96e43537SVincent Donnefort 
368*96e43537SVincent Donnefort static int trace_pipe_release(struct inode *inode, struct file *filp)
369*96e43537SVincent Donnefort {
370*96e43537SVincent Donnefort 	struct trace_remote_iterator *iter = filp->private_data;
371*96e43537SVincent Donnefort 	struct trace_remote *remote = iter->remote;
372*96e43537SVincent Donnefort 
373*96e43537SVincent Donnefort 	guard(mutex)(&remote->lock);
374*96e43537SVincent Donnefort 
375*96e43537SVincent Donnefort 	trace_remote_iter_free(iter);
376*96e43537SVincent Donnefort 
377*96e43537SVincent Donnefort 	return 0;
378*96e43537SVincent Donnefort }
379*96e43537SVincent Donnefort 
380*96e43537SVincent Donnefort static ssize_t trace_pipe_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
381*96e43537SVincent Donnefort {
382*96e43537SVincent Donnefort 	struct trace_remote_iterator *iter = filp->private_data;
383*96e43537SVincent Donnefort 	struct trace_buffer *trace_buffer = iter->remote->trace_buffer;
384*96e43537SVincent Donnefort 	int ret;
385*96e43537SVincent Donnefort 
386*96e43537SVincent Donnefort copy_to_user:
387*96e43537SVincent Donnefort 	ret = trace_seq_to_user(&iter->seq, ubuf, cnt);
388*96e43537SVincent Donnefort 	if (ret != -EBUSY)
389*96e43537SVincent Donnefort 		return ret;
390*96e43537SVincent Donnefort 
391*96e43537SVincent Donnefort 	trace_seq_init(&iter->seq);
392*96e43537SVincent Donnefort 
393*96e43537SVincent Donnefort 	ret = ring_buffer_wait(trace_buffer, iter->cpu, 0, NULL, NULL);
394*96e43537SVincent Donnefort 	if (ret < 0)
395*96e43537SVincent Donnefort 		return ret;
396*96e43537SVincent Donnefort 
397*96e43537SVincent Donnefort 	while (trace_remote_iter_read_event(iter)) {
398*96e43537SVincent Donnefort 		int prev_len = iter->seq.seq.len;
399*96e43537SVincent Donnefort 
400*96e43537SVincent Donnefort 		if (trace_remote_iter_print_event(iter)) {
401*96e43537SVincent Donnefort 			iter->seq.seq.len = prev_len;
402*96e43537SVincent Donnefort 			break;
403*96e43537SVincent Donnefort 		}
404*96e43537SVincent Donnefort 
405*96e43537SVincent Donnefort 		ring_buffer_consume(trace_buffer, iter->evt_cpu, NULL, NULL);
406*96e43537SVincent Donnefort 	}
407*96e43537SVincent Donnefort 
408*96e43537SVincent Donnefort 	goto copy_to_user;
409*96e43537SVincent Donnefort }
410*96e43537SVincent Donnefort 
411*96e43537SVincent Donnefort static const struct file_operations trace_pipe_fops = {
412*96e43537SVincent Donnefort 	.open		= trace_pipe_open,
413*96e43537SVincent Donnefort 	.read		= trace_pipe_read,
414*96e43537SVincent Donnefort 	.release	= trace_pipe_release,
415*96e43537SVincent Donnefort };
416*96e43537SVincent Donnefort 
417*96e43537SVincent Donnefort static int trace_remote_init_tracefs(const char *name, struct trace_remote *remote)
418*96e43537SVincent Donnefort {
419*96e43537SVincent Donnefort 	struct dentry *remote_d, *percpu_d, *d;
420*96e43537SVincent Donnefort 	static struct dentry *root;
421*96e43537SVincent Donnefort 	static DEFINE_MUTEX(lock);
422*96e43537SVincent Donnefort 	bool root_inited = false;
423*96e43537SVincent Donnefort 	int cpu;
424*96e43537SVincent Donnefort 
425*96e43537SVincent Donnefort 	guard(mutex)(&lock);
426*96e43537SVincent Donnefort 
427*96e43537SVincent Donnefort 	if (!root) {
428*96e43537SVincent Donnefort 		root = tracefs_create_dir(TRACEFS_DIR, NULL);
429*96e43537SVincent Donnefort 		if (!root) {
430*96e43537SVincent Donnefort 			pr_err("Failed to create tracefs dir "TRACEFS_DIR"\n");
431*96e43537SVincent Donnefort 			return -ENOMEM;
432*96e43537SVincent Donnefort 		}
433*96e43537SVincent Donnefort 		root_inited = true;
434*96e43537SVincent Donnefort 	}
435*96e43537SVincent Donnefort 
436*96e43537SVincent Donnefort 	remote_d = tracefs_create_dir(name, root);
437*96e43537SVincent Donnefort 	if (!remote_d) {
438*96e43537SVincent Donnefort 		pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/\n", name);
439*96e43537SVincent Donnefort 		goto err;
440*96e43537SVincent Donnefort 	}
441*96e43537SVincent Donnefort 
442*96e43537SVincent Donnefort 	d = trace_create_file("tracing_on", TRACEFS_MODE_WRITE, remote_d, remote, &tracing_on_fops);
443*96e43537SVincent Donnefort 	if (!d)
444*96e43537SVincent Donnefort 		goto err;
445*96e43537SVincent Donnefort 
446*96e43537SVincent Donnefort 	d = trace_create_file("buffer_size_kb", TRACEFS_MODE_WRITE, remote_d, remote,
447*96e43537SVincent Donnefort 			      &buffer_size_kb_fops);
448*96e43537SVincent Donnefort 	if (!d)
449*96e43537SVincent Donnefort 		goto err;
450*96e43537SVincent Donnefort 
451*96e43537SVincent Donnefort 	d = trace_create_file("trace_pipe", TRACEFS_MODE_READ, remote_d, remote, &trace_pipe_fops);
452*96e43537SVincent Donnefort 	if (!d)
453*96e43537SVincent Donnefort 		goto err;
454*96e43537SVincent Donnefort 
455*96e43537SVincent Donnefort 	percpu_d = tracefs_create_dir("per_cpu", remote_d);
456*96e43537SVincent Donnefort 	if (!percpu_d) {
457*96e43537SVincent Donnefort 		pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/per_cpu/\n", name);
458*96e43537SVincent Donnefort 		goto err;
459*96e43537SVincent Donnefort 	}
460*96e43537SVincent Donnefort 
461*96e43537SVincent Donnefort 	for_each_possible_cpu(cpu) {
462*96e43537SVincent Donnefort 		struct dentry *cpu_d;
463*96e43537SVincent Donnefort 		char cpu_name[16];
464*96e43537SVincent Donnefort 
465*96e43537SVincent Donnefort 		snprintf(cpu_name, sizeof(cpu_name), "cpu%d", cpu);
466*96e43537SVincent Donnefort 		cpu_d = tracefs_create_dir(cpu_name, percpu_d);
467*96e43537SVincent Donnefort 		if (!cpu_d) {
468*96e43537SVincent Donnefort 			pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/percpu/cpu%d\n",
469*96e43537SVincent Donnefort 			       name, cpu);
470*96e43537SVincent Donnefort 			goto err;
471*96e43537SVincent Donnefort 		}
472*96e43537SVincent Donnefort 
473*96e43537SVincent Donnefort 		d = trace_create_cpu_file("trace_pipe", TRACEFS_MODE_READ, cpu_d, remote, cpu,
474*96e43537SVincent Donnefort 					  &trace_pipe_fops);
475*96e43537SVincent Donnefort 		if (!d)
476*96e43537SVincent Donnefort 			goto err;
477*96e43537SVincent Donnefort 	}
478*96e43537SVincent Donnefort 
479*96e43537SVincent Donnefort 	return 0;
480*96e43537SVincent Donnefort 
481*96e43537SVincent Donnefort err:
482*96e43537SVincent Donnefort 	if (root_inited) {
483*96e43537SVincent Donnefort 		tracefs_remove(root);
484*96e43537SVincent Donnefort 		root = NULL;
485*96e43537SVincent Donnefort 	} else {
486*96e43537SVincent Donnefort 		tracefs_remove(remote_d);
487*96e43537SVincent Donnefort 	}
488*96e43537SVincent Donnefort 
489*96e43537SVincent Donnefort 	return -ENOMEM;
490*96e43537SVincent Donnefort }
491*96e43537SVincent Donnefort 
492*96e43537SVincent Donnefort /**
493*96e43537SVincent Donnefort  * trace_remote_register() - Register a Tracefs remote
494*96e43537SVincent Donnefort  * @name:	Name of the remote, used for the Tracefs remotes/ directory.
495*96e43537SVincent Donnefort  * @cbs:	Set of callbacks used to control the remote.
496*96e43537SVincent Donnefort  * @priv:	Private data, passed to each callback from @cbs.
497*96e43537SVincent Donnefort  * @events:	Array of events. &remote_event.name and &remote_event.id must be
498*96e43537SVincent Donnefort  *		filled by the caller.
499*96e43537SVincent Donnefort  * @nr_events:	Number of events in the @events array.
500*96e43537SVincent Donnefort  *
501*96e43537SVincent Donnefort  * A trace remote is an entity, outside of the kernel (most likely firmware or
502*96e43537SVincent Donnefort  * hypervisor) capable of writing events into a Tracefs compatible ring-buffer.
503*96e43537SVincent Donnefort  * The kernel would then act as a reader.
504*96e43537SVincent Donnefort  *
505*96e43537SVincent Donnefort  * The registered remote will be found under the Tracefs directory
506*96e43537SVincent Donnefort  * remotes/<name>.
507*96e43537SVincent Donnefort  *
508*96e43537SVincent Donnefort  * Return: 0 on success, negative error code on failure.
509*96e43537SVincent Donnefort  */
510*96e43537SVincent Donnefort int trace_remote_register(const char *name, struct trace_remote_callbacks *cbs, void *priv)
511*96e43537SVincent Donnefort {
512*96e43537SVincent Donnefort 	struct trace_remote *remote;
513*96e43537SVincent Donnefort 
514*96e43537SVincent Donnefort 	remote = kzalloc_obj(*remote);
515*96e43537SVincent Donnefort 	if (!remote)
516*96e43537SVincent Donnefort 		return -ENOMEM;
517*96e43537SVincent Donnefort 
518*96e43537SVincent Donnefort 	remote->cbs = cbs;
519*96e43537SVincent Donnefort 	remote->priv = priv;
520*96e43537SVincent Donnefort 	remote->trace_buffer_size = 7 << 10;
521*96e43537SVincent Donnefort 	remote->poll_ms = 100;
522*96e43537SVincent Donnefort 	mutex_init(&remote->lock);
523*96e43537SVincent Donnefort 
524*96e43537SVincent Donnefort 	if (trace_remote_init_tracefs(name, remote)) {
525*96e43537SVincent Donnefort 		kfree(remote);
526*96e43537SVincent Donnefort 		return -ENOMEM;
527*96e43537SVincent Donnefort 	}
528*96e43537SVincent Donnefort 
529*96e43537SVincent Donnefort 	return 0;
530*96e43537SVincent Donnefort }
531*96e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_register);
532*96e43537SVincent Donnefort 
533*96e43537SVincent Donnefort /**
534*96e43537SVincent Donnefort  * trace_remote_free_buffer() - Free trace buffer allocated with trace_remote_alloc_buffer()
535*96e43537SVincent Donnefort  * @desc:	Descriptor of the per-CPU ring-buffers, originally filled by
536*96e43537SVincent Donnefort  *		trace_remote_alloc_buffer()
537*96e43537SVincent Donnefort  *
538*96e43537SVincent Donnefort  * Most likely called from &trace_remote_callbacks.unload_trace_buffer.
539*96e43537SVincent Donnefort  */
540*96e43537SVincent Donnefort void trace_remote_free_buffer(struct trace_buffer_desc *desc)
541*96e43537SVincent Donnefort {
542*96e43537SVincent Donnefort 	struct ring_buffer_desc *rb_desc;
543*96e43537SVincent Donnefort 	int cpu;
544*96e43537SVincent Donnefort 
545*96e43537SVincent Donnefort 	for_each_ring_buffer_desc(rb_desc, cpu, desc) {
546*96e43537SVincent Donnefort 		unsigned int id;
547*96e43537SVincent Donnefort 
548*96e43537SVincent Donnefort 		free_page(rb_desc->meta_va);
549*96e43537SVincent Donnefort 
550*96e43537SVincent Donnefort 		for (id = 0; id < rb_desc->nr_page_va; id++)
551*96e43537SVincent Donnefort 			free_page(rb_desc->page_va[id]);
552*96e43537SVincent Donnefort 	}
553*96e43537SVincent Donnefort }
554*96e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_free_buffer);
555*96e43537SVincent Donnefort 
556*96e43537SVincent Donnefort /**
557*96e43537SVincent Donnefort  * trace_remote_alloc_buffer() - Dynamically allocate a trace buffer
558*96e43537SVincent Donnefort  * @desc:		Uninitialized trace_buffer_desc
559*96e43537SVincent Donnefort  * @desc_size:		Size of the trace_buffer_desc. Must be at least equal to
560*96e43537SVincent Donnefort  *			trace_buffer_desc_size()
561*96e43537SVincent Donnefort  * @buffer_size:	Size in bytes of each per-CPU ring-buffer
562*96e43537SVincent Donnefort  * @cpumask:		CPUs to allocate a ring-buffer for
563*96e43537SVincent Donnefort  *
564*96e43537SVincent Donnefort  * Helper to dynamically allocate a set of pages (enough to cover @buffer_size)
565*96e43537SVincent Donnefort  * for each CPU from @cpumask and fill @desc. Most likely called from
566*96e43537SVincent Donnefort  * &trace_remote_callbacks.load_trace_buffer.
567*96e43537SVincent Donnefort  *
568*96e43537SVincent Donnefort  * Return: 0 on success, negative error code on failure.
569*96e43537SVincent Donnefort  */
570*96e43537SVincent Donnefort int trace_remote_alloc_buffer(struct trace_buffer_desc *desc, size_t desc_size, size_t buffer_size,
571*96e43537SVincent Donnefort 			      const struct cpumask *cpumask)
572*96e43537SVincent Donnefort {
573*96e43537SVincent Donnefort 	unsigned int nr_pages = max(DIV_ROUND_UP(buffer_size, PAGE_SIZE), 2UL) + 1;
574*96e43537SVincent Donnefort 	void *desc_end = desc + desc_size;
575*96e43537SVincent Donnefort 	struct ring_buffer_desc *rb_desc;
576*96e43537SVincent Donnefort 	int cpu, ret = -ENOMEM;
577*96e43537SVincent Donnefort 
578*96e43537SVincent Donnefort 	if (desc_size < struct_size(desc, __data, 0))
579*96e43537SVincent Donnefort 		return -EINVAL;
580*96e43537SVincent Donnefort 
581*96e43537SVincent Donnefort 	desc->nr_cpus = 0;
582*96e43537SVincent Donnefort 	desc->struct_len = struct_size(desc, __data, 0);
583*96e43537SVincent Donnefort 
584*96e43537SVincent Donnefort 	rb_desc = (struct ring_buffer_desc *)&desc->__data[0];
585*96e43537SVincent Donnefort 
586*96e43537SVincent Donnefort 	for_each_cpu(cpu, cpumask) {
587*96e43537SVincent Donnefort 		unsigned int id;
588*96e43537SVincent Donnefort 
589*96e43537SVincent Donnefort 		if ((void *)rb_desc + struct_size(rb_desc, page_va, nr_pages) > desc_end) {
590*96e43537SVincent Donnefort 			ret = -EINVAL;
591*96e43537SVincent Donnefort 			goto err;
592*96e43537SVincent Donnefort 		}
593*96e43537SVincent Donnefort 
594*96e43537SVincent Donnefort 		rb_desc->cpu = cpu;
595*96e43537SVincent Donnefort 		rb_desc->nr_page_va = 0;
596*96e43537SVincent Donnefort 		rb_desc->meta_va = (unsigned long)__get_free_page(GFP_KERNEL);
597*96e43537SVincent Donnefort 		if (!rb_desc->meta_va)
598*96e43537SVincent Donnefort 			goto err;
599*96e43537SVincent Donnefort 
600*96e43537SVincent Donnefort 		for (id = 0; id < nr_pages; id++) {
601*96e43537SVincent Donnefort 			rb_desc->page_va[id] = (unsigned long)__get_free_page(GFP_KERNEL);
602*96e43537SVincent Donnefort 			if (!rb_desc->page_va[id])
603*96e43537SVincent Donnefort 				goto err;
604*96e43537SVincent Donnefort 
605*96e43537SVincent Donnefort 			rb_desc->nr_page_va++;
606*96e43537SVincent Donnefort 		}
607*96e43537SVincent Donnefort 		desc->nr_cpus++;
608*96e43537SVincent Donnefort 		desc->struct_len += offsetof(struct ring_buffer_desc, page_va);
609*96e43537SVincent Donnefort 		desc->struct_len += struct_size(rb_desc, page_va, rb_desc->nr_page_va);
610*96e43537SVincent Donnefort 		rb_desc = __next_ring_buffer_desc(rb_desc);
611*96e43537SVincent Donnefort 	}
612*96e43537SVincent Donnefort 
613*96e43537SVincent Donnefort 	return 0;
614*96e43537SVincent Donnefort 
615*96e43537SVincent Donnefort err:
616*96e43537SVincent Donnefort 	trace_remote_free_buffer(desc);
617*96e43537SVincent Donnefort 	return ret;
618*96e43537SVincent Donnefort }
619*96e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_alloc_buffer);
620