1
2
3
4
5#include <common.h>
6#include <command.h>
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>
12
13#if defined(CONFIG_CMD_BEDBUG) && defined(CONFIG_4xx)
14
15#define MAX_BREAK_POINTS 4
16
17extern CPU_DEBUG_CTX bug_ctx;
18
19void bedbug405_init __P ((void));
20void bedbug405_do_break __P ((cmd_tbl_t *, int, int, char * const []));
21void bedbug405_break_isr __P ((struct pt_regs *));
22int bedbug405_find_empty __P ((void));
23int bedbug405_set __P ((int, unsigned long));
24int bedbug405_clear __P ((int));
25
26
27
28
29
30
31
32void bedbug405_init (void)
33{
34 int i;
35
36
37
38 bug_ctx.hw_debug_enabled = 0;
39 bug_ctx.stopped = 0;
40 bug_ctx.current_bp = 0;
41 bug_ctx.regs = NULL;
42
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;
48
49 for (i = 1; i <= MAX_BREAK_POINTS; ++i)
50 (*bug_ctx.clear) (i);
51
52 puts ("BEDBUG:ready\n");
53 return;
54}
55
56
57
58
59
60
61
62
63
64
65
66void bedbug405_do_break (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
67{
68 long addr = 0;
69 int which_bp;
70
71
72
73 if (argc < 2) {
74 cmd_usage(cmdtp);
75 return;
76 }
77
78
79
80 if (strcmp (argv[1], "off") == 0) {
81 if (bug_ctx.hw_debug_enabled == 0) {
82 printf ("No breakpoints enabled\n");
83 return;
84 }
85
86 which_bp = simple_strtoul (argv[2], NULL, 10);
87
88 if (bug_ctx.clear)
89 (*bug_ctx.clear) (which_bp);
90
91 printf ("Breakpoint %d removed\n", which_bp);
92 return;
93 }
94
95
96
97 if (strcmp (argv[1], "show") == 0) {
98 for (which_bp = 1; which_bp <= MAX_BREAK_POINTS; ++which_bp) {
99
100 switch (which_bp) {
101 case 1:
102 addr = GET_IAC1 ();
103 break;
104 case 2:
105 addr = GET_IAC2 ();
106 break;
107 case 3:
108 addr = GET_IAC3 ();
109 break;
110 case 4:
111 addr = GET_IAC4 ();
112 break;
113 }
114
115 printf ("Breakpoint [%d]: ", which_bp);
116 if (addr == 0)
117 printf ("NOT SET\n");
118 else
119 disppc ((unsigned char *) addr, 0, 1, bedbug_puts,
120 F_RADHEX);
121 }
122 return;
123 }
124
125
126
127 if (!isdigit (argv[1][0])) {
128 cmd_usage(cmdtp);
129 return;
130 }
131
132 addr = simple_strtoul (argv[1], NULL, 16) & 0xfffffffc;
133
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);
137 }
138
139 return;
140}
141
142
143
144
145
146
147
148
149
150
151void bedbug405_break_isr (struct pt_regs *regs)
152{
153 unsigned long dbsr_val;
154 unsigned long addr = 0;
155
156
157
158 dbsr_val = GET_DBSR ();
159
160 if (dbsr_val & DBSR_IA1) {
161 bug_ctx.current_bp = 1;
162 addr = GET_IAC1 ();
163 SET_DBSR (DBSR_IA1);
164 } else if (dbsr_val & DBSR_IA2) {
165 bug_ctx.current_bp = 2;
166 addr = GET_IAC2 ();
167 SET_DBSR (DBSR_IA2);
168 } else if (dbsr_val & DBSR_IA3) {
169 bug_ctx.current_bp = 3;
170 addr = GET_IAC3 ();
171 SET_DBSR (DBSR_IA3);
172 } else if (dbsr_val & DBSR_IA4) {
173 bug_ctx.current_bp = 4;
174 addr = GET_IAC4 ();
175 SET_DBSR (DBSR_IA4);
176 }
177
178 bedbug_main_loop (addr, regs);
179 return;
180}
181
182
183
184
185
186
187
188
189int bedbug405_find_empty (void)
190{
191
192
193 if (GET_IAC1 () == 0)
194 return 1;
195
196 if (GET_IAC2 () == 0)
197 return 2;
198
199 if (GET_IAC3 () == 0)
200 return 3;
201
202 if (GET_IAC4 () == 0)
203 return 4;
204
205 return 0;
206}
207
208
209
210
211
212
213
214
215
216
217
218int bedbug405_set (int which_bp, unsigned long addr)
219{
220
221
222
223 if ((bug_ctx.find_empty) && (!which_bp) &&
224 (which_bp = (*bug_ctx.find_empty) ()) == 0) {
225 printf ("All breakpoints in use\n");
226 return 0;
227 }
228
229 if (which_bp < 1 || which_bp > MAX_BREAK_POINTS) {
230 printf ("Invalid break point # %d\n", which_bp);
231 return 0;
232 }
233
234 if (!bug_ctx.hw_debug_enabled) {
235 SET_MSR (GET_MSR () | 0x200);
236 SET_DBCR0 (GET_DBCR0 () | DBCR0_IDM);
237 bug_ctx.hw_debug_enabled = 1;
238 }
239
240 switch (which_bp) {
241 case 1:
242 SET_IAC1 (addr);
243 SET_DBCR0 (GET_DBCR0 () | DBCR0_IA1);
244 break;
245
246 case 2:
247 SET_IAC2 (addr);
248 SET_DBCR0 (GET_DBCR0 () | DBCR0_IA2);
249 break;
250
251 case 3:
252 SET_IAC3 (addr);
253 SET_DBCR0 (GET_DBCR0 () | DBCR0_IA3);
254 break;
255
256 case 4:
257 SET_IAC4 (addr);
258 SET_DBCR0 (GET_DBCR0 () | DBCR0_IA4);
259 break;
260 }
261
262 return which_bp;
263}
264
265
266
267
268
269
270
271
272int bedbug405_clear (int which_bp)
273{
274
275
276 if (which_bp < 1 || which_bp > MAX_BREAK_POINTS) {
277 printf ("Invalid break point # (%d)\n", which_bp);
278 return -1;
279 }
280
281 switch (which_bp) {
282 case 1:
283 SET_IAC1 (0);
284 SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA1);
285 break;
286
287 case 2:
288 SET_IAC2 (0);
289 SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA2);
290 break;
291
292 case 3:
293 SET_IAC3 (0);
294 SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA3);
295 break;
296
297 case 4:
298 SET_IAC4 (0);
299 SET_DBCR0 (GET_DBCR0 () & ~DBCR0_IA4);
300 break;
301 }
302
303 return 0;
304}
305
306
307
308#endif
309