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 2196e43537SVincent Donnefort struct trace_remote_iterator { 2296e43537SVincent Donnefort struct trace_remote *remote; 2396e43537SVincent Donnefort struct trace_seq seq; 2496e43537SVincent Donnefort struct delayed_work poll_work; 2596e43537SVincent Donnefort unsigned long lost_events; 2696e43537SVincent Donnefort u64 ts; 2796e43537SVincent Donnefort int cpu; 2896e43537SVincent Donnefort int evt_cpu; 2996e43537SVincent Donnefort }; 3096e43537SVincent Donnefort 3196e43537SVincent Donnefort struct trace_remote { 3296e43537SVincent Donnefort struct trace_remote_callbacks *cbs; 3396e43537SVincent Donnefort void *priv; 3496e43537SVincent Donnefort struct trace_buffer *trace_buffer; 3596e43537SVincent Donnefort struct trace_buffer_desc *trace_buffer_desc; 3696e43537SVincent Donnefort unsigned long trace_buffer_size; 3796e43537SVincent Donnefort struct ring_buffer_remote rb_remote; 3896e43537SVincent Donnefort struct mutex lock; 3996e43537SVincent Donnefort unsigned int nr_readers; 4096e43537SVincent Donnefort unsigned int poll_ms; 4196e43537SVincent Donnefort bool tracing_on; 4296e43537SVincent Donnefort }; 4396e43537SVincent Donnefort 4496e43537SVincent Donnefort static bool trace_remote_loaded(struct trace_remote *remote) 4596e43537SVincent Donnefort { 4696e43537SVincent Donnefort return !!remote->trace_buffer; 4796e43537SVincent Donnefort } 4896e43537SVincent Donnefort 4996e43537SVincent Donnefort static int trace_remote_load(struct trace_remote *remote) 5096e43537SVincent Donnefort { 5196e43537SVincent Donnefort struct ring_buffer_remote *rb_remote = &remote->rb_remote; 5296e43537SVincent Donnefort struct trace_buffer_desc *desc; 5396e43537SVincent Donnefort 5496e43537SVincent Donnefort lockdep_assert_held(&remote->lock); 5596e43537SVincent Donnefort 5696e43537SVincent Donnefort if (trace_remote_loaded(remote)) 5796e43537SVincent Donnefort return 0; 5896e43537SVincent Donnefort 5996e43537SVincent Donnefort desc = remote->cbs->load_trace_buffer(remote->trace_buffer_size, remote->priv); 6096e43537SVincent Donnefort if (IS_ERR(desc)) 6196e43537SVincent Donnefort return PTR_ERR(desc); 6296e43537SVincent Donnefort 6396e43537SVincent Donnefort rb_remote->desc = desc; 6496e43537SVincent Donnefort rb_remote->swap_reader_page = remote->cbs->swap_reader_page; 6596e43537SVincent Donnefort rb_remote->priv = remote->priv; 66*9af4ab0eSVincent Donnefort rb_remote->reset = remote->cbs->reset; 6796e43537SVincent Donnefort remote->trace_buffer = ring_buffer_alloc_remote(rb_remote); 6896e43537SVincent Donnefort if (!remote->trace_buffer) { 6996e43537SVincent Donnefort remote->cbs->unload_trace_buffer(desc, remote->priv); 7096e43537SVincent Donnefort return -ENOMEM; 7196e43537SVincent Donnefort } 7296e43537SVincent Donnefort 7396e43537SVincent Donnefort remote->trace_buffer_desc = desc; 7496e43537SVincent Donnefort 7596e43537SVincent Donnefort return 0; 7696e43537SVincent Donnefort } 7796e43537SVincent Donnefort 7896e43537SVincent Donnefort static void trace_remote_try_unload(struct trace_remote *remote) 7996e43537SVincent Donnefort { 8096e43537SVincent Donnefort lockdep_assert_held(&remote->lock); 8196e43537SVincent Donnefort 8296e43537SVincent Donnefort if (!trace_remote_loaded(remote)) 8396e43537SVincent Donnefort return; 8496e43537SVincent Donnefort 8596e43537SVincent Donnefort /* The buffer is being read or writable */ 8696e43537SVincent Donnefort if (remote->nr_readers || remote->tracing_on) 8796e43537SVincent Donnefort return; 8896e43537SVincent Donnefort 8996e43537SVincent Donnefort /* The buffer has readable data */ 9096e43537SVincent Donnefort if (!ring_buffer_empty(remote->trace_buffer)) 9196e43537SVincent Donnefort return; 9296e43537SVincent Donnefort 9396e43537SVincent Donnefort ring_buffer_free(remote->trace_buffer); 9496e43537SVincent Donnefort remote->trace_buffer = NULL; 9596e43537SVincent Donnefort remote->cbs->unload_trace_buffer(remote->trace_buffer_desc, remote->priv); 9696e43537SVincent Donnefort } 9796e43537SVincent Donnefort 9896e43537SVincent Donnefort static int trace_remote_enable_tracing(struct trace_remote *remote) 9996e43537SVincent Donnefort { 10096e43537SVincent Donnefort int ret; 10196e43537SVincent Donnefort 10296e43537SVincent Donnefort lockdep_assert_held(&remote->lock); 10396e43537SVincent Donnefort 10496e43537SVincent Donnefort if (remote->tracing_on) 10596e43537SVincent Donnefort return 0; 10696e43537SVincent Donnefort 10796e43537SVincent Donnefort ret = trace_remote_load(remote); 10896e43537SVincent Donnefort if (ret) 10996e43537SVincent Donnefort return ret; 11096e43537SVincent Donnefort 11196e43537SVincent Donnefort ret = remote->cbs->enable_tracing(true, remote->priv); 11296e43537SVincent Donnefort if (ret) { 11396e43537SVincent Donnefort trace_remote_try_unload(remote); 11496e43537SVincent Donnefort return ret; 11596e43537SVincent Donnefort } 11696e43537SVincent Donnefort 11796e43537SVincent Donnefort remote->tracing_on = true; 11896e43537SVincent Donnefort 11996e43537SVincent Donnefort return 0; 12096e43537SVincent Donnefort } 12196e43537SVincent Donnefort 12296e43537SVincent Donnefort static int trace_remote_disable_tracing(struct trace_remote *remote) 12396e43537SVincent Donnefort { 12496e43537SVincent Donnefort int ret; 12596e43537SVincent Donnefort 12696e43537SVincent Donnefort lockdep_assert_held(&remote->lock); 12796e43537SVincent Donnefort 12896e43537SVincent Donnefort if (!remote->tracing_on) 12996e43537SVincent Donnefort return 0; 13096e43537SVincent Donnefort 13196e43537SVincent Donnefort ret = remote->cbs->enable_tracing(false, remote->priv); 13296e43537SVincent Donnefort if (ret) 13396e43537SVincent Donnefort return ret; 13496e43537SVincent Donnefort 13596e43537SVincent Donnefort ring_buffer_poll_remote(remote->trace_buffer, RING_BUFFER_ALL_CPUS); 13696e43537SVincent Donnefort remote->tracing_on = false; 13796e43537SVincent Donnefort trace_remote_try_unload(remote); 13896e43537SVincent Donnefort 13996e43537SVincent Donnefort return 0; 14096e43537SVincent Donnefort } 14196e43537SVincent Donnefort 142*9af4ab0eSVincent Donnefort static void trace_remote_reset(struct trace_remote *remote, int cpu) 143*9af4ab0eSVincent Donnefort { 144*9af4ab0eSVincent Donnefort lockdep_assert_held(&remote->lock); 145*9af4ab0eSVincent Donnefort 146*9af4ab0eSVincent Donnefort if (!trace_remote_loaded(remote)) 147*9af4ab0eSVincent Donnefort return; 148*9af4ab0eSVincent Donnefort 149*9af4ab0eSVincent Donnefort if (cpu == RING_BUFFER_ALL_CPUS) 150*9af4ab0eSVincent Donnefort ring_buffer_reset(remote->trace_buffer); 151*9af4ab0eSVincent Donnefort else 152*9af4ab0eSVincent Donnefort ring_buffer_reset_cpu(remote->trace_buffer, cpu); 153*9af4ab0eSVincent Donnefort 154*9af4ab0eSVincent Donnefort trace_remote_try_unload(remote); 155*9af4ab0eSVincent Donnefort } 156*9af4ab0eSVincent Donnefort 15796e43537SVincent Donnefort static ssize_t 15896e43537SVincent Donnefort tracing_on_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) 15996e43537SVincent Donnefort { 16096e43537SVincent Donnefort struct trace_remote *remote = filp->private_data; 16196e43537SVincent Donnefort unsigned long val; 16296e43537SVincent Donnefort int ret; 16396e43537SVincent Donnefort 16496e43537SVincent Donnefort ret = kstrtoul_from_user(ubuf, cnt, 10, &val); 16596e43537SVincent Donnefort if (ret) 16696e43537SVincent Donnefort return ret; 16796e43537SVincent Donnefort 16896e43537SVincent Donnefort guard(mutex)(&remote->lock); 16996e43537SVincent Donnefort 17096e43537SVincent Donnefort ret = val ? trace_remote_enable_tracing(remote) : trace_remote_disable_tracing(remote); 17196e43537SVincent Donnefort if (ret) 17296e43537SVincent Donnefort return ret; 17396e43537SVincent Donnefort 17496e43537SVincent Donnefort return cnt; 17596e43537SVincent Donnefort } 17696e43537SVincent Donnefort static int tracing_on_show(struct seq_file *s, void *unused) 17796e43537SVincent Donnefort { 17896e43537SVincent Donnefort struct trace_remote *remote = s->private; 17996e43537SVincent Donnefort 18096e43537SVincent Donnefort seq_printf(s, "%d\n", remote->tracing_on); 18196e43537SVincent Donnefort 18296e43537SVincent Donnefort return 0; 18396e43537SVincent Donnefort } 18496e43537SVincent Donnefort DEFINE_SHOW_STORE_ATTRIBUTE(tracing_on); 18596e43537SVincent Donnefort 18696e43537SVincent Donnefort static ssize_t buffer_size_kb_write(struct file *filp, const char __user *ubuf, size_t cnt, 18796e43537SVincent Donnefort loff_t *ppos) 18896e43537SVincent Donnefort { 18996e43537SVincent Donnefort struct trace_remote *remote = filp->private_data; 19096e43537SVincent Donnefort unsigned long val; 19196e43537SVincent Donnefort int ret; 19296e43537SVincent Donnefort 19396e43537SVincent Donnefort ret = kstrtoul_from_user(ubuf, cnt, 10, &val); 19496e43537SVincent Donnefort if (ret) 19596e43537SVincent Donnefort return ret; 19696e43537SVincent Donnefort 19796e43537SVincent Donnefort /* KiB to Bytes */ 19896e43537SVincent Donnefort if (!val || check_shl_overflow(val, 10, &val)) 19996e43537SVincent Donnefort return -EINVAL; 20096e43537SVincent Donnefort 20196e43537SVincent Donnefort guard(mutex)(&remote->lock); 20296e43537SVincent Donnefort 20396e43537SVincent Donnefort if (trace_remote_loaded(remote)) 20496e43537SVincent Donnefort return -EBUSY; 20596e43537SVincent Donnefort 20696e43537SVincent Donnefort remote->trace_buffer_size = val; 20796e43537SVincent Donnefort 20896e43537SVincent Donnefort return cnt; 20996e43537SVincent Donnefort } 21096e43537SVincent Donnefort 21196e43537SVincent Donnefort static int buffer_size_kb_show(struct seq_file *s, void *unused) 21296e43537SVincent Donnefort { 21396e43537SVincent Donnefort struct trace_remote *remote = s->private; 21496e43537SVincent Donnefort 21596e43537SVincent Donnefort seq_printf(s, "%lu (%s)\n", remote->trace_buffer_size >> 10, 21696e43537SVincent Donnefort trace_remote_loaded(remote) ? "loaded" : "unloaded"); 21796e43537SVincent Donnefort 21896e43537SVincent Donnefort return 0; 21996e43537SVincent Donnefort } 22096e43537SVincent Donnefort DEFINE_SHOW_STORE_ATTRIBUTE(buffer_size_kb); 22196e43537SVincent Donnefort 22296e43537SVincent Donnefort static int trace_remote_get(struct trace_remote *remote, int cpu) 22396e43537SVincent Donnefort { 22496e43537SVincent Donnefort int ret; 22596e43537SVincent Donnefort 22696e43537SVincent Donnefort if (remote->nr_readers == UINT_MAX) 22796e43537SVincent Donnefort return -EBUSY; 22896e43537SVincent Donnefort 22996e43537SVincent Donnefort ret = trace_remote_load(remote); 23096e43537SVincent Donnefort if (ret) 23196e43537SVincent Donnefort return ret; 23296e43537SVincent Donnefort 23396e43537SVincent Donnefort remote->nr_readers++; 23496e43537SVincent Donnefort 23596e43537SVincent Donnefort return 0; 23696e43537SVincent Donnefort } 23796e43537SVincent Donnefort 23896e43537SVincent Donnefort static void trace_remote_put(struct trace_remote *remote) 23996e43537SVincent Donnefort { 24096e43537SVincent Donnefort if (WARN_ON(!remote->nr_readers)) 24196e43537SVincent Donnefort return; 24296e43537SVincent Donnefort 24396e43537SVincent Donnefort remote->nr_readers--; 24496e43537SVincent Donnefort if (remote->nr_readers) 24596e43537SVincent Donnefort return; 24696e43537SVincent Donnefort 24796e43537SVincent Donnefort trace_remote_try_unload(remote); 24896e43537SVincent Donnefort } 24996e43537SVincent Donnefort 25096e43537SVincent Donnefort static void __poll_remote(struct work_struct *work) 25196e43537SVincent Donnefort { 25296e43537SVincent Donnefort struct delayed_work *dwork = to_delayed_work(work); 25396e43537SVincent Donnefort struct trace_remote_iterator *iter; 25496e43537SVincent Donnefort 25596e43537SVincent Donnefort iter = container_of(dwork, struct trace_remote_iterator, poll_work); 25696e43537SVincent Donnefort ring_buffer_poll_remote(iter->remote->trace_buffer, iter->cpu); 25796e43537SVincent Donnefort schedule_delayed_work((struct delayed_work *)work, 25896e43537SVincent Donnefort msecs_to_jiffies(iter->remote->poll_ms)); 25996e43537SVincent Donnefort } 26096e43537SVincent Donnefort 26196e43537SVincent Donnefort static struct trace_remote_iterator *trace_remote_iter(struct trace_remote *remote, int cpu) 26296e43537SVincent Donnefort { 26396e43537SVincent Donnefort struct trace_remote_iterator *iter = NULL; 26496e43537SVincent Donnefort int ret; 26596e43537SVincent Donnefort 26696e43537SVincent Donnefort lockdep_assert_held(&remote->lock); 26796e43537SVincent Donnefort 26896e43537SVincent Donnefort 26996e43537SVincent Donnefort ret = trace_remote_get(remote, cpu); 27096e43537SVincent Donnefort if (ret) 27196e43537SVincent Donnefort return ERR_PTR(ret); 27296e43537SVincent Donnefort 27396e43537SVincent Donnefort /* Test the CPU */ 27496e43537SVincent Donnefort ret = ring_buffer_poll_remote(remote->trace_buffer, cpu); 27596e43537SVincent Donnefort if (ret) 27696e43537SVincent Donnefort goto err; 27796e43537SVincent Donnefort 27896e43537SVincent Donnefort iter = kzalloc_obj(*iter); 27996e43537SVincent Donnefort if (iter) { 28096e43537SVincent Donnefort iter->remote = remote; 28196e43537SVincent Donnefort iter->cpu = cpu; 28296e43537SVincent Donnefort trace_seq_init(&iter->seq); 28396e43537SVincent Donnefort INIT_DELAYED_WORK(&iter->poll_work, __poll_remote); 28496e43537SVincent Donnefort schedule_delayed_work(&iter->poll_work, msecs_to_jiffies(remote->poll_ms)); 28596e43537SVincent Donnefort 28696e43537SVincent Donnefort return iter; 28796e43537SVincent Donnefort } 28896e43537SVincent Donnefort ret = -ENOMEM; 28996e43537SVincent Donnefort 29096e43537SVincent Donnefort err: 29196e43537SVincent Donnefort kfree(iter); 29296e43537SVincent Donnefort trace_remote_put(remote); 29396e43537SVincent Donnefort 29496e43537SVincent Donnefort return ERR_PTR(ret); 29596e43537SVincent Donnefort } 29696e43537SVincent Donnefort 29796e43537SVincent Donnefort static void trace_remote_iter_free(struct trace_remote_iterator *iter) 29896e43537SVincent Donnefort { 29996e43537SVincent Donnefort struct trace_remote *remote; 30096e43537SVincent Donnefort 30196e43537SVincent Donnefort if (!iter) 30296e43537SVincent Donnefort return; 30396e43537SVincent Donnefort 30496e43537SVincent Donnefort remote = iter->remote; 30596e43537SVincent Donnefort 30696e43537SVincent Donnefort lockdep_assert_held(&remote->lock); 30796e43537SVincent Donnefort 30896e43537SVincent Donnefort kfree(iter); 30996e43537SVincent Donnefort trace_remote_put(remote); 31096e43537SVincent Donnefort } 31196e43537SVincent Donnefort 31296e43537SVincent Donnefort static bool trace_remote_iter_read_event(struct trace_remote_iterator *iter) 31396e43537SVincent Donnefort { 31496e43537SVincent Donnefort struct trace_buffer *trace_buffer = iter->remote->trace_buffer; 31596e43537SVincent Donnefort int cpu = iter->cpu; 31696e43537SVincent Donnefort 31796e43537SVincent Donnefort if (cpu != RING_BUFFER_ALL_CPUS) { 31896e43537SVincent Donnefort if (ring_buffer_empty_cpu(trace_buffer, cpu)) 31996e43537SVincent Donnefort return false; 32096e43537SVincent Donnefort 32196e43537SVincent Donnefort if (!ring_buffer_peek(trace_buffer, cpu, &iter->ts, &iter->lost_events)) 32296e43537SVincent Donnefort return false; 32396e43537SVincent Donnefort 32496e43537SVincent Donnefort iter->evt_cpu = cpu; 32596e43537SVincent Donnefort return true; 32696e43537SVincent Donnefort } 32796e43537SVincent Donnefort 32896e43537SVincent Donnefort iter->ts = U64_MAX; 32996e43537SVincent Donnefort for_each_possible_cpu(cpu) { 33096e43537SVincent Donnefort unsigned long lost_events; 33196e43537SVincent Donnefort u64 ts; 33296e43537SVincent Donnefort 33396e43537SVincent Donnefort if (ring_buffer_empty_cpu(trace_buffer, cpu)) 33496e43537SVincent Donnefort continue; 33596e43537SVincent Donnefort 33696e43537SVincent Donnefort if (!ring_buffer_peek(trace_buffer, cpu, &ts, &lost_events)) 33796e43537SVincent Donnefort continue; 33896e43537SVincent Donnefort 33996e43537SVincent Donnefort if (ts >= iter->ts) 34096e43537SVincent Donnefort continue; 34196e43537SVincent Donnefort 34296e43537SVincent Donnefort iter->ts = ts; 34396e43537SVincent Donnefort iter->evt_cpu = cpu; 34496e43537SVincent Donnefort iter->lost_events = lost_events; 34596e43537SVincent Donnefort } 34696e43537SVincent Donnefort 34796e43537SVincent Donnefort return iter->ts != U64_MAX; 34896e43537SVincent Donnefort } 34996e43537SVincent Donnefort 35096e43537SVincent Donnefort static int trace_remote_iter_print_event(struct trace_remote_iterator *iter) 35196e43537SVincent Donnefort { 35296e43537SVincent Donnefort unsigned long usecs_rem; 35396e43537SVincent Donnefort u64 ts = iter->ts; 35496e43537SVincent Donnefort 35596e43537SVincent Donnefort if (iter->lost_events) 35696e43537SVincent Donnefort trace_seq_printf(&iter->seq, "CPU:%d [LOST %lu EVENTS]\n", 35796e43537SVincent Donnefort iter->evt_cpu, iter->lost_events); 35896e43537SVincent Donnefort 35996e43537SVincent Donnefort do_div(ts, 1000); 36096e43537SVincent Donnefort usecs_rem = do_div(ts, USEC_PER_SEC); 36196e43537SVincent Donnefort 36296e43537SVincent Donnefort trace_seq_printf(&iter->seq, "[%03d]\t%5llu.%06lu: ", iter->evt_cpu, 36396e43537SVincent Donnefort ts, usecs_rem); 36496e43537SVincent Donnefort 36596e43537SVincent Donnefort return trace_seq_has_overflowed(&iter->seq) ? -EOVERFLOW : 0; 36696e43537SVincent Donnefort } 36796e43537SVincent Donnefort 36896e43537SVincent Donnefort static int trace_pipe_open(struct inode *inode, struct file *filp) 36996e43537SVincent Donnefort { 37096e43537SVincent Donnefort struct trace_remote *remote = inode->i_private; 37196e43537SVincent Donnefort struct trace_remote_iterator *iter; 37296e43537SVincent Donnefort int cpu = RING_BUFFER_ALL_CPUS; 37396e43537SVincent Donnefort 37496e43537SVincent Donnefort if (inode->i_cdev) 37596e43537SVincent Donnefort cpu = (long)inode->i_cdev - 1; 37696e43537SVincent Donnefort 37796e43537SVincent Donnefort guard(mutex)(&remote->lock); 37896e43537SVincent Donnefort iter = trace_remote_iter(remote, cpu); 37996e43537SVincent Donnefort filp->private_data = iter; 38096e43537SVincent Donnefort 38196e43537SVincent Donnefort return IS_ERR(iter) ? PTR_ERR(iter) : 0; 38296e43537SVincent Donnefort } 38396e43537SVincent Donnefort 38496e43537SVincent Donnefort static int trace_pipe_release(struct inode *inode, struct file *filp) 38596e43537SVincent Donnefort { 38696e43537SVincent Donnefort struct trace_remote_iterator *iter = filp->private_data; 38796e43537SVincent Donnefort struct trace_remote *remote = iter->remote; 38896e43537SVincent Donnefort 38996e43537SVincent Donnefort guard(mutex)(&remote->lock); 39096e43537SVincent Donnefort 39196e43537SVincent Donnefort trace_remote_iter_free(iter); 39296e43537SVincent Donnefort 39396e43537SVincent Donnefort return 0; 39496e43537SVincent Donnefort } 39596e43537SVincent Donnefort 39696e43537SVincent Donnefort static ssize_t trace_pipe_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) 39796e43537SVincent Donnefort { 39896e43537SVincent Donnefort struct trace_remote_iterator *iter = filp->private_data; 39996e43537SVincent Donnefort struct trace_buffer *trace_buffer = iter->remote->trace_buffer; 40096e43537SVincent Donnefort int ret; 40196e43537SVincent Donnefort 40296e43537SVincent Donnefort copy_to_user: 40396e43537SVincent Donnefort ret = trace_seq_to_user(&iter->seq, ubuf, cnt); 40496e43537SVincent Donnefort if (ret != -EBUSY) 40596e43537SVincent Donnefort return ret; 40696e43537SVincent Donnefort 40796e43537SVincent Donnefort trace_seq_init(&iter->seq); 40896e43537SVincent Donnefort 40996e43537SVincent Donnefort ret = ring_buffer_wait(trace_buffer, iter->cpu, 0, NULL, NULL); 41096e43537SVincent Donnefort if (ret < 0) 41196e43537SVincent Donnefort return ret; 41296e43537SVincent Donnefort 41396e43537SVincent Donnefort while (trace_remote_iter_read_event(iter)) { 41496e43537SVincent Donnefort int prev_len = iter->seq.seq.len; 41596e43537SVincent Donnefort 41696e43537SVincent Donnefort if (trace_remote_iter_print_event(iter)) { 41796e43537SVincent Donnefort iter->seq.seq.len = prev_len; 41896e43537SVincent Donnefort break; 41996e43537SVincent Donnefort } 42096e43537SVincent Donnefort 42196e43537SVincent Donnefort ring_buffer_consume(trace_buffer, iter->evt_cpu, NULL, NULL); 42296e43537SVincent Donnefort } 42396e43537SVincent Donnefort 42496e43537SVincent Donnefort goto copy_to_user; 42596e43537SVincent Donnefort } 42696e43537SVincent Donnefort 42796e43537SVincent Donnefort static const struct file_operations trace_pipe_fops = { 42896e43537SVincent Donnefort .open = trace_pipe_open, 42996e43537SVincent Donnefort .read = trace_pipe_read, 43096e43537SVincent Donnefort .release = trace_pipe_release, 43196e43537SVincent Donnefort }; 43296e43537SVincent Donnefort 433*9af4ab0eSVincent Donnefort static ssize_t trace_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) 434*9af4ab0eSVincent Donnefort { 435*9af4ab0eSVincent Donnefort struct inode *inode = file_inode(filp); 436*9af4ab0eSVincent Donnefort struct trace_remote *remote = inode->i_private; 437*9af4ab0eSVincent Donnefort int cpu = RING_BUFFER_ALL_CPUS; 438*9af4ab0eSVincent Donnefort 439*9af4ab0eSVincent Donnefort if (inode->i_cdev) 440*9af4ab0eSVincent Donnefort cpu = (long)inode->i_cdev - 1; 441*9af4ab0eSVincent Donnefort 442*9af4ab0eSVincent Donnefort guard(mutex)(&remote->lock); 443*9af4ab0eSVincent Donnefort 444*9af4ab0eSVincent Donnefort trace_remote_reset(remote, cpu); 445*9af4ab0eSVincent Donnefort 446*9af4ab0eSVincent Donnefort return cnt; 447*9af4ab0eSVincent Donnefort } 448*9af4ab0eSVincent Donnefort 449*9af4ab0eSVincent Donnefort static const struct file_operations trace_fops = { 450*9af4ab0eSVincent Donnefort .write = trace_write, 451*9af4ab0eSVincent Donnefort }; 452*9af4ab0eSVincent Donnefort 45396e43537SVincent Donnefort static int trace_remote_init_tracefs(const char *name, struct trace_remote *remote) 45496e43537SVincent Donnefort { 45596e43537SVincent Donnefort struct dentry *remote_d, *percpu_d, *d; 45696e43537SVincent Donnefort static struct dentry *root; 45796e43537SVincent Donnefort static DEFINE_MUTEX(lock); 45896e43537SVincent Donnefort bool root_inited = false; 45996e43537SVincent Donnefort int cpu; 46096e43537SVincent Donnefort 46196e43537SVincent Donnefort guard(mutex)(&lock); 46296e43537SVincent Donnefort 46396e43537SVincent Donnefort if (!root) { 46496e43537SVincent Donnefort root = tracefs_create_dir(TRACEFS_DIR, NULL); 46596e43537SVincent Donnefort if (!root) { 46696e43537SVincent Donnefort pr_err("Failed to create tracefs dir "TRACEFS_DIR"\n"); 46796e43537SVincent Donnefort return -ENOMEM; 46896e43537SVincent Donnefort } 46996e43537SVincent Donnefort root_inited = true; 47096e43537SVincent Donnefort } 47196e43537SVincent Donnefort 47296e43537SVincent Donnefort remote_d = tracefs_create_dir(name, root); 47396e43537SVincent Donnefort if (!remote_d) { 47496e43537SVincent Donnefort pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/\n", name); 47596e43537SVincent Donnefort goto err; 47696e43537SVincent Donnefort } 47796e43537SVincent Donnefort 47896e43537SVincent Donnefort d = trace_create_file("tracing_on", TRACEFS_MODE_WRITE, remote_d, remote, &tracing_on_fops); 47996e43537SVincent Donnefort if (!d) 48096e43537SVincent Donnefort goto err; 48196e43537SVincent Donnefort 48296e43537SVincent Donnefort d = trace_create_file("buffer_size_kb", TRACEFS_MODE_WRITE, remote_d, remote, 48396e43537SVincent Donnefort &buffer_size_kb_fops); 48496e43537SVincent Donnefort if (!d) 48596e43537SVincent Donnefort goto err; 48696e43537SVincent Donnefort 48796e43537SVincent Donnefort d = trace_create_file("trace_pipe", TRACEFS_MODE_READ, remote_d, remote, &trace_pipe_fops); 48896e43537SVincent Donnefort if (!d) 48996e43537SVincent Donnefort goto err; 49096e43537SVincent Donnefort 491*9af4ab0eSVincent Donnefort d = trace_create_file("trace", TRACEFS_MODE_WRITE, remote_d, remote, &trace_fops); 492*9af4ab0eSVincent Donnefort if (!d) 493*9af4ab0eSVincent Donnefort goto err; 494*9af4ab0eSVincent Donnefort 49596e43537SVincent Donnefort percpu_d = tracefs_create_dir("per_cpu", remote_d); 49696e43537SVincent Donnefort if (!percpu_d) { 49796e43537SVincent Donnefort pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/per_cpu/\n", name); 49896e43537SVincent Donnefort goto err; 49996e43537SVincent Donnefort } 50096e43537SVincent Donnefort 50196e43537SVincent Donnefort for_each_possible_cpu(cpu) { 50296e43537SVincent Donnefort struct dentry *cpu_d; 50396e43537SVincent Donnefort char cpu_name[16]; 50496e43537SVincent Donnefort 50596e43537SVincent Donnefort snprintf(cpu_name, sizeof(cpu_name), "cpu%d", cpu); 50696e43537SVincent Donnefort cpu_d = tracefs_create_dir(cpu_name, percpu_d); 50796e43537SVincent Donnefort if (!cpu_d) { 50896e43537SVincent Donnefort pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/percpu/cpu%d\n", 50996e43537SVincent Donnefort name, cpu); 51096e43537SVincent Donnefort goto err; 51196e43537SVincent Donnefort } 51296e43537SVincent Donnefort 51396e43537SVincent Donnefort d = trace_create_cpu_file("trace_pipe", TRACEFS_MODE_READ, cpu_d, remote, cpu, 51496e43537SVincent Donnefort &trace_pipe_fops); 51596e43537SVincent Donnefort if (!d) 51696e43537SVincent Donnefort goto err; 517*9af4ab0eSVincent Donnefort 518*9af4ab0eSVincent Donnefort d = trace_create_cpu_file("trace", TRACEFS_MODE_WRITE, cpu_d, remote, cpu, 519*9af4ab0eSVincent Donnefort &trace_fops); 520*9af4ab0eSVincent Donnefort if (!d) 521*9af4ab0eSVincent Donnefort goto err; 52296e43537SVincent Donnefort } 52396e43537SVincent Donnefort 52496e43537SVincent Donnefort return 0; 52596e43537SVincent Donnefort 52696e43537SVincent Donnefort err: 52796e43537SVincent Donnefort if (root_inited) { 52896e43537SVincent Donnefort tracefs_remove(root); 52996e43537SVincent Donnefort root = NULL; 53096e43537SVincent Donnefort } else { 53196e43537SVincent Donnefort tracefs_remove(remote_d); 53296e43537SVincent Donnefort } 53396e43537SVincent Donnefort 53496e43537SVincent Donnefort return -ENOMEM; 53596e43537SVincent Donnefort } 53696e43537SVincent Donnefort 53796e43537SVincent Donnefort /** 53896e43537SVincent Donnefort * trace_remote_register() - Register a Tracefs remote 53996e43537SVincent Donnefort * @name: Name of the remote, used for the Tracefs remotes/ directory. 54096e43537SVincent Donnefort * @cbs: Set of callbacks used to control the remote. 54196e43537SVincent Donnefort * @priv: Private data, passed to each callback from @cbs. 54296e43537SVincent Donnefort * @events: Array of events. &remote_event.name and &remote_event.id must be 54396e43537SVincent Donnefort * filled by the caller. 54496e43537SVincent Donnefort * @nr_events: Number of events in the @events array. 54596e43537SVincent Donnefort * 54696e43537SVincent Donnefort * A trace remote is an entity, outside of the kernel (most likely firmware or 54796e43537SVincent Donnefort * hypervisor) capable of writing events into a Tracefs compatible ring-buffer. 54896e43537SVincent Donnefort * The kernel would then act as a reader. 54996e43537SVincent Donnefort * 55096e43537SVincent Donnefort * The registered remote will be found under the Tracefs directory 55196e43537SVincent Donnefort * remotes/<name>. 55296e43537SVincent Donnefort * 55396e43537SVincent Donnefort * Return: 0 on success, negative error code on failure. 55496e43537SVincent Donnefort */ 55596e43537SVincent Donnefort int trace_remote_register(const char *name, struct trace_remote_callbacks *cbs, void *priv) 55696e43537SVincent Donnefort { 55796e43537SVincent Donnefort struct trace_remote *remote; 55896e43537SVincent Donnefort 55996e43537SVincent Donnefort remote = kzalloc_obj(*remote); 56096e43537SVincent Donnefort if (!remote) 56196e43537SVincent Donnefort return -ENOMEM; 56296e43537SVincent Donnefort 56396e43537SVincent Donnefort remote->cbs = cbs; 56496e43537SVincent Donnefort remote->priv = priv; 56596e43537SVincent Donnefort remote->trace_buffer_size = 7 << 10; 56696e43537SVincent Donnefort remote->poll_ms = 100; 56796e43537SVincent Donnefort mutex_init(&remote->lock); 56896e43537SVincent Donnefort 56996e43537SVincent Donnefort if (trace_remote_init_tracefs(name, remote)) { 57096e43537SVincent Donnefort kfree(remote); 57196e43537SVincent Donnefort return -ENOMEM; 57296e43537SVincent Donnefort } 57396e43537SVincent Donnefort 57496e43537SVincent Donnefort return 0; 57596e43537SVincent Donnefort } 57696e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_register); 57796e43537SVincent Donnefort 57896e43537SVincent Donnefort /** 57996e43537SVincent Donnefort * trace_remote_free_buffer() - Free trace buffer allocated with trace_remote_alloc_buffer() 58096e43537SVincent Donnefort * @desc: Descriptor of the per-CPU ring-buffers, originally filled by 58196e43537SVincent Donnefort * trace_remote_alloc_buffer() 58296e43537SVincent Donnefort * 58396e43537SVincent Donnefort * Most likely called from &trace_remote_callbacks.unload_trace_buffer. 58496e43537SVincent Donnefort */ 58596e43537SVincent Donnefort void trace_remote_free_buffer(struct trace_buffer_desc *desc) 58696e43537SVincent Donnefort { 58796e43537SVincent Donnefort struct ring_buffer_desc *rb_desc; 58896e43537SVincent Donnefort int cpu; 58996e43537SVincent Donnefort 59096e43537SVincent Donnefort for_each_ring_buffer_desc(rb_desc, cpu, desc) { 59196e43537SVincent Donnefort unsigned int id; 59296e43537SVincent Donnefort 59396e43537SVincent Donnefort free_page(rb_desc->meta_va); 59496e43537SVincent Donnefort 59596e43537SVincent Donnefort for (id = 0; id < rb_desc->nr_page_va; id++) 59696e43537SVincent Donnefort free_page(rb_desc->page_va[id]); 59796e43537SVincent Donnefort } 59896e43537SVincent Donnefort } 59996e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_free_buffer); 60096e43537SVincent Donnefort 60196e43537SVincent Donnefort /** 60296e43537SVincent Donnefort * trace_remote_alloc_buffer() - Dynamically allocate a trace buffer 60396e43537SVincent Donnefort * @desc: Uninitialized trace_buffer_desc 60496e43537SVincent Donnefort * @desc_size: Size of the trace_buffer_desc. Must be at least equal to 60596e43537SVincent Donnefort * trace_buffer_desc_size() 60696e43537SVincent Donnefort * @buffer_size: Size in bytes of each per-CPU ring-buffer 60796e43537SVincent Donnefort * @cpumask: CPUs to allocate a ring-buffer for 60896e43537SVincent Donnefort * 60996e43537SVincent Donnefort * Helper to dynamically allocate a set of pages (enough to cover @buffer_size) 61096e43537SVincent Donnefort * for each CPU from @cpumask and fill @desc. Most likely called from 61196e43537SVincent Donnefort * &trace_remote_callbacks.load_trace_buffer. 61296e43537SVincent Donnefort * 61396e43537SVincent Donnefort * Return: 0 on success, negative error code on failure. 61496e43537SVincent Donnefort */ 61596e43537SVincent Donnefort int trace_remote_alloc_buffer(struct trace_buffer_desc *desc, size_t desc_size, size_t buffer_size, 61696e43537SVincent Donnefort const struct cpumask *cpumask) 61796e43537SVincent Donnefort { 61896e43537SVincent Donnefort unsigned int nr_pages = max(DIV_ROUND_UP(buffer_size, PAGE_SIZE), 2UL) + 1; 61996e43537SVincent Donnefort void *desc_end = desc + desc_size; 62096e43537SVincent Donnefort struct ring_buffer_desc *rb_desc; 62196e43537SVincent Donnefort int cpu, ret = -ENOMEM; 62296e43537SVincent Donnefort 62396e43537SVincent Donnefort if (desc_size < struct_size(desc, __data, 0)) 62496e43537SVincent Donnefort return -EINVAL; 62596e43537SVincent Donnefort 62696e43537SVincent Donnefort desc->nr_cpus = 0; 62796e43537SVincent Donnefort desc->struct_len = struct_size(desc, __data, 0); 62896e43537SVincent Donnefort 62996e43537SVincent Donnefort rb_desc = (struct ring_buffer_desc *)&desc->__data[0]; 63096e43537SVincent Donnefort 63196e43537SVincent Donnefort for_each_cpu(cpu, cpumask) { 63296e43537SVincent Donnefort unsigned int id; 63396e43537SVincent Donnefort 63496e43537SVincent Donnefort if ((void *)rb_desc + struct_size(rb_desc, page_va, nr_pages) > desc_end) { 63596e43537SVincent Donnefort ret = -EINVAL; 63696e43537SVincent Donnefort goto err; 63796e43537SVincent Donnefort } 63896e43537SVincent Donnefort 63996e43537SVincent Donnefort rb_desc->cpu = cpu; 64096e43537SVincent Donnefort rb_desc->nr_page_va = 0; 64196e43537SVincent Donnefort rb_desc->meta_va = (unsigned long)__get_free_page(GFP_KERNEL); 64296e43537SVincent Donnefort if (!rb_desc->meta_va) 64396e43537SVincent Donnefort goto err; 64496e43537SVincent Donnefort 64596e43537SVincent Donnefort for (id = 0; id < nr_pages; id++) { 64696e43537SVincent Donnefort rb_desc->page_va[id] = (unsigned long)__get_free_page(GFP_KERNEL); 64796e43537SVincent Donnefort if (!rb_desc->page_va[id]) 64896e43537SVincent Donnefort goto err; 64996e43537SVincent Donnefort 65096e43537SVincent Donnefort rb_desc->nr_page_va++; 65196e43537SVincent Donnefort } 65296e43537SVincent Donnefort desc->nr_cpus++; 65396e43537SVincent Donnefort desc->struct_len += offsetof(struct ring_buffer_desc, page_va); 65496e43537SVincent Donnefort desc->struct_len += struct_size(rb_desc, page_va, rb_desc->nr_page_va); 65596e43537SVincent Donnefort rb_desc = __next_ring_buffer_desc(rb_desc); 65696e43537SVincent Donnefort } 65796e43537SVincent Donnefort 65896e43537SVincent Donnefort return 0; 65996e43537SVincent Donnefort 66096e43537SVincent Donnefort err: 66196e43537SVincent Donnefort trace_remote_free_buffer(desc); 66296e43537SVincent Donnefort return ret; 66396e43537SVincent Donnefort } 66496e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_alloc_buffer); 665