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., *
17 ***************************************************************************/
23 #include <helper/replacements.h>
26 #include "arm_disassembler.h"
29 #include <helper/binarybuffer.h>
30 #include <helper/command.h>
36 #include "armv8_opcodes.h"
38 #include "target_type.h"
40 #define __unused __attribute__((unused))
42 static const char * const armv8_state_strings
[] = {
43 "AArch32", "Thumb", "Jazelle", "ThumbEE", "AArch64",
49 } armv8_mode_data
[] = {
50 /* These special modes are currently only supported
51 * by ARMv6M and ARMv7M profiles */
102 .psr
= ARMV8_64_EL3H
,
106 /** Map PSR mode bits to the name of an ARM processor operating mode. */
107 const char *armv8_mode_name(unsigned psr_mode
)
109 for (unsigned i
= 0; i
< ARRAY_SIZE(armv8_mode_data
); i
++) {
110 if (armv8_mode_data
[i
].psr
== psr_mode
)
111 return armv8_mode_data
[i
].name
;
113 LOG_ERROR("unrecognized psr mode: %#02x", psr_mode
);
114 return "UNRECOGNIZED";
117 int armv8_mode_to_number(enum arm_mode mode
)
121 /* map MODE_ANY to user mode */
154 LOG_ERROR("invalid mode value encountered %d", mode
);
159 static int armv8_read_reg(struct armv8_common
*armv8
, int regnum
, uint64_t *regval
)
161 struct arm_dpm
*dpm
= &armv8
->dpm
;
168 retval
= dpm
->instr_read_data_dcc_64(dpm
,
169 ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0
, regnum
), &value_64
);
172 retval
= dpm
->instr_read_data_r0_64(dpm
,
173 ARMV8_MOVFSP_64(0), &value_64
);
176 retval
= dpm
->instr_read_data_r0_64(dpm
,
177 ARMV8_MRS_DLR(0), &value_64
);
180 retval
= dpm
->instr_read_data_r0(dpm
,
181 ARMV8_MRS_DSPSR(0), &value
);
185 retval
= dpm
->instr_read_data_r0_64(dpm
,
186 ARMV8_MRS(SYSTEM_ELR_EL1
, 0), &value_64
);
189 retval
= dpm
->instr_read_data_r0_64(dpm
,
190 ARMV8_MRS(SYSTEM_ELR_EL2
, 0), &value_64
);
193 retval
= dpm
->instr_read_data_r0_64(dpm
,
194 ARMV8_MRS(SYSTEM_ELR_EL3
, 0), &value_64
);
197 retval
= dpm
->instr_read_data_r0(dpm
,
198 ARMV8_MRS(SYSTEM_ESR_EL1
, 0), &value
);
202 retval
= dpm
->instr_read_data_r0(dpm
,
203 ARMV8_MRS(SYSTEM_ESR_EL2
, 0), &value
);
207 retval
= dpm
->instr_read_data_r0(dpm
,
208 ARMV8_MRS(SYSTEM_ESR_EL3
, 0), &value
);
212 retval
= dpm
->instr_read_data_r0(dpm
,
213 ARMV8_MRS(SYSTEM_SPSR_EL1
, 0), &value
);
217 retval
= dpm
->instr_read_data_r0(dpm
,
218 ARMV8_MRS(SYSTEM_SPSR_EL2
, 0), &value
);
222 retval
= dpm
->instr_read_data_r0(dpm
,
223 ARMV8_MRS(SYSTEM_SPSR_EL3
, 0), &value
);
231 if (retval
== ERROR_OK
&& regval
!= NULL
)
237 static int armv8_write_reg(struct armv8_common
*armv8
, int regnum
, uint64_t value_64
)
239 struct arm_dpm
*dpm
= &armv8
->dpm
;
245 retval
= dpm
->instr_write_data_dcc_64(dpm
,
246 ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0
, regnum
),
250 retval
= dpm
->instr_write_data_r0_64(dpm
,
255 retval
= dpm
->instr_write_data_r0_64(dpm
,
261 retval
= dpm
->instr_write_data_r0(dpm
,
265 /* registers clobbered by taking exception in debug state */
267 retval
= dpm
->instr_write_data_r0_64(dpm
,
268 ARMV8_MSR_GP(SYSTEM_ELR_EL1
, 0), value_64
);
271 retval
= dpm
->instr_write_data_r0_64(dpm
,
272 ARMV8_MSR_GP(SYSTEM_ELR_EL2
, 0), value_64
);
275 retval
= dpm
->instr_write_data_r0_64(dpm
,
276 ARMV8_MSR_GP(SYSTEM_ELR_EL3
, 0), value_64
);
280 retval
= dpm
->instr_write_data_r0(dpm
,
281 ARMV8_MSR_GP(SYSTEM_ESR_EL1
, 0), value
);
285 retval
= dpm
->instr_write_data_r0(dpm
,
286 ARMV8_MSR_GP(SYSTEM_ESR_EL2
, 0), value
);
290 retval
= dpm
->instr_write_data_r0(dpm
,
291 ARMV8_MSR_GP(SYSTEM_ESR_EL3
, 0), value
);
295 retval
= dpm
->instr_write_data_r0(dpm
,
296 ARMV8_MSR_GP(SYSTEM_SPSR_EL1
, 0), value
);
300 retval
= dpm
->instr_write_data_r0(dpm
,
301 ARMV8_MSR_GP(SYSTEM_SPSR_EL2
, 0), value
);
305 retval
= dpm
->instr_write_data_r0(dpm
,
306 ARMV8_MSR_GP(SYSTEM_SPSR_EL3
, 0), value
);
316 static int armv8_read_reg32(struct armv8_common
*armv8
, int regnum
, uint64_t *regval
)
318 struct arm_dpm
*dpm
= &armv8
->dpm
;
323 case ARMV8_R0
... ARMV8_R14
:
324 /* return via DCC: "MCR p14, 0, Rnum, c0, c5, 0" */
325 retval
= dpm
->instr_read_data_dcc(dpm
,
326 ARMV4_5_MCR(14, 0, regnum
, 0, 5, 0),
330 retval
= dpm
->instr_read_data_dcc(dpm
,
331 ARMV4_5_MCR(14, 0, 13, 0, 5, 0),
335 retval
= dpm
->instr_read_data_r0(dpm
,
340 retval
= dpm
->instr_read_data_r0(dpm
,
344 case ARMV8_ELR_EL1
: /* mapped to LR_svc */
345 retval
= dpm
->instr_read_data_dcc(dpm
,
346 ARMV4_5_MCR(14, 0, 14, 0, 5, 0),
349 case ARMV8_ELR_EL2
: /* mapped to ELR_hyp */
350 retval
= dpm
->instr_read_data_r0(dpm
,
351 ARMV8_MRS_T1(0, 14, 0, 1),
354 case ARMV8_ELR_EL3
: /* mapped to LR_mon */
355 retval
= dpm
->instr_read_data_dcc(dpm
,
356 ARMV4_5_MCR(14, 0, 14, 0, 5, 0),
359 case ARMV8_ESR_EL1
: /* mapped to DFSR */
360 retval
= dpm
->instr_read_data_r0(dpm
,
361 ARMV4_5_MRC(15, 0, 0, 5, 0, 0),
364 case ARMV8_ESR_EL2
: /* mapped to HSR */
365 retval
= dpm
->instr_read_data_r0(dpm
,
366 ARMV4_5_MRC(15, 4, 0, 5, 2, 0),
369 case ARMV8_ESR_EL3
: /* FIXME: no equivalent in aarch32? */
372 case ARMV8_SPSR_EL1
: /* mapped to SPSR_svc */
373 retval
= dpm
->instr_read_data_r0(dpm
,
374 ARMV8_MRS_xPSR_T1(1, 0),
377 case ARMV8_SPSR_EL2
: /* mapped to SPSR_hyp */
378 retval
= dpm
->instr_read_data_r0(dpm
,
379 ARMV8_MRS_xPSR_T1(1, 0),
382 case ARMV8_SPSR_EL3
: /* mapped to SPSR_mon */
383 retval
= dpm
->instr_read_data_r0(dpm
,
384 ARMV8_MRS_xPSR_T1(1, 0),
392 if (retval
== ERROR_OK
&& regval
!= NULL
)
398 static int armv8_write_reg32(struct armv8_common
*armv8
, int regnum
, uint64_t value
)
400 struct arm_dpm
*dpm
= &armv8
->dpm
;
404 case ARMV8_R0
... ARMV8_R14
:
405 /* load register from DCC: "MRC p14, 0, Rnum, c0, c5, 0" */
406 retval
= dpm
->instr_write_data_dcc(dpm
,
407 ARMV4_5_MRC(14, 0, regnum
, 0, 5, 0), value
);
410 retval
= dpm
->instr_write_data_dcc(dpm
,
411 ARMV4_5_MRC(14, 0, 13, 0, 5, 0),
415 * read r0 from DCC; then "MOV pc, r0" */
416 retval
= dpm
->instr_write_data_r0(dpm
,
417 ARMV8_MCR_DLR(0), value
);
419 case ARMV8_xPSR
: /* CPSR */
420 /* read r0 from DCC, then "MCR r0, DSPSR" */
421 retval
= dpm
->instr_write_data_r0(dpm
,
422 ARMV8_MCR_DSPSR(0), value
);
424 case ARMV8_ELR_EL1
: /* mapped to LR_svc */
425 retval
= dpm
->instr_write_data_dcc(dpm
,
426 ARMV4_5_MRC(14, 0, 14, 0, 5, 0),
429 case ARMV8_ELR_EL2
: /* mapped to ELR_hyp */
430 retval
= dpm
->instr_write_data_r0(dpm
,
431 ARMV8_MSR_GP_T1(0, 14, 0, 1),
434 case ARMV8_ELR_EL3
: /* mapped to LR_mon */
435 retval
= dpm
->instr_write_data_dcc(dpm
,
436 ARMV4_5_MRC(14, 0, 14, 0, 5, 0),
439 case ARMV8_ESR_EL1
: /* mapped to DFSR */
440 retval
= dpm
->instr_write_data_r0(dpm
,
441 ARMV4_5_MCR(15, 0, 0, 5, 0, 0),
444 case ARMV8_ESR_EL2
: /* mapped to HSR */
445 retval
= dpm
->instr_write_data_r0(dpm
,
446 ARMV4_5_MCR(15, 4, 0, 5, 2, 0),
449 case ARMV8_ESR_EL3
: /* FIXME: no equivalent in aarch32? */
452 case ARMV8_SPSR_EL1
: /* mapped to SPSR_svc */
453 retval
= dpm
->instr_write_data_r0(dpm
,
454 ARMV8_MSR_GP_xPSR_T1(1, 0, 15),
457 case ARMV8_SPSR_EL2
: /* mapped to SPSR_hyp */
458 retval
= dpm
->instr_write_data_r0(dpm
,
459 ARMV8_MSR_GP_xPSR_T1(1, 0, 15),
462 case ARMV8_SPSR_EL3
: /* mapped to SPSR_mon */
463 retval
= dpm
->instr_write_data_r0(dpm
,
464 ARMV8_MSR_GP_xPSR_T1(1, 0, 15),
476 void armv8_select_reg_access(struct armv8_common
*armv8
, bool is_aarch64
)
479 armv8
->read_reg_u64
= armv8_read_reg
;
480 armv8
->write_reg_u64
= armv8_write_reg
;
482 armv8
->read_reg_u64
= armv8_read_reg32
;
483 armv8
->write_reg_u64
= armv8_write_reg32
;
487 /* retrieve core id cluster id */
488 int armv8_read_mpidr(struct armv8_common
*armv8
)
490 int retval
= ERROR_FAIL
;
491 struct arm_dpm
*dpm
= armv8
->arm
.dpm
;
494 retval
= dpm
->prepare(dpm
);
495 if (retval
!= ERROR_OK
)
498 retval
= dpm
->instr_read_data_r0(dpm
, armv8_opcode(armv8
, READ_REG_MPIDR
), &mpidr
);
499 if (retval
!= ERROR_OK
)
502 armv8
->multi_processor_system
= (mpidr
>> 30) & 1;
503 armv8
->cluster_id
= (mpidr
>> 8) & 0xf;
504 armv8
->cpu_id
= mpidr
& 0x3;
505 LOG_INFO("%s cluster %x core %x %s", target_name(armv8
->arm
.target
),
508 armv8
->multi_processor_system
== 0 ? "multi core" : "mono core");
511 LOG_ERROR("mpdir not in multiprocessor format");
519 * Configures host-side ARM records to reflect the specified CPSR.
520 * Later, code can use arm_reg_current() to map register numbers
521 * according to how they are exposed by this mode.
523 void armv8_set_cpsr(struct arm
*arm
, uint32_t cpsr
)
525 uint32_t mode
= cpsr
& 0x1F;
527 /* NOTE: this may be called very early, before the register
528 * cache is set up. We can't defend against many errors, in
529 * particular against CPSRs that aren't valid *here* ...
532 buf_set_u32(arm
->cpsr
->value
, 0, 32, cpsr
);
533 arm
->cpsr
->valid
= 1;
534 arm
->cpsr
->dirty
= 0;
537 /* Older ARMs won't have the J bit */
538 enum arm_state state
= 0xFF;
540 if (((cpsr
& 0x10) >> 4) == 0) {
541 state
= ARM_STATE_AARCH64
;
543 if (cpsr
& (1 << 5)) { /* T */
544 if (cpsr
& (1 << 24)) { /* J */
545 LOG_WARNING("ThumbEE -- incomplete support");
546 state
= ARM_STATE_THUMB_EE
;
548 state
= ARM_STATE_THUMB
;
550 if (cpsr
& (1 << 24)) { /* J */
551 LOG_ERROR("Jazelle state handling is BROKEN!");
552 state
= ARM_STATE_JAZELLE
;
554 state
= ARM_STATE_ARM
;
557 arm
->core_state
= state
;
558 if (arm
->core_state
== ARM_STATE_AARCH64
)
559 arm
->core_mode
= (mode
<< 4) | 0xf;
561 arm
->core_mode
= mode
;
563 LOG_DEBUG("set CPSR %#8.8x: %s mode, %s state", (unsigned) cpsr
,
564 armv8_mode_name(arm
->core_mode
),
565 armv8_state_strings
[arm
->core_state
]);
568 static void armv8_show_fault_registers32(struct armv8_common
*armv8
)
570 uint32_t dfsr
, ifsr
, dfar
, ifar
;
571 struct arm_dpm
*dpm
= armv8
->arm
.dpm
;
574 retval
= dpm
->prepare(dpm
);
575 if (retval
!= ERROR_OK
)
578 /* ARMV4_5_MRC(cpnum, op1, r0, CRn, CRm, op2) */
580 /* c5/c0 - {data, instruction} fault status registers */
581 retval
= dpm
->instr_read_data_r0(dpm
,
582 ARMV4_5_MRC(15, 0, 0, 5, 0, 0),
584 if (retval
!= ERROR_OK
)
587 retval
= dpm
->instr_read_data_r0(dpm
,
588 ARMV4_5_MRC(15, 0, 0, 5, 0, 1),
590 if (retval
!= ERROR_OK
)
593 /* c6/c0 - {data, instruction} fault address registers */
594 retval
= dpm
->instr_read_data_r0(dpm
,
595 ARMV4_5_MRC(15, 0, 0, 6, 0, 0),
597 if (retval
!= ERROR_OK
)
600 retval
= dpm
->instr_read_data_r0(dpm
,
601 ARMV4_5_MRC(15, 0, 0, 6, 0, 2),
603 if (retval
!= ERROR_OK
)
606 LOG_USER("Data fault registers DFSR: %8.8" PRIx32
607 ", DFAR: %8.8" PRIx32
, dfsr
, dfar
);
608 LOG_USER("Instruction fault registers IFSR: %8.8" PRIx32
609 ", IFAR: %8.8" PRIx32
, ifsr
, ifar
);
612 /* (void) */ dpm
->finish(dpm
);
615 static void armv8_show_fault_registers(struct target
*target
)
617 struct armv8_common
*armv8
= target_to_armv8(target
);
619 if (armv8
->arm
.core_state
!= ARM_STATE_AARCH64
)
620 armv8_show_fault_registers32(armv8
);
623 static uint8_t armv8_pa_size(uint32_t ps
)
646 LOG_INFO("Unknow physicall address size");
652 static __unused
int armv8_read_ttbcr32(struct target
*target
)
654 struct armv8_common
*armv8
= target_to_armv8(target
);
655 struct arm_dpm
*dpm
= armv8
->arm
.dpm
;
656 uint32_t ttbcr
, ttbcr_n
;
657 int retval
= dpm
->prepare(dpm
);
658 if (retval
!= ERROR_OK
)
660 /* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
661 retval
= dpm
->instr_read_data_r0(dpm
,
662 ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
664 if (retval
!= ERROR_OK
)
667 LOG_DEBUG("ttbcr %" PRIx32
, ttbcr
);
669 ttbcr_n
= ttbcr
& 0x7;
670 armv8
->armv8_mmu
.ttbcr
= ttbcr
;
673 * ARM Architecture Reference Manual (ARMv7-A and ARMv7-Redition),
674 * document # ARM DDI 0406C
676 armv8
->armv8_mmu
.ttbr_range
[0] = 0xffffffff >> ttbcr_n
;
677 armv8
->armv8_mmu
.ttbr_range
[1] = 0xffffffff;
678 armv8
->armv8_mmu
.ttbr_mask
[0] = 0xffffffff << (14 - ttbcr_n
);
679 armv8
->armv8_mmu
.ttbr_mask
[1] = 0xffffffff << 14;
681 LOG_DEBUG("ttbr1 %s, ttbr0_mask %" PRIx32
" ttbr1_mask %" PRIx32
,
682 (ttbcr_n
!= 0) ? "used" : "not used",
683 armv8
->armv8_mmu
.ttbr_mask
[0],
684 armv8
->armv8_mmu
.ttbr_mask
[1]);
691 static __unused
int armv8_read_ttbcr(struct target
*target
)
693 struct armv8_common
*armv8
= target_to_armv8(target
);
694 struct arm_dpm
*dpm
= armv8
->arm
.dpm
;
695 struct arm
*arm
= &armv8
->arm
;
699 int retval
= dpm
->prepare(dpm
);
700 if (retval
!= ERROR_OK
)
703 /* claaer ttrr1_used and ttbr0_mask */
704 memset(&armv8
->armv8_mmu
.ttbr1_used
, 0, sizeof(armv8
->armv8_mmu
.ttbr1_used
));
705 memset(&armv8
->armv8_mmu
.ttbr0_mask
, 0, sizeof(armv8
->armv8_mmu
.ttbr0_mask
));
707 switch (armv8_curel_from_core_mode(arm
->core_mode
)) {
708 case SYSTEM_CUREL_EL3
:
709 retval
= dpm
->instr_read_data_r0(dpm
,
710 ARMV8_MRS(SYSTEM_TCR_EL3
, 0),
712 retval
+= dpm
->instr_read_data_r0_64(dpm
,
713 ARMV8_MRS(SYSTEM_TTBR0_EL3
, 0),
715 if (retval
!= ERROR_OK
)
717 armv8
->va_size
= 64 - (ttbcr
& 0x3F);
718 armv8
->pa_size
= armv8_pa_size((ttbcr
>> 16) & 7);
719 armv8
->page_size
= (ttbcr
>> 14) & 3;
721 case SYSTEM_CUREL_EL2
:
722 retval
= dpm
->instr_read_data_r0(dpm
,
723 ARMV8_MRS(SYSTEM_TCR_EL2
, 0),
725 retval
+= dpm
->instr_read_data_r0_64(dpm
,
726 ARMV8_MRS(SYSTEM_TTBR0_EL2
, 0),
728 if (retval
!= ERROR_OK
)
730 armv8
->va_size
= 64 - (ttbcr
& 0x3F);
731 armv8
->pa_size
= armv8_pa_size((ttbcr
>> 16) & 7);
732 armv8
->page_size
= (ttbcr
>> 14) & 3;
734 case SYSTEM_CUREL_EL0
:
735 armv8_dpm_modeswitch(dpm
, ARMV8_64_EL1H
);
737 case SYSTEM_CUREL_EL1
:
738 retval
= dpm
->instr_read_data_r0_64(dpm
,
739 ARMV8_MRS(SYSTEM_TCR_EL1
, 0),
741 armv8
->va_size
= 64 - (ttbcr_64
& 0x3F);
742 armv8
->pa_size
= armv8_pa_size((ttbcr_64
>> 32) & 7);
743 armv8
->page_size
= (ttbcr_64
>> 14) & 3;
744 armv8
->armv8_mmu
.ttbr1_used
= (((ttbcr_64
>> 16) & 0x3F) != 0) ? 1 : 0;
745 armv8
->armv8_mmu
.ttbr0_mask
= 0x0000FFFFFFFFFFFF;
746 retval
+= dpm
->instr_read_data_r0_64(dpm
,
747 ARMV8_MRS(SYSTEM_TTBR0_EL1
| (armv8
->armv8_mmu
.ttbr1_used
), 0),
749 if (retval
!= ERROR_OK
)
753 LOG_ERROR("unknow core state");
757 if (retval
!= ERROR_OK
)
760 if (armv8
->armv8_mmu
.ttbr1_used
== 1)
761 LOG_INFO("TTBR0 access above %" PRIx64
, (uint64_t)(armv8
->armv8_mmu
.ttbr0_mask
));
764 armv8_dpm_modeswitch(dpm
, ARM_MODE_ANY
);
769 /* method adapted to cortex A : reused arm v4 v5 method*/
770 int armv8_mmu_translate_va(struct target
*target
, target_addr_t va
, target_addr_t
*val
)
775 /* V8 method VA TO PA */
776 int armv8_mmu_translate_va_pa(struct target
*target
, target_addr_t va
,
777 target_addr_t
*val
, int meminfo
)
779 struct armv8_common
*armv8
= target_to_armv8(target
);
780 struct arm
*arm
= target_to_arm(target
);
781 struct arm_dpm
*dpm
= &armv8
->dpm
;
782 enum arm_mode target_mode
= ARM_MODE_ANY
;
787 static const char * const shared_name
[] = {
788 "Non-", "UNDEFINED ", "Outer ", "Inner "
791 static const char * const secure_name
[] = {
792 "Secure", "Not Secure"
795 retval
= dpm
->prepare(dpm
);
796 if (retval
!= ERROR_OK
)
799 switch (armv8_curel_from_core_mode(arm
->core_mode
)) {
800 case SYSTEM_CUREL_EL0
:
801 instr
= ARMV8_SYS(SYSTEM_ATS12E0R
, 0);
802 /* can only execute instruction at EL2 */
803 target_mode
= ARMV8_64_EL2H
;
805 case SYSTEM_CUREL_EL1
:
806 instr
= ARMV8_SYS(SYSTEM_ATS12E1R
, 0);
807 /* can only execute instruction at EL2 */
808 target_mode
= ARMV8_64_EL2H
;
810 case SYSTEM_CUREL_EL2
:
811 instr
= ARMV8_SYS(SYSTEM_ATS1E2R
, 0);
813 case SYSTEM_CUREL_EL3
:
814 instr
= ARMV8_SYS(SYSTEM_ATS1E3R
, 0);
821 if (target_mode
!= ARM_MODE_ANY
)
822 armv8_dpm_modeswitch(dpm
, target_mode
);
824 /* write VA to R0 and execute translation instruction */
825 retval
= dpm
->instr_write_data_r0_64(dpm
, instr
, (uint64_t)va
);
826 /* read result from PAR_EL1 */
827 if (retval
== ERROR_OK
)
828 retval
= dpm
->instr_read_data_r0_64(dpm
, ARMV8_MRS(SYSTEM_PAR_EL1
, 0), &par
);
830 /* switch back to saved PE mode */
831 if (target_mode
!= ARM_MODE_ANY
)
832 armv8_dpm_modeswitch(dpm
, ARM_MODE_ANY
);
836 if (retval
!= ERROR_OK
)
839 if (retval
!= ERROR_OK
)
843 LOG_ERROR("Address translation failed at stage %i, FST=%x, PTW=%i",
844 ((int)(par
>> 9) & 1)+1, (int)(par
>> 1) & 0x3f, (int)(par
>> 8) & 1);
849 *val
= (par
& 0xFFFFFFFFF000UL
) | (va
& 0xFFF);
851 int SH
= (par
>> 7) & 3;
852 int NS
= (par
>> 9) & 1;
853 int ATTR
= (par
>> 56) & 0xFF;
855 char *memtype
= (ATTR
& 0xF0) == 0 ? "Device Memory" : "Normal Memory";
857 LOG_USER("%sshareable, %s",
858 shared_name
[SH
], secure_name
[NS
]);
859 LOG_USER("%s", memtype
);
866 int armv8_handle_cache_info_command(struct command_context
*cmd_ctx
,
867 struct armv8_cache_common
*armv8_cache
)
869 if (armv8_cache
->info
== -1) {
870 command_print(cmd_ctx
, "cache not yet identified");
874 if (armv8_cache
->display_cache_info
)
875 armv8_cache
->display_cache_info(cmd_ctx
, armv8_cache
);
879 int armv8_init_arch_info(struct target
*target
, struct armv8_common
*armv8
)
881 struct arm
*arm
= &armv8
->arm
;
882 arm
->arch_info
= armv8
;
883 target
->arch_info
= &armv8
->arm
;
884 /* target is useful in all function arm v4 5 compatible */
885 armv8
->arm
.target
= target
;
886 armv8
->arm
.common_magic
= ARM_COMMON_MAGIC
;
887 armv8
->common_magic
= ARMV8_COMMON_MAGIC
;
889 armv8
->armv8_mmu
.armv8_cache
.l2_cache
= NULL
;
890 armv8
->armv8_mmu
.armv8_cache
.info
= -1;
891 armv8
->armv8_mmu
.armv8_cache
.flush_all_data_cache
= NULL
;
892 armv8
->armv8_mmu
.armv8_cache
.display_cache_info
= NULL
;
896 int armv8_aarch64_state(struct target
*target
)
898 struct arm
*arm
= target_to_arm(target
);
900 if (arm
->common_magic
!= ARM_COMMON_MAGIC
) {
901 LOG_ERROR("BUG: called for a non-ARM target");
905 LOG_USER("target halted in %s state due to %s, current mode: %s\n"
906 "cpsr: 0x%8.8" PRIx32
" pc: 0x%" PRIx64
"%s",
907 armv8_state_strings
[arm
->core_state
],
908 debug_reason_name(target
),
909 armv8_mode_name(arm
->core_mode
),
910 buf_get_u32(arm
->cpsr
->value
, 0, 32),
911 buf_get_u64(arm
->pc
->value
, 0, 64),
912 arm
->is_semihosting
? ", semihosting" : "");
917 int armv8_arch_state(struct target
*target
)
919 static const char * const state
[] = {
920 "disabled", "enabled"
923 struct armv8_common
*armv8
= target_to_armv8(target
);
924 struct arm
*arm
= &armv8
->arm
;
926 if (armv8
->common_magic
!= ARMV8_COMMON_MAGIC
) {
927 LOG_ERROR("BUG: called for a non-Armv8 target");
928 return ERROR_COMMAND_SYNTAX_ERROR
;
931 if (arm
->core_state
== ARM_STATE_AARCH64
)
932 armv8_aarch64_state(target
);
934 arm_arch_state(target
);
936 LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
937 state
[armv8
->armv8_mmu
.mmu_enabled
],
938 state
[armv8
->armv8_mmu
.armv8_cache
.d_u_cache_enabled
],
939 state
[armv8
->armv8_mmu
.armv8_cache
.i_cache_enabled
]);
941 if (arm
->core_mode
== ARM_MODE_ABT
)
942 armv8_show_fault_registers(target
);
944 if (target
->debug_reason
== DBG_REASON_WATCHPOINT
)
945 LOG_USER("Watchpoint triggered at PC %#08x",
946 (unsigned) armv8
->dpm
.wp_pc
);
951 static const struct {
960 { ARMV8_R0
, "x0", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
961 { ARMV8_R1
, "x1", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
962 { ARMV8_R2
, "x2", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
963 { ARMV8_R3
, "x3", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
964 { ARMV8_R4
, "x4", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
965 { ARMV8_R5
, "x5", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
966 { ARMV8_R6
, "x6", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
967 { ARMV8_R7
, "x7", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
968 { ARMV8_R8
, "x8", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
969 { ARMV8_R9
, "x9", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
970 { ARMV8_R10
, "x10", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
971 { ARMV8_R11
, "x11", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
972 { ARMV8_R12
, "x12", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
973 { ARMV8_R13
, "x13", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
974 { ARMV8_R14
, "x14", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
975 { ARMV8_R15
, "x15", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
976 { ARMV8_R16
, "x16", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
977 { ARMV8_R17
, "x17", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
978 { ARMV8_R18
, "x18", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
979 { ARMV8_R19
, "x19", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
980 { ARMV8_R20
, "x20", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
981 { ARMV8_R21
, "x21", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
982 { ARMV8_R22
, "x22", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
983 { ARMV8_R23
, "x23", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
984 { ARMV8_R24
, "x24", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
985 { ARMV8_R25
, "x25", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
986 { ARMV8_R26
, "x26", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
987 { ARMV8_R27
, "x27", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
988 { ARMV8_R28
, "x28", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
989 { ARMV8_R29
, "x29", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
990 { ARMV8_R30
, "x30", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
992 { ARMV8_SP
, "sp", 64, ARM_MODE_ANY
, REG_TYPE_DATA_PTR
, "general", "org.gnu.gdb.aarch64.core" },
993 { ARMV8_PC
, "pc", 64, ARM_MODE_ANY
, REG_TYPE_CODE_PTR
, "general", "org.gnu.gdb.aarch64.core" },
995 { ARMV8_xPSR
, "CPSR", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.aarch64.core" },
997 { ARMV8_ELR_EL1
, "ELR_EL1", 64, ARMV8_64_EL1H
, REG_TYPE_CODE_PTR
, "banked", "net.sourceforge.openocd.banked" },
998 { ARMV8_ESR_EL1
, "ESR_EL1", 32, ARMV8_64_EL1H
, REG_TYPE_UINT32
, "banked", "net.sourceforge.openocd.banked" },
999 { ARMV8_SPSR_EL1
, "SPSR_EL1", 32, ARMV8_64_EL1H
, REG_TYPE_UINT32
, "banked", "net.sourceforge.openocd.banked" },
1001 { ARMV8_ELR_EL2
, "ELR_EL2", 64, ARMV8_64_EL2H
, REG_TYPE_CODE_PTR
, "banked", "net.sourceforge.openocd.banked" },
1002 { ARMV8_ESR_EL2
, "ESR_EL2", 32, ARMV8_64_EL2H
, REG_TYPE_UINT32
, "banked", "net.sourceforge.openocd.banked" },
1003 { ARMV8_SPSR_EL2
, "SPSR_EL2", 32, ARMV8_64_EL2H
, REG_TYPE_UINT32
, "banked", "net.sourceforge.openocd.banked" },
1005 { ARMV8_ELR_EL3
, "ELR_EL3", 64, ARMV8_64_EL3H
, REG_TYPE_CODE_PTR
, "banked", "net.sourceforge.openocd.banked" },
1006 { ARMV8_ESR_EL3
, "ESR_EL3", 32, ARMV8_64_EL3H
, REG_TYPE_UINT32
, "banked", "net.sourceforge.openocd.banked" },
1007 { ARMV8_SPSR_EL3
, "SPSR_EL3", 32, ARMV8_64_EL3H
, REG_TYPE_UINT32
, "banked", "net.sourceforge.openocd.banked" },
1010 static const struct {
1017 const char *feature
;
1018 } armv8_regs32
[] = {
1019 { ARMV8_R0
, "r0", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1020 { ARMV8_R1
, "r1", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1021 { ARMV8_R2
, "r2", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1022 { ARMV8_R3
, "r3", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1023 { ARMV8_R4
, "r4", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1024 { ARMV8_R5
, "r5", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1025 { ARMV8_R6
, "r6", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1026 { ARMV8_R7
, "r7", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1027 { ARMV8_R8
, "r8", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1028 { ARMV8_R9
, "r9", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1029 { ARMV8_R10
, "r10", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1030 { ARMV8_R11
, "r11", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1031 { ARMV8_R12
, "r12", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1032 { ARMV8_R13
, "sp", 32, ARM_MODE_ANY
, REG_TYPE_DATA_PTR
, "general", "org.gnu.gdb.arm.core" },
1033 { ARMV8_R14
, "lr", 32, ARM_MODE_ANY
, REG_TYPE_CODE_PTR
, "general", "org.gnu.gdb.arm.core" },
1034 { ARMV8_PC
, "pc", 32, ARM_MODE_ANY
, REG_TYPE_CODE_PTR
, "general", "org.gnu.gdb.arm.core" },
1035 { ARMV8_xPSR
, "cpsr", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1038 #define ARMV8_NUM_REGS ARRAY_SIZE(armv8_regs)
1039 #define ARMV8_NUM_REGS32 ARRAY_SIZE(armv8_regs32)
1041 static int armv8_get_core_reg(struct reg
*reg
)
1043 struct arm_reg
*armv8_reg
= reg
->arch_info
;
1044 struct target
*target
= armv8_reg
->target
;
1045 struct arm
*arm
= target_to_arm(target
);
1047 if (target
->state
!= TARGET_HALTED
)
1048 return ERROR_TARGET_NOT_HALTED
;
1050 return arm
->read_core_reg(target
, reg
, armv8_reg
->num
, arm
->core_mode
);
1053 static int armv8_set_core_reg(struct reg
*reg
, uint8_t *buf
)
1055 struct arm_reg
*armv8_reg
= reg
->arch_info
;
1056 struct target
*target
= armv8_reg
->target
;
1057 struct arm
*arm
= target_to_arm(target
);
1058 uint64_t value
= buf_get_u64(buf
, 0, 64);
1060 if (target
->state
!= TARGET_HALTED
)
1061 return ERROR_TARGET_NOT_HALTED
;
1063 if (reg
== arm
->cpsr
) {
1064 armv8_set_cpsr(arm
, (uint32_t)value
);
1066 buf_set_u64(reg
->value
, 0, 64, value
);
1075 static const struct reg_arch_type armv8_reg_type
= {
1076 .get
= armv8_get_core_reg
,
1077 .set
= armv8_set_core_reg
,
1080 static int armv8_get_core_reg32(struct reg
*reg
)
1082 struct arm_reg
*armv8_reg
= reg
->arch_info
;
1083 struct target
*target
= armv8_reg
->target
;
1084 struct arm
*arm
= target_to_arm(target
);
1085 struct reg_cache
*cache
= arm
->core_cache
;
1089 /* get the corresponding Aarch64 register */
1090 reg64
= cache
->reg_list
+ armv8_reg
->num
;
1096 retval
= arm
->read_core_reg(target
, reg
, armv8_reg
->num
, arm
->core_mode
);
1097 if (retval
== ERROR_OK
)
1098 reg
->valid
= reg64
->valid
;
1103 static int armv8_set_core_reg32(struct reg
*reg
, uint8_t *buf
)
1105 struct arm_reg
*armv8_reg
= reg
->arch_info
;
1106 struct target
*target
= armv8_reg
->target
;
1107 struct arm
*arm
= target_to_arm(target
);
1108 struct reg_cache
*cache
= arm
->core_cache
;
1109 struct reg
*reg64
= cache
->reg_list
+ armv8_reg
->num
;
1110 uint32_t value
= buf_get_u32(buf
, 0, 32);
1112 if (target
->state
!= TARGET_HALTED
)
1113 return ERROR_TARGET_NOT_HALTED
;
1115 if (reg64
== arm
->cpsr
) {
1116 armv8_set_cpsr(arm
, value
);
1118 buf_set_u32(reg
->value
, 0, 32, value
);
1128 static const struct reg_arch_type armv8_reg32_type
= {
1129 .get
= armv8_get_core_reg32
,
1130 .set
= armv8_set_core_reg32
,
1133 /** Builds cache of architecturally defined registers. */
1134 struct reg_cache
*armv8_build_reg_cache(struct target
*target
)
1136 struct armv8_common
*armv8
= target_to_armv8(target
);
1137 struct arm
*arm
= &armv8
->arm
;
1138 int num_regs
= ARMV8_NUM_REGS
;
1139 int num_regs32
= ARMV8_NUM_REGS32
;
1140 struct reg_cache
**cache_p
= register_get_last_cache_p(&target
->reg_cache
);
1141 struct reg_cache
*cache
= malloc(sizeof(struct reg_cache
));
1142 struct reg_cache
*cache32
= malloc(sizeof(struct reg_cache
));
1143 struct reg
*reg_list
= calloc(num_regs
, sizeof(struct reg
));
1144 struct reg
*reg_list32
= calloc(num_regs32
, sizeof(struct reg
));
1145 struct arm_reg
*arch_info
= calloc(num_regs
, sizeof(struct arm_reg
));
1146 struct reg_feature
*feature
;
1149 /* Build the process context cache */
1150 cache
->name
= "Aarch64 registers";
1151 cache
->next
= cache32
;
1152 cache
->reg_list
= reg_list
;
1153 cache
->num_regs
= num_regs
;
1155 for (i
= 0; i
< num_regs
; i
++) {
1156 arch_info
[i
].num
= armv8_regs
[i
].id
;
1157 arch_info
[i
].mode
= armv8_regs
[i
].mode
;
1158 arch_info
[i
].target
= target
;
1159 arch_info
[i
].arm
= arm
;
1161 reg_list
[i
].name
= armv8_regs
[i
].name
;
1162 reg_list
[i
].size
= armv8_regs
[i
].bits
;
1163 reg_list
[i
].value
= &arch_info
[i
].value
[0];
1164 reg_list
[i
].type
= &armv8_reg_type
;
1165 reg_list
[i
].arch_info
= &arch_info
[i
];
1167 reg_list
[i
].group
= armv8_regs
[i
].group
;
1168 reg_list
[i
].number
= i
;
1169 reg_list
[i
].exist
= true;
1170 reg_list
[i
].caller_save
= true; /* gdb defaults to true */
1172 feature
= calloc(1, sizeof(struct reg_feature
));
1174 feature
->name
= armv8_regs
[i
].feature
;
1175 reg_list
[i
].feature
= feature
;
1177 LOG_ERROR("unable to allocate feature list");
1179 reg_list
[i
].reg_data_type
= calloc(1, sizeof(struct reg_data_type
));
1180 if (reg_list
[i
].reg_data_type
)
1181 reg_list
[i
].reg_data_type
->type
= armv8_regs
[i
].type
;
1183 LOG_ERROR("unable to allocate reg type list");
1186 arm
->cpsr
= reg_list
+ ARMV8_xPSR
;
1187 arm
->pc
= reg_list
+ ARMV8_PC
;
1188 arm
->core_cache
= cache
;
1190 /* shadow cache for ARM mode registers */
1191 cache32
->name
= "Aarch32 registers";
1192 cache32
->next
= NULL
;
1193 cache32
->reg_list
= reg_list32
;
1194 cache32
->num_regs
= num_regs32
;
1196 for (i
= 0; i
< num_regs32
; i
++) {
1197 reg_list32
[i
].name
= armv8_regs32
[i
].name
;
1198 reg_list32
[i
].size
= armv8_regs32
[i
].bits
;
1199 reg_list32
[i
].value
= &arch_info
[armv8_regs32
[i
].id
].value
[0];
1200 reg_list32
[i
].type
= &armv8_reg32_type
;
1201 reg_list32
[i
].arch_info
= &arch_info
[armv8_regs32
[i
].id
];
1202 reg_list32
[i
].group
= armv8_regs32
[i
].group
;
1203 reg_list32
[i
].number
= i
;
1204 reg_list32
[i
].exist
= true;
1205 reg_list32
[i
].caller_save
= true;
1207 feature
= calloc(1, sizeof(struct reg_feature
));
1209 feature
->name
= armv8_regs32
[i
].feature
;
1210 reg_list32
[i
].feature
= feature
;
1212 LOG_ERROR("unable to allocate feature list");
1214 reg_list32
[i
].reg_data_type
= calloc(1, sizeof(struct reg_data_type
));
1215 if (reg_list32
[i
].reg_data_type
)
1216 reg_list32
[i
].reg_data_type
->type
= armv8_regs32
[i
].type
;
1218 LOG_ERROR("unable to allocate reg type list");
1225 struct reg
*armv8_reg_current(struct arm
*arm
, unsigned regnum
)
1229 if (regnum
> (ARMV8_LAST_REG
- 1))
1232 r
= arm
->core_cache
->reg_list
+ regnum
;
1236 const struct command_registration armv8_command_handlers
[] = {
1238 .chain
= dap_command_handlers
,
1240 COMMAND_REGISTRATION_DONE
1244 int armv8_get_gdb_reg_list(struct target
*target
,
1245 struct reg
**reg_list
[], int *reg_list_size
,
1246 enum target_register_class reg_class
)
1248 struct arm
*arm
= target_to_arm(target
);
1251 if (arm
->core_state
== ARM_STATE_AARCH64
) {
1253 LOG_DEBUG("Creating Aarch64 register list");
1255 switch (reg_class
) {
1256 case REG_CLASS_GENERAL
:
1257 *reg_list_size
= ARMV8_ELR_EL1
;
1258 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
1260 for (i
= 0; i
< *reg_list_size
; i
++)
1261 (*reg_list
)[i
] = armv8_reg_current(arm
, i
);
1265 *reg_list_size
= ARMV8_LAST_REG
;
1266 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
1268 for (i
= 0; i
< *reg_list_size
; i
++)
1269 (*reg_list
)[i
] = armv8_reg_current(arm
, i
);
1274 LOG_ERROR("not a valid register class type in query.");
1278 struct reg_cache
*cache32
= arm
->core_cache
->next
;
1280 LOG_DEBUG("Creating Aarch32 register list");
1282 switch (reg_class
) {
1283 case REG_CLASS_GENERAL
:
1285 *reg_list_size
= cache32
->num_regs
;
1286 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
1288 for (i
= 0; i
< *reg_list_size
; i
++)
1289 (*reg_list
)[i
] = cache32
->reg_list
+ i
;
1293 LOG_ERROR("not a valid register class type in query.");
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)