linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 1/2] arm: process: dump memory around registers when displaying regs
@ 2017-04-25 13:44 Enric Balletbo i Serra
  2017-04-25 13:44 ` [PATCH v2 2/2] arm64: " Enric Balletbo i Serra
  2017-05-29  9:23 ` [PATCH v2 1/2] arm: " Enric Balletbo Serra
  0 siblings, 2 replies; 3+ messages in thread
From: Enric Balletbo i Serra @ 2017-04-25 13:44 UTC (permalink / raw)
  To: Russell King
  Cc: John Stultz, Michael Davidson, San Mehat, Greg Hackmann,
	linux-arm-kernel, linux-kernel

Dump a block of kernel memory from around the registers in the kernel oops
dump. This is behind a config option (DEBUG_AROUND_REGS), since it adds
a bunch of noise to the kernel logs (which someone can find valuable but
not everyone else will).

This is extremely useful in diagnosing remote crashes, and is based heavily
on original work by Michael Davidson <md@google.com> and San Mehat
<san@google.com>.

Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
---
This is a second version of a patch that was initially sent by John Stultz
in 2010[1], current version is a rework trying to address the feedback
received in the first version. We're still carrying this patch on recent
chromeos kernels and find it useful. This is a second attempt to try
to get this acceptable, so waiting for your feedback, and I hope I'll be
able to do the modifications needed.

Changes since v1:
 - Use dump_mem() to dump memory.
 - Put the code behind a config option.

[1] http://www.spinics.net/lists/arm-kernel/msg107477.html
---
 arch/arm/include/asm/traps.h |  1 +
 arch/arm/kernel/process.c    | 34 ++++++++++++++++++++++++++++++++++
 arch/arm/kernel/traps.c      |  6 ++----
 lib/Kconfig.debug            | 11 +++++++++++
 4 files changed, 48 insertions(+), 4 deletions(-)

diff --git a/arch/arm/include/asm/traps.h b/arch/arm/include/asm/traps.h
index f555bb3..24e65c2 100644
--- a/arch/arm/include/asm/traps.h
+++ b/arch/arm/include/asm/traps.h
@@ -47,6 +47,7 @@ static inline int in_exception_text(unsigned long ptr)
 }
 
 extern void __init early_trap_init(void *);
+extern void dump_mem(const char *lvl, const char *str, unsigned long bottom, unsigned long top);
 extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame);
 extern void ptrace_break(struct task_struct *tsk, struct pt_regs *regs);
 
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 939e8b5..3894cf2 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -34,6 +34,7 @@
 
 #include <asm/processor.h>
 #include <asm/thread_notify.h>
+#include <asm/traps.h>
 #include <asm/stacktrace.h>
 #include <asm/system_misc.h>
 #include <asm/mach/time.h>
@@ -94,6 +95,37 @@ void arch_cpu_idle_exit(void)
 	ledtrig_cpu(CPU_LED_IDLE_END);
 }
 
+/*
+ * Dump a block of kernel memory from around the given address
+ */
+static void __show_regs_extra_data(struct pt_regs *regs, int nbytes)
+{
+#ifdef CONFIG_DEBUG_AROUND_REGS
+	struct map_regs {
+		unsigned long reg;
+		const char *name;
+	};
+	struct map_regs map_dump[] = {
+		{ regs->ARM_pc, "PC " }, { regs->ARM_lr, "LR " },
+		{ regs->ARM_sp, "SP " }, { regs->ARM_ip, "IP " },
+		{ regs->ARM_fp, "FP " }, { regs->ARM_r0, "R0 " },
+		{ regs->ARM_r1, "R1 " }, { regs->ARM_r2, "R2 " },
+		{ regs->ARM_r3, "R3 " }, { regs->ARM_r4, "R4 " },
+		{ regs->ARM_r5, "R5 " }, { regs->ARM_r6, "R6 " },
+		{ regs->ARM_r7, "R7 " }, { regs->ARM_r8, "R8 " },
+		{ regs->ARM_r9, "R9 " }, { regs->ARM_r10, "R10 " },
+		{ -1, NULL },
+	};
+	struct map_regs *map = map_dump;
+
+	while (map->name) {
+		dump_mem("", map->name, map->reg - nbytes,
+			 map->reg + nbytes);
+		map++;
+	}
+#endif
+}
+
 void __show_regs(struct pt_regs *regs)
 {
 	unsigned long flags;
@@ -185,6 +217,8 @@ void __show_regs(struct pt_regs *regs)
 		printk("Control: %08x%s\n", ctrl, buf);
 	}
 #endif
+
+	__show_regs_extra_data(regs, 128);
 }
 
 void show_regs(struct pt_regs * regs)
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 948c648..f4ee05b 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -62,8 +62,6 @@ static int __init user_debug_setup(char *str)
 __setup("user_debug=", user_debug_setup);
 #endif
 
-static void dump_mem(const char *, const char *, unsigned long, unsigned long);
-
 void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame)
 {
 #ifdef CONFIG_KALLSYMS
@@ -115,8 +113,8 @@ static int verify_stack(unsigned long sp)
 /*
  * Dump out the contents of some memory nicely...
  */
-static void dump_mem(const char *lvl, const char *str, unsigned long bottom,
-		     unsigned long top)
+void dump_mem(const char *lvl, const char *str, unsigned long bottom,
+	      unsigned long top)
 {
 	unsigned long first;
 	mm_segment_t fs;
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 77fadfa..b72d4ce6 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -726,6 +726,17 @@ config DEBUG_STACKOVERFLOW
 
 	  If in doubt, say "N".
 
+config DEBUG_AROUND_REGS
+	bool "Dump a block of kernel memory from around registers"
+	depends on DEBUG_KERNEL
+	help
+	  Say Y here to dump a block of kernel memory around the registers
+	  in the kernel oops dump. This is useful in diagnosing remote
+	  crashes.
+
+	  Note that selecting this option will increase significally the
+	  information in the oops dump. Most people should say N here.
+
 source "lib/Kconfig.kmemcheck"
 
 source "lib/Kconfig.kasan"
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH v2 2/2] arm64: process: dump memory around registers when displaying regs
  2017-04-25 13:44 [PATCH v2 1/2] arm: process: dump memory around registers when displaying regs Enric Balletbo i Serra
@ 2017-04-25 13:44 ` Enric Balletbo i Serra
  2017-05-29  9:23 ` [PATCH v2 1/2] arm: " Enric Balletbo Serra
  1 sibling, 0 replies; 3+ messages in thread
From: Enric Balletbo i Serra @ 2017-04-25 13:44 UTC (permalink / raw)
  To: Russell King
  Cc: John Stultz, Michael Davidson, San Mehat, Greg Hackmann,
	linux-arm-kernel, linux-kernel

From: Greg Hackmann <ghackmann@google.com>

Dump a block of kernel memory from around the registers in the kernel oops
dump. This is behind a config option (DEBUG_AROUND_REGS), since it adds
a bunch of noise to the kernel logs (which someone can find valuable but
not everyone else will).

This is extremely useful in diagnosing remote crashes, and is based heavily
on original work by Michael Davidson <md@google.com> and San Mehat
<san@google.com>.

Signed-off-by: Greg Hackmann <ghackmann@google.com>
[rework to use dump_mem]
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
---
Same as 1/2 but for arm64 architecture.

Changes since v1:
 - Did not exists.
---
 arch/arm64/include/asm/traps.h |  3 +++
 arch/arm64/kernel/process.c    | 26 ++++++++++++++++++++++++++
 arch/arm64/kernel/traps.c      |  4 ++--
 3 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h
index 02e9035..140f642 100644
--- a/arch/arm64/include/asm/traps.h
+++ b/arch/arm64/include/asm/traps.h
@@ -60,4 +60,7 @@ static inline int in_exception_text(unsigned long ptr)
 	return in ? : __in_irqentry_text(ptr);
 }
 
+void dump_mem(const char *lvl, const char *str, unsigned long bottom,
+	      unsigned long top);
+
 #endif
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index ae2a835..5ee2f48 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -58,6 +58,7 @@
 #include <asm/mmu_context.h>
 #include <asm/processor.h>
 #include <asm/stacktrace.h>
+#include <asm/traps.h>
 
 #ifdef CONFIG_CC_STACKPROTECTOR
 #include <linux/stackprotector.h>
@@ -170,6 +171,28 @@ void machine_restart(char *cmd)
 	while (1);
 }
 
+/*
+ * Dump a block of kernel memory from around the given address
+ */
+static void __show_regs_extra_data(struct pt_regs *regs, int nbytes)
+{
+#ifdef CONFIG_DEBUG_AROUND_REGS
+	int i;
+
+	dump_mem("", "PC ", regs->pc - nbytes, regs->pc + nbytes);
+	dump_mem("", "LR ", regs->regs[30] - nbytes, regs->regs[30] + nbytes);
+	dump_mem("", "SP ", regs->sp - nbytes, regs->sp + nbytes);
+
+	for (i = 0; i < 30; i++) {
+		char name[4];
+
+		snprintf(name, sizeof(name), "X%u", i);
+		dump_mem("", name, regs->regs[i] - nbytes,
+			 regs->regs[i] + nbytes);
+	}
+#endif
+}
+
 void __show_regs(struct pt_regs *regs)
 {
 	int i, top_reg;
@@ -205,6 +228,9 @@ void __show_regs(struct pt_regs *regs)
 
 		pr_cont("\n");
 	}
+
+	if (!user_mode(regs))
+		__show_regs_extra_data(regs, 128);
 }
 
 void show_regs(struct pt_regs * regs)
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 1de444e..6d07675 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -59,8 +59,8 @@ int show_unhandled_signals = 1;
 /*
  * Dump out the contents of some kernel memory nicely...
  */
-static void dump_mem(const char *lvl, const char *str, unsigned long bottom,
-		     unsigned long top)
+void dump_mem(const char *lvl, const char *str, unsigned long bottom,
+	      unsigned long top)
 {
 	unsigned long first;
 	mm_segment_t fs;
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v2 1/2] arm: process: dump memory around registers when displaying regs
  2017-04-25 13:44 [PATCH v2 1/2] arm: process: dump memory around registers when displaying regs Enric Balletbo i Serra
  2017-04-25 13:44 ` [PATCH v2 2/2] arm64: " Enric Balletbo i Serra
@ 2017-05-29  9:23 ` Enric Balletbo Serra
  1 sibling, 0 replies; 3+ messages in thread
From: Enric Balletbo Serra @ 2017-05-29  9:23 UTC (permalink / raw)
  To: Enric Balletbo i Serra
  Cc: Russell King, John Stultz, Michael Davidson, San Mehat,
	Greg Hackmann, linux-arm-kernel, linux-kernel

2017-04-25 15:44 GMT+02:00 Enric Balletbo i Serra
<enric.balletbo@collabora.com>:
> Dump a block of kernel memory from around the registers in the kernel oops
> dump. This is behind a config option (DEBUG_AROUND_REGS), since it adds
> a bunch of noise to the kernel logs (which someone can find valuable but
> not everyone else will).
>
> This is extremely useful in diagnosing remote crashes, and is based heavily
> on original work by Michael Davidson <md@google.com> and San Mehat
> <san@google.com>.
>
> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
> ---
> This is a second version of a patch that was initially sent by John Stultz
> in 2010[1], current version is a rework trying to address the feedback
> received in the first version. We're still carrying this patch on recent
> chromeos kernels and find it useful. This is a second attempt to try
> to get this acceptable, so waiting for your feedback, and I hope I'll be
> able to do the modifications needed.
>
> Changes since v1:
>  - Use dump_mem() to dump memory.
>  - Put the code behind a config option.
>
> [1] http://www.spinics.net/lists/arm-kernel/msg107477.html
> ---
>  arch/arm/include/asm/traps.h |  1 +
>  arch/arm/kernel/process.c    | 34 ++++++++++++++++++++++++++++++++++
>  arch/arm/kernel/traps.c      |  6 ++----
>  lib/Kconfig.debug            | 11 +++++++++++
>  4 files changed, 48 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm/include/asm/traps.h b/arch/arm/include/asm/traps.h
> index f555bb3..24e65c2 100644
> --- a/arch/arm/include/asm/traps.h
> +++ b/arch/arm/include/asm/traps.h
> @@ -47,6 +47,7 @@ static inline int in_exception_text(unsigned long ptr)
>  }
>
>  extern void __init early_trap_init(void *);
> +extern void dump_mem(const char *lvl, const char *str, unsigned long bottom, unsigned long top);
>  extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame);
>  extern void ptrace_break(struct task_struct *tsk, struct pt_regs *regs);
>
> diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
> index 939e8b5..3894cf2 100644
> --- a/arch/arm/kernel/process.c
> +++ b/arch/arm/kernel/process.c
> @@ -34,6 +34,7 @@
>
>  #include <asm/processor.h>
>  #include <asm/thread_notify.h>
> +#include <asm/traps.h>
>  #include <asm/stacktrace.h>
>  #include <asm/system_misc.h>
>  #include <asm/mach/time.h>
> @@ -94,6 +95,37 @@ void arch_cpu_idle_exit(void)
>         ledtrig_cpu(CPU_LED_IDLE_END);
>  }
>
> +/*
> + * Dump a block of kernel memory from around the given address
> + */
> +static void __show_regs_extra_data(struct pt_regs *regs, int nbytes)
> +{
> +#ifdef CONFIG_DEBUG_AROUND_REGS
> +       struct map_regs {
> +               unsigned long reg;
> +               const char *name;
> +       };
> +       struct map_regs map_dump[] = {
> +               { regs->ARM_pc, "PC " }, { regs->ARM_lr, "LR " },
> +               { regs->ARM_sp, "SP " }, { regs->ARM_ip, "IP " },
> +               { regs->ARM_fp, "FP " }, { regs->ARM_r0, "R0 " },
> +               { regs->ARM_r1, "R1 " }, { regs->ARM_r2, "R2 " },
> +               { regs->ARM_r3, "R3 " }, { regs->ARM_r4, "R4 " },
> +               { regs->ARM_r5, "R5 " }, { regs->ARM_r6, "R6 " },
> +               { regs->ARM_r7, "R7 " }, { regs->ARM_r8, "R8 " },
> +               { regs->ARM_r9, "R9 " }, { regs->ARM_r10, "R10 " },
> +               { -1, NULL },
> +       };
> +       struct map_regs *map = map_dump;
> +
> +       while (map->name) {
> +               dump_mem("", map->name, map->reg - nbytes,
> +                        map->reg + nbytes);
> +               map++;
> +       }
> +#endif
> +}
> +
>  void __show_regs(struct pt_regs *regs)
>  {
>         unsigned long flags;
> @@ -185,6 +217,8 @@ void __show_regs(struct pt_regs *regs)
>                 printk("Control: %08x%s\n", ctrl, buf);
>         }
>  #endif
> +
> +       __show_regs_extra_data(regs, 128);
>  }
>
>  void show_regs(struct pt_regs * regs)
> diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
> index 948c648..f4ee05b 100644
> --- a/arch/arm/kernel/traps.c
> +++ b/arch/arm/kernel/traps.c
> @@ -62,8 +62,6 @@ static int __init user_debug_setup(char *str)
>  __setup("user_debug=", user_debug_setup);
>  #endif
>
> -static void dump_mem(const char *, const char *, unsigned long, unsigned long);
> -
>  void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame)
>  {
>  #ifdef CONFIG_KALLSYMS
> @@ -115,8 +113,8 @@ static int verify_stack(unsigned long sp)
>  /*
>   * Dump out the contents of some memory nicely...
>   */
> -static void dump_mem(const char *lvl, const char *str, unsigned long bottom,
> -                    unsigned long top)
> +void dump_mem(const char *lvl, const char *str, unsigned long bottom,
> +             unsigned long top)
>  {
>         unsigned long first;
>         mm_segment_t fs;
> diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
> index 77fadfa..b72d4ce6 100644
> --- a/lib/Kconfig.debug
> +++ b/lib/Kconfig.debug
> @@ -726,6 +726,17 @@ config DEBUG_STACKOVERFLOW
>
>           If in doubt, say "N".
>
> +config DEBUG_AROUND_REGS
> +       bool "Dump a block of kernel memory from around registers"
> +       depends on DEBUG_KERNEL
> +       help
> +         Say Y here to dump a block of kernel memory around the registers
> +         in the kernel oops dump. This is useful in diagnosing remote
> +         crashes.
> +
> +         Note that selecting this option will increase significally the
> +         information in the oops dump. Most people should say N here.
> +
>  source "lib/Kconfig.kmemcheck"
>
>  source "lib/Kconfig.kasan"
> --
> 2.9.3
>

Currently this patch might need to be rebased on top of linux-next,
but before do
this can I ask for some feedback on these patches. Thoughts?

Many thanks,
 Enric

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2017-05-29  9:23 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-25 13:44 [PATCH v2 1/2] arm: process: dump memory around registers when displaying regs Enric Balletbo i Serra
2017-04-25 13:44 ` [PATCH v2 2/2] arm64: " Enric Balletbo i Serra
2017-05-29  9:23 ` [PATCH v2 1/2] arm: " Enric Balletbo Serra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).