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 21330b0cceSVincent Donnefort enum tri_type { 22330b0cceSVincent Donnefort TRI_CONSUMING, 23330b0cceSVincent Donnefort TRI_NONCONSUMING, 24330b0cceSVincent Donnefort }; 25330b0cceSVincent 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; 32330b0cceSVincent Donnefort struct ring_buffer_iter *rb_iter; 33330b0cceSVincent Donnefort struct ring_buffer_iter **rb_iters; 3407252915SVincent Donnefort struct remote_event_hdr *evt; 3596e43537SVincent Donnefort int cpu; 3696e43537SVincent Donnefort int evt_cpu; 37330b0cceSVincent Donnefort loff_t pos; 38330b0cceSVincent Donnefort enum tri_type type; 3996e43537SVincent Donnefort }; 4096e43537SVincent Donnefort 4196e43537SVincent Donnefort struct trace_remote { 4296e43537SVincent Donnefort struct trace_remote_callbacks *cbs; 4396e43537SVincent Donnefort void *priv; 4496e43537SVincent Donnefort struct trace_buffer *trace_buffer; 4596e43537SVincent Donnefort struct trace_buffer_desc *trace_buffer_desc; 4607252915SVincent Donnefort struct dentry *dentry; 4707252915SVincent Donnefort struct eventfs_inode *eventfs; 4807252915SVincent Donnefort struct remote_event *events; 4907252915SVincent Donnefort unsigned long nr_events; 5096e43537SVincent Donnefort unsigned long trace_buffer_size; 5196e43537SVincent Donnefort struct ring_buffer_remote rb_remote; 5296e43537SVincent Donnefort struct mutex lock; 53330b0cceSVincent Donnefort struct rw_semaphore reader_lock; 54330b0cceSVincent Donnefort struct rw_semaphore *pcpu_reader_locks; 5596e43537SVincent Donnefort unsigned int nr_readers; 5696e43537SVincent Donnefort unsigned int poll_ms; 5796e43537SVincent Donnefort bool tracing_on; 5896e43537SVincent Donnefort }; 5996e43537SVincent Donnefort 6096e43537SVincent Donnefort static bool trace_remote_loaded(struct trace_remote *remote) 6196e43537SVincent Donnefort { 6296e43537SVincent Donnefort return !!remote->trace_buffer; 6396e43537SVincent Donnefort } 6496e43537SVincent Donnefort 6596e43537SVincent Donnefort static int trace_remote_load(struct trace_remote *remote) 6696e43537SVincent Donnefort { 6796e43537SVincent Donnefort struct ring_buffer_remote *rb_remote = &remote->rb_remote; 6896e43537SVincent Donnefort struct trace_buffer_desc *desc; 6996e43537SVincent Donnefort 7096e43537SVincent Donnefort lockdep_assert_held(&remote->lock); 7196e43537SVincent Donnefort 7296e43537SVincent Donnefort if (trace_remote_loaded(remote)) 7396e43537SVincent Donnefort return 0; 7496e43537SVincent Donnefort 7596e43537SVincent Donnefort desc = remote->cbs->load_trace_buffer(remote->trace_buffer_size, remote->priv); 7696e43537SVincent Donnefort if (IS_ERR(desc)) 7796e43537SVincent Donnefort return PTR_ERR(desc); 7896e43537SVincent Donnefort 7996e43537SVincent Donnefort rb_remote->desc = desc; 8096e43537SVincent Donnefort rb_remote->swap_reader_page = remote->cbs->swap_reader_page; 8196e43537SVincent Donnefort rb_remote->priv = remote->priv; 829af4ab0eSVincent Donnefort rb_remote->reset = remote->cbs->reset; 8396e43537SVincent Donnefort remote->trace_buffer = ring_buffer_alloc_remote(rb_remote); 8496e43537SVincent Donnefort if (!remote->trace_buffer) { 8596e43537SVincent Donnefort remote->cbs->unload_trace_buffer(desc, remote->priv); 8696e43537SVincent Donnefort return -ENOMEM; 8796e43537SVincent Donnefort } 8896e43537SVincent Donnefort 8996e43537SVincent Donnefort remote->trace_buffer_desc = desc; 9096e43537SVincent Donnefort 9196e43537SVincent Donnefort return 0; 9296e43537SVincent Donnefort } 9396e43537SVincent Donnefort 9496e43537SVincent Donnefort static void trace_remote_try_unload(struct trace_remote *remote) 9596e43537SVincent Donnefort { 9696e43537SVincent Donnefort lockdep_assert_held(&remote->lock); 9796e43537SVincent Donnefort 9896e43537SVincent Donnefort if (!trace_remote_loaded(remote)) 9996e43537SVincent Donnefort return; 10096e43537SVincent Donnefort 10196e43537SVincent Donnefort /* The buffer is being read or writable */ 10296e43537SVincent Donnefort if (remote->nr_readers || remote->tracing_on) 10396e43537SVincent Donnefort return; 10496e43537SVincent Donnefort 10596e43537SVincent Donnefort /* The buffer has readable data */ 10696e43537SVincent Donnefort if (!ring_buffer_empty(remote->trace_buffer)) 10796e43537SVincent Donnefort return; 10896e43537SVincent Donnefort 10996e43537SVincent Donnefort ring_buffer_free(remote->trace_buffer); 11096e43537SVincent Donnefort remote->trace_buffer = NULL; 11196e43537SVincent Donnefort remote->cbs->unload_trace_buffer(remote->trace_buffer_desc, remote->priv); 11296e43537SVincent Donnefort } 11396e43537SVincent Donnefort 11496e43537SVincent Donnefort static int trace_remote_enable_tracing(struct trace_remote *remote) 11596e43537SVincent Donnefort { 11696e43537SVincent Donnefort int ret; 11796e43537SVincent Donnefort 11896e43537SVincent Donnefort lockdep_assert_held(&remote->lock); 11996e43537SVincent Donnefort 12096e43537SVincent Donnefort if (remote->tracing_on) 12196e43537SVincent Donnefort return 0; 12296e43537SVincent Donnefort 12396e43537SVincent Donnefort ret = trace_remote_load(remote); 12496e43537SVincent Donnefort if (ret) 12596e43537SVincent Donnefort return ret; 12696e43537SVincent Donnefort 12796e43537SVincent Donnefort ret = remote->cbs->enable_tracing(true, remote->priv); 12896e43537SVincent Donnefort if (ret) { 12996e43537SVincent Donnefort trace_remote_try_unload(remote); 13096e43537SVincent Donnefort return ret; 13196e43537SVincent Donnefort } 13296e43537SVincent Donnefort 13396e43537SVincent Donnefort remote->tracing_on = true; 13496e43537SVincent Donnefort 13596e43537SVincent Donnefort return 0; 13696e43537SVincent Donnefort } 13796e43537SVincent Donnefort 13896e43537SVincent Donnefort static int trace_remote_disable_tracing(struct trace_remote *remote) 13996e43537SVincent Donnefort { 14096e43537SVincent Donnefort int ret; 14196e43537SVincent Donnefort 14296e43537SVincent Donnefort lockdep_assert_held(&remote->lock); 14396e43537SVincent Donnefort 14496e43537SVincent Donnefort if (!remote->tracing_on) 14596e43537SVincent Donnefort return 0; 14696e43537SVincent Donnefort 14796e43537SVincent Donnefort ret = remote->cbs->enable_tracing(false, remote->priv); 14896e43537SVincent Donnefort if (ret) 14996e43537SVincent Donnefort return ret; 15096e43537SVincent Donnefort 15196e43537SVincent Donnefort ring_buffer_poll_remote(remote->trace_buffer, RING_BUFFER_ALL_CPUS); 15296e43537SVincent Donnefort remote->tracing_on = false; 15396e43537SVincent Donnefort trace_remote_try_unload(remote); 15496e43537SVincent Donnefort 15596e43537SVincent Donnefort return 0; 15696e43537SVincent Donnefort } 15796e43537SVincent Donnefort 1589af4ab0eSVincent Donnefort static void trace_remote_reset(struct trace_remote *remote, int cpu) 1599af4ab0eSVincent Donnefort { 1609af4ab0eSVincent Donnefort lockdep_assert_held(&remote->lock); 1619af4ab0eSVincent Donnefort 1629af4ab0eSVincent Donnefort if (!trace_remote_loaded(remote)) 1639af4ab0eSVincent Donnefort return; 1649af4ab0eSVincent Donnefort 1659af4ab0eSVincent Donnefort if (cpu == RING_BUFFER_ALL_CPUS) 1669af4ab0eSVincent Donnefort ring_buffer_reset(remote->trace_buffer); 1679af4ab0eSVincent Donnefort else 1689af4ab0eSVincent Donnefort ring_buffer_reset_cpu(remote->trace_buffer, cpu); 1699af4ab0eSVincent Donnefort 1709af4ab0eSVincent Donnefort trace_remote_try_unload(remote); 1719af4ab0eSVincent Donnefort } 1729af4ab0eSVincent Donnefort 17396e43537SVincent Donnefort static ssize_t 17496e43537SVincent Donnefort tracing_on_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) 17596e43537SVincent Donnefort { 17607252915SVincent Donnefort struct seq_file *seq = filp->private_data; 17707252915SVincent Donnefort struct trace_remote *remote = seq->private; 17896e43537SVincent Donnefort unsigned long val; 17996e43537SVincent Donnefort int ret; 18096e43537SVincent Donnefort 18196e43537SVincent Donnefort ret = kstrtoul_from_user(ubuf, cnt, 10, &val); 18296e43537SVincent Donnefort if (ret) 18396e43537SVincent Donnefort return ret; 18496e43537SVincent Donnefort 18596e43537SVincent Donnefort guard(mutex)(&remote->lock); 18696e43537SVincent Donnefort 18796e43537SVincent Donnefort ret = val ? trace_remote_enable_tracing(remote) : trace_remote_disable_tracing(remote); 18896e43537SVincent Donnefort if (ret) 18996e43537SVincent Donnefort return ret; 19096e43537SVincent Donnefort 19196e43537SVincent Donnefort return cnt; 19296e43537SVincent Donnefort } 19396e43537SVincent Donnefort static int tracing_on_show(struct seq_file *s, void *unused) 19496e43537SVincent Donnefort { 19596e43537SVincent Donnefort struct trace_remote *remote = s->private; 19696e43537SVincent Donnefort 19796e43537SVincent Donnefort seq_printf(s, "%d\n", remote->tracing_on); 19896e43537SVincent Donnefort 19996e43537SVincent Donnefort return 0; 20096e43537SVincent Donnefort } 20196e43537SVincent Donnefort DEFINE_SHOW_STORE_ATTRIBUTE(tracing_on); 20296e43537SVincent Donnefort 20396e43537SVincent Donnefort static ssize_t buffer_size_kb_write(struct file *filp, const char __user *ubuf, size_t cnt, 20496e43537SVincent Donnefort loff_t *ppos) 20596e43537SVincent Donnefort { 20607252915SVincent Donnefort struct seq_file *seq = filp->private_data; 20707252915SVincent Donnefort struct trace_remote *remote = seq->private; 20896e43537SVincent Donnefort unsigned long val; 20996e43537SVincent Donnefort int ret; 21096e43537SVincent Donnefort 21196e43537SVincent Donnefort ret = kstrtoul_from_user(ubuf, cnt, 10, &val); 21296e43537SVincent Donnefort if (ret) 21396e43537SVincent Donnefort return ret; 21496e43537SVincent Donnefort 21596e43537SVincent Donnefort /* KiB to Bytes */ 21696e43537SVincent Donnefort if (!val || check_shl_overflow(val, 10, &val)) 21796e43537SVincent Donnefort return -EINVAL; 21896e43537SVincent Donnefort 21996e43537SVincent Donnefort guard(mutex)(&remote->lock); 22096e43537SVincent Donnefort 22196e43537SVincent Donnefort if (trace_remote_loaded(remote)) 22296e43537SVincent Donnefort return -EBUSY; 22396e43537SVincent Donnefort 22496e43537SVincent Donnefort remote->trace_buffer_size = val; 22596e43537SVincent Donnefort 22696e43537SVincent Donnefort return cnt; 22796e43537SVincent Donnefort } 22896e43537SVincent Donnefort 22996e43537SVincent Donnefort static int buffer_size_kb_show(struct seq_file *s, void *unused) 23096e43537SVincent Donnefort { 23196e43537SVincent Donnefort struct trace_remote *remote = s->private; 23296e43537SVincent Donnefort 23396e43537SVincent Donnefort seq_printf(s, "%lu (%s)\n", remote->trace_buffer_size >> 10, 23496e43537SVincent Donnefort trace_remote_loaded(remote) ? "loaded" : "unloaded"); 23596e43537SVincent Donnefort 23696e43537SVincent Donnefort return 0; 23796e43537SVincent Donnefort } 23896e43537SVincent Donnefort DEFINE_SHOW_STORE_ATTRIBUTE(buffer_size_kb); 23996e43537SVincent Donnefort 24096e43537SVincent Donnefort static int trace_remote_get(struct trace_remote *remote, int cpu) 24196e43537SVincent Donnefort { 24296e43537SVincent Donnefort int ret; 24396e43537SVincent Donnefort 24496e43537SVincent Donnefort if (remote->nr_readers == UINT_MAX) 24596e43537SVincent Donnefort return -EBUSY; 24696e43537SVincent Donnefort 24796e43537SVincent Donnefort ret = trace_remote_load(remote); 24896e43537SVincent Donnefort if (ret) 24996e43537SVincent Donnefort return ret; 25096e43537SVincent Donnefort 251330b0cceSVincent Donnefort if (cpu != RING_BUFFER_ALL_CPUS && !remote->pcpu_reader_locks) { 252330b0cceSVincent Donnefort int lock_cpu; 253330b0cceSVincent Donnefort 254330b0cceSVincent Donnefort remote->pcpu_reader_locks = kcalloc(nr_cpu_ids, sizeof(*remote->pcpu_reader_locks), 255330b0cceSVincent Donnefort GFP_KERNEL); 256330b0cceSVincent Donnefort if (!remote->pcpu_reader_locks) { 257330b0cceSVincent Donnefort trace_remote_try_unload(remote); 258330b0cceSVincent Donnefort return -ENOMEM; 259330b0cceSVincent Donnefort } 260330b0cceSVincent Donnefort 261330b0cceSVincent Donnefort for_each_possible_cpu(lock_cpu) 262330b0cceSVincent Donnefort init_rwsem(&remote->pcpu_reader_locks[lock_cpu]); 263330b0cceSVincent Donnefort } 264330b0cceSVincent Donnefort 26596e43537SVincent Donnefort remote->nr_readers++; 26696e43537SVincent Donnefort 26796e43537SVincent Donnefort return 0; 26896e43537SVincent Donnefort } 26996e43537SVincent Donnefort 27096e43537SVincent Donnefort static void trace_remote_put(struct trace_remote *remote) 27196e43537SVincent Donnefort { 27296e43537SVincent Donnefort if (WARN_ON(!remote->nr_readers)) 27396e43537SVincent Donnefort return; 27496e43537SVincent Donnefort 27596e43537SVincent Donnefort remote->nr_readers--; 27696e43537SVincent Donnefort if (remote->nr_readers) 27796e43537SVincent Donnefort return; 27896e43537SVincent Donnefort 279330b0cceSVincent Donnefort kfree(remote->pcpu_reader_locks); 280330b0cceSVincent Donnefort remote->pcpu_reader_locks = NULL; 281330b0cceSVincent Donnefort 28296e43537SVincent Donnefort trace_remote_try_unload(remote); 28396e43537SVincent Donnefort } 28496e43537SVincent Donnefort 285*ce47b798SVincent Donnefort static bool trace_remote_has_cpu(struct trace_remote *remote, int cpu) 286*ce47b798SVincent Donnefort { 287*ce47b798SVincent Donnefort if (cpu == RING_BUFFER_ALL_CPUS) 288*ce47b798SVincent Donnefort return true; 289*ce47b798SVincent Donnefort 290*ce47b798SVincent Donnefort return ring_buffer_poll_remote(remote->trace_buffer, cpu) == 0; 291*ce47b798SVincent Donnefort } 292*ce47b798SVincent Donnefort 29396e43537SVincent Donnefort static void __poll_remote(struct work_struct *work) 29496e43537SVincent Donnefort { 29596e43537SVincent Donnefort struct delayed_work *dwork = to_delayed_work(work); 29696e43537SVincent Donnefort struct trace_remote_iterator *iter; 29796e43537SVincent Donnefort 29896e43537SVincent Donnefort iter = container_of(dwork, struct trace_remote_iterator, poll_work); 29996e43537SVincent Donnefort ring_buffer_poll_remote(iter->remote->trace_buffer, iter->cpu); 30096e43537SVincent Donnefort schedule_delayed_work((struct delayed_work *)work, 30196e43537SVincent Donnefort msecs_to_jiffies(iter->remote->poll_ms)); 30296e43537SVincent Donnefort } 30396e43537SVincent Donnefort 304330b0cceSVincent Donnefort static void __free_ring_buffer_iter(struct trace_remote_iterator *iter, int cpu) 305330b0cceSVincent Donnefort { 306330b0cceSVincent Donnefort if (cpu != RING_BUFFER_ALL_CPUS) { 307330b0cceSVincent Donnefort ring_buffer_read_finish(iter->rb_iter); 308330b0cceSVincent Donnefort return; 309330b0cceSVincent Donnefort } 310330b0cceSVincent Donnefort 311330b0cceSVincent Donnefort for_each_possible_cpu(cpu) { 312330b0cceSVincent Donnefort if (iter->rb_iters[cpu]) 313330b0cceSVincent Donnefort ring_buffer_read_finish(iter->rb_iters[cpu]); 314330b0cceSVincent Donnefort } 315330b0cceSVincent Donnefort 316330b0cceSVincent Donnefort kfree(iter->rb_iters); 317330b0cceSVincent Donnefort } 318330b0cceSVincent Donnefort 319330b0cceSVincent Donnefort static int __alloc_ring_buffer_iter(struct trace_remote_iterator *iter, int cpu) 320330b0cceSVincent Donnefort { 321330b0cceSVincent Donnefort if (cpu != RING_BUFFER_ALL_CPUS) { 322330b0cceSVincent Donnefort iter->rb_iter = ring_buffer_read_start(iter->remote->trace_buffer, cpu, GFP_KERNEL); 323330b0cceSVincent Donnefort 324330b0cceSVincent Donnefort return iter->rb_iter ? 0 : -ENOMEM; 325330b0cceSVincent Donnefort } 326330b0cceSVincent Donnefort 327330b0cceSVincent Donnefort iter->rb_iters = kcalloc(nr_cpu_ids, sizeof(*iter->rb_iters), GFP_KERNEL); 328330b0cceSVincent Donnefort if (!iter->rb_iters) 329330b0cceSVincent Donnefort return -ENOMEM; 330330b0cceSVincent Donnefort 331330b0cceSVincent Donnefort for_each_possible_cpu(cpu) { 332330b0cceSVincent Donnefort iter->rb_iters[cpu] = ring_buffer_read_start(iter->remote->trace_buffer, cpu, 333330b0cceSVincent Donnefort GFP_KERNEL); 334330b0cceSVincent Donnefort if (!iter->rb_iters[cpu]) { 335*ce47b798SVincent Donnefort /* This CPU isn't part of trace_buffer. Skip it */ 336*ce47b798SVincent Donnefort if (!trace_remote_has_cpu(iter->remote, cpu)) 337*ce47b798SVincent Donnefort continue; 338*ce47b798SVincent Donnefort 339330b0cceSVincent Donnefort __free_ring_buffer_iter(iter, RING_BUFFER_ALL_CPUS); 340330b0cceSVincent Donnefort return -ENOMEM; 341330b0cceSVincent Donnefort } 342330b0cceSVincent Donnefort } 343330b0cceSVincent Donnefort 344330b0cceSVincent Donnefort return 0; 345330b0cceSVincent Donnefort } 346330b0cceSVincent Donnefort 347330b0cceSVincent Donnefort static struct trace_remote_iterator 348330b0cceSVincent Donnefort *trace_remote_iter(struct trace_remote *remote, int cpu, enum tri_type type) 34996e43537SVincent Donnefort { 35096e43537SVincent Donnefort struct trace_remote_iterator *iter = NULL; 35196e43537SVincent Donnefort int ret; 35296e43537SVincent Donnefort 35396e43537SVincent Donnefort lockdep_assert_held(&remote->lock); 35496e43537SVincent Donnefort 355330b0cceSVincent Donnefort if (type == TRI_NONCONSUMING && !trace_remote_loaded(remote)) 356330b0cceSVincent Donnefort return NULL; 35796e43537SVincent Donnefort 35896e43537SVincent Donnefort ret = trace_remote_get(remote, cpu); 35996e43537SVincent Donnefort if (ret) 36096e43537SVincent Donnefort return ERR_PTR(ret); 36196e43537SVincent Donnefort 362*ce47b798SVincent Donnefort if (!trace_remote_has_cpu(remote, cpu)) { 363*ce47b798SVincent Donnefort ret = -ENODEV; 36496e43537SVincent Donnefort goto err; 365*ce47b798SVincent Donnefort } 36696e43537SVincent Donnefort 36796e43537SVincent Donnefort iter = kzalloc_obj(*iter); 36896e43537SVincent Donnefort if (iter) { 36996e43537SVincent Donnefort iter->remote = remote; 37096e43537SVincent Donnefort iter->cpu = cpu; 371330b0cceSVincent Donnefort iter->type = type; 37296e43537SVincent Donnefort trace_seq_init(&iter->seq); 373330b0cceSVincent Donnefort 374330b0cceSVincent Donnefort switch (type) { 375330b0cceSVincent Donnefort case TRI_CONSUMING: 376*ce47b798SVincent Donnefort ring_buffer_poll_remote(remote->trace_buffer, cpu); 37796e43537SVincent Donnefort INIT_DELAYED_WORK(&iter->poll_work, __poll_remote); 37896e43537SVincent Donnefort schedule_delayed_work(&iter->poll_work, msecs_to_jiffies(remote->poll_ms)); 379330b0cceSVincent Donnefort break; 380330b0cceSVincent Donnefort case TRI_NONCONSUMING: 381330b0cceSVincent Donnefort ret = __alloc_ring_buffer_iter(iter, cpu); 382330b0cceSVincent Donnefort break; 383330b0cceSVincent Donnefort } 384330b0cceSVincent Donnefort 385330b0cceSVincent Donnefort if (ret) 386330b0cceSVincent Donnefort goto err; 38796e43537SVincent Donnefort 38896e43537SVincent Donnefort return iter; 38996e43537SVincent Donnefort } 39096e43537SVincent Donnefort ret = -ENOMEM; 39196e43537SVincent Donnefort 39296e43537SVincent Donnefort err: 39396e43537SVincent Donnefort kfree(iter); 39496e43537SVincent Donnefort trace_remote_put(remote); 39596e43537SVincent Donnefort 39696e43537SVincent Donnefort return ERR_PTR(ret); 39796e43537SVincent Donnefort } 39896e43537SVincent Donnefort 39996e43537SVincent Donnefort static void trace_remote_iter_free(struct trace_remote_iterator *iter) 40096e43537SVincent Donnefort { 40196e43537SVincent Donnefort struct trace_remote *remote; 40296e43537SVincent Donnefort 40396e43537SVincent Donnefort if (!iter) 40496e43537SVincent Donnefort return; 40596e43537SVincent Donnefort 40696e43537SVincent Donnefort remote = iter->remote; 40796e43537SVincent Donnefort 40896e43537SVincent Donnefort lockdep_assert_held(&remote->lock); 40996e43537SVincent Donnefort 410330b0cceSVincent Donnefort switch (iter->type) { 411330b0cceSVincent Donnefort case TRI_CONSUMING: 412330b0cceSVincent Donnefort cancel_delayed_work_sync(&iter->poll_work); 413330b0cceSVincent Donnefort break; 414330b0cceSVincent Donnefort case TRI_NONCONSUMING: 415330b0cceSVincent Donnefort __free_ring_buffer_iter(iter, iter->cpu); 416330b0cceSVincent Donnefort break; 417330b0cceSVincent Donnefort } 418330b0cceSVincent Donnefort 41996e43537SVincent Donnefort kfree(iter); 42096e43537SVincent Donnefort trace_remote_put(remote); 42196e43537SVincent Donnefort } 42296e43537SVincent Donnefort 423330b0cceSVincent Donnefort static void trace_remote_iter_read_start(struct trace_remote_iterator *iter) 424330b0cceSVincent Donnefort { 425330b0cceSVincent Donnefort struct trace_remote *remote = iter->remote; 426330b0cceSVincent Donnefort int cpu = iter->cpu; 427330b0cceSVincent Donnefort 428330b0cceSVincent Donnefort /* Acquire global reader lock */ 429330b0cceSVincent Donnefort if (cpu == RING_BUFFER_ALL_CPUS && iter->type == TRI_CONSUMING) 430330b0cceSVincent Donnefort down_write(&remote->reader_lock); 431330b0cceSVincent Donnefort else 432330b0cceSVincent Donnefort down_read(&remote->reader_lock); 433330b0cceSVincent Donnefort 434330b0cceSVincent Donnefort if (cpu == RING_BUFFER_ALL_CPUS) 435330b0cceSVincent Donnefort return; 436330b0cceSVincent Donnefort 437330b0cceSVincent Donnefort /* 438330b0cceSVincent Donnefort * No need for the remote lock here, iter holds a reference on 439330b0cceSVincent Donnefort * remote->nr_readers 440330b0cceSVincent Donnefort */ 441330b0cceSVincent Donnefort 442330b0cceSVincent Donnefort /* Get the per-CPU one */ 443330b0cceSVincent Donnefort if (WARN_ON_ONCE(!remote->pcpu_reader_locks)) 444330b0cceSVincent Donnefort return; 445330b0cceSVincent Donnefort 446330b0cceSVincent Donnefort if (iter->type == TRI_CONSUMING) 447330b0cceSVincent Donnefort down_write(&remote->pcpu_reader_locks[cpu]); 448330b0cceSVincent Donnefort else 449330b0cceSVincent Donnefort down_read(&remote->pcpu_reader_locks[cpu]); 450330b0cceSVincent Donnefort } 451330b0cceSVincent Donnefort 452330b0cceSVincent Donnefort static void trace_remote_iter_read_finished(struct trace_remote_iterator *iter) 453330b0cceSVincent Donnefort { 454330b0cceSVincent Donnefort struct trace_remote *remote = iter->remote; 455330b0cceSVincent Donnefort int cpu = iter->cpu; 456330b0cceSVincent Donnefort 457330b0cceSVincent Donnefort /* Release per-CPU reader lock */ 458330b0cceSVincent Donnefort if (cpu != RING_BUFFER_ALL_CPUS) { 459330b0cceSVincent Donnefort /* 460330b0cceSVincent Donnefort * No need for the remote lock here, iter holds a reference on 461330b0cceSVincent Donnefort * remote->nr_readers 462330b0cceSVincent Donnefort */ 463330b0cceSVincent Donnefort if (iter->type == TRI_CONSUMING) 464330b0cceSVincent Donnefort up_write(&remote->pcpu_reader_locks[cpu]); 465330b0cceSVincent Donnefort else 466330b0cceSVincent Donnefort up_read(&remote->pcpu_reader_locks[cpu]); 467330b0cceSVincent Donnefort } 468330b0cceSVincent Donnefort 469330b0cceSVincent Donnefort /* Release global reader lock */ 470330b0cceSVincent Donnefort if (cpu == RING_BUFFER_ALL_CPUS && iter->type == TRI_CONSUMING) 471330b0cceSVincent Donnefort up_write(&remote->reader_lock); 472330b0cceSVincent Donnefort else 473330b0cceSVincent Donnefort up_read(&remote->reader_lock); 474330b0cceSVincent Donnefort } 475330b0cceSVincent Donnefort 476330b0cceSVincent Donnefort static struct ring_buffer_iter *__get_rb_iter(struct trace_remote_iterator *iter, int cpu) 477330b0cceSVincent Donnefort { 478330b0cceSVincent Donnefort return iter->cpu != RING_BUFFER_ALL_CPUS ? iter->rb_iter : iter->rb_iters[cpu]; 479330b0cceSVincent Donnefort } 480330b0cceSVincent Donnefort 481330b0cceSVincent Donnefort static struct ring_buffer_event * 482330b0cceSVincent Donnefort __peek_event(struct trace_remote_iterator *iter, int cpu, u64 *ts, unsigned long *lost_events) 483330b0cceSVincent Donnefort { 484330b0cceSVincent Donnefort struct ring_buffer_event *rb_evt; 485330b0cceSVincent Donnefort struct ring_buffer_iter *rb_iter; 486330b0cceSVincent Donnefort 487330b0cceSVincent Donnefort switch (iter->type) { 488330b0cceSVincent Donnefort case TRI_CONSUMING: 489330b0cceSVincent Donnefort return ring_buffer_peek(iter->remote->trace_buffer, cpu, ts, lost_events); 490330b0cceSVincent Donnefort case TRI_NONCONSUMING: 491330b0cceSVincent Donnefort rb_iter = __get_rb_iter(iter, cpu); 492*ce47b798SVincent Donnefort if (!rb_iter) 493*ce47b798SVincent Donnefort return NULL; 494*ce47b798SVincent Donnefort 495330b0cceSVincent Donnefort rb_evt = ring_buffer_iter_peek(rb_iter, ts); 496330b0cceSVincent Donnefort if (!rb_evt) 497330b0cceSVincent Donnefort return NULL; 498330b0cceSVincent Donnefort 499330b0cceSVincent Donnefort *lost_events = ring_buffer_iter_dropped(rb_iter); 500330b0cceSVincent Donnefort 501330b0cceSVincent Donnefort return rb_evt; 502330b0cceSVincent Donnefort } 503330b0cceSVincent Donnefort 504330b0cceSVincent Donnefort return NULL; 505330b0cceSVincent Donnefort } 506330b0cceSVincent Donnefort 50796e43537SVincent Donnefort static bool trace_remote_iter_read_event(struct trace_remote_iterator *iter) 50896e43537SVincent Donnefort { 50996e43537SVincent Donnefort struct trace_buffer *trace_buffer = iter->remote->trace_buffer; 51007252915SVincent Donnefort struct ring_buffer_event *rb_evt; 51196e43537SVincent Donnefort int cpu = iter->cpu; 51296e43537SVincent Donnefort 51396e43537SVincent Donnefort if (cpu != RING_BUFFER_ALL_CPUS) { 51496e43537SVincent Donnefort if (ring_buffer_empty_cpu(trace_buffer, cpu)) 51596e43537SVincent Donnefort return false; 51696e43537SVincent Donnefort 51707252915SVincent Donnefort rb_evt = __peek_event(iter, cpu, &iter->ts, &iter->lost_events); 51807252915SVincent Donnefort if (!rb_evt) 51996e43537SVincent Donnefort return false; 52096e43537SVincent Donnefort 52196e43537SVincent Donnefort iter->evt_cpu = cpu; 52207252915SVincent Donnefort iter->evt = ring_buffer_event_data(rb_evt); 52396e43537SVincent Donnefort return true; 52496e43537SVincent Donnefort } 52596e43537SVincent Donnefort 52696e43537SVincent Donnefort iter->ts = U64_MAX; 52796e43537SVincent Donnefort for_each_possible_cpu(cpu) { 52896e43537SVincent Donnefort unsigned long lost_events; 52996e43537SVincent Donnefort u64 ts; 53096e43537SVincent Donnefort 53196e43537SVincent Donnefort if (ring_buffer_empty_cpu(trace_buffer, cpu)) 53296e43537SVincent Donnefort continue; 53396e43537SVincent Donnefort 53407252915SVincent Donnefort rb_evt = __peek_event(iter, cpu, &ts, &lost_events); 53507252915SVincent Donnefort if (!rb_evt) 53696e43537SVincent Donnefort continue; 53796e43537SVincent Donnefort 53896e43537SVincent Donnefort if (ts >= iter->ts) 53996e43537SVincent Donnefort continue; 54096e43537SVincent Donnefort 54196e43537SVincent Donnefort iter->ts = ts; 54296e43537SVincent Donnefort iter->evt_cpu = cpu; 54307252915SVincent Donnefort iter->evt = ring_buffer_event_data(rb_evt); 54496e43537SVincent Donnefort iter->lost_events = lost_events; 54596e43537SVincent Donnefort } 54696e43537SVincent Donnefort 54796e43537SVincent Donnefort return iter->ts != U64_MAX; 54896e43537SVincent Donnefort } 54996e43537SVincent Donnefort 550330b0cceSVincent Donnefort static void trace_remote_iter_move(struct trace_remote_iterator *iter) 551330b0cceSVincent Donnefort { 552330b0cceSVincent Donnefort struct trace_buffer *trace_buffer = iter->remote->trace_buffer; 553330b0cceSVincent Donnefort 554330b0cceSVincent Donnefort switch (iter->type) { 555330b0cceSVincent Donnefort case TRI_CONSUMING: 556330b0cceSVincent Donnefort ring_buffer_consume(trace_buffer, iter->evt_cpu, NULL, NULL); 557330b0cceSVincent Donnefort break; 558330b0cceSVincent Donnefort case TRI_NONCONSUMING: 559330b0cceSVincent Donnefort ring_buffer_iter_advance(__get_rb_iter(iter, iter->evt_cpu)); 560330b0cceSVincent Donnefort break; 561330b0cceSVincent Donnefort } 562330b0cceSVincent Donnefort } 563330b0cceSVincent Donnefort 56407252915SVincent Donnefort static struct remote_event *trace_remote_find_event(struct trace_remote *remote, unsigned short id); 56507252915SVincent Donnefort 56696e43537SVincent Donnefort static int trace_remote_iter_print_event(struct trace_remote_iterator *iter) 56796e43537SVincent Donnefort { 56807252915SVincent Donnefort struct remote_event *evt; 56996e43537SVincent Donnefort unsigned long usecs_rem; 57096e43537SVincent Donnefort u64 ts = iter->ts; 57196e43537SVincent Donnefort 57296e43537SVincent Donnefort if (iter->lost_events) 57396e43537SVincent Donnefort trace_seq_printf(&iter->seq, "CPU:%d [LOST %lu EVENTS]\n", 57496e43537SVincent Donnefort iter->evt_cpu, iter->lost_events); 57596e43537SVincent Donnefort 57696e43537SVincent Donnefort do_div(ts, 1000); 57796e43537SVincent Donnefort usecs_rem = do_div(ts, USEC_PER_SEC); 57896e43537SVincent Donnefort 57996e43537SVincent Donnefort trace_seq_printf(&iter->seq, "[%03d]\t%5llu.%06lu: ", iter->evt_cpu, 58096e43537SVincent Donnefort ts, usecs_rem); 58196e43537SVincent Donnefort 58207252915SVincent Donnefort evt = trace_remote_find_event(iter->remote, iter->evt->id); 58307252915SVincent Donnefort if (!evt) 58407252915SVincent Donnefort trace_seq_printf(&iter->seq, "UNKNOWN id=%d\n", iter->evt->id); 58507252915SVincent Donnefort else 58607252915SVincent Donnefort evt->print(iter->evt, &iter->seq); 58707252915SVincent Donnefort 58896e43537SVincent Donnefort return trace_seq_has_overflowed(&iter->seq) ? -EOVERFLOW : 0; 58996e43537SVincent Donnefort } 59096e43537SVincent Donnefort 59196e43537SVincent Donnefort static int trace_pipe_open(struct inode *inode, struct file *filp) 59296e43537SVincent Donnefort { 59396e43537SVincent Donnefort struct trace_remote *remote = inode->i_private; 59496e43537SVincent Donnefort struct trace_remote_iterator *iter; 595330b0cceSVincent Donnefort int cpu = tracing_get_cpu(inode); 59696e43537SVincent Donnefort 59796e43537SVincent Donnefort guard(mutex)(&remote->lock); 598330b0cceSVincent Donnefort 599330b0cceSVincent Donnefort iter = trace_remote_iter(remote, cpu, TRI_CONSUMING); 600330b0cceSVincent Donnefort if (IS_ERR(iter)) 601330b0cceSVincent Donnefort return PTR_ERR(iter); 602330b0cceSVincent Donnefort 60396e43537SVincent Donnefort filp->private_data = iter; 60496e43537SVincent Donnefort 60596e43537SVincent Donnefort return IS_ERR(iter) ? PTR_ERR(iter) : 0; 60696e43537SVincent Donnefort } 60796e43537SVincent Donnefort 60896e43537SVincent Donnefort static int trace_pipe_release(struct inode *inode, struct file *filp) 60996e43537SVincent Donnefort { 61096e43537SVincent Donnefort struct trace_remote_iterator *iter = filp->private_data; 61196e43537SVincent Donnefort struct trace_remote *remote = iter->remote; 61296e43537SVincent Donnefort 61396e43537SVincent Donnefort guard(mutex)(&remote->lock); 61496e43537SVincent Donnefort 61596e43537SVincent Donnefort trace_remote_iter_free(iter); 61696e43537SVincent Donnefort 61796e43537SVincent Donnefort return 0; 61896e43537SVincent Donnefort } 61996e43537SVincent Donnefort 62096e43537SVincent Donnefort static ssize_t trace_pipe_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) 62196e43537SVincent Donnefort { 62296e43537SVincent Donnefort struct trace_remote_iterator *iter = filp->private_data; 62396e43537SVincent Donnefort struct trace_buffer *trace_buffer = iter->remote->trace_buffer; 62496e43537SVincent Donnefort int ret; 62596e43537SVincent Donnefort 62696e43537SVincent Donnefort copy_to_user: 62796e43537SVincent Donnefort ret = trace_seq_to_user(&iter->seq, ubuf, cnt); 62896e43537SVincent Donnefort if (ret != -EBUSY) 62996e43537SVincent Donnefort return ret; 63096e43537SVincent Donnefort 63196e43537SVincent Donnefort trace_seq_init(&iter->seq); 63296e43537SVincent Donnefort 63396e43537SVincent Donnefort ret = ring_buffer_wait(trace_buffer, iter->cpu, 0, NULL, NULL); 63496e43537SVincent Donnefort if (ret < 0) 63596e43537SVincent Donnefort return ret; 63696e43537SVincent Donnefort 637330b0cceSVincent Donnefort trace_remote_iter_read_start(iter); 638330b0cceSVincent Donnefort 63996e43537SVincent Donnefort while (trace_remote_iter_read_event(iter)) { 64096e43537SVincent Donnefort int prev_len = iter->seq.seq.len; 64196e43537SVincent Donnefort 64296e43537SVincent Donnefort if (trace_remote_iter_print_event(iter)) { 64396e43537SVincent Donnefort iter->seq.seq.len = prev_len; 64496e43537SVincent Donnefort break; 64596e43537SVincent Donnefort } 64696e43537SVincent Donnefort 647330b0cceSVincent Donnefort trace_remote_iter_move(iter); 64896e43537SVincent Donnefort } 64996e43537SVincent Donnefort 650330b0cceSVincent Donnefort trace_remote_iter_read_finished(iter); 651330b0cceSVincent Donnefort 65296e43537SVincent Donnefort goto copy_to_user; 65396e43537SVincent Donnefort } 65496e43537SVincent Donnefort 65596e43537SVincent Donnefort static const struct file_operations trace_pipe_fops = { 65696e43537SVincent Donnefort .open = trace_pipe_open, 65796e43537SVincent Donnefort .read = trace_pipe_read, 65896e43537SVincent Donnefort .release = trace_pipe_release, 65996e43537SVincent Donnefort }; 66096e43537SVincent Donnefort 661330b0cceSVincent Donnefort static void *trace_next(struct seq_file *m, void *v, loff_t *pos) 662330b0cceSVincent Donnefort { 663330b0cceSVincent Donnefort struct trace_remote_iterator *iter = m->private; 664330b0cceSVincent Donnefort 665330b0cceSVincent Donnefort ++*pos; 666330b0cceSVincent Donnefort 667330b0cceSVincent Donnefort if (!iter || !trace_remote_iter_read_event(iter)) 668330b0cceSVincent Donnefort return NULL; 669330b0cceSVincent Donnefort 670330b0cceSVincent Donnefort trace_remote_iter_move(iter); 671330b0cceSVincent Donnefort iter->pos++; 672330b0cceSVincent Donnefort 673330b0cceSVincent Donnefort return iter; 674330b0cceSVincent Donnefort } 675330b0cceSVincent Donnefort 676330b0cceSVincent Donnefort static void *trace_start(struct seq_file *m, loff_t *pos) 677330b0cceSVincent Donnefort { 678330b0cceSVincent Donnefort struct trace_remote_iterator *iter = m->private; 679330b0cceSVincent Donnefort loff_t i; 680330b0cceSVincent Donnefort 681330b0cceSVincent Donnefort if (!iter) 682330b0cceSVincent Donnefort return NULL; 683330b0cceSVincent Donnefort 684330b0cceSVincent Donnefort trace_remote_iter_read_start(iter); 685330b0cceSVincent Donnefort 686330b0cceSVincent Donnefort if (!*pos) { 687330b0cceSVincent Donnefort iter->pos = -1; 688330b0cceSVincent Donnefort return trace_next(m, NULL, &i); 689330b0cceSVincent Donnefort } 690330b0cceSVincent Donnefort 691330b0cceSVincent Donnefort i = iter->pos; 692330b0cceSVincent Donnefort while (i < *pos) { 693330b0cceSVincent Donnefort iter = trace_next(m, NULL, &i); 694330b0cceSVincent Donnefort if (!iter) 695330b0cceSVincent Donnefort return NULL; 696330b0cceSVincent Donnefort } 697330b0cceSVincent Donnefort 698330b0cceSVincent Donnefort return iter; 699330b0cceSVincent Donnefort } 700330b0cceSVincent Donnefort 701330b0cceSVincent Donnefort static int trace_show(struct seq_file *m, void *v) 702330b0cceSVincent Donnefort { 703330b0cceSVincent Donnefort struct trace_remote_iterator *iter = v; 704330b0cceSVincent Donnefort 705330b0cceSVincent Donnefort trace_seq_init(&iter->seq); 706330b0cceSVincent Donnefort 707330b0cceSVincent Donnefort if (trace_remote_iter_print_event(iter)) { 708330b0cceSVincent Donnefort seq_printf(m, "[EVENT %d PRINT TOO BIG]\n", iter->evt->id); 709330b0cceSVincent Donnefort return 0; 710330b0cceSVincent Donnefort } 711330b0cceSVincent Donnefort 712330b0cceSVincent Donnefort return trace_print_seq(m, &iter->seq); 713330b0cceSVincent Donnefort } 714330b0cceSVincent Donnefort 715330b0cceSVincent Donnefort static void trace_stop(struct seq_file *m, void *v) 716330b0cceSVincent Donnefort { 717330b0cceSVincent Donnefort struct trace_remote_iterator *iter = m->private; 718330b0cceSVincent Donnefort 719330b0cceSVincent Donnefort if (iter) 720330b0cceSVincent Donnefort trace_remote_iter_read_finished(iter); 721330b0cceSVincent Donnefort } 722330b0cceSVincent Donnefort 723330b0cceSVincent Donnefort static const struct seq_operations trace_sops = { 724330b0cceSVincent Donnefort .start = trace_start, 725330b0cceSVincent Donnefort .next = trace_next, 726330b0cceSVincent Donnefort .show = trace_show, 727330b0cceSVincent Donnefort .stop = trace_stop, 728330b0cceSVincent Donnefort }; 729330b0cceSVincent Donnefort 730330b0cceSVincent Donnefort static int trace_open(struct inode *inode, struct file *filp) 731330b0cceSVincent Donnefort { 732330b0cceSVincent Donnefort struct trace_remote *remote = inode->i_private; 733330b0cceSVincent Donnefort struct trace_remote_iterator *iter = NULL; 734330b0cceSVincent Donnefort int cpu = tracing_get_cpu(inode); 735330b0cceSVincent Donnefort int ret; 736330b0cceSVincent Donnefort 737330b0cceSVincent Donnefort if (!(filp->f_mode & FMODE_READ)) 738330b0cceSVincent Donnefort return 0; 739330b0cceSVincent Donnefort 740330b0cceSVincent Donnefort guard(mutex)(&remote->lock); 741330b0cceSVincent Donnefort 742330b0cceSVincent Donnefort iter = trace_remote_iter(remote, cpu, TRI_NONCONSUMING); 743330b0cceSVincent Donnefort if (IS_ERR(iter)) 744330b0cceSVincent Donnefort return PTR_ERR(iter); 745330b0cceSVincent Donnefort 746330b0cceSVincent Donnefort ret = seq_open(filp, &trace_sops); 747330b0cceSVincent Donnefort if (ret) { 748330b0cceSVincent Donnefort trace_remote_iter_free(iter); 749330b0cceSVincent Donnefort return ret; 750330b0cceSVincent Donnefort } 751330b0cceSVincent Donnefort 752330b0cceSVincent Donnefort ((struct seq_file *)filp->private_data)->private = (void *)iter; 753330b0cceSVincent Donnefort 754330b0cceSVincent Donnefort return 0; 755330b0cceSVincent Donnefort } 756330b0cceSVincent Donnefort 757330b0cceSVincent Donnefort static int trace_release(struct inode *inode, struct file *filp) 758330b0cceSVincent Donnefort { 759330b0cceSVincent Donnefort struct trace_remote_iterator *iter; 760330b0cceSVincent Donnefort 761330b0cceSVincent Donnefort if (!(filp->f_mode & FMODE_READ)) 762330b0cceSVincent Donnefort return 0; 763330b0cceSVincent Donnefort 764330b0cceSVincent Donnefort iter = ((struct seq_file *)filp->private_data)->private; 765330b0cceSVincent Donnefort seq_release(inode, filp); 766330b0cceSVincent Donnefort 767330b0cceSVincent Donnefort if (!iter) 768330b0cceSVincent Donnefort return 0; 769330b0cceSVincent Donnefort 770330b0cceSVincent Donnefort guard(mutex)(&iter->remote->lock); 771330b0cceSVincent Donnefort 772330b0cceSVincent Donnefort trace_remote_iter_free(iter); 773330b0cceSVincent Donnefort 774330b0cceSVincent Donnefort return 0; 775330b0cceSVincent Donnefort } 776330b0cceSVincent Donnefort 7779af4ab0eSVincent Donnefort static ssize_t trace_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) 7789af4ab0eSVincent Donnefort { 7799af4ab0eSVincent Donnefort struct inode *inode = file_inode(filp); 7809af4ab0eSVincent Donnefort struct trace_remote *remote = inode->i_private; 781330b0cceSVincent Donnefort int cpu = tracing_get_cpu(inode); 7829af4ab0eSVincent Donnefort 7839af4ab0eSVincent Donnefort guard(mutex)(&remote->lock); 7849af4ab0eSVincent Donnefort 7859af4ab0eSVincent Donnefort trace_remote_reset(remote, cpu); 7869af4ab0eSVincent Donnefort 7879af4ab0eSVincent Donnefort return cnt; 7889af4ab0eSVincent Donnefort } 7899af4ab0eSVincent Donnefort 7909af4ab0eSVincent Donnefort static const struct file_operations trace_fops = { 791330b0cceSVincent Donnefort .open = trace_open, 7929af4ab0eSVincent Donnefort .write = trace_write, 793330b0cceSVincent Donnefort .read = seq_read, 794330b0cceSVincent Donnefort .read_iter = seq_read_iter, 795330b0cceSVincent Donnefort .release = trace_release, 7969af4ab0eSVincent Donnefort }; 7979af4ab0eSVincent Donnefort 79896e43537SVincent Donnefort static int trace_remote_init_tracefs(const char *name, struct trace_remote *remote) 79996e43537SVincent Donnefort { 80096e43537SVincent Donnefort struct dentry *remote_d, *percpu_d, *d; 80196e43537SVincent Donnefort static struct dentry *root; 80296e43537SVincent Donnefort static DEFINE_MUTEX(lock); 80396e43537SVincent Donnefort bool root_inited = false; 80496e43537SVincent Donnefort int cpu; 80596e43537SVincent Donnefort 80696e43537SVincent Donnefort guard(mutex)(&lock); 80796e43537SVincent Donnefort 80896e43537SVincent Donnefort if (!root) { 80996e43537SVincent Donnefort root = tracefs_create_dir(TRACEFS_DIR, NULL); 81096e43537SVincent Donnefort if (!root) { 81196e43537SVincent Donnefort pr_err("Failed to create tracefs dir "TRACEFS_DIR"\n"); 81296e43537SVincent Donnefort return -ENOMEM; 81396e43537SVincent Donnefort } 81496e43537SVincent Donnefort root_inited = true; 81596e43537SVincent Donnefort } 81696e43537SVincent Donnefort 81796e43537SVincent Donnefort remote_d = tracefs_create_dir(name, root); 81896e43537SVincent Donnefort if (!remote_d) { 81996e43537SVincent Donnefort pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/\n", name); 82096e43537SVincent Donnefort goto err; 82196e43537SVincent Donnefort } 82296e43537SVincent Donnefort 82396e43537SVincent Donnefort d = trace_create_file("tracing_on", TRACEFS_MODE_WRITE, remote_d, remote, &tracing_on_fops); 82496e43537SVincent Donnefort if (!d) 82596e43537SVincent Donnefort goto err; 82696e43537SVincent Donnefort 82796e43537SVincent Donnefort d = trace_create_file("buffer_size_kb", TRACEFS_MODE_WRITE, remote_d, remote, 82896e43537SVincent Donnefort &buffer_size_kb_fops); 82996e43537SVincent Donnefort if (!d) 83096e43537SVincent Donnefort goto err; 83196e43537SVincent Donnefort 83296e43537SVincent Donnefort d = trace_create_file("trace_pipe", TRACEFS_MODE_READ, remote_d, remote, &trace_pipe_fops); 83396e43537SVincent Donnefort if (!d) 83496e43537SVincent Donnefort goto err; 83596e43537SVincent Donnefort 8369af4ab0eSVincent Donnefort d = trace_create_file("trace", TRACEFS_MODE_WRITE, remote_d, remote, &trace_fops); 8379af4ab0eSVincent Donnefort if (!d) 8389af4ab0eSVincent Donnefort goto err; 8399af4ab0eSVincent Donnefort 84096e43537SVincent Donnefort percpu_d = tracefs_create_dir("per_cpu", remote_d); 84196e43537SVincent Donnefort if (!percpu_d) { 84296e43537SVincent Donnefort pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/per_cpu/\n", name); 84396e43537SVincent Donnefort goto err; 84496e43537SVincent Donnefort } 84596e43537SVincent Donnefort 84696e43537SVincent Donnefort for_each_possible_cpu(cpu) { 84796e43537SVincent Donnefort struct dentry *cpu_d; 84896e43537SVincent Donnefort char cpu_name[16]; 84996e43537SVincent Donnefort 85096e43537SVincent Donnefort snprintf(cpu_name, sizeof(cpu_name), "cpu%d", cpu); 85196e43537SVincent Donnefort cpu_d = tracefs_create_dir(cpu_name, percpu_d); 85296e43537SVincent Donnefort if (!cpu_d) { 85396e43537SVincent Donnefort pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/percpu/cpu%d\n", 85496e43537SVincent Donnefort name, cpu); 85596e43537SVincent Donnefort goto err; 85696e43537SVincent Donnefort } 85796e43537SVincent Donnefort 85896e43537SVincent Donnefort d = trace_create_cpu_file("trace_pipe", TRACEFS_MODE_READ, cpu_d, remote, cpu, 85996e43537SVincent Donnefort &trace_pipe_fops); 86096e43537SVincent Donnefort if (!d) 86196e43537SVincent Donnefort goto err; 8629af4ab0eSVincent Donnefort 8639af4ab0eSVincent Donnefort d = trace_create_cpu_file("trace", TRACEFS_MODE_WRITE, cpu_d, remote, cpu, 8649af4ab0eSVincent Donnefort &trace_fops); 8659af4ab0eSVincent Donnefort if (!d) 8669af4ab0eSVincent Donnefort goto err; 86796e43537SVincent Donnefort } 86896e43537SVincent Donnefort 86907252915SVincent Donnefort remote->dentry = remote_d; 87007252915SVincent Donnefort 87196e43537SVincent Donnefort return 0; 87296e43537SVincent Donnefort 87396e43537SVincent Donnefort err: 87496e43537SVincent Donnefort if (root_inited) { 87596e43537SVincent Donnefort tracefs_remove(root); 87696e43537SVincent Donnefort root = NULL; 87796e43537SVincent Donnefort } else { 87896e43537SVincent Donnefort tracefs_remove(remote_d); 87996e43537SVincent Donnefort } 88096e43537SVincent Donnefort 88196e43537SVincent Donnefort return -ENOMEM; 88296e43537SVincent Donnefort } 88396e43537SVincent Donnefort 88407252915SVincent Donnefort static int trace_remote_register_events(const char *remote_name, struct trace_remote *remote, 88507252915SVincent Donnefort struct remote_event *events, size_t nr_events); 88607252915SVincent Donnefort 88796e43537SVincent Donnefort /** 88896e43537SVincent Donnefort * trace_remote_register() - Register a Tracefs remote 88996e43537SVincent Donnefort * @name: Name of the remote, used for the Tracefs remotes/ directory. 89096e43537SVincent Donnefort * @cbs: Set of callbacks used to control the remote. 89196e43537SVincent Donnefort * @priv: Private data, passed to each callback from @cbs. 89296e43537SVincent Donnefort * @events: Array of events. &remote_event.name and &remote_event.id must be 89396e43537SVincent Donnefort * filled by the caller. 89496e43537SVincent Donnefort * @nr_events: Number of events in the @events array. 89596e43537SVincent Donnefort * 89696e43537SVincent Donnefort * A trace remote is an entity, outside of the kernel (most likely firmware or 89796e43537SVincent Donnefort * hypervisor) capable of writing events into a Tracefs compatible ring-buffer. 89896e43537SVincent Donnefort * The kernel would then act as a reader. 89996e43537SVincent Donnefort * 90096e43537SVincent Donnefort * The registered remote will be found under the Tracefs directory 90196e43537SVincent Donnefort * remotes/<name>. 90296e43537SVincent Donnefort * 90396e43537SVincent Donnefort * Return: 0 on success, negative error code on failure. 90496e43537SVincent Donnefort */ 90507252915SVincent Donnefort int trace_remote_register(const char *name, struct trace_remote_callbacks *cbs, void *priv, 90607252915SVincent Donnefort struct remote_event *events, size_t nr_events) 90796e43537SVincent Donnefort { 90896e43537SVincent Donnefort struct trace_remote *remote; 909bf2ba0f8SVincent Donnefort int ret; 91096e43537SVincent Donnefort 91196e43537SVincent Donnefort remote = kzalloc_obj(*remote); 91296e43537SVincent Donnefort if (!remote) 91396e43537SVincent Donnefort return -ENOMEM; 91496e43537SVincent Donnefort 91596e43537SVincent Donnefort remote->cbs = cbs; 91696e43537SVincent Donnefort remote->priv = priv; 91796e43537SVincent Donnefort remote->trace_buffer_size = 7 << 10; 91896e43537SVincent Donnefort remote->poll_ms = 100; 91996e43537SVincent Donnefort mutex_init(&remote->lock); 920330b0cceSVincent Donnefort init_rwsem(&remote->reader_lock); 92196e43537SVincent Donnefort 92296e43537SVincent Donnefort if (trace_remote_init_tracefs(name, remote)) { 92396e43537SVincent Donnefort kfree(remote); 92496e43537SVincent Donnefort return -ENOMEM; 92596e43537SVincent Donnefort } 92696e43537SVincent Donnefort 92707252915SVincent Donnefort ret = trace_remote_register_events(name, remote, events, nr_events); 92807252915SVincent Donnefort if (ret) { 92907252915SVincent Donnefort pr_err("Failed to register events for trace remote '%s' (%d)\n", 93007252915SVincent Donnefort name, ret); 93107252915SVincent Donnefort return ret; 93207252915SVincent Donnefort } 93307252915SVincent Donnefort 934bf2ba0f8SVincent Donnefort ret = cbs->init ? cbs->init(remote->dentry, priv) : 0; 935bf2ba0f8SVincent Donnefort if (ret) 936bf2ba0f8SVincent Donnefort pr_err("Init failed for trace remote '%s' (%d)\n", name, ret); 937bf2ba0f8SVincent Donnefort 938bf2ba0f8SVincent Donnefort return ret; 93996e43537SVincent Donnefort } 94096e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_register); 94196e43537SVincent Donnefort 94296e43537SVincent Donnefort /** 94396e43537SVincent Donnefort * trace_remote_free_buffer() - Free trace buffer allocated with trace_remote_alloc_buffer() 94496e43537SVincent Donnefort * @desc: Descriptor of the per-CPU ring-buffers, originally filled by 94596e43537SVincent Donnefort * trace_remote_alloc_buffer() 94696e43537SVincent Donnefort * 94796e43537SVincent Donnefort * Most likely called from &trace_remote_callbacks.unload_trace_buffer. 94896e43537SVincent Donnefort */ 94996e43537SVincent Donnefort void trace_remote_free_buffer(struct trace_buffer_desc *desc) 95096e43537SVincent Donnefort { 95196e43537SVincent Donnefort struct ring_buffer_desc *rb_desc; 95296e43537SVincent Donnefort int cpu; 95396e43537SVincent Donnefort 95496e43537SVincent Donnefort for_each_ring_buffer_desc(rb_desc, cpu, desc) { 95596e43537SVincent Donnefort unsigned int id; 95696e43537SVincent Donnefort 95796e43537SVincent Donnefort free_page(rb_desc->meta_va); 95896e43537SVincent Donnefort 95996e43537SVincent Donnefort for (id = 0; id < rb_desc->nr_page_va; id++) 96096e43537SVincent Donnefort free_page(rb_desc->page_va[id]); 96196e43537SVincent Donnefort } 96296e43537SVincent Donnefort } 96396e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_free_buffer); 96496e43537SVincent Donnefort 96596e43537SVincent Donnefort /** 96696e43537SVincent Donnefort * trace_remote_alloc_buffer() - Dynamically allocate a trace buffer 96796e43537SVincent Donnefort * @desc: Uninitialized trace_buffer_desc 96896e43537SVincent Donnefort * @desc_size: Size of the trace_buffer_desc. Must be at least equal to 96996e43537SVincent Donnefort * trace_buffer_desc_size() 97096e43537SVincent Donnefort * @buffer_size: Size in bytes of each per-CPU ring-buffer 97196e43537SVincent Donnefort * @cpumask: CPUs to allocate a ring-buffer for 97296e43537SVincent Donnefort * 97396e43537SVincent Donnefort * Helper to dynamically allocate a set of pages (enough to cover @buffer_size) 97496e43537SVincent Donnefort * for each CPU from @cpumask and fill @desc. Most likely called from 97596e43537SVincent Donnefort * &trace_remote_callbacks.load_trace_buffer. 97696e43537SVincent Donnefort * 97796e43537SVincent Donnefort * Return: 0 on success, negative error code on failure. 97896e43537SVincent Donnefort */ 97996e43537SVincent Donnefort int trace_remote_alloc_buffer(struct trace_buffer_desc *desc, size_t desc_size, size_t buffer_size, 98096e43537SVincent Donnefort const struct cpumask *cpumask) 98196e43537SVincent Donnefort { 98296e43537SVincent Donnefort unsigned int nr_pages = max(DIV_ROUND_UP(buffer_size, PAGE_SIZE), 2UL) + 1; 98396e43537SVincent Donnefort void *desc_end = desc + desc_size; 98496e43537SVincent Donnefort struct ring_buffer_desc *rb_desc; 98596e43537SVincent Donnefort int cpu, ret = -ENOMEM; 98696e43537SVincent Donnefort 98796e43537SVincent Donnefort if (desc_size < struct_size(desc, __data, 0)) 98896e43537SVincent Donnefort return -EINVAL; 98996e43537SVincent Donnefort 99096e43537SVincent Donnefort desc->nr_cpus = 0; 99196e43537SVincent Donnefort desc->struct_len = struct_size(desc, __data, 0); 99296e43537SVincent Donnefort 99396e43537SVincent Donnefort rb_desc = (struct ring_buffer_desc *)&desc->__data[0]; 99496e43537SVincent Donnefort 99596e43537SVincent Donnefort for_each_cpu(cpu, cpumask) { 99696e43537SVincent Donnefort unsigned int id; 99796e43537SVincent Donnefort 99896e43537SVincent Donnefort if ((void *)rb_desc + struct_size(rb_desc, page_va, nr_pages) > desc_end) { 99996e43537SVincent Donnefort ret = -EINVAL; 100096e43537SVincent Donnefort goto err; 100196e43537SVincent Donnefort } 100296e43537SVincent Donnefort 100396e43537SVincent Donnefort rb_desc->cpu = cpu; 100496e43537SVincent Donnefort rb_desc->nr_page_va = 0; 100596e43537SVincent Donnefort rb_desc->meta_va = (unsigned long)__get_free_page(GFP_KERNEL); 100696e43537SVincent Donnefort if (!rb_desc->meta_va) 100796e43537SVincent Donnefort goto err; 100896e43537SVincent Donnefort 100996e43537SVincent Donnefort for (id = 0; id < nr_pages; id++) { 101096e43537SVincent Donnefort rb_desc->page_va[id] = (unsigned long)__get_free_page(GFP_KERNEL); 101196e43537SVincent Donnefort if (!rb_desc->page_va[id]) 101296e43537SVincent Donnefort goto err; 101396e43537SVincent Donnefort 101496e43537SVincent Donnefort rb_desc->nr_page_va++; 101596e43537SVincent Donnefort } 101696e43537SVincent Donnefort desc->nr_cpus++; 101796e43537SVincent Donnefort desc->struct_len += offsetof(struct ring_buffer_desc, page_va); 101896e43537SVincent Donnefort desc->struct_len += struct_size(rb_desc, page_va, rb_desc->nr_page_va); 101996e43537SVincent Donnefort rb_desc = __next_ring_buffer_desc(rb_desc); 102096e43537SVincent Donnefort } 102196e43537SVincent Donnefort 102296e43537SVincent Donnefort return 0; 102396e43537SVincent Donnefort 102496e43537SVincent Donnefort err: 102596e43537SVincent Donnefort trace_remote_free_buffer(desc); 102696e43537SVincent Donnefort return ret; 102796e43537SVincent Donnefort } 102896e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_alloc_buffer); 102907252915SVincent Donnefort 103007252915SVincent Donnefort static int 103107252915SVincent Donnefort trace_remote_enable_event(struct trace_remote *remote, struct remote_event *evt, bool enable) 103207252915SVincent Donnefort { 103307252915SVincent Donnefort int ret; 103407252915SVincent Donnefort 103507252915SVincent Donnefort lockdep_assert_held(&remote->lock); 103607252915SVincent Donnefort 103707252915SVincent Donnefort if (evt->enabled == enable) 103807252915SVincent Donnefort return 0; 103907252915SVincent Donnefort 104007252915SVincent Donnefort ret = remote->cbs->enable_event(evt->id, enable, remote->priv); 104107252915SVincent Donnefort if (ret) 104207252915SVincent Donnefort return ret; 104307252915SVincent Donnefort 104407252915SVincent Donnefort evt->enabled = enable; 104507252915SVincent Donnefort 104607252915SVincent Donnefort return 0; 104707252915SVincent Donnefort } 104807252915SVincent Donnefort 104907252915SVincent Donnefort static int remote_event_enable_show(struct seq_file *s, void *unused) 105007252915SVincent Donnefort { 105107252915SVincent Donnefort struct remote_event *evt = s->private; 105207252915SVincent Donnefort 105307252915SVincent Donnefort seq_printf(s, "%d\n", evt->enabled); 105407252915SVincent Donnefort 105507252915SVincent Donnefort return 0; 105607252915SVincent Donnefort } 105707252915SVincent Donnefort 105807252915SVincent Donnefort static ssize_t remote_event_enable_write(struct file *filp, const char __user *ubuf, 105907252915SVincent Donnefort size_t count, loff_t *ppos) 106007252915SVincent Donnefort { 106107252915SVincent Donnefort struct seq_file *seq = filp->private_data; 106207252915SVincent Donnefort struct remote_event *evt = seq->private; 106307252915SVincent Donnefort struct trace_remote *remote = evt->remote; 106407252915SVincent Donnefort u8 enable; 106507252915SVincent Donnefort int ret; 106607252915SVincent Donnefort 106707252915SVincent Donnefort ret = kstrtou8_from_user(ubuf, count, 10, &enable); 106807252915SVincent Donnefort if (ret) 106907252915SVincent Donnefort return ret; 107007252915SVincent Donnefort 107107252915SVincent Donnefort guard(mutex)(&remote->lock); 107207252915SVincent Donnefort 107307252915SVincent Donnefort ret = trace_remote_enable_event(remote, evt, enable); 107407252915SVincent Donnefort if (ret) 107507252915SVincent Donnefort return ret; 107607252915SVincent Donnefort 107707252915SVincent Donnefort return count; 107807252915SVincent Donnefort } 107907252915SVincent Donnefort DEFINE_SHOW_STORE_ATTRIBUTE(remote_event_enable); 108007252915SVincent Donnefort 108107252915SVincent Donnefort static int remote_event_id_show(struct seq_file *s, void *unused) 108207252915SVincent Donnefort { 108307252915SVincent Donnefort struct remote_event *evt = s->private; 108407252915SVincent Donnefort 108507252915SVincent Donnefort seq_printf(s, "%d\n", evt->id); 108607252915SVincent Donnefort 108707252915SVincent Donnefort return 0; 108807252915SVincent Donnefort } 108907252915SVincent Donnefort DEFINE_SHOW_ATTRIBUTE(remote_event_id); 109007252915SVincent Donnefort 109107252915SVincent Donnefort static int remote_event_format_show(struct seq_file *s, void *unused) 109207252915SVincent Donnefort { 109307252915SVincent Donnefort size_t offset = sizeof(struct remote_event_hdr); 109407252915SVincent Donnefort struct remote_event *evt = s->private; 109507252915SVincent Donnefort struct trace_event_fields *field; 109607252915SVincent Donnefort 109707252915SVincent Donnefort seq_printf(s, "name: %s\n", evt->name); 109807252915SVincent Donnefort seq_printf(s, "ID: %d\n", evt->id); 109907252915SVincent Donnefort seq_puts(s, 110007252915SVincent Donnefort "format:\n\tfield:unsigned short common_type;\toffset:0;\tsize:2;\tsigned:0;\n\n"); 110107252915SVincent Donnefort 110207252915SVincent Donnefort field = &evt->fields[0]; 110307252915SVincent Donnefort while (field->name) { 110407252915SVincent Donnefort seq_printf(s, "\tfield:%s %s;\toffset:%zu;\tsize:%u;\tsigned:%d;\n", 110507252915SVincent Donnefort field->type, field->name, offset, field->size, 110607252915SVincent Donnefort field->is_signed); 110707252915SVincent Donnefort offset += field->size; 110807252915SVincent Donnefort field++; 110907252915SVincent Donnefort } 111007252915SVincent Donnefort 111107252915SVincent Donnefort if (field != &evt->fields[0]) 111207252915SVincent Donnefort seq_puts(s, "\n"); 111307252915SVincent Donnefort 111407252915SVincent Donnefort seq_printf(s, "print fmt: %s\n", evt->print_fmt); 111507252915SVincent Donnefort 111607252915SVincent Donnefort return 0; 111707252915SVincent Donnefort } 111807252915SVincent Donnefort DEFINE_SHOW_ATTRIBUTE(remote_event_format); 111907252915SVincent Donnefort 112007252915SVincent Donnefort static int remote_event_callback(const char *name, umode_t *mode, void **data, 112107252915SVincent Donnefort const struct file_operations **fops) 112207252915SVincent Donnefort { 112307252915SVincent Donnefort if (!strcmp(name, "enable")) { 112407252915SVincent Donnefort *mode = TRACEFS_MODE_WRITE; 112507252915SVincent Donnefort *fops = &remote_event_enable_fops; 112607252915SVincent Donnefort return 1; 112707252915SVincent Donnefort } 112807252915SVincent Donnefort 112907252915SVincent Donnefort if (!strcmp(name, "id")) { 113007252915SVincent Donnefort *mode = TRACEFS_MODE_READ; 113107252915SVincent Donnefort *fops = &remote_event_id_fops; 113207252915SVincent Donnefort return 1; 113307252915SVincent Donnefort } 113407252915SVincent Donnefort 113507252915SVincent Donnefort if (!strcmp(name, "format")) { 113607252915SVincent Donnefort *mode = TRACEFS_MODE_READ; 113707252915SVincent Donnefort *fops = &remote_event_format_fops; 113807252915SVincent Donnefort return 1; 113907252915SVincent Donnefort } 114007252915SVincent Donnefort 114107252915SVincent Donnefort return 0; 114207252915SVincent Donnefort } 114307252915SVincent Donnefort 1144775cb093SVincent Donnefort static ssize_t remote_events_dir_enable_write(struct file *filp, const char __user *ubuf, 1145775cb093SVincent Donnefort size_t count, loff_t *ppos) 1146775cb093SVincent Donnefort { 1147775cb093SVincent Donnefort struct trace_remote *remote = file_inode(filp)->i_private; 1148775cb093SVincent Donnefort int i, ret; 1149775cb093SVincent Donnefort u8 enable; 1150775cb093SVincent Donnefort 1151775cb093SVincent Donnefort ret = kstrtou8_from_user(ubuf, count, 10, &enable); 1152775cb093SVincent Donnefort if (ret) 1153775cb093SVincent Donnefort return ret; 1154775cb093SVincent Donnefort 1155775cb093SVincent Donnefort guard(mutex)(&remote->lock); 1156775cb093SVincent Donnefort 1157775cb093SVincent Donnefort for (i = 0; i < remote->nr_events; i++) { 1158775cb093SVincent Donnefort struct remote_event *evt = &remote->events[i]; 1159775cb093SVincent Donnefort 1160775cb093SVincent Donnefort trace_remote_enable_event(remote, evt, enable); 1161775cb093SVincent Donnefort } 1162775cb093SVincent Donnefort 1163775cb093SVincent Donnefort return count; 1164775cb093SVincent Donnefort } 1165775cb093SVincent Donnefort 1166775cb093SVincent Donnefort static ssize_t remote_events_dir_enable_read(struct file *filp, char __user *ubuf, size_t cnt, 1167775cb093SVincent Donnefort loff_t *ppos) 1168775cb093SVincent Donnefort { 1169775cb093SVincent Donnefort struct trace_remote *remote = file_inode(filp)->i_private; 1170775cb093SVincent Donnefort const char enabled_char[] = {'0', '1', 'X'}; 1171775cb093SVincent Donnefort char enabled_str[] = " \n"; 1172775cb093SVincent Donnefort int i, enabled = -1; 1173775cb093SVincent Donnefort 1174775cb093SVincent Donnefort guard(mutex)(&remote->lock); 1175775cb093SVincent Donnefort 1176775cb093SVincent Donnefort for (i = 0; i < remote->nr_events; i++) { 1177775cb093SVincent Donnefort struct remote_event *evt = &remote->events[i]; 1178775cb093SVincent Donnefort 1179775cb093SVincent Donnefort if (enabled == -1) { 1180775cb093SVincent Donnefort enabled = evt->enabled; 1181775cb093SVincent Donnefort } else if (enabled != evt->enabled) { 1182775cb093SVincent Donnefort enabled = 2; 1183775cb093SVincent Donnefort break; 1184775cb093SVincent Donnefort } 1185775cb093SVincent Donnefort } 1186775cb093SVincent Donnefort 1187775cb093SVincent Donnefort enabled_str[0] = enabled_char[enabled == -1 ? 0 : enabled]; 1188775cb093SVincent Donnefort 1189775cb093SVincent Donnefort return simple_read_from_buffer(ubuf, cnt, ppos, enabled_str, 2); 1190775cb093SVincent Donnefort } 1191775cb093SVincent Donnefort 1192775cb093SVincent Donnefort static const struct file_operations remote_events_dir_enable_fops = { 1193775cb093SVincent Donnefort .write = remote_events_dir_enable_write, 1194775cb093SVincent Donnefort .read = remote_events_dir_enable_read, 1195775cb093SVincent Donnefort }; 1196775cb093SVincent Donnefort 1197775cb093SVincent Donnefort static ssize_t 1198775cb093SVincent Donnefort remote_events_dir_header_page_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) 1199775cb093SVincent Donnefort { 1200775cb093SVincent Donnefort struct trace_seq *s; 1201775cb093SVincent Donnefort int ret; 1202775cb093SVincent Donnefort 1203775cb093SVincent Donnefort s = kmalloc(sizeof(*s), GFP_KERNEL); 1204775cb093SVincent Donnefort if (!s) 1205775cb093SVincent Donnefort return -ENOMEM; 1206775cb093SVincent Donnefort 1207775cb093SVincent Donnefort trace_seq_init(s); 1208775cb093SVincent Donnefort 1209775cb093SVincent Donnefort ring_buffer_print_page_header(NULL, s); 1210775cb093SVincent Donnefort ret = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, trace_seq_used(s)); 1211775cb093SVincent Donnefort kfree(s); 1212775cb093SVincent Donnefort 1213775cb093SVincent Donnefort return ret; 1214775cb093SVincent Donnefort } 1215775cb093SVincent Donnefort 1216775cb093SVincent Donnefort static const struct file_operations remote_events_dir_header_page_fops = { 1217775cb093SVincent Donnefort .read = remote_events_dir_header_page_read, 1218775cb093SVincent Donnefort }; 1219775cb093SVincent Donnefort 1220775cb093SVincent Donnefort static ssize_t 1221775cb093SVincent Donnefort remote_events_dir_header_event_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) 1222775cb093SVincent Donnefort { 1223775cb093SVincent Donnefort struct trace_seq *s; 1224775cb093SVincent Donnefort int ret; 1225775cb093SVincent Donnefort 1226775cb093SVincent Donnefort s = kmalloc(sizeof(*s), GFP_KERNEL); 1227775cb093SVincent Donnefort if (!s) 1228775cb093SVincent Donnefort return -ENOMEM; 1229775cb093SVincent Donnefort 1230775cb093SVincent Donnefort trace_seq_init(s); 1231775cb093SVincent Donnefort 1232775cb093SVincent Donnefort ring_buffer_print_entry_header(s); 1233775cb093SVincent Donnefort ret = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, trace_seq_used(s)); 1234775cb093SVincent Donnefort kfree(s); 1235775cb093SVincent Donnefort 1236775cb093SVincent Donnefort return ret; 1237775cb093SVincent Donnefort } 1238775cb093SVincent Donnefort 1239775cb093SVincent Donnefort static const struct file_operations remote_events_dir_header_event_fops = { 1240775cb093SVincent Donnefort .read = remote_events_dir_header_event_read, 1241775cb093SVincent Donnefort }; 1242775cb093SVincent Donnefort 1243775cb093SVincent Donnefort static int remote_events_dir_callback(const char *name, umode_t *mode, void **data, 1244775cb093SVincent Donnefort const struct file_operations **fops) 1245775cb093SVincent Donnefort { 1246775cb093SVincent Donnefort if (!strcmp(name, "enable")) { 1247775cb093SVincent Donnefort *mode = TRACEFS_MODE_WRITE; 1248775cb093SVincent Donnefort *fops = &remote_events_dir_enable_fops; 1249775cb093SVincent Donnefort return 1; 1250775cb093SVincent Donnefort } 1251775cb093SVincent Donnefort 1252775cb093SVincent Donnefort if (!strcmp(name, "header_page")) { 1253775cb093SVincent Donnefort *mode = TRACEFS_MODE_READ; 1254775cb093SVincent Donnefort *fops = &remote_events_dir_header_page_fops; 1255775cb093SVincent Donnefort return 1; 1256775cb093SVincent Donnefort } 1257775cb093SVincent Donnefort 1258775cb093SVincent Donnefort if (!strcmp(name, "header_event")) { 1259775cb093SVincent Donnefort *mode = TRACEFS_MODE_READ; 1260775cb093SVincent Donnefort *fops = &remote_events_dir_header_event_fops; 1261775cb093SVincent Donnefort return 1; 1262775cb093SVincent Donnefort } 1263775cb093SVincent Donnefort 1264775cb093SVincent Donnefort return 0; 1265775cb093SVincent Donnefort } 1266775cb093SVincent Donnefort 126707252915SVincent Donnefort static int trace_remote_init_eventfs(const char *remote_name, struct trace_remote *remote, 126807252915SVincent Donnefort struct remote_event *evt) 126907252915SVincent Donnefort { 127007252915SVincent Donnefort struct eventfs_inode *eventfs = remote->eventfs; 1271775cb093SVincent Donnefort static struct eventfs_entry dir_entries[] = { 1272775cb093SVincent Donnefort { 1273775cb093SVincent Donnefort .name = "enable", 1274775cb093SVincent Donnefort .callback = remote_events_dir_callback, 1275775cb093SVincent Donnefort }, { 1276775cb093SVincent Donnefort .name = "header_page", 1277775cb093SVincent Donnefort .callback = remote_events_dir_callback, 1278775cb093SVincent Donnefort }, { 1279775cb093SVincent Donnefort .name = "header_event", 1280775cb093SVincent Donnefort .callback = remote_events_dir_callback, 1281775cb093SVincent Donnefort } 1282775cb093SVincent Donnefort }; 128307252915SVincent Donnefort static struct eventfs_entry entries[] = { 128407252915SVincent Donnefort { 128507252915SVincent Donnefort .name = "enable", 128607252915SVincent Donnefort .callback = remote_event_callback, 128707252915SVincent Donnefort }, { 128807252915SVincent Donnefort .name = "id", 128907252915SVincent Donnefort .callback = remote_event_callback, 129007252915SVincent Donnefort }, { 129107252915SVincent Donnefort .name = "format", 129207252915SVincent Donnefort .callback = remote_event_callback, 129307252915SVincent Donnefort } 129407252915SVincent Donnefort }; 129507252915SVincent Donnefort bool eventfs_create = false; 129607252915SVincent Donnefort 129707252915SVincent Donnefort if (!eventfs) { 1298775cb093SVincent Donnefort eventfs = eventfs_create_events_dir("events", remote->dentry, dir_entries, 1299775cb093SVincent Donnefort ARRAY_SIZE(dir_entries), remote); 130007252915SVincent Donnefort if (IS_ERR(eventfs)) 130107252915SVincent Donnefort return PTR_ERR(eventfs); 130207252915SVincent Donnefort 130307252915SVincent Donnefort /* 130407252915SVincent Donnefort * Create similar hierarchy as local events even if a single system is supported at 130507252915SVincent Donnefort * the moment 130607252915SVincent Donnefort */ 130707252915SVincent Donnefort eventfs = eventfs_create_dir(remote_name, eventfs, NULL, 0, NULL); 130807252915SVincent Donnefort if (IS_ERR(eventfs)) 130907252915SVincent Donnefort return PTR_ERR(eventfs); 131007252915SVincent Donnefort 131107252915SVincent Donnefort remote->eventfs = eventfs; 131207252915SVincent Donnefort eventfs_create = true; 131307252915SVincent Donnefort } 131407252915SVincent Donnefort 131507252915SVincent Donnefort eventfs = eventfs_create_dir(evt->name, eventfs, entries, ARRAY_SIZE(entries), evt); 131607252915SVincent Donnefort if (IS_ERR(eventfs)) { 131707252915SVincent Donnefort if (eventfs_create) { 131807252915SVincent Donnefort eventfs_remove_events_dir(remote->eventfs); 131907252915SVincent Donnefort remote->eventfs = NULL; 132007252915SVincent Donnefort } 132107252915SVincent Donnefort return PTR_ERR(eventfs); 132207252915SVincent Donnefort } 132307252915SVincent Donnefort 132407252915SVincent Donnefort return 0; 132507252915SVincent Donnefort } 132607252915SVincent Donnefort 132707252915SVincent Donnefort static int trace_remote_attach_events(struct trace_remote *remote, struct remote_event *events, 132807252915SVincent Donnefort size_t nr_events) 132907252915SVincent Donnefort { 133007252915SVincent Donnefort int i; 133107252915SVincent Donnefort 133207252915SVincent Donnefort for (i = 0; i < nr_events; i++) { 133307252915SVincent Donnefort struct remote_event *evt = &events[i]; 133407252915SVincent Donnefort 133507252915SVincent Donnefort if (evt->remote) 133607252915SVincent Donnefort return -EEXIST; 133707252915SVincent Donnefort 133807252915SVincent Donnefort evt->remote = remote; 133907252915SVincent Donnefort 134007252915SVincent Donnefort /* We need events to be sorted for efficient lookup */ 134107252915SVincent Donnefort if (i && evt->id <= events[i - 1].id) 134207252915SVincent Donnefort return -EINVAL; 134307252915SVincent Donnefort } 134407252915SVincent Donnefort 134507252915SVincent Donnefort remote->events = events; 134607252915SVincent Donnefort remote->nr_events = nr_events; 134707252915SVincent Donnefort 134807252915SVincent Donnefort return 0; 134907252915SVincent Donnefort } 135007252915SVincent Donnefort 135107252915SVincent Donnefort static int trace_remote_register_events(const char *remote_name, struct trace_remote *remote, 135207252915SVincent Donnefort struct remote_event *events, size_t nr_events) 135307252915SVincent Donnefort { 135407252915SVincent Donnefort int i, ret; 135507252915SVincent Donnefort 135607252915SVincent Donnefort ret = trace_remote_attach_events(remote, events, nr_events); 135707252915SVincent Donnefort if (ret) 135807252915SVincent Donnefort return ret; 135907252915SVincent Donnefort 136007252915SVincent Donnefort for (i = 0; i < nr_events; i++) { 136107252915SVincent Donnefort struct remote_event *evt = &events[i]; 136207252915SVincent Donnefort 136307252915SVincent Donnefort ret = trace_remote_init_eventfs(remote_name, remote, evt); 136407252915SVincent Donnefort if (ret) 136507252915SVincent Donnefort pr_warn("Failed to init eventfs for event '%s' (%d)", 136607252915SVincent Donnefort evt->name, ret); 136707252915SVincent Donnefort } 136807252915SVincent Donnefort 136907252915SVincent Donnefort return 0; 137007252915SVincent Donnefort } 137107252915SVincent Donnefort 137207252915SVincent Donnefort static int __cmp_events(const void *key, const void *data) 137307252915SVincent Donnefort { 137407252915SVincent Donnefort const struct remote_event *evt = data; 137507252915SVincent Donnefort int id = (int)((long)key); 137607252915SVincent Donnefort 137707252915SVincent Donnefort return id - (int)evt->id; 137807252915SVincent Donnefort } 137907252915SVincent Donnefort 138007252915SVincent Donnefort static struct remote_event *trace_remote_find_event(struct trace_remote *remote, unsigned short id) 138107252915SVincent Donnefort { 138207252915SVincent Donnefort return bsearch((const void *)(unsigned long)id, remote->events, remote->nr_events, 138307252915SVincent Donnefort sizeof(*remote->events), __cmp_events); 138407252915SVincent Donnefort } 1385