xref: /linux/kernel/trace/trace_remote.c (revision 330b0cceb30634864d1e9c661eb5524c52d70c07)
196e43537SVincent Donnefort // SPDX-License-Identifier: GPL-2.0
296e43537SVincent Donnefort /*
396e43537SVincent Donnefort  * Copyright (C) 2025 - Google LLC
496e43537SVincent Donnefort  * Author: Vincent Donnefort <vdonnefort@google.com>
596e43537SVincent Donnefort  */
696e43537SVincent Donnefort 
796e43537SVincent Donnefort #include <linux/kstrtox.h>
896e43537SVincent Donnefort #include <linux/lockdep.h>
996e43537SVincent Donnefort #include <linux/mutex.h>
1096e43537SVincent Donnefort #include <linux/tracefs.h>
1196e43537SVincent Donnefort #include <linux/trace_remote.h>
1296e43537SVincent Donnefort #include <linux/trace_seq.h>
1396e43537SVincent Donnefort #include <linux/types.h>
1496e43537SVincent Donnefort 
1596e43537SVincent Donnefort #include "trace.h"
1696e43537SVincent Donnefort 
1796e43537SVincent Donnefort #define TRACEFS_DIR		"remotes"
1896e43537SVincent Donnefort #define TRACEFS_MODE_WRITE	0640
1996e43537SVincent Donnefort #define TRACEFS_MODE_READ	0440
2096e43537SVincent Donnefort 
21*330b0cceSVincent Donnefort enum tri_type {
22*330b0cceSVincent Donnefort 	TRI_CONSUMING,
23*330b0cceSVincent Donnefort 	TRI_NONCONSUMING,
24*330b0cceSVincent Donnefort };
25*330b0cceSVincent Donnefort 
2696e43537SVincent Donnefort struct trace_remote_iterator {
2796e43537SVincent Donnefort 	struct trace_remote		*remote;
2896e43537SVincent Donnefort 	struct trace_seq		seq;
2996e43537SVincent Donnefort 	struct delayed_work		poll_work;
3096e43537SVincent Donnefort 	unsigned long			lost_events;
3196e43537SVincent Donnefort 	u64				ts;
32*330b0cceSVincent Donnefort 	struct ring_buffer_iter		*rb_iter;
33*330b0cceSVincent Donnefort 	struct ring_buffer_iter		**rb_iters;
3496e43537SVincent Donnefort 	int				cpu;
3596e43537SVincent Donnefort 	int				evt_cpu;
36*330b0cceSVincent Donnefort 	loff_t				pos;
37*330b0cceSVincent Donnefort 	enum tri_type			type;
3896e43537SVincent Donnefort };
3996e43537SVincent Donnefort 
4096e43537SVincent Donnefort struct trace_remote {
4196e43537SVincent Donnefort 	struct trace_remote_callbacks	*cbs;
4296e43537SVincent Donnefort 	void				*priv;
4396e43537SVincent Donnefort 	struct trace_buffer		*trace_buffer;
4496e43537SVincent Donnefort 	struct trace_buffer_desc	*trace_buffer_desc;
4596e43537SVincent Donnefort 	unsigned long			trace_buffer_size;
4696e43537SVincent Donnefort 	struct ring_buffer_remote	rb_remote;
4796e43537SVincent Donnefort 	struct mutex			lock;
48*330b0cceSVincent Donnefort 	struct rw_semaphore		reader_lock;
49*330b0cceSVincent Donnefort 	struct rw_semaphore		*pcpu_reader_locks;
5096e43537SVincent Donnefort 	unsigned int			nr_readers;
5196e43537SVincent Donnefort 	unsigned int			poll_ms;
5296e43537SVincent Donnefort 	bool				tracing_on;
5396e43537SVincent Donnefort };
5496e43537SVincent Donnefort 
5596e43537SVincent Donnefort static bool trace_remote_loaded(struct trace_remote *remote)
5696e43537SVincent Donnefort {
5796e43537SVincent Donnefort 	return !!remote->trace_buffer;
5896e43537SVincent Donnefort }
5996e43537SVincent Donnefort 
6096e43537SVincent Donnefort static int trace_remote_load(struct trace_remote *remote)
6196e43537SVincent Donnefort {
6296e43537SVincent Donnefort 	struct ring_buffer_remote *rb_remote = &remote->rb_remote;
6396e43537SVincent Donnefort 	struct trace_buffer_desc *desc;
6496e43537SVincent Donnefort 
6596e43537SVincent Donnefort 	lockdep_assert_held(&remote->lock);
6696e43537SVincent Donnefort 
6796e43537SVincent Donnefort 	if (trace_remote_loaded(remote))
6896e43537SVincent Donnefort 		return 0;
6996e43537SVincent Donnefort 
7096e43537SVincent Donnefort 	desc = remote->cbs->load_trace_buffer(remote->trace_buffer_size, remote->priv);
7196e43537SVincent Donnefort 	if (IS_ERR(desc))
7296e43537SVincent Donnefort 		return PTR_ERR(desc);
7396e43537SVincent Donnefort 
7496e43537SVincent Donnefort 	rb_remote->desc = desc;
7596e43537SVincent Donnefort 	rb_remote->swap_reader_page = remote->cbs->swap_reader_page;
7696e43537SVincent Donnefort 	rb_remote->priv = remote->priv;
779af4ab0eSVincent Donnefort 	rb_remote->reset = remote->cbs->reset;
7896e43537SVincent Donnefort 	remote->trace_buffer = ring_buffer_alloc_remote(rb_remote);
7996e43537SVincent Donnefort 	if (!remote->trace_buffer) {
8096e43537SVincent Donnefort 		remote->cbs->unload_trace_buffer(desc, remote->priv);
8196e43537SVincent Donnefort 		return -ENOMEM;
8296e43537SVincent Donnefort 	}
8396e43537SVincent Donnefort 
8496e43537SVincent Donnefort 	remote->trace_buffer_desc = desc;
8596e43537SVincent Donnefort 
8696e43537SVincent Donnefort 	return 0;
8796e43537SVincent Donnefort }
8896e43537SVincent Donnefort 
8996e43537SVincent Donnefort static void trace_remote_try_unload(struct trace_remote *remote)
9096e43537SVincent Donnefort {
9196e43537SVincent Donnefort 	lockdep_assert_held(&remote->lock);
9296e43537SVincent Donnefort 
9396e43537SVincent Donnefort 	if (!trace_remote_loaded(remote))
9496e43537SVincent Donnefort 		return;
9596e43537SVincent Donnefort 
9696e43537SVincent Donnefort 	/* The buffer is being read or writable */
9796e43537SVincent Donnefort 	if (remote->nr_readers || remote->tracing_on)
9896e43537SVincent Donnefort 		return;
9996e43537SVincent Donnefort 
10096e43537SVincent Donnefort 	/* The buffer has readable data */
10196e43537SVincent Donnefort 	if (!ring_buffer_empty(remote->trace_buffer))
10296e43537SVincent Donnefort 		return;
10396e43537SVincent Donnefort 
10496e43537SVincent Donnefort 	ring_buffer_free(remote->trace_buffer);
10596e43537SVincent Donnefort 	remote->trace_buffer = NULL;
10696e43537SVincent Donnefort 	remote->cbs->unload_trace_buffer(remote->trace_buffer_desc, remote->priv);
10796e43537SVincent Donnefort }
10896e43537SVincent Donnefort 
10996e43537SVincent Donnefort static int trace_remote_enable_tracing(struct trace_remote *remote)
11096e43537SVincent Donnefort {
11196e43537SVincent Donnefort 	int ret;
11296e43537SVincent Donnefort 
11396e43537SVincent Donnefort 	lockdep_assert_held(&remote->lock);
11496e43537SVincent Donnefort 
11596e43537SVincent Donnefort 	if (remote->tracing_on)
11696e43537SVincent Donnefort 		return 0;
11796e43537SVincent Donnefort 
11896e43537SVincent Donnefort 	ret = trace_remote_load(remote);
11996e43537SVincent Donnefort 	if (ret)
12096e43537SVincent Donnefort 		return ret;
12196e43537SVincent Donnefort 
12296e43537SVincent Donnefort 	ret = remote->cbs->enable_tracing(true, remote->priv);
12396e43537SVincent Donnefort 	if (ret) {
12496e43537SVincent Donnefort 		trace_remote_try_unload(remote);
12596e43537SVincent Donnefort 		return ret;
12696e43537SVincent Donnefort 	}
12796e43537SVincent Donnefort 
12896e43537SVincent Donnefort 	remote->tracing_on = true;
12996e43537SVincent Donnefort 
13096e43537SVincent Donnefort 	return 0;
13196e43537SVincent Donnefort }
13296e43537SVincent Donnefort 
13396e43537SVincent Donnefort static int trace_remote_disable_tracing(struct trace_remote *remote)
13496e43537SVincent Donnefort {
13596e43537SVincent Donnefort 	int ret;
13696e43537SVincent Donnefort 
13796e43537SVincent Donnefort 	lockdep_assert_held(&remote->lock);
13896e43537SVincent Donnefort 
13996e43537SVincent Donnefort 	if (!remote->tracing_on)
14096e43537SVincent Donnefort 		return 0;
14196e43537SVincent Donnefort 
14296e43537SVincent Donnefort 	ret = remote->cbs->enable_tracing(false, remote->priv);
14396e43537SVincent Donnefort 	if (ret)
14496e43537SVincent Donnefort 		return ret;
14596e43537SVincent Donnefort 
14696e43537SVincent Donnefort 	ring_buffer_poll_remote(remote->trace_buffer, RING_BUFFER_ALL_CPUS);
14796e43537SVincent Donnefort 	remote->tracing_on = false;
14896e43537SVincent Donnefort 	trace_remote_try_unload(remote);
14996e43537SVincent Donnefort 
15096e43537SVincent Donnefort 	return 0;
15196e43537SVincent Donnefort }
15296e43537SVincent Donnefort 
1539af4ab0eSVincent Donnefort static void trace_remote_reset(struct trace_remote *remote, int cpu)
1549af4ab0eSVincent Donnefort {
1559af4ab0eSVincent Donnefort 	lockdep_assert_held(&remote->lock);
1569af4ab0eSVincent Donnefort 
1579af4ab0eSVincent Donnefort 	if (!trace_remote_loaded(remote))
1589af4ab0eSVincent Donnefort 		return;
1599af4ab0eSVincent Donnefort 
1609af4ab0eSVincent Donnefort 	if (cpu == RING_BUFFER_ALL_CPUS)
1619af4ab0eSVincent Donnefort 		ring_buffer_reset(remote->trace_buffer);
1629af4ab0eSVincent Donnefort 	else
1639af4ab0eSVincent Donnefort 		ring_buffer_reset_cpu(remote->trace_buffer, cpu);
1649af4ab0eSVincent Donnefort 
1659af4ab0eSVincent Donnefort 	trace_remote_try_unload(remote);
1669af4ab0eSVincent Donnefort }
1679af4ab0eSVincent Donnefort 
16896e43537SVincent Donnefort static ssize_t
16996e43537SVincent Donnefort tracing_on_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
17096e43537SVincent Donnefort {
17196e43537SVincent Donnefort 	struct trace_remote *remote = filp->private_data;
17296e43537SVincent Donnefort 	unsigned long val;
17396e43537SVincent Donnefort 	int ret;
17496e43537SVincent Donnefort 
17596e43537SVincent Donnefort 	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
17696e43537SVincent Donnefort 	if (ret)
17796e43537SVincent Donnefort 		return ret;
17896e43537SVincent Donnefort 
17996e43537SVincent Donnefort 	guard(mutex)(&remote->lock);
18096e43537SVincent Donnefort 
18196e43537SVincent Donnefort 	ret = val ? trace_remote_enable_tracing(remote) : trace_remote_disable_tracing(remote);
18296e43537SVincent Donnefort 	if (ret)
18396e43537SVincent Donnefort 		return ret;
18496e43537SVincent Donnefort 
18596e43537SVincent Donnefort 	return cnt;
18696e43537SVincent Donnefort }
18796e43537SVincent Donnefort static int tracing_on_show(struct seq_file *s, void *unused)
18896e43537SVincent Donnefort {
18996e43537SVincent Donnefort 	struct trace_remote *remote = s->private;
19096e43537SVincent Donnefort 
19196e43537SVincent Donnefort 	seq_printf(s, "%d\n", remote->tracing_on);
19296e43537SVincent Donnefort 
19396e43537SVincent Donnefort 	return 0;
19496e43537SVincent Donnefort }
19596e43537SVincent Donnefort DEFINE_SHOW_STORE_ATTRIBUTE(tracing_on);
19696e43537SVincent Donnefort 
19796e43537SVincent Donnefort static ssize_t buffer_size_kb_write(struct file *filp, const char __user *ubuf, size_t cnt,
19896e43537SVincent Donnefort 				    loff_t *ppos)
19996e43537SVincent Donnefort {
20096e43537SVincent Donnefort 	struct trace_remote *remote = filp->private_data;
20196e43537SVincent Donnefort 	unsigned long val;
20296e43537SVincent Donnefort 	int ret;
20396e43537SVincent Donnefort 
20496e43537SVincent Donnefort 	ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
20596e43537SVincent Donnefort 	if (ret)
20696e43537SVincent Donnefort 		return ret;
20796e43537SVincent Donnefort 
20896e43537SVincent Donnefort 	/* KiB to Bytes */
20996e43537SVincent Donnefort 	if (!val || check_shl_overflow(val, 10, &val))
21096e43537SVincent Donnefort 		return -EINVAL;
21196e43537SVincent Donnefort 
21296e43537SVincent Donnefort 	guard(mutex)(&remote->lock);
21396e43537SVincent Donnefort 
21496e43537SVincent Donnefort 	if (trace_remote_loaded(remote))
21596e43537SVincent Donnefort 		return -EBUSY;
21696e43537SVincent Donnefort 
21796e43537SVincent Donnefort 	remote->trace_buffer_size = val;
21896e43537SVincent Donnefort 
21996e43537SVincent Donnefort 	return cnt;
22096e43537SVincent Donnefort }
22196e43537SVincent Donnefort 
22296e43537SVincent Donnefort static int buffer_size_kb_show(struct seq_file *s, void *unused)
22396e43537SVincent Donnefort {
22496e43537SVincent Donnefort 	struct trace_remote *remote = s->private;
22596e43537SVincent Donnefort 
22696e43537SVincent Donnefort 	seq_printf(s, "%lu (%s)\n", remote->trace_buffer_size >> 10,
22796e43537SVincent Donnefort 		   trace_remote_loaded(remote) ? "loaded" : "unloaded");
22896e43537SVincent Donnefort 
22996e43537SVincent Donnefort 	return 0;
23096e43537SVincent Donnefort }
23196e43537SVincent Donnefort DEFINE_SHOW_STORE_ATTRIBUTE(buffer_size_kb);
23296e43537SVincent Donnefort 
23396e43537SVincent Donnefort static int trace_remote_get(struct trace_remote *remote, int cpu)
23496e43537SVincent Donnefort {
23596e43537SVincent Donnefort 	int ret;
23696e43537SVincent Donnefort 
23796e43537SVincent Donnefort 	if (remote->nr_readers == UINT_MAX)
23896e43537SVincent Donnefort 		return -EBUSY;
23996e43537SVincent Donnefort 
24096e43537SVincent Donnefort 	ret = trace_remote_load(remote);
24196e43537SVincent Donnefort 	if (ret)
24296e43537SVincent Donnefort 		return ret;
24396e43537SVincent Donnefort 
244*330b0cceSVincent Donnefort 	if (cpu != RING_BUFFER_ALL_CPUS && !remote->pcpu_reader_locks) {
245*330b0cceSVincent Donnefort 		int lock_cpu;
246*330b0cceSVincent Donnefort 
247*330b0cceSVincent Donnefort 		remote->pcpu_reader_locks = kcalloc(nr_cpu_ids, sizeof(*remote->pcpu_reader_locks),
248*330b0cceSVincent Donnefort 						    GFP_KERNEL);
249*330b0cceSVincent Donnefort 		if (!remote->pcpu_reader_locks) {
250*330b0cceSVincent Donnefort 			trace_remote_try_unload(remote);
251*330b0cceSVincent Donnefort 			return -ENOMEM;
252*330b0cceSVincent Donnefort 		}
253*330b0cceSVincent Donnefort 
254*330b0cceSVincent Donnefort 		for_each_possible_cpu(lock_cpu)
255*330b0cceSVincent Donnefort 			init_rwsem(&remote->pcpu_reader_locks[lock_cpu]);
256*330b0cceSVincent Donnefort 	}
257*330b0cceSVincent Donnefort 
25896e43537SVincent Donnefort 	remote->nr_readers++;
25996e43537SVincent Donnefort 
26096e43537SVincent Donnefort 	return 0;
26196e43537SVincent Donnefort }
26296e43537SVincent Donnefort 
26396e43537SVincent Donnefort static void trace_remote_put(struct trace_remote *remote)
26496e43537SVincent Donnefort {
26596e43537SVincent Donnefort 	if (WARN_ON(!remote->nr_readers))
26696e43537SVincent Donnefort 		return;
26796e43537SVincent Donnefort 
26896e43537SVincent Donnefort 	remote->nr_readers--;
26996e43537SVincent Donnefort 	if (remote->nr_readers)
27096e43537SVincent Donnefort 		return;
27196e43537SVincent Donnefort 
272*330b0cceSVincent Donnefort 	kfree(remote->pcpu_reader_locks);
273*330b0cceSVincent Donnefort 	remote->pcpu_reader_locks = NULL;
274*330b0cceSVincent Donnefort 
27596e43537SVincent Donnefort 	trace_remote_try_unload(remote);
27696e43537SVincent Donnefort }
27796e43537SVincent Donnefort 
27896e43537SVincent Donnefort static void __poll_remote(struct work_struct *work)
27996e43537SVincent Donnefort {
28096e43537SVincent Donnefort 	struct delayed_work *dwork = to_delayed_work(work);
28196e43537SVincent Donnefort 	struct trace_remote_iterator *iter;
28296e43537SVincent Donnefort 
28396e43537SVincent Donnefort 	iter = container_of(dwork, struct trace_remote_iterator, poll_work);
28496e43537SVincent Donnefort 	ring_buffer_poll_remote(iter->remote->trace_buffer, iter->cpu);
28596e43537SVincent Donnefort 	schedule_delayed_work((struct delayed_work *)work,
28696e43537SVincent Donnefort 			      msecs_to_jiffies(iter->remote->poll_ms));
28796e43537SVincent Donnefort }
28896e43537SVincent Donnefort 
289*330b0cceSVincent Donnefort static void __free_ring_buffer_iter(struct trace_remote_iterator *iter, int cpu)
290*330b0cceSVincent Donnefort {
291*330b0cceSVincent Donnefort 	if (cpu != RING_BUFFER_ALL_CPUS) {
292*330b0cceSVincent Donnefort 		ring_buffer_read_finish(iter->rb_iter);
293*330b0cceSVincent Donnefort 		return;
294*330b0cceSVincent Donnefort 	}
295*330b0cceSVincent Donnefort 
296*330b0cceSVincent Donnefort 	for_each_possible_cpu(cpu) {
297*330b0cceSVincent Donnefort 		if (iter->rb_iters[cpu])
298*330b0cceSVincent Donnefort 			ring_buffer_read_finish(iter->rb_iters[cpu]);
299*330b0cceSVincent Donnefort 	}
300*330b0cceSVincent Donnefort 
301*330b0cceSVincent Donnefort 	kfree(iter->rb_iters);
302*330b0cceSVincent Donnefort }
303*330b0cceSVincent Donnefort 
304*330b0cceSVincent Donnefort static int __alloc_ring_buffer_iter(struct trace_remote_iterator *iter, int cpu)
305*330b0cceSVincent Donnefort {
306*330b0cceSVincent Donnefort 	if (cpu != RING_BUFFER_ALL_CPUS) {
307*330b0cceSVincent Donnefort 		iter->rb_iter = ring_buffer_read_start(iter->remote->trace_buffer, cpu, GFP_KERNEL);
308*330b0cceSVincent Donnefort 
309*330b0cceSVincent Donnefort 		return iter->rb_iter ? 0 : -ENOMEM;
310*330b0cceSVincent Donnefort 	}
311*330b0cceSVincent Donnefort 
312*330b0cceSVincent Donnefort 	iter->rb_iters = kcalloc(nr_cpu_ids, sizeof(*iter->rb_iters), GFP_KERNEL);
313*330b0cceSVincent Donnefort 	if (!iter->rb_iters)
314*330b0cceSVincent Donnefort 		return -ENOMEM;
315*330b0cceSVincent Donnefort 
316*330b0cceSVincent Donnefort 	for_each_possible_cpu(cpu) {
317*330b0cceSVincent Donnefort 		iter->rb_iters[cpu] = ring_buffer_read_start(iter->remote->trace_buffer, cpu,
318*330b0cceSVincent Donnefort 							     GFP_KERNEL);
319*330b0cceSVincent Donnefort 		if (!iter->rb_iters[cpu]) {
320*330b0cceSVincent Donnefort 			__free_ring_buffer_iter(iter, RING_BUFFER_ALL_CPUS);
321*330b0cceSVincent Donnefort 			return -ENOMEM;
322*330b0cceSVincent Donnefort 		}
323*330b0cceSVincent Donnefort 	}
324*330b0cceSVincent Donnefort 
325*330b0cceSVincent Donnefort 	return 0;
326*330b0cceSVincent Donnefort }
327*330b0cceSVincent Donnefort 
328*330b0cceSVincent Donnefort static struct trace_remote_iterator
329*330b0cceSVincent Donnefort *trace_remote_iter(struct trace_remote *remote, int cpu, enum tri_type type)
33096e43537SVincent Donnefort {
33196e43537SVincent Donnefort 	struct trace_remote_iterator *iter = NULL;
33296e43537SVincent Donnefort 	int ret;
33396e43537SVincent Donnefort 
33496e43537SVincent Donnefort 	lockdep_assert_held(&remote->lock);
33596e43537SVincent Donnefort 
336*330b0cceSVincent Donnefort 	if (type == TRI_NONCONSUMING && !trace_remote_loaded(remote))
337*330b0cceSVincent Donnefort 		return NULL;
33896e43537SVincent Donnefort 
33996e43537SVincent Donnefort 	ret = trace_remote_get(remote, cpu);
34096e43537SVincent Donnefort 	if (ret)
34196e43537SVincent Donnefort 		return ERR_PTR(ret);
34296e43537SVincent Donnefort 
34396e43537SVincent Donnefort 	/* Test the CPU */
34496e43537SVincent Donnefort 	ret = ring_buffer_poll_remote(remote->trace_buffer, cpu);
34596e43537SVincent Donnefort 	if (ret)
34696e43537SVincent Donnefort 		goto err;
34796e43537SVincent Donnefort 
34896e43537SVincent Donnefort 	iter = kzalloc_obj(*iter);
34996e43537SVincent Donnefort 	if (iter) {
35096e43537SVincent Donnefort 		iter->remote = remote;
35196e43537SVincent Donnefort 		iter->cpu = cpu;
352*330b0cceSVincent Donnefort 		iter->type = type;
35396e43537SVincent Donnefort 		trace_seq_init(&iter->seq);
354*330b0cceSVincent Donnefort 
355*330b0cceSVincent Donnefort 		switch (type) {
356*330b0cceSVincent Donnefort 		case TRI_CONSUMING:
35796e43537SVincent Donnefort 			INIT_DELAYED_WORK(&iter->poll_work, __poll_remote);
35896e43537SVincent Donnefort 			schedule_delayed_work(&iter->poll_work, msecs_to_jiffies(remote->poll_ms));
359*330b0cceSVincent Donnefort 			break;
360*330b0cceSVincent Donnefort 		case TRI_NONCONSUMING:
361*330b0cceSVincent Donnefort 			ret = __alloc_ring_buffer_iter(iter, cpu);
362*330b0cceSVincent Donnefort 			break;
363*330b0cceSVincent Donnefort 		}
364*330b0cceSVincent Donnefort 
365*330b0cceSVincent Donnefort 		if (ret)
366*330b0cceSVincent Donnefort 			goto err;
36796e43537SVincent Donnefort 
36896e43537SVincent Donnefort 		return iter;
36996e43537SVincent Donnefort 	}
37096e43537SVincent Donnefort 	ret = -ENOMEM;
37196e43537SVincent Donnefort 
37296e43537SVincent Donnefort err:
37396e43537SVincent Donnefort 	kfree(iter);
37496e43537SVincent Donnefort 	trace_remote_put(remote);
37596e43537SVincent Donnefort 
37696e43537SVincent Donnefort 	return ERR_PTR(ret);
37796e43537SVincent Donnefort }
37896e43537SVincent Donnefort 
37996e43537SVincent Donnefort static void trace_remote_iter_free(struct trace_remote_iterator *iter)
38096e43537SVincent Donnefort {
38196e43537SVincent Donnefort 	struct trace_remote *remote;
38296e43537SVincent Donnefort 
38396e43537SVincent Donnefort 	if (!iter)
38496e43537SVincent Donnefort 		return;
38596e43537SVincent Donnefort 
38696e43537SVincent Donnefort 	remote = iter->remote;
38796e43537SVincent Donnefort 
38896e43537SVincent Donnefort 	lockdep_assert_held(&remote->lock);
38996e43537SVincent Donnefort 
390*330b0cceSVincent Donnefort 	switch (iter->type) {
391*330b0cceSVincent Donnefort 	case TRI_CONSUMING:
392*330b0cceSVincent Donnefort 		cancel_delayed_work_sync(&iter->poll_work);
393*330b0cceSVincent Donnefort 		break;
394*330b0cceSVincent Donnefort 	case TRI_NONCONSUMING:
395*330b0cceSVincent Donnefort 		__free_ring_buffer_iter(iter, iter->cpu);
396*330b0cceSVincent Donnefort 		break;
397*330b0cceSVincent Donnefort 	}
398*330b0cceSVincent Donnefort 
39996e43537SVincent Donnefort 	kfree(iter);
40096e43537SVincent Donnefort 	trace_remote_put(remote);
40196e43537SVincent Donnefort }
40296e43537SVincent Donnefort 
403*330b0cceSVincent Donnefort static void trace_remote_iter_read_start(struct trace_remote_iterator *iter)
404*330b0cceSVincent Donnefort {
405*330b0cceSVincent Donnefort 	struct trace_remote *remote = iter->remote;
406*330b0cceSVincent Donnefort 	int cpu = iter->cpu;
407*330b0cceSVincent Donnefort 
408*330b0cceSVincent Donnefort 	/* Acquire global reader lock */
409*330b0cceSVincent Donnefort 	if (cpu == RING_BUFFER_ALL_CPUS && iter->type == TRI_CONSUMING)
410*330b0cceSVincent Donnefort 		down_write(&remote->reader_lock);
411*330b0cceSVincent Donnefort 	else
412*330b0cceSVincent Donnefort 		down_read(&remote->reader_lock);
413*330b0cceSVincent Donnefort 
414*330b0cceSVincent Donnefort 	if (cpu == RING_BUFFER_ALL_CPUS)
415*330b0cceSVincent Donnefort 		return;
416*330b0cceSVincent Donnefort 
417*330b0cceSVincent Donnefort 	/*
418*330b0cceSVincent Donnefort 	 * No need for the remote lock here, iter holds a reference on
419*330b0cceSVincent Donnefort 	 * remote->nr_readers
420*330b0cceSVincent Donnefort 	 */
421*330b0cceSVincent Donnefort 
422*330b0cceSVincent Donnefort 	/* Get the per-CPU one */
423*330b0cceSVincent Donnefort 	if (WARN_ON_ONCE(!remote->pcpu_reader_locks))
424*330b0cceSVincent Donnefort 		return;
425*330b0cceSVincent Donnefort 
426*330b0cceSVincent Donnefort 	if (iter->type == TRI_CONSUMING)
427*330b0cceSVincent Donnefort 		down_write(&remote->pcpu_reader_locks[cpu]);
428*330b0cceSVincent Donnefort 	else
429*330b0cceSVincent Donnefort 		down_read(&remote->pcpu_reader_locks[cpu]);
430*330b0cceSVincent Donnefort }
431*330b0cceSVincent Donnefort 
432*330b0cceSVincent Donnefort static void trace_remote_iter_read_finished(struct trace_remote_iterator *iter)
433*330b0cceSVincent Donnefort {
434*330b0cceSVincent Donnefort 	struct trace_remote *remote = iter->remote;
435*330b0cceSVincent Donnefort 	int cpu = iter->cpu;
436*330b0cceSVincent Donnefort 
437*330b0cceSVincent Donnefort 	/* Release per-CPU reader lock */
438*330b0cceSVincent Donnefort 	if (cpu != RING_BUFFER_ALL_CPUS) {
439*330b0cceSVincent Donnefort 		/*
440*330b0cceSVincent Donnefort 		 * No need for the remote lock here, iter holds a reference on
441*330b0cceSVincent Donnefort 		 * remote->nr_readers
442*330b0cceSVincent Donnefort 		 */
443*330b0cceSVincent Donnefort 		if (iter->type == TRI_CONSUMING)
444*330b0cceSVincent Donnefort 			up_write(&remote->pcpu_reader_locks[cpu]);
445*330b0cceSVincent Donnefort 		else
446*330b0cceSVincent Donnefort 			up_read(&remote->pcpu_reader_locks[cpu]);
447*330b0cceSVincent Donnefort 	}
448*330b0cceSVincent Donnefort 
449*330b0cceSVincent Donnefort 	/* Release global reader lock */
450*330b0cceSVincent Donnefort 	if (cpu == RING_BUFFER_ALL_CPUS && iter->type == TRI_CONSUMING)
451*330b0cceSVincent Donnefort 		up_write(&remote->reader_lock);
452*330b0cceSVincent Donnefort 	else
453*330b0cceSVincent Donnefort 		up_read(&remote->reader_lock);
454*330b0cceSVincent Donnefort }
455*330b0cceSVincent Donnefort 
456*330b0cceSVincent Donnefort static struct ring_buffer_iter *__get_rb_iter(struct trace_remote_iterator *iter, int cpu)
457*330b0cceSVincent Donnefort {
458*330b0cceSVincent Donnefort 	return iter->cpu != RING_BUFFER_ALL_CPUS ? iter->rb_iter : iter->rb_iters[cpu];
459*330b0cceSVincent Donnefort }
460*330b0cceSVincent Donnefort 
461*330b0cceSVincent Donnefort static struct ring_buffer_event *
462*330b0cceSVincent Donnefort __peek_event(struct trace_remote_iterator *iter, int cpu, u64 *ts, unsigned long *lost_events)
463*330b0cceSVincent Donnefort {
464*330b0cceSVincent Donnefort 	struct ring_buffer_event *rb_evt;
465*330b0cceSVincent Donnefort 	struct ring_buffer_iter *rb_iter;
466*330b0cceSVincent Donnefort 
467*330b0cceSVincent Donnefort 	switch (iter->type) {
468*330b0cceSVincent Donnefort 	case TRI_CONSUMING:
469*330b0cceSVincent Donnefort 		return ring_buffer_peek(iter->remote->trace_buffer, cpu, ts, lost_events);
470*330b0cceSVincent Donnefort 	case TRI_NONCONSUMING:
471*330b0cceSVincent Donnefort 		rb_iter = __get_rb_iter(iter, cpu);
472*330b0cceSVincent Donnefort 		rb_evt = ring_buffer_iter_peek(rb_iter, ts);
473*330b0cceSVincent Donnefort 		if (!rb_evt)
474*330b0cceSVincent Donnefort 			return NULL;
475*330b0cceSVincent Donnefort 
476*330b0cceSVincent Donnefort 		*lost_events = ring_buffer_iter_dropped(rb_iter);
477*330b0cceSVincent Donnefort 
478*330b0cceSVincent Donnefort 		return rb_evt;
479*330b0cceSVincent Donnefort 	}
480*330b0cceSVincent Donnefort 
481*330b0cceSVincent Donnefort 	return NULL;
482*330b0cceSVincent Donnefort }
483*330b0cceSVincent Donnefort 
48496e43537SVincent Donnefort static bool trace_remote_iter_read_event(struct trace_remote_iterator *iter)
48596e43537SVincent Donnefort {
48696e43537SVincent Donnefort 	struct trace_buffer *trace_buffer = iter->remote->trace_buffer;
48796e43537SVincent Donnefort 	int cpu = iter->cpu;
48896e43537SVincent Donnefort 
48996e43537SVincent Donnefort 	if (cpu != RING_BUFFER_ALL_CPUS) {
49096e43537SVincent Donnefort 		if (ring_buffer_empty_cpu(trace_buffer, cpu))
49196e43537SVincent Donnefort 			return false;
49296e43537SVincent Donnefort 
493*330b0cceSVincent Donnefort 		if (!__peek_event(iter, cpu, &iter->ts, &iter->lost_events))
49496e43537SVincent Donnefort 			return false;
49596e43537SVincent Donnefort 
49696e43537SVincent Donnefort 		iter->evt_cpu = cpu;
49796e43537SVincent Donnefort 		return true;
49896e43537SVincent Donnefort 	}
49996e43537SVincent Donnefort 
50096e43537SVincent Donnefort 	iter->ts = U64_MAX;
50196e43537SVincent Donnefort 	for_each_possible_cpu(cpu) {
50296e43537SVincent Donnefort 		unsigned long lost_events;
50396e43537SVincent Donnefort 		u64 ts;
50496e43537SVincent Donnefort 
50596e43537SVincent Donnefort 		if (ring_buffer_empty_cpu(trace_buffer, cpu))
50696e43537SVincent Donnefort 			continue;
50796e43537SVincent Donnefort 
508*330b0cceSVincent Donnefort 		if (!__peek_event(iter, cpu, &ts, &lost_events))
50996e43537SVincent Donnefort 			continue;
51096e43537SVincent Donnefort 
51196e43537SVincent Donnefort 		if (ts >= iter->ts)
51296e43537SVincent Donnefort 			continue;
51396e43537SVincent Donnefort 
51496e43537SVincent Donnefort 		iter->ts = ts;
51596e43537SVincent Donnefort 		iter->evt_cpu = cpu;
51696e43537SVincent Donnefort 		iter->lost_events = lost_events;
51796e43537SVincent Donnefort 	}
51896e43537SVincent Donnefort 
51996e43537SVincent Donnefort 	return iter->ts != U64_MAX;
52096e43537SVincent Donnefort }
52196e43537SVincent Donnefort 
522*330b0cceSVincent Donnefort static void trace_remote_iter_move(struct trace_remote_iterator *iter)
523*330b0cceSVincent Donnefort {
524*330b0cceSVincent Donnefort 	struct trace_buffer *trace_buffer = iter->remote->trace_buffer;
525*330b0cceSVincent Donnefort 
526*330b0cceSVincent Donnefort 	switch (iter->type) {
527*330b0cceSVincent Donnefort 	case TRI_CONSUMING:
528*330b0cceSVincent Donnefort 		ring_buffer_consume(trace_buffer, iter->evt_cpu, NULL, NULL);
529*330b0cceSVincent Donnefort 		break;
530*330b0cceSVincent Donnefort 	case TRI_NONCONSUMING:
531*330b0cceSVincent Donnefort 		ring_buffer_iter_advance(__get_rb_iter(iter, iter->evt_cpu));
532*330b0cceSVincent Donnefort 		break;
533*330b0cceSVincent Donnefort 	}
534*330b0cceSVincent Donnefort }
535*330b0cceSVincent Donnefort 
53696e43537SVincent Donnefort static int trace_remote_iter_print_event(struct trace_remote_iterator *iter)
53796e43537SVincent Donnefort {
53896e43537SVincent Donnefort 	unsigned long usecs_rem;
53996e43537SVincent Donnefort 	u64 ts = iter->ts;
54096e43537SVincent Donnefort 
54196e43537SVincent Donnefort 	if (iter->lost_events)
54296e43537SVincent Donnefort 		trace_seq_printf(&iter->seq, "CPU:%d [LOST %lu EVENTS]\n",
54396e43537SVincent Donnefort 				 iter->evt_cpu, iter->lost_events);
54496e43537SVincent Donnefort 
54596e43537SVincent Donnefort 	do_div(ts, 1000);
54696e43537SVincent Donnefort 	usecs_rem = do_div(ts, USEC_PER_SEC);
54796e43537SVincent Donnefort 
54896e43537SVincent Donnefort 	trace_seq_printf(&iter->seq, "[%03d]\t%5llu.%06lu: ", iter->evt_cpu,
54996e43537SVincent Donnefort 			 ts, usecs_rem);
55096e43537SVincent Donnefort 
55196e43537SVincent Donnefort 	return trace_seq_has_overflowed(&iter->seq) ? -EOVERFLOW : 0;
55296e43537SVincent Donnefort }
55396e43537SVincent Donnefort 
55496e43537SVincent Donnefort static int trace_pipe_open(struct inode *inode, struct file *filp)
55596e43537SVincent Donnefort {
55696e43537SVincent Donnefort 	struct trace_remote *remote = inode->i_private;
55796e43537SVincent Donnefort 	struct trace_remote_iterator *iter;
558*330b0cceSVincent Donnefort 	int cpu = tracing_get_cpu(inode);
55996e43537SVincent Donnefort 
56096e43537SVincent Donnefort 	guard(mutex)(&remote->lock);
561*330b0cceSVincent Donnefort 
562*330b0cceSVincent Donnefort 	iter = trace_remote_iter(remote, cpu, TRI_CONSUMING);
563*330b0cceSVincent Donnefort 	if (IS_ERR(iter))
564*330b0cceSVincent Donnefort 		return PTR_ERR(iter);
565*330b0cceSVincent Donnefort 
56696e43537SVincent Donnefort 	filp->private_data = iter;
56796e43537SVincent Donnefort 
56896e43537SVincent Donnefort 	return IS_ERR(iter) ? PTR_ERR(iter) : 0;
56996e43537SVincent Donnefort }
57096e43537SVincent Donnefort 
57196e43537SVincent Donnefort static int trace_pipe_release(struct inode *inode, struct file *filp)
57296e43537SVincent Donnefort {
57396e43537SVincent Donnefort 	struct trace_remote_iterator *iter = filp->private_data;
57496e43537SVincent Donnefort 	struct trace_remote *remote = iter->remote;
57596e43537SVincent Donnefort 
57696e43537SVincent Donnefort 	guard(mutex)(&remote->lock);
57796e43537SVincent Donnefort 
57896e43537SVincent Donnefort 	trace_remote_iter_free(iter);
57996e43537SVincent Donnefort 
58096e43537SVincent Donnefort 	return 0;
58196e43537SVincent Donnefort }
58296e43537SVincent Donnefort 
58396e43537SVincent Donnefort static ssize_t trace_pipe_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos)
58496e43537SVincent Donnefort {
58596e43537SVincent Donnefort 	struct trace_remote_iterator *iter = filp->private_data;
58696e43537SVincent Donnefort 	struct trace_buffer *trace_buffer = iter->remote->trace_buffer;
58796e43537SVincent Donnefort 	int ret;
58896e43537SVincent Donnefort 
58996e43537SVincent Donnefort copy_to_user:
59096e43537SVincent Donnefort 	ret = trace_seq_to_user(&iter->seq, ubuf, cnt);
59196e43537SVincent Donnefort 	if (ret != -EBUSY)
59296e43537SVincent Donnefort 		return ret;
59396e43537SVincent Donnefort 
59496e43537SVincent Donnefort 	trace_seq_init(&iter->seq);
59596e43537SVincent Donnefort 
59696e43537SVincent Donnefort 	ret = ring_buffer_wait(trace_buffer, iter->cpu, 0, NULL, NULL);
59796e43537SVincent Donnefort 	if (ret < 0)
59896e43537SVincent Donnefort 		return ret;
59996e43537SVincent Donnefort 
600*330b0cceSVincent Donnefort 	trace_remote_iter_read_start(iter);
601*330b0cceSVincent Donnefort 
60296e43537SVincent Donnefort 	while (trace_remote_iter_read_event(iter)) {
60396e43537SVincent Donnefort 		int prev_len = iter->seq.seq.len;
60496e43537SVincent Donnefort 
60596e43537SVincent Donnefort 		if (trace_remote_iter_print_event(iter)) {
60696e43537SVincent Donnefort 			iter->seq.seq.len = prev_len;
60796e43537SVincent Donnefort 			break;
60896e43537SVincent Donnefort 		}
60996e43537SVincent Donnefort 
610*330b0cceSVincent Donnefort 		trace_remote_iter_move(iter);
61196e43537SVincent Donnefort 	}
61296e43537SVincent Donnefort 
613*330b0cceSVincent Donnefort 	trace_remote_iter_read_finished(iter);
614*330b0cceSVincent Donnefort 
61596e43537SVincent Donnefort 	goto copy_to_user;
61696e43537SVincent Donnefort }
61796e43537SVincent Donnefort 
61896e43537SVincent Donnefort static const struct file_operations trace_pipe_fops = {
61996e43537SVincent Donnefort 	.open		= trace_pipe_open,
62096e43537SVincent Donnefort 	.read		= trace_pipe_read,
62196e43537SVincent Donnefort 	.release	= trace_pipe_release,
62296e43537SVincent Donnefort };
62396e43537SVincent Donnefort 
624*330b0cceSVincent Donnefort static void *trace_next(struct seq_file *m, void *v, loff_t *pos)
625*330b0cceSVincent Donnefort {
626*330b0cceSVincent Donnefort 	struct trace_remote_iterator *iter = m->private;
627*330b0cceSVincent Donnefort 
628*330b0cceSVincent Donnefort 	++*pos;
629*330b0cceSVincent Donnefort 
630*330b0cceSVincent Donnefort 	if (!iter || !trace_remote_iter_read_event(iter))
631*330b0cceSVincent Donnefort 		return NULL;
632*330b0cceSVincent Donnefort 
633*330b0cceSVincent Donnefort 	trace_remote_iter_move(iter);
634*330b0cceSVincent Donnefort 	iter->pos++;
635*330b0cceSVincent Donnefort 
636*330b0cceSVincent Donnefort 	return iter;
637*330b0cceSVincent Donnefort }
638*330b0cceSVincent Donnefort 
639*330b0cceSVincent Donnefort static void *trace_start(struct seq_file *m, loff_t *pos)
640*330b0cceSVincent Donnefort {
641*330b0cceSVincent Donnefort 	struct trace_remote_iterator *iter = m->private;
642*330b0cceSVincent Donnefort 	loff_t i;
643*330b0cceSVincent Donnefort 
644*330b0cceSVincent Donnefort 	if (!iter)
645*330b0cceSVincent Donnefort 		return NULL;
646*330b0cceSVincent Donnefort 
647*330b0cceSVincent Donnefort 	trace_remote_iter_read_start(iter);
648*330b0cceSVincent Donnefort 
649*330b0cceSVincent Donnefort 	if (!*pos) {
650*330b0cceSVincent Donnefort 		iter->pos = -1;
651*330b0cceSVincent Donnefort 		return trace_next(m, NULL, &i);
652*330b0cceSVincent Donnefort 	}
653*330b0cceSVincent Donnefort 
654*330b0cceSVincent Donnefort 	i = iter->pos;
655*330b0cceSVincent Donnefort 	while (i < *pos) {
656*330b0cceSVincent Donnefort 		iter = trace_next(m, NULL, &i);
657*330b0cceSVincent Donnefort 		if (!iter)
658*330b0cceSVincent Donnefort 			return NULL;
659*330b0cceSVincent Donnefort 	}
660*330b0cceSVincent Donnefort 
661*330b0cceSVincent Donnefort 	return iter;
662*330b0cceSVincent Donnefort }
663*330b0cceSVincent Donnefort 
664*330b0cceSVincent Donnefort static int trace_show(struct seq_file *m, void *v)
665*330b0cceSVincent Donnefort {
666*330b0cceSVincent Donnefort 	struct trace_remote_iterator *iter = v;
667*330b0cceSVincent Donnefort 
668*330b0cceSVincent Donnefort 	trace_seq_init(&iter->seq);
669*330b0cceSVincent Donnefort 
670*330b0cceSVincent Donnefort 	if (trace_remote_iter_print_event(iter)) {
671*330b0cceSVincent Donnefort 		seq_printf(m, "[EVENT %d PRINT TOO BIG]\n", iter->evt->id);
672*330b0cceSVincent Donnefort 		return 0;
673*330b0cceSVincent Donnefort 	}
674*330b0cceSVincent Donnefort 
675*330b0cceSVincent Donnefort 	return trace_print_seq(m, &iter->seq);
676*330b0cceSVincent Donnefort }
677*330b0cceSVincent Donnefort 
678*330b0cceSVincent Donnefort static void trace_stop(struct seq_file *m, void *v)
679*330b0cceSVincent Donnefort {
680*330b0cceSVincent Donnefort 	struct trace_remote_iterator *iter = m->private;
681*330b0cceSVincent Donnefort 
682*330b0cceSVincent Donnefort 	if (iter)
683*330b0cceSVincent Donnefort 		trace_remote_iter_read_finished(iter);
684*330b0cceSVincent Donnefort }
685*330b0cceSVincent Donnefort 
686*330b0cceSVincent Donnefort static const struct seq_operations trace_sops = {
687*330b0cceSVincent Donnefort 	.start		= trace_start,
688*330b0cceSVincent Donnefort 	.next		= trace_next,
689*330b0cceSVincent Donnefort 	.show		= trace_show,
690*330b0cceSVincent Donnefort 	.stop		= trace_stop,
691*330b0cceSVincent Donnefort };
692*330b0cceSVincent Donnefort 
693*330b0cceSVincent Donnefort static int trace_open(struct inode *inode, struct file *filp)
694*330b0cceSVincent Donnefort {
695*330b0cceSVincent Donnefort 	struct trace_remote *remote = inode->i_private;
696*330b0cceSVincent Donnefort 	struct trace_remote_iterator *iter = NULL;
697*330b0cceSVincent Donnefort 	int cpu = tracing_get_cpu(inode);
698*330b0cceSVincent Donnefort 	int ret;
699*330b0cceSVincent Donnefort 
700*330b0cceSVincent Donnefort 	if (!(filp->f_mode & FMODE_READ))
701*330b0cceSVincent Donnefort 		return 0;
702*330b0cceSVincent Donnefort 
703*330b0cceSVincent Donnefort 	guard(mutex)(&remote->lock);
704*330b0cceSVincent Donnefort 
705*330b0cceSVincent Donnefort 	iter = trace_remote_iter(remote, cpu, TRI_NONCONSUMING);
706*330b0cceSVincent Donnefort 	if (IS_ERR(iter))
707*330b0cceSVincent Donnefort 		return PTR_ERR(iter);
708*330b0cceSVincent Donnefort 
709*330b0cceSVincent Donnefort 	ret = seq_open(filp, &trace_sops);
710*330b0cceSVincent Donnefort 	if (ret) {
711*330b0cceSVincent Donnefort 		trace_remote_iter_free(iter);
712*330b0cceSVincent Donnefort 		return ret;
713*330b0cceSVincent Donnefort 	}
714*330b0cceSVincent Donnefort 
715*330b0cceSVincent Donnefort 	((struct seq_file *)filp->private_data)->private = (void *)iter;
716*330b0cceSVincent Donnefort 
717*330b0cceSVincent Donnefort 	return 0;
718*330b0cceSVincent Donnefort }
719*330b0cceSVincent Donnefort 
720*330b0cceSVincent Donnefort static int trace_release(struct inode *inode, struct file *filp)
721*330b0cceSVincent Donnefort {
722*330b0cceSVincent Donnefort 	struct trace_remote_iterator *iter;
723*330b0cceSVincent Donnefort 
724*330b0cceSVincent Donnefort 	if (!(filp->f_mode & FMODE_READ))
725*330b0cceSVincent Donnefort 		return 0;
726*330b0cceSVincent Donnefort 
727*330b0cceSVincent Donnefort 	iter = ((struct seq_file *)filp->private_data)->private;
728*330b0cceSVincent Donnefort 	seq_release(inode, filp);
729*330b0cceSVincent Donnefort 
730*330b0cceSVincent Donnefort 	if (!iter)
731*330b0cceSVincent Donnefort 		return 0;
732*330b0cceSVincent Donnefort 
733*330b0cceSVincent Donnefort 	guard(mutex)(&iter->remote->lock);
734*330b0cceSVincent Donnefort 
735*330b0cceSVincent Donnefort 	trace_remote_iter_free(iter);
736*330b0cceSVincent Donnefort 
737*330b0cceSVincent Donnefort 	return 0;
738*330b0cceSVincent Donnefort }
739*330b0cceSVincent Donnefort 
7409af4ab0eSVincent Donnefort static ssize_t trace_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
7419af4ab0eSVincent Donnefort {
7429af4ab0eSVincent Donnefort 	struct inode *inode = file_inode(filp);
7439af4ab0eSVincent Donnefort 	struct trace_remote *remote = inode->i_private;
744*330b0cceSVincent Donnefort 	int cpu = tracing_get_cpu(inode);
7459af4ab0eSVincent Donnefort 
7469af4ab0eSVincent Donnefort 	guard(mutex)(&remote->lock);
7479af4ab0eSVincent Donnefort 
7489af4ab0eSVincent Donnefort 	trace_remote_reset(remote, cpu);
7499af4ab0eSVincent Donnefort 
7509af4ab0eSVincent Donnefort 	return cnt;
7519af4ab0eSVincent Donnefort }
7529af4ab0eSVincent Donnefort 
7539af4ab0eSVincent Donnefort static const struct file_operations trace_fops = {
754*330b0cceSVincent Donnefort 	.open		= trace_open,
7559af4ab0eSVincent Donnefort 	.write		= trace_write,
756*330b0cceSVincent Donnefort 	.read		= seq_read,
757*330b0cceSVincent Donnefort 	.read_iter	= seq_read_iter,
758*330b0cceSVincent Donnefort 	.release	= trace_release,
7599af4ab0eSVincent Donnefort };
7609af4ab0eSVincent Donnefort 
76196e43537SVincent Donnefort static int trace_remote_init_tracefs(const char *name, struct trace_remote *remote)
76296e43537SVincent Donnefort {
76396e43537SVincent Donnefort 	struct dentry *remote_d, *percpu_d, *d;
76496e43537SVincent Donnefort 	static struct dentry *root;
76596e43537SVincent Donnefort 	static DEFINE_MUTEX(lock);
76696e43537SVincent Donnefort 	bool root_inited = false;
76796e43537SVincent Donnefort 	int cpu;
76896e43537SVincent Donnefort 
76996e43537SVincent Donnefort 	guard(mutex)(&lock);
77096e43537SVincent Donnefort 
77196e43537SVincent Donnefort 	if (!root) {
77296e43537SVincent Donnefort 		root = tracefs_create_dir(TRACEFS_DIR, NULL);
77396e43537SVincent Donnefort 		if (!root) {
77496e43537SVincent Donnefort 			pr_err("Failed to create tracefs dir "TRACEFS_DIR"\n");
77596e43537SVincent Donnefort 			return -ENOMEM;
77696e43537SVincent Donnefort 		}
77796e43537SVincent Donnefort 		root_inited = true;
77896e43537SVincent Donnefort 	}
77996e43537SVincent Donnefort 
78096e43537SVincent Donnefort 	remote_d = tracefs_create_dir(name, root);
78196e43537SVincent Donnefort 	if (!remote_d) {
78296e43537SVincent Donnefort 		pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/\n", name);
78396e43537SVincent Donnefort 		goto err;
78496e43537SVincent Donnefort 	}
78596e43537SVincent Donnefort 
78696e43537SVincent Donnefort 	d = trace_create_file("tracing_on", TRACEFS_MODE_WRITE, remote_d, remote, &tracing_on_fops);
78796e43537SVincent Donnefort 	if (!d)
78896e43537SVincent Donnefort 		goto err;
78996e43537SVincent Donnefort 
79096e43537SVincent Donnefort 	d = trace_create_file("buffer_size_kb", TRACEFS_MODE_WRITE, remote_d, remote,
79196e43537SVincent Donnefort 			      &buffer_size_kb_fops);
79296e43537SVincent Donnefort 	if (!d)
79396e43537SVincent Donnefort 		goto err;
79496e43537SVincent Donnefort 
79596e43537SVincent Donnefort 	d = trace_create_file("trace_pipe", TRACEFS_MODE_READ, remote_d, remote, &trace_pipe_fops);
79696e43537SVincent Donnefort 	if (!d)
79796e43537SVincent Donnefort 		goto err;
79896e43537SVincent Donnefort 
7999af4ab0eSVincent Donnefort 	d = trace_create_file("trace", TRACEFS_MODE_WRITE, remote_d, remote, &trace_fops);
8009af4ab0eSVincent Donnefort 	if (!d)
8019af4ab0eSVincent Donnefort 		goto err;
8029af4ab0eSVincent Donnefort 
80396e43537SVincent Donnefort 	percpu_d = tracefs_create_dir("per_cpu", remote_d);
80496e43537SVincent Donnefort 	if (!percpu_d) {
80596e43537SVincent Donnefort 		pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/per_cpu/\n", name);
80696e43537SVincent Donnefort 		goto err;
80796e43537SVincent Donnefort 	}
80896e43537SVincent Donnefort 
80996e43537SVincent Donnefort 	for_each_possible_cpu(cpu) {
81096e43537SVincent Donnefort 		struct dentry *cpu_d;
81196e43537SVincent Donnefort 		char cpu_name[16];
81296e43537SVincent Donnefort 
81396e43537SVincent Donnefort 		snprintf(cpu_name, sizeof(cpu_name), "cpu%d", cpu);
81496e43537SVincent Donnefort 		cpu_d = tracefs_create_dir(cpu_name, percpu_d);
81596e43537SVincent Donnefort 		if (!cpu_d) {
81696e43537SVincent Donnefort 			pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/percpu/cpu%d\n",
81796e43537SVincent Donnefort 			       name, cpu);
81896e43537SVincent Donnefort 			goto err;
81996e43537SVincent Donnefort 		}
82096e43537SVincent Donnefort 
82196e43537SVincent Donnefort 		d = trace_create_cpu_file("trace_pipe", TRACEFS_MODE_READ, cpu_d, remote, cpu,
82296e43537SVincent Donnefort 					  &trace_pipe_fops);
82396e43537SVincent Donnefort 		if (!d)
82496e43537SVincent Donnefort 			goto err;
8259af4ab0eSVincent Donnefort 
8269af4ab0eSVincent Donnefort 		d = trace_create_cpu_file("trace", TRACEFS_MODE_WRITE, cpu_d, remote, cpu,
8279af4ab0eSVincent Donnefort 					  &trace_fops);
8289af4ab0eSVincent Donnefort 		if (!d)
8299af4ab0eSVincent Donnefort 			goto err;
83096e43537SVincent Donnefort 	}
83196e43537SVincent Donnefort 
83296e43537SVincent Donnefort 	return 0;
83396e43537SVincent Donnefort 
83496e43537SVincent Donnefort err:
83596e43537SVincent Donnefort 	if (root_inited) {
83696e43537SVincent Donnefort 		tracefs_remove(root);
83796e43537SVincent Donnefort 		root = NULL;
83896e43537SVincent Donnefort 	} else {
83996e43537SVincent Donnefort 		tracefs_remove(remote_d);
84096e43537SVincent Donnefort 	}
84196e43537SVincent Donnefort 
84296e43537SVincent Donnefort 	return -ENOMEM;
84396e43537SVincent Donnefort }
84496e43537SVincent Donnefort 
84596e43537SVincent Donnefort /**
84696e43537SVincent Donnefort  * trace_remote_register() - Register a Tracefs remote
84796e43537SVincent Donnefort  * @name:	Name of the remote, used for the Tracefs remotes/ directory.
84896e43537SVincent Donnefort  * @cbs:	Set of callbacks used to control the remote.
84996e43537SVincent Donnefort  * @priv:	Private data, passed to each callback from @cbs.
85096e43537SVincent Donnefort  * @events:	Array of events. &remote_event.name and &remote_event.id must be
85196e43537SVincent Donnefort  *		filled by the caller.
85296e43537SVincent Donnefort  * @nr_events:	Number of events in the @events array.
85396e43537SVincent Donnefort  *
85496e43537SVincent Donnefort  * A trace remote is an entity, outside of the kernel (most likely firmware or
85596e43537SVincent Donnefort  * hypervisor) capable of writing events into a Tracefs compatible ring-buffer.
85696e43537SVincent Donnefort  * The kernel would then act as a reader.
85796e43537SVincent Donnefort  *
85896e43537SVincent Donnefort  * The registered remote will be found under the Tracefs directory
85996e43537SVincent Donnefort  * remotes/<name>.
86096e43537SVincent Donnefort  *
86196e43537SVincent Donnefort  * Return: 0 on success, negative error code on failure.
86296e43537SVincent Donnefort  */
86396e43537SVincent Donnefort int trace_remote_register(const char *name, struct trace_remote_callbacks *cbs, void *priv)
86496e43537SVincent Donnefort {
86596e43537SVincent Donnefort 	struct trace_remote *remote;
86696e43537SVincent Donnefort 
86796e43537SVincent Donnefort 	remote = kzalloc_obj(*remote);
86896e43537SVincent Donnefort 	if (!remote)
86996e43537SVincent Donnefort 		return -ENOMEM;
87096e43537SVincent Donnefort 
87196e43537SVincent Donnefort 	remote->cbs = cbs;
87296e43537SVincent Donnefort 	remote->priv = priv;
87396e43537SVincent Donnefort 	remote->trace_buffer_size = 7 << 10;
87496e43537SVincent Donnefort 	remote->poll_ms = 100;
87596e43537SVincent Donnefort 	mutex_init(&remote->lock);
876*330b0cceSVincent Donnefort 	init_rwsem(&remote->reader_lock);
87796e43537SVincent Donnefort 
87896e43537SVincent Donnefort 	if (trace_remote_init_tracefs(name, remote)) {
87996e43537SVincent Donnefort 		kfree(remote);
88096e43537SVincent Donnefort 		return -ENOMEM;
88196e43537SVincent Donnefort 	}
88296e43537SVincent Donnefort 
88396e43537SVincent Donnefort 	return 0;
88496e43537SVincent Donnefort }
88596e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_register);
88696e43537SVincent Donnefort 
88796e43537SVincent Donnefort /**
88896e43537SVincent Donnefort  * trace_remote_free_buffer() - Free trace buffer allocated with trace_remote_alloc_buffer()
88996e43537SVincent Donnefort  * @desc:	Descriptor of the per-CPU ring-buffers, originally filled by
89096e43537SVincent Donnefort  *		trace_remote_alloc_buffer()
89196e43537SVincent Donnefort  *
89296e43537SVincent Donnefort  * Most likely called from &trace_remote_callbacks.unload_trace_buffer.
89396e43537SVincent Donnefort  */
89496e43537SVincent Donnefort void trace_remote_free_buffer(struct trace_buffer_desc *desc)
89596e43537SVincent Donnefort {
89696e43537SVincent Donnefort 	struct ring_buffer_desc *rb_desc;
89796e43537SVincent Donnefort 	int cpu;
89896e43537SVincent Donnefort 
89996e43537SVincent Donnefort 	for_each_ring_buffer_desc(rb_desc, cpu, desc) {
90096e43537SVincent Donnefort 		unsigned int id;
90196e43537SVincent Donnefort 
90296e43537SVincent Donnefort 		free_page(rb_desc->meta_va);
90396e43537SVincent Donnefort 
90496e43537SVincent Donnefort 		for (id = 0; id < rb_desc->nr_page_va; id++)
90596e43537SVincent Donnefort 			free_page(rb_desc->page_va[id]);
90696e43537SVincent Donnefort 	}
90796e43537SVincent Donnefort }
90896e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_free_buffer);
90996e43537SVincent Donnefort 
91096e43537SVincent Donnefort /**
91196e43537SVincent Donnefort  * trace_remote_alloc_buffer() - Dynamically allocate a trace buffer
91296e43537SVincent Donnefort  * @desc:		Uninitialized trace_buffer_desc
91396e43537SVincent Donnefort  * @desc_size:		Size of the trace_buffer_desc. Must be at least equal to
91496e43537SVincent Donnefort  *			trace_buffer_desc_size()
91596e43537SVincent Donnefort  * @buffer_size:	Size in bytes of each per-CPU ring-buffer
91696e43537SVincent Donnefort  * @cpumask:		CPUs to allocate a ring-buffer for
91796e43537SVincent Donnefort  *
91896e43537SVincent Donnefort  * Helper to dynamically allocate a set of pages (enough to cover @buffer_size)
91996e43537SVincent Donnefort  * for each CPU from @cpumask and fill @desc. Most likely called from
92096e43537SVincent Donnefort  * &trace_remote_callbacks.load_trace_buffer.
92196e43537SVincent Donnefort  *
92296e43537SVincent Donnefort  * Return: 0 on success, negative error code on failure.
92396e43537SVincent Donnefort  */
92496e43537SVincent Donnefort int trace_remote_alloc_buffer(struct trace_buffer_desc *desc, size_t desc_size, size_t buffer_size,
92596e43537SVincent Donnefort 			      const struct cpumask *cpumask)
92696e43537SVincent Donnefort {
92796e43537SVincent Donnefort 	unsigned int nr_pages = max(DIV_ROUND_UP(buffer_size, PAGE_SIZE), 2UL) + 1;
92896e43537SVincent Donnefort 	void *desc_end = desc + desc_size;
92996e43537SVincent Donnefort 	struct ring_buffer_desc *rb_desc;
93096e43537SVincent Donnefort 	int cpu, ret = -ENOMEM;
93196e43537SVincent Donnefort 
93296e43537SVincent Donnefort 	if (desc_size < struct_size(desc, __data, 0))
93396e43537SVincent Donnefort 		return -EINVAL;
93496e43537SVincent Donnefort 
93596e43537SVincent Donnefort 	desc->nr_cpus = 0;
93696e43537SVincent Donnefort 	desc->struct_len = struct_size(desc, __data, 0);
93796e43537SVincent Donnefort 
93896e43537SVincent Donnefort 	rb_desc = (struct ring_buffer_desc *)&desc->__data[0];
93996e43537SVincent Donnefort 
94096e43537SVincent Donnefort 	for_each_cpu(cpu, cpumask) {
94196e43537SVincent Donnefort 		unsigned int id;
94296e43537SVincent Donnefort 
94396e43537SVincent Donnefort 		if ((void *)rb_desc + struct_size(rb_desc, page_va, nr_pages) > desc_end) {
94496e43537SVincent Donnefort 			ret = -EINVAL;
94596e43537SVincent Donnefort 			goto err;
94696e43537SVincent Donnefort 		}
94796e43537SVincent Donnefort 
94896e43537SVincent Donnefort 		rb_desc->cpu = cpu;
94996e43537SVincent Donnefort 		rb_desc->nr_page_va = 0;
95096e43537SVincent Donnefort 		rb_desc->meta_va = (unsigned long)__get_free_page(GFP_KERNEL);
95196e43537SVincent Donnefort 		if (!rb_desc->meta_va)
95296e43537SVincent Donnefort 			goto err;
95396e43537SVincent Donnefort 
95496e43537SVincent Donnefort 		for (id = 0; id < nr_pages; id++) {
95596e43537SVincent Donnefort 			rb_desc->page_va[id] = (unsigned long)__get_free_page(GFP_KERNEL);
95696e43537SVincent Donnefort 			if (!rb_desc->page_va[id])
95796e43537SVincent Donnefort 				goto err;
95896e43537SVincent Donnefort 
95996e43537SVincent Donnefort 			rb_desc->nr_page_va++;
96096e43537SVincent Donnefort 		}
96196e43537SVincent Donnefort 		desc->nr_cpus++;
96296e43537SVincent Donnefort 		desc->struct_len += offsetof(struct ring_buffer_desc, page_va);
96396e43537SVincent Donnefort 		desc->struct_len += struct_size(rb_desc, page_va, rb_desc->nr_page_va);
96496e43537SVincent Donnefort 		rb_desc = __next_ring_buffer_desc(rb_desc);
96596e43537SVincent Donnefort 	}
96696e43537SVincent Donnefort 
96796e43537SVincent Donnefort 	return 0;
96896e43537SVincent Donnefort 
96996e43537SVincent Donnefort err:
97096e43537SVincent Donnefort 	trace_remote_free_buffer(desc);
97196e43537SVincent Donnefort 	return ret;
97296e43537SVincent Donnefort }
97396e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_alloc_buffer);
974