aarch64: Add ARMv8 AARCH64 support files
[openocd.git] / src / target / armv8.c
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 ***************************************************************************/
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include <helper/replacements.h>
24
25 #include "armv8.h"
26 #include "arm_disassembler.h"
27
28 #include "register.h"
29 #include <helper/binarybuffer.h>
30 #include <helper/command.h>
31
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35
36 #include "arm_opcodes.h"
37 #include "target.h"
38 #include "target_type.h"
39
40 static int armv8_read_core_reg(struct target *target, struct reg *r,
41 int num, enum arm_mode mode)
42 {
43 uint64_t reg_value;
44 int retval;
45 struct arm_reg *armv8_core_reg;
46 struct armv8_common *armv8 = target_to_armv8(target);
47
48 assert(num < (int)armv8->arm.core_cache->num_regs);
49
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, &reg_value);
53
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;
57
58 return retval;
59 }
60
61 #if 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)
64 {
65 int retval;
66 struct arm_reg *armv8_core_reg;
67 struct armv8_common *armv8 = target_to_armv8(target);
68
69 assert(num < (int)armv8->arm.core_cache->num_regs);
70
71 armv8_core_reg = armv8->arm.core_cache->reg_list[num].arch_info;
72 retval = armv8->store_core_reg_u64(target,
73 armv8_core_reg->num,
74 value);
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;
79 }
80
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;
84
85 return ERROR_OK;
86 }
87 #endif
88
89 static void armv8_show_fault_registers(struct target *target)
90 {
91 /* TODO */
92 }
93
94 static int armv8_read_ttbcr(struct target *target)
95 {
96 struct armv8_common *armv8 = target_to_armv8(target);
97 struct arm_dpm *dpm = armv8->arm.dpm;
98 uint32_t ttbcr;
99 int retval = dpm->prepare(dpm);
100 if (retval != ERROR_OK)
101 goto done;
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),
105 &ttbcr);
106 if (retval != ERROR_OK)
107 goto done;
108 armv8->armv8_mmu.ttbr1_used = ((ttbcr & 0x7) != 0) ? 1 : 0;
109 armv8->armv8_mmu.ttbr0_mask = 7 << (32 - ((ttbcr & 0x7)));
110 #if 0
111 LOG_INFO("ttb1 %s ,ttb0_mask %x",
112 armv8->armv8_mmu.ttbr1_used ? "used" : "not used",
113 armv8->armv8_mmu.ttbr0_mask);
114 #endif
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;
119 } else {
120 /* fix me , default is hard coded LINUX border */
121 armv8->armv8_mmu.os_border = 0xc0000000;
122 }
123 done:
124 dpm->finish(dpm);
125 return retval;
126 }
127
128
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)
131 {
132 uint32_t first_lvl_descriptor = 0x0;
133 uint32_t second_lvl_descriptor = 0x0;
134 int retval;
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))) {
142 /* select ttb 1 */
143 ttb = 1;
144 }
145 retval = dpm->prepare(dpm);
146 if (retval != ERROR_OK)
147 goto done;
148
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),
152 &ttb);
153 if (retval != ERROR_OK)
154 return retval;
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)
159 return retval;
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);
164
165 if ((first_lvl_descriptor & 0x3) == 0) {
166 LOG_ERROR("Address translation failure");
167 return ERROR_TARGET_TRANSLATION_FAULT;
168 }
169
170
171 if ((first_lvl_descriptor & 0x3) == 2) {
172 /* section descriptor */
173 *val = (first_lvl_descriptor & 0xfff00000) | (va & 0x000fffff);
174 return ERROR_OK;
175 }
176
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)
183 return retval;
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)
190 return retval;
191 }
192
193 second_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *)
194 &second_lvl_descriptor);
195
196 LOG_DEBUG("2nd lvl desc: %8.8" PRIx32 "", second_lvl_descriptor);
197
198 if ((second_lvl_descriptor & 0x3) == 0) {
199 LOG_ERROR("Address translation failure");
200 return ERROR_TARGET_TRANSLATION_FAULT;
201 }
202
203 if ((second_lvl_descriptor & 0x3) == 1) {
204 /* large page descriptor */
205 *val = (second_lvl_descriptor & 0xffff0000) | (va & 0x0000ffff);
206 return ERROR_OK;
207 }
208
209 if ((second_lvl_descriptor & 0x3) == 2) {
210 /* small page descriptor */
211 *val = (second_lvl_descriptor & 0xfffff000) | (va & 0x00000fff);
212 return ERROR_OK;
213 }
214
215 if ((second_lvl_descriptor & 0x3) == 3) {
216 *val = (second_lvl_descriptor & 0xfffffc00) | (va & 0x000003ff);
217 return ERROR_OK;
218 }
219
220 /* should not happen */
221 LOG_ERROR("Address translation failure");
222 return ERROR_TARGET_TRANSLATION_FAULT;
223
224 done:
225 return retval;
226 }
227
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)
231 {
232 return ERROR_OK;
233 }
234
235 static int armv8_handle_inner_cache_info_command(struct command_context *cmd_ctx,
236 struct armv8_cache_common *armv8_cache)
237 {
238 if (armv8_cache->ctype == -1) {
239 command_print(cmd_ctx, "cache not yet identified");
240 return ERROR_OK;
241 }
242
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);
249
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);
256
257 return ERROR_OK;
258 }
259
260 static int _armv8_flush_all_data(struct target *target)
261 {
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;
267 int retval;
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");
271 return ERROR_OK;
272 }
273 retval = dpm->prepare(dpm);
274 if (retval != ERROR_OK)
275 goto done;
276 do {
277 c_way = d_u_size->way;
278 do {
279 uint32_t value = (c_index << d_u_size->index_shift)
280 | (c_way << d_u_size->way_shift);
281 /* DCCISW */
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),
285 value);
286 if (retval != ERROR_OK)
287 goto done;
288 c_way -= 1;
289 } while (c_way >= 0);
290 c_index -= 1;
291 } while (c_index >= 0);
292 return retval;
293 done:
294 LOG_ERROR("flushed failed");
295 dpm->finish(dpm);
296 return retval;
297 }
298
299 static int armv8_flush_all_data(struct target *target)
300 {
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");
306 return retval;
307 }
308
309 if (target->smp) {
310 /* look if all the other target have been flushed in order to flush level
311 * 2 */
312 struct target_list *head;
313 struct target *curr;
314 head = target->head;
315 while (head != (struct target_list *)NULL) {
316 curr = head->target;
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);
320 }
321 head = head->next;
322 }
323 } else
324 retval = _armv8_flush_all_data(target);
325 return retval;
326 }
327
328 int armv8_handle_cache_info_command(struct command_context *cmd_ctx,
329 struct armv8_cache_common *armv8_cache)
330 {
331 if (armv8_cache->ctype == -1) {
332 command_print(cmd_ctx, "cache not yet identified");
333 return ERROR_OK;
334 }
335
336 if (armv8_cache->display_cache_info)
337 armv8_cache->display_cache_info(cmd_ctx, armv8_cache);
338 return ERROR_OK;
339 }
340
341 /* retrieve core id cluster id */
342 static int armv8_read_mpidr(struct target *target)
343 {
344 int retval = ERROR_FAIL;
345 struct armv8_common *armv8 = target_to_armv8(target);
346 struct arm_dpm *dpm = armv8->arm.dpm;
347 uint32_t mpidr;
348 retval = dpm->prepare(dpm);
349 if (retval != ERROR_OK)
350 goto done;
351 /* MRC p15,0,<Rd>,c0,c0,5; read Multiprocessor ID register*/
352
353 retval = dpm->instr_read_data_r0(dpm,
354 ARMV4_5_MRC(15, 0, 0, 0, 0, 5),
355 &mpidr);
356 if (retval != ERROR_OK)
357 goto done;
358 if (mpidr & 1<<31) {
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),
363 armv8->cluster_id,
364 armv8->cpu_id,
365 armv8->multi_processor_system == 0 ? "multi core" : "mono core");
366
367 } else
368 LOG_ERROR("mpdir not in multiprocessor format");
369
370 done:
371 dpm->finish(dpm);
372 return retval;
373
374
375 }
376
377 int armv8_identify_cache(struct target *target)
378 {
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);
389
390 if (retval != ERROR_OK)
391 goto done;
392 /* retrieve CLIDR
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),
396 &clidr);
397 if (retval != ERROR_OK)
398 goto done;
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");
405 }
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),
410 &cache_selected);
411 if (retval != ERROR_OK)
412 goto done;
413
414 retval = armv8->arm.mrc(target, 15,
415 2, 0, /* op1, op2 */
416 0, 0, /* CRn, CRm */
417 &cache_selected);
418 if (retval != ERROR_OK)
419 goto done;
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),
425 1);
426 if (retval != ERROR_OK)
427 goto done;
428
429 /* read CCSIDR
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),
435 &cache_i_reg);
436 if (retval != ERROR_OK)
437 goto done;
438
439 /* select data cache*/
440 retval = dpm->instr_write_data_r0(dpm,
441 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
442 0);
443 if (retval != ERROR_OK)
444 goto done;
445
446 retval = dpm->instr_read_data_r0(dpm,
447 ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
448 &cache_d_reg);
449 if (retval != ERROR_OK)
450 goto done;
451
452 /* restore selected cache */
453 dpm->instr_write_data_r0(dpm,
454 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
455 cache_selected);
456
457 if (retval != ERROR_OK)
458 goto done;
459 dpm->finish(dpm);
460
461 /* put fake type */
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;
471 {
472 int i = 0;
473 while (((cache->d_u_size.way_shift >> i) & 1) != 1)
474 i++;
475 cache->d_u_size.way_shift = 32-i;
476 }
477 #if 0
478 LOG_INFO("data cache index %d << %d, way %d << %d",
479 cache->d_u_size.index, cache->d_u_size.index_shift,
480 cache->d_u_size.way,
481 cache->d_u_size.way_shift);
482
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);
487 #endif
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;
497 {
498 int i = 0;
499 while (((cache->i_size.way_shift >> i) & 1) != 1)
500 i++;
501 cache->i_size.way_shift = 32-i;
502 }
503 #if 0
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);
507
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);
512 #endif
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;
519 }
520 armv8->armv8_mmu.armv8_cache.ctype = 0;
521
522 done:
523 dpm->finish(dpm);
524 armv8_read_mpidr(target);
525 return retval;
526
527 }
528
529 int armv8_init_arch_info(struct target *target, struct armv8_common *armv8)
530 {
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;
538
539 arm->read_core_reg = armv8_read_core_reg;
540 #if 0
541 arm->write_core_reg = armv8_write_core_reg;
542 #endif
543
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;
548 return ERROR_OK;
549 }
550
551 int armv8_arch_state(struct target *target)
552 {
553 static const char * const state[] = {
554 "disabled", "enabled"
555 };
556
557 struct armv8_common *armv8 = target_to_armv8(target);
558 struct arm *arm = &armv8->arm;
559
560 if (armv8->common_magic != ARMV8_COMMON_MAGIC) {
561 LOG_ERROR("BUG: called for a non-Armv8 target");
562 return ERROR_COMMAND_SYNTAX_ERROR;
563 }
564
565 arm_arch_state(target);
566
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]);
571 } else {
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]);
576 }
577
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);
583
584 return ERROR_OK;
585 }
586
587 static const struct {
588 unsigned id;
589 const char *name;
590 unsigned bits;
591 enum reg_type type;
592 const char *group;
593 const char *feature;
594 } armv8_regs[] = {
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" },
626
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" },
629
630 { ARMV8_xPSR, "CPSR", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
631 };
632
633 #define ARMV8_NUM_REGS ARRAY_SIZE(armv8_regs)
634
635
636 static int armv8_get_core_reg(struct reg *reg)
637 {
638 int retval;
639 struct arm_reg *armv8_reg = reg->arch_info;
640 struct target *target = armv8_reg->target;
641 struct arm *arm = target_to_arm(target);
642
643 if (target->state != TARGET_HALTED)
644 return ERROR_TARGET_NOT_HALTED;
645
646 retval = arm->read_core_reg(target, reg, armv8_reg->num, arm->core_mode);
647
648 return retval;
649 }
650
651 static int armv8_set_core_reg(struct reg *reg, uint8_t *buf)
652 {
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);
656
657 if (target->state != TARGET_HALTED)
658 return ERROR_TARGET_NOT_HALTED;
659
660 buf_set_u64(reg->value, 0, 64, value);
661 reg->dirty = 1;
662 reg->valid = 1;
663
664 return ERROR_OK;
665 }
666
667 static const struct reg_arch_type armv8_reg_type = {
668 .get = armv8_get_core_reg,
669 .set = armv8_set_core_reg,
670 };
671
672 /** Builds cache of architecturally defined registers. */
673 struct reg_cache *armv8_build_reg_cache(struct target *target)
674 {
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;
683 int i;
684
685 /* Build the process context cache */
686 cache->name = "arm v8 registers";
687 cache->next = NULL;
688 cache->reg_list = reg_list;
689 cache->num_regs = num_regs;
690 (*cache_p) = cache;
691
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;
696
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];
704
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 */
709
710 feature = calloc(1, sizeof(struct reg_feature));
711 if (feature) {
712 feature->name = armv8_regs[i].feature;
713 reg_list[i].feature = feature;
714 } else
715 LOG_ERROR("unable to allocate feature list");
716
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;
720 else
721 LOG_ERROR("unable to allocate reg type list");
722 }
723
724 arm->cpsr = reg_list + ARMV8_xPSR;
725 arm->pc = reg_list + ARMV8_PC;
726 arm->core_cache = cache;
727
728 return cache;
729 }
730
731 struct reg *armv8_reg_current(struct arm *arm, unsigned regnum)
732 {
733 struct reg *r;
734
735 if (regnum > 33)
736 return NULL;
737
738 r = arm->core_cache->reg_list + regnum;
739 return r;
740 }
741
742 const struct command_registration armv8_command_handlers[] = {
743 {
744 .chain = dap_command_handlers,
745 },
746 COMMAND_REGISTRATION_DONE
747 };
748
749
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)
753 {
754 struct arm *arm = target_to_arm(target);
755 int i;
756
757 switch (reg_class) {
758 case REG_CLASS_GENERAL:
759 case REG_CLASS_ALL:
760 *reg_list_size = 34;
761 *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
762
763 for (i = 0; i < *reg_list_size; i++)
764 (*reg_list)[i] = armv8_reg_current(arm, i);
765
766 return ERROR_OK;
767 break;
768
769 default:
770 LOG_ERROR("not a valid register class type in query.");
771 return ERROR_FAIL;
772 break;
773 }
774 }

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)