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 28596e43537SVincent Donnefort static void __poll_remote(struct work_struct *work) 28696e43537SVincent Donnefort { 28796e43537SVincent Donnefort struct delayed_work *dwork = to_delayed_work(work); 28896e43537SVincent Donnefort struct trace_remote_iterator *iter; 28996e43537SVincent Donnefort 29096e43537SVincent Donnefort iter = container_of(dwork, struct trace_remote_iterator, poll_work); 29196e43537SVincent Donnefort ring_buffer_poll_remote(iter->remote->trace_buffer, iter->cpu); 29296e43537SVincent Donnefort schedule_delayed_work((struct delayed_work *)work, 29396e43537SVincent Donnefort msecs_to_jiffies(iter->remote->poll_ms)); 29496e43537SVincent Donnefort } 29596e43537SVincent Donnefort 296330b0cceSVincent Donnefort static void __free_ring_buffer_iter(struct trace_remote_iterator *iter, int cpu) 297330b0cceSVincent Donnefort { 298330b0cceSVincent Donnefort if (cpu != RING_BUFFER_ALL_CPUS) { 299330b0cceSVincent Donnefort ring_buffer_read_finish(iter->rb_iter); 300330b0cceSVincent Donnefort return; 301330b0cceSVincent Donnefort } 302330b0cceSVincent Donnefort 303330b0cceSVincent Donnefort for_each_possible_cpu(cpu) { 304330b0cceSVincent Donnefort if (iter->rb_iters[cpu]) 305330b0cceSVincent Donnefort ring_buffer_read_finish(iter->rb_iters[cpu]); 306330b0cceSVincent Donnefort } 307330b0cceSVincent Donnefort 308330b0cceSVincent Donnefort kfree(iter->rb_iters); 309330b0cceSVincent Donnefort } 310330b0cceSVincent Donnefort 311330b0cceSVincent Donnefort static int __alloc_ring_buffer_iter(struct trace_remote_iterator *iter, int cpu) 312330b0cceSVincent Donnefort { 313330b0cceSVincent Donnefort if (cpu != RING_BUFFER_ALL_CPUS) { 314330b0cceSVincent Donnefort iter->rb_iter = ring_buffer_read_start(iter->remote->trace_buffer, cpu, GFP_KERNEL); 315330b0cceSVincent Donnefort 316330b0cceSVincent Donnefort return iter->rb_iter ? 0 : -ENOMEM; 317330b0cceSVincent Donnefort } 318330b0cceSVincent Donnefort 319330b0cceSVincent Donnefort iter->rb_iters = kcalloc(nr_cpu_ids, sizeof(*iter->rb_iters), GFP_KERNEL); 320330b0cceSVincent Donnefort if (!iter->rb_iters) 321330b0cceSVincent Donnefort return -ENOMEM; 322330b0cceSVincent Donnefort 323330b0cceSVincent Donnefort for_each_possible_cpu(cpu) { 324330b0cceSVincent Donnefort iter->rb_iters[cpu] = ring_buffer_read_start(iter->remote->trace_buffer, cpu, 325330b0cceSVincent Donnefort GFP_KERNEL); 326330b0cceSVincent Donnefort if (!iter->rb_iters[cpu]) { 327330b0cceSVincent Donnefort __free_ring_buffer_iter(iter, RING_BUFFER_ALL_CPUS); 328330b0cceSVincent Donnefort return -ENOMEM; 329330b0cceSVincent Donnefort } 330330b0cceSVincent Donnefort } 331330b0cceSVincent Donnefort 332330b0cceSVincent Donnefort return 0; 333330b0cceSVincent Donnefort } 334330b0cceSVincent Donnefort 335330b0cceSVincent Donnefort static struct trace_remote_iterator 336330b0cceSVincent Donnefort *trace_remote_iter(struct trace_remote *remote, int cpu, enum tri_type type) 33796e43537SVincent Donnefort { 33896e43537SVincent Donnefort struct trace_remote_iterator *iter = NULL; 33996e43537SVincent Donnefort int ret; 34096e43537SVincent Donnefort 34196e43537SVincent Donnefort lockdep_assert_held(&remote->lock); 34296e43537SVincent Donnefort 343330b0cceSVincent Donnefort if (type == TRI_NONCONSUMING && !trace_remote_loaded(remote)) 344330b0cceSVincent Donnefort return NULL; 34596e43537SVincent Donnefort 34696e43537SVincent Donnefort ret = trace_remote_get(remote, cpu); 34796e43537SVincent Donnefort if (ret) 34896e43537SVincent Donnefort return ERR_PTR(ret); 34996e43537SVincent Donnefort 35096e43537SVincent Donnefort /* Test the CPU */ 35196e43537SVincent Donnefort ret = ring_buffer_poll_remote(remote->trace_buffer, cpu); 35296e43537SVincent Donnefort if (ret) 35396e43537SVincent Donnefort goto err; 35496e43537SVincent Donnefort 35596e43537SVincent Donnefort iter = kzalloc_obj(*iter); 35696e43537SVincent Donnefort if (iter) { 35796e43537SVincent Donnefort iter->remote = remote; 35896e43537SVincent Donnefort iter->cpu = cpu; 359330b0cceSVincent Donnefort iter->type = type; 36096e43537SVincent Donnefort trace_seq_init(&iter->seq); 361330b0cceSVincent Donnefort 362330b0cceSVincent Donnefort switch (type) { 363330b0cceSVincent Donnefort case TRI_CONSUMING: 36496e43537SVincent Donnefort INIT_DELAYED_WORK(&iter->poll_work, __poll_remote); 36596e43537SVincent Donnefort schedule_delayed_work(&iter->poll_work, msecs_to_jiffies(remote->poll_ms)); 366330b0cceSVincent Donnefort break; 367330b0cceSVincent Donnefort case TRI_NONCONSUMING: 368330b0cceSVincent Donnefort ret = __alloc_ring_buffer_iter(iter, cpu); 369330b0cceSVincent Donnefort break; 370330b0cceSVincent Donnefort } 371330b0cceSVincent Donnefort 372330b0cceSVincent Donnefort if (ret) 373330b0cceSVincent Donnefort goto err; 37496e43537SVincent Donnefort 37596e43537SVincent Donnefort return iter; 37696e43537SVincent Donnefort } 37796e43537SVincent Donnefort ret = -ENOMEM; 37896e43537SVincent Donnefort 37996e43537SVincent Donnefort err: 38096e43537SVincent Donnefort kfree(iter); 38196e43537SVincent Donnefort trace_remote_put(remote); 38296e43537SVincent Donnefort 38396e43537SVincent Donnefort return ERR_PTR(ret); 38496e43537SVincent Donnefort } 38596e43537SVincent Donnefort 38696e43537SVincent Donnefort static void trace_remote_iter_free(struct trace_remote_iterator *iter) 38796e43537SVincent Donnefort { 38896e43537SVincent Donnefort struct trace_remote *remote; 38996e43537SVincent Donnefort 39096e43537SVincent Donnefort if (!iter) 39196e43537SVincent Donnefort return; 39296e43537SVincent Donnefort 39396e43537SVincent Donnefort remote = iter->remote; 39496e43537SVincent Donnefort 39596e43537SVincent Donnefort lockdep_assert_held(&remote->lock); 39696e43537SVincent Donnefort 397330b0cceSVincent Donnefort switch (iter->type) { 398330b0cceSVincent Donnefort case TRI_CONSUMING: 399330b0cceSVincent Donnefort cancel_delayed_work_sync(&iter->poll_work); 400330b0cceSVincent Donnefort break; 401330b0cceSVincent Donnefort case TRI_NONCONSUMING: 402330b0cceSVincent Donnefort __free_ring_buffer_iter(iter, iter->cpu); 403330b0cceSVincent Donnefort break; 404330b0cceSVincent Donnefort } 405330b0cceSVincent Donnefort 40696e43537SVincent Donnefort kfree(iter); 40796e43537SVincent Donnefort trace_remote_put(remote); 40896e43537SVincent Donnefort } 40996e43537SVincent Donnefort 410330b0cceSVincent Donnefort static void trace_remote_iter_read_start(struct trace_remote_iterator *iter) 411330b0cceSVincent Donnefort { 412330b0cceSVincent Donnefort struct trace_remote *remote = iter->remote; 413330b0cceSVincent Donnefort int cpu = iter->cpu; 414330b0cceSVincent Donnefort 415330b0cceSVincent Donnefort /* Acquire global reader lock */ 416330b0cceSVincent Donnefort if (cpu == RING_BUFFER_ALL_CPUS && iter->type == TRI_CONSUMING) 417330b0cceSVincent Donnefort down_write(&remote->reader_lock); 418330b0cceSVincent Donnefort else 419330b0cceSVincent Donnefort down_read(&remote->reader_lock); 420330b0cceSVincent Donnefort 421330b0cceSVincent Donnefort if (cpu == RING_BUFFER_ALL_CPUS) 422330b0cceSVincent Donnefort return; 423330b0cceSVincent Donnefort 424330b0cceSVincent Donnefort /* 425330b0cceSVincent Donnefort * No need for the remote lock here, iter holds a reference on 426330b0cceSVincent Donnefort * remote->nr_readers 427330b0cceSVincent Donnefort */ 428330b0cceSVincent Donnefort 429330b0cceSVincent Donnefort /* Get the per-CPU one */ 430330b0cceSVincent Donnefort if (WARN_ON_ONCE(!remote->pcpu_reader_locks)) 431330b0cceSVincent Donnefort return; 432330b0cceSVincent Donnefort 433330b0cceSVincent Donnefort if (iter->type == TRI_CONSUMING) 434330b0cceSVincent Donnefort down_write(&remote->pcpu_reader_locks[cpu]); 435330b0cceSVincent Donnefort else 436330b0cceSVincent Donnefort down_read(&remote->pcpu_reader_locks[cpu]); 437330b0cceSVincent Donnefort } 438330b0cceSVincent Donnefort 439330b0cceSVincent Donnefort static void trace_remote_iter_read_finished(struct trace_remote_iterator *iter) 440330b0cceSVincent Donnefort { 441330b0cceSVincent Donnefort struct trace_remote *remote = iter->remote; 442330b0cceSVincent Donnefort int cpu = iter->cpu; 443330b0cceSVincent Donnefort 444330b0cceSVincent Donnefort /* Release per-CPU reader lock */ 445330b0cceSVincent Donnefort if (cpu != RING_BUFFER_ALL_CPUS) { 446330b0cceSVincent Donnefort /* 447330b0cceSVincent Donnefort * No need for the remote lock here, iter holds a reference on 448330b0cceSVincent Donnefort * remote->nr_readers 449330b0cceSVincent Donnefort */ 450330b0cceSVincent Donnefort if (iter->type == TRI_CONSUMING) 451330b0cceSVincent Donnefort up_write(&remote->pcpu_reader_locks[cpu]); 452330b0cceSVincent Donnefort else 453330b0cceSVincent Donnefort up_read(&remote->pcpu_reader_locks[cpu]); 454330b0cceSVincent Donnefort } 455330b0cceSVincent Donnefort 456330b0cceSVincent Donnefort /* Release global reader lock */ 457330b0cceSVincent Donnefort if (cpu == RING_BUFFER_ALL_CPUS && iter->type == TRI_CONSUMING) 458330b0cceSVincent Donnefort up_write(&remote->reader_lock); 459330b0cceSVincent Donnefort else 460330b0cceSVincent Donnefort up_read(&remote->reader_lock); 461330b0cceSVincent Donnefort } 462330b0cceSVincent Donnefort 463330b0cceSVincent Donnefort static struct ring_buffer_iter *__get_rb_iter(struct trace_remote_iterator *iter, int cpu) 464330b0cceSVincent Donnefort { 465330b0cceSVincent Donnefort return iter->cpu != RING_BUFFER_ALL_CPUS ? iter->rb_iter : iter->rb_iters[cpu]; 466330b0cceSVincent Donnefort } 467330b0cceSVincent Donnefort 468330b0cceSVincent Donnefort static struct ring_buffer_event * 469330b0cceSVincent Donnefort __peek_event(struct trace_remote_iterator *iter, int cpu, u64 *ts, unsigned long *lost_events) 470330b0cceSVincent Donnefort { 471330b0cceSVincent Donnefort struct ring_buffer_event *rb_evt; 472330b0cceSVincent Donnefort struct ring_buffer_iter *rb_iter; 473330b0cceSVincent Donnefort 474330b0cceSVincent Donnefort switch (iter->type) { 475330b0cceSVincent Donnefort case TRI_CONSUMING: 476330b0cceSVincent Donnefort return ring_buffer_peek(iter->remote->trace_buffer, cpu, ts, lost_events); 477330b0cceSVincent Donnefort case TRI_NONCONSUMING: 478330b0cceSVincent Donnefort rb_iter = __get_rb_iter(iter, cpu); 479330b0cceSVincent Donnefort rb_evt = ring_buffer_iter_peek(rb_iter, ts); 480330b0cceSVincent Donnefort if (!rb_evt) 481330b0cceSVincent Donnefort return NULL; 482330b0cceSVincent Donnefort 483330b0cceSVincent Donnefort *lost_events = ring_buffer_iter_dropped(rb_iter); 484330b0cceSVincent Donnefort 485330b0cceSVincent Donnefort return rb_evt; 486330b0cceSVincent Donnefort } 487330b0cceSVincent Donnefort 488330b0cceSVincent Donnefort return NULL; 489330b0cceSVincent Donnefort } 490330b0cceSVincent Donnefort 49196e43537SVincent Donnefort static bool trace_remote_iter_read_event(struct trace_remote_iterator *iter) 49296e43537SVincent Donnefort { 49396e43537SVincent Donnefort struct trace_buffer *trace_buffer = iter->remote->trace_buffer; 49407252915SVincent Donnefort struct ring_buffer_event *rb_evt; 49596e43537SVincent Donnefort int cpu = iter->cpu; 49696e43537SVincent Donnefort 49796e43537SVincent Donnefort if (cpu != RING_BUFFER_ALL_CPUS) { 49896e43537SVincent Donnefort if (ring_buffer_empty_cpu(trace_buffer, cpu)) 49996e43537SVincent Donnefort return false; 50096e43537SVincent Donnefort 50107252915SVincent Donnefort rb_evt = __peek_event(iter, cpu, &iter->ts, &iter->lost_events); 50207252915SVincent Donnefort if (!rb_evt) 50396e43537SVincent Donnefort return false; 50496e43537SVincent Donnefort 50596e43537SVincent Donnefort iter->evt_cpu = cpu; 50607252915SVincent Donnefort iter->evt = ring_buffer_event_data(rb_evt); 50796e43537SVincent Donnefort return true; 50896e43537SVincent Donnefort } 50996e43537SVincent Donnefort 51096e43537SVincent Donnefort iter->ts = U64_MAX; 51196e43537SVincent Donnefort for_each_possible_cpu(cpu) { 51296e43537SVincent Donnefort unsigned long lost_events; 51396e43537SVincent Donnefort u64 ts; 51496e43537SVincent Donnefort 51596e43537SVincent Donnefort if (ring_buffer_empty_cpu(trace_buffer, cpu)) 51696e43537SVincent Donnefort continue; 51796e43537SVincent Donnefort 51807252915SVincent Donnefort rb_evt = __peek_event(iter, cpu, &ts, &lost_events); 51907252915SVincent Donnefort if (!rb_evt) 52096e43537SVincent Donnefort continue; 52196e43537SVincent Donnefort 52296e43537SVincent Donnefort if (ts >= iter->ts) 52396e43537SVincent Donnefort continue; 52496e43537SVincent Donnefort 52596e43537SVincent Donnefort iter->ts = ts; 52696e43537SVincent Donnefort iter->evt_cpu = cpu; 52707252915SVincent Donnefort iter->evt = ring_buffer_event_data(rb_evt); 52896e43537SVincent Donnefort iter->lost_events = lost_events; 52996e43537SVincent Donnefort } 53096e43537SVincent Donnefort 53196e43537SVincent Donnefort return iter->ts != U64_MAX; 53296e43537SVincent Donnefort } 53396e43537SVincent Donnefort 534330b0cceSVincent Donnefort static void trace_remote_iter_move(struct trace_remote_iterator *iter) 535330b0cceSVincent Donnefort { 536330b0cceSVincent Donnefort struct trace_buffer *trace_buffer = iter->remote->trace_buffer; 537330b0cceSVincent Donnefort 538330b0cceSVincent Donnefort switch (iter->type) { 539330b0cceSVincent Donnefort case TRI_CONSUMING: 540330b0cceSVincent Donnefort ring_buffer_consume(trace_buffer, iter->evt_cpu, NULL, NULL); 541330b0cceSVincent Donnefort break; 542330b0cceSVincent Donnefort case TRI_NONCONSUMING: 543330b0cceSVincent Donnefort ring_buffer_iter_advance(__get_rb_iter(iter, iter->evt_cpu)); 544330b0cceSVincent Donnefort break; 545330b0cceSVincent Donnefort } 546330b0cceSVincent Donnefort } 547330b0cceSVincent Donnefort 54807252915SVincent Donnefort static struct remote_event *trace_remote_find_event(struct trace_remote *remote, unsigned short id); 54907252915SVincent Donnefort 55096e43537SVincent Donnefort static int trace_remote_iter_print_event(struct trace_remote_iterator *iter) 55196e43537SVincent Donnefort { 55207252915SVincent Donnefort struct remote_event *evt; 55396e43537SVincent Donnefort unsigned long usecs_rem; 55496e43537SVincent Donnefort u64 ts = iter->ts; 55596e43537SVincent Donnefort 55696e43537SVincent Donnefort if (iter->lost_events) 55796e43537SVincent Donnefort trace_seq_printf(&iter->seq, "CPU:%d [LOST %lu EVENTS]\n", 55896e43537SVincent Donnefort iter->evt_cpu, iter->lost_events); 55996e43537SVincent Donnefort 56096e43537SVincent Donnefort do_div(ts, 1000); 56196e43537SVincent Donnefort usecs_rem = do_div(ts, USEC_PER_SEC); 56296e43537SVincent Donnefort 56396e43537SVincent Donnefort trace_seq_printf(&iter->seq, "[%03d]\t%5llu.%06lu: ", iter->evt_cpu, 56496e43537SVincent Donnefort ts, usecs_rem); 56596e43537SVincent Donnefort 56607252915SVincent Donnefort evt = trace_remote_find_event(iter->remote, iter->evt->id); 56707252915SVincent Donnefort if (!evt) 56807252915SVincent Donnefort trace_seq_printf(&iter->seq, "UNKNOWN id=%d\n", iter->evt->id); 56907252915SVincent Donnefort else 57007252915SVincent Donnefort evt->print(iter->evt, &iter->seq); 57107252915SVincent Donnefort 57296e43537SVincent Donnefort return trace_seq_has_overflowed(&iter->seq) ? -EOVERFLOW : 0; 57396e43537SVincent Donnefort } 57496e43537SVincent Donnefort 57596e43537SVincent Donnefort static int trace_pipe_open(struct inode *inode, struct file *filp) 57696e43537SVincent Donnefort { 57796e43537SVincent Donnefort struct trace_remote *remote = inode->i_private; 57896e43537SVincent Donnefort struct trace_remote_iterator *iter; 579330b0cceSVincent Donnefort int cpu = tracing_get_cpu(inode); 58096e43537SVincent Donnefort 58196e43537SVincent Donnefort guard(mutex)(&remote->lock); 582330b0cceSVincent Donnefort 583330b0cceSVincent Donnefort iter = trace_remote_iter(remote, cpu, TRI_CONSUMING); 584330b0cceSVincent Donnefort if (IS_ERR(iter)) 585330b0cceSVincent Donnefort return PTR_ERR(iter); 586330b0cceSVincent Donnefort 58796e43537SVincent Donnefort filp->private_data = iter; 58896e43537SVincent Donnefort 58996e43537SVincent Donnefort return IS_ERR(iter) ? PTR_ERR(iter) : 0; 59096e43537SVincent Donnefort } 59196e43537SVincent Donnefort 59296e43537SVincent Donnefort static int trace_pipe_release(struct inode *inode, struct file *filp) 59396e43537SVincent Donnefort { 59496e43537SVincent Donnefort struct trace_remote_iterator *iter = filp->private_data; 59596e43537SVincent Donnefort struct trace_remote *remote = iter->remote; 59696e43537SVincent Donnefort 59796e43537SVincent Donnefort guard(mutex)(&remote->lock); 59896e43537SVincent Donnefort 59996e43537SVincent Donnefort trace_remote_iter_free(iter); 60096e43537SVincent Donnefort 60196e43537SVincent Donnefort return 0; 60296e43537SVincent Donnefort } 60396e43537SVincent Donnefort 60496e43537SVincent Donnefort static ssize_t trace_pipe_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) 60596e43537SVincent Donnefort { 60696e43537SVincent Donnefort struct trace_remote_iterator *iter = filp->private_data; 60796e43537SVincent Donnefort struct trace_buffer *trace_buffer = iter->remote->trace_buffer; 60896e43537SVincent Donnefort int ret; 60996e43537SVincent Donnefort 61096e43537SVincent Donnefort copy_to_user: 61196e43537SVincent Donnefort ret = trace_seq_to_user(&iter->seq, ubuf, cnt); 61296e43537SVincent Donnefort if (ret != -EBUSY) 61396e43537SVincent Donnefort return ret; 61496e43537SVincent Donnefort 61596e43537SVincent Donnefort trace_seq_init(&iter->seq); 61696e43537SVincent Donnefort 61796e43537SVincent Donnefort ret = ring_buffer_wait(trace_buffer, iter->cpu, 0, NULL, NULL); 61896e43537SVincent Donnefort if (ret < 0) 61996e43537SVincent Donnefort return ret; 62096e43537SVincent Donnefort 621330b0cceSVincent Donnefort trace_remote_iter_read_start(iter); 622330b0cceSVincent Donnefort 62396e43537SVincent Donnefort while (trace_remote_iter_read_event(iter)) { 62496e43537SVincent Donnefort int prev_len = iter->seq.seq.len; 62596e43537SVincent Donnefort 62696e43537SVincent Donnefort if (trace_remote_iter_print_event(iter)) { 62796e43537SVincent Donnefort iter->seq.seq.len = prev_len; 62896e43537SVincent Donnefort break; 62996e43537SVincent Donnefort } 63096e43537SVincent Donnefort 631330b0cceSVincent Donnefort trace_remote_iter_move(iter); 63296e43537SVincent Donnefort } 63396e43537SVincent Donnefort 634330b0cceSVincent Donnefort trace_remote_iter_read_finished(iter); 635330b0cceSVincent Donnefort 63696e43537SVincent Donnefort goto copy_to_user; 63796e43537SVincent Donnefort } 63896e43537SVincent Donnefort 63996e43537SVincent Donnefort static const struct file_operations trace_pipe_fops = { 64096e43537SVincent Donnefort .open = trace_pipe_open, 64196e43537SVincent Donnefort .read = trace_pipe_read, 64296e43537SVincent Donnefort .release = trace_pipe_release, 64396e43537SVincent Donnefort }; 64496e43537SVincent Donnefort 645330b0cceSVincent Donnefort static void *trace_next(struct seq_file *m, void *v, loff_t *pos) 646330b0cceSVincent Donnefort { 647330b0cceSVincent Donnefort struct trace_remote_iterator *iter = m->private; 648330b0cceSVincent Donnefort 649330b0cceSVincent Donnefort ++*pos; 650330b0cceSVincent Donnefort 651330b0cceSVincent Donnefort if (!iter || !trace_remote_iter_read_event(iter)) 652330b0cceSVincent Donnefort return NULL; 653330b0cceSVincent Donnefort 654330b0cceSVincent Donnefort trace_remote_iter_move(iter); 655330b0cceSVincent Donnefort iter->pos++; 656330b0cceSVincent Donnefort 657330b0cceSVincent Donnefort return iter; 658330b0cceSVincent Donnefort } 659330b0cceSVincent Donnefort 660330b0cceSVincent Donnefort static void *trace_start(struct seq_file *m, loff_t *pos) 661330b0cceSVincent Donnefort { 662330b0cceSVincent Donnefort struct trace_remote_iterator *iter = m->private; 663330b0cceSVincent Donnefort loff_t i; 664330b0cceSVincent Donnefort 665330b0cceSVincent Donnefort if (!iter) 666330b0cceSVincent Donnefort return NULL; 667330b0cceSVincent Donnefort 668330b0cceSVincent Donnefort trace_remote_iter_read_start(iter); 669330b0cceSVincent Donnefort 670330b0cceSVincent Donnefort if (!*pos) { 671330b0cceSVincent Donnefort iter->pos = -1; 672330b0cceSVincent Donnefort return trace_next(m, NULL, &i); 673330b0cceSVincent Donnefort } 674330b0cceSVincent Donnefort 675330b0cceSVincent Donnefort i = iter->pos; 676330b0cceSVincent Donnefort while (i < *pos) { 677330b0cceSVincent Donnefort iter = trace_next(m, NULL, &i); 678330b0cceSVincent Donnefort if (!iter) 679330b0cceSVincent Donnefort return NULL; 680330b0cceSVincent Donnefort } 681330b0cceSVincent Donnefort 682330b0cceSVincent Donnefort return iter; 683330b0cceSVincent Donnefort } 684330b0cceSVincent Donnefort 685330b0cceSVincent Donnefort static int trace_show(struct seq_file *m, void *v) 686330b0cceSVincent Donnefort { 687330b0cceSVincent Donnefort struct trace_remote_iterator *iter = v; 688330b0cceSVincent Donnefort 689330b0cceSVincent Donnefort trace_seq_init(&iter->seq); 690330b0cceSVincent Donnefort 691330b0cceSVincent Donnefort if (trace_remote_iter_print_event(iter)) { 692330b0cceSVincent Donnefort seq_printf(m, "[EVENT %d PRINT TOO BIG]\n", iter->evt->id); 693330b0cceSVincent Donnefort return 0; 694330b0cceSVincent Donnefort } 695330b0cceSVincent Donnefort 696330b0cceSVincent Donnefort return trace_print_seq(m, &iter->seq); 697330b0cceSVincent Donnefort } 698330b0cceSVincent Donnefort 699330b0cceSVincent Donnefort static void trace_stop(struct seq_file *m, void *v) 700330b0cceSVincent Donnefort { 701330b0cceSVincent Donnefort struct trace_remote_iterator *iter = m->private; 702330b0cceSVincent Donnefort 703330b0cceSVincent Donnefort if (iter) 704330b0cceSVincent Donnefort trace_remote_iter_read_finished(iter); 705330b0cceSVincent Donnefort } 706330b0cceSVincent Donnefort 707330b0cceSVincent Donnefort static const struct seq_operations trace_sops = { 708330b0cceSVincent Donnefort .start = trace_start, 709330b0cceSVincent Donnefort .next = trace_next, 710330b0cceSVincent Donnefort .show = trace_show, 711330b0cceSVincent Donnefort .stop = trace_stop, 712330b0cceSVincent Donnefort }; 713330b0cceSVincent Donnefort 714330b0cceSVincent Donnefort static int trace_open(struct inode *inode, struct file *filp) 715330b0cceSVincent Donnefort { 716330b0cceSVincent Donnefort struct trace_remote *remote = inode->i_private; 717330b0cceSVincent Donnefort struct trace_remote_iterator *iter = NULL; 718330b0cceSVincent Donnefort int cpu = tracing_get_cpu(inode); 719330b0cceSVincent Donnefort int ret; 720330b0cceSVincent Donnefort 721330b0cceSVincent Donnefort if (!(filp->f_mode & FMODE_READ)) 722330b0cceSVincent Donnefort return 0; 723330b0cceSVincent Donnefort 724330b0cceSVincent Donnefort guard(mutex)(&remote->lock); 725330b0cceSVincent Donnefort 726330b0cceSVincent Donnefort iter = trace_remote_iter(remote, cpu, TRI_NONCONSUMING); 727330b0cceSVincent Donnefort if (IS_ERR(iter)) 728330b0cceSVincent Donnefort return PTR_ERR(iter); 729330b0cceSVincent Donnefort 730330b0cceSVincent Donnefort ret = seq_open(filp, &trace_sops); 731330b0cceSVincent Donnefort if (ret) { 732330b0cceSVincent Donnefort trace_remote_iter_free(iter); 733330b0cceSVincent Donnefort return ret; 734330b0cceSVincent Donnefort } 735330b0cceSVincent Donnefort 736330b0cceSVincent Donnefort ((struct seq_file *)filp->private_data)->private = (void *)iter; 737330b0cceSVincent Donnefort 738330b0cceSVincent Donnefort return 0; 739330b0cceSVincent Donnefort } 740330b0cceSVincent Donnefort 741330b0cceSVincent Donnefort static int trace_release(struct inode *inode, struct file *filp) 742330b0cceSVincent Donnefort { 743330b0cceSVincent Donnefort struct trace_remote_iterator *iter; 744330b0cceSVincent Donnefort 745330b0cceSVincent Donnefort if (!(filp->f_mode & FMODE_READ)) 746330b0cceSVincent Donnefort return 0; 747330b0cceSVincent Donnefort 748330b0cceSVincent Donnefort iter = ((struct seq_file *)filp->private_data)->private; 749330b0cceSVincent Donnefort seq_release(inode, filp); 750330b0cceSVincent Donnefort 751330b0cceSVincent Donnefort if (!iter) 752330b0cceSVincent Donnefort return 0; 753330b0cceSVincent Donnefort 754330b0cceSVincent Donnefort guard(mutex)(&iter->remote->lock); 755330b0cceSVincent Donnefort 756330b0cceSVincent Donnefort trace_remote_iter_free(iter); 757330b0cceSVincent Donnefort 758330b0cceSVincent Donnefort return 0; 759330b0cceSVincent Donnefort } 760330b0cceSVincent Donnefort 7619af4ab0eSVincent Donnefort static ssize_t trace_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) 7629af4ab0eSVincent Donnefort { 7639af4ab0eSVincent Donnefort struct inode *inode = file_inode(filp); 7649af4ab0eSVincent Donnefort struct trace_remote *remote = inode->i_private; 765330b0cceSVincent Donnefort int cpu = tracing_get_cpu(inode); 7669af4ab0eSVincent Donnefort 7679af4ab0eSVincent Donnefort guard(mutex)(&remote->lock); 7689af4ab0eSVincent Donnefort 7699af4ab0eSVincent Donnefort trace_remote_reset(remote, cpu); 7709af4ab0eSVincent Donnefort 7719af4ab0eSVincent Donnefort return cnt; 7729af4ab0eSVincent Donnefort } 7739af4ab0eSVincent Donnefort 7749af4ab0eSVincent Donnefort static const struct file_operations trace_fops = { 775330b0cceSVincent Donnefort .open = trace_open, 7769af4ab0eSVincent Donnefort .write = trace_write, 777330b0cceSVincent Donnefort .read = seq_read, 778330b0cceSVincent Donnefort .read_iter = seq_read_iter, 779330b0cceSVincent Donnefort .release = trace_release, 7809af4ab0eSVincent Donnefort }; 7819af4ab0eSVincent Donnefort 78296e43537SVincent Donnefort static int trace_remote_init_tracefs(const char *name, struct trace_remote *remote) 78396e43537SVincent Donnefort { 78496e43537SVincent Donnefort struct dentry *remote_d, *percpu_d, *d; 78596e43537SVincent Donnefort static struct dentry *root; 78696e43537SVincent Donnefort static DEFINE_MUTEX(lock); 78796e43537SVincent Donnefort bool root_inited = false; 78896e43537SVincent Donnefort int cpu; 78996e43537SVincent Donnefort 79096e43537SVincent Donnefort guard(mutex)(&lock); 79196e43537SVincent Donnefort 79296e43537SVincent Donnefort if (!root) { 79396e43537SVincent Donnefort root = tracefs_create_dir(TRACEFS_DIR, NULL); 79496e43537SVincent Donnefort if (!root) { 79596e43537SVincent Donnefort pr_err("Failed to create tracefs dir "TRACEFS_DIR"\n"); 79696e43537SVincent Donnefort return -ENOMEM; 79796e43537SVincent Donnefort } 79896e43537SVincent Donnefort root_inited = true; 79996e43537SVincent Donnefort } 80096e43537SVincent Donnefort 80196e43537SVincent Donnefort remote_d = tracefs_create_dir(name, root); 80296e43537SVincent Donnefort if (!remote_d) { 80396e43537SVincent Donnefort pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/\n", name); 80496e43537SVincent Donnefort goto err; 80596e43537SVincent Donnefort } 80696e43537SVincent Donnefort 80796e43537SVincent Donnefort d = trace_create_file("tracing_on", TRACEFS_MODE_WRITE, remote_d, remote, &tracing_on_fops); 80896e43537SVincent Donnefort if (!d) 80996e43537SVincent Donnefort goto err; 81096e43537SVincent Donnefort 81196e43537SVincent Donnefort d = trace_create_file("buffer_size_kb", TRACEFS_MODE_WRITE, remote_d, remote, 81296e43537SVincent Donnefort &buffer_size_kb_fops); 81396e43537SVincent Donnefort if (!d) 81496e43537SVincent Donnefort goto err; 81596e43537SVincent Donnefort 81696e43537SVincent Donnefort d = trace_create_file("trace_pipe", TRACEFS_MODE_READ, remote_d, remote, &trace_pipe_fops); 81796e43537SVincent Donnefort if (!d) 81896e43537SVincent Donnefort goto err; 81996e43537SVincent Donnefort 8209af4ab0eSVincent Donnefort d = trace_create_file("trace", TRACEFS_MODE_WRITE, remote_d, remote, &trace_fops); 8219af4ab0eSVincent Donnefort if (!d) 8229af4ab0eSVincent Donnefort goto err; 8239af4ab0eSVincent Donnefort 82496e43537SVincent Donnefort percpu_d = tracefs_create_dir("per_cpu", remote_d); 82596e43537SVincent Donnefort if (!percpu_d) { 82696e43537SVincent Donnefort pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/per_cpu/\n", name); 82796e43537SVincent Donnefort goto err; 82896e43537SVincent Donnefort } 82996e43537SVincent Donnefort 83096e43537SVincent Donnefort for_each_possible_cpu(cpu) { 83196e43537SVincent Donnefort struct dentry *cpu_d; 83296e43537SVincent Donnefort char cpu_name[16]; 83396e43537SVincent Donnefort 83496e43537SVincent Donnefort snprintf(cpu_name, sizeof(cpu_name), "cpu%d", cpu); 83596e43537SVincent Donnefort cpu_d = tracefs_create_dir(cpu_name, percpu_d); 83696e43537SVincent Donnefort if (!cpu_d) { 83796e43537SVincent Donnefort pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/percpu/cpu%d\n", 83896e43537SVincent Donnefort name, cpu); 83996e43537SVincent Donnefort goto err; 84096e43537SVincent Donnefort } 84196e43537SVincent Donnefort 84296e43537SVincent Donnefort d = trace_create_cpu_file("trace_pipe", TRACEFS_MODE_READ, cpu_d, remote, cpu, 84396e43537SVincent Donnefort &trace_pipe_fops); 84496e43537SVincent Donnefort if (!d) 84596e43537SVincent Donnefort goto err; 8469af4ab0eSVincent Donnefort 8479af4ab0eSVincent Donnefort d = trace_create_cpu_file("trace", TRACEFS_MODE_WRITE, cpu_d, remote, cpu, 8489af4ab0eSVincent Donnefort &trace_fops); 8499af4ab0eSVincent Donnefort if (!d) 8509af4ab0eSVincent Donnefort goto err; 85196e43537SVincent Donnefort } 85296e43537SVincent Donnefort 85307252915SVincent Donnefort remote->dentry = remote_d; 85407252915SVincent Donnefort 85596e43537SVincent Donnefort return 0; 85696e43537SVincent Donnefort 85796e43537SVincent Donnefort err: 85896e43537SVincent Donnefort if (root_inited) { 85996e43537SVincent Donnefort tracefs_remove(root); 86096e43537SVincent Donnefort root = NULL; 86196e43537SVincent Donnefort } else { 86296e43537SVincent Donnefort tracefs_remove(remote_d); 86396e43537SVincent Donnefort } 86496e43537SVincent Donnefort 86596e43537SVincent Donnefort return -ENOMEM; 86696e43537SVincent Donnefort } 86796e43537SVincent Donnefort 86807252915SVincent Donnefort static int trace_remote_register_events(const char *remote_name, struct trace_remote *remote, 86907252915SVincent Donnefort struct remote_event *events, size_t nr_events); 87007252915SVincent Donnefort 87196e43537SVincent Donnefort /** 87296e43537SVincent Donnefort * trace_remote_register() - Register a Tracefs remote 87396e43537SVincent Donnefort * @name: Name of the remote, used for the Tracefs remotes/ directory. 87496e43537SVincent Donnefort * @cbs: Set of callbacks used to control the remote. 87596e43537SVincent Donnefort * @priv: Private data, passed to each callback from @cbs. 87696e43537SVincent Donnefort * @events: Array of events. &remote_event.name and &remote_event.id must be 87796e43537SVincent Donnefort * filled by the caller. 87896e43537SVincent Donnefort * @nr_events: Number of events in the @events array. 87996e43537SVincent Donnefort * 88096e43537SVincent Donnefort * A trace remote is an entity, outside of the kernel (most likely firmware or 88196e43537SVincent Donnefort * hypervisor) capable of writing events into a Tracefs compatible ring-buffer. 88296e43537SVincent Donnefort * The kernel would then act as a reader. 88396e43537SVincent Donnefort * 88496e43537SVincent Donnefort * The registered remote will be found under the Tracefs directory 88596e43537SVincent Donnefort * remotes/<name>. 88696e43537SVincent Donnefort * 88796e43537SVincent Donnefort * Return: 0 on success, negative error code on failure. 88896e43537SVincent Donnefort */ 88907252915SVincent Donnefort int trace_remote_register(const char *name, struct trace_remote_callbacks *cbs, void *priv, 89007252915SVincent Donnefort struct remote_event *events, size_t nr_events) 89196e43537SVincent Donnefort { 89296e43537SVincent Donnefort struct trace_remote *remote; 893bf2ba0f8SVincent Donnefort int ret; 89496e43537SVincent Donnefort 89596e43537SVincent Donnefort remote = kzalloc_obj(*remote); 89696e43537SVincent Donnefort if (!remote) 89796e43537SVincent Donnefort return -ENOMEM; 89896e43537SVincent Donnefort 89996e43537SVincent Donnefort remote->cbs = cbs; 90096e43537SVincent Donnefort remote->priv = priv; 90196e43537SVincent Donnefort remote->trace_buffer_size = 7 << 10; 90296e43537SVincent Donnefort remote->poll_ms = 100; 90396e43537SVincent Donnefort mutex_init(&remote->lock); 904330b0cceSVincent Donnefort init_rwsem(&remote->reader_lock); 90596e43537SVincent Donnefort 90696e43537SVincent Donnefort if (trace_remote_init_tracefs(name, remote)) { 90796e43537SVincent Donnefort kfree(remote); 90896e43537SVincent Donnefort return -ENOMEM; 90996e43537SVincent Donnefort } 91096e43537SVincent Donnefort 91107252915SVincent Donnefort ret = trace_remote_register_events(name, remote, events, nr_events); 91207252915SVincent Donnefort if (ret) { 91307252915SVincent Donnefort pr_err("Failed to register events for trace remote '%s' (%d)\n", 91407252915SVincent Donnefort name, ret); 91507252915SVincent Donnefort return ret; 91607252915SVincent Donnefort } 91707252915SVincent Donnefort 918bf2ba0f8SVincent Donnefort ret = cbs->init ? cbs->init(remote->dentry, priv) : 0; 919bf2ba0f8SVincent Donnefort if (ret) 920bf2ba0f8SVincent Donnefort pr_err("Init failed for trace remote '%s' (%d)\n", name, ret); 921bf2ba0f8SVincent Donnefort 922bf2ba0f8SVincent Donnefort return ret; 92396e43537SVincent Donnefort } 92496e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_register); 92596e43537SVincent Donnefort 92696e43537SVincent Donnefort /** 92796e43537SVincent Donnefort * trace_remote_free_buffer() - Free trace buffer allocated with trace_remote_alloc_buffer() 92896e43537SVincent Donnefort * @desc: Descriptor of the per-CPU ring-buffers, originally filled by 92996e43537SVincent Donnefort * trace_remote_alloc_buffer() 93096e43537SVincent Donnefort * 93196e43537SVincent Donnefort * Most likely called from &trace_remote_callbacks.unload_trace_buffer. 93296e43537SVincent Donnefort */ 93396e43537SVincent Donnefort void trace_remote_free_buffer(struct trace_buffer_desc *desc) 93496e43537SVincent Donnefort { 93596e43537SVincent Donnefort struct ring_buffer_desc *rb_desc; 93696e43537SVincent Donnefort int cpu; 93796e43537SVincent Donnefort 93896e43537SVincent Donnefort for_each_ring_buffer_desc(rb_desc, cpu, desc) { 93996e43537SVincent Donnefort unsigned int id; 94096e43537SVincent Donnefort 94196e43537SVincent Donnefort free_page(rb_desc->meta_va); 94296e43537SVincent Donnefort 94396e43537SVincent Donnefort for (id = 0; id < rb_desc->nr_page_va; id++) 94496e43537SVincent Donnefort free_page(rb_desc->page_va[id]); 94596e43537SVincent Donnefort } 94696e43537SVincent Donnefort } 94796e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_free_buffer); 94896e43537SVincent Donnefort 94996e43537SVincent Donnefort /** 95096e43537SVincent Donnefort * trace_remote_alloc_buffer() - Dynamically allocate a trace buffer 95196e43537SVincent Donnefort * @desc: Uninitialized trace_buffer_desc 95296e43537SVincent Donnefort * @desc_size: Size of the trace_buffer_desc. Must be at least equal to 95396e43537SVincent Donnefort * trace_buffer_desc_size() 95496e43537SVincent Donnefort * @buffer_size: Size in bytes of each per-CPU ring-buffer 95596e43537SVincent Donnefort * @cpumask: CPUs to allocate a ring-buffer for 95696e43537SVincent Donnefort * 95796e43537SVincent Donnefort * Helper to dynamically allocate a set of pages (enough to cover @buffer_size) 95896e43537SVincent Donnefort * for each CPU from @cpumask and fill @desc. Most likely called from 95996e43537SVincent Donnefort * &trace_remote_callbacks.load_trace_buffer. 96096e43537SVincent Donnefort * 96196e43537SVincent Donnefort * Return: 0 on success, negative error code on failure. 96296e43537SVincent Donnefort */ 96396e43537SVincent Donnefort int trace_remote_alloc_buffer(struct trace_buffer_desc *desc, size_t desc_size, size_t buffer_size, 96496e43537SVincent Donnefort const struct cpumask *cpumask) 96596e43537SVincent Donnefort { 96696e43537SVincent Donnefort unsigned int nr_pages = max(DIV_ROUND_UP(buffer_size, PAGE_SIZE), 2UL) + 1; 96796e43537SVincent Donnefort void *desc_end = desc + desc_size; 96896e43537SVincent Donnefort struct ring_buffer_desc *rb_desc; 96996e43537SVincent Donnefort int cpu, ret = -ENOMEM; 97096e43537SVincent Donnefort 97196e43537SVincent Donnefort if (desc_size < struct_size(desc, __data, 0)) 97296e43537SVincent Donnefort return -EINVAL; 97396e43537SVincent Donnefort 97496e43537SVincent Donnefort desc->nr_cpus = 0; 97596e43537SVincent Donnefort desc->struct_len = struct_size(desc, __data, 0); 97696e43537SVincent Donnefort 97796e43537SVincent Donnefort rb_desc = (struct ring_buffer_desc *)&desc->__data[0]; 97896e43537SVincent Donnefort 97996e43537SVincent Donnefort for_each_cpu(cpu, cpumask) { 98096e43537SVincent Donnefort unsigned int id; 98196e43537SVincent Donnefort 98296e43537SVincent Donnefort if ((void *)rb_desc + struct_size(rb_desc, page_va, nr_pages) > desc_end) { 98396e43537SVincent Donnefort ret = -EINVAL; 98496e43537SVincent Donnefort goto err; 98596e43537SVincent Donnefort } 98696e43537SVincent Donnefort 98796e43537SVincent Donnefort rb_desc->cpu = cpu; 98896e43537SVincent Donnefort rb_desc->nr_page_va = 0; 98996e43537SVincent Donnefort rb_desc->meta_va = (unsigned long)__get_free_page(GFP_KERNEL); 99096e43537SVincent Donnefort if (!rb_desc->meta_va) 99196e43537SVincent Donnefort goto err; 99296e43537SVincent Donnefort 99396e43537SVincent Donnefort for (id = 0; id < nr_pages; id++) { 99496e43537SVincent Donnefort rb_desc->page_va[id] = (unsigned long)__get_free_page(GFP_KERNEL); 99596e43537SVincent Donnefort if (!rb_desc->page_va[id]) 99696e43537SVincent Donnefort goto err; 99796e43537SVincent Donnefort 99896e43537SVincent Donnefort rb_desc->nr_page_va++; 99996e43537SVincent Donnefort } 100096e43537SVincent Donnefort desc->nr_cpus++; 100196e43537SVincent Donnefort desc->struct_len += offsetof(struct ring_buffer_desc, page_va); 100296e43537SVincent Donnefort desc->struct_len += struct_size(rb_desc, page_va, rb_desc->nr_page_va); 100396e43537SVincent Donnefort rb_desc = __next_ring_buffer_desc(rb_desc); 100496e43537SVincent Donnefort } 100596e43537SVincent Donnefort 100696e43537SVincent Donnefort return 0; 100796e43537SVincent Donnefort 100896e43537SVincent Donnefort err: 100996e43537SVincent Donnefort trace_remote_free_buffer(desc); 101096e43537SVincent Donnefort return ret; 101196e43537SVincent Donnefort } 101296e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_alloc_buffer); 101307252915SVincent Donnefort 101407252915SVincent Donnefort static int 101507252915SVincent Donnefort trace_remote_enable_event(struct trace_remote *remote, struct remote_event *evt, bool enable) 101607252915SVincent Donnefort { 101707252915SVincent Donnefort int ret; 101807252915SVincent Donnefort 101907252915SVincent Donnefort lockdep_assert_held(&remote->lock); 102007252915SVincent Donnefort 102107252915SVincent Donnefort if (evt->enabled == enable) 102207252915SVincent Donnefort return 0; 102307252915SVincent Donnefort 102407252915SVincent Donnefort ret = remote->cbs->enable_event(evt->id, enable, remote->priv); 102507252915SVincent Donnefort if (ret) 102607252915SVincent Donnefort return ret; 102707252915SVincent Donnefort 102807252915SVincent Donnefort evt->enabled = enable; 102907252915SVincent Donnefort 103007252915SVincent Donnefort return 0; 103107252915SVincent Donnefort } 103207252915SVincent Donnefort 103307252915SVincent Donnefort static int remote_event_enable_show(struct seq_file *s, void *unused) 103407252915SVincent Donnefort { 103507252915SVincent Donnefort struct remote_event *evt = s->private; 103607252915SVincent Donnefort 103707252915SVincent Donnefort seq_printf(s, "%d\n", evt->enabled); 103807252915SVincent Donnefort 103907252915SVincent Donnefort return 0; 104007252915SVincent Donnefort } 104107252915SVincent Donnefort 104207252915SVincent Donnefort static ssize_t remote_event_enable_write(struct file *filp, const char __user *ubuf, 104307252915SVincent Donnefort size_t count, loff_t *ppos) 104407252915SVincent Donnefort { 104507252915SVincent Donnefort struct seq_file *seq = filp->private_data; 104607252915SVincent Donnefort struct remote_event *evt = seq->private; 104707252915SVincent Donnefort struct trace_remote *remote = evt->remote; 104807252915SVincent Donnefort u8 enable; 104907252915SVincent Donnefort int ret; 105007252915SVincent Donnefort 105107252915SVincent Donnefort ret = kstrtou8_from_user(ubuf, count, 10, &enable); 105207252915SVincent Donnefort if (ret) 105307252915SVincent Donnefort return ret; 105407252915SVincent Donnefort 105507252915SVincent Donnefort guard(mutex)(&remote->lock); 105607252915SVincent Donnefort 105707252915SVincent Donnefort ret = trace_remote_enable_event(remote, evt, enable); 105807252915SVincent Donnefort if (ret) 105907252915SVincent Donnefort return ret; 106007252915SVincent Donnefort 106107252915SVincent Donnefort return count; 106207252915SVincent Donnefort } 106307252915SVincent Donnefort DEFINE_SHOW_STORE_ATTRIBUTE(remote_event_enable); 106407252915SVincent Donnefort 106507252915SVincent Donnefort static int remote_event_id_show(struct seq_file *s, void *unused) 106607252915SVincent Donnefort { 106707252915SVincent Donnefort struct remote_event *evt = s->private; 106807252915SVincent Donnefort 106907252915SVincent Donnefort seq_printf(s, "%d\n", evt->id); 107007252915SVincent Donnefort 107107252915SVincent Donnefort return 0; 107207252915SVincent Donnefort } 107307252915SVincent Donnefort DEFINE_SHOW_ATTRIBUTE(remote_event_id); 107407252915SVincent Donnefort 107507252915SVincent Donnefort static int remote_event_format_show(struct seq_file *s, void *unused) 107607252915SVincent Donnefort { 107707252915SVincent Donnefort size_t offset = sizeof(struct remote_event_hdr); 107807252915SVincent Donnefort struct remote_event *evt = s->private; 107907252915SVincent Donnefort struct trace_event_fields *field; 108007252915SVincent Donnefort 108107252915SVincent Donnefort seq_printf(s, "name: %s\n", evt->name); 108207252915SVincent Donnefort seq_printf(s, "ID: %d\n", evt->id); 108307252915SVincent Donnefort seq_puts(s, 108407252915SVincent Donnefort "format:\n\tfield:unsigned short common_type;\toffset:0;\tsize:2;\tsigned:0;\n\n"); 108507252915SVincent Donnefort 108607252915SVincent Donnefort field = &evt->fields[0]; 108707252915SVincent Donnefort while (field->name) { 108807252915SVincent Donnefort seq_printf(s, "\tfield:%s %s;\toffset:%zu;\tsize:%u;\tsigned:%d;\n", 108907252915SVincent Donnefort field->type, field->name, offset, field->size, 109007252915SVincent Donnefort field->is_signed); 109107252915SVincent Donnefort offset += field->size; 109207252915SVincent Donnefort field++; 109307252915SVincent Donnefort } 109407252915SVincent Donnefort 109507252915SVincent Donnefort if (field != &evt->fields[0]) 109607252915SVincent Donnefort seq_puts(s, "\n"); 109707252915SVincent Donnefort 109807252915SVincent Donnefort seq_printf(s, "print fmt: %s\n", evt->print_fmt); 109907252915SVincent Donnefort 110007252915SVincent Donnefort return 0; 110107252915SVincent Donnefort } 110207252915SVincent Donnefort DEFINE_SHOW_ATTRIBUTE(remote_event_format); 110307252915SVincent Donnefort 110407252915SVincent Donnefort static int remote_event_callback(const char *name, umode_t *mode, void **data, 110507252915SVincent Donnefort const struct file_operations **fops) 110607252915SVincent Donnefort { 110707252915SVincent Donnefort if (!strcmp(name, "enable")) { 110807252915SVincent Donnefort *mode = TRACEFS_MODE_WRITE; 110907252915SVincent Donnefort *fops = &remote_event_enable_fops; 111007252915SVincent Donnefort return 1; 111107252915SVincent Donnefort } 111207252915SVincent Donnefort 111307252915SVincent Donnefort if (!strcmp(name, "id")) { 111407252915SVincent Donnefort *mode = TRACEFS_MODE_READ; 111507252915SVincent Donnefort *fops = &remote_event_id_fops; 111607252915SVincent Donnefort return 1; 111707252915SVincent Donnefort } 111807252915SVincent Donnefort 111907252915SVincent Donnefort if (!strcmp(name, "format")) { 112007252915SVincent Donnefort *mode = TRACEFS_MODE_READ; 112107252915SVincent Donnefort *fops = &remote_event_format_fops; 112207252915SVincent Donnefort return 1; 112307252915SVincent Donnefort } 112407252915SVincent Donnefort 112507252915SVincent Donnefort return 0; 112607252915SVincent Donnefort } 112707252915SVincent Donnefort 1128*775cb093SVincent Donnefort static ssize_t remote_events_dir_enable_write(struct file *filp, const char __user *ubuf, 1129*775cb093SVincent Donnefort size_t count, loff_t *ppos) 1130*775cb093SVincent Donnefort { 1131*775cb093SVincent Donnefort struct trace_remote *remote = file_inode(filp)->i_private; 1132*775cb093SVincent Donnefort int i, ret; 1133*775cb093SVincent Donnefort u8 enable; 1134*775cb093SVincent Donnefort 1135*775cb093SVincent Donnefort ret = kstrtou8_from_user(ubuf, count, 10, &enable); 1136*775cb093SVincent Donnefort if (ret) 1137*775cb093SVincent Donnefort return ret; 1138*775cb093SVincent Donnefort 1139*775cb093SVincent Donnefort guard(mutex)(&remote->lock); 1140*775cb093SVincent Donnefort 1141*775cb093SVincent Donnefort for (i = 0; i < remote->nr_events; i++) { 1142*775cb093SVincent Donnefort struct remote_event *evt = &remote->events[i]; 1143*775cb093SVincent Donnefort 1144*775cb093SVincent Donnefort trace_remote_enable_event(remote, evt, enable); 1145*775cb093SVincent Donnefort } 1146*775cb093SVincent Donnefort 1147*775cb093SVincent Donnefort return count; 1148*775cb093SVincent Donnefort } 1149*775cb093SVincent Donnefort 1150*775cb093SVincent Donnefort static ssize_t remote_events_dir_enable_read(struct file *filp, char __user *ubuf, size_t cnt, 1151*775cb093SVincent Donnefort loff_t *ppos) 1152*775cb093SVincent Donnefort { 1153*775cb093SVincent Donnefort struct trace_remote *remote = file_inode(filp)->i_private; 1154*775cb093SVincent Donnefort const char enabled_char[] = {'0', '1', 'X'}; 1155*775cb093SVincent Donnefort char enabled_str[] = " \n"; 1156*775cb093SVincent Donnefort int i, enabled = -1; 1157*775cb093SVincent Donnefort 1158*775cb093SVincent Donnefort guard(mutex)(&remote->lock); 1159*775cb093SVincent Donnefort 1160*775cb093SVincent Donnefort for (i = 0; i < remote->nr_events; i++) { 1161*775cb093SVincent Donnefort struct remote_event *evt = &remote->events[i]; 1162*775cb093SVincent Donnefort 1163*775cb093SVincent Donnefort if (enabled == -1) { 1164*775cb093SVincent Donnefort enabled = evt->enabled; 1165*775cb093SVincent Donnefort } else if (enabled != evt->enabled) { 1166*775cb093SVincent Donnefort enabled = 2; 1167*775cb093SVincent Donnefort break; 1168*775cb093SVincent Donnefort } 1169*775cb093SVincent Donnefort } 1170*775cb093SVincent Donnefort 1171*775cb093SVincent Donnefort enabled_str[0] = enabled_char[enabled == -1 ? 0 : enabled]; 1172*775cb093SVincent Donnefort 1173*775cb093SVincent Donnefort return simple_read_from_buffer(ubuf, cnt, ppos, enabled_str, 2); 1174*775cb093SVincent Donnefort } 1175*775cb093SVincent Donnefort 1176*775cb093SVincent Donnefort static const struct file_operations remote_events_dir_enable_fops = { 1177*775cb093SVincent Donnefort .write = remote_events_dir_enable_write, 1178*775cb093SVincent Donnefort .read = remote_events_dir_enable_read, 1179*775cb093SVincent Donnefort }; 1180*775cb093SVincent Donnefort 1181*775cb093SVincent Donnefort static ssize_t 1182*775cb093SVincent Donnefort remote_events_dir_header_page_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) 1183*775cb093SVincent Donnefort { 1184*775cb093SVincent Donnefort struct trace_seq *s; 1185*775cb093SVincent Donnefort int ret; 1186*775cb093SVincent Donnefort 1187*775cb093SVincent Donnefort s = kmalloc(sizeof(*s), GFP_KERNEL); 1188*775cb093SVincent Donnefort if (!s) 1189*775cb093SVincent Donnefort return -ENOMEM; 1190*775cb093SVincent Donnefort 1191*775cb093SVincent Donnefort trace_seq_init(s); 1192*775cb093SVincent Donnefort 1193*775cb093SVincent Donnefort ring_buffer_print_page_header(NULL, s); 1194*775cb093SVincent Donnefort ret = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, trace_seq_used(s)); 1195*775cb093SVincent Donnefort kfree(s); 1196*775cb093SVincent Donnefort 1197*775cb093SVincent Donnefort return ret; 1198*775cb093SVincent Donnefort } 1199*775cb093SVincent Donnefort 1200*775cb093SVincent Donnefort static const struct file_operations remote_events_dir_header_page_fops = { 1201*775cb093SVincent Donnefort .read = remote_events_dir_header_page_read, 1202*775cb093SVincent Donnefort }; 1203*775cb093SVincent Donnefort 1204*775cb093SVincent Donnefort static ssize_t 1205*775cb093SVincent Donnefort remote_events_dir_header_event_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) 1206*775cb093SVincent Donnefort { 1207*775cb093SVincent Donnefort struct trace_seq *s; 1208*775cb093SVincent Donnefort int ret; 1209*775cb093SVincent Donnefort 1210*775cb093SVincent Donnefort s = kmalloc(sizeof(*s), GFP_KERNEL); 1211*775cb093SVincent Donnefort if (!s) 1212*775cb093SVincent Donnefort return -ENOMEM; 1213*775cb093SVincent Donnefort 1214*775cb093SVincent Donnefort trace_seq_init(s); 1215*775cb093SVincent Donnefort 1216*775cb093SVincent Donnefort ring_buffer_print_entry_header(s); 1217*775cb093SVincent Donnefort ret = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, trace_seq_used(s)); 1218*775cb093SVincent Donnefort kfree(s); 1219*775cb093SVincent Donnefort 1220*775cb093SVincent Donnefort return ret; 1221*775cb093SVincent Donnefort } 1222*775cb093SVincent Donnefort 1223*775cb093SVincent Donnefort static const struct file_operations remote_events_dir_header_event_fops = { 1224*775cb093SVincent Donnefort .read = remote_events_dir_header_event_read, 1225*775cb093SVincent Donnefort }; 1226*775cb093SVincent Donnefort 1227*775cb093SVincent Donnefort static int remote_events_dir_callback(const char *name, umode_t *mode, void **data, 1228*775cb093SVincent Donnefort const struct file_operations **fops) 1229*775cb093SVincent Donnefort { 1230*775cb093SVincent Donnefort if (!strcmp(name, "enable")) { 1231*775cb093SVincent Donnefort *mode = TRACEFS_MODE_WRITE; 1232*775cb093SVincent Donnefort *fops = &remote_events_dir_enable_fops; 1233*775cb093SVincent Donnefort return 1; 1234*775cb093SVincent Donnefort } 1235*775cb093SVincent Donnefort 1236*775cb093SVincent Donnefort if (!strcmp(name, "header_page")) { 1237*775cb093SVincent Donnefort *mode = TRACEFS_MODE_READ; 1238*775cb093SVincent Donnefort *fops = &remote_events_dir_header_page_fops; 1239*775cb093SVincent Donnefort return 1; 1240*775cb093SVincent Donnefort } 1241*775cb093SVincent Donnefort 1242*775cb093SVincent Donnefort if (!strcmp(name, "header_event")) { 1243*775cb093SVincent Donnefort *mode = TRACEFS_MODE_READ; 1244*775cb093SVincent Donnefort *fops = &remote_events_dir_header_event_fops; 1245*775cb093SVincent Donnefort return 1; 1246*775cb093SVincent Donnefort } 1247*775cb093SVincent Donnefort 1248*775cb093SVincent Donnefort return 0; 1249*775cb093SVincent Donnefort } 1250*775cb093SVincent Donnefort 125107252915SVincent Donnefort static int trace_remote_init_eventfs(const char *remote_name, struct trace_remote *remote, 125207252915SVincent Donnefort struct remote_event *evt) 125307252915SVincent Donnefort { 125407252915SVincent Donnefort struct eventfs_inode *eventfs = remote->eventfs; 1255*775cb093SVincent Donnefort static struct eventfs_entry dir_entries[] = { 1256*775cb093SVincent Donnefort { 1257*775cb093SVincent Donnefort .name = "enable", 1258*775cb093SVincent Donnefort .callback = remote_events_dir_callback, 1259*775cb093SVincent Donnefort }, { 1260*775cb093SVincent Donnefort .name = "header_page", 1261*775cb093SVincent Donnefort .callback = remote_events_dir_callback, 1262*775cb093SVincent Donnefort }, { 1263*775cb093SVincent Donnefort .name = "header_event", 1264*775cb093SVincent Donnefort .callback = remote_events_dir_callback, 1265*775cb093SVincent Donnefort } 1266*775cb093SVincent Donnefort }; 126707252915SVincent Donnefort static struct eventfs_entry entries[] = { 126807252915SVincent Donnefort { 126907252915SVincent Donnefort .name = "enable", 127007252915SVincent Donnefort .callback = remote_event_callback, 127107252915SVincent Donnefort }, { 127207252915SVincent Donnefort .name = "id", 127307252915SVincent Donnefort .callback = remote_event_callback, 127407252915SVincent Donnefort }, { 127507252915SVincent Donnefort .name = "format", 127607252915SVincent Donnefort .callback = remote_event_callback, 127707252915SVincent Donnefort } 127807252915SVincent Donnefort }; 127907252915SVincent Donnefort bool eventfs_create = false; 128007252915SVincent Donnefort 128107252915SVincent Donnefort if (!eventfs) { 1282*775cb093SVincent Donnefort eventfs = eventfs_create_events_dir("events", remote->dentry, dir_entries, 1283*775cb093SVincent Donnefort ARRAY_SIZE(dir_entries), remote); 128407252915SVincent Donnefort if (IS_ERR(eventfs)) 128507252915SVincent Donnefort return PTR_ERR(eventfs); 128607252915SVincent Donnefort 128707252915SVincent Donnefort /* 128807252915SVincent Donnefort * Create similar hierarchy as local events even if a single system is supported at 128907252915SVincent Donnefort * the moment 129007252915SVincent Donnefort */ 129107252915SVincent Donnefort eventfs = eventfs_create_dir(remote_name, eventfs, NULL, 0, NULL); 129207252915SVincent Donnefort if (IS_ERR(eventfs)) 129307252915SVincent Donnefort return PTR_ERR(eventfs); 129407252915SVincent Donnefort 129507252915SVincent Donnefort remote->eventfs = eventfs; 129607252915SVincent Donnefort eventfs_create = true; 129707252915SVincent Donnefort } 129807252915SVincent Donnefort 129907252915SVincent Donnefort eventfs = eventfs_create_dir(evt->name, eventfs, entries, ARRAY_SIZE(entries), evt); 130007252915SVincent Donnefort if (IS_ERR(eventfs)) { 130107252915SVincent Donnefort if (eventfs_create) { 130207252915SVincent Donnefort eventfs_remove_events_dir(remote->eventfs); 130307252915SVincent Donnefort remote->eventfs = NULL; 130407252915SVincent Donnefort } 130507252915SVincent Donnefort return PTR_ERR(eventfs); 130607252915SVincent Donnefort } 130707252915SVincent Donnefort 130807252915SVincent Donnefort return 0; 130907252915SVincent Donnefort } 131007252915SVincent Donnefort 131107252915SVincent Donnefort static int trace_remote_attach_events(struct trace_remote *remote, struct remote_event *events, 131207252915SVincent Donnefort size_t nr_events) 131307252915SVincent Donnefort { 131407252915SVincent Donnefort int i; 131507252915SVincent Donnefort 131607252915SVincent Donnefort for (i = 0; i < nr_events; i++) { 131707252915SVincent Donnefort struct remote_event *evt = &events[i]; 131807252915SVincent Donnefort 131907252915SVincent Donnefort if (evt->remote) 132007252915SVincent Donnefort return -EEXIST; 132107252915SVincent Donnefort 132207252915SVincent Donnefort evt->remote = remote; 132307252915SVincent Donnefort 132407252915SVincent Donnefort /* We need events to be sorted for efficient lookup */ 132507252915SVincent Donnefort if (i && evt->id <= events[i - 1].id) 132607252915SVincent Donnefort return -EINVAL; 132707252915SVincent Donnefort } 132807252915SVincent Donnefort 132907252915SVincent Donnefort remote->events = events; 133007252915SVincent Donnefort remote->nr_events = nr_events; 133107252915SVincent Donnefort 133207252915SVincent Donnefort return 0; 133307252915SVincent Donnefort } 133407252915SVincent Donnefort 133507252915SVincent Donnefort static int trace_remote_register_events(const char *remote_name, struct trace_remote *remote, 133607252915SVincent Donnefort struct remote_event *events, size_t nr_events) 133707252915SVincent Donnefort { 133807252915SVincent Donnefort int i, ret; 133907252915SVincent Donnefort 134007252915SVincent Donnefort ret = trace_remote_attach_events(remote, events, nr_events); 134107252915SVincent Donnefort if (ret) 134207252915SVincent Donnefort return ret; 134307252915SVincent Donnefort 134407252915SVincent Donnefort for (i = 0; i < nr_events; i++) { 134507252915SVincent Donnefort struct remote_event *evt = &events[i]; 134607252915SVincent Donnefort 134707252915SVincent Donnefort ret = trace_remote_init_eventfs(remote_name, remote, evt); 134807252915SVincent Donnefort if (ret) 134907252915SVincent Donnefort pr_warn("Failed to init eventfs for event '%s' (%d)", 135007252915SVincent Donnefort evt->name, ret); 135107252915SVincent Donnefort } 135207252915SVincent Donnefort 135307252915SVincent Donnefort return 0; 135407252915SVincent Donnefort } 135507252915SVincent Donnefort 135607252915SVincent Donnefort static int __cmp_events(const void *key, const void *data) 135707252915SVincent Donnefort { 135807252915SVincent Donnefort const struct remote_event *evt = data; 135907252915SVincent Donnefort int id = (int)((long)key); 136007252915SVincent Donnefort 136107252915SVincent Donnefort return id - (int)evt->id; 136207252915SVincent Donnefort } 136307252915SVincent Donnefort 136407252915SVincent Donnefort static struct remote_event *trace_remote_find_event(struct trace_remote *remote, unsigned short id) 136507252915SVincent Donnefort { 136607252915SVincent Donnefort return bsearch((const void *)(unsigned long)id, remote->events, remote->nr_events, 136707252915SVincent Donnefort sizeof(*remote->events), __cmp_events); 136807252915SVincent Donnefort } 1369