ARM DPM: support updating HW breakpoints
[openocd.git] / src / target / arm_dpm.c
1 /*
2 * Copyright (C) 2009 by David Brownell
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "arm.h"
25 #include "arm_dpm.h"
26 #include <jtag/jtag.h>
27 #include "register.h"
28 #include "breakpoints.h"
29 #include "target_type.h"
30 #include "arm_opcodes.h"
31
32
33 /**
34 * @file
35 * Implements various ARM DPM operations using architectural debug registers.
36 * These routines layer over core-specific communication methods to cope with
37 * implementation differences between cores like ARM1136 and Cortex-A8.
38 */
39
40 /*----------------------------------------------------------------------*/
41
42 /*
43 * Coprocessor support
44 */
45
46 /* Read coprocessor */
47 static int dpm_mrc(struct target *target, int cpnum,
48 uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm,
49 uint32_t *value)
50 {
51 struct arm *arm = target_to_arm(target);
52 struct arm_dpm *dpm = arm->dpm;
53 int retval;
54
55 retval = dpm->prepare(dpm);
56 if (retval != ERROR_OK)
57 return retval;
58
59 LOG_DEBUG("MRC p%d, %d, r0, c%d, c%d, %d", cpnum,
60 (int) op1, (int) CRn,
61 (int) CRm, (int) op2);
62
63 /* read coprocessor register into R0; return via DCC */
64 retval = dpm->instr_read_data_r0(dpm,
65 ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2),
66 value);
67
68 /* (void) */ dpm->finish(dpm);
69 return retval;
70 }
71
72 static int dpm_mcr(struct target *target, int cpnum,
73 uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm,
74 uint32_t value)
75 {
76 struct arm *arm = target_to_arm(target);
77 struct arm_dpm *dpm = arm->dpm;
78 int retval;
79
80 retval = dpm->prepare(dpm);
81 if (retval != ERROR_OK)
82 return retval;
83
84 LOG_DEBUG("MCR p%d, %d, r0, c%d, c%d, %d", cpnum,
85 (int) op1, (int) CRn,
86 (int) CRm, (int) op2);
87
88 /* read DCC into r0; then write coprocessor register from R0 */
89 retval = dpm->instr_write_data_r0(dpm,
90 ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2),
91 value);
92
93 /* (void) */ dpm->finish(dpm);
94 return retval;
95 }
96
97 /*----------------------------------------------------------------------*/
98
99 /*
100 * Register access utilities
101 */
102
103 /* Toggles between recorded core mode (USR, SVC, etc) and a temporary one.
104 * Routines *must* restore the original mode before returning!!
105 */
106 static int dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode)
107 {
108 int retval;
109 uint32_t cpsr;
110
111 /* restore previous mode */
112 if (mode == ARM_MODE_ANY)
113 cpsr = buf_get_u32(dpm->arm->cpsr->value, 0, 32);
114
115 /* else force to the specified mode */
116 else
117 cpsr = mode;
118
119 retval = dpm->instr_write_data_r0(dpm, ARMV4_5_MSR_GP(0, 0xf, 0), cpsr);
120
121 if (dpm->instr_cpsr_sync)
122 retval = dpm->instr_cpsr_sync(dpm);
123
124 return retval;
125 }
126
127 /* just read the register -- rely on the core mode being right */
128 static int dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
129 {
130 uint32_t value;
131 int retval;
132
133 switch (regnum) {
134 case 0 ... 14:
135 /* return via DCC: "MCR p14, 0, Rnum, c0, c5, 0" */
136 retval = dpm->instr_read_data_dcc(dpm,
137 ARMV4_5_MCR(14, 0, regnum, 0, 5, 0),
138 &value);
139 break;
140 case 15: /* PC */
141 /* "MOV r0, pc"; then return via DCC */
142 retval = dpm->instr_read_data_r0(dpm, 0xe1a0000f, &value);
143
144 /* NOTE: this seems like a slightly awkward place to update
145 * this value ... but if the PC gets written (the only way
146 * to change what we compute), the arch spec says subsequent
147 * reads return values which are "unpredictable". So this
148 * is always right except in those broken-by-intent cases.
149 */
150 switch (dpm->arm->core_state) {
151 case ARM_STATE_ARM:
152 value -= 8;
153 break;
154 case ARM_STATE_THUMB:
155 case ARM_STATE_THUMB_EE:
156 value -= 4;
157 break;
158 case ARM_STATE_JAZELLE:
159 /* core-specific ... ? */
160 LOG_WARNING("Jazelle PC adjustment unknown");
161 break;
162 }
163 break;
164 default:
165 /* 16: "MRS r0, CPSR"; then return via DCC
166 * 17: "MRS r0, SPSR"; then return via DCC
167 */
168 retval = dpm->instr_read_data_r0(dpm,
169 ARMV4_5_MRS(0, regnum & 1),
170 &value);
171 break;
172 }
173
174 if (retval == ERROR_OK) {
175 buf_set_u32(r->value, 0, 32, value);
176 r->valid = true;
177 r->dirty = false;
178 LOG_DEBUG("READ: %s, %8.8x", r->name, (unsigned) value);
179 }
180
181 return retval;
182 }
183
184 /* just write the register -- rely on the core mode being right */
185 static int dpm_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
186 {
187 int retval;
188 uint32_t value = buf_get_u32(r->value, 0, 32);
189
190 switch (regnum) {
191 case 0 ... 14:
192 /* load register from DCC: "MRC p14, 0, Rnum, c0, c5, 0" */
193 retval = dpm->instr_write_data_dcc(dpm,
194 ARMV4_5_MRC(14, 0, regnum, 0, 5, 0),
195 value);
196 break;
197 case 15: /* PC */
198 /* read r0 from DCC; then "MOV pc, r0" */
199 retval = dpm->instr_write_data_r0(dpm, 0xe1a0f000, value);
200 break;
201 default:
202 /* 16: read r0 from DCC, then "MSR r0, CPSR_cxsf"
203 * 17: read r0 from DCC, then "MSR r0, SPSR_cxsf"
204 */
205 retval = dpm->instr_write_data_r0(dpm,
206 ARMV4_5_MSR_GP(0, 0xf, regnum & 1),
207 value);
208
209 if (regnum == 16 && dpm->instr_cpsr_sync)
210 retval = dpm->instr_cpsr_sync(dpm);
211
212 break;
213 }
214
215 if (retval == ERROR_OK) {
216 r->dirty = false;
217 LOG_DEBUG("WRITE: %s, %8.8x", r->name, (unsigned) value);
218 }
219
220 return retval;
221 }
222
223 /**
224 * Read basic registers of the the current context: R0 to R15, and CPSR;
225 * sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb).
226 * In normal operation this is called on entry to halting debug state,
227 * possibly after some other operations supporting restore of debug state
228 * or making sure the CPU is fully idle (drain write buffer, etc).
229 */
230 int arm_dpm_read_current_registers(struct arm_dpm *dpm)
231 {
232 struct arm *arm = dpm->arm;
233 uint32_t cpsr;
234 int retval;
235 struct reg *r;
236
237 retval = dpm->prepare(dpm);
238 if (retval != ERROR_OK)
239 return retval;
240
241 /* read R0 first (it's used for scratch), then CPSR */
242 r = arm->core_cache->reg_list + 0;
243 if (!r->valid) {
244 retval = dpm_read_reg(dpm, r, 0);
245 if (retval != ERROR_OK)
246 goto fail;
247 }
248 r->dirty = true;
249
250 retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRS(0, 0), &cpsr);
251 if (retval != ERROR_OK)
252 goto fail;
253
254 /* update core mode and state, plus shadow mapping for R8..R14 */
255 arm_set_cpsr(arm, cpsr);
256
257 /* REVISIT we can probably avoid reading R1..R14, saving time... */
258 for (unsigned i = 1; i < 16; i++) {
259 r = arm_reg_current(arm, i);
260 if (r->valid)
261 continue;
262
263 retval = dpm_read_reg(dpm, r, i);
264 if (retval != ERROR_OK)
265 goto fail;
266 }
267
268 /* NOTE: SPSR ignored (if it's even relevant). */
269
270 /* REVISIT the debugger can trigger various exceptions. See the
271 * ARMv7A architecture spec, section C5.7, for more info about
272 * what defenses are needed; v6 debug has the most issues.
273 */
274
275 fail:
276 /* (void) */ dpm->finish(dpm);
277 return retval;
278 }
279
280 /* Avoid needless I/O ... leave breakpoints and watchpoints alone
281 * unless they're removed, or need updating because of single-stepping
282 * or running debugger code.
283 */
284 static int dpm_maybe_update_bpwp(struct arm_dpm *dpm, bool bpwp,
285 struct dpm_bpwp *xp, int *set_p)
286 {
287 int retval = ERROR_OK;
288 bool disable;
289
290 if (!set_p) {
291 if (!xp->dirty)
292 goto done;
293 xp->dirty = false;
294 /* removed or startup; we must disable it */
295 disable = true;
296 } else if (bpwp) {
297 if (!xp->dirty)
298 goto done;
299 /* disabled, but we must set it */
300 xp->dirty = disable = false;
301 *set_p = true;
302 } else {
303 if (!*set_p)
304 goto done;
305 /* set, but we must temporarily disable it */
306 xp->dirty = disable = true;
307 *set_p = false;
308 }
309
310 if (disable)
311 retval = dpm->bpwp_disable(dpm, xp->number);
312 else
313 retval = dpm->bpwp_enable(dpm, xp->number,
314 xp->address, xp->control);
315
316 if (retval != ERROR_OK)
317 LOG_ERROR("%s: can't %s HW bp/wp %d",
318 disable ? "disable" : "enable",
319 target_name(dpm->arm->target),
320 xp->number);
321 done:
322 return retval;
323 }
324
325 /**
326 * Writes all modified core registers for all processor modes. In normal
327 * operation this is called on exit from halting debug state.
328 *
329 * @param dpm: represents the processor
330 * @param bpwp: true ensures breakpoints and watchpoints are set,
331 * false ensures they are cleared
332 */
333 int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp)
334 {
335 struct arm *arm = dpm->arm;
336 struct reg_cache *cache = arm->core_cache;
337 int retval;
338 bool did_write;
339
340 retval = dpm->prepare(dpm);
341 if (retval != ERROR_OK)
342 goto done;
343
344 /* enable/disable hardware breakpoints */
345 for (unsigned i = 0; i < dpm->nbp; i++) {
346 struct dpm_bp *dbp = dpm->dbp + i;
347 struct breakpoint *bp = dbp->bp;
348
349 retval = dpm_maybe_update_bpwp(dpm, bpwp, &dbp->bpwp,
350 bp ? &bp->set : NULL);
351 }
352
353 /* enable/disable watchpoints */
354 for (unsigned i = 0; i < dpm->nwp; i++) {
355 struct dpm_wp *dwp = dpm->dwp + i;
356 struct watchpoint *wp = dwp->wp;
357
358 retval = dpm_maybe_update_bpwp(dpm, bpwp, &dwp->bpwp,
359 wp ? &wp->set : NULL);
360 }
361
362 /* NOTE: writes to breakpoint and watchpoint registers might
363 * be queued, and need (efficient/batched) flushing later.
364 */
365
366 /* Scan the registers until we find one that's both dirty and
367 * eligible for flushing. Flush that and everything else that
368 * shares the same core mode setting. Typically this won't
369 * actually find anything to do...
370 */
371 do {
372 enum arm_mode mode = ARM_MODE_ANY;
373
374 did_write = false;
375
376 /* check everything except our scratch register R0 */
377 for (unsigned i = 1; i < cache->num_regs; i++) {
378 struct arm_reg *r;
379 unsigned regnum;
380
381 /* also skip PC, CPSR, and non-dirty */
382 if (i == 15)
383 continue;
384 if (arm->cpsr == cache->reg_list + i)
385 continue;
386 if (!cache->reg_list[i].dirty)
387 continue;
388
389 r = cache->reg_list[i].arch_info;
390 regnum = r->num;
391
392 /* may need to pick and set a mode */
393 if (!did_write) {
394 enum arm_mode tmode;
395
396 did_write = true;
397 mode = tmode = r->mode;
398
399 /* cope with special cases */
400 switch (regnum) {
401 case 8 ... 12:
402 /* r8..r12 "anything but FIQ" case;
403 * we "know" core mode is accurate
404 * since we haven't changed it yet
405 */
406 if (arm->core_mode == ARM_MODE_FIQ
407 && ARM_MODE_ANY
408 != mode)
409 tmode = ARM_MODE_USR;
410 break;
411 case 16:
412 /* SPSR */
413 regnum++;
414 break;
415 }
416
417 /* REVISIT error checks */
418 if (tmode != ARM_MODE_ANY)
419 retval = dpm_modeswitch(dpm, tmode);
420 }
421 if (r->mode != mode)
422 continue;
423
424 retval = dpm_write_reg(dpm,
425 &cache->reg_list[i],
426 regnum);
427
428 }
429
430 } while (did_write);
431
432 /* Restore original CPSR ... assuming either that we changed it,
433 * or it's dirty. Must write PC to ensure the return address is
434 * defined, and must not write it before CPSR.
435 */
436 retval = dpm_modeswitch(dpm, ARM_MODE_ANY);
437 arm->cpsr->dirty = false;
438
439 retval = dpm_write_reg(dpm, &cache->reg_list[15], 15);
440 cache->reg_list[15].dirty = false;
441
442 /* flush R0 -- it's *very* dirty by now */
443 retval = dpm_write_reg(dpm, &cache->reg_list[0], 0);
444 cache->reg_list[0].dirty = false;
445
446 /* (void) */ dpm->finish(dpm);
447 done:
448 return retval;
449 }
450
451 /* Returns ARM_MODE_ANY or temporary mode to use while reading the
452 * specified register ... works around flakiness from ARM core calls.
453 * Caller already filtered out SPSR access; mode is never MODE_SYS
454 * or MODE_ANY.
455 */
456 static enum arm_mode dpm_mapmode(struct arm *arm,
457 unsigned num, enum arm_mode mode)
458 {
459 enum arm_mode amode = arm->core_mode;
460
461 /* don't switch if the mode is already correct */
462 if (amode == ARM_MODE_SYS)
463 amode = ARM_MODE_USR;
464 if (mode == amode)
465 return ARM_MODE_ANY;
466
467 switch (num) {
468 /* don't switch for non-shadowed registers (r0..r7, r15/pc, cpsr) */
469 case 0 ... 7:
470 case 15:
471 case 16:
472 break;
473 /* r8..r12 aren't shadowed for anything except FIQ */
474 case 8 ... 12:
475 if (mode == ARM_MODE_FIQ)
476 return mode;
477 break;
478 /* r13/sp, and r14/lr are always shadowed */
479 case 13:
480 case 14:
481 return mode;
482 default:
483 LOG_WARNING("invalid register #%u", num);
484 break;
485 }
486 return ARM_MODE_ANY;
487 }
488
489
490 /*
491 * Standard ARM register accessors ... there are three methods
492 * in "struct arm", to support individual read/write and bulk read
493 * of registers.
494 */
495
496 static int arm_dpm_read_core_reg(struct target *target, struct reg *r,
497 int regnum, enum arm_mode mode)
498 {
499 struct arm_dpm *dpm = target_to_arm(target)->dpm;
500 int retval;
501
502 if (regnum < 0 || regnum > 16)
503 return ERROR_INVALID_ARGUMENTS;
504
505 if (regnum == 16) {
506 if (mode != ARM_MODE_ANY)
507 regnum = 17;
508 } else
509 mode = dpm_mapmode(dpm->arm, regnum, mode);
510
511 /* REVISIT what happens if we try to read SPSR in a core mode
512 * which has no such register?
513 */
514
515 retval = dpm->prepare(dpm);
516 if (retval != ERROR_OK)
517 return retval;
518
519 if (mode != ARM_MODE_ANY) {
520 retval = dpm_modeswitch(dpm, mode);
521 if (retval != ERROR_OK)
522 goto fail;
523 }
524
525 retval = dpm_read_reg(dpm, r, regnum);
526 /* always clean up, regardless of error */
527
528 if (mode != ARM_MODE_ANY)
529 /* (void) */ dpm_modeswitch(dpm, ARM_MODE_ANY);
530
531 fail:
532 /* (void) */ dpm->finish(dpm);
533 return retval;
534 }
535
536 static int arm_dpm_write_core_reg(struct target *target, struct reg *r,
537 int regnum, enum arm_mode mode, uint32_t value)
538 {
539 struct arm_dpm *dpm = target_to_arm(target)->dpm;
540 int retval;
541
542
543 if (regnum < 0 || regnum > 16)
544 return ERROR_INVALID_ARGUMENTS;
545
546 if (regnum == 16) {
547 if (mode != ARM_MODE_ANY)
548 regnum = 17;
549 } else
550 mode = dpm_mapmode(dpm->arm, regnum, mode);
551
552 /* REVISIT what happens if we try to write SPSR in a core mode
553 * which has no such register?
554 */
555
556 retval = dpm->prepare(dpm);
557 if (retval != ERROR_OK)
558 return retval;
559
560 if (mode != ARM_MODE_ANY) {
561 retval = dpm_modeswitch(dpm, mode);
562 if (retval != ERROR_OK)
563 goto fail;
564 }
565
566 retval = dpm_write_reg(dpm, r, regnum);
567 /* always clean up, regardless of error */
568
569 if (mode != ARM_MODE_ANY)
570 /* (void) */ dpm_modeswitch(dpm, ARM_MODE_ANY);
571
572 fail:
573 /* (void) */ dpm->finish(dpm);
574 return retval;
575 }
576
577 static int arm_dpm_full_context(struct target *target)
578 {
579 struct arm *arm = target_to_arm(target);
580 struct arm_dpm *dpm = arm->dpm;
581 struct reg_cache *cache = arm->core_cache;
582 int retval;
583 bool did_read;
584
585 retval = dpm->prepare(dpm);
586 if (retval != ERROR_OK)
587 goto done;
588
589 do {
590 enum arm_mode mode = ARM_MODE_ANY;
591
592 did_read = false;
593
594 /* We "know" arm_dpm_read_current_registers() was called so
595 * the unmapped registers (R0..R7, PC, AND CPSR) and some
596 * view of R8..R14 are current. We also "know" oddities of
597 * register mapping: special cases for R8..R12 and SPSR.
598 *
599 * Pick some mode with unread registers and read them all.
600 * Repeat until done.
601 */
602 for (unsigned i = 0; i < cache->num_regs; i++) {
603 struct arm_reg *r;
604
605 if (cache->reg_list[i].valid)
606 continue;
607 r = cache->reg_list[i].arch_info;
608
609 /* may need to pick a mode and set CPSR */
610 if (!did_read) {
611 did_read = true;
612 mode = r->mode;
613
614 /* For R8..R12 when we've entered debug
615 * state in FIQ mode... patch mode.
616 */
617 if (mode == ARM_MODE_ANY)
618 mode = ARM_MODE_USR;
619
620 /* REVISIT error checks */
621 retval = dpm_modeswitch(dpm, mode);
622 }
623 if (r->mode != mode)
624 continue;
625
626 /* CPSR was read, so "R16" must mean SPSR */
627 retval = dpm_read_reg(dpm,
628 &cache->reg_list[i],
629 (r->num == 16) ? 17 : r->num);
630
631 }
632
633 } while (did_read);
634
635 retval = dpm_modeswitch(dpm, ARM_MODE_ANY);
636 /* (void) */ dpm->finish(dpm);
637 done:
638 return retval;
639 }
640
641
642 /*----------------------------------------------------------------------*/
643
644 /*
645 * Breakpoint and Watchpoint support.
646 *
647 * Hardware {break,watch}points are usually left active, to minimize
648 * debug entry/exit costs. When they are set or cleared, it's done in
649 * batches. Also, DPM-conformant hardware can update debug registers
650 * regardless of whether the CPU is running or halted ... though that
651 * fact isn't currently leveraged.
652 */
653
654 static int dpm_watchpoint_setup(struct arm_dpm *dpm, unsigned index,
655 struct watchpoint *wp)
656 {
657 uint32_t addr = wp->address;
658 uint32_t control;
659
660 /* this hardware doesn't support data value matching or masking */
661 if (wp->value || wp->mask != ~(uint32_t)0) {
662 LOG_DEBUG("watchpoint values and masking not supported");
663 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
664 }
665
666 control = (1 << 0) /* enable */
667 | (3 << 1); /* both user and privileged access */
668
669 switch (wp->rw) {
670 case WPT_READ:
671 control |= 1 << 3;
672 break;
673 case WPT_WRITE:
674 control |= 2 << 3;
675 break;
676 case WPT_ACCESS:
677 control |= 3 << 3;
678 break;
679 }
680
681 /* Match 1, 2, or all 4 byte addresses in this word.
682 *
683 * FIXME: v7 hardware allows lengths up to 2 GB, and has eight
684 * byte address select bits. Support larger wp->length, if addr
685 * is suitably aligned.
686 */
687 switch (wp->length) {
688 case 1:
689 control |= (1 << (addr & 3)) << 5;
690 addr &= ~3;
691 break;
692 case 2:
693 /* require 2-byte alignment */
694 if (!(addr & 1)) {
695 control |= (3 << (addr & 2)) << 5;
696 break;
697 }
698 /* FALL THROUGH */
699 case 4:
700 /* require 4-byte alignment */
701 if (!(addr & 3)) {
702 control |= 0xf << 5;
703 break;
704 }
705 /* FALL THROUGH */
706 default:
707 LOG_DEBUG("bad watchpoint length or alignment");
708 return ERROR_INVALID_ARGUMENTS;
709 }
710
711 /* other control bits:
712 * bits 9:12 == 0 ... only checking up to four byte addresses (v7 only)
713 * bits 15:14 == 0 ... both secure and nonsecure states (v6.1+ only)
714 * bit 20 == 0 ... not linked to a context ID
715 * bit 28:24 == 0 ... not ignoring N LSBs (v7 only)
716 */
717
718 dpm->dwp[index].wp = wp;
719 dpm->dwp[index].bpwp.address = addr & ~3;
720 dpm->dwp[index].bpwp.control = control;
721 dpm->dwp[index].bpwp.dirty = true;
722
723 /* hardware is updated in write_dirty_registers() */
724 return ERROR_OK;
725 }
726
727
728 static int dpm_add_watchpoint(struct target *target, struct watchpoint *wp)
729 {
730 struct arm *arm = target_to_arm(target);
731 struct arm_dpm *dpm = arm->dpm;
732 int retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
733
734 if (dpm->bpwp_enable) {
735 for (unsigned i = 0; i < dpm->nwp; i++) {
736 if (!dpm->dwp[i].wp) {
737 retval = dpm_watchpoint_setup(dpm, i, wp);
738 break;
739 }
740 }
741 }
742
743 return retval;
744 }
745
746 static int dpm_remove_watchpoint(struct target *target, struct watchpoint *wp)
747 {
748 struct arm *arm = target_to_arm(target);
749 struct arm_dpm *dpm = arm->dpm;
750 int retval = ERROR_INVALID_ARGUMENTS;
751
752 for (unsigned i = 0; i < dpm->nwp; i++) {
753 if (dpm->dwp[i].wp == wp) {
754 dpm->dwp[i].wp = NULL;
755 dpm->dwp[i].bpwp.dirty = true;
756
757 /* hardware is updated in write_dirty_registers() */
758 retval = ERROR_OK;
759 break;
760 }
761 }
762
763 return retval;
764 }
765
766 void arm_dpm_report_wfar(struct arm_dpm *dpm, uint32_t addr)
767 {
768 switch (dpm->arm->core_state) {
769 case ARM_STATE_ARM:
770 addr -= 8;
771 break;
772 case ARM_STATE_THUMB:
773 case ARM_STATE_THUMB_EE:
774 addr -= 4;
775 break;
776 case ARM_STATE_JAZELLE:
777 /* ?? */
778 break;
779 }
780 dpm->wp_pc = addr;
781 }
782
783 /*----------------------------------------------------------------------*/
784
785 /*
786 * Other debug and support utilities
787 */
788
789 void arm_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dscr)
790 {
791 struct target *target = dpm->arm->target;
792
793 dpm->dscr = dscr;
794
795 /* Examine debug reason */
796 switch (DSCR_ENTRY(dscr)) {
797 case 6: /* Data abort (v6 only) */
798 case 7: /* Prefetch abort (v6 only) */
799 /* FALL THROUGH -- assume a v6 core in abort mode */
800 case 0: /* HALT request from debugger */
801 case 4: /* EDBGRQ */
802 target->debug_reason = DBG_REASON_DBGRQ;
803 break;
804 case 1: /* HW breakpoint */
805 case 3: /* SW BKPT */
806 case 5: /* vector catch */
807 target->debug_reason = DBG_REASON_BREAKPOINT;
808 break;
809 case 2: /* asynch watchpoint */
810 case 10: /* precise watchpoint */
811 target->debug_reason = DBG_REASON_WATCHPOINT;
812 break;
813 default:
814 target->debug_reason = DBG_REASON_UNDEFINED;
815 break;
816 }
817 }
818
819 /*----------------------------------------------------------------------*/
820
821 /*
822 * Setup and management support.
823 */
824
825 /**
826 * Hooks up this DPM to its associated target; call only once.
827 * Initially this only covers the register cache.
828 *
829 * Oh, and watchpoints. Yeah.
830 */
831 int arm_dpm_setup(struct arm_dpm *dpm)
832 {
833 struct arm *arm = dpm->arm;
834 struct target *target = arm->target;
835 struct reg_cache *cache;
836
837 arm->dpm = dpm;
838
839 /* register access setup */
840 arm->full_context = arm_dpm_full_context;
841 arm->read_core_reg = arm_dpm_read_core_reg;
842 arm->write_core_reg = arm_dpm_write_core_reg;
843
844 cache = arm_build_reg_cache(target, arm);
845 if (!cache)
846 return ERROR_FAIL;
847
848 *register_get_last_cache_p(&target->reg_cache) = cache;
849
850 /* coprocessor access setup */
851 arm->mrc = dpm_mrc;
852 arm->mcr = dpm_mcr;
853
854 /* breakpoint and watchpoint setup */
855 target->type->add_watchpoint = dpm_add_watchpoint;
856 target->type->remove_watchpoint = dpm_remove_watchpoint;
857
858 /* FIXME add breakpoint support */
859 /* FIXME add vector catch support */
860
861 dpm->nbp = 1 + ((dpm->didr >> 24) & 0xf);
862 dpm->dbp = calloc(dpm->nbp, sizeof *dpm->dbp);
863
864 dpm->nwp = 1 + ((dpm->didr >> 28) & 0xf);
865 dpm->dwp = calloc(dpm->nwp, sizeof *dpm->dwp);
866
867 if (!dpm->dbp || !dpm->dwp) {
868 free(dpm->dbp);
869 free(dpm->dwp);
870 return ERROR_FAIL;
871 }
872
873 LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
874 target_name(target), dpm->nbp, dpm->nwp);
875
876 /* REVISIT ... and some of those breakpoints could match
877 * execution context IDs...
878 */
879
880 return ERROR_OK;
881 }
882
883 /**
884 * Reinitializes DPM state at the beginning of a new debug session
885 * or after a reset which may have affected the debug module.
886 */
887 int arm_dpm_initialize(struct arm_dpm *dpm)
888 {
889 /* Disable all breakpoints and watchpoints at startup. */
890 if (dpm->bpwp_disable) {
891 unsigned i;
892
893 for (i = 0; i < dpm->nbp; i++) {
894 dpm->dbp[i].bpwp.number = i;
895 (void) dpm->bpwp_disable(dpm, i);
896 }
897 for (i = 0; i < dpm->nwp; i++) {
898 dpm->dwp[i].bpwp.number = 16 + i;
899 (void) dpm->bpwp_disable(dpm, 16 + i);
900 }
901 } else
902 LOG_WARNING("%s: can't disable breakpoints and watchpoints",
903 target_name(dpm->arm->target));
904
905 return ERROR_OK;
906 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)