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 "arm_opcodes.h"
38 #include "target_type.h"
40 static int armv8_read_core_reg(struct target
*target
, struct reg
*r
,
41 int num
, enum arm_mode mode
)
45 struct arm_reg
*armv8_core_reg
;
46 struct armv8_common
*armv8
= target_to_armv8(target
);
48 assert(num
< (int)armv8
->arm
.core_cache
->num_regs
);
50 armv8_core_reg
= armv8
->arm
.core_cache
->reg_list
[num
].arch_info
;
51 retval
= armv8
->load_core_reg_u64(target
,
52 armv8_core_reg
->num
, ®_value
);
54 buf_set_u64(armv8
->arm
.core_cache
->reg_list
[num
].value
, 0, 64, reg_value
);
55 armv8
->arm
.core_cache
->reg_list
[num
].valid
= 1;
56 armv8
->arm
.core_cache
->reg_list
[num
].dirty
= 0;
62 static int armv8_write_core_reg(struct target
*target
, struct reg
*r
,
63 int num
, enum arm_mode mode
, target_addr_t value
)
66 struct arm_reg
*armv8_core_reg
;
67 struct armv8_common
*armv8
= target_to_armv8(target
);
69 assert(num
< (int)armv8
->arm
.core_cache
->num_regs
);
71 armv8_core_reg
= armv8
->arm
.core_cache
->reg_list
[num
].arch_info
;
72 retval
= armv8
->store_core_reg_u64(target
,
75 if (retval
!= ERROR_OK
) {
76 LOG_ERROR("JTAG failure");
77 armv8
->arm
.core_cache
->reg_list
[num
].dirty
= armv8
->arm
.core_cache
->reg_list
[num
].valid
;
78 return ERROR_JTAG_DEVICE_ERROR
;
81 LOG_DEBUG("write core reg %i value 0x%" PRIx64
"", num
, value
);
82 armv8
->arm
.core_cache
->reg_list
[num
].valid
= 1;
83 armv8
->arm
.core_cache
->reg_list
[num
].dirty
= 0;
89 static void armv8_show_fault_registers(struct target
*target
)
94 static int armv8_read_ttbcr(struct target
*target
)
96 struct armv8_common
*armv8
= target_to_armv8(target
);
97 struct arm_dpm
*dpm
= armv8
->arm
.dpm
;
99 int retval
= dpm
->prepare(dpm
);
100 if (retval
!= ERROR_OK
)
102 /* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
103 retval
= dpm
->instr_read_data_r0(dpm
,
104 ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
106 if (retval
!= ERROR_OK
)
108 armv8
->armv8_mmu
.ttbr1_used
= ((ttbcr
& 0x7) != 0) ? 1 : 0;
109 armv8
->armv8_mmu
.ttbr0_mask
= 7 << (32 - ((ttbcr
& 0x7)));
111 LOG_INFO("ttb1 %s ,ttb0_mask %x",
112 armv8
->armv8_mmu
.ttbr1_used
? "used" : "not used",
113 armv8
->armv8_mmu
.ttbr0_mask
);
115 if (armv8
->armv8_mmu
.ttbr1_used
== 1) {
116 LOG_INFO("SVC access above %" PRIx32
,
117 (uint32_t)(0xffffffff & armv8
->armv8_mmu
.ttbr0_mask
));
118 armv8
->armv8_mmu
.os_border
= 0xffffffff & armv8
->armv8_mmu
.ttbr0_mask
;
120 /* fix me , default is hard coded LINUX border */
121 armv8
->armv8_mmu
.os_border
= 0xc0000000;
129 /* method adapted to cortex A : reused arm v4 v5 method*/
130 int armv8_mmu_translate_va(struct target
*target
, uint32_t va
, uint32_t *val
)
132 uint32_t first_lvl_descriptor
= 0x0;
133 uint32_t second_lvl_descriptor
= 0x0;
135 struct armv8_common
*armv8
= target_to_armv8(target
);
136 struct arm_dpm
*dpm
= armv8
->arm
.dpm
;
137 uint32_t ttb
= 0; /* default ttb0 */
138 if (armv8
->armv8_mmu
.ttbr1_used
== -1)
139 armv8_read_ttbcr(target
);
140 if ((armv8
->armv8_mmu
.ttbr1_used
) &&
141 (va
> (0xffffffff & armv8
->armv8_mmu
.ttbr0_mask
))) {
145 retval
= dpm
->prepare(dpm
);
146 if (retval
!= ERROR_OK
)
149 /* MRC p15,0,<Rt>,c2,c0,ttb */
150 retval
= dpm
->instr_read_data_r0(dpm
,
151 ARMV4_5_MRC(15, 0, 0, 2, 0, ttb
),
153 if (retval
!= ERROR_OK
)
155 retval
= armv8
->armv8_mmu
.read_physical_memory(target
,
156 (ttb
& 0xffffc000) | ((va
& 0xfff00000) >> 18),
157 4, 1, (uint8_t *)&first_lvl_descriptor
);
158 if (retval
!= ERROR_OK
)
160 first_lvl_descriptor
= target_buffer_get_u32(target
, (uint8_t *)
161 &first_lvl_descriptor
);
162 /* reuse armv4_5 piece of code, specific armv8 changes may come later */
163 LOG_DEBUG("1st lvl desc: %8.8" PRIx32
"", first_lvl_descriptor
);
165 if ((first_lvl_descriptor
& 0x3) == 0) {
166 LOG_ERROR("Address translation failure");
167 return ERROR_TARGET_TRANSLATION_FAULT
;
171 if ((first_lvl_descriptor
& 0x3) == 2) {
172 /* section descriptor */
173 *val
= (first_lvl_descriptor
& 0xfff00000) | (va
& 0x000fffff);
177 if ((first_lvl_descriptor
& 0x3) == 1) {
178 /* coarse page table */
179 retval
= armv8
->armv8_mmu
.read_physical_memory(target
,
180 (first_lvl_descriptor
& 0xfffffc00) | ((va
& 0x000ff000) >> 10),
181 4, 1, (uint8_t *)&second_lvl_descriptor
);
182 if (retval
!= ERROR_OK
)
184 } else if ((first_lvl_descriptor
& 0x3) == 3) {
185 /* fine page table */
186 retval
= armv8
->armv8_mmu
.read_physical_memory(target
,
187 (first_lvl_descriptor
& 0xfffff000) | ((va
& 0x000ffc00) >> 8),
188 4, 1, (uint8_t *)&second_lvl_descriptor
);
189 if (retval
!= ERROR_OK
)
193 second_lvl_descriptor
= target_buffer_get_u32(target
, (uint8_t *)
194 &second_lvl_descriptor
);
196 LOG_DEBUG("2nd lvl desc: %8.8" PRIx32
"", second_lvl_descriptor
);
198 if ((second_lvl_descriptor
& 0x3) == 0) {
199 LOG_ERROR("Address translation failure");
200 return ERROR_TARGET_TRANSLATION_FAULT
;
203 if ((second_lvl_descriptor
& 0x3) == 1) {
204 /* large page descriptor */
205 *val
= (second_lvl_descriptor
& 0xffff0000) | (va
& 0x0000ffff);
209 if ((second_lvl_descriptor
& 0x3) == 2) {
210 /* small page descriptor */
211 *val
= (second_lvl_descriptor
& 0xfffff000) | (va
& 0x00000fff);
215 if ((second_lvl_descriptor
& 0x3) == 3) {
216 *val
= (second_lvl_descriptor
& 0xfffffc00) | (va
& 0x000003ff);
220 /* should not happen */
221 LOG_ERROR("Address translation failure");
222 return ERROR_TARGET_TRANSLATION_FAULT
;
228 /* V8 method VA TO PA */
229 int armv8_mmu_translate_va_pa(struct target
*target
, target_addr_t va
,
230 target_addr_t
*val
, int meminfo
)
235 static int armv8_handle_inner_cache_info_command(struct command_context
*cmd_ctx
,
236 struct armv8_cache_common
*armv8_cache
)
238 if (armv8_cache
->ctype
== -1) {
239 command_print(cmd_ctx
, "cache not yet identified");
243 command_print(cmd_ctx
,
244 "D-Cache: linelen %" PRIi32
", associativity %" PRIi32
", nsets %" PRIi32
", cachesize %" PRId32
" KBytes",
245 armv8_cache
->d_u_size
.linelen
,
246 armv8_cache
->d_u_size
.associativity
,
247 armv8_cache
->d_u_size
.nsets
,
248 armv8_cache
->d_u_size
.cachesize
);
250 command_print(cmd_ctx
,
251 "I-Cache: linelen %" PRIi32
", associativity %" PRIi32
", nsets %" PRIi32
", cachesize %" PRId32
" KBytes",
252 armv8_cache
->i_size
.linelen
,
253 armv8_cache
->i_size
.associativity
,
254 armv8_cache
->i_size
.nsets
,
255 armv8_cache
->i_size
.cachesize
);
260 static int _armv8_flush_all_data(struct target
*target
)
262 struct armv8_common
*armv8
= target_to_armv8(target
);
263 struct arm_dpm
*dpm
= armv8
->arm
.dpm
;
264 struct armv8_cachesize
*d_u_size
=
265 &(armv8
->armv8_mmu
.armv8_cache
.d_u_size
);
266 int32_t c_way
, c_index
= d_u_size
->index
;
268 /* check that cache data is on at target halt */
269 if (!armv8
->armv8_mmu
.armv8_cache
.d_u_cache_enabled
) {
270 LOG_INFO("flushed not performed :cache not on at target halt");
273 retval
= dpm
->prepare(dpm
);
274 if (retval
!= ERROR_OK
)
277 c_way
= d_u_size
->way
;
279 uint32_t value
= (c_index
<< d_u_size
->index_shift
)
280 | (c_way
<< d_u_size
->way_shift
);
282 /* LOG_INFO ("%d %d %x",c_way,c_index,value); */
283 retval
= dpm
->instr_write_data_r0(dpm
,
284 ARMV4_5_MCR(15, 0, 0, 7, 14, 2),
286 if (retval
!= ERROR_OK
)
289 } while (c_way
>= 0);
291 } while (c_index
>= 0);
294 LOG_ERROR("flushed failed");
299 static int armv8_flush_all_data(struct target
*target
)
301 int retval
= ERROR_FAIL
;
302 /* check that armv8_cache is correctly identify */
303 struct armv8_common
*armv8
= target_to_armv8(target
);
304 if (armv8
->armv8_mmu
.armv8_cache
.ctype
== -1) {
305 LOG_ERROR("trying to flush un-identified cache");
310 /* look if all the other target have been flushed in order to flush level
312 struct target_list
*head
;
315 while (head
!= (struct target_list
*)NULL
) {
317 if (curr
->state
== TARGET_HALTED
) {
318 LOG_INFO("Wait flushing data l1 on core %" PRId32
, curr
->coreid
);
319 retval
= _armv8_flush_all_data(curr
);
324 retval
= _armv8_flush_all_data(target
);
328 int armv8_handle_cache_info_command(struct command_context
*cmd_ctx
,
329 struct armv8_cache_common
*armv8_cache
)
331 if (armv8_cache
->ctype
== -1) {
332 command_print(cmd_ctx
, "cache not yet identified");
336 if (armv8_cache
->display_cache_info
)
337 armv8_cache
->display_cache_info(cmd_ctx
, armv8_cache
);
341 /* retrieve core id cluster id */
342 static int armv8_read_mpidr(struct target
*target
)
344 int retval
= ERROR_FAIL
;
345 struct armv8_common
*armv8
= target_to_armv8(target
);
346 struct arm_dpm
*dpm
= armv8
->arm
.dpm
;
348 retval
= dpm
->prepare(dpm
);
349 if (retval
!= ERROR_OK
)
351 /* MRC p15,0,<Rd>,c0,c0,5; read Multiprocessor ID register*/
353 retval
= dpm
->instr_read_data_r0(dpm
,
354 ARMV4_5_MRC(15, 0, 0, 0, 0, 5),
356 if (retval
!= ERROR_OK
)
359 armv8
->multi_processor_system
= (mpidr
>> 30) & 1;
360 armv8
->cluster_id
= (mpidr
>> 8) & 0xf;
361 armv8
->cpu_id
= mpidr
& 0x3;
362 LOG_INFO("%s cluster %x core %x %s", target_name(target
),
365 armv8
->multi_processor_system
== 0 ? "multi core" : "mono core");
368 LOG_ERROR("mpdir not in multiprocessor format");
377 int armv8_identify_cache(struct target
*target
)
379 /* read cache descriptor */
380 int retval
= ERROR_FAIL
;
381 struct armv8_common
*armv8
= target_to_armv8(target
);
382 struct arm_dpm
*dpm
= armv8
->arm
.dpm
;
383 uint32_t cache_selected
, clidr
;
384 uint32_t cache_i_reg
, cache_d_reg
;
385 struct armv8_cache_common
*cache
= &(armv8
->armv8_mmu
.armv8_cache
);
386 if (!armv8
->is_armv7r
)
387 armv8_read_ttbcr(target
);
388 retval
= dpm
->prepare(dpm
);
390 if (retval
!= ERROR_OK
)
393 * mrc p15, 1, r0, c0, c0, 1 @ read clidr */
394 retval
= dpm
->instr_read_data_r0(dpm
,
395 ARMV4_5_MRC(15, 1, 0, 0, 0, 1),
397 if (retval
!= ERROR_OK
)
399 clidr
= (clidr
& 0x7000000) >> 23;
400 LOG_INFO("number of cache level %" PRIx32
, (uint32_t)(clidr
/ 2));
401 if ((clidr
/ 2) > 1) {
402 /* FIXME not supported present in cortex A8 and later */
403 /* in cortex A7, A15 */
404 LOG_ERROR("cache l2 present :not supported");
406 /* retrieve selected cache
407 * MRC p15, 2,<Rd>, c0, c0, 0; Read CSSELR */
408 retval
= dpm
->instr_read_data_r0(dpm
,
409 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
411 if (retval
!= ERROR_OK
)
414 retval
= armv8
->arm
.mrc(target
, 15,
418 if (retval
!= ERROR_OK
)
420 /* select instruction cache
421 * MCR p15, 2,<Rd>, c0, c0, 0; Write CSSELR
422 * [0] : 1 instruction cache selection , 0 data cache selection */
423 retval
= dpm
->instr_write_data_r0(dpm
,
424 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
426 if (retval
!= ERROR_OK
)
430 * MRC P15,1,<RT>,C0, C0,0 ;on cortex A9 read CCSIDR
431 * [2:0] line size 001 eight word per line
432 * [27:13] NumSet 0x7f 16KB, 0xff 32Kbytes, 0x1ff 64Kbytes */
433 retval
= dpm
->instr_read_data_r0(dpm
,
434 ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
436 if (retval
!= ERROR_OK
)
439 /* select data cache*/
440 retval
= dpm
->instr_write_data_r0(dpm
,
441 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
443 if (retval
!= ERROR_OK
)
446 retval
= dpm
->instr_read_data_r0(dpm
,
447 ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
449 if (retval
!= ERROR_OK
)
452 /* restore selected cache */
453 dpm
->instr_write_data_r0(dpm
,
454 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
457 if (retval
!= ERROR_OK
)
462 cache
->d_u_size
.linelen
= 16 << (cache_d_reg
& 0x7);
463 cache
->d_u_size
.cachesize
= (((cache_d_reg
>> 13) & 0x7fff)+1)/8;
464 cache
->d_u_size
.nsets
= (cache_d_reg
>> 13) & 0x7fff;
465 cache
->d_u_size
.associativity
= ((cache_d_reg
>> 3) & 0x3ff) + 1;
466 /* compute info for set way operation on cache */
467 cache
->d_u_size
.index_shift
= (cache_d_reg
& 0x7) + 4;
468 cache
->d_u_size
.index
= (cache_d_reg
>> 13) & 0x7fff;
469 cache
->d_u_size
.way
= ((cache_d_reg
>> 3) & 0x3ff);
470 cache
->d_u_size
.way_shift
= cache
->d_u_size
.way
+ 1;
473 while (((cache
->d_u_size
.way_shift
>> i
) & 1) != 1)
475 cache
->d_u_size
.way_shift
= 32-i
;
478 LOG_INFO("data cache index %d << %d, way %d << %d",
479 cache
->d_u_size
.index
, cache
->d_u_size
.index_shift
,
481 cache
->d_u_size
.way_shift
);
483 LOG_INFO("data cache %d bytes %d KBytes asso %d ways",
484 cache
->d_u_size
.linelen
,
485 cache
->d_u_size
.cachesize
,
486 cache
->d_u_size
.associativity
);
488 cache
->i_size
.linelen
= 16 << (cache_i_reg
& 0x7);
489 cache
->i_size
.associativity
= ((cache_i_reg
>> 3) & 0x3ff) + 1;
490 cache
->i_size
.nsets
= (cache_i_reg
>> 13) & 0x7fff;
491 cache
->i_size
.cachesize
= (((cache_i_reg
>> 13) & 0x7fff)+1)/8;
492 /* compute info for set way operation on cache */
493 cache
->i_size
.index_shift
= (cache_i_reg
& 0x7) + 4;
494 cache
->i_size
.index
= (cache_i_reg
>> 13) & 0x7fff;
495 cache
->i_size
.way
= ((cache_i_reg
>> 3) & 0x3ff);
496 cache
->i_size
.way_shift
= cache
->i_size
.way
+ 1;
499 while (((cache
->i_size
.way_shift
>> i
) & 1) != 1)
501 cache
->i_size
.way_shift
= 32-i
;
504 LOG_INFO("instruction cache index %d << %d, way %d << %d",
505 cache
->i_size
.index
, cache
->i_size
.index_shift
,
506 cache
->i_size
.way
, cache
->i_size
.way_shift
);
508 LOG_INFO("instruction cache %d bytes %d KBytes asso %d ways",
509 cache
->i_size
.linelen
,
510 cache
->i_size
.cachesize
,
511 cache
->i_size
.associativity
);
513 /* if no l2 cache initialize l1 data cache flush function function */
514 if (armv8
->armv8_mmu
.armv8_cache
.flush_all_data_cache
== NULL
) {
515 armv8
->armv8_mmu
.armv8_cache
.display_cache_info
=
516 armv8_handle_inner_cache_info_command
;
517 armv8
->armv8_mmu
.armv8_cache
.flush_all_data_cache
=
518 armv8_flush_all_data
;
520 armv8
->armv8_mmu
.armv8_cache
.ctype
= 0;
524 armv8_read_mpidr(target
);
529 int armv8_init_arch_info(struct target
*target
, struct armv8_common
*armv8
)
531 struct arm
*arm
= &armv8
->arm
;
532 arm
->arch_info
= armv8
;
533 target
->arch_info
= &armv8
->arm
;
534 /* target is useful in all function arm v4 5 compatible */
535 armv8
->arm
.target
= target
;
536 armv8
->arm
.common_magic
= ARM_COMMON_MAGIC
;
537 armv8
->common_magic
= ARMV8_COMMON_MAGIC
;
539 arm
->read_core_reg
= armv8_read_core_reg
;
541 arm
->write_core_reg
= armv8_write_core_reg
;
544 armv8
->armv8_mmu
.armv8_cache
.l2_cache
= NULL
;
545 armv8
->armv8_mmu
.armv8_cache
.ctype
= -1;
546 armv8
->armv8_mmu
.armv8_cache
.flush_all_data_cache
= NULL
;
547 armv8
->armv8_mmu
.armv8_cache
.display_cache_info
= NULL
;
551 int armv8_arch_state(struct target
*target
)
553 static const char * const state
[] = {
554 "disabled", "enabled"
557 struct armv8_common
*armv8
= target_to_armv8(target
);
558 struct arm
*arm
= &armv8
->arm
;
560 if (armv8
->common_magic
!= ARMV8_COMMON_MAGIC
) {
561 LOG_ERROR("BUG: called for a non-Armv8 target");
562 return ERROR_COMMAND_SYNTAX_ERROR
;
565 arm_arch_state(target
);
567 if (armv8
->is_armv7r
) {
568 LOG_USER("D-Cache: %s, I-Cache: %s",
569 state
[armv8
->armv8_mmu
.armv8_cache
.d_u_cache_enabled
],
570 state
[armv8
->armv8_mmu
.armv8_cache
.i_cache_enabled
]);
572 LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
573 state
[armv8
->armv8_mmu
.mmu_enabled
],
574 state
[armv8
->armv8_mmu
.armv8_cache
.d_u_cache_enabled
],
575 state
[armv8
->armv8_mmu
.armv8_cache
.i_cache_enabled
]);
578 if (arm
->core_mode
== ARM_MODE_ABT
)
579 armv8_show_fault_registers(target
);
580 if (target
->debug_reason
== DBG_REASON_WATCHPOINT
)
581 LOG_USER("Watchpoint triggered at PC %#08x",
582 (unsigned) armv8
->dpm
.wp_pc
);
587 static const struct {
595 { ARMV8_R0
, "x0", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
596 { ARMV8_R1
, "x1", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
597 { ARMV8_R2
, "x2", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
598 { ARMV8_R3
, "x3", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
599 { ARMV8_R4
, "x4", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
600 { ARMV8_R5
, "x5", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
601 { ARMV8_R6
, "x6", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
602 { ARMV8_R7
, "x7", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
603 { ARMV8_R8
, "x8", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
604 { ARMV8_R9
, "x9", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
605 { ARMV8_R10
, "x10", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
606 { ARMV8_R11
, "x11", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
607 { ARMV8_R12
, "x12", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
608 { ARMV8_R13
, "x13", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
609 { ARMV8_R14
, "x14", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
610 { ARMV8_R15
, "x15", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
611 { ARMV8_R16
, "x16", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
612 { ARMV8_R17
, "x17", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
613 { ARMV8_R18
, "x18", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
614 { ARMV8_R19
, "x19", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
615 { ARMV8_R20
, "x20", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
616 { ARMV8_R21
, "x21", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
617 { ARMV8_R22
, "x22", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
618 { ARMV8_R23
, "x23", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
619 { ARMV8_R24
, "x24", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
620 { ARMV8_R25
, "x25", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
621 { ARMV8_R26
, "x26", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
622 { ARMV8_R27
, "x27", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
623 { ARMV8_R28
, "x28", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
624 { ARMV8_R29
, "x29", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
625 { ARMV8_R30
, "x30", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
627 { ARMV8_R31
, "sp", 64, REG_TYPE_DATA_PTR
, "general", "org.gnu.gdb.aarch64.core" },
628 { ARMV8_PC
, "pc", 64, REG_TYPE_CODE_PTR
, "general", "org.gnu.gdb.aarch64.core" },
630 { ARMV8_xPSR
, "CPSR", 64, REG_TYPE_INT
, "general", "org.gnu.gdb.aarch64.core" },
633 #define ARMV8_NUM_REGS ARRAY_SIZE(armv8_regs)
636 static int armv8_get_core_reg(struct reg
*reg
)
639 struct arm_reg
*armv8_reg
= reg
->arch_info
;
640 struct target
*target
= armv8_reg
->target
;
641 struct arm
*arm
= target_to_arm(target
);
643 if (target
->state
!= TARGET_HALTED
)
644 return ERROR_TARGET_NOT_HALTED
;
646 retval
= arm
->read_core_reg(target
, reg
, armv8_reg
->num
, arm
->core_mode
);
651 static int armv8_set_core_reg(struct reg
*reg
, uint8_t *buf
)
653 struct arm_reg
*armv8_reg
= reg
->arch_info
;
654 struct target
*target
= armv8_reg
->target
;
655 uint64_t value
= buf_get_u64(buf
, 0, 64);
657 if (target
->state
!= TARGET_HALTED
)
658 return ERROR_TARGET_NOT_HALTED
;
660 buf_set_u64(reg
->value
, 0, 64, value
);
667 static const struct reg_arch_type armv8_reg_type
= {
668 .get
= armv8_get_core_reg
,
669 .set
= armv8_set_core_reg
,
672 /** Builds cache of architecturally defined registers. */
673 struct reg_cache
*armv8_build_reg_cache(struct target
*target
)
675 struct armv8_common
*armv8
= target_to_armv8(target
);
676 struct arm
*arm
= &armv8
->arm
;
677 int num_regs
= ARMV8_NUM_REGS
;
678 struct reg_cache
**cache_p
= register_get_last_cache_p(&target
->reg_cache
);
679 struct reg_cache
*cache
= malloc(sizeof(struct reg_cache
));
680 struct reg
*reg_list
= calloc(num_regs
, sizeof(struct reg
));
681 struct arm_reg
*arch_info
= calloc(num_regs
, sizeof(struct arm_reg
));
682 struct reg_feature
*feature
;
685 /* Build the process context cache */
686 cache
->name
= "arm v8 registers";
688 cache
->reg_list
= reg_list
;
689 cache
->num_regs
= num_regs
;
692 for (i
= 0; i
< num_regs
; i
++) {
693 arch_info
[i
].num
= armv8_regs
[i
].id
;
694 arch_info
[i
].target
= target
;
695 arch_info
[i
].arm
= arm
;
697 reg_list
[i
].name
= armv8_regs
[i
].name
;
698 reg_list
[i
].size
= armv8_regs
[i
].bits
;
699 reg_list
[i
].value
= calloc(1, 4);
700 reg_list
[i
].dirty
= 0;
701 reg_list
[i
].valid
= 0;
702 reg_list
[i
].type
= &armv8_reg_type
;
703 reg_list
[i
].arch_info
= &arch_info
[i
];
705 reg_list
[i
].group
= armv8_regs
[i
].group
;
706 reg_list
[i
].number
= i
;
707 reg_list
[i
].exist
= true;
708 reg_list
[i
].caller_save
= true; /* gdb defaults to true */
710 feature
= calloc(1, sizeof(struct reg_feature
));
712 feature
->name
= armv8_regs
[i
].feature
;
713 reg_list
[i
].feature
= feature
;
715 LOG_ERROR("unable to allocate feature list");
717 reg_list
[i
].reg_data_type
= calloc(1, sizeof(struct reg_data_type
));
718 if (reg_list
[i
].reg_data_type
)
719 reg_list
[i
].reg_data_type
->type
= armv8_regs
[i
].type
;
721 LOG_ERROR("unable to allocate reg type list");
724 arm
->cpsr
= reg_list
+ ARMV8_xPSR
;
725 arm
->pc
= reg_list
+ ARMV8_PC
;
726 arm
->core_cache
= cache
;
731 struct reg
*armv8_reg_current(struct arm
*arm
, unsigned regnum
)
738 r
= arm
->core_cache
->reg_list
+ regnum
;
742 const struct command_registration armv8_command_handlers
[] = {
744 .chain
= dap_command_handlers
,
746 COMMAND_REGISTRATION_DONE
750 int armv8_get_gdb_reg_list(struct target
*target
,
751 struct reg
**reg_list
[], int *reg_list_size
,
752 enum target_register_class reg_class
)
754 struct arm
*arm
= target_to_arm(target
);
758 case REG_CLASS_GENERAL
:
761 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
763 for (i
= 0; i
< *reg_list_size
; i
++)
764 (*reg_list
)[i
] = armv8_reg_current(arm
, i
);
770 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)