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