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 <helper/time_support.h>
32 static int aarch64_poll(struct target
*target
);
33 static int aarch64_debug_entry(struct target
*target
);
34 static int aarch64_restore_context(struct target
*target
, bool bpwp
);
35 static int aarch64_set_breakpoint(struct target
*target
,
36 struct breakpoint
*breakpoint
, uint8_t matchmode
);
37 static int aarch64_set_context_breakpoint(struct target
*target
,
38 struct breakpoint
*breakpoint
, uint8_t matchmode
);
39 static int aarch64_set_hybrid_breakpoint(struct target
*target
,
40 struct breakpoint
*breakpoint
);
41 static int aarch64_unset_breakpoint(struct target
*target
,
42 struct breakpoint
*breakpoint
);
43 static int aarch64_mmu(struct target
*target
, int *enabled
);
44 static int aarch64_virt2phys(struct target
*target
,
45 target_addr_t virt
, target_addr_t
*phys
);
46 static int aarch64_read_apb_ap_memory(struct target
*target
,
47 uint64_t address
, uint32_t size
, uint32_t count
, uint8_t *buffer
);
48 static int aarch64_instr_write_data_r0(struct arm_dpm
*dpm
,
49 uint32_t opcode
, uint32_t data
);
51 static int aarch64_restore_system_control_reg(struct target
*target
)
53 int retval
= ERROR_OK
;
55 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
56 struct armv8_common
*armv8
= target_to_armv8(target
);
58 if (aarch64
->system_control_reg
!= aarch64
->system_control_reg_curr
) {
59 aarch64
->system_control_reg_curr
= aarch64
->system_control_reg
;
60 retval
= aarch64_instr_write_data_r0(armv8
->arm
.dpm
,
62 aarch64
->system_control_reg
);
68 /* check address before aarch64_apb read write access with mmu on
69 * remove apb predictible data abort */
70 static int aarch64_check_address(struct target
*target
, uint32_t address
)
75 /* modify system_control_reg in order to enable or disable mmu for :
76 * - virt2phys address conversion
77 * - read or write memory in phys or virt address */
78 static int aarch64_mmu_modify(struct target
*target
, int enable
)
80 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
81 struct armv8_common
*armv8
= &aarch64
->armv8_common
;
82 int retval
= ERROR_OK
;
85 /* if mmu enabled at target stop and mmu not enable */
86 if (!(aarch64
->system_control_reg
& 0x1U
)) {
87 LOG_ERROR("trying to enable mmu on target stopped with mmu disable");
90 if (!(aarch64
->system_control_reg_curr
& 0x1U
)) {
91 aarch64
->system_control_reg_curr
|= 0x1U
;
92 retval
= aarch64_instr_write_data_r0(armv8
->arm
.dpm
,
94 aarch64
->system_control_reg_curr
);
97 if (aarch64
->system_control_reg_curr
& 0x4U
) {
98 /* data cache is active */
99 aarch64
->system_control_reg_curr
&= ~0x4U
;
100 /* flush data cache armv7 function to be called */
101 if (armv8
->armv8_mmu
.armv8_cache
.flush_all_data_cache
)
102 armv8
->armv8_mmu
.armv8_cache
.flush_all_data_cache(target
);
104 if ((aarch64
->system_control_reg_curr
& 0x1U
)) {
105 aarch64
->system_control_reg_curr
&= ~0x1U
;
106 retval
= aarch64_instr_write_data_r0(armv8
->arm
.dpm
,
108 aarch64
->system_control_reg_curr
);
115 * Basic debug access, very low level assumes state is saved
117 static int aarch64_init_debug_access(struct target
*target
)
119 struct armv8_common
*armv8
= target_to_armv8(target
);
125 /* Unlocking the debug registers for modification
126 * The debugport might be uninitialised so try twice */
127 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
128 armv8
->debug_base
+ CPUV8_DBG_LOCKACCESS
, 0xC5ACCE55);
129 if (retval
!= ERROR_OK
) {
131 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
132 armv8
->debug_base
+ CPUV8_DBG_LOCKACCESS
, 0xC5ACCE55);
133 if (retval
== ERROR_OK
)
134 LOG_USER("Locking debug access failed on first, but succeeded on second try.");
136 if (retval
!= ERROR_OK
)
138 /* Clear Sticky Power Down status Bit in PRSR to enable access to
139 the registers in the Core Power Domain */
140 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
141 armv8
->debug_base
+ CPUV8_DBG_PRSR
, &dummy
);
142 if (retval
!= ERROR_OK
)
145 /* Enabling of instruction execution in debug mode is done in debug_entry code */
147 /* Resync breakpoint registers */
149 /* Since this is likely called from init or reset, update target state information*/
150 return aarch64_poll(target
);
153 /* To reduce needless round-trips, pass in a pointer to the current
154 * DSCR value. Initialize it to zero if you just need to know the
155 * value on return from this function; or DSCR_ITE if you
156 * happen to know that no instruction is pending.
158 static int aarch64_exec_opcode(struct target
*target
,
159 uint32_t opcode
, uint32_t *dscr_p
)
163 struct armv8_common
*armv8
= target_to_armv8(target
);
164 dscr
= dscr_p
? *dscr_p
: 0;
166 LOG_DEBUG("exec opcode 0x%08" PRIx32
, opcode
);
168 /* Wait for InstrCompl bit to be set */
169 long long then
= timeval_ms();
170 while ((dscr
& DSCR_ITE
) == 0) {
171 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
172 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
173 if (retval
!= ERROR_OK
) {
174 LOG_ERROR("Could not read DSCR register, opcode = 0x%08" PRIx32
, opcode
);
177 if (timeval_ms() > then
+ 1000) {
178 LOG_ERROR("Timeout waiting for aarch64_exec_opcode");
183 retval
= mem_ap_write_u32(armv8
->debug_ap
,
184 armv8
->debug_base
+ CPUV8_DBG_ITR
, opcode
);
185 if (retval
!= ERROR_OK
)
190 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
191 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
192 if (retval
!= ERROR_OK
) {
193 LOG_ERROR("Could not read DSCR register");
196 if (timeval_ms() > then
+ 1000) {
197 LOG_ERROR("Timeout waiting for aarch64_exec_opcode");
200 } while ((dscr
& DSCR_ITE
) == 0); /* Wait for InstrCompl bit to be set */
208 /* Write to memory mapped registers directly with no cache or mmu handling */
209 static int aarch64_dap_write_memap_register_u32(struct target
*target
,
214 struct armv8_common
*armv8
= target_to_armv8(target
);
216 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
, address
, value
);
222 * AARCH64 implementation of Debug Programmer's Model
224 * NOTE the invariant: these routines return with DSCR_ITE set,
225 * so there's no need to poll for it before executing an instruction.
227 * NOTE that in several of these cases the "stall" mode might be useful.
228 * It'd let us queue a few operations together... prepare/finish might
229 * be the places to enable/disable that mode.
232 static inline struct aarch64_common
*dpm_to_a8(struct arm_dpm
*dpm
)
234 return container_of(dpm
, struct aarch64_common
, armv8_common
.dpm
);
237 static int aarch64_write_dcc(struct armv8_common
*armv8
, uint32_t data
)
239 LOG_DEBUG("write DCC 0x%08" PRIx32
, data
);
240 return mem_ap_write_u32(armv8
->debug_ap
,
241 armv8
->debug_base
+ CPUV8_DBG_DTRRX
, data
);
244 static int aarch64_write_dcc_64(struct armv8_common
*armv8
, uint64_t data
)
247 LOG_DEBUG("write DCC Low word0x%08" PRIx32
, (unsigned)data
);
248 LOG_DEBUG("write DCC High word 0x%08" PRIx32
, (unsigned)(data
>> 32));
249 ret
= mem_ap_write_u32(armv8
->debug_ap
,
250 armv8
->debug_base
+ CPUV8_DBG_DTRRX
, data
);
251 ret
+= mem_ap_write_u32(armv8
->debug_ap
,
252 armv8
->debug_base
+ CPUV8_DBG_DTRTX
, data
>> 32);
256 static int aarch64_read_dcc(struct armv8_common
*armv8
, uint32_t *data
,
259 uint32_t dscr
= DSCR_ITE
;
265 /* Wait for DTRRXfull */
266 long long then
= timeval_ms();
267 while ((dscr
& DSCR_DTR_TX_FULL
) == 0) {
268 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
269 armv8
->debug_base
+ CPUV8_DBG_DSCR
,
271 if (retval
!= ERROR_OK
)
273 if (timeval_ms() > then
+ 1000) {
274 LOG_ERROR("Timeout waiting for read dcc");
279 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
280 armv8
->debug_base
+ CPUV8_DBG_DTRTX
,
282 if (retval
!= ERROR_OK
)
284 LOG_DEBUG("read DCC 0x%08" PRIx32
, *data
);
292 static int aarch64_read_dcc_64(struct armv8_common
*armv8
, uint64_t *data
,
295 uint32_t dscr
= DSCR_ITE
;
302 /* Wait for DTRRXfull */
303 long long then
= timeval_ms();
304 while ((dscr
& DSCR_DTR_TX_FULL
) == 0) {
305 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
306 armv8
->debug_base
+ CPUV8_DBG_DSCR
,
308 if (retval
!= ERROR_OK
)
310 if (timeval_ms() > then
+ 1000) {
311 LOG_ERROR("Timeout waiting for read dcc");
316 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
317 armv8
->debug_base
+ CPUV8_DBG_DTRTX
,
319 if (retval
!= ERROR_OK
)
322 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
323 armv8
->debug_base
+ CPUV8_DBG_DTRRX
,
325 if (retval
!= ERROR_OK
)
328 *data
= *(uint32_t *)data
| (uint64_t)higher
<< 32;
329 LOG_DEBUG("read DCC 0x%16.16" PRIx64
, *data
);
337 static int aarch64_dpm_prepare(struct arm_dpm
*dpm
)
339 struct aarch64_common
*a8
= dpm_to_a8(dpm
);
343 /* set up invariant: INSTR_COMP is set after ever DPM operation */
344 long long then
= timeval_ms();
346 retval
= mem_ap_read_atomic_u32(a8
->armv8_common
.debug_ap
,
347 a8
->armv8_common
.debug_base
+ CPUV8_DBG_DSCR
,
349 if (retval
!= ERROR_OK
)
351 if ((dscr
& DSCR_ITE
) != 0)
353 if (timeval_ms() > then
+ 1000) {
354 LOG_ERROR("Timeout waiting for dpm prepare");
359 /* this "should never happen" ... */
360 if (dscr
& DSCR_DTR_RX_FULL
) {
361 LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32
, dscr
);
363 retval
= aarch64_exec_opcode(
364 a8
->armv8_common
.arm
.target
,
367 if (retval
!= ERROR_OK
)
374 static int aarch64_dpm_finish(struct arm_dpm
*dpm
)
376 /* REVISIT what could be done here? */
380 static int aarch64_instr_execute(struct arm_dpm
*dpm
,
383 struct aarch64_common
*a8
= dpm_to_a8(dpm
);
384 uint32_t dscr
= DSCR_ITE
;
386 return aarch64_exec_opcode(
387 a8
->armv8_common
.arm
.target
,
392 static int aarch64_instr_write_data_dcc(struct arm_dpm
*dpm
,
393 uint32_t opcode
, uint32_t data
)
395 struct aarch64_common
*a8
= dpm_to_a8(dpm
);
397 uint32_t dscr
= DSCR_ITE
;
399 retval
= aarch64_write_dcc(&a8
->armv8_common
, data
);
400 if (retval
!= ERROR_OK
)
403 return aarch64_exec_opcode(
404 a8
->armv8_common
.arm
.target
,
409 static int aarch64_instr_write_data_dcc_64(struct arm_dpm
*dpm
,
410 uint32_t opcode
, uint64_t data
)
412 struct aarch64_common
*a8
= dpm_to_a8(dpm
);
414 uint32_t dscr
= DSCR_ITE
;
416 retval
= aarch64_write_dcc_64(&a8
->armv8_common
, data
);
417 if (retval
!= ERROR_OK
)
420 return aarch64_exec_opcode(
421 a8
->armv8_common
.arm
.target
,
426 static int aarch64_instr_write_data_r0(struct arm_dpm
*dpm
,
427 uint32_t opcode
, uint32_t data
)
429 struct aarch64_common
*a8
= dpm_to_a8(dpm
);
430 uint32_t dscr
= DSCR_ITE
;
433 retval
= aarch64_write_dcc(&a8
->armv8_common
, data
);
434 if (retval
!= ERROR_OK
)
437 retval
= aarch64_exec_opcode(
438 a8
->armv8_common
.arm
.target
,
441 if (retval
!= ERROR_OK
)
444 /* then the opcode, taking data from R0 */
445 retval
= aarch64_exec_opcode(
446 a8
->armv8_common
.arm
.target
,
453 static int aarch64_instr_write_data_r0_64(struct arm_dpm
*dpm
,
454 uint32_t opcode
, uint64_t data
)
456 struct aarch64_common
*a8
= dpm_to_a8(dpm
);
457 uint32_t dscr
= DSCR_ITE
;
460 retval
= aarch64_write_dcc_64(&a8
->armv8_common
, data
);
461 if (retval
!= ERROR_OK
)
464 retval
= aarch64_exec_opcode(
465 a8
->armv8_common
.arm
.target
,
468 if (retval
!= ERROR_OK
)
471 /* then the opcode, taking data from R0 */
472 retval
= aarch64_exec_opcode(
473 a8
->armv8_common
.arm
.target
,
480 static int aarch64_instr_cpsr_sync(struct arm_dpm
*dpm
)
482 struct target
*target
= dpm
->arm
->target
;
483 uint32_t dscr
= DSCR_ITE
;
485 /* "Prefetch flush" after modifying execution status in CPSR */
486 return aarch64_exec_opcode(target
,
487 ARMV4_5_MCR(15, 0, 0, 7, 5, 4),
491 static int aarch64_instr_read_data_dcc(struct arm_dpm
*dpm
,
492 uint32_t opcode
, uint32_t *data
)
494 struct aarch64_common
*a8
= dpm_to_a8(dpm
);
496 uint32_t dscr
= DSCR_ITE
;
498 /* the opcode, writing data to DCC */
499 retval
= aarch64_exec_opcode(
500 a8
->armv8_common
.arm
.target
,
503 if (retval
!= ERROR_OK
)
506 return aarch64_read_dcc(&a8
->armv8_common
, data
, &dscr
);
509 static int aarch64_instr_read_data_dcc_64(struct arm_dpm
*dpm
,
510 uint32_t opcode
, uint64_t *data
)
512 struct aarch64_common
*a8
= dpm_to_a8(dpm
);
514 uint32_t dscr
= DSCR_ITE
;
516 /* the opcode, writing data to DCC */
517 retval
= aarch64_exec_opcode(
518 a8
->armv8_common
.arm
.target
,
521 if (retval
!= ERROR_OK
)
524 return aarch64_read_dcc_64(&a8
->armv8_common
, data
, &dscr
);
527 static int aarch64_instr_read_data_r0(struct arm_dpm
*dpm
,
528 uint32_t opcode
, uint32_t *data
)
530 struct aarch64_common
*a8
= dpm_to_a8(dpm
);
531 uint32_t dscr
= DSCR_ITE
;
534 /* the opcode, writing data to R0 */
535 retval
= aarch64_exec_opcode(
536 a8
->armv8_common
.arm
.target
,
539 if (retval
!= ERROR_OK
)
542 /* write R0 to DCC */
543 retval
= aarch64_exec_opcode(
544 a8
->armv8_common
.arm
.target
,
545 0xd5130400, /* msr dbgdtr_el0, x0 */
547 if (retval
!= ERROR_OK
)
550 return aarch64_read_dcc(&a8
->armv8_common
, data
, &dscr
);
553 static int aarch64_instr_read_data_r0_64(struct arm_dpm
*dpm
,
554 uint32_t opcode
, uint64_t *data
)
556 struct aarch64_common
*a8
= dpm_to_a8(dpm
);
557 uint32_t dscr
= DSCR_ITE
;
560 /* the opcode, writing data to R0 */
561 retval
= aarch64_exec_opcode(
562 a8
->armv8_common
.arm
.target
,
565 if (retval
!= ERROR_OK
)
568 /* write R0 to DCC */
569 retval
= aarch64_exec_opcode(
570 a8
->armv8_common
.arm
.target
,
571 0xd5130400, /* msr dbgdtr_el0, x0 */
573 if (retval
!= ERROR_OK
)
576 return aarch64_read_dcc_64(&a8
->armv8_common
, data
, &dscr
);
579 static int aarch64_bpwp_enable(struct arm_dpm
*dpm
, unsigned index_t
,
580 uint32_t addr
, uint32_t control
)
582 struct aarch64_common
*a8
= dpm_to_a8(dpm
);
583 uint32_t vr
= a8
->armv8_common
.debug_base
;
584 uint32_t cr
= a8
->armv8_common
.debug_base
;
588 case 0 ... 15: /* breakpoints */
589 vr
+= CPUV8_DBG_BVR_BASE
;
590 cr
+= CPUV8_DBG_BCR_BASE
;
592 case 16 ... 31: /* watchpoints */
593 vr
+= CPUV8_DBG_WVR_BASE
;
594 cr
+= CPUV8_DBG_WCR_BASE
;
603 LOG_DEBUG("A8: bpwp enable, vr %08x cr %08x",
604 (unsigned) vr
, (unsigned) cr
);
606 retval
= aarch64_dap_write_memap_register_u32(dpm
->arm
->target
,
608 if (retval
!= ERROR_OK
)
610 retval
= aarch64_dap_write_memap_register_u32(dpm
->arm
->target
,
615 static int aarch64_bpwp_disable(struct arm_dpm
*dpm
, unsigned index_t
)
620 struct aarch64_common
*a
= dpm_to_a8(dpm
);
625 cr
= a
->armv8_common
.debug_base
+ CPUV8_DBG_BCR_BASE
;
628 cr
= a
->armv8_common
.debug_base
+ CPUV8_DBG_WCR_BASE
;
636 LOG_DEBUG("A: bpwp disable, cr %08x", (unsigned) cr
);
638 /* clear control register */
639 return aarch64_dap_write_memap_register_u32(dpm
->arm
->target
, cr
, 0);
643 static int aarch64_dpm_setup(struct aarch64_common
*a8
, uint32_t debug
)
645 struct arm_dpm
*dpm
= &a8
->armv8_common
.dpm
;
648 dpm
->arm
= &a8
->armv8_common
.arm
;
651 dpm
->prepare
= aarch64_dpm_prepare
;
652 dpm
->finish
= aarch64_dpm_finish
;
654 dpm
->instr_execute
= aarch64_instr_execute
;
655 dpm
->instr_write_data_dcc
= aarch64_instr_write_data_dcc
;
656 dpm
->instr_write_data_dcc_64
= aarch64_instr_write_data_dcc_64
;
657 dpm
->instr_write_data_r0
= aarch64_instr_write_data_r0
;
658 dpm
->instr_write_data_r0_64
= aarch64_instr_write_data_r0_64
;
659 dpm
->instr_cpsr_sync
= aarch64_instr_cpsr_sync
;
661 dpm
->instr_read_data_dcc
= aarch64_instr_read_data_dcc
;
662 dpm
->instr_read_data_dcc_64
= aarch64_instr_read_data_dcc_64
;
663 dpm
->instr_read_data_r0
= aarch64_instr_read_data_r0
;
664 dpm
->instr_read_data_r0_64
= aarch64_instr_read_data_r0_64
;
666 dpm
->arm_reg_current
= armv8_reg_current
;
668 dpm
->bpwp_enable
= aarch64_bpwp_enable
;
669 dpm
->bpwp_disable
= aarch64_bpwp_disable
;
671 retval
= armv8_dpm_setup(dpm
);
672 if (retval
== ERROR_OK
)
673 retval
= armv8_dpm_initialize(dpm
);
677 static struct target
*get_aarch64(struct target
*target
, int32_t coreid
)
679 struct target_list
*head
;
683 while (head
!= (struct target_list
*)NULL
) {
685 if ((curr
->coreid
== coreid
) && (curr
->state
== TARGET_HALTED
))
691 static int aarch64_halt(struct target
*target
);
693 static int aarch64_halt_smp(struct target
*target
)
696 struct target_list
*head
;
699 while (head
!= (struct target_list
*)NULL
) {
701 if ((curr
!= target
) && (curr
->state
!= TARGET_HALTED
))
702 retval
+= aarch64_halt(curr
);
708 static int update_halt_gdb(struct target
*target
)
711 if (target
->gdb_service
&& target
->gdb_service
->core
[0] == -1) {
712 target
->gdb_service
->target
= target
;
713 target
->gdb_service
->core
[0] = target
->coreid
;
714 retval
+= aarch64_halt_smp(target
);
720 * Cortex-A8 Run control
723 static int aarch64_poll(struct target
*target
)
725 int retval
= ERROR_OK
;
727 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
728 struct armv8_common
*armv8
= &aarch64
->armv8_common
;
729 enum target_state prev_target_state
= target
->state
;
730 /* toggle to another core is done by gdb as follow */
731 /* maint packet J core_id */
733 /* the next polling trigger an halt event sent to gdb */
734 if ((target
->state
== TARGET_HALTED
) && (target
->smp
) &&
735 (target
->gdb_service
) &&
736 (target
->gdb_service
->target
== NULL
)) {
737 target
->gdb_service
->target
=
738 get_aarch64(target
, target
->gdb_service
->core
[1]);
739 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
742 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
743 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
744 if (retval
!= ERROR_OK
)
746 aarch64
->cpudbg_dscr
= dscr
;
748 if (DSCR_RUN_MODE(dscr
) == (DSCR_CORE_HALTED
| DSCR_CORE_RESTARTED
)) {
749 if (prev_target_state
!= TARGET_HALTED
) {
750 /* We have a halting debug event */
751 LOG_DEBUG("Target halted");
752 target
->state
= TARGET_HALTED
;
753 if ((prev_target_state
== TARGET_RUNNING
)
754 || (prev_target_state
== TARGET_UNKNOWN
)
755 || (prev_target_state
== TARGET_RESET
)) {
756 retval
= aarch64_debug_entry(target
);
757 if (retval
!= ERROR_OK
)
760 retval
= update_halt_gdb(target
);
761 if (retval
!= ERROR_OK
)
764 target_call_event_callbacks(target
,
765 TARGET_EVENT_HALTED
);
767 if (prev_target_state
== TARGET_DEBUG_RUNNING
) {
770 retval
= aarch64_debug_entry(target
);
771 if (retval
!= ERROR_OK
)
774 retval
= update_halt_gdb(target
);
775 if (retval
!= ERROR_OK
)
779 target_call_event_callbacks(target
,
780 TARGET_EVENT_DEBUG_HALTED
);
783 } else if (DSCR_RUN_MODE(dscr
) == DSCR_CORE_RESTARTED
)
784 target
->state
= TARGET_RUNNING
;
786 LOG_DEBUG("Unknown target state dscr = 0x%08" PRIx32
, dscr
);
787 target
->state
= TARGET_UNKNOWN
;
793 static int aarch64_halt(struct target
*target
)
795 int retval
= ERROR_OK
;
797 struct armv8_common
*armv8
= target_to_armv8(target
);
800 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
801 armv8
->cti_base
+ CTI_CTR
, 1);
802 if (retval
!= ERROR_OK
)
805 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
806 armv8
->cti_base
+ CTI_GATE
, 3);
807 if (retval
!= ERROR_OK
)
810 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
811 armv8
->cti_base
+ CTI_OUTEN0
, 1);
812 if (retval
!= ERROR_OK
)
815 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
816 armv8
->cti_base
+ CTI_OUTEN1
, 2);
817 if (retval
!= ERROR_OK
)
821 * add HDE in halting debug mode
823 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
824 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
825 if (retval
!= ERROR_OK
)
828 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
829 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
| DSCR_HDE
);
830 if (retval
!= ERROR_OK
)
833 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
834 armv8
->cti_base
+ CTI_APPPULSE
, 1);
835 if (retval
!= ERROR_OK
)
838 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
839 armv8
->cti_base
+ CTI_INACK
, 1);
840 if (retval
!= ERROR_OK
)
844 long long then
= timeval_ms();
846 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
847 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
848 if (retval
!= ERROR_OK
)
850 if ((dscr
& DSCRV8_HALT_MASK
) != 0)
852 if (timeval_ms() > then
+ 1000) {
853 LOG_ERROR("Timeout waiting for halt");
858 target
->debug_reason
= DBG_REASON_DBGRQ
;
863 static int aarch64_internal_restore(struct target
*target
, int current
,
864 uint64_t *address
, int handle_breakpoints
, int debug_execution
)
866 struct armv8_common
*armv8
= target_to_armv8(target
);
867 struct arm
*arm
= &armv8
->arm
;
871 if (!debug_execution
)
872 target_free_all_working_areas(target
);
874 /* current = 1: continue on current pc, otherwise continue at <address> */
875 resume_pc
= buf_get_u64(arm
->pc
->value
, 0, 64);
877 resume_pc
= *address
;
879 *address
= resume_pc
;
881 /* Make sure that the Armv7 gdb thumb fixups does not
882 * kill the return address
884 switch (arm
->core_state
) {
886 resume_pc
&= 0xFFFFFFFC;
888 case ARM_STATE_AARCH64
:
889 resume_pc
&= 0xFFFFFFFFFFFFFFFC;
891 case ARM_STATE_THUMB
:
892 case ARM_STATE_THUMB_EE
:
893 /* When the return address is loaded into PC
894 * bit 0 must be 1 to stay in Thumb state
898 case ARM_STATE_JAZELLE
:
899 LOG_ERROR("How do I resume into Jazelle state??");
902 LOG_DEBUG("resume pc = 0x%16" PRIx64
, resume_pc
);
903 buf_set_u64(arm
->pc
->value
, 0, 64, resume_pc
);
906 dpmv8_modeswitch(&armv8
->dpm
, ARM_MODE_ANY
);
908 /* called it now before restoring context because it uses cpu
909 * register r0 for restoring system control register */
910 retval
= aarch64_restore_system_control_reg(target
);
911 if (retval
!= ERROR_OK
)
913 retval
= aarch64_restore_context(target
, handle_breakpoints
);
914 if (retval
!= ERROR_OK
)
916 target
->debug_reason
= DBG_REASON_NOTHALTED
;
917 target
->state
= TARGET_RUNNING
;
919 /* registers are now invalid */
920 register_cache_invalidate(arm
->core_cache
);
923 /* the front-end may request us not to handle breakpoints */
924 if (handle_breakpoints
) {
925 /* Single step past breakpoint at current address */
926 breakpoint
= breakpoint_find(target
, resume_pc
);
928 LOG_DEBUG("unset breakpoint at 0x%8.8x", breakpoint
->address
);
929 cortex_m3_unset_breakpoint(target
, breakpoint
);
930 cortex_m3_single_step_core(target
);
931 cortex_m3_set_breakpoint(target
, breakpoint
);
939 static int aarch64_internal_restart(struct target
*target
)
941 struct armv8_common
*armv8
= target_to_armv8(target
);
942 struct arm
*arm
= &armv8
->arm
;
946 * * Restart core and wait for it to be started. Clear ITRen and sticky
947 * * exception flags: see ARMv7 ARM, C5.9.
949 * REVISIT: for single stepping, we probably want to
950 * disable IRQs by default, with optional override...
953 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
954 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
955 if (retval
!= ERROR_OK
)
958 if ((dscr
& DSCR_ITE
) == 0)
959 LOG_ERROR("DSCR InstrCompl must be set before leaving debug!");
961 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
962 armv8
->cti_base
+ CTI_APPPULSE
, 2);
963 if (retval
!= ERROR_OK
)
966 long long then
= timeval_ms();
968 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
969 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
970 if (retval
!= ERROR_OK
)
972 if ((dscr
& DSCR_HDE
) != 0)
974 if (timeval_ms() > then
+ 1000) {
975 LOG_ERROR("Timeout waiting for resume");
980 target
->debug_reason
= DBG_REASON_NOTHALTED
;
981 target
->state
= TARGET_RUNNING
;
983 /* registers are now invalid */
984 register_cache_invalidate(arm
->core_cache
);
989 static int aarch64_restore_smp(struct target
*target
, int handle_breakpoints
)
992 struct target_list
*head
;
996 while (head
!= (struct target_list
*)NULL
) {
998 if ((curr
!= target
) && (curr
->state
!= TARGET_RUNNING
)) {
999 /* resume current address , not in step mode */
1000 retval
+= aarch64_internal_restore(curr
, 1, &address
,
1001 handle_breakpoints
, 0);
1002 retval
+= aarch64_internal_restart(curr
);
1010 static int aarch64_resume(struct target
*target
, int current
,
1011 target_addr_t address
, int handle_breakpoints
, int debug_execution
)
1014 uint64_t addr
= address
;
1016 /* dummy resume for smp toggle in order to reduce gdb impact */
1017 if ((target
->smp
) && (target
->gdb_service
->core
[1] != -1)) {
1018 /* simulate a start and halt of target */
1019 target
->gdb_service
->target
= NULL
;
1020 target
->gdb_service
->core
[0] = target
->gdb_service
->core
[1];
1021 /* fake resume at next poll we play the target core[1], see poll*/
1022 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
1025 aarch64_internal_restore(target
, current
, &addr
, handle_breakpoints
,
1028 target
->gdb_service
->core
[0] = -1;
1029 retval
= aarch64_restore_smp(target
, handle_breakpoints
);
1030 if (retval
!= ERROR_OK
)
1033 aarch64_internal_restart(target
);
1035 if (!debug_execution
) {
1036 target
->state
= TARGET_RUNNING
;
1037 target_call_event_callbacks(target
, TARGET_EVENT_RESUMED
);
1038 LOG_DEBUG("target resumed at 0x%" PRIx64
, addr
);
1040 target
->state
= TARGET_DEBUG_RUNNING
;
1041 target_call_event_callbacks(target
, TARGET_EVENT_DEBUG_RESUMED
);
1042 LOG_DEBUG("target debug resumed at 0x%" PRIx64
, addr
);
1048 static int aarch64_debug_entry(struct target
*target
)
1051 int retval
= ERROR_OK
;
1052 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
1053 struct armv8_common
*armv8
= target_to_armv8(target
);
1056 LOG_DEBUG("dscr = 0x%08" PRIx32
, aarch64
->cpudbg_dscr
);
1058 /* REVISIT surely we should not re-read DSCR !! */
1059 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
1060 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
1061 if (retval
!= ERROR_OK
)
1064 /* REVISIT see A8 TRM 12.11.4 steps 2..3 -- make sure that any
1065 * imprecise data aborts get discarded by issuing a Data
1066 * Synchronization Barrier: ARMV4_5_MCR(15, 0, 0, 7, 10, 4).
1069 /* Enable the ITR execution once we are in debug mode */
1070 dscr
|= DSCR_ITR_EN
;
1071 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1072 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
);
1073 if (retval
!= ERROR_OK
)
1076 /* Examine debug reason */
1077 arm_dpm_report_dscr(&armv8
->dpm
, aarch64
->cpudbg_dscr
);
1078 mem_ap_read_atomic_u32(armv8
->debug_ap
,
1079 armv8
->debug_base
+ CPUV8_DBG_EDESR
, &tmp
);
1080 if ((tmp
& 0x7) == 0x4)
1081 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
1083 /* save address of instruction that triggered the watchpoint? */
1084 if (target
->debug_reason
== DBG_REASON_WATCHPOINT
) {
1087 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
1088 armv8
->debug_base
+ CPUV8_DBG_WFAR0
,
1090 if (retval
!= ERROR_OK
)
1092 arm_dpm_report_wfar(&armv8
->dpm
, wfar
);
1095 retval
= armv8_dpm_read_current_registers(&armv8
->dpm
);
1097 if (armv8
->post_debug_entry
) {
1098 retval
= armv8
->post_debug_entry(target
);
1099 if (retval
!= ERROR_OK
)
1106 static int aarch64_post_debug_entry(struct target
*target
)
1108 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
1109 struct armv8_common
*armv8
= &aarch64
->armv8_common
;
1110 struct armv8_mmu_common
*armv8_mmu
= &armv8
->armv8_mmu
;
1111 uint32_t sctlr_el1
= 0;
1114 mem_ap_write_atomic_u32(armv8
->debug_ap
,
1115 armv8
->debug_base
+ CPUV8_DBG_DRCR
, 1<<2);
1116 retval
= aarch64_instr_read_data_r0(armv8
->arm
.dpm
,
1117 0xd5381000, &sctlr_el1
);
1118 if (retval
!= ERROR_OK
)
1121 LOG_DEBUG("sctlr_el1 = %#8.8x", sctlr_el1
);
1122 aarch64
->system_control_reg
= sctlr_el1
;
1123 aarch64
->system_control_reg_curr
= sctlr_el1
;
1124 aarch64
->curr_mode
= armv8
->arm
.core_mode
;
1126 armv8_mmu
->mmu_enabled
= sctlr_el1
& 0x1U
? 1 : 0;
1127 armv8_mmu
->armv8_cache
.d_u_cache_enabled
= sctlr_el1
& 0x4U
? 1 : 0;
1128 armv8_mmu
->armv8_cache
.i_cache_enabled
= sctlr_el1
& 0x1000U
? 1 : 0;
1131 if (armv8
->armv8_mmu
.armv8_cache
.ctype
== -1)
1132 armv8_identify_cache(target
);
1138 static int aarch64_step(struct target
*target
, int current
, target_addr_t address
,
1139 int handle_breakpoints
)
1141 struct armv8_common
*armv8
= target_to_armv8(target
);
1145 if (target
->state
!= TARGET_HALTED
) {
1146 LOG_WARNING("target not halted");
1147 return ERROR_TARGET_NOT_HALTED
;
1150 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
1151 armv8
->debug_base
+ CPUV8_DBG_EDECR
, &tmp
);
1152 if (retval
!= ERROR_OK
)
1155 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1156 armv8
->debug_base
+ CPUV8_DBG_EDECR
, (tmp
|0x4));
1157 if (retval
!= ERROR_OK
)
1160 target
->debug_reason
= DBG_REASON_SINGLESTEP
;
1161 retval
= aarch64_resume(target
, 1, address
, 0, 0);
1162 if (retval
!= ERROR_OK
)
1165 long long then
= timeval_ms();
1166 while (target
->state
!= TARGET_HALTED
) {
1167 mem_ap_read_atomic_u32(armv8
->debug_ap
,
1168 armv8
->debug_base
+ CPUV8_DBG_EDESR
, &tmp
);
1169 LOG_DEBUG("DESR = %#x", tmp
);
1170 retval
= aarch64_poll(target
);
1171 if (retval
!= ERROR_OK
)
1173 if (timeval_ms() > then
+ 1000) {
1174 LOG_ERROR("timeout waiting for target halt");
1179 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1180 armv8
->debug_base
+ CPUV8_DBG_EDECR
, (tmp
&(~0x4)));
1181 if (retval
!= ERROR_OK
)
1184 target_call_event_callbacks(target
, TARGET_EVENT_HALTED
);
1185 if (target
->state
== TARGET_HALTED
)
1186 LOG_DEBUG("target stepped");
1191 static int aarch64_restore_context(struct target
*target
, bool bpwp
)
1193 struct armv8_common
*armv8
= target_to_armv8(target
);
1197 if (armv8
->pre_restore_context
)
1198 armv8
->pre_restore_context(target
);
1200 return armv8_dpm_write_dirty_registers(&armv8
->dpm
, bpwp
);
1205 * Cortex-A8 Breakpoint and watchpoint functions
1208 /* Setup hardware Breakpoint Register Pair */
1209 static int aarch64_set_breakpoint(struct target
*target
,
1210 struct breakpoint
*breakpoint
, uint8_t matchmode
)
1215 uint8_t byte_addr_select
= 0x0F;
1216 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
1217 struct armv8_common
*armv8
= &aarch64
->armv8_common
;
1218 struct aarch64_brp
*brp_list
= aarch64
->brp_list
;
1221 if (breakpoint
->set
) {
1222 LOG_WARNING("breakpoint already set");
1226 if (breakpoint
->type
== BKPT_HARD
) {
1228 while (brp_list
[brp_i
].used
&& (brp_i
< aarch64
->brp_num
))
1230 if (brp_i
>= aarch64
->brp_num
) {
1231 LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
1232 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1234 breakpoint
->set
= brp_i
+ 1;
1235 if (breakpoint
->length
== 2)
1236 byte_addr_select
= (3 << (breakpoint
->address
& 0x02));
1237 control
= ((matchmode
& 0x7) << 20)
1239 | (byte_addr_select
<< 5)
1241 brp_list
[brp_i
].used
= 1;
1242 brp_list
[brp_i
].value
= breakpoint
->address
& 0xFFFFFFFFFFFFFFFC;
1243 brp_list
[brp_i
].control
= control
;
1244 bpt_value
= brp_list
[brp_i
].value
;
1246 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1247 + CPUV8_DBG_BVR_BASE
+ 16 * brp_list
[brp_i
].BRPn
,
1248 (uint32_t)(bpt_value
& 0xFFFFFFFF));
1249 if (retval
!= ERROR_OK
)
1251 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1252 + CPUV8_DBG_BVR_BASE
+ 4 + 16 * brp_list
[brp_i
].BRPn
,
1253 (uint32_t)(bpt_value
>> 32));
1254 if (retval
!= ERROR_OK
)
1257 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1258 + CPUV8_DBG_BCR_BASE
+ 16 * brp_list
[brp_i
].BRPn
,
1259 brp_list
[brp_i
].control
);
1260 if (retval
!= ERROR_OK
)
1262 LOG_DEBUG("brp %i control 0x%0" PRIx32
" value 0x%" TARGET_PRIxADDR
, brp_i
,
1263 brp_list
[brp_i
].control
,
1264 brp_list
[brp_i
].value
);
1266 } else if (breakpoint
->type
== BKPT_SOFT
) {
1268 buf_set_u32(code
, 0, 32, 0xD4400000);
1270 retval
= target_read_memory(target
,
1271 breakpoint
->address
& 0xFFFFFFFFFFFFFFFE,
1272 breakpoint
->length
, 1,
1273 breakpoint
->orig_instr
);
1274 if (retval
!= ERROR_OK
)
1276 retval
= target_write_memory(target
,
1277 breakpoint
->address
& 0xFFFFFFFFFFFFFFFE,
1278 breakpoint
->length
, 1, code
);
1279 if (retval
!= ERROR_OK
)
1281 breakpoint
->set
= 0x11; /* Any nice value but 0 */
1284 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
1285 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
1286 /* Ensure that halting debug mode is enable */
1287 dscr
= dscr
| DSCR_HDE
;
1288 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1289 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
);
1290 if (retval
!= ERROR_OK
) {
1291 LOG_DEBUG("Failed to set DSCR.HDE");
1298 static int aarch64_set_context_breakpoint(struct target
*target
,
1299 struct breakpoint
*breakpoint
, uint8_t matchmode
)
1301 int retval
= ERROR_FAIL
;
1304 uint8_t byte_addr_select
= 0x0F;
1305 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
1306 struct armv8_common
*armv8
= &aarch64
->armv8_common
;
1307 struct aarch64_brp
*brp_list
= aarch64
->brp_list
;
1309 if (breakpoint
->set
) {
1310 LOG_WARNING("breakpoint already set");
1313 /*check available context BRPs*/
1314 while ((brp_list
[brp_i
].used
||
1315 (brp_list
[brp_i
].type
!= BRP_CONTEXT
)) && (brp_i
< aarch64
->brp_num
))
1318 if (brp_i
>= aarch64
->brp_num
) {
1319 LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
1323 breakpoint
->set
= brp_i
+ 1;
1324 control
= ((matchmode
& 0x7) << 20)
1326 | (byte_addr_select
<< 5)
1328 brp_list
[brp_i
].used
= 1;
1329 brp_list
[brp_i
].value
= (breakpoint
->asid
);
1330 brp_list
[brp_i
].control
= control
;
1331 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1332 + CPUV8_DBG_BVR_BASE
+ 16 * brp_list
[brp_i
].BRPn
,
1333 brp_list
[brp_i
].value
);
1334 if (retval
!= ERROR_OK
)
1336 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1337 + CPUV8_DBG_BCR_BASE
+ 16 * brp_list
[brp_i
].BRPn
,
1338 brp_list
[brp_i
].control
);
1339 if (retval
!= ERROR_OK
)
1341 LOG_DEBUG("brp %i control 0x%0" PRIx32
" value 0x%" TARGET_PRIxADDR
, brp_i
,
1342 brp_list
[brp_i
].control
,
1343 brp_list
[brp_i
].value
);
1348 static int aarch64_set_hybrid_breakpoint(struct target
*target
, struct breakpoint
*breakpoint
)
1350 int retval
= ERROR_FAIL
;
1351 int brp_1
= 0; /* holds the contextID pair */
1352 int brp_2
= 0; /* holds the IVA pair */
1353 uint32_t control_CTX
, control_IVA
;
1354 uint8_t CTX_byte_addr_select
= 0x0F;
1355 uint8_t IVA_byte_addr_select
= 0x0F;
1356 uint8_t CTX_machmode
= 0x03;
1357 uint8_t IVA_machmode
= 0x01;
1358 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
1359 struct armv8_common
*armv8
= &aarch64
->armv8_common
;
1360 struct aarch64_brp
*brp_list
= aarch64
->brp_list
;
1362 if (breakpoint
->set
) {
1363 LOG_WARNING("breakpoint already set");
1366 /*check available context BRPs*/
1367 while ((brp_list
[brp_1
].used
||
1368 (brp_list
[brp_1
].type
!= BRP_CONTEXT
)) && (brp_1
< aarch64
->brp_num
))
1371 printf("brp(CTX) found num: %d\n", brp_1
);
1372 if (brp_1
>= aarch64
->brp_num
) {
1373 LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
1377 while ((brp_list
[brp_2
].used
||
1378 (brp_list
[brp_2
].type
!= BRP_NORMAL
)) && (brp_2
< aarch64
->brp_num
))
1381 printf("brp(IVA) found num: %d\n", brp_2
);
1382 if (brp_2
>= aarch64
->brp_num
) {
1383 LOG_ERROR("ERROR Can not find free Breakpoint Register Pair");
1387 breakpoint
->set
= brp_1
+ 1;
1388 breakpoint
->linked_BRP
= brp_2
;
1389 control_CTX
= ((CTX_machmode
& 0x7) << 20)
1392 | (CTX_byte_addr_select
<< 5)
1394 brp_list
[brp_1
].used
= 1;
1395 brp_list
[brp_1
].value
= (breakpoint
->asid
);
1396 brp_list
[brp_1
].control
= control_CTX
;
1397 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1398 + CPUV8_DBG_BVR_BASE
+ 16 * brp_list
[brp_1
].BRPn
,
1399 brp_list
[brp_1
].value
);
1400 if (retval
!= ERROR_OK
)
1402 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1403 + CPUV8_DBG_BCR_BASE
+ 16 * brp_list
[brp_1
].BRPn
,
1404 brp_list
[brp_1
].control
);
1405 if (retval
!= ERROR_OK
)
1408 control_IVA
= ((IVA_machmode
& 0x7) << 20)
1411 | (IVA_byte_addr_select
<< 5)
1413 brp_list
[brp_2
].used
= 1;
1414 brp_list
[brp_2
].value
= breakpoint
->address
& 0xFFFFFFFFFFFFFFFC;
1415 brp_list
[brp_2
].control
= control_IVA
;
1416 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1417 + CPUV8_DBG_BVR_BASE
+ 16 * brp_list
[brp_2
].BRPn
,
1418 brp_list
[brp_2
].value
& 0xFFFFFFFF);
1419 if (retval
!= ERROR_OK
)
1421 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1422 + CPUV8_DBG_BVR_BASE
+ 4 + 16 * brp_list
[brp_2
].BRPn
,
1423 brp_list
[brp_2
].value
>> 32);
1424 if (retval
!= ERROR_OK
)
1426 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1427 + CPUV8_DBG_BCR_BASE
+ 16 * brp_list
[brp_2
].BRPn
,
1428 brp_list
[brp_2
].control
);
1429 if (retval
!= ERROR_OK
)
1435 static int aarch64_unset_breakpoint(struct target
*target
, struct breakpoint
*breakpoint
)
1438 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
1439 struct armv8_common
*armv8
= &aarch64
->armv8_common
;
1440 struct aarch64_brp
*brp_list
= aarch64
->brp_list
;
1442 if (!breakpoint
->set
) {
1443 LOG_WARNING("breakpoint not set");
1447 if (breakpoint
->type
== BKPT_HARD
) {
1448 if ((breakpoint
->address
!= 0) && (breakpoint
->asid
!= 0)) {
1449 int brp_i
= breakpoint
->set
- 1;
1450 int brp_j
= breakpoint
->linked_BRP
;
1451 if ((brp_i
< 0) || (brp_i
>= aarch64
->brp_num
)) {
1452 LOG_DEBUG("Invalid BRP number in breakpoint");
1455 LOG_DEBUG("rbp %i control 0x%0" PRIx32
" value 0x%" TARGET_PRIxADDR
, brp_i
,
1456 brp_list
[brp_i
].control
, brp_list
[brp_i
].value
);
1457 brp_list
[brp_i
].used
= 0;
1458 brp_list
[brp_i
].value
= 0;
1459 brp_list
[brp_i
].control
= 0;
1460 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1461 + CPUV8_DBG_BCR_BASE
+ 16 * brp_list
[brp_i
].BRPn
,
1462 brp_list
[brp_i
].control
);
1463 if (retval
!= ERROR_OK
)
1465 if ((brp_j
< 0) || (brp_j
>= aarch64
->brp_num
)) {
1466 LOG_DEBUG("Invalid BRP number in breakpoint");
1469 LOG_DEBUG("rbp %i control 0x%0" PRIx32
" value 0x%0" PRIx64
, brp_j
,
1470 brp_list
[brp_j
].control
, brp_list
[brp_j
].value
);
1471 brp_list
[brp_j
].used
= 0;
1472 brp_list
[brp_j
].value
= 0;
1473 brp_list
[brp_j
].control
= 0;
1474 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1475 + CPUV8_DBG_BCR_BASE
+ 16 * brp_list
[brp_j
].BRPn
,
1476 brp_list
[brp_j
].control
);
1477 if (retval
!= ERROR_OK
)
1479 breakpoint
->linked_BRP
= 0;
1480 breakpoint
->set
= 0;
1484 int brp_i
= breakpoint
->set
- 1;
1485 if ((brp_i
< 0) || (brp_i
>= aarch64
->brp_num
)) {
1486 LOG_DEBUG("Invalid BRP number in breakpoint");
1489 LOG_DEBUG("rbp %i control 0x%0" PRIx32
" value 0x%0" PRIx64
, brp_i
,
1490 brp_list
[brp_i
].control
, brp_list
[brp_i
].value
);
1491 brp_list
[brp_i
].used
= 0;
1492 brp_list
[brp_i
].value
= 0;
1493 brp_list
[brp_i
].control
= 0;
1494 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1495 + CPUV8_DBG_BCR_BASE
+ 16 * brp_list
[brp_i
].BRPn
,
1496 brp_list
[brp_i
].control
);
1497 if (retval
!= ERROR_OK
)
1499 retval
= aarch64_dap_write_memap_register_u32(target
, armv8
->debug_base
1500 + CPUV8_DBG_BVR_BASE
+ 16 * brp_list
[brp_i
].BRPn
,
1501 brp_list
[brp_i
].value
);
1502 if (retval
!= ERROR_OK
)
1504 breakpoint
->set
= 0;
1508 /* restore original instruction (kept in target endianness) */
1509 if (breakpoint
->length
== 4) {
1510 retval
= target_write_memory(target
,
1511 breakpoint
->address
& 0xFFFFFFFFFFFFFFFE,
1512 4, 1, breakpoint
->orig_instr
);
1513 if (retval
!= ERROR_OK
)
1516 retval
= target_write_memory(target
,
1517 breakpoint
->address
& 0xFFFFFFFFFFFFFFFE,
1518 2, 1, breakpoint
->orig_instr
);
1519 if (retval
!= ERROR_OK
)
1523 breakpoint
->set
= 0;
1528 static int aarch64_add_breakpoint(struct target
*target
,
1529 struct breakpoint
*breakpoint
)
1531 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
1533 if ((breakpoint
->type
== BKPT_HARD
) && (aarch64
->brp_num_available
< 1)) {
1534 LOG_INFO("no hardware breakpoint available");
1535 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1538 if (breakpoint
->type
== BKPT_HARD
)
1539 aarch64
->brp_num_available
--;
1541 return aarch64_set_breakpoint(target
, breakpoint
, 0x00); /* Exact match */
1544 static int aarch64_add_context_breakpoint(struct target
*target
,
1545 struct breakpoint
*breakpoint
)
1547 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
1549 if ((breakpoint
->type
== BKPT_HARD
) && (aarch64
->brp_num_available
< 1)) {
1550 LOG_INFO("no hardware breakpoint available");
1551 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1554 if (breakpoint
->type
== BKPT_HARD
)
1555 aarch64
->brp_num_available
--;
1557 return aarch64_set_context_breakpoint(target
, breakpoint
, 0x02); /* asid match */
1560 static int aarch64_add_hybrid_breakpoint(struct target
*target
,
1561 struct breakpoint
*breakpoint
)
1563 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
1565 if ((breakpoint
->type
== BKPT_HARD
) && (aarch64
->brp_num_available
< 1)) {
1566 LOG_INFO("no hardware breakpoint available");
1567 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1570 if (breakpoint
->type
== BKPT_HARD
)
1571 aarch64
->brp_num_available
--;
1573 return aarch64_set_hybrid_breakpoint(target
, breakpoint
); /* ??? */
1577 static int aarch64_remove_breakpoint(struct target
*target
, struct breakpoint
*breakpoint
)
1579 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
1582 /* It is perfectly possible to remove breakpoints while the target is running */
1583 if (target
->state
!= TARGET_HALTED
) {
1584 LOG_WARNING("target not halted");
1585 return ERROR_TARGET_NOT_HALTED
;
1589 if (breakpoint
->set
) {
1590 aarch64_unset_breakpoint(target
, breakpoint
);
1591 if (breakpoint
->type
== BKPT_HARD
)
1592 aarch64
->brp_num_available
++;
1599 * Cortex-A8 Reset functions
1602 static int aarch64_assert_reset(struct target
*target
)
1604 struct armv8_common
*armv8
= target_to_armv8(target
);
1608 /* FIXME when halt is requested, make it work somehow... */
1610 /* Issue some kind of warm reset. */
1611 if (target_has_event_action(target
, TARGET_EVENT_RESET_ASSERT
))
1612 target_handle_event(target
, TARGET_EVENT_RESET_ASSERT
);
1613 else if (jtag_get_reset_config() & RESET_HAS_SRST
) {
1614 /* REVISIT handle "pulls" cases, if there's
1615 * hardware that needs them to work.
1617 jtag_add_reset(0, 1);
1619 LOG_ERROR("%s: how to reset?", target_name(target
));
1623 /* registers are now invalid */
1624 register_cache_invalidate(armv8
->arm
.core_cache
);
1626 target
->state
= TARGET_RESET
;
1631 static int aarch64_deassert_reset(struct target
*target
)
1637 /* be certain SRST is off */
1638 jtag_add_reset(0, 0);
1640 retval
= aarch64_poll(target
);
1641 if (retval
!= ERROR_OK
)
1644 if (target
->reset_halt
) {
1645 if (target
->state
!= TARGET_HALTED
) {
1646 LOG_WARNING("%s: ran after reset and before halt ...",
1647 target_name(target
));
1648 retval
= target_halt(target
);
1649 if (retval
!= ERROR_OK
)
1657 static int aarch64_write_apb_ap_memory(struct target
*target
,
1658 uint64_t address
, uint32_t size
,
1659 uint32_t count
, const uint8_t *buffer
)
1661 /* write memory through APB-AP */
1662 int retval
= ERROR_COMMAND_SYNTAX_ERROR
;
1663 struct armv8_common
*armv8
= target_to_armv8(target
);
1664 struct arm
*arm
= &armv8
->arm
;
1665 int total_bytes
= count
* size
;
1667 int start_byte
= address
& 0x3;
1668 int end_byte
= (address
+ total_bytes
) & 0x3;
1671 uint8_t *tmp_buff
= NULL
;
1673 LOG_DEBUG("Writing APB-AP memory address 0x%" PRIx64
" size %" PRIu32
" count%" PRIu32
,
1674 address
, size
, count
);
1675 if (target
->state
!= TARGET_HALTED
) {
1676 LOG_WARNING("target not halted");
1677 return ERROR_TARGET_NOT_HALTED
;
1680 total_u32
= DIV_ROUND_UP((address
& 3) + total_bytes
, 4);
1682 /* Mark register R0 as dirty, as it will be used
1683 * for transferring the data.
1684 * It will be restored automatically when exiting
1687 reg
= armv8_reg_current(arm
, 1);
1690 reg
= armv8_reg_current(arm
, 0);
1693 /* clear any abort */
1694 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1695 armv8
->debug_base
+ CPUV8_DBG_DRCR
, DRCR_CSE
);
1696 if (retval
!= ERROR_OK
)
1700 /* This algorithm comes from DDI0487A.g, chapter J9.1 */
1702 /* The algorithm only copies 32 bit words, so the buffer
1703 * should be expanded to include the words at either end.
1704 * The first and last words will be read first to avoid
1705 * corruption if needed.
1707 tmp_buff
= malloc(total_u32
* 4);
1709 if ((start_byte
!= 0) && (total_u32
> 1)) {
1710 /* First bytes not aligned - read the 32 bit word to avoid corrupting
1711 * the other bytes in the word.
1713 retval
= aarch64_read_apb_ap_memory(target
, (address
& ~0x3), 4, 1, tmp_buff
);
1714 if (retval
!= ERROR_OK
)
1715 goto error_free_buff_w
;
1718 /* If end of write is not aligned, or the write is less than 4 bytes */
1719 if ((end_byte
!= 0) ||
1720 ((total_u32
== 1) && (total_bytes
!= 4))) {
1722 /* Read the last word to avoid corruption during 32 bit write */
1723 int mem_offset
= (total_u32
-1) * 4;
1724 retval
= aarch64_read_apb_ap_memory(target
, (address
& ~0x3) + mem_offset
, 4, 1, &tmp_buff
[mem_offset
]);
1725 if (retval
!= ERROR_OK
)
1726 goto error_free_buff_w
;
1729 /* Copy the write buffer over the top of the temporary buffer */
1730 memcpy(&tmp_buff
[start_byte
], buffer
, total_bytes
);
1732 /* We now have a 32 bit aligned buffer that can be written */
1735 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
1736 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
1737 if (retval
!= ERROR_OK
)
1738 goto error_free_buff_w
;
1740 /* Set Normal access mode */
1741 dscr
= (dscr
& ~DSCR_MA
);
1742 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1743 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
);
1745 if (arm
->core_state
== ARM_STATE_AARCH64
) {
1746 /* Write X0 with value 'address' using write procedure */
1747 /* Step 1.a+b - Write the address for read access into DBGDTR_EL0 */
1748 retval
+= aarch64_write_dcc_64(armv8
, address
& ~0x3ULL
);
1749 /* Step 1.c - Copy value from DTR to R0 using instruction mrs DBGDTR_EL0, x0 */
1750 retval
+= aarch64_exec_opcode(target
,
1751 ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0
, 0), &dscr
);
1753 /* Write R0 with value 'address' using write procedure */
1754 /* Step 1.a+b - Write the address for read access into DBGDTRRX */
1755 retval
+= aarch64_write_dcc(armv8
, address
& ~0x3ULL
);
1756 /* Step 1.c - Copy value from DTR to R0 using instruction mrc DBGDTRTXint, r0 */
1757 retval
+= aarch64_exec_opcode(target
,
1758 T32_FMTITR(ARMV4_5_MRC(14, 0, 0, 0, 5, 0)), &dscr
);
1761 /* Step 1.d - Change DCC to memory mode */
1762 dscr
= dscr
| DSCR_MA
;
1763 retval
+= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1764 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
);
1765 if (retval
!= ERROR_OK
)
1766 goto error_unset_dtr_w
;
1769 /* Step 2.a - Do the write */
1770 retval
= mem_ap_write_buf_noincr(armv8
->debug_ap
,
1771 tmp_buff
, 4, total_u32
, armv8
->debug_base
+ CPUV8_DBG_DTRRX
);
1772 if (retval
!= ERROR_OK
)
1773 goto error_unset_dtr_w
;
1775 /* Step 3.a - Switch DTR mode back to Normal mode */
1776 dscr
= (dscr
& ~DSCR_MA
);
1777 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1778 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
);
1779 if (retval
!= ERROR_OK
)
1780 goto error_unset_dtr_w
;
1782 /* Check for sticky abort flags in the DSCR */
1783 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
1784 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
1785 if (retval
!= ERROR_OK
)
1786 goto error_free_buff_w
;
1787 if (dscr
& (DSCR_ERR
| DSCR_SYS_ERROR_PEND
)) {
1788 /* Abort occurred - clear it and exit */
1789 LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32
, dscr
);
1790 mem_ap_write_atomic_u32(armv8
->debug_ap
,
1791 armv8
->debug_base
+ CPUV8_DBG_DRCR
, 1<<2);
1792 goto error_free_buff_w
;
1800 /* Unset DTR mode */
1801 mem_ap_read_atomic_u32(armv8
->debug_ap
,
1802 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
1803 dscr
= (dscr
& ~DSCR_MA
);
1804 mem_ap_write_atomic_u32(armv8
->debug_ap
,
1805 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
);
1812 static int aarch64_read_apb_ap_memory(struct target
*target
,
1813 target_addr_t address
, uint32_t size
,
1814 uint32_t count
, uint8_t *buffer
)
1816 /* read memory through APB-AP */
1817 int retval
= ERROR_COMMAND_SYNTAX_ERROR
;
1818 struct armv8_common
*armv8
= target_to_armv8(target
);
1819 struct arm
*arm
= &armv8
->arm
;
1820 int total_bytes
= count
* size
;
1822 int start_byte
= address
& 0x3;
1823 int end_byte
= (address
+ total_bytes
) & 0x3;
1826 uint8_t *tmp_buff
= NULL
;
1830 LOG_DEBUG("Reading APB-AP memory address 0x%" TARGET_PRIxADDR
" size %" PRIu32
" count%" PRIu32
,
1831 address
, size
, count
);
1832 if (target
->state
!= TARGET_HALTED
) {
1833 LOG_WARNING("target not halted");
1834 return ERROR_TARGET_NOT_HALTED
;
1837 total_u32
= DIV_ROUND_UP((address
& 3) + total_bytes
, 4);
1838 /* Mark register X0, X1 as dirty, as it will be used
1839 * for transferring the data.
1840 * It will be restored automatically when exiting
1843 reg
= armv8_reg_current(arm
, 1);
1846 reg
= armv8_reg_current(arm
, 0);
1849 /* clear any abort */
1850 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1851 armv8
->debug_base
+ CPUV8_DBG_DRCR
, DRCR_CSE
);
1852 if (retval
!= ERROR_OK
)
1853 goto error_free_buff_r
;
1856 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
1857 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
1859 /* This algorithm comes from DDI0487A.g, chapter J9.1 */
1861 /* Set Normal access mode */
1862 dscr
= (dscr
& ~DSCR_MA
);
1863 retval
+= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1864 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
);
1866 if (arm
->core_state
== ARM_STATE_AARCH64
) {
1867 /* Write X0 with value 'address' using write procedure */
1868 /* Step 1.a+b - Write the address for read access into DBGDTR_EL0 */
1869 retval
+= aarch64_write_dcc_64(armv8
, address
& ~0x3ULL
);
1870 /* Step 1.c - Copy value from DTR to R0 using instruction mrs DBGDTR_EL0, x0 */
1871 retval
+= aarch64_exec_opcode(target
, ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0
, 0), &dscr
);
1872 /* Step 1.d - Dummy operation to ensure EDSCR.Txfull == 1 */
1873 retval
+= aarch64_exec_opcode(target
, ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0
, 0), &dscr
);
1874 /* Step 1.e - Change DCC to memory mode */
1875 dscr
= dscr
| DSCR_MA
;
1876 retval
+= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1877 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
);
1878 /* Step 1.f - read DBGDTRTX and discard the value */
1879 retval
+= mem_ap_read_atomic_u32(armv8
->debug_ap
,
1880 armv8
->debug_base
+ CPUV8_DBG_DTRTX
, &value
);
1882 /* Write R0 with value 'address' using write procedure */
1883 /* Step 1.a+b - Write the address for read access into DBGDTRRXint */
1884 retval
+= aarch64_write_dcc(armv8
, address
& ~0x3ULL
);
1885 /* Step 1.c - Copy value from DTR to R0 using instruction mrc DBGDTRTXint, r0 */
1886 retval
+= aarch64_exec_opcode(target
,
1887 T32_FMTITR(ARMV4_5_MRC(14, 0, 0, 0, 5, 0)), &dscr
);
1888 /* Step 1.d - Dummy operation to ensure EDSCR.Txfull == 1 */
1889 retval
+= aarch64_exec_opcode(target
,
1890 T32_FMTITR(ARMV4_5_MCR(14, 0, 0, 0, 5, 0)), &dscr
);
1891 /* Step 1.e - Change DCC to memory mode */
1892 dscr
= dscr
| DSCR_MA
;
1893 retval
+= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1894 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
);
1895 /* Step 1.f - read DBGDTRTX and discard the value */
1896 retval
+= mem_ap_read_atomic_u32(armv8
->debug_ap
,
1897 armv8
->debug_base
+ CPUV8_DBG_DTRTX
, &value
);
1900 if (retval
!= ERROR_OK
)
1901 goto error_unset_dtr_r
;
1903 /* Optimize the read as much as we can, either way we read in a single pass */
1904 if ((start_byte
) || (end_byte
)) {
1905 /* The algorithm only copies 32 bit words, so the buffer
1906 * should be expanded to include the words at either end.
1907 * The first and last words will be read into a temp buffer
1908 * to avoid corruption
1910 tmp_buff
= malloc(total_u32
* 4);
1912 goto error_unset_dtr_r
;
1914 /* use the tmp buffer to read the entire data */
1915 u8buf_ptr
= tmp_buff
;
1917 /* address and read length are aligned so read directly into the passed buffer */
1920 /* Read the data - Each read of the DTRTX register causes the instruction to be reissued
1921 * Abort flags are sticky, so can be read at end of transactions
1923 * This data is read in aligned to 32 bit boundary.
1926 /* Step 2.a - Loop n-1 times, each read of DBGDTRTX reads the data from [X0] and
1927 * increments X0 by 4. */
1928 retval
= mem_ap_read_buf_noincr(armv8
->debug_ap
, u8buf_ptr
, 4, total_u32
-1,
1929 armv8
->debug_base
+ CPUV8_DBG_DTRTX
);
1930 if (retval
!= ERROR_OK
)
1931 goto error_unset_dtr_r
;
1933 /* Step 3.a - set DTR access mode back to Normal mode */
1934 dscr
= (dscr
& ~DSCR_MA
);
1935 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1936 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
);
1937 if (retval
!= ERROR_OK
)
1938 goto error_free_buff_r
;
1940 /* Step 3.b - read DBGDTRTX for the final value */
1941 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
1942 armv8
->debug_base
+ CPUV8_DBG_DTRTX
, &value
);
1943 memcpy(u8buf_ptr
+ (total_u32
-1) * 4, &value
, 4);
1945 /* Check for sticky abort flags in the DSCR */
1946 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
1947 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
1948 if (retval
!= ERROR_OK
)
1949 goto error_free_buff_r
;
1950 if (dscr
& (DSCR_ERR
| DSCR_SYS_ERROR_PEND
)) {
1951 /* Abort occurred - clear it and exit */
1952 LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32
, dscr
);
1953 mem_ap_write_atomic_u32(armv8
->debug_ap
,
1954 armv8
->debug_base
+ CPUV8_DBG_DRCR
, DRCR_CSE
);
1955 goto error_free_buff_r
;
1958 /* check if we need to copy aligned data by applying any shift necessary */
1960 memcpy(buffer
, tmp_buff
+ start_byte
, total_bytes
);
1968 /* Unset DTR mode */
1969 mem_ap_read_atomic_u32(armv8
->debug_ap
,
1970 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
1971 dscr
= (dscr
& ~DSCR_MA
);
1972 mem_ap_write_atomic_u32(armv8
->debug_ap
,
1973 armv8
->debug_base
+ CPUV8_DBG_DSCR
, dscr
);
1980 static int aarch64_read_phys_memory(struct target
*target
,
1981 target_addr_t address
, uint32_t size
,
1982 uint32_t count
, uint8_t *buffer
)
1984 struct armv8_common
*armv8
= target_to_armv8(target
);
1985 int retval
= ERROR_COMMAND_SYNTAX_ERROR
;
1986 struct adiv5_dap
*swjdp
= armv8
->arm
.dap
;
1987 uint8_t apsel
= swjdp
->apsel
;
1988 LOG_DEBUG("Reading memory at real address 0x%" TARGET_PRIxADDR
"; size %" PRId32
"; count %" PRId32
,
1989 address
, size
, count
);
1991 if (count
&& buffer
) {
1993 if (armv8
->memory_ap_available
&& (apsel
== armv8
->memory_ap
->ap_num
)) {
1995 /* read memory through AHB-AP */
1996 retval
= mem_ap_read_buf(armv8
->memory_ap
, buffer
, size
, count
, address
);
1998 /* read memory through APB-AP */
1999 retval
= aarch64_mmu_modify(target
, 0);
2000 if (retval
!= ERROR_OK
)
2002 retval
= aarch64_read_apb_ap_memory(target
, address
, size
, count
, buffer
);
2008 static int aarch64_read_memory(struct target
*target
, target_addr_t address
,
2009 uint32_t size
, uint32_t count
, uint8_t *buffer
)
2011 int mmu_enabled
= 0;
2012 target_addr_t virt
, phys
;
2014 struct armv8_common
*armv8
= target_to_armv8(target
);
2015 struct adiv5_dap
*swjdp
= armv8
->arm
.dap
;
2016 uint8_t apsel
= swjdp
->apsel
;
2018 /* aarch64 handles unaligned memory access */
2019 LOG_DEBUG("Reading memory at address 0x%" TARGET_PRIxADDR
"; size %" PRId32
"; count %" PRId32
, address
,
2022 /* determine if MMU was enabled on target stop */
2023 if (!armv8
->is_armv7r
) {
2024 retval
= aarch64_mmu(target
, &mmu_enabled
);
2025 if (retval
!= ERROR_OK
)
2029 if (armv8
->memory_ap_available
&& (apsel
== armv8
->memory_ap
->ap_num
)) {
2032 retval
= aarch64_virt2phys(target
, virt
, &phys
);
2033 if (retval
!= ERROR_OK
)
2036 LOG_DEBUG("Reading at virtual address. Translating v:0x%" TARGET_PRIxADDR
" to r:0x%" TARGET_PRIxADDR
,
2040 retval
= aarch64_read_phys_memory(target
, address
, size
, count
,
2044 retval
= aarch64_check_address(target
, address
);
2045 if (retval
!= ERROR_OK
)
2047 /* enable MMU as we could have disabled it for phys
2049 retval
= aarch64_mmu_modify(target
, 1);
2050 if (retval
!= ERROR_OK
)
2053 retval
= aarch64_read_apb_ap_memory(target
, address
, size
,
2059 static int aarch64_write_phys_memory(struct target
*target
,
2060 target_addr_t address
, uint32_t size
,
2061 uint32_t count
, const uint8_t *buffer
)
2063 struct armv8_common
*armv8
= target_to_armv8(target
);
2064 struct adiv5_dap
*swjdp
= armv8
->arm
.dap
;
2065 int retval
= ERROR_COMMAND_SYNTAX_ERROR
;
2066 uint8_t apsel
= swjdp
->apsel
;
2068 LOG_DEBUG("Writing memory to real address 0x%" TARGET_PRIxADDR
"; size %" PRId32
"; count %" PRId32
, address
,
2071 if (count
&& buffer
) {
2073 if (armv8
->memory_ap_available
&& (apsel
== armv8
->memory_ap
->ap_num
)) {
2075 /* write memory through AHB-AP */
2076 retval
= mem_ap_write_buf(armv8
->memory_ap
, buffer
, size
, count
, address
);
2079 /* write memory through APB-AP */
2080 if (!armv8
->is_armv7r
) {
2081 retval
= aarch64_mmu_modify(target
, 0);
2082 if (retval
!= ERROR_OK
)
2085 return aarch64_write_apb_ap_memory(target
, address
, size
, count
, buffer
);
2090 /* REVISIT this op is generic ARMv7-A/R stuff */
2091 if (retval
== ERROR_OK
&& target
->state
== TARGET_HALTED
) {
2092 struct arm_dpm
*dpm
= armv8
->arm
.dpm
;
2094 retval
= dpm
->prepare(dpm
);
2095 if (retval
!= ERROR_OK
)
2098 /* The Cache handling will NOT work with MMU active, the
2099 * wrong addresses will be invalidated!
2101 * For both ICache and DCache, walk all cache lines in the
2102 * address range. Cortex-A8 has fixed 64 byte line length.
2104 * REVISIT per ARMv7, these may trigger watchpoints ...
2107 /* invalidate I-Cache */
2108 if (armv8
->armv8_mmu
.armv8_cache
.i_cache_enabled
) {
2109 /* ICIMVAU - Invalidate Cache single entry
2111 * MCR p15, 0, r0, c7, c5, 1
2113 for (uint32_t cacheline
= address
;
2114 cacheline
< address
+ size
* count
;
2116 retval
= dpm
->instr_write_data_r0(dpm
,
2117 ARMV4_5_MCR(15, 0, 0, 7, 5, 1),
2119 if (retval
!= ERROR_OK
)
2124 /* invalidate D-Cache */
2125 if (armv8
->armv8_mmu
.armv8_cache
.d_u_cache_enabled
) {
2126 /* DCIMVAC - Invalidate data Cache line
2128 * MCR p15, 0, r0, c7, c6, 1
2130 for (uint32_t cacheline
= address
;
2131 cacheline
< address
+ size
* count
;
2133 retval
= dpm
->instr_write_data_r0(dpm
,
2134 ARMV4_5_MCR(15, 0, 0, 7, 6, 1),
2136 if (retval
!= ERROR_OK
)
2141 /* (void) */ dpm
->finish(dpm
);
2147 static int aarch64_write_memory(struct target
*target
, target_addr_t address
,
2148 uint32_t size
, uint32_t count
, const uint8_t *buffer
)
2150 int mmu_enabled
= 0;
2151 target_addr_t virt
, phys
;
2153 struct armv8_common
*armv8
= target_to_armv8(target
);
2154 struct adiv5_dap
*swjdp
= armv8
->arm
.dap
;
2155 uint8_t apsel
= swjdp
->apsel
;
2157 /* aarch64 handles unaligned memory access */
2158 LOG_DEBUG("Writing memory at address 0x%" TARGET_PRIxADDR
"; size %" PRId32
2159 "; count %" PRId32
, address
, size
, count
);
2161 /* determine if MMU was enabled on target stop */
2162 if (!armv8
->is_armv7r
) {
2163 retval
= aarch64_mmu(target
, &mmu_enabled
);
2164 if (retval
!= ERROR_OK
)
2168 if (armv8
->memory_ap_available
&& (apsel
== armv8
->memory_ap
->ap_num
)) {
2169 LOG_DEBUG("Writing memory to address 0x%" TARGET_PRIxADDR
"; size %"
2170 PRId32
"; count %" PRId32
, address
, size
, count
);
2173 retval
= aarch64_virt2phys(target
, virt
, &phys
);
2174 if (retval
!= ERROR_OK
)
2177 LOG_DEBUG("Writing to virtual address. Translating v:0x%"
2178 TARGET_PRIxADDR
" to r:0x%" TARGET_PRIxADDR
, virt
, phys
);
2181 retval
= aarch64_write_phys_memory(target
, address
, size
,
2185 retval
= aarch64_check_address(target
, address
);
2186 if (retval
!= ERROR_OK
)
2188 /* enable MMU as we could have disabled it for phys access */
2189 retval
= aarch64_mmu_modify(target
, 1);
2190 if (retval
!= ERROR_OK
)
2193 retval
= aarch64_write_apb_ap_memory(target
, address
, size
, count
, buffer
);
2198 static int aarch64_handle_target_request(void *priv
)
2200 struct target
*target
= priv
;
2201 struct armv8_common
*armv8
= target_to_armv8(target
);
2204 if (!target_was_examined(target
))
2206 if (!target
->dbg_msg_enabled
)
2209 if (target
->state
== TARGET_RUNNING
) {
2212 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2213 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
2215 /* check if we have data */
2216 while ((dscr
& DSCR_DTR_TX_FULL
) && (retval
== ERROR_OK
)) {
2217 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2218 armv8
->debug_base
+ CPUV8_DBG_DTRTX
, &request
);
2219 if (retval
== ERROR_OK
) {
2220 target_request(target
, request
);
2221 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2222 armv8
->debug_base
+ CPUV8_DBG_DSCR
, &dscr
);
2230 static int aarch64_examine_first(struct target
*target
)
2232 struct aarch64_common
*aarch64
= target_to_aarch64(target
);
2233 struct armv8_common
*armv8
= &aarch64
->armv8_common
;
2234 struct adiv5_dap
*swjdp
= armv8
->arm
.dap
;
2235 int retval
= ERROR_OK
;
2236 uint32_t pfr
, debug
, ctypr
, ttypr
, cpuid
;
2239 /* We do one extra read to ensure DAP is configured,
2240 * we call ahbap_debugport_init(swjdp) instead
2242 retval
= dap_dp_init(swjdp
);
2243 if (retval
!= ERROR_OK
)
2246 /* Search for the APB-AB - it is needed for access to debug registers */
2247 retval
= dap_find_ap(swjdp
, AP_TYPE_APB_AP
, &armv8
->debug_ap
);
2248 if (retval
!= ERROR_OK
) {
2249 LOG_ERROR("Could not find APB-AP for debug access");
2253 retval
= mem_ap_init(armv8
->debug_ap
);
2254 if (retval
!= ERROR_OK
) {
2255 LOG_ERROR("Could not initialize the APB-AP");
2259 armv8
->debug_ap
->memaccess_tck
= 80;
2261 /* Search for the AHB-AB */
2262 armv8
->memory_ap_available
= false;
2263 retval
= dap_find_ap(swjdp
, AP_TYPE_AHB_AP
, &armv8
->memory_ap
);
2264 if (retval
== ERROR_OK
) {
2265 retval
= mem_ap_init(armv8
->memory_ap
);
2266 if (retval
== ERROR_OK
)
2267 armv8
->memory_ap_available
= true;
2269 if (retval
!= ERROR_OK
) {
2270 /* AHB-AP not found or unavailable - use the CPU */
2271 LOG_DEBUG("No AHB-AP available for memory access");
2275 if (!target
->dbgbase_set
) {
2277 /* Get ROM Table base */
2279 int32_t coreidx
= target
->coreid
;
2280 retval
= dap_get_debugbase(armv8
->debug_ap
, &dbgbase
, &apid
);
2281 if (retval
!= ERROR_OK
)
2283 /* Lookup 0x15 -- Processor DAP */
2284 retval
= dap_lookup_cs_component(armv8
->debug_ap
, dbgbase
, 0x15,
2285 &armv8
->debug_base
, &coreidx
);
2286 if (retval
!= ERROR_OK
)
2288 LOG_DEBUG("Detected core %" PRId32
" dbgbase: %08" PRIx32
,
2289 coreidx
, armv8
->debug_base
);
2291 armv8
->debug_base
= target
->dbgbase
;
2293 LOG_DEBUG("Target ctibase is 0x%x", target
->ctibase
);
2294 if (target
->ctibase
== 0)
2295 armv8
->cti_base
= target
->ctibase
= armv8
->debug_base
+ 0x1000;
2297 armv8
->cti_base
= target
->ctibase
;
2299 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
2300 armv8
->debug_base
+ CPUV8_DBG_LOCKACCESS
, 0xC5ACCE55);
2301 if (retval
!= ERROR_OK
) {
2302 LOG_DEBUG("Examine %s failed", "oslock");
2306 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2307 armv8
->debug_base
+ 0x88, &cpuid
);
2308 LOG_DEBUG("0x88 = %x", cpuid
);
2310 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2311 armv8
->debug_base
+ 0x314, &cpuid
);
2312 LOG_DEBUG("0x314 = %x", cpuid
);
2314 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2315 armv8
->debug_base
+ 0x310, &cpuid
);
2316 LOG_DEBUG("0x310 = %x", cpuid
);
2317 if (retval
!= ERROR_OK
)
2320 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2321 armv8
->debug_base
+ CPUDBG_CPUID
, &cpuid
);
2322 if (retval
!= ERROR_OK
) {
2323 LOG_DEBUG("Examine %s failed", "CPUID");
2327 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2328 armv8
->debug_base
+ CPUDBG_CTYPR
, &ctypr
);
2329 if (retval
!= ERROR_OK
) {
2330 LOG_DEBUG("Examine %s failed", "CTYPR");
2334 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2335 armv8
->debug_base
+ CPUDBG_TTYPR
, &ttypr
);
2336 if (retval
!= ERROR_OK
) {
2337 LOG_DEBUG("Examine %s failed", "TTYPR");
2341 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2342 armv8
->debug_base
+ ID_AA64PFR0_EL1
, &pfr
);
2343 if (retval
!= ERROR_OK
) {
2344 LOG_DEBUG("Examine %s failed", "ID_AA64DFR0_EL1");
2347 retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
2348 armv8
->debug_base
+ ID_AA64DFR0_EL1
, &debug
);
2349 if (retval
!= ERROR_OK
) {
2350 LOG_DEBUG("Examine %s failed", "ID_AA64DFR0_EL1");
2354 LOG_DEBUG("cpuid = 0x%08" PRIx32
, cpuid
);
2355 LOG_DEBUG("ctypr = 0x%08" PRIx32
, ctypr
);
2356 LOG_DEBUG("ttypr = 0x%08" PRIx32
, ttypr
);
2357 LOG_DEBUG("ID_AA64PFR0_EL1 = 0x%08" PRIx32
, pfr
);
2358 LOG_DEBUG("ID_AA64DFR0_EL1 = 0x%08" PRIx32
, debug
);
2360 armv8
->arm
.core_type
= ARM_MODE_MON
;
2361 armv8
->arm
.core_state
= ARM_STATE_AARCH64
;
2362 retval
= aarch64_dpm_setup(aarch64
, debug
);
2363 if (retval
!= ERROR_OK
)
2366 /* Setup Breakpoint Register Pairs */
2367 aarch64
->brp_num
= ((debug
>> 12) & 0x0F) + 1;
2368 aarch64
->brp_num_context
= ((debug
>> 28) & 0x0F) + 1;
2370 /* hack - no context bpt support yet */
2371 aarch64
->brp_num_context
= 0;
2373 aarch64
->brp_num_available
= aarch64
->brp_num
;
2374 aarch64
->brp_list
= calloc(aarch64
->brp_num
, sizeof(struct aarch64_brp
));
2375 for (i
= 0; i
< aarch64
->brp_num
; i
++) {
2376 aarch64
->brp_list
[i
].used
= 0;
2377 if (i
< (aarch64
->brp_num
-aarch64
->brp_num_context
))
2378 aarch64
->brp_list
[i
].type
= BRP_NORMAL
;
2380 aarch64
->brp_list
[i
].type
= BRP_CONTEXT
;
2381 aarch64
->brp_list
[i
].value
= 0;
2382 aarch64
->brp_list
[i
].control
= 0;
2383 aarch64
->brp_list
[i
].BRPn
= i
;
2386 LOG_DEBUG("Configured %i hw breakpoints", aarch64
->brp_num
);
2388 target_set_examined(target
);
2392 static int aarch64_examine(struct target
*target
)
2394 int retval
= ERROR_OK
;
2396 /* don't re-probe hardware after each reset */
2397 if (!target_was_examined(target
))
2398 retval
= aarch64_examine_first(target
);
2400 /* Configure core debug access */
2401 if (retval
== ERROR_OK
)
2402 retval
= aarch64_init_debug_access(target
);
2408 * Cortex-A8 target creation and initialization
2411 static int aarch64_init_target(struct command_context
*cmd_ctx
,
2412 struct target
*target
)
2414 /* examine_first() does a bunch of this */
2418 static int aarch64_init_arch_info(struct target
*target
,
2419 struct aarch64_common
*aarch64
, struct jtag_tap
*tap
)
2421 struct armv8_common
*armv8
= &aarch64
->armv8_common
;
2422 struct adiv5_dap
*dap
= armv8
->arm
.dap
;
2424 armv8
->arm
.dap
= dap
;
2426 /* Setup struct aarch64_common */
2427 aarch64
->common_magic
= AARCH64_COMMON_MAGIC
;
2428 /* tap has no dap initialized */
2430 tap
->dap
= dap_init();
2432 /* Leave (only) generic DAP stuff for debugport_init() */
2433 tap
->dap
->tap
= tap
;
2436 armv8
->arm
.dap
= tap
->dap
;
2438 aarch64
->fast_reg_read
= 0;
2440 /* register arch-specific functions */
2441 armv8
->examine_debug_reason
= NULL
;
2443 armv8
->post_debug_entry
= aarch64_post_debug_entry
;
2445 armv8
->pre_restore_context
= NULL
;
2447 armv8
->armv8_mmu
.read_physical_memory
= aarch64_read_phys_memory
;
2449 /* REVISIT v7a setup should be in a v7a-specific routine */
2450 armv8_init_arch_info(target
, armv8
);
2451 target_register_timer_callback(aarch64_handle_target_request
, 1, 1, target
);
2456 static int aarch64_target_create(struct target
*target
, Jim_Interp
*interp
)
2458 struct aarch64_common
*aarch64
= calloc(1, sizeof(struct aarch64_common
));
2460 aarch64
->armv8_common
.is_armv7r
= false;
2462 return aarch64_init_arch_info(target
, aarch64
, target
->tap
);
2465 static int aarch64_mmu(struct target
*target
, int *enabled
)
2467 if (target
->state
!= TARGET_HALTED
) {
2468 LOG_ERROR("%s: target not halted", __func__
);
2469 return ERROR_TARGET_INVALID
;
2472 *enabled
= target_to_aarch64(target
)->armv8_common
.armv8_mmu
.mmu_enabled
;
2476 static int aarch64_virt2phys(struct target
*target
, target_addr_t virt
,
2477 target_addr_t
*phys
)
2479 int retval
= ERROR_FAIL
;
2480 struct armv8_common
*armv8
= target_to_armv8(target
);
2481 struct adiv5_dap
*swjdp
= armv8
->arm
.dap
;
2482 uint8_t apsel
= swjdp
->apsel
;
2483 if (armv8
->memory_ap_available
&& (apsel
== armv8
->memory_ap
->ap_num
)) {
2485 retval
= armv8_mmu_translate_va(target
,
2487 if (retval
!= ERROR_OK
)
2490 } else {/* use this method if armv8->memory_ap not selected
2491 * mmu must be enable in order to get a correct translation */
2492 retval
= aarch64_mmu_modify(target
, 1);
2493 if (retval
!= ERROR_OK
)
2495 retval
= armv8_mmu_translate_va_pa(target
, virt
, phys
, 1);
2501 COMMAND_HANDLER(aarch64_handle_cache_info_command
)
2503 struct target
*target
= get_current_target(CMD_CTX
);
2504 struct armv8_common
*armv8
= target_to_armv8(target
);
2506 return armv8_handle_cache_info_command(CMD_CTX
,
2507 &armv8
->armv8_mmu
.armv8_cache
);
2511 COMMAND_HANDLER(aarch64_handle_dbginit_command
)
2513 struct target
*target
= get_current_target(CMD_CTX
);
2514 if (!target_was_examined(target
)) {
2515 LOG_ERROR("target not examined yet");
2519 return aarch64_init_debug_access(target
);
2521 COMMAND_HANDLER(aarch64_handle_smp_off_command
)
2523 struct target
*target
= get_current_target(CMD_CTX
);
2524 /* check target is an smp target */
2525 struct target_list
*head
;
2526 struct target
*curr
;
2527 head
= target
->head
;
2529 if (head
!= (struct target_list
*)NULL
) {
2530 while (head
!= (struct target_list
*)NULL
) {
2531 curr
= head
->target
;
2535 /* fixes the target display to the debugger */
2536 target
->gdb_service
->target
= target
;
2541 COMMAND_HANDLER(aarch64_handle_smp_on_command
)
2543 struct target
*target
= get_current_target(CMD_CTX
);
2544 struct target_list
*head
;
2545 struct target
*curr
;
2546 head
= target
->head
;
2547 if (head
!= (struct target_list
*)NULL
) {
2549 while (head
!= (struct target_list
*)NULL
) {
2550 curr
= head
->target
;
2558 COMMAND_HANDLER(aarch64_handle_smp_gdb_command
)
2560 struct target
*target
= get_current_target(CMD_CTX
);
2561 int retval
= ERROR_OK
;
2562 struct target_list
*head
;
2563 head
= target
->head
;
2564 if (head
!= (struct target_list
*)NULL
) {
2565 if (CMD_ARGC
== 1) {
2567 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], coreid
);
2568 if (ERROR_OK
!= retval
)
2570 target
->gdb_service
->core
[1] = coreid
;
2573 command_print(CMD_CTX
, "gdb coreid %" PRId32
" -> %" PRId32
, target
->gdb_service
->core
[0]
2574 , target
->gdb_service
->core
[1]);
2579 static const struct command_registration aarch64_exec_command_handlers
[] = {
2581 .name
= "cache_info",
2582 .handler
= aarch64_handle_cache_info_command
,
2583 .mode
= COMMAND_EXEC
,
2584 .help
= "display information about target caches",
2589 .handler
= aarch64_handle_dbginit_command
,
2590 .mode
= COMMAND_EXEC
,
2591 .help
= "Initialize core debug",
2594 { .name
= "smp_off",
2595 .handler
= aarch64_handle_smp_off_command
,
2596 .mode
= COMMAND_EXEC
,
2597 .help
= "Stop smp handling",
2602 .handler
= aarch64_handle_smp_on_command
,
2603 .mode
= COMMAND_EXEC
,
2604 .help
= "Restart smp handling",
2609 .handler
= aarch64_handle_smp_gdb_command
,
2610 .mode
= COMMAND_EXEC
,
2611 .help
= "display/fix current core played to gdb",
2616 COMMAND_REGISTRATION_DONE
2618 static const struct command_registration aarch64_command_handlers
[] = {
2620 .chain
= arm_command_handlers
,
2623 .chain
= armv8_command_handlers
,
2627 .mode
= COMMAND_ANY
,
2628 .help
= "Cortex-A command group",
2630 .chain
= aarch64_exec_command_handlers
,
2632 COMMAND_REGISTRATION_DONE
2635 struct target_type aarch64_target
= {
2638 .poll
= aarch64_poll
,
2639 .arch_state
= armv8_arch_state
,
2641 .halt
= aarch64_halt
,
2642 .resume
= aarch64_resume
,
2643 .step
= aarch64_step
,
2645 .assert_reset
= aarch64_assert_reset
,
2646 .deassert_reset
= aarch64_deassert_reset
,
2648 /* REVISIT allow exporting VFP3 registers ... */
2649 .get_gdb_reg_list
= armv8_get_gdb_reg_list
,
2651 .read_memory
= aarch64_read_memory
,
2652 .write_memory
= aarch64_write_memory
,
2654 .checksum_memory
= arm_checksum_memory
,
2655 .blank_check_memory
= arm_blank_check_memory
,
2657 .run_algorithm
= armv4_5_run_algorithm
,
2659 .add_breakpoint
= aarch64_add_breakpoint
,
2660 .add_context_breakpoint
= aarch64_add_context_breakpoint
,
2661 .add_hybrid_breakpoint
= aarch64_add_hybrid_breakpoint
,
2662 .remove_breakpoint
= aarch64_remove_breakpoint
,
2663 .add_watchpoint
= NULL
,
2664 .remove_watchpoint
= NULL
,
2666 .commands
= aarch64_command_handlers
,
2667 .target_create
= aarch64_target_create
,
2668 .init_target
= aarch64_init_target
,
2669 .examine
= aarch64_examine
,
2671 .read_phys_memory
= aarch64_read_phys_memory
,
2672 .write_phys_memory
= aarch64_write_phys_memory
,
2674 .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)