1*96e43537SVincent Donnefort // SPDX-License-Identifier: GPL-2.0 2*96e43537SVincent Donnefort /* 3*96e43537SVincent Donnefort * Copyright (C) 2025 - Google LLC 4*96e43537SVincent Donnefort * Author: Vincent Donnefort <vdonnefort@google.com> 5*96e43537SVincent Donnefort */ 6*96e43537SVincent Donnefort 7*96e43537SVincent Donnefort #include <linux/kstrtox.h> 8*96e43537SVincent Donnefort #include <linux/lockdep.h> 9*96e43537SVincent Donnefort #include <linux/mutex.h> 10*96e43537SVincent Donnefort #include <linux/tracefs.h> 11*96e43537SVincent Donnefort #include <linux/trace_remote.h> 12*96e43537SVincent Donnefort #include <linux/trace_seq.h> 13*96e43537SVincent Donnefort #include <linux/types.h> 14*96e43537SVincent Donnefort 15*96e43537SVincent Donnefort #include "trace.h" 16*96e43537SVincent Donnefort 17*96e43537SVincent Donnefort #define TRACEFS_DIR "remotes" 18*96e43537SVincent Donnefort #define TRACEFS_MODE_WRITE 0640 19*96e43537SVincent Donnefort #define TRACEFS_MODE_READ 0440 20*96e43537SVincent Donnefort 21*96e43537SVincent Donnefort struct trace_remote_iterator { 22*96e43537SVincent Donnefort struct trace_remote *remote; 23*96e43537SVincent Donnefort struct trace_seq seq; 24*96e43537SVincent Donnefort struct delayed_work poll_work; 25*96e43537SVincent Donnefort unsigned long lost_events; 26*96e43537SVincent Donnefort u64 ts; 27*96e43537SVincent Donnefort int cpu; 28*96e43537SVincent Donnefort int evt_cpu; 29*96e43537SVincent Donnefort }; 30*96e43537SVincent Donnefort 31*96e43537SVincent Donnefort struct trace_remote { 32*96e43537SVincent Donnefort struct trace_remote_callbacks *cbs; 33*96e43537SVincent Donnefort void *priv; 34*96e43537SVincent Donnefort struct trace_buffer *trace_buffer; 35*96e43537SVincent Donnefort struct trace_buffer_desc *trace_buffer_desc; 36*96e43537SVincent Donnefort unsigned long trace_buffer_size; 37*96e43537SVincent Donnefort struct ring_buffer_remote rb_remote; 38*96e43537SVincent Donnefort struct mutex lock; 39*96e43537SVincent Donnefort unsigned int nr_readers; 40*96e43537SVincent Donnefort unsigned int poll_ms; 41*96e43537SVincent Donnefort bool tracing_on; 42*96e43537SVincent Donnefort }; 43*96e43537SVincent Donnefort 44*96e43537SVincent Donnefort static bool trace_remote_loaded(struct trace_remote *remote) 45*96e43537SVincent Donnefort { 46*96e43537SVincent Donnefort return !!remote->trace_buffer; 47*96e43537SVincent Donnefort } 48*96e43537SVincent Donnefort 49*96e43537SVincent Donnefort static int trace_remote_load(struct trace_remote *remote) 50*96e43537SVincent Donnefort { 51*96e43537SVincent Donnefort struct ring_buffer_remote *rb_remote = &remote->rb_remote; 52*96e43537SVincent Donnefort struct trace_buffer_desc *desc; 53*96e43537SVincent Donnefort 54*96e43537SVincent Donnefort lockdep_assert_held(&remote->lock); 55*96e43537SVincent Donnefort 56*96e43537SVincent Donnefort if (trace_remote_loaded(remote)) 57*96e43537SVincent Donnefort return 0; 58*96e43537SVincent Donnefort 59*96e43537SVincent Donnefort desc = remote->cbs->load_trace_buffer(remote->trace_buffer_size, remote->priv); 60*96e43537SVincent Donnefort if (IS_ERR(desc)) 61*96e43537SVincent Donnefort return PTR_ERR(desc); 62*96e43537SVincent Donnefort 63*96e43537SVincent Donnefort rb_remote->desc = desc; 64*96e43537SVincent Donnefort rb_remote->swap_reader_page = remote->cbs->swap_reader_page; 65*96e43537SVincent Donnefort rb_remote->priv = remote->priv; 66*96e43537SVincent Donnefort remote->trace_buffer = ring_buffer_alloc_remote(rb_remote); 67*96e43537SVincent Donnefort if (!remote->trace_buffer) { 68*96e43537SVincent Donnefort remote->cbs->unload_trace_buffer(desc, remote->priv); 69*96e43537SVincent Donnefort return -ENOMEM; 70*96e43537SVincent Donnefort } 71*96e43537SVincent Donnefort 72*96e43537SVincent Donnefort remote->trace_buffer_desc = desc; 73*96e43537SVincent Donnefort 74*96e43537SVincent Donnefort return 0; 75*96e43537SVincent Donnefort } 76*96e43537SVincent Donnefort 77*96e43537SVincent Donnefort static void trace_remote_try_unload(struct trace_remote *remote) 78*96e43537SVincent Donnefort { 79*96e43537SVincent Donnefort lockdep_assert_held(&remote->lock); 80*96e43537SVincent Donnefort 81*96e43537SVincent Donnefort if (!trace_remote_loaded(remote)) 82*96e43537SVincent Donnefort return; 83*96e43537SVincent Donnefort 84*96e43537SVincent Donnefort /* The buffer is being read or writable */ 85*96e43537SVincent Donnefort if (remote->nr_readers || remote->tracing_on) 86*96e43537SVincent Donnefort return; 87*96e43537SVincent Donnefort 88*96e43537SVincent Donnefort /* The buffer has readable data */ 89*96e43537SVincent Donnefort if (!ring_buffer_empty(remote->trace_buffer)) 90*96e43537SVincent Donnefort return; 91*96e43537SVincent Donnefort 92*96e43537SVincent Donnefort ring_buffer_free(remote->trace_buffer); 93*96e43537SVincent Donnefort remote->trace_buffer = NULL; 94*96e43537SVincent Donnefort remote->cbs->unload_trace_buffer(remote->trace_buffer_desc, remote->priv); 95*96e43537SVincent Donnefort } 96*96e43537SVincent Donnefort 97*96e43537SVincent Donnefort static int trace_remote_enable_tracing(struct trace_remote *remote) 98*96e43537SVincent Donnefort { 99*96e43537SVincent Donnefort int ret; 100*96e43537SVincent Donnefort 101*96e43537SVincent Donnefort lockdep_assert_held(&remote->lock); 102*96e43537SVincent Donnefort 103*96e43537SVincent Donnefort if (remote->tracing_on) 104*96e43537SVincent Donnefort return 0; 105*96e43537SVincent Donnefort 106*96e43537SVincent Donnefort ret = trace_remote_load(remote); 107*96e43537SVincent Donnefort if (ret) 108*96e43537SVincent Donnefort return ret; 109*96e43537SVincent Donnefort 110*96e43537SVincent Donnefort ret = remote->cbs->enable_tracing(true, remote->priv); 111*96e43537SVincent Donnefort if (ret) { 112*96e43537SVincent Donnefort trace_remote_try_unload(remote); 113*96e43537SVincent Donnefort return ret; 114*96e43537SVincent Donnefort } 115*96e43537SVincent Donnefort 116*96e43537SVincent Donnefort remote->tracing_on = true; 117*96e43537SVincent Donnefort 118*96e43537SVincent Donnefort return 0; 119*96e43537SVincent Donnefort } 120*96e43537SVincent Donnefort 121*96e43537SVincent Donnefort static int trace_remote_disable_tracing(struct trace_remote *remote) 122*96e43537SVincent Donnefort { 123*96e43537SVincent Donnefort int ret; 124*96e43537SVincent Donnefort 125*96e43537SVincent Donnefort lockdep_assert_held(&remote->lock); 126*96e43537SVincent Donnefort 127*96e43537SVincent Donnefort if (!remote->tracing_on) 128*96e43537SVincent Donnefort return 0; 129*96e43537SVincent Donnefort 130*96e43537SVincent Donnefort ret = remote->cbs->enable_tracing(false, remote->priv); 131*96e43537SVincent Donnefort if (ret) 132*96e43537SVincent Donnefort return ret; 133*96e43537SVincent Donnefort 134*96e43537SVincent Donnefort ring_buffer_poll_remote(remote->trace_buffer, RING_BUFFER_ALL_CPUS); 135*96e43537SVincent Donnefort remote->tracing_on = false; 136*96e43537SVincent Donnefort trace_remote_try_unload(remote); 137*96e43537SVincent Donnefort 138*96e43537SVincent Donnefort return 0; 139*96e43537SVincent Donnefort } 140*96e43537SVincent Donnefort 141*96e43537SVincent Donnefort static ssize_t 142*96e43537SVincent Donnefort tracing_on_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos) 143*96e43537SVincent Donnefort { 144*96e43537SVincent Donnefort struct trace_remote *remote = filp->private_data; 145*96e43537SVincent Donnefort unsigned long val; 146*96e43537SVincent Donnefort int ret; 147*96e43537SVincent Donnefort 148*96e43537SVincent Donnefort ret = kstrtoul_from_user(ubuf, cnt, 10, &val); 149*96e43537SVincent Donnefort if (ret) 150*96e43537SVincent Donnefort return ret; 151*96e43537SVincent Donnefort 152*96e43537SVincent Donnefort guard(mutex)(&remote->lock); 153*96e43537SVincent Donnefort 154*96e43537SVincent Donnefort ret = val ? trace_remote_enable_tracing(remote) : trace_remote_disable_tracing(remote); 155*96e43537SVincent Donnefort if (ret) 156*96e43537SVincent Donnefort return ret; 157*96e43537SVincent Donnefort 158*96e43537SVincent Donnefort return cnt; 159*96e43537SVincent Donnefort } 160*96e43537SVincent Donnefort static int tracing_on_show(struct seq_file *s, void *unused) 161*96e43537SVincent Donnefort { 162*96e43537SVincent Donnefort struct trace_remote *remote = s->private; 163*96e43537SVincent Donnefort 164*96e43537SVincent Donnefort seq_printf(s, "%d\n", remote->tracing_on); 165*96e43537SVincent Donnefort 166*96e43537SVincent Donnefort return 0; 167*96e43537SVincent Donnefort } 168*96e43537SVincent Donnefort DEFINE_SHOW_STORE_ATTRIBUTE(tracing_on); 169*96e43537SVincent Donnefort 170*96e43537SVincent Donnefort static ssize_t buffer_size_kb_write(struct file *filp, const char __user *ubuf, size_t cnt, 171*96e43537SVincent Donnefort loff_t *ppos) 172*96e43537SVincent Donnefort { 173*96e43537SVincent Donnefort struct trace_remote *remote = filp->private_data; 174*96e43537SVincent Donnefort unsigned long val; 175*96e43537SVincent Donnefort int ret; 176*96e43537SVincent Donnefort 177*96e43537SVincent Donnefort ret = kstrtoul_from_user(ubuf, cnt, 10, &val); 178*96e43537SVincent Donnefort if (ret) 179*96e43537SVincent Donnefort return ret; 180*96e43537SVincent Donnefort 181*96e43537SVincent Donnefort /* KiB to Bytes */ 182*96e43537SVincent Donnefort if (!val || check_shl_overflow(val, 10, &val)) 183*96e43537SVincent Donnefort return -EINVAL; 184*96e43537SVincent Donnefort 185*96e43537SVincent Donnefort guard(mutex)(&remote->lock); 186*96e43537SVincent Donnefort 187*96e43537SVincent Donnefort if (trace_remote_loaded(remote)) 188*96e43537SVincent Donnefort return -EBUSY; 189*96e43537SVincent Donnefort 190*96e43537SVincent Donnefort remote->trace_buffer_size = val; 191*96e43537SVincent Donnefort 192*96e43537SVincent Donnefort return cnt; 193*96e43537SVincent Donnefort } 194*96e43537SVincent Donnefort 195*96e43537SVincent Donnefort static int buffer_size_kb_show(struct seq_file *s, void *unused) 196*96e43537SVincent Donnefort { 197*96e43537SVincent Donnefort struct trace_remote *remote = s->private; 198*96e43537SVincent Donnefort 199*96e43537SVincent Donnefort seq_printf(s, "%lu (%s)\n", remote->trace_buffer_size >> 10, 200*96e43537SVincent Donnefort trace_remote_loaded(remote) ? "loaded" : "unloaded"); 201*96e43537SVincent Donnefort 202*96e43537SVincent Donnefort return 0; 203*96e43537SVincent Donnefort } 204*96e43537SVincent Donnefort DEFINE_SHOW_STORE_ATTRIBUTE(buffer_size_kb); 205*96e43537SVincent Donnefort 206*96e43537SVincent Donnefort static int trace_remote_get(struct trace_remote *remote, int cpu) 207*96e43537SVincent Donnefort { 208*96e43537SVincent Donnefort int ret; 209*96e43537SVincent Donnefort 210*96e43537SVincent Donnefort if (remote->nr_readers == UINT_MAX) 211*96e43537SVincent Donnefort return -EBUSY; 212*96e43537SVincent Donnefort 213*96e43537SVincent Donnefort ret = trace_remote_load(remote); 214*96e43537SVincent Donnefort if (ret) 215*96e43537SVincent Donnefort return ret; 216*96e43537SVincent Donnefort 217*96e43537SVincent Donnefort remote->nr_readers++; 218*96e43537SVincent Donnefort 219*96e43537SVincent Donnefort return 0; 220*96e43537SVincent Donnefort } 221*96e43537SVincent Donnefort 222*96e43537SVincent Donnefort static void trace_remote_put(struct trace_remote *remote) 223*96e43537SVincent Donnefort { 224*96e43537SVincent Donnefort if (WARN_ON(!remote->nr_readers)) 225*96e43537SVincent Donnefort return; 226*96e43537SVincent Donnefort 227*96e43537SVincent Donnefort remote->nr_readers--; 228*96e43537SVincent Donnefort if (remote->nr_readers) 229*96e43537SVincent Donnefort return; 230*96e43537SVincent Donnefort 231*96e43537SVincent Donnefort trace_remote_try_unload(remote); 232*96e43537SVincent Donnefort } 233*96e43537SVincent Donnefort 234*96e43537SVincent Donnefort static void __poll_remote(struct work_struct *work) 235*96e43537SVincent Donnefort { 236*96e43537SVincent Donnefort struct delayed_work *dwork = to_delayed_work(work); 237*96e43537SVincent Donnefort struct trace_remote_iterator *iter; 238*96e43537SVincent Donnefort 239*96e43537SVincent Donnefort iter = container_of(dwork, struct trace_remote_iterator, poll_work); 240*96e43537SVincent Donnefort ring_buffer_poll_remote(iter->remote->trace_buffer, iter->cpu); 241*96e43537SVincent Donnefort schedule_delayed_work((struct delayed_work *)work, 242*96e43537SVincent Donnefort msecs_to_jiffies(iter->remote->poll_ms)); 243*96e43537SVincent Donnefort } 244*96e43537SVincent Donnefort 245*96e43537SVincent Donnefort static struct trace_remote_iterator *trace_remote_iter(struct trace_remote *remote, int cpu) 246*96e43537SVincent Donnefort { 247*96e43537SVincent Donnefort struct trace_remote_iterator *iter = NULL; 248*96e43537SVincent Donnefort int ret; 249*96e43537SVincent Donnefort 250*96e43537SVincent Donnefort lockdep_assert_held(&remote->lock); 251*96e43537SVincent Donnefort 252*96e43537SVincent Donnefort 253*96e43537SVincent Donnefort ret = trace_remote_get(remote, cpu); 254*96e43537SVincent Donnefort if (ret) 255*96e43537SVincent Donnefort return ERR_PTR(ret); 256*96e43537SVincent Donnefort 257*96e43537SVincent Donnefort /* Test the CPU */ 258*96e43537SVincent Donnefort ret = ring_buffer_poll_remote(remote->trace_buffer, cpu); 259*96e43537SVincent Donnefort if (ret) 260*96e43537SVincent Donnefort goto err; 261*96e43537SVincent Donnefort 262*96e43537SVincent Donnefort iter = kzalloc_obj(*iter); 263*96e43537SVincent Donnefort if (iter) { 264*96e43537SVincent Donnefort iter->remote = remote; 265*96e43537SVincent Donnefort iter->cpu = cpu; 266*96e43537SVincent Donnefort trace_seq_init(&iter->seq); 267*96e43537SVincent Donnefort INIT_DELAYED_WORK(&iter->poll_work, __poll_remote); 268*96e43537SVincent Donnefort schedule_delayed_work(&iter->poll_work, msecs_to_jiffies(remote->poll_ms)); 269*96e43537SVincent Donnefort 270*96e43537SVincent Donnefort return iter; 271*96e43537SVincent Donnefort } 272*96e43537SVincent Donnefort ret = -ENOMEM; 273*96e43537SVincent Donnefort 274*96e43537SVincent Donnefort err: 275*96e43537SVincent Donnefort kfree(iter); 276*96e43537SVincent Donnefort trace_remote_put(remote); 277*96e43537SVincent Donnefort 278*96e43537SVincent Donnefort return ERR_PTR(ret); 279*96e43537SVincent Donnefort } 280*96e43537SVincent Donnefort 281*96e43537SVincent Donnefort static void trace_remote_iter_free(struct trace_remote_iterator *iter) 282*96e43537SVincent Donnefort { 283*96e43537SVincent Donnefort struct trace_remote *remote; 284*96e43537SVincent Donnefort 285*96e43537SVincent Donnefort if (!iter) 286*96e43537SVincent Donnefort return; 287*96e43537SVincent Donnefort 288*96e43537SVincent Donnefort remote = iter->remote; 289*96e43537SVincent Donnefort 290*96e43537SVincent Donnefort lockdep_assert_held(&remote->lock); 291*96e43537SVincent Donnefort 292*96e43537SVincent Donnefort kfree(iter); 293*96e43537SVincent Donnefort trace_remote_put(remote); 294*96e43537SVincent Donnefort } 295*96e43537SVincent Donnefort 296*96e43537SVincent Donnefort static bool trace_remote_iter_read_event(struct trace_remote_iterator *iter) 297*96e43537SVincent Donnefort { 298*96e43537SVincent Donnefort struct trace_buffer *trace_buffer = iter->remote->trace_buffer; 299*96e43537SVincent Donnefort int cpu = iter->cpu; 300*96e43537SVincent Donnefort 301*96e43537SVincent Donnefort if (cpu != RING_BUFFER_ALL_CPUS) { 302*96e43537SVincent Donnefort if (ring_buffer_empty_cpu(trace_buffer, cpu)) 303*96e43537SVincent Donnefort return false; 304*96e43537SVincent Donnefort 305*96e43537SVincent Donnefort if (!ring_buffer_peek(trace_buffer, cpu, &iter->ts, &iter->lost_events)) 306*96e43537SVincent Donnefort return false; 307*96e43537SVincent Donnefort 308*96e43537SVincent Donnefort iter->evt_cpu = cpu; 309*96e43537SVincent Donnefort return true; 310*96e43537SVincent Donnefort } 311*96e43537SVincent Donnefort 312*96e43537SVincent Donnefort iter->ts = U64_MAX; 313*96e43537SVincent Donnefort for_each_possible_cpu(cpu) { 314*96e43537SVincent Donnefort unsigned long lost_events; 315*96e43537SVincent Donnefort u64 ts; 316*96e43537SVincent Donnefort 317*96e43537SVincent Donnefort if (ring_buffer_empty_cpu(trace_buffer, cpu)) 318*96e43537SVincent Donnefort continue; 319*96e43537SVincent Donnefort 320*96e43537SVincent Donnefort if (!ring_buffer_peek(trace_buffer, cpu, &ts, &lost_events)) 321*96e43537SVincent Donnefort continue; 322*96e43537SVincent Donnefort 323*96e43537SVincent Donnefort if (ts >= iter->ts) 324*96e43537SVincent Donnefort continue; 325*96e43537SVincent Donnefort 326*96e43537SVincent Donnefort iter->ts = ts; 327*96e43537SVincent Donnefort iter->evt_cpu = cpu; 328*96e43537SVincent Donnefort iter->lost_events = lost_events; 329*96e43537SVincent Donnefort } 330*96e43537SVincent Donnefort 331*96e43537SVincent Donnefort return iter->ts != U64_MAX; 332*96e43537SVincent Donnefort } 333*96e43537SVincent Donnefort 334*96e43537SVincent Donnefort static int trace_remote_iter_print_event(struct trace_remote_iterator *iter) 335*96e43537SVincent Donnefort { 336*96e43537SVincent Donnefort unsigned long usecs_rem; 337*96e43537SVincent Donnefort u64 ts = iter->ts; 338*96e43537SVincent Donnefort 339*96e43537SVincent Donnefort if (iter->lost_events) 340*96e43537SVincent Donnefort trace_seq_printf(&iter->seq, "CPU:%d [LOST %lu EVENTS]\n", 341*96e43537SVincent Donnefort iter->evt_cpu, iter->lost_events); 342*96e43537SVincent Donnefort 343*96e43537SVincent Donnefort do_div(ts, 1000); 344*96e43537SVincent Donnefort usecs_rem = do_div(ts, USEC_PER_SEC); 345*96e43537SVincent Donnefort 346*96e43537SVincent Donnefort trace_seq_printf(&iter->seq, "[%03d]\t%5llu.%06lu: ", iter->evt_cpu, 347*96e43537SVincent Donnefort ts, usecs_rem); 348*96e43537SVincent Donnefort 349*96e43537SVincent Donnefort return trace_seq_has_overflowed(&iter->seq) ? -EOVERFLOW : 0; 350*96e43537SVincent Donnefort } 351*96e43537SVincent Donnefort 352*96e43537SVincent Donnefort static int trace_pipe_open(struct inode *inode, struct file *filp) 353*96e43537SVincent Donnefort { 354*96e43537SVincent Donnefort struct trace_remote *remote = inode->i_private; 355*96e43537SVincent Donnefort struct trace_remote_iterator *iter; 356*96e43537SVincent Donnefort int cpu = RING_BUFFER_ALL_CPUS; 357*96e43537SVincent Donnefort 358*96e43537SVincent Donnefort if (inode->i_cdev) 359*96e43537SVincent Donnefort cpu = (long)inode->i_cdev - 1; 360*96e43537SVincent Donnefort 361*96e43537SVincent Donnefort guard(mutex)(&remote->lock); 362*96e43537SVincent Donnefort iter = trace_remote_iter(remote, cpu); 363*96e43537SVincent Donnefort filp->private_data = iter; 364*96e43537SVincent Donnefort 365*96e43537SVincent Donnefort return IS_ERR(iter) ? PTR_ERR(iter) : 0; 366*96e43537SVincent Donnefort } 367*96e43537SVincent Donnefort 368*96e43537SVincent Donnefort static int trace_pipe_release(struct inode *inode, struct file *filp) 369*96e43537SVincent Donnefort { 370*96e43537SVincent Donnefort struct trace_remote_iterator *iter = filp->private_data; 371*96e43537SVincent Donnefort struct trace_remote *remote = iter->remote; 372*96e43537SVincent Donnefort 373*96e43537SVincent Donnefort guard(mutex)(&remote->lock); 374*96e43537SVincent Donnefort 375*96e43537SVincent Donnefort trace_remote_iter_free(iter); 376*96e43537SVincent Donnefort 377*96e43537SVincent Donnefort return 0; 378*96e43537SVincent Donnefort } 379*96e43537SVincent Donnefort 380*96e43537SVincent Donnefort static ssize_t trace_pipe_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) 381*96e43537SVincent Donnefort { 382*96e43537SVincent Donnefort struct trace_remote_iterator *iter = filp->private_data; 383*96e43537SVincent Donnefort struct trace_buffer *trace_buffer = iter->remote->trace_buffer; 384*96e43537SVincent Donnefort int ret; 385*96e43537SVincent Donnefort 386*96e43537SVincent Donnefort copy_to_user: 387*96e43537SVincent Donnefort ret = trace_seq_to_user(&iter->seq, ubuf, cnt); 388*96e43537SVincent Donnefort if (ret != -EBUSY) 389*96e43537SVincent Donnefort return ret; 390*96e43537SVincent Donnefort 391*96e43537SVincent Donnefort trace_seq_init(&iter->seq); 392*96e43537SVincent Donnefort 393*96e43537SVincent Donnefort ret = ring_buffer_wait(trace_buffer, iter->cpu, 0, NULL, NULL); 394*96e43537SVincent Donnefort if (ret < 0) 395*96e43537SVincent Donnefort return ret; 396*96e43537SVincent Donnefort 397*96e43537SVincent Donnefort while (trace_remote_iter_read_event(iter)) { 398*96e43537SVincent Donnefort int prev_len = iter->seq.seq.len; 399*96e43537SVincent Donnefort 400*96e43537SVincent Donnefort if (trace_remote_iter_print_event(iter)) { 401*96e43537SVincent Donnefort iter->seq.seq.len = prev_len; 402*96e43537SVincent Donnefort break; 403*96e43537SVincent Donnefort } 404*96e43537SVincent Donnefort 405*96e43537SVincent Donnefort ring_buffer_consume(trace_buffer, iter->evt_cpu, NULL, NULL); 406*96e43537SVincent Donnefort } 407*96e43537SVincent Donnefort 408*96e43537SVincent Donnefort goto copy_to_user; 409*96e43537SVincent Donnefort } 410*96e43537SVincent Donnefort 411*96e43537SVincent Donnefort static const struct file_operations trace_pipe_fops = { 412*96e43537SVincent Donnefort .open = trace_pipe_open, 413*96e43537SVincent Donnefort .read = trace_pipe_read, 414*96e43537SVincent Donnefort .release = trace_pipe_release, 415*96e43537SVincent Donnefort }; 416*96e43537SVincent Donnefort 417*96e43537SVincent Donnefort static int trace_remote_init_tracefs(const char *name, struct trace_remote *remote) 418*96e43537SVincent Donnefort { 419*96e43537SVincent Donnefort struct dentry *remote_d, *percpu_d, *d; 420*96e43537SVincent Donnefort static struct dentry *root; 421*96e43537SVincent Donnefort static DEFINE_MUTEX(lock); 422*96e43537SVincent Donnefort bool root_inited = false; 423*96e43537SVincent Donnefort int cpu; 424*96e43537SVincent Donnefort 425*96e43537SVincent Donnefort guard(mutex)(&lock); 426*96e43537SVincent Donnefort 427*96e43537SVincent Donnefort if (!root) { 428*96e43537SVincent Donnefort root = tracefs_create_dir(TRACEFS_DIR, NULL); 429*96e43537SVincent Donnefort if (!root) { 430*96e43537SVincent Donnefort pr_err("Failed to create tracefs dir "TRACEFS_DIR"\n"); 431*96e43537SVincent Donnefort return -ENOMEM; 432*96e43537SVincent Donnefort } 433*96e43537SVincent Donnefort root_inited = true; 434*96e43537SVincent Donnefort } 435*96e43537SVincent Donnefort 436*96e43537SVincent Donnefort remote_d = tracefs_create_dir(name, root); 437*96e43537SVincent Donnefort if (!remote_d) { 438*96e43537SVincent Donnefort pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/\n", name); 439*96e43537SVincent Donnefort goto err; 440*96e43537SVincent Donnefort } 441*96e43537SVincent Donnefort 442*96e43537SVincent Donnefort d = trace_create_file("tracing_on", TRACEFS_MODE_WRITE, remote_d, remote, &tracing_on_fops); 443*96e43537SVincent Donnefort if (!d) 444*96e43537SVincent Donnefort goto err; 445*96e43537SVincent Donnefort 446*96e43537SVincent Donnefort d = trace_create_file("buffer_size_kb", TRACEFS_MODE_WRITE, remote_d, remote, 447*96e43537SVincent Donnefort &buffer_size_kb_fops); 448*96e43537SVincent Donnefort if (!d) 449*96e43537SVincent Donnefort goto err; 450*96e43537SVincent Donnefort 451*96e43537SVincent Donnefort d = trace_create_file("trace_pipe", TRACEFS_MODE_READ, remote_d, remote, &trace_pipe_fops); 452*96e43537SVincent Donnefort if (!d) 453*96e43537SVincent Donnefort goto err; 454*96e43537SVincent Donnefort 455*96e43537SVincent Donnefort percpu_d = tracefs_create_dir("per_cpu", remote_d); 456*96e43537SVincent Donnefort if (!percpu_d) { 457*96e43537SVincent Donnefort pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/per_cpu/\n", name); 458*96e43537SVincent Donnefort goto err; 459*96e43537SVincent Donnefort } 460*96e43537SVincent Donnefort 461*96e43537SVincent Donnefort for_each_possible_cpu(cpu) { 462*96e43537SVincent Donnefort struct dentry *cpu_d; 463*96e43537SVincent Donnefort char cpu_name[16]; 464*96e43537SVincent Donnefort 465*96e43537SVincent Donnefort snprintf(cpu_name, sizeof(cpu_name), "cpu%d", cpu); 466*96e43537SVincent Donnefort cpu_d = tracefs_create_dir(cpu_name, percpu_d); 467*96e43537SVincent Donnefort if (!cpu_d) { 468*96e43537SVincent Donnefort pr_err("Failed to create tracefs dir "TRACEFS_DIR"%s/percpu/cpu%d\n", 469*96e43537SVincent Donnefort name, cpu); 470*96e43537SVincent Donnefort goto err; 471*96e43537SVincent Donnefort } 472*96e43537SVincent Donnefort 473*96e43537SVincent Donnefort d = trace_create_cpu_file("trace_pipe", TRACEFS_MODE_READ, cpu_d, remote, cpu, 474*96e43537SVincent Donnefort &trace_pipe_fops); 475*96e43537SVincent Donnefort if (!d) 476*96e43537SVincent Donnefort goto err; 477*96e43537SVincent Donnefort } 478*96e43537SVincent Donnefort 479*96e43537SVincent Donnefort return 0; 480*96e43537SVincent Donnefort 481*96e43537SVincent Donnefort err: 482*96e43537SVincent Donnefort if (root_inited) { 483*96e43537SVincent Donnefort tracefs_remove(root); 484*96e43537SVincent Donnefort root = NULL; 485*96e43537SVincent Donnefort } else { 486*96e43537SVincent Donnefort tracefs_remove(remote_d); 487*96e43537SVincent Donnefort } 488*96e43537SVincent Donnefort 489*96e43537SVincent Donnefort return -ENOMEM; 490*96e43537SVincent Donnefort } 491*96e43537SVincent Donnefort 492*96e43537SVincent Donnefort /** 493*96e43537SVincent Donnefort * trace_remote_register() - Register a Tracefs remote 494*96e43537SVincent Donnefort * @name: Name of the remote, used for the Tracefs remotes/ directory. 495*96e43537SVincent Donnefort * @cbs: Set of callbacks used to control the remote. 496*96e43537SVincent Donnefort * @priv: Private data, passed to each callback from @cbs. 497*96e43537SVincent Donnefort * @events: Array of events. &remote_event.name and &remote_event.id must be 498*96e43537SVincent Donnefort * filled by the caller. 499*96e43537SVincent Donnefort * @nr_events: Number of events in the @events array. 500*96e43537SVincent Donnefort * 501*96e43537SVincent Donnefort * A trace remote is an entity, outside of the kernel (most likely firmware or 502*96e43537SVincent Donnefort * hypervisor) capable of writing events into a Tracefs compatible ring-buffer. 503*96e43537SVincent Donnefort * The kernel would then act as a reader. 504*96e43537SVincent Donnefort * 505*96e43537SVincent Donnefort * The registered remote will be found under the Tracefs directory 506*96e43537SVincent Donnefort * remotes/<name>. 507*96e43537SVincent Donnefort * 508*96e43537SVincent Donnefort * Return: 0 on success, negative error code on failure. 509*96e43537SVincent Donnefort */ 510*96e43537SVincent Donnefort int trace_remote_register(const char *name, struct trace_remote_callbacks *cbs, void *priv) 511*96e43537SVincent Donnefort { 512*96e43537SVincent Donnefort struct trace_remote *remote; 513*96e43537SVincent Donnefort 514*96e43537SVincent Donnefort remote = kzalloc_obj(*remote); 515*96e43537SVincent Donnefort if (!remote) 516*96e43537SVincent Donnefort return -ENOMEM; 517*96e43537SVincent Donnefort 518*96e43537SVincent Donnefort remote->cbs = cbs; 519*96e43537SVincent Donnefort remote->priv = priv; 520*96e43537SVincent Donnefort remote->trace_buffer_size = 7 << 10; 521*96e43537SVincent Donnefort remote->poll_ms = 100; 522*96e43537SVincent Donnefort mutex_init(&remote->lock); 523*96e43537SVincent Donnefort 524*96e43537SVincent Donnefort if (trace_remote_init_tracefs(name, remote)) { 525*96e43537SVincent Donnefort kfree(remote); 526*96e43537SVincent Donnefort return -ENOMEM; 527*96e43537SVincent Donnefort } 528*96e43537SVincent Donnefort 529*96e43537SVincent Donnefort return 0; 530*96e43537SVincent Donnefort } 531*96e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_register); 532*96e43537SVincent Donnefort 533*96e43537SVincent Donnefort /** 534*96e43537SVincent Donnefort * trace_remote_free_buffer() - Free trace buffer allocated with trace_remote_alloc_buffer() 535*96e43537SVincent Donnefort * @desc: Descriptor of the per-CPU ring-buffers, originally filled by 536*96e43537SVincent Donnefort * trace_remote_alloc_buffer() 537*96e43537SVincent Donnefort * 538*96e43537SVincent Donnefort * Most likely called from &trace_remote_callbacks.unload_trace_buffer. 539*96e43537SVincent Donnefort */ 540*96e43537SVincent Donnefort void trace_remote_free_buffer(struct trace_buffer_desc *desc) 541*96e43537SVincent Donnefort { 542*96e43537SVincent Donnefort struct ring_buffer_desc *rb_desc; 543*96e43537SVincent Donnefort int cpu; 544*96e43537SVincent Donnefort 545*96e43537SVincent Donnefort for_each_ring_buffer_desc(rb_desc, cpu, desc) { 546*96e43537SVincent Donnefort unsigned int id; 547*96e43537SVincent Donnefort 548*96e43537SVincent Donnefort free_page(rb_desc->meta_va); 549*96e43537SVincent Donnefort 550*96e43537SVincent Donnefort for (id = 0; id < rb_desc->nr_page_va; id++) 551*96e43537SVincent Donnefort free_page(rb_desc->page_va[id]); 552*96e43537SVincent Donnefort } 553*96e43537SVincent Donnefort } 554*96e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_free_buffer); 555*96e43537SVincent Donnefort 556*96e43537SVincent Donnefort /** 557*96e43537SVincent Donnefort * trace_remote_alloc_buffer() - Dynamically allocate a trace buffer 558*96e43537SVincent Donnefort * @desc: Uninitialized trace_buffer_desc 559*96e43537SVincent Donnefort * @desc_size: Size of the trace_buffer_desc. Must be at least equal to 560*96e43537SVincent Donnefort * trace_buffer_desc_size() 561*96e43537SVincent Donnefort * @buffer_size: Size in bytes of each per-CPU ring-buffer 562*96e43537SVincent Donnefort * @cpumask: CPUs to allocate a ring-buffer for 563*96e43537SVincent Donnefort * 564*96e43537SVincent Donnefort * Helper to dynamically allocate a set of pages (enough to cover @buffer_size) 565*96e43537SVincent Donnefort * for each CPU from @cpumask and fill @desc. Most likely called from 566*96e43537SVincent Donnefort * &trace_remote_callbacks.load_trace_buffer. 567*96e43537SVincent Donnefort * 568*96e43537SVincent Donnefort * Return: 0 on success, negative error code on failure. 569*96e43537SVincent Donnefort */ 570*96e43537SVincent Donnefort int trace_remote_alloc_buffer(struct trace_buffer_desc *desc, size_t desc_size, size_t buffer_size, 571*96e43537SVincent Donnefort const struct cpumask *cpumask) 572*96e43537SVincent Donnefort { 573*96e43537SVincent Donnefort unsigned int nr_pages = max(DIV_ROUND_UP(buffer_size, PAGE_SIZE), 2UL) + 1; 574*96e43537SVincent Donnefort void *desc_end = desc + desc_size; 575*96e43537SVincent Donnefort struct ring_buffer_desc *rb_desc; 576*96e43537SVincent Donnefort int cpu, ret = -ENOMEM; 577*96e43537SVincent Donnefort 578*96e43537SVincent Donnefort if (desc_size < struct_size(desc, __data, 0)) 579*96e43537SVincent Donnefort return -EINVAL; 580*96e43537SVincent Donnefort 581*96e43537SVincent Donnefort desc->nr_cpus = 0; 582*96e43537SVincent Donnefort desc->struct_len = struct_size(desc, __data, 0); 583*96e43537SVincent Donnefort 584*96e43537SVincent Donnefort rb_desc = (struct ring_buffer_desc *)&desc->__data[0]; 585*96e43537SVincent Donnefort 586*96e43537SVincent Donnefort for_each_cpu(cpu, cpumask) { 587*96e43537SVincent Donnefort unsigned int id; 588*96e43537SVincent Donnefort 589*96e43537SVincent Donnefort if ((void *)rb_desc + struct_size(rb_desc, page_va, nr_pages) > desc_end) { 590*96e43537SVincent Donnefort ret = -EINVAL; 591*96e43537SVincent Donnefort goto err; 592*96e43537SVincent Donnefort } 593*96e43537SVincent Donnefort 594*96e43537SVincent Donnefort rb_desc->cpu = cpu; 595*96e43537SVincent Donnefort rb_desc->nr_page_va = 0; 596*96e43537SVincent Donnefort rb_desc->meta_va = (unsigned long)__get_free_page(GFP_KERNEL); 597*96e43537SVincent Donnefort if (!rb_desc->meta_va) 598*96e43537SVincent Donnefort goto err; 599*96e43537SVincent Donnefort 600*96e43537SVincent Donnefort for (id = 0; id < nr_pages; id++) { 601*96e43537SVincent Donnefort rb_desc->page_va[id] = (unsigned long)__get_free_page(GFP_KERNEL); 602*96e43537SVincent Donnefort if (!rb_desc->page_va[id]) 603*96e43537SVincent Donnefort goto err; 604*96e43537SVincent Donnefort 605*96e43537SVincent Donnefort rb_desc->nr_page_va++; 606*96e43537SVincent Donnefort } 607*96e43537SVincent Donnefort desc->nr_cpus++; 608*96e43537SVincent Donnefort desc->struct_len += offsetof(struct ring_buffer_desc, page_va); 609*96e43537SVincent Donnefort desc->struct_len += struct_size(rb_desc, page_va, rb_desc->nr_page_va); 610*96e43537SVincent Donnefort rb_desc = __next_ring_buffer_desc(rb_desc); 611*96e43537SVincent Donnefort } 612*96e43537SVincent Donnefort 613*96e43537SVincent Donnefort return 0; 614*96e43537SVincent Donnefort 615*96e43537SVincent Donnefort err: 616*96e43537SVincent Donnefort trace_remote_free_buffer(desc); 617*96e43537SVincent Donnefort return ret; 618*96e43537SVincent Donnefort } 619*96e43537SVincent Donnefort EXPORT_SYMBOL_GPL(trace_remote_alloc_buffer); 620