diff options
author | Robin Getz <robin.getz@analog.com> | 2009-07-06 10:53:19 -0400 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2009-09-16 21:31:43 -0400 |
commit | 3f871feaf3390c6d6e578818f867917c2e4738a2 (patch) | |
tree | 3b7ebc72793903361bb4b108bd829b21ede3fc01 | |
parent | 53e18df745b6f833df07ead62ded09ebae3b0303 (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.h | 2 | ||||
-rw-r--r-- | arch/blackfin/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/blackfin/kernel/setup.c | 2 | ||||
-rw-r--r-- | arch/blackfin/kernel/shadow_console.c | 78 |
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 110f1c1f845c..f5b6b7d972e8 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 |
25 | extern int setup_early_printk(char *); | 25 | extern int setup_early_printk(char *); |
26 | extern 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 141d9281e4b0..a8ddbc8ed5af 100644 --- a/arch/blackfin/kernel/Makefile +++ b/arch/blackfin/kernel/Makefile | |||
@@ -26,6 +26,7 @@ obj-$(CONFIG_MODULES) += module.o | |||
26 | obj-$(CONFIG_KGDB) += kgdb.o | 26 | obj-$(CONFIG_KGDB) += kgdb.o |
27 | obj-$(CONFIG_KGDB_TESTS) += kgdb_test.o | 27 | obj-$(CONFIG_KGDB_TESTS) += kgdb_test.o |
28 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | 28 | obj-$(CONFIG_EARLY_PRINTK) += early_printk.o |
29 | obj-$(CONFIG_EARLY_PRINTK) += shadow_console.o | ||
29 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | 30 | obj-$(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 6dbf21930a91..3974764acd2c 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 000000000000..15819ff10573 --- /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 | |||
25 | static __initdata char *shadow_console_buffer = (char *)SHADOW_CONSOLE_START; | ||
26 | |||
27 | static __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 | |||
43 | static __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 | |||
64 | static __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 | } | ||
78 | pure_initcall(disable_shadow_console); | ||