e516518ad4faf5f8eb23cfe21c13991eb9253845
[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 "armv8_opcodes.h"
37 #include "arm_opcodes.h"
38 #include "target.h"
39 #include "target_type.h"
40
41 static int armv8_read_core_reg(struct target *target, struct reg *r,
42 int num, enum arm_mode mode)
43 {
44 uint64_t reg_value;
45 int retval;
46 struct arm_reg *armv8_core_reg;
47 struct armv8_common *armv8 = target_to_armv8(target);
48
49 assert(num < (int)armv8->arm.core_cache->num_regs);
50
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);
54
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;
58
59 return retval;
60 }
61
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)
65 {
66 int retval;
67 struct arm_reg *armv8_core_reg;
68 struct armv8_common *armv8 = target_to_armv8(target);
69
70 assert(num < (int)armv8->arm.core_cache->num_regs);
71
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;
80 }
81
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;
85
86 return ERROR_OK;
87 }
88 #endif
89
90 static void armv8_show_fault_registers(struct target *target)
91 {
92 /* TODO */
93 }
94
95 static int armv8_read_ttbcr(struct target *target)
96 {
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;
123 }
124 done:
125 dpm->finish(dpm);
126 return retval;
127 }
128
129
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)
132 {
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;
145 }
146 retval = dpm->prepare(dpm);
147 if (retval != ERROR_OK)
148 goto done;
149
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);
165
166 if ((first_lvl_descriptor & 0x3) == 0) {
167 LOG_ERROR("Address translation failure");
168 return ERROR_TARGET_TRANSLATION_FAULT;
169 }
170
171
172 if ((first_lvl_descriptor & 0x3) == 2) {
173 /* section descriptor */
174 *val = (first_lvl_descriptor & 0xfff00000) | (va & 0x000fffff);
175 return ERROR_OK;
176 }
177
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;
192 }
193
194 second_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *)
195 &second_lvl_descriptor);
196
197 LOG_DEBUG("2nd lvl desc: %8.8" PRIx32 "", second_lvl_descriptor);
198
199 if ((second_lvl_descriptor & 0x3) == 0) {
200 LOG_ERROR("Address translation failure");
201 return ERROR_TARGET_TRANSLATION_FAULT;
202 }
203
204 if ((second_lvl_descriptor & 0x3) == 1) {
205 /* large page descriptor */
206 *val = (second_lvl_descriptor & 0xffff0000) | (va & 0x0000ffff);
207 return ERROR_OK;
208 }
209
210 if ((second_lvl_descriptor & 0x3) == 2) {
211 /* small page descriptor */
212 *val = (second_lvl_descriptor & 0xfffff000) | (va & 0x00000fff);
213 return ERROR_OK;
214 }
215
216 if ((second_lvl_descriptor & 0x3) == 3) {
217 *val = (second_lvl_descriptor & 0xfffffc00) | (va & 0x000003ff);
218 return ERROR_OK;
219 }
220
221 /* should not happen */
222 LOG_ERROR("Address translation failure");
223 return ERROR_TARGET_TRANSLATION_FAULT;
224
225 done:
226 return retval;
227 }
228
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)
232 {
233 return ERROR_OK;
234 }
235
236 static int armv8_handle_inner_cache_info_command(struct command_context *cmd_ctx,
237 struct armv8_cache_common *armv8_cache)
238 {
239 if (armv8_cache->ctype == -1) {
240 command_print(cmd_ctx, "cache not yet identified");
241 return ERROR_OK;
242 }
243
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);
250
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);
257
258 return ERROR_OK;
259 }
260
261 static int _armv8_flush_all_data(struct target *target)
262 {
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;
273 }
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;
298 }
299
300 static int armv8_flush_all_data(struct target *target)
301 {
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;
308 }
309
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);
321 }
322 head = head->next;
323 }
324 } else
325 retval = _armv8_flush_all_data(target);
326 return retval;
327 }
328
329 int armv8_handle_cache_info_command(struct command_context *cmd_ctx,
330 struct armv8_cache_common *armv8_cache)
331 {
332 if (armv8_cache->ctype == -1) {
333 command_print(cmd_ctx, "cache not yet identified");
334 return ERROR_OK;
335 }
336
337 if (armv8_cache->display_cache_info)
338 armv8_cache->display_cache_info(cmd_ctx, armv8_cache);
339 return ERROR_OK;
340 }
341
342 /* retrieve core id cluster id */
343 static int armv8_read_mpidr(struct target *target)
344 {
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*/
353
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");
367
368 } else
369 LOG_ERROR("mpdir not in multiprocessor format");
370
371 done:
372 dpm->finish(dpm);
373 return retval;
374
375
376 }
377
378 int armv8_identify_cache(struct target *target)
379 {
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);
390
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");
406 }
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;
414
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),
426 1);
427 if (retval != ERROR_OK)
428 goto done;
429
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;
439
440 /* select data cache*/
441 retval = dpm->instr_write_data_r0(dpm,
442 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
443 0);
444 if (retval != ERROR_OK)
445 goto done;
446
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;
452
453 /* restore selected cache */
454 dpm->instr_write_data_r0(dpm,
455 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
456 cache_selected);
457
458 if (retval != ERROR_OK)
459 goto done;
460 dpm->finish(dpm);
461
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;
472 {
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;
477 }
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);
483
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;
498 {
499 int i = 0;
500 while (((cache->i_size.way_shift >> i) & 1) != 1)
501 i++;
502 cache->i_size.way_shift = 32-i;
503 }
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);
508
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;
520 }
521 armv8->armv8_mmu.armv8_cache.ctype = 0;
522
523 done:
524 dpm->finish(dpm);
525 armv8_read_mpidr(target);
526 return retval;
527
528 }
529
530 int armv8_init_arch_info(struct target *target, struct armv8_common *armv8)
531 {
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;
539
540 arm->read_core_reg = armv8_read_core_reg;
541 #if 0
542 arm->write_core_reg = armv8_write_core_reg;
543 #endif
544
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;
550 }
551
552 int armv8_arch_state(struct target *target)
553 {
554 static const char * const state[] = {
555 "disabled", "enabled"
556 };
557
558 struct armv8_common *armv8 = target_to_armv8(target);
559 struct arm *arm = &armv8->arm;
560
561 if (armv8->common_magic != ARMV8_COMMON_MAGIC) {
562 LOG_ERROR("BUG: called for a non-Armv8 target");
563 return ERROR_COMMAND_SYNTAX_ERROR;
564 }
565
566 arm_arch_state(target);
567
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]);
577 }
578
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);
584
585 return ERROR_OK;
586 }
587
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" },
627
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" },
630
631 { ARMV8_xPSR, "CPSR", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
632 };
633
634 #define ARMV8_NUM_REGS ARRAY_SIZE(armv8_regs)
635
636
637 static int armv8_get_core_reg(struct reg *reg)
638 {
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);
643
644 if (target->state != TARGET_HALTED)
645 return ERROR_TARGET_NOT_HALTED;
646
647 retval = arm->read_core_reg(target, reg, armv8_reg->num, arm->core_mode);
648
649 return retval;
650 }
651
652 static int armv8_set_core_reg(struct reg *reg, uint8_t *buf)
653 {
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);
657
658 if (target->state != TARGET_HALTED)
659 return ERROR_TARGET_NOT_HALTED;
660
661 buf_set_u64(reg->value, 0, 64, value);
662 reg->dirty = 1;
663 reg->valid = 1;
664
665 return ERROR_OK;
666 }
667
668 static const struct reg_arch_type armv8_reg_type = {
669 .get = armv8_get_core_reg,
670 .set = armv8_set_core_reg,
671 };
672
673 /** Builds cache of architecturally defined registers. */
674 struct reg_cache *armv8_build_reg_cache(struct target *target)
675 {
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;
685
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;
692
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;
697
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];
705
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 */
710
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");
717
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");
723 }
724
725 arm->cpsr = reg_list + ARMV8_xPSR;
726 arm->pc = reg_list + ARMV8_PC;
727 arm->core_cache = cache;
728
729 return cache;
730 }
731
732 struct reg *armv8_reg_current(struct arm *arm, unsigned regnum)
733 {
734 struct reg *r;
735
736 if (regnum > 33)
737 return NULL;
738
739 r = arm->core_cache->reg_list + regnum;
740 return r;
741 }
742
743 const struct command_registration armv8_command_handlers[] = {
744 {
745 .chain = dap_command_handlers,
746 },
747 COMMAND_REGISTRATION_DONE
748 };
749
750
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)
754 {
755 struct arm *arm = target_to_arm(target);
756 int i;
757
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));
763
764 for (i = 0; i < *reg_list_size; i++)
765 (*reg_list)[i] = armv8_reg_current(arm, i);
766
767 return ERROR_OK;
768 break;
769
770 default:
771 LOG_ERROR("not a valid register class type in query.");
772 return ERROR_FAIL;
773 break;
774 }
775 }

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)