ARM: move opcode macros to <target/arm_opcodes.h>
[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 "armv4_5.h" /* REVISIT to become 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 /**
281 * Writes all modified core registers for all processor modes. In normal
282 * operation this is called on exit from halting debug state.
283 *
284 * @param dpm: represents the processor
285 * @param bpwp: true ensures breakpoints and watchpoints are set,
286 * false ensures they are cleared
287 */
288 int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp)
289 {
290 struct arm *arm = dpm->arm;
291 struct reg_cache *cache = arm->core_cache;
292 int retval;
293 bool did_write;
294
295 retval = dpm->prepare(dpm);
296 if (retval != ERROR_OK)
297 goto done;
298
299 /* enable/disable watchpoints */
300 for (unsigned i = 0; i < dpm->nwp; i++) {
301 struct dpm_wp *dwp = dpm->dwp + i;
302 struct watchpoint *wp = dwp->wp;
303 bool disable;
304
305 /* Avoid needless I/O ... leave watchpoints alone
306 * unless they're removed, or need updating because
307 * of single-stepping or running debugger code.
308 */
309 if (!wp) {
310 if (!dwp->dirty)
311 continue;
312 dwp->dirty = false;
313 /* removed or startup; we must disable it */
314 disable = true;
315 } else if (bpwp) {
316 if (!dwp->dirty)
317 continue;
318 /* disabled, but we must set it */
319 dwp->dirty = disable = false;
320 wp->set = true;
321 } else {
322 if (!wp->set)
323 continue;
324 /* set, but we must temporarily disable it */
325 dwp->dirty = disable = true;
326 wp->set = false;
327 }
328
329 if (disable)
330 retval = dpm->bpwp_disable(dpm, 16 + i);
331 else
332 retval = dpm->bpwp_enable(dpm, 16 + i,
333 wp->address & ~3, dwp->control);
334
335 if (retval != ERROR_OK)
336 LOG_ERROR("%s: can't %s HW watchpoint %d",
337 target_name(arm->target),
338 disable ? "disable" : "enable",
339 i);
340 }
341
342 /* NOTE: writes to breakpoint and watchpoint registers might
343 * be queued, and need (efficient/batched) flushing later.
344 */
345
346 /* Scan the registers until we find one that's both dirty and
347 * eligible for flushing. Flush that and everything else that
348 * shares the same core mode setting. Typically this won't
349 * actually find anything to do...
350 */
351 do {
352 enum arm_mode mode = ARM_MODE_ANY;
353
354 did_write = false;
355
356 /* check everything except our scratch register R0 */
357 for (unsigned i = 1; i < cache->num_regs; i++) {
358 struct arm_reg *r;
359 unsigned regnum;
360
361 /* also skip PC, CPSR, and non-dirty */
362 if (i == 15)
363 continue;
364 if (arm->cpsr == cache->reg_list + i)
365 continue;
366 if (!cache->reg_list[i].dirty)
367 continue;
368
369 r = cache->reg_list[i].arch_info;
370 regnum = r->num;
371
372 /* may need to pick and set a mode */
373 if (!did_write) {
374 enum arm_mode tmode;
375
376 did_write = true;
377 mode = tmode = r->mode;
378
379 /* cope with special cases */
380 switch (regnum) {
381 case 8 ... 12:
382 /* r8..r12 "anything but FIQ" case;
383 * we "know" core mode is accurate
384 * since we haven't changed it yet
385 */
386 if (arm->core_mode == ARM_MODE_FIQ
387 && ARM_MODE_ANY
388 != mode)
389 tmode = ARM_MODE_USR;
390 break;
391 case 16:
392 /* SPSR */
393 regnum++;
394 break;
395 }
396
397 /* REVISIT error checks */
398 if (tmode != ARM_MODE_ANY)
399 retval = dpm_modeswitch(dpm, tmode);
400 }
401 if (r->mode != mode)
402 continue;
403
404 retval = dpm_write_reg(dpm,
405 &cache->reg_list[i],
406 regnum);
407
408 }
409
410 } while (did_write);
411
412 /* Restore original CPSR ... assuming either that we changed it,
413 * or it's dirty. Must write PC to ensure the return address is
414 * defined, and must not write it before CPSR.
415 */
416 retval = dpm_modeswitch(dpm, ARM_MODE_ANY);
417 arm->cpsr->dirty = false;
418
419 retval = dpm_write_reg(dpm, &cache->reg_list[15], 15);
420 cache->reg_list[15].dirty = false;
421
422 /* flush R0 -- it's *very* dirty by now */
423 retval = dpm_write_reg(dpm, &cache->reg_list[0], 0);
424 cache->reg_list[0].dirty = false;
425
426 /* (void) */ dpm->finish(dpm);
427 done:
428 return retval;
429 }
430
431 /* Returns ARM_MODE_ANY or temporary mode to use while reading the
432 * specified register ... works around flakiness from ARM core calls.
433 * Caller already filtered out SPSR access; mode is never MODE_SYS
434 * or MODE_ANY.
435 */
436 static enum arm_mode dpm_mapmode(struct arm *arm,
437 unsigned num, enum arm_mode mode)
438 {
439 enum arm_mode amode = arm->core_mode;
440
441 /* don't switch if the mode is already correct */
442 if (amode == ARM_MODE_SYS)
443 amode = ARM_MODE_USR;
444 if (mode == amode)
445 return ARM_MODE_ANY;
446
447 switch (num) {
448 /* don't switch for non-shadowed registers (r0..r7, r15/pc, cpsr) */
449 case 0 ... 7:
450 case 15:
451 case 16:
452 break;
453 /* r8..r12 aren't shadowed for anything except FIQ */
454 case 8 ... 12:
455 if (mode == ARM_MODE_FIQ)
456 return mode;
457 break;
458 /* r13/sp, and r14/lr are always shadowed */
459 case 13:
460 case 14:
461 return mode;
462 default:
463 LOG_WARNING("invalid register #%u", num);
464 break;
465 }
466 return ARM_MODE_ANY;
467 }
468
469
470 /*
471 * Standard ARM register accessors ... there are three methods
472 * in "struct arm", to support individual read/write and bulk read
473 * of registers.
474 */
475
476 static int arm_dpm_read_core_reg(struct target *target, struct reg *r,
477 int regnum, enum arm_mode mode)
478 {
479 struct arm_dpm *dpm = target_to_arm(target)->dpm;
480 int retval;
481
482 if (regnum < 0 || regnum > 16)
483 return ERROR_INVALID_ARGUMENTS;
484
485 if (regnum == 16) {
486 if (mode != ARM_MODE_ANY)
487 regnum = 17;
488 } else
489 mode = dpm_mapmode(dpm->arm, regnum, mode);
490
491 /* REVISIT what happens if we try to read SPSR in a core mode
492 * which has no such register?
493 */
494
495 retval = dpm->prepare(dpm);
496 if (retval != ERROR_OK)
497 return retval;
498
499 if (mode != ARM_MODE_ANY) {
500 retval = dpm_modeswitch(dpm, mode);
501 if (retval != ERROR_OK)
502 goto fail;
503 }
504
505 retval = dpm_read_reg(dpm, r, regnum);
506 /* always clean up, regardless of error */
507
508 if (mode != ARM_MODE_ANY)
509 /* (void) */ dpm_modeswitch(dpm, ARM_MODE_ANY);
510
511 fail:
512 /* (void) */ dpm->finish(dpm);
513 return retval;
514 }
515
516 static int arm_dpm_write_core_reg(struct target *target, struct reg *r,
517 int regnum, enum arm_mode mode, uint32_t value)
518 {
519 struct arm_dpm *dpm = target_to_arm(target)->dpm;
520 int retval;
521
522
523 if (regnum < 0 || regnum > 16)
524 return ERROR_INVALID_ARGUMENTS;
525
526 if (regnum == 16) {
527 if (mode != ARM_MODE_ANY)
528 regnum = 17;
529 } else
530 mode = dpm_mapmode(dpm->arm, regnum, mode);
531
532 /* REVISIT what happens if we try to write SPSR in a core mode
533 * which has no such register?
534 */
535
536 retval = dpm->prepare(dpm);
537 if (retval != ERROR_OK)
538 return retval;
539
540 if (mode != ARM_MODE_ANY) {
541 retval = dpm_modeswitch(dpm, mode);
542 if (retval != ERROR_OK)
543 goto fail;
544 }
545
546 retval = dpm_write_reg(dpm, r, regnum);
547 /* always clean up, regardless of error */
548
549 if (mode != ARM_MODE_ANY)
550 /* (void) */ dpm_modeswitch(dpm, ARM_MODE_ANY);
551
552 fail:
553 /* (void) */ dpm->finish(dpm);
554 return retval;
555 }
556
557 static int arm_dpm_full_context(struct target *target)
558 {
559 struct arm *arm = target_to_arm(target);
560 struct arm_dpm *dpm = arm->dpm;
561 struct reg_cache *cache = arm->core_cache;
562 int retval;
563 bool did_read;
564
565 retval = dpm->prepare(dpm);
566 if (retval != ERROR_OK)
567 goto done;
568
569 do {
570 enum arm_mode mode = ARM_MODE_ANY;
571
572 did_read = false;
573
574 /* We "know" arm_dpm_read_current_registers() was called so
575 * the unmapped registers (R0..R7, PC, AND CPSR) and some
576 * view of R8..R14 are current. We also "know" oddities of
577 * register mapping: special cases for R8..R12 and SPSR.
578 *
579 * Pick some mode with unread registers and read them all.
580 * Repeat until done.
581 */
582 for (unsigned i = 0; i < cache->num_regs; i++) {
583 struct arm_reg *r;
584
585 if (cache->reg_list[i].valid)
586 continue;
587 r = cache->reg_list[i].arch_info;
588
589 /* may need to pick a mode and set CPSR */
590 if (!did_read) {
591 did_read = true;
592 mode = r->mode;
593
594 /* For R8..R12 when we've entered debug
595 * state in FIQ mode... patch mode.
596 */
597 if (mode == ARM_MODE_ANY)
598 mode = ARM_MODE_USR;
599
600 /* REVISIT error checks */
601 retval = dpm_modeswitch(dpm, mode);
602 }
603 if (r->mode != mode)
604 continue;
605
606 /* CPSR was read, so "R16" must mean SPSR */
607 retval = dpm_read_reg(dpm,
608 &cache->reg_list[i],
609 (r->num == 16) ? 17 : r->num);
610
611 }
612
613 } while (did_read);
614
615 retval = dpm_modeswitch(dpm, ARM_MODE_ANY);
616 /* (void) */ dpm->finish(dpm);
617 done:
618 return retval;
619 }
620
621
622 /*----------------------------------------------------------------------*/
623
624 /*
625 * Breakpoint and Watchpoint support.
626 *
627 * Hardware {break,watch}points are usually left active, to minimize
628 * debug entry/exit costs. When they are set or cleared, it's done in
629 * batches. Also, DPM-conformant hardware can update debug registers
630 * regardless of whether the CPU is running or halted ... though that
631 * fact isn't currently leveraged.
632 */
633
634 static int dpm_watchpoint_setup(struct arm_dpm *dpm, unsigned index,
635 struct watchpoint *wp)
636 {
637 uint32_t addr = wp->address;
638 uint32_t control;
639
640 /* this hardware doesn't support data value matching or masking */
641 if (wp->value || wp->mask != ~(uint32_t)0) {
642 LOG_DEBUG("watchpoint values and masking not supported");
643 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
644 }
645
646 control = (1 << 0) /* enable */
647 | (3 << 1); /* both user and privileged access */
648
649 switch (wp->rw) {
650 case WPT_READ:
651 control |= 1 << 3;
652 break;
653 case WPT_WRITE:
654 control |= 2 << 3;
655 break;
656 case WPT_ACCESS:
657 control |= 3 << 3;
658 break;
659 }
660
661 /* Match 1, 2, or all 4 byte addresses in this word.
662 *
663 * FIXME: v7 hardware allows lengths up to 2 GB, and has eight
664 * byte address select bits. Support larger wp->length, if addr
665 * is suitably aligned.
666 */
667 switch (wp->length) {
668 case 1:
669 control |= (1 << (addr & 3)) << 5;
670 addr &= ~3;
671 break;
672 case 2:
673 /* require 2-byte alignment */
674 if (!(addr & 1)) {
675 control |= (3 << (addr & 2)) << 5;
676 break;
677 }
678 /* FALL THROUGH */
679 case 4:
680 /* require 4-byte alignment */
681 if (!(addr & 3)) {
682 control |= 0xf << 5;
683 break;
684 }
685 /* FALL THROUGH */
686 default:
687 LOG_DEBUG("bad watchpoint length or alignment");
688 return ERROR_INVALID_ARGUMENTS;
689 }
690
691 /* other control bits:
692 * bits 9:12 == 0 ... only checking up to four byte addresses (v7 only)
693 * bits 15:14 == 0 ... both secure and nonsecure states (v6.1+ only)
694 * bit 20 == 0 ... not linked to a context ID
695 * bit 28:24 == 0 ... not ignoring N LSBs (v7 only)
696 */
697
698 dpm->dwp[index].wp = wp;
699 dpm->dwp[index].control = control;
700 dpm->dwp[index].dirty = true;
701
702 /* hardware is updated in write_dirty_registers() */
703 return ERROR_OK;
704 }
705
706
707 static int dpm_add_watchpoint(struct target *target, struct watchpoint *wp)
708 {
709 struct arm *arm = target_to_arm(target);
710 struct arm_dpm *dpm = arm->dpm;
711 int retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
712
713 if (dpm->bpwp_enable) {
714 for (unsigned i = 0; i < dpm->nwp; i++) {
715 if (!dpm->dwp[i].wp) {
716 retval = dpm_watchpoint_setup(dpm, i, wp);
717 break;
718 }
719 }
720 }
721
722 return retval;
723 }
724
725 static int dpm_remove_watchpoint(struct target *target, struct watchpoint *wp)
726 {
727 struct arm *arm = target_to_arm(target);
728 struct arm_dpm *dpm = arm->dpm;
729 int retval = ERROR_INVALID_ARGUMENTS;
730
731 for (unsigned i = 0; i < dpm->nwp; i++) {
732 if (dpm->dwp[i].wp == wp) {
733 dpm->dwp[i].wp = NULL;
734 dpm->dwp[i].dirty = true;
735
736 /* hardware is updated in write_dirty_registers() */
737 retval = ERROR_OK;
738 break;
739 }
740 }
741
742 return retval;
743 }
744
745 void arm_dpm_report_wfar(struct arm_dpm *dpm, uint32_t addr)
746 {
747 switch (dpm->arm->core_state) {
748 case ARM_STATE_ARM:
749 addr -= 8;
750 break;
751 case ARM_STATE_THUMB:
752 case ARM_STATE_THUMB_EE:
753 addr -= 4;
754 break;
755 case ARM_STATE_JAZELLE:
756 /* ?? */
757 break;
758 }
759 dpm->wp_pc = addr;
760 }
761
762 /*----------------------------------------------------------------------*/
763
764 /*
765 * Other debug and support utilities
766 */
767
768 void arm_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dscr)
769 {
770 struct target *target = dpm->arm->target;
771
772 dpm->dscr = dscr;
773
774 /* Examine debug reason */
775 switch (DSCR_ENTRY(dscr)) {
776 case 6: /* Data abort (v6 only) */
777 case 7: /* Prefetch abort (v6 only) */
778 /* FALL THROUGH -- assume a v6 core in abort mode */
779 case 0: /* HALT request from debugger */
780 case 4: /* EDBGRQ */
781 target->debug_reason = DBG_REASON_DBGRQ;
782 break;
783 case 1: /* HW breakpoint */
784 case 3: /* SW BKPT */
785 case 5: /* vector catch */
786 target->debug_reason = DBG_REASON_BREAKPOINT;
787 break;
788 case 2: /* asynch watchpoint */
789 case 10: /* precise watchpoint */
790 target->debug_reason = DBG_REASON_WATCHPOINT;
791 break;
792 default:
793 target->debug_reason = DBG_REASON_UNDEFINED;
794 break;
795 }
796 }
797
798 /*----------------------------------------------------------------------*/
799
800 /*
801 * Setup and management support.
802 */
803
804 /**
805 * Hooks up this DPM to its associated target; call only once.
806 * Initially this only covers the register cache.
807 *
808 * Oh, and watchpoints. Yeah.
809 */
810 int arm_dpm_setup(struct arm_dpm *dpm)
811 {
812 struct arm *arm = dpm->arm;
813 struct target *target = arm->target;
814 struct reg_cache *cache;
815
816 arm->dpm = dpm;
817
818 /* register access setup */
819 arm->full_context = arm_dpm_full_context;
820 arm->read_core_reg = arm_dpm_read_core_reg;
821 arm->write_core_reg = arm_dpm_write_core_reg;
822
823 cache = arm_build_reg_cache(target, arm);
824 if (!cache)
825 return ERROR_FAIL;
826
827 *register_get_last_cache_p(&target->reg_cache) = cache;
828
829 /* coprocessor access setup */
830 arm->mrc = dpm_mrc;
831 arm->mcr = dpm_mcr;
832
833 /* breakpoint and watchpoint setup */
834 target->type->add_watchpoint = dpm_add_watchpoint;
835 target->type->remove_watchpoint = dpm_remove_watchpoint;
836
837 /* FIXME add breakpoint support */
838 /* FIXME add vector catch support */
839
840 dpm->nbp = 1 + ((dpm->didr >> 24) & 0xf);
841 dpm->dbp = calloc(dpm->nbp, sizeof *dpm->dbp);
842
843 dpm->nwp = 1 + ((dpm->didr >> 28) & 0xf);
844 dpm->dwp = calloc(dpm->nwp, sizeof *dpm->dwp);
845
846 if (!dpm->dbp || !dpm->dwp) {
847 free(dpm->dbp);
848 free(dpm->dwp);
849 return ERROR_FAIL;
850 }
851
852 LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
853 target_name(target), dpm->nbp, dpm->nwp);
854
855 /* REVISIT ... and some of those breakpoints could match
856 * execution context IDs...
857 */
858
859 return ERROR_OK;
860 }
861
862 /**
863 * Reinitializes DPM state at the beginning of a new debug session
864 * or after a reset which may have affected the debug module.
865 */
866 int arm_dpm_initialize(struct arm_dpm *dpm)
867 {
868 /* Disable all breakpoints and watchpoints at startup. */
869 if (dpm->bpwp_disable) {
870 unsigned i;
871
872 for (i = 0; i < dpm->nbp; i++)
873 (void) dpm->bpwp_disable(dpm, i);
874 for (i = 0; i < dpm->nwp; i++)
875 (void) dpm->bpwp_disable(dpm, 16 + i);
876 } else
877 LOG_WARNING("%s: can't disable breakpoints and watchpoints",
878 target_name(dpm->arm->target));
879
880 return ERROR_OK;
881 }

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)