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

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)