Rev 3071 | Rev 3790 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3071 | Rev 3139 | ||
---|---|---|---|
Line 31... | Line 31... | ||
31 | */ |
31 | */ |
32 | /** @file |
32 | /** @file |
33 | */ |
33 | */ |
34 | 34 | ||
35 | #include <arch/debugger.h> |
35 | #include <arch/debugger.h> |
- | 36 | #include <arch/barrier.h> |
|
36 | #include <memstr.h> |
37 | #include <memstr.h> |
37 | #include <console/kconsole.h> |
38 | #include <console/kconsole.h> |
38 | #include <console/cmd.h> |
39 | #include <console/cmd.h> |
39 | #include <symtab.h> |
40 | #include <symtab.h> |
40 | #include <print.h> |
41 | #include <print.h> |
Line 70... | Line 71... | ||
70 | static cmd_arg_t add_argv = { |
71 | static cmd_arg_t add_argv = { |
71 | .type = ARG_TYPE_INT |
72 | .type = ARG_TYPE_INT |
72 | }; |
73 | }; |
73 | static cmd_info_t addbkpt_info = { |
74 | static cmd_info_t addbkpt_info = { |
74 | .name = "addbkpt", |
75 | .name = "addbkpt", |
75 | .description = "addbkpt <&symbol> - new bkpoint. Break on J/Branch insts unsupported.", |
76 | .description = "addbkpt <&symbol> - new bkpoint. Break on J/Branch " |
- | 77 | "insts unsupported.", |
|
76 | .func = cmd_add_breakpoint, |
78 | .func = cmd_add_breakpoint, |
77 | .argc = 1, |
79 | .argc = 1, |
78 | .argv = &add_argv |
80 | .argv = &add_argv |
79 | }; |
81 | }; |
80 | 82 | ||
Line 82... | Line 84... | ||
82 | { .type = ARG_TYPE_INT }, |
84 | { .type = ARG_TYPE_INT }, |
83 | { .type = ARG_TYPE_INT } |
85 | { .type = ARG_TYPE_INT } |
84 | }; |
86 | }; |
85 | static cmd_info_t addbkpte_info = { |
87 | static cmd_info_t addbkpte_info = { |
86 | .name = "addbkpte", |
88 | .name = "addbkpte", |
87 | .description = "addebkpte <&symbol> <&func> - new bkpoint. Call func(or Nothing if 0).", |
89 | .description = "addebkpte <&symbol> <&func> - new bkpoint. Call " |
- | 90 | "func(or Nothing if 0).", |
|
88 | .func = cmd_add_breakpoint, |
91 | .func = cmd_add_breakpoint, |
89 | .argc = 2, |
92 | .argc = 2, |
90 | .argv = adde_argv |
93 | .argv = adde_argv |
91 | }; |
94 | }; |
92 | 95 | ||
93 | static struct { |
96 | static struct { |
94 | uint32_t andmask; |
97 | uint32_t andmask; |
95 | uint32_t value; |
98 | uint32_t value; |
96 | }jmpinstr[] = { |
99 | } jmpinstr[] = { |
97 | {0xf3ff0000, 0x41000000}, /* BCzF */ |
100 | {0xf3ff0000, 0x41000000}, /* BCzF */ |
98 | {0xf3ff0000, 0x41020000}, /* BCzFL */ |
101 | {0xf3ff0000, 0x41020000}, /* BCzFL */ |
99 | {0xf3ff0000, 0x41010000}, /* BCzT */ |
102 | {0xf3ff0000, 0x41010000}, /* BCzT */ |
100 | {0xf3ff0000, 0x41030000}, /* BCzTL */ |
103 | {0xf3ff0000, 0x41030000}, /* BCzTL */ |
101 | {0xfc000000, 0x10000000}, /* BEQ */ |
104 | {0xfc000000, 0x10000000}, /* BEQ */ |
Line 115... | Line 118... | ||
115 | {0xfc000000, 0x14000000}, /* BNE */ |
118 | {0xfc000000, 0x14000000}, /* BNE */ |
116 | {0xfc000000, 0x54000000}, /* BNEL */ |
119 | {0xfc000000, 0x54000000}, /* BNEL */ |
117 | {0xfc000000, 0x08000000}, /* J */ |
120 | {0xfc000000, 0x08000000}, /* J */ |
118 | {0xfc000000, 0x0c000000}, /* JAL */ |
121 | {0xfc000000, 0x0c000000}, /* JAL */ |
119 | {0xfc1f07ff, 0x00000009}, /* JALR */ |
122 | {0xfc1f07ff, 0x00000009}, /* JALR */ |
120 | {0,0} /* EndOfTable */ |
123 | {0, 0} /* EndOfTable */ |
121 | }; |
124 | }; |
122 | 125 | ||
123 | /** Test, if the given instruction is a jump or branch instruction |
126 | /** Test, if the given instruction is a jump or branch instruction |
124 | * |
127 | * |
125 | * @param instr Instruction code |
128 | * @param instr Instruction code |
Line 127... | Line 130... | ||
127 | */ |
130 | */ |
128 | static bool is_jump(unative_t instr) |
131 | static bool is_jump(unative_t instr) |
129 | { |
132 | { |
130 | int i; |
133 | int i; |
131 | 134 | ||
132 | for (i=0;jmpinstr[i].andmask;i++) { |
135 | for (i = 0; jmpinstr[i].andmask; i++) { |
133 | if ((instr & jmpinstr[i].andmask) == jmpinstr[i].value) |
136 | if ((instr & jmpinstr[i].andmask) == jmpinstr[i].value) |
134 | return true; |
137 | return true; |
135 | } |
138 | } |
136 | 139 | ||
137 | return false; |
140 | return false; |
Line 155... | Line 158... | ||
155 | for (i = 0; i < BKPOINTS_MAX; i++) { |
158 | for (i = 0; i < BKPOINTS_MAX; i++) { |
156 | if (breakpoints[i].address == (uintptr_t)argv->intval) { |
159 | if (breakpoints[i].address == (uintptr_t)argv->intval) { |
157 | printf("Duplicate breakpoint %d.\n", i); |
160 | printf("Duplicate breakpoint %d.\n", i); |
158 | spinlock_unlock(&bkpoints_lock); |
161 | spinlock_unlock(&bkpoints_lock); |
159 | return 0; |
162 | return 0; |
160 | } else if (breakpoints[i].address == (uintptr_t)argv->intval + sizeof(unative_t) || \ |
163 | } else if (breakpoints[i].address == (uintptr_t)argv->intval + |
- | 164 | sizeof(unative_t) || breakpoints[i].address == |
|
161 | breakpoints[i].address == (uintptr_t)argv->intval - sizeof(unative_t)) { |
165 | (uintptr_t)argv->intval - sizeof(unative_t)) { |
162 | printf("Adjacent breakpoints not supported, conflict with %d.\n", i); |
166 | printf("Adjacent breakpoints not supported, conflict " |
- | 167 | "with %d.\n", i); |
|
163 | spinlock_unlock(&bkpoints_lock); |
168 | spinlock_unlock(&bkpoints_lock); |
164 | return 0; |
169 | return 0; |
165 | } |
170 | } |
166 | 171 | ||
167 | } |
172 | } |
168 | 173 | ||
169 | for (i=0; i<BKPOINTS_MAX; i++) |
174 | for (i = 0; i < BKPOINTS_MAX; i++) |
170 | if (!breakpoints[i].address) { |
175 | if (!breakpoints[i].address) { |
171 | cur = &breakpoints[i]; |
176 | cur = &breakpoints[i]; |
172 | break; |
177 | break; |
173 | } |
178 | } |
174 | if (!cur) { |
179 | if (!cur) { |
Line 183... | Line 188... | ||
183 | cur->nextinstruction = ((unative_t *)cur->address)[1]; |
188 | cur->nextinstruction = ((unative_t *)cur->address)[1]; |
184 | if (argv == &add_argv) { |
189 | if (argv == &add_argv) { |
185 | cur->flags = 0; |
190 | cur->flags = 0; |
186 | } else { /* We are add extended */ |
191 | } else { /* We are add extended */ |
187 | cur->flags = BKPOINT_FUNCCALL; |
192 | cur->flags = BKPOINT_FUNCCALL; |
188 | cur->bkfunc = (void (*)(void *, istate_t *)) argv[1].intval; |
193 | cur->bkfunc = (void (*)(void *, istate_t *)) argv[1].intval; |
189 | } |
194 | } |
190 | if (is_jump(cur->instruction)) |
195 | if (is_jump(cur->instruction)) |
191 | cur->flags |= BKPOINT_ONESHOT; |
196 | cur->flags |= BKPOINT_ONESHOT; |
192 | cur->counter = 0; |
197 | cur->counter = 0; |
193 | 198 | ||
194 | /* Set breakpoint */ |
199 | /* Set breakpoint */ |
195 | *((unative_t *)cur->address) = 0x0d; |
200 | *((unative_t *)cur->address) = 0x0d; |
- | 201 | smc_coherence(cur->address); |
|
196 | 202 | ||
197 | spinlock_unlock(&bkpoint_lock); |
203 | spinlock_unlock(&bkpoint_lock); |
198 | interrupts_restore(ipl); |
204 | interrupts_restore(ipl); |
199 | 205 | ||
200 | return 1; |
206 | return 1; |
201 | } |
207 | } |
202 | 208 | ||
203 | - | ||
204 | - | ||
205 | /** Remove breakpoint from table */ |
209 | /** Remove breakpoint from table */ |
206 | int cmd_del_breakpoint(cmd_arg_t *argv) |
210 | int cmd_del_breakpoint(cmd_arg_t *argv) |
207 | { |
211 | { |
208 | bpinfo_t *cur; |
212 | bpinfo_t *cur; |
209 | ipl_t ipl; |
213 | ipl_t ipl; |
Line 227... | Line 231... | ||
227 | spinlock_unlock(&bkpoint_lock); |
231 | spinlock_unlock(&bkpoint_lock); |
228 | interrupts_restore(ipl); |
232 | interrupts_restore(ipl); |
229 | return 0; |
233 | return 0; |
230 | } |
234 | } |
231 | ((uint32_t *)cur->address)[0] = cur->instruction; |
235 | ((uint32_t *)cur->address)[0] = cur->instruction; |
- | 236 | smc_coherence(((uint32_t *)cur->address)[0]); |
|
232 | ((uint32_t *)cur->address)[1] = cur->nextinstruction; |
237 | ((uint32_t *)cur->address)[1] = cur->nextinstruction; |
- | 238 | smc_coherence(((uint32_t *)cur->address)[1]); |
|
233 | 239 | ||
234 | cur->address = NULL; |
240 | cur->address = NULL; |
235 | 241 | ||
236 | spinlock_unlock(&bkpoint_lock); |
242 | spinlock_unlock(&bkpoint_lock); |
237 | interrupts_restore(ipl); |
243 | interrupts_restore(ipl); |
Line 250... | Line 256... | ||
250 | for (i = 0; i < BKPOINTS_MAX; i++) |
256 | for (i = 0; i < BKPOINTS_MAX; i++) |
251 | if (breakpoints[i].address) { |
257 | if (breakpoints[i].address) { |
252 | symbol = get_symtab_entry(breakpoints[i].address); |
258 | symbol = get_symtab_entry(breakpoints[i].address); |
253 | 259 | ||
254 | printf("%-2u %-5d %#10zx %-6s %-7s %-8s %s\n", i, |
260 | printf("%-2u %-5d %#10zx %-6s %-7s %-8s %s\n", i, |
255 | breakpoints[i].counter, breakpoints[i].address, |
261 | breakpoints[i].counter, breakpoints[i].address, |
256 | ((breakpoints[i].flags & BKPOINT_INPROG) ? "true" : "false"), |
262 | ((breakpoints[i].flags & BKPOINT_INPROG) ? "true" : |
257 | ((breakpoints[i].flags & BKPOINT_ONESHOT) ? "true" : "false"), |
263 | "false"), ((breakpoints[i].flags & BKPOINT_ONESHOT) |
- | 264 | ? "true" : "false"), ((breakpoints[i].flags & |
|
258 | ((breakpoints[i].flags & BKPOINT_FUNCCALL) ? "true" : "false"), |
265 | BKPOINT_FUNCCALL) ? "true" : "false"), symbol); |
259 | symbol); |
- | |
260 | } |
266 | } |
261 | return 1; |
267 | return 1; |
262 | } |
268 | } |
263 | 269 | ||
264 | /** Initialize debugger */ |
270 | /** Initialize debugger */ |
265 | void debugger_init() |
271 | void debugger_init() |
266 | { |
272 | { |
267 | int i; |
273 | int i; |
268 | 274 | ||
269 | for (i=0; i<BKPOINTS_MAX; i++) |
275 | for (i = 0; i < BKPOINTS_MAX; i++) |
270 | breakpoints[i].address = NULL; |
276 | breakpoints[i].address = NULL; |
271 | 277 | ||
272 | cmd_initialize(&bkpts_info); |
278 | cmd_initialize(&bkpts_info); |
273 | if (!cmd_register(&bkpts_info)) |
279 | if (!cmd_register(&bkpts_info)) |
274 | panic("could not register command %s\n", bkpts_info.name); |
280 | panic("could not register command %s\n", bkpts_info.name); |
Line 303... | Line 309... | ||
303 | /* test branch delay slot */ |
309 | /* test branch delay slot */ |
304 | if (cp0_cause_read() & 0x80000000) |
310 | if (cp0_cause_read() & 0x80000000) |
305 | panic("Breakpoint in branch delay slot not supported.\n"); |
311 | panic("Breakpoint in branch delay slot not supported.\n"); |
306 | 312 | ||
307 | spinlock_lock(&bkpoint_lock); |
313 | spinlock_lock(&bkpoint_lock); |
308 | for (i=0; i<BKPOINTS_MAX; i++) { |
314 | for (i = 0; i < BKPOINTS_MAX; i++) { |
309 | /* Normal breakpoint */ |
315 | /* Normal breakpoint */ |
310 | if (fireaddr == breakpoints[i].address \ |
316 | if (fireaddr == breakpoints[i].address && |
311 | && !(breakpoints[i].flags & BKPOINT_REINST)) { |
317 | !(breakpoints[i].flags & BKPOINT_REINST)) { |
312 | cur = &breakpoints[i]; |
318 | cur = &breakpoints[i]; |
313 | break; |
319 | break; |
314 | } |
320 | } |
315 | /* Reinst only breakpoint */ |
321 | /* Reinst only breakpoint */ |
316 | if ((breakpoints[i].flags & BKPOINT_REINST) \ |
322 | if ((breakpoints[i].flags & BKPOINT_REINST) && |
317 | && (fireaddr == breakpoints[i].address + sizeof(unative_t))) { |
323 | (fireaddr == breakpoints[i].address + sizeof(unative_t))) { |
318 | cur = &breakpoints[i]; |
324 | cur = &breakpoints[i]; |
319 | break; |
325 | break; |
320 | } |
326 | } |
321 | } |
327 | } |
322 | if (cur) { |
328 | if (cur) { |
323 | if (cur->flags & BKPOINT_REINST) { |
329 | if (cur->flags & BKPOINT_REINST) { |
324 | /* Set breakpoint on first instruction */ |
330 | /* Set breakpoint on first instruction */ |
325 | ((uint32_t *)cur->address)[0] = 0x0d; |
331 | ((uint32_t *)cur->address)[0] = 0x0d; |
- | 332 | smc_coherence(((uint32_t *)cur->address)[0]); |
|
326 | /* Return back the second */ |
333 | /* Return back the second */ |
327 | ((uint32_t *)cur->address)[1] = cur->nextinstruction; |
334 | ((uint32_t *)cur->address)[1] = cur->nextinstruction; |
- | 335 | smc_coherence(((uint32_t *)cur->address)[1]); |
|
328 | cur->flags &= ~BKPOINT_REINST; |
336 | cur->flags &= ~BKPOINT_REINST; |
329 | spinlock_unlock(&bkpoint_lock); |
337 | spinlock_unlock(&bkpoint_lock); |
330 | return; |
338 | return; |
331 | } |
339 | } |
332 | if (cur->flags & BKPOINT_INPROG) |
340 | if (cur->flags & BKPOINT_INPROG) |
333 | printf("Warning: breakpoint recursion\n"); |
341 | printf("Warning: breakpoint recursion\n"); |
334 | 342 | ||
335 | if (!(cur->flags & BKPOINT_FUNCCALL)) |
343 | if (!(cur->flags & BKPOINT_FUNCCALL)) |
336 | printf("***Breakpoint %d: %p in %s.\n", i, |
344 | printf("***Breakpoint %d: %p in %s.\n", i, fireaddr, |
337 | fireaddr, get_symtab_entry(istate->epc)); |
345 | get_symtab_entry(istate->epc)); |
338 | 346 | ||
339 | /* Return first instruction back */ |
347 | /* Return first instruction back */ |
340 | ((uint32_t *)cur->address)[0] = cur->instruction; |
348 | ((uint32_t *)cur->address)[0] = cur->instruction; |
- | 349 | smc_coherence(cur->address); |
|
341 | 350 | ||
342 | if (! (cur->flags & BKPOINT_ONESHOT)) { |
351 | if (! (cur->flags & BKPOINT_ONESHOT)) { |
343 | /* Set Breakpoint on next instruction */ |
352 | /* Set Breakpoint on next instruction */ |
344 | ((uint32_t *)cur->address)[1] = 0x0d; |
353 | ((uint32_t *)cur->address)[1] = 0x0d; |
345 | cur->flags |= BKPOINT_REINST; |
354 | cur->flags |= BKPOINT_REINST; |