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 static const char * const armv8_state_strings
[] = {
41 "AArch32", "Thumb", "Jazelle", "ThumbEE", "AArch64",
47 } armv8_mode_data
[] = {
48 /* These special modes are currently only supported
49 * by ARMv6M and ARMv7M profiles */
100 .psr
= ARMV8_64_EL3H
,
104 /** Map PSR mode bits to the name of an ARM processor operating mode. */
105 const char *armv8_mode_name(unsigned psr_mode
)
107 for (unsigned i
= 0; i
< ARRAY_SIZE(armv8_mode_data
); i
++) {
108 if (armv8_mode_data
[i
].psr
== psr_mode
)
109 return armv8_mode_data
[i
].name
;
111 LOG_ERROR("unrecognized psr mode: %#02x", psr_mode
);
112 return "UNRECOGNIZED";
115 int armv8_mode_to_number(enum arm_mode mode
)
119 /* map MODE_ANY to user mode */
152 LOG_ERROR("invalid mode value encountered %d", mode
);
157 static int armv8_read_reg(struct armv8_common
*armv8
, int regnum
, uint64_t *regval
)
159 struct arm_dpm
*dpm
= &armv8
->dpm
;
166 retval
= dpm
->instr_read_data_dcc_64(dpm
,
167 ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0
, regnum
), &value_64
);
170 retval
= dpm
->instr_read_data_r0_64(dpm
,
171 ARMV8_MOVFSP_64(0), &value_64
);
174 retval
= dpm
->instr_read_data_r0_64(dpm
,
175 ARMV8_MRS_DLR(0), &value_64
);
178 retval
= dpm
->instr_read_data_r0(dpm
,
179 ARMV8_MRS_DSPSR(0), &value
);
183 retval
= dpm
->instr_read_data_r0_64(dpm
,
184 ARMV8_MRS(SYSTEM_ELR_EL1
, 0), &value_64
);
187 retval
= dpm
->instr_read_data_r0_64(dpm
,
188 ARMV8_MRS(SYSTEM_ELR_EL2
, 0), &value_64
);
191 retval
= dpm
->instr_read_data_r0_64(dpm
,
192 ARMV8_MRS(SYSTEM_ELR_EL3
, 0), &value_64
);
195 retval
= dpm
->instr_read_data_r0(dpm
,
196 ARMV8_MRS(SYSTEM_ESR_EL1
, 0), &value
);
200 retval
= dpm
->instr_read_data_r0(dpm
,
201 ARMV8_MRS(SYSTEM_ESR_EL2
, 0), &value
);
205 retval
= dpm
->instr_read_data_r0(dpm
,
206 ARMV8_MRS(SYSTEM_ESR_EL3
, 0), &value
);
210 retval
= dpm
->instr_read_data_r0(dpm
,
211 ARMV8_MRS(SYSTEM_SPSR_EL1
, 0), &value
);
215 retval
= dpm
->instr_read_data_r0(dpm
,
216 ARMV8_MRS(SYSTEM_SPSR_EL2
, 0), &value
);
220 retval
= dpm
->instr_read_data_r0(dpm
,
221 ARMV8_MRS(SYSTEM_SPSR_EL3
, 0), &value
);
229 if (retval
== ERROR_OK
&& regval
!= NULL
)
235 static int armv8_write_reg(struct armv8_common
*armv8
, int regnum
, uint64_t value_64
)
237 struct arm_dpm
*dpm
= &armv8
->dpm
;
243 retval
= dpm
->instr_write_data_dcc_64(dpm
,
244 ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0
, regnum
),
248 retval
= dpm
->instr_write_data_r0_64(dpm
,
253 retval
= dpm
->instr_write_data_r0_64(dpm
,
259 retval
= dpm
->instr_write_data_r0(dpm
,
263 /* registers clobbered by taking exception in debug state */
265 retval
= dpm
->instr_write_data_r0_64(dpm
,
266 ARMV8_MSR_GP(SYSTEM_ELR_EL1
, 0), value_64
);
269 retval
= dpm
->instr_write_data_r0_64(dpm
,
270 ARMV8_MSR_GP(SYSTEM_ELR_EL2
, 0), value_64
);
273 retval
= dpm
->instr_write_data_r0_64(dpm
,
274 ARMV8_MSR_GP(SYSTEM_ELR_EL3
, 0), value_64
);
278 retval
= dpm
->instr_write_data_r0(dpm
,
279 ARMV8_MSR_GP(SYSTEM_ESR_EL1
, 0), value
);
283 retval
= dpm
->instr_write_data_r0(dpm
,
284 ARMV8_MSR_GP(SYSTEM_ESR_EL2
, 0), value
);
288 retval
= dpm
->instr_write_data_r0(dpm
,
289 ARMV8_MSR_GP(SYSTEM_ESR_EL3
, 0), value
);
293 retval
= dpm
->instr_write_data_r0(dpm
,
294 ARMV8_MSR_GP(SYSTEM_SPSR_EL1
, 0), value
);
298 retval
= dpm
->instr_write_data_r0(dpm
,
299 ARMV8_MSR_GP(SYSTEM_SPSR_EL2
, 0), value
);
303 retval
= dpm
->instr_write_data_r0(dpm
,
304 ARMV8_MSR_GP(SYSTEM_SPSR_EL3
, 0), value
);
314 static int armv8_read_reg32(struct armv8_common
*armv8
, int regnum
, uint64_t *regval
)
316 struct arm_dpm
*dpm
= &armv8
->dpm
;
321 case ARMV8_R0
... ARMV8_R14
:
322 /* return via DCC: "MCR p14, 0, Rnum, c0, c5, 0" */
323 retval
= dpm
->instr_read_data_dcc(dpm
,
324 ARMV4_5_MCR(14, 0, regnum
, 0, 5, 0),
328 retval
= dpm
->instr_read_data_dcc(dpm
,
329 ARMV4_5_MCR(14, 0, 13, 0, 5, 0),
333 retval
= dpm
->instr_read_data_r0(dpm
,
338 retval
= dpm
->instr_read_data_r0(dpm
,
342 case ARMV8_ELR_EL1
: /* mapped to LR_svc */
343 retval
= dpm
->instr_read_data_dcc(dpm
,
344 ARMV4_5_MCR(14, 0, 14, 0, 5, 0),
347 case ARMV8_ELR_EL2
: /* mapped to ELR_hyp */
348 retval
= dpm
->instr_read_data_r0(dpm
,
349 ARMV8_MRS_T1(0, 14, 0, 1),
352 case ARMV8_ELR_EL3
: /* mapped to LR_mon */
353 retval
= dpm
->instr_read_data_dcc(dpm
,
354 ARMV4_5_MCR(14, 0, 14, 0, 5, 0),
357 case ARMV8_ESR_EL1
: /* mapped to DFSR */
358 retval
= dpm
->instr_read_data_r0(dpm
,
359 ARMV4_5_MRC(15, 0, 0, 5, 0, 0),
362 case ARMV8_ESR_EL2
: /* mapped to HSR */
363 retval
= dpm
->instr_read_data_r0(dpm
,
364 ARMV4_5_MRC(15, 4, 0, 5, 2, 0),
367 case ARMV8_ESR_EL3
: /* FIXME: no equivalent in aarch32? */
370 case ARMV8_SPSR_EL1
: /* mapped to SPSR_svc */
371 retval
= dpm
->instr_read_data_r0(dpm
,
372 ARMV8_MRS_xPSR_T1(1, 0),
375 case ARMV8_SPSR_EL2
: /* mapped to SPSR_hyp */
376 retval
= dpm
->instr_read_data_r0(dpm
,
377 ARMV8_MRS_xPSR_T1(1, 0),
380 case ARMV8_SPSR_EL3
: /* mapped to SPSR_mon */
381 retval
= dpm
->instr_read_data_r0(dpm
,
382 ARMV8_MRS_xPSR_T1(1, 0),
390 if (retval
== ERROR_OK
&& regval
!= NULL
)
396 static int armv8_write_reg32(struct armv8_common
*armv8
, int regnum
, uint64_t value
)
398 struct arm_dpm
*dpm
= &armv8
->dpm
;
402 case ARMV8_R0
... ARMV8_R14
:
403 /* load register from DCC: "MRC p14, 0, Rnum, c0, c5, 0" */
404 retval
= dpm
->instr_write_data_dcc(dpm
,
405 ARMV4_5_MRC(14, 0, regnum
, 0, 5, 0), value
);
408 retval
= dpm
->instr_write_data_dcc(dpm
,
409 ARMV4_5_MRC(14, 0, 13, 0, 5, 0), value
);
412 * read r0 from DCC; then "MOV pc, r0" */
413 retval
= dpm
->instr_write_data_r0(dpm
,
414 ARMV8_MCR_DLR(0), value
);
416 case ARMV8_xPSR
: /* CPSR */
417 /* read r0 from DCC, then "MCR r0, DSPSR" */
418 retval
= dpm
->instr_write_data_r0(dpm
,
419 ARMV8_MCR_DSPSR(0), value
);
421 case ARMV8_ELR_EL1
: /* mapped to LR_svc */
422 retval
= dpm
->instr_write_data_dcc(dpm
,
423 ARMV4_5_MRC(14, 0, 14, 0, 5, 0),
426 case ARMV8_ELR_EL2
: /* mapped to ELR_hyp */
427 retval
= dpm
->instr_write_data_r0(dpm
,
428 ARMV8_MSR_GP_T1(0, 14, 0, 1),
431 case ARMV8_ELR_EL3
: /* mapped to LR_mon */
432 retval
= dpm
->instr_write_data_dcc(dpm
,
433 ARMV4_5_MRC(14, 0, 14, 0, 5, 0),
436 case ARMV8_ESR_EL1
: /* mapped to DFSR */
437 retval
= dpm
->instr_write_data_r0(dpm
,
438 ARMV4_5_MCR(15, 0, 0, 5, 0, 0),
441 case ARMV8_ESR_EL2
: /* mapped to HSR */
442 retval
= dpm
->instr_write_data_r0(dpm
,
443 ARMV4_5_MCR(15, 4, 0, 5, 2, 0),
446 case ARMV8_ESR_EL3
: /* FIXME: no equivalent in aarch32? */
449 case ARMV8_SPSR_EL1
: /* mapped to SPSR_svc */
450 retval
= dpm
->instr_write_data_r0(dpm
,
451 ARMV8_MSR_GP_xPSR_T1(1, 0, 15),
454 case ARMV8_SPSR_EL2
: /* mapped to SPSR_hyp */
455 retval
= dpm
->instr_write_data_r0(dpm
,
456 ARMV8_MSR_GP_xPSR_T1(1, 0, 15),
459 case ARMV8_SPSR_EL3
: /* mapped to SPSR_mon */
460 retval
= dpm
->instr_write_data_r0(dpm
,
461 ARMV8_MSR_GP_xPSR_T1(1, 0, 15),
473 void armv8_select_reg_access(struct armv8_common
*armv8
, bool is_aarch64
)
476 armv8
->read_reg_u64
= armv8_read_reg
;
477 armv8
->write_reg_u64
= armv8_write_reg
;
479 armv8
->read_reg_u64
= armv8_read_reg32
;
480 armv8
->write_reg_u64
= armv8_write_reg32
;
484 /* retrieve core id cluster id */
485 int armv8_read_mpidr(struct armv8_common
*armv8
)
487 int retval
= ERROR_FAIL
;
488 struct arm_dpm
*dpm
= armv8
->arm
.dpm
;
491 retval
= dpm
->prepare(dpm
);
492 if (retval
!= ERROR_OK
)
495 retval
= dpm
->instr_read_data_r0(dpm
, armv8_opcode(armv8
, READ_REG_MPIDR
), &mpidr
);
496 if (retval
!= ERROR_OK
)
499 armv8
->multi_processor_system
= (mpidr
>> 30) & 1;
500 armv8
->cluster_id
= (mpidr
>> 8) & 0xf;
501 armv8
->cpu_id
= mpidr
& 0x3;
502 LOG_INFO("%s cluster %x core %x %s", target_name(armv8
->arm
.target
),
505 armv8
->multi_processor_system
== 0 ? "multi core" : "single core");
507 LOG_ERROR("mpidr not in multiprocessor format");
515 * Configures host-side ARM records to reflect the specified CPSR.
516 * Later, code can use arm_reg_current() to map register numbers
517 * according to how they are exposed by this mode.
519 void armv8_set_cpsr(struct arm
*arm
, uint32_t cpsr
)
521 uint32_t mode
= cpsr
& 0x1F;
523 /* NOTE: this may be called very early, before the register
524 * cache is set up. We can't defend against many errors, in
525 * particular against CPSRs that aren't valid *here* ...
528 buf_set_u32(arm
->cpsr
->value
, 0, 32, cpsr
);
529 arm
->cpsr
->valid
= 1;
530 arm
->cpsr
->dirty
= 0;
533 /* Older ARMs won't have the J bit */
534 enum arm_state state
= 0xFF;
536 if (((cpsr
& 0x10) >> 4) == 0) {
537 state
= ARM_STATE_AARCH64
;
539 if (cpsr
& (1 << 5)) { /* T */
540 if (cpsr
& (1 << 24)) { /* J */
541 LOG_WARNING("ThumbEE -- incomplete support");
542 state
= ARM_STATE_THUMB_EE
;
544 state
= ARM_STATE_THUMB
;
546 if (cpsr
& (1 << 24)) { /* J */
547 LOG_ERROR("Jazelle state handling is BROKEN!");
548 state
= ARM_STATE_JAZELLE
;
550 state
= ARM_STATE_ARM
;
553 arm
->core_state
= state
;
554 if (arm
->core_state
== ARM_STATE_AARCH64
)
555 arm
->core_mode
= (mode
<< 4) | 0xf;
557 arm
->core_mode
= mode
;
559 LOG_DEBUG("set CPSR %#8.8x: %s mode, %s state", (unsigned) cpsr
,
560 armv8_mode_name(arm
->core_mode
),
561 armv8_state_strings
[arm
->core_state
]);
564 static void armv8_show_fault_registers32(struct armv8_common
*armv8
)
566 uint32_t dfsr
, ifsr
, dfar
, ifar
;
567 struct arm_dpm
*dpm
= armv8
->arm
.dpm
;
570 retval
= dpm
->prepare(dpm
);
571 if (retval
!= ERROR_OK
)
574 /* ARMV4_5_MRC(cpnum, op1, r0, CRn, CRm, op2) */
576 /* c5/c0 - {data, instruction} fault status registers */
577 retval
= dpm
->instr_read_data_r0(dpm
,
578 ARMV4_5_MRC(15, 0, 0, 5, 0, 0),
580 if (retval
!= ERROR_OK
)
583 retval
= dpm
->instr_read_data_r0(dpm
,
584 ARMV4_5_MRC(15, 0, 0, 5, 0, 1),
586 if (retval
!= ERROR_OK
)
589 /* c6/c0 - {data, instruction} fault address registers */
590 retval
= dpm
->instr_read_data_r0(dpm
,
591 ARMV4_5_MRC(15, 0, 0, 6, 0, 0),
593 if (retval
!= ERROR_OK
)
596 retval
= dpm
->instr_read_data_r0(dpm
,
597 ARMV4_5_MRC(15, 0, 0, 6, 0, 2),
599 if (retval
!= ERROR_OK
)
602 LOG_USER("Data fault registers DFSR: %8.8" PRIx32
603 ", DFAR: %8.8" PRIx32
, dfsr
, dfar
);
604 LOG_USER("Instruction fault registers IFSR: %8.8" PRIx32
605 ", IFAR: %8.8" PRIx32
, ifsr
, ifar
);
608 /* (void) */ dpm
->finish(dpm
);
611 static __attribute__((unused
)) void armv8_show_fault_registers(struct target
*target
)
613 struct armv8_common
*armv8
= target_to_armv8(target
);
615 if (armv8
->arm
.core_state
!= ARM_STATE_AARCH64
)
616 armv8_show_fault_registers32(armv8
);
619 static uint8_t armv8_pa_size(uint32_t ps
)
642 LOG_INFO("Unknow physicall address size");
648 static __attribute__((unused
)) int armv8_read_ttbcr32(struct target
*target
)
650 struct armv8_common
*armv8
= target_to_armv8(target
);
651 struct arm_dpm
*dpm
= armv8
->arm
.dpm
;
652 uint32_t ttbcr
, ttbcr_n
;
653 int retval
= dpm
->prepare(dpm
);
654 if (retval
!= ERROR_OK
)
656 /* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
657 retval
= dpm
->instr_read_data_r0(dpm
,
658 ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
660 if (retval
!= ERROR_OK
)
663 LOG_DEBUG("ttbcr %" PRIx32
, ttbcr
);
665 ttbcr_n
= ttbcr
& 0x7;
666 armv8
->armv8_mmu
.ttbcr
= ttbcr
;
669 * ARM Architecture Reference Manual (ARMv7-A and ARMv7-Redition),
670 * document # ARM DDI 0406C
672 armv8
->armv8_mmu
.ttbr_range
[0] = 0xffffffff >> ttbcr_n
;
673 armv8
->armv8_mmu
.ttbr_range
[1] = 0xffffffff;
674 armv8
->armv8_mmu
.ttbr_mask
[0] = 0xffffffff << (14 - ttbcr_n
);
675 armv8
->armv8_mmu
.ttbr_mask
[1] = 0xffffffff << 14;
677 LOG_DEBUG("ttbr1 %s, ttbr0_mask %" PRIx32
" ttbr1_mask %" PRIx32
,
678 (ttbcr_n
!= 0) ? "used" : "not used",
679 armv8
->armv8_mmu
.ttbr_mask
[0],
680 armv8
->armv8_mmu
.ttbr_mask
[1]);
687 static __attribute__((unused
)) int armv8_read_ttbcr(struct target
*target
)
689 struct armv8_common
*armv8
= target_to_armv8(target
);
690 struct arm_dpm
*dpm
= armv8
->arm
.dpm
;
691 struct arm
*arm
= &armv8
->arm
;
695 int retval
= dpm
->prepare(dpm
);
696 if (retval
!= ERROR_OK
)
699 /* claaer ttrr1_used and ttbr0_mask */
700 memset(&armv8
->armv8_mmu
.ttbr1_used
, 0, sizeof(armv8
->armv8_mmu
.ttbr1_used
));
701 memset(&armv8
->armv8_mmu
.ttbr0_mask
, 0, sizeof(armv8
->armv8_mmu
.ttbr0_mask
));
703 switch (armv8_curel_from_core_mode(arm
->core_mode
)) {
704 case SYSTEM_CUREL_EL3
:
705 retval
= dpm
->instr_read_data_r0(dpm
,
706 ARMV8_MRS(SYSTEM_TCR_EL3
, 0),
708 retval
+= dpm
->instr_read_data_r0_64(dpm
,
709 ARMV8_MRS(SYSTEM_TTBR0_EL3
, 0),
711 if (retval
!= ERROR_OK
)
713 armv8
->va_size
= 64 - (ttbcr
& 0x3F);
714 armv8
->pa_size
= armv8_pa_size((ttbcr
>> 16) & 7);
715 armv8
->page_size
= (ttbcr
>> 14) & 3;
717 case SYSTEM_CUREL_EL2
:
718 retval
= dpm
->instr_read_data_r0(dpm
,
719 ARMV8_MRS(SYSTEM_TCR_EL2
, 0),
721 retval
+= dpm
->instr_read_data_r0_64(dpm
,
722 ARMV8_MRS(SYSTEM_TTBR0_EL2
, 0),
724 if (retval
!= ERROR_OK
)
726 armv8
->va_size
= 64 - (ttbcr
& 0x3F);
727 armv8
->pa_size
= armv8_pa_size((ttbcr
>> 16) & 7);
728 armv8
->page_size
= (ttbcr
>> 14) & 3;
730 case SYSTEM_CUREL_EL0
:
731 armv8_dpm_modeswitch(dpm
, ARMV8_64_EL1H
);
733 case SYSTEM_CUREL_EL1
:
734 retval
= dpm
->instr_read_data_r0_64(dpm
,
735 ARMV8_MRS(SYSTEM_TCR_EL1
, 0),
737 armv8
->va_size
= 64 - (ttbcr_64
& 0x3F);
738 armv8
->pa_size
= armv8_pa_size((ttbcr_64
>> 32) & 7);
739 armv8
->page_size
= (ttbcr_64
>> 14) & 3;
740 armv8
->armv8_mmu
.ttbr1_used
= (((ttbcr_64
>> 16) & 0x3F) != 0) ? 1 : 0;
741 armv8
->armv8_mmu
.ttbr0_mask
= 0x0000FFFFFFFFFFFF;
742 retval
+= dpm
->instr_read_data_r0_64(dpm
,
743 ARMV8_MRS(SYSTEM_TTBR0_EL1
| (armv8
->armv8_mmu
.ttbr1_used
), 0),
745 if (retval
!= ERROR_OK
)
749 LOG_ERROR("unknow core state");
753 if (retval
!= ERROR_OK
)
756 if (armv8
->armv8_mmu
.ttbr1_used
== 1)
757 LOG_INFO("TTBR0 access above %" PRIx64
, (uint64_t)(armv8
->armv8_mmu
.ttbr0_mask
));
760 armv8_dpm_modeswitch(dpm
, ARM_MODE_ANY
);
765 /* method adapted to cortex A : reused arm v4 v5 method*/
766 int armv8_mmu_translate_va(struct target
*target
, target_addr_t va
, target_addr_t
*val
)
771 /* V8 method VA TO PA */
772 int armv8_mmu_translate_va_pa(struct target
*target
, target_addr_t va
,
773 target_addr_t
*val
, int meminfo
)
775 struct armv8_common
*armv8
= target_to_armv8(target
);
776 struct arm
*arm
= target_to_arm(target
);
777 struct arm_dpm
*dpm
= &armv8
->dpm
;
778 enum arm_mode target_mode
= ARM_MODE_ANY
;
783 static const char * const shared_name
[] = {
784 "Non-", "UNDEFINED ", "Outer ", "Inner "
787 static const char * const secure_name
[] = {
788 "Secure", "Not Secure"
791 retval
= dpm
->prepare(dpm
);
792 if (retval
!= ERROR_OK
)
795 switch (armv8_curel_from_core_mode(arm
->core_mode
)) {
796 case SYSTEM_CUREL_EL0
:
797 instr
= ARMV8_SYS(SYSTEM_ATS12E0R
, 0);
798 /* can only execute instruction at EL2 */
799 target_mode
= ARMV8_64_EL2H
;
801 case SYSTEM_CUREL_EL1
:
802 instr
= ARMV8_SYS(SYSTEM_ATS12E1R
, 0);
803 /* can only execute instruction at EL2 */
804 target_mode
= ARMV8_64_EL2H
;
806 case SYSTEM_CUREL_EL2
:
807 instr
= ARMV8_SYS(SYSTEM_ATS1E2R
, 0);
809 case SYSTEM_CUREL_EL3
:
810 instr
= ARMV8_SYS(SYSTEM_ATS1E3R
, 0);
817 if (target_mode
!= ARM_MODE_ANY
)
818 armv8_dpm_modeswitch(dpm
, target_mode
);
820 /* write VA to R0 and execute translation instruction */
821 retval
= dpm
->instr_write_data_r0_64(dpm
, instr
, (uint64_t)va
);
822 /* read result from PAR_EL1 */
823 if (retval
== ERROR_OK
)
824 retval
= dpm
->instr_read_data_r0_64(dpm
, ARMV8_MRS(SYSTEM_PAR_EL1
, 0), &par
);
826 /* switch back to saved PE mode */
827 if (target_mode
!= ARM_MODE_ANY
)
828 armv8_dpm_modeswitch(dpm
, ARM_MODE_ANY
);
832 if (retval
!= ERROR_OK
)
836 LOG_ERROR("Address translation failed at stage %i, FST=%x, PTW=%i",
837 ((int)(par
>> 9) & 1)+1, (int)(par
>> 1) & 0x3f, (int)(par
>> 8) & 1);
842 *val
= (par
& 0xFFFFFFFFF000UL
) | (va
& 0xFFF);
844 int SH
= (par
>> 7) & 3;
845 int NS
= (par
>> 9) & 1;
846 int ATTR
= (par
>> 56) & 0xFF;
848 char *memtype
= (ATTR
& 0xF0) == 0 ? "Device Memory" : "Normal Memory";
850 LOG_USER("%sshareable, %s",
851 shared_name
[SH
], secure_name
[NS
]);
852 LOG_USER("%s", memtype
);
859 int armv8_handle_cache_info_command(struct command_context
*cmd_ctx
,
860 struct armv8_cache_common
*armv8_cache
)
862 if (armv8_cache
->info
== -1) {
863 command_print(cmd_ctx
, "cache not yet identified");
867 if (armv8_cache
->display_cache_info
)
868 armv8_cache
->display_cache_info(cmd_ctx
, armv8_cache
);
872 int armv8_init_arch_info(struct target
*target
, struct armv8_common
*armv8
)
874 struct arm
*arm
= &armv8
->arm
;
875 arm
->arch_info
= armv8
;
876 target
->arch_info
= &armv8
->arm
;
877 /* target is useful in all function arm v4 5 compatible */
878 armv8
->arm
.target
= target
;
879 armv8
->arm
.common_magic
= ARM_COMMON_MAGIC
;
880 armv8
->common_magic
= ARMV8_COMMON_MAGIC
;
882 armv8
->armv8_mmu
.armv8_cache
.l2_cache
= NULL
;
883 armv8
->armv8_mmu
.armv8_cache
.info
= -1;
884 armv8
->armv8_mmu
.armv8_cache
.flush_all_data_cache
= NULL
;
885 armv8
->armv8_mmu
.armv8_cache
.display_cache_info
= NULL
;
889 int armv8_aarch64_state(struct target
*target
)
891 struct arm
*arm
= target_to_arm(target
);
893 if (arm
->common_magic
!= ARM_COMMON_MAGIC
) {
894 LOG_ERROR("BUG: called for a non-ARM target");
898 LOG_USER("target halted in %s state due to %s, current mode: %s\n"
899 "cpsr: 0x%8.8" PRIx32
" pc: 0x%" PRIx64
"%s",
900 armv8_state_strings
[arm
->core_state
],
901 debug_reason_name(target
),
902 armv8_mode_name(arm
->core_mode
),
903 buf_get_u32(arm
->cpsr
->value
, 0, 32),
904 buf_get_u64(arm
->pc
->value
, 0, 64),
905 arm
->is_semihosting
? ", semihosting" : "");
910 int armv8_arch_state(struct target
*target
)
912 static const char * const state
[] = {
913 "disabled", "enabled"
916 struct armv8_common
*armv8
= target_to_armv8(target
);
917 struct arm
*arm
= &armv8
->arm
;
919 if (armv8
->common_magic
!= ARMV8_COMMON_MAGIC
) {
920 LOG_ERROR("BUG: called for a non-Armv8 target");
921 return ERROR_COMMAND_SYNTAX_ERROR
;
924 if (arm
->core_state
== ARM_STATE_AARCH64
)
925 armv8_aarch64_state(target
);
927 arm_arch_state(target
);
929 LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
930 state
[armv8
->armv8_mmu
.mmu_enabled
],
931 state
[armv8
->armv8_mmu
.armv8_cache
.d_u_cache_enabled
],
932 state
[armv8
->armv8_mmu
.armv8_cache
.i_cache_enabled
]);
934 if (arm
->core_mode
== ARM_MODE_ABT
)
935 armv8_show_fault_registers(target
);
937 if (target
->debug_reason
== DBG_REASON_WATCHPOINT
)
938 LOG_USER("Watchpoint triggered at PC %#08x",
939 (unsigned) armv8
->dpm
.wp_pc
);
944 static const struct {
953 { ARMV8_R0
, "x0", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
954 { ARMV8_R1
, "x1", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
955 { ARMV8_R2
, "x2", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
956 { ARMV8_R3
, "x3", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
957 { ARMV8_R4
, "x4", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
958 { ARMV8_R5
, "x5", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
959 { ARMV8_R6
, "x6", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
960 { ARMV8_R7
, "x7", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
961 { ARMV8_R8
, "x8", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
962 { ARMV8_R9
, "x9", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
963 { ARMV8_R10
, "x10", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
964 { ARMV8_R11
, "x11", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
965 { ARMV8_R12
, "x12", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
966 { ARMV8_R13
, "x13", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
967 { ARMV8_R14
, "x14", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
968 { ARMV8_R15
, "x15", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
969 { ARMV8_R16
, "x16", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
970 { ARMV8_R17
, "x17", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
971 { ARMV8_R18
, "x18", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
972 { ARMV8_R19
, "x19", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
973 { ARMV8_R20
, "x20", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
974 { ARMV8_R21
, "x21", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
975 { ARMV8_R22
, "x22", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
976 { ARMV8_R23
, "x23", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
977 { ARMV8_R24
, "x24", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
978 { ARMV8_R25
, "x25", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
979 { ARMV8_R26
, "x26", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
980 { ARMV8_R27
, "x27", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
981 { ARMV8_R28
, "x28", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
982 { ARMV8_R29
, "x29", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
983 { ARMV8_R30
, "x30", 64, ARM_MODE_ANY
, REG_TYPE_UINT64
, "general", "org.gnu.gdb.aarch64.core" },
985 { ARMV8_SP
, "sp", 64, ARM_MODE_ANY
, REG_TYPE_DATA_PTR
, "general", "org.gnu.gdb.aarch64.core" },
986 { ARMV8_PC
, "pc", 64, ARM_MODE_ANY
, REG_TYPE_CODE_PTR
, "general", "org.gnu.gdb.aarch64.core" },
988 { ARMV8_xPSR
, "CPSR", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.aarch64.core" },
990 { ARMV8_ELR_EL1
, "ELR_EL1", 64, ARMV8_64_EL1H
, REG_TYPE_CODE_PTR
, "banked", "net.sourceforge.openocd.banked" },
991 { ARMV8_ESR_EL1
, "ESR_EL1", 32, ARMV8_64_EL1H
, REG_TYPE_UINT32
, "banked", "net.sourceforge.openocd.banked" },
992 { ARMV8_SPSR_EL1
, "SPSR_EL1", 32, ARMV8_64_EL1H
, REG_TYPE_UINT32
, "banked", "net.sourceforge.openocd.banked" },
994 { ARMV8_ELR_EL2
, "ELR_EL2", 64, ARMV8_64_EL2H
, REG_TYPE_CODE_PTR
, "banked", "net.sourceforge.openocd.banked" },
995 { ARMV8_ESR_EL2
, "ESR_EL2", 32, ARMV8_64_EL2H
, REG_TYPE_UINT32
, "banked", "net.sourceforge.openocd.banked" },
996 { ARMV8_SPSR_EL2
, "SPSR_EL2", 32, ARMV8_64_EL2H
, REG_TYPE_UINT32
, "banked", "net.sourceforge.openocd.banked" },
998 { ARMV8_ELR_EL3
, "ELR_EL3", 64, ARMV8_64_EL3H
, REG_TYPE_CODE_PTR
, "banked", "net.sourceforge.openocd.banked" },
999 { ARMV8_ESR_EL3
, "ESR_EL3", 32, ARMV8_64_EL3H
, REG_TYPE_UINT32
, "banked", "net.sourceforge.openocd.banked" },
1000 { ARMV8_SPSR_EL3
, "SPSR_EL3", 32, ARMV8_64_EL3H
, REG_TYPE_UINT32
, "banked", "net.sourceforge.openocd.banked" },
1003 static const struct {
1010 const char *feature
;
1011 } armv8_regs32
[] = {
1012 { ARMV8_R0
, "r0", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1013 { ARMV8_R1
, "r1", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1014 { ARMV8_R2
, "r2", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1015 { ARMV8_R3
, "r3", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1016 { ARMV8_R4
, "r4", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1017 { ARMV8_R5
, "r5", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1018 { ARMV8_R6
, "r6", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1019 { ARMV8_R7
, "r7", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1020 { ARMV8_R8
, "r8", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1021 { ARMV8_R9
, "r9", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1022 { ARMV8_R10
, "r10", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1023 { ARMV8_R11
, "r11", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1024 { ARMV8_R12
, "r12", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1025 { ARMV8_R13
, "sp", 32, ARM_MODE_ANY
, REG_TYPE_DATA_PTR
, "general", "org.gnu.gdb.arm.core" },
1026 { ARMV8_R14
, "lr", 32, ARM_MODE_ANY
, REG_TYPE_CODE_PTR
, "general", "org.gnu.gdb.arm.core" },
1027 { ARMV8_PC
, "pc", 32, ARM_MODE_ANY
, REG_TYPE_CODE_PTR
, "general", "org.gnu.gdb.arm.core" },
1028 { ARMV8_xPSR
, "cpsr", 32, ARM_MODE_ANY
, REG_TYPE_UINT32
, "general", "org.gnu.gdb.arm.core" },
1031 #define ARMV8_NUM_REGS ARRAY_SIZE(armv8_regs)
1032 #define ARMV8_NUM_REGS32 ARRAY_SIZE(armv8_regs32)
1034 static int armv8_get_core_reg(struct reg
*reg
)
1036 struct arm_reg
*armv8_reg
= reg
->arch_info
;
1037 struct target
*target
= armv8_reg
->target
;
1038 struct arm
*arm
= target_to_arm(target
);
1040 if (target
->state
!= TARGET_HALTED
)
1041 return ERROR_TARGET_NOT_HALTED
;
1043 return arm
->read_core_reg(target
, reg
, armv8_reg
->num
, arm
->core_mode
);
1046 static int armv8_set_core_reg(struct reg
*reg
, uint8_t *buf
)
1048 struct arm_reg
*armv8_reg
= reg
->arch_info
;
1049 struct target
*target
= armv8_reg
->target
;
1050 struct arm
*arm
= target_to_arm(target
);
1051 uint64_t value
= buf_get_u64(buf
, 0, 64);
1053 if (target
->state
!= TARGET_HALTED
)
1054 return ERROR_TARGET_NOT_HALTED
;
1056 if (reg
== arm
->cpsr
) {
1057 armv8_set_cpsr(arm
, (uint32_t)value
);
1059 buf_set_u64(reg
->value
, 0, 64, value
);
1068 static const struct reg_arch_type armv8_reg_type
= {
1069 .get
= armv8_get_core_reg
,
1070 .set
= armv8_set_core_reg
,
1073 static int armv8_get_core_reg32(struct reg
*reg
)
1075 struct arm_reg
*armv8_reg
= reg
->arch_info
;
1076 struct target
*target
= armv8_reg
->target
;
1077 struct arm
*arm
= target_to_arm(target
);
1078 struct reg_cache
*cache
= arm
->core_cache
;
1082 /* get the corresponding Aarch64 register */
1083 reg64
= cache
->reg_list
+ armv8_reg
->num
;
1089 retval
= arm
->read_core_reg(target
, reg64
, armv8_reg
->num
, arm
->core_mode
);
1090 if (retval
== ERROR_OK
)
1091 reg
->valid
= reg64
->valid
;
1096 static int armv8_set_core_reg32(struct reg
*reg
, uint8_t *buf
)
1098 struct arm_reg
*armv8_reg
= reg
->arch_info
;
1099 struct target
*target
= armv8_reg
->target
;
1100 struct arm
*arm
= target_to_arm(target
);
1101 struct reg_cache
*cache
= arm
->core_cache
;
1102 struct reg
*reg64
= cache
->reg_list
+ armv8_reg
->num
;
1103 uint32_t value
= buf_get_u32(buf
, 0, 32);
1105 if (reg64
== arm
->cpsr
) {
1106 armv8_set_cpsr(arm
, value
);
1108 buf_set_u32(reg
->value
, 0, 32, value
);
1118 static const struct reg_arch_type armv8_reg32_type
= {
1119 .get
= armv8_get_core_reg32
,
1120 .set
= armv8_set_core_reg32
,
1123 /** Builds cache of architecturally defined registers. */
1124 struct reg_cache
*armv8_build_reg_cache(struct target
*target
)
1126 struct armv8_common
*armv8
= target_to_armv8(target
);
1127 struct arm
*arm
= &armv8
->arm
;
1128 int num_regs
= ARMV8_NUM_REGS
;
1129 int num_regs32
= ARMV8_NUM_REGS32
;
1130 struct reg_cache
**cache_p
= register_get_last_cache_p(&target
->reg_cache
);
1131 struct reg_cache
*cache
= malloc(sizeof(struct reg_cache
));
1132 struct reg_cache
*cache32
= malloc(sizeof(struct reg_cache
));
1133 struct reg
*reg_list
= calloc(num_regs
, sizeof(struct reg
));
1134 struct reg
*reg_list32
= calloc(num_regs32
, sizeof(struct reg
));
1135 struct arm_reg
*arch_info
= calloc(num_regs
, sizeof(struct arm_reg
));
1136 struct reg_feature
*feature
;
1139 /* Build the process context cache */
1140 cache
->name
= "Aarch64 registers";
1141 cache
->next
= cache32
;
1142 cache
->reg_list
= reg_list
;
1143 cache
->num_regs
= num_regs
;
1145 for (i
= 0; i
< num_regs
; i
++) {
1146 arch_info
[i
].num
= armv8_regs
[i
].id
;
1147 arch_info
[i
].mode
= armv8_regs
[i
].mode
;
1148 arch_info
[i
].target
= target
;
1149 arch_info
[i
].arm
= arm
;
1151 reg_list
[i
].name
= armv8_regs
[i
].name
;
1152 reg_list
[i
].size
= armv8_regs
[i
].bits
;
1153 reg_list
[i
].value
= &arch_info
[i
].value
[0];
1154 reg_list
[i
].type
= &armv8_reg_type
;
1155 reg_list
[i
].arch_info
= &arch_info
[i
];
1157 reg_list
[i
].group
= armv8_regs
[i
].group
;
1158 reg_list
[i
].number
= i
;
1159 reg_list
[i
].exist
= true;
1160 reg_list
[i
].caller_save
= true; /* gdb defaults to true */
1162 feature
= calloc(1, sizeof(struct reg_feature
));
1164 feature
->name
= armv8_regs
[i
].feature
;
1165 reg_list
[i
].feature
= feature
;
1167 LOG_ERROR("unable to allocate feature list");
1169 reg_list
[i
].reg_data_type
= calloc(1, sizeof(struct reg_data_type
));
1170 if (reg_list
[i
].reg_data_type
)
1171 reg_list
[i
].reg_data_type
->type
= armv8_regs
[i
].type
;
1173 LOG_ERROR("unable to allocate reg type list");
1176 arm
->cpsr
= reg_list
+ ARMV8_xPSR
;
1177 arm
->pc
= reg_list
+ ARMV8_PC
;
1178 arm
->core_cache
= cache
;
1180 /* shadow cache for ARM mode registers */
1181 cache32
->name
= "Aarch32 registers";
1182 cache32
->next
= NULL
;
1183 cache32
->reg_list
= reg_list32
;
1184 cache32
->num_regs
= num_regs32
;
1186 for (i
= 0; i
< num_regs32
; i
++) {
1187 reg_list32
[i
].name
= armv8_regs32
[i
].name
;
1188 reg_list32
[i
].size
= armv8_regs32
[i
].bits
;
1189 reg_list32
[i
].value
= &arch_info
[armv8_regs32
[i
].id
].value
[0];
1190 reg_list32
[i
].type
= &armv8_reg32_type
;
1191 reg_list32
[i
].arch_info
= &arch_info
[armv8_regs32
[i
].id
];
1192 reg_list32
[i
].group
= armv8_regs32
[i
].group
;
1193 reg_list32
[i
].number
= i
;
1194 reg_list32
[i
].exist
= true;
1195 reg_list32
[i
].caller_save
= true;
1197 feature
= calloc(1, sizeof(struct reg_feature
));
1199 feature
->name
= armv8_regs32
[i
].feature
;
1200 reg_list32
[i
].feature
= feature
;
1202 LOG_ERROR("unable to allocate feature list");
1204 reg_list32
[i
].reg_data_type
= calloc(1, sizeof(struct reg_data_type
));
1205 if (reg_list32
[i
].reg_data_type
)
1206 reg_list32
[i
].reg_data_type
->type
= armv8_regs32
[i
].type
;
1208 LOG_ERROR("unable to allocate reg type list");
1215 struct reg
*armv8_reg_current(struct arm
*arm
, unsigned regnum
)
1219 if (regnum
> (ARMV8_LAST_REG
- 1))
1222 r
= arm
->core_cache
->reg_list
+ regnum
;
1226 const struct command_registration armv8_command_handlers
[] = {
1228 .chain
= dap_command_handlers
,
1230 COMMAND_REGISTRATION_DONE
1234 int armv8_get_gdb_reg_list(struct target
*target
,
1235 struct reg
**reg_list
[], int *reg_list_size
,
1236 enum target_register_class reg_class
)
1238 struct arm
*arm
= target_to_arm(target
);
1241 if (arm
->core_state
== ARM_STATE_AARCH64
) {
1243 LOG_DEBUG("Creating Aarch64 register list for target %s", target_name(target
));
1245 switch (reg_class
) {
1246 case REG_CLASS_GENERAL
:
1247 *reg_list_size
= ARMV8_ELR_EL1
;
1248 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
1250 for (i
= 0; i
< *reg_list_size
; i
++)
1251 (*reg_list
)[i
] = armv8_reg_current(arm
, i
);
1255 *reg_list_size
= ARMV8_LAST_REG
;
1256 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
1258 for (i
= 0; i
< *reg_list_size
; i
++)
1259 (*reg_list
)[i
] = armv8_reg_current(arm
, i
);
1264 LOG_ERROR("not a valid register class type in query.");
1268 struct reg_cache
*cache32
= arm
->core_cache
->next
;
1270 LOG_DEBUG("Creating Aarch32 register list for target %s", target_name(target
));
1272 switch (reg_class
) {
1273 case REG_CLASS_GENERAL
:
1275 *reg_list_size
= cache32
->num_regs
;
1276 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
1278 for (i
= 0; i
< *reg_list_size
; i
++)
1279 (*reg_list
)[i
] = cache32
->reg_list
+ i
;
1283 LOG_ERROR("not a valid register class type in query.");
1289 int armv8_set_dbgreg_bits(struct armv8_common
*armv8
, unsigned int reg
, unsigned long mask
, unsigned long value
)
1294 int retval
= mem_ap_read_atomic_u32(armv8
->debug_ap
,
1295 armv8
->debug_base
+ reg
, &tmp
);
1296 if (ERROR_OK
!= retval
)
1299 /* clear bitfield */
1302 tmp
|= value
& mask
;
1304 /* write new value */
1305 retval
= mem_ap_write_atomic_u32(armv8
->debug_ap
,
1306 armv8
->debug_base
+ reg
, tmp
);
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)