summaryrefslogtreecommitdiff
path: root/fs/pstore
diff options
context:
space:
mode:
Diffstat (limited to 'fs/pstore')
-rw-r--r--fs/pstore/ftrace.c48
-rw-r--r--fs/pstore/inode.c12
-rw-r--r--fs/pstore/internal.h2
-rw-r--r--fs/pstore/ram.c2
-rw-r--r--fs/pstore/ram_core.c7
5 files changed, 50 insertions, 21 deletions
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 <linux/cache.h>
#include <linux/slab.h>
#include <asm/barrier.h>
+#include <asm/setup.h>
#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..b4ec8009b8dc 100644
--- a/fs/pstore/ram_core.c
+++ b/fs/pstore/ram_core.c
@@ -12,7 +12,6 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/list.h>
-#include <linux/memblock.h>
#include <linux/rslib.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
@@ -450,7 +449,7 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size,
pages[i] = pfn_to_page(addr >> PAGE_SHIFT);
}
/*
- * VM_IOREMAP used here to bypass this region during vread()
+ * VM_IOREMAP used here to bypass this region during vread_iter()
* and kmap_atomic() (i.e. kcore) to avoid __va() failures.
*/
vaddr = vmap(pages, page_count, VM_MAP | VM_IOREMAP, prot);
@@ -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