aarch64: fix reading of MPIDR
[openocd.git] / src / target / armv8.c
blobe516518ad4faf5f8eb23cfe21c13991eb9253845
1 /***************************************************************************
2 * Copyright (C) 2015 by David Ung *
3 * *
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. *
8 * *
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. *
13 * *
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 ***************************************************************************/
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
23 #include <helper/replacements.h>
25 #include "armv8.h"
26 #include "arm_disassembler.h"
28 #include "register.h"
29 #include <helper/binarybuffer.h>
30 #include <helper/command.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
36 #include "armv8_opcodes.h"
37 #include "arm_opcodes.h"
38 #include "target.h"
39 #include "target_type.h"
41 static int armv8_read_core_reg(struct target *target, struct reg *r,
42 int num, enum arm_mode mode)
44 uint64_t reg_value;
45 int retval;
46 struct arm_reg *armv8_core_reg;
47 struct armv8_common *armv8 = target_to_armv8(target);
49 assert(num < (int)armv8->arm.core_cache->num_regs);
51 armv8_core_reg = armv8->arm.core_cache->reg_list[num].arch_info;
52 retval = armv8->load_core_reg_u64(target,
53 armv8_core_reg->num, &reg_value);
55 buf_set_u64(armv8->arm.core_cache->reg_list[num].value, 0, 64, reg_value);
56 armv8->arm.core_cache->reg_list[num].valid = 1;
57 armv8->arm.core_cache->reg_list[num].dirty = 0;
59 return retval;
62 #if 0
63 static int armv8_write_core_reg(struct target *target, struct reg *r,
64 int num, enum arm_mode mode, target_addr_t value)
66 int retval;
67 struct arm_reg *armv8_core_reg;
68 struct armv8_common *armv8 = target_to_armv8(target);
70 assert(num < (int)armv8->arm.core_cache->num_regs);
72 armv8_core_reg = armv8->arm.core_cache->reg_list[num].arch_info;
73 retval = armv8->store_core_reg_u64(target,
74 armv8_core_reg->num,
75 value);
76 if (retval != ERROR_OK) {
77 LOG_ERROR("JTAG failure");
78 armv8->arm.core_cache->reg_list[num].dirty = armv8->arm.core_cache->reg_list[num].valid;
79 return ERROR_JTAG_DEVICE_ERROR;
82 LOG_DEBUG("write core reg %i value 0x%" PRIx64 "", num, value);
83 armv8->arm.core_cache->reg_list[num].valid = 1;
84 armv8->arm.core_cache->reg_list[num].dirty = 0;
86 return ERROR_OK;
88 #endif
90 static void armv8_show_fault_registers(struct target *target)
92 /* TODO */
95 static int armv8_read_ttbcr(struct target *target)
97 struct armv8_common *armv8 = target_to_armv8(target);
98 struct arm_dpm *dpm = armv8->arm.dpm;
99 uint32_t ttbcr;
100 int retval = dpm->prepare(dpm);
101 if (retval != ERROR_OK)
102 goto done;
103 /* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
104 retval = dpm->instr_read_data_r0(dpm,
105 ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
106 &ttbcr);
107 if (retval != ERROR_OK)
108 goto done;
109 armv8->armv8_mmu.ttbr1_used = ((ttbcr & 0x7) != 0) ? 1 : 0;
110 armv8->armv8_mmu.ttbr0_mask = 7 << (32 - ((ttbcr & 0x7)));
111 #if 0
112 LOG_INFO("ttb1 %s ,ttb0_mask %x",
113 armv8->armv8_mmu.ttbr1_used ? "used" : "not used",
114 armv8->armv8_mmu.ttbr0_mask);
115 #endif
116 if (armv8->armv8_mmu.ttbr1_used == 1) {
117 LOG_INFO("SVC access above %" PRIx32,
118 (uint32_t)(0xffffffff & armv8->armv8_mmu.ttbr0_mask));
119 armv8->armv8_mmu.os_border = 0xffffffff & armv8->armv8_mmu.ttbr0_mask;
120 } else {
121 /* fix me , default is hard coded LINUX border */
122 armv8->armv8_mmu.os_border = 0xc0000000;
124 done:
125 dpm->finish(dpm);
126 return retval;
130 /* method adapted to cortex A : reused arm v4 v5 method*/
131 int armv8_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val)
133 uint32_t first_lvl_descriptor = 0x0;
134 uint32_t second_lvl_descriptor = 0x0;
135 int retval;
136 struct armv8_common *armv8 = target_to_armv8(target);
137 struct arm_dpm *dpm = armv8->arm.dpm;
138 uint32_t ttb = 0; /* default ttb0 */
139 if (armv8->armv8_mmu.ttbr1_used == -1)
140 armv8_read_ttbcr(target);
141 if ((armv8->armv8_mmu.ttbr1_used) &&
142 (va > (0xffffffff & armv8->armv8_mmu.ttbr0_mask))) {
143 /* select ttb 1 */
144 ttb = 1;
146 retval = dpm->prepare(dpm);
147 if (retval != ERROR_OK)
148 goto done;
150 /* MRC p15,0,<Rt>,c2,c0,ttb */
151 retval = dpm->instr_read_data_r0(dpm,
152 ARMV4_5_MRC(15, 0, 0, 2, 0, ttb),
153 &ttb);
154 if (retval != ERROR_OK)
155 return retval;
156 retval = armv8->armv8_mmu.read_physical_memory(target,
157 (ttb & 0xffffc000) | ((va & 0xfff00000) >> 18),
158 4, 1, (uint8_t *)&first_lvl_descriptor);
159 if (retval != ERROR_OK)
160 return retval;
161 first_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *)
162 &first_lvl_descriptor);
163 /* reuse armv4_5 piece of code, specific armv8 changes may come later */
164 LOG_DEBUG("1st lvl desc: %8.8" PRIx32 "", first_lvl_descriptor);
166 if ((first_lvl_descriptor & 0x3) == 0) {
167 LOG_ERROR("Address translation failure");
168 return ERROR_TARGET_TRANSLATION_FAULT;
172 if ((first_lvl_descriptor & 0x3) == 2) {
173 /* section descriptor */
174 *val = (first_lvl_descriptor & 0xfff00000) | (va & 0x000fffff);
175 return ERROR_OK;
178 if ((first_lvl_descriptor & 0x3) == 1) {
179 /* coarse page table */
180 retval = armv8->armv8_mmu.read_physical_memory(target,
181 (first_lvl_descriptor & 0xfffffc00) | ((va & 0x000ff000) >> 10),
182 4, 1, (uint8_t *)&second_lvl_descriptor);
183 if (retval != ERROR_OK)
184 return retval;
185 } else if ((first_lvl_descriptor & 0x3) == 3) {
186 /* fine page table */
187 retval = armv8->armv8_mmu.read_physical_memory(target,
188 (first_lvl_descriptor & 0xfffff000) | ((va & 0x000ffc00) >> 8),
189 4, 1, (uint8_t *)&second_lvl_descriptor);
190 if (retval != ERROR_OK)
191 return retval;
194 second_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *)
195 &second_lvl_descriptor);
197 LOG_DEBUG("2nd lvl desc: %8.8" PRIx32 "", second_lvl_descriptor);
199 if ((second_lvl_descriptor & 0x3) == 0) {
200 LOG_ERROR("Address translation failure");
201 return ERROR_TARGET_TRANSLATION_FAULT;
204 if ((second_lvl_descriptor & 0x3) == 1) {
205 /* large page descriptor */
206 *val = (second_lvl_descriptor & 0xffff0000) | (va & 0x0000ffff);
207 return ERROR_OK;
210 if ((second_lvl_descriptor & 0x3) == 2) {
211 /* small page descriptor */
212 *val = (second_lvl_descriptor & 0xfffff000) | (va & 0x00000fff);
213 return ERROR_OK;
216 if ((second_lvl_descriptor & 0x3) == 3) {
217 *val = (second_lvl_descriptor & 0xfffffc00) | (va & 0x000003ff);
218 return ERROR_OK;
221 /* should not happen */
222 LOG_ERROR("Address translation failure");
223 return ERROR_TARGET_TRANSLATION_FAULT;
225 done:
226 return retval;
229 /* V8 method VA TO PA */
230 int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va,
231 target_addr_t *val, int meminfo)
233 return ERROR_OK;
236 static int armv8_handle_inner_cache_info_command(struct command_context *cmd_ctx,
237 struct armv8_cache_common *armv8_cache)
239 if (armv8_cache->ctype == -1) {
240 command_print(cmd_ctx, "cache not yet identified");
241 return ERROR_OK;
244 command_print(cmd_ctx,
245 "D-Cache: linelen %" PRIi32 ", associativity %" PRIi32 ", nsets %" PRIi32 ", cachesize %" PRId32 " KBytes",
246 armv8_cache->d_u_size.linelen,
247 armv8_cache->d_u_size.associativity,
248 armv8_cache->d_u_size.nsets,
249 armv8_cache->d_u_size.cachesize);
251 command_print(cmd_ctx,
252 "I-Cache: linelen %" PRIi32 ", associativity %" PRIi32 ", nsets %" PRIi32 ", cachesize %" PRId32 " KBytes",
253 armv8_cache->i_size.linelen,
254 armv8_cache->i_size.associativity,
255 armv8_cache->i_size.nsets,
256 armv8_cache->i_size.cachesize);
258 return ERROR_OK;
261 static int _armv8_flush_all_data(struct target *target)
263 struct armv8_common *armv8 = target_to_armv8(target);
264 struct arm_dpm *dpm = armv8->arm.dpm;
265 struct armv8_cachesize *d_u_size =
266 &(armv8->armv8_mmu.armv8_cache.d_u_size);
267 int32_t c_way, c_index = d_u_size->index;
268 int retval;
269 /* check that cache data is on at target halt */
270 if (!armv8->armv8_mmu.armv8_cache.d_u_cache_enabled) {
271 LOG_INFO("flushed not performed :cache not on at target halt");
272 return ERROR_OK;
274 retval = dpm->prepare(dpm);
275 if (retval != ERROR_OK)
276 goto done;
277 do {
278 c_way = d_u_size->way;
279 do {
280 uint32_t value = (c_index << d_u_size->index_shift)
281 | (c_way << d_u_size->way_shift);
282 /* DCCISW */
283 /* LOG_INFO ("%d %d %x",c_way,c_index,value); */
284 retval = dpm->instr_write_data_r0(dpm,
285 ARMV4_5_MCR(15, 0, 0, 7, 14, 2),
286 value);
287 if (retval != ERROR_OK)
288 goto done;
289 c_way -= 1;
290 } while (c_way >= 0);
291 c_index -= 1;
292 } while (c_index >= 0);
293 return retval;
294 done:
295 LOG_ERROR("flushed failed");
296 dpm->finish(dpm);
297 return retval;
300 static int armv8_flush_all_data(struct target *target)
302 int retval = ERROR_FAIL;
303 /* check that armv8_cache is correctly identify */
304 struct armv8_common *armv8 = target_to_armv8(target);
305 if (armv8->armv8_mmu.armv8_cache.ctype == -1) {
306 LOG_ERROR("trying to flush un-identified cache");
307 return retval;
310 if (target->smp) {
311 /* look if all the other target have been flushed in order to flush level
312 * 2 */
313 struct target_list *head;
314 struct target *curr;
315 head = target->head;
316 while (head != (struct target_list *)NULL) {
317 curr = head->target;
318 if (curr->state == TARGET_HALTED) {
319 LOG_INFO("Wait flushing data l1 on core %" PRId32, curr->coreid);
320 retval = _armv8_flush_all_data(curr);
322 head = head->next;
324 } else
325 retval = _armv8_flush_all_data(target);
326 return retval;
329 int armv8_handle_cache_info_command(struct command_context *cmd_ctx,
330 struct armv8_cache_common *armv8_cache)
332 if (armv8_cache->ctype == -1) {
333 command_print(cmd_ctx, "cache not yet identified");
334 return ERROR_OK;
337 if (armv8_cache->display_cache_info)
338 armv8_cache->display_cache_info(cmd_ctx, armv8_cache);
339 return ERROR_OK;
342 /* retrieve core id cluster id */
343 static int armv8_read_mpidr(struct target *target)
345 int retval = ERROR_FAIL;
346 struct armv8_common *armv8 = target_to_armv8(target);
347 struct arm_dpm *dpm = armv8->arm.dpm;
348 uint32_t mpidr;
349 retval = dpm->prepare(dpm);
350 if (retval != ERROR_OK)
351 goto done;
352 /* MRC p15,0,<Rd>,c0,c0,5; read Multiprocessor ID register*/
354 retval = dpm->instr_read_data_r0(dpm,
355 ARMV8_MRS(SYSTEM_MPIDR, 0),
356 &mpidr);
357 if (retval != ERROR_OK)
358 goto done;
359 if (mpidr & 1<<31) {
360 armv8->multi_processor_system = (mpidr >> 30) & 1;
361 armv8->cluster_id = (mpidr >> 8) & 0xf;
362 armv8->cpu_id = mpidr & 0x3;
363 LOG_INFO("%s cluster %x core %x %s", target_name(target),
364 armv8->cluster_id,
365 armv8->cpu_id,
366 armv8->multi_processor_system == 0 ? "multi core" : "mono core");
368 } else
369 LOG_ERROR("mpdir not in multiprocessor format");
371 done:
372 dpm->finish(dpm);
373 return retval;
378 int armv8_identify_cache(struct target *target)
380 /* read cache descriptor */
381 int retval = ERROR_FAIL;
382 struct armv8_common *armv8 = target_to_armv8(target);
383 struct arm_dpm *dpm = armv8->arm.dpm;
384 uint32_t cache_selected, clidr;
385 uint32_t cache_i_reg, cache_d_reg;
386 struct armv8_cache_common *cache = &(armv8->armv8_mmu.armv8_cache);
387 if (!armv8->is_armv7r)
388 armv8_read_ttbcr(target);
389 retval = dpm->prepare(dpm);
391 if (retval != ERROR_OK)
392 goto done;
393 /* retrieve CLIDR
394 * mrc p15, 1, r0, c0, c0, 1 @ read clidr */
395 retval = dpm->instr_read_data_r0(dpm,
396 ARMV4_5_MRC(15, 1, 0, 0, 0, 1),
397 &clidr);
398 if (retval != ERROR_OK)
399 goto done;
400 clidr = (clidr & 0x7000000) >> 23;
401 LOG_INFO("number of cache level %" PRIx32, (uint32_t)(clidr / 2));
402 if ((clidr / 2) > 1) {
403 /* FIXME not supported present in cortex A8 and later */
404 /* in cortex A7, A15 */
405 LOG_ERROR("cache l2 present :not supported");
407 /* retrieve selected cache
408 * MRC p15, 2,<Rd>, c0, c0, 0; Read CSSELR */
409 retval = dpm->instr_read_data_r0(dpm,
410 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
411 &cache_selected);
412 if (retval != ERROR_OK)
413 goto done;
415 retval = armv8->arm.mrc(target, 15,
416 2, 0, /* op1, op2 */
417 0, 0, /* CRn, CRm */
418 &cache_selected);
419 if (retval != ERROR_OK)
420 goto done;
421 /* select instruction cache
422 * MCR p15, 2,<Rd>, c0, c0, 0; Write CSSELR
423 * [0] : 1 instruction cache selection , 0 data cache selection */
424 retval = dpm->instr_write_data_r0(dpm,
425 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
427 if (retval != ERROR_OK)
428 goto done;
430 /* read CCSIDR
431 * MRC P15,1,<RT>,C0, C0,0 ;on cortex A9 read CCSIDR
432 * [2:0] line size 001 eight word per line
433 * [27:13] NumSet 0x7f 16KB, 0xff 32Kbytes, 0x1ff 64Kbytes */
434 retval = dpm->instr_read_data_r0(dpm,
435 ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
436 &cache_i_reg);
437 if (retval != ERROR_OK)
438 goto done;
440 /* select data cache*/
441 retval = dpm->instr_write_data_r0(dpm,
442 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
444 if (retval != ERROR_OK)
445 goto done;
447 retval = dpm->instr_read_data_r0(dpm,
448 ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
449 &cache_d_reg);
450 if (retval != ERROR_OK)
451 goto done;
453 /* restore selected cache */
454 dpm->instr_write_data_r0(dpm,
455 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
456 cache_selected);
458 if (retval != ERROR_OK)
459 goto done;
460 dpm->finish(dpm);
462 /* put fake type */
463 cache->d_u_size.linelen = 16 << (cache_d_reg & 0x7);
464 cache->d_u_size.cachesize = (((cache_d_reg >> 13) & 0x7fff)+1)/8;
465 cache->d_u_size.nsets = (cache_d_reg >> 13) & 0x7fff;
466 cache->d_u_size.associativity = ((cache_d_reg >> 3) & 0x3ff) + 1;
467 /* compute info for set way operation on cache */
468 cache->d_u_size.index_shift = (cache_d_reg & 0x7) + 4;
469 cache->d_u_size.index = (cache_d_reg >> 13) & 0x7fff;
470 cache->d_u_size.way = ((cache_d_reg >> 3) & 0x3ff);
471 cache->d_u_size.way_shift = cache->d_u_size.way + 1;
473 int i = 0;
474 while (((cache->d_u_size.way_shift >> i) & 1) != 1)
475 i++;
476 cache->d_u_size.way_shift = 32-i;
478 #if 0
479 LOG_INFO("data cache index %d << %d, way %d << %d",
480 cache->d_u_size.index, cache->d_u_size.index_shift,
481 cache->d_u_size.way,
482 cache->d_u_size.way_shift);
484 LOG_INFO("data cache %d bytes %d KBytes asso %d ways",
485 cache->d_u_size.linelen,
486 cache->d_u_size.cachesize,
487 cache->d_u_size.associativity);
488 #endif
489 cache->i_size.linelen = 16 << (cache_i_reg & 0x7);
490 cache->i_size.associativity = ((cache_i_reg >> 3) & 0x3ff) + 1;
491 cache->i_size.nsets = (cache_i_reg >> 13) & 0x7fff;
492 cache->i_size.cachesize = (((cache_i_reg >> 13) & 0x7fff)+1)/8;
493 /* compute info for set way operation on cache */
494 cache->i_size.index_shift = (cache_i_reg & 0x7) + 4;
495 cache->i_size.index = (cache_i_reg >> 13) & 0x7fff;
496 cache->i_size.way = ((cache_i_reg >> 3) & 0x3ff);
497 cache->i_size.way_shift = cache->i_size.way + 1;
499 int i = 0;
500 while (((cache->i_size.way_shift >> i) & 1) != 1)
501 i++;
502 cache->i_size.way_shift = 32-i;
504 #if 0
505 LOG_INFO("instruction cache index %d << %d, way %d << %d",
506 cache->i_size.index, cache->i_size.index_shift,
507 cache->i_size.way, cache->i_size.way_shift);
509 LOG_INFO("instruction cache %d bytes %d KBytes asso %d ways",
510 cache->i_size.linelen,
511 cache->i_size.cachesize,
512 cache->i_size.associativity);
513 #endif
514 /* if no l2 cache initialize l1 data cache flush function function */
515 if (armv8->armv8_mmu.armv8_cache.flush_all_data_cache == NULL) {
516 armv8->armv8_mmu.armv8_cache.display_cache_info =
517 armv8_handle_inner_cache_info_command;
518 armv8->armv8_mmu.armv8_cache.flush_all_data_cache =
519 armv8_flush_all_data;
521 armv8->armv8_mmu.armv8_cache.ctype = 0;
523 done:
524 dpm->finish(dpm);
525 armv8_read_mpidr(target);
526 return retval;
530 int armv8_init_arch_info(struct target *target, struct armv8_common *armv8)
532 struct arm *arm = &armv8->arm;
533 arm->arch_info = armv8;
534 target->arch_info = &armv8->arm;
535 /* target is useful in all function arm v4 5 compatible */
536 armv8->arm.target = target;
537 armv8->arm.common_magic = ARM_COMMON_MAGIC;
538 armv8->common_magic = ARMV8_COMMON_MAGIC;
540 arm->read_core_reg = armv8_read_core_reg;
541 #if 0
542 arm->write_core_reg = armv8_write_core_reg;
543 #endif
545 armv8->armv8_mmu.armv8_cache.l2_cache = NULL;
546 armv8->armv8_mmu.armv8_cache.ctype = -1;
547 armv8->armv8_mmu.armv8_cache.flush_all_data_cache = NULL;
548 armv8->armv8_mmu.armv8_cache.display_cache_info = NULL;
549 return ERROR_OK;
552 int armv8_arch_state(struct target *target)
554 static const char * const state[] = {
555 "disabled", "enabled"
558 struct armv8_common *armv8 = target_to_armv8(target);
559 struct arm *arm = &armv8->arm;
561 if (armv8->common_magic != ARMV8_COMMON_MAGIC) {
562 LOG_ERROR("BUG: called for a non-Armv8 target");
563 return ERROR_COMMAND_SYNTAX_ERROR;
566 arm_arch_state(target);
568 if (armv8->is_armv7r) {
569 LOG_USER("D-Cache: %s, I-Cache: %s",
570 state[armv8->armv8_mmu.armv8_cache.d_u_cache_enabled],
571 state[armv8->armv8_mmu.armv8_cache.i_cache_enabled]);
572 } else {
573 LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
574 state[armv8->armv8_mmu.mmu_enabled],
575 state[armv8->armv8_mmu.armv8_cache.d_u_cache_enabled],
576 state[armv8->armv8_mmu.armv8_cache.i_cache_enabled]);
579 if (arm->core_mode == ARM_MODE_ABT)
580 armv8_show_fault_registers(target);
581 if (target->debug_reason == DBG_REASON_WATCHPOINT)
582 LOG_USER("Watchpoint triggered at PC %#08x",
583 (unsigned) armv8->dpm.wp_pc);
585 return ERROR_OK;
588 static const struct {
589 unsigned id;
590 const char *name;
591 unsigned bits;
592 enum reg_type type;
593 const char *group;
594 const char *feature;
595 } armv8_regs[] = {
596 { ARMV8_R0, "x0", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
597 { ARMV8_R1, "x1", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
598 { ARMV8_R2, "x2", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
599 { ARMV8_R3, "x3", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
600 { ARMV8_R4, "x4", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
601 { ARMV8_R5, "x5", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
602 { ARMV8_R6, "x6", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
603 { ARMV8_R7, "x7", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
604 { ARMV8_R8, "x8", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
605 { ARMV8_R9, "x9", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
606 { ARMV8_R10, "x10", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
607 { ARMV8_R11, "x11", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
608 { ARMV8_R12, "x12", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
609 { ARMV8_R13, "x13", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
610 { ARMV8_R14, "x14", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
611 { ARMV8_R15, "x15", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
612 { ARMV8_R16, "x16", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
613 { ARMV8_R17, "x17", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
614 { ARMV8_R18, "x18", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
615 { ARMV8_R19, "x19", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
616 { ARMV8_R20, "x20", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
617 { ARMV8_R21, "x21", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
618 { ARMV8_R22, "x22", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
619 { ARMV8_R23, "x23", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
620 { ARMV8_R24, "x24", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
621 { ARMV8_R25, "x25", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
622 { ARMV8_R26, "x26", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
623 { ARMV8_R27, "x27", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
624 { ARMV8_R28, "x28", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
625 { ARMV8_R29, "x29", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
626 { ARMV8_R30, "x30", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
628 { ARMV8_R31, "sp", 64, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.aarch64.core" },
629 { ARMV8_PC, "pc", 64, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.aarch64.core" },
631 { ARMV8_xPSR, "CPSR", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
634 #define ARMV8_NUM_REGS ARRAY_SIZE(armv8_regs)
637 static int armv8_get_core_reg(struct reg *reg)
639 int retval;
640 struct arm_reg *armv8_reg = reg->arch_info;
641 struct target *target = armv8_reg->target;
642 struct arm *arm = target_to_arm(target);
644 if (target->state != TARGET_HALTED)
645 return ERROR_TARGET_NOT_HALTED;
647 retval = arm->read_core_reg(target, reg, armv8_reg->num, arm->core_mode);
649 return retval;
652 static int armv8_set_core_reg(struct reg *reg, uint8_t *buf)
654 struct arm_reg *armv8_reg = reg->arch_info;
655 struct target *target = armv8_reg->target;
656 uint64_t value = buf_get_u64(buf, 0, 64);
658 if (target->state != TARGET_HALTED)
659 return ERROR_TARGET_NOT_HALTED;
661 buf_set_u64(reg->value, 0, 64, value);
662 reg->dirty = 1;
663 reg->valid = 1;
665 return ERROR_OK;
668 static const struct reg_arch_type armv8_reg_type = {
669 .get = armv8_get_core_reg,
670 .set = armv8_set_core_reg,
673 /** Builds cache of architecturally defined registers. */
674 struct reg_cache *armv8_build_reg_cache(struct target *target)
676 struct armv8_common *armv8 = target_to_armv8(target);
677 struct arm *arm = &armv8->arm;
678 int num_regs = ARMV8_NUM_REGS;
679 struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
680 struct reg_cache *cache = malloc(sizeof(struct reg_cache));
681 struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
682 struct arm_reg *arch_info = calloc(num_regs, sizeof(struct arm_reg));
683 struct reg_feature *feature;
684 int i;
686 /* Build the process context cache */
687 cache->name = "arm v8 registers";
688 cache->next = NULL;
689 cache->reg_list = reg_list;
690 cache->num_regs = num_regs;
691 (*cache_p) = cache;
693 for (i = 0; i < num_regs; i++) {
694 arch_info[i].num = armv8_regs[i].id;
695 arch_info[i].target = target;
696 arch_info[i].arm = arm;
698 reg_list[i].name = armv8_regs[i].name;
699 reg_list[i].size = armv8_regs[i].bits;
700 reg_list[i].value = calloc(1, 4);
701 reg_list[i].dirty = 0;
702 reg_list[i].valid = 0;
703 reg_list[i].type = &armv8_reg_type;
704 reg_list[i].arch_info = &arch_info[i];
706 reg_list[i].group = armv8_regs[i].group;
707 reg_list[i].number = i;
708 reg_list[i].exist = true;
709 reg_list[i].caller_save = true; /* gdb defaults to true */
711 feature = calloc(1, sizeof(struct reg_feature));
712 if (feature) {
713 feature->name = armv8_regs[i].feature;
714 reg_list[i].feature = feature;
715 } else
716 LOG_ERROR("unable to allocate feature list");
718 reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
719 if (reg_list[i].reg_data_type)
720 reg_list[i].reg_data_type->type = armv8_regs[i].type;
721 else
722 LOG_ERROR("unable to allocate reg type list");
725 arm->cpsr = reg_list + ARMV8_xPSR;
726 arm->pc = reg_list + ARMV8_PC;
727 arm->core_cache = cache;
729 return cache;
732 struct reg *armv8_reg_current(struct arm *arm, unsigned regnum)
734 struct reg *r;
736 if (regnum > 33)
737 return NULL;
739 r = arm->core_cache->reg_list + regnum;
740 return r;
743 const struct command_registration armv8_command_handlers[] = {
745 .chain = dap_command_handlers,
747 COMMAND_REGISTRATION_DONE
751 int armv8_get_gdb_reg_list(struct target *target,
752 struct reg **reg_list[], int *reg_list_size,
753 enum target_register_class reg_class)
755 struct arm *arm = target_to_arm(target);
756 int i;
758 switch (reg_class) {
759 case REG_CLASS_GENERAL:
760 case REG_CLASS_ALL:
761 *reg_list_size = 34;
762 *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
764 for (i = 0; i < *reg_list_size; i++)
765 (*reg_list)[i] = armv8_reg_current(arm, i);
767 return ERROR_OK;
768 break;
770 default:
771 LOG_ERROR("not a valid register class type in query.");
772 return ERROR_FAIL;
773 break;