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

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)