^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright 2012 Google, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/irqflags.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/percpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/atomic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/ftrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/cache.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/barrier.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /* This doesn't need to be atomic: speed is chosen over correctness here. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static u64 pstore_ftrace_stamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static void notrace pstore_ftrace_call(unsigned long ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) unsigned long parent_ip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct ftrace_ops *op,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct pstore_ftrace_record rec = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct pstore_record record = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) .type = PSTORE_TYPE_FTRACE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) .buf = (char *)&rec,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) .size = sizeof(rec),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) .psi = psinfo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (unlikely(oops_in_progress))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) rec.ip = ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) rec.parent_ip = parent_ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) pstore_ftrace_write_timestamp(&rec, pstore_ftrace_stamp++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) pstore_ftrace_encode_cpu(&rec, raw_smp_processor_id());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) psinfo->write(&record);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static struct ftrace_ops pstore_ftrace_ops __read_mostly = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) .func = pstore_ftrace_call,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static DEFINE_MUTEX(pstore_ftrace_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static bool pstore_ftrace_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static ssize_t pstore_ftrace_knob_write(struct file *f, const char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) u8 on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) ssize_t ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) ret = kstrtou8_from_user(buf, count, 2, &on);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) mutex_lock(&pstore_ftrace_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (!on ^ pstore_ftrace_enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ftrace_ops_set_global_filter(&pstore_ftrace_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) ret = register_ftrace_function(&pstore_ftrace_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) ret = unregister_ftrace_function(&pstore_ftrace_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) pr_err("%s: unable to %sregister ftrace ops: %zd\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) __func__, on ? "" : "un", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) pstore_ftrace_enabled = on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) ret = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) mutex_unlock(&pstore_ftrace_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static ssize_t pstore_ftrace_knob_read(struct file *f, char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) size_t count, loff_t *ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) char val[] = { '0' + pstore_ftrace_enabled, '\n' };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) return simple_read_from_buffer(buf, count, ppos, val, sizeof(val));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static const struct file_operations pstore_knob_fops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .open = simple_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) .read = pstore_ftrace_knob_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) .write = pstore_ftrace_knob_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static struct dentry *pstore_ftrace_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) void pstore_register_ftrace(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (!psinfo->write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) pstore_ftrace_dir = debugfs_create_dir("pstore", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) debugfs_create_file("record_ftrace", 0600, pstore_ftrace_dir, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) &pstore_knob_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) void pstore_unregister_ftrace(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) mutex_lock(&pstore_ftrace_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (pstore_ftrace_enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) unregister_ftrace_function(&pstore_ftrace_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) pstore_ftrace_enabled = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) mutex_unlock(&pstore_ftrace_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) debugfs_remove_recursive(pstore_ftrace_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) ssize_t pstore_ftrace_combine_log(char **dest_log, size_t *dest_log_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) const char *src_log, size_t src_log_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) size_t dest_size, src_size, total, dest_off, src_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) size_t dest_idx = 0, src_idx = 0, merged_idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) void *merged_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct pstore_ftrace_record *drec, *srec, *mrec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) size_t record_size = sizeof(struct pstore_ftrace_record);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) dest_off = *dest_log_size % record_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) dest_size = *dest_log_size - dest_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) src_off = src_log_size % record_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) src_size = src_log_size - src_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) total = dest_size + src_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) merged_buf = kmalloc(total, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (!merged_buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) drec = (struct pstore_ftrace_record *)(*dest_log + dest_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) srec = (struct pstore_ftrace_record *)(src_log + src_off);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) mrec = (struct pstore_ftrace_record *)(merged_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) while (dest_size > 0 && src_size > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (pstore_ftrace_read_timestamp(&drec[dest_idx]) <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) pstore_ftrace_read_timestamp(&srec[src_idx])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) mrec[merged_idx++] = drec[dest_idx++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) dest_size -= record_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) mrec[merged_idx++] = srec[src_idx++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) src_size -= record_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) while (dest_size > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) mrec[merged_idx++] = drec[dest_idx++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) dest_size -= record_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) while (src_size > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) mrec[merged_idx++] = srec[src_idx++];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) src_size -= record_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) kfree(*dest_log);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) *dest_log = merged_buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) *dest_log_size = total;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) EXPORT_SYMBOL_GPL(pstore_ftrace_combine_log);