2 * Copyright (C) 2009 by David Brownell
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.
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.
22 #include "armv8_dpm.h"
23 #include <jtag/jtag.h>
25 #include "breakpoints.h"
26 #include "target_type.h"
27 #include "armv8_opcodes.h"
32 * Implements various ARM DPM operations using architectural debug registers.
33 * These routines layer over core-specific communication methods to cope with
34 * implementation differences between cores like ARM1136 and Cortex-A8.
36 * The "Debug Programmers' Model" (DPM) for ARMv6 and ARMv7 is defined by
37 * Part C (Debug Architecture) of the ARM Architecture Reference Manual,
38 * ARMv7-A and ARMv7-R edition (ARM DDI 0406B). In OpenOCD, DPM operations
39 * are abstracted through internal programming interfaces to share code and
40 * to minimize needless differences in debug behavior between cores.
43 /*----------------------------------------------------------------------*/
49 /* Read coprocessor */
50 static int dpmv8_mrc(struct target
*target
, int cpnum
,
51 uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
,
54 struct arm
*arm
= target_to_arm(target
);
55 struct arm_dpm
*dpm
= arm
->dpm
;
58 retval
= dpm
->prepare(dpm
);
59 if (retval
!= ERROR_OK
)
62 LOG_DEBUG("MRC p%d, %d, r0, c%d, c%d, %d", cpnum
,
64 (int) CRm
, (int) op2
);
66 /* read coprocessor register into R0; return via DCC */
67 retval
= dpm
->instr_read_data_r0(dpm
,
68 T32_FMTITR(ARMV4_5_MRC(cpnum
, op1
, 0, CRn
, CRm
, op2
)),
71 /* (void) */ dpm
->finish(dpm
);
75 static int dpmv8_mcr(struct target
*target
, int cpnum
,
76 uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
,
79 struct arm
*arm
= target_to_arm(target
);
80 struct arm_dpm
*dpm
= arm
->dpm
;
83 retval
= dpm
->prepare(dpm
);
84 if (retval
!= ERROR_OK
)
87 LOG_DEBUG("MCR p%d, %d, r0, c%d, c%d, %d", cpnum
,
89 (int) CRm
, (int) op2
);
91 /* read DCC into r0; then write coprocessor register from R0 */
92 retval
= dpm
->instr_write_data_r0(dpm
,
93 T32_FMTITR(ARMV4_5_MCR(cpnum
, op1
, 0, CRn
, CRm
, op2
)),
96 /* (void) */ dpm
->finish(dpm
);
100 static int dpmv8_mrs(struct target
*target
, uint32_t op0
,
101 uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
,
104 struct arm
*arm
= target_to_arm(target
);
105 struct arm_dpm
*dpm
= arm
->dpm
;
109 retval
= dpm
->prepare(dpm
);
110 if (retval
!= ERROR_OK
)
112 op_code
= ((op0
& 0x3) << 19 | (op1
& 0x7) << 16 | (CRn
& 0xF) << 12 |\
113 (CRm
& 0xF) << 8 | (op2
& 0x7) << 5);
115 LOG_DEBUG("MRS p%d, %d, r0, c%d, c%d, %d", (int)op0
,
116 (int) op1
, (int) CRn
,
117 (int) CRm
, (int) op2
);
118 /* read coprocessor register into R0; return via DCC */
119 retval
= dpm
->instr_read_data_r0(dpm
,
120 ARMV8_MRS(op_code
, 0),
123 /* (void) */ dpm
->finish(dpm
);
127 static int dpmv8_msr(struct target
*target
, uint32_t op0
,
128 uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
,
131 struct arm
*arm
= target_to_arm(target
);
132 struct arm_dpm
*dpm
= arm
->dpm
;
136 retval
= dpm
->prepare(dpm
);
137 if (retval
!= ERROR_OK
)
140 op_code
= ((op0
& 0x3) << 19 | (op1
& 0x7) << 16 | (CRn
& 0xF) << 12 |\
141 (CRm
& 0xF) << 8 | (op2
& 0x7) << 5);
143 LOG_DEBUG("MSR p%d, %d, r0, c%d, c%d, %d", (int)op0
,
144 (int) op1
, (int) CRn
,
145 (int) CRm
, (int) op2
);
147 /* read DCC into r0; then write coprocessor register from R0 */
148 retval
= dpm
->instr_write_data_r0(dpm
,
149 ARMV8_MSR_GP(op_code
, 0),
152 /* (void) */ dpm
->finish(dpm
);
156 /*----------------------------------------------------------------------*/
159 * Register access utilities
162 /* Toggles between recorded core mode (USR, SVC, etc) and a temporary one.
163 * Routines *must* restore the original mode before returning!!
165 int dpmv8_modeswitch(struct arm_dpm
*dpm
, enum arm_mode mode
)
170 /* restore previous mode */
171 if (mode
== ARM_MODE_ANY
)
172 cpsr
= buf_get_u32(dpm
->arm
->cpsr
->value
, 0, 32);
174 /* else force to the specified mode */
178 switch ((cpsr
& 0xC) >> 2) {
179 case SYSTEM_CUREL_EL1
:
180 retval
= dpm
->instr_execute(dpm
, ARMV8_DCPS1(11));
181 if (retval
!= ERROR_OK
)
184 case SYSTEM_CUREL_EL2
:
185 retval
= dpm
->instr_execute(dpm
, ARMV8_DCPS2(11));
186 if (retval
!= ERROR_OK
)
190 case SYSTEM_CUREL_EL3
:
191 retval
= dpm
->instr_execute(dpm
, ARMV8_DCPS3(11));
192 if (retval
!= ERROR_OK
)
197 LOG_DEBUG("unknow mode 0x%x", (unsigned) ((cpsr
& 0xC) >> 2));
202 retval
= dpm
->instr_write_data_r0(dpm
, ARMV8_MSR_DSPSR(0), cpsr
);
203 if (retval
!= ERROR_OK
)
206 if (dpm
->instr_cpsr_sync
)
207 retval
= dpm
->instr_cpsr_sync(dpm
);
212 /* just read the register -- rely on the core mode being right */
213 static int dpmv8_read_reg(struct arm_dpm
*dpm
, struct reg
*r
, unsigned regnum
)
217 int retval
= ERROR_FAIL
;
221 retval
= dpm
->instr_read_data_dcc_64(dpm
,
222 ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0
, regnum
),
226 retval
= dpm
->instr_read_data_r0_64(dpm
,
231 retval
= dpm
->instr_read_data_r0_64(dpm
,
236 retval
= dpm
->instr_read_data_r0(dpm
,
240 LOG_DEBUG("READ: %s fail", r
->name
);
244 if (retval
== ERROR_OK
) {
247 buf_set_u64(r
->value
, 0, 32, value_64
);
249 LOG_DEBUG("READ: %s, %16.8llx", r
->name
, (unsigned long long) value_64
);
251 LOG_DEBUG("READ: %s, %8.8x", r
->name
, (unsigned) value
);
256 /* just write the register -- rely on the core mode being right */
257 static int dpmv8_write_reg(struct arm_dpm
*dpm
, struct reg
*r
, unsigned regnum
)
259 int retval
= ERROR_FAIL
;
260 uint32_t value
= 0xFFFFFFFF;
261 uint64_t value_64
= 0xFFFFFFFFFFFFFFFF;
265 value_64
= buf_get_u64(r
->value
, 0, 64);
266 retval
= dpm
->instr_write_data_dcc_64(dpm
,
267 ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0
, regnum
),
271 value_64
= buf_get_u64(r
->value
, 0, 64);
272 retval
= dpm
->instr_write_data_r0_64(dpm
,
277 value_64
= buf_get_u64(r
->value
, 0, 64);
278 retval
= dpm
->instr_write_data_r0_64(dpm
,
283 value
= buf_get_u32(r
->value
, 0, 32);
284 retval
= dpm
->instr_write_data_r0(dpm
,
288 LOG_DEBUG("write: %s fail", r
->name
);
293 if (retval
== ERROR_OK
) {
296 LOG_DEBUG("WRITE: %s, %16.8llx", r
->name
, (unsigned long long) value_64
);
298 LOG_DEBUG("WRITE: %s, %8.8x", r
->name
, (unsigned) value
);
305 * Read basic registers of the the current context: R0 to R15, and CPSR;
306 * sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb).
307 * In normal operation this is called on entry to halting debug state,
308 * possibly after some other operations supporting restore of debug state
309 * or making sure the CPU is fully idle (drain write buffer, etc).
311 int armv8_dpm_read_current_registers(struct arm_dpm
*dpm
)
313 struct arm
*arm
= dpm
->arm
;
318 retval
= dpm
->prepare(dpm
);
319 if (retval
!= ERROR_OK
)
322 /* read R0 first (it's used for scratch), then CPSR */
323 r
= arm
->core_cache
->reg_list
+ 0;
325 retval
= dpmv8_read_reg(dpm
, r
, 0);
326 if (retval
!= ERROR_OK
)
330 /* read cpsr to r0 and get it back */
331 retval
= dpm
->instr_read_data_r0(dpm
, ARMV8_MRS_DSPSR(0), &cpsr
);
332 if (retval
!= ERROR_OK
)
335 /* update core mode and state, plus shadow mapping for R8..R14 */
336 armv8_set_cpsr(arm
, cpsr
);
338 /* REVISIT we can probably avoid reading R1..R14, saving time... */
339 for (unsigned i
= 1; i
< arm
->core_cache
->num_regs
; i
++) {
340 r
= armv8_reg_current(arm
, i
);
344 retval
= dpmv8_read_reg(dpm
, r
, i
);
345 if (retval
!= ERROR_OK
)
349 /* NOTE: SPSR ignored (if it's even relevant). */
351 /* REVISIT the debugger can trigger various exceptions. See the
352 * ARMv7A architecture spec, section C5.7, for more info about
353 * what defenses are needed; v6 debug has the most issues.
357 /* (void) */ dpm
->finish(dpm
);
361 /* Avoid needless I/O ... leave breakpoints and watchpoints alone
362 * unless they're removed, or need updating because of single-stepping
363 * or running debugger code.
365 static int dpmv8_maybe_update_bpwp(struct arm_dpm
*dpm
, bool bpwp
,
366 struct dpm_bpwp
*xp
, int *set_p
)
368 int retval
= ERROR_OK
;
375 /* removed or startup; we must disable it */
380 /* disabled, but we must set it */
381 xp
->dirty
= disable
= false;
386 /* set, but we must temporarily disable it */
387 xp
->dirty
= disable
= true;
392 retval
= dpm
->bpwp_disable(dpm
, xp
->number
);
394 retval
= dpm
->bpwp_enable(dpm
, xp
->number
,
395 xp
->address
, xp
->control
);
397 if (retval
!= ERROR_OK
)
398 LOG_ERROR("%s: can't %s HW %spoint %d",
399 disable
? "disable" : "enable",
400 target_name(dpm
->arm
->target
),
401 (xp
->number
< 16) ? "break" : "watch",
407 static int dpmv8_add_breakpoint(struct target
*target
, struct breakpoint
*bp
);
410 * Writes all modified core registers for all processor modes. In normal
411 * operation this is called on exit from halting debug state.
413 * @param dpm: represents the processor
414 * @param bpwp: true ensures breakpoints and watchpoints are set,
415 * false ensures they are cleared
417 int armv8_dpm_write_dirty_registers(struct arm_dpm
*dpm
, bool bpwp
)
419 struct arm
*arm
= dpm
->arm
;
420 struct reg_cache
*cache
= arm
->core_cache
;
423 retval
= dpm
->prepare(dpm
);
424 if (retval
!= ERROR_OK
)
427 /* If we're managing hardware breakpoints for this core, enable
428 * or disable them as requested.
430 * REVISIT We don't yet manage them for ANY cores. Eventually
431 * we should be able to assume we handle them; but until then,
432 * cope with the hand-crafted breakpoint code.
434 if (arm
->target
->type
->add_breakpoint
== dpmv8_add_breakpoint
) {
435 for (unsigned i
= 0; i
< dpm
->nbp
; i
++) {
436 struct dpm_bp
*dbp
= dpm
->dbp
+ i
;
437 struct breakpoint
*bp
= dbp
->bp
;
439 retval
= dpmv8_maybe_update_bpwp(dpm
, bpwp
, &dbp
->bpwp
,
440 bp
? &bp
->set
: NULL
);
441 if (retval
!= ERROR_OK
)
446 /* enable/disable watchpoints */
447 for (unsigned i
= 0; i
< dpm
->nwp
; i
++) {
448 struct dpm_wp
*dwp
= dpm
->dwp
+ i
;
449 struct watchpoint
*wp
= dwp
->wp
;
451 retval
= dpmv8_maybe_update_bpwp(dpm
, bpwp
, &dwp
->bpwp
,
452 wp
? &wp
->set
: NULL
);
453 if (retval
!= ERROR_OK
)
457 /* NOTE: writes to breakpoint and watchpoint registers might
458 * be queued, and need (efficient/batched) flushing later.
461 /* Scan the registers until we find one that's both dirty and
462 * eligible for flushing. Flush that and everything else that
463 * shares the same core mode setting. Typically this won't
464 * actually find anything to do...
467 /* check everything except our scratch register R0 */
468 for (unsigned i
= 1; i
< cache
->num_regs
; i
++) {
472 /* also skip PC, CPSR, and non-dirty */
473 if (i
== (arm
->core_cache
->num_regs
- 2))
475 if (arm
->cpsr
== cache
->reg_list
+ i
)
477 if (!cache
->reg_list
[i
].dirty
)
480 r
= cache
->reg_list
[i
].arch_info
;
483 retval
= dpmv8_write_reg(dpm
,
486 if (retval
!= ERROR_OK
)
491 /* Restore original CPSR ... assuming either that we changed it,
492 * or it's dirty. Must write PC to ensure the return address is
493 * defined, and must not write it before CPSR.
495 retval
= dpmv8_modeswitch(dpm
, ARM_MODE_ANY
);
496 if (retval
!= ERROR_OK
)
498 arm
->cpsr
->dirty
= false;
500 retval
= dpmv8_write_reg(dpm
, arm
->pc
, (arm
->core_cache
->num_regs
- 2));
501 if (retval
!= ERROR_OK
)
503 arm
->pc
->dirty
= false;
505 /* flush R0 -- it's *very* dirty by now */
506 retval
= dpmv8_write_reg(dpm
, &cache
->reg_list
[0], 0);
507 if (retval
!= ERROR_OK
)
509 cache
->reg_list
[0].dirty
= false;
511 /* (void) */ dpm
->finish(dpm
);
517 * Standard ARM register accessors ... there are three methods
518 * in "struct arm", to support individual read/write and bulk read
522 static int armv8_dpm_read_core_reg(struct target
*target
, struct reg
*r
,
523 int regnum
, enum arm_mode mode
)
525 struct arm
*arm
= target_to_arm(target
);
526 struct arm_dpm
*dpm
= target_to_arm(target
)->dpm
;
528 int max
= arm
->core_cache
->num_regs
;
530 if (regnum
< 0 || regnum
> max
)
531 return ERROR_COMMAND_SYNTAX_ERROR
;
533 /* REVISIT what happens if we try to read SPSR in a core mode
534 * which has no such register?
537 retval
= dpm
->prepare(dpm
);
538 if (retval
!= ERROR_OK
)
541 retval
= dpmv8_read_reg(dpm
, r
, regnum
);
542 if (retval
!= ERROR_OK
)
546 /* (void) */ dpm
->finish(dpm
);
550 static int armv8_dpm_write_core_reg(struct target
*target
, struct reg
*r
,
551 int regnum
, enum arm_mode mode
, uint8_t *value
)
553 struct arm
*arm
= target_to_arm(target
);
554 struct arm_dpm
*dpm
= target_to_arm(target
)->dpm
;
556 int max
= arm
->core_cache
->num_regs
;
558 if (regnum
< 0 || regnum
> max
)
559 return ERROR_COMMAND_SYNTAX_ERROR
;
561 /* REVISIT what happens if we try to write SPSR in a core mode
562 * which has no such register?
565 retval
= dpm
->prepare(dpm
);
566 if (retval
!= ERROR_OK
)
569 retval
= dpmv8_write_reg(dpm
, r
, regnum
);
570 /* always clean up, regardless of error */
572 /* (void) */ dpm
->finish(dpm
);
576 static int armv8_dpm_full_context(struct target
*target
)
578 struct arm
*arm
= target_to_arm(target
);
579 struct arm_dpm
*dpm
= arm
->dpm
;
580 struct reg_cache
*cache
= arm
->core_cache
;
584 retval
= dpm
->prepare(dpm
);
585 if (retval
!= ERROR_OK
)
589 enum arm_mode mode
= ARM_MODE_ANY
;
593 /* We "know" arm_dpm_read_current_registers() was called so
594 * the unmapped registers (R0..R7, PC, AND CPSR) and some
595 * view of R8..R14 are current. We also "know" oddities of
596 * register mapping: special cases for R8..R12 and SPSR.
598 * Pick some mode with unread registers and read them all.
601 for (unsigned i
= 0; i
< cache
->num_regs
; i
++) {
604 if (cache
->reg_list
[i
].valid
)
606 r
= cache
->reg_list
[i
].arch_info
;
608 /* may need to pick a mode and set CPSR */
613 /* For regular (ARM_MODE_ANY) R8..R12
614 * in case we've entered debug state
615 * in FIQ mode we need to patch mode.
617 if (mode
!= ARM_MODE_ANY
)
618 retval
= dpmv8_modeswitch(dpm
, mode
);
620 retval
= dpmv8_modeswitch(dpm
, ARM_MODE_USR
);
622 if (retval
!= ERROR_OK
)
628 /* CPSR was read, so "R16" must mean SPSR */
629 retval
= dpmv8_read_reg(dpm
,
631 (r
->num
== 16) ? 17 : r
->num
);
632 if (retval
!= ERROR_OK
)
638 retval
= dpmv8_modeswitch(dpm
, ARM_MODE_ANY
);
639 /* (void) */ dpm
->finish(dpm
);
645 /*----------------------------------------------------------------------*/
648 * Breakpoint and Watchpoint support.
650 * Hardware {break,watch}points are usually left active, to minimize
651 * debug entry/exit costs. When they are set or cleared, it's done in
652 * batches. Also, DPM-conformant hardware can update debug registers
653 * regardless of whether the CPU is running or halted ... though that
654 * fact isn't currently leveraged.
657 static int dpmv8_bpwp_setup(struct arm_dpm
*dpm
, struct dpm_bpwp
*xp
,
658 uint32_t addr
, uint32_t length
)
662 control
= (1 << 0) /* enable */
663 | (3 << 1); /* both user and privileged access */
665 /* Match 1, 2, or all 4 byte addresses in this word.
667 * FIXME: v7 hardware allows lengths up to 2 GB for BP and WP.
668 * Support larger length, when addr is suitably aligned. In
669 * particular, allow watchpoints on 8 byte "double" values.
671 * REVISIT allow watchpoints on unaligned 2-bit values; and on
672 * v7 hardware, unaligned 4-byte ones too.
676 control
|= (1 << (addr
& 3)) << 5;
679 /* require 2-byte alignment */
681 control
|= (3 << (addr
& 2)) << 5;
686 /* require 4-byte alignment */
693 LOG_ERROR("unsupported {break,watch}point length/alignment");
694 return ERROR_COMMAND_SYNTAX_ERROR
;
697 /* other shared control bits:
698 * bits 15:14 == 0 ... both secure and nonsecure states (v6.1+ only)
699 * bit 20 == 0 ... not linked to a context ID
700 * bit 28:24 == 0 ... not ignoring N LSBs (v7 only)
703 xp
->address
= addr
& ~3;
704 xp
->control
= control
;
707 LOG_DEBUG("BPWP: addr %8.8" PRIx32
", control %" PRIx32
", number %d",
708 xp
->address
, control
, xp
->number
);
710 /* hardware is updated in write_dirty_registers() */
714 static int dpmv8_add_breakpoint(struct target
*target
, struct breakpoint
*bp
)
716 struct arm
*arm
= target_to_arm(target
);
717 struct arm_dpm
*dpm
= arm
->dpm
;
718 int retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
721 return ERROR_COMMAND_SYNTAX_ERROR
;
722 if (!dpm
->bpwp_enable
)
725 /* FIXME we need a generic solution for software breakpoints. */
726 if (bp
->type
== BKPT_SOFT
)
727 LOG_DEBUG("using HW bkpt, not SW...");
729 for (unsigned i
= 0; i
< dpm
->nbp
; i
++) {
730 if (!dpm
->dbp
[i
].bp
) {
731 retval
= dpmv8_bpwp_setup(dpm
, &dpm
->dbp
[i
].bpwp
,
732 bp
->address
, bp
->length
);
733 if (retval
== ERROR_OK
)
742 static int dpmv8_remove_breakpoint(struct target
*target
, struct breakpoint
*bp
)
744 struct arm
*arm
= target_to_arm(target
);
745 struct arm_dpm
*dpm
= arm
->dpm
;
746 int retval
= ERROR_COMMAND_SYNTAX_ERROR
;
748 for (unsigned i
= 0; i
< dpm
->nbp
; i
++) {
749 if (dpm
->dbp
[i
].bp
== bp
) {
750 dpm
->dbp
[i
].bp
= NULL
;
751 dpm
->dbp
[i
].bpwp
.dirty
= true;
753 /* hardware is updated in write_dirty_registers() */
762 static int dpmv8_watchpoint_setup(struct arm_dpm
*dpm
, unsigned index_t
,
763 struct watchpoint
*wp
)
766 struct dpm_wp
*dwp
= dpm
->dwp
+ index_t
;
769 /* this hardware doesn't support data value matching or masking */
770 if (wp
->value
|| wp
->mask
!= ~(uint32_t)0) {
771 LOG_DEBUG("watchpoint values and masking not supported");
772 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
775 retval
= dpmv8_bpwp_setup(dpm
, &dwp
->bpwp
, wp
->address
, wp
->length
);
776 if (retval
!= ERROR_OK
)
779 control
= dwp
->bpwp
.control
;
791 dwp
->bpwp
.control
= control
;
793 dpm
->dwp
[index_t
].wp
= wp
;
798 static int dpmv8_add_watchpoint(struct target
*target
, struct watchpoint
*wp
)
800 struct arm
*arm
= target_to_arm(target
);
801 struct arm_dpm
*dpm
= arm
->dpm
;
802 int retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
804 if (dpm
->bpwp_enable
) {
805 for (unsigned i
= 0; i
< dpm
->nwp
; i
++) {
806 if (!dpm
->dwp
[i
].wp
) {
807 retval
= dpmv8_watchpoint_setup(dpm
, i
, wp
);
816 static int dpmv8_remove_watchpoint(struct target
*target
, struct watchpoint
*wp
)
818 struct arm
*arm
= target_to_arm(target
);
819 struct arm_dpm
*dpm
= arm
->dpm
;
820 int retval
= ERROR_COMMAND_SYNTAX_ERROR
;
822 for (unsigned i
= 0; i
< dpm
->nwp
; i
++) {
823 if (dpm
->dwp
[i
].wp
== wp
) {
824 dpm
->dwp
[i
].wp
= NULL
;
825 dpm
->dwp
[i
].bpwp
.dirty
= true;
827 /* hardware is updated in write_dirty_registers() */
836 void armv8_dpm_report_wfar(struct arm_dpm
*dpm
, uint64_t addr
)
838 switch (dpm
->arm
->core_state
) {
840 case ARM_STATE_AARCH64
:
843 case ARM_STATE_THUMB
:
844 case ARM_STATE_THUMB_EE
:
847 case ARM_STATE_JAZELLE
:
851 LOG_DEBUG("Unknow core_state");
857 /*----------------------------------------------------------------------*/
860 * Other debug and support utilities
863 void armv8_dpm_report_dscr(struct arm_dpm
*dpm
, uint32_t dscr
)
865 struct target
*target
= dpm
->arm
->target
;
869 /* Examine debug reason */
870 switch (DSCR_ENTRY(dscr
)) {
871 /* FALL THROUGH -- assume a v6 core in abort mode */
872 case DSCRV8_ENTRY_HLT
: /* HALT request from debugger */
873 case DSCRV8_ENTRY_EXT_DEBUG
: /* EDBGRQ */
874 target
->debug_reason
= DBG_REASON_DBGRQ
;
876 case DSCRV8_ENTRY_HALT_STEP_EXECLU
: /* HALT step */
877 case DSCRV8_ENTRY_HALT_STEP_NORMAL
: /* Halt step*/
878 case DSCRV8_ENTRY_HALT_STEP
:
879 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
881 case DSCRV8_ENTRY_BKPT
: /* SW BKPT */
882 case DSCRV8_ENTRY_RESET_CATCH
: /* Reset catch */
883 case DSCRV8_ENTRY_OS_UNLOCK
: /*OS unlock catch*/
884 case DSCRV8_ENTRY_EXCEPTION_CATCH
: /*exception catch*/
885 case DSCRV8_ENTRY_SW_ACCESS_DBG
: /*SW access dbg register*/
886 target
->debug_reason
= DBG_REASON_BREAKPOINT
;
888 case DSCRV8_ENTRY_WATCHPOINT
: /* asynch watchpoint */
889 target
->debug_reason
= DBG_REASON_WATCHPOINT
;
892 target
->debug_reason
= DBG_REASON_UNDEFINED
;
898 /*----------------------------------------------------------------------*/
901 * Setup and management support.
905 * Hooks up this DPM to its associated target; call only once.
906 * Initially this only covers the register cache.
908 * Oh, and watchpoints. Yeah.
910 int armv8_dpm_setup(struct arm_dpm
*dpm
)
912 struct arm
*arm
= dpm
->arm
;
913 struct target
*target
= arm
->target
;
914 struct reg_cache
*cache
;
917 /* register access setup */
918 arm
->full_context
= armv8_dpm_full_context
;
919 arm
->read_core_reg
= armv8_dpm_read_core_reg
;
920 arm
->write_core_reg
= armv8_dpm_write_core_reg
;
922 if (arm
->core_cache
== NULL
) {
923 cache
= armv8_build_reg_cache(target
);
928 /* coprocessor access setup */
929 arm
->mrc
= dpmv8_mrc
;
930 arm
->mcr
= dpmv8_mcr
;
931 arm
->mrs
= dpmv8_mrs
;
932 arm
->msr
= dpmv8_msr
;
933 /* breakpoint setup -- optional until it works everywhere */
934 if (!target
->type
->add_breakpoint
) {
935 target
->type
->add_breakpoint
= dpmv8_add_breakpoint
;
936 target
->type
->remove_breakpoint
= dpmv8_remove_breakpoint
;
939 /* watchpoint setup */
940 target
->type
->add_watchpoint
= dpmv8_add_watchpoint
;
941 target
->type
->remove_watchpoint
= dpmv8_remove_watchpoint
;
943 /* FIXME add vector catch support */
945 dpm
->nbp
= 1 + ((dpm
->didr
>> 12) & 0xf);
946 dpm
->dbp
= calloc(dpm
->nbp
, sizeof *dpm
->dbp
);
948 dpm
->nwp
= 1 + ((dpm
->didr
>> 20) & 0xf);
949 dpm
->dwp
= calloc(dpm
->nwp
, sizeof *dpm
->dwp
);
951 if (!dpm
->dbp
|| !dpm
->dwp
) {
957 LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
958 target_name(target
), dpm
->nbp
, dpm
->nwp
);
960 /* REVISIT ... and some of those breakpoints could match
961 * execution context IDs...
968 * Reinitializes DPM state at the beginning of a new debug session
969 * or after a reset which may have affected the debug module.
971 int armv8_dpm_initialize(struct arm_dpm
*dpm
)
973 /* Disable all breakpoints and watchpoints at startup. */
974 if (dpm
->bpwp_disable
) {
977 for (i
= 0; i
< dpm
->nbp
; i
++) {
978 dpm
->dbp
[i
].bpwp
.number
= i
;
979 (void) dpm
->bpwp_disable(dpm
, i
);
981 for (i
= 0; i
< dpm
->nwp
; i
++) {
982 dpm
->dwp
[i
].bpwp
.number
= 16 + i
;
983 (void) dpm
->bpwp_disable(dpm
, 16 + i
);
986 LOG_WARNING("%s: can't disable breakpoints and watchpoints",
987 target_name(dpm
->arm
->target
));
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)