summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLingutla Chandrasekhar <clingutla@codeaurora.org>2017-08-05 14:26:56 +0530
committerGerrit - the friendly Code Review server <code-review@localhost>2017-09-01 02:51:08 -0700
commitaf5a88a343145f4e2235a2cda97cb0494a07b9b6 (patch)
tree4c7735187f15207111183c4e48f0dec95d8148db
parent285229fa976cb9ffe5147cc4b363748c999160f9 (diff)
soc: qcom: dump current task stack and task_struct for minidump
Register the current stack and task_struct of all cpus to the minidump table on panic. Change-Id: I6906721f8c734dbf8142dc49e80dc730530f028c Signed-off-by: Lingutla Chandrasekhar <clingutla@codeaurora.org>
-rw-r--r--arch/arm64/kernel/smp.c2
-rw-r--r--drivers/soc/qcom/common_log.c27
-rw-r--r--include/soc/qcom/minidump.h5
-rw-r--r--kernel/panic.c2
4 files changed, 36 insertions, 0 deletions
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index a3a6b2ea9b4d..d031a85e0bc7 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -54,6 +54,7 @@
#include <asm/ptrace.h>
#include <asm/virt.h>
#include <asm/edac.h>
+#include <soc/qcom/minidump.h>
#define CREATE_TRACE_POINTS
#include <trace/events/ipi.h>
@@ -740,6 +741,7 @@ static void ipi_cpu_stop(unsigned int cpu, struct pt_regs *regs)
pr_crit("CPU%u: stopping\n", cpu);
show_regs(regs);
dump_stack();
+ dump_stack_minidump(regs->sp);
arm64_check_cache_ecc(NULL);
raw_spin_unlock(&stop_lock);
}
diff --git a/drivers/soc/qcom/common_log.c b/drivers/soc/qcom/common_log.c
index 1e8744b41e4c..11ca86a4ba41 100644
--- a/drivers/soc/qcom/common_log.c
+++ b/drivers/soc/qcom/common_log.c
@@ -18,6 +18,7 @@
#include <linux/slab.h>
#include <linux/kmemleak.h>
#include <linux/async.h>
+#include <linux/thread_info.h>
#include <soc/qcom/memory_dump.h>
#include <soc/qcom/minidump.h>
#include <asm/sections.h>
@@ -256,6 +257,32 @@ static void __init register_kernel_sections(void)
}
}
+#ifdef CONFIG_QCOM_MINIDUMP
+void dump_stack_minidump(u64 sp)
+{
+ struct md_region ksp_entry, ktsk_entry;
+ u32 cpu = smp_processor_id();
+
+ if (sp < KIMAGE_VADDR || sp > -256UL)
+ sp = current_stack_pointer;
+
+ sp &= ~(THREAD_SIZE - 1);
+ scnprintf(ksp_entry.name, sizeof(ksp_entry.name), "KSTACK%d", cpu);
+ ksp_entry.virt_addr = sp;
+ ksp_entry.phys_addr = virt_to_phys((uintptr_t *)sp);
+ ksp_entry.size = THREAD_SIZE;
+ if (msm_minidump_add_region(&ksp_entry))
+ pr_err("Failed to add stack of cpu %d in Minidump\n", cpu);
+
+ scnprintf(ktsk_entry.name, sizeof(ktsk_entry.name), "KTASK%d", cpu);
+ ktsk_entry.virt_addr = (u64)current;
+ ktsk_entry.phys_addr = virt_to_phys((uintptr_t *)current);
+ ktsk_entry.size = sizeof(struct task_struct);
+ if (msm_minidump_add_region(&ktsk_entry))
+ pr_err("Failed to add current task %d in Minidump\n", cpu);
+}
+#endif
+
static void __init async_common_log_init(void *data, async_cookie_t cookie)
{
register_kernel_sections();
diff --git a/include/soc/qcom/minidump.h b/include/soc/qcom/minidump.h
index 5eb18cb1a365..d5970cfef643 100644
--- a/include/soc/qcom/minidump.h
+++ b/include/soc/qcom/minidump.h
@@ -39,11 +39,16 @@ struct md_region {
extern int msm_minidump_add_region(const struct md_region *entry);
/* Sets to true, if minidump table is initialized */
extern bool minidump_enabled;
+extern void dump_stack_minidump(u64 sp);
#else
static inline int msm_minidump_add_region(const struct md_region *entry)
{
/* Return quietly, if minidump is not supported */
return 0;
}
+
+static inline void dump_stack_minidump(u64 sp) {}
#endif
+
+
#endif
diff --git a/kernel/panic.c b/kernel/panic.c
index 679254405510..75f564a94a82 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/nmi.h>
#include <linux/console.h>
+#include <soc/qcom/minidump.h>
#define CREATE_TRACE_POINTS
#include <trace/events/exception.h>
@@ -108,6 +109,7 @@ void panic(const char *fmt, ...)
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
+ dump_stack_minidump(0);
pr_emerg("Kernel panic - not syncing: %s\n", buf);
#ifdef CONFIG_DEBUG_BUGVERBOSE
/*