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

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)