1 /***************************************************************************
2 * Copyright (C) 2015 by David Ung *
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. *
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., *
18 ***************************************************************************/
24 #include "breakpoints.h"
27 #include "target_request.h"
28 #include "target_type.h"
29 #include "armv8_opcodes.h"
30 #include "armv8_cache.h"
31 #include <helper/time_support.h>
33 static int aarch64_poll(struct target
*target
);
34 static int aarch64_debug_entry(struct target
*target
);
35 static int aarch64_restore_context(struct target
*target
, bool bpwp
);
36 static int aarch64_set_breakpoint(struct target
*target
,
37 struct breakpoint
*breakpoint
, uint8_t matchmode
);
38 static int aarch64_set_context_breakpoint(struct target
*target
,
39 struct breakpoint
*breakpoint
, uint8_t matchmode
);
40 static int aarch64_set_hybrid_breakpoint(struct target
*target
,
41 struct breakpoint
*breakpoint
);
42 static int aarch64_unset_breakpoint(struct target
*target
,
43 struct breakpoint
*breakpoint
);
44 static int aarch64_mmu(struct target
*target
, int *enabled
);
45 static int aarch64_virt2phys(struct target
*target
,
46 target_addr_t virt
, target_addr_t
*phys
);
47 static int aarch64_read_apb_ap_memory(struct target
*target
,
48 uint64_t address
, uint32_t size
, uint32_t count
, uint8_t *buffer
);
49 static int aarch64_instr_write_data_r0(struct arm_dpm
*dpm
,
50 uint32_t opcode
, uint32_t data
);
52 static int aarch64_restore_system_control_reg(struct target
*target
)
54 int retval
= ERROR_OK
;
56 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
57 struct armv8_common
*armv8
= target_to_armv8(target
);
59 if (aarch64
->system_control_reg
!= aarch64
->system_control_reg_curr
) {
60 aarch64
->system_control_reg_curr
= aarch64
->system_control_reg
;
61 /* LOG_INFO("cp15_control_reg: %8.8" PRIx32, cortex_v8->cp15_control_reg); */
63 switch (armv8
->arm
.core_mode
) {
67 retval
= armv8
->arm
.msr(target
, 3, /*op 0*/
70 aarch64
->system_control_reg
);
71 if (retval
!= ERROR_OK
)
76 retval
= armv8
->arm
.msr(target
, 3, /*op 0*/
79 aarch64
->system_control_reg
);
80 if (retval
!= ERROR_OK
)
85 retval
= armv8
->arm
.msr(target
, 3, /*op 0*/
88 aarch64
->system_control_reg
);
89 if (retval
!= ERROR_OK
)
93 LOG_DEBUG("unknow cpu state 0x%x" PRIx32
, armv8
->arm
.core_state
);
99 /* check address before aarch64_apb read write access with mmu on
100 * remove apb predictible data abort */
101 static int aarch64_check_address(struct target
*target
, uint32_t address
)
106 /* modify system_control_reg in order to enable or disable mmu for :
107 * - virt2phys address conversion
108 * - read or write memory in phys or virt address */
109 static int aarch64_mmu_modify(struct target
*target
, int enable
)
111 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
112 struct armv8_common
*armv8
= &aarch64
->armv8_common
;
113 int retval
= ERROR_OK
;
116 /* if mmu enabled at target stop and mmu not enable */
117 if (!(aarch64
->system_control_reg
& 0x1U
)) {
118 LOG_ERROR("trying to enable mmu on target stopped with mmu disable");
121 if (!(aarch64
->system_control_reg_curr
& 0x1U
)) {
122 aarch64
->system_control_reg_curr
|= 0x1U
;
123 switch (armv8
->arm
.core_mode
) {
127 retval
= armv8
->arm
.msr(target
, 3, /*op 0*/
130 aarch64
->system_control_reg_curr
);
131 if (retval
!= ERROR_OK
)
136 retval
= armv8
->arm
.msr(target
, 3, /*op 0*/
139 aarch64
->system_control_reg_curr
);
140 if (retval
!= ERROR_OK
)
145 retval
= armv8
->arm
.msr(target
, 3, /*op 0*/
148 aarch64
->system_control_reg_curr
);
149 if (retval
!= ERROR_OK
)
153 LOG_DEBUG("unknow cpu state 0x%x" PRIx32
, armv8
->arm
.core_state
);
157 if (aarch64
->system_control_reg_curr
& 0x4U
) {
158 /* data cache is active */
159 aarch64
->system_control_reg_curr
&= ~0x4U
;
160 /* flush data cache armv7 function to be called */
161 if (armv8
->armv8_mmu
.armv8_cache
.flush_all_data_cache
)
162 armv8
->armv8_mmu
.armv8_cache
.flush_all_data_cache(target
);
164 if ((aarch64
->system_control_reg_curr
& 0x1U
)) {
165 aarch64
->system_control_reg_curr
&= ~0x1U
;
166 switch (armv8
->arm
.core_mode
) {
170 retval
= armv8
->arm
.msr(target
, 3, /*op 0*/
173 aarch64
->system_control_reg_curr
);
174 if (retval
!= ERROR_OK
)
179 retval
= armv8
->arm
.msr(target
, 3, /*op 0*/
182 aarch64
->system_control_reg_curr
);
183 if (retval
!= ERROR_OK
)
188 retval
= armv8
->arm
.msr(target
, 3, /*op 0*/
191 aarch64
->system_control_reg_curr
);
192 if (retval
!= ERROR_OK
)
196 LOG_DEBUG("unknow cpu state 0x%x" PRIx32
, armv8
->arm
.core_state
);
205 * Basic debug access, very low level assumes state is saved
207 static int aarch64_init_debug_access(struct target
*target
)
209 struct armv8_common
*armv8
= target_to_armv8(target
);
215 /* Unlocking the debug registers for modification
216 * The debugport might be uninitialised so try twice */
217 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
218 armv8
->debug_base
+ CPUV8_DBG_LOCKACCESS
, 0xC5ACCE55);
219 if (retval
!= ERROR_OK
) {
221 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
222 armv8
->debug_base
+ CPUV8_DBG_LOCKACCESS
, 0xC5ACCE55);
223 if (retval
== ERROR_OK
)
224 LOG_USER("Locking debug access failed on first, but succeeded on second try.");
226 if (retval
!= ERROR_OK
)
228 /* Clear Sticky Power Down status Bit in PRSR to enable access to
229 the registers in the Core Power Domain */
230 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
231 armv8
->debug_base
+ CPUV8_DBG_PRSR
, &dummy
);
232 if (retval
!= ERROR_OK
)
235 /* Enabling of instruction execution in debug mode is done in debug_entry code */
237 /* Resync breakpoint registers */
239 /* Since this is likely called from init or reset, update target state information*/
240 return aarch64_poll(target
);
243 /* To reduce needless round-trips, pass in a pointer to the current
244 * DSCR value. Initialize it to zero if you just need to know the
245 * value on return from this function; or DSCR_ITE if you
246 * happen to know that no instruction is pending.
248 static int aarch64_exec_opcode(struct target
*target
,
249 uint32_t opcode
, uint32_t *dscr_p
)
253 struct armv8_common
*armv8
= target_to_armv8(target
);
254 dscr
= dscr_p
? *dscr_p
: 0;
256 LOG_DEBUG("exec opcode 0x%08" PRIx32
, opcode
);
258 /* Wait for InstrCompl bit to be set */
259 long long then
= timeval_ms();
260 while ((dscr
& DSCR_ITE
) == 0) {
261 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
262 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
263 if (retval
!= ERROR_OK
) {
264 LOG_ERROR("Could not read DSCR register, opcode = 0x%08" PRIx32
, opcode
);
267 if (timeval_ms() > then
+ 1000) {
268 LOG_ERROR("Timeout waiting for aarch64_exec_opcode");
273 retval
= mem_ap_write_u32(armv8
->debug_ap
,
274 armv8
->debug_base
+ CPUV8_DBG_ITR
, opcode
);
275 if (retval
!= ERROR_OK
)
280 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
281 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
282 if (retval
!= ERROR_OK
) {
283 LOG_ERROR("Could not read DSCR register");
286 if (timeval_ms() > then
+ 1000) {
287 LOG_ERROR("Timeout waiting for aarch64_exec_opcode");
290 } while ((dscr
& DSCR_ITE
) == 0); /* Wait for InstrCompl bit to be set */
298 /* Write to memory mapped registers directly with no cache or mmu handling */
299 static int aarch64_dap_write_memap_register_u32(struct target
*target
,
304 struct armv8_common
*armv8
= target_to_armv8(target
);
306 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
, address
, value
);
312 * AARCH64 implementation of Debug Programmer's Model
314 * NOTE the invariant: these routines return with DSCR_ITE set,
315 * so there's no need to poll for it before executing an instruction.
317 * NOTE that in several of these cases the "stall" mode might be useful.
318 * It'd let us queue a few operations together... prepare/finish might
319 * be the places to enable/disable that mode.
322 static inline struct aarch64_common
*dpm_to_a8(struct arm_dpm
*dpm
)
324 return container_of(dpm
, struct aarch64_common
, armv8_common
.dpm
);
327 static int aarch64_write_dcc(struct armv8_common
*armv8
, uint32_t data
)
329 LOG_DEBUG("write DCC 0x%08" PRIx32
, data
);
330 return mem_ap_write_u32(armv8
->debug_ap
,
331 armv8
->debug_base
+ CPUV8_DBG_DTRRX
, data
);
334 static int aarch64_write_dcc_64(struct armv8_common
*armv8
, uint64_t data
)
337 LOG_DEBUG("write DCC Low word0x%08" PRIx32
, (unsigned)data
);
338 LOG_DEBUG("write DCC High word 0x%08" PRIx32
, (unsigned)(data
>> 32));
339 ret
= mem_ap_write_u32(armv8
->debug_ap
,
340 armv8
->debug_base
+ CPUV8_DBG_DTRRX
, data
);
341 ret
+= mem_ap_write_u32(armv8
->debug_ap
,
342 armv8
->debug_base
+ CPUV8_DBG_DTRTX
, data
>> 32);
346 static int aarch64_read_dcc(struct armv8_common
*armv8
, uint32_t *data
,
349 uint32_t dscr
= DSCR_ITE
;
355 /* Wait for DTRRXfull */
356 long long then
= timeval_ms();
357 while ((dscr
& DSCR_DTR_TX_FULL
) == 0) {
358 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
359 armv8
->debug_base
+ CPUV8_DBG_DSCR
,
361 if (retval
!= ERROR_OK
)
363 if (timeval_ms() > then
+ 1000) {
364 LOG_ERROR("Timeout waiting for read dcc");
369 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
370 armv8
->debug_base
+ CPUV8_DBG_DTRTX
,
372 if (retval
!= ERROR_OK
)
374 LOG_DEBUG("read DCC 0x%08" PRIx32
, *data
);
382 static int aarch64_read_dcc_64(struct armv8_common
*armv8
, uint64_t *data
,
385 uint32_t dscr
= DSCR_ITE
;
392 /* Wait for DTRRXfull */
393 long long then
= timeval_ms();
394 while ((dscr
& DSCR_DTR_TX_FULL
) == 0) {
395 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
396 armv8
->debug_base
+ CPUV8_DBG_DSCR
,
398 if (retval
!= ERROR_OK
)
400 if (timeval_ms() > then
+ 1000) {
401 LOG_ERROR("Timeout waiting for read dcc");
406 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
407 armv8
->debug_base
+ CPUV8_DBG_DTRTX
,
409 if (retval
!= ERROR_OK
)
412 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
413 armv8
->debug_base
+ CPUV8_DBG_DTRRX
,
415 if (retval
!= ERROR_OK
)
418 *data
= *(uint32_t *)data
| (uint64_t)higher
<< 32;
419 LOG_DEBUG("read DCC 0x%16.16" PRIx64
, *data
);
427 static int aarch64_dpm_prepare(struct arm_dpm
*dpm
)
429 struct aarch64_common
*a8
= dpm_to_a8(dpm
);
433 /* set up invariant: INSTR_COMP is set after ever DPM operation */
434 long long then
= timeval_ms();
436 retval
= mem_ap_read_atomic_u32(a8
->armv8_common
.debug_ap
,
437 a8
->armv8_common
.debug_base
+ CPUV8_DBG_DSCR
,
439 if (retval
!= ERROR_OK
)
441 if ((dscr
& DSCR_ITE
) != 0)
443 if (timeval_ms() > then
+ 1000) {
444 LOG_ERROR("Timeout waiting for dpm prepare");
449 /* this "should never happen" ... */
450 if (dscr
& DSCR_DTR_RX_FULL
) {
451 LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32
, dscr
);
453 retval
= mem_ap_read_u32(a8
->armv8_common
.debug_ap
,
454 a8
->armv8_common
.debug_base
+ CPUV8_DBG_DTRRX
, &dscr
);
455 if (retval
!= ERROR_OK
)
458 /* Clear sticky error */
459 retval
= mem_ap_write_u32(a8
->armv8_common
.debug_ap
,
460 a8
->armv8_common
.debug_base
+ CPUV8_DBG_DRCR
, DRCR_CSE
);
461 if (retval
!= ERROR_OK
)
468 static int aarch64_dpm_finish(struct arm_dpm
*dpm
)
470 /* REVISIT what could be done here? */
474 static int aarch64_instr_execute(struct arm_dpm
*dpm
,
477 struct aarch64_common
*a8
= dpm_to_a8(dpm
);
478 uint32_t dscr
= DSCR_ITE
;
480 return aarch64_exec_opcode(
481 a8
->armv8_common
.arm
.target
,
486 static int aarch64_instr_write_data_dcc(struct arm_dpm
*dpm
,
487 uint32_t opcode
, uint32_t data
)
489 struct aarch64_common
*a8
= dpm_to_a8(dpm
);
491 uint32_t dscr
= DSCR_ITE
;
493 retval
= aarch64_write_dcc(&a8
->armv8_common
, data
);
494 if (retval
!= ERROR_OK
)
497 return aarch64_exec_opcode(
498 a8
->armv8_common
.arm
.target
,
503 static int aarch64_instr_write_data_dcc_64(struct arm_dpm
*dpm
,
504 uint32_t opcode
, uint64_t data
)
506 struct aarch64_common
*a8
= dpm_to_a8(dpm
);
508 uint32_t dscr
= DSCR_ITE
;
510 retval
= aarch64_write_dcc_64(&a8
->armv8_common
, data
);
511 if (retval
!= ERROR_OK
)
514 return aarch64_exec_opcode(
515 a8
->armv8_common
.arm
.target
,
520 static int aarch64_instr_write_data_r0(struct arm_dpm
*dpm
,
521 uint32_t opcode
, uint32_t data
)
523 struct aarch64_common
*a8
= dpm_to_a8(dpm
);
524 uint32_t dscr
= DSCR_ITE
;
527 retval
= aarch64_write_dcc(&a8
->armv8_common
, data
);
528 if (retval
!= ERROR_OK
)
531 retval
= aarch64_exec_opcode(
532 a8
->armv8_common
.arm
.target
,
533 ARMV8_MRS(SYSTEM_DBG_DTRRX_EL0
, 0),
535 if (retval
!= ERROR_OK
)
538 /* then the opcode, taking data from R0 */
539 retval
= aarch64_exec_opcode(
540 a8
->armv8_common
.arm
.target
,
547 static int aarch64_instr_write_data_r0_64(struct arm_dpm
*dpm
,
548 uint32_t opcode
, uint64_t data
)
550 struct aarch64_common
*a8
= dpm_to_a8(dpm
);
551 uint32_t dscr
= DSCR_ITE
;
554 retval
= aarch64_write_dcc_64(&a8
->armv8_common
, data
);
555 if (retval
!= ERROR_OK
)
558 retval
= aarch64_exec_opcode(
559 a8
->armv8_common
.arm
.target
,
560 ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0
, 0),
562 if (retval
!= ERROR_OK
)
565 /* then the opcode, taking data from R0 */
566 retval
= aarch64_exec_opcode(
567 a8
->armv8_common
.arm
.target
,
574 static int aarch64_instr_cpsr_sync(struct arm_dpm
*dpm
)
576 struct target
*target
= dpm
->arm
->target
;
577 uint32_t dscr
= DSCR_ITE
;
579 /* "Prefetch flush" after modifying execution status in CPSR */
580 return aarch64_exec_opcode(target
,
585 static int aarch64_instr_read_data_dcc(struct arm_dpm
*dpm
,
586 uint32_t opcode
, uint32_t *data
)
588 struct aarch64_common
*a8
= dpm_to_a8(dpm
);
590 uint32_t dscr
= DSCR_ITE
;
592 /* the opcode, writing data to DCC */
593 retval
= aarch64_exec_opcode(
594 a8
->armv8_common
.arm
.target
,
597 if (retval
!= ERROR_OK
)
600 return aarch64_read_dcc(&a8
->armv8_common
, data
, &dscr
);
603 static int aarch64_instr_read_data_dcc_64(struct arm_dpm
*dpm
,
604 uint32_t opcode
, uint64_t *data
)
606 struct aarch64_common
*a8
= dpm_to_a8(dpm
);
608 uint32_t dscr
= DSCR_ITE
;
610 /* the opcode, writing data to DCC */
611 retval
= aarch64_exec_opcode(
612 a8
->armv8_common
.arm
.target
,
615 if (retval
!= ERROR_OK
)
618 return aarch64_read_dcc_64(&a8
->armv8_common
, data
, &dscr
);
621 static int aarch64_instr_read_data_r0(struct arm_dpm
*dpm
,
622 uint32_t opcode
, uint32_t *data
)
624 struct aarch64_common
*a8
= dpm_to_a8(dpm
);
625 uint32_t dscr
= DSCR_ITE
;
628 /* the opcode, writing data to R0 */
629 retval
= aarch64_exec_opcode(
630 a8
->armv8_common
.arm
.target
,
633 if (retval
!= ERROR_OK
)
636 /* write R0 to DCC */
637 retval
= aarch64_exec_opcode(
638 a8
->armv8_common
.arm
.target
,
639 ARMV8_MSR_GP(SYSTEM_DBG_DTRTX_EL0
, 0), /* msr dbgdtr_el0, x0 */
641 if (retval
!= ERROR_OK
)
644 return aarch64_read_dcc(&a8
->armv8_common
, data
, &dscr
);
647 static int aarch64_instr_read_data_r0_64(struct arm_dpm
*dpm
,
648 uint32_t opcode
, uint64_t *data
)
650 struct aarch64_common
*a8
= dpm_to_a8(dpm
);
651 uint32_t dscr
= DSCR_ITE
;
654 /* the opcode, writing data to R0 */
655 retval
= aarch64_exec_opcode(
656 a8
->armv8_common
.arm
.target
,
659 if (retval
!= ERROR_OK
)
662 /* write R0 to DCC */
663 retval
= aarch64_exec_opcode(
664 a8
->armv8_common
.arm
.target
,
665 ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0
, 0), /* msr dbgdtr_el0, x0 */
667 if (retval
!= ERROR_OK
)
670 return aarch64_read_dcc_64(&a8
->armv8_common
, data
, &dscr
);
673 static int aarch64_bpwp_enable(struct arm_dpm
*dpm
, unsigned index_t
,
674 uint32_t addr
, uint32_t control
)
676 struct aarch64_common
*a8
= dpm_to_a8(dpm
);
677 uint32_t vr
= a8
->armv8_common
.debug_base
;
678 uint32_t cr
= a8
->armv8_common
.debug_base
;
682 case 0 ... 15: /* breakpoints */
683 vr
+= CPUV8_DBG_BVR_BASE
;
684 cr
+= CPUV8_DBG_BCR_BASE
;
686 case 16 ... 31: /* watchpoints */
687 vr
+= CPUV8_DBG_WVR_BASE
;
688 cr
+= CPUV8_DBG_WCR_BASE
;
697 LOG_DEBUG("A8: bpwp enable, vr %08x cr %08x",
698 (unsigned) vr
, (unsigned) cr
);
700 retval
= aarch64_dap_write_memap_register_u32(dpm
->arm
->target
,
702 if (retval
!= ERROR_OK
)
704 retval
= aarch64_dap_write_memap_register_u32(dpm
->arm
->target
,
709 static int aarch64_bpwp_disable(struct arm_dpm
*dpm
, unsigned index_t
)
711 struct aarch64_common
*a
= dpm_to_a8(dpm
);
716 cr
= a
->armv8_common
.debug_base
+ CPUV8_DBG_BCR_BASE
;
719 cr
= a
->armv8_common
.debug_base
+ CPUV8_DBG_WCR_BASE
;
727 LOG_DEBUG("A: bpwp disable, cr %08x", (unsigned) cr
);
729 /* clear control register */
730 return aarch64_dap_write_memap_register_u32(dpm
->arm
->target
, cr
, 0);
734 static int aarch64_dpm_setup(struct aarch64_common
*a8
, uint64_t debug
)
736 struct arm_dpm
*dpm
= &a8
->armv8_common
.dpm
;
739 dpm
->arm
= &a8
->armv8_common
.arm
;
742 dpm
->prepare
= aarch64_dpm_prepare
;
743 dpm
->finish
= aarch64_dpm_finish
;
745 dpm
->instr_execute
= aarch64_instr_execute
;
746 dpm
->instr_write_data_dcc
= aarch64_instr_write_data_dcc
;
747 dpm
->instr_write_data_dcc_64
= aarch64_instr_write_data_dcc_64
;
748 dpm
->instr_write_data_r0
= aarch64_instr_write_data_r0
;
749 dpm
->instr_write_data_r0_64
= aarch64_instr_write_data_r0_64
;
750 dpm
->instr_cpsr_sync
= aarch64_instr_cpsr_sync
;
752 dpm
->instr_read_data_dcc
= aarch64_instr_read_data_dcc
;
753 dpm
->instr_read_data_dcc_64
= aarch64_instr_read_data_dcc_64
;
754 dpm
->instr_read_data_r0
= aarch64_instr_read_data_r0
;
755 dpm
->instr_read_data_r0_64
= aarch64_instr_read_data_r0_64
;
757 dpm
->arm_reg_current
= armv8_reg_current
;
759 dpm
->bpwp_enable
= aarch64_bpwp_enable
;
760 dpm
->bpwp_disable
= aarch64_bpwp_disable
;
762 retval
= armv8_dpm_setup(dpm
);
763 if (retval
== ERROR_OK
)
764 retval
= armv8_dpm_initialize(dpm
);
768 static struct target
*get_aarch64(struct target
*target
, int32_t coreid
)
770 struct target_list
*head
;
774 while (head
!= (struct target_list
*)NULL
) {
776 if ((curr
->coreid
== coreid
) && (curr
->state
== TARGET_HALTED
))
782 static int aarch64_halt(struct target
*target
);
784 static int aarch64_halt_smp(struct target
*target
)
787 struct target_list
*head
;
790 while (head
!= (struct target_list
*)NULL
) {
792 if ((curr
!= target
) && (curr
->state
!= TARGET_HALTED
))
793 retval
+= aarch64_halt(curr
);
799 static int update_halt_gdb(struct target
*target
)
802 if (target
->gdb_service
&& target
->gdb_service
->core
[0] == -1) {
803 target
->gdb_service
->target
= target
;
804 target
->gdb_service
->core
[0] = target
->coreid
;
805 retval
+= aarch64_halt_smp(target
);
811 * Cortex-A8 Run control
814 static int aarch64_poll(struct target
*target
)
816 int retval
= ERROR_OK
;
818 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
819 struct armv8_common
*armv8
= &aarch64
->armv8_common
;
820 enum target_state prev_target_state
= target
->state
;
821 /* toggle to another core is done by gdb as follow */
822 /* maint packet J core_id */
824 /* the next polling trigger an halt event sent to gdb */
825 if ((target
->state
== TARGET_HALTED
) && (target
->smp
) &&
826 (target
->gdb_service
) &&
827 (target
->gdb_service
->target
== NULL
)) {
828 target
->gdb_service
->target
=
829 get_aarch64(target
, target
->gdb_service
->core
[1]);
830 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
833 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
834 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
835 if (retval
!= ERROR_OK
)
837 aarch64
->cpudbg_dscr
= dscr
;
839 if (DSCR_RUN_MODE(dscr
) == 0x3) {
840 if (prev_target_state
!= TARGET_HALTED
) {
841 /* We have a halting debug event */
842 LOG_DEBUG("Target halted");
843 target
->state
= TARGET_HALTED
;
844 if ((prev_target_state
== TARGET_RUNNING
)
845 || (prev_target_state
== TARGET_UNKNOWN
)
846 || (prev_target_state
== TARGET_RESET
)) {
847 retval
= aarch64_debug_entry(target
);
848 if (retval
!= ERROR_OK
)
851 retval
= update_halt_gdb(target
);
852 if (retval
!= ERROR_OK
)
855 target_call_event_callbacks(target
,
856 TARGET_EVENT_HALTED
);
858 if (prev_target_state
== TARGET_DEBUG_RUNNING
) {
861 retval
= aarch64_debug_entry(target
);
862 if (retval
!= ERROR_OK
)
865 retval
= update_halt_gdb(target
);
866 if (retval
!= ERROR_OK
)
870 target_call_event_callbacks(target
,
871 TARGET_EVENT_DEBUG_HALTED
);
875 target
->state
= TARGET_RUNNING
;
880 static int aarch64_halt(struct target
*target
)
882 int retval
= ERROR_OK
;
884 struct armv8_common
*armv8
= target_to_armv8(target
);
887 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
888 armv8
->cti_base
+ CTI_CTR
, 1);
889 if (retval
!= ERROR_OK
)
892 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
893 armv8
->cti_base
+ CTI_GATE
, 3);
894 if (retval
!= ERROR_OK
)
897 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
898 armv8
->cti_base
+ CTI_OUTEN0
, 1);
899 if (retval
!= ERROR_OK
)
902 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
903 armv8
->cti_base
+ CTI_OUTEN1
, 2);
904 if (retval
!= ERROR_OK
)
908 * add HDE in halting debug mode
910 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
911 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
912 if (retval
!= ERROR_OK
)
915 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
916 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
| DSCR_HDE
);
917 if (retval
!= ERROR_OK
)
920 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
921 armv8
->cti_base
+ CTI_APPPULSE
, 1);
922 if (retval
!= ERROR_OK
)
925 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
926 armv8
->cti_base
+ CTI_INACK
, 1);
927 if (retval
!= ERROR_OK
)
931 long long then
= timeval_ms();
933 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
934 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
935 if (retval
!= ERROR_OK
)
937 if ((dscr
& DSCRV8_HALT_MASK
) != 0)
939 if (timeval_ms() > then
+ 1000) {
940 LOG_ERROR("Timeout waiting for halt");
945 target
->debug_reason
= DBG_REASON_DBGRQ
;
950 static int aarch64_internal_restore(struct target
*target
, int current
,
951 uint64_t *address
, int handle_breakpoints
, int debug_execution
)
953 struct armv8_common
*armv8
= target_to_armv8(target
);
954 struct arm
*arm
= &armv8
->arm
;
958 if (!debug_execution
)
959 target_free_all_working_areas(target
);
961 /* current = 1: continue on current pc, otherwise continue at <address> */
962 resume_pc
= buf_get_u64(arm
->pc
->value
, 0, 64);
964 resume_pc
= *address
;
966 *address
= resume_pc
;
968 /* Make sure that the Armv7 gdb thumb fixups does not
969 * kill the return address
971 switch (arm
->core_state
) {
973 resume_pc
&= 0xFFFFFFFC;
975 case ARM_STATE_AARCH64
:
976 resume_pc
&= 0xFFFFFFFFFFFFFFFC;
978 case ARM_STATE_THUMB
:
979 case ARM_STATE_THUMB_EE
:
980 /* When the return address is loaded into PC
981 * bit 0 must be 1 to stay in Thumb state
985 case ARM_STATE_JAZELLE
:
986 LOG_ERROR("How do I resume into Jazelle state??");
989 LOG_DEBUG("resume pc = 0x%16" PRIx64
, resume_pc
);
990 buf_set_u64(arm
->pc
->value
, 0, 64, resume_pc
);
993 dpmv8_modeswitch(&armv8
->dpm
, ARM_MODE_ANY
);
995 /* called it now before restoring context because it uses cpu
996 * register r0 for restoring system control register */
997 retval
= aarch64_restore_system_control_reg(target
);
998 if (retval
!= ERROR_OK
)
1000 retval
= aarch64_restore_context(target
, handle_breakpoints
);
1001 if (retval
!= ERROR_OK
)
1003 target
->debug_reason
= DBG_REASON_NOTHALTED
;
1004 target
->state
= TARGET_RUNNING
;
1006 /* registers are now invalid */
1007 register_cache_invalidate(arm
->core_cache
);
1010 /* the front-end may request us not to handle breakpoints */
1011 if (handle_breakpoints
) {
1012 /* Single step past breakpoint at current address */
1013 breakpoint
= breakpoint_find(target
, resume_pc
);
1015 LOG_DEBUG("unset breakpoint at 0x%8.8x", breakpoint
->address
);
1016 cortex_m3_unset_breakpoint(target
, breakpoint
);
1017 cortex_m3_single_step_core(target
);
1018 cortex_m3_set_breakpoint(target
, breakpoint
);
1026 static int aarch64_internal_restart(struct target
*target
)
1028 struct armv8_common
*armv8
= target_to_armv8(target
);
1029 struct arm
*arm
= &armv8
->arm
;
1033 * * Restart core and wait for it to be started. Clear ITRen and sticky
1034 * * exception flags: see ARMv7 ARM, C5.9.
1036 * REVISIT: for single stepping, we probably want to
1037 * disable IRQs by default, with optional override...
1040 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
1041 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
1042 if (retval
!= ERROR_OK
)
1045 if ((dscr
& DSCR_ITE
) == 0)
1046 LOG_ERROR("DSCR InstrCompl must be set before leaving debug!");
1048 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1049 armv8
->cti_base
+ CTI_APPPULSE
, 2);
1050 if (retval
!= ERROR_OK
)
1053 long long then
= timeval_ms();
1055 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
1056 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
1057 if (retval
!= ERROR_OK
)
1059 if ((dscr
& DSCR_HDE
) != 0)
1061 if (timeval_ms() > then
+ 1000) {
1062 LOG_ERROR("Timeout waiting for resume");
1067 target
->debug_reason
= DBG_REASON_NOTHALTED
;
1068 target
->state
= TARGET_RUNNING
;
1070 /* registers are now invalid */
1071 register_cache_invalidate(arm
->core_cache
);
1076 static int aarch64_restore_smp(struct target
*target
, int handle_breakpoints
)
1079 struct target_list
*head
;
1080 struct target
*curr
;
1082 head
= target
->head
;
1083 while (head
!= (struct target_list
*)NULL
) {
1084 curr
= head
->target
;
1085 if ((curr
!= target
) && (curr
->state
!= TARGET_RUNNING
)) {
1086 /* resume current address , not in step mode */
1087 retval
+= aarch64_internal_restore(curr
, 1, &address
,
1088 handle_breakpoints
, 0);
1089 retval
+= aarch64_internal_restart(curr
);
1097 static int aarch64_resume(struct target
*target
, int current
,
1098 target_addr_t address
, int handle_breakpoints
, int debug_execution
)
1101 uint64_t addr
= address
;
1103 /* dummy resume for smp toggle in order to reduce gdb impact */
1104 if ((target
->smp
) && (target
->gdb_service
->core
[1] != -1)) {
1105 /* simulate a start and halt of target */
1106 target
->gdb_service
->target
= NULL
;
1107 target
->gdb_service
->core
[0] = target
->gdb_service
->core
[1];
1108 /* fake resume at next poll we play the target core[1], see poll*/
1109 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
1112 aarch64_internal_restore(target
, current
, &addr
, handle_breakpoints
,
1115 target
->gdb_service
->core
[0] = -1;
1116 retval
= aarch64_restore_smp(target
, handle_breakpoints
);
1117 if (retval
!= ERROR_OK
)
1120 aarch64_internal_restart(target
);
1122 if (!debug_execution
) {
1123 target
->state
= TARGET_RUNNING
;
1124 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
1125 LOG_DEBUG("target resumed at 0x%" PRIx64
, addr
);
1127 target
->state
= TARGET_DEBUG_RUNNING
;
1128 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_RESUMED
);
1129 LOG_DEBUG("target debug resumed at 0x%" PRIx64
, addr
);
1135 static int aarch64_debug_entry(struct target
*target
)
1137 int retval
= ERROR_OK
;
1138 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
1139 struct armv8_common
*armv8
= target_to_armv8(target
);
1141 LOG_DEBUG("dscr = 0x%08" PRIx32
, aarch64
->cpudbg_dscr
);
1143 /* REVISIT see A8 TRM 12.11.4 steps 2..3 -- make sure that any
1144 * imprecise data aborts get discarded by issuing a Data
1145 * Synchronization Barrier: ARMV4_5_MCR(15, 0, 0, 7, 10, 4).
1148 /* make sure to clear all sticky errors */
1149 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1150 armv8
->debug_base
+ CPUV8_DBG_DRCR
, DRCR_CSE
);
1151 if (retval
!= ERROR_OK
)
1154 /* Examine debug reason */
1155 armv8_dpm_report_dscr(&armv8
->dpm
, aarch64
->cpudbg_dscr
);
1157 /* save address of instruction that triggered the watchpoint? */
1158 if (target
->debug_reason
== DBG_REASON_WATCHPOINT
) {
1162 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
1163 armv8
->debug_base
+ CPUV8_DBG_WFAR1
,
1165 if (retval
!= ERROR_OK
)
1168 wfar
= (wfar
<< 32);
1169 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
1170 armv8
->debug_base
+ CPUV8_DBG_WFAR0
,
1172 if (retval
!= ERROR_OK
)
1175 armv8_dpm_report_wfar(&armv8
->dpm
, wfar
);
1178 retval
= armv8_dpm_read_current_registers(&armv8
->dpm
);
1180 if (armv8
->post_debug_entry
) {
1181 retval
= armv8
->post_debug_entry(target
);
1182 if (retval
!= ERROR_OK
)
1189 static int aarch64_post_debug_entry(struct target
*target
)
1191 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
1192 struct armv8_common
*armv8
= &aarch64
->armv8_common
;
1195 mem_ap_write_atomic_u32(armv8
->debug_ap
,
1196 armv8
->debug_base
+ CPUV8_DBG_DRCR
, 1<<2);
1197 switch (armv8
->arm
.core_mode
) {
1201 retval
= armv8
->arm
.mrs(target
, 3, /*op 0*/
1202 0, 0, /* op1, op2 */
1203 1, 0, /* CRn, CRm */
1204 &aarch64
->system_control_reg
);
1205 if (retval
!= ERROR_OK
)
1210 retval
= armv8
->arm
.mrs(target
, 3, /*op 0*/
1211 4, 0, /* op1, op2 */
1212 1, 0, /* CRn, CRm */
1213 &aarch64
->system_control_reg
);
1214 if (retval
!= ERROR_OK
)
1219 retval
= armv8
->arm
.mrs(target
, 3, /*op 0*/
1220 6, 0, /* op1, op2 */
1221 1, 0, /* CRn, CRm */
1222 &aarch64
->system_control_reg
);
1223 if (retval
!= ERROR_OK
)
1227 LOG_DEBUG("unknow cpu state 0x%x" PRIx32
, armv8
->arm
.core_state
);
1229 LOG_DEBUG("System_register: %8.8" PRIx32
, aarch64
->system_control_reg
);
1230 aarch64
->system_control_reg_curr
= aarch64
->system_control_reg
;
1232 if (armv8
->armv8_mmu
.armv8_cache
.ctype
== -1)
1233 armv8_identify_cache(target
);
1235 armv8
->armv8_mmu
.mmu_enabled
=
1236 (aarch64
->system_control_reg
& 0x1U
) ? 1 : 0;
1237 armv8
->armv8_mmu
.armv8_cache
.d_u_cache_enabled
=
1238 (aarch64
->system_control_reg
& 0x4U
) ? 1 : 0;
1239 armv8
->armv8_mmu
.armv8_cache
.i_cache_enabled
=
1240 (aarch64
->system_control_reg
& 0x1000U
) ? 1 : 0;
1241 aarch64
->curr_mode
= armv8
->arm
.core_mode
;
1245 static int aarch64_set_dscr_bits(struct target
*target
, unsigned long bit_mask
, unsigned long value
)
1247 struct armv8_common
*armv8
= target_to_armv8(target
);
1251 int retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
1252 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
1253 if (ERROR_OK
!= retval
)
1256 /* clear bitfield */
1259 dscr
|= value
& bit_mask
;
1261 /* write new DSCR */
1262 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1263 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
);
1267 static int aarch64_step(struct target
*target
, int current
, target_addr_t address
,
1268 int handle_breakpoints
)
1270 struct armv8_common
*armv8
= target_to_armv8(target
);
1274 if (target
->state
!= TARGET_HALTED
) {
1275 LOG_WARNING("target not halted");
1276 return ERROR_TARGET_NOT_HALTED
;
1279 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
1280 armv8
->debug_base
+ CPUV8_DBG_EDECR
, &edecr
);
1281 if (retval
!= ERROR_OK
)
1284 /* make sure EDECR.SS is not set when restoring the register */
1287 /* set EDECR.SS to enter hardware step mode */
1288 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1289 armv8
->debug_base
+ CPUV8_DBG_EDECR
, (edecr
|0x4));
1290 if (retval
!= ERROR_OK
)
1293 /* disable interrupts while stepping */
1294 retval
= aarch64_set_dscr_bits(target
, 0x3 << 22, 0x3 << 22);
1295 if (retval
!= ERROR_OK
)
1298 /* resume the target */
1299 retval
= aarch64_resume(target
, current
, address
, 0, 0);
1300 if (retval
!= ERROR_OK
)
1303 long long then
= timeval_ms();
1304 while (target
->state
!= TARGET_HALTED
) {
1305 retval
= aarch64_poll(target
);
1306 if (retval
!= ERROR_OK
)
1308 if (timeval_ms() > then
+ 1000) {
1309 LOG_ERROR("timeout waiting for target halt");
1315 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1316 armv8
->debug_base
+ CPUV8_DBG_EDECR
, edecr
);
1317 if (retval
!= ERROR_OK
)
1320 /* restore interrupts */
1321 retval
= aarch64_set_dscr_bits(target
, 0x3 << 22, 0);
1322 if (retval
!= ERROR_OK
)
1328 static int aarch64_restore_context(struct target
*target
, bool bpwp
)
1330 struct armv8_common
*armv8
= target_to_armv8(target
);
1334 if (armv8
->pre_restore_context
)
1335 armv8
->pre_restore_context(target
);
1337 return armv8_dpm_write_dirty_registers(&armv8
->dpm
, bpwp
);
1342 * Cortex-A8 Breakpoint and watchpoint functions
1345 /* Setup hardware Breakpoint Register Pair */
1346 static int aarch64_set_breakpoint(struct target
*target
,
1347 struct breakpoint
*breakpoint
, uint8_t matchmode
)
1352 uint8_t byte_addr_select
= 0x0F;
1353 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
1354 struct armv8_common
*armv8
= &aarch64
->armv8_common
;
1355 struct aarch64_brp
*brp_list
= aarch64
->brp_list
;
1358 if (breakpoint
->set
) {
1359 LOG_WARNING("breakpoint already set");
1363 if (breakpoint
->type
== BKPT_HARD
) {
1365 while (brp_list
[brp_i
].used
&& (brp_i
< aarch64
->brp_num
))
1367 if (brp_i
>= aarch64
->brp_num
) {
1368 LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
1369 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1371 breakpoint
->set
= brp_i
+ 1;
1372 if (breakpoint
->length
== 2)
1373 byte_addr_select
= (3 << (breakpoint
->address
& 0x02));
1374 control
= ((matchmode
& 0x7) << 20)
1376 | (byte_addr_select
<< 5)
1378 brp_list
[brp_i
].used
= 1;
1379 brp_list
[brp_i
].value
= breakpoint
->address
& 0xFFFFFFFFFFFFFFFC;
1380 brp_list
[brp_i
].control
= control
;
1381 bpt_value
= brp_list
[brp_i
].value
;
1383 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1384 + CPUV8_DBG_BVR_BASE
+ 16 * brp_list
[brp_i
].BRPn
,
1385 (uint32_t)(bpt_value
& 0xFFFFFFFF));
1386 if (retval
!= ERROR_OK
)
1388 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1389 + CPUV8_DBG_BVR_BASE
+ 4 + 16 * brp_list
[brp_i
].BRPn
,
1390 (uint32_t)(bpt_value
>> 32));
1391 if (retval
!= ERROR_OK
)
1394 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1395 + CPUV8_DBG_BCR_BASE
+ 16 * brp_list
[brp_i
].BRPn
,
1396 brp_list
[brp_i
].control
);
1397 if (retval
!= ERROR_OK
)
1399 LOG_DEBUG("brp %i control 0x%0" PRIx32
" value 0x%" TARGET_PRIxADDR
, brp_i
,
1400 brp_list
[brp_i
].control
,
1401 brp_list
[brp_i
].value
);
1403 } else if (breakpoint
->type
== BKPT_SOFT
) {
1406 buf_set_u32(code
, 0, 32, ARMV8_HLT(0x11));
1407 retval
= target_read_memory(target
,
1408 breakpoint
->address
& 0xFFFFFFFFFFFFFFFE,
1409 breakpoint
->length
, 1,
1410 breakpoint
->orig_instr
);
1411 if (retval
!= ERROR_OK
)
1414 armv8_cache_d_inner_flush_virt(armv8
,
1415 breakpoint
->address
& 0xFFFFFFFFFFFFFFFE,
1416 breakpoint
->length
);
1418 retval
= target_write_memory(target
,
1419 breakpoint
->address
& 0xFFFFFFFFFFFFFFFE,
1420 breakpoint
->length
, 1, code
);
1421 if (retval
!= ERROR_OK
)
1424 armv8_cache_d_inner_flush_virt(armv8
,
1425 breakpoint
->address
& 0xFFFFFFFFFFFFFFFE,
1426 breakpoint
->length
);
1428 armv8_cache_i_inner_inval_virt(armv8
,
1429 breakpoint
->address
& 0xFFFFFFFFFFFFFFFE,
1430 breakpoint
->length
);
1432 breakpoint
->set
= 0x11; /* Any nice value but 0 */
1435 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
1436 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
1437 /* Ensure that halting debug mode is enable */
1438 dscr
= dscr
| DSCR_HDE
;
1439 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1440 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
);
1441 if (retval
!= ERROR_OK
) {
1442 LOG_DEBUG("Failed to set DSCR.HDE");
1449 static int aarch64_set_context_breakpoint(struct target
*target
,
1450 struct breakpoint
*breakpoint
, uint8_t matchmode
)
1452 int retval
= ERROR_FAIL
;
1455 uint8_t byte_addr_select
= 0x0F;
1456 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
1457 struct armv8_common
*armv8
= &aarch64
->armv8_common
;
1458 struct aarch64_brp
*brp_list
= aarch64
->brp_list
;
1460 if (breakpoint
->set
) {
1461 LOG_WARNING("breakpoint already set");
1464 /*check available context BRPs*/
1465 while ((brp_list
[brp_i
].used
||
1466 (brp_list
[brp_i
].type
!= BRP_CONTEXT
)) && (brp_i
< aarch64
->brp_num
))
1469 if (brp_i
>= aarch64
->brp_num
) {
1470 LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
1474 breakpoint
->set
= brp_i
+ 1;
1475 control
= ((matchmode
& 0x7) << 20)
1477 | (byte_addr_select
<< 5)
1479 brp_list
[brp_i
].used
= 1;
1480 brp_list
[brp_i
].value
= (breakpoint
->asid
);
1481 brp_list
[brp_i
].control
= control
;
1482 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1483 + CPUV8_DBG_BVR_BASE
+ 16 * brp_list
[brp_i
].BRPn
,
1484 brp_list
[brp_i
].value
);
1485 if (retval
!= ERROR_OK
)
1487 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1488 + CPUV8_DBG_BCR_BASE
+ 16 * brp_list
[brp_i
].BRPn
,
1489 brp_list
[brp_i
].control
);
1490 if (retval
!= ERROR_OK
)
1492 LOG_DEBUG("brp %i control 0x%0" PRIx32
" value 0x%" TARGET_PRIxADDR
, brp_i
,
1493 brp_list
[brp_i
].control
,
1494 brp_list
[brp_i
].value
);
1499 static int aarch64_set_hybrid_breakpoint(struct target
*target
, struct breakpoint
*breakpoint
)
1501 int retval
= ERROR_FAIL
;
1502 int brp_1
= 0; /* holds the contextID pair */
1503 int brp_2
= 0; /* holds the IVA pair */
1504 uint32_t control_CTX
, control_IVA
;
1505 uint8_t CTX_byte_addr_select
= 0x0F;
1506 uint8_t IVA_byte_addr_select
= 0x0F;
1507 uint8_t CTX_machmode
= 0x03;
1508 uint8_t IVA_machmode
= 0x01;
1509 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
1510 struct armv8_common
*armv8
= &aarch64
->armv8_common
;
1511 struct aarch64_brp
*brp_list
= aarch64
->brp_list
;
1513 if (breakpoint
->set
) {
1514 LOG_WARNING("breakpoint already set");
1517 /*check available context BRPs*/
1518 while ((brp_list
[brp_1
].used
||
1519 (brp_list
[brp_1
].type
!= BRP_CONTEXT
)) && (brp_1
< aarch64
->brp_num
))
1522 printf("brp(CTX) found num: %d\n", brp_1
);
1523 if (brp_1
>= aarch64
->brp_num
) {
1524 LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
1528 while ((brp_list
[brp_2
].used
||
1529 (brp_list
[brp_2
].type
!= BRP_NORMAL
)) && (brp_2
< aarch64
->brp_num
))
1532 printf("brp(IVA) found num: %d\n", brp_2
);
1533 if (brp_2
>= aarch64
->brp_num
) {
1534 LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
1538 breakpoint
->set
= brp_1
+ 1;
1539 breakpoint
->linked_BRP
= brp_2
;
1540 control_CTX
= ((CTX_machmode
& 0x7) << 20)
1543 | (CTX_byte_addr_select
<< 5)
1545 brp_list
[brp_1
].used
= 1;
1546 brp_list
[brp_1
].value
= (breakpoint
->asid
);
1547 brp_list
[brp_1
].control
= control_CTX
;
1548 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1549 + CPUV8_DBG_BVR_BASE
+ 16 * brp_list
[brp_1
].BRPn
,
1550 brp_list
[brp_1
].value
);
1551 if (retval
!= ERROR_OK
)
1553 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1554 + CPUV8_DBG_BCR_BASE
+ 16 * brp_list
[brp_1
].BRPn
,
1555 brp_list
[brp_1
].control
);
1556 if (retval
!= ERROR_OK
)
1559 control_IVA
= ((IVA_machmode
& 0x7) << 20)
1562 | (IVA_byte_addr_select
<< 5)
1564 brp_list
[brp_2
].used
= 1;
1565 brp_list
[brp_2
].value
= breakpoint
->address
& 0xFFFFFFFFFFFFFFFC;
1566 brp_list
[brp_2
].control
= control_IVA
;
1567 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1568 + CPUV8_DBG_BVR_BASE
+ 16 * brp_list
[brp_2
].BRPn
,
1569 brp_list
[brp_2
].value
& 0xFFFFFFFF);
1570 if (retval
!= ERROR_OK
)
1572 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1573 + CPUV8_DBG_BVR_BASE
+ 4 + 16 * brp_list
[brp_2
].BRPn
,
1574 brp_list
[brp_2
].value
>> 32);
1575 if (retval
!= ERROR_OK
)
1577 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1578 + CPUV8_DBG_BCR_BASE
+ 16 * brp_list
[brp_2
].BRPn
,
1579 brp_list
[brp_2
].control
);
1580 if (retval
!= ERROR_OK
)
1586 static int aarch64_unset_breakpoint(struct target
*target
, struct breakpoint
*breakpoint
)
1589 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
1590 struct armv8_common
*armv8
= &aarch64
->armv8_common
;
1591 struct aarch64_brp
*brp_list
= aarch64
->brp_list
;
1593 if (!breakpoint
->set
) {
1594 LOG_WARNING("breakpoint not set");
1598 if (breakpoint
->type
== BKPT_HARD
) {
1599 if ((breakpoint
->address
!= 0) && (breakpoint
->asid
!= 0)) {
1600 int brp_i
= breakpoint
->set
- 1;
1601 int brp_j
= breakpoint
->linked_BRP
;
1602 if ((brp_i
< 0) || (brp_i
>= aarch64
->brp_num
)) {
1603 LOG_DEBUG("Invalid BRP number in breakpoint");
1606 LOG_DEBUG("rbp %i control 0x%0" PRIx32
" value 0x%" TARGET_PRIxADDR
, brp_i
,
1607 brp_list
[brp_i
].control
, brp_list
[brp_i
].value
);
1608 brp_list
[brp_i
].used
= 0;
1609 brp_list
[brp_i
].value
= 0;
1610 brp_list
[brp_i
].control
= 0;
1611 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1612 + CPUV8_DBG_BCR_BASE
+ 16 * brp_list
[brp_i
].BRPn
,
1613 brp_list
[brp_i
].control
);
1614 if (retval
!= ERROR_OK
)
1616 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1617 + CPUV8_DBG_BVR_BASE
+ 16 * brp_list
[brp_i
].BRPn
,
1618 (uint32_t)brp_list
[brp_i
].value
);
1619 if (retval
!= ERROR_OK
)
1621 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1622 + CPUV8_DBG_BVR_BASE
+ 4 + 16 * brp_list
[brp_i
].BRPn
,
1623 (uint32_t)brp_list
[brp_i
].value
);
1624 if (retval
!= ERROR_OK
)
1626 if ((brp_j
< 0) || (brp_j
>= aarch64
->brp_num
)) {
1627 LOG_DEBUG("Invalid BRP number in breakpoint");
1630 LOG_DEBUG("rbp %i control 0x%0" PRIx32
" value 0x%0" PRIx64
, brp_j
,
1631 brp_list
[brp_j
].control
, brp_list
[brp_j
].value
);
1632 brp_list
[brp_j
].used
= 0;
1633 brp_list
[brp_j
].value
= 0;
1634 brp_list
[brp_j
].control
= 0;
1635 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1636 + CPUV8_DBG_BCR_BASE
+ 16 * brp_list
[brp_j
].BRPn
,
1637 brp_list
[brp_j
].control
);
1638 if (retval
!= ERROR_OK
)
1640 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1641 + CPUV8_DBG_BVR_BASE
+ 16 * brp_list
[brp_j
].BRPn
,
1642 (uint32_t)brp_list
[brp_j
].value
);
1643 if (retval
!= ERROR_OK
)
1645 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1646 + CPUV8_DBG_BVR_BASE
+ 4 + 16 * brp_list
[brp_j
].BRPn
,
1647 (uint32_t)brp_list
[brp_j
].value
);
1648 if (retval
!= ERROR_OK
)
1651 breakpoint
->linked_BRP
= 0;
1652 breakpoint
->set
= 0;
1656 int brp_i
= breakpoint
->set
- 1;
1657 if ((brp_i
< 0) || (brp_i
>= aarch64
->brp_num
)) {
1658 LOG_DEBUG("Invalid BRP number in breakpoint");
1661 LOG_DEBUG("rbp %i control 0x%0" PRIx32
" value 0x%0" PRIx64
, brp_i
,
1662 brp_list
[brp_i
].control
, brp_list
[brp_i
].value
);
1663 brp_list
[brp_i
].used
= 0;
1664 brp_list
[brp_i
].value
= 0;
1665 brp_list
[brp_i
].control
= 0;
1666 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1667 + CPUV8_DBG_BCR_BASE
+ 16 * brp_list
[brp_i
].BRPn
,
1668 brp_list
[brp_i
].control
);
1669 if (retval
!= ERROR_OK
)
1671 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1672 + CPUV8_DBG_BVR_BASE
+ 16 * brp_list
[brp_i
].BRPn
,
1673 brp_list
[brp_i
].value
);
1674 if (retval
!= ERROR_OK
)
1677 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1678 + CPUV8_DBG_BVR_BASE
+ 4 + 16 * brp_list
[brp_i
].BRPn
,
1679 (uint32_t)brp_list
[brp_i
].value
);
1680 if (retval
!= ERROR_OK
)
1682 breakpoint
->set
= 0;
1686 /* restore original instruction (kept in target endianness) */
1688 armv8_cache_d_inner_flush_virt(armv8
,
1689 breakpoint
->address
& 0xFFFFFFFFFFFFFFFE,
1690 breakpoint
->length
);
1692 if (breakpoint
->length
== 4) {
1693 retval
= target_write_memory(target
,
1694 breakpoint
->address
& 0xFFFFFFFFFFFFFFFE,
1695 4, 1, breakpoint
->orig_instr
);
1696 if (retval
!= ERROR_OK
)
1699 retval
= target_write_memory(target
,
1700 breakpoint
->address
& 0xFFFFFFFFFFFFFFFE,
1701 2, 1, breakpoint
->orig_instr
);
1702 if (retval
!= ERROR_OK
)
1706 armv8_cache_d_inner_flush_virt(armv8
,
1707 breakpoint
->address
& 0xFFFFFFFFFFFFFFFE,
1708 breakpoint
->length
);
1710 armv8_cache_i_inner_inval_virt(armv8
,
1711 breakpoint
->address
& 0xFFFFFFFFFFFFFFFE,
1712 breakpoint
->length
);
1714 breakpoint
->set
= 0;
1719 static int aarch64_add_breakpoint(struct target
*target
,
1720 struct breakpoint
*breakpoint
)
1722 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
1724 if ((breakpoint
->type
== BKPT_HARD
) && (aarch64
->brp_num_available
< 1)) {
1725 LOG_INFO("no hardware breakpoint available");
1726 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1729 if (breakpoint
->type
== BKPT_HARD
)
1730 aarch64
->brp_num_available
--;
1732 return aarch64_set_breakpoint(target
, breakpoint
, 0x00); /* Exact match */
1735 static int aarch64_add_context_breakpoint(struct target
*target
,
1736 struct breakpoint
*breakpoint
)
1738 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
1740 if ((breakpoint
->type
== BKPT_HARD
) && (aarch64
->brp_num_available
< 1)) {
1741 LOG_INFO("no hardware breakpoint available");
1742 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1745 if (breakpoint
->type
== BKPT_HARD
)
1746 aarch64
->brp_num_available
--;
1748 return aarch64_set_context_breakpoint(target
, breakpoint
, 0x02); /* asid match */
1751 static int aarch64_add_hybrid_breakpoint(struct target
*target
,
1752 struct breakpoint
*breakpoint
)
1754 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
1756 if ((breakpoint
->type
== BKPT_HARD
) && (aarch64
->brp_num_available
< 1)) {
1757 LOG_INFO("no hardware breakpoint available");
1758 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1761 if (breakpoint
->type
== BKPT_HARD
)
1762 aarch64
->brp_num_available
--;
1764 return aarch64_set_hybrid_breakpoint(target
, breakpoint
); /* ??? */
1768 static int aarch64_remove_breakpoint(struct target
*target
, struct breakpoint
*breakpoint
)
1770 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
1773 /* It is perfectly possible to remove breakpoints while the target is running */
1774 if (target
->state
!= TARGET_HALTED
) {
1775 LOG_WARNING("target not halted");
1776 return ERROR_TARGET_NOT_HALTED
;
1780 if (breakpoint
->set
) {
1781 aarch64_unset_breakpoint(target
, breakpoint
);
1782 if (breakpoint
->type
== BKPT_HARD
)
1783 aarch64
->brp_num_available
++;
1790 * Cortex-A8 Reset functions
1793 static int aarch64_assert_reset(struct target
*target
)
1795 struct armv8_common
*armv8
= target_to_armv8(target
);
1799 /* FIXME when halt is requested, make it work somehow... */
1801 /* Issue some kind of warm reset. */
1802 if (target_has_event_action(target
, TARGET_EVENT_RESET_ASSERT
))
1803 target_handle_event(target
, TARGET_EVENT_RESET_ASSERT
);
1804 else if (jtag_get_reset_config() & RESET_HAS_SRST
) {
1805 /* REVISIT handle "pulls" cases, if there's
1806 * hardware that needs them to work.
1808 jtag_add_reset(0, 1);
1810 LOG_ERROR("%s: how to reset?", target_name(target
));
1814 /* registers are now invalid */
1815 register_cache_invalidate(armv8
->arm
.core_cache
);
1817 target
->state
= TARGET_RESET
;
1822 static int aarch64_deassert_reset(struct target
*target
)
1828 /* be certain SRST is off */
1829 jtag_add_reset(0, 0);
1831 retval
= aarch64_poll(target
);
1832 if (retval
!= ERROR_OK
)
1835 if (target
->reset_halt
) {
1836 if (target
->state
!= TARGET_HALTED
) {
1837 LOG_WARNING("%s: ran after reset and before halt ...",
1838 target_name(target
));
1839 retval
= target_halt(target
);
1840 if (retval
!= ERROR_OK
)
1848 static int aarch64_write_apb_ap_memory(struct target
*target
,
1849 uint64_t address
, uint32_t size
,
1850 uint32_t count
, const uint8_t *buffer
)
1852 /* write memory through APB-AP */
1853 int retval
= ERROR_COMMAND_SYNTAX_ERROR
;
1854 struct armv8_common
*armv8
= target_to_armv8(target
);
1855 struct arm
*arm
= &armv8
->arm
;
1856 int total_bytes
= count
* size
;
1858 int start_byte
= address
& 0x3;
1859 int end_byte
= (address
+ total_bytes
) & 0x3;
1862 uint8_t *tmp_buff
= NULL
;
1864 LOG_DEBUG("Writing APB-AP memory address 0x%" PRIx64
" size %" PRIu32
" count%" PRIu32
,
1865 address
, size
, count
);
1866 if (target
->state
!= TARGET_HALTED
) {
1867 LOG_WARNING("target not halted");
1868 return ERROR_TARGET_NOT_HALTED
;
1871 total_u32
= DIV_ROUND_UP((address
& 3) + total_bytes
, 4);
1873 /* Mark register R0 as dirty, as it will be used
1874 * for transferring the data.
1875 * It will be restored automatically when exiting
1878 reg
= armv8_reg_current(arm
, 1);
1881 reg
= armv8_reg_current(arm
, 0);
1884 /* clear any abort */
1885 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1886 armv8
->debug_base
+ CPUV8_DBG_DRCR
, DRCR_CSE
);
1887 if (retval
!= ERROR_OK
)
1891 /* This algorithm comes from DDI0487A.g, chapter J9.1 */
1893 /* The algorithm only copies 32 bit words, so the buffer
1894 * should be expanded to include the words at either end.
1895 * The first and last words will be read first to avoid
1896 * corruption if needed.
1898 tmp_buff
= malloc(total_u32
* 4);
1900 if ((start_byte
!= 0) && (total_u32
> 1)) {
1901 /* First bytes not aligned - read the 32 bit word to avoid corrupting
1902 * the other bytes in the word.
1904 retval
= aarch64_read_apb_ap_memory(target
, (address
& ~0x3), 4, 1, tmp_buff
);
1905 if (retval
!= ERROR_OK
)
1906 goto error_free_buff_w
;
1909 /* If end of write is not aligned, or the write is less than 4 bytes */
1910 if ((end_byte
!= 0) ||
1911 ((total_u32
== 1) && (total_bytes
!= 4))) {
1913 /* Read the last word to avoid corruption during 32 bit write */
1914 int mem_offset
= (total_u32
-1) * 4;
1915 retval
= aarch64_read_apb_ap_memory(target
, (address
& ~0x3) + mem_offset
, 4, 1, &tmp_buff
[mem_offset
]);
1916 if (retval
!= ERROR_OK
)
1917 goto error_free_buff_w
;
1920 /* Copy the write buffer over the top of the temporary buffer */
1921 memcpy(&tmp_buff
[start_byte
], buffer
, total_bytes
);
1923 /* We now have a 32 bit aligned buffer that can be written */
1926 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
1927 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
1928 if (retval
!= ERROR_OK
)
1929 goto error_free_buff_w
;
1931 /* Set Normal access mode */
1932 dscr
= (dscr
& ~DSCR_MA
);
1933 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1934 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
);
1936 if (arm
->core_state
== ARM_STATE_AARCH64
) {
1937 /* Write X0 with value 'address' using write procedure */
1938 /* Step 1.a+b - Write the address for read access into DBGDTR_EL0 */
1939 retval
+= aarch64_write_dcc_64(armv8
, address
& ~0x3ULL
);
1940 /* Step 1.c - Copy value from DTR to R0 using instruction mrs DBGDTR_EL0, x0 */
1941 retval
+= aarch64_exec_opcode(target
,
1942 ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0
, 0), &dscr
);
1944 /* Write R0 with value 'address' using write procedure */
1945 /* Step 1.a+b - Write the address for read access into DBGDTRRX */
1946 retval
+= aarch64_write_dcc(armv8
, address
& ~0x3ULL
);
1947 /* Step 1.c - Copy value from DTR to R0 using instruction mrc DBGDTRTXint, r0 */
1948 retval
+= aarch64_exec_opcode(target
,
1949 T32_FMTITR(ARMV4_5_MRC(14, 0, 0, 0, 5, 0)), &dscr
);
1952 /* Step 1.d - Change DCC to memory mode */
1953 dscr
= dscr
| DSCR_MA
;
1954 retval
+= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1955 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
);
1956 if (retval
!= ERROR_OK
)
1957 goto error_unset_dtr_w
;
1960 /* Step 2.a - Do the write */
1961 retval
= mem_ap_write_buf_noincr(armv8
->debug_ap
,
1962 tmp_buff
, 4, total_u32
, armv8
->debug_base
+ CPUV8_DBG_DTRRX
);
1963 if (retval
!= ERROR_OK
)
1964 goto error_unset_dtr_w
;
1966 /* Step 3.a - Switch DTR mode back to Normal mode */
1967 dscr
= (dscr
& ~DSCR_MA
);
1968 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1969 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
);
1970 if (retval
!= ERROR_OK
)
1971 goto error_unset_dtr_w
;
1973 /* Check for sticky abort flags in the DSCR */
1974 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
1975 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
1976 if (retval
!= ERROR_OK
)
1977 goto error_free_buff_w
;
1978 if (dscr
& (DSCR_ERR
| DSCR_SYS_ERROR_PEND
)) {
1979 /* Abort occurred - clear it and exit */
1980 LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32
, dscr
);
1981 mem_ap_write_atomic_u32(armv8
->debug_ap
,
1982 armv8
->debug_base
+ CPUV8_DBG_DRCR
, 1<<2);
1983 goto error_free_buff_w
;
1991 /* Unset DTR mode */
1992 mem_ap_read_atomic_u32(armv8
->debug_ap
,
1993 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
1994 dscr
= (dscr
& ~DSCR_MA
);
1995 mem_ap_write_atomic_u32(armv8
->debug_ap
,
1996 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
);
2003 static int aarch64_read_apb_ap_memory(struct target
*target
,
2004 target_addr_t address
, uint32_t size
,
2005 uint32_t count
, uint8_t *buffer
)
2007 /* read memory through APB-AP */
2008 int retval
= ERROR_COMMAND_SYNTAX_ERROR
;
2009 struct armv8_common
*armv8
= target_to_armv8(target
);
2010 struct arm
*arm
= &armv8
->arm
;
2011 int total_bytes
= count
* size
;
2013 int start_byte
= address
& 0x3;
2014 int end_byte
= (address
+ total_bytes
) & 0x3;
2017 uint8_t *tmp_buff
= NULL
;
2021 LOG_DEBUG("Reading APB-AP memory address 0x%" TARGET_PRIxADDR
" size %" PRIu32
" count%" PRIu32
,
2022 address
, size
, count
);
2023 if (target
->state
!= TARGET_HALTED
) {
2024 LOG_WARNING("target not halted");
2025 return ERROR_TARGET_NOT_HALTED
;
2028 total_u32
= DIV_ROUND_UP((address
& 3) + total_bytes
, 4);
2029 /* Mark register X0, X1 as dirty, as it will be used
2030 * for transferring the data.
2031 * It will be restored automatically when exiting
2034 reg
= armv8_reg_current(arm
, 1);
2037 reg
= armv8_reg_current(arm
, 0);
2040 /* clear any abort */
2041 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
2042 armv8
->debug_base
+ CPUV8_DBG_DRCR
, DRCR_CSE
);
2043 if (retval
!= ERROR_OK
)
2044 goto error_free_buff_r
;
2047 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2048 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
2050 /* This algorithm comes from DDI0487A.g, chapter J9.1 */
2052 /* Set Normal access mode */
2053 dscr
= (dscr
& ~DSCR_MA
);
2054 retval
+= mem_ap_write_atomic_u32(armv8
->debug_ap
,
2055 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
);
2057 if (arm
->core_state
== ARM_STATE_AARCH64
) {
2058 /* Write X0 with value 'address' using write procedure */
2059 /* Step 1.a+b - Write the address for read access into DBGDTR_EL0 */
2060 retval
+= aarch64_write_dcc_64(armv8
, address
& ~0x3ULL
);
2061 /* Step 1.c - Copy value from DTR to R0 using instruction mrs DBGDTR_EL0, x0 */
2062 retval
+= aarch64_exec_opcode(target
, ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0
, 0), &dscr
);
2063 /* Step 1.d - Dummy operation to ensure EDSCR.Txfull == 1 */
2064 retval
+= aarch64_exec_opcode(target
, ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0
, 0), &dscr
);
2065 /* Step 1.e - Change DCC to memory mode */
2066 dscr
= dscr
| DSCR_MA
;
2067 retval
+= mem_ap_write_atomic_u32(armv8
->debug_ap
,
2068 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
);
2069 /* Step 1.f - read DBGDTRTX and discard the value */
2070 retval
+= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2071 armv8
->debug_base
+ CPUV8_DBG_DTRTX
, &value
);
2073 /* Write R0 with value 'address' using write procedure */
2074 /* Step 1.a+b - Write the address for read access into DBGDTRRXint */
2075 retval
+= aarch64_write_dcc(armv8
, address
& ~0x3ULL
);
2076 /* Step 1.c - Copy value from DTR to R0 using instruction mrc DBGDTRTXint, r0 */
2077 retval
+= aarch64_exec_opcode(target
,
2078 T32_FMTITR(ARMV4_5_MRC(14, 0, 0, 0, 5, 0)), &dscr
);
2079 /* Step 1.d - Dummy operation to ensure EDSCR.Txfull == 1 */
2080 retval
+= aarch64_exec_opcode(target
,
2081 T32_FMTITR(ARMV4_5_MCR(14, 0, 0, 0, 5, 0)), &dscr
);
2082 /* Step 1.e - Change DCC to memory mode */
2083 dscr
= dscr
| DSCR_MA
;
2084 retval
+= mem_ap_write_atomic_u32(armv8
->debug_ap
,
2085 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
);
2086 /* Step 1.f - read DBGDTRTX and discard the value */
2087 retval
+= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2088 armv8
->debug_base
+ CPUV8_DBG_DTRTX
, &value
);
2091 if (retval
!= ERROR_OK
)
2092 goto error_unset_dtr_r
;
2094 /* Optimize the read as much as we can, either way we read in a single pass */
2095 if ((start_byte
) || (end_byte
)) {
2096 /* The algorithm only copies 32 bit words, so the buffer
2097 * should be expanded to include the words at either end.
2098 * The first and last words will be read into a temp buffer
2099 * to avoid corruption
2101 tmp_buff
= malloc(total_u32
* 4);
2103 goto error_unset_dtr_r
;
2105 /* use the tmp buffer to read the entire data */
2106 u8buf_ptr
= tmp_buff
;
2108 /* address and read length are aligned so read directly into the passed buffer */
2111 /* Read the data - Each read of the DTRTX register causes the instruction to be reissued
2112 * Abort flags are sticky, so can be read at end of transactions
2114 * This data is read in aligned to 32 bit boundary.
2117 /* Step 2.a - Loop n-1 times, each read of DBGDTRTX reads the data from [X0] and
2118 * increments X0 by 4. */
2119 retval
= mem_ap_read_buf_noincr(armv8
->debug_ap
, u8buf_ptr
, 4, total_u32
-1,
2120 armv8
->debug_base
+ CPUV8_DBG_DTRTX
);
2121 if (retval
!= ERROR_OK
)
2122 goto error_unset_dtr_r
;
2124 /* Step 3.a - set DTR access mode back to Normal mode */
2125 dscr
= (dscr
& ~DSCR_MA
);
2126 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
2127 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
);
2128 if (retval
!= ERROR_OK
)
2129 goto error_free_buff_r
;
2131 /* Step 3.b - read DBGDTRTX for the final value */
2132 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2133 armv8
->debug_base
+ CPUV8_DBG_DTRTX
, &value
);
2134 memcpy(u8buf_ptr
+ (total_u32
-1) * 4, &value
, 4);
2136 /* Check for sticky abort flags in the DSCR */
2137 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2138 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
2139 if (retval
!= ERROR_OK
)
2140 goto error_free_buff_r
;
2141 if (dscr
& (DSCR_ERR
| DSCR_SYS_ERROR_PEND
)) {
2142 /* Abort occurred - clear it and exit */
2143 LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32
, dscr
);
2144 mem_ap_write_atomic_u32(armv8
->debug_ap
,
2145 armv8
->debug_base
+ CPUV8_DBG_DRCR
, DRCR_CSE
);
2146 goto error_free_buff_r
;
2149 /* check if we need to copy aligned data by applying any shift necessary */
2151 memcpy(buffer
, tmp_buff
+ start_byte
, total_bytes
);
2159 /* Unset DTR mode */
2160 mem_ap_read_atomic_u32(armv8
->debug_ap
,
2161 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
2162 dscr
= (dscr
& ~DSCR_MA
);
2163 mem_ap_write_atomic_u32(armv8
->debug_ap
,
2164 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
);
2171 static int aarch64_read_phys_memory(struct target
*target
,
2172 target_addr_t address
, uint32_t size
,
2173 uint32_t count
, uint8_t *buffer
)
2175 int retval
= ERROR_COMMAND_SYNTAX_ERROR
;
2176 LOG_DEBUG("Reading memory at real address 0x%" TARGET_PRIxADDR
"; size %" PRId32
"; count %" PRId32
,
2177 address
, size
, count
);
2179 if (count
&& buffer
) {
2180 /* read memory through APB-AP */
2181 retval
= aarch64_mmu_modify(target
, 0);
2182 if (retval
!= ERROR_OK
)
2184 retval
= aarch64_read_apb_ap_memory(target
, address
, size
, count
, buffer
);
2189 static int aarch64_read_memory(struct target
*target
, target_addr_t address
,
2190 uint32_t size
, uint32_t count
, uint8_t *buffer
)
2192 int mmu_enabled
= 0;
2195 /* aarch64 handles unaligned memory access */
2196 LOG_DEBUG("Reading memory at address 0x%" TARGET_PRIxADDR
"; size %" PRId32
"; count %" PRId32
, address
,
2199 /* determine if MMU was enabled on target stop */
2200 retval
= aarch64_mmu(target
, &mmu_enabled
);
2201 if (retval
!= ERROR_OK
)
2205 retval
= aarch64_check_address(target
, address
);
2206 if (retval
!= ERROR_OK
)
2208 /* enable MMU as we could have disabled it for phys access */
2209 retval
= aarch64_mmu_modify(target
, 1);
2210 if (retval
!= ERROR_OK
)
2213 return aarch64_read_apb_ap_memory(target
, address
, size
, count
, buffer
);
2216 static int aarch64_write_phys_memory(struct target
*target
,
2217 target_addr_t address
, uint32_t size
,
2218 uint32_t count
, const uint8_t *buffer
)
2220 int retval
= ERROR_COMMAND_SYNTAX_ERROR
;
2222 LOG_DEBUG("Writing memory to real address 0x%" TARGET_PRIxADDR
"; size %" PRId32
"; count %" PRId32
, address
,
2225 if (count
&& buffer
) {
2226 /* write memory through APB-AP */
2227 retval
= aarch64_mmu_modify(target
, 0);
2228 if (retval
!= ERROR_OK
)
2230 return aarch64_write_apb_ap_memory(target
, address
, size
, count
, buffer
);
2236 static int aarch64_write_memory(struct target
*target
, target_addr_t address
,
2237 uint32_t size
, uint32_t count
, const uint8_t *buffer
)
2239 int mmu_enabled
= 0;
2242 /* aarch64 handles unaligned memory access */
2243 LOG_DEBUG("Writing memory at address 0x%" TARGET_PRIxADDR
"; size %" PRId32
2244 "; count %" PRId32
, address
, size
, count
);
2246 /* determine if MMU was enabled on target stop */
2247 retval
= aarch64_mmu(target
, &mmu_enabled
);
2248 if (retval
!= ERROR_OK
)
2252 retval
= aarch64_check_address(target
, address
);
2253 if (retval
!= ERROR_OK
)
2255 /* enable MMU as we could have disabled it for phys access */
2256 retval
= aarch64_mmu_modify(target
, 1);
2257 if (retval
!= ERROR_OK
)
2260 return aarch64_write_apb_ap_memory(target
, address
, size
, count
, buffer
);
2263 static int aarch64_handle_target_request(void *priv
)
2265 struct target
*target
= priv
;
2266 struct armv8_common
*armv8
= target_to_armv8(target
);
2269 if (!target_was_examined(target
))
2271 if (!target
->dbg_msg_enabled
)
2274 if (target
->state
== TARGET_RUNNING
) {
2277 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2278 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
2280 /* check if we have data */
2281 while ((dscr
& DSCR_DTR_TX_FULL
) && (retval
== ERROR_OK
)) {
2282 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2283 armv8
->debug_base
+ CPUV8_DBG_DTRTX
, &request
);
2284 if (retval
== ERROR_OK
) {
2285 target_request(target
, request
);
2286 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2287 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
2295 static int aarch64_examine_first(struct target
*target
)
2297 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
2298 struct armv8_common
*armv8
= &aarch64
->armv8_common
;
2299 struct adiv5_dap
*swjdp
= armv8
->arm
.dap
;
2301 int retval
= ERROR_OK
;
2302 uint64_t debug
, ttypr
;
2304 uint32_t tmp0
, tmp1
;
2305 debug
= ttypr
= cpuid
= 0;
2307 /* We do one extra read to ensure DAP is configured,
2308 * we call ahbap_debugport_init(swjdp) instead
2310 retval
= dap_dp_init(swjdp
);
2311 if (retval
!= ERROR_OK
)
2314 /* Search for the APB-AB - it is needed for access to debug registers */
2315 retval
= dap_find_ap(swjdp
, AP_TYPE_APB_AP
, &armv8
->debug_ap
);
2316 if (retval
!= ERROR_OK
) {
2317 LOG_ERROR("Could not find APB-AP for debug access");
2321 retval
= mem_ap_init(armv8
->debug_ap
);
2322 if (retval
!= ERROR_OK
) {
2323 LOG_ERROR("Could not initialize the APB-AP");
2327 armv8
->debug_ap
->memaccess_tck
= 80;
2329 if (!target
->dbgbase_set
) {
2331 /* Get ROM Table base */
2333 int32_t coreidx
= target
->coreid
;
2334 retval
= dap_get_debugbase(armv8
->debug_ap
, &dbgbase
, &apid
);
2335 if (retval
!= ERROR_OK
)
2337 /* Lookup 0x15 -- Processor DAP */
2338 retval
= dap_lookup_cs_component(armv8
->debug_ap
, dbgbase
, 0x15,
2339 &armv8
->debug_base
, &coreidx
);
2340 if (retval
!= ERROR_OK
)
2342 LOG_DEBUG("Detected core %" PRId32
" dbgbase: %08" PRIx32
2343 " apid: %08" PRIx32
, coreidx
, armv8
->debug_base
, apid
);
2345 armv8
->debug_base
= target
->dbgbase
;
2347 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
2348 armv8
->debug_base
+ CPUV8_DBG_LOCKACCESS
, 0xC5ACCE55);
2349 if (retval
!= ERROR_OK
) {
2350 LOG_DEBUG("LOCK debug access fail");
2354 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
2355 armv8
->debug_base
+ CPUV8_DBG_OSLAR
, 0);
2356 if (retval
!= ERROR_OK
) {
2357 LOG_DEBUG("Examine %s failed", "oslock");
2361 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2362 armv8
->debug_base
+ CPUV8_DBG_MAINID0
, &cpuid
);
2363 if (retval
!= ERROR_OK
) {
2364 LOG_DEBUG("Examine %s failed", "CPUID");
2368 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2369 armv8
->debug_base
+ CPUV8_DBG_MEMFEATURE0
, &tmp0
);
2370 retval
+= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2371 armv8
->debug_base
+ CPUV8_DBG_MEMFEATURE0
+ 4, &tmp1
);
2372 if (retval
!= ERROR_OK
) {
2373 LOG_DEBUG("Examine %s failed", "Memory Model Type");
2377 ttypr
= (ttypr
<< 32) | tmp0
;
2379 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2380 armv8
->debug_base
+ CPUV8_DBG_DBGFEATURE0
, &tmp0
);
2381 retval
+= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2382 armv8
->debug_base
+ CPUV8_DBG_DBGFEATURE0
+ 4, &tmp1
);
2383 if (retval
!= ERROR_OK
) {
2384 LOG_DEBUG("Examine %s failed", "ID_AA64DFR0_EL1");
2388 debug
= (debug
<< 32) | tmp0
;
2390 LOG_DEBUG("cpuid = 0x%08" PRIx32
, cpuid
);
2391 LOG_DEBUG("ttypr = 0x%08" PRIx64
, ttypr
);
2392 LOG_DEBUG("debug = 0x%08" PRIx64
, debug
);
2394 if (target
->ctibase
== 0) {
2395 /* assume a v8 rom table layout */
2396 armv8
->cti_base
= target
->ctibase
= armv8
->debug_base
+ 0x10000;
2397 LOG_INFO("Target ctibase is not set, assuming 0x%0" PRIx32
, target
->ctibase
);
2399 armv8
->cti_base
= target
->ctibase
;
2401 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
2402 armv8
->cti_base
+ CTI_UNLOCK
, 0xC5ACCE55);
2403 if (retval
!= ERROR_OK
)
2407 armv8
->arm
.core_type
= ARM_MODE_MON
;
2408 retval
= aarch64_dpm_setup(aarch64
, debug
);
2409 if (retval
!= ERROR_OK
)
2412 /* Setup Breakpoint Register Pairs */
2413 aarch64
->brp_num
= (uint32_t)((debug
>> 12) & 0x0F) + 1;
2414 aarch64
->brp_num_context
= (uint32_t)((debug
>> 28) & 0x0F) + 1;
2415 aarch64
->brp_num_available
= aarch64
->brp_num
;
2416 aarch64
->brp_list
= calloc(aarch64
->brp_num
, sizeof(struct aarch64_brp
));
2417 for (i
= 0; i
< aarch64
->brp_num
; i
++) {
2418 aarch64
->brp_list
[i
].used
= 0;
2419 if (i
< (aarch64
->brp_num
-aarch64
->brp_num_context
))
2420 aarch64
->brp_list
[i
].type
= BRP_NORMAL
;
2422 aarch64
->brp_list
[i
].type
= BRP_CONTEXT
;
2423 aarch64
->brp_list
[i
].value
= 0;
2424 aarch64
->brp_list
[i
].control
= 0;
2425 aarch64
->brp_list
[i
].BRPn
= i
;
2428 LOG_DEBUG("Configured %i hw breakpoints", aarch64
->brp_num
);
2430 target_set_examined(target
);
2434 static int aarch64_examine(struct target
*target
)
2436 int retval
= ERROR_OK
;
2438 /* don't re-probe hardware after each reset */
2439 if (!target_was_examined(target
))
2440 retval
= aarch64_examine_first(target
);
2442 /* Configure core debug access */
2443 if (retval
== ERROR_OK
)
2444 retval
= aarch64_init_debug_access(target
);
2450 * Cortex-A8 target creation and initialization
2453 static int aarch64_init_target(struct command_context
*cmd_ctx
,
2454 struct target
*target
)
2456 /* examine_first() does a bunch of this */
2460 static int aarch64_init_arch_info(struct target
*target
,
2461 struct aarch64_common
*aarch64
, struct jtag_tap
*tap
)
2463 struct armv8_common
*armv8
= &aarch64
->armv8_common
;
2464 struct adiv5_dap
*dap
= armv8
->arm
.dap
;
2466 armv8
->arm
.dap
= dap
;
2468 /* Setup struct aarch64_common */
2469 aarch64
->common_magic
= AARCH64_COMMON_MAGIC
;
2470 /* tap has no dap initialized */
2472 tap
->dap
= dap_init();
2474 /* Leave (only) generic DAP stuff for debugport_init() */
2475 tap
->dap
->tap
= tap
;
2478 armv8
->arm
.dap
= tap
->dap
;
2480 aarch64
->fast_reg_read
= 0;
2482 /* register arch-specific functions */
2483 armv8
->examine_debug_reason
= NULL
;
2485 armv8
->post_debug_entry
= aarch64_post_debug_entry
;
2487 armv8
->pre_restore_context
= NULL
;
2489 armv8
->armv8_mmu
.read_physical_memory
= aarch64_read_phys_memory
;
2491 /* REVISIT v7a setup should be in a v7a-specific routine */
2492 armv8_init_arch_info(target
, armv8
);
2493 target_register_timer_callback(aarch64_handle_target_request
, 1, 1, target
);
2498 static int aarch64_target_create(struct target
*target
, Jim_Interp
*interp
)
2500 struct aarch64_common
*aarch64
= calloc(1, sizeof(struct aarch64_common
));
2502 return aarch64_init_arch_info(target
, aarch64
, target
->tap
);
2505 static int aarch64_mmu(struct target
*target
, int *enabled
)
2507 if (target
->state
!= TARGET_HALTED
) {
2508 LOG_ERROR("%s: target not halted", __func__
);
2509 return ERROR_TARGET_INVALID
;
2512 *enabled
= target_to_aarch64(target
)->armv8_common
.armv8_mmu
.mmu_enabled
;
2516 static int aarch64_virt2phys(struct target
*target
, target_addr_t virt
,
2517 target_addr_t
*phys
)
2519 return armv8_mmu_translate_va(target
, virt
, phys
);
2522 COMMAND_HANDLER(aarch64_handle_cache_info_command
)
2524 struct target
*target
= get_current_target(CMD_CTX
);
2525 struct armv8_common
*armv8
= target_to_armv8(target
);
2527 return armv8_handle_cache_info_command(CMD_CTX
,
2528 &armv8
->armv8_mmu
.armv8_cache
);
2532 COMMAND_HANDLER(aarch64_handle_dbginit_command
)
2534 struct target
*target
= get_current_target(CMD_CTX
);
2535 if (!target_was_examined(target
)) {
2536 LOG_ERROR("target not examined yet");
2540 return aarch64_init_debug_access(target
);
2542 COMMAND_HANDLER(aarch64_handle_smp_off_command
)
2544 struct target
*target
= get_current_target(CMD_CTX
);
2545 /* check target is an smp target */
2546 struct target_list
*head
;
2547 struct target
*curr
;
2548 head
= target
->head
;
2550 if (head
!= (struct target_list
*)NULL
) {
2551 while (head
!= (struct target_list
*)NULL
) {
2552 curr
= head
->target
;
2556 /* fixes the target display to the debugger */
2557 target
->gdb_service
->target
= target
;
2562 COMMAND_HANDLER(aarch64_handle_smp_on_command
)
2564 struct target
*target
= get_current_target(CMD_CTX
);
2565 struct target_list
*head
;
2566 struct target
*curr
;
2567 head
= target
->head
;
2568 if (head
!= (struct target_list
*)NULL
) {
2570 while (head
!= (struct target_list
*)NULL
) {
2571 curr
= head
->target
;
2579 COMMAND_HANDLER(aarch64_handle_smp_gdb_command
)
2581 struct target
*target
= get_current_target(CMD_CTX
);
2582 int retval
= ERROR_OK
;
2583 struct target_list
*head
;
2584 head
= target
->head
;
2585 if (head
!= (struct target_list
*)NULL
) {
2586 if (CMD_ARGC
== 1) {
2588 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], coreid
);
2589 if (ERROR_OK
!= retval
)
2591 target
->gdb_service
->core
[1] = coreid
;
2594 command_print(CMD_CTX
, "gdb coreid %" PRId32
" -> %" PRId32
, target
->gdb_service
->core
[0]
2595 , target
->gdb_service
->core
[1]);
2600 static const struct command_registration aarch64_exec_command_handlers
[] = {
2602 .name
= "cache_info",
2603 .handler
= aarch64_handle_cache_info_command
,
2604 .mode
= COMMAND_EXEC
,
2605 .help
= "display information about target caches",
2610 .handler
= aarch64_handle_dbginit_command
,
2611 .mode
= COMMAND_EXEC
,
2612 .help
= "Initialize core debug",
2615 { .name
= "smp_off",
2616 .handler
= aarch64_handle_smp_off_command
,
2617 .mode
= COMMAND_EXEC
,
2618 .help
= "Stop smp handling",
2623 .handler
= aarch64_handle_smp_on_command
,
2624 .mode
= COMMAND_EXEC
,
2625 .help
= "Restart smp handling",
2630 .handler
= aarch64_handle_smp_gdb_command
,
2631 .mode
= COMMAND_EXEC
,
2632 .help
= "display/fix current core played to gdb",
2637 COMMAND_REGISTRATION_DONE
2639 static const struct command_registration aarch64_command_handlers
[] = {
2641 .chain
= arm_command_handlers
,
2644 .chain
= armv8_command_handlers
,
2648 .mode
= COMMAND_ANY
,
2649 .help
= "Cortex-A command group",
2651 .chain
= aarch64_exec_command_handlers
,
2653 COMMAND_REGISTRATION_DONE
2656 struct target_type aarch64_target
= {
2659 .poll
= aarch64_poll
,
2660 .arch_state
= armv8_arch_state
,
2662 .halt
= aarch64_halt
,
2663 .resume
= aarch64_resume
,
2664 .step
= aarch64_step
,
2666 .assert_reset
= aarch64_assert_reset
,
2667 .deassert_reset
= aarch64_deassert_reset
,
2669 /* REVISIT allow exporting VFP3 registers ... */
2670 .get_gdb_reg_list
= armv8_get_gdb_reg_list
,
2672 .read_memory
= aarch64_read_memory
,
2673 .write_memory
= aarch64_write_memory
,
2675 .checksum_memory
= arm_checksum_memory
,
2676 .blank_check_memory
= arm_blank_check_memory
,
2678 .run_algorithm
= armv4_5_run_algorithm
,
2680 .add_breakpoint
= aarch64_add_breakpoint
,
2681 .add_context_breakpoint
= aarch64_add_context_breakpoint
,
2682 .add_hybrid_breakpoint
= aarch64_add_hybrid_breakpoint
,
2683 .remove_breakpoint
= aarch64_remove_breakpoint
,
2684 .add_watchpoint
= NULL
,
2685 .remove_watchpoint
= NULL
,
2687 .commands
= aarch64_command_handlers
,
2688 .target_create
= aarch64_target_create
,
2689 .init_target
= aarch64_init_target
,
2690 .examine
= aarch64_examine
,
2692 .read_phys_memory
= aarch64_read_phys_memory
,
2693 .write_phys_memory
= aarch64_write_phys_memory
,
2695 .virt2phys
= aarch64_virt2phys
,
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)