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"
37 #include "arm_opcodes.h"
39 #include "target_type.h"
41 static const char * const armv8_state_strings
[] = {
42 "ARM", "Thumb", "Jazelle", "ThumbEE", "ARM64",
48 /* For user and system modes, these list indices for all registers.
49 * otherwise they're just indices for the shadow registers and SPSR.
51 unsigned short n_indices
;
52 const uint8_t *indices
;
53 } armv8_mode_data
[] = {
54 /* These special modes are currently only supported
55 * by ARMv6M and ARMv7M profiles */
86 /** Map PSR mode bits to the name of an ARM processor operating mode. */
87 const char *armv8_mode_name(unsigned psr_mode
)
89 for (unsigned i
= 0; i
< ARRAY_SIZE(armv8_mode_data
); i
++) {
90 if (armv8_mode_data
[i
].psr
== psr_mode
)
91 return armv8_mode_data
[i
].name
;
93 LOG_ERROR("unrecognized psr mode: %#02x", psr_mode
);
94 return "UNRECOGNIZED";
97 int armv8_mode_to_number(enum arm_mode mode
)
101 /* map MODE_ANY to user mode */
134 LOG_ERROR("invalid mode value encountered %d", mode
);
140 static int armv8_read_core_reg(struct target
*target
, struct reg
*r
,
141 int num
, enum arm_mode mode
)
145 struct arm_reg
*armv8_core_reg
;
146 struct armv8_common
*armv8
= target_to_armv8(target
);
148 assert(num
< (int)armv8
->arm
.core_cache
->num_regs
);
150 armv8_core_reg
= armv8
->arm
.core_cache
->reg_list
[num
].arch_info
;
151 retval
= armv8
->load_core_reg_u64(target
,
152 armv8_core_reg
->num
, ®_value
);
154 buf_set_u64(armv8
->arm
.core_cache
->reg_list
[num
].value
, 0, 64, reg_value
);
155 armv8
->arm
.core_cache
->reg_list
[num
].valid
= 1;
156 armv8
->arm
.core_cache
->reg_list
[num
].dirty
= 0;
162 static int armv8_write_core_reg(struct target
*target
, struct reg
*r
,
163 int num
, enum arm_mode mode
, target_addr_t value
)
166 struct arm_reg
*armv8_core_reg
;
167 struct armv8_common
*armv8
= target_to_armv8(target
);
169 assert(num
< (int)armv8
->arm
.core_cache
->num_regs
);
171 armv8_core_reg
= armv8
->arm
.core_cache
->reg_list
[num
].arch_info
;
172 retval
= armv8
->store_core_reg_u64(target
,
175 if (retval
!= ERROR_OK
) {
176 LOG_ERROR("JTAG failure");
177 armv8
->arm
.core_cache
->reg_list
[num
].dirty
= armv8
->arm
.core_cache
->reg_list
[num
].valid
;
178 return ERROR_JTAG_DEVICE_ERROR
;
181 LOG_DEBUG("write core reg %i value 0x%" PRIx64
"", num
, value
);
182 armv8
->arm
.core_cache
->reg_list
[num
].valid
= 1;
183 armv8
->arm
.core_cache
->reg_list
[num
].dirty
= 0;
189 * Configures host-side ARM records to reflect the specified CPSR.
190 * Later, code can use arm_reg_current() to map register numbers
191 * according to how they are exposed by this mode.
193 void armv8_set_cpsr(struct arm
*arm
, uint32_t cpsr
)
195 uint32_t mode
= cpsr
& 0x1F;
197 /* NOTE: this may be called very early, before the register
198 * cache is set up. We can't defend against many errors, in
199 * particular against CPSRs that aren't valid *here* ...
202 buf_set_u32(arm
->cpsr
->value
, 0, 32, cpsr
);
203 arm
->cpsr
->valid
= 1;
204 arm
->cpsr
->dirty
= 0;
207 /* Older ARMs won't have the J bit */
208 enum arm_state state
= 0xFF;
210 if (((cpsr
& 0x10) >> 4) == 0) {
211 state
= ARM_STATE_AARCH64
;
213 if (cpsr
& (1 << 5)) { /* T */
214 if (cpsr
& (1 << 24)) { /* J */
215 LOG_WARNING("ThumbEE -- incomplete support");
216 state
= ARM_STATE_THUMB_EE
;
218 state
= ARM_STATE_THUMB
;
220 if (cpsr
& (1 << 24)) { /* J */
221 LOG_ERROR("Jazelle state handling is BROKEN!");
222 state
= ARM_STATE_JAZELLE
;
224 state
= ARM_STATE_ARM
;
227 arm
->core_state
= state
;
228 if (arm
->core_state
== ARM_STATE_AARCH64
) {
230 case SYSTEM_AAR64_MODE_EL0t
:
231 arm
->core_mode
= ARMV8_64_EL0T
;
233 case SYSTEM_AAR64_MODE_EL1t
:
234 arm
->core_mode
= ARMV8_64_EL0T
;
236 case SYSTEM_AAR64_MODE_EL1h
:
237 arm
->core_mode
= ARMV8_64_EL1H
;
239 case SYSTEM_AAR64_MODE_EL2t
:
240 arm
->core_mode
= ARMV8_64_EL2T
;
242 case SYSTEM_AAR64_MODE_EL2h
:
243 arm
->core_mode
= ARMV8_64_EL2H
;
245 case SYSTEM_AAR64_MODE_EL3t
:
246 arm
->core_mode
= ARMV8_64_EL3T
;
248 case SYSTEM_AAR64_MODE_EL3h
:
249 arm
->core_mode
= ARMV8_64_EL3H
;
252 LOG_DEBUG("unknow mode 0x%x", (unsigned) (mode
));
256 arm
->core_mode
= mode
;
259 LOG_DEBUG("set CPSR %#8.8x: %s mode, %s state", (unsigned) cpsr
,
260 armv8_mode_name(arm
->core_mode
),
261 armv8_state_strings
[arm
->core_state
]);
264 static void armv8_show_fault_registers(struct target
*target
)
269 static uint8_t armv8_pa_size(uint32_t ps
)
292 LOG_INFO("Unknow physicall address size");
298 static int armv8_read_ttbcr(struct target
*target
)
300 struct armv8_common
*armv8
= target_to_armv8(target
);
301 struct arm_dpm
*dpm
= armv8
->arm
.dpm
;
302 struct arm
*arm
= &armv8
->arm
;
306 int retval
= dpm
->prepare(dpm
);
307 if (retval
!= ERROR_OK
)
310 /* claaer ttrr1_used and ttbr0_mask */
311 memset(&armv8
->armv8_mmu
.ttbr1_used
, 0, sizeof(armv8
->armv8_mmu
.ttbr1_used
));
312 memset(&armv8
->armv8_mmu
.ttbr0_mask
, 0, sizeof(armv8
->armv8_mmu
.ttbr0_mask
));
314 switch (arm
->core_mode
) {
317 retval
= dpm
->instr_read_data_r0(dpm
,
318 ARMV8_MRS(SYSTEM_TCR_EL3
, 0),
320 retval
+= dpm
->instr_read_data_r0_64(dpm
,
321 ARMV8_MRS(SYSTEM_TTBR0_EL3
, 0),
323 if (retval
!= ERROR_OK
)
325 armv8
->va_size
= 64 - (ttbcr
& 0x3F);
326 armv8
->pa_size
= armv8_pa_size((ttbcr
>> 16) & 7);
327 armv8
->page_size
= (ttbcr
>> 14) & 3;
331 retval
= dpm
->instr_read_data_r0(dpm
,
332 ARMV8_MRS(SYSTEM_TCR_EL2
, 0),
334 retval
+= dpm
->instr_read_data_r0_64(dpm
,
335 ARMV8_MRS(SYSTEM_TTBR0_EL2
, 0),
337 if (retval
!= ERROR_OK
)
339 armv8
->va_size
= 64 - (ttbcr
& 0x3F);
340 armv8
->pa_size
= armv8_pa_size((ttbcr
>> 16) & 7);
341 armv8
->page_size
= (ttbcr
>> 14) & 3;
346 retval
= dpm
->instr_read_data_r0_64(dpm
,
347 ARMV8_MRS(SYSTEM_TCR_EL1
, 0),
349 armv8
->va_size
= 64 - (ttbcr_64
& 0x3F);
350 armv8
->pa_size
= armv8_pa_size((ttbcr_64
>> 32) & 7);
351 armv8
->page_size
= (ttbcr_64
>> 14) & 3;
352 armv8
->armv8_mmu
.ttbr1_used
= (((ttbcr_64
>> 16) & 0x3F) != 0) ? 1 : 0;
353 armv8
->armv8_mmu
.ttbr0_mask
= 0x0000FFFFFFFFFFFF;
354 retval
+= dpm
->instr_read_data_r0_64(dpm
,
355 ARMV8_MRS(SYSTEM_TTBR0_EL1
| (armv8
->armv8_mmu
.ttbr1_used
), 0),
357 if (retval
!= ERROR_OK
)
361 LOG_ERROR("unknow core state");
365 if (retval
!= ERROR_OK
)
369 LOG_INFO("ttb1 %s ,ttb0_mask %llx",
370 armv8
->armv8_mmu
.ttbr1_used
? "used" : "not used",
371 armv8
->armv8_mmu
.ttbr0_mask
);
373 if (armv8
->armv8_mmu
.ttbr1_used
== 1) {
374 LOG_INFO("TTBR0 access above %" PRIx64
,
375 (uint64_t)(armv8
->armv8_mmu
.ttbr0_mask
));
376 armv8
->armv8_mmu
.os_border
= armv8
->armv8_mmu
.ttbr0_mask
;
378 /* fix me , default is hard coded LINUX border */
379 armv8
->armv8_mmu
.os_border
= 0xc0000000;
387 /* method adapted to cortex A : reused arm v4 v5 method*/
388 int armv8_mmu_translate_va(struct target
*target
, uint32_t va
, uint32_t *val
)
390 uint32_t first_lvl_descriptor
= 0x0;
391 uint32_t second_lvl_descriptor
= 0x0;
393 struct armv8_common
*armv8
= target_to_armv8(target
);
394 struct arm_dpm
*dpm
= armv8
->arm
.dpm
;
395 uint32_t ttb
= 0; /* default ttb0 */
396 if (armv8
->armv8_mmu
.ttbr1_used
== -1)
397 armv8_read_ttbcr(target
);
398 if ((armv8
->armv8_mmu
.ttbr1_used
) &&
399 (va
> (0xffffffff & armv8
->armv8_mmu
.ttbr0_mask
))) {
403 retval
= dpm
->prepare(dpm
);
404 if (retval
!= ERROR_OK
)
407 /* MRC p15,0,<Rt>,c2,c0,ttb */
408 retval
= dpm
->instr_read_data_r0(dpm
,
409 ARMV4_5_MRC(15, 0, 0, 2, 0, ttb
),
411 if (retval
!= ERROR_OK
)
413 retval
= armv8
->armv8_mmu
.read_physical_memory(target
,
414 (ttb
& 0xffffc000) | ((va
& 0xfff00000) >> 18),
415 4, 1, (uint8_t *)&first_lvl_descriptor
);
416 if (retval
!= ERROR_OK
)
418 first_lvl_descriptor
= target_buffer_get_u32(target
, (uint8_t *)
419 &first_lvl_descriptor
);
420 /* reuse armv4_5 piece of code, specific armv8 changes may come later */
421 LOG_DEBUG("1st lvl desc: %8.8" PRIx32
"", first_lvl_descriptor
);
423 if ((first_lvl_descriptor
& 0x3) == 0) {
424 LOG_ERROR("Address translation failure");
425 return ERROR_TARGET_TRANSLATION_FAULT
;
429 if ((first_lvl_descriptor
& 0x3) == 2) {
430 /* section descriptor */
431 *val
= (first_lvl_descriptor
& 0xfff00000) | (va
& 0x000fffff);
435 if ((first_lvl_descriptor
& 0x3) == 1) {
436 /* coarse page table */
437 retval
= armv8
->armv8_mmu
.read_physical_memory(target
,
438 (first_lvl_descriptor
& 0xfffffc00) | ((va
& 0x000ff000) >> 10),
439 4, 1, (uint8_t *)&second_lvl_descriptor
);
440 if (retval
!= ERROR_OK
)
442 } else if ((first_lvl_descriptor
& 0x3) == 3) {
443 /* fine page table */
444 retval
= armv8
->armv8_mmu
.read_physical_memory(target
,
445 (first_lvl_descriptor
& 0xfffff000) | ((va
& 0x000ffc00) >> 8),
446 4, 1, (uint8_t *)&second_lvl_descriptor
);
447 if (retval
!= ERROR_OK
)
451 second_lvl_descriptor
= target_buffer_get_u32(target
, (uint8_t *)
452 &second_lvl_descriptor
);
454 LOG_DEBUG("2nd lvl desc: %8.8" PRIx32
"", second_lvl_descriptor
);
456 if ((second_lvl_descriptor
& 0x3) == 0) {
457 LOG_ERROR("Address translation failure");
458 return ERROR_TARGET_TRANSLATION_FAULT
;
461 if ((second_lvl_descriptor
& 0x3) == 1) {
462 /* large page descriptor */
463 *val
= (second_lvl_descriptor
& 0xffff0000) | (va
& 0x0000ffff);
467 if ((second_lvl_descriptor
& 0x3) == 2) {
468 /* small page descriptor */
469 *val
= (second_lvl_descriptor
& 0xfffff000) | (va
& 0x00000fff);
473 if ((second_lvl_descriptor
& 0x3) == 3) {
474 *val
= (second_lvl_descriptor
& 0xfffffc00) | (va
& 0x000003ff);
478 /* should not happen */
479 LOG_ERROR("Address translation failure");
480 return ERROR_TARGET_TRANSLATION_FAULT
;
486 /* V8 method VA TO PA */
487 int armv8_mmu_translate_va_pa(struct target
*target
, target_addr_t va
,
488 target_addr_t
*val
, int meminfo
)
493 static int armv8_handle_inner_cache_info_command(struct command_context
*cmd_ctx
,
494 struct armv8_cache_common
*armv8_cache
)
496 if (armv8_cache
->ctype
== -1) {
497 command_print(cmd_ctx
, "cache not yet identified");
501 command_print(cmd_ctx
,
502 "D-Cache: linelen %" PRIi32
", associativity %" PRIi32
", nsets %" PRIi32
", cachesize %" PRId32
" KBytes",
503 armv8_cache
->d_u_size
.linelen
,
504 armv8_cache
->d_u_size
.associativity
,
505 armv8_cache
->d_u_size
.nsets
,
506 armv8_cache
->d_u_size
.cachesize
);
508 command_print(cmd_ctx
,
509 "I-Cache: linelen %" PRIi32
", associativity %" PRIi32
", nsets %" PRIi32
", cachesize %" PRId32
" KBytes",
510 armv8_cache
->i_size
.linelen
,
511 armv8_cache
->i_size
.associativity
,
512 armv8_cache
->i_size
.nsets
,
513 armv8_cache
->i_size
.cachesize
);
518 static int _armv8_flush_all_data(struct target
*target
)
520 struct armv8_common
*armv8
= target_to_armv8(target
);
521 struct arm_dpm
*dpm
= armv8
->arm
.dpm
;
522 struct armv8_cachesize
*d_u_size
=
523 &(armv8
->armv8_mmu
.armv8_cache
.d_u_size
);
524 int32_t c_way
, c_index
= d_u_size
->index
;
526 /* check that cache data is on at target halt */
527 if (!armv8
->armv8_mmu
.armv8_cache
.d_u_cache_enabled
) {
528 LOG_INFO("flushed not performed :cache not on at target halt");
531 retval
= dpm
->prepare(dpm
);
532 if (retval
!= ERROR_OK
)
535 c_way
= d_u_size
->way
;
537 uint32_t value
= (c_index
<< d_u_size
->index_shift
)
538 | (c_way
<< d_u_size
->way_shift
);
540 /* LOG_INFO ("%d %d %x",c_way,c_index,value); */
541 retval
= dpm
->instr_write_data_r0(dpm
,
542 ARMV4_5_MCR(15, 0, 0, 7, 14, 2),
544 if (retval
!= ERROR_OK
)
547 } while (c_way
>= 0);
549 } while (c_index
>= 0);
552 LOG_ERROR("flushed failed");
557 static int armv8_flush_all_data(struct target
*target
)
559 int retval
= ERROR_FAIL
;
560 /* check that armv8_cache is correctly identify */
561 struct armv8_common
*armv8
= target_to_armv8(target
);
562 if (armv8
->armv8_mmu
.armv8_cache
.ctype
== -1) {
563 LOG_ERROR("trying to flush un-identified cache");
568 /* look if all the other target have been flushed in order to flush level
570 struct target_list
*head
;
573 while (head
!= (struct target_list
*)NULL
) {
575 if (curr
->state
== TARGET_HALTED
) {
576 LOG_INFO("Wait flushing data l1 on core %" PRId32
, curr
->coreid
);
577 retval
= _armv8_flush_all_data(curr
);
582 retval
= _armv8_flush_all_data(target
);
586 int armv8_handle_cache_info_command(struct command_context
*cmd_ctx
,
587 struct armv8_cache_common
*armv8_cache
)
589 if (armv8_cache
->ctype
== -1) {
590 command_print(cmd_ctx
, "cache not yet identified");
594 if (armv8_cache
->display_cache_info
)
595 armv8_cache
->display_cache_info(cmd_ctx
, armv8_cache
);
599 /* retrieve core id cluster id */
600 static int armv8_read_mpidr(struct target
*target
)
602 int retval
= ERROR_FAIL
;
603 struct armv8_common
*armv8
= target_to_armv8(target
);
604 struct arm_dpm
*dpm
= armv8
->arm
.dpm
;
606 retval
= dpm
->prepare(dpm
);
607 if (retval
!= ERROR_OK
)
609 /* MRC p15,0,<Rd>,c0,c0,5; read Multiprocessor ID register*/
611 retval
= dpm
->instr_read_data_r0(dpm
,
612 ARMV8_MRS(SYSTEM_MPIDR
, 0),
614 if (retval
!= ERROR_OK
)
617 armv8
->multi_processor_system
= (mpidr
>> 30) & 1;
618 armv8
->cluster_id
= (mpidr
>> 8) & 0xf;
619 armv8
->cpu_id
= mpidr
& 0x3;
620 LOG_INFO("%s cluster %x core %x %s", target_name(target
),
623 armv8
->multi_processor_system
== 0 ? "multi core" : "mono core");
626 LOG_ERROR("mpdir not in multiprocessor format");
635 int armv8_identify_cache(struct target
*target
)
637 /* read cache descriptor */
638 int retval
= ERROR_FAIL
;
639 struct armv8_common
*armv8
= target_to_armv8(target
);
640 struct arm_dpm
*dpm
= armv8
->arm
.dpm
;
641 uint32_t cache_selected
, clidr
;
642 uint32_t cache_i_reg
, cache_d_reg
;
643 struct armv8_cache_common
*cache
= &(armv8
->armv8_mmu
.armv8_cache
);
644 armv8_read_ttbcr(target
);
645 retval
= dpm
->prepare(dpm
);
647 if (retval
!= ERROR_OK
)
650 * mrc p15, 1, r0, c0, c0, 1 @ read clidr */
651 retval
= dpm
->instr_read_data_r0(dpm
,
652 ARMV8_MRS(SYSTEM_CLIDR
, 0),
654 if (retval
!= ERROR_OK
)
656 clidr
= (clidr
& 0x7000000) >> 23;
657 LOG_INFO("number of cache level %" PRIx32
, (uint32_t)(clidr
/ 2));
658 if ((clidr
/ 2) > 1) {
659 /* FIXME not supported present in cortex A8 and later */
660 /* in cortex A7, A15 */
661 LOG_ERROR("cache l2 present :not supported");
663 /* retrieve selected cache*/
664 retval
= dpm
->instr_read_data_r0(dpm
,
665 ARMV8_MRS(SYSTEM_CSSELR
, 0),
667 if (retval
!= ERROR_OK
)
671 /* select instruction cache
672 * [0] : 1 instruction cache selection , 0 data cache selection */
673 retval
= dpm
->instr_write_data_r0(dpm
,
674 ARMV8_MRS(SYSTEM_CSSELR
, 0),
676 if (retval
!= ERROR_OK
)
680 * MRC P15,1,<RT>,C0, C0,0 ;on cortex A9 read CCSIDR
681 * [2:0] line size 001 eight word per line
682 * [27:13] NumSet 0x7f 16KB, 0xff 32Kbytes, 0x1ff 64Kbytes */
683 retval
= dpm
->instr_read_data_r0(dpm
,
684 ARMV8_MRS(SYSTEM_CCSIDR
, 0),
686 if (retval
!= ERROR_OK
)
689 /* select data cache*/
690 retval
= dpm
->instr_write_data_r0(dpm
,
691 ARMV8_MRS(SYSTEM_CSSELR
, 0),
693 if (retval
!= ERROR_OK
)
696 retval
= dpm
->instr_read_data_r0(dpm
,
697 ARMV8_MRS(SYSTEM_CCSIDR
, 0),
699 if (retval
!= ERROR_OK
)
702 /* restore selected cache */
703 dpm
->instr_write_data_r0(dpm
,
704 ARMV8_MRS(SYSTEM_CSSELR
, 0),
707 if (retval
!= ERROR_OK
)
712 cache
->d_u_size
.linelen
= 16 << (cache_d_reg
& 0x7);
713 cache
->d_u_size
.cachesize
= (((cache_d_reg
>> 13) & 0x7fff)+1)/8;
714 cache
->d_u_size
.nsets
= (cache_d_reg
>> 13) & 0x7fff;
715 cache
->d_u_size
.associativity
= ((cache_d_reg
>> 3) & 0x3ff) + 1;
716 /* compute info for set way operation on cache */
717 cache
->d_u_size
.index_shift
= (cache_d_reg
& 0x7) + 4;
718 cache
->d_u_size
.index
= (cache_d_reg
>> 13) & 0x7fff;
719 cache
->d_u_size
.way
= ((cache_d_reg
>> 3) & 0x3ff);
720 cache
->d_u_size
.way_shift
= cache
->d_u_size
.way
+ 1;
723 while (((cache
->d_u_size
.way_shift
>> i
) & 1) != 1)
725 cache
->d_u_size
.way_shift
= 32-i
;
728 LOG_INFO("data cache index %d << %d, way %d << %d",
729 cache
->d_u_size
.index
, cache
->d_u_size
.index_shift
,
731 cache
->d_u_size
.way_shift
);
733 LOG_INFO("data cache %d bytes %d KBytes asso %d ways",
734 cache
->d_u_size
.linelen
,
735 cache
->d_u_size
.cachesize
,
736 cache
->d_u_size
.associativity
);
738 cache
->i_size
.linelen
= 16 << (cache_i_reg
& 0x7);
739 cache
->i_size
.associativity
= ((cache_i_reg
>> 3) & 0x3ff) + 1;
740 cache
->i_size
.nsets
= (cache_i_reg
>> 13) & 0x7fff;
741 cache
->i_size
.cachesize
= (((cache_i_reg
>> 13) & 0x7fff)+1)/8;
742 /* compute info for set way operation on cache */
743 cache
->i_size
.index_shift
= (cache_i_reg
& 0x7) + 4;
744 cache
->i_size
.index
= (cache_i_reg
>> 13) & 0x7fff;
745 cache
->i_size
.way
= ((cache_i_reg
>> 3) & 0x3ff);
746 cache
->i_size
.way_shift
= cache
->i_size
.way
+ 1;
749 while (((cache
->i_size
.way_shift
>> i
) & 1) != 1)
751 cache
->i_size
.way_shift
= 32-i
;
754 LOG_INFO("instruction cache index %d << %d, way %d << %d",
755 cache
->i_size
.index
, cache
->i_size
.index_shift
,
756 cache
->i_size
.way
, cache
->i_size
.way_shift
);
758 LOG_INFO("instruction cache %d bytes %d KBytes asso %d ways",
759 cache
->i_size
.linelen
,
760 cache
->i_size
.cachesize
,
761 cache
->i_size
.associativity
);
763 /* if no l2 cache initialize l1 data cache flush function function */
764 if (armv8
->armv8_mmu
.armv8_cache
.flush_all_data_cache
== NULL
) {
765 armv8
->armv8_mmu
.armv8_cache
.display_cache_info
=
766 armv8_handle_inner_cache_info_command
;
767 armv8
->armv8_mmu
.armv8_cache
.flush_all_data_cache
=
768 armv8_flush_all_data
;
770 armv8
->armv8_mmu
.armv8_cache
.ctype
= 0;
774 armv8_read_mpidr(target
);
779 int armv8_init_arch_info(struct target
*target
, struct armv8_common
*armv8
)
781 struct arm
*arm
= &armv8
->arm
;
782 arm
->arch_info
= armv8
;
783 target
->arch_info
= &armv8
->arm
;
784 /* target is useful in all function arm v4 5 compatible */
785 armv8
->arm
.target
= target
;
786 armv8
->arm
.common_magic
= ARM_COMMON_MAGIC
;
787 armv8
->common_magic
= ARMV8_COMMON_MAGIC
;
789 arm
->read_core_reg
= armv8_read_core_reg
;
791 arm
->write_core_reg
= armv8_write_core_reg
;
794 armv8
->armv8_mmu
.armv8_cache
.l2_cache
= NULL
;
795 armv8
->armv8_mmu
.armv8_cache
.ctype
= -1;
796 armv8
->armv8_mmu
.armv8_cache
.flush_all_data_cache
= NULL
;
797 armv8
->armv8_mmu
.armv8_cache
.display_cache_info
= NULL
;
801 int armv8_arch_state(struct target
*target
)
803 static const char * const state
[] = {
804 "disabled", "enabled"
807 struct armv8_common
*armv8
= target_to_armv8(target
);
808 struct arm
*arm
= &armv8
->arm
;
810 if (armv8
->common_magic
!= ARMV8_COMMON_MAGIC
) {
811 LOG_ERROR("BUG: called for a non-Armv8 target");
812 return ERROR_COMMAND_SYNTAX_ERROR
;
815 arm_arch_state(target
);
817 if (armv8
->is_armv7r
) {
818 LOG_USER("D-Cache: %s, I-Cache: %s",
819 state
[armv8
->armv8_mmu
.armv8_cache
.d_u_cache_enabled
],
820 state
[armv8
->armv8_mmu
.armv8_cache
.i_cache_enabled
]);
822 LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
823 state
[armv8
->armv8_mmu
.mmu_enabled
],
824 state
[armv8
->armv8_mmu
.armv8_cache
.d_u_cache_enabled
],
825 state
[armv8
->armv8_mmu
.armv8_cache
.i_cache_enabled
]);
828 if (arm
->core_mode
== ARM_MODE_ABT
)
829 armv8_show_fault_registers(target
);
830 if (target
->debug_reason
== DBG_REASON_WATCHPOINT
)
831 LOG_USER("Watchpoint triggered at PC %#08x",
832 (unsigned) armv8
->dpm
.wp_pc
);
837 static const struct {
845 { ARMV8_R0
, "x0", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
846 { ARMV8_R1
, "x1", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
847 { ARMV8_R2
, "x2", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
848 { ARMV8_R3
, "x3", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
849 { ARMV8_R4
, "x4", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
850 { ARMV8_R5
, "x5", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
851 { ARMV8_R6
, "x6", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
852 { ARMV8_R7
, "x7", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
853 { ARMV8_R8
, "x8", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
854 { ARMV8_R9
, "x9", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
855 { ARMV8_R10
, "x10", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
856 { ARMV8_R11
, "x11", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
857 { ARMV8_R12
, "x12", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
858 { ARMV8_R13
, "x13", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
859 { ARMV8_R14
, "x14", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
860 { ARMV8_R15
, "x15", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
861 { ARMV8_R16
, "x16", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
862 { ARMV8_R17
, "x17", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
863 { ARMV8_R18
, "x18", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
864 { ARMV8_R19
, "x19", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
865 { ARMV8_R20
, "x20", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
866 { ARMV8_R21
, "x21", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
867 { ARMV8_R22
, "x22", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
868 { ARMV8_R23
, "x23", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
869 { ARMV8_R24
, "x24", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
870 { ARMV8_R25
, "x25", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
871 { ARMV8_R26
, "x26", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
872 { ARMV8_R27
, "x27", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
873 { ARMV8_R28
, "x28", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
874 { ARMV8_R29
, "x29", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
875 { ARMV8_R30
, "x30", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
877 { ARMV8_R31
, "sp", 64, REG_TYPE_DATA_PTR
, "general", "org.gnu.gdb.aarch64.core" },
878 { ARMV8_PC
, "pc", 64, REG_TYPE_CODE_PTR
, "general", "org.gnu.gdb.aarch64.core" },
880 { ARMV8_xPSR
, "CPSR", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
883 #define ARMV8_NUM_REGS ARRAY_SIZE(armv8_regs)
886 static int armv8_get_core_reg(struct reg
*reg
)
889 struct arm_reg
*armv8_reg
= reg
->arch_info
;
890 struct target
*target
= armv8_reg
->target
;
891 struct arm
*arm
= target_to_arm(target
);
893 if (target
->state
!= TARGET_HALTED
)
894 return ERROR_TARGET_NOT_HALTED
;
896 retval
= arm
->read_core_reg(target
, reg
, armv8_reg
->num
, arm
->core_mode
);
901 static int armv8_set_core_reg(struct reg
*reg
, uint8_t *buf
)
903 struct arm_reg
*armv8_reg
= reg
->arch_info
;
904 struct target
*target
= armv8_reg
->target
;
905 uint64_t value
= buf_get_u64(buf
, 0, 64);
907 if (target
->state
!= TARGET_HALTED
)
908 return ERROR_TARGET_NOT_HALTED
;
910 buf_set_u64(reg
->value
, 0, 64, value
);
917 static const struct reg_arch_type armv8_reg_type
= {
918 .get
= armv8_get_core_reg
,
919 .set
= armv8_set_core_reg
,
922 /** Builds cache of architecturally defined registers. */
923 struct reg_cache
*armv8_build_reg_cache(struct target
*target
)
925 struct armv8_common
*armv8
= target_to_armv8(target
);
926 struct arm
*arm
= &armv8
->arm
;
927 int num_regs
= ARMV8_NUM_REGS
;
928 struct reg_cache
**cache_p
= register_get_last_cache_p(&target
->reg_cache
);
929 struct reg_cache
*cache
= malloc(sizeof(struct reg_cache
));
930 struct reg
*reg_list
= calloc(num_regs
, sizeof(struct reg
));
931 struct arm_reg
*arch_info
= calloc(num_regs
, sizeof(struct arm_reg
));
932 struct reg_feature
*feature
;
935 /* Build the process context cache */
936 cache
->name
= "arm v8 registers";
938 cache
->reg_list
= reg_list
;
939 cache
->num_regs
= num_regs
;
942 for (i
= 0; i
< num_regs
; i
++) {
943 arch_info
[i
].num
= armv8_regs
[i
].id
;
944 arch_info
[i
].target
= target
;
945 arch_info
[i
].arm
= arm
;
947 reg_list
[i
].name
= armv8_regs
[i
].name
;
948 reg_list
[i
].size
= armv8_regs
[i
].bits
;
949 reg_list
[i
].value
= calloc(1, 4);
950 reg_list
[i
].dirty
= 0;
951 reg_list
[i
].valid
= 0;
952 reg_list
[i
].type
= &armv8_reg_type
;
953 reg_list
[i
].arch_info
= &arch_info
[i
];
955 reg_list
[i
].group
= armv8_regs
[i
].group
;
956 reg_list
[i
].number
= i
;
957 reg_list
[i
].exist
= true;
958 reg_list
[i
].caller_save
= true; /* gdb defaults to true */
960 feature
= calloc(1, sizeof(struct reg_feature
));
962 feature
->name
= armv8_regs
[i
].feature
;
963 reg_list
[i
].feature
= feature
;
965 LOG_ERROR("unable to allocate feature list");
967 reg_list
[i
].reg_data_type
= calloc(1, sizeof(struct reg_data_type
));
968 if (reg_list
[i
].reg_data_type
)
969 reg_list
[i
].reg_data_type
->type
= armv8_regs
[i
].type
;
971 LOG_ERROR("unable to allocate reg type list");
974 arm
->cpsr
= reg_list
+ ARMV8_xPSR
;
975 arm
->pc
= reg_list
+ ARMV8_PC
;
976 arm
->core_cache
= cache
;
981 struct reg
*armv8_reg_current(struct arm
*arm
, unsigned regnum
)
988 r
= arm
->core_cache
->reg_list
+ regnum
;
992 const struct command_registration armv8_command_handlers
[] = {
994 .chain
= dap_command_handlers
,
996 COMMAND_REGISTRATION_DONE
1000 int armv8_get_gdb_reg_list(struct target
*target
,
1001 struct reg
**reg_list
[], int *reg_list_size
,
1002 enum target_register_class reg_class
)
1004 struct arm
*arm
= target_to_arm(target
);
1007 switch (reg_class
) {
1008 case REG_CLASS_GENERAL
:
1010 *reg_list_size
= 34;
1011 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
1013 for (i
= 0; i
< *reg_list_size
; i
++)
1014 (*reg_list
)[i
] = armv8_reg_current(arm
, i
);
1020 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)