1/* 2 * Copyright (C) 2012 Google, Inc. 3 * 4 * This software is licensed under the terms of the GNU General Public 5 * License version 2, as published by the Free Software Foundation, and 6 * may be copied, distributed, and modified under those terms. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 */ 14 15#include <linux/debugfs.h> 16#include <linux/errno.h> 17#include <linux/kernel.h> 18#include <linux/init.h> 19#include <linux/io.h> 20#include <linux/persistent_ram.h> 21#include <linux/platform_device.h> 22#include <linux/seq_file.h> 23#include <linux/slab.h> 24 25#include "../../../kernel/trace/trace.h" 26 27struct persistent_trace_record { 28 unsigned long ip; 29 unsigned long parent_ip; 30}; 31 32#define REC_SIZE sizeof(struct persistent_trace_record) 33 34static struct persistent_ram_zone *persistent_trace; 35 36static int persistent_trace_enabled; 37 38static struct trace_array *persistent_trace_array; 39 40static struct ftrace_ops trace_ops; 41 42static int persistent_tracer_init(struct trace_array *tr) 43{ 44 persistent_trace_array = tr; 45 tr->cpu = get_cpu(); 46 put_cpu(); 47 48 tracing_start_cmdline_record(); 49 50 persistent_trace_enabled = 0; 51 smp_wmb(); 52 53 register_ftrace_function(&trace_ops); 54 55 smp_wmb(); 56 persistent_trace_enabled = 1; 57 58 return 0; 59} 60 61static void persistent_trace_reset(struct trace_array *tr) 62{ 63 persistent_trace_enabled = 0; 64 smp_wmb(); 65 66 unregister_ftrace_function(&trace_ops); 67 68 tracing_stop_cmdline_record(); 69} 70 71static void persistent_trace_start(struct trace_array *tr) 72{ 73 tracing_reset_online_cpus(tr); 74} 75 76static void persistent_trace_call(unsigned long ip, unsigned long parent_ip) 77{ 78 struct trace_array *tr = persistent_trace_array; 79 struct trace_array_cpu *data; 80 long disabled; 81 struct persistent_trace_record rec; 82 unsigned long flags; 83 int cpu; 84 85 smp_rmb(); 86 if (unlikely(!persistent_trace_enabled)) 87 return; 88 89 if (unlikely(oops_in_progress)) 90 return; 91 92 /* 93 * Need to use raw, since this must be called before the 94 * recursive protection is performed. 95 */ 96 local_irq_save(flags); 97 cpu = raw_smp_processor_id(); 98 data = tr->data[cpu]; 99 disabled = atomic_inc_return(&data->disabled); 100 101 if (likely(disabled == 1)) { 102 rec.ip = ip; 103 rec.parent_ip = parent_ip; 104 rec.ip |= cpu; 105 persistent_ram_write(persistent_trace, &rec, sizeof(rec)); 106 } 107 108 atomic_dec(&data->disabled); 109 local_irq_restore(flags); 110} 111 112static struct ftrace_ops trace_ops __read_mostly = { 113 .func = persistent_trace_call, 114 .flags = FTRACE_OPS_FL_GLOBAL, 115}; 116 117static struct tracer persistent_tracer __read_mostly = { 118 .name = "persistent", 119 .init = persistent_tracer_init, 120 .reset = persistent_trace_reset, 121 .start = persistent_trace_start, 122 .wait_pipe = poll_wait_pipe, 123}; 124 125struct persistent_trace_seq_data { 126 const void *ptr; 127 size_t off; 128 size_t size; 129}; 130 131void *persistent_trace_seq_start(struct seq_file *s, loff_t *pos) 132{ 133 struct persistent_trace_seq_data *data; 134 135 data = kzalloc(sizeof(*data), GFP_KERNEL); 136 if (!data) 137 return NULL; 138 139 data->ptr = persistent_ram_old(persistent_trace); 140 data->size = persistent_ram_old_size(persistent_trace); 141 data->off = data->size % REC_SIZE; 142 143 data->off += *pos * REC_SIZE; 144 145 if (data->off + REC_SIZE > data->size) { 146 kfree(data); 147 return NULL; 148 } 149 150 return data; 151 152} 153void persistent_trace_seq_stop(struct seq_file *s, void *v) 154{ 155 kfree(v); 156} 157 158void *persistent_trace_seq_next(struct seq_file *s, void *v, loff_t *pos) 159{ 160 struct persistent_trace_seq_data *data = v; 161 162 data->off += REC_SIZE; 163 164 if (data->off + REC_SIZE > data->size) 165 return NULL; 166 167 (*pos)++; 168 169 return data; 170} 171 172int persistent_trace_seq_show(struct seq_file *s, void *v) 173{ 174 struct persistent_trace_seq_data *data = v; 175 struct persistent_trace_record *rec; 176 177 rec = (struct persistent_trace_record *)(data->ptr + data->off); 178 179 seq_printf(s, "%ld %08lx %08lx %pf <- %pF\n", 180 rec->ip & 3, rec->ip, rec->parent_ip, 181 (void *)rec->ip, (void *)rec->parent_ip); 182 183 return 0; 184} 185 186static const struct seq_operations persistent_trace_seq_ops = { 187 .start = persistent_trace_seq_start, 188 .next = persistent_trace_seq_next, 189 .stop = persistent_trace_seq_stop, 190 .show = persistent_trace_seq_show, 191}; 192 193static int persistent_trace_old_open(struct inode *inode, struct file *file) 194{ 195 return seq_open(file, &persistent_trace_seq_ops); 196} 197 198static const struct file_operations persistent_trace_old_fops = { 199 .open = persistent_trace_old_open, 200 .read = seq_read, 201 .llseek = seq_lseek, 202 .release = seq_release, 203}; 204 205static int __devinit persistent_trace_probe(struct platform_device *pdev) 206{ 207 struct dentry *d; 208 int ret; 209 210 persistent_trace = persistent_ram_init_ringbuffer(&pdev->dev, false); 211 if (IS_ERR(persistent_trace)) { 212 pr_err("persistent_trace: failed to init ringbuffer: %ld\n", 213 PTR_ERR(persistent_trace)); 214 return PTR_ERR(persistent_trace); 215 } 216 217 ret = register_tracer(&persistent_tracer); 218 if (ret) 219 pr_err("persistent_trace: failed to register tracer"); 220 221 if (persistent_ram_old_size(persistent_trace) > 0) { 222 d = debugfs_create_file("persistent_trace", S_IRUGO, NULL, 223 NULL, &persistent_trace_old_fops); 224 if (IS_ERR_OR_NULL(d)) 225 pr_err("persistent_trace: failed to create old file\n"); 226 } 227 228 return 0; 229} 230 231static struct platform_driver persistent_trace_driver = { 232 .probe = persistent_trace_probe, 233 .driver = { 234 .name = "persistent_trace", 235 }, 236}; 237 238static int __init persistent_trace_init(void) 239{ 240 return platform_driver_register(&persistent_trace_driver); 241} 242core_initcall(persistent_trace_init); 243