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

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)