2 * File: arch/blackfin/kernel/kgdb.c
9 * Rev: $Id: kgdb_bfin_linux-2.6.x.patch 4934 2007-02-13 09:32:11Z sonicz $
12 * Copyright 2005-2006 Analog Devices Inc.
14 * Bugs: Enter bugs at http://blackfin.uclinux.org/
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.
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.
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
32 #include <linux/string.h>
33 #include <linux/kernel.h>
34 #include <linux/sched.h>
35 #include <linux/smp.h>
36 #include <linux/spinlock.h>
37 #include <linux/delay.h>
38 #include <linux/ptrace.h> /* for linux pt_regs struct */
39 #include <linux/kgdb.h>
40 #include <linux/console.h>
41 #include <linux/init.h>
42 #include <linux/debugger.h>
43 #include <linux/errno.h>
44 #include <linux/irq.h>
45 #include <asm/system.h>
46 #include <asm/traps.h>
47 #include <asm/blackfin.h>
49 /* Put the error code here just in case the user cares. */
51 /* Likewise, the vector number here (since GDB only gets the signal
52 number through the usual means, and that's not very specific). */
53 int gdb_bf533vector
= -1;
55 #if KGDB_MAX_NO_CPUS != 8
56 #error change the definition of slavecpulocks
59 void regs_to_gdb_regs(unsigned long *gdb_regs
, struct pt_regs
*regs
)
61 gdb_regs
[BFIN_R0
] = regs
->r0
;
62 gdb_regs
[BFIN_R1
] = regs
->r1
;
63 gdb_regs
[BFIN_R2
] = regs
->r2
;
64 gdb_regs
[BFIN_R3
] = regs
->r3
;
65 gdb_regs
[BFIN_R4
] = regs
->r4
;
66 gdb_regs
[BFIN_R5
] = regs
->r5
;
67 gdb_regs
[BFIN_R6
] = regs
->r6
;
68 gdb_regs
[BFIN_R7
] = regs
->r7
;
69 gdb_regs
[BFIN_P0
] = regs
->p0
;
70 gdb_regs
[BFIN_P1
] = regs
->p1
;
71 gdb_regs
[BFIN_P2
] = regs
->p2
;
72 gdb_regs
[BFIN_P3
] = regs
->p3
;
73 gdb_regs
[BFIN_P4
] = regs
->p4
;
74 gdb_regs
[BFIN_P5
] = regs
->p5
;
75 gdb_regs
[BFIN_SP
] = regs
->reserved
;
76 gdb_regs
[BFIN_FP
] = regs
->fp
;
77 gdb_regs
[BFIN_I0
] = regs
->i0
;
78 gdb_regs
[BFIN_I1
] = regs
->i1
;
79 gdb_regs
[BFIN_I2
] = regs
->i2
;
80 gdb_regs
[BFIN_I3
] = regs
->i3
;
81 gdb_regs
[BFIN_M0
] = regs
->m0
;
82 gdb_regs
[BFIN_M1
] = regs
->m1
;
83 gdb_regs
[BFIN_M2
] = regs
->m2
;
84 gdb_regs
[BFIN_M3
] = regs
->m3
;
85 gdb_regs
[BFIN_B0
] = regs
->b0
;
86 gdb_regs
[BFIN_B1
] = regs
->b1
;
87 gdb_regs
[BFIN_B2
] = regs
->b2
;
88 gdb_regs
[BFIN_B3
] = regs
->b3
;
89 gdb_regs
[BFIN_L0
] = regs
->l0
;
90 gdb_regs
[BFIN_L1
] = regs
->l1
;
91 gdb_regs
[BFIN_L2
] = regs
->l2
;
92 gdb_regs
[BFIN_L3
] = regs
->l3
;
93 gdb_regs
[BFIN_A0_DOT_X
] = regs
->a0x
;
94 gdb_regs
[BFIN_A0_DOT_W
] = regs
->a0w
;
95 gdb_regs
[BFIN_A1_DOT_X
] = regs
->a1x
;
96 gdb_regs
[BFIN_A1_DOT_W
] = regs
->a1w
;
97 gdb_regs
[BFIN_ASTAT
] = regs
->astat
;
98 gdb_regs
[BFIN_RETS
] = regs
->rets
;
99 gdb_regs
[BFIN_LC0
] = regs
->lc0
;
100 gdb_regs
[BFIN_LT0
] = regs
->lt0
;
101 gdb_regs
[BFIN_LB0
] = regs
->lb0
;
102 gdb_regs
[BFIN_LC1
] = regs
->lc1
;
103 gdb_regs
[BFIN_LT1
] = regs
->lt1
;
104 gdb_regs
[BFIN_LB1
] = regs
->lb1
;
105 gdb_regs
[BFIN_CYCLES
] = 0;
106 gdb_regs
[BFIN_CYCLES2
] = 0;
107 gdb_regs
[BFIN_USP
] = regs
->usp
;
108 gdb_regs
[BFIN_SEQSTAT
] = regs
->seqstat
;
109 gdb_regs
[BFIN_SYSCFG
] = regs
->syscfg
;
110 gdb_regs
[BFIN_RETI
] = regs
->pc
;
111 gdb_regs
[BFIN_RETX
] = regs
->retx
;
112 gdb_regs
[BFIN_RETN
] = regs
->retn
;
113 gdb_regs
[BFIN_RETE
] = regs
->rete
;
114 gdb_regs
[BFIN_PC
] = regs
->pc
;
115 gdb_regs
[BFIN_CC
] = 0;
116 gdb_regs
[BFIN_EXTRA1
] = 0;
117 gdb_regs
[BFIN_EXTRA2
] = 0;
118 gdb_regs
[BFIN_EXTRA3
] = 0;
119 gdb_regs
[BFIN_IPEND
] = regs
->ipend
;
123 * Extracts ebp, esp and eip values understandable by gdb from the values
124 * saved by switch_to.
125 * thread.esp points to ebp. flags and ebp are pushed in switch_to hence esp
126 * prior to entering switch_to is 8 greater then the value that is saved.
127 * If switch_to changes, change following code appropriately.
129 void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs
, struct task_struct
*p
)
131 gdb_regs
[BFIN_SP
] = p
->thread
.ksp
;
132 gdb_regs
[BFIN_PC
] = p
->thread
.pc
;
133 gdb_regs
[BFIN_SEQSTAT
] = p
->thread
.seqstat
;
136 void gdb_regs_to_regs(unsigned long *gdb_regs
, struct pt_regs
*regs
)
138 regs
->r0
= gdb_regs
[BFIN_R0
];
139 regs
->r1
= gdb_regs
[BFIN_R1
];
140 regs
->r2
= gdb_regs
[BFIN_R2
];
141 regs
->r3
= gdb_regs
[BFIN_R3
];
142 regs
->r4
= gdb_regs
[BFIN_R4
];
143 regs
->r5
= gdb_regs
[BFIN_R5
];
144 regs
->r6
= gdb_regs
[BFIN_R6
];
145 regs
->r7
= gdb_regs
[BFIN_R7
];
146 regs
->p0
= gdb_regs
[BFIN_P0
];
147 regs
->p1
= gdb_regs
[BFIN_P1
];
148 regs
->p2
= gdb_regs
[BFIN_P2
];
149 regs
->p3
= gdb_regs
[BFIN_P3
];
150 regs
->p4
= gdb_regs
[BFIN_P4
];
151 regs
->p5
= gdb_regs
[BFIN_P5
];
152 regs
->fp
= gdb_regs
[BFIN_FP
];
153 regs
->i0
= gdb_regs
[BFIN_I0
];
154 regs
->i1
= gdb_regs
[BFIN_I1
];
155 regs
->i2
= gdb_regs
[BFIN_I2
];
156 regs
->i3
= gdb_regs
[BFIN_I3
];
157 regs
->m0
= gdb_regs
[BFIN_M0
];
158 regs
->m1
= gdb_regs
[BFIN_M1
];
159 regs
->m2
= gdb_regs
[BFIN_M2
];
160 regs
->m3
= gdb_regs
[BFIN_M3
];
161 regs
->b0
= gdb_regs
[BFIN_B0
];
162 regs
->b1
= gdb_regs
[BFIN_B1
];
163 regs
->b2
= gdb_regs
[BFIN_B2
];
164 regs
->b3
= gdb_regs
[BFIN_B3
];
165 regs
->l0
= gdb_regs
[BFIN_L0
];
166 regs
->l1
= gdb_regs
[BFIN_L1
];
167 regs
->l2
= gdb_regs
[BFIN_L2
];
168 regs
->l3
= gdb_regs
[BFIN_L3
];
169 regs
->a0x
= gdb_regs
[BFIN_A0_DOT_X
];
170 regs
->a0w
= gdb_regs
[BFIN_A0_DOT_W
];
171 regs
->a1x
= gdb_regs
[BFIN_A1_DOT_X
];
172 regs
->a1w
= gdb_regs
[BFIN_A1_DOT_W
];
173 regs
->rets
= gdb_regs
[BFIN_RETS
];
174 regs
->lc0
= gdb_regs
[BFIN_LC0
];
175 regs
->lt0
= gdb_regs
[BFIN_LT0
];
176 regs
->lb0
= gdb_regs
[BFIN_LB0
];
177 regs
->lc1
= gdb_regs
[BFIN_LC1
];
178 regs
->lt1
= gdb_regs
[BFIN_LT1
];
179 regs
->lb1
= gdb_regs
[BFIN_LB1
];
180 regs
->usp
= gdb_regs
[BFIN_USP
];
181 regs
->syscfg
= gdb_regs
[BFIN_SYSCFG
];
182 regs
->retx
= gdb_regs
[BFIN_PC
];
183 regs
->retn
= gdb_regs
[BFIN_RETN
];
184 regs
->rete
= gdb_regs
[BFIN_RETE
];
185 regs
->pc
= gdb_regs
[BFIN_PC
];
187 #if 0 /* can't change these */
188 regs
->astat
= gdb_regs
[BFIN_ASTAT
];
189 regs
->seqstat
= gdb_regs
[BFIN_SEQSTAT
];
190 regs
->ipend
= gdb_regs
[BFIN_IPEND
];
194 struct hw_breakpoint
{
195 unsigned int occupied
:1;
197 unsigned int enabled
:1;
199 unsigned int dataacc
:2;
200 unsigned short count
;
202 } breakinfo
[HW_BREAKPOINT_NUM
];
204 int kgdb_arch_init(void)
206 kgdb_remove_all_hw_break();
210 int kgdb_set_hw_break(unsigned long addr
)
213 for (breakno
= 0; breakno
< HW_BREAKPOINT_NUM
; breakno
++)
214 if (!breakinfo
[breakno
].occupied
) {
215 breakinfo
[breakno
].occupied
= 1;
216 breakinfo
[breakno
].enabled
= 1;
217 breakinfo
[breakno
].type
= 1;
218 breakinfo
[breakno
].addr
= addr
;
225 int kgdb_remove_hw_break(unsigned long addr
)
228 for (breakno
= 0; breakno
< HW_BREAKPOINT_NUM
; breakno
++)
229 if (breakinfo
[breakno
].addr
== addr
)
230 memset(&(breakinfo
[breakno
]), 0, sizeof(struct hw_breakpoint
));
235 void kgdb_remove_all_hw_break(void)
237 memset(breakinfo
, 0, sizeof(struct hw_breakpoint
)*8);
241 void kgdb_show_info(void)
243 printk(KERN_DEBUG "hwd: wpia0=0x%x, wpiacnt0=%d, wpiactl=0x%x, wpstat=0x%x\n",
244 bfin_read_WPIA0(), bfin_read_WPIACNT0(),
245 bfin_read_WPIACTL(), bfin_read_WPSTAT());
249 void kgdb_correct_hw_break(void)
253 uint32_t wpdactl
= bfin_read_WPDACTL();
256 for (breakno
= 0; breakno
< HW_BREAKPOINT_NUM
; breakno
++) {
257 if (breakinfo
[breakno
].type
== 1) {
260 if (breakinfo
[breakno
].enabled
&& !(wpdactl
& WPIAEN0
)) {
262 wpdactl
&= ~(WPIREN01
|EMUSW0
);
263 wpdactl
|= WPIAEN0
|WPICNTEN0
;
264 bfin_write_WPIA0(breakinfo
[breakno
].addr
);
265 bfin_write_WPIACNT0(breakinfo
[breakno
].skip
);
266 } else if (!breakinfo
[breakno
].enabled
&& (wpdactl
& WPIAEN0
)) {
273 if (breakinfo
[breakno
].enabled
&& !(wpdactl
& WPIAEN1
)) {
275 wpdactl
&= ~(WPIREN01
|EMUSW1
);
276 wpdactl
|= WPIAEN1
|WPICNTEN1
;
277 bfin_write_WPIA1(breakinfo
[breakno
].addr
);
278 bfin_write_WPIACNT1(breakinfo
[breakno
].skip
);
279 } else if (!breakinfo
[breakno
].enabled
&& (wpdactl
& WPIAEN1
)) {
286 if (breakinfo
[breakno
].enabled
&& !(wpdactl
& WPIAEN2
)) {
288 wpdactl
&= ~(WPIREN23
|EMUSW2
);
289 wpdactl
|= WPIAEN2
|WPICNTEN2
;
290 bfin_write_WPIA2(breakinfo
[breakno
].addr
);
291 bfin_write_WPIACNT2(breakinfo
[breakno
].skip
);
292 } else if (!breakinfo
[breakno
].enabled
&& (wpdactl
& WPIAEN2
)) {
299 if (breakinfo
[breakno
].enabled
&& !(wpdactl
& WPIAEN3
)) {
301 wpdactl
&= ~(WPIREN23
|EMUSW3
);
302 wpdactl
|= WPIAEN3
|WPICNTEN3
;
303 bfin_write_WPIA3(breakinfo
[breakno
].addr
);
304 bfin_write_WPIACNT3(breakinfo
[breakno
].skip
);
305 } else if (!breakinfo
[breakno
].enabled
&& (wpdactl
& WPIAEN3
)) {
311 if (breakinfo
[breakno
].enabled
&& !(wpdactl
& WPIAEN4
)) {
313 wpdactl
&= ~(WPIREN45
|EMUSW4
);
314 wpdactl
|= WPIAEN4
|WPICNTEN4
;
315 bfin_write_WPIA4(breakinfo
[breakno
].addr
);
316 bfin_write_WPIACNT4(breakinfo
[breakno
].skip
);
317 } else if (!breakinfo
[breakno
].enabled
&& (wpdactl
& WPIAEN4
)) {
323 if (breakinfo
[breakno
].enabled
&& !(wpdactl
& WPIAEN5
)) {
325 wpdactl
&= ~(WPIREN45
|EMUSW5
);
326 wpdactl
|= WPIAEN5
|WPICNTEN5
;
327 bfin_write_WPIA5(breakinfo
[breakno
].addr
);
328 bfin_write_WPIACNT5(breakinfo
[breakno
].skip
);
329 } else if (!breakinfo
[breakno
].enabled
&& (wpdactl
& WPIAEN5
)) {
340 /*printk("correct_hw_break: wpdactl=0x%x\n", wpdactl);*/
341 bfin_write_WPDACTL(wpdactl
);
343 /*kgdb_show_info();*/
347 void kgdb_disable_hw_debug(struct pt_regs
*regs
)
349 /* Disable hardware debugging while we are in kgdb */
350 bfin_write_WPIACTL(bfin_read_WPIACTL() & ~0x1);
354 void kgdb_post_master_code(struct pt_regs
*regs
, int eVector
, int err_code
)
356 /* Master processor is completely in the debugger */
357 gdb_bf533vector
= eVector
;
358 gdb_bf533errcode
= err_code
;
361 int kgdb_arch_handle_exception(int exceptionVector
, int signo
,
362 int err_code
, char *remcom_in_buffer
,
363 char *remcom_out_buffer
,
364 struct pt_regs
*linux_regs
)
372 switch (remcom_in_buffer
[0]) {
375 if (kgdb_contthread
&& kgdb_contthread
!= current
) {
376 strcpy(remcom_out_buffer
, "E00");
380 kgdb_contthread
= NULL
;
382 /* try to read optional parameter, pc unchanged if no parm */
383 ptr
= &remcom_in_buffer
[1];
384 if (kgdb_hex2long(&ptr
, &addr
)) {
385 linux_regs
->retx
= addr
;
387 newPC
= linux_regs
->retx
;
389 /* clear the trace bit */
390 linux_regs
->syscfg
&= 0xfffffffe;
392 /* set the trace bit if we're stepping */
393 if (remcom_in_buffer
[0] == 's') {
394 linux_regs
->syscfg
|= 0x1;
398 wp_status
= bfin_read_WPSTAT();
401 if (exceptionVector
== VEC_WATCH
) {
402 for (breakno
= 0; breakno
< 6; ++breakno
) {
403 if (wp_status
& (1 << breakno
)) {
409 kgdb_correct_hw_break();
411 bfin_write_WPSTAT(0);
415 return -1; /* this means that we do not want to exit from the handler */
418 struct kgdb_arch arch_kgdb_ops
= {
419 .gdb_bpt_instr
= {0xa1},
420 .flags
= KGDB_HW_BREAKPOINT
,