aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobin Getz <robin.getz@analog.com>2009-07-06 10:53:19 -0400
committerMike Frysinger <vapier@gentoo.org>2009-09-16 21:31:43 -0400
commit3f871feaf3390c6d6e578818f867917c2e4738a2 (patch)
tree3b7ebc72793903361bb4b108bd829b21ede3fc01
parent53e18df745b6f833df07ead62ded09ebae3b0303 (diff)
Blackfin: add an early shadow console
Add a memory based shadow console to keep a copy of the printk buffer in a location which can be found externally. This allows bootloaders to locate and utilize the log buffer in case of silent (early/resume/etc...) crashes. Signed-off-by: Robin Getz <robin.getz@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
-rw-r--r--arch/blackfin/include/asm/early_printk.h2
-rw-r--r--arch/blackfin/kernel/Makefile1
-rw-r--r--arch/blackfin/kernel/setup.c2
-rw-r--r--arch/blackfin/kernel/shadow_console.c78
4 files changed, 83 insertions, 0 deletions
diff --git a/arch/blackfin/include/asm/early_printk.h b/arch/blackfin/include/asm/early_printk.h
index 110f1c1f845..f5b6b7d972e 100644
--- a/arch/blackfin/include/asm/early_printk.h
+++ b/arch/blackfin/include/asm/early_printk.h
@@ -23,6 +23,8 @@
23 23
24#ifdef CONFIG_EARLY_PRINTK 24#ifdef CONFIG_EARLY_PRINTK
25extern int setup_early_printk(char *); 25extern int setup_early_printk(char *);
26extern void enable_shadow_console(void);
26#else 27#else
27#define setup_early_printk(fmt) do { } while (0) 28#define setup_early_printk(fmt) do { } while (0)
29#define enable_shadow_console(fmt) do { } while (0)
28#endif /* CONFIG_EARLY_PRINTK */ 30#endif /* CONFIG_EARLY_PRINTK */
diff --git a/arch/blackfin/kernel/Makefile b/arch/blackfin/kernel/Makefile
index 141d9281e4b..a8ddbc8ed5a 100644
--- a/arch/blackfin/kernel/Makefile
+++ b/arch/blackfin/kernel/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_MODULES) += module.o
26obj-$(CONFIG_KGDB) += kgdb.o 26obj-$(CONFIG_KGDB) += kgdb.o
27obj-$(CONFIG_KGDB_TESTS) += kgdb_test.o 27obj-$(CONFIG_KGDB_TESTS) += kgdb_test.o
28obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 28obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
29obj-$(CONFIG_EARLY_PRINTK) += shadow_console.o
29obj-$(CONFIG_STACKTRACE) += stacktrace.o 30obj-$(CONFIG_STACKTRACE) += stacktrace.o
30 31
31# the kgdb test puts code into L2 and without linker 32# the kgdb test puts code into L2 and without linker
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c
index 6dbf21930a9..3974764acd2 100644
--- a/arch/blackfin/kernel/setup.c
+++ b/arch/blackfin/kernel/setup.c
@@ -810,6 +810,8 @@ void __init setup_arch(char **cmdline_p)
810{ 810{
811 unsigned long sclk, cclk; 811 unsigned long sclk, cclk;
812 812
813 enable_shadow_console();
814
813 /* Check to make sure we are running on the right processor */ 815 /* Check to make sure we are running on the right processor */
814 if (unlikely(CPUID != bfin_cpuid())) 816 if (unlikely(CPUID != bfin_cpuid()))
815 printk(KERN_ERR "ERROR: Not running on ADSP-%s: unknown CPUID 0x%04x Rev 0.%d\n", 817 printk(KERN_ERR "ERROR: Not running on ADSP-%s: unknown CPUID 0x%04x Rev 0.%d\n",
diff --git a/arch/blackfin/kernel/shadow_console.c b/arch/blackfin/kernel/shadow_console.c
new file mode 100644
index 00000000000..15819ff1057
--- /dev/null
+++ b/arch/blackfin/kernel/shadow_console.c
@@ -0,0 +1,78 @@
1/*
2 * manage a small early shadow of the log buffer which we can pass between the
3 * bootloader so early crash messages are communicated properly and easily
4 *
5 * Copyright 2009 Analog Devices Inc.
6 *
7 * Enter bugs at http://blackfin.uclinux.org/
8 *
9 * Licensed under the GPL-2 or later.
10 */
11
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/console.h>
15#include <linux/string.h>
16#include <asm/blackfin.h>
17#include <asm/irq_handler.h>
18#include <asm/early_printk.h>
19
20#define SHADOW_CONSOLE_START (0x500)
21#define SHADOW_CONSOLE_END (0x1000)
22#define SHADOW_CONSOLE_MAGIC_LOC (0x4F0)
23#define SHADOW_CONSOLE_MAGIC (0xDEADBEEF)
24
25static __initdata char *shadow_console_buffer = (char *)SHADOW_CONSOLE_START;
26
27static __init void early_shadow_write(struct console *con, const char *s,
28 unsigned int n)
29{
30 /*
31 * save 2 bytes for the double null at the end
32 * once we fail on a long line, make sure we don't write a short line afterwards
33 */
34 if ((shadow_console_buffer + n) <= (char *)(SHADOW_CONSOLE_END - 2)) {
35 memcpy(shadow_console_buffer, s, n);
36 shadow_console_buffer += n;
37 shadow_console_buffer[0] = 0;
38 shadow_console_buffer[1] = 0;
39 } else
40 shadow_console_buffer = (char *)SHADOW_CONSOLE_END;
41}
42
43static __initdata struct console early_shadow_console = {
44 .name = "early_shadow",
45 .write = early_shadow_write,
46 .flags = CON_BOOT | CON_PRINTBUFFER,
47 .index = -1,
48 .device = 0,
49};
50
51__init void enable_shadow_console(void)
52{
53 int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC;
54
55 if (!(early_shadow_console.flags & CON_ENABLED)) {
56 register_console(&early_shadow_console);
57 /* for now, assume things are going to fail */
58 *loc = SHADOW_CONSOLE_MAGIC;
59 loc++;
60 *loc = SHADOW_CONSOLE_START;
61 }
62}
63
64static __init int disable_shadow_console(void)
65{
66 /*
67 * by the time pure_initcall runs, the standard console is enabled,
68 * and the early_console is off, so unset the magic numbers
69 * unregistering the console is taken care of in common code (See
70 * ./kernel/printk:disable_boot_consoles() )
71 */
72 int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC;
73
74 *loc = 0;
75
76 return 0;
77}
78pure_initcall(disable_shadow_console);