diff options
-rw-r--r-- | arch/blackfin/include/asm/early_printk.h | 22 | ||||
-rw-r--r-- | arch/blackfin/kernel/bfin_dma_5xx.c | 6 | ||||
-rw-r--r-- | arch/blackfin/kernel/early_printk.c | 74 | ||||
-rw-r--r-- | arch/blackfin/kernel/setup.c | 3 | ||||
-rw-r--r-- | arch/blackfin/kernel/shadow_console.c | 51 | ||||
-rw-r--r-- | arch/blackfin/mach-common/head.S | 11 | ||||
-rw-r--r-- | arch/blackfin/mm/init.c | 3 |
7 files changed, 158 insertions, 12 deletions
diff --git a/arch/blackfin/include/asm/early_printk.h b/arch/blackfin/include/asm/early_printk.h index f5b6b7d972e8..53a762b6fcd2 100644 --- a/arch/blackfin/include/asm/early_printk.h +++ b/arch/blackfin/include/asm/early_printk.h | |||
@@ -21,10 +21,32 @@ | |||
21 | * GNU General Public License for more details. | 21 | * GNU General Public License for more details. |
22 | */ | 22 | */ |
23 | 23 | ||
24 | |||
25 | #ifndef __ASM_EARLY_PRINTK_H__ | ||
26 | #define __ASM_EARLY_PRINTK_H__ | ||
27 | |||
24 | #ifdef CONFIG_EARLY_PRINTK | 28 | #ifdef CONFIG_EARLY_PRINTK |
29 | /* For those that don't include it already */ | ||
30 | #include <linux/console.h> | ||
31 | |||
25 | extern int setup_early_printk(char *); | 32 | extern int setup_early_printk(char *); |
26 | extern void enable_shadow_console(void); | 33 | extern void enable_shadow_console(void); |
34 | extern int shadow_console_enabled(void); | ||
35 | extern void mark_shadow_error(void); | ||
36 | extern void early_shadow_reg(unsigned long reg, unsigned int n); | ||
37 | extern void early_shadow_write(struct console *con, const char *s, | ||
38 | unsigned int n) __attribute__((nonnull(2))); | ||
39 | #define early_shadow_puts(str) early_shadow_write(NULL, str, strlen(str)) | ||
40 | #define early_shadow_stamp() \ | ||
41 | do { \ | ||
42 | early_shadow_puts(__FILE__ " : " __stringify(__LINE__) " ["); \ | ||
43 | early_shadow_puts(__func__); \ | ||
44 | early_shadow_puts("]\n"); \ | ||
45 | } while (0) | ||
27 | #else | 46 | #else |
28 | #define setup_early_printk(fmt) do { } while (0) | 47 | #define setup_early_printk(fmt) do { } while (0) |
29 | #define enable_shadow_console(fmt) do { } while (0) | 48 | #define enable_shadow_console(fmt) do { } while (0) |
49 | #define early_shadow_stamp() do { } while (0) | ||
30 | #endif /* CONFIG_EARLY_PRINTK */ | 50 | #endif /* CONFIG_EARLY_PRINTK */ |
51 | |||
52 | #endif /* __ASM_EARLY_PRINTK_H__ */ | ||
diff --git a/arch/blackfin/kernel/bfin_dma_5xx.c b/arch/blackfin/kernel/bfin_dma_5xx.c index 9f9b82816652..14dea1a87b7c 100644 --- a/arch/blackfin/kernel/bfin_dma_5xx.c +++ b/arch/blackfin/kernel/bfin_dma_5xx.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <asm/cacheflush.h> | 19 | #include <asm/cacheflush.h> |
20 | #include <asm/dma.h> | 20 | #include <asm/dma.h> |
21 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
22 | #include <asm/early_printk.h> | ||
22 | 23 | ||
23 | /* | 24 | /* |
24 | * To make sure we work around 05000119 - we always check DMA_DONE bit, | 25 | * To make sure we work around 05000119 - we always check DMA_DONE bit, |
@@ -236,6 +237,7 @@ void blackfin_dma_resume(void) | |||
236 | */ | 237 | */ |
237 | void __init blackfin_dma_early_init(void) | 238 | void __init blackfin_dma_early_init(void) |
238 | { | 239 | { |
240 | early_shadow_stamp(); | ||
239 | bfin_write_MDMA_S0_CONFIG(0); | 241 | bfin_write_MDMA_S0_CONFIG(0); |
240 | bfin_write_MDMA_S1_CONFIG(0); | 242 | bfin_write_MDMA_S1_CONFIG(0); |
241 | } | 243 | } |
@@ -246,6 +248,8 @@ void __init early_dma_memcpy(void *pdst, const void *psrc, size_t size) | |||
246 | unsigned long src = (unsigned long)psrc; | 248 | unsigned long src = (unsigned long)psrc; |
247 | struct dma_register *dst_ch, *src_ch; | 249 | struct dma_register *dst_ch, *src_ch; |
248 | 250 | ||
251 | early_shadow_stamp(); | ||
252 | |||
249 | /* We assume that everything is 4 byte aligned, so include | 253 | /* We assume that everything is 4 byte aligned, so include |
250 | * a basic sanity check | 254 | * a basic sanity check |
251 | */ | 255 | */ |
@@ -300,6 +304,8 @@ void __init early_dma_memcpy(void *pdst, const void *psrc, size_t size) | |||
300 | 304 | ||
301 | void __init early_dma_memcpy_done(void) | 305 | void __init early_dma_memcpy_done(void) |
302 | { | 306 | { |
307 | early_shadow_stamp(); | ||
308 | |||
303 | while ((bfin_read_MDMA_S0_CONFIG() && !(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)) || | 309 | while ((bfin_read_MDMA_S0_CONFIG() && !(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE)) || |
304 | (bfin_read_MDMA_S1_CONFIG() && !(bfin_read_MDMA_D1_IRQ_STATUS() & DMA_DONE))) | 310 | (bfin_read_MDMA_S1_CONFIG() && !(bfin_read_MDMA_D1_IRQ_STATUS() & DMA_DONE))) |
305 | continue; | 311 | continue; |
diff --git a/arch/blackfin/kernel/early_printk.c b/arch/blackfin/kernel/early_printk.c index 2ab56811841c..931c78b5ea1f 100644 --- a/arch/blackfin/kernel/early_printk.c +++ b/arch/blackfin/kernel/early_printk.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/serial_core.h> | 27 | #include <linux/serial_core.h> |
28 | #include <linux/console.h> | 28 | #include <linux/console.h> |
29 | #include <linux/string.h> | 29 | #include <linux/string.h> |
30 | #include <linux/reboot.h> | ||
30 | #include <asm/blackfin.h> | 31 | #include <asm/blackfin.h> |
31 | #include <asm/irq_handler.h> | 32 | #include <asm/irq_handler.h> |
32 | #include <asm/early_printk.h> | 33 | #include <asm/early_printk.h> |
@@ -181,6 +182,22 @@ asmlinkage void __init init_early_exception_vectors(void) | |||
181 | u32 evt; | 182 | u32 evt; |
182 | SSYNC(); | 183 | SSYNC(); |
183 | 184 | ||
185 | /* | ||
186 | * This starts up the shadow buffer, incase anything crashes before | ||
187 | * setup arch | ||
188 | */ | ||
189 | mark_shadow_error(); | ||
190 | early_shadow_puts(linux_banner); | ||
191 | early_shadow_stamp(); | ||
192 | |||
193 | if (CPUID != bfin_cpuid()) { | ||
194 | early_shadow_puts("Running on wrong machine type, expected"); | ||
195 | early_shadow_reg(CPUID, 16); | ||
196 | early_shadow_puts(", but running on"); | ||
197 | early_shadow_reg(bfin_cpuid(), 16); | ||
198 | early_shadow_puts("\n"); | ||
199 | } | ||
200 | |||
184 | /* cannot program in software: | 201 | /* cannot program in software: |
185 | * evt0 - emulation (jtag) | 202 | * evt0 - emulation (jtag) |
186 | * evt1 - reset | 203 | * evt1 - reset |
@@ -199,6 +216,7 @@ asmlinkage void __init init_early_exception_vectors(void) | |||
199 | 216 | ||
200 | } | 217 | } |
201 | 218 | ||
219 | __attribute__((__noreturn__)) | ||
202 | asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr) | 220 | asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr) |
203 | { | 221 | { |
204 | /* This can happen before the uart is initialized, so initialize | 222 | /* This can happen before the uart is initialized, so initialize |
@@ -210,10 +228,58 @@ asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr) | |||
210 | if (likely(early_console == NULL) && CPUID == bfin_cpuid()) | 228 | if (likely(early_console == NULL) && CPUID == bfin_cpuid()) |
211 | setup_early_printk(DEFAULT_EARLY_PORT); | 229 | setup_early_printk(DEFAULT_EARLY_PORT); |
212 | 230 | ||
213 | printk(KERN_EMERG "Early panic\n"); | 231 | if (!shadow_console_enabled()) { |
214 | dump_bfin_mem(fp); | 232 | /* crap - we crashed before setup_arch() */ |
215 | show_regs(fp); | 233 | early_shadow_puts("panic before setup_arch\n"); |
216 | dump_bfin_trace_buffer(); | 234 | early_shadow_puts("IPEND:"); |
235 | early_shadow_reg(fp->ipend, 16); | ||
236 | if (fp->seqstat & SEQSTAT_EXCAUSE) { | ||
237 | early_shadow_puts("\nEXCAUSE:"); | ||
238 | early_shadow_reg(fp->seqstat & SEQSTAT_EXCAUSE, 8); | ||
239 | } | ||
240 | if (fp->seqstat & SEQSTAT_HWERRCAUSE) { | ||
241 | early_shadow_puts("\nHWERRCAUSE:"); | ||
242 | early_shadow_reg( | ||
243 | (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14, 8); | ||
244 | } | ||
245 | early_shadow_puts("\nErr @"); | ||
246 | if (fp->ipend & EVT_EVX) | ||
247 | early_shadow_reg(fp->retx, 32); | ||
248 | else | ||
249 | early_shadow_reg(fp->pc, 32); | ||
250 | #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON | ||
251 | early_shadow_puts("\nTrace:"); | ||
252 | if (likely(bfin_read_TBUFSTAT() & TBUFCNT)) { | ||
253 | while (bfin_read_TBUFSTAT() & TBUFCNT) { | ||
254 | early_shadow_puts("\nT :"); | ||
255 | early_shadow_reg(bfin_read_TBUF(), 32); | ||
256 | early_shadow_puts("\n S :"); | ||
257 | early_shadow_reg(bfin_read_TBUF(), 32); | ||
258 | } | ||
259 | } | ||
260 | #endif | ||
261 | early_shadow_puts("\nUse bfin-elf-addr2line to determine " | ||
262 | "function names\n"); | ||
263 | /* | ||
264 | * We should panic(), but we can't - since panic calls printk, | ||
265 | * and printk uses memcpy. | ||
266 | * we want to reboot, but if the machine type is different, | ||
267 | * can't due to machine specific reboot sequences | ||
268 | */ | ||
269 | if (CPUID == bfin_cpuid()) { | ||
270 | early_shadow_puts("Trying to restart\n"); | ||
271 | machine_restart(""); | ||
272 | } | ||
273 | |||
274 | early_shadow_puts("Halting, since it is not safe to restart\n"); | ||
275 | while (1) | ||
276 | asm volatile ("EMUEXCPT; IDLE;\n"); | ||
277 | |||
278 | } else { | ||
279 | printk(KERN_EMERG "Early panic\n"); | ||
280 | show_regs(fp); | ||
281 | dump_bfin_trace_buffer(); | ||
282 | } | ||
217 | 283 | ||
218 | panic("Died early"); | 284 | panic("Died early"); |
219 | } | 285 | } |
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 3974764acd2c..f92fffc31689 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c | |||
@@ -187,6 +187,8 @@ void __init bfin_relocate_l1_mem(void) | |||
187 | unsigned long l1_data_b_length; | 187 | unsigned long l1_data_b_length; |
188 | unsigned long l2_length; | 188 | unsigned long l2_length; |
189 | 189 | ||
190 | early_shadow_stamp(); | ||
191 | |||
190 | /* | 192 | /* |
191 | * due to the ALIGN(4) in the arch/blackfin/kernel/vmlinux.lds.S | 193 | * due to the ALIGN(4) in the arch/blackfin/kernel/vmlinux.lds.S |
192 | * we know that everything about l1 text/data is nice and aligned, | 194 | * we know that everything about l1 text/data is nice and aligned, |
@@ -1352,6 +1354,7 @@ const struct seq_operations cpuinfo_op = { | |||
1352 | 1354 | ||
1353 | void __init cmdline_init(const char *r0) | 1355 | void __init cmdline_init(const char *r0) |
1354 | { | 1356 | { |
1357 | early_shadow_stamp(); | ||
1355 | if (r0) | 1358 | if (r0) |
1356 | strncpy(command_line, r0, COMMAND_LINE_SIZE); | 1359 | strncpy(command_line, r0, COMMAND_LINE_SIZE); |
1357 | } | 1360 | } |
diff --git a/arch/blackfin/kernel/shadow_console.c b/arch/blackfin/kernel/shadow_console.c index 15819ff10573..8b8c7107a162 100644 --- a/arch/blackfin/kernel/shadow_console.c +++ b/arch/blackfin/kernel/shadow_console.c | |||
@@ -24,15 +24,18 @@ | |||
24 | 24 | ||
25 | static __initdata char *shadow_console_buffer = (char *)SHADOW_CONSOLE_START; | 25 | static __initdata char *shadow_console_buffer = (char *)SHADOW_CONSOLE_START; |
26 | 26 | ||
27 | static __init void early_shadow_write(struct console *con, const char *s, | 27 | __init void early_shadow_write(struct console *con, const char *s, |
28 | unsigned int n) | 28 | unsigned int n) |
29 | { | 29 | { |
30 | unsigned int i; | ||
30 | /* | 31 | /* |
31 | * save 2 bytes for the double null at the end | 32 | * 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 | * once we fail on a long line, make sure we don't write a short line afterwards |
33 | */ | 34 | */ |
34 | if ((shadow_console_buffer + n) <= (char *)(SHADOW_CONSOLE_END - 2)) { | 35 | if ((shadow_console_buffer + n) <= (char *)(SHADOW_CONSOLE_END - 2)) { |
35 | memcpy(shadow_console_buffer, s, n); | 36 | /* can't use memcpy - it may not be relocated yet */ |
37 | for (i = 0; i <= n; i++) | ||
38 | shadow_console_buffer[i] = s[i]; | ||
36 | shadow_console_buffer += n; | 39 | shadow_console_buffer += n; |
37 | shadow_console_buffer[0] = 0; | 40 | shadow_console_buffer[0] = 0; |
38 | shadow_console_buffer[1] = 0; | 41 | shadow_console_buffer[1] = 0; |
@@ -48,16 +51,24 @@ static __initdata struct console early_shadow_console = { | |||
48 | .device = 0, | 51 | .device = 0, |
49 | }; | 52 | }; |
50 | 53 | ||
51 | __init void enable_shadow_console(void) | 54 | __init int shadow_console_enabled(void) |
55 | { | ||
56 | return early_shadow_console.flags & CON_ENABLED; | ||
57 | } | ||
58 | |||
59 | __init void mark_shadow_error(void) | ||
52 | { | 60 | { |
53 | int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC; | 61 | int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC; |
62 | loc[0] = SHADOW_CONSOLE_MAGIC; | ||
63 | loc[1] = SHADOW_CONSOLE_START; | ||
64 | } | ||
54 | 65 | ||
55 | if (!(early_shadow_console.flags & CON_ENABLED)) { | 66 | __init void enable_shadow_console(void) |
67 | { | ||
68 | if (!shadow_console_enabled()) { | ||
56 | register_console(&early_shadow_console); | 69 | register_console(&early_shadow_console); |
57 | /* for now, assume things are going to fail */ | 70 | /* for now, assume things are going to fail */ |
58 | *loc = SHADOW_CONSOLE_MAGIC; | 71 | mark_shadow_error(); |
59 | loc++; | ||
60 | *loc = SHADOW_CONSOLE_START; | ||
61 | } | 72 | } |
62 | } | 73 | } |
63 | 74 | ||
@@ -71,8 +82,32 @@ static __init int disable_shadow_console(void) | |||
71 | */ | 82 | */ |
72 | int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC; | 83 | int *loc = (int *)SHADOW_CONSOLE_MAGIC_LOC; |
73 | 84 | ||
74 | *loc = 0; | 85 | loc[0] = 0; |
75 | 86 | ||
76 | return 0; | 87 | return 0; |
77 | } | 88 | } |
78 | pure_initcall(disable_shadow_console); | 89 | pure_initcall(disable_shadow_console); |
90 | |||
91 | /* | ||
92 | * since we can't use printk, dump numbers (as hex), n = # bits | ||
93 | */ | ||
94 | __init void early_shadow_reg(unsigned long reg, unsigned int n) | ||
95 | { | ||
96 | /* | ||
97 | * can't use any "normal" kernel features, since thay | ||
98 | * may not be relocated to their execute address yet | ||
99 | */ | ||
100 | int i; | ||
101 | char ascii[11] = " 0x"; | ||
102 | |||
103 | n = n / 4; | ||
104 | reg = reg << ((8 - n) * 4); | ||
105 | n += 3; | ||
106 | |||
107 | for (i = 3; i <= n ; i++) { | ||
108 | ascii[i] = hex_asc_lo(reg >> 28); | ||
109 | reg <<= 4; | ||
110 | } | ||
111 | early_shadow_write(NULL, ascii, n); | ||
112 | |||
113 | } | ||
diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S index f826f6b9f917..66910121fa6f 100644 --- a/arch/blackfin/mach-common/head.S +++ b/arch/blackfin/mach-common/head.S | |||
@@ -153,6 +153,8 @@ ENTRY(__start) | |||
153 | 153 | ||
154 | #ifdef CONFIG_EARLY_PRINTK | 154 | #ifdef CONFIG_EARLY_PRINTK |
155 | call _init_early_exception_vectors; | 155 | call _init_early_exception_vectors; |
156 | r0 = (EVT_IVHW | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU); | ||
157 | sti r0; | ||
156 | #endif | 158 | #endif |
157 | 159 | ||
158 | r0 = 0 (x); | 160 | r0 = 0 (x); |
@@ -212,12 +214,21 @@ ENTRY(__start) | |||
212 | [p0] = p1; | 214 | [p0] = p1; |
213 | csync; | 215 | csync; |
214 | 216 | ||
217 | #ifdef CONFIG_EARLY_PRINTK | ||
218 | r0 = (EVT_IVG15 | EVT_IVHW | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU) (z); | ||
219 | #else | ||
215 | r0 = EVT_IVG15 (z); | 220 | r0 = EVT_IVG15 (z); |
221 | #endif | ||
216 | sti r0; | 222 | sti r0; |
217 | 223 | ||
218 | raise 15; | 224 | raise 15; |
225 | #ifdef CONFIG_EARLY_PRINTK | ||
226 | p0.l = _early_trap; | ||
227 | p0.h = _early_trap; | ||
228 | #else | ||
219 | p0.l = .LWAIT_HERE; | 229 | p0.l = .LWAIT_HERE; |
220 | p0.h = .LWAIT_HERE; | 230 | p0.h = .LWAIT_HERE; |
231 | #endif | ||
221 | reti = p0; | 232 | reti = p0; |
222 | #if ANOMALY_05000281 | 233 | #if ANOMALY_05000281 |
223 | nop; nop; nop; | 234 | nop; nop; nop; |
diff --git a/arch/blackfin/mm/init.c b/arch/blackfin/mm/init.c index 68bd0bd680cd..b88ce7fda548 100644 --- a/arch/blackfin/mm/init.c +++ b/arch/blackfin/mm/init.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <asm/bfin-global.h> | 33 | #include <asm/bfin-global.h> |
34 | #include <asm/pda.h> | 34 | #include <asm/pda.h> |
35 | #include <asm/cplbinit.h> | 35 | #include <asm/cplbinit.h> |
36 | #include <asm/early_printk.h> | ||
36 | #include "blackfin_sram.h" | 37 | #include "blackfin_sram.h" |
37 | 38 | ||
38 | /* | 39 | /* |
@@ -113,6 +114,8 @@ asmlinkage void __init init_pda(void) | |||
113 | { | 114 | { |
114 | unsigned int cpu = raw_smp_processor_id(); | 115 | unsigned int cpu = raw_smp_processor_id(); |
115 | 116 | ||
117 | early_shadow_stamp(); | ||
118 | |||
116 | /* Initialize the PDA fields holding references to other parts | 119 | /* Initialize the PDA fields holding references to other parts |
117 | of the memory. The content of such memory is still | 120 | of the memory. The content of such memory is still |
118 | undefined at the time of the call, we are only setting up | 121 | undefined at the time of the call, we are only setting up |