eecfa70976af0ed0ff3ca50788965701c6af0796
[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 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 retval = dpm->prepare(dpm);
558 if (retval != ERROR_OK)
559 goto done;
560
561 /* retrieve CTR
562 * mrc p15, 0, r0, c0, c0, 1 @ read ctr */
563 retval = dpm->instr_read_data_r0(dpm,
564 ARMV4_5_MRC(15, 0, 0, 0, 0, 1),
565 &ctr);
566 if (retval != ERROR_OK)
567 goto done;
568
569 cache->iminline = 4UL << (ctr & 0xf);
570 cache->dminline = 4UL << ((ctr & 0xf0000) >> 16);
571 LOG_DEBUG("ctr %" PRIx32 " ctr.iminline %" PRId32 " ctr.dminline %" PRId32,
572 ctr, cache->iminline, cache->dminline);
573
574 /* retrieve CLIDR
575 * mrc p15, 1, r0, c0, c0, 1 @ read clidr */
576 retval = dpm->instr_read_data_r0(dpm,
577 ARMV4_5_MRC(15, 1, 0, 0, 0, 1),
578 &clidr);
579 if (retval != ERROR_OK)
580 goto done;
581
582 cache->loc = (clidr & 0x7000000) >> 24;
583 LOG_DEBUG("Number of cache levels to PoC %" PRId32, cache->loc);
584
585 /* retrieve selected cache for later restore
586 * MRC p15, 2,<Rd>, c0, c0, 0; Read CSSELR */
587 retval = dpm->instr_read_data_r0(dpm,
588 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
589 &csselr);
590 if (retval != ERROR_OK)
591 goto done;
592
593 /* retrieve all available inner caches */
594 for (cl = 0; cl < cache->loc; clidr >>= 3, cl++) {
595
596 /* isolate cache type at current level */
597 ctype = clidr & 7;
598
599 /* skip reserved values */
600 if (ctype > CACHE_LEVEL_HAS_UNIFIED_CACHE)
601 continue;
602
603 /* separate d or unified d/i cache at this level ? */
604 if (ctype & (CACHE_LEVEL_HAS_UNIFIED_CACHE | CACHE_LEVEL_HAS_D_CACHE)) {
605 /* retrieve d-cache info */
606 retval = get_cache_info(dpm, cl, 0, &cache_reg);
607 if (retval != ERROR_OK)
608 goto done;
609 cache->arch[cl].d_u_size = decode_cache_reg(cache_reg);
610
611 LOG_DEBUG("data/unified cache index %d << %d, way %d << %d",
612 cache->arch[cl].d_u_size.index,
613 cache->arch[cl].d_u_size.index_shift,
614 cache->arch[cl].d_u_size.way,
615 cache->arch[cl].d_u_size.way_shift);
616
617 LOG_DEBUG("cacheline %d bytes %d KBytes asso %d ways",
618 cache->arch[cl].d_u_size.linelen,
619 cache->arch[cl].d_u_size.cachesize,
620 cache->arch[cl].d_u_size.associativity);
621 }
622
623 /* separate i-cache at this level ? */
624 if (ctype & CACHE_LEVEL_HAS_I_CACHE) {
625 /* retrieve i-cache info */
626 retval = get_cache_info(dpm, cl, 1, &cache_reg);
627 if (retval != ERROR_OK)
628 goto done;
629 cache->arch[cl].i_size = decode_cache_reg(cache_reg);
630
631 LOG_DEBUG("instruction cache index %d << %d, way %d << %d",
632 cache->arch[cl].i_size.index,
633 cache->arch[cl].i_size.index_shift,
634 cache->arch[cl].i_size.way,
635 cache->arch[cl].i_size.way_shift);
636
637 LOG_DEBUG("cacheline %d bytes %d KBytes asso %d ways",
638 cache->arch[cl].i_size.linelen,
639 cache->arch[cl].i_size.cachesize,
640 cache->arch[cl].i_size.associativity);
641 }
642
643 cache->arch[cl].ctype = ctype;
644 }
645
646 /* restore selected cache */
647 dpm->instr_write_data_r0(dpm,
648 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
649 csselr);
650
651 if (retval != ERROR_OK)
652 goto done;
653
654 /* if no l2 cache initialize l1 data cache flush function function */
655 if (armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache == NULL) {
656 armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache =
657 armv7a_cache_auto_flush_all_data;
658 }
659
660 armv7a->armv7a_mmu.armv7a_cache.info = 1;
661 done:
662 dpm->finish(dpm);
663 armv7a_read_mpidr(target);
664 return retval;
665
666 }
667
668 static int armv7a_setup_semihosting(struct target *target, int enable)
669 {
670 struct armv7a_common *armv7a = target_to_armv7a(target);
671 uint32_t vcr;
672 int ret;
673
674 ret = mem_ap_read_atomic_u32(armv7a->debug_ap,
675 armv7a->debug_base + CPUDBG_VCR,
676 &vcr);
677 if (ret < 0) {
678 LOG_ERROR("Failed to read VCR register\n");
679 return ret;
680 }
681
682 if (enable)
683 vcr |= DBG_VCR_SVC_MASK;
684 else
685 vcr &= ~DBG_VCR_SVC_MASK;
686
687 ret = mem_ap_write_atomic_u32(armv7a->debug_ap,
688 armv7a->debug_base + CPUDBG_VCR,
689 vcr);
690 if (ret < 0)
691 LOG_ERROR("Failed to write VCR register\n");
692
693 return ret;
694 }
695
696 int armv7a_init_arch_info(struct target *target, struct armv7a_common *armv7a)
697 {
698 struct arm *arm = &armv7a->arm;
699 arm->arch_info = armv7a;
700 target->arch_info = &armv7a->arm;
701 arm->setup_semihosting = armv7a_setup_semihosting;
702 /* target is useful in all function arm v4 5 compatible */
703 armv7a->arm.target = target;
704 armv7a->arm.common_magic = ARM_COMMON_MAGIC;
705 armv7a->common_magic = ARMV7_COMMON_MAGIC;
706 armv7a->armv7a_mmu.armv7a_cache.info = -1;
707 armv7a->armv7a_mmu.armv7a_cache.outer_cache = NULL;
708 armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache = NULL;
709 armv7a->armv7a_mmu.armv7a_cache.auto_cache_enabled = 1;
710 return ERROR_OK;
711 }
712
713 int armv7a_arch_state(struct target *target)
714 {
715 static const char *state[] = {
716 "disabled", "enabled"
717 };
718
719 struct armv7a_common *armv7a = target_to_armv7a(target);
720 struct arm *arm = &armv7a->arm;
721
722 if (armv7a->common_magic != ARMV7_COMMON_MAGIC) {
723 LOG_ERROR("BUG: called for a non-ARMv7A target");
724 return ERROR_COMMAND_SYNTAX_ERROR;
725 }
726
727 arm_arch_state(target);
728
729 if (armv7a->is_armv7r) {
730 LOG_USER("D-Cache: %s, I-Cache: %s",
731 state[armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled],
732 state[armv7a->armv7a_mmu.armv7a_cache.i_cache_enabled]);
733 } else {
734 LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
735 state[armv7a->armv7a_mmu.mmu_enabled],
736 state[armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled],
737 state[armv7a->armv7a_mmu.armv7a_cache.i_cache_enabled]);
738 }
739
740 if (arm->core_mode == ARM_MODE_ABT)
741 armv7a_show_fault_registers(target);
742 if (target->debug_reason == DBG_REASON_WATCHPOINT)
743 LOG_USER("Watchpoint triggered at PC %#08x",
744 (unsigned) armv7a->dpm.wp_pc);
745
746 return ERROR_OK;
747 }
748
749 static const struct command_registration l2_cache_commands[] = {
750 {
751 .name = "l2x",
752 .handler = handle_cache_l2x,
753 .mode = COMMAND_EXEC,
754 .help = "configure l2x cache "
755 "",
756 .usage = "[base_addr] [number_of_way]",
757 },
758 COMMAND_REGISTRATION_DONE
759
760 };
761
762 const struct command_registration l2x_cache_command_handlers[] = {
763 {
764 .name = "cache_config",
765 .mode = COMMAND_EXEC,
766 .help = "cache configuration for a target",
767 .usage = "",
768 .chain = l2_cache_commands,
769 },
770 COMMAND_REGISTRATION_DONE
771 };
772
773 const struct command_registration armv7a_command_handlers[] = {
774 {
775 .chain = l2x_cache_command_handlers,
776 },
777 {
778 .chain = arm7a_cache_command_handlers,
779 },
780 COMMAND_REGISTRATION_DONE
781 };

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)