diff options
Diffstat (limited to 'arch/blackfin/kernel')
-rw-r--r-- | arch/blackfin/kernel/asm-offsets.c | 1 | ||||
-rw-r--r-- | arch/blackfin/kernel/bfin_gpio.c | 9 | ||||
-rw-r--r-- | arch/blackfin/kernel/cplb-mpu/cplbinit.c | 12 | ||||
-rw-r--r-- | arch/blackfin/kernel/cplb-mpu/cplbmgr.c | 14 | ||||
-rw-r--r-- | arch/blackfin/kernel/cplb-nompu/cplbinit.c | 6 | ||||
-rw-r--r-- | arch/blackfin/kernel/early_printk.c | 12 | ||||
-rw-r--r-- | arch/blackfin/kernel/kgdb.c | 711 | ||||
-rw-r--r-- | arch/blackfin/kernel/ptrace.c | 215 | ||||
-rw-r--r-- | arch/blackfin/kernel/reboot.c | 18 | ||||
-rw-r--r-- | arch/blackfin/kernel/setup.c | 97 | ||||
-rw-r--r-- | arch/blackfin/kernel/traps.c | 367 |
11 files changed, 987 insertions, 475 deletions
diff --git a/arch/blackfin/kernel/asm-offsets.c b/arch/blackfin/kernel/asm-offsets.c index 881afe9082c7..9bb85dd5ccb3 100644 --- a/arch/blackfin/kernel/asm-offsets.c +++ b/arch/blackfin/kernel/asm-offsets.c | |||
@@ -60,6 +60,7 @@ int main(void) | |||
60 | DEFINE(KERNEL_STACK_SIZE, THREAD_SIZE); | 60 | DEFINE(KERNEL_STACK_SIZE, THREAD_SIZE); |
61 | 61 | ||
62 | /* offsets into the pt_regs */ | 62 | /* offsets into the pt_regs */ |
63 | DEFINE(PT_ORIG_R0, offsetof(struct pt_regs, orig_r0)); | ||
63 | DEFINE(PT_ORIG_P0, offsetof(struct pt_regs, orig_p0)); | 64 | DEFINE(PT_ORIG_P0, offsetof(struct pt_regs, orig_p0)); |
64 | DEFINE(PT_ORIG_PC, offsetof(struct pt_regs, orig_pc)); | 65 | DEFINE(PT_ORIG_PC, offsetof(struct pt_regs, orig_pc)); |
65 | DEFINE(PT_R0, offsetof(struct pt_regs, r0)); | 66 | DEFINE(PT_R0, offsetof(struct pt_regs, r0)); |
diff --git a/arch/blackfin/kernel/bfin_gpio.c b/arch/blackfin/kernel/bfin_gpio.c index ecbd141e0ef2..6e08f425bb44 100644 --- a/arch/blackfin/kernel/bfin_gpio.c +++ b/arch/blackfin/kernel/bfin_gpio.c | |||
@@ -231,14 +231,14 @@ inline int check_gpio(unsigned gpio) | |||
231 | } | 231 | } |
232 | #endif | 232 | #endif |
233 | 233 | ||
234 | void gpio_error(unsigned gpio) | 234 | static void gpio_error(unsigned gpio) |
235 | { | 235 | { |
236 | printk(KERN_ERR "bfin-gpio: GPIO %d wasn't requested!\n", gpio); | 236 | printk(KERN_ERR "bfin-gpio: GPIO %d wasn't requested!\n", gpio); |
237 | } | 237 | } |
238 | 238 | ||
239 | static void set_label(unsigned short ident, const char *label) | 239 | static void set_label(unsigned short ident, const char *label) |
240 | { | 240 | { |
241 | if (label && str_ident) { | 241 | if (label) { |
242 | strncpy(str_ident[ident].name, label, | 242 | strncpy(str_ident[ident].name, label, |
243 | RESOURCE_LABEL_SIZE); | 243 | RESOURCE_LABEL_SIZE); |
244 | str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0; | 244 | str_ident[ident].name[RESOURCE_LABEL_SIZE - 1] = 0; |
@@ -247,9 +247,6 @@ static void set_label(unsigned short ident, const char *label) | |||
247 | 247 | ||
248 | static char *get_label(unsigned short ident) | 248 | static char *get_label(unsigned short ident) |
249 | { | 249 | { |
250 | if (!str_ident) | ||
251 | return "UNKNOWN"; | ||
252 | |||
253 | return (*str_ident[ident].name ? str_ident[ident].name : "UNKNOWN"); | 250 | return (*str_ident[ident].name ? str_ident[ident].name : "UNKNOWN"); |
254 | } | 251 | } |
255 | 252 | ||
@@ -260,7 +257,7 @@ static int cmp_label(unsigned short ident, const char *label) | |||
260 | printk(KERN_ERR "Please provide none-null label\n"); | 257 | printk(KERN_ERR "Please provide none-null label\n"); |
261 | } | 258 | } |
262 | 259 | ||
263 | if (label && str_ident) | 260 | if (label) |
264 | return strncmp(str_ident[ident].name, | 261 | return strncmp(str_ident[ident].name, |
265 | label, strlen(label)); | 262 | label, strlen(label)); |
266 | else | 263 | else |
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbinit.c b/arch/blackfin/kernel/cplb-mpu/cplbinit.c index 48060105346a..55af729f8495 100644 --- a/arch/blackfin/kernel/cplb-mpu/cplbinit.c +++ b/arch/blackfin/kernel/cplb-mpu/cplbinit.c | |||
@@ -36,7 +36,7 @@ struct cplb_entry dcplb_tbl[MAX_CPLBS]; | |||
36 | int first_switched_icplb, first_switched_dcplb; | 36 | int first_switched_icplb, first_switched_dcplb; |
37 | int first_mask_dcplb; | 37 | int first_mask_dcplb; |
38 | 38 | ||
39 | void __init generate_cpl_tables(void) | 39 | void __init generate_cplb_tables(void) |
40 | { | 40 | { |
41 | int i_d, i_i; | 41 | int i_d, i_i; |
42 | unsigned long addr; | 42 | unsigned long addr; |
@@ -83,8 +83,18 @@ void __init generate_cpl_tables(void) | |||
83 | dcplb_tbl[i_d].addr = L1_DATA_A_START; | 83 | dcplb_tbl[i_d].addr = L1_DATA_A_START; |
84 | dcplb_tbl[i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB; | 84 | dcplb_tbl[i_d++].data = L1_DMEMORY | PAGE_SIZE_4MB; |
85 | #endif | 85 | #endif |
86 | #if L1_CODE_LENGTH > 0 | ||
86 | icplb_tbl[i_i].addr = L1_CODE_START; | 87 | icplb_tbl[i_i].addr = L1_CODE_START; |
87 | icplb_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB; | 88 | icplb_tbl[i_i++].data = L1_IMEMORY | PAGE_SIZE_4MB; |
89 | #endif | ||
90 | |||
91 | /* Cover L2 memory */ | ||
92 | #if L2_LENGTH > 0 | ||
93 | dcplb_tbl[i_d].addr = L2_START; | ||
94 | dcplb_tbl[i_d++].data = L2_DMEMORY | PAGE_SIZE_1MB; | ||
95 | icplb_tbl[i_i].addr = L2_START; | ||
96 | icplb_tbl[i_i++].data = L2_IMEMORY | PAGE_SIZE_1MB; | ||
97 | #endif | ||
88 | 98 | ||
89 | first_mask_dcplb = i_d; | 99 | first_mask_dcplb = i_d; |
90 | first_switched_dcplb = i_d + (1 << page_mask_order); | 100 | first_switched_dcplb = i_d + (1 << page_mask_order); |
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c index 99f2831e2964..5094677fd09e 100644 --- a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c +++ b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c | |||
@@ -322,9 +322,11 @@ int cplb_hdr(int seqstat, struct pt_regs *regs) | |||
322 | void flush_switched_cplbs(void) | 322 | void flush_switched_cplbs(void) |
323 | { | 323 | { |
324 | int i; | 324 | int i; |
325 | unsigned long flags; | ||
325 | 326 | ||
326 | nr_cplb_flush++; | 327 | nr_cplb_flush++; |
327 | 328 | ||
329 | local_irq_save(flags); | ||
328 | disable_icplb(); | 330 | disable_icplb(); |
329 | for (i = first_switched_icplb; i < MAX_CPLBS; i++) { | 331 | for (i = first_switched_icplb; i < MAX_CPLBS; i++) { |
330 | icplb_tbl[i].data = 0; | 332 | icplb_tbl[i].data = 0; |
@@ -338,6 +340,8 @@ void flush_switched_cplbs(void) | |||
338 | bfin_write32(DCPLB_DATA0 + i * 4, 0); | 340 | bfin_write32(DCPLB_DATA0 + i * 4, 0); |
339 | } | 341 | } |
340 | enable_dcplb(); | 342 | enable_dcplb(); |
343 | local_irq_restore(flags); | ||
344 | |||
341 | } | 345 | } |
342 | 346 | ||
343 | void set_mask_dcplbs(unsigned long *masks) | 347 | void set_mask_dcplbs(unsigned long *masks) |
@@ -345,10 +349,15 @@ void set_mask_dcplbs(unsigned long *masks) | |||
345 | int i; | 349 | int i; |
346 | unsigned long addr = (unsigned long)masks; | 350 | unsigned long addr = (unsigned long)masks; |
347 | unsigned long d_data; | 351 | unsigned long d_data; |
348 | current_rwx_mask = masks; | 352 | unsigned long flags; |
349 | 353 | ||
350 | if (!masks) | 354 | if (!masks) { |
355 | current_rwx_mask = masks; | ||
351 | return; | 356 | return; |
357 | } | ||
358 | |||
359 | local_irq_save(flags); | ||
360 | current_rwx_mask = masks; | ||
352 | 361 | ||
353 | d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB; | 362 | d_data = CPLB_SUPV_WR | CPLB_VALID | CPLB_DIRTY | PAGE_SIZE_4KB; |
354 | #ifdef CONFIG_BFIN_DCACHE | 363 | #ifdef CONFIG_BFIN_DCACHE |
@@ -367,4 +376,5 @@ void set_mask_dcplbs(unsigned long *masks) | |||
367 | addr += PAGE_SIZE; | 376 | addr += PAGE_SIZE; |
368 | } | 377 | } |
369 | enable_dcplb(); | 378 | enable_dcplb(); |
379 | local_irq_restore(flags); | ||
370 | } | 380 | } |
diff --git a/arch/blackfin/kernel/cplb-nompu/cplbinit.c b/arch/blackfin/kernel/cplb-nompu/cplbinit.c index 728f708d3981..301252e84441 100644 --- a/arch/blackfin/kernel/cplb-nompu/cplbinit.c +++ b/arch/blackfin/kernel/cplb-nompu/cplbinit.c | |||
@@ -168,8 +168,8 @@ static struct cplb_desc cplb_data[] = { | |||
168 | .end = L2_START + L2_LENGTH, | 168 | .end = L2_START + L2_LENGTH, |
169 | .psize = SIZE_1M, | 169 | .psize = SIZE_1M, |
170 | .attr = SWITCH_T | I_CPLB | D_CPLB, | 170 | .attr = SWITCH_T | I_CPLB | D_CPLB, |
171 | .i_conf = L2_MEMORY, | 171 | .i_conf = L2_IMEMORY, |
172 | .d_conf = L2_MEMORY, | 172 | .d_conf = L2_DMEMORY, |
173 | .valid = (L2_LENGTH > 0), | 173 | .valid = (L2_LENGTH > 0), |
174 | .name = "L2 Memory", | 174 | .name = "L2 Memory", |
175 | }, | 175 | }, |
@@ -308,7 +308,7 @@ __fill_data_cplbtab(struct cplb_tab *t, int i, u32 a_start, u32 a_end) | |||
308 | } | 308 | } |
309 | } | 309 | } |
310 | 310 | ||
311 | void __init generate_cpl_tables(void) | 311 | void __init generate_cplb_tables(void) |
312 | { | 312 | { |
313 | 313 | ||
314 | u16 i, j, process; | 314 | u16 i, j, process; |
diff --git a/arch/blackfin/kernel/early_printk.c b/arch/blackfin/kernel/early_printk.c index 60f67f90fe35..1f4e3d2e0901 100644 --- a/arch/blackfin/kernel/early_printk.c +++ b/arch/blackfin/kernel/early_printk.c | |||
@@ -35,6 +35,9 @@ | |||
35 | extern struct console *bfin_earlyserial_init(unsigned int port, | 35 | extern struct console *bfin_earlyserial_init(unsigned int port, |
36 | unsigned int cflag); | 36 | unsigned int cflag); |
37 | #endif | 37 | #endif |
38 | #ifdef CONFIG_BFIN_JTAG_COMM | ||
39 | extern struct console *bfin_jc_early_init(void); | ||
40 | #endif | ||
38 | 41 | ||
39 | static struct console *early_console; | 42 | static struct console *early_console; |
40 | 43 | ||
@@ -142,6 +145,15 @@ int __init setup_early_printk(char *buf) | |||
142 | early_console = earlyserial_init(buf); | 145 | early_console = earlyserial_init(buf); |
143 | } | 146 | } |
144 | #endif | 147 | #endif |
148 | |||
149 | #ifdef CONFIG_BFIN_JTAG_COMM | ||
150 | /* Check for Blackfin JTAG */ | ||
151 | if (!strncmp(buf, "jtag", 4)) { | ||
152 | buf += 4; | ||
153 | early_console = bfin_jc_early_init(); | ||
154 | } | ||
155 | #endif | ||
156 | |||
145 | #ifdef CONFIG_FB | 157 | #ifdef CONFIG_FB |
146 | /* TODO: add framebuffer console support */ | 158 | /* TODO: add framebuffer console support */ |
147 | #endif | 159 | #endif |
diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c index a1f9641a6425..b795a207742c 100644 --- a/arch/blackfin/kernel/kgdb.c +++ b/arch/blackfin/kernel/kgdb.c | |||
@@ -1,32 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * File: arch/blackfin/kernel/kgdb.c | 2 | * arch/blackfin/kernel/kgdb.c - Blackfin kgdb pieces |
3 | * Based on: | ||
4 | * Author: Sonic Zhang | ||
5 | * | 3 | * |
6 | * Created: | 4 | * Copyright 2005-2008 Analog Devices Inc. |
7 | * Description: | ||
8 | * | 5 | * |
9 | * Rev: $Id: kgdb_bfin_linux-2.6.x.patch 4934 2007-02-13 09:32:11Z sonicz $ | 6 | * Licensed under the GPL-2 or later. |
10 | * | ||
11 | * Modified: | ||
12 | * Copyright 2005-2006 Analog Devices Inc. | ||
13 | * | ||
14 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or modify | ||
17 | * it under the terms of the GNU General Public License as published by | ||
18 | * the Free Software Foundation; either version 2 of the License, or | ||
19 | * (at your option) any later version. | ||
20 | * | ||
21 | * This program is distributed in the hope that it will be useful, | ||
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
24 | * GNU General Public License for more details. | ||
25 | * | ||
26 | * You should have received a copy of the GNU General Public License | ||
27 | * along with this program; if not, see the file COPYING, or write | ||
28 | * to the Free Software Foundation, Inc., | ||
29 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
30 | */ | 7 | */ |
31 | 8 | ||
32 | #include <linux/string.h> | 9 | #include <linux/string.h> |
@@ -39,24 +16,29 @@ | |||
39 | #include <linux/kgdb.h> | 16 | #include <linux/kgdb.h> |
40 | #include <linux/console.h> | 17 | #include <linux/console.h> |
41 | #include <linux/init.h> | 18 | #include <linux/init.h> |
42 | #include <linux/debugger.h> | ||
43 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
44 | #include <linux/irq.h> | 20 | #include <linux/irq.h> |
21 | #include <linux/uaccess.h> | ||
45 | #include <asm/system.h> | 22 | #include <asm/system.h> |
46 | #include <asm/traps.h> | 23 | #include <asm/traps.h> |
47 | #include <asm/blackfin.h> | 24 | #include <asm/blackfin.h> |
25 | #include <asm/dma.h> | ||
48 | 26 | ||
49 | /* Put the error code here just in case the user cares. */ | 27 | /* Put the error code here just in case the user cares. */ |
50 | int gdb_bf533errcode; | 28 | int gdb_bfin_errcode; |
51 | /* Likewise, the vector number here (since GDB only gets the signal | 29 | /* Likewise, the vector number here (since GDB only gets the signal |
52 | number through the usual means, and that's not very specific). */ | 30 | number through the usual means, and that's not very specific). */ |
53 | int gdb_bf533vector = -1; | 31 | int gdb_bfin_vector = -1; |
54 | 32 | ||
55 | #if KGDB_MAX_NO_CPUS != 8 | 33 | #if KGDB_MAX_NO_CPUS != 8 |
56 | #error change the definition of slavecpulocks | 34 | #error change the definition of slavecpulocks |
57 | #endif | 35 | #endif |
58 | 36 | ||
59 | void regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) | 37 | #ifdef CONFIG_BFIN_WDT |
38 | # error "Please unselect blackfin watchdog driver before build KGDB." | ||
39 | #endif | ||
40 | |||
41 | void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) | ||
60 | { | 42 | { |
61 | gdb_regs[BFIN_R0] = regs->r0; | 43 | gdb_regs[BFIN_R0] = regs->r0; |
62 | gdb_regs[BFIN_R1] = regs->r1; | 44 | gdb_regs[BFIN_R1] = regs->r1; |
@@ -133,7 +115,7 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) | |||
133 | gdb_regs[BFIN_SEQSTAT] = p->thread.seqstat; | 115 | gdb_regs[BFIN_SEQSTAT] = p->thread.seqstat; |
134 | } | 116 | } |
135 | 117 | ||
136 | void gdb_regs_to_regs(unsigned long *gdb_regs, struct pt_regs *regs) | 118 | void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) |
137 | { | 119 | { |
138 | regs->r0 = gdb_regs[BFIN_R0]; | 120 | regs->r0 = gdb_regs[BFIN_R0]; |
139 | regs->r1 = gdb_regs[BFIN_R1]; | 121 | regs->r1 = gdb_regs[BFIN_R1]; |
@@ -199,171 +181,208 @@ struct hw_breakpoint { | |||
199 | unsigned int dataacc:2; | 181 | unsigned int dataacc:2; |
200 | unsigned short count; | 182 | unsigned short count; |
201 | unsigned int addr; | 183 | unsigned int addr; |
202 | } breakinfo[HW_BREAKPOINT_NUM]; | 184 | } breakinfo[HW_WATCHPOINT_NUM]; |
203 | 185 | ||
204 | int kgdb_arch_init(void) | 186 | int bfin_set_hw_break(unsigned long addr, int len, enum kgdb_bptype type) |
205 | { | ||
206 | debugger_step = 0; | ||
207 | |||
208 | kgdb_remove_all_hw_break(); | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | int kgdb_set_hw_break(unsigned long addr) | ||
213 | { | 187 | { |
214 | int breakno; | 188 | int breakno; |
215 | for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++) | 189 | int bfin_type; |
216 | if (!breakinfo[breakno].occupied) { | 190 | int dataacc = 0; |
191 | |||
192 | switch (type) { | ||
193 | case BP_HARDWARE_BREAKPOINT: | ||
194 | bfin_type = TYPE_INST_WATCHPOINT; | ||
195 | break; | ||
196 | case BP_WRITE_WATCHPOINT: | ||
197 | dataacc = 1; | ||
198 | bfin_type = TYPE_DATA_WATCHPOINT; | ||
199 | break; | ||
200 | case BP_READ_WATCHPOINT: | ||
201 | dataacc = 2; | ||
202 | bfin_type = TYPE_DATA_WATCHPOINT; | ||
203 | break; | ||
204 | case BP_ACCESS_WATCHPOINT: | ||
205 | dataacc = 3; | ||
206 | bfin_type = TYPE_DATA_WATCHPOINT; | ||
207 | break; | ||
208 | default: | ||
209 | return -ENOSPC; | ||
210 | } | ||
211 | |||
212 | /* Becasue hardware data watchpoint impelemented in current | ||
213 | * Blackfin can not trigger an exception event as the hardware | ||
214 | * instrction watchpoint does, we ignaore all data watch point here. | ||
215 | * They can be turned on easily after future blackfin design | ||
216 | * supports this feature. | ||
217 | */ | ||
218 | for (breakno = 0; breakno < HW_INST_WATCHPOINT_NUM; breakno++) | ||
219 | if (bfin_type == breakinfo[breakno].type | ||
220 | && !breakinfo[breakno].occupied) { | ||
217 | breakinfo[breakno].occupied = 1; | 221 | breakinfo[breakno].occupied = 1; |
218 | breakinfo[breakno].enabled = 1; | 222 | breakinfo[breakno].enabled = 1; |
219 | breakinfo[breakno].type = 1; | ||
220 | breakinfo[breakno].addr = addr; | 223 | breakinfo[breakno].addr = addr; |
224 | breakinfo[breakno].dataacc = dataacc; | ||
225 | breakinfo[breakno].count = 0; | ||
221 | return 0; | 226 | return 0; |
222 | } | 227 | } |
223 | 228 | ||
224 | return -ENOSPC; | 229 | return -ENOSPC; |
225 | } | 230 | } |
226 | 231 | ||
227 | int kgdb_remove_hw_break(unsigned long addr) | 232 | int bfin_remove_hw_break(unsigned long addr, int len, enum kgdb_bptype type) |
228 | { | 233 | { |
229 | int breakno; | 234 | int breakno; |
230 | for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++) | 235 | int bfin_type; |
231 | if (breakinfo[breakno].addr == addr) | 236 | |
232 | memset(&(breakinfo[breakno]), 0, sizeof(struct hw_breakpoint)); | 237 | switch (type) { |
238 | case BP_HARDWARE_BREAKPOINT: | ||
239 | bfin_type = TYPE_INST_WATCHPOINT; | ||
240 | break; | ||
241 | case BP_WRITE_WATCHPOINT: | ||
242 | case BP_READ_WATCHPOINT: | ||
243 | case BP_ACCESS_WATCHPOINT: | ||
244 | bfin_type = TYPE_DATA_WATCHPOINT; | ||
245 | break; | ||
246 | default: | ||
247 | return 0; | ||
248 | } | ||
249 | for (breakno = 0; breakno < HW_WATCHPOINT_NUM; breakno++) | ||
250 | if (bfin_type == breakinfo[breakno].type | ||
251 | && breakinfo[breakno].occupied | ||
252 | && breakinfo[breakno].addr == addr) { | ||
253 | breakinfo[breakno].occupied = 0; | ||
254 | breakinfo[breakno].enabled = 0; | ||
255 | } | ||
233 | 256 | ||
234 | return 0; | 257 | return 0; |
235 | } | 258 | } |
236 | 259 | ||
237 | void kgdb_remove_all_hw_break(void) | 260 | void bfin_remove_all_hw_break(void) |
238 | { | 261 | { |
239 | memset(breakinfo, 0, sizeof(struct hw_breakpoint)*8); | 262 | int breakno; |
240 | } | ||
241 | 263 | ||
242 | /* | 264 | memset(breakinfo, 0, sizeof(struct hw_breakpoint)*HW_WATCHPOINT_NUM); |
243 | void kgdb_show_info(void) | 265 | |
244 | { | 266 | for (breakno = 0; breakno < HW_INST_WATCHPOINT_NUM; breakno++) |
245 | printk(KERN_DEBUG "hwd: wpia0=0x%x, wpiacnt0=%d, wpiactl=0x%x, wpstat=0x%x\n", | 267 | breakinfo[breakno].type = TYPE_INST_WATCHPOINT; |
246 | bfin_read_WPIA0(), bfin_read_WPIACNT0(), | 268 | for (; breakno < HW_WATCHPOINT_NUM; breakno++) |
247 | bfin_read_WPIACTL(), bfin_read_WPSTAT()); | 269 | breakinfo[breakno].type = TYPE_DATA_WATCHPOINT; |
248 | } | 270 | } |
249 | */ | ||
250 | 271 | ||
251 | void kgdb_correct_hw_break(void) | 272 | void bfin_correct_hw_break(void) |
252 | { | 273 | { |
253 | int breakno; | 274 | int breakno; |
254 | int correctit; | 275 | unsigned int wpiactl = 0; |
255 | uint32_t wpdactl = bfin_read_WPDACTL(); | 276 | unsigned int wpdactl = 0; |
277 | int enable_wp = 0; | ||
278 | |||
279 | for (breakno = 0; breakno < HW_WATCHPOINT_NUM; breakno++) | ||
280 | if (breakinfo[breakno].enabled) { | ||
281 | enable_wp = 1; | ||
256 | 282 | ||
257 | correctit = 0; | ||
258 | for (breakno = 0; breakno < HW_BREAKPOINT_NUM; breakno++) { | ||
259 | if (breakinfo[breakno].type == 1) { | ||
260 | switch (breakno) { | 283 | switch (breakno) { |
261 | case 0: | 284 | case 0: |
262 | if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN0)) { | 285 | wpiactl |= WPIAEN0|WPICNTEN0; |
263 | correctit = 1; | 286 | bfin_write_WPIA0(breakinfo[breakno].addr); |
264 | wpdactl &= ~(WPIREN01|EMUSW0); | 287 | bfin_write_WPIACNT0(breakinfo[breakno].count |
265 | wpdactl |= WPIAEN0|WPICNTEN0; | 288 | + breakinfo->skip); |
266 | bfin_write_WPIA0(breakinfo[breakno].addr); | ||
267 | bfin_write_WPIACNT0(breakinfo[breakno].skip); | ||
268 | } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN0)) { | ||
269 | correctit = 1; | ||
270 | wpdactl &= ~WPIAEN0; | ||
271 | } | ||
272 | break; | 289 | break; |
273 | |||
274 | case 1: | 290 | case 1: |
275 | if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN1)) { | 291 | wpiactl |= WPIAEN1|WPICNTEN1; |
276 | correctit = 1; | 292 | bfin_write_WPIA1(breakinfo[breakno].addr); |
277 | wpdactl &= ~(WPIREN01|EMUSW1); | 293 | bfin_write_WPIACNT1(breakinfo[breakno].count |
278 | wpdactl |= WPIAEN1|WPICNTEN1; | 294 | + breakinfo->skip); |
279 | bfin_write_WPIA1(breakinfo[breakno].addr); | ||
280 | bfin_write_WPIACNT1(breakinfo[breakno].skip); | ||
281 | } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN1)) { | ||
282 | correctit = 1; | ||
283 | wpdactl &= ~WPIAEN1; | ||
284 | } | ||
285 | break; | 295 | break; |
286 | |||
287 | case 2: | 296 | case 2: |
288 | if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN2)) { | 297 | wpiactl |= WPIAEN2|WPICNTEN2; |
289 | correctit = 1; | 298 | bfin_write_WPIA2(breakinfo[breakno].addr); |
290 | wpdactl &= ~(WPIREN23|EMUSW2); | 299 | bfin_write_WPIACNT2(breakinfo[breakno].count |
291 | wpdactl |= WPIAEN2|WPICNTEN2; | 300 | + breakinfo->skip); |
292 | bfin_write_WPIA2(breakinfo[breakno].addr); | ||
293 | bfin_write_WPIACNT2(breakinfo[breakno].skip); | ||
294 | } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN2)) { | ||
295 | correctit = 1; | ||
296 | wpdactl &= ~WPIAEN2; | ||
297 | } | ||
298 | break; | 301 | break; |
299 | |||
300 | case 3: | 302 | case 3: |
301 | if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN3)) { | 303 | wpiactl |= WPIAEN3|WPICNTEN3; |
302 | correctit = 1; | 304 | bfin_write_WPIA3(breakinfo[breakno].addr); |
303 | wpdactl &= ~(WPIREN23|EMUSW3); | 305 | bfin_write_WPIACNT3(breakinfo[breakno].count |
304 | wpdactl |= WPIAEN3|WPICNTEN3; | 306 | + breakinfo->skip); |
305 | bfin_write_WPIA3(breakinfo[breakno].addr); | ||
306 | bfin_write_WPIACNT3(breakinfo[breakno].skip); | ||
307 | } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN3)) { | ||
308 | correctit = 1; | ||
309 | wpdactl &= ~WPIAEN3; | ||
310 | } | ||
311 | break; | 307 | break; |
312 | case 4: | 308 | case 4: |
313 | if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN4)) { | 309 | wpiactl |= WPIAEN4|WPICNTEN4; |
314 | correctit = 1; | 310 | bfin_write_WPIA4(breakinfo[breakno].addr); |
315 | wpdactl &= ~(WPIREN45|EMUSW4); | 311 | bfin_write_WPIACNT4(breakinfo[breakno].count |
316 | wpdactl |= WPIAEN4|WPICNTEN4; | 312 | + breakinfo->skip); |
317 | bfin_write_WPIA4(breakinfo[breakno].addr); | ||
318 | bfin_write_WPIACNT4(breakinfo[breakno].skip); | ||
319 | } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN4)) { | ||
320 | correctit = 1; | ||
321 | wpdactl &= ~WPIAEN4; | ||
322 | } | ||
323 | break; | 313 | break; |
324 | case 5: | 314 | case 5: |
325 | if (breakinfo[breakno].enabled && !(wpdactl & WPIAEN5)) { | 315 | wpiactl |= WPIAEN5|WPICNTEN5; |
326 | correctit = 1; | 316 | bfin_write_WPIA5(breakinfo[breakno].addr); |
327 | wpdactl &= ~(WPIREN45|EMUSW5); | 317 | bfin_write_WPIACNT5(breakinfo[breakno].count |
328 | wpdactl |= WPIAEN5|WPICNTEN5; | 318 | + breakinfo->skip); |
329 | bfin_write_WPIA5(breakinfo[breakno].addr); | 319 | break; |
330 | bfin_write_WPIACNT5(breakinfo[breakno].skip); | 320 | case 6: |
331 | } else if (!breakinfo[breakno].enabled && (wpdactl & WPIAEN5)) { | 321 | wpdactl |= WPDAEN0|WPDCNTEN0|WPDSRC0; |
332 | correctit = 1; | 322 | wpdactl |= breakinfo[breakno].dataacc |
333 | wpdactl &= ~WPIAEN5; | 323 | << WPDACC0_OFFSET; |
334 | } | 324 | bfin_write_WPDA0(breakinfo[breakno].addr); |
325 | bfin_write_WPDACNT0(breakinfo[breakno].count | ||
326 | + breakinfo->skip); | ||
327 | break; | ||
328 | case 7: | ||
329 | wpdactl |= WPDAEN1|WPDCNTEN1|WPDSRC1; | ||
330 | wpdactl |= breakinfo[breakno].dataacc | ||
331 | << WPDACC1_OFFSET; | ||
332 | bfin_write_WPDA1(breakinfo[breakno].addr); | ||
333 | bfin_write_WPDACNT1(breakinfo[breakno].count | ||
334 | + breakinfo->skip); | ||
335 | break; | 335 | break; |
336 | } | 336 | } |
337 | } | 337 | } |
338 | } | 338 | |
339 | if (correctit) { | 339 | /* Should enable WPPWR bit first before set any other |
340 | wpdactl &= ~WPAND; | 340 | * WPIACTL and WPDACTL bits */ |
341 | wpdactl |= WPPWR; | 341 | if (enable_wp) { |
342 | /*printk("correct_hw_break: wpdactl=0x%x\n", wpdactl);*/ | 342 | bfin_write_WPIACTL(WPPWR); |
343 | CSYNC(); | ||
344 | bfin_write_WPIACTL(wpiactl|WPPWR); | ||
343 | bfin_write_WPDACTL(wpdactl); | 345 | bfin_write_WPDACTL(wpdactl); |
344 | CSYNC(); | 346 | CSYNC(); |
345 | /*kgdb_show_info();*/ | ||
346 | } | 347 | } |
347 | } | 348 | } |
348 | 349 | ||
349 | void kgdb_disable_hw_debug(struct pt_regs *regs) | 350 | void kgdb_disable_hw_debug(struct pt_regs *regs) |
350 | { | 351 | { |
351 | /* Disable hardware debugging while we are in kgdb */ | 352 | /* Disable hardware debugging while we are in kgdb */ |
352 | bfin_write_WPIACTL(bfin_read_WPIACTL() & ~0x1); | 353 | bfin_write_WPIACTL(0); |
354 | bfin_write_WPDACTL(0); | ||
353 | CSYNC(); | 355 | CSYNC(); |
354 | } | 356 | } |
355 | 357 | ||
356 | void kgdb_post_master_code(struct pt_regs *regs, int eVector, int err_code) | 358 | #ifdef CONFIG_SMP |
359 | void kgdb_passive_cpu_callback(void *info) | ||
360 | { | ||
361 | kgdb_nmicallback(raw_smp_processor_id(), get_irq_regs()); | ||
362 | } | ||
363 | |||
364 | void kgdb_roundup_cpus(unsigned long flags) | ||
365 | { | ||
366 | smp_call_function(kgdb_passive_cpu_callback, NULL, 0, 0); | ||
367 | } | ||
368 | |||
369 | void kgdb_roundup_cpu(int cpu, unsigned long flags) | ||
370 | { | ||
371 | smp_call_function_single(cpu, kgdb_passive_cpu_callback, NULL, 0, 0); | ||
372 | } | ||
373 | #endif | ||
374 | |||
375 | void kgdb_post_primary_code(struct pt_regs *regs, int eVector, int err_code) | ||
357 | { | 376 | { |
358 | /* Master processor is completely in the debugger */ | 377 | /* Master processor is completely in the debugger */ |
359 | gdb_bf533vector = eVector; | 378 | gdb_bfin_vector = eVector; |
360 | gdb_bf533errcode = err_code; | 379 | gdb_bfin_errcode = err_code; |
361 | } | 380 | } |
362 | 381 | ||
363 | int kgdb_arch_handle_exception(int exceptionVector, int signo, | 382 | int kgdb_arch_handle_exception(int vector, int signo, |
364 | int err_code, char *remcom_in_buffer, | 383 | int err_code, char *remcom_in_buffer, |
365 | char *remcom_out_buffer, | 384 | char *remcom_out_buffer, |
366 | struct pt_regs *linux_regs) | 385 | struct pt_regs *regs) |
367 | { | 386 | { |
368 | long addr; | 387 | long addr; |
369 | long breakno; | 388 | long breakno; |
@@ -385,44 +404,40 @@ int kgdb_arch_handle_exception(int exceptionVector, int signo, | |||
385 | /* try to read optional parameter, pc unchanged if no parm */ | 404 | /* try to read optional parameter, pc unchanged if no parm */ |
386 | ptr = &remcom_in_buffer[1]; | 405 | ptr = &remcom_in_buffer[1]; |
387 | if (kgdb_hex2long(&ptr, &addr)) { | 406 | if (kgdb_hex2long(&ptr, &addr)) { |
388 | linux_regs->retx = addr; | 407 | regs->retx = addr; |
389 | } | 408 | } |
390 | newPC = linux_regs->retx; | 409 | newPC = regs->retx; |
391 | 410 | ||
392 | /* clear the trace bit */ | 411 | /* clear the trace bit */ |
393 | linux_regs->syscfg &= 0xfffffffe; | 412 | regs->syscfg &= 0xfffffffe; |
394 | 413 | ||
395 | /* set the trace bit if we're stepping */ | 414 | /* set the trace bit if we're stepping */ |
396 | if (remcom_in_buffer[0] == 's') { | 415 | if (remcom_in_buffer[0] == 's') { |
397 | linux_regs->syscfg |= 0x1; | 416 | regs->syscfg |= 0x1; |
398 | debugger_step = linux_regs->ipend; | 417 | kgdb_single_step = regs->ipend; |
399 | debugger_step >>= 6; | 418 | kgdb_single_step >>= 6; |
400 | for (i = 10; i > 0; i--, debugger_step >>= 1) | 419 | for (i = 10; i > 0; i--, kgdb_single_step >>= 1) |
401 | if (debugger_step & 1) | 420 | if (kgdb_single_step & 1) |
402 | break; | 421 | break; |
403 | /* i indicate event priority of current stopped instruction | 422 | /* i indicate event priority of current stopped instruction |
404 | * user space instruction is 0, IVG15 is 1, IVTMR is 10. | 423 | * user space instruction is 0, IVG15 is 1, IVTMR is 10. |
405 | * debugger_step > 0 means in single step mode | 424 | * kgdb_single_step > 0 means in single step mode |
406 | */ | 425 | */ |
407 | debugger_step = i + 1; | 426 | kgdb_single_step = i + 1; |
408 | } else { | ||
409 | debugger_step = 0; | ||
410 | } | 427 | } |
411 | 428 | ||
412 | wp_status = bfin_read_WPSTAT(); | 429 | if (vector == VEC_WATCH) { |
413 | CSYNC(); | 430 | wp_status = bfin_read_WPSTAT(); |
414 | 431 | for (breakno = 0; breakno < HW_WATCHPOINT_NUM; breakno++) { | |
415 | if (exceptionVector == VEC_WATCH) { | ||
416 | for (breakno = 0; breakno < 6; ++breakno) { | ||
417 | if (wp_status & (1 << breakno)) { | 432 | if (wp_status & (1 << breakno)) { |
418 | breakinfo->skip = 1; | 433 | breakinfo->skip = 1; |
419 | break; | 434 | break; |
420 | } | 435 | } |
421 | } | 436 | } |
437 | bfin_write_WPSTAT(0); | ||
422 | } | 438 | } |
423 | kgdb_correct_hw_break(); | ||
424 | 439 | ||
425 | bfin_write_WPSTAT(0); | 440 | bfin_correct_hw_break(); |
426 | 441 | ||
427 | return 0; | 442 | return 0; |
428 | } /* switch */ | 443 | } /* switch */ |
@@ -431,5 +446,385 @@ int kgdb_arch_handle_exception(int exceptionVector, int signo, | |||
431 | 446 | ||
432 | struct kgdb_arch arch_kgdb_ops = { | 447 | struct kgdb_arch arch_kgdb_ops = { |
433 | .gdb_bpt_instr = {0xa1}, | 448 | .gdb_bpt_instr = {0xa1}, |
449 | #ifdef CONFIG_SMP | ||
450 | .flags = KGDB_HW_BREAKPOINT|KGDB_THR_PROC_SWAP, | ||
451 | #else | ||
434 | .flags = KGDB_HW_BREAKPOINT, | 452 | .flags = KGDB_HW_BREAKPOINT, |
453 | #endif | ||
454 | .set_hw_breakpoint = bfin_set_hw_break, | ||
455 | .remove_hw_breakpoint = bfin_remove_hw_break, | ||
456 | .remove_all_hw_break = bfin_remove_all_hw_break, | ||
457 | .correct_hw_break = bfin_correct_hw_break, | ||
435 | }; | 458 | }; |
459 | |||
460 | static int hex(char ch) | ||
461 | { | ||
462 | if ((ch >= 'a') && (ch <= 'f')) | ||
463 | return ch - 'a' + 10; | ||
464 | if ((ch >= '0') && (ch <= '9')) | ||
465 | return ch - '0'; | ||
466 | if ((ch >= 'A') && (ch <= 'F')) | ||
467 | return ch - 'A' + 10; | ||
468 | return -1; | ||
469 | } | ||
470 | |||
471 | static int validate_memory_access_address(unsigned long addr, int size) | ||
472 | { | ||
473 | int cpu = raw_smp_processor_id(); | ||
474 | |||
475 | if (size < 0) | ||
476 | return EFAULT; | ||
477 | if (addr >= 0x1000 && (addr + size) <= physical_mem_end) | ||
478 | return 0; | ||
479 | if (addr >= SYSMMR_BASE) | ||
480 | return 0; | ||
481 | if (addr >= ASYNC_BANK0_BASE | ||
482 | && addr + size <= ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE) | ||
483 | return 0; | ||
484 | if (cpu == 0) { | ||
485 | if (addr >= L1_SCRATCH_START | ||
486 | && (addr + size <= L1_SCRATCH_START + L1_SCRATCH_LENGTH)) | ||
487 | return 0; | ||
488 | #if L1_CODE_LENGTH != 0 | ||
489 | if (addr >= L1_CODE_START | ||
490 | && (addr + size <= L1_CODE_START + L1_CODE_LENGTH)) | ||
491 | return 0; | ||
492 | #endif | ||
493 | #if L1_DATA_A_LENGTH != 0 | ||
494 | if (addr >= L1_DATA_A_START | ||
495 | && (addr + size <= L1_DATA_A_START + L1_DATA_A_LENGTH)) | ||
496 | return 0; | ||
497 | #endif | ||
498 | #if L1_DATA_B_LENGTH != 0 | ||
499 | if (addr >= L1_DATA_B_START | ||
500 | && (addr + size <= L1_DATA_B_START + L1_DATA_B_LENGTH)) | ||
501 | return 0; | ||
502 | #endif | ||
503 | #ifdef CONFIG_SMP | ||
504 | } else if (cpu == 1) { | ||
505 | if (addr >= COREB_L1_SCRATCH_START | ||
506 | && (addr + size <= COREB_L1_SCRATCH_START | ||
507 | + L1_SCRATCH_LENGTH)) | ||
508 | return 0; | ||
509 | # if L1_CODE_LENGTH != 0 | ||
510 | if (addr >= COREB_L1_CODE_START | ||
511 | && (addr + size <= COREB_L1_CODE_START + L1_CODE_LENGTH)) | ||
512 | return 0; | ||
513 | # endif | ||
514 | # if L1_DATA_A_LENGTH != 0 | ||
515 | if (addr >= COREB_L1_DATA_A_START | ||
516 | && (addr + size <= COREB_L1_DATA_A_START + L1_DATA_A_LENGTH)) | ||
517 | return 0; | ||
518 | # endif | ||
519 | # if L1_DATA_B_LENGTH != 0 | ||
520 | if (addr >= COREB_L1_DATA_B_START | ||
521 | && (addr + size <= COREB_L1_DATA_B_START + L1_DATA_B_LENGTH)) | ||
522 | return 0; | ||
523 | # endif | ||
524 | #endif | ||
525 | } | ||
526 | |||
527 | #if L2_LENGTH != 0 | ||
528 | if (addr >= L2_START | ||
529 | && addr + size <= L2_START + L2_LENGTH) | ||
530 | return 0; | ||
531 | #endif | ||
532 | |||
533 | return EFAULT; | ||
534 | } | ||
535 | |||
536 | /* | ||
537 | * Convert the memory pointed to by mem into hex, placing result in buf. | ||
538 | * Return a pointer to the last char put in buf (null). May return an error. | ||
539 | */ | ||
540 | int kgdb_mem2hex(char *mem, char *buf, int count) | ||
541 | { | ||
542 | char *tmp; | ||
543 | int err = 0; | ||
544 | unsigned char *pch; | ||
545 | unsigned short mmr16; | ||
546 | unsigned long mmr32; | ||
547 | int cpu = raw_smp_processor_id(); | ||
548 | |||
549 | if (validate_memory_access_address((unsigned long)mem, count)) | ||
550 | return EFAULT; | ||
551 | |||
552 | /* | ||
553 | * We use the upper half of buf as an intermediate buffer for the | ||
554 | * raw memory copy. Hex conversion will work against this one. | ||
555 | */ | ||
556 | tmp = buf + count; | ||
557 | |||
558 | if ((unsigned int)mem >= SYSMMR_BASE) { /*access MMR registers*/ | ||
559 | switch (count) { | ||
560 | case 2: | ||
561 | if ((unsigned int)mem % 2 == 0) { | ||
562 | mmr16 = *(unsigned short *)mem; | ||
563 | pch = (unsigned char *)&mmr16; | ||
564 | *tmp++ = *pch++; | ||
565 | *tmp++ = *pch++; | ||
566 | tmp -= 2; | ||
567 | } else | ||
568 | err = EFAULT; | ||
569 | break; | ||
570 | case 4: | ||
571 | if ((unsigned int)mem % 4 == 0) { | ||
572 | mmr32 = *(unsigned long *)mem; | ||
573 | pch = (unsigned char *)&mmr32; | ||
574 | *tmp++ = *pch++; | ||
575 | *tmp++ = *pch++; | ||
576 | *tmp++ = *pch++; | ||
577 | *tmp++ = *pch++; | ||
578 | tmp -= 4; | ||
579 | } else | ||
580 | err = EFAULT; | ||
581 | break; | ||
582 | default: | ||
583 | err = EFAULT; | ||
584 | } | ||
585 | } else if (cpu == 0 && (unsigned int)mem >= L1_CODE_START && | ||
586 | (unsigned int)(mem + count) <= L1_CODE_START + L1_CODE_LENGTH | ||
587 | #ifdef CONFIG_SMP | ||
588 | || cpu == 1 && (unsigned int)mem >= COREB_L1_CODE_START && | ||
589 | (unsigned int)(mem + count) <= | ||
590 | COREB_L1_CODE_START + L1_CODE_LENGTH | ||
591 | #endif | ||
592 | ) { | ||
593 | /* access L1 instruction SRAM*/ | ||
594 | if (dma_memcpy(tmp, mem, count) == NULL) | ||
595 | err = EFAULT; | ||
596 | } else | ||
597 | err = probe_kernel_read(tmp, mem, count); | ||
598 | |||
599 | if (!err) { | ||
600 | while (count > 0) { | ||
601 | buf = pack_hex_byte(buf, *tmp); | ||
602 | tmp++; | ||
603 | count--; | ||
604 | } | ||
605 | |||
606 | *buf = 0; | ||
607 | } | ||
608 | |||
609 | return err; | ||
610 | } | ||
611 | |||
612 | /* | ||
613 | * Copy the binary array pointed to by buf into mem. Fix $, #, and | ||
614 | * 0x7d escaped with 0x7d. Return a pointer to the character after | ||
615 | * the last byte written. | ||
616 | */ | ||
617 | int kgdb_ebin2mem(char *buf, char *mem, int count) | ||
618 | { | ||
619 | char *tmp_old; | ||
620 | char *tmp_new; | ||
621 | unsigned short *mmr16; | ||
622 | unsigned long *mmr32; | ||
623 | int err = 0; | ||
624 | int size = 0; | ||
625 | int cpu = raw_smp_processor_id(); | ||
626 | |||
627 | tmp_old = tmp_new = buf; | ||
628 | |||
629 | while (count-- > 0) { | ||
630 | if (*tmp_old == 0x7d) | ||
631 | *tmp_new = *(++tmp_old) ^ 0x20; | ||
632 | else | ||
633 | *tmp_new = *tmp_old; | ||
634 | tmp_new++; | ||
635 | tmp_old++; | ||
636 | size++; | ||
637 | } | ||
638 | |||
639 | if (validate_memory_access_address((unsigned long)mem, size)) | ||
640 | return EFAULT; | ||
641 | |||
642 | if ((unsigned int)mem >= SYSMMR_BASE) { /*access MMR registers*/ | ||
643 | switch (size) { | ||
644 | case 2: | ||
645 | if ((unsigned int)mem % 2 == 0) { | ||
646 | mmr16 = (unsigned short *)buf; | ||
647 | *(unsigned short *)mem = *mmr16; | ||
648 | } else | ||
649 | return EFAULT; | ||
650 | break; | ||
651 | case 4: | ||
652 | if ((unsigned int)mem % 4 == 0) { | ||
653 | mmr32 = (unsigned long *)buf; | ||
654 | *(unsigned long *)mem = *mmr32; | ||
655 | } else | ||
656 | return EFAULT; | ||
657 | break; | ||
658 | default: | ||
659 | return EFAULT; | ||
660 | } | ||
661 | } else if (cpu == 0 && (unsigned int)mem >= L1_CODE_START && | ||
662 | (unsigned int)(mem + count) < L1_CODE_START + L1_CODE_LENGTH | ||
663 | #ifdef CONFIG_SMP | ||
664 | || cpu == 1 && (unsigned int)mem >= COREB_L1_CODE_START && | ||
665 | (unsigned int)(mem + count) <= | ||
666 | COREB_L1_CODE_START + L1_CODE_LENGTH | ||
667 | #endif | ||
668 | ) { | ||
669 | /* access L1 instruction SRAM */ | ||
670 | if (dma_memcpy(mem, buf, size) == NULL) | ||
671 | err = EFAULT; | ||
672 | } else | ||
673 | err = probe_kernel_write(mem, buf, size); | ||
674 | |||
675 | return err; | ||
676 | } | ||
677 | |||
678 | /* | ||
679 | * Convert the hex array pointed to by buf into binary to be placed in mem. | ||
680 | * Return a pointer to the character AFTER the last byte written. | ||
681 | * May return an error. | ||
682 | */ | ||
683 | int kgdb_hex2mem(char *buf, char *mem, int count) | ||
684 | { | ||
685 | char *tmp_raw; | ||
686 | char *tmp_hex; | ||
687 | unsigned short *mmr16; | ||
688 | unsigned long *mmr32; | ||
689 | int cpu = raw_smp_processor_id(); | ||
690 | |||
691 | if (validate_memory_access_address((unsigned long)mem, count)) | ||
692 | return EFAULT; | ||
693 | |||
694 | /* | ||
695 | * We use the upper half of buf as an intermediate buffer for the | ||
696 | * raw memory that is converted from hex. | ||
697 | */ | ||
698 | tmp_raw = buf + count * 2; | ||
699 | |||
700 | tmp_hex = tmp_raw - 1; | ||
701 | while (tmp_hex >= buf) { | ||
702 | tmp_raw--; | ||
703 | *tmp_raw = hex(*tmp_hex--); | ||
704 | *tmp_raw |= hex(*tmp_hex--) << 4; | ||
705 | } | ||
706 | |||
707 | if ((unsigned int)mem >= SYSMMR_BASE) { /*access MMR registers*/ | ||
708 | switch (count) { | ||
709 | case 2: | ||
710 | if ((unsigned int)mem % 2 == 0) { | ||
711 | mmr16 = (unsigned short *)tmp_raw; | ||
712 | *(unsigned short *)mem = *mmr16; | ||
713 | } else | ||
714 | return EFAULT; | ||
715 | break; | ||
716 | case 4: | ||
717 | if ((unsigned int)mem % 4 == 0) { | ||
718 | mmr32 = (unsigned long *)tmp_raw; | ||
719 | *(unsigned long *)mem = *mmr32; | ||
720 | } else | ||
721 | return EFAULT; | ||
722 | break; | ||
723 | default: | ||
724 | return EFAULT; | ||
725 | } | ||
726 | } else if (cpu == 0 && (unsigned int)mem >= L1_CODE_START && | ||
727 | (unsigned int)(mem + count) <= L1_CODE_START + L1_CODE_LENGTH | ||
728 | #ifdef CONFIG_SMP | ||
729 | || cpu == 1 && (unsigned int)mem >= COREB_L1_CODE_START && | ||
730 | (unsigned int)(mem + count) <= | ||
731 | COREB_L1_CODE_START + L1_CODE_LENGTH | ||
732 | #endif | ||
733 | ) { | ||
734 | /* access L1 instruction SRAM */ | ||
735 | if (dma_memcpy(mem, tmp_raw, count) == NULL) | ||
736 | return EFAULT; | ||
737 | } else | ||
738 | return probe_kernel_write(mem, tmp_raw, count); | ||
739 | return 0; | ||
740 | } | ||
741 | |||
742 | int kgdb_validate_break_address(unsigned long addr) | ||
743 | { | ||
744 | int cpu = raw_smp_processor_id(); | ||
745 | |||
746 | if (addr >= 0x1000 && (addr + BREAK_INSTR_SIZE) <= physical_mem_end) | ||
747 | return 0; | ||
748 | if (addr >= ASYNC_BANK0_BASE | ||
749 | && addr + BREAK_INSTR_SIZE <= ASYNC_BANK3_BASE + ASYNC_BANK3_BASE) | ||
750 | return 0; | ||
751 | #if L1_CODE_LENGTH != 0 | ||
752 | if (cpu == 0 && addr >= L1_CODE_START | ||
753 | && addr + BREAK_INSTR_SIZE <= L1_CODE_START + L1_CODE_LENGTH) | ||
754 | return 0; | ||
755 | # ifdef CONFIG_SMP | ||
756 | else if (cpu == 1 && addr >= COREB_L1_CODE_START | ||
757 | && addr + BREAK_INSTR_SIZE <= COREB_L1_CODE_START + L1_CODE_LENGTH) | ||
758 | return 0; | ||
759 | # endif | ||
760 | #endif | ||
761 | #if L2_LENGTH != 0 | ||
762 | if (addr >= L2_START | ||
763 | && addr + BREAK_INSTR_SIZE <= L2_START + L2_LENGTH) | ||
764 | return 0; | ||
765 | #endif | ||
766 | |||
767 | return EFAULT; | ||
768 | } | ||
769 | |||
770 | int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr) | ||
771 | { | ||
772 | int err; | ||
773 | int cpu = raw_smp_processor_id(); | ||
774 | |||
775 | if ((cpu == 0 && (unsigned int)addr >= L1_CODE_START | ||
776 | && (unsigned int)(addr + BREAK_INSTR_SIZE) | ||
777 | < L1_CODE_START + L1_CODE_LENGTH) | ||
778 | #ifdef CONFIG_SMP | ||
779 | || (cpu == 1 && (unsigned int)addr >= COREB_L1_CODE_START | ||
780 | && (unsigned int)(addr + BREAK_INSTR_SIZE) | ||
781 | < COREB_L1_CODE_START + L1_CODE_LENGTH) | ||
782 | #endif | ||
783 | ) { | ||
784 | /* access L1 instruction SRAM */ | ||
785 | if (dma_memcpy(saved_instr, (void *)addr, BREAK_INSTR_SIZE) | ||
786 | == NULL) | ||
787 | return -EFAULT; | ||
788 | |||
789 | if (dma_memcpy((void *)addr, arch_kgdb_ops.gdb_bpt_instr, | ||
790 | BREAK_INSTR_SIZE) == NULL) | ||
791 | return -EFAULT; | ||
792 | |||
793 | return 0; | ||
794 | } else { | ||
795 | err = probe_kernel_read(saved_instr, (char *)addr, | ||
796 | BREAK_INSTR_SIZE); | ||
797 | if (err) | ||
798 | return err; | ||
799 | |||
800 | return probe_kernel_write((char *)addr, | ||
801 | arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE); | ||
802 | } | ||
803 | } | ||
804 | |||
805 | int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle) | ||
806 | { | ||
807 | if ((unsigned int)addr >= L1_CODE_START && | ||
808 | (unsigned int)(addr + BREAK_INSTR_SIZE) < | ||
809 | L1_CODE_START + L1_CODE_LENGTH) { | ||
810 | /* access L1 instruction SRAM */ | ||
811 | if (dma_memcpy((void *)addr, bundle, BREAK_INSTR_SIZE) == NULL) | ||
812 | return -EFAULT; | ||
813 | |||
814 | return 0; | ||
815 | } else | ||
816 | return probe_kernel_write((char *)addr, | ||
817 | (char *)bundle, BREAK_INSTR_SIZE); | ||
818 | } | ||
819 | |||
820 | int kgdb_arch_init(void) | ||
821 | { | ||
822 | kgdb_single_step = 0; | ||
823 | |||
824 | bfin_remove_all_hw_break(); | ||
825 | return 0; | ||
826 | } | ||
827 | |||
828 | void kgdb_arch_exit(void) | ||
829 | { | ||
830 | } | ||
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index bf1a51d8e608..140bf00e9974 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c | |||
@@ -46,7 +46,6 @@ | |||
46 | #include <asm/dma.h> | 46 | #include <asm/dma.h> |
47 | #include <asm/fixed_code.h> | 47 | #include <asm/fixed_code.h> |
48 | 48 | ||
49 | #define MAX_SHARED_LIBS 3 | ||
50 | #define TEXT_OFFSET 0 | 49 | #define TEXT_OFFSET 0 |
51 | /* | 50 | /* |
52 | * does not yet catch signals sent when the child dies. | 51 | * does not yet catch signals sent when the child dies. |
@@ -161,21 +160,32 @@ static inline int is_user_addr_valid(struct task_struct *child, | |||
161 | struct vm_list_struct *vml; | 160 | struct vm_list_struct *vml; |
162 | struct sram_list_struct *sraml; | 161 | struct sram_list_struct *sraml; |
163 | 162 | ||
163 | /* overflow */ | ||
164 | if (start + len < start) | ||
165 | return -EIO; | ||
166 | |||
164 | for (vml = child->mm->context.vmlist; vml; vml = vml->next) | 167 | for (vml = child->mm->context.vmlist; vml; vml = vml->next) |
165 | if (start >= vml->vma->vm_start && start + len <= vml->vma->vm_end) | 168 | if (start >= vml->vma->vm_start && start + len < vml->vma->vm_end) |
166 | return 0; | 169 | return 0; |
167 | 170 | ||
168 | for (sraml = child->mm->context.sram_list; sraml; sraml = sraml->next) | 171 | for (sraml = child->mm->context.sram_list; sraml; sraml = sraml->next) |
169 | if (start >= (unsigned long)sraml->addr | 172 | if (start >= (unsigned long)sraml->addr |
170 | && start + len <= (unsigned long)sraml->addr + sraml->length) | 173 | && start + len < (unsigned long)sraml->addr + sraml->length) |
171 | return 0; | 174 | return 0; |
172 | 175 | ||
173 | if (start >= FIXED_CODE_START && start + len <= FIXED_CODE_END) | 176 | if (start >= FIXED_CODE_START && start + len < FIXED_CODE_END) |
174 | return 0; | 177 | return 0; |
175 | 178 | ||
176 | return -EIO; | 179 | return -EIO; |
177 | } | 180 | } |
178 | 181 | ||
182 | void ptrace_enable(struct task_struct *child) | ||
183 | { | ||
184 | unsigned long tmp; | ||
185 | tmp = get_reg(child, PT_SYSCFG) | (TRACE_BITS); | ||
186 | put_reg(child, PT_SYSCFG, tmp); | ||
187 | } | ||
188 | |||
179 | /* | 189 | /* |
180 | * Called by kernel/ptrace.c when detaching.. | 190 | * Called by kernel/ptrace.c when detaching.. |
181 | * | 191 | * |
@@ -192,14 +202,12 @@ void ptrace_disable(struct task_struct *child) | |||
192 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 202 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
193 | { | 203 | { |
194 | int ret; | 204 | int ret; |
195 | int add = 0; | ||
196 | unsigned long __user *datap = (unsigned long __user *)data; | 205 | unsigned long __user *datap = (unsigned long __user *)data; |
197 | 206 | ||
198 | switch (request) { | 207 | switch (request) { |
199 | /* when I and D space are separate, these will need to be fixed. */ | 208 | /* when I and D space are separate, these will need to be fixed. */ |
200 | case PTRACE_PEEKDATA: | 209 | case PTRACE_PEEKDATA: |
201 | pr_debug("ptrace: PEEKDATA\n"); | 210 | pr_debug("ptrace: PEEKDATA\n"); |
202 | add = MAX_SHARED_LIBS * 4; /* space between text and data */ | ||
203 | /* fall through */ | 211 | /* fall through */ |
204 | case PTRACE_PEEKTEXT: /* read word at location addr. */ | 212 | case PTRACE_PEEKTEXT: /* read word at location addr. */ |
205 | { | 213 | { |
@@ -207,40 +215,35 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
207 | int copied; | 215 | int copied; |
208 | 216 | ||
209 | ret = -EIO; | 217 | ret = -EIO; |
210 | pr_debug("ptrace: PEEKTEXT at addr 0x%08lx + add %d %ld\n", addr, add, | 218 | pr_debug("ptrace: PEEKTEXT at addr 0x%08lx + %ld\n", addr, sizeof(data)); |
211 | sizeof(data)); | 219 | if (is_user_addr_valid(child, addr, sizeof(tmp)) < 0) |
212 | if (is_user_addr_valid(child, addr + add, sizeof(tmp)) < 0) | ||
213 | break; | 220 | break; |
214 | pr_debug("ptrace: user address is valid\n"); | 221 | pr_debug("ptrace: user address is valid\n"); |
215 | 222 | ||
216 | #if L1_CODE_LENGTH != 0 | 223 | if (L1_CODE_LENGTH != 0 && addr >= L1_CODE_START |
217 | if (addr + add >= L1_CODE_START | 224 | && addr + sizeof(tmp) <= L1_CODE_START + L1_CODE_LENGTH) { |
218 | && addr + add + sizeof(tmp) <= L1_CODE_START + L1_CODE_LENGTH) { | 225 | safe_dma_memcpy (&tmp, (const void *)(addr), sizeof(tmp)); |
219 | safe_dma_memcpy (&tmp, (const void *)(addr + add), sizeof(tmp)); | ||
220 | copied = sizeof(tmp); | 226 | copied = sizeof(tmp); |
221 | } else | 227 | |
222 | #endif | 228 | } else if (L1_DATA_A_LENGTH != 0 && addr >= L1_DATA_A_START |
223 | #if L1_DATA_A_LENGTH != 0 | 229 | && addr + sizeof(tmp) <= L1_DATA_A_START + L1_DATA_A_LENGTH) { |
224 | if (addr + add >= L1_DATA_A_START | 230 | memcpy(&tmp, (const void *)(addr), sizeof(tmp)); |
225 | && addr + add + sizeof(tmp) <= L1_DATA_A_START + L1_DATA_A_LENGTH) { | ||
226 | memcpy(&tmp, (const void *)(addr + add), sizeof(tmp)); | ||
227 | copied = sizeof(tmp); | 231 | copied = sizeof(tmp); |
228 | } else | 232 | |
229 | #endif | 233 | } else if (L1_DATA_B_LENGTH != 0 && addr >= L1_DATA_B_START |
230 | #if L1_DATA_B_LENGTH != 0 | 234 | && addr + sizeof(tmp) <= L1_DATA_B_START + L1_DATA_B_LENGTH) { |
231 | if (addr + add >= L1_DATA_B_START | 235 | memcpy(&tmp, (const void *)(addr), sizeof(tmp)); |
232 | && addr + add + sizeof(tmp) <= L1_DATA_B_START + L1_DATA_B_LENGTH) { | ||
233 | memcpy(&tmp, (const void *)(addr + add), sizeof(tmp)); | ||
234 | copied = sizeof(tmp); | 236 | copied = sizeof(tmp); |
235 | } else | 237 | |
236 | #endif | 238 | } else if (addr >= FIXED_CODE_START |
237 | if (addr + add >= FIXED_CODE_START | 239 | && addr + sizeof(tmp) <= FIXED_CODE_END) { |
238 | && addr + add + sizeof(tmp) <= FIXED_CODE_END) { | 240 | memcpy(&tmp, (const void *)(addr), sizeof(tmp)); |
239 | memcpy(&tmp, (const void *)(addr + add), sizeof(tmp)); | ||
240 | copied = sizeof(tmp); | 241 | copied = sizeof(tmp); |
242 | |||
241 | } else | 243 | } else |
242 | copied = access_process_vm(child, addr + add, &tmp, | 244 | copied = access_process_vm(child, addr, &tmp, |
243 | sizeof(tmp), 0); | 245 | sizeof(tmp), 0); |
246 | |||
244 | pr_debug("ptrace: copied size %d [0x%08lx]\n", copied, tmp); | 247 | pr_debug("ptrace: copied size %d [0x%08lx]\n", copied, tmp); |
245 | if (copied != sizeof(tmp)) | 248 | if (copied != sizeof(tmp)) |
246 | break; | 249 | break; |
@@ -284,47 +287,43 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
284 | 287 | ||
285 | /* when I and D space are separate, this will have to be fixed. */ | 288 | /* when I and D space are separate, this will have to be fixed. */ |
286 | case PTRACE_POKEDATA: | 289 | case PTRACE_POKEDATA: |
287 | printk(KERN_NOTICE "ptrace: PTRACE_PEEKDATA\n"); | 290 | pr_debug("ptrace: PTRACE_PEEKDATA\n"); |
288 | /* fall through */ | 291 | /* fall through */ |
289 | case PTRACE_POKETEXT: /* write the word at location addr. */ | 292 | case PTRACE_POKETEXT: /* write the word at location addr. */ |
290 | { | 293 | { |
291 | int copied; | 294 | int copied; |
292 | 295 | ||
293 | ret = -EIO; | 296 | ret = -EIO; |
294 | pr_debug("ptrace: POKETEXT at addr 0x%08lx + add %d %ld bytes %lx\n", | 297 | pr_debug("ptrace: POKETEXT at addr 0x%08lx + %ld bytes %lx\n", |
295 | addr, add, sizeof(data), data); | 298 | addr, sizeof(data), data); |
296 | if (is_user_addr_valid(child, addr + add, sizeof(data)) < 0) | 299 | if (is_user_addr_valid(child, addr, sizeof(data)) < 0) |
297 | break; | 300 | break; |
298 | pr_debug("ptrace: user address is valid\n"); | 301 | pr_debug("ptrace: user address is valid\n"); |
299 | 302 | ||
300 | #if L1_CODE_LENGTH != 0 | 303 | if (L1_CODE_LENGTH != 0 && addr >= L1_CODE_START |
301 | if (addr + add >= L1_CODE_START | 304 | && addr + sizeof(data) <= L1_CODE_START + L1_CODE_LENGTH) { |
302 | && addr + add + sizeof(data) <= L1_CODE_START + L1_CODE_LENGTH) { | 305 | safe_dma_memcpy ((void *)(addr), &data, sizeof(data)); |
303 | safe_dma_memcpy ((void *)(addr + add), &data, sizeof(data)); | ||
304 | copied = sizeof(data); | 306 | copied = sizeof(data); |
305 | } else | 307 | |
306 | #endif | 308 | } else if (L1_DATA_A_LENGTH != 0 && addr >= L1_DATA_A_START |
307 | #if L1_DATA_A_LENGTH != 0 | 309 | && addr + sizeof(data) <= L1_DATA_A_START + L1_DATA_A_LENGTH) { |
308 | if (addr + add >= L1_DATA_A_START | 310 | memcpy((void *)(addr), &data, sizeof(data)); |
309 | && addr + add + sizeof(data) <= L1_DATA_A_START + L1_DATA_A_LENGTH) { | ||
310 | memcpy((void *)(addr + add), &data, sizeof(data)); | ||
311 | copied = sizeof(data); | 311 | copied = sizeof(data); |
312 | } else | 312 | |
313 | #endif | 313 | } else if (L1_DATA_B_LENGTH != 0 && addr >= L1_DATA_B_START |
314 | #if L1_DATA_B_LENGTH != 0 | 314 | && addr + sizeof(data) <= L1_DATA_B_START + L1_DATA_B_LENGTH) { |
315 | if (addr + add >= L1_DATA_B_START | 315 | memcpy((void *)(addr), &data, sizeof(data)); |
316 | && addr + add + sizeof(data) <= L1_DATA_B_START + L1_DATA_B_LENGTH) { | ||
317 | memcpy((void *)(addr + add), &data, sizeof(data)); | ||
318 | copied = sizeof(data); | 316 | copied = sizeof(data); |
319 | } else | 317 | |
320 | #endif | 318 | } else if (addr >= FIXED_CODE_START |
321 | if (addr + add >= FIXED_CODE_START | 319 | && addr + sizeof(data) <= FIXED_CODE_END) { |
322 | && addr + add + sizeof(data) <= FIXED_CODE_END) { | 320 | memcpy((void *)(addr), &data, sizeof(data)); |
323 | memcpy((void *)(addr + add), &data, sizeof(data)); | ||
324 | copied = sizeof(data); | 321 | copied = sizeof(data); |
322 | |||
325 | } else | 323 | } else |
326 | copied = access_process_vm(child, addr + add, &data, | 324 | copied = access_process_vm(child, addr, &data, |
327 | sizeof(data), 1); | 325 | sizeof(data), 1); |
326 | |||
328 | pr_debug("ptrace: copied size %d\n", copied); | 327 | pr_debug("ptrace: copied size %d\n", copied); |
329 | if (copied != sizeof(data)) | 328 | if (copied != sizeof(data)) |
330 | break; | 329 | break; |
@@ -351,29 +350,22 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
351 | break; | 350 | break; |
352 | 351 | ||
353 | case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ | 352 | case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ |
354 | case PTRACE_CONT: | 353 | case PTRACE_CONT: /* restart after signal. */ |
355 | { /* restart after signal. */ | 354 | pr_debug("ptrace: syscall/cont\n"); |
356 | long tmp; | ||
357 | 355 | ||
358 | pr_debug("ptrace_cont\n"); | 356 | ret = -EIO; |
359 | 357 | if (!valid_signal(data)) | |
360 | ret = -EIO; | ||
361 | if (!valid_signal(data)) | ||
362 | break; | ||
363 | if (request == PTRACE_SYSCALL) | ||
364 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
365 | else | ||
366 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
367 | |||
368 | child->exit_code = data; | ||
369 | /* make sure the single step bit is not set. */ | ||
370 | tmp = get_reg(child, PT_SYSCFG) & ~(TRACE_BITS); | ||
371 | put_reg(child, PT_SYSCFG, tmp); | ||
372 | pr_debug("before wake_up_process\n"); | ||
373 | wake_up_process(child); | ||
374 | ret = 0; | ||
375 | break; | 358 | break; |
376 | } | 359 | if (request == PTRACE_SYSCALL) |
360 | set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
361 | else | ||
362 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
363 | child->exit_code = data; | ||
364 | ptrace_disable(child); | ||
365 | pr_debug("ptrace: before wake_up_process\n"); | ||
366 | wake_up_process(child); | ||
367 | ret = 0; | ||
368 | break; | ||
377 | 369 | ||
378 | /* | 370 | /* |
379 | * make the child exit. Best I can do is send it a sigkill. | 371 | * make the child exit. Best I can do is send it a sigkill. |
@@ -381,55 +373,37 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
381 | * exit. | 373 | * exit. |
382 | */ | 374 | */ |
383 | case PTRACE_KILL: | 375 | case PTRACE_KILL: |
384 | { | 376 | ret = 0; |
385 | long tmp; | 377 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ |
386 | ret = 0; | ||
387 | if (child->exit_state == EXIT_ZOMBIE) /* already dead */ | ||
388 | break; | ||
389 | child->exit_code = SIGKILL; | ||
390 | /* make sure the single step bit is not set. */ | ||
391 | tmp = get_reg(child, PT_SYSCFG) & ~(TRACE_BITS); | ||
392 | put_reg(child, PT_SYSCFG, tmp); | ||
393 | wake_up_process(child); | ||
394 | break; | 378 | break; |
395 | } | 379 | child->exit_code = SIGKILL; |
396 | 380 | ptrace_disable(child); | |
397 | case PTRACE_SINGLESTEP: | 381 | wake_up_process(child); |
398 | { /* set the trap flag. */ | 382 | break; |
399 | long tmp; | ||
400 | |||
401 | pr_debug("single step\n"); | ||
402 | ret = -EIO; | ||
403 | if (!valid_signal(data)) | ||
404 | break; | ||
405 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); | ||
406 | |||
407 | tmp = get_reg(child, PT_SYSCFG) | (TRACE_BITS); | ||
408 | put_reg(child, PT_SYSCFG, tmp); | ||
409 | 383 | ||
410 | child->exit_code = data; | 384 | case PTRACE_SINGLESTEP: /* set the trap flag. */ |
411 | /* give it a chance to run. */ | 385 | pr_debug("ptrace: single step\n"); |
412 | wake_up_process(child); | 386 | ret = -EIO; |
413 | ret = 0; | 387 | if (!valid_signal(data)) |
414 | break; | 388 | break; |
415 | } | 389 | clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); |
390 | ptrace_enable(child); | ||
391 | child->exit_code = data; | ||
392 | wake_up_process(child); | ||
393 | ret = 0; | ||
394 | break; | ||
416 | 395 | ||
417 | case PTRACE_GETREGS: | 396 | case PTRACE_GETREGS: |
418 | { | 397 | /* Get all gp regs from the child. */ |
419 | 398 | ret = ptrace_getregs(child, datap); | |
420 | /* Get all gp regs from the child. */ | 399 | break; |
421 | ret = ptrace_getregs(child, datap); | ||
422 | break; | ||
423 | } | ||
424 | 400 | ||
425 | case PTRACE_SETREGS: | 401 | case PTRACE_SETREGS: |
426 | { | 402 | printk(KERN_WARNING "ptrace: SETREGS: **** NOT IMPLEMENTED ***\n"); |
427 | printk(KERN_NOTICE | 403 | /* Set all gp regs in the child. */ |
428 | "ptrace: SETREGS: **** NOT IMPLEMENTED ***\n"); | 404 | ret = 0; |
429 | /* Set all gp regs in the child. */ | 405 | break; |
430 | ret = 0; | 406 | |
431 | break; | ||
432 | } | ||
433 | default: | 407 | default: |
434 | ret = ptrace_request(child, request, addr, data); | 408 | ret = ptrace_request(child, request, addr, data); |
435 | break; | 409 | break; |
@@ -440,7 +414,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
440 | 414 | ||
441 | asmlinkage void syscall_trace(void) | 415 | asmlinkage void syscall_trace(void) |
442 | { | 416 | { |
443 | |||
444 | if (!test_thread_flag(TIF_SYSCALL_TRACE)) | 417 | if (!test_thread_flag(TIF_SYSCALL_TRACE)) |
445 | return; | 418 | return; |
446 | 419 | ||
diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c index 367e2dc09881..ae97ca407b0d 100644 --- a/arch/blackfin/kernel/reboot.c +++ b/arch/blackfin/kernel/reboot.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <asm/bfin-global.h> | 10 | #include <asm/bfin-global.h> |
11 | #include <asm/reboot.h> | 11 | #include <asm/reboot.h> |
12 | #include <asm/system.h> | 12 | #include <asm/system.h> |
13 | #include <asm/bfrom.h> | ||
13 | 14 | ||
14 | /* A system soft reset makes external memory unusable so force | 15 | /* A system soft reset makes external memory unusable so force |
15 | * this function into L1. We use the compiler ssync here rather | 16 | * this function into L1. We use the compiler ssync here rather |
@@ -20,7 +21,7 @@ | |||
20 | * the core reset. | 21 | * the core reset. |
21 | */ | 22 | */ |
22 | __attribute__((l1_text)) | 23 | __attribute__((l1_text)) |
23 | void bfin_reset(void) | 24 | static void bfin_reset(void) |
24 | { | 25 | { |
25 | /* Wait for completion of "system" events such as cache line | 26 | /* Wait for completion of "system" events such as cache line |
26 | * line fills so that we avoid infinite stalls later on as | 27 | * line fills so that we avoid infinite stalls later on as |
@@ -34,15 +35,15 @@ void bfin_reset(void) | |||
34 | bfin_write_SWRST(0x7); | 35 | bfin_write_SWRST(0x7); |
35 | 36 | ||
36 | /* Due to the way reset is handled in the hardware, we need | 37 | /* Due to the way reset is handled in the hardware, we need |
37 | * to delay for 7 SCLKS. The only reliable way to do this is | 38 | * to delay for 10 SCLKS. The only reliable way to do this is |
38 | * to calculate the CCLK/SCLK ratio and multiply 7. For now, | 39 | * to calculate the CCLK/SCLK ratio and multiply 10. For now, |
39 | * we'll assume worse case which is a 1:15 ratio. | 40 | * we'll assume worse case which is a 1:15 ratio. |
40 | */ | 41 | */ |
41 | asm( | 42 | asm( |
42 | "LSETUP (1f, 1f) LC0 = %0\n" | 43 | "LSETUP (1f, 1f) LC0 = %0\n" |
43 | "1: nop;" | 44 | "1: nop;" |
44 | : | 45 | : |
45 | : "a" (15 * 7) | 46 | : "a" (15 * 10) |
46 | : "LC0", "LB0", "LT0" | 47 | : "LC0", "LB0", "LT0" |
47 | ); | 48 | ); |
48 | 49 | ||
@@ -74,7 +75,14 @@ void machine_restart(char *cmd) | |||
74 | { | 75 | { |
75 | native_machine_restart(cmd); | 76 | native_machine_restart(cmd); |
76 | local_irq_disable(); | 77 | local_irq_disable(); |
77 | bfin_reset(); | 78 | if (ANOMALY_05000353 || ANOMALY_05000386) |
79 | bfin_reset(); | ||
80 | else | ||
81 | /* the bootrom checks to see how it was reset and will | ||
82 | * automatically perform a software reset for us when | ||
83 | * it starts executing boot | ||
84 | */ | ||
85 | asm("raise 1;"); | ||
78 | } | 86 | } |
79 | 87 | ||
80 | __attribute__((weak)) | 88 | __attribute__((weak)) |
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 7a82d10b4ebf..7f35d1046cd8 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c | |||
@@ -42,6 +42,7 @@ EXPORT_SYMBOL(memory_start); | |||
42 | EXPORT_SYMBOL(memory_end); | 42 | EXPORT_SYMBOL(memory_end); |
43 | EXPORT_SYMBOL(physical_mem_end); | 43 | EXPORT_SYMBOL(physical_mem_end); |
44 | EXPORT_SYMBOL(_ramend); | 44 | EXPORT_SYMBOL(_ramend); |
45 | EXPORT_SYMBOL(reserved_mem_dcache_on); | ||
45 | 46 | ||
46 | #ifdef CONFIG_MTD_UCLINUX | 47 | #ifdef CONFIG_MTD_UCLINUX |
47 | unsigned long memory_mtd_end, memory_mtd_start, mtd_size; | 48 | unsigned long memory_mtd_end, memory_mtd_start, mtd_size; |
@@ -52,7 +53,8 @@ EXPORT_SYMBOL(mtd_size); | |||
52 | #endif | 53 | #endif |
53 | 54 | ||
54 | char __initdata command_line[COMMAND_LINE_SIZE]; | 55 | char __initdata command_line[COMMAND_LINE_SIZE]; |
55 | unsigned int __initdata *__retx; | 56 | void __initdata *init_retx, *init_saved_retx, *init_saved_seqstat, |
57 | *init_saved_icplb_fault_addr, *init_saved_dcplb_fault_addr; | ||
56 | 58 | ||
57 | /* boot memmap, for parsing "memmap=" */ | 59 | /* boot memmap, for parsing "memmap=" */ |
58 | #define BFIN_MEMMAP_MAX 128 /* number of entries in bfin_memmap */ | 60 | #define BFIN_MEMMAP_MAX 128 /* number of entries in bfin_memmap */ |
@@ -77,10 +79,10 @@ static struct change_member *change_point[2*BFIN_MEMMAP_MAX] __initdata; | |||
77 | static struct bfin_memmap_entry *overlap_list[BFIN_MEMMAP_MAX] __initdata; | 79 | static struct bfin_memmap_entry *overlap_list[BFIN_MEMMAP_MAX] __initdata; |
78 | static struct bfin_memmap_entry new_map[BFIN_MEMMAP_MAX] __initdata; | 80 | static struct bfin_memmap_entry new_map[BFIN_MEMMAP_MAX] __initdata; |
79 | 81 | ||
80 | void __init bf53x_cache_init(void) | 82 | void __init bfin_cache_init(void) |
81 | { | 83 | { |
82 | #if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE) | 84 | #if defined(CONFIG_BFIN_DCACHE) || defined(CONFIG_BFIN_ICACHE) |
83 | generate_cpl_tables(); | 85 | generate_cplb_tables(); |
84 | #endif | 86 | #endif |
85 | 87 | ||
86 | #ifdef CONFIG_BFIN_ICACHE | 88 | #ifdef CONFIG_BFIN_ICACHE |
@@ -100,7 +102,7 @@ void __init bf53x_cache_init(void) | |||
100 | #endif | 102 | #endif |
101 | } | 103 | } |
102 | 104 | ||
103 | void __init bf53x_relocate_l1_mem(void) | 105 | void __init bfin_relocate_l1_mem(void) |
104 | { | 106 | { |
105 | unsigned long l1_code_length; | 107 | unsigned long l1_code_length; |
106 | unsigned long l1_data_a_length; | 108 | unsigned long l1_data_a_length; |
@@ -410,7 +412,7 @@ static __init void parse_cmdline_early(char *cmdline_p) | |||
410 | * [_rambase, _ramstart]: kernel image | 412 | * [_rambase, _ramstart]: kernel image |
411 | * [memory_start, memory_end]: dynamic memory managed by kernel | 413 | * [memory_start, memory_end]: dynamic memory managed by kernel |
412 | * [memory_end, _ramend]: reserved memory | 414 | * [memory_end, _ramend]: reserved memory |
413 | * [meory_mtd_start(memory_end), | 415 | * [memory_mtd_start(memory_end), |
414 | * memory_mtd_start + mtd_size]: rootfs (if any) | 416 | * memory_mtd_start + mtd_size]: rootfs (if any) |
415 | * [_ramend - DMA_UNCACHED_REGION, | 417 | * [_ramend - DMA_UNCACHED_REGION, |
416 | * _ramend]: uncached DMA region | 418 | * _ramend]: uncached DMA region |
@@ -782,16 +784,25 @@ void __init setup_arch(char **cmdline_p) | |||
782 | 784 | ||
783 | _bfin_swrst = bfin_read_SWRST(); | 785 | _bfin_swrst = bfin_read_SWRST(); |
784 | 786 | ||
785 | /* If we double fault, reset the system - otherwise we hang forever */ | 787 | #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT |
786 | bfin_write_SWRST(DOUBLE_FAULT); | 788 | bfin_write_SWRST(_bfin_swrst & ~DOUBLE_FAULT); |
789 | #endif | ||
790 | #ifdef CONFIG_DEBUG_DOUBLEFAULT_RESET | ||
791 | bfin_write_SWRST(_bfin_swrst | DOUBLE_FAULT); | ||
792 | #endif | ||
787 | 793 | ||
788 | if (_bfin_swrst & RESET_DOUBLE) | 794 | if (_bfin_swrst & RESET_DOUBLE) { |
789 | /* | 795 | printk(KERN_EMERG "Recovering from DOUBLE FAULT event\n"); |
790 | * don't decode the address, since you don't know if this | 796 | #ifdef CONFIG_DEBUG_DOUBLEFAULT |
791 | * kernel's symbol map is the same as the crashing kernel | 797 | /* We assume the crashing kernel, and the current symbol table match */ |
792 | */ | 798 | printk(KERN_EMERG " While handling exception (EXCAUSE = 0x%x) at %pF\n", |
793 | printk(KERN_INFO "Recovering from Double Fault event at %pF\n", __retx); | 799 | (int)init_saved_seqstat & SEQSTAT_EXCAUSE, init_saved_retx); |
794 | else if (_bfin_swrst & RESET_WDOG) | 800 | printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %pF\n", init_saved_dcplb_fault_addr); |
801 | printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %pF\n", init_saved_icplb_fault_addr); | ||
802 | #endif | ||
803 | printk(KERN_NOTICE " The instruction at %pF caused a double exception\n", | ||
804 | init_retx); | ||
805 | } else if (_bfin_swrst & RESET_WDOG) | ||
795 | printk(KERN_INFO "Recovering from Watchdog event\n"); | 806 | printk(KERN_INFO "Recovering from Watchdog event\n"); |
796 | else if (_bfin_swrst & RESET_SOFTWARE) | 807 | else if (_bfin_swrst & RESET_SOFTWARE) |
797 | printk(KERN_NOTICE "Reset caused by Software reset\n"); | 808 | printk(KERN_NOTICE "Reset caused by Software reset\n"); |
@@ -803,17 +814,24 @@ void __init setup_arch(char **cmdline_p) | |||
803 | printk(KERN_INFO "Compiled for ADSP-%s Rev none\n", CPU); | 814 | printk(KERN_INFO "Compiled for ADSP-%s Rev none\n", CPU); |
804 | else | 815 | else |
805 | printk(KERN_INFO "Compiled for ADSP-%s Rev 0.%d\n", CPU, bfin_compiled_revid()); | 816 | printk(KERN_INFO "Compiled for ADSP-%s Rev 0.%d\n", CPU, bfin_compiled_revid()); |
806 | if (bfin_revid() != bfin_compiled_revid()) { | 817 | |
807 | if (bfin_compiled_revid() == -1) | 818 | if (unlikely(CPUID != bfin_cpuid())) |
808 | printk(KERN_ERR "Warning: Compiled for Rev none, but running on Rev %d\n", | 819 | printk(KERN_ERR "ERROR: Not running on ADSP-%s: unknown CPUID 0x%04x Rev 0.%d\n", |
809 | bfin_revid()); | 820 | CPU, bfin_cpuid(), bfin_revid()); |
810 | else if (bfin_compiled_revid() != 0xffff) | 821 | else { |
811 | printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n", | 822 | if (bfin_revid() != bfin_compiled_revid()) { |
812 | bfin_compiled_revid(), bfin_revid()); | 823 | if (bfin_compiled_revid() == -1) |
824 | printk(KERN_ERR "Warning: Compiled for Rev none, but running on Rev %d\n", | ||
825 | bfin_revid()); | ||
826 | else if (bfin_compiled_revid() != 0xffff) | ||
827 | printk(KERN_ERR "Warning: Compiled for Rev %d, but running on Rev %d\n", | ||
828 | bfin_compiled_revid(), bfin_revid()); | ||
829 | } | ||
830 | if (bfin_revid() <= CONFIG_BF_REV_MIN || bfin_revid() > CONFIG_BF_REV_MAX) | ||
831 | printk(KERN_ERR "Warning: Unsupported Chip Revision ADSP-%s Rev 0.%d detected\n", | ||
832 | CPU, bfin_revid()); | ||
813 | } | 833 | } |
814 | if (bfin_revid() < SUPPORTED_REVID) | 834 | |
815 | printk(KERN_ERR "Warning: Unsupported Chip Revision ADSP-%s Rev 0.%d detected\n", | ||
816 | CPU, bfin_revid()); | ||
817 | printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n"); | 835 | printk(KERN_INFO "Blackfin Linux support by http://blackfin.uclinux.org/\n"); |
818 | 836 | ||
819 | printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu MHz System Clock\n", | 837 | printk(KERN_INFO "Processor Speed: %lu MHz core clock and %lu MHz System Clock\n", |
@@ -850,7 +868,7 @@ void __init setup_arch(char **cmdline_p) | |||
850 | != SAFE_USER_INSTRUCTION - FIXED_CODE_START); | 868 | != SAFE_USER_INSTRUCTION - FIXED_CODE_START); |
851 | 869 | ||
852 | init_exception_vectors(); | 870 | init_exception_vectors(); |
853 | bf53x_cache_init(); | 871 | bfin_cache_init(); |
854 | } | 872 | } |
855 | 873 | ||
856 | static int __init topology_init(void) | 874 | static int __init topology_init(void) |
@@ -986,13 +1004,18 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
986 | } | 1004 | } |
987 | 1005 | ||
988 | seq_printf(m, "processor\t: %d\n" | 1006 | seq_printf(m, "processor\t: %d\n" |
989 | "vendor_id\t: %s\n" | 1007 | "vendor_id\t: %s\n", |
990 | "cpu family\t: 0x%x\n" | 1008 | *(unsigned int *)v, |
991 | "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n" | 1009 | vendor); |
1010 | |||
1011 | if (CPUID == bfin_cpuid()) | ||
1012 | seq_printf(m, "cpu family\t: 0x%04x\n", CPUID); | ||
1013 | else | ||
1014 | seq_printf(m, "cpu family\t: Compiled for:0x%04x, running on:0x%04x\n", | ||
1015 | CPUID, bfin_cpuid()); | ||
1016 | |||
1017 | seq_printf(m, "model name\t: ADSP-%s %lu(MHz CCLK) %lu(MHz SCLK) (%s)\n" | ||
992 | "stepping\t: %d\n", | 1018 | "stepping\t: %d\n", |
993 | 0, | ||
994 | vendor, | ||
995 | (bfin_read_CHIPID() & CHIPID_FAMILY), | ||
996 | cpu, cclk/1000000, sclk/1000000, | 1019 | cpu, cclk/1000000, sclk/1000000, |
997 | #ifdef CONFIG_MPU | 1020 | #ifdef CONFIG_MPU |
998 | "mpu on", | 1021 | "mpu on", |
@@ -1038,7 +1061,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
1038 | if ((bfin_read_DMEM_CONTROL() & (ENDCPLB | DMC_ENABLE)) != (ENDCPLB | DMC_ENABLE)) | 1061 | if ((bfin_read_DMEM_CONTROL() & (ENDCPLB | DMC_ENABLE)) != (ENDCPLB | DMC_ENABLE)) |
1039 | dcache_size = 0; | 1062 | dcache_size = 0; |
1040 | 1063 | ||
1041 | if ((bfin_read_IMEM_CONTROL() & (IMC | ENICPLB)) == (IMC | ENICPLB)) | 1064 | if ((bfin_read_IMEM_CONTROL() & (IMC | ENICPLB)) != (IMC | ENICPLB)) |
1042 | icache_size = 0; | 1065 | icache_size = 0; |
1043 | 1066 | ||
1044 | seq_printf(m, "cache size\t: %d KB(L1 icache) " | 1067 | seq_printf(m, "cache size\t: %d KB(L1 icache) " |
@@ -1127,12 +1150,18 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
1127 | 1150 | ||
1128 | static void *c_start(struct seq_file *m, loff_t *pos) | 1151 | static void *c_start(struct seq_file *m, loff_t *pos) |
1129 | { | 1152 | { |
1130 | return *pos < NR_CPUS ? ((void *)0x12345678) : NULL; | 1153 | if (*pos == 0) |
1154 | *pos = first_cpu(cpu_online_map); | ||
1155 | if (*pos >= num_online_cpus()) | ||
1156 | return NULL; | ||
1157 | |||
1158 | return pos; | ||
1131 | } | 1159 | } |
1132 | 1160 | ||
1133 | static void *c_next(struct seq_file *m, void *v, loff_t *pos) | 1161 | static void *c_next(struct seq_file *m, void *v, loff_t *pos) |
1134 | { | 1162 | { |
1135 | ++*pos; | 1163 | *pos = next_cpu(*pos, cpu_online_map); |
1164 | |||
1136 | return c_start(m, pos); | 1165 | return c_start(m, pos); |
1137 | } | 1166 | } |
1138 | 1167 | ||
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 9a9d5083acfd..1aa2c788e228 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c | |||
@@ -34,20 +34,19 @@ | |||
34 | #include <linux/fs.h> | 34 | #include <linux/fs.h> |
35 | #include <asm/traps.h> | 35 | #include <asm/traps.h> |
36 | #include <asm/cacheflush.h> | 36 | #include <asm/cacheflush.h> |
37 | #include <asm/cplb.h> | ||
37 | #include <asm/blackfin.h> | 38 | #include <asm/blackfin.h> |
38 | #include <asm/irq_handler.h> | 39 | #include <asm/irq_handler.h> |
39 | #include <linux/irq.h> | 40 | #include <linux/irq.h> |
40 | #include <asm/trace.h> | 41 | #include <asm/trace.h> |
41 | #include <asm/fixed_code.h> | 42 | #include <asm/fixed_code.h> |
42 | #include <asm/dma.h> | ||
43 | 43 | ||
44 | #ifdef CONFIG_KGDB | 44 | #ifdef CONFIG_KGDB |
45 | # include <linux/debugger.h> | ||
46 | # include <linux/kgdb.h> | 45 | # include <linux/kgdb.h> |
47 | 46 | ||
48 | # define CHK_DEBUGGER_TRAP() \ | 47 | # define CHK_DEBUGGER_TRAP() \ |
49 | do { \ | 48 | do { \ |
50 | CHK_DEBUGGER(trapnr, sig, info.si_code, fp, ); \ | 49 | kgdb_handle_exception(trapnr, sig, info.si_code, fp); \ |
51 | } while (0) | 50 | } while (0) |
52 | # define CHK_DEBUGGER_TRAP_MAYBE() \ | 51 | # define CHK_DEBUGGER_TRAP_MAYBE() \ |
53 | do { \ | 52 | do { \ |
@@ -59,6 +58,15 @@ | |||
59 | # define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0) | 58 | # define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0) |
60 | #endif | 59 | #endif |
61 | 60 | ||
61 | |||
62 | #ifdef CONFIG_VERBOSE_DEBUG | ||
63 | #define verbose_printk(fmt, arg...) \ | ||
64 | printk(fmt, ##arg) | ||
65 | #else | ||
66 | #define verbose_printk(fmt, arg...) \ | ||
67 | ({ if (0) printk(fmt, ##arg); 0; }) | ||
68 | #endif | ||
69 | |||
62 | /* Initiate the event table handler */ | 70 | /* Initiate the event table handler */ |
63 | void __init trap_init(void) | 71 | void __init trap_init(void) |
64 | { | 72 | { |
@@ -67,10 +75,19 @@ void __init trap_init(void) | |||
67 | CSYNC(); | 75 | CSYNC(); |
68 | } | 76 | } |
69 | 77 | ||
70 | unsigned long saved_icplb_fault_addr, saved_dcplb_fault_addr; | 78 | /* |
79 | * Used to save the RETX, SEQSTAT, I/D CPLB FAULT ADDR | ||
80 | * values across the transition from exception to IRQ5. | ||
81 | * We put these in L1, so they are going to be in a valid | ||
82 | * location during exception context | ||
83 | */ | ||
84 | __attribute__((l1_data)) | ||
85 | unsigned long saved_retx, saved_seqstat, | ||
86 | saved_icplb_fault_addr, saved_dcplb_fault_addr; | ||
71 | 87 | ||
72 | static void decode_address(char *buf, unsigned long address) | 88 | static void decode_address(char *buf, unsigned long address) |
73 | { | 89 | { |
90 | #ifdef CONFIG_DEBUG_VERBOSE | ||
74 | struct vm_list_struct *vml; | 91 | struct vm_list_struct *vml; |
75 | struct task_struct *p; | 92 | struct task_struct *p; |
76 | struct mm_struct *mm; | 93 | struct mm_struct *mm; |
@@ -178,16 +195,39 @@ static void decode_address(char *buf, unsigned long address) | |||
178 | 195 | ||
179 | done: | 196 | done: |
180 | write_unlock_irqrestore(&tasklist_lock, flags); | 197 | write_unlock_irqrestore(&tasklist_lock, flags); |
198 | #else | ||
199 | sprintf(buf, " "); | ||
200 | #endif | ||
181 | } | 201 | } |
182 | 202 | ||
183 | asmlinkage void double_fault_c(struct pt_regs *fp) | 203 | asmlinkage void double_fault_c(struct pt_regs *fp) |
184 | { | 204 | { |
185 | console_verbose(); | 205 | console_verbose(); |
186 | oops_in_progress = 1; | 206 | oops_in_progress = 1; |
207 | #ifdef CONFIG_DEBUG_VERBOSE | ||
187 | printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n"); | 208 | printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n"); |
188 | dump_bfin_process(fp); | 209 | #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT |
189 | dump_bfin_mem(fp); | 210 | if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) { |
190 | show_regs(fp); | 211 | char buf[150]; |
212 | decode_address(buf, saved_retx); | ||
213 | printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n", | ||
214 | (int)saved_seqstat & SEQSTAT_EXCAUSE, buf); | ||
215 | decode_address(buf, saved_dcplb_fault_addr); | ||
216 | printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %s\n", buf); | ||
217 | decode_address(buf, saved_icplb_fault_addr); | ||
218 | printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %s\n", buf); | ||
219 | |||
220 | decode_address(buf, fp->retx); | ||
221 | printk(KERN_NOTICE "The instruction at %s caused a double exception\n", | ||
222 | buf); | ||
223 | } else | ||
224 | #endif | ||
225 | { | ||
226 | dump_bfin_process(fp); | ||
227 | dump_bfin_mem(fp); | ||
228 | show_regs(fp); | ||
229 | } | ||
230 | #endif | ||
191 | panic("Double Fault - unrecoverable event\n"); | 231 | panic("Double Fault - unrecoverable event\n"); |
192 | 232 | ||
193 | } | 233 | } |
@@ -259,34 +299,42 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
259 | return; | 299 | return; |
260 | else | 300 | else |
261 | break; | 301 | break; |
302 | /* 0x03 - User Defined, userspace stack overflow */ | ||
303 | case VEC_EXCPT03: | ||
304 | info.si_code = SEGV_STACKFLOW; | ||
305 | sig = SIGSEGV; | ||
306 | verbose_printk(KERN_NOTICE EXC_0x03(KERN_NOTICE)); | ||
307 | CHK_DEBUGGER_TRAP_MAYBE(); | ||
308 | break; | ||
309 | /* 0x02 - KGDB initial connection and break signal trap */ | ||
310 | case VEC_EXCPT02: | ||
262 | #ifdef CONFIG_KGDB | 311 | #ifdef CONFIG_KGDB |
263 | case VEC_EXCPT02 : /* gdb connection */ | ||
264 | info.si_code = TRAP_ILLTRAP; | 312 | info.si_code = TRAP_ILLTRAP; |
265 | sig = SIGTRAP; | 313 | sig = SIGTRAP; |
266 | CHK_DEBUGGER_TRAP(); | 314 | CHK_DEBUGGER_TRAP(); |
267 | return; | 315 | return; |
268 | #else | ||
269 | /* 0x02 - User Defined, Caught by default */ | ||
270 | #endif | 316 | #endif |
271 | /* 0x03 - User Defined, userspace stack overflow */ | 317 | /* 0x04 - User Defined */ |
272 | case VEC_EXCPT03: | 318 | /* 0x05 - User Defined */ |
273 | info.si_code = SEGV_STACKFLOW; | 319 | /* 0x06 - User Defined */ |
274 | sig = SIGSEGV; | 320 | /* 0x07 - User Defined */ |
275 | printk(KERN_NOTICE EXC_0x03(KERN_NOTICE)); | 321 | /* 0x08 - User Defined */ |
276 | CHK_DEBUGGER_TRAP(); | 322 | /* 0x09 - User Defined */ |
323 | /* 0x0A - User Defined */ | ||
324 | /* 0x0B - User Defined */ | ||
325 | /* 0x0C - User Defined */ | ||
326 | /* 0x0D - User Defined */ | ||
327 | /* 0x0E - User Defined */ | ||
328 | /* 0x0F - User Defined */ | ||
329 | /* If we got here, it is most likely that someone was trying to use a | ||
330 | * custom exception handler, and it is not actually installed properly | ||
331 | */ | ||
332 | case VEC_EXCPT04 ... VEC_EXCPT15: | ||
333 | info.si_code = ILL_ILLPARAOP; | ||
334 | sig = SIGILL; | ||
335 | verbose_printk(KERN_NOTICE EXC_0x04(KERN_NOTICE)); | ||
336 | CHK_DEBUGGER_TRAP_MAYBE(); | ||
277 | break; | 337 | break; |
278 | /* 0x04 - User Defined, Caught by default */ | ||
279 | /* 0x05 - User Defined, Caught by default */ | ||
280 | /* 0x06 - User Defined, Caught by default */ | ||
281 | /* 0x07 - User Defined, Caught by default */ | ||
282 | /* 0x08 - User Defined, Caught by default */ | ||
283 | /* 0x09 - User Defined, Caught by default */ | ||
284 | /* 0x0A - User Defined, Caught by default */ | ||
285 | /* 0x0B - User Defined, Caught by default */ | ||
286 | /* 0x0C - User Defined, Caught by default */ | ||
287 | /* 0x0D - User Defined, Caught by default */ | ||
288 | /* 0x0E - User Defined, Caught by default */ | ||
289 | /* 0x0F - User Defined, Caught by default */ | ||
290 | /* 0x10 HW Single step, handled here */ | 338 | /* 0x10 HW Single step, handled here */ |
291 | case VEC_STEP: | 339 | case VEC_STEP: |
292 | info.si_code = TRAP_STEP; | 340 | info.si_code = TRAP_STEP; |
@@ -301,8 +349,8 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
301 | case VEC_OVFLOW: | 349 | case VEC_OVFLOW: |
302 | info.si_code = TRAP_TRACEFLOW; | 350 | info.si_code = TRAP_TRACEFLOW; |
303 | sig = SIGTRAP; | 351 | sig = SIGTRAP; |
304 | printk(KERN_NOTICE EXC_0x11(KERN_NOTICE)); | 352 | verbose_printk(KERN_NOTICE EXC_0x11(KERN_NOTICE)); |
305 | CHK_DEBUGGER_TRAP(); | 353 | CHK_DEBUGGER_TRAP_MAYBE(); |
306 | break; | 354 | break; |
307 | /* 0x12 - Reserved, Caught by default */ | 355 | /* 0x12 - Reserved, Caught by default */ |
308 | /* 0x13 - Reserved, Caught by default */ | 356 | /* 0x13 - Reserved, Caught by default */ |
@@ -323,44 +371,43 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
323 | case VEC_UNDEF_I: | 371 | case VEC_UNDEF_I: |
324 | info.si_code = ILL_ILLOPC; | 372 | info.si_code = ILL_ILLOPC; |
325 | sig = SIGILL; | 373 | sig = SIGILL; |
326 | printk(KERN_NOTICE EXC_0x21(KERN_NOTICE)); | 374 | verbose_printk(KERN_NOTICE EXC_0x21(KERN_NOTICE)); |
327 | CHK_DEBUGGER_TRAP(); | 375 | CHK_DEBUGGER_TRAP_MAYBE(); |
328 | break; | 376 | break; |
329 | /* 0x22 - Illegal Instruction Combination, handled here */ | 377 | /* 0x22 - Illegal Instruction Combination, handled here */ |
330 | case VEC_ILGAL_I: | 378 | case VEC_ILGAL_I: |
331 | info.si_code = ILL_ILLPARAOP; | 379 | info.si_code = ILL_ILLPARAOP; |
332 | sig = SIGILL; | 380 | sig = SIGILL; |
333 | printk(KERN_NOTICE EXC_0x22(KERN_NOTICE)); | 381 | verbose_printk(KERN_NOTICE EXC_0x22(KERN_NOTICE)); |
334 | CHK_DEBUGGER_TRAP(); | 382 | CHK_DEBUGGER_TRAP_MAYBE(); |
335 | break; | 383 | break; |
336 | /* 0x23 - Data CPLB protection violation, handled here */ | 384 | /* 0x23 - Data CPLB protection violation, handled here */ |
337 | case VEC_CPLB_VL: | 385 | case VEC_CPLB_VL: |
338 | info.si_code = ILL_CPLB_VI; | 386 | info.si_code = ILL_CPLB_VI; |
339 | sig = SIGBUS; | 387 | sig = SIGBUS; |
340 | printk(KERN_NOTICE EXC_0x23(KERN_NOTICE)); | 388 | verbose_printk(KERN_NOTICE EXC_0x23(KERN_NOTICE)); |
341 | CHK_DEBUGGER_TRAP(); | 389 | CHK_DEBUGGER_TRAP_MAYBE(); |
342 | break; | 390 | break; |
343 | /* 0x24 - Data access misaligned, handled here */ | 391 | /* 0x24 - Data access misaligned, handled here */ |
344 | case VEC_MISALI_D: | 392 | case VEC_MISALI_D: |
345 | info.si_code = BUS_ADRALN; | 393 | info.si_code = BUS_ADRALN; |
346 | sig = SIGBUS; | 394 | sig = SIGBUS; |
347 | printk(KERN_NOTICE EXC_0x24(KERN_NOTICE)); | 395 | verbose_printk(KERN_NOTICE EXC_0x24(KERN_NOTICE)); |
348 | CHK_DEBUGGER_TRAP(); | 396 | CHK_DEBUGGER_TRAP_MAYBE(); |
349 | break; | 397 | break; |
350 | /* 0x25 - Unrecoverable Event, handled here */ | 398 | /* 0x25 - Unrecoverable Event, handled here */ |
351 | case VEC_UNCOV: | 399 | case VEC_UNCOV: |
352 | info.si_code = ILL_ILLEXCPT; | 400 | info.si_code = ILL_ILLEXCPT; |
353 | sig = SIGILL; | 401 | sig = SIGILL; |
354 | printk(KERN_NOTICE EXC_0x25(KERN_NOTICE)); | 402 | verbose_printk(KERN_NOTICE EXC_0x25(KERN_NOTICE)); |
355 | CHK_DEBUGGER_TRAP(); | 403 | CHK_DEBUGGER_TRAP_MAYBE(); |
356 | break; | 404 | break; |
357 | /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr, | 405 | /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr, |
358 | error case is handled here */ | 406 | error case is handled here */ |
359 | case VEC_CPLB_M: | 407 | case VEC_CPLB_M: |
360 | info.si_code = BUS_ADRALN; | 408 | info.si_code = BUS_ADRALN; |
361 | sig = SIGBUS; | 409 | sig = SIGBUS; |
362 | printk(KERN_NOTICE EXC_0x26(KERN_NOTICE)); | 410 | verbose_printk(KERN_NOTICE EXC_0x26(KERN_NOTICE)); |
363 | CHK_DEBUGGER_TRAP(); | ||
364 | break; | 411 | break; |
365 | /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */ | 412 | /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */ |
366 | case VEC_CPLB_MHIT: | 413 | case VEC_CPLB_MHIT: |
@@ -368,11 +415,11 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
368 | sig = SIGSEGV; | 415 | sig = SIGSEGV; |
369 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO | 416 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO |
370 | if (saved_dcplb_fault_addr < FIXED_CODE_START) | 417 | if (saved_dcplb_fault_addr < FIXED_CODE_START) |
371 | printk(KERN_NOTICE "NULL pointer access\n"); | 418 | verbose_printk(KERN_NOTICE "NULL pointer access\n"); |
372 | else | 419 | else |
373 | #endif | 420 | #endif |
374 | printk(KERN_NOTICE EXC_0x27(KERN_NOTICE)); | 421 | verbose_printk(KERN_NOTICE EXC_0x27(KERN_NOTICE)); |
375 | CHK_DEBUGGER_TRAP(); | 422 | CHK_DEBUGGER_TRAP_MAYBE(); |
376 | break; | 423 | break; |
377 | /* 0x28 - Emulation Watchpoint, handled here */ | 424 | /* 0x28 - Emulation Watchpoint, handled here */ |
378 | case VEC_WATCH: | 425 | case VEC_WATCH: |
@@ -390,8 +437,8 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
390 | case VEC_ISTRU_VL: /* ADSP-BF535 only (MH) */ | 437 | case VEC_ISTRU_VL: /* ADSP-BF535 only (MH) */ |
391 | info.si_code = BUS_OPFETCH; | 438 | info.si_code = BUS_OPFETCH; |
392 | sig = SIGBUS; | 439 | sig = SIGBUS; |
393 | printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n"); | 440 | verbose_printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n"); |
394 | CHK_DEBUGGER_TRAP(); | 441 | CHK_DEBUGGER_TRAP_MAYBE(); |
395 | break; | 442 | break; |
396 | #else | 443 | #else |
397 | /* 0x29 - Reserved, Caught by default */ | 444 | /* 0x29 - Reserved, Caught by default */ |
@@ -400,22 +447,21 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
400 | case VEC_MISALI_I: | 447 | case VEC_MISALI_I: |
401 | info.si_code = BUS_ADRALN; | 448 | info.si_code = BUS_ADRALN; |
402 | sig = SIGBUS; | 449 | sig = SIGBUS; |
403 | printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE)); | 450 | verbose_printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE)); |
404 | CHK_DEBUGGER_TRAP(); | 451 | CHK_DEBUGGER_TRAP_MAYBE(); |
405 | break; | 452 | break; |
406 | /* 0x2B - Instruction CPLB protection violation, handled here */ | 453 | /* 0x2B - Instruction CPLB protection violation, handled here */ |
407 | case VEC_CPLB_I_VL: | 454 | case VEC_CPLB_I_VL: |
408 | info.si_code = ILL_CPLB_VI; | 455 | info.si_code = ILL_CPLB_VI; |
409 | sig = SIGBUS; | 456 | sig = SIGBUS; |
410 | printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE)); | 457 | verbose_printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE)); |
411 | CHK_DEBUGGER_TRAP(); | 458 | CHK_DEBUGGER_TRAP_MAYBE(); |
412 | break; | 459 | break; |
413 | /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */ | 460 | /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */ |
414 | case VEC_CPLB_I_M: | 461 | case VEC_CPLB_I_M: |
415 | info.si_code = ILL_CPLB_MISS; | 462 | info.si_code = ILL_CPLB_MISS; |
416 | sig = SIGBUS; | 463 | sig = SIGBUS; |
417 | printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE)); | 464 | verbose_printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE)); |
418 | CHK_DEBUGGER_TRAP(); | ||
419 | break; | 465 | break; |
420 | /* 0x2D - Instruction CPLB Multiple Hits, handled here */ | 466 | /* 0x2D - Instruction CPLB Multiple Hits, handled here */ |
421 | case VEC_CPLB_I_MHIT: | 467 | case VEC_CPLB_I_MHIT: |
@@ -423,18 +469,18 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
423 | sig = SIGSEGV; | 469 | sig = SIGSEGV; |
424 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO | 470 | #ifdef CONFIG_DEBUG_HUNT_FOR_ZERO |
425 | if (saved_icplb_fault_addr < FIXED_CODE_START) | 471 | if (saved_icplb_fault_addr < FIXED_CODE_START) |
426 | printk(KERN_NOTICE "Jump to NULL address\n"); | 472 | verbose_printk(KERN_NOTICE "Jump to NULL address\n"); |
427 | else | 473 | else |
428 | #endif | 474 | #endif |
429 | printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE)); | 475 | verbose_printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE)); |
430 | CHK_DEBUGGER_TRAP(); | 476 | CHK_DEBUGGER_TRAP_MAYBE(); |
431 | break; | 477 | break; |
432 | /* 0x2E - Illegal use of Supervisor Resource, handled here */ | 478 | /* 0x2E - Illegal use of Supervisor Resource, handled here */ |
433 | case VEC_ILL_RES: | 479 | case VEC_ILL_RES: |
434 | info.si_code = ILL_PRVOPC; | 480 | info.si_code = ILL_PRVOPC; |
435 | sig = SIGILL; | 481 | sig = SIGILL; |
436 | printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE)); | 482 | verbose_printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE)); |
437 | CHK_DEBUGGER_TRAP(); | 483 | CHK_DEBUGGER_TRAP_MAYBE(); |
438 | break; | 484 | break; |
439 | /* 0x2F - Reserved, Caught by default */ | 485 | /* 0x2F - Reserved, Caught by default */ |
440 | /* 0x30 - Reserved, Caught by default */ | 486 | /* 0x30 - Reserved, Caught by default */ |
@@ -461,17 +507,17 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
461 | case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR): | 507 | case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR): |
462 | info.si_code = BUS_ADRALN; | 508 | info.si_code = BUS_ADRALN; |
463 | sig = SIGBUS; | 509 | sig = SIGBUS; |
464 | printk(KERN_NOTICE HWC_x2(KERN_NOTICE)); | 510 | verbose_printk(KERN_NOTICE HWC_x2(KERN_NOTICE)); |
465 | break; | 511 | break; |
466 | /* External Memory Addressing Error */ | 512 | /* External Memory Addressing Error */ |
467 | case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR): | 513 | case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR): |
468 | info.si_code = BUS_ADRERR; | 514 | info.si_code = BUS_ADRERR; |
469 | sig = SIGBUS; | 515 | sig = SIGBUS; |
470 | printk(KERN_NOTICE HWC_x3(KERN_NOTICE)); | 516 | verbose_printk(KERN_NOTICE HWC_x3(KERN_NOTICE)); |
471 | break; | 517 | break; |
472 | /* Performance Monitor Overflow */ | 518 | /* Performance Monitor Overflow */ |
473 | case (SEQSTAT_HWERRCAUSE_PERF_FLOW): | 519 | case (SEQSTAT_HWERRCAUSE_PERF_FLOW): |
474 | printk(KERN_NOTICE HWC_x12(KERN_NOTICE)); | 520 | verbose_printk(KERN_NOTICE HWC_x12(KERN_NOTICE)); |
475 | break; | 521 | break; |
476 | /* RAISE 5 instruction */ | 522 | /* RAISE 5 instruction */ |
477 | case (SEQSTAT_HWERRCAUSE_RAISE_5): | 523 | case (SEQSTAT_HWERRCAUSE_RAISE_5): |
@@ -481,21 +527,25 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
481 | printk(KERN_NOTICE HWC_default(KERN_NOTICE)); | 527 | printk(KERN_NOTICE HWC_default(KERN_NOTICE)); |
482 | break; | 528 | break; |
483 | } | 529 | } |
484 | CHK_DEBUGGER_TRAP(); | 530 | CHK_DEBUGGER_TRAP_MAYBE(); |
485 | break; | 531 | break; |
532 | /* | ||
533 | * We should be handling all known exception types above, | ||
534 | * if we get here we hit a reserved one, so panic | ||
535 | */ | ||
486 | default: | 536 | default: |
487 | info.si_code = TRAP_ILLTRAP; | 537 | oops_in_progress = 1; |
488 | sig = SIGTRAP; | 538 | info.si_code = ILL_ILLPARAOP; |
489 | printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n", | 539 | sig = SIGILL; |
540 | verbose_printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n", | ||
490 | (fp->seqstat & SEQSTAT_EXCAUSE)); | 541 | (fp->seqstat & SEQSTAT_EXCAUSE)); |
491 | CHK_DEBUGGER_TRAP(); | 542 | CHK_DEBUGGER_TRAP_MAYBE(); |
492 | break; | 543 | break; |
493 | } | 544 | } |
494 | 545 | ||
495 | BUG_ON(sig == 0); | 546 | BUG_ON(sig == 0); |
496 | 547 | ||
497 | if (sig != SIGTRAP) { | 548 | if (sig != SIGTRAP) { |
498 | unsigned long *stack; | ||
499 | dump_bfin_process(fp); | 549 | dump_bfin_process(fp); |
500 | dump_bfin_mem(fp); | 550 | dump_bfin_mem(fp); |
501 | show_regs(fp); | 551 | show_regs(fp); |
@@ -503,7 +553,7 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
503 | /* Print out the trace buffer if it makes sense */ | 553 | /* Print out the trace buffer if it makes sense */ |
504 | #ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE | 554 | #ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE |
505 | if (trapnr == VEC_CPLB_I_M || trapnr == VEC_CPLB_M) | 555 | if (trapnr == VEC_CPLB_I_M || trapnr == VEC_CPLB_M) |
506 | printk(KERN_NOTICE "No trace since you do not have " | 556 | verbose_printk(KERN_NOTICE "No trace since you do not have " |
507 | "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n" | 557 | "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n" |
508 | KERN_NOTICE "\n"); | 558 | KERN_NOTICE "\n"); |
509 | else | 559 | else |
@@ -512,20 +562,22 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
512 | 562 | ||
513 | if (oops_in_progress) { | 563 | if (oops_in_progress) { |
514 | /* Dump the current kernel stack */ | 564 | /* Dump the current kernel stack */ |
515 | printk(KERN_NOTICE "\n" KERN_NOTICE "Kernel Stack\n"); | 565 | verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "Kernel Stack\n"); |
516 | show_stack(current, NULL); | 566 | show_stack(current, NULL); |
517 | |||
518 | print_modules(); | 567 | print_modules(); |
519 | #ifndef CONFIG_ACCESS_CHECK | 568 | #ifndef CONFIG_ACCESS_CHECK |
520 | printk(KERN_EMERG "Please turn on " | 569 | verbose_printk(KERN_EMERG "Please turn on " |
521 | "CONFIG_ACCESS_CHECK\n"); | 570 | "CONFIG_ACCESS_CHECK\n"); |
522 | #endif | 571 | #endif |
523 | panic("Kernel exception"); | 572 | panic("Kernel exception"); |
524 | } else { | 573 | } else { |
574 | #ifdef CONFIG_VERBOSE_DEBUG | ||
575 | unsigned long *stack; | ||
525 | /* Dump the user space stack */ | 576 | /* Dump the user space stack */ |
526 | stack = (unsigned long *)rdusp(); | 577 | stack = (unsigned long *)rdusp(); |
527 | printk(KERN_NOTICE "Userspace Stack\n"); | 578 | verbose_printk(KERN_NOTICE "Userspace Stack\n"); |
528 | show_stack(NULL, stack); | 579 | show_stack(NULL, stack); |
580 | #endif | ||
529 | } | 581 | } |
530 | } | 582 | } |
531 | 583 | ||
@@ -546,7 +598,7 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
546 | * Similar to get_user, do some address checking, then dereference | 598 | * Similar to get_user, do some address checking, then dereference |
547 | * Return true on sucess, false on bad address | 599 | * Return true on sucess, false on bad address |
548 | */ | 600 | */ |
549 | bool get_instruction(unsigned short *val, unsigned short *address) | 601 | static bool get_instruction(unsigned short *val, unsigned short *address) |
550 | { | 602 | { |
551 | 603 | ||
552 | unsigned long addr; | 604 | unsigned long addr; |
@@ -592,7 +644,7 @@ bool get_instruction(unsigned short *val, unsigned short *address) | |||
592 | 644 | ||
593 | #if L1_CODE_LENGTH != 0 | 645 | #if L1_CODE_LENGTH != 0 |
594 | if (addr >= L1_CODE_START && (addr + 2) <= (L1_CODE_START + L1_CODE_LENGTH)) { | 646 | if (addr >= L1_CODE_START && (addr + 2) <= (L1_CODE_START + L1_CODE_LENGTH)) { |
595 | dma_memcpy(val, address, 2); | 647 | isram_memcpy(val, address, 2); |
596 | return true; | 648 | return true; |
597 | } | 649 | } |
598 | #endif | 650 | #endif |
@@ -607,45 +659,48 @@ bool get_instruction(unsigned short *val, unsigned short *address) | |||
607 | * These are the normal instructions which cause change of flow, which | 659 | * These are the normal instructions which cause change of flow, which |
608 | * would be at the source of the trace buffer | 660 | * would be at the source of the trace buffer |
609 | */ | 661 | */ |
610 | void decode_instruction(unsigned short *address) | 662 | #ifdef CONFIG_DEBUG_VERBOSE |
663 | static void decode_instruction(unsigned short *address) | ||
611 | { | 664 | { |
612 | unsigned short opcode; | 665 | unsigned short opcode; |
613 | 666 | ||
614 | if (get_instruction(&opcode, address)) { | 667 | if (get_instruction(&opcode, address)) { |
615 | if (opcode == 0x0010) | 668 | if (opcode == 0x0010) |
616 | printk("RTS"); | 669 | verbose_printk("RTS"); |
617 | else if (opcode == 0x0011) | 670 | else if (opcode == 0x0011) |
618 | printk("RTI"); | 671 | verbose_printk("RTI"); |
619 | else if (opcode == 0x0012) | 672 | else if (opcode == 0x0012) |
620 | printk("RTX"); | 673 | verbose_printk("RTX"); |
621 | else if (opcode >= 0x0050 && opcode <= 0x0057) | 674 | else if (opcode >= 0x0050 && opcode <= 0x0057) |
622 | printk("JUMP (P%i)", opcode & 7); | 675 | verbose_printk("JUMP (P%i)", opcode & 7); |
623 | else if (opcode >= 0x0060 && opcode <= 0x0067) | 676 | else if (opcode >= 0x0060 && opcode <= 0x0067) |
624 | printk("CALL (P%i)", opcode & 7); | 677 | verbose_printk("CALL (P%i)", opcode & 7); |
625 | else if (opcode >= 0x0070 && opcode <= 0x0077) | 678 | else if (opcode >= 0x0070 && opcode <= 0x0077) |
626 | printk("CALL (PC+P%i)", opcode & 7); | 679 | verbose_printk("CALL (PC+P%i)", opcode & 7); |
627 | else if (opcode >= 0x0080 && opcode <= 0x0087) | 680 | else if (opcode >= 0x0080 && opcode <= 0x0087) |
628 | printk("JUMP (PC+P%i)", opcode & 7); | 681 | verbose_printk("JUMP (PC+P%i)", opcode & 7); |
629 | else if ((opcode >= 0x1000 && opcode <= 0x13FF) || (opcode >= 0x1800 && opcode <= 0x1BFF)) | 682 | else if ((opcode >= 0x1000 && opcode <= 0x13FF) || (opcode >= 0x1800 && opcode <= 0x1BFF)) |
630 | printk("IF !CC JUMP"); | 683 | verbose_printk("IF !CC JUMP"); |
631 | else if ((opcode >= 0x1400 && opcode <= 0x17ff) || (opcode >= 0x1c00 && opcode <= 0x1fff)) | 684 | else if ((opcode >= 0x1400 && opcode <= 0x17ff) || (opcode >= 0x1c00 && opcode <= 0x1fff)) |
632 | printk("IF CC JUMP"); | 685 | verbose_printk("IF CC JUMP"); |
633 | else if (opcode >= 0x2000 && opcode <= 0x2fff) | 686 | else if (opcode >= 0x2000 && opcode <= 0x2fff) |
634 | printk("JUMP.S"); | 687 | verbose_printk("JUMP.S"); |
635 | else if (opcode >= 0xe080 && opcode <= 0xe0ff) | 688 | else if (opcode >= 0xe080 && opcode <= 0xe0ff) |
636 | printk("LSETUP"); | 689 | verbose_printk("LSETUP"); |
637 | else if (opcode >= 0xe200 && opcode <= 0xe2ff) | 690 | else if (opcode >= 0xe200 && opcode <= 0xe2ff) |
638 | printk("JUMP.L"); | 691 | verbose_printk("JUMP.L"); |
639 | else if (opcode >= 0xe300 && opcode <= 0xe3ff) | 692 | else if (opcode >= 0xe300 && opcode <= 0xe3ff) |
640 | printk("CALL pcrel"); | 693 | verbose_printk("CALL pcrel"); |
641 | else | 694 | else |
642 | printk("0x%04x", opcode); | 695 | verbose_printk("0x%04x", opcode); |
643 | } | 696 | } |
644 | 697 | ||
645 | } | 698 | } |
699 | #endif | ||
646 | 700 | ||
647 | void dump_bfin_trace_buffer(void) | 701 | void dump_bfin_trace_buffer(void) |
648 | { | 702 | { |
703 | #ifdef CONFIG_DEBUG_VERBOSE | ||
649 | #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON | 704 | #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON |
650 | int tflags, i = 0; | 705 | int tflags, i = 0; |
651 | char buf[150]; | 706 | char buf[150]; |
@@ -701,6 +756,7 @@ void dump_bfin_trace_buffer(void) | |||
701 | 756 | ||
702 | trace_buffer_restore(tflags); | 757 | trace_buffer_restore(tflags); |
703 | #endif | 758 | #endif |
759 | #endif | ||
704 | } | 760 | } |
705 | EXPORT_SYMBOL(dump_bfin_trace_buffer); | 761 | EXPORT_SYMBOL(dump_bfin_trace_buffer); |
706 | 762 | ||
@@ -708,7 +764,7 @@ EXPORT_SYMBOL(dump_bfin_trace_buffer); | |||
708 | * Checks to see if the address pointed to is either a | 764 | * Checks to see if the address pointed to is either a |
709 | * 16-bit CALL instruction, or a 32-bit CALL instruction | 765 | * 16-bit CALL instruction, or a 32-bit CALL instruction |
710 | */ | 766 | */ |
711 | bool is_bfin_call(unsigned short *addr) | 767 | static bool is_bfin_call(unsigned short *addr) |
712 | { | 768 | { |
713 | unsigned short opcode = 0, *ins_addr; | 769 | unsigned short opcode = 0, *ins_addr; |
714 | ins_addr = (unsigned short *)addr; | 770 | ins_addr = (unsigned short *)addr; |
@@ -730,8 +786,10 @@ bool is_bfin_call(unsigned short *addr) | |||
730 | return false; | 786 | return false; |
731 | 787 | ||
732 | } | 788 | } |
789 | |||
733 | void show_stack(struct task_struct *task, unsigned long *stack) | 790 | void show_stack(struct task_struct *task, unsigned long *stack) |
734 | { | 791 | { |
792 | #ifdef CONFIG_PRINTK | ||
735 | unsigned int *addr, *endstack, *fp = 0, *frame; | 793 | unsigned int *addr, *endstack, *fp = 0, *frame; |
736 | unsigned short *ins_addr; | 794 | unsigned short *ins_addr; |
737 | char buf[150]; | 795 | char buf[150]; |
@@ -756,8 +814,10 @@ void show_stack(struct task_struct *task, unsigned long *stack) | |||
756 | } else | 814 | } else |
757 | endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack); | 815 | endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack); |
758 | 816 | ||
817 | printk(KERN_NOTICE "Stack info:\n"); | ||
759 | decode_address(buf, (unsigned int)stack); | 818 | decode_address(buf, (unsigned int)stack); |
760 | printk(KERN_NOTICE "Stack info:\n" KERN_NOTICE " SP: [0x%p] %s\n", stack, buf); | 819 | printk(KERN_NOTICE " SP: [0x%p] %s\n", stack, buf); |
820 | |||
761 | addr = (unsigned int *)((unsigned int)stack & ~0x3F); | 821 | addr = (unsigned int *)((unsigned int)stack & ~0x3F); |
762 | 822 | ||
763 | /* First thing is to look for a frame pointer */ | 823 | /* First thing is to look for a frame pointer */ |
@@ -848,7 +908,7 @@ void show_stack(struct task_struct *task, unsigned long *stack) | |||
848 | if (!j) | 908 | if (!j) |
849 | printk("\n"); | 909 | printk("\n"); |
850 | } | 910 | } |
851 | 911 | #endif | |
852 | } | 912 | } |
853 | 913 | ||
854 | void dump_stack(void) | 914 | void dump_stack(void) |
@@ -866,38 +926,39 @@ EXPORT_SYMBOL(dump_stack); | |||
866 | 926 | ||
867 | void dump_bfin_process(struct pt_regs *fp) | 927 | void dump_bfin_process(struct pt_regs *fp) |
868 | { | 928 | { |
929 | #ifdef CONFIG_DEBUG_VERBOSE | ||
869 | /* We should be able to look at fp->ipend, but we don't push it on the | 930 | /* We should be able to look at fp->ipend, but we don't push it on the |
870 | * stack all the time, so do this until we fix that */ | 931 | * stack all the time, so do this until we fix that */ |
871 | unsigned int context = bfin_read_IPEND(); | 932 | unsigned int context = bfin_read_IPEND(); |
872 | 933 | ||
873 | if (oops_in_progress) | 934 | if (oops_in_progress) |
874 | printk(KERN_EMERG "Kernel OOPS in progress\n"); | 935 | verbose_printk(KERN_EMERG "Kernel OOPS in progress\n"); |
875 | 936 | ||
876 | if (context & 0x0020 && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) | 937 | if (context & 0x0020 && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) |
877 | printk(KERN_NOTICE "HW Error context\n"); | 938 | verbose_printk(KERN_NOTICE "HW Error context\n"); |
878 | else if (context & 0x0020) | 939 | else if (context & 0x0020) |
879 | printk(KERN_NOTICE "Deferred Exception context\n"); | 940 | verbose_printk(KERN_NOTICE "Deferred Exception context\n"); |
880 | else if (context & 0x3FC0) | 941 | else if (context & 0x3FC0) |
881 | printk(KERN_NOTICE "Interrupt context\n"); | 942 | verbose_printk(KERN_NOTICE "Interrupt context\n"); |
882 | else if (context & 0x4000) | 943 | else if (context & 0x4000) |
883 | printk(KERN_NOTICE "Deferred Interrupt context\n"); | 944 | verbose_printk(KERN_NOTICE "Deferred Interrupt context\n"); |
884 | else if (context & 0x8000) | 945 | else if (context & 0x8000) |
885 | printk(KERN_NOTICE "Kernel process context\n"); | 946 | verbose_printk(KERN_NOTICE "Kernel process context\n"); |
886 | 947 | ||
887 | /* Because we are crashing, and pointers could be bad, we check things | 948 | /* Because we are crashing, and pointers could be bad, we check things |
888 | * pretty closely before we use them | 949 | * pretty closely before we use them |
889 | */ | 950 | */ |
890 | if ((unsigned long)current >= FIXED_CODE_START && | 951 | if ((unsigned long)current >= FIXED_CODE_START && |
891 | !((unsigned long)current & 0x3) && current->pid) { | 952 | !((unsigned long)current & 0x3) && current->pid) { |
892 | printk(KERN_NOTICE "CURRENT PROCESS:\n"); | 953 | verbose_printk(KERN_NOTICE "CURRENT PROCESS:\n"); |
893 | if (current->comm >= (char *)FIXED_CODE_START) | 954 | if (current->comm >= (char *)FIXED_CODE_START) |
894 | printk(KERN_NOTICE "COMM=%s PID=%d\n", | 955 | verbose_printk(KERN_NOTICE "COMM=%s PID=%d\n", |
895 | current->comm, current->pid); | 956 | current->comm, current->pid); |
896 | else | 957 | else |
897 | printk(KERN_NOTICE "COMM= invalid\n"); | 958 | verbose_printk(KERN_NOTICE "COMM= invalid\n"); |
898 | 959 | ||
899 | if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START) | 960 | if (!((unsigned long)current->mm & 0x3) && (unsigned long)current->mm >= FIXED_CODE_START) |
900 | printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" | 961 | verbose_printk(KERN_NOTICE "TEXT = 0x%p-0x%p DATA = 0x%p-0x%p\n" |
901 | KERN_NOTICE " BSS = 0x%p-0x%p USER-STACK = 0x%p\n" | 962 | KERN_NOTICE " BSS = 0x%p-0x%p USER-STACK = 0x%p\n" |
902 | KERN_NOTICE "\n", | 963 | KERN_NOTICE "\n", |
903 | (void *)current->mm->start_code, | 964 | (void *)current->mm->start_code, |
@@ -908,38 +969,40 @@ void dump_bfin_process(struct pt_regs *fp) | |||
908 | (void *)current->mm->brk, | 969 | (void *)current->mm->brk, |
909 | (void *)current->mm->start_stack); | 970 | (void *)current->mm->start_stack); |
910 | else | 971 | else |
911 | printk(KERN_NOTICE "invalid mm\n"); | 972 | verbose_printk(KERN_NOTICE "invalid mm\n"); |
912 | } else | 973 | } else |
913 | printk(KERN_NOTICE "\n" KERN_NOTICE | 974 | verbose_printk(KERN_NOTICE "\n" KERN_NOTICE |
914 | "No Valid process in current context\n"); | 975 | "No Valid process in current context\n"); |
976 | #endif | ||
915 | } | 977 | } |
916 | 978 | ||
917 | void dump_bfin_mem(struct pt_regs *fp) | 979 | void dump_bfin_mem(struct pt_regs *fp) |
918 | { | 980 | { |
981 | #ifdef CONFIG_DEBUG_VERBOSE | ||
919 | unsigned short *addr, *erraddr, val = 0, err = 0; | 982 | unsigned short *addr, *erraddr, val = 0, err = 0; |
920 | char sti = 0, buf[6]; | 983 | char sti = 0, buf[6]; |
921 | 984 | ||
922 | erraddr = (void *)fp->pc; | 985 | erraddr = (void *)fp->pc; |
923 | 986 | ||
924 | printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr); | 987 | verbose_printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr); |
925 | 988 | ||
926 | for (addr = (unsigned short *)((unsigned long)erraddr & ~0xF) - 0x10; | 989 | for (addr = (unsigned short *)((unsigned long)erraddr & ~0xF) - 0x10; |
927 | addr < (unsigned short *)((unsigned long)erraddr & ~0xF) + 0x10; | 990 | addr < (unsigned short *)((unsigned long)erraddr & ~0xF) + 0x10; |
928 | addr++) { | 991 | addr++) { |
929 | if (!((unsigned long)addr & 0xF)) | 992 | if (!((unsigned long)addr & 0xF)) |
930 | printk("\n" KERN_NOTICE "0x%p: ", addr); | 993 | verbose_printk("\n" KERN_NOTICE "0x%p: ", addr); |
931 | 994 | ||
932 | if (get_instruction(&val, addr)) { | 995 | if (!get_instruction(&val, addr)) { |
933 | val = 0; | 996 | val = 0; |
934 | sprintf(buf, "????"); | 997 | sprintf(buf, "????"); |
935 | } else | 998 | } else |
936 | sprintf(buf, "%04x", val); | 999 | sprintf(buf, "%04x", val); |
937 | 1000 | ||
938 | if (addr == erraddr) { | 1001 | if (addr == erraddr) { |
939 | printk("[%s]", buf); | 1002 | verbose_printk("[%s]", buf); |
940 | err = val; | 1003 | err = val; |
941 | } else | 1004 | } else |
942 | printk(" %s ", buf); | 1005 | verbose_printk(" %s ", buf); |
943 | 1006 | ||
944 | /* Do any previous instructions turn on interrupts? */ | 1007 | /* Do any previous instructions turn on interrupts? */ |
945 | if (addr <= erraddr && /* in the past */ | 1008 | if (addr <= erraddr && /* in the past */ |
@@ -948,14 +1011,14 @@ void dump_bfin_mem(struct pt_regs *fp) | |||
948 | sti = 1; | 1011 | sti = 1; |
949 | } | 1012 | } |
950 | 1013 | ||
951 | printk("\n"); | 1014 | verbose_printk("\n"); |
952 | 1015 | ||
953 | /* Hardware error interrupts can be deferred */ | 1016 | /* Hardware error interrupts can be deferred */ |
954 | if (unlikely(sti && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR && | 1017 | if (unlikely(sti && (fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR && |
955 | oops_in_progress)){ | 1018 | oops_in_progress)){ |
956 | printk(KERN_NOTICE "Looks like this was a deferred error - sorry\n"); | 1019 | verbose_printk(KERN_NOTICE "Looks like this was a deferred error - sorry\n"); |
957 | #ifndef CONFIG_DEBUG_HWERR | 1020 | #ifndef CONFIG_DEBUG_HWERR |
958 | printk(KERN_NOTICE "The remaining message may be meaningless\n" | 1021 | verbose_printk(KERN_NOTICE "The remaining message may be meaningless\n" |
959 | KERN_NOTICE "You should enable CONFIG_DEBUG_HWERR to get a" | 1022 | KERN_NOTICE "You should enable CONFIG_DEBUG_HWERR to get a" |
960 | " better idea where it came from\n"); | 1023 | " better idea where it came from\n"); |
961 | #else | 1024 | #else |
@@ -969,34 +1032,47 @@ void dump_bfin_mem(struct pt_regs *fp) | |||
969 | /* And the last RETI points to the current userspace context */ | 1032 | /* And the last RETI points to the current userspace context */ |
970 | if ((fp + 1)->pc >= current->mm->start_code && | 1033 | if ((fp + 1)->pc >= current->mm->start_code && |
971 | (fp + 1)->pc <= current->mm->end_code) { | 1034 | (fp + 1)->pc <= current->mm->end_code) { |
972 | printk(KERN_NOTICE "It might be better to look around here : \n"); | 1035 | verbose_printk(KERN_NOTICE "It might be better to look around here : \n"); |
973 | printk(KERN_NOTICE "-------------------------------------------\n"); | 1036 | verbose_printk(KERN_NOTICE "-------------------------------------------\n"); |
974 | show_regs(fp + 1); | 1037 | show_regs(fp + 1); |
975 | printk(KERN_NOTICE "-------------------------------------------\n"); | 1038 | verbose_printk(KERN_NOTICE "-------------------------------------------\n"); |
976 | } | 1039 | } |
977 | } | 1040 | } |
978 | #endif | 1041 | #endif |
979 | } | 1042 | } |
1043 | #endif | ||
980 | } | 1044 | } |
981 | 1045 | ||
982 | void show_regs(struct pt_regs *fp) | 1046 | void show_regs(struct pt_regs *fp) |
983 | { | 1047 | { |
1048 | #ifdef CONFIG_DEBUG_VERBOSE | ||
984 | char buf [150]; | 1049 | char buf [150]; |
985 | struct irqaction *action; | 1050 | struct irqaction *action; |
986 | unsigned int i; | 1051 | unsigned int i; |
987 | unsigned long flags; | 1052 | unsigned long flags; |
988 | 1053 | ||
989 | printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted()); | 1054 | verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "SEQUENCER STATUS:\t\t%s\n", print_tainted()); |
990 | printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", | 1055 | verbose_printk(KERN_NOTICE " SEQSTAT: %08lx IPEND: %04lx SYSCFG: %04lx\n", |
991 | (long)fp->seqstat, fp->ipend, fp->syscfg); | 1056 | (long)fp->seqstat, fp->ipend, fp->syscfg); |
992 | printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n", | 1057 | if ((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR) { |
993 | (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14); | 1058 | verbose_printk(KERN_NOTICE " HWERRCAUSE: 0x%lx\n", |
994 | printk(KERN_NOTICE " EXCAUSE : 0x%lx\n", | 1059 | (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14); |
1060 | #ifdef EBIU_ERRMST | ||
1061 | /* If the error was from the EBIU, print it out */ | ||
1062 | if (bfin_read_EBIU_ERRMST() & CORE_ERROR) { | ||
1063 | verbose_printk(KERN_NOTICE " EBIU Error Reason : 0x%04x\n", | ||
1064 | bfin_read_EBIU_ERRMST()); | ||
1065 | verbose_printk(KERN_NOTICE " EBIU Error Address : 0x%08x\n", | ||
1066 | bfin_read_EBIU_ERRADD()); | ||
1067 | } | ||
1068 | #endif | ||
1069 | } | ||
1070 | verbose_printk(KERN_NOTICE " EXCAUSE : 0x%lx\n", | ||
995 | fp->seqstat & SEQSTAT_EXCAUSE); | 1071 | fp->seqstat & SEQSTAT_EXCAUSE); |
996 | for (i = 6; i <= 15 ; i++) { | 1072 | for (i = 6; i <= 15 ; i++) { |
997 | if (fp->ipend & (1 << i)) { | 1073 | if (fp->ipend & (1 << i)) { |
998 | decode_address(buf, bfin_read32(EVT0 + 4*i)); | 1074 | decode_address(buf, bfin_read32(EVT0 + 4*i)); |
999 | printk(KERN_NOTICE " physical IVG%i asserted : %s\n", i, buf); | 1075 | verbose_printk(KERN_NOTICE " physical IVG%i asserted : %s\n", i, buf); |
1000 | } | 1076 | } |
1001 | } | 1077 | } |
1002 | 1078 | ||
@@ -1009,64 +1085,65 @@ void show_regs(struct pt_regs *fp) | |||
1009 | goto unlock; | 1085 | goto unlock; |
1010 | 1086 | ||
1011 | decode_address(buf, (unsigned int)action->handler); | 1087 | decode_address(buf, (unsigned int)action->handler); |
1012 | printk(KERN_NOTICE " logical irq %3d mapped : %s", i, buf); | 1088 | verbose_printk(KERN_NOTICE " logical irq %3d mapped : %s", i, buf); |
1013 | for (action = action->next; action; action = action->next) { | 1089 | for (action = action->next; action; action = action->next) { |
1014 | decode_address(buf, (unsigned int)action->handler); | 1090 | decode_address(buf, (unsigned int)action->handler); |
1015 | printk(", %s", buf); | 1091 | verbose_printk(", %s", buf); |
1016 | } | 1092 | } |
1017 | printk("\n"); | 1093 | verbose_printk("\n"); |
1018 | unlock: | 1094 | unlock: |
1019 | spin_unlock_irqrestore(&irq_desc[i].lock, flags); | 1095 | spin_unlock_irqrestore(&irq_desc[i].lock, flags); |
1020 | } | 1096 | } |
1021 | } | 1097 | } |
1022 | 1098 | ||
1023 | decode_address(buf, fp->rete); | 1099 | decode_address(buf, fp->rete); |
1024 | printk(KERN_NOTICE " RETE: %s\n", buf); | 1100 | verbose_printk(KERN_NOTICE " RETE: %s\n", buf); |
1025 | decode_address(buf, fp->retn); | 1101 | decode_address(buf, fp->retn); |
1026 | printk(KERN_NOTICE " RETN: %s\n", buf); | 1102 | verbose_printk(KERN_NOTICE " RETN: %s\n", buf); |
1027 | decode_address(buf, fp->retx); | 1103 | decode_address(buf, fp->retx); |
1028 | printk(KERN_NOTICE " RETX: %s\n", buf); | 1104 | verbose_printk(KERN_NOTICE " RETX: %s\n", buf); |
1029 | decode_address(buf, fp->rets); | 1105 | decode_address(buf, fp->rets); |
1030 | printk(KERN_NOTICE " RETS: %s\n", buf); | 1106 | verbose_printk(KERN_NOTICE " RETS: %s\n", buf); |
1031 | decode_address(buf, fp->pc); | 1107 | decode_address(buf, fp->pc); |
1032 | printk(KERN_NOTICE " PC : %s\n", buf); | 1108 | verbose_printk(KERN_NOTICE " PC : %s\n", buf); |
1033 | 1109 | ||
1034 | if (((long)fp->seqstat & SEQSTAT_EXCAUSE) && | 1110 | if (((long)fp->seqstat & SEQSTAT_EXCAUSE) && |
1035 | (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) { | 1111 | (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) { |
1036 | decode_address(buf, saved_dcplb_fault_addr); | 1112 | decode_address(buf, saved_dcplb_fault_addr); |
1037 | printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf); | 1113 | verbose_printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf); |
1038 | decode_address(buf, saved_icplb_fault_addr); | 1114 | decode_address(buf, saved_icplb_fault_addr); |
1039 | printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf); | 1115 | verbose_printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf); |
1040 | } | 1116 | } |
1041 | 1117 | ||
1042 | printk(KERN_NOTICE "\n" KERN_NOTICE "PROCESSOR STATE:\n"); | 1118 | verbose_printk(KERN_NOTICE "\n" KERN_NOTICE "PROCESSOR STATE:\n"); |
1043 | printk(KERN_NOTICE " R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n", | 1119 | verbose_printk(KERN_NOTICE " R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n", |
1044 | fp->r0, fp->r1, fp->r2, fp->r3); | 1120 | fp->r0, fp->r1, fp->r2, fp->r3); |
1045 | printk(KERN_NOTICE " R4 : %08lx R5 : %08lx R6 : %08lx R7 : %08lx\n", | 1121 | verbose_printk(KERN_NOTICE " R4 : %08lx R5 : %08lx R6 : %08lx R7 : %08lx\n", |
1046 | fp->r4, fp->r5, fp->r6, fp->r7); | 1122 | fp->r4, fp->r5, fp->r6, fp->r7); |
1047 | printk(KERN_NOTICE " P0 : %08lx P1 : %08lx P2 : %08lx P3 : %08lx\n", | 1123 | verbose_printk(KERN_NOTICE " P0 : %08lx P1 : %08lx P2 : %08lx P3 : %08lx\n", |
1048 | fp->p0, fp->p1, fp->p2, fp->p3); | 1124 | fp->p0, fp->p1, fp->p2, fp->p3); |
1049 | printk(KERN_NOTICE " P4 : %08lx P5 : %08lx FP : %08lx SP : %08lx\n", | 1125 | verbose_printk(KERN_NOTICE " P4 : %08lx P5 : %08lx FP : %08lx SP : %08lx\n", |
1050 | fp->p4, fp->p5, fp->fp, (long)fp); | 1126 | fp->p4, fp->p5, fp->fp, (long)fp); |
1051 | printk(KERN_NOTICE " LB0: %08lx LT0: %08lx LC0: %08lx\n", | 1127 | verbose_printk(KERN_NOTICE " LB0: %08lx LT0: %08lx LC0: %08lx\n", |
1052 | fp->lb0, fp->lt0, fp->lc0); | 1128 | fp->lb0, fp->lt0, fp->lc0); |
1053 | printk(KERN_NOTICE " LB1: %08lx LT1: %08lx LC1: %08lx\n", | 1129 | verbose_printk(KERN_NOTICE " LB1: %08lx LT1: %08lx LC1: %08lx\n", |
1054 | fp->lb1, fp->lt1, fp->lc1); | 1130 | fp->lb1, fp->lt1, fp->lc1); |
1055 | printk(KERN_NOTICE " B0 : %08lx L0 : %08lx M0 : %08lx I0 : %08lx\n", | 1131 | verbose_printk(KERN_NOTICE " B0 : %08lx L0 : %08lx M0 : %08lx I0 : %08lx\n", |
1056 | fp->b0, fp->l0, fp->m0, fp->i0); | 1132 | fp->b0, fp->l0, fp->m0, fp->i0); |
1057 | printk(KERN_NOTICE " B1 : %08lx L1 : %08lx M1 : %08lx I1 : %08lx\n", | 1133 | verbose_printk(KERN_NOTICE " B1 : %08lx L1 : %08lx M1 : %08lx I1 : %08lx\n", |
1058 | fp->b1, fp->l1, fp->m1, fp->i1); | 1134 | fp->b1, fp->l1, fp->m1, fp->i1); |
1059 | printk(KERN_NOTICE " B2 : %08lx L2 : %08lx M2 : %08lx I2 : %08lx\n", | 1135 | verbose_printk(KERN_NOTICE " B2 : %08lx L2 : %08lx M2 : %08lx I2 : %08lx\n", |
1060 | fp->b2, fp->l2, fp->m2, fp->i2); | 1136 | fp->b2, fp->l2, fp->m2, fp->i2); |
1061 | printk(KERN_NOTICE " B3 : %08lx L3 : %08lx M3 : %08lx I3 : %08lx\n", | 1137 | verbose_printk(KERN_NOTICE " B3 : %08lx L3 : %08lx M3 : %08lx I3 : %08lx\n", |
1062 | fp->b3, fp->l3, fp->m3, fp->i3); | 1138 | fp->b3, fp->l3, fp->m3, fp->i3); |
1063 | printk(KERN_NOTICE "A0.w: %08lx A0.x: %08lx A1.w: %08lx A1.x: %08lx\n", | 1139 | verbose_printk(KERN_NOTICE "A0.w: %08lx A0.x: %08lx A1.w: %08lx A1.x: %08lx\n", |
1064 | fp->a0w, fp->a0x, fp->a1w, fp->a1x); | 1140 | fp->a0w, fp->a0x, fp->a1w, fp->a1x); |
1065 | 1141 | ||
1066 | printk(KERN_NOTICE "USP : %08lx ASTAT: %08lx\n", | 1142 | verbose_printk(KERN_NOTICE "USP : %08lx ASTAT: %08lx\n", |
1067 | rdusp(), fp->astat); | 1143 | rdusp(), fp->astat); |
1068 | 1144 | ||
1069 | printk(KERN_NOTICE "\n"); | 1145 | verbose_printk(KERN_NOTICE "\n"); |
1146 | #endif | ||
1070 | } | 1147 | } |
1071 | 1148 | ||
1072 | #ifdef CONFIG_SYS_BFIN_SPINLOCK_L1 | 1149 | #ifdef CONFIG_SYS_BFIN_SPINLOCK_L1 |