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.");