2 * Bedbug Functions specific to the PPC405 chip
7 #include <linux/ctype.h>
8 #include <bedbug/type.h>
9 #include <bedbug/bedbug.h>
10 #include <bedbug/regs.h>
11 #include <bedbug/ppc.h>
13 #if defined(CONFIG_CMD_BEDBUG) && defined(CONFIG_4xx)
15 #define MAX_BREAK_POINTS 4
17 extern CPU_DEBUG_CTX bug_ctx
;
19 void bedbug405_init
__P ((void));
20 void bedbug405_do_break
__P ((cmd_tbl_t
*, int, int, char *[]));
21 void bedbug405_break_isr
__P ((struct pt_regs
*));
22 int bedbug405_find_empty
__P ((void));
23 int bedbug405_set
__P ((int, unsigned long));
24 int bedbug405_clear
__P ((int));
27 /* ======================================================================
28 * Initialize the global bug_ctx structure for the AMCC PPC405. Clear all
30 * ====================================================================== */
32 void bedbug405_init (void)
36 /* -------------------------------------------------- */
38 bug_ctx
.hw_debug_enabled
= 0;
40 bug_ctx
.current_bp
= 0;
43 bug_ctx
.do_break
= bedbug405_do_break
;
44 bug_ctx
.break_isr
= bedbug405_break_isr
;
45 bug_ctx
.find_empty
= bedbug405_find_empty
;
46 bug_ctx
.set
= bedbug405_set
;
47 bug_ctx
.clear
= bedbug405_clear
;
49 for (i
= 1; i
<= MAX_BREAK_POINTS
; ++i
)
52 puts ("BEDBUG:ready\n");
54 } /* bedbug_init_breakpoints */
58 /* ======================================================================
59 * Set/clear/show one of the hardware breakpoints for the 405. The "off"
60 * string will disable a specific breakpoint. The "show" string will
61 * display the current breakpoints. Otherwise an address will set a
62 * breakpoint at that address. Setting a breakpoint uses the CPU-specific
63 * set routine which will assign a breakpoint number.
64 * ====================================================================== */
66 void bedbug405_do_break (cmd_tbl_t
* cmdtp
, int flag
, int argc
, char *argv
[])
68 long addr
= 0; /* Address to break at */
69 int which_bp
; /* Breakpoint number */
71 /* -------------------------------------------------- */
74 printf ("Usage:\n%s\n", cmdtp
->usage
);
78 /* Turn off a breakpoint */
80 if (strcmp (argv
[1], "off") == 0) {
81 if (bug_ctx
.hw_debug_enabled
== 0) {
82 printf ("No breakpoints enabled\n");
86 which_bp
= simple_strtoul (argv
[2], NULL
, 10);
89 (*bug_ctx
.clear
) (which_bp
);
91 printf ("Breakpoint %d removed\n", which_bp
);
95 /* Show a list of breakpoints */
97 if (strcmp (argv
[1], "show") == 0) {
98 for (which_bp
= 1; which_bp
<= MAX_BREAK_POINTS
; ++which_bp
) {
115 printf ("Breakpoint [%d]: ", which_bp
);
117 printf ("NOT SET\n");
119 disppc ((unsigned char *) addr
, 0, 1, bedbug_puts
,
125 /* Set a breakpoint at the address */
127 if (!isdigit (argv
[1][0])) {
128 printf ("Usage:\n%s\n", cmdtp
->usage
);
132 addr
= simple_strtoul (argv
[1], NULL
, 16) & 0xfffffffc;
134 if ((bug_ctx
.set
) && (which_bp
= (*bug_ctx
.set
) (0, addr
)) > 0) {
135 printf ("Breakpoint [%d]: ", which_bp
);
136 disppc ((unsigned char *) addr
, 0, 1, bedbug_puts
, F_RADHEX
);
140 } /* bedbug405_do_break */
144 /* ======================================================================
145 * Handle a breakpoint. First determine which breakpoint was hit by
146 * looking at the DeBug Status Register (DBSR), clear the breakpoint
147 * and enter a mini main loop. Stay in the loop until the stopped flag
148 * in the debug context is cleared.
149 * ====================================================================== */
151 void bedbug405_break_isr (struct pt_regs
*regs
)
153 unsigned long dbsr_val
; /* Value of the DBSR */
154 unsigned long addr
= 0; /* Address stopped at */
156 /* -------------------------------------------------- */
158 dbsr_val
= GET_DBSR ();
160 if (dbsr_val
& DBSR_IA1
) {
161 bug_ctx
.current_bp
= 1;
163 SET_DBSR (DBSR_IA1
); /* Write a 1 to clear */
164 } else if (dbsr_val
& DBSR_IA2
) {
165 bug_ctx
.current_bp
= 2;
167 SET_DBSR (DBSR_IA2
); /* Write a 1 to clear */
168 } else if (dbsr_val
& DBSR_IA3
) {
169 bug_ctx
.current_bp
= 3;
171 SET_DBSR (DBSR_IA3
); /* Write a 1 to clear */
172 } else if (dbsr_val
& DBSR_IA4
) {
173 bug_ctx
.current_bp
= 4;
175 SET_DBSR (DBSR_IA4
); /* Write a 1 to clear */
178 bedbug_main_loop (addr
, regs
);
180 } /* bedbug405_break_isr */
184 /* ======================================================================
185 * Look through all of the hardware breakpoints available to see if one
187 * ====================================================================== */
189 int bedbug405_find_empty (void)
191 /* -------------------------------------------------- */
193 if (GET_IAC1 () == 0)
196 if (GET_IAC2 () == 0)
199 if (GET_IAC3 () == 0)
202 if (GET_IAC4 () == 0)
206 } /* bedbug405_find_empty */
210 /* ======================================================================
211 * Set a breakpoint. If 'which_bp' is zero then find an unused breakpoint
212 * number, otherwise reassign the given breakpoint. If hardware debugging
213 * is not enabled, then turn it on via the MSR and DBCR0. Set the break
214 * address in the appropriate IACx register and enable proper address
215 * beakpoint in DBCR0.
216 * ====================================================================== */
218 int bedbug405_set (int which_bp
, unsigned long addr
)
220 /* -------------------------------------------------- */
222 /* Only look if which_bp == 0, else use which_bp */
223 if ((bug_ctx
.find_empty
) && (!which_bp
) &&
224 (which_bp
= (*bug_ctx
.find_empty
) ()) == 0) {
225 printf ("All breakpoints in use\n");
229 if (which_bp
< 1 || which_bp
> MAX_BREAK_POINTS
) {
230 printf ("Invalid break point # %d\n", which_bp
);
234 if (!bug_ctx
.hw_debug_enabled
) {
235 SET_MSR (GET_MSR () | 0x200); /* set MSR[ DE ] */
236 SET_DBCR0 (GET_DBCR0 () | DBCR0_IDM
);
237 bug_ctx
.hw_debug_enabled
= 1;
243 SET_DBCR0 (GET_DBCR0 () | DBCR0_IA1
);
248 SET_DBCR0 (GET_DBCR0 () | DBCR0_IA2
);
253 SET_DBCR0 (GET_DBCR0 () | DBCR0_IA3
);
258 SET_DBCR0 (GET_DBCR0 () | DBCR0_IA4
);
263 } /* bedbug405_set */
267 /* ======================================================================
268 * Disable a specific breakoint by setting the appropriate IACx register
269 * to zero and claring the instruction address breakpoint in DBCR0.
270 * ====================================================================== */
272 int bedbug405_clear (int which_bp
)
274 /* -------------------------------------------------- */
276 if (which_bp
< 1 || which_bp
> MAX_BREAK_POINTS
) {
277 printf ("Invalid break point # (%d)\n", which_bp
);
284 SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA1
);
289 SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA2
);
294 SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA3
);
299 SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA4
);
304 } /* bedbug405_clear */
307 /* ====================================================================== */