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"
29 #include "helper/time_support.h"
34 * Implements various ARM DPM operations using architectural debug registers.
35 * These routines layer over core-specific communication methods to cope with
36 * implementation differences between cores like ARM1136 and Cortex-A8.
38 * The "Debug Programmers' Model" (DPM) for ARMv6 and ARMv7 is defined by
39 * Part C (Debug Architecture) of the ARM Architecture Reference Manual,
40 * ARMv7-A and ARMv7-R edition (ARM DDI 0406B). In OpenOCD, DPM operations
41 * are abstracted through internal programming interfaces to share code and
42 * to minimize needless differences in debug behavior between cores.
45 /*----------------------------------------------------------------------*/
47 static int dpmv8_write_dcc(struct armv8_common
*armv8
, uint32_t data
)
49 LOG_DEBUG("write DCC 0x%08" PRIx32
, data
);
50 return mem_ap_write_u32(armv8
->debug_ap
,
51 armv8
->debug_base
+ CPUV8_DBG_DTRRX
, data
);
54 static int dpmv8_write_dcc_64(struct armv8_common
*armv8
, uint64_t data
)
57 LOG_DEBUG("write DCC Low word 0x%08" PRIx32
, (unsigned)data
);
58 LOG_DEBUG("write DCC High word 0x%08" PRIx32
, (unsigned)(data
>> 32));
59 ret
= mem_ap_write_u32(armv8
->debug_ap
,
60 armv8
->debug_base
+ CPUV8_DBG_DTRRX
, data
);
61 ret
+= mem_ap_write_u32(armv8
->debug_ap
,
62 armv8
->debug_base
+ CPUV8_DBG_DTRTX
, data
>> 32);
66 static int dpmv8_read_dcc(struct armv8_common
*armv8
, uint32_t *data
,
69 uint32_t dscr
= DSCR_ITE
;
75 /* Wait for DTRRXfull */
76 long long then
= timeval_ms();
77 while ((dscr
& DSCR_DTR_TX_FULL
) == 0) {
78 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
79 armv8
->debug_base
+ CPUV8_DBG_DSCR
,
81 if (retval
!= ERROR_OK
)
83 if (timeval_ms() > then
+ 1000) {
84 LOG_ERROR("Timeout waiting for read dcc");
89 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
90 armv8
->debug_base
+ CPUV8_DBG_DTRTX
,
92 if (retval
!= ERROR_OK
)
94 LOG_DEBUG("read DCC 0x%08" PRIx32
, *data
);
102 static int dpmv8_read_dcc_64(struct armv8_common
*armv8
, uint64_t *data
,
105 uint32_t dscr
= DSCR_ITE
;
112 /* Wait for DTRRXfull */
113 long long then
= timeval_ms();
114 while ((dscr
& DSCR_DTR_TX_FULL
) == 0) {
115 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
116 armv8
->debug_base
+ CPUV8_DBG_DSCR
,
118 if (retval
!= ERROR_OK
)
120 if (timeval_ms() > then
+ 1000) {
121 LOG_ERROR("Timeout waiting for read dcc");
126 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
127 armv8
->debug_base
+ CPUV8_DBG_DTRTX
,
129 if (retval
!= ERROR_OK
)
132 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
133 armv8
->debug_base
+ CPUV8_DBG_DTRRX
,
135 if (retval
!= ERROR_OK
)
138 *data
= *(uint32_t *)data
| (uint64_t)higher
<< 32;
139 LOG_DEBUG("read DCC 0x%16.16" PRIx64
, *data
);
147 static int dpmv8_dpm_prepare(struct arm_dpm
*dpm
)
149 struct armv8_common
*armv8
= dpm
->arm
->arch_info
;
153 /* set up invariant: INSTR_COMP is set after ever DPM operation */
154 long long then
= timeval_ms();
156 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
157 armv8
->debug_base
+ CPUV8_DBG_DSCR
,
159 if (retval
!= ERROR_OK
)
161 if ((dscr
& DSCR_ITE
) != 0)
163 if (timeval_ms() > then
+ 1000) {
164 LOG_ERROR("Timeout waiting for dpm prepare");
169 /* this "should never happen" ... */
170 if (dscr
& DSCR_DTR_RX_FULL
) {
171 LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32
, dscr
);
173 retval
= mem_ap_read_u32(armv8
->debug_ap
,
174 armv8
->debug_base
+ CPUV8_DBG_DTRRX
, &dscr
);
175 if (retval
!= ERROR_OK
)
178 /* Clear sticky error */
179 retval
= mem_ap_write_u32(armv8
->debug_ap
,
180 armv8
->debug_base
+ CPUV8_DBG_DRCR
, DRCR_CSE
);
181 if (retval
!= ERROR_OK
)
188 static int dpmv8_dpm_finish(struct arm_dpm
*dpm
)
190 /* REVISIT what could be done here? */
194 static int dpmv8_exec_opcode(struct arm_dpm
*dpm
,
195 uint32_t opcode
, uint32_t *p_dscr
)
197 struct armv8_common
*armv8
= dpm
->arm
->arch_info
;
198 uint32_t dscr
= DSCR_ITE
;
201 LOG_DEBUG("exec opcode 0x%08" PRIx32
, opcode
);
206 /* Wait for InstrCompl bit to be set */
207 long long then
= timeval_ms();
208 while ((dscr
& DSCR_ITE
) == 0) {
209 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
210 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
211 if (retval
!= ERROR_OK
) {
212 LOG_ERROR("Could not read DSCR register, opcode = 0x%08" PRIx32
, opcode
);
215 if (timeval_ms() > then
+ 1000) {
216 LOG_ERROR("Timeout waiting for aarch64_exec_opcode");
221 retval
= mem_ap_write_u32(armv8
->debug_ap
,
222 armv8
->debug_base
+ CPUV8_DBG_ITR
, opcode
);
223 if (retval
!= ERROR_OK
)
228 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
229 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
230 if (retval
!= ERROR_OK
) {
231 LOG_ERROR("Could not read DSCR register");
234 if (timeval_ms() > then
+ 1000) {
235 LOG_ERROR("Timeout waiting for aarch64_exec_opcode");
238 } while ((dscr
& DSCR_ITE
) == 0); /* Wait for InstrCompl bit to be set */
246 static int dpmv8_instr_execute(struct arm_dpm
*dpm
, uint32_t opcode
)
248 return dpmv8_exec_opcode(dpm
, opcode
, NULL
);
251 static int dpmv8_instr_write_data_dcc(struct arm_dpm
*dpm
,
252 uint32_t opcode
, uint32_t data
)
254 struct armv8_common
*armv8
= dpm
->arm
->arch_info
;
257 retval
= dpmv8_write_dcc(armv8
, data
);
258 if (retval
!= ERROR_OK
)
261 return dpmv8_exec_opcode(dpm
, opcode
, 0);
264 static int dpmv8_instr_write_data_dcc_64(struct arm_dpm
*dpm
,
265 uint32_t opcode
, uint64_t data
)
267 struct armv8_common
*armv8
= dpm
->arm
->arch_info
;
270 retval
= dpmv8_write_dcc_64(armv8
, data
);
271 if (retval
!= ERROR_OK
)
274 return dpmv8_exec_opcode(dpm
, opcode
, 0);
277 static int dpmv8_instr_write_data_r0(struct arm_dpm
*dpm
,
278 uint32_t opcode
, uint32_t data
)
280 struct armv8_common
*armv8
= dpm
->arm
->arch_info
;
281 uint32_t dscr
= DSCR_ITE
;
284 retval
= dpmv8_write_dcc(armv8
, data
);
285 if (retval
!= ERROR_OK
)
288 retval
= dpmv8_exec_opcode(dpm
, armv8_opcode(armv8
, READ_REG_DTRRX
), &dscr
);
289 if (retval
!= ERROR_OK
)
292 /* then the opcode, taking data from R0 */
293 return dpmv8_exec_opcode(dpm
, opcode
, &dscr
);
296 static int dpmv8_instr_write_data_r0_64(struct arm_dpm
*dpm
,
297 uint32_t opcode
, uint64_t data
)
299 struct armv8_common
*armv8
= dpm
->arm
->arch_info
;
300 uint32_t dscr
= DSCR_ITE
;
303 retval
= dpmv8_write_dcc_64(armv8
, data
);
304 if (retval
!= ERROR_OK
)
307 retval
= dpmv8_exec_opcode(dpm
, ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0
, 0), &dscr
);
308 if (retval
!= ERROR_OK
)
311 /* then the opcode, taking data from R0 */
312 return dpmv8_exec_opcode(dpm
, opcode
, &dscr
);
315 static int dpmv8_instr_cpsr_sync(struct arm_dpm
*dpm
)
317 struct armv8_common
*armv8
= dpm
->arm
->arch_info
;
318 /* "Prefetch flush" after modifying execution status in CPSR */
319 return dpmv8_exec_opcode(dpm
, armv8_opcode(armv8
, ARMV8_OPC_DSB_SY
), NULL
);
322 static int dpmv8_instr_read_data_dcc(struct arm_dpm
*dpm
,
323 uint32_t opcode
, uint32_t *data
)
325 struct armv8_common
*armv8
= dpm
->arm
->arch_info
;
326 uint32_t dscr
= DSCR_ITE
;
329 /* the opcode, writing data to DCC */
330 retval
= dpmv8_exec_opcode(dpm
, opcode
, &dscr
);
331 if (retval
!= ERROR_OK
)
334 return dpmv8_read_dcc(armv8
, data
, &dscr
);
337 static int dpmv8_instr_read_data_dcc_64(struct arm_dpm
*dpm
,
338 uint32_t opcode
, uint64_t *data
)
340 struct armv8_common
*armv8
= dpm
->arm
->arch_info
;
341 uint32_t dscr
= DSCR_ITE
;
344 /* the opcode, writing data to DCC */
345 retval
= dpmv8_exec_opcode(dpm
, opcode
, &dscr
);
346 if (retval
!= ERROR_OK
)
349 return dpmv8_read_dcc_64(armv8
, data
, &dscr
);
352 static int dpmv8_instr_read_data_r0(struct arm_dpm
*dpm
,
353 uint32_t opcode
, uint32_t *data
)
355 struct armv8_common
*armv8
= dpm
->arm
->arch_info
;
356 uint32_t dscr
= DSCR_ITE
;
359 /* the opcode, writing data to R0 */
360 retval
= dpmv8_exec_opcode(dpm
, opcode
, &dscr
);
361 if (retval
!= ERROR_OK
)
364 /* write R0 to DCC */
365 retval
= dpmv8_exec_opcode(dpm
, armv8_opcode(armv8
, WRITE_REG_DTRTX
), &dscr
);
366 if (retval
!= ERROR_OK
)
369 return dpmv8_read_dcc(armv8
, data
, &dscr
);
372 static int dpmv8_instr_read_data_r0_64(struct arm_dpm
*dpm
,
373 uint32_t opcode
, uint64_t *data
)
375 struct armv8_common
*armv8
= dpm
->arm
->arch_info
;
376 uint32_t dscr
= DSCR_ITE
;
379 /* the opcode, writing data to R0 */
380 retval
= dpmv8_exec_opcode(dpm
, opcode
, &dscr
);
381 if (retval
!= ERROR_OK
)
384 /* write R0 to DCC */
385 retval
= dpmv8_exec_opcode(dpm
, ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0
, 0), &dscr
);
386 if (retval
!= ERROR_OK
)
389 return dpmv8_read_dcc_64(armv8
, data
, &dscr
);
393 static int dpmv8_bpwp_enable(struct arm_dpm
*dpm
, unsigned index_t
,
394 target_addr_t addr
, uint32_t control
)
396 struct armv8_common
*armv8
= dpm
->arm
->arch_info
;
397 uint32_t vr
= armv8
->debug_base
;
398 uint32_t cr
= armv8
->debug_base
;
402 case 0 ... 15: /* breakpoints */
403 vr
+= CPUV8_DBG_BVR_BASE
;
404 cr
+= CPUV8_DBG_BCR_BASE
;
406 case 16 ... 31: /* watchpoints */
407 vr
+= CPUV8_DBG_WVR_BASE
;
408 cr
+= CPUV8_DBG_WCR_BASE
;
417 LOG_DEBUG("A8: bpwp enable, vr %08x cr %08x",
418 (unsigned) vr
, (unsigned) cr
);
420 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
, vr
, addr
);
421 if (retval
!= ERROR_OK
)
423 return mem_ap_write_atomic_u32(armv8
->debug_ap
, cr
, control
);
427 static int dpmv8_bpwp_disable(struct arm_dpm
*dpm
, unsigned index_t
)
429 struct armv8_common
*armv8
= dpm
->arm
->arch_info
;
434 cr
= armv8
->debug_base
+ CPUV8_DBG_BCR_BASE
;
437 cr
= armv8
->debug_base
+ CPUV8_DBG_WCR_BASE
;
445 LOG_DEBUG("A: bpwp disable, cr %08x", (unsigned) cr
);
447 /* clear control register */
448 return mem_ap_write_atomic_u32(armv8
->debug_ap
, cr
, 0);
452 * Coprocessor support
455 /* Read coprocessor */
456 static int dpmv8_mrc(struct target
*target
, int cpnum
,
457 uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
,
460 struct arm
*arm
= target_to_arm(target
);
461 struct arm_dpm
*dpm
= arm
->dpm
;
464 retval
= dpm
->prepare(dpm
);
465 if (retval
!= ERROR_OK
)
468 LOG_DEBUG("MRC p%d, %d, r0, c%d, c%d, %d", cpnum
,
469 (int) op1
, (int) CRn
,
470 (int) CRm
, (int) op2
);
472 /* read coprocessor register into R0; return via DCC */
473 retval
= dpm
->instr_read_data_r0(dpm
,
474 T32_FMTITR(ARMV4_5_MRC(cpnum
, op1
, 0, CRn
, CRm
, op2
)),
477 /* (void) */ dpm
->finish(dpm
);
481 static int dpmv8_mcr(struct target
*target
, int cpnum
,
482 uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
,
485 struct arm
*arm
= target_to_arm(target
);
486 struct arm_dpm
*dpm
= arm
->dpm
;
489 retval
= dpm
->prepare(dpm
);
490 if (retval
!= ERROR_OK
)
493 LOG_DEBUG("MCR p%d, %d, r0, c%d, c%d, %d", cpnum
,
494 (int) op1
, (int) CRn
,
495 (int) CRm
, (int) op2
);
497 /* read DCC into r0; then write coprocessor register from R0 */
498 retval
= dpm
->instr_write_data_r0(dpm
,
499 T32_FMTITR(ARMV4_5_MCR(cpnum
, op1
, 0, CRn
, CRm
, op2
)),
502 /* (void) */ dpm
->finish(dpm
);
506 static int dpmv8_mrs(struct target
*target
, uint32_t op0
,
507 uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
,
510 struct arm
*arm
= target_to_arm(target
);
511 struct arm_dpm
*dpm
= arm
->dpm
;
515 retval
= dpm
->prepare(dpm
);
516 if (retval
!= ERROR_OK
)
518 op_code
= ((op0
& 0x3) << 19 | (op1
& 0x7) << 16 | (CRn
& 0xF) << 12 |\
519 (CRm
& 0xF) << 8 | (op2
& 0x7) << 5);
521 LOG_DEBUG("MRS p%d, %d, r0, c%d, c%d, %d", (int)op0
,
522 (int) op1
, (int) CRn
,
523 (int) CRm
, (int) op2
);
524 /* read coprocessor register into R0; return via DCC */
525 retval
= dpm
->instr_read_data_r0(dpm
,
526 ARMV8_MRS(op_code
, 0),
529 /* (void) */ dpm
->finish(dpm
);
533 static int dpmv8_msr(struct target
*target
, uint32_t op0
,
534 uint32_t op1
, uint32_t op2
, uint32_t CRn
, uint32_t CRm
,
537 struct arm
*arm
= target_to_arm(target
);
538 struct arm_dpm
*dpm
= arm
->dpm
;
542 retval
= dpm
->prepare(dpm
);
543 if (retval
!= ERROR_OK
)
546 op_code
= ((op0
& 0x3) << 19 | (op1
& 0x7) << 16 | (CRn
& 0xF) << 12 |\
547 (CRm
& 0xF) << 8 | (op2
& 0x7) << 5);
549 LOG_DEBUG("MSR p%d, %d, r0, c%d, c%d, %d", (int)op0
,
550 (int) op1
, (int) CRn
,
551 (int) CRm
, (int) op2
);
553 /* read DCC into r0; then write coprocessor register from R0 */
554 retval
= dpm
->instr_write_data_r0(dpm
,
555 ARMV8_MSR_GP(op_code
, 0),
558 /* (void) */ dpm
->finish(dpm
);
562 /*----------------------------------------------------------------------*/
565 * Register access utilities
568 /* Toggles between recorded core mode (USR, SVC, etc) and a temporary one.
569 * Routines *must* restore the original mode before returning!!
571 int dpmv8_modeswitch(struct arm_dpm
*dpm
, enum arm_mode mode
)
573 struct armv8_common
*armv8
= (struct armv8_common
*)dpm
->arm
->arch_info
;
577 /* restore previous mode */
578 if (mode
== ARM_MODE_ANY
)
579 cpsr
= buf_get_u32(dpm
->arm
->cpsr
->value
, 0, 32);
581 /* else force to the specified mode */
585 switch ((cpsr
& 0xC) >> 2) {
586 case SYSTEM_CUREL_EL1
:
587 retval
= dpm
->instr_execute(dpm
, ARMV8_DCPS1(11));
588 if (retval
!= ERROR_OK
)
591 case SYSTEM_CUREL_EL2
:
592 retval
= dpm
->instr_execute(dpm
, ARMV8_DCPS2(11));
593 if (retval
!= ERROR_OK
)
597 case SYSTEM_CUREL_EL3
:
598 retval
= dpm
->instr_execute(dpm
, ARMV8_DCPS3(11));
599 if (retval
!= ERROR_OK
)
604 LOG_DEBUG("unknow mode 0x%x", (unsigned) ((cpsr
& 0xC) >> 2));
609 retval
= dpm
->instr_write_data_r0(dpm
, armv8_opcode(armv8
, WRITE_REG_DSPSR
), cpsr
);
610 if (retval
!= ERROR_OK
)
613 if (dpm
->instr_cpsr_sync
)
614 retval
= dpm
->instr_cpsr_sync(dpm
);
619 static int dpmv8_read_reg32(struct arm_dpm
*dpm
, struct reg
*r
, unsigned regnum
)
622 int retval
= ERROR_FAIL
;
627 /* return via DCC: "MCR p14, 0, Rnum, c0, c5, 0" */
628 retval
= dpm
->instr_read_data_dcc(dpm
,
629 T32_FMTITR(ARMV4_5_MCR(14, 0, regnum
, 0, 5, 0)),
633 retval
= dpm
->instr_read_data_dcc(dpm
,
634 T32_FMTITR(ARMV4_5_MCR(14, 0, 13, 0, 5, 0)),
638 retval
= dpm
->instr_read_data_r0(dpm
,
639 T32_FMTITR(ARMV8_MRC_DLR(0)),
643 retval
= dpm
->instr_read_data_r0(dpm
,
644 T32_FMTITR(ARMV8_MRC_DSPSR(0)),
648 LOG_DEBUG("READ: %s ignored", r
->name
);
655 if (retval
== ERROR_OK
) {
658 buf_set_u64(r
->value
, 0, 32, value
);
659 LOG_DEBUG("READ: %s, %8.8x", r
->name
, (unsigned) value
);
664 static int dpmv8_write_reg32(struct arm_dpm
*dpm
, struct reg
*r
, unsigned regnum
)
667 uint64_t value
= buf_get_u64(r
->value
, 0, 32);
671 /* load register from DCC: "MRC p14, 0, Rnum, c0, c5, 0" */
672 retval
= dpm
->instr_write_data_dcc(dpm
,
673 T32_FMTITR(ARMV4_5_MRC(14, 0, regnum
, 0, 5, 0)), value
);
676 * read r0 from DCC; then "MOV pc, r0" */
677 retval
= dpm
->instr_write_data_r0(dpm
,
678 T32_FMTITR(ARMV8_MCR_DLR(0)), value
);
680 case ARMV8_xPSR
: /* CPSR */
681 /* read r0 from DCC, then "MCR r0, DSPSR" */
682 retval
= dpm
->instr_write_data_r0(dpm
,
683 T32_FMTITR(ARMV8_MCR_DSPSR(0)), value
);
687 LOG_DEBUG("WRITE: %s ignored", r
->name
);
691 if (retval
== ERROR_OK
) {
693 LOG_DEBUG("WRITE: %s, %8.8x", r
->name
, (unsigned) value
);
699 /* just read the register -- rely on the core mode being right */
700 static int dpmv8_read_reg(struct arm_dpm
*dpm
, struct reg
*r
, unsigned regnum
)
704 int retval
= ERROR_FAIL
;
708 retval
= dpm
->instr_read_data_dcc_64(dpm
,
709 ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0
, regnum
),
713 retval
= dpm
->instr_read_data_r0_64(dpm
,
718 retval
= dpm
->instr_read_data_r0_64(dpm
,
723 retval
= dpm
->instr_read_data_r0(dpm
,
728 LOG_DEBUG("READ: %s fail", r
->name
);
732 if (retval
== ERROR_OK
) {
736 buf_set_u64(r
->value
, 0, 64, value_64
);
737 LOG_DEBUG("READ: %s, %16.8llx", r
->name
, (unsigned long long) value_64
);
739 buf_set_u32(r
->value
, 0, 32, value
);
740 LOG_DEBUG("READ: %s, %8.8x", r
->name
, (unsigned) value
);
746 /* just write the register -- rely on the core mode being right */
747 static int dpmv8_write_reg(struct arm_dpm
*dpm
, struct reg
*r
, unsigned regnum
)
749 int retval
= ERROR_FAIL
;
750 uint32_t value
= 0xFFFFFFFF;
751 uint64_t value_64
= 0xFFFFFFFFFFFFFFFF;
755 value_64
= buf_get_u64(r
->value
, 0, 64);
756 retval
= dpm
->instr_write_data_dcc_64(dpm
,
757 ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0
, regnum
),
761 value_64
= buf_get_u64(r
->value
, 0, 64);
762 retval
= dpm
->instr_write_data_r0_64(dpm
,
767 value_64
= buf_get_u64(r
->value
, 0, 64);
768 retval
= dpm
->instr_write_data_r0_64(dpm
,
773 value
= buf_get_u32(r
->value
, 0, 32);
774 retval
= dpm
->instr_write_data_r0(dpm
,
779 LOG_DEBUG("write: %s fail", r
->name
);
784 if (retval
== ERROR_OK
) {
787 LOG_DEBUG("WRITE: %s, %16.8llx", r
->name
, (unsigned long long) value_64
);
789 LOG_DEBUG("WRITE: %s, %8.8x", r
->name
, (unsigned) value
);
795 static inline enum arm_state
dpm_get_core_state(uint32_t dscr
)
797 int el
= (dscr
>> 8) & 0x3;
798 int rw
= (dscr
>> 10) & 0xF;
800 LOG_DEBUG("EL:%i, RW:0x%x", el
, rw
);
802 /* DSCR.RW = 0b1111 - all EL are using AArch64 state */
804 return ARM_STATE_AARCH64
;
806 /* DSCR.RW = 0b1110 - all EL > 0 are using AArch64 state */
807 if (rw
== 0xE && el
> 0)
808 return ARM_STATE_AARCH64
;
810 /* DSCR.RW = 0b110x - all EL > 1 are using Aarch64 state */
811 if ((rw
& 0xE) == 0xC && el
> 1)
812 return ARM_STATE_AARCH64
;
814 /* DSCR.RW = 0b10xx - all EL > 2 are using Aarch64 state */
815 if ((rw
& 0xC) == 0x8 && el
> 2)
816 return ARM_STATE_AARCH64
;
818 /* DSCR.RW = 0b0xxx - all EL are using AArch32 state */
820 return ARM_STATE_ARM
;
822 return ARM_STATE_ARM
;
826 * Read basic registers of the the current context: R0 to R15, and CPSR;
827 * sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb).
828 * In normal operation this is called on entry to halting debug state,
829 * possibly after some other operations supporting restore of debug state
830 * or making sure the CPU is fully idle (drain write buffer, etc).
832 int armv8_dpm_read_current_registers(struct arm_dpm
*dpm
)
834 struct arm
*arm
= dpm
->arm
;
835 struct armv8_common
*armv8
= (struct armv8_common
*)arm
->arch_info
;
836 enum arm_state core_state
;
842 retval
= dpm
->prepare(dpm
);
843 if (retval
!= ERROR_OK
)
846 core_state
= dpm_get_core_state(dpm
->dscr
);
848 armv8_select_opcodes(armv8
, core_state
);
850 /* read R0 first (it's used for scratch), then CPSR */
851 r
= arm
->core_cache
->reg_list
+ 0;
853 retval
= core_state
== ARM_STATE_AARCH64
?
854 dpmv8_read_reg(dpm
, r
, 0) : dpmv8_read_reg32(dpm
, r
, 0);
855 if (retval
!= ERROR_OK
)
860 /* read cpsr to r0 and get it back */
861 retval
= dpm
->instr_read_data_r0(dpm
, armv8_opcode(armv8
, READ_REG_DSPSR
), &cpsr
);
862 if (retval
!= ERROR_OK
)
865 /* update core mode and state, plus shadow mapping for R8..R14 */
866 armv8_set_cpsr(arm
, cpsr
);
868 /* REVISIT we can probably avoid reading R1..R14, saving time... */
869 for (unsigned i
= 1; i
< arm
->core_cache
->num_regs
; i
++) {
870 r
= armv8_reg_current(arm
, i
);
874 retval
= core_state
== ARM_STATE_AARCH64
?
875 dpmv8_read_reg(dpm
, r
, i
) : dpmv8_read_reg32(dpm
, r
, i
);
877 if (retval
!= ERROR_OK
)
881 /* NOTE: SPSR ignored (if it's even relevant). */
883 /* REVISIT the debugger can trigger various exceptions. See the
884 * ARMv7A architecture spec, section C5.7, for more info about
885 * what defenses are needed; v6 debug has the most issues.
889 /* (void) */ dpm
->finish(dpm
);
893 /* Avoid needless I/O ... leave breakpoints and watchpoints alone
894 * unless they're removed, or need updating because of single-stepping
895 * or running debugger code.
897 static int dpmv8_maybe_update_bpwp(struct arm_dpm
*dpm
, bool bpwp
,
898 struct dpm_bpwp
*xp
, int *set_p
)
900 int retval
= ERROR_OK
;
907 /* removed or startup; we must disable it */
912 /* disabled, but we must set it */
913 xp
->dirty
= disable
= false;
918 /* set, but we must temporarily disable it */
919 xp
->dirty
= disable
= true;
924 retval
= dpm
->bpwp_disable(dpm
, xp
->number
);
926 retval
= dpm
->bpwp_enable(dpm
, xp
->number
,
927 xp
->address
, xp
->control
);
929 if (retval
!= ERROR_OK
)
930 LOG_ERROR("%s: can't %s HW %spoint %d",
931 disable
? "disable" : "enable",
932 target_name(dpm
->arm
->target
),
933 (xp
->number
< 16) ? "break" : "watch",
939 static int dpmv8_add_breakpoint(struct target
*target
, struct breakpoint
*bp
);
942 * Writes all modified core registers for all processor modes. In normal
943 * operation this is called on exit from halting debug state.
945 * @param dpm: represents the processor
946 * @param bpwp: true ensures breakpoints and watchpoints are set,
947 * false ensures they are cleared
949 int armv8_dpm_write_dirty_registers(struct arm_dpm
*dpm
, bool bpwp
)
951 struct arm
*arm
= dpm
->arm
;
952 struct reg_cache
*cache
= arm
->core_cache
;
954 bool is_aarch64
= arm
->core_state
== ARM_STATE_AARCH64
;
956 retval
= dpm
->prepare(dpm
);
957 if (retval
!= ERROR_OK
)
960 /* If we're managing hardware breakpoints for this core, enable
961 * or disable them as requested.
963 * REVISIT We don't yet manage them for ANY cores. Eventually
964 * we should be able to assume we handle them; but until then,
965 * cope with the hand-crafted breakpoint code.
967 if (arm
->target
->type
->add_breakpoint
== dpmv8_add_breakpoint
) {
968 for (unsigned i
= 0; i
< dpm
->nbp
; i
++) {
969 struct dpm_bp
*dbp
= dpm
->dbp
+ i
;
970 struct breakpoint
*bp
= dbp
->bp
;
972 retval
= dpmv8_maybe_update_bpwp(dpm
, bpwp
, &dbp
->bpwp
,
973 bp
? &bp
->set
: NULL
);
974 if (retval
!= ERROR_OK
)
979 /* enable/disable watchpoints */
980 for (unsigned i
= 0; i
< dpm
->nwp
; i
++) {
981 struct dpm_wp
*dwp
= dpm
->dwp
+ i
;
982 struct watchpoint
*wp
= dwp
->wp
;
984 retval
= dpmv8_maybe_update_bpwp(dpm
, bpwp
, &dwp
->bpwp
,
985 wp
? &wp
->set
: NULL
);
986 if (retval
!= ERROR_OK
)
990 /* NOTE: writes to breakpoint and watchpoint registers might
991 * be queued, and need (efficient/batched) flushing later.
994 /* Scan the registers until we find one that's both dirty and
995 * eligible for flushing. Flush that and everything else that
996 * shares the same core mode setting. Typically this won't
997 * actually find anything to do...
1000 /* check everything except our scratch register R0 */
1001 for (unsigned i
= 1; i
< cache
->num_regs
; i
++) {
1005 /* also skip PC, CPSR, and non-dirty */
1006 if (i
== (arm
->core_cache
->num_regs
- 2))
1008 if (arm
->cpsr
== cache
->reg_list
+ i
)
1010 if (!cache
->reg_list
[i
].dirty
)
1013 r
= cache
->reg_list
[i
].arch_info
;
1016 retval
= is_aarch64
? dpmv8_write_reg(dpm
, &cache
->reg_list
[i
], regnum
)
1017 : dpmv8_write_reg32(dpm
, &cache
->reg_list
[i
], regnum
);
1018 if (retval
!= ERROR_OK
)
1023 /* Restore original CPSR ... assuming either that we changed it,
1024 * or it's dirty. Must write PC to ensure the return address is
1025 * defined, and must not write it before CPSR.
1027 retval
= dpmv8_modeswitch(dpm
, ARM_MODE_ANY
);
1028 if (retval
!= ERROR_OK
)
1030 arm
->cpsr
->dirty
= false;
1032 retval
= is_aarch64
? dpmv8_write_reg(dpm
, arm
->pc
, (arm
->core_cache
->num_regs
- 2))
1033 : dpmv8_write_reg32(dpm
, arm
->pc
, (arm
->core_cache
->num_regs
- 2));
1034 if (retval
!= ERROR_OK
)
1036 arm
->pc
->dirty
= false;
1038 /* flush R0 -- it's *very* dirty by now */
1039 retval
= is_aarch64
? dpmv8_write_reg(dpm
, &cache
->reg_list
[0], 0)
1040 : dpmv8_write_reg32(dpm
, &cache
->reg_list
[0], 0);
1041 if (retval
!= ERROR_OK
)
1043 cache
->reg_list
[0].dirty
= false;
1045 /* (void) */ dpm
->finish(dpm
);
1051 * Standard ARM register accessors ... there are three methods
1052 * in "struct arm", to support individual read/write and bulk read
1056 static int armv8_dpm_read_core_reg(struct target
*target
, struct reg
*r
,
1057 int regnum
, enum arm_mode mode
)
1059 struct arm
*arm
= target_to_arm(target
);
1060 struct arm_dpm
*dpm
= target_to_arm(target
)->dpm
;
1062 int max
= arm
->core_cache
->num_regs
;
1064 if (regnum
< 0 || regnum
> max
)
1065 return ERROR_COMMAND_SYNTAX_ERROR
;
1067 /* REVISIT what happens if we try to read SPSR in a core mode
1068 * which has no such register?
1071 retval
= dpm
->prepare(dpm
);
1072 if (retval
!= ERROR_OK
)
1075 retval
= arm
->core_state
== ARM_STATE_AARCH64
?
1076 dpmv8_read_reg(dpm
, r
, regnum
) : dpmv8_read_reg32(dpm
, r
, regnum
);
1077 if (retval
!= ERROR_OK
)
1081 /* (void) */ dpm
->finish(dpm
);
1085 static int armv8_dpm_write_core_reg(struct target
*target
, struct reg
*r
,
1086 int regnum
, enum arm_mode mode
, uint8_t *value
)
1088 struct arm
*arm
= target_to_arm(target
);
1089 struct arm_dpm
*dpm
= target_to_arm(target
)->dpm
;
1091 int max
= arm
->core_cache
->num_regs
;
1093 if (regnum
< 0 || regnum
> max
)
1094 return ERROR_COMMAND_SYNTAX_ERROR
;
1096 /* REVISIT what happens if we try to write SPSR in a core mode
1097 * which has no such register?
1100 retval
= dpm
->prepare(dpm
);
1101 if (retval
!= ERROR_OK
)
1104 retval
= arm
->core_state
== ARM_STATE_AARCH64
?
1105 dpmv8_write_reg(dpm
, r
, regnum
) : dpmv8_write_reg32(dpm
, r
, regnum
);
1107 /* always clean up, regardless of error */
1109 /* (void) */ dpm
->finish(dpm
);
1113 static int armv8_dpm_full_context(struct target
*target
)
1115 struct arm
*arm
= target_to_arm(target
);
1116 struct arm_dpm
*dpm
= arm
->dpm
;
1117 struct reg_cache
*cache
= arm
->core_cache
;
1121 retval
= dpm
->prepare(dpm
);
1122 if (retval
!= ERROR_OK
)
1126 enum arm_mode mode
= ARM_MODE_ANY
;
1130 /* We "know" arm_dpm_read_current_registers() was called so
1131 * the unmapped registers (R0..R7, PC, AND CPSR) and some
1132 * view of R8..R14 are current. We also "know" oddities of
1133 * register mapping: special cases for R8..R12 and SPSR.
1135 * Pick some mode with unread registers and read them all.
1136 * Repeat until done.
1138 for (unsigned i
= 0; i
< cache
->num_regs
; i
++) {
1141 if (cache
->reg_list
[i
].valid
)
1143 r
= cache
->reg_list
[i
].arch_info
;
1145 /* may need to pick a mode and set CPSR */
1150 /* For regular (ARM_MODE_ANY) R8..R12
1151 * in case we've entered debug state
1152 * in FIQ mode we need to patch mode.
1154 if (mode
!= ARM_MODE_ANY
)
1155 retval
= dpmv8_modeswitch(dpm
, mode
);
1157 retval
= dpmv8_modeswitch(dpm
, ARM_MODE_USR
);
1159 if (retval
!= ERROR_OK
)
1162 if (r
->mode
!= mode
)
1165 /* CPSR was read, so "R16" must mean SPSR */
1166 retval
= dpmv8_read_reg(dpm
,
1167 &cache
->reg_list
[i
],
1168 (r
->num
== 16) ? 17 : r
->num
);
1169 if (retval
!= ERROR_OK
)
1175 retval
= dpmv8_modeswitch(dpm
, ARM_MODE_ANY
);
1176 /* (void) */ dpm
->finish(dpm
);
1182 /*----------------------------------------------------------------------*/
1185 * Breakpoint and Watchpoint support.
1187 * Hardware {break,watch}points are usually left active, to minimize
1188 * debug entry/exit costs. When they are set or cleared, it's done in
1189 * batches. Also, DPM-conformant hardware can update debug registers
1190 * regardless of whether the CPU is running or halted ... though that
1191 * fact isn't currently leveraged.
1194 static int dpmv8_bpwp_setup(struct arm_dpm
*dpm
, struct dpm_bpwp
*xp
,
1195 uint32_t addr
, uint32_t length
)
1199 control
= (1 << 0) /* enable */
1200 | (3 << 1); /* both user and privileged access */
1202 /* Match 1, 2, or all 4 byte addresses in this word.
1204 * FIXME: v7 hardware allows lengths up to 2 GB for BP and WP.
1205 * Support larger length, when addr is suitably aligned. In
1206 * particular, allow watchpoints on 8 byte "double" values.
1208 * REVISIT allow watchpoints on unaligned 2-bit values; and on
1209 * v7 hardware, unaligned 4-byte ones too.
1213 control
|= (1 << (addr
& 3)) << 5;
1216 /* require 2-byte alignment */
1218 control
|= (3 << (addr
& 2)) << 5;
1223 /* require 4-byte alignment */
1225 control
|= 0xf << 5;
1230 LOG_ERROR("unsupported {break,watch}point length/alignment");
1231 return ERROR_COMMAND_SYNTAX_ERROR
;
1234 /* other shared control bits:
1235 * bits 15:14 == 0 ... both secure and nonsecure states (v6.1+ only)
1236 * bit 20 == 0 ... not linked to a context ID
1237 * bit 28:24 == 0 ... not ignoring N LSBs (v7 only)
1240 xp
->address
= addr
& ~3;
1241 xp
->control
= control
;
1244 LOG_DEBUG("BPWP: addr %8.8" PRIx32
", control %" PRIx32
", number %d",
1245 xp
->address
, control
, xp
->number
);
1247 /* hardware is updated in write_dirty_registers() */
1251 static int dpmv8_add_breakpoint(struct target
*target
, struct breakpoint
*bp
)
1253 struct arm
*arm
= target_to_arm(target
);
1254 struct arm_dpm
*dpm
= arm
->dpm
;
1255 int retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1258 return ERROR_COMMAND_SYNTAX_ERROR
;
1259 if (!dpm
->bpwp_enable
)
1262 /* FIXME we need a generic solution for software breakpoints. */
1263 if (bp
->type
== BKPT_SOFT
)
1264 LOG_DEBUG("using HW bkpt, not SW...");
1266 for (unsigned i
= 0; i
< dpm
->nbp
; i
++) {
1267 if (!dpm
->dbp
[i
].bp
) {
1268 retval
= dpmv8_bpwp_setup(dpm
, &dpm
->dbp
[i
].bpwp
,
1269 bp
->address
, bp
->length
);
1270 if (retval
== ERROR_OK
)
1271 dpm
->dbp
[i
].bp
= bp
;
1279 static int dpmv8_remove_breakpoint(struct target
*target
, struct breakpoint
*bp
)
1281 struct arm
*arm
= target_to_arm(target
);
1282 struct arm_dpm
*dpm
= arm
->dpm
;
1283 int retval
= ERROR_COMMAND_SYNTAX_ERROR
;
1285 for (unsigned i
= 0; i
< dpm
->nbp
; i
++) {
1286 if (dpm
->dbp
[i
].bp
== bp
) {
1287 dpm
->dbp
[i
].bp
= NULL
;
1288 dpm
->dbp
[i
].bpwp
.dirty
= true;
1290 /* hardware is updated in write_dirty_registers() */
1299 static int dpmv8_watchpoint_setup(struct arm_dpm
*dpm
, unsigned index_t
,
1300 struct watchpoint
*wp
)
1303 struct dpm_wp
*dwp
= dpm
->dwp
+ index_t
;
1306 /* this hardware doesn't support data value matching or masking */
1307 if (wp
->value
|| wp
->mask
!= ~(uint32_t)0) {
1308 LOG_DEBUG("watchpoint values and masking not supported");
1309 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1312 retval
= dpmv8_bpwp_setup(dpm
, &dwp
->bpwp
, wp
->address
, wp
->length
);
1313 if (retval
!= ERROR_OK
)
1316 control
= dwp
->bpwp
.control
;
1328 dwp
->bpwp
.control
= control
;
1330 dpm
->dwp
[index_t
].wp
= wp
;
1335 static int dpmv8_add_watchpoint(struct target
*target
, struct watchpoint
*wp
)
1337 struct arm
*arm
= target_to_arm(target
);
1338 struct arm_dpm
*dpm
= arm
->dpm
;
1339 int retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1341 if (dpm
->bpwp_enable
) {
1342 for (unsigned i
= 0; i
< dpm
->nwp
; i
++) {
1343 if (!dpm
->dwp
[i
].wp
) {
1344 retval
= dpmv8_watchpoint_setup(dpm
, i
, wp
);
1353 static int dpmv8_remove_watchpoint(struct target
*target
, struct watchpoint
*wp
)
1355 struct arm
*arm
= target_to_arm(target
);
1356 struct arm_dpm
*dpm
= arm
->dpm
;
1357 int retval
= ERROR_COMMAND_SYNTAX_ERROR
;
1359 for (unsigned i
= 0; i
< dpm
->nwp
; i
++) {
1360 if (dpm
->dwp
[i
].wp
== wp
) {
1361 dpm
->dwp
[i
].wp
= NULL
;
1362 dpm
->dwp
[i
].bpwp
.dirty
= true;
1364 /* hardware is updated in write_dirty_registers() */
1373 void armv8_dpm_report_wfar(struct arm_dpm
*dpm
, uint64_t addr
)
1375 switch (dpm
->arm
->core_state
) {
1377 case ARM_STATE_AARCH64
:
1380 case ARM_STATE_THUMB
:
1381 case ARM_STATE_THUMB_EE
:
1384 case ARM_STATE_JAZELLE
:
1388 LOG_DEBUG("Unknow core_state");
1394 /*----------------------------------------------------------------------*/
1397 * Other debug and support utilities
1400 void armv8_dpm_report_dscr(struct arm_dpm
*dpm
, uint32_t dscr
)
1402 struct target
*target
= dpm
->arm
->target
;
1406 /* Examine debug reason */
1407 switch (DSCR_ENTRY(dscr
)) {
1408 /* FALL THROUGH -- assume a v6 core in abort mode */
1409 case DSCRV8_ENTRY_EXT_DEBUG
: /* EDBGRQ */
1410 target
->debug_reason
= DBG_REASON_DBGRQ
;
1412 case DSCRV8_ENTRY_HALT_STEP_EXECLU
: /* HALT step */
1413 case DSCRV8_ENTRY_HALT_STEP_NORMAL
: /* Halt step*/
1414 case DSCRV8_ENTRY_HALT_STEP
:
1415 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
1417 case DSCRV8_ENTRY_HLT
: /* HLT instruction (software breakpoint) */
1418 case DSCRV8_ENTRY_BKPT
: /* SW BKPT (?) */
1419 case DSCRV8_ENTRY_RESET_CATCH
: /* Reset catch */
1420 case DSCRV8_ENTRY_OS_UNLOCK
: /*OS unlock catch*/
1421 case DSCRV8_ENTRY_EXCEPTION_CATCH
: /*exception catch*/
1422 case DSCRV8_ENTRY_SW_ACCESS_DBG
: /*SW access dbg register*/
1423 target
->debug_reason
= DBG_REASON_BREAKPOINT
;
1425 case DSCRV8_ENTRY_WATCHPOINT
: /* asynch watchpoint */
1426 target
->debug_reason
= DBG_REASON_WATCHPOINT
;
1429 target
->debug_reason
= DBG_REASON_UNDEFINED
;
1435 /*----------------------------------------------------------------------*/
1438 * Setup and management support.
1442 * Hooks up this DPM to its associated target; call only once.
1443 * Initially this only covers the register cache.
1445 * Oh, and watchpoints. Yeah.
1447 int armv8_dpm_setup(struct arm_dpm
*dpm
)
1449 struct arm
*arm
= dpm
->arm
;
1450 struct target
*target
= arm
->target
;
1451 struct reg_cache
*cache
;
1454 /* register access setup */
1455 arm
->full_context
= armv8_dpm_full_context
;
1456 arm
->read_core_reg
= armv8_dpm_read_core_reg
;
1457 arm
->write_core_reg
= armv8_dpm_write_core_reg
;
1459 if (arm
->core_cache
== NULL
) {
1460 cache
= armv8_build_reg_cache(target
);
1465 /* coprocessor access setup */
1466 arm
->mrc
= dpmv8_mrc
;
1467 arm
->mcr
= dpmv8_mcr
;
1468 arm
->mrs
= dpmv8_mrs
;
1469 arm
->msr
= dpmv8_msr
;
1471 dpm
->prepare
= dpmv8_dpm_prepare
;
1472 dpm
->finish
= dpmv8_dpm_finish
;
1474 dpm
->instr_execute
= dpmv8_instr_execute
;
1475 dpm
->instr_write_data_dcc
= dpmv8_instr_write_data_dcc
;
1476 dpm
->instr_write_data_dcc_64
= dpmv8_instr_write_data_dcc_64
;
1477 dpm
->instr_write_data_r0
= dpmv8_instr_write_data_r0
;
1478 dpm
->instr_write_data_r0_64
= dpmv8_instr_write_data_r0_64
;
1479 dpm
->instr_cpsr_sync
= dpmv8_instr_cpsr_sync
;
1481 dpm
->instr_read_data_dcc
= dpmv8_instr_read_data_dcc
;
1482 dpm
->instr_read_data_dcc_64
= dpmv8_instr_read_data_dcc_64
;
1483 dpm
->instr_read_data_r0
= dpmv8_instr_read_data_r0
;
1484 dpm
->instr_read_data_r0_64
= dpmv8_instr_read_data_r0_64
;
1486 dpm
->arm_reg_current
= armv8_reg_current
;
1488 /* dpm->bpwp_enable = dpmv8_bpwp_enable; */
1489 dpm
->bpwp_disable
= dpmv8_bpwp_disable
;
1491 /* breakpoint setup -- optional until it works everywhere */
1492 if (!target
->type
->add_breakpoint
) {
1493 target
->type
->add_breakpoint
= dpmv8_add_breakpoint
;
1494 target
->type
->remove_breakpoint
= dpmv8_remove_breakpoint
;
1497 /* watchpoint setup */
1498 target
->type
->add_watchpoint
= dpmv8_add_watchpoint
;
1499 target
->type
->remove_watchpoint
= dpmv8_remove_watchpoint
;
1501 /* FIXME add vector catch support */
1503 dpm
->nbp
= 1 + ((dpm
->didr
>> 12) & 0xf);
1504 dpm
->dbp
= calloc(dpm
->nbp
, sizeof *dpm
->dbp
);
1506 dpm
->nwp
= 1 + ((dpm
->didr
>> 20) & 0xf);
1507 dpm
->dwp
= calloc(dpm
->nwp
, sizeof *dpm
->dwp
);
1509 if (!dpm
->dbp
|| !dpm
->dwp
) {
1515 LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
1516 target_name(target
), dpm
->nbp
, dpm
->nwp
);
1518 /* REVISIT ... and some of those breakpoints could match
1519 * execution context IDs...
1526 * Reinitializes DPM state at the beginning of a new debug session
1527 * or after a reset which may have affected the debug module.
1529 int armv8_dpm_initialize(struct arm_dpm
*dpm
)
1531 /* Disable all breakpoints and watchpoints at startup. */
1532 if (dpm
->bpwp_disable
) {
1535 for (i
= 0; i
< dpm
->nbp
; i
++) {
1536 dpm
->dbp
[i
].bpwp
.number
= i
;
1537 (void) dpm
->bpwp_disable(dpm
, i
);
1539 for (i
= 0; i
< dpm
->nwp
; i
++) {
1540 dpm
->dwp
[i
].bpwp
.number
= 16 + i
;
1541 (void) dpm
->bpwp_disable(dpm
, 16 + i
);
1544 LOG_WARNING("%s: can't disable breakpoints and watchpoints",
1545 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)