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
)
167 struct armv8_common
*armv8
= (struct armv8_common
*)dpm
->arm
->arch_info
;
171 /* restore previous mode */
172 if (mode
== ARM_MODE_ANY
)
173 cpsr
= buf_get_u32(dpm
->arm
->cpsr
->value
, 0, 32);
175 /* else force to the specified mode */
179 switch ((cpsr
& 0xC) >> 2) {
180 case SYSTEM_CUREL_EL1
:
181 retval
= dpm
->instr_execute(dpm
, ARMV8_DCPS1(11));
182 if (retval
!= ERROR_OK
)
185 case SYSTEM_CUREL_EL2
:
186 retval
= dpm
->instr_execute(dpm
, ARMV8_DCPS2(11));
187 if (retval
!= ERROR_OK
)
191 case SYSTEM_CUREL_EL3
:
192 retval
= dpm
->instr_execute(dpm
, ARMV8_DCPS3(11));
193 if (retval
!= ERROR_OK
)
198 LOG_DEBUG("unknow mode 0x%x", (unsigned) ((cpsr
& 0xC) >> 2));
203 retval
= dpm
->instr_write_data_r0(dpm
, armv8_opcode(armv8
, WRITE_REG_DSPSR
), cpsr
);
204 if (retval
!= ERROR_OK
)
207 if (dpm
->instr_cpsr_sync
)
208 retval
= dpm
->instr_cpsr_sync(dpm
);
213 static int dpmv8_read_reg32(struct arm_dpm
*dpm
, struct reg
*r
, unsigned regnum
)
216 int retval
= ERROR_FAIL
;
221 /* return via DCC: "MCR p14, 0, Rnum, c0, c5, 0" */
222 retval
= dpm
->instr_read_data_dcc(dpm
,
223 T32_FMTITR(ARMV4_5_MCR(14, 0, regnum
, 0, 5, 0)),
227 retval
= dpm
->instr_read_data_dcc(dpm
,
228 T32_FMTITR(ARMV4_5_MCR(14, 0, 13, 0, 5, 0)),
232 retval
= dpm
->instr_read_data_r0(dpm
,
233 T32_FMTITR(ARMV8_MRC_DLR(0)),
237 retval
= dpm
->instr_read_data_r0(dpm
,
238 T32_FMTITR(ARMV8_MRC_DSPSR(0)),
242 LOG_DEBUG("READ: %s ignored", r
->name
);
249 if (retval
== ERROR_OK
) {
252 buf_set_u64(r
->value
, 0, 32, value
);
253 LOG_DEBUG("READ: %s, %8.8x", r
->name
, (unsigned) value
);
258 static int dpmv8_write_reg32(struct arm_dpm
*dpm
, struct reg
*r
, unsigned regnum
)
261 uint64_t value
= buf_get_u64(r
->value
, 0, 32);
265 /* load register from DCC: "MRC p14, 0, Rnum, c0, c5, 0" */
266 retval
= dpm
->instr_write_data_dcc(dpm
,
267 T32_FMTITR(ARMV4_5_MRC(14, 0, regnum
, 0, 5, 0)), value
);
270 * read r0 from DCC; then "MOV pc, r0" */
271 retval
= dpm
->instr_write_data_r0(dpm
,
272 T32_FMTITR(ARMV8_MCR_DLR(0)), value
);
274 case ARMV8_xPSR
: /* CPSR */
275 /* read r0 from DCC, then "MCR r0, DSPSR" */
276 retval
= dpm
->instr_write_data_r0(dpm
,
277 T32_FMTITR(ARMV8_MCR_DSPSR(0)), value
);
281 LOG_DEBUG("WRITE: %s ignored", r
->name
);
285 if (retval
== ERROR_OK
) {
287 LOG_DEBUG("WRITE: %s, %8.8x", r
->name
, (unsigned) value
);
293 /* just read the register -- rely on the core mode being right */
294 static int dpmv8_read_reg(struct arm_dpm
*dpm
, struct reg
*r
, unsigned regnum
)
298 int retval
= ERROR_FAIL
;
302 retval
= dpm
->instr_read_data_dcc_64(dpm
,
303 ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0
, regnum
),
307 retval
= dpm
->instr_read_data_r0_64(dpm
,
312 retval
= dpm
->instr_read_data_r0_64(dpm
,
317 retval
= dpm
->instr_read_data_r0(dpm
,
322 LOG_DEBUG("READ: %s fail", r
->name
);
326 if (retval
== ERROR_OK
) {
330 buf_set_u64(r
->value
, 0, 64, value_64
);
331 LOG_DEBUG("READ: %s, %16.8llx", r
->name
, (unsigned long long) value_64
);
333 buf_set_u32(r
->value
, 0, 32, value
);
334 LOG_DEBUG("READ: %s, %8.8x", r
->name
, (unsigned) value
);
340 /* just write the register -- rely on the core mode being right */
341 static int dpmv8_write_reg(struct arm_dpm
*dpm
, struct reg
*r
, unsigned regnum
)
343 int retval
= ERROR_FAIL
;
344 uint32_t value
= 0xFFFFFFFF;
345 uint64_t value_64
= 0xFFFFFFFFFFFFFFFF;
349 value_64
= buf_get_u64(r
->value
, 0, 64);
350 retval
= dpm
->instr_write_data_dcc_64(dpm
,
351 ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0
, regnum
),
355 value_64
= buf_get_u64(r
->value
, 0, 64);
356 retval
= dpm
->instr_write_data_r0_64(dpm
,
361 value_64
= buf_get_u64(r
->value
, 0, 64);
362 retval
= dpm
->instr_write_data_r0_64(dpm
,
367 value
= buf_get_u32(r
->value
, 0, 32);
368 retval
= dpm
->instr_write_data_r0(dpm
,
373 LOG_DEBUG("write: %s fail", r
->name
);
378 if (retval
== ERROR_OK
) {
381 LOG_DEBUG("WRITE: %s, %16.8llx", r
->name
, (unsigned long long) value_64
);
383 LOG_DEBUG("WRITE: %s, %8.8x", r
->name
, (unsigned) value
);
389 static inline enum arm_state
dpm_get_core_state(uint32_t dscr
)
391 int el
= (dscr
>> 8) & 0x3;
392 int rw
= (dscr
>> 10) & 0xF;
394 LOG_DEBUG("EL:%i, RW:0x%x", el
, rw
);
396 /* DSCR.RW = 0b1111 - all EL are using AArch64 state */
398 return ARM_STATE_AARCH64
;
400 /* DSCR.RW = 0b1110 - all EL > 0 are using AArch64 state */
401 if (rw
== 0xE && el
> 0)
402 return ARM_STATE_AARCH64
;
404 /* DSCR.RW = 0b110x - all EL > 1 are using Aarch64 state */
405 if ((rw
& 0xE) == 0xC && el
> 1)
406 return ARM_STATE_AARCH64
;
408 /* DSCR.RW = 0b10xx - all EL > 2 are using Aarch64 state */
409 if ((rw
& 0xC) == 0x8 && el
> 2)
410 return ARM_STATE_AARCH64
;
412 /* DSCR.RW = 0b0xxx - all EL are using AArch32 state */
414 return ARM_STATE_ARM
;
416 return ARM_STATE_ARM
;
420 * Read basic registers of the the current context: R0 to R15, and CPSR;
421 * sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb).
422 * In normal operation this is called on entry to halting debug state,
423 * possibly after some other operations supporting restore of debug state
424 * or making sure the CPU is fully idle (drain write buffer, etc).
426 int armv8_dpm_read_current_registers(struct arm_dpm
*dpm
)
428 struct arm
*arm
= dpm
->arm
;
429 struct armv8_common
*armv8
= (struct armv8_common
*)arm
->arch_info
;
430 enum arm_state core_state
;
436 retval
= dpm
->prepare(dpm
);
437 if (retval
!= ERROR_OK
)
440 core_state
= dpm_get_core_state(dpm
->dscr
);
442 armv8_select_opcodes(armv8
, core_state
);
444 /* read R0 first (it's used for scratch), then CPSR */
445 r
= arm
->core_cache
->reg_list
+ 0;
447 retval
= core_state
== ARM_STATE_AARCH64
?
448 dpmv8_read_reg(dpm
, r
, 0) : dpmv8_read_reg32(dpm
, r
, 0);
449 if (retval
!= ERROR_OK
)
454 /* read cpsr to r0 and get it back */
455 retval
= dpm
->instr_read_data_r0(dpm
, armv8_opcode(armv8
, READ_REG_DSPSR
), &cpsr
);
456 if (retval
!= ERROR_OK
)
459 /* update core mode and state, plus shadow mapping for R8..R14 */
460 armv8_set_cpsr(arm
, cpsr
);
462 /* REVISIT we can probably avoid reading R1..R14, saving time... */
463 for (unsigned i
= 1; i
< arm
->core_cache
->num_regs
; i
++) {
464 r
= armv8_reg_current(arm
, i
);
468 retval
= core_state
== ARM_STATE_AARCH64
?
469 dpmv8_read_reg(dpm
, r
, i
) : dpmv8_read_reg32(dpm
, r
, i
);
471 if (retval
!= ERROR_OK
)
475 /* NOTE: SPSR ignored (if it's even relevant). */
477 /* REVISIT the debugger can trigger various exceptions. See the
478 * ARMv7A architecture spec, section C5.7, for more info about
479 * what defenses are needed; v6 debug has the most issues.
483 /* (void) */ dpm
->finish(dpm
);
487 /* Avoid needless I/O ... leave breakpoints and watchpoints alone
488 * unless they're removed, or need updating because of single-stepping
489 * or running debugger code.
491 static int dpmv8_maybe_update_bpwp(struct arm_dpm
*dpm
, bool bpwp
,
492 struct dpm_bpwp
*xp
, int *set_p
)
494 int retval
= ERROR_OK
;
501 /* removed or startup; we must disable it */
506 /* disabled, but we must set it */
507 xp
->dirty
= disable
= false;
512 /* set, but we must temporarily disable it */
513 xp
->dirty
= disable
= true;
518 retval
= dpm
->bpwp_disable(dpm
, xp
->number
);
520 retval
= dpm
->bpwp_enable(dpm
, xp
->number
,
521 xp
->address
, xp
->control
);
523 if (retval
!= ERROR_OK
)
524 LOG_ERROR("%s: can't %s HW %spoint %d",
525 disable
? "disable" : "enable",
526 target_name(dpm
->arm
->target
),
527 (xp
->number
< 16) ? "break" : "watch",
533 static int dpmv8_add_breakpoint(struct target
*target
, struct breakpoint
*bp
);
536 * Writes all modified core registers for all processor modes. In normal
537 * operation this is called on exit from halting debug state.
539 * @param dpm: represents the processor
540 * @param bpwp: true ensures breakpoints and watchpoints are set,
541 * false ensures they are cleared
543 int armv8_dpm_write_dirty_registers(struct arm_dpm
*dpm
, bool bpwp
)
545 struct arm
*arm
= dpm
->arm
;
546 struct reg_cache
*cache
= arm
->core_cache
;
548 bool is_aarch64
= arm
->core_state
== ARM_STATE_AARCH64
;
550 retval
= dpm
->prepare(dpm
);
551 if (retval
!= ERROR_OK
)
554 /* If we're managing hardware breakpoints for this core, enable
555 * or disable them as requested.
557 * REVISIT We don't yet manage them for ANY cores. Eventually
558 * we should be able to assume we handle them; but until then,
559 * cope with the hand-crafted breakpoint code.
561 if (arm
->target
->type
->add_breakpoint
== dpmv8_add_breakpoint
) {
562 for (unsigned i
= 0; i
< dpm
->nbp
; i
++) {
563 struct dpm_bp
*dbp
= dpm
->dbp
+ i
;
564 struct breakpoint
*bp
= dbp
->bp
;
566 retval
= dpmv8_maybe_update_bpwp(dpm
, bpwp
, &dbp
->bpwp
,
567 bp
? &bp
->set
: NULL
);
568 if (retval
!= ERROR_OK
)
573 /* enable/disable watchpoints */
574 for (unsigned i
= 0; i
< dpm
->nwp
; i
++) {
575 struct dpm_wp
*dwp
= dpm
->dwp
+ i
;
576 struct watchpoint
*wp
= dwp
->wp
;
578 retval
= dpmv8_maybe_update_bpwp(dpm
, bpwp
, &dwp
->bpwp
,
579 wp
? &wp
->set
: NULL
);
580 if (retval
!= ERROR_OK
)
584 /* NOTE: writes to breakpoint and watchpoint registers might
585 * be queued, and need (efficient/batched) flushing later.
588 /* Scan the registers until we find one that's both dirty and
589 * eligible for flushing. Flush that and everything else that
590 * shares the same core mode setting. Typically this won't
591 * actually find anything to do...
594 /* check everything except our scratch register R0 */
595 for (unsigned i
= 1; i
< cache
->num_regs
; i
++) {
599 /* also skip PC, CPSR, and non-dirty */
600 if (i
== (arm
->core_cache
->num_regs
- 2))
602 if (arm
->cpsr
== cache
->reg_list
+ i
)
604 if (!cache
->reg_list
[i
].dirty
)
607 r
= cache
->reg_list
[i
].arch_info
;
610 retval
= is_aarch64
? dpmv8_write_reg(dpm
, &cache
->reg_list
[i
], regnum
)
611 : dpmv8_write_reg32(dpm
, &cache
->reg_list
[i
], regnum
);
612 if (retval
!= ERROR_OK
)
617 /* Restore original CPSR ... assuming either that we changed it,
618 * or it's dirty. Must write PC to ensure the return address is
619 * defined, and must not write it before CPSR.
621 retval
= dpmv8_modeswitch(dpm
, ARM_MODE_ANY
);
622 if (retval
!= ERROR_OK
)
624 arm
->cpsr
->dirty
= false;
626 retval
= is_aarch64
? dpmv8_write_reg(dpm
, arm
->pc
, (arm
->core_cache
->num_regs
- 2))
627 : dpmv8_write_reg32(dpm
, arm
->pc
, (arm
->core_cache
->num_regs
- 2));
628 if (retval
!= ERROR_OK
)
630 arm
->pc
->dirty
= false;
632 /* flush R0 -- it's *very* dirty by now */
633 retval
= is_aarch64
? dpmv8_write_reg(dpm
, &cache
->reg_list
[0], 0)
634 : dpmv8_write_reg32(dpm
, &cache
->reg_list
[0], 0);
635 if (retval
!= ERROR_OK
)
637 cache
->reg_list
[0].dirty
= false;
639 /* (void) */ dpm
->finish(dpm
);
645 * Standard ARM register accessors ... there are three methods
646 * in "struct arm", to support individual read/write and bulk read
650 static int armv8_dpm_read_core_reg(struct target
*target
, struct reg
*r
,
651 int regnum
, enum arm_mode mode
)
653 struct arm
*arm
= target_to_arm(target
);
654 struct arm_dpm
*dpm
= target_to_arm(target
)->dpm
;
656 int max
= arm
->core_cache
->num_regs
;
658 if (regnum
< 0 || regnum
> max
)
659 return ERROR_COMMAND_SYNTAX_ERROR
;
661 /* REVISIT what happens if we try to read SPSR in a core mode
662 * which has no such register?
665 retval
= dpm
->prepare(dpm
);
666 if (retval
!= ERROR_OK
)
669 retval
= arm
->core_state
== ARM_STATE_AARCH64
?
670 dpmv8_read_reg(dpm
, r
, regnum
) : dpmv8_read_reg32(dpm
, r
, regnum
);
671 if (retval
!= ERROR_OK
)
675 /* (void) */ dpm
->finish(dpm
);
679 static int armv8_dpm_write_core_reg(struct target
*target
, struct reg
*r
,
680 int regnum
, enum arm_mode mode
, uint8_t *value
)
682 struct arm
*arm
= target_to_arm(target
);
683 struct arm_dpm
*dpm
= target_to_arm(target
)->dpm
;
685 int max
= arm
->core_cache
->num_regs
;
687 if (regnum
< 0 || regnum
> max
)
688 return ERROR_COMMAND_SYNTAX_ERROR
;
690 /* REVISIT what happens if we try to write SPSR in a core mode
691 * which has no such register?
694 retval
= dpm
->prepare(dpm
);
695 if (retval
!= ERROR_OK
)
698 retval
= arm
->core_state
== ARM_STATE_AARCH64
?
699 dpmv8_write_reg(dpm
, r
, regnum
) : dpmv8_write_reg32(dpm
, r
, regnum
);
701 /* always clean up, regardless of error */
703 /* (void) */ dpm
->finish(dpm
);
707 static int armv8_dpm_full_context(struct target
*target
)
709 struct arm
*arm
= target_to_arm(target
);
710 struct arm_dpm
*dpm
= arm
->dpm
;
711 struct reg_cache
*cache
= arm
->core_cache
;
715 retval
= dpm
->prepare(dpm
);
716 if (retval
!= ERROR_OK
)
720 enum arm_mode mode
= ARM_MODE_ANY
;
724 /* We "know" arm_dpm_read_current_registers() was called so
725 * the unmapped registers (R0..R7, PC, AND CPSR) and some
726 * view of R8..R14 are current. We also "know" oddities of
727 * register mapping: special cases for R8..R12 and SPSR.
729 * Pick some mode with unread registers and read them all.
732 for (unsigned i
= 0; i
< cache
->num_regs
; i
++) {
735 if (cache
->reg_list
[i
].valid
)
737 r
= cache
->reg_list
[i
].arch_info
;
739 /* may need to pick a mode and set CPSR */
744 /* For regular (ARM_MODE_ANY) R8..R12
745 * in case we've entered debug state
746 * in FIQ mode we need to patch mode.
748 if (mode
!= ARM_MODE_ANY
)
749 retval
= dpmv8_modeswitch(dpm
, mode
);
751 retval
= dpmv8_modeswitch(dpm
, ARM_MODE_USR
);
753 if (retval
!= ERROR_OK
)
759 /* CPSR was read, so "R16" must mean SPSR */
760 retval
= dpmv8_read_reg(dpm
,
762 (r
->num
== 16) ? 17 : r
->num
);
763 if (retval
!= ERROR_OK
)
769 retval
= dpmv8_modeswitch(dpm
, ARM_MODE_ANY
);
770 /* (void) */ dpm
->finish(dpm
);
776 /*----------------------------------------------------------------------*/
779 * Breakpoint and Watchpoint support.
781 * Hardware {break,watch}points are usually left active, to minimize
782 * debug entry/exit costs. When they are set or cleared, it's done in
783 * batches. Also, DPM-conformant hardware can update debug registers
784 * regardless of whether the CPU is running or halted ... though that
785 * fact isn't currently leveraged.
788 static int dpmv8_bpwp_setup(struct arm_dpm
*dpm
, struct dpm_bpwp
*xp
,
789 uint32_t addr
, uint32_t length
)
793 control
= (1 << 0) /* enable */
794 | (3 << 1); /* both user and privileged access */
796 /* Match 1, 2, or all 4 byte addresses in this word.
798 * FIXME: v7 hardware allows lengths up to 2 GB for BP and WP.
799 * Support larger length, when addr is suitably aligned. In
800 * particular, allow watchpoints on 8 byte "double" values.
802 * REVISIT allow watchpoints on unaligned 2-bit values; and on
803 * v7 hardware, unaligned 4-byte ones too.
807 control
|= (1 << (addr
& 3)) << 5;
810 /* require 2-byte alignment */
812 control
|= (3 << (addr
& 2)) << 5;
817 /* require 4-byte alignment */
824 LOG_ERROR("unsupported {break,watch}point length/alignment");
825 return ERROR_COMMAND_SYNTAX_ERROR
;
828 /* other shared control bits:
829 * bits 15:14 == 0 ... both secure and nonsecure states (v6.1+ only)
830 * bit 20 == 0 ... not linked to a context ID
831 * bit 28:24 == 0 ... not ignoring N LSBs (v7 only)
834 xp
->address
= addr
& ~3;
835 xp
->control
= control
;
838 LOG_DEBUG("BPWP: addr %8.8" PRIx32
", control %" PRIx32
", number %d",
839 xp
->address
, control
, xp
->number
);
841 /* hardware is updated in write_dirty_registers() */
845 static int dpmv8_add_breakpoint(struct target
*target
, struct breakpoint
*bp
)
847 struct arm
*arm
= target_to_arm(target
);
848 struct arm_dpm
*dpm
= arm
->dpm
;
849 int retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
852 return ERROR_COMMAND_SYNTAX_ERROR
;
853 if (!dpm
->bpwp_enable
)
856 /* FIXME we need a generic solution for software breakpoints. */
857 if (bp
->type
== BKPT_SOFT
)
858 LOG_DEBUG("using HW bkpt, not SW...");
860 for (unsigned i
= 0; i
< dpm
->nbp
; i
++) {
861 if (!dpm
->dbp
[i
].bp
) {
862 retval
= dpmv8_bpwp_setup(dpm
, &dpm
->dbp
[i
].bpwp
,
863 bp
->address
, bp
->length
);
864 if (retval
== ERROR_OK
)
873 static int dpmv8_remove_breakpoint(struct target
*target
, struct breakpoint
*bp
)
875 struct arm
*arm
= target_to_arm(target
);
876 struct arm_dpm
*dpm
= arm
->dpm
;
877 int retval
= ERROR_COMMAND_SYNTAX_ERROR
;
879 for (unsigned i
= 0; i
< dpm
->nbp
; i
++) {
880 if (dpm
->dbp
[i
].bp
== bp
) {
881 dpm
->dbp
[i
].bp
= NULL
;
882 dpm
->dbp
[i
].bpwp
.dirty
= true;
884 /* hardware is updated in write_dirty_registers() */
893 static int dpmv8_watchpoint_setup(struct arm_dpm
*dpm
, unsigned index_t
,
894 struct watchpoint
*wp
)
897 struct dpm_wp
*dwp
= dpm
->dwp
+ index_t
;
900 /* this hardware doesn't support data value matching or masking */
901 if (wp
->value
|| wp
->mask
!= ~(uint32_t)0) {
902 LOG_DEBUG("watchpoint values and masking not supported");
903 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
906 retval
= dpmv8_bpwp_setup(dpm
, &dwp
->bpwp
, wp
->address
, wp
->length
);
907 if (retval
!= ERROR_OK
)
910 control
= dwp
->bpwp
.control
;
922 dwp
->bpwp
.control
= control
;
924 dpm
->dwp
[index_t
].wp
= wp
;
929 static int dpmv8_add_watchpoint(struct target
*target
, struct watchpoint
*wp
)
931 struct arm
*arm
= target_to_arm(target
);
932 struct arm_dpm
*dpm
= arm
->dpm
;
933 int retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
935 if (dpm
->bpwp_enable
) {
936 for (unsigned i
= 0; i
< dpm
->nwp
; i
++) {
937 if (!dpm
->dwp
[i
].wp
) {
938 retval
= dpmv8_watchpoint_setup(dpm
, i
, wp
);
947 static int dpmv8_remove_watchpoint(struct target
*target
, struct watchpoint
*wp
)
949 struct arm
*arm
= target_to_arm(target
);
950 struct arm_dpm
*dpm
= arm
->dpm
;
951 int retval
= ERROR_COMMAND_SYNTAX_ERROR
;
953 for (unsigned i
= 0; i
< dpm
->nwp
; i
++) {
954 if (dpm
->dwp
[i
].wp
== wp
) {
955 dpm
->dwp
[i
].wp
= NULL
;
956 dpm
->dwp
[i
].bpwp
.dirty
= true;
958 /* hardware is updated in write_dirty_registers() */
967 void armv8_dpm_report_wfar(struct arm_dpm
*dpm
, uint64_t addr
)
969 switch (dpm
->arm
->core_state
) {
971 case ARM_STATE_AARCH64
:
974 case ARM_STATE_THUMB
:
975 case ARM_STATE_THUMB_EE
:
978 case ARM_STATE_JAZELLE
:
982 LOG_DEBUG("Unknow core_state");
988 /*----------------------------------------------------------------------*/
991 * Other debug and support utilities
994 void armv8_dpm_report_dscr(struct arm_dpm
*dpm
, uint32_t dscr
)
996 struct target
*target
= dpm
->arm
->target
;
1000 /* Examine debug reason */
1001 switch (DSCR_ENTRY(dscr
)) {
1002 /* FALL THROUGH -- assume a v6 core in abort mode */
1003 case DSCRV8_ENTRY_EXT_DEBUG
: /* EDBGRQ */
1004 target
->debug_reason
= DBG_REASON_DBGRQ
;
1006 case DSCRV8_ENTRY_HALT_STEP_EXECLU
: /* HALT step */
1007 case DSCRV8_ENTRY_HALT_STEP_NORMAL
: /* Halt step*/
1008 case DSCRV8_ENTRY_HALT_STEP
:
1009 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
1011 case DSCRV8_ENTRY_HLT
: /* HLT instruction (software breakpoint) */
1012 case DSCRV8_ENTRY_BKPT
: /* SW BKPT (?) */
1013 case DSCRV8_ENTRY_RESET_CATCH
: /* Reset catch */
1014 case DSCRV8_ENTRY_OS_UNLOCK
: /*OS unlock catch*/
1015 case DSCRV8_ENTRY_EXCEPTION_CATCH
: /*exception catch*/
1016 case DSCRV8_ENTRY_SW_ACCESS_DBG
: /*SW access dbg register*/
1017 target
->debug_reason
= DBG_REASON_BREAKPOINT
;
1019 case DSCRV8_ENTRY_WATCHPOINT
: /* asynch watchpoint */
1020 target
->debug_reason
= DBG_REASON_WATCHPOINT
;
1023 target
->debug_reason
= DBG_REASON_UNDEFINED
;
1029 /*----------------------------------------------------------------------*/
1032 * Setup and management support.
1036 * Hooks up this DPM to its associated target; call only once.
1037 * Initially this only covers the register cache.
1039 * Oh, and watchpoints. Yeah.
1041 int armv8_dpm_setup(struct arm_dpm
*dpm
)
1043 struct arm
*arm
= dpm
->arm
;
1044 struct target
*target
= arm
->target
;
1045 struct reg_cache
*cache
;
1048 /* register access setup */
1049 arm
->full_context
= armv8_dpm_full_context
;
1050 arm
->read_core_reg
= armv8_dpm_read_core_reg
;
1051 arm
->write_core_reg
= armv8_dpm_write_core_reg
;
1053 if (arm
->core_cache
== NULL
) {
1054 cache
= armv8_build_reg_cache(target
);
1059 /* coprocessor access setup */
1060 arm
->mrc
= dpmv8_mrc
;
1061 arm
->mcr
= dpmv8_mcr
;
1062 arm
->mrs
= dpmv8_mrs
;
1063 arm
->msr
= dpmv8_msr
;
1064 /* breakpoint setup -- optional until it works everywhere */
1065 if (!target
->type
->add_breakpoint
) {
1066 target
->type
->add_breakpoint
= dpmv8_add_breakpoint
;
1067 target
->type
->remove_breakpoint
= dpmv8_remove_breakpoint
;
1070 /* watchpoint setup */
1071 target
->type
->add_watchpoint
= dpmv8_add_watchpoint
;
1072 target
->type
->remove_watchpoint
= dpmv8_remove_watchpoint
;
1074 /* FIXME add vector catch support */
1076 dpm
->nbp
= 1 + ((dpm
->didr
>> 12) & 0xf);
1077 dpm
->dbp
= calloc(dpm
->nbp
, sizeof *dpm
->dbp
);
1079 dpm
->nwp
= 1 + ((dpm
->didr
>> 20) & 0xf);
1080 dpm
->dwp
= calloc(dpm
->nwp
, sizeof *dpm
->dwp
);
1082 if (!dpm
->dbp
|| !dpm
->dwp
) {
1088 LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
1089 target_name(target
), dpm
->nbp
, dpm
->nwp
);
1091 /* REVISIT ... and some of those breakpoints could match
1092 * execution context IDs...
1099 * Reinitializes DPM state at the beginning of a new debug session
1100 * or after a reset which may have affected the debug module.
1102 int armv8_dpm_initialize(struct arm_dpm
*dpm
)
1104 /* Disable all breakpoints and watchpoints at startup. */
1105 if (dpm
->bpwp_disable
) {
1108 for (i
= 0; i
< dpm
->nbp
; i
++) {
1109 dpm
->dbp
[i
].bpwp
.number
= i
;
1110 (void) dpm
->bpwp_disable(dpm
, i
);
1112 for (i
= 0; i
< dpm
->nwp
; i
++) {
1113 dpm
->dwp
[i
].bpwp
.number
= 16 + i
;
1114 (void) dpm
->bpwp_disable(dpm
, 16 + i
);
1117 LOG_WARNING("%s: can't disable breakpoints and watchpoints",
1118 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)