aarch64: fix reading of translation table registers
[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
387 /* method adapted to cortex A : reused arm v4 v5 method*/
388 int armv8_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val)
389 {
390 uint32_t first_lvl_descriptor = 0x0;
391 uint32_t second_lvl_descriptor = 0x0;
392 int retval;
393 struct armv8_common *armv8 = target_to_armv8(target);
394 struct arm_dpm *dpm = armv8->arm.dpm;
395 uint32_t ttb = 0; /* default ttb0 */
396 if (armv8->armv8_mmu.ttbr1_used == -1)
397 armv8_read_ttbcr(target);
398 if ((armv8->armv8_mmu.ttbr1_used) &&
399 (va > (0xffffffff & armv8->armv8_mmu.ttbr0_mask))) {
400 /* select ttb 1 */
401 ttb = 1;
402 }
403 retval = dpm->prepare(dpm);
404 if (retval != ERROR_OK)
405 goto done;
406
407 /* MRC p15,0,<Rt>,c2,c0,ttb */
408 retval = dpm->instr_read_data_r0(dpm,
409 ARMV4_5_MRC(15, 0, 0, 2, 0, ttb),
410 &ttb);
411 if (retval != ERROR_OK)
412 return retval;
413 retval = armv8->armv8_mmu.read_physical_memory(target,
414 (ttb & 0xffffc000) | ((va & 0xfff00000) >> 18),
415 4, 1, (uint8_t *)&first_lvl_descriptor);
416 if (retval != ERROR_OK)
417 return retval;
418 first_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *)
419 &first_lvl_descriptor);
420 /* reuse armv4_5 piece of code, specific armv8 changes may come later */
421 LOG_DEBUG("1st lvl desc: %8.8" PRIx32 "", first_lvl_descriptor);
422
423 if ((first_lvl_descriptor & 0x3) == 0) {
424 LOG_ERROR("Address translation failure");
425 return ERROR_TARGET_TRANSLATION_FAULT;
426 }
427
428
429 if ((first_lvl_descriptor & 0x3) == 2) {
430 /* section descriptor */
431 *val = (first_lvl_descriptor & 0xfff00000) | (va & 0x000fffff);
432 return ERROR_OK;
433 }
434
435 if ((first_lvl_descriptor & 0x3) == 1) {
436 /* coarse page table */
437 retval = armv8->armv8_mmu.read_physical_memory(target,
438 (first_lvl_descriptor & 0xfffffc00) | ((va & 0x000ff000) >> 10),
439 4, 1, (uint8_t *)&second_lvl_descriptor);
440 if (retval != ERROR_OK)
441 return retval;
442 } else if ((first_lvl_descriptor & 0x3) == 3) {
443 /* fine page table */
444 retval = armv8->armv8_mmu.read_physical_memory(target,
445 (first_lvl_descriptor & 0xfffff000) | ((va & 0x000ffc00) >> 8),
446 4, 1, (uint8_t *)&second_lvl_descriptor);
447 if (retval != ERROR_OK)
448 return retval;
449 }
450
451 second_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *)
452 &second_lvl_descriptor);
453
454 LOG_DEBUG("2nd lvl desc: %8.8" PRIx32 "", second_lvl_descriptor);
455
456 if ((second_lvl_descriptor & 0x3) == 0) {
457 LOG_ERROR("Address translation failure");
458 return ERROR_TARGET_TRANSLATION_FAULT;
459 }
460
461 if ((second_lvl_descriptor & 0x3) == 1) {
462 /* large page descriptor */
463 *val = (second_lvl_descriptor & 0xffff0000) | (va & 0x0000ffff);
464 return ERROR_OK;
465 }
466
467 if ((second_lvl_descriptor & 0x3) == 2) {
468 /* small page descriptor */
469 *val = (second_lvl_descriptor & 0xfffff000) | (va & 0x00000fff);
470 return ERROR_OK;
471 }
472
473 if ((second_lvl_descriptor & 0x3) == 3) {
474 *val = (second_lvl_descriptor & 0xfffffc00) | (va & 0x000003ff);
475 return ERROR_OK;
476 }
477
478 /* should not happen */
479 LOG_ERROR("Address translation failure");
480 return ERROR_TARGET_TRANSLATION_FAULT;
481
482 done:
483 return retval;
484 }
485
486 /* V8 method VA TO PA */
487 int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va,
488 target_addr_t *val, int meminfo)
489 {
490 return ERROR_OK;
491 }
492
493 static int armv8_handle_inner_cache_info_command(struct command_context *cmd_ctx,
494 struct armv8_cache_common *armv8_cache)
495 {
496 if (armv8_cache->ctype == -1) {
497 command_print(cmd_ctx, "cache not yet identified");
498 return ERROR_OK;
499 }
500
501 command_print(cmd_ctx,
502 "D-Cache: linelen %" PRIi32 ", associativity %" PRIi32 ", nsets %" PRIi32 ", cachesize %" PRId32 " KBytes",
503 armv8_cache->d_u_size.linelen,
504 armv8_cache->d_u_size.associativity,
505 armv8_cache->d_u_size.nsets,
506 armv8_cache->d_u_size.cachesize);
507
508 command_print(cmd_ctx,
509 "I-Cache: linelen %" PRIi32 ", associativity %" PRIi32 ", nsets %" PRIi32 ", cachesize %" PRId32 " KBytes",
510 armv8_cache->i_size.linelen,
511 armv8_cache->i_size.associativity,
512 armv8_cache->i_size.nsets,
513 armv8_cache->i_size.cachesize);
514
515 return ERROR_OK;
516 }
517
518 static int _armv8_flush_all_data(struct target *target)
519 {
520 struct armv8_common *armv8 = target_to_armv8(target);
521 struct arm_dpm *dpm = armv8->arm.dpm;
522 struct armv8_cachesize *d_u_size =
523 &(armv8->armv8_mmu.armv8_cache.d_u_size);
524 int32_t c_way, c_index = d_u_size->index;
525 int retval;
526 /* check that cache data is on at target halt */
527 if (!armv8->armv8_mmu.armv8_cache.d_u_cache_enabled) {
528 LOG_INFO("flushed not performed :cache not on at target halt");
529 return ERROR_OK;
530 }
531 retval = dpm->prepare(dpm);
532 if (retval != ERROR_OK)
533 goto done;
534 do {
535 c_way = d_u_size->way;
536 do {
537 uint32_t value = (c_index << d_u_size->index_shift)
538 | (c_way << d_u_size->way_shift);
539 /* DCCISW */
540 /* LOG_INFO ("%d %d %x",c_way,c_index,value); */
541 retval = dpm->instr_write_data_r0(dpm,
542 ARMV4_5_MCR(15, 0, 0, 7, 14, 2),
543 value);
544 if (retval != ERROR_OK)
545 goto done;
546 c_way -= 1;
547 } while (c_way >= 0);
548 c_index -= 1;
549 } while (c_index >= 0);
550 return retval;
551 done:
552 LOG_ERROR("flushed failed");
553 dpm->finish(dpm);
554 return retval;
555 }
556
557 static int armv8_flush_all_data(struct target *target)
558 {
559 int retval = ERROR_FAIL;
560 /* check that armv8_cache is correctly identify */
561 struct armv8_common *armv8 = target_to_armv8(target);
562 if (armv8->armv8_mmu.armv8_cache.ctype == -1) {
563 LOG_ERROR("trying to flush un-identified cache");
564 return retval;
565 }
566
567 if (target->smp) {
568 /* look if all the other target have been flushed in order to flush level
569 * 2 */
570 struct target_list *head;
571 struct target *curr;
572 head = target->head;
573 while (head != (struct target_list *)NULL) {
574 curr = head->target;
575 if (curr->state == TARGET_HALTED) {
576 LOG_INFO("Wait flushing data l1 on core %" PRId32, curr->coreid);
577 retval = _armv8_flush_all_data(curr);
578 }
579 head = head->next;
580 }
581 } else
582 retval = _armv8_flush_all_data(target);
583 return retval;
584 }
585
586 int armv8_handle_cache_info_command(struct command_context *cmd_ctx,
587 struct armv8_cache_common *armv8_cache)
588 {
589 if (armv8_cache->ctype == -1) {
590 command_print(cmd_ctx, "cache not yet identified");
591 return ERROR_OK;
592 }
593
594 if (armv8_cache->display_cache_info)
595 armv8_cache->display_cache_info(cmd_ctx, armv8_cache);
596 return ERROR_OK;
597 }
598
599 /* retrieve core id cluster id */
600 static int armv8_read_mpidr(struct target *target)
601 {
602 int retval = ERROR_FAIL;
603 struct armv8_common *armv8 = target_to_armv8(target);
604 struct arm_dpm *dpm = armv8->arm.dpm;
605 uint32_t mpidr;
606 retval = dpm->prepare(dpm);
607 if (retval != ERROR_OK)
608 goto done;
609 /* MRC p15,0,<Rd>,c0,c0,5; read Multiprocessor ID register*/
610
611 retval = dpm->instr_read_data_r0(dpm,
612 ARMV8_MRS(SYSTEM_MPIDR, 0),
613 &mpidr);
614 if (retval != ERROR_OK)
615 goto done;
616 if (mpidr & 1<<31) {
617 armv8->multi_processor_system = (mpidr >> 30) & 1;
618 armv8->cluster_id = (mpidr >> 8) & 0xf;
619 armv8->cpu_id = mpidr & 0x3;
620 LOG_INFO("%s cluster %x core %x %s", target_name(target),
621 armv8->cluster_id,
622 armv8->cpu_id,
623 armv8->multi_processor_system == 0 ? "multi core" : "mono core");
624
625 } else
626 LOG_ERROR("mpdir not in multiprocessor format");
627
628 done:
629 dpm->finish(dpm);
630 return retval;
631
632
633 }
634
635 int armv8_identify_cache(struct target *target)
636 {
637 /* read cache descriptor */
638 int retval = ERROR_FAIL;
639 struct armv8_common *armv8 = target_to_armv8(target);
640 struct arm_dpm *dpm = armv8->arm.dpm;
641 uint32_t cache_selected, clidr;
642 uint32_t cache_i_reg, cache_d_reg;
643 struct armv8_cache_common *cache = &(armv8->armv8_mmu.armv8_cache);
644 if (!armv8->is_armv7r)
645 armv8_read_ttbcr(target);
646 retval = dpm->prepare(dpm);
647
648 if (retval != ERROR_OK)
649 goto done;
650 /* retrieve CLIDR
651 * mrc p15, 1, r0, c0, c0, 1 @ read clidr */
652 retval = dpm->instr_read_data_r0(dpm,
653 ARMV4_5_MRC(15, 1, 0, 0, 0, 1),
654 &clidr);
655 if (retval != ERROR_OK)
656 goto done;
657 clidr = (clidr & 0x7000000) >> 23;
658 LOG_INFO("number of cache level %" PRIx32, (uint32_t)(clidr / 2));
659 if ((clidr / 2) > 1) {
660 /* FIXME not supported present in cortex A8 and later */
661 /* in cortex A7, A15 */
662 LOG_ERROR("cache l2 present :not supported");
663 }
664 /* retrieve selected cache
665 * MRC p15, 2,<Rd>, c0, c0, 0; Read CSSELR */
666 retval = dpm->instr_read_data_r0(dpm,
667 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
668 &cache_selected);
669 if (retval != ERROR_OK)
670 goto done;
671
672 retval = armv8->arm.mrc(target, 15,
673 2, 0, /* op1, op2 */
674 0, 0, /* CRn, CRm */
675 &cache_selected);
676 if (retval != ERROR_OK)
677 goto done;
678 /* select instruction cache
679 * MCR p15, 2,<Rd>, c0, c0, 0; Write CSSELR
680 * [0] : 1 instruction cache selection , 0 data cache selection */
681 retval = dpm->instr_write_data_r0(dpm,
682 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
683 1);
684 if (retval != ERROR_OK)
685 goto done;
686
687 /* read CCSIDR
688 * MRC P15,1,<RT>,C0, C0,0 ;on cortex A9 read CCSIDR
689 * [2:0] line size 001 eight word per line
690 * [27:13] NumSet 0x7f 16KB, 0xff 32Kbytes, 0x1ff 64Kbytes */
691 retval = dpm->instr_read_data_r0(dpm,
692 ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
693 &cache_i_reg);
694 if (retval != ERROR_OK)
695 goto done;
696
697 /* select data cache*/
698 retval = dpm->instr_write_data_r0(dpm,
699 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
700 0);
701 if (retval != ERROR_OK)
702 goto done;
703
704 retval = dpm->instr_read_data_r0(dpm,
705 ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
706 &cache_d_reg);
707 if (retval != ERROR_OK)
708 goto done;
709
710 /* restore selected cache */
711 dpm->instr_write_data_r0(dpm,
712 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
713 cache_selected);
714
715 if (retval != ERROR_OK)
716 goto done;
717 dpm->finish(dpm);
718
719 /* put fake type */
720 cache->d_u_size.linelen = 16 << (cache_d_reg & 0x7);
721 cache->d_u_size.cachesize = (((cache_d_reg >> 13) & 0x7fff)+1)/8;
722 cache->d_u_size.nsets = (cache_d_reg >> 13) & 0x7fff;
723 cache->d_u_size.associativity = ((cache_d_reg >> 3) & 0x3ff) + 1;
724 /* compute info for set way operation on cache */
725 cache->d_u_size.index_shift = (cache_d_reg & 0x7) + 4;
726 cache->d_u_size.index = (cache_d_reg >> 13) & 0x7fff;
727 cache->d_u_size.way = ((cache_d_reg >> 3) & 0x3ff);
728 cache->d_u_size.way_shift = cache->d_u_size.way + 1;
729 {
730 int i = 0;
731 while (((cache->d_u_size.way_shift >> i) & 1) != 1)
732 i++;
733 cache->d_u_size.way_shift = 32-i;
734 }
735 #if 0
736 LOG_INFO("data cache index %d << %d, way %d << %d",
737 cache->d_u_size.index, cache->d_u_size.index_shift,
738 cache->d_u_size.way,
739 cache->d_u_size.way_shift);
740
741 LOG_INFO("data cache %d bytes %d KBytes asso %d ways",
742 cache->d_u_size.linelen,
743 cache->d_u_size.cachesize,
744 cache->d_u_size.associativity);
745 #endif
746 cache->i_size.linelen = 16 << (cache_i_reg & 0x7);
747 cache->i_size.associativity = ((cache_i_reg >> 3) & 0x3ff) + 1;
748 cache->i_size.nsets = (cache_i_reg >> 13) & 0x7fff;
749 cache->i_size.cachesize = (((cache_i_reg >> 13) & 0x7fff)+1)/8;
750 /* compute info for set way operation on cache */
751 cache->i_size.index_shift = (cache_i_reg & 0x7) + 4;
752 cache->i_size.index = (cache_i_reg >> 13) & 0x7fff;
753 cache->i_size.way = ((cache_i_reg >> 3) & 0x3ff);
754 cache->i_size.way_shift = cache->i_size.way + 1;
755 {
756 int i = 0;
757 while (((cache->i_size.way_shift >> i) & 1) != 1)
758 i++;
759 cache->i_size.way_shift = 32-i;
760 }
761 #if 0
762 LOG_INFO("instruction cache index %d << %d, way %d << %d",
763 cache->i_size.index, cache->i_size.index_shift,
764 cache->i_size.way, cache->i_size.way_shift);
765
766 LOG_INFO("instruction cache %d bytes %d KBytes asso %d ways",
767 cache->i_size.linelen,
768 cache->i_size.cachesize,
769 cache->i_size.associativity);
770 #endif
771 /* if no l2 cache initialize l1 data cache flush function function */
772 if (armv8->armv8_mmu.armv8_cache.flush_all_data_cache == NULL) {
773 armv8->armv8_mmu.armv8_cache.display_cache_info =
774 armv8_handle_inner_cache_info_command;
775 armv8->armv8_mmu.armv8_cache.flush_all_data_cache =
776 armv8_flush_all_data;
777 }
778 armv8->armv8_mmu.armv8_cache.ctype = 0;
779
780 done:
781 dpm->finish(dpm);
782 armv8_read_mpidr(target);
783 return retval;
784
785 }
786
787 int armv8_init_arch_info(struct target *target, struct armv8_common *armv8)
788 {
789 struct arm *arm = &armv8->arm;
790 arm->arch_info = armv8;
791 target->arch_info = &armv8->arm;
792 /* target is useful in all function arm v4 5 compatible */
793 armv8->arm.target = target;
794 armv8->arm.common_magic = ARM_COMMON_MAGIC;
795 armv8->common_magic = ARMV8_COMMON_MAGIC;
796
797 arm->read_core_reg = armv8_read_core_reg;
798 #if 0
799 arm->write_core_reg = armv8_write_core_reg;
800 #endif
801
802 armv8->armv8_mmu.armv8_cache.l2_cache = NULL;
803 armv8->armv8_mmu.armv8_cache.ctype = -1;
804 armv8->armv8_mmu.armv8_cache.flush_all_data_cache = NULL;
805 armv8->armv8_mmu.armv8_cache.display_cache_info = NULL;
806 return ERROR_OK;
807 }
808
809 int armv8_arch_state(struct target *target)
810 {
811 static const char * const state[] = {
812 "disabled", "enabled"
813 };
814
815 struct armv8_common *armv8 = target_to_armv8(target);
816 struct arm *arm = &armv8->arm;
817
818 if (armv8->common_magic != ARMV8_COMMON_MAGIC) {
819 LOG_ERROR("BUG: called for a non-Armv8 target");
820 return ERROR_COMMAND_SYNTAX_ERROR;
821 }
822
823 arm_arch_state(target);
824
825 if (armv8->is_armv7r) {
826 LOG_USER("D-Cache: %s, I-Cache: %s",
827 state[armv8->armv8_mmu.armv8_cache.d_u_cache_enabled],
828 state[armv8->armv8_mmu.armv8_cache.i_cache_enabled]);
829 } else {
830 LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
831 state[armv8->armv8_mmu.mmu_enabled],
832 state[armv8->armv8_mmu.armv8_cache.d_u_cache_enabled],
833 state[armv8->armv8_mmu.armv8_cache.i_cache_enabled]);
834 }
835
836 if (arm->core_mode == ARM_MODE_ABT)
837 armv8_show_fault_registers(target);
838 if (target->debug_reason == DBG_REASON_WATCHPOINT)
839 LOG_USER("Watchpoint triggered at PC %#08x",
840 (unsigned) armv8->dpm.wp_pc);
841
842 return ERROR_OK;
843 }
844
845 static const struct {
846 unsigned id;
847 const char *name;
848 unsigned bits;
849 enum reg_type type;
850 const char *group;
851 const char *feature;
852 } armv8_regs[] = {
853 { ARMV8_R0, "x0", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
854 { ARMV8_R1, "x1", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
855 { ARMV8_R2, "x2", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
856 { ARMV8_R3, "x3", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
857 { ARMV8_R4, "x4", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
858 { ARMV8_R5, "x5", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
859 { ARMV8_R6, "x6", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
860 { ARMV8_R7, "x7", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
861 { ARMV8_R8, "x8", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
862 { ARMV8_R9, "x9", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
863 { ARMV8_R10, "x10", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
864 { ARMV8_R11, "x11", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
865 { ARMV8_R12, "x12", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
866 { ARMV8_R13, "x13", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
867 { ARMV8_R14, "x14", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
868 { ARMV8_R15, "x15", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
869 { ARMV8_R16, "x16", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
870 { ARMV8_R17, "x17", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
871 { ARMV8_R18, "x18", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
872 { ARMV8_R19, "x19", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
873 { ARMV8_R20, "x20", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
874 { ARMV8_R21, "x21", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
875 { ARMV8_R22, "x22", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
876 { ARMV8_R23, "x23", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
877 { ARMV8_R24, "x24", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
878 { ARMV8_R25, "x25", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
879 { ARMV8_R26, "x26", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
880 { ARMV8_R27, "x27", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
881 { ARMV8_R28, "x28", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
882 { ARMV8_R29, "x29", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
883 { ARMV8_R30, "x30", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
884
885 { ARMV8_R31, "sp", 64, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.aarch64.core" },
886 { ARMV8_PC, "pc", 64, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.aarch64.core" },
887
888 { ARMV8_xPSR, "CPSR", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" },
889 };
890
891 #define ARMV8_NUM_REGS ARRAY_SIZE(armv8_regs)
892
893
894 static int armv8_get_core_reg(struct reg *reg)
895 {
896 int retval;
897 struct arm_reg *armv8_reg = reg->arch_info;
898 struct target *target = armv8_reg->target;
899 struct arm *arm = target_to_arm(target);
900
901 if (target->state != TARGET_HALTED)
902 return ERROR_TARGET_NOT_HALTED;
903
904 retval = arm->read_core_reg(target, reg, armv8_reg->num, arm->core_mode);
905
906 return retval;
907 }
908
909 static int armv8_set_core_reg(struct reg *reg, uint8_t *buf)
910 {
911 struct arm_reg *armv8_reg = reg->arch_info;
912 struct target *target = armv8_reg->target;
913 uint64_t value = buf_get_u64(buf, 0, 64);
914
915 if (target->state != TARGET_HALTED)
916 return ERROR_TARGET_NOT_HALTED;
917
918 buf_set_u64(reg->value, 0, 64, value);
919 reg->dirty = 1;
920 reg->valid = 1;
921
922 return ERROR_OK;
923 }
924
925 static const struct reg_arch_type armv8_reg_type = {
926 .get = armv8_get_core_reg,
927 .set = armv8_set_core_reg,
928 };
929
930 /** Builds cache of architecturally defined registers. */
931 struct reg_cache *armv8_build_reg_cache(struct target *target)
932 {
933 struct armv8_common *armv8 = target_to_armv8(target);
934 struct arm *arm = &armv8->arm;
935 int num_regs = ARMV8_NUM_REGS;
936 struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
937 struct reg_cache *cache = malloc(sizeof(struct reg_cache));
938 struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
939 struct arm_reg *arch_info = calloc(num_regs, sizeof(struct arm_reg));
940 struct reg_feature *feature;
941 int i;
942
943 /* Build the process context cache */
944 cache->name = "arm v8 registers";
945 cache->next = NULL;
946 cache->reg_list = reg_list;
947 cache->num_regs = num_regs;
948 (*cache_p) = cache;
949
950 for (i = 0; i < num_regs; i++) {
951 arch_info[i].num = armv8_regs[i].id;
952 arch_info[i].target = target;
953 arch_info[i].arm = arm;
954
955 reg_list[i].name = armv8_regs[i].name;
956 reg_list[i].size = armv8_regs[i].bits;
957 reg_list[i].value = calloc(1, 4);
958 reg_list[i].dirty = 0;
959 reg_list[i].valid = 0;
960 reg_list[i].type = &armv8_reg_type;
961 reg_list[i].arch_info = &arch_info[i];
962
963 reg_list[i].group = armv8_regs[i].group;
964 reg_list[i].number = i;
965 reg_list[i].exist = true;
966 reg_list[i].caller_save = true; /* gdb defaults to true */
967
968 feature = calloc(1, sizeof(struct reg_feature));
969 if (feature) {
970 feature->name = armv8_regs[i].feature;
971 reg_list[i].feature = feature;
972 } else
973 LOG_ERROR("unable to allocate feature list");
974
975 reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
976 if (reg_list[i].reg_data_type)
977 reg_list[i].reg_data_type->type = armv8_regs[i].type;
978 else
979 LOG_ERROR("unable to allocate reg type list");
980 }
981
982 arm->cpsr = reg_list + ARMV8_xPSR;
983 arm->pc = reg_list + ARMV8_PC;
984 arm->core_cache = cache;
985
986 return cache;
987 }
988
989 struct reg *armv8_reg_current(struct arm *arm, unsigned regnum)
990 {
991 struct reg *r;
992
993 if (regnum > 33)
994 return NULL;
995
996 r = arm->core_cache->reg_list + regnum;
997 return r;
998 }
999
1000 const struct command_registration armv8_command_handlers[] = {
1001 {
1002 .chain = dap_command_handlers,
1003 },
1004 COMMAND_REGISTRATION_DONE
1005 };
1006
1007
1008 int armv8_get_gdb_reg_list(struct target *target,
1009 struct reg **reg_list[], int *reg_list_size,
1010 enum target_register_class reg_class)
1011 {
1012 struct arm *arm = target_to_arm(target);
1013 int i;
1014
1015 switch (reg_class) {
1016 case REG_CLASS_GENERAL:
1017 case REG_CLASS_ALL:
1018 *reg_list_size = 34;
1019 *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
1020
1021 for (i = 0; i < *reg_list_size; i++)
1022 (*reg_list)[i] = armv8_reg_current(arm, i);
1023
1024 return ERROR_OK;
1025 break;
1026
1027 default:
1028 LOG_ERROR("not a valid register class type in query.");
1029 return ERROR_FAIL;
1030 break;
1031 }
1032 }

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)