root/fs/pstore/ftrace.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pstore_ftrace_call
  2. pstore_ftrace_knob_write
  3. pstore_ftrace_knob_read
  4. pstore_register_ftrace
  5. pstore_unregister_ftrace

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright 2012  Google, Inc.
   4  */
   5 
   6 #include <linux/kernel.h>
   7 #include <linux/compiler.h>
   8 #include <linux/irqflags.h>
   9 #include <linux/percpu.h>
  10 #include <linux/smp.h>
  11 #include <linux/atomic.h>
  12 #include <linux/types.h>
  13 #include <linux/mutex.h>
  14 #include <linux/ftrace.h>
  15 #include <linux/fs.h>
  16 #include <linux/debugfs.h>
  17 #include <linux/err.h>
  18 #include <linux/cache.h>
  19 #include <asm/barrier.h>
  20 #include "internal.h"
  21 
  22 /* This doesn't need to be atomic: speed is chosen over correctness here. */
  23 static u64 pstore_ftrace_stamp;
  24 
  25 static void notrace pstore_ftrace_call(unsigned long ip,
  26                                        unsigned long parent_ip,
  27                                        struct ftrace_ops *op,
  28                                        struct pt_regs *regs)
  29 {
  30         unsigned long flags;
  31         struct pstore_ftrace_record rec = {};
  32         struct pstore_record record = {
  33                 .type = PSTORE_TYPE_FTRACE,
  34                 .buf = (char *)&rec,
  35                 .size = sizeof(rec),
  36                 .psi = psinfo,
  37         };
  38 
  39         if (unlikely(oops_in_progress))
  40                 return;
  41 
  42         local_irq_save(flags);
  43 
  44         rec.ip = ip;
  45         rec.parent_ip = parent_ip;
  46         pstore_ftrace_write_timestamp(&rec, pstore_ftrace_stamp++);
  47         pstore_ftrace_encode_cpu(&rec, raw_smp_processor_id());
  48         psinfo->write(&record);
  49 
  50         local_irq_restore(flags);
  51 }
  52 
  53 static struct ftrace_ops pstore_ftrace_ops __read_mostly = {
  54         .func   = pstore_ftrace_call,
  55 };
  56 
  57 static DEFINE_MUTEX(pstore_ftrace_lock);
  58 static bool pstore_ftrace_enabled;
  59 
  60 static ssize_t pstore_ftrace_knob_write(struct file *f, const char __user *buf,
  61                                         size_t count, loff_t *ppos)
  62 {
  63         u8 on;
  64         ssize_t ret;
  65 
  66         ret = kstrtou8_from_user(buf, count, 2, &on);
  67         if (ret)
  68                 return ret;
  69 
  70         mutex_lock(&pstore_ftrace_lock);
  71 
  72         if (!on ^ pstore_ftrace_enabled)
  73                 goto out;
  74 
  75         if (on) {
  76                 ftrace_ops_set_global_filter(&pstore_ftrace_ops);
  77                 ret = register_ftrace_function(&pstore_ftrace_ops);
  78         } else {
  79                 ret = unregister_ftrace_function(&pstore_ftrace_ops);
  80         }
  81 
  82         if (ret) {
  83                 pr_err("%s: unable to %sregister ftrace ops: %zd\n",
  84                        __func__, on ? "" : "un", ret);
  85                 goto err;
  86         }
  87 
  88         pstore_ftrace_enabled = on;
  89 out:
  90         ret = count;
  91 err:
  92         mutex_unlock(&pstore_ftrace_lock);
  93 
  94         return ret;
  95 }
  96 
  97 static ssize_t pstore_ftrace_knob_read(struct file *f, char __user *buf,
  98                                        size_t count, loff_t *ppos)
  99 {
 100         char val[] = { '0' + pstore_ftrace_enabled, '\n' };
 101 
 102         return simple_read_from_buffer(buf, count, ppos, val, sizeof(val));
 103 }
 104 
 105 static const struct file_operations pstore_knob_fops = {
 106         .open   = simple_open,
 107         .read   = pstore_ftrace_knob_read,
 108         .write  = pstore_ftrace_knob_write,
 109 };
 110 
 111 static struct dentry *pstore_ftrace_dir;
 112 
 113 void pstore_register_ftrace(void)
 114 {
 115         if (!psinfo->write)
 116                 return;
 117 
 118         pstore_ftrace_dir = debugfs_create_dir("pstore", NULL);
 119 
 120         debugfs_create_file("record_ftrace", 0600, pstore_ftrace_dir, NULL,
 121                             &pstore_knob_fops);
 122 }
 123 
 124 void pstore_unregister_ftrace(void)
 125 {
 126         mutex_lock(&pstore_ftrace_lock);
 127         if (pstore_ftrace_enabled) {
 128                 unregister_ftrace_function(&pstore_ftrace_ops);
 129                 pstore_ftrace_enabled = false;
 130         }
 131         mutex_unlock(&pstore_ftrace_lock);
 132 
 133         debugfs_remove_recursive(pstore_ftrace_dir);
 134 }

/* [<][>][^][v][top][bottom][index][help] */