diff options
author | Sonic Zhang <sonic.zhang@analog.com> | 2008-10-13 02:07:19 -0400 |
---|---|---|
committer | Bryan Wu <cooloney@kernel.org> | 2008-10-13 02:07:19 -0400 |
commit | a5ac0129249611fc4a35e6d7cd9b8462d67e5798 (patch) | |
tree | 9fd28b5e6e10cce341e63a1fd9885fae5e019643 /arch/blackfin | |
parent | 5d2e321306f82550e6d354b3210a18b86bdb13c1 (diff) |
Blackfin arch: add supporting for kgdb
Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
Diffstat (limited to 'arch/blackfin')
-rw-r--r-- | arch/blackfin/Kconfig.debug | 3 | ||||
-rw-r--r-- | arch/blackfin/include/asm/kgdb.h | 21 | ||||
-rw-r--r-- | arch/blackfin/kernel/kgdb.c | 711 | ||||
-rw-r--r-- | arch/blackfin/kernel/traps.c | 35 | ||||
-rw-r--r-- | arch/blackfin/mach-bf561/include/mach/mem_map.h | 18 | ||||
-rw-r--r-- | arch/blackfin/mach-common/entry.S | 9 | ||||
-rw-r--r-- | arch/blackfin/mach-common/ints-priority.c | 4 |
7 files changed, 606 insertions, 195 deletions
diff --git a/arch/blackfin/Kconfig.debug b/arch/blackfin/Kconfig.debug index 0afa89818722..2cb0a3080d79 100644 --- a/arch/blackfin/Kconfig.debug +++ b/arch/blackfin/Kconfig.debug | |||
@@ -2,6 +2,9 @@ menu "Kernel hacking" | |||
2 | 2 | ||
3 | source "lib/Kconfig.debug" | 3 | source "lib/Kconfig.debug" |
4 | 4 | ||
5 | config HAVE_ARCH_KGDB | ||
6 | def_bool y | ||
7 | |||
5 | config DEBUG_MMRS | 8 | config DEBUG_MMRS |
6 | bool "Generate Blackfin MMR tree" | 9 | bool "Generate Blackfin MMR tree" |
7 | select DEBUG_FS | 10 | select DEBUG_FS |
diff --git a/arch/blackfin/include/asm/kgdb.h b/arch/blackfin/include/asm/kgdb.h index 0f73847fd6bc..26ebac6646d8 100644 --- a/arch/blackfin/include/asm/kgdb.h +++ b/arch/blackfin/include/asm/kgdb.h | |||
@@ -124,9 +124,16 @@ enum regnames { | |||
124 | /* Number of bytes of registers. */ | 124 | /* Number of bytes of registers. */ |
125 | #define NUMREGBYTES BFIN_NUM_REGS*4 | 125 | #define NUMREGBYTES BFIN_NUM_REGS*4 |
126 | 126 | ||
127 | #define BREAKPOINT() asm(" EXCPT 2;"); | 127 | static inline void arch_kgdb_breakpoint(void) |
128 | #define BREAK_INSTR_SIZE 2 | 128 | { |
129 | #define HW_BREAKPOINT_NUM 6 | 129 | asm(" EXCPT 2;"); |
130 | } | ||
131 | #define BREAK_INSTR_SIZE 2 | ||
132 | #define CACHE_FLUSH_IS_SAFE 1 | ||
133 | #define HW_INST_WATCHPOINT_NUM 6 | ||
134 | #define HW_WATCHPOINT_NUM 8 | ||
135 | #define TYPE_INST_WATCHPOINT 0 | ||
136 | #define TYPE_DATA_WATCHPOINT 1 | ||
130 | 137 | ||
131 | /* Instruction watchpoint address control register bits mask */ | 138 | /* Instruction watchpoint address control register bits mask */ |
132 | #define WPPWR 0x1 | 139 | #define WPPWR 0x1 |
@@ -163,10 +170,11 @@ enum regnames { | |||
163 | #define WPDAEN1 0x8 | 170 | #define WPDAEN1 0x8 |
164 | #define WPDCNTEN0 0x10 | 171 | #define WPDCNTEN0 0x10 |
165 | #define WPDCNTEN1 0x20 | 172 | #define WPDCNTEN1 0x20 |
173 | |||
166 | #define WPDSRC0 0xc0 | 174 | #define WPDSRC0 0xc0 |
167 | #define WPDACC0 0x300 | 175 | #define WPDACC0_OFFSET 8 |
168 | #define WPDSRC1 0xc00 | 176 | #define WPDSRC1 0xc00 |
169 | #define WPDACC1 0x3000 | 177 | #define WPDACC1_OFFSET 12 |
170 | 178 | ||
171 | /* Watchpoint status register bits mask */ | 179 | /* Watchpoint status register bits mask */ |
172 | #define STATIA0 0x1 | 180 | #define STATIA0 0x1 |
@@ -178,7 +186,4 @@ enum regnames { | |||
178 | #define STATDA0 0x40 | 186 | #define STATDA0 0x40 |
179 | #define STATDA1 0x80 | 187 | #define STATDA1 0x80 |
180 | 188 | ||
181 | extern void kgdb_print(const char *fmt, ...); | ||
182 | extern void init_kgdb_uart(void); | ||
183 | |||
184 | #endif | 189 | #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/traps.c b/arch/blackfin/kernel/traps.c index bd41fca315dd..8d561baef896 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c | |||
@@ -43,12 +43,11 @@ | |||
43 | #include <asm/dma.h> | 43 | #include <asm/dma.h> |
44 | 44 | ||
45 | #ifdef CONFIG_KGDB | 45 | #ifdef CONFIG_KGDB |
46 | # include <linux/debugger.h> | ||
47 | # include <linux/kgdb.h> | 46 | # include <linux/kgdb.h> |
48 | 47 | ||
49 | # define CHK_DEBUGGER_TRAP() \ | 48 | # define CHK_DEBUGGER_TRAP() \ |
50 | do { \ | 49 | do { \ |
51 | CHK_DEBUGGER(trapnr, sig, info.si_code, fp, ); \ | 50 | kgdb_handle_exception(trapnr, sig, info.si_code, fp); \ |
52 | } while (0) | 51 | } while (0) |
53 | # define CHK_DEBUGGER_TRAP_MAYBE() \ | 52 | # define CHK_DEBUGGER_TRAP_MAYBE() \ |
54 | do { \ | 53 | do { \ |
@@ -300,7 +299,7 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
300 | info.si_code = SEGV_STACKFLOW; | 299 | info.si_code = SEGV_STACKFLOW; |
301 | sig = SIGSEGV; | 300 | sig = SIGSEGV; |
302 | printk(KERN_NOTICE EXC_0x03(KERN_NOTICE)); | 301 | printk(KERN_NOTICE EXC_0x03(KERN_NOTICE)); |
303 | CHK_DEBUGGER_TRAP(); | 302 | CHK_DEBUGGER_TRAP_MAYBE(); |
304 | break; | 303 | break; |
305 | /* 0x04 - User Defined, Caught by default */ | 304 | /* 0x04 - User Defined, Caught by default */ |
306 | /* 0x05 - User Defined, Caught by default */ | 305 | /* 0x05 - User Defined, Caught by default */ |
@@ -329,7 +328,7 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
329 | info.si_code = TRAP_TRACEFLOW; | 328 | info.si_code = TRAP_TRACEFLOW; |
330 | sig = SIGTRAP; | 329 | sig = SIGTRAP; |
331 | printk(KERN_NOTICE EXC_0x11(KERN_NOTICE)); | 330 | printk(KERN_NOTICE EXC_0x11(KERN_NOTICE)); |
332 | CHK_DEBUGGER_TRAP(); | 331 | CHK_DEBUGGER_TRAP_MAYBE(); |
333 | break; | 332 | break; |
334 | /* 0x12 - Reserved, Caught by default */ | 333 | /* 0x12 - Reserved, Caught by default */ |
335 | /* 0x13 - Reserved, Caught by default */ | 334 | /* 0x13 - Reserved, Caught by default */ |
@@ -351,35 +350,35 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
351 | info.si_code = ILL_ILLOPC; | 350 | info.si_code = ILL_ILLOPC; |
352 | sig = SIGILL; | 351 | sig = SIGILL; |
353 | printk(KERN_NOTICE EXC_0x21(KERN_NOTICE)); | 352 | printk(KERN_NOTICE EXC_0x21(KERN_NOTICE)); |
354 | CHK_DEBUGGER_TRAP(); | 353 | CHK_DEBUGGER_TRAP_MAYBE(); |
355 | break; | 354 | break; |
356 | /* 0x22 - Illegal Instruction Combination, handled here */ | 355 | /* 0x22 - Illegal Instruction Combination, handled here */ |
357 | case VEC_ILGAL_I: | 356 | case VEC_ILGAL_I: |
358 | info.si_code = ILL_ILLPARAOP; | 357 | info.si_code = ILL_ILLPARAOP; |
359 | sig = SIGILL; | 358 | sig = SIGILL; |
360 | printk(KERN_NOTICE EXC_0x22(KERN_NOTICE)); | 359 | printk(KERN_NOTICE EXC_0x22(KERN_NOTICE)); |
361 | CHK_DEBUGGER_TRAP(); | 360 | CHK_DEBUGGER_TRAP_MAYBE(); |
362 | break; | 361 | break; |
363 | /* 0x23 - Data CPLB protection violation, handled here */ | 362 | /* 0x23 - Data CPLB protection violation, handled here */ |
364 | case VEC_CPLB_VL: | 363 | case VEC_CPLB_VL: |
365 | info.si_code = ILL_CPLB_VI; | 364 | info.si_code = ILL_CPLB_VI; |
366 | sig = SIGBUS; | 365 | sig = SIGBUS; |
367 | printk(KERN_NOTICE EXC_0x23(KERN_NOTICE)); | 366 | printk(KERN_NOTICE EXC_0x23(KERN_NOTICE)); |
368 | CHK_DEBUGGER_TRAP(); | 367 | CHK_DEBUGGER_TRAP_MAYBE(); |
369 | break; | 368 | break; |
370 | /* 0x24 - Data access misaligned, handled here */ | 369 | /* 0x24 - Data access misaligned, handled here */ |
371 | case VEC_MISALI_D: | 370 | case VEC_MISALI_D: |
372 | info.si_code = BUS_ADRALN; | 371 | info.si_code = BUS_ADRALN; |
373 | sig = SIGBUS; | 372 | sig = SIGBUS; |
374 | printk(KERN_NOTICE EXC_0x24(KERN_NOTICE)); | 373 | printk(KERN_NOTICE EXC_0x24(KERN_NOTICE)); |
375 | CHK_DEBUGGER_TRAP(); | 374 | CHK_DEBUGGER_TRAP_MAYBE(); |
376 | break; | 375 | break; |
377 | /* 0x25 - Unrecoverable Event, handled here */ | 376 | /* 0x25 - Unrecoverable Event, handled here */ |
378 | case VEC_UNCOV: | 377 | case VEC_UNCOV: |
379 | info.si_code = ILL_ILLEXCPT; | 378 | info.si_code = ILL_ILLEXCPT; |
380 | sig = SIGILL; | 379 | sig = SIGILL; |
381 | printk(KERN_NOTICE EXC_0x25(KERN_NOTICE)); | 380 | printk(KERN_NOTICE EXC_0x25(KERN_NOTICE)); |
382 | CHK_DEBUGGER_TRAP(); | 381 | CHK_DEBUGGER_TRAP_MAYBE(); |
383 | break; | 382 | break; |
384 | /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr, | 383 | /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr, |
385 | error case is handled here */ | 384 | error case is handled here */ |
@@ -387,7 +386,6 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
387 | info.si_code = BUS_ADRALN; | 386 | info.si_code = BUS_ADRALN; |
388 | sig = SIGBUS; | 387 | sig = SIGBUS; |
389 | printk(KERN_NOTICE EXC_0x26(KERN_NOTICE)); | 388 | printk(KERN_NOTICE EXC_0x26(KERN_NOTICE)); |
390 | CHK_DEBUGGER_TRAP(); | ||
391 | break; | 389 | break; |
392 | /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */ | 390 | /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */ |
393 | case VEC_CPLB_MHIT: | 391 | case VEC_CPLB_MHIT: |
@@ -399,7 +397,7 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
399 | else | 397 | else |
400 | #endif | 398 | #endif |
401 | printk(KERN_NOTICE EXC_0x27(KERN_NOTICE)); | 399 | printk(KERN_NOTICE EXC_0x27(KERN_NOTICE)); |
402 | CHK_DEBUGGER_TRAP(); | 400 | CHK_DEBUGGER_TRAP_MAYBE(); |
403 | break; | 401 | break; |
404 | /* 0x28 - Emulation Watchpoint, handled here */ | 402 | /* 0x28 - Emulation Watchpoint, handled here */ |
405 | case VEC_WATCH: | 403 | case VEC_WATCH: |
@@ -418,7 +416,7 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
418 | info.si_code = BUS_OPFETCH; | 416 | info.si_code = BUS_OPFETCH; |
419 | sig = SIGBUS; | 417 | sig = SIGBUS; |
420 | printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n"); | 418 | printk(KERN_NOTICE "BF535: VEC_ISTRU_VL\n"); |
421 | CHK_DEBUGGER_TRAP(); | 419 | CHK_DEBUGGER_TRAP_MAYBE(); |
422 | break; | 420 | break; |
423 | #else | 421 | #else |
424 | /* 0x29 - Reserved, Caught by default */ | 422 | /* 0x29 - Reserved, Caught by default */ |
@@ -428,21 +426,20 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
428 | info.si_code = BUS_ADRALN; | 426 | info.si_code = BUS_ADRALN; |
429 | sig = SIGBUS; | 427 | sig = SIGBUS; |
430 | printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE)); | 428 | printk(KERN_NOTICE EXC_0x2A(KERN_NOTICE)); |
431 | CHK_DEBUGGER_TRAP(); | 429 | CHK_DEBUGGER_TRAP_MAYBE(); |
432 | break; | 430 | break; |
433 | /* 0x2B - Instruction CPLB protection violation, handled here */ | 431 | /* 0x2B - Instruction CPLB protection violation, handled here */ |
434 | case VEC_CPLB_I_VL: | 432 | case VEC_CPLB_I_VL: |
435 | info.si_code = ILL_CPLB_VI; | 433 | info.si_code = ILL_CPLB_VI; |
436 | sig = SIGBUS; | 434 | sig = SIGBUS; |
437 | printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE)); | 435 | printk(KERN_NOTICE EXC_0x2B(KERN_NOTICE)); |
438 | CHK_DEBUGGER_TRAP(); | 436 | CHK_DEBUGGER_TRAP_MAYBE(); |
439 | break; | 437 | break; |
440 | /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */ | 438 | /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */ |
441 | case VEC_CPLB_I_M: | 439 | case VEC_CPLB_I_M: |
442 | info.si_code = ILL_CPLB_MISS; | 440 | info.si_code = ILL_CPLB_MISS; |
443 | sig = SIGBUS; | 441 | sig = SIGBUS; |
444 | printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE)); | 442 | printk(KERN_NOTICE EXC_0x2C(KERN_NOTICE)); |
445 | CHK_DEBUGGER_TRAP(); | ||
446 | break; | 443 | break; |
447 | /* 0x2D - Instruction CPLB Multiple Hits, handled here */ | 444 | /* 0x2D - Instruction CPLB Multiple Hits, handled here */ |
448 | case VEC_CPLB_I_MHIT: | 445 | case VEC_CPLB_I_MHIT: |
@@ -454,14 +451,14 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
454 | else | 451 | else |
455 | #endif | 452 | #endif |
456 | printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE)); | 453 | printk(KERN_NOTICE EXC_0x2D(KERN_NOTICE)); |
457 | CHK_DEBUGGER_TRAP(); | 454 | CHK_DEBUGGER_TRAP_MAYBE(); |
458 | break; | 455 | break; |
459 | /* 0x2E - Illegal use of Supervisor Resource, handled here */ | 456 | /* 0x2E - Illegal use of Supervisor Resource, handled here */ |
460 | case VEC_ILL_RES: | 457 | case VEC_ILL_RES: |
461 | info.si_code = ILL_PRVOPC; | 458 | info.si_code = ILL_PRVOPC; |
462 | sig = SIGILL; | 459 | sig = SIGILL; |
463 | printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE)); | 460 | printk(KERN_NOTICE EXC_0x2E(KERN_NOTICE)); |
464 | CHK_DEBUGGER_TRAP(); | 461 | CHK_DEBUGGER_TRAP_MAYBE(); |
465 | break; | 462 | break; |
466 | /* 0x2F - Reserved, Caught by default */ | 463 | /* 0x2F - Reserved, Caught by default */ |
467 | /* 0x30 - Reserved, Caught by default */ | 464 | /* 0x30 - Reserved, Caught by default */ |
@@ -508,14 +505,14 @@ asmlinkage void trap_c(struct pt_regs *fp) | |||
508 | printk(KERN_NOTICE HWC_default(KERN_NOTICE)); | 505 | printk(KERN_NOTICE HWC_default(KERN_NOTICE)); |
509 | break; | 506 | break; |
510 | } | 507 | } |
511 | CHK_DEBUGGER_TRAP(); | 508 | CHK_DEBUGGER_TRAP_MAYBE(); |
512 | break; | 509 | break; |
513 | default: | 510 | default: |
514 | info.si_code = TRAP_ILLTRAP; | 511 | info.si_code = TRAP_ILLTRAP; |
515 | sig = SIGTRAP; | 512 | sig = SIGTRAP; |
516 | printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n", | 513 | printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n", |
517 | (fp->seqstat & SEQSTAT_EXCAUSE)); | 514 | (fp->seqstat & SEQSTAT_EXCAUSE)); |
518 | CHK_DEBUGGER_TRAP(); | 515 | CHK_DEBUGGER_TRAP_MAYBE(); |
519 | break; | 516 | break; |
520 | } | 517 | } |
521 | 518 | ||
diff --git a/arch/blackfin/mach-bf561/include/mach/mem_map.h b/arch/blackfin/mach-bf561/include/mach/mem_map.h index c26d8486cc4b..9d6674ad1e5e 100644 --- a/arch/blackfin/mach-bf561/include/mach/mem_map.h +++ b/arch/blackfin/mach-bf561/include/mach/mem_map.h | |||
@@ -35,9 +35,16 @@ | |||
35 | /* Memory Map for ADSP-BF561 processors */ | 35 | /* Memory Map for ADSP-BF561 processors */ |
36 | 36 | ||
37 | #ifdef CONFIG_BF561 | 37 | #ifdef CONFIG_BF561 |
38 | #define L1_CODE_START 0xFFA00000 | 38 | #define COREA_L1_CODE_START 0xFFA00000 |
39 | #define L1_DATA_A_START 0xFF800000 | 39 | #define COREA_L1_DATA_A_START 0xFF800000 |
40 | #define L1_DATA_B_START 0xFF900000 | 40 | #define COREA_L1_DATA_B_START 0xFF900000 |
41 | #define COREB_L1_CODE_START 0xFF600000 | ||
42 | #define COREB_L1_DATA_A_START 0xFF500000 | ||
43 | #define COREB_L1_DATA_B_START 0xFF400000 | ||
44 | |||
45 | #define L1_CODE_START COREA_L1_CODE_START | ||
46 | #define L1_DATA_A_START COREA_L1_DATA_A_START | ||
47 | #define L1_DATA_B_START COREA_L1_DATA_B_START | ||
41 | 48 | ||
42 | #define L1_CODE_LENGTH 0x4000 | 49 | #define L1_CODE_LENGTH 0x4000 |
43 | 50 | ||
@@ -72,7 +79,10 @@ | |||
72 | 79 | ||
73 | /* Scratch Pad Memory */ | 80 | /* Scratch Pad Memory */ |
74 | 81 | ||
75 | #define L1_SCRATCH_START 0xFFB00000 | 82 | #define COREA_L1_SCRATCH_START 0xFFB00000 |
83 | #define COREB_L1_SCRATCH_START 0xFF700000 | ||
84 | |||
85 | #define L1_SCRATCH_START COREA_L1_SCRATCH_START | ||
76 | #define L1_SCRATCH_LENGTH 0x1000 | 86 | #define L1_SCRATCH_LENGTH 0x1000 |
77 | 87 | ||
78 | #endif /* _MEM_MAP_533_H_ */ | 88 | #endif /* _MEM_MAP_533_H_ */ |
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index 90c7397036ed..5a219b228de3 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S | |||
@@ -190,8 +190,8 @@ ENTRY(_ex_single_step) | |||
190 | if cc jump .Lfind_priority_done; | 190 | if cc jump .Lfind_priority_done; |
191 | jump.s .Lfind_priority_start; | 191 | jump.s .Lfind_priority_start; |
192 | .Lfind_priority_done: | 192 | .Lfind_priority_done: |
193 | p4.l = _debugger_step; | 193 | p4.l = _kgdb_single_step; |
194 | p4.h = _debugger_step; | 194 | p4.h = _kgdb_single_step; |
195 | r6 = [p4]; | 195 | r6 = [p4]; |
196 | cc = r6 == 0; | 196 | cc = r6 == 0; |
197 | if cc jump .Ldo_single_step; | 197 | if cc jump .Ldo_single_step; |
@@ -1071,7 +1071,12 @@ ENTRY(_ex_table) | |||
1071 | */ | 1071 | */ |
1072 | .long _ex_syscall /* 0x00 - User Defined - Linux Syscall */ | 1072 | .long _ex_syscall /* 0x00 - User Defined - Linux Syscall */ |
1073 | .long _ex_soft_bp /* 0x01 - User Defined - Software breakpoint */ | 1073 | .long _ex_soft_bp /* 0x01 - User Defined - Software breakpoint */ |
1074 | #ifdef CONFIG_KGDB | ||
1075 | .long _ex_trap_c /* 0x02 - User Defined - KGDB initial connection | ||
1076 | and break signal trap */ | ||
1077 | #else | ||
1074 | .long _ex_replaceable /* 0x02 - User Defined */ | 1078 | .long _ex_replaceable /* 0x02 - User Defined */ |
1079 | #endif | ||
1075 | .long _ex_trap_c /* 0x03 - User Defined - userspace stack overflow */ | 1080 | .long _ex_trap_c /* 0x03 - User Defined - userspace stack overflow */ |
1076 | .long _ex_trap_c /* 0x04 - User Defined - dump trace buffer */ | 1081 | .long _ex_trap_c /* 0x04 - User Defined - dump trace buffer */ |
1077 | .long _ex_replaceable /* 0x05 - User Defined */ | 1082 | .long _ex_replaceable /* 0x05 - User Defined */ |
diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 5fa536727c61..ff4d5c2879a5 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c | |||
@@ -1136,8 +1136,4 @@ void do_irq(int vec, struct pt_regs *fp) | |||
1136 | vec = ivg->irqno; | 1136 | vec = ivg->irqno; |
1137 | } | 1137 | } |
1138 | asm_do_IRQ(vec, fp); | 1138 | asm_do_IRQ(vec, fp); |
1139 | |||
1140 | #ifdef CONFIG_KGDB | ||
1141 | kgdb_process_breakpoint(); | ||
1142 | #endif | ||
1143 | } | 1139 | } |