diff --git a/fs/pstore/ftrace.c b/fs/pstore/ftrace.c index 776cae20af4e..f937c6a33bea 100644 --- a/fs/pstore/ftrace.c +++ b/fs/pstore/ftrace.c @@ -18,11 +18,35 @@ #include #include #include +#include #include "internal.h" /* This doesn't need to be atomic: speed is chosen over correctness here. */ static u64 pstore_ftrace_stamp; +static inline unsigned long adjust_ip(unsigned long ip) +{ +#if defined(CONFIG_RANDOMIZE_BASE) && !defined(PSTORE_CPU_IN_IP) && IS_BUILTIN(CONFIG_PSTORE) + if (core_kernel_text(ip)) + return ip - kaslr_offset(); + + __clear_bit(BITS_PER_LONG - 1, &ip); +#endif + return ip; +} + +inline unsigned long decode_ip(unsigned long ip) +{ +#if defined(CONFIG_RANDOMIZE_BASE) && !defined(PSTORE_CPU_IN_IP) && IS_BUILTIN(CONFIG_PSTORE) + if (test_bit(BITS_PER_LONG - 1, &ip)) + return ip + kaslr_offset(); + + __set_bit(BITS_PER_LONG - 1, &ip); + +#endif + return ip; +} + static void notrace pstore_ftrace_call(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *op, @@ -47,8 +71,8 @@ static void notrace pstore_ftrace_call(unsigned long ip, local_irq_save(flags); - rec.ip = ip; - rec.parent_ip = parent_ip; + rec.ip = adjust_ip(ip); + rec.parent_ip = adjust_ip(parent_ip); pstore_ftrace_write_timestamp(&rec, pstore_ftrace_stamp++); pstore_ftrace_encode_cpu(&rec, raw_smp_processor_id()); psinfo->write(&record); @@ -62,13 +86,16 @@ static struct ftrace_ops pstore_ftrace_ops __read_mostly = { }; static DEFINE_MUTEX(pstore_ftrace_lock); -static bool pstore_ftrace_enabled; +static bool record_ftrace; +module_param(record_ftrace, bool, 0400); +MODULE_PARM_DESC(record_ftrace, + "enable ftrace recording immediately (default: off)"); static int pstore_set_ftrace_enabled(bool on) { ssize_t ret; - if (on == pstore_ftrace_enabled) + if (on == record_ftrace) return 0; if (on) { @@ -82,7 +109,7 @@ static int pstore_set_ftrace_enabled(bool on) pr_err("%s: unable to %sregister ftrace ops: %zd\n", __func__, on ? "" : "un", ret); } else { - pstore_ftrace_enabled = on; + record_ftrace = on; } return ret; @@ -111,7 +138,7 @@ static ssize_t pstore_ftrace_knob_write(struct file *f, const char __user *buf, static ssize_t pstore_ftrace_knob_read(struct file *f, char __user *buf, size_t count, loff_t *ppos) { - char val[] = { '0' + pstore_ftrace_enabled, '\n' }; + char val[] = { '0' + record_ftrace, '\n' }; return simple_read_from_buffer(buf, count, ppos, val, sizeof(val)); } @@ -124,11 +151,6 @@ static const struct file_operations pstore_knob_fops = { static struct dentry *pstore_ftrace_dir; -static bool record_ftrace; -module_param(record_ftrace, bool, 0400); -MODULE_PARM_DESC(record_ftrace, - "enable ftrace recording immediately (default: off)"); - void pstore_register_ftrace(void) { if (!psinfo->write) @@ -145,9 +167,9 @@ void pstore_register_ftrace(void) void pstore_unregister_ftrace(void) { mutex_lock(&pstore_ftrace_lock); - if (pstore_ftrace_enabled) { + if (record_ftrace) { unregister_ftrace_function(&pstore_ftrace_ops); - pstore_ftrace_enabled = false; + record_ftrace = false; } mutex_unlock(&pstore_ftrace_lock); diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c index 83fa0bb3435a..cf499ba72702 100644 --- a/fs/pstore/inode.c +++ b/fs/pstore/inode.c @@ -74,9 +74,9 @@ static void *pstore_ftrace_seq_start(struct seq_file *s, loff_t *pos) if (!data) return NULL; - data->off = ps->total_size % REC_SIZE; + data->off = ps->record->size % REC_SIZE; data->off += *pos * REC_SIZE; - if (data->off + REC_SIZE > ps->total_size) + if (data->off + REC_SIZE > ps->record->size) return NULL; return_ptr(data); @@ -94,7 +94,7 @@ static void *pstore_ftrace_seq_next(struct seq_file *s, void *v, loff_t *pos) (*pos)++; data->off += REC_SIZE; - if (data->off + REC_SIZE > ps->total_size) + if (data->off + REC_SIZE > ps->record->size) return NULL; return data; @@ -105,17 +105,19 @@ static int pstore_ftrace_seq_show(struct seq_file *s, void *v) struct pstore_private *ps = s->private; struct pstore_ftrace_seq_data *data = v; struct pstore_ftrace_record *rec; + unsigned long ip, parent_ip; if (!data) return 0; rec = (struct pstore_ftrace_record *)(ps->record->buf + data->off); + ip = decode_ip(rec->ip); + parent_ip = decode_ip(rec->parent_ip); seq_printf(s, "CPU:%d ts:%llu %08lx %08lx %ps <- %pS\n", pstore_ftrace_decode_cpu(rec), pstore_ftrace_read_timestamp(rec), - rec->ip, rec->parent_ip, (void *)rec->ip, - (void *)rec->parent_ip); + ip, parent_ip, (void *)ip, (void *)parent_ip); return 0; } diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h index a0fc51196910..079284120db9 100644 --- a/fs/pstore/internal.h +++ b/fs/pstore/internal.h @@ -9,6 +9,7 @@ extern unsigned int kmsg_bytes; #ifdef CONFIG_PSTORE_FTRACE +extern unsigned long decode_ip(unsigned long ip); extern void pstore_register_ftrace(void); extern void pstore_unregister_ftrace(void); ssize_t pstore_ftrace_combine_log(char **dest_log, size_t *dest_log_size, @@ -16,6 +17,7 @@ ssize_t pstore_ftrace_combine_log(char **dest_log, size_t *dest_log_size, #else static inline void pstore_register_ftrace(void) {} static inline void pstore_unregister_ftrace(void) {} +static inline unsigned long decode_ip(unsigned long ip) { return ip; } static inline ssize_t pstore_ftrace_combine_log(char **dest_log, size_t *dest_log_size, const char *src_log, size_t src_log_size) diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index d1f895e57a95..2eb0d4fa2186 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -71,7 +71,7 @@ MODULE_PARM_DESC(max_reason, static int ramoops_ecc; module_param_named(ecc, ramoops_ecc, int, 0400); -MODULE_PARM_DESC(ramoops_ecc, +MODULE_PARM_DESC(ecc, "if non-zero, the option enables ECC support and specifies " "ECC buffer size in bytes (1 is a special value, means 16 " "bytes ECC)"); diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c index ed97494abf60..05048c6f787a 100644 --- a/fs/pstore/ram_core.c +++ b/fs/pstore/ram_core.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -488,6 +487,10 @@ static void *persistent_ram_iomap(phys_addr_t start, size_t size, else va = ioremap_wc(start, size); + /* We must release the mem region if ioremap fails. */ + if (!va) + release_mem_region(start, size); + /* * Since request_mem_region() and ioremap() are byte-granularity * there is no need handle anything special like we do when the