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; 3496e43537SVincent Donnefort int cpu; 3596e43537SVincent Donnefort int evt_cpu; 36330b0cceSVincent Donnefort loff_t pos; 37330b0cceSVincent 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; 48330b0cceSVincent Donnefort struct rw_semaphore reader_lock; 49330b0cceSVincent 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 244330b0cceSVincent Donnefort if (cpu != RING_BUFFER_ALL_CPUS && !remote->pcpu_reader_locks) { 245330b0cceSVincent Donnefort int lock_cpu; 246330b0cceSVincent Donnefort 247330b0cceSVincent Donnefort remote->pcpu_reader_locks = kcalloc(nr_cpu_ids, sizeof(*remote->pcpu_reader_locks), 248330b0cceSVincent Donnefort GFP_KERNEL); 249330b0cceSVincent Donnefort if (!remote->pcpu_reader_locks) { 250330b0cceSVincent Donnefort trace_remote_try_unload(remote); 251330b0cceSVincent Donnefort return -ENOMEM; 252330b0cceSVincent Donnefort } 253330b0cceSVincent Donnefort 254330b0cceSVincent Donnefort for_each_possible_cpu(lock_cpu) 255330b0cceSVincent Donnefort init_rwsem(&remote->pcpu_reader_locks[lock_cpu]); 256330b0cceSVincent Donnefort } 257330b0cceSVincent 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 272330b0cceSVincent Donnefort kfree(remote->pcpu_reader_locks); 273330b0cceSVincent Donnefort remote->pcpu_reader_locks = NULL; 274330b0cceSVincent 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 289330b0cceSVincent Donnefort static void __free_ring_buffer_iter(struct trace_remote_iterator *iter, int cpu) 290330b0cceSVincent Donnefort { 291330b0cceSVincent Donnefort if (cpu != RING_BUFFER_ALL_CPUS) { 292330b0cceSVincent Donnefort ring_buffer_read_finish(iter->rb_iter); 293330b0cceSVincent Donnefort return; 294330b0cceSVincent Donnefort } 295330b0cceSVincent Donnefort 296330b0cceSVincent Donnefort for_each_possible_cpu(cpu) { 297330b0cceSVincent Donnefort if (iter->rb_iters[cpu]) 298330b0cceSVincent Donnefort ring_buffer_read_finish(iter->rb_iters[cpu]); 299330b0cceSVincent Donnefort } 300330b0cceSVincent Donnefort 301330b0cceSVincent Donnefort kfree(iter->rb_iters); 302330b0cceSVincent Donnefort } 303330b0cceSVincent Donnefort 304330b0cceSVincent Donnefort static int __alloc_ring_buffer_iter(struct trace_remote_iterator *iter, int cpu) 305330b0cceSVincent Donnefort { 306330b0cceSVincent Donnefort if (cpu != RING_BUFFER_ALL_CPUS) { 307330b0cceSVincent Donnefort iter->rb_iter = ring_buffer_read_start(iter->remote->trace_buffer, cpu, GFP_KERNEL); 308330b0cceSVincent Donnefort 309330b0cceSVincent Donnefort return iter->rb_iter ? 0 : -ENOMEM; 310330b0cceSVincent Donnefort } 311330b0cceSVincent Donnefort 312330b0cceSVincent Donnefort iter->rb_iters = kcalloc(nr_cpu_ids, sizeof(*iter->rb_iters), GFP_KERNEL); 313330b0cceSVincent Donnefort if (!iter->rb_iters) 314330b0cceSVincent Donnefort return -ENOMEM; 315330b0cceSVincent Donnefort 316330b0cceSVincent Donnefort for_each_possible_cpu(cpu) { 317330b0cceSVincent Donnefort iter->rb_iters[cpu] = ring_buffer_read_start(iter->remote->trace_buffer, cpu, 318330b0cceSVincent Donnefort GFP_KERNEL); 319330b0cceSVincent Donnefort if (!iter->rb_iters[cpu]) { 320330b0cceSVincent Donnefort __free_ring_buffer_iter(iter, RING_BUFFER_ALL_CPUS); 321330b0cceSVincent Donnefort return -ENOMEM; 322330b0cceSVincent Donnefort } 323330b0cceSVincent Donnefort } 324330b0cceSVincent Donnefort 325330b0cceSVincent Donnefort return 0; 326330b0cceSVincent Donnefort } 327330b0cceSVincent Donnefort 328330b0cceSVincent Donnefort static struct trace_remote_iterator 329330b0cceSVincent 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 336330b0cceSVincent Donnefort if (type == TRI_NONCONSUMING && !trace_remote_loaded(remote)) 337330b0cceSVincent 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; 352330b0cceSVincent Donnefort iter->type = type; 35396e43537SVincent Donnefort trace_seq_init(&iter->seq); 354330b0cceSVincent Donnefort 355330b0cceSVincent Donnefort switch (type) { 356330b0cceSVincent 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)); 359330b0cceSVincent Donnefort break; 360330b0cceSVincent Donnefort case TRI_NONCONSUMING: 361330b0cceSVincent Donnefort ret = __alloc_ring_buffer_iter(iter, cpu); 362330b0cceSVincent Donnefort break; 363330b0cceSVincent Donnefort } 364330b0cceSVincent Donnefort 365330b0cceSVincent Donnefort if (ret) 366330b0cceSVincent 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 390330b0cceSVincent Donnefort switch (iter->type) { 391330b0cceSVincent Donnefort case TRI_CONSUMING: 392330b0cceSVincent Donnefort cancel_delayed_work_sync(&iter->poll_work); 393330b0cceSVincent Donnefort break; 394330b0cceSVincent Donnefort case TRI_NONCONSUMING: 395330b0cceSVincent Donnefort __free_ring_buffer_iter(iter, iter->cpu); 396330b0cceSVincent Donnefort break; 397330b0cceSVincent Donnefort } 398330b0cceSVincent Donnefort 39996e43537SVincent Donnefort kfree(iter); 40096e43537SVincent Donnefort trace_remote_put(remote); 40196e43537SVincent Donnefort } 40296e43537SVincent Donnefort 403330b0cceSVincent Donnefort static void trace_remote_iter_read_start(struct trace_remote_iterator *iter) 404330b0cceSVincent Donnefort { 405330b0cceSVincent Donnefort struct trace_remote *remote = iter->remote; 406330b0cceSVincent Donnefort int cpu = iter->cpu; 407330b0cceSVincent Donnefort 408330b0cceSVincent Donnefort /* Acquire global reader lock */ 409330b0cceSVincent Donnefort if (cpu == RING_BUFFER_ALL_CPUS && iter->type == TRI_CONSUMING) 410330b0cceSVincent Donnefort down_write(&remote->reader_lock); 411330b0cceSVincent Donnefort else 412330b0cceSVincent Donnefort down_read(&remote->reader_lock); 413330b0cceSVincent Donnefort 414330b0cceSVincent Donnefort if (cpu == RING_BUFFER_ALL_CPUS) 415330b0cceSVincent Donnefort return; 416330b0cceSVincent Donnefort 417330b0cceSVincent Donnefort /* 418330b0cceSVincent Donnefort * No need for the remote lock here, iter holds a reference on 419330b0cceSVincent Donnefort * remote->nr_readers 420330b0cceSVincent Donnefort */ 421330b0cceSVincent Donnefort 422330b0cceSVincent Donnefort /* Get the per-CPU one */ 423330b0cceSVincent Donnefort if (WARN_ON_ONCE(!remote->pcpu_reader_locks)) 424330b0cceSVincent Donnefort return; 425330b0cceSVincent Donnefort 426330b0cceSVincent Donnefort if (iter->type == TRI_CONSUMING) 427330b0cceSVincent Donnefort down_write(&remote->pcpu_reader_locks[cpu]); 428330b0cceSVincent Donnefort else 429330b0cceSVincent Donnefort down_read(&remote->pcpu_reader_locks[cpu]); 430330b0cceSVincent Donnefort } 431330b0cceSVincent Donnefort 432330b0cceSVincent Donnefort static void trace_remote_iter_read_finished(struct trace_remote_iterator *iter) 433330b0cceSVincent Donnefort { 434330b0cceSVincent Donnefort struct trace_remote *remote = iter->remote; 435330b0cceSVincent Donnefort int cpu = iter->cpu; 436330b0cceSVincent Donnefort 437330b0cceSVincent Donnefort /* Release per-CPU reader lock */ 438330b0cceSVincent Donnefort if (cpu != RING_BUFFER_ALL_CPUS) { 439330b0cceSVincent Donnefort /* 440330b0cceSVincent Donnefort * No need for the remote lock here, iter holds a reference on 441330b0cceSVincent Donnefort * remote->nr_readers 442330b0cceSVincent Donnefort */ 443330b0cceSVincent Donnefort if (iter->type == TRI_CONSUMING) 444330b0cceSVincent Donnefort up_write(&remote->pcpu_reader_locks[cpu]); 445330b0cceSVincent Donnefort else 446330b0cceSVincent Donnefort up_read(&remote->pcpu_reader_locks[cpu]); 447330b0cceSVincent Donnefort } 448330b0cceSVincent Donnefort 449330b0cceSVincent Donnefort /* Release global reader lock */ 450330b0cceSVincent Donnefort if (cpu == RING_BUFFER_ALL_CPUS && iter->type == TRI_CONSUMING) 451330b0cceSVincent Donnefort up_write(&remote->reader_lock); 452330b0cceSVincent Donnefort else 453330b0cceSVincent Donnefort up_read(&remote->reader_lock); 454330b0cceSVincent Donnefort } 455330b0cceSVincent Donnefort 456330b0cceSVincent Donnefort static struct ring_buffer_iter *__get_rb_iter(struct trace_remote_iterator *iter, int cpu) 457330b0cceSVincent Donnefort { 458330b0cceSVincent Donnefort return iter->cpu != RING_BUFFER_ALL_CPUS ? iter->rb_iter : iter->rb_iters[cpu]; 459330b0cceSVincent Donnefort } 460330b0cceSVincent Donnefort 461330b0cceSVincent Donnefort static struct ring_buffer_event * 462330b0cceSVincent Donnefort __peek_event(struct trace_remote_iterator *iter, int cpu, u64 *ts, unsigned long *lost_events) 463330b0cceSVincent Donnefort { 464330b0cceSVincent Donnefort struct ring_buffer_event *rb_evt; 465330b0cceSVincent Donnefort struct ring_buffer_iter *rb_iter; 466330b0cceSVincent Donnefort 467330b0cceSVincent Donnefort switch (iter->type) { 468330b0cceSVincent Donnefort case TRI_CONSUMING: 469330b0cceSVincent Donnefort return ring_buffer_peek(iter->remote->trace_buffer, cpu, ts, lost_events); 470330b0cceSVincent Donnefort case TRI_NONCONSUMING: 471330b0cceSVincent Donnefort rb_iter = __get_rb_iter(iter, cpu); 472330b0cceSVincent Donnefort rb_evt = ring_buffer_iter_peek(rb_iter, ts); 473330b0cceSVincent Donnefort if (!rb_evt) 474330b0cceSVincent Donnefort return NULL; 475330b0cceSVincent Donnefort 476330b0cceSVincent Donnefort *lost_events = ring_buffer_iter_dropped(rb_iter); 477330b0cceSVincent Donnefort 478330b0cceSVincent Donnefort return rb_evt; 479330b0cceSVincent Donnefort } 480330b0cceSVincent Donnefort 481330b0cceSVincent Donnefort return NULL; 482330b0cceSVincent Donnefort } 483330b0cceSVincent 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 493330b0cceSVincent 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 508330b0cceSVincent 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 522330b0cceSVincent Donnefort static void trace_remote_iter_move(struct trace_remote_iterator *iter) 523330b0cceSVincent Donnefort { 524330b0cceSVincent Donnefort struct trace_buffer *trace_buffer = iter->remote->trace_buffer; 525330b0cceSVincent Donnefort 526330b0cceSVincent Donnefort switch (iter->type) { 527330b0cceSVincent Donnefort case TRI_CONSUMING: 528330b0cceSVincent Donnefort ring_buffer_consume(trace_buffer, iter->evt_cpu, NULL, NULL); 529330b0cceSVincent Donnefort break; 530330b0cceSVincent Donnefort case TRI_NONCONSUMING: 531330b0cceSVincent Donnefort ring_buffer_iter_advance(__get_rb_iter(iter, iter->evt_cpu)); 532330b0cceSVincent Donnefort break; 533330b0cceSVincent Donnefort } 534330b0cceSVincent Donnefort } 535330b0cceSVincent 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; 558330b0cceSVincent Donnefort int cpu = tracing_get_cpu(inode); 55996e43537SVincent Donnefort 56096e43537SVincent Donnefort guard(mutex)(&remote->lock); 561330b0cceSVincent Donnefort 562330b0cceSVincent Donnefort iter = trace_remote_iter(remote, cpu, TRI_CONSUMING); 563330b0cceSVincent Donnefort if (IS_ERR(iter)) 564330b0cceSVincent Donnefort return PTR_ERR(iter); 565330b0cceSVincent 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 600330b0cceSVincent Donnefort trace_remote_iter_read_start(iter); 601330b0cceSVincent 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 610330b0cceSVincent Donnefort trace_remote_iter_move(iter); 61196e43537SVincent Donnefort } 61296e43537SVincent Donnefort 613330b0cceSVincent Donnefort trace_remote_iter_read_finished(iter); 614330b0cceSVincent 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 624330b0cceSVincent Donnefort static void *trace_next(struct seq_file *m, void *v, loff_t *pos) 625330b0cceSVincent Donnefort { 626330b0cceSVincent Donnefort struct trace_remote_iterator *iter = m->private; 627330b0cceSVincent Donnefort 628330b0cceSVincent Donnefort ++*pos; 629330b0cceSVincent Donnefort 630330b0cceSVincent Donnefort if (!iter || !trace_remote_iter_read_event(iter)) 631330b0cceSVincent Donnefort return NULL; 632330b0cceSVincent Donnefort 633330b0cceSVincent Donnefort trace_remote_iter_move(iter); 634330b0cceSVincent Donnefort iter->pos++; 635330b0cceSVincent Donnefort 636330b0cceSVincent Donnefort return iter; 637330b0cceSVincent Donnefort } 638330b0cceSVincent Donnefort 639330b0cceSVincent Donnefort static void *trace_start(struct seq_file *m, loff_t *pos) 640330b0cceSVincent Donnefort { 641330b0cceSVincent Donnefort struct trace_remote_iterator *iter = m->private; 642330b0cceSVincent Donnefort loff_t i; 643330b0cceSVincent Donnefort 644330b0cceSVincent Donnefort if (!iter) 645330b0cceSVincent Donnefort return NULL; 646330b0cceSVincent Donnefort 647330b0cceSVincent Donnefort trace_remote_iter_read_start(iter); 648330b0cceSVincent Donnefort 649330b0cceSVincent Donnefort if (!*pos) { 650330b0cceSVincent Donnefort iter->pos = -1; 651330b0cceSVincent Donnefort return trace_next(m, NULL, &i); 652330b0cceSVincent Donnefort } 653330b0cceSVincent Donnefort 654330b0cceSVincent Donnefort i = iter->pos; 655330b0cceSVincent Donnefort while (i < *pos) { 656330b0cceSVincent Donnefort iter = trace_next(m, NULL, &i); 657330b0cceSVincent Donnefort if (!iter) 658330b0cceSVincent Donnefort return NULL; 659330b0cceSVincent Donnefort } 660330b0cceSVincent Donnefort 661330b0cceSVincent Donnefort return iter; 662330b0cceSVincent Donnefort } 663330b0cceSVincent Donnefort 664330b0cceSVincent Donnefort static int trace_show(struct seq_file *m, void *v) 665330b0cceSVincent Donnefort { 666330b0cceSVincent Donnefort struct trace_remote_iterator *iter = v; 667330b0cceSVincent Donnefort 668330b0cceSVincent Donnefort trace_seq_init(&iter->seq); 669330b0cceSVincent Donnefort 670330b0cceSVincent Donnefort if (trace_remote_iter_print_event(iter)) { 671330b0cceSVincent Donnefort seq_printf(m, "[EVENT %d PRINT TOO BIG]\n", iter->evt->id); 672330b0cceSVincent Donnefort return 0; 673330b0cceSVincent Donnefort } 674330b0cceSVincent Donnefort 675330b0cceSVincent Donnefort return trace_print_seq(m, &iter->seq); 676330b0cceSVincent Donnefort } 677330b0cceSVincent Donnefort 678330b0cceSVincent Donnefort static void trace_stop(struct seq_file *m, void *v) 679330b0cceSVincent Donnefort { 680330b0cceSVincent Donnefort struct trace_remote_iterator *iter = m->private; 681330b0cceSVincent Donnefort 682330b0cceSVincent Donnefort if (iter) 683330b0cceSVincent Donnefort trace_remote_iter_read_finished(iter); 684330b0cceSVincent Donnefort } 685330b0cceSVincent Donnefort 686330b0cceSVincent Donnefort static const struct seq_operations trace_sops = { 687330b0cceSVincent Donnefort .start = trace_start, 688330b0cceSVincent Donnefort .next = trace_next, 689330b0cceSVincent Donnefort .show = trace_show, 690330b0cceSVincent Donnefort .stop = trace_stop, 691330b0cceSVincent Donnefort }; 692330b0cceSVincent Donnefort 693330b0cceSVincent Donnefort static int trace_open(struct inode *inode, struct file *filp) 694330b0cceSVincent Donnefort { 695330b0cceSVincent Donnefort struct trace_remote *remote = inode->i_private; 696330b0cceSVincent Donnefort struct trace_remote_iterator *iter = NULL; 697330b0cceSVincent Donnefort int cpu = tracing_get_cpu(inode); 698330b0cceSVincent Donnefort int ret; 699330b0cceSVincent Donnefort 700330b0cceSVincent Donnefort if (!(filp->f_mode & FMODE_READ)) 701330b0cceSVincent Donnefort return 0; 702330b0cceSVincent Donnefort 703330b0cceSVincent Donnefort guard(mutex)(&remote->lock); 704330b0cceSVincent Donnefort 705330b0cceSVincent Donnefort iter = trace_remote_iter(remote, cpu, TRI_NONCONSUMING); 706330b0cceSVincent Donnefort if (IS_ERR(iter)) 707330b0cceSVincent Donnefort return PTR_ERR(iter); 708330b0cceSVincent Donnefort 709330b0cceSVincent Donnefort ret = seq_open(filp, &trace_sops); 710330b0cceSVincent Donnefort if (ret) { 711330b0cceSVincent Donnefort trace_remote_iter_free(iter); 712330b0cceSVincent Donnefort return ret; 713330b0cceSVincent Donnefort } 714330b0cceSVincent Donnefort 715330b0cceSVincent Donnefort ((struct seq_file *)filp->private_data)->private = (void *)iter; 716330b0cceSVincent Donnefort 717330b0cceSVincent Donnefort return 0; 718330b0cceSVincent Donnefort } 719330b0cceSVincent Donnefort 720330b0cceSVincent Donnefort static int trace_release(struct inode *inode, struct file *filp) 721330b0cceSVincent Donnefort { 722330b0cceSVincent Donnefort struct trace_remote_iterator *iter; 723330b0cceSVincent Donnefort 724330b0cceSVincent Donnefort if (!(filp->f_mode & FMODE_READ)) 725330b0cceSVincent Donnefort return 0; 726330b0cceSVincent Donnefort 727330b0cceSVincent Donnefort iter = ((struct seq_file *)filp->private_data)->private; 728330b0cceSVincent Donnefort seq_release(inode, filp); 729330b0cceSVincent Donnefort 730330b0cceSVincent Donnefort if (!iter) 731330b0cceSVincent Donnefort return 0; 732330b0cceSVincent Donnefort 733330b0cceSVincent Donnefort guard(mutex)(&iter->remote->lock); 734330b0cceSVincent Donnefort 735330b0cceSVincent Donnefort trace_remote_iter_free(iter); 736330b0cceSVincent Donnefort 737330b0cceSVincent Donnefort return 0; 738330b0cceSVincent Donnefort } 739330b0cceSVincent 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; 744330b0cceSVincent 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 = { 754330b0cceSVincent Donnefort .open = trace_open, 7559af4ab0eSVincent Donnefort .write = trace_write, 756330b0cceSVincent Donnefort .read = seq_read, 757330b0cceSVincent Donnefort .read_iter = seq_read_iter, 758330b0cceSVincent 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; 866*bf2ba0f8SVincent Donnefort int ret; 86796e43537SVincent Donnefort 86896e43537SVincent Donnefort remote = kzalloc_obj(*remote); 86996e43537SVincent Donnefort if (!remote) 87096e43537SVincent Donnefort return -ENOMEM; 87196e43537SVincent Donnefort 87296e43537SVincent Donnefort remote->cbs = cbs; 87396e43537SVincent Donnefort remote->priv = priv; 87496e43537SVincent Donnefort remote->trace_buffer_size = 7 << 10; 87596e43537SVincent Donnefort remote->poll_ms = 100; 87696e43537SVincent Donnefort mutex_init(&remote->lock); 877330b0cceSVincent Donnefort init_rwsem(&remote->reader_lock); 87896e43537SVincent Donnefort 87996e43537SVincent Donnefort if (trace_remote_init_tracefs(name, remote)) { 88096e43537SVincent Donnefort kfree(remote); 88196e43537SVincent Donnefort return -ENOMEM; 88296e43537SVincent Donnefort } 88396e43537SVincent Donnefort 884*bf2ba0f8SVincent Donnefort ret = cbs->init ? cbs->init(remote->dentry, priv) : 0; 885*bf2ba0f8SVincent Donnefort if (ret) 886*bf2ba0f8SVincent Donnefort pr_err("Init failed for trace remote '%s' (%d)\n", name, ret); 887*bf2ba0f8SVincent Donnefort 888*bf2ba0f8SVincent Donnefort return ret; 88996e43537SVincent Donnefort } 89096e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_register); 89196e43537SVincent Donnefort 89296e43537SVincent Donnefort /** 89396e43537SVincent Donnefort * trace_remote_free_buffer() - Free trace buffer allocated with trace_remote_alloc_buffer() 89496e43537SVincent Donnefort * @desc: Descriptor of the per-CPU ring-buffers, originally filled by 89596e43537SVincent Donnefort * trace_remote_alloc_buffer() 89696e43537SVincent Donnefort * 89796e43537SVincent Donnefort * Most likely called from &trace_remote_callbacks.unload_trace_buffer. 89896e43537SVincent Donnefort */ 89996e43537SVincent Donnefort void trace_remote_free_buffer(struct trace_buffer_desc *desc) 90096e43537SVincent Donnefort { 90196e43537SVincent Donnefort struct ring_buffer_desc *rb_desc; 90296e43537SVincent Donnefort int cpu; 90396e43537SVincent Donnefort 90496e43537SVincent Donnefort for_each_ring_buffer_desc(rb_desc, cpu, desc) { 90596e43537SVincent Donnefort unsigned int id; 90696e43537SVincent Donnefort 90796e43537SVincent Donnefort free_page(rb_desc->meta_va); 90896e43537SVincent Donnefort 90996e43537SVincent Donnefort for (id = 0; id < rb_desc->nr_page_va; id++) 91096e43537SVincent Donnefort free_page(rb_desc->page_va[id]); 91196e43537SVincent Donnefort } 91296e43537SVincent Donnefort } 91396e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_free_buffer); 91496e43537SVincent Donnefort 91596e43537SVincent Donnefort /** 91696e43537SVincent Donnefort * trace_remote_alloc_buffer() - Dynamically allocate a trace buffer 91796e43537SVincent Donnefort * @desc: Uninitialized trace_buffer_desc 91896e43537SVincent Donnefort * @desc_size: Size of the trace_buffer_desc. Must be at least equal to 91996e43537SVincent Donnefort * trace_buffer_desc_size() 92096e43537SVincent Donnefort * @buffer_size: Size in bytes of each per-CPU ring-buffer 92196e43537SVincent Donnefort * @cpumask: CPUs to allocate a ring-buffer for 92296e43537SVincent Donnefort * 92396e43537SVincent Donnefort * Helper to dynamically allocate a set of pages (enough to cover @buffer_size) 92496e43537SVincent Donnefort * for each CPU from @cpumask and fill @desc. Most likely called from 92596e43537SVincent Donnefort * &trace_remote_callbacks.load_trace_buffer. 92696e43537SVincent Donnefort * 92796e43537SVincent Donnefort * Return: 0 on success, negative error code on failure. 92896e43537SVincent Donnefort */ 92996e43537SVincent Donnefort int trace_remote_alloc_buffer(struct trace_buffer_desc *desc, size_t desc_size, size_t buffer_size, 93096e43537SVincent Donnefort const struct cpumask *cpumask) 93196e43537SVincent Donnefort { 93296e43537SVincent Donnefort unsigned int nr_pages = max(DIV_ROUND_UP(buffer_size, PAGE_SIZE), 2UL) + 1; 93396e43537SVincent Donnefort void *desc_end = desc + desc_size; 93496e43537SVincent Donnefort struct ring_buffer_desc *rb_desc; 93596e43537SVincent Donnefort int cpu, ret = -ENOMEM; 93696e43537SVincent Donnefort 93796e43537SVincent Donnefort if (desc_size < struct_size(desc, __data, 0)) 93896e43537SVincent Donnefort return -EINVAL; 93996e43537SVincent Donnefort 94096e43537SVincent Donnefort desc->nr_cpus = 0; 94196e43537SVincent Donnefort desc->struct_len = struct_size(desc, __data, 0); 94296e43537SVincent Donnefort 94396e43537SVincent Donnefort rb_desc = (struct ring_buffer_desc *)&desc->__data[0]; 94496e43537SVincent Donnefort 94596e43537SVincent Donnefort for_each_cpu(cpu, cpumask) { 94696e43537SVincent Donnefort unsigned int id; 94796e43537SVincent Donnefort 94896e43537SVincent Donnefort if ((void *)rb_desc + struct_size(rb_desc, page_va, nr_pages) > desc_end) { 94996e43537SVincent Donnefort ret = -EINVAL; 95096e43537SVincent Donnefort goto err; 95196e43537SVincent Donnefort } 95296e43537SVincent Donnefort 95396e43537SVincent Donnefort rb_desc->cpu = cpu; 95496e43537SVincent Donnefort rb_desc->nr_page_va = 0; 95596e43537SVincent Donnefort rb_desc->meta_va = (unsigned long)__get_free_page(GFP_KERNEL); 95696e43537SVincent Donnefort if (!rb_desc->meta_va) 95796e43537SVincent Donnefort goto err; 95896e43537SVincent Donnefort 95996e43537SVincent Donnefort for (id = 0; id < nr_pages; id++) { 96096e43537SVincent Donnefort rb_desc->page_va[id] = (unsigned long)__get_free_page(GFP_KERNEL); 96196e43537SVincent Donnefort if (!rb_desc->page_va[id]) 96296e43537SVincent Donnefort goto err; 96396e43537SVincent Donnefort 96496e43537SVincent Donnefort rb_desc->nr_page_va++; 96596e43537SVincent Donnefort } 96696e43537SVincent Donnefort desc->nr_cpus++; 96796e43537SVincent Donnefort desc->struct_len += offsetof(struct ring_buffer_desc, page_va); 96896e43537SVincent Donnefort desc->struct_len += struct_size(rb_desc, page_va, rb_desc->nr_page_va); 96996e43537SVincent Donnefort rb_desc = __next_ring_buffer_desc(rb_desc); 97096e43537SVincent Donnefort } 97196e43537SVincent Donnefort 97296e43537SVincent Donnefort return 0; 97396e43537SVincent Donnefort 97496e43537SVincent Donnefort err: 97596e43537SVincent Donnefort trace_remote_free_buffer(desc); 97696e43537SVincent Donnefort return ret; 97796e43537SVincent Donnefort } 97896e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_alloc_buffer); 979