aarch64: correct display for aarch64 state
[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 const char * const armv8_state_strings[] = {
42 "ARM", "Thumb", "Jazelle", "ThumbEE", "ARM64",
43 };
44
45 static const struct {
46 const char *name;
47 unsigned psr;
48 /* For user and system modes, these list indices for all registers.
49 * otherwise they're just indices for the shadow registers and SPSR.
50 */
51 unsigned short n_indices;
52 const uint8_t *indices;
53 } armv8_mode_data[] = {
54 /* These special modes are currently only supported
55 * by ARMv6M and ARMv7M profiles */
56 {
57 .name = "EL0T",
58 .psr = ARMV8_64_EL0T,
59 },
60 {
61 .name = "EL1T",
62 .psr = ARMV8_64_EL1T,
63 },
64 {
65 .name = "EL1H",
66 .psr = ARMV8_64_EL1H,
67 },
68 {
69 .name = "EL2T",
70 .psr = ARMV8_64_EL2T,
71 },
72 {
73 .name = "EL2H",
74 .psr = ARMV8_64_EL2H,
75 },
76 {
77 .name = "EL3T",
78 .psr = ARMV8_64_EL3T,
79 },
80 {
81 .name = "EL3H",
82 .psr = ARMV8_64_EL3H,
83 },
84 };
85
86 /** Map PSR mode bits to the name of an ARM processor operating mode. */
87 const char *armv8_mode_name(unsigned psr_mode)
88 {
89 for (unsigned i = 0; i < ARRAY_SIZE(armv8_mode_data); i++) {
90 if (armv8_mode_data[i].psr == psr_mode)
91 return armv8_mode_data[i].name;
92 }
93 LOG_ERROR("unrecognized psr mode: %#02x", psr_mode);
94 return "UNRECOGNIZED";
95 }
96
97 int armv8_mode_to_number(enum arm_mode mode)
98 {
99 switch (mode) {
100 case ARM_MODE_ANY:
101 /* map MODE_ANY to user mode */
102 case ARM_MODE_USR:
103 return 0;
104 case ARM_MODE_FIQ:
105 return 1;
106 case ARM_MODE_IRQ:
107 return 2;
108 case ARM_MODE_SVC:
109 return 3;
110 case ARM_MODE_ABT:
111 return 4;
112 case ARM_MODE_UND:
113 return 5;
114 case ARM_MODE_SYS:
115 return 6;
116 case ARM_MODE_MON:
117 return 7;
118 case ARMV8_64_EL0T:
119 return 8;
120 case ARMV8_64_EL1T:
121 return 9;
122 case ARMV8_64_EL1H:
123 return 10;
124 case ARMV8_64_EL2T:
125 return 11;
126 case ARMV8_64_EL2H:
127 return 12;
128 case ARMV8_64_EL3T:
129 return 13;
130 case ARMV8_64_EL3H:
131 return 14;
132
133 default:
134 LOG_ERROR("invalid mode value encountered %d", mode);
135 return -1;
136 }
137 }
138
139
140 static int armv8_read_core_reg(struct target *target, struct reg *r,
141 int num, enum arm_mode mode)
142 {
143 uint64_t reg_value;
144 int retval;
145 struct arm_reg *armv8_core_reg;
146 struct armv8_common *armv8 = target_to_armv8(target);
147
148 assert(num < (int)armv8->arm.core_cache->num_regs);
149
150 armv8_core_reg = armv8->arm.core_cache->reg_list[num].arch_info;
151 retval = armv8->load_core_reg_u64(target,
152 armv8_core_reg->num, &reg_value);
153
154 buf_set_u64(armv8->arm.core_cache->reg_list[num].value, 0, 64, reg_value);
155 armv8->arm.core_cache->reg_list[num].valid = 1;
156 armv8->arm.core_cache->reg_list[num].dirty = 0;
157
158 return retval;
159 }
160
161 #if 0
162 static int armv8_write_core_reg(struct target *target, struct reg *r,
163 int num, enum arm_mode mode, target_addr_t value)
164 {
165 int retval;
166 struct arm_reg *armv8_core_reg;
167 struct armv8_common *armv8 = target_to_armv8(target);
168
169 assert(num < (int)armv8->arm.core_cache->num_regs);
170
171 armv8_core_reg = armv8->arm.core_cache->reg_list[num].arch_info;
172 retval = armv8->store_core_reg_u64(target,
173 armv8_core_reg->num,
174 value);
175 if (retval != ERROR_OK) {
176 LOG_ERROR("JTAG failure");
177 armv8->arm.core_cache->reg_list[num].dirty = armv8->arm.core_cache->reg_list[num].valid;
178 return ERROR_JTAG_DEVICE_ERROR;
179 }
180
181 LOG_DEBUG("write core reg %i value 0x%" PRIx64 "", num, value);
182 armv8->arm.core_cache->reg_list[num].valid = 1;
183 armv8->arm.core_cache->reg_list[num].dirty = 0;
184
185 return ERROR_OK;
186 }
187 #endif
188 /**
189 * Configures host-side ARM records to reflect the specified CPSR.
190 * Later, code can use arm_reg_current() to map register numbers
191 * according to how they are exposed by this mode.
192 */
193 void armv8_set_cpsr(struct arm *arm, uint32_t cpsr)
194 {
195 uint32_t mode = cpsr & 0x1F;
196
197 /* NOTE: this may be called very early, before the register
198 * cache is set up. We can't defend against many errors, in
199 * particular against CPSRs that aren't valid *here* ...
200 */
201 if (arm->cpsr) {
202 buf_set_u32(arm->cpsr->value, 0, 32, cpsr);
203 arm->cpsr->valid = 1;
204 arm->cpsr->dirty = 0;
205 }
206
207 /* Older ARMs won't have the J bit */
208 enum arm_state state = 0xFF;
209
210 if (((cpsr & 0x10) >> 4) == 0) {
211 state = ARM_STATE_AARCH64;
212 } else {
213 if (cpsr & (1 << 5)) { /* T */
214 if (cpsr & (1 << 24)) { /* J */
215 LOG_WARNING("ThumbEE -- incomplete support");
216 state = ARM_STATE_THUMB_EE;
217 } else
218 state = ARM_STATE_THUMB;
219 } else {
220 if (cpsr & (1 << 24)) { /* J */
221 LOG_ERROR("Jazelle state handling is BROKEN!");
222 state = ARM_STATE_JAZELLE;
223 } else
224 state = ARM_STATE_ARM;
225 }
226 }
227 arm->core_state = state;
228 if (arm->core_state == ARM_STATE_AARCH64) {
229 switch (mode) {
230 case SYSTEM_AAR64_MODE_EL0t:
231 arm->core_mode = ARMV8_64_EL0T;
232 break;
233 case SYSTEM_AAR64_MODE_EL1t:
234 arm->core_mode = ARMV8_64_EL0T;
235 break;
236 case SYSTEM_AAR64_MODE_EL1h:
237 arm->core_mode = ARMV8_64_EL1H;
238 break;
239 case SYSTEM_AAR64_MODE_EL2t:
240 arm->core_mode = ARMV8_64_EL2T;
241 break;
242 case SYSTEM_AAR64_MODE_EL2h:
243 arm->core_mode = ARMV8_64_EL2H;
244 break;
245 case SYSTEM_AAR64_MODE_EL3t:
246 arm->core_mode = ARMV8_64_EL3T;
247 break;
248 case SYSTEM_AAR64_MODE_EL3h:
249 arm->core_mode = ARMV8_64_EL3H;
250 break;
251 default:
252 LOG_DEBUG("unknow mode 0x%x", (unsigned) (mode));
253 break;
254 }
255 } else {
256 arm->core_mode = mode;
257 }
258
259 LOG_DEBUG("set CPSR %#8.8x: %s mode, %s state", (unsigned) cpsr,
260 armv8_mode_name(arm->core_mode),
261 armv8_state_strings[arm->core_state]);
262 }
263
264 static void armv8_show_fault_registers(struct target *target)
265 {
266 /* TODO */
267 }
268
269 static uint8_t armv8_pa_size(uint32_t ps)
270 {
271 uint8_t ret = 0;
272 switch (ps) {
273 case 0:
274 ret = 32;
275 break;
276 case 1:
277 ret = 36;
278 break;
279 case 2:
280 ret = 40;
281 break;
282 case 3:
283 ret = 42;
284 break;
285 case 4:
286 ret = 44;
287 break;
288 case 5:
289 ret = 48;
290 break;
291 default:
292 LOG_INFO("Unknow physicall address size");
293 break;
294 }
295 return ret;
296 }
297
298 static int armv8_read_ttbcr(struct target *target)
299 {
300 struct armv8_common *armv8 = target_to_armv8(target);
301 struct arm_dpm *dpm = armv8->arm.dpm;
302 struct arm *arm = &armv8->arm;
303 uint32_t ttbcr;
304 uint64_t ttbcr_64;
305
306 int retval = dpm->prepare(dpm);
307 if (retval != ERROR_OK)
308 goto done;
309
310 /* claaer ttrr1_used and ttbr0_mask */
311 memset(&armv8->armv8_mmu.ttbr1_used, 0, sizeof(armv8->armv8_mmu.ttbr1_used));
312 memset(&armv8->armv8_mmu.ttbr0_mask, 0, sizeof(armv8->armv8_mmu.ttbr0_mask));
313
314 switch (arm->core_mode) {
315 case ARMV8_64_EL3H:
316 case ARMV8_64_EL3T:
317 retval = dpm->instr_read_data_r0(dpm,
318 ARMV8_MRS(SYSTEM_TCR_EL3, 0),
319 &ttbcr);
320 retval += dpm->instr_read_data_r0_64(dpm,
321 ARMV8_MRS(SYSTEM_TTBR0_EL3, 0),
322 &armv8->ttbr_base);
323 if (retval != ERROR_OK)
324 goto done;
325 armv8->va_size = 64 - (ttbcr & 0x3F);
326 armv8->pa_size = armv8_pa_size((ttbcr >> 16) & 7);
327 armv8->page_size = (ttbcr >> 14) & 3;
328 break;
329 case ARMV8_64_EL2T:
330 case ARMV8_64_EL2H:
331 retval = dpm->instr_read_data_r0(dpm,
332 ARMV8_MRS(SYSTEM_TCR_EL2, 0),
333 &ttbcr);
334 retval += dpm->instr_read_data_r0_64(dpm,
335 ARMV8_MRS(SYSTEM_TTBR0_EL2, 0),
336 &armv8->ttbr_base);
337 if (retval != ERROR_OK)
338 goto done;
339 armv8->va_size = 64 - (ttbcr & 0x3F);
340 armv8->pa_size = armv8_pa_size((ttbcr >> 16) & 7);
341 armv8->page_size = (ttbcr >> 14) & 3;
342 break;
343 case ARMV8_64_EL0T:
344 case ARMV8_64_EL1T:
345 case ARMV8_64_EL1H:
346 retval = dpm->instr_read_data_r0_64(dpm,
347 ARMV8_MRS(SYSTEM_TCR_EL1, 0),
348 &ttbcr_64);
349 armv8->va_size = 64 - (ttbcr_64 & 0x3F);
350 armv8->pa_size = armv8_pa_size((ttbcr_64 >> 32) & 7);
351 armv8->page_size = (ttbcr_64 >> 14) & 3;
352 armv8->armv8_mmu.ttbr1_used = (((ttbcr_64 >> 16) & 0x3F) != 0) ? 1 : 0;
353 armv8->armv8_mmu.ttbr0_mask = 0x0000FFFFFFFFFFFF;
354 retval += dpm->instr_read_data_r0_64(dpm,
355 ARMV8_MRS(SYSTEM_TTBR0_EL1 | (armv8->armv8_mmu.ttbr1_used), 0),
356 &armv8->ttbr_base);
357 if (retval != ERROR_OK)
358 goto done;
359 break;
360 default:
361 LOG_ERROR("unknow core state");
362 retval = ERROR_FAIL;
363 break;
364 }
365 if (retval != ERROR_OK)
366 goto done;
367
368 #if 0
369 LOG_INFO("ttb1 %s ,ttb0_mask %llx",
370 armv8->armv8_mmu.ttbr1_used ? "used" : "not used",
371 armv8->armv8_mmu.ttbr0_mask);
372 #endif
373 if (armv8->armv8_mmu.ttbr1_used == 1) {
374 LOG_INFO("TTBR0 access above %" PRIx64,
375 (uint64_t)(armv8->armv8_mmu.ttbr0_mask));
376 armv8->armv8_mmu.os_border = armv8->armv8_mmu.ttbr0_mask;
377 } else {
378 /* fix me , default is hard coded LINUX border */
379 armv8->armv8_mmu.os_border = 0xc0000000;
380 }
381 done:
382 dpm->finish(dpm);
383 return retval;
384 }
385
386 static int armv8_4K_translate(struct target *target, uint32_t va, uint32_t *val)
387 {
388 LOG_ERROR("4K page Address translation need to add");
389 return ERROR_FAIL;
390 }
391
392
393 /* method adapted to cortex A : reused arm v4 v5 method*/
394 int armv8_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val)
395 {
396 int retval = ERROR_FAIL;
397 struct armv8_common *armv8 = target_to_armv8(target);
398 struct arm_dpm *dpm = armv8->arm.dpm;
399
400 retval = dpm->prepare(dpm);
401 retval += armv8_read_ttbcr(target);
402 if (retval != ERROR_OK)
403 goto done;
404 if (armv8->page_size == 0)
405 return armv8_4K_translate(target, va, val);
406
407 done:
408 dpm->finish(dpm);
409 return ERROR_FAIL;
410 }
411
412 /* V8 method VA TO PA */
413 int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va,
414 target_addr_t *val, int meminfo)
415 {
416 return ERROR_OK;
417 }
418
419 static int armv8_handle_inner_cache_info_command(struct command_context *cmd_ctx,
420 struct armv8_cache_common *armv8_cache)
421 {
422 if (armv8_cache->ctype == -1) {
423 command_print(cmd_ctx, "cache not yet identified");
424 return ERROR_OK;
425 }
426
427 command_print(cmd_ctx,
428 "D-Cache: linelen %" PRIi32 ", associativity %" PRIi32 ", nsets %" PRIi32 ", cachesize %" PRId32 " KBytes",
429 armv8_cache->d_u_size.linelen,
430 armv8_cache->d_u_size.associativity,
431 armv8_cache->d_u_size.nsets,
432 armv8_cache->d_u_size.cachesize);
433
434 command_print(cmd_ctx,
435 "I-Cache: linelen %" PRIi32 ", associativity %" PRIi32 ", nsets %" PRIi32 ", cachesize %" PRId32 " KBytes",
436 armv8_cache->i_size.linelen,
437 armv8_cache->i_size.associativity,
438 armv8_cache->i_size.nsets,
439 armv8_cache->i_size.cachesize);
440
441 return ERROR_OK;
442 }
443
444 static int _armv8_flush_all_data(struct target *target)
445 {
446 struct armv8_common *armv8 = target_to_armv8(target);
447 struct arm_dpm *dpm = armv8->arm.dpm;
448 struct armv8_cachesize *d_u_size =
449 &(armv8->armv8_mmu.armv8_cache.d_u_size);
450 int32_t c_way, c_index = d_u_size->index;
451 int retval;
452 /* check that cache data is on at target halt */
453 if (!armv8->armv8_mmu.armv8_cache.d_u_cache_enabled) {
454 LOG_INFO("flushed not performed :cache not on at target halt");
455 return ERROR_OK;
456 }
457 retval = dpm->prepare(dpm);
458 if (retval != ERROR_OK)
459 goto done;
460 do {
461 c_way = d_u_size->way;
462 do {
463 uint32_t value = (c_index << d_u_size->index_shift)
464 | (c_way << d_u_size->way_shift);
465 /* DCCISW */
466 /* LOG_INFO ("%d %d %x",c_way,c_index,value); */
467 retval = dpm->instr_write_data_r0(dpm,
468 ARMV4_5_MCR(15, 0, 0, 7, 14, 2),
469 value);
470 if (retval != ERROR_OK)
471 goto done;
472 c_way -= 1;
473 } while (c_way >= 0);
474 c_index -= 1;
475 } while (c_index >= 0);
476 return retval;
477 done:
478 LOG_ERROR("flushed failed");
479 dpm->finish(dpm);
480 return retval;
481 }
482
483 static int armv8_flush_all_data(struct target *target)
484 {
485 int retval = ERROR_FAIL;
486 /* check that armv8_cache is correctly identify */
487 struct armv8_common *armv8 = target_to_armv8(target);
488 if (armv8->armv8_mmu.armv8_cache.ctype == -1) {
489 LOG_ERROR("trying to flush un-identified cache");
490 return retval;
491 }
492
493 if (target->smp) {
494 /* look if all the other target have been flushed in order to flush level
495 * 2 */
496 struct target_list *head;
497 struct target *curr;
498 head = target->head;
499 while (head != (struct target_list *)NULL) {
500 curr = head->target;
501 if (curr->state == TARGET_HALTED) {
502 LOG_INFO("Wait flushing data l1 on core %" PRId32, curr->coreid);
503 retval = _armv8_flush_all_data(curr);
504 }
505 head = head->next;
506 }
507 } else
508 retval = _armv8_flush_all_data(target);
509 return retval;
510 }
511
512 int armv8_handle_cache_info_command(struct command_context *cmd_ctx,
513 struct armv8_cache_common *armv8_cache)
514 {
515 if (armv8_cache->ctype == -1) {
516 command_print(cmd_ctx, "cache not yet identified");
517 return ERROR_OK;
518 }
519
520 if (armv8_cache->display_cache_info)
521 armv8_cache->display_cache_info(cmd_ctx, armv8_cache);
522 return ERROR_OK;
523 }
524
525 /* retrieve core id cluster id */
526 static int armv8_read_mpidr(struct target *target)
527 {
528 int retval = ERROR_FAIL;
529 struct armv8_common *armv8 = target_to_armv8(target);
530 struct arm_dpm *dpm = armv8->arm.dpm;
531 uint32_t mpidr;
532 retval = dpm->prepare(dpm);
533 if (retval != ERROR_OK)
534 goto done;
535 /* MRC p15,0,<Rd>,c0,c0,5; read Multiprocessor ID register*/
536
537 retval = dpm->instr_read_data_r0(dpm,
538 ARMV8_MRS(SYSTEM_MPIDR, 0),
539 &mpidr);
540 if (retval != ERROR_OK)
541 goto done;
542 if (mpidr & 1<<31) {
543 armv8->multi_processor_system = (mpidr >> 30) & 1;
544 armv8->cluster_id = (mpidr >> 8) & 0xf;
545 armv8->cpu_id = mpidr & 0x3;
546 LOG_INFO("%s cluster %x core %x %s", target_name(target),
547 armv8->cluster_id,
548 armv8->cpu_id,
549 armv8->multi_processor_system == 0 ? "multi core" : "mono core");
550
551 } else
552 LOG_ERROR("mpdir not in multiprocessor format");
553
554 done:
555 dpm->finish(dpm);
556 return retval;
557
558
559 }
560
561 int armv8_identify_cache(struct target *target)
562 {
563 /* read cache descriptor */
564 int retval = ERROR_FAIL;
565 struct armv8_common *armv8 = target_to_armv8(target);
566 struct arm_dpm *dpm = armv8->arm.dpm;
567 uint32_t cache_selected, clidr;
568 uint32_t cache_i_reg, cache_d_reg;
569 struct armv8_cache_common *cache = &(armv8->armv8_mmu.armv8_cache);
570 armv8_read_ttbcr(target);
571 retval = dpm->prepare(dpm);
572
573 if (retval != ERROR_OK)
574 goto done;
575 /* retrieve CLIDR
576 * mrc p15, 1, r0, c0, c0, 1 @ read clidr */
577 retval = dpm->instr_read_data_r0(dpm,
578 ARMV8_MRS(SYSTEM_CLIDR, 0),
579 &clidr);
580 if (retval != ERROR_OK)
581 goto done;
582 clidr = (clidr & 0x7000000) >> 23;
583 LOG_INFO("number of cache level %" PRIx32, (uint32_t)(clidr / 2));
584 if ((clidr / 2) > 1) {
585 /* FIXME not supported present in cortex A8 and later */
586 /* in cortex A7, A15 */
587 LOG_ERROR("cache l2 present :not supported");
588 }
589 /* retrieve selected cache*/
590 retval = dpm->instr_read_data_r0(dpm,
591 ARMV8_MRS(SYSTEM_CSSELR, 0),
592 &cache_selected);
593 if (retval != ERROR_OK)
594 goto done;
595
596
597 /* select instruction cache
598 * [0] : 1 instruction cache selection , 0 data cache selection */
599 retval = dpm->instr_write_data_r0(dpm,
600 ARMV8_MRS(SYSTEM_CSSELR, 0),
601 1);
602 if (retval != ERROR_OK)
603 goto done;
604
605 /* read CCSIDR
606 * MRC P15,1,<RT>,C0, C0,0 ;on cortex A9 read CCSIDR
607 * [2:0] line size 001 eight word per line
608 * [27:13] NumSet 0x7f 16KB, 0xff 32Kbytes, 0x1ff 64Kbytes */
609 retval = dpm->instr_read_data_r0(dpm,
610 ARMV8_MRS(SYSTEM_CCSIDR, 0),
611 &cache_i_reg);
612 if (retval != ERROR_OK)
613 goto done;
614
615 /* select data cache*/
616 retval = dpm->instr_write_data_r0(dpm,
617 ARMV8_MRS(SYSTEM_CSSELR, 0),
618 0);
619 if (retval != ERROR_OK)
620 goto done;
621
622 retval = dpm->instr_read_data_r0(dpm,
623 ARMV8_MRS(SYSTEM_CCSIDR, 0),
624 &cache_d_reg);
625 if (retval != ERROR_OK)
626 goto done;
627
628 /* restore selected cache */
629 dpm->instr_write_data_r0(dpm,
630 ARMV8_MRS(SYSTEM_CSSELR, 0),
631 cache_selected);
632
633 if (retval != ERROR_OK)
634 goto done;
635 dpm->finish(dpm);
636
637 /* put fake type */
638 cache->d_u_size.linelen = 16 << (cache_d_reg & 0x7);
639 cache->d_u_size.cachesize = (((cache_d_reg >> 13) & 0x7fff)+1)/8;
640 cache->d_u_size.nsets = (cache_d_reg >> 13) & 0x7fff;
641 cache->d_u_size.associativity = ((cache_d_reg >> 3) & 0x3ff) + 1;
642 /* compute info for set way operation on cache */
643 cache->d_u_size.index_shift = (cache_d_reg & 0x7) + 4;
644 cache->d_u_size.index = (cache_d_reg >> 13) & 0x7fff;
645 cache->d_u_size.way = ((cache_d_reg >> 3) & 0x3ff);
646 cache->d_u_size.way_shift = cache->d_u_size.way + 1;
647 {
648 int i = 0;
649 while (((cache->d_u_size.way_shift >> i) & 1) != 1)
650 i++;
651 cache->d_u_size.way_shift = 32-i;
652 }
653 #if 0
654 LOG_INFO("data cache index %d << %d, way %d << %d",
655 cache->d_u_size.index, cache->d_u_size.index_shift,
656 cache->d_u_size.way,
657 cache->d_u_size.way_shift);
658
659 LOG_INFO("data cache %d bytes %d KBytes asso %d ways",
660 cache->d_u_size.linelen,
661 cache->d_u_size.cachesize,
662 cache->d_u_size.associativity);
663 #endif
664 cache->i_size.linelen = 16 << (cache_i_reg & 0x7);
665 cache->i_size.associativity = ((cache_i_reg >> 3) & 0x3ff) + 1;
666 cache->i_size.nsets = (cache_i_reg >> 13) & 0x7fff;
667 cache->i_size.cachesize = (((cache_i_reg >> 13) & 0x7fff)+1)/8;
668 /* compute info for set way operation on cache */
669 cache->i_size.index_shift = (cache_i_reg & 0x7) + 4;
670 cache->i_size.index = (cache_i_reg >> 13) & 0x7fff;
671 cache->i_size.way = ((cache_i_reg >> 3) & 0x3ff);
672 cache->i_size.way_shift = cache->i_size.way + 1;
673 {
674 int i = 0;
675 while (((cache->i_size.way_shift >> i) & 1) != 1)
676 i++;
677 cache->i_size.way_shift = 32-i;
678 }
679 #if 0
680 LOG_INFO("instruction cache index %d << %d, way %d << %d",
681 cache->i_size.index, cache->i_size.index_shift,
682 cache->i_size.way, cache->i_size.way_shift);
683
684 LOG_INFO("instruction cache %d bytes %d KBytes asso %d ways",
685 cache->i_size.linelen,
686 cache->i_size.cachesize,
687 cache->i_size.associativity);
688 #endif
689 /* if no l2 cache initialize l1 data cache flush function function */
690 if (armv8->armv8_mmu.armv8_cache.flush_all_data_cache == NULL) {
691 armv8->armv8_mmu.armv8_cache.display_cache_info =
692 armv8_handle_inner_cache_info_command;
693 armv8->armv8_mmu.armv8_cache.flush_all_data_cache =
694 armv8_flush_all_data;
695 }
696 armv8->armv8_mmu.armv8_cache.ctype = 0;
697
698 done:
699 dpm->finish(dpm);
700 armv8_read_mpidr(target);
701 return retval;
702
703 }
704
705 int armv8_init_arch_info(struct target *target, struct armv8_common *armv8)
706 {
707 struct arm *arm = &armv8->arm;
708 arm->arch_info = armv8;
709 target->arch_info = &armv8->arm;
710 /* target is useful in all function arm v4 5 compatible */
711 armv8->arm.target = target;
712 armv8->arm.common_magic = ARM_COMMON_MAGIC;
713 armv8->common_magic = ARMV8_COMMON_MAGIC;
714
715 arm->read_core_reg = armv8_read_core_reg;
716 #if 0
717 arm->write_core_reg = armv8_write_core_reg;
718 #endif
719
720 armv8->armv8_mmu.armv8_cache.l2_cache = NULL;
721 armv8->armv8_mmu.armv8_cache.ctype = -1;
722 armv8->armv8_mmu.armv8_cache.flush_all_data_cache = NULL;
723 armv8->armv8_mmu.armv8_cache.display_cache_info = NULL;
724 return ERROR_OK;
725 }
726
727 int armv8_aarch64_state(struct target *target)
728 {
729 struct arm *arm = target_to_arm(target);
730
731 if (arm->common_magic != ARM_COMMON_MAGIC) {
732 LOG_ERROR("BUG: called for a non-ARM target");
733 return ERROR_FAIL;
734 }
735
736 LOG_USER("target halted in %s state due to %s, current mode: %s\n"
737 "cpsr: 0x%8.8" PRIx32 " pc: 0x%" PRIx64 "%s",
738 armv8_state_strings[arm->core_state],
739 debug_reason_name(target),
740 armv8_mode_name(arm->core_mode),
741 buf_get_u32(arm->cpsr->value, 0, 32),
742 buf_get_u64(arm->pc->value, 0, 64),
743 arm->is_semihosting ? ", semihosting" : "");
744
745 return ERROR_OK;
746 }
747
748 int armv8_arch_state(struct target *target)
749 {
750 static const char * const state[] = {
751 "disabled", "enabled"
752 };
753
754 struct armv8_common *armv8 = target_to_armv8(target);
755 struct arm *arm = &armv8->arm;
756
757 if (armv8->common_magic != ARMV8_COMMON_MAGIC) {
758 LOG_ERROR("BUG: called for a non-Armv8 target");
759 return ERROR_COMMAND_SYNTAX_ERROR;
760 }
761
762 if (arm->core_state == ARM_STATE_AARCH64)
763 armv8_aarch64_state(target);
764 else
765 arm_arch_state(target);
766
767 LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
768 state[armv8->armv8_mmu.mmu_enabled],
769 state[armv8->armv8_mmu.armv8_cache.d_u_cache_enabled],
770 state[armv8->armv8_mmu.armv8_cache.i_cache_enabled]);
771
772 if (arm->core_mode == ARM_MODE_ABT)
773 armv8_show_fault_registers(target);
774 if (target->debug_reason == DBG_REASON_WATCHPOINT)
775 LOG_USER("Watchpoint triggered at PC %#08x",
776 (unsigned) armv8->dpm.wp_pc);
777
778 return ERROR_OK;
779 }
780
781 static const struct {
782 unsigned id;
783 const char *name;
784 unsigned bits;
785 enum reg_type type;
786 const char *group;
787 const char *feature;
788 } armv8_regs[] = {
789 { ARMV8_R0, "x0", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
790 { ARMV8_R1, "x1", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
791 { ARMV8_R2, "x2", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
792 { ARMV8_R3, "x3", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
793 { ARMV8_R4, "x4", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
794 { ARMV8_R5, "x5", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
795 { ARMV8_R6, "x6", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
796 { ARMV8_R7, "x7", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
797 { ARMV8_R8, "x8", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
798 { ARMV8_R9, "x9", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
799 { ARMV8_R10, "x10", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
800 { ARMV8_R11, "x11", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
801 { ARMV8_R12, "x12", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
802 { ARMV8_R13, "x13", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
803 { ARMV8_R14, "x14", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
804 { ARMV8_R15, "x15", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
805 { ARMV8_R16, "x16", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
806 { ARMV8_R17, "x17", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
807 { ARMV8_R18, "x18", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
808 { ARMV8_R19, "x19", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
809 { ARMV8_R20, "x20", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
810 { ARMV8_R21, "x21", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
811 { ARMV8_R22, "x22", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
812 { ARMV8_R23, "x23", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
813 { ARMV8_R24, "x24", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
814 { ARMV8_R25, "x25", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
815 { ARMV8_R26, "x26", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
816 { ARMV8_R27, "x27", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
817 { ARMV8_R28, "x28", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
818 { ARMV8_R29, "x29", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
819 { ARMV8_R30, "x30", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
820
821 { ARMV8_R31, "sp", 64, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.aarch64.core" },
822 { ARMV8_PC, "pc", 64, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.aarch64.core" },
823
824 { ARMV8_xPSR, "CPSR", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
825 };
826
827 #define ARMV8_NUM_REGS ARRAY_SIZE(armv8_regs)
828
829
830 static int armv8_get_core_reg(struct reg *reg)
831 {
832 int retval;
833 struct arm_reg *armv8_reg = reg->arch_info;
834 struct target *target = armv8_reg->target;
835 struct arm *arm = target_to_arm(target);
836
837 if (target->state != TARGET_HALTED)
838 return ERROR_TARGET_NOT_HALTED;
839
840 retval = arm->read_core_reg(target, reg, armv8_reg->num, arm->core_mode);
841
842 return retval;
843 }
844
845 static int armv8_set_core_reg(struct reg *reg, uint8_t *buf)
846 {
847 struct arm_reg *armv8_reg = reg->arch_info;
848 struct target *target = armv8_reg->target;
849 uint64_t value = buf_get_u64(buf, 0, 64);
850
851 if (target->state != TARGET_HALTED)
852 return ERROR_TARGET_NOT_HALTED;
853
854 buf_set_u64(reg->value, 0, 64, value);
855 reg->dirty = 1;
856 reg->valid = 1;
857
858 return ERROR_OK;
859 }
860
861 static const struct reg_arch_type armv8_reg_type = {
862 .get = armv8_get_core_reg,
863 .set = armv8_set_core_reg,
864 };
865
866 /** Builds cache of architecturally defined registers. */
867 struct reg_cache *armv8_build_reg_cache(struct target *target)
868 {
869 struct armv8_common *armv8 = target_to_armv8(target);
870 struct arm *arm = &armv8->arm;
871 int num_regs = ARMV8_NUM_REGS;
872 struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
873 struct reg_cache *cache = malloc(sizeof(struct reg_cache));
874 struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
875 struct arm_reg *arch_info = calloc(num_regs, sizeof(struct arm_reg));
876 struct reg_feature *feature;
877 int i;
878
879 /* Build the process context cache */
880 cache->name = "arm v8 registers";
881 cache->next = NULL;
882 cache->reg_list = reg_list;
883 cache->num_regs = num_regs;
884 (*cache_p) = cache;
885
886 for (i = 0; i < num_regs; i++) {
887 arch_info[i].num = armv8_regs[i].id;
888 arch_info[i].target = target;
889 arch_info[i].arm = arm;
890
891 reg_list[i].name = armv8_regs[i].name;
892 reg_list[i].size = armv8_regs[i].bits;
893 reg_list[i].value = calloc(1, 4);
894 reg_list[i].dirty = 0;
895 reg_list[i].valid = 0;
896 reg_list[i].type = &armv8_reg_type;
897 reg_list[i].arch_info = &arch_info[i];
898
899 reg_list[i].group = armv8_regs[i].group;
900 reg_list[i].number = i;
901 reg_list[i].exist = true;
902 reg_list[i].caller_save = true; /* gdb defaults to true */
903
904 feature = calloc(1, sizeof(struct reg_feature));
905 if (feature) {
906 feature->name = armv8_regs[i].feature;
907 reg_list[i].feature = feature;
908 } else
909 LOG_ERROR("unable to allocate feature list");
910
911 reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
912 if (reg_list[i].reg_data_type)
913 reg_list[i].reg_data_type->type = armv8_regs[i].type;
914 else
915 LOG_ERROR("unable to allocate reg type list");
916 }
917
918 arm->cpsr = reg_list + ARMV8_xPSR;
919 arm->pc = reg_list + ARMV8_PC;
920 arm->core_cache = cache;
921
922 return cache;
923 }
924
925 struct reg *armv8_reg_current(struct arm *arm, unsigned regnum)
926 {
927 struct reg *r;
928
929 if (regnum > (ARMV8_LAST_REG - 1))
930 return NULL;
931
932 r = arm->core_cache->reg_list + regnum;
933 return r;
934 }
935
936 const struct command_registration armv8_command_handlers[] = {
937 {
938 .chain = dap_command_handlers,
939 },
940 COMMAND_REGISTRATION_DONE
941 };
942
943
944 int armv8_get_gdb_reg_list(struct target *target,
945 struct reg **reg_list[], int *reg_list_size,
946 enum target_register_class reg_class)
947 {
948 struct arm *arm = target_to_arm(target);
949 int i;
950
951 switch (reg_class) {
952 case REG_CLASS_GENERAL:
953 case REG_CLASS_ALL:
954 *reg_list_size = ARMV8_LAST_REG;
955 *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
956
957 for (i = 0; i < ARMV8_LAST_REG; i++)
958 (*reg_list)[i] = armv8_reg_current(arm, i);
959
960 return ERROR_OK;
961
962 default:
963 LOG_ERROR("not a valid register class type in query.");
964 return ERROR_FAIL;
965 break;
966 }
967 }

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)