18416e5a94ab0527e5d0b49eeab8c28b781506dd
[openocd.git] / src / target / armv7a.c
1 /***************************************************************************
2 * Copyright (C) 2009 by David Brownell *
3 * *
4 * Copyright (C) ST-Ericsson SA 2011 michel.jaouen@stericsson.com *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
20 ***************************************************************************/
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <helper/replacements.h>
27
28 #include "armv7a.h"
29 #include "arm_disassembler.h"
30
31 #include "register.h"
32 #include <helper/binarybuffer.h>
33 #include <helper/command.h>
34
35 #include <stdlib.h>
36 #include <string.h>
37 #include <unistd.h>
38
39 #include "arm_opcodes.h"
40 #include "target.h"
41 #include "target_type.h"
42
43 static void armv7a_show_fault_registers(struct target *target)
44 {
45 uint32_t dfsr, ifsr, dfar, ifar;
46 struct armv7a_common *armv7a = target_to_armv7a(target);
47 struct arm_dpm *dpm = armv7a->arm.dpm;
48 int retval;
49
50 retval = dpm->prepare(dpm);
51 if (retval != ERROR_OK)
52 return;
53
54 /* ARMV4_5_MRC(cpnum, op1, r0, CRn, CRm, op2) */
55
56 /* c5/c0 - {data, instruction} fault status registers */
57 retval = dpm->instr_read_data_r0(dpm,
58 ARMV4_5_MRC(15, 0, 0, 5, 0, 0),
59 &dfsr);
60 if (retval != ERROR_OK)
61 goto done;
62
63 retval = dpm->instr_read_data_r0(dpm,
64 ARMV4_5_MRC(15, 0, 0, 5, 0, 1),
65 &ifsr);
66 if (retval != ERROR_OK)
67 goto done;
68
69 /* c6/c0 - {data, instruction} fault address registers */
70 retval = dpm->instr_read_data_r0(dpm,
71 ARMV4_5_MRC(15, 0, 0, 6, 0, 0),
72 &dfar);
73 if (retval != ERROR_OK)
74 goto done;
75
76 retval = dpm->instr_read_data_r0(dpm,
77 ARMV4_5_MRC(15, 0, 0, 6, 0, 2),
78 &ifar);
79 if (retval != ERROR_OK)
80 goto done;
81
82 LOG_USER("Data fault registers DFSR: %8.8" PRIx32
83 ", DFAR: %8.8" PRIx32, dfsr, dfar);
84 LOG_USER("Instruction fault registers IFSR: %8.8" PRIx32
85 ", IFAR: %8.8" PRIx32, ifsr, ifar);
86
87 done:
88 /* (void) */ dpm->finish(dpm);
89 }
90
91
92 /* retrieve main id register */
93 static int armv7a_read_midr(struct target *target)
94 {
95 int retval = ERROR_FAIL;
96 struct armv7a_common *armv7a = target_to_armv7a(target);
97 struct arm_dpm *dpm = armv7a->arm.dpm;
98 uint32_t midr;
99 retval = dpm->prepare(dpm);
100 if (retval != ERROR_OK)
101 goto done;
102 /* MRC p15,0,<Rd>,c0,c0,0; read main id register*/
103
104 retval = dpm->instr_read_data_r0(dpm,
105 ARMV4_5_MRC(15, 0, 0, 0, 0, 0),
106 &midr);
107 if (retval != ERROR_OK)
108 goto done;
109
110 armv7a->rev = (midr & 0xf);
111 armv7a->partnum = (midr >> 4) & 0xfff;
112 armv7a->arch = (midr >> 16) & 0xf;
113 armv7a->variant = (midr >> 20) & 0xf;
114 armv7a->implementor = (midr >> 24) & 0xff;
115 LOG_INFO("%s rev %" PRIx32 ", partnum %" PRIx32 ", arch %" PRIx32
116 ", variant %" PRIx32 ", implementor %" PRIx32,
117 target->cmd_name,
118 armv7a->rev,
119 armv7a->partnum,
120 armv7a->arch,
121 armv7a->variant,
122 armv7a->implementor);
123
124 done:
125 dpm->finish(dpm);
126 return retval;
127 }
128
129 static int armv7a_read_ttbcr(struct target *target)
130 {
131 struct armv7a_common *armv7a = target_to_armv7a(target);
132 struct arm_dpm *dpm = armv7a->arm.dpm;
133 uint32_t ttbcr, ttbcr_n;
134 int retval = dpm->prepare(dpm);
135 if (retval != ERROR_OK)
136 goto done;
137 /* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
138 retval = dpm->instr_read_data_r0(dpm,
139 ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
140 &ttbcr);
141 if (retval != ERROR_OK)
142 goto done;
143
144 LOG_DEBUG("ttbcr %" PRIx32, ttbcr);
145
146 ttbcr_n = ttbcr & 0x7;
147 armv7a->armv7a_mmu.ttbcr = ttbcr;
148 armv7a->armv7a_mmu.cached = 1;
149
150 /*
151 * ARM Architecture Reference Manual (ARMv7-A and ARMv7-Redition),
152 * document # ARM DDI 0406C
153 */
154 armv7a->armv7a_mmu.ttbr_range[0] = 0xffffffff >> ttbcr_n;
155 armv7a->armv7a_mmu.ttbr_range[1] = 0xffffffff;
156 armv7a->armv7a_mmu.ttbr_mask[0] = 0xffffffff << (14 - ttbcr_n);
157 armv7a->armv7a_mmu.ttbr_mask[1] = 0xffffffff << 14;
158 armv7a->armv7a_mmu.cached = 1;
159
160 retval = armv7a_read_midr(target);
161 if (retval != ERROR_OK)
162 goto done;
163
164 /* FIXME: why this special case based on part number? */
165 if ((armv7a->partnum & 0xf) == 0) {
166 /* ARM DDI 0344H , ARM DDI 0407F */
167 armv7a->armv7a_mmu.ttbr_mask[0] = 7 << (32 - ttbcr_n);
168 }
169
170 LOG_DEBUG("ttbr1 %s, ttbr0_mask %" PRIx32 " ttbr1_mask %" PRIx32,
171 (ttbcr_n != 0) ? "used" : "not used",
172 armv7a->armv7a_mmu.ttbr_mask[0],
173 armv7a->armv7a_mmu.ttbr_mask[1]);
174
175 /* FIXME: default is hard coded LINUX border */
176 armv7a->armv7a_mmu.os_border = 0xc0000000;
177 if (ttbcr_n != 0) {
178 LOG_INFO("SVC access above %" PRIx32,
179 armv7a->armv7a_mmu.ttbr_range[0] + 1);
180 armv7a->armv7a_mmu.os_border = armv7a->armv7a_mmu.ttbr_range[0] + 1;
181 }
182 done:
183 dpm->finish(dpm);
184 return retval;
185 }
186
187 /* method adapted to cortex A : reused arm v4 v5 method*/
188 int armv7a_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val)
189 {
190 uint32_t first_lvl_descriptor = 0x0;
191 uint32_t second_lvl_descriptor = 0x0;
192 int retval;
193 struct armv7a_common *armv7a = target_to_armv7a(target);
194 struct arm_dpm *dpm = armv7a->arm.dpm;
195 uint32_t ttbidx = 0; /* default to ttbr0 */
196 uint32_t ttb_mask;
197 uint32_t va_mask;
198 uint32_t ttbcr;
199 uint32_t ttb;
200
201 retval = dpm->prepare(dpm);
202 if (retval != ERROR_OK)
203 goto done;
204
205 /* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
206 retval = dpm->instr_read_data_r0(dpm,
207 ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
208 &ttbcr);
209 if (retval != ERROR_OK)
210 goto done;
211
212 /* if ttbcr has changed or was not read before, re-read the information */
213 if ((armv7a->armv7a_mmu.cached == 0) ||
214 (armv7a->armv7a_mmu.ttbcr != ttbcr)) {
215 armv7a_read_ttbcr(target);
216 }
217
218 /* if va is above the range handled by ttbr0, select ttbr1 */
219 if (va > armv7a->armv7a_mmu.ttbr_range[0]) {
220 /* select ttb 1 */
221 ttbidx = 1;
222 }
223 /* MRC p15,0,<Rt>,c2,c0,ttbidx */
224 retval = dpm->instr_read_data_r0(dpm,
225 ARMV4_5_MRC(15, 0, 0, 2, 0, ttbidx),
226 &ttb);
227 if (retval != ERROR_OK)
228 return retval;
229
230 ttb_mask = armv7a->armv7a_mmu.ttbr_mask[ttbidx];
231 va_mask = 0xfff00000 & armv7a->armv7a_mmu.ttbr_range[ttbidx];
232
233 LOG_DEBUG("ttb_mask %" PRIx32 " va_mask %" PRIx32 " ttbidx %i",
234 ttb_mask, va_mask, ttbidx);
235 retval = armv7a->armv7a_mmu.read_physical_memory(target,
236 (ttb & ttb_mask) | ((va & va_mask) >> 18),
237 4, 1, (uint8_t *)&first_lvl_descriptor);
238 if (retval != ERROR_OK)
239 return retval;
240 first_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *)
241 &first_lvl_descriptor);
242 /* reuse armv4_5 piece of code, specific armv7a changes may come later */
243 LOG_DEBUG("1st lvl desc: %8.8" PRIx32 "", first_lvl_descriptor);
244
245 if ((first_lvl_descriptor & 0x3) == 0) {
246 LOG_ERROR("Address translation failure");
247 return ERROR_TARGET_TRANSLATION_FAULT;
248 }
249
250
251 if ((first_lvl_descriptor & 0x40002) == 2) {
252 /* section descriptor */
253 *val = (first_lvl_descriptor & 0xfff00000) | (va & 0x000fffff);
254 return ERROR_OK;
255 } else if ((first_lvl_descriptor & 0x40002) == 0x40002) {
256 /* supersection descriptor */
257 if (first_lvl_descriptor & 0x00f001e0) {
258 LOG_ERROR("Physical address does not fit into 32 bits");
259 return ERROR_TARGET_TRANSLATION_FAULT;
260 }
261 *val = (first_lvl_descriptor & 0xff000000) | (va & 0x00ffffff);
262 return ERROR_OK;
263 }
264
265 /* page table */
266 retval = armv7a->armv7a_mmu.read_physical_memory(target,
267 (first_lvl_descriptor & 0xfffffc00) | ((va & 0x000ff000) >> 10),
268 4, 1, (uint8_t *)&second_lvl_descriptor);
269 if (retval != ERROR_OK)
270 return retval;
271
272 second_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *)
273 &second_lvl_descriptor);
274
275 LOG_DEBUG("2nd lvl desc: %8.8" PRIx32 "", second_lvl_descriptor);
276
277 if ((second_lvl_descriptor & 0x3) == 0) {
278 LOG_ERROR("Address translation failure");
279 return ERROR_TARGET_TRANSLATION_FAULT;
280 }
281
282 if ((second_lvl_descriptor & 0x3) == 1) {
283 /* large page descriptor */
284 *val = (second_lvl_descriptor & 0xffff0000) | (va & 0x0000ffff);
285 } else {
286 /* small page descriptor */
287 *val = (second_lvl_descriptor & 0xfffff000) | (va & 0x00000fff);
288 }
289
290 return ERROR_OK;
291
292 done:
293 return retval;
294 }
295
296 /* V7 method VA TO PA */
297 int armv7a_mmu_translate_va_pa(struct target *target, uint32_t va,
298 uint32_t *val, int meminfo)
299 {
300 int retval = ERROR_FAIL;
301 struct armv7a_common *armv7a = target_to_armv7a(target);
302 struct arm_dpm *dpm = armv7a->arm.dpm;
303 uint32_t virt = va & ~0xfff;
304 uint32_t NOS, NS, INNER, OUTER;
305 *val = 0xdeadbeef;
306 retval = dpm->prepare(dpm);
307 if (retval != ERROR_OK)
308 goto done;
309 /* mmu must be enable in order to get a correct translation
310 * use VA to PA CP15 register for conversion */
311 retval = dpm->instr_write_data_r0(dpm,
312 ARMV4_5_MCR(15, 0, 0, 7, 8, 0),
313 virt);
314 if (retval != ERROR_OK)
315 goto done;
316 retval = dpm->instr_read_data_r0(dpm,
317 ARMV4_5_MRC(15, 0, 0, 7, 4, 0),
318 val);
319 /* decode memory attribute */
320 NOS = (*val >> 10) & 1; /* Not Outer shareable */
321 NS = (*val >> 9) & 1; /* Non secure */
322 INNER = (*val >> 4) & 0x7;
323 OUTER = (*val >> 2) & 0x3;
324
325 if (retval != ERROR_OK)
326 goto done;
327 *val = (*val & ~0xfff) + (va & 0xfff);
328 if (*val == va)
329 LOG_WARNING("virt = phys : MMU disable !!");
330 if (meminfo) {
331 LOG_INFO("%" PRIx32 " : %" PRIx32 " %s outer shareable %s secured",
332 va, *val,
333 NOS == 1 ? "not" : " ",
334 NS == 1 ? "not" : "");
335 switch (OUTER) {
336 case 0:
337 LOG_INFO("outer: Non-Cacheable");
338 break;
339 case 1:
340 LOG_INFO("outer: Write-Back, Write-Allocate");
341 break;
342 case 2:
343 LOG_INFO("outer: Write-Through, No Write-Allocate");
344 break;
345 case 3:
346 LOG_INFO("outer: Write-Back, no Write-Allocate");
347 break;
348 }
349 switch (INNER) {
350 case 0:
351 LOG_INFO("inner: Non-Cacheable");
352 break;
353 case 1:
354 LOG_INFO("inner: Strongly-ordered");
355 break;
356 case 3:
357 LOG_INFO("inner: Device");
358 break;
359 case 5:
360 LOG_INFO("inner: Write-Back, Write-Allocate");
361 break;
362 case 6:
363 LOG_INFO("inner: Write-Through");
364 break;
365 case 7:
366 LOG_INFO("inner: Write-Back, no Write-Allocate");
367
368 default:
369 LOG_INFO("inner: %" PRIx32 " ???", INNER);
370 }
371 }
372
373 done:
374 dpm->finish(dpm);
375
376 return retval;
377 }
378
379 static int armv7a_handle_inner_cache_info_command(struct command_context *cmd_ctx,
380 struct armv7a_cache_common *armv7a_cache)
381 {
382 int cl;
383
384 if (armv7a_cache->info == -1) {
385 command_print(cmd_ctx, "cache not yet identified");
386 return ERROR_OK;
387 }
388
389 for (cl = 0; cl < armv7a_cache->loc; cl++) {
390 struct armv7a_arch_cache *arch = &(armv7a_cache->arch[cl]);
391
392 if (arch->ctype & 1) {
393 command_print(cmd_ctx,
394 "L%d I-Cache: linelen %" PRIi32
395 ", associativity %" PRIi32
396 ", nsets %" PRIi32
397 ", cachesize %" PRId32 " KBytes",
398 cl+1,
399 arch->i_size.linelen,
400 arch->i_size.associativity,
401 arch->i_size.nsets,
402 arch->i_size.cachesize);
403 }
404
405 if (arch->ctype >= 2) {
406 command_print(cmd_ctx,
407 "L%d D-Cache: linelen %" PRIi32
408 ", associativity %" PRIi32
409 ", nsets %" PRIi32
410 ", cachesize %" PRId32 " KBytes",
411 cl+1,
412 arch->d_u_size.linelen,
413 arch->d_u_size.associativity,
414 arch->d_u_size.nsets,
415 arch->d_u_size.cachesize);
416 }
417 }
418
419 return ERROR_OK;
420 }
421
422 /* FIXME: remove it */
423 static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t way)
424 {
425 struct armv7a_l2x_cache *l2x_cache;
426 struct target_list *head = target->head;
427 struct target *curr;
428
429 struct armv7a_common *armv7a = target_to_armv7a(target);
430 l2x_cache = calloc(1, sizeof(struct armv7a_l2x_cache));
431 l2x_cache->base = base;
432 l2x_cache->way = way;
433 /*LOG_INFO("cache l2 initialized base %x way %d",
434 l2x_cache->base,l2x_cache->way);*/
435 if (armv7a->armv7a_mmu.armv7a_cache.outer_cache)
436 LOG_INFO("outer cache already initialized\n");
437 armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache;
438 /* initialize all target in this cluster (smp target)
439 * l2 cache must be configured after smp declaration */
440 while (head != (struct target_list *)NULL) {
441 curr = head->target;
442 if (curr != target) {
443 armv7a = target_to_armv7a(curr);
444 if (armv7a->armv7a_mmu.armv7a_cache.outer_cache)
445 LOG_ERROR("smp target : outer cache already initialized\n");
446 armv7a->armv7a_mmu.armv7a_cache.outer_cache = l2x_cache;
447 }
448 head = head->next;
449 }
450 return JIM_OK;
451 }
452
453 /* FIXME: remove it */
454 COMMAND_HANDLER(handle_cache_l2x)
455 {
456 struct target *target = get_current_target(CMD_CTX);
457 uint32_t base, way;
458
459 if (CMD_ARGC != 2)
460 return ERROR_COMMAND_SYNTAX_ERROR;
461
462 /* command_print(CMD_CTX, "%s %s", CMD_ARGV[0], CMD_ARGV[1]); */
463 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], base);
464 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], way);
465
466 /* AP address is in bits 31:24 of DP_SELECT */
467 armv7a_l2x_cache_init(target, base, way);
468
469 return ERROR_OK;
470 }
471
472 int armv7a_handle_cache_info_command(struct command_context *cmd_ctx,
473 struct armv7a_cache_common *armv7a_cache)
474 {
475 struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache *)
476 (armv7a_cache->outer_cache);
477
478 if (armv7a_cache->info == -1) {
479 command_print(cmd_ctx, "cache not yet identified");
480 return ERROR_OK;
481 }
482
483 if (armv7a_cache->display_cache_info)
484 armv7a_cache->display_cache_info(cmd_ctx, armv7a_cache);
485 if (l2x_cache != NULL)
486 command_print(cmd_ctx, "Outer unified cache Base Address 0x%" PRIx32 ", %" PRId32 " ways",
487 l2x_cache->base, l2x_cache->way);
488
489 return ERROR_OK;
490 }
491
492 /* retrieve core id cluster id */
493 static int armv7a_read_mpidr(struct target *target)
494 {
495 int retval = ERROR_FAIL;
496 struct armv7a_common *armv7a = target_to_armv7a(target);
497 struct arm_dpm *dpm = armv7a->arm.dpm;
498 uint32_t mpidr;
499 retval = dpm->prepare(dpm);
500 if (retval != ERROR_OK)
501 goto done;
502 /* MRC p15,0,<Rd>,c0,c0,5; read Multiprocessor ID register*/
503
504 retval = dpm->instr_read_data_r0(dpm,
505 ARMV4_5_MRC(15, 0, 0, 0, 0, 5),
506 &mpidr);
507 if (retval != ERROR_OK)
508 goto done;
509
510 /* ARMv7R uses a different format for MPIDR.
511 * When configured uniprocessor (most R cores) it reads as 0.
512 * This will need to be implemented for multiprocessor ARMv7R cores. */
513 if (armv7a->is_armv7r) {
514 if (mpidr)
515 LOG_ERROR("MPIDR nonzero in ARMv7-R target");
516 goto done;
517 }
518
519 if (mpidr & 1<<31) {
520 armv7a->multi_processor_system = (mpidr >> 30) & 1;
521 armv7a->cluster_id = (mpidr >> 8) & 0xf;
522 armv7a->cpu_id = mpidr & 0x3;
523 LOG_INFO("%s cluster %x core %x %s", target_name(target),
524 armv7a->cluster_id,
525 armv7a->cpu_id,
526 armv7a->multi_processor_system == 0 ? "multi core" : "mono core");
527
528 } else
529 LOG_ERROR("MPIDR not in multiprocessor format");
530
531 done:
532 dpm->finish(dpm);
533 return retval;
534
535
536 }
537
538 static int get_cache_info(struct arm_dpm *dpm, int cl, int ct, uint32_t *cache_reg)
539 {
540 int retval = ERROR_OK;
541
542 /* select cache level */
543 retval = dpm->instr_write_data_r0(dpm,
544 ARMV4_5_MCR(15, 2, 0, 0, 0, 0),
545 (cl << 1) | (ct == 1 ? 1 : 0));
546 if (retval != ERROR_OK)
547 goto done;
548
549 retval = dpm->instr_read_data_r0(dpm,
550 ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
551 cache_reg);
552 done:
553 return retval;
554 }
555
556 static struct armv7a_cachesize decode_cache_reg(uint32_t cache_reg)
557 {
558 struct armv7a_cachesize size;
559 int i = 0;
560
561 size.linelen = 16 << (cache_reg & 0x7);
562 size.associativity = ((cache_reg >> 3) & 0x3ff) + 1;
563 size.nsets = ((cache_reg >> 13) & 0x7fff) + 1;
564 size.cachesize = size.linelen * size.associativity * size.nsets / 1024;
565
566 /* compute info for set way operation on cache */
567 size.index_shift = (cache_reg & 0x7) + 4;
568 size.index = (cache_reg >> 13) & 0x7fff;
569 size.way = ((cache_reg >> 3) & 0x3ff);
570
571 while (((size.way << i) & 0x80000000) == 0)
572 i++;
573 size.way_shift = i;
574
575 return size;
576 }
577
578 int armv7a_identify_cache(struct target *target)
579 {
580 /* read cache descriptor */
581 int retval = ERROR_FAIL;
582 struct armv7a_common *armv7a = target_to_armv7a(target);
583 struct arm_dpm *dpm = armv7a->arm.dpm;
584 uint32_t csselr, clidr, ctr;
585 uint32_t cache_reg;
586 int cl, ctype;
587 struct armv7a_cache_common *cache =
588 &(armv7a->armv7a_mmu.armv7a_cache);
589
590 if (!armv7a->is_armv7r)
591 armv7a_read_ttbcr(target);
592
593 retval = dpm->prepare(dpm);
594 if (retval != ERROR_OK)
595 goto done;
596
597 /* retrieve CTR
598 * mrc p15, 0, r0, c0, c0, 1 @ read ctr */
599 retval = dpm->instr_read_data_r0(dpm,
600 ARMV4_5_MRC(15, 0, 0, 0, 0, 1),
601 &ctr);
602 if (retval != ERROR_OK)
603 goto done;
604
605 cache->iminline = 4UL << (ctr & 0xf);
606 cache->dminline = 4UL << ((ctr & 0xf0000) >> 16);
607 LOG_DEBUG("ctr %" PRIx32 " ctr.iminline %" PRId32 " ctr.dminline %" PRId32,
608 ctr, cache->iminline, cache->dminline);
609
610 /* retrieve CLIDR
611 * mrc p15, 1, r0, c0, c0, 1 @ read clidr */
612 retval = dpm->instr_read_data_r0(dpm,
613 ARMV4_5_MRC(15, 1, 0, 0, 0, 1),
614 &clidr);
615 if (retval != ERROR_OK)
616 goto done;
617
618 cache->loc = (clidr & 0x7000000) >> 24;
619 LOG_DEBUG("Number of cache levels to PoC %" PRId32, cache->loc);
620
621 /* retrieve selected cache for later restore
622 * MRC p15, 2,<Rd>, c0, c0, 0; Read CSSELR */
623 retval = dpm->instr_read_data_r0(dpm,
624 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
625 &csselr);
626 if (retval != ERROR_OK)
627 goto done;
628
629 /* retrieve all available inner caches */
630 for (cl = 0; cl < cache->loc; clidr >>= 3, cl++) {
631
632 /* isolate cache type at current level */
633 ctype = clidr & 7;
634
635 /* skip reserved values */
636 if (ctype > CACHE_LEVEL_HAS_UNIFIED_CACHE)
637 continue;
638
639 /* separate d or unified d/i cache at this level ? */
640 if (ctype & (CACHE_LEVEL_HAS_UNIFIED_CACHE | CACHE_LEVEL_HAS_D_CACHE)) {
641 /* retrieve d-cache info */
642 retval = get_cache_info(dpm, cl, 0, &cache_reg);
643 if (retval != ERROR_OK)
644 goto done;
645 cache->arch[cl].d_u_size = decode_cache_reg(cache_reg);
646
647 LOG_DEBUG("data/unified cache index %d << %d, way %d << %d",
648 cache->arch[cl].d_u_size.index,
649 cache->arch[cl].d_u_size.index_shift,
650 cache->arch[cl].d_u_size.way,
651 cache->arch[cl].d_u_size.way_shift);
652
653 LOG_DEBUG("cacheline %d bytes %d KBytes asso %d ways",
654 cache->arch[cl].d_u_size.linelen,
655 cache->arch[cl].d_u_size.cachesize,
656 cache->arch[cl].d_u_size.associativity);
657 }
658
659 /* separate i-cache at this level ? */
660 if (ctype & CACHE_LEVEL_HAS_I_CACHE) {
661 /* retrieve i-cache info */
662 retval = get_cache_info(dpm, cl, 1, &cache_reg);
663 if (retval != ERROR_OK)
664 goto done;
665 cache->arch[cl].i_size = decode_cache_reg(cache_reg);
666
667 LOG_DEBUG("instruction cache index %d << %d, way %d << %d",
668 cache->arch[cl].i_size.index,
669 cache->arch[cl].i_size.index_shift,
670 cache->arch[cl].i_size.way,
671 cache->arch[cl].i_size.way_shift);
672
673 LOG_DEBUG("cacheline %d bytes %d KBytes asso %d ways",
674 cache->arch[cl].i_size.linelen,
675 cache->arch[cl].i_size.cachesize,
676 cache->arch[cl].i_size.associativity);
677 }
678
679 cache->arch[cl].ctype = ctype;
680 }
681
682 /* restore selected cache */
683 dpm->instr_write_data_r0(dpm,
684 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
685 csselr);
686
687 if (retval != ERROR_OK)
688 goto done;
689
690 /* if no l2 cache initialize l1 data cache flush function function */
691 if (armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache == NULL) {
692 armv7a->armv7a_mmu.armv7a_cache.display_cache_info =
693 armv7a_handle_inner_cache_info_command;
694 armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache =
695 armv7a_cache_auto_flush_all_data;
696 }
697
698 armv7a->armv7a_mmu.armv7a_cache.info = 1;
699 done:
700 dpm->finish(dpm);
701 armv7a_read_mpidr(target);
702 return retval;
703
704 }
705
706 int armv7a_init_arch_info(struct target *target, struct armv7a_common *armv7a)
707 {
708 struct arm *arm = &armv7a->arm;
709 arm->arch_info = armv7a;
710 target->arch_info = &armv7a->arm;
711 /* target is useful in all function arm v4 5 compatible */
712 armv7a->arm.target = target;
713 armv7a->arm.common_magic = ARM_COMMON_MAGIC;
714 armv7a->common_magic = ARMV7_COMMON_MAGIC;
715 armv7a->armv7a_mmu.armv7a_cache.info = -1;
716 armv7a->armv7a_mmu.armv7a_cache.outer_cache = NULL;
717 armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache = NULL;
718 armv7a->armv7a_mmu.armv7a_cache.display_cache_info = NULL;
719 armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled = 1;
720 return ERROR_OK;
721 }
722
723 int armv7a_arch_state(struct target *target)
724 {
725 static const char *state[] = {
726 "disabled", "enabled"
727 };
728
729 struct armv7a_common *armv7a = target_to_armv7a(target);
730 struct arm *arm = &armv7a->arm;
731
732 if (armv7a->common_magic != ARMV7_COMMON_MAGIC) {
733 LOG_ERROR("BUG: called for a non-ARMv7A target");
734 return ERROR_COMMAND_SYNTAX_ERROR;
735 }
736
737 arm_arch_state(target);
738
739 if (armv7a->is_armv7r) {
740 LOG_USER("D-Cache: %s, I-Cache: %s",
741 state[armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled],
742 state[armv7a->armv7a_mmu.armv7a_cache.i_cache_enabled]);
743 } else {
744 LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
745 state[armv7a->armv7a_mmu.mmu_enabled],
746 state[armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled],
747 state[armv7a->armv7a_mmu.armv7a_cache.i_cache_enabled]);
748 }
749
750 if (arm->core_mode == ARM_MODE_ABT)
751 armv7a_show_fault_registers(target);
752 if (target->debug_reason == DBG_REASON_WATCHPOINT)
753 LOG_USER("Watchpoint triggered at PC %#08x",
754 (unsigned) armv7a->dpm.wp_pc);
755
756 return ERROR_OK;
757 }
758
759 static const struct command_registration l2_cache_commands[] = {
760 {
761 .name = "l2x",
762 .handler = handle_cache_l2x,
763 .mode = COMMAND_EXEC,
764 .help = "configure l2x cache "
765 "",
766 .usage = "[base_addr] [number_of_way]",
767 },
768 COMMAND_REGISTRATION_DONE
769
770 };
771
772 const struct command_registration l2x_cache_command_handlers[] = {
773 {
774 .name = "cache_config",
775 .mode = COMMAND_EXEC,
776 .help = "cache configuration for a target",
777 .usage = "",
778 .chain = l2_cache_commands,
779 },
780 COMMAND_REGISTRATION_DONE
781 };
782
783 const struct command_registration armv7a_command_handlers[] = {
784 {
785 .chain = dap_command_handlers,
786 },
787 {
788 .chain = l2x_cache_command_handlers,
789 },
790 {
791 .chain = arm7a_cache_command_handlers,
792 },
793 COMMAND_REGISTRATION_DONE
794 };

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)