1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2009 by David Brownell *
6 * Copyright (C) ST-Ericsson SA 2011 michel.jaouen@stericsson.com *
7 ***************************************************************************/
13 #include <helper/replacements.h>
16 #include "armv7a_mmu.h"
17 #include "arm_disassembler.h"
20 #include <helper/binarybuffer.h>
21 #include <helper/command.h>
27 #include "arm_opcodes.h"
29 #include "target_type.h"
32 static void armv7a_show_fault_registers(struct target
*target
)
34 uint32_t dfsr
, ifsr
, dfar
, ifar
;
35 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
36 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
39 retval
= dpm
->prepare(dpm
);
40 if (retval
!= ERROR_OK
)
43 /* ARMV4_5_MRC(cpnum, op1, r0, crn, crm, op2) */
45 /* c5/c0 - {data, instruction} fault status registers */
46 retval
= dpm
->instr_read_data_r0(dpm
,
47 ARMV4_5_MRC(15, 0, 0, 5, 0, 0),
49 if (retval
!= ERROR_OK
)
52 retval
= dpm
->instr_read_data_r0(dpm
,
53 ARMV4_5_MRC(15, 0, 0, 5, 0, 1),
55 if (retval
!= ERROR_OK
)
58 /* c6/c0 - {data, instruction} fault address registers */
59 retval
= dpm
->instr_read_data_r0(dpm
,
60 ARMV4_5_MRC(15, 0, 0, 6, 0, 0),
62 if (retval
!= ERROR_OK
)
65 retval
= dpm
->instr_read_data_r0(dpm
,
66 ARMV4_5_MRC(15, 0, 0, 6, 0, 2),
68 if (retval
!= ERROR_OK
)
71 LOG_USER("Data fault registers DFSR: %8.8" PRIx32
72 ", DFAR: %8.8" PRIx32
, dfsr
, dfar
);
73 LOG_USER("Instruction fault registers IFSR: %8.8" PRIx32
74 ", IFAR: %8.8" PRIx32
, ifsr
, ifar
);
77 /* (void) */ dpm
->finish(dpm
);
81 /* retrieve main id register */
82 static int armv7a_read_midr(struct target
*target
)
84 int retval
= ERROR_FAIL
;
85 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
86 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
88 retval
= dpm
->prepare(dpm
);
89 if (retval
!= ERROR_OK
)
91 /* MRC p15,0,<Rd>,c0,c0,0; read main id register*/
93 retval
= dpm
->instr_read_data_r0(dpm
,
94 ARMV4_5_MRC(15, 0, 0, 0, 0, 0),
96 if (retval
!= ERROR_OK
)
99 armv7a
->rev
= (midr
& 0xf);
100 armv7a
->partnum
= (midr
>> 4) & 0xfff;
101 armv7a
->arch
= (midr
>> 16) & 0xf;
102 armv7a
->variant
= (midr
>> 20) & 0xf;
103 armv7a
->implementor
= (midr
>> 24) & 0xff;
104 LOG_DEBUG("%s rev %" PRIx32
", partnum %" PRIx32
", arch %" PRIx32
105 ", variant %" PRIx32
", implementor %" PRIx32
,
111 armv7a
->implementor
);
118 int armv7a_read_ttbcr(struct target
*target
)
120 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
121 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
122 uint32_t ttbcr
, ttbcr_n
;
126 retval
= dpm
->prepare(dpm
);
127 if (retval
!= ERROR_OK
)
130 /* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
131 retval
= dpm
->instr_read_data_r0(dpm
,
132 ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
134 if (retval
!= ERROR_OK
)
137 LOG_DEBUG("ttbcr %" PRIx32
, ttbcr
);
139 ttbcr_n
= ttbcr
& 0x7;
140 armv7a
->armv7a_mmu
.ttbcr
= ttbcr
;
141 armv7a
->armv7a_mmu
.cached
= 1;
143 for (ttbidx
= 0; ttbidx
< 2; ttbidx
++) {
144 /* MRC p15,0,<Rt>,c2,c0,ttbidx */
145 retval
= dpm
->instr_read_data_r0(dpm
,
146 ARMV4_5_MRC(15, 0, 0, 2, 0, ttbidx
),
147 &armv7a
->armv7a_mmu
.ttbr
[ttbidx
]);
148 if (retval
!= ERROR_OK
)
153 * ARM Architecture Reference Manual (ARMv7-A and ARMv7-R edition),
154 * document # ARM DDI 0406C
156 armv7a
->armv7a_mmu
.ttbr_range
[0] = 0xffffffff >> ttbcr_n
;
157 armv7a
->armv7a_mmu
.ttbr_range
[1] = 0xffffffff;
158 armv7a
->armv7a_mmu
.ttbr_mask
[0] = 0xffffffff << (14 - ttbcr_n
);
159 armv7a
->armv7a_mmu
.ttbr_mask
[1] = 0xffffffff << 14;
160 armv7a
->armv7a_mmu
.cached
= 1;
162 retval
= armv7a_read_midr(target
);
163 if (retval
!= ERROR_OK
)
166 /* FIXME: why this special case based on part number? */
167 if ((armv7a
->partnum
& 0xf) == 0) {
168 /* ARM DDI 0344H , ARM DDI 0407F */
169 armv7a
->armv7a_mmu
.ttbr_mask
[0] = 7 << (32 - ttbcr_n
);
172 LOG_DEBUG("ttbr1 %s, ttbr0_mask %" PRIx32
" ttbr1_mask %" PRIx32
,
173 (ttbcr_n
!= 0) ? "used" : "not used",
174 armv7a
->armv7a_mmu
.ttbr_mask
[0],
175 armv7a
->armv7a_mmu
.ttbr_mask
[1]);
182 /* FIXME: remove it */
183 static int armv7a_l2x_cache_init(struct target
*target
, uint32_t base
, uint32_t way
)
185 struct armv7a_l2x_cache
*l2x_cache
;
186 struct target_list
*head
;
188 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
189 l2x_cache
= calloc(1, sizeof(struct armv7a_l2x_cache
));
190 l2x_cache
->base
= base
;
191 l2x_cache
->way
= way
;
192 /*LOG_INFO("cache l2 initialized base %x way %d",
193 l2x_cache->base,l2x_cache->way);*/
194 if (armv7a
->armv7a_mmu
.armv7a_cache
.outer_cache
)
195 LOG_INFO("outer cache already initialized\n");
196 armv7a
->armv7a_mmu
.armv7a_cache
.outer_cache
= l2x_cache
;
197 /* initialize all target in this cluster (smp target)
198 * l2 cache must be configured after smp declaration */
199 foreach_smp_target(head
, target
->smp_targets
) {
200 struct target
*curr
= head
->target
;
201 if (curr
!= target
) {
202 armv7a
= target_to_armv7a(curr
);
203 if (armv7a
->armv7a_mmu
.armv7a_cache
.outer_cache
)
204 LOG_ERROR("smp target : outer cache already initialized\n");
205 armv7a
->armv7a_mmu
.armv7a_cache
.outer_cache
= l2x_cache
;
211 /* FIXME: remove it */
212 COMMAND_HANDLER(handle_cache_l2x
)
214 struct target
*target
= get_current_target(CMD_CTX
);
218 return ERROR_COMMAND_SYNTAX_ERROR
;
220 /* command_print(CMD, "%s %s", CMD_ARGV[0], CMD_ARGV[1]); */
221 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], base
);
222 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], way
);
224 /* AP address is in bits 31:24 of DP_SELECT */
225 armv7a_l2x_cache_init(target
, base
, way
);
230 int armv7a_handle_cache_info_command(struct command_invocation
*cmd
,
231 struct armv7a_cache_common
*armv7a_cache
)
233 struct armv7a_l2x_cache
*l2x_cache
= (struct armv7a_l2x_cache
*)
234 (armv7a_cache
->outer_cache
);
238 if (armv7a_cache
->info
== -1) {
239 command_print(cmd
, "cache not yet identified");
243 for (cl
= 0; cl
< armv7a_cache
->loc
; cl
++) {
244 struct armv7a_arch_cache
*arch
= &(armv7a_cache
->arch
[cl
]);
246 if (arch
->ctype
& 1) {
248 "L%d I-Cache: linelen %" PRIu32
249 ", associativity %" PRIu32
251 ", cachesize %" PRIu32
" KBytes",
253 arch
->i_size
.linelen
,
254 arch
->i_size
.associativity
,
256 arch
->i_size
.cachesize
);
259 if (arch
->ctype
>= 2) {
261 "L%d D-Cache: linelen %" PRIu32
262 ", associativity %" PRIu32
264 ", cachesize %" PRIu32
" KBytes",
266 arch
->d_u_size
.linelen
,
267 arch
->d_u_size
.associativity
,
268 arch
->d_u_size
.nsets
,
269 arch
->d_u_size
.cachesize
);
274 command_print(cmd
, "Outer unified cache Base Address 0x%" PRIx32
", %" PRIu32
" ways",
275 l2x_cache
->base
, l2x_cache
->way
);
280 /* retrieve core id cluster id */
281 static int armv7a_read_mpidr(struct target
*target
)
283 int retval
= ERROR_FAIL
;
284 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
285 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
287 retval
= dpm
->prepare(dpm
);
288 if (retval
!= ERROR_OK
)
290 /* MRC p15,0,<Rd>,c0,c0,5; read Multiprocessor ID register*/
292 retval
= dpm
->instr_read_data_r0(dpm
,
293 ARMV4_5_MRC(15, 0, 0, 0, 0, 5),
295 if (retval
!= ERROR_OK
)
298 /* Is register in Multiprocessing Extensions register format? */
299 if (mpidr
& MPIDR_MP_EXT
) {
300 LOG_DEBUG("%s: MPIDR 0x%" PRIx32
, target_name(target
), mpidr
);
301 armv7a
->multi_processor_system
= (mpidr
>> 30) & 1;
302 armv7a
->multi_threading_processor
= (mpidr
>> 24) & 1;
303 armv7a
->level2_id
= (mpidr
>> 16) & 0xf;
304 armv7a
->cluster_id
= (mpidr
>> 8) & 0xf;
305 armv7a
->cpu_id
= mpidr
& 0xf;
306 LOG_INFO("%s: MPIDR level2 %x, cluster %x, core %x, %s, %s",
311 armv7a
->multi_processor_system
== 0 ? "multi core" : "mono core",
312 armv7a
->multi_threading_processor
== 1 ? "SMT" : "no SMT");
315 LOG_ERROR("MPIDR not in multiprocessor format");
324 static int get_cache_info(struct arm_dpm
*dpm
, int cl
, int ct
, uint32_t *cache_reg
)
326 int retval
= ERROR_OK
;
328 /* select cache level */
329 retval
= dpm
->instr_write_data_r0(dpm
,
330 ARMV4_5_MCR(15, 2, 0, 0, 0, 0),
331 (cl
<< 1) | (ct
== 1 ? 1 : 0));
332 if (retval
!= ERROR_OK
)
335 retval
= dpm
->instr_read_data_r0(dpm
,
336 ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
342 static struct armv7a_cachesize
decode_cache_reg(uint32_t cache_reg
)
344 struct armv7a_cachesize size
;
347 size
.linelen
= 16 << (cache_reg
& 0x7);
348 size
.associativity
= ((cache_reg
>> 3) & 0x3ff) + 1;
349 size
.nsets
= ((cache_reg
>> 13) & 0x7fff) + 1;
350 size
.cachesize
= size
.linelen
* size
.associativity
* size
.nsets
/ 1024;
352 /* compute info for set way operation on cache */
353 size
.index_shift
= (cache_reg
& 0x7) + 4;
354 size
.index
= (cache_reg
>> 13) & 0x7fff;
355 size
.way
= ((cache_reg
>> 3) & 0x3ff);
357 while (((size
.way
<< i
) & 0x80000000) == 0)
364 int armv7a_identify_cache(struct target
*target
)
366 /* read cache descriptor */
367 int retval
= ERROR_FAIL
;
368 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
369 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
370 uint32_t csselr
, clidr
, ctr
;
373 struct armv7a_cache_common
*cache
=
374 &(armv7a
->armv7a_mmu
.armv7a_cache
);
376 retval
= dpm
->prepare(dpm
);
377 if (retval
!= ERROR_OK
)
381 * mrc p15, 0, r0, c0, c0, 1 @ read ctr */
382 retval
= dpm
->instr_read_data_r0(dpm
,
383 ARMV4_5_MRC(15, 0, 0, 0, 0, 1),
385 if (retval
!= ERROR_OK
)
388 cache
->iminline
= 4UL << (ctr
& 0xf);
389 cache
->dminline
= 4UL << ((ctr
& 0xf0000) >> 16);
390 LOG_DEBUG("ctr %" PRIx32
" ctr.iminline %" PRIu32
" ctr.dminline %" PRIu32
,
391 ctr
, cache
->iminline
, cache
->dminline
);
394 * mrc p15, 1, r0, c0, c0, 1 @ read clidr */
395 retval
= dpm
->instr_read_data_r0(dpm
,
396 ARMV4_5_MRC(15, 1, 0, 0, 0, 1),
398 if (retval
!= ERROR_OK
)
401 cache
->loc
= (clidr
& 0x7000000) >> 24;
402 LOG_DEBUG("Number of cache levels to PoC %" PRId32
, cache
->loc
);
404 /* retrieve selected cache for later restore
405 * MRC p15, 2,<Rd>, c0, c0, 0; Read CSSELR */
406 retval
= dpm
->instr_read_data_r0(dpm
,
407 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
409 if (retval
!= ERROR_OK
)
412 /* retrieve all available inner caches */
413 for (cl
= 0; cl
< cache
->loc
; clidr
>>= 3, cl
++) {
415 /* isolate cache type at current level */
418 /* skip reserved values */
419 if (ctype
> CACHE_LEVEL_HAS_UNIFIED_CACHE
)
422 /* separate d or unified d/i cache at this level ? */
423 if (ctype
& (CACHE_LEVEL_HAS_UNIFIED_CACHE
| CACHE_LEVEL_HAS_D_CACHE
)) {
424 /* retrieve d-cache info */
425 retval
= get_cache_info(dpm
, cl
, 0, &cache_reg
);
426 if (retval
!= ERROR_OK
)
428 cache
->arch
[cl
].d_u_size
= decode_cache_reg(cache_reg
);
430 LOG_DEBUG("data/unified cache index %" PRIu32
" << %" PRIu32
", way %" PRIu32
" << %" PRIu32
,
431 cache
->arch
[cl
].d_u_size
.index
,
432 cache
->arch
[cl
].d_u_size
.index_shift
,
433 cache
->arch
[cl
].d_u_size
.way
,
434 cache
->arch
[cl
].d_u_size
.way_shift
);
436 LOG_DEBUG("cacheline %" PRIu32
" bytes %" PRIu32
" KBytes asso %" PRIu32
" ways",
437 cache
->arch
[cl
].d_u_size
.linelen
,
438 cache
->arch
[cl
].d_u_size
.cachesize
,
439 cache
->arch
[cl
].d_u_size
.associativity
);
442 /* separate i-cache at this level ? */
443 if (ctype
& CACHE_LEVEL_HAS_I_CACHE
) {
444 /* retrieve i-cache info */
445 retval
= get_cache_info(dpm
, cl
, 1, &cache_reg
);
446 if (retval
!= ERROR_OK
)
448 cache
->arch
[cl
].i_size
= decode_cache_reg(cache_reg
);
450 LOG_DEBUG("instruction cache index %" PRIu32
" << %" PRIu32
", way %" PRIu32
" << %" PRIu32
,
451 cache
->arch
[cl
].i_size
.index
,
452 cache
->arch
[cl
].i_size
.index_shift
,
453 cache
->arch
[cl
].i_size
.way
,
454 cache
->arch
[cl
].i_size
.way_shift
);
456 LOG_DEBUG("cacheline %" PRIu32
" bytes %" PRIu32
" KBytes asso %" PRIu32
" ways",
457 cache
->arch
[cl
].i_size
.linelen
,
458 cache
->arch
[cl
].i_size
.cachesize
,
459 cache
->arch
[cl
].i_size
.associativity
);
462 cache
->arch
[cl
].ctype
= ctype
;
465 /* restore selected cache */
466 dpm
->instr_write_data_r0(dpm
,
467 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
470 if (retval
!= ERROR_OK
)
473 /* if no l2 cache initialize l1 data cache flush function function */
474 if (!armv7a
->armv7a_mmu
.armv7a_cache
.flush_all_data_cache
) {
475 armv7a
->armv7a_mmu
.armv7a_cache
.flush_all_data_cache
=
476 armv7a_cache_auto_flush_all_data
;
479 armv7a
->armv7a_mmu
.armv7a_cache
.info
= 1;
482 armv7a_read_mpidr(target
);
487 static int armv7a_setup_semihosting(struct target
*target
, int enable
)
489 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
493 ret
= mem_ap_read_atomic_u32(armv7a
->debug_ap
,
494 armv7a
->debug_base
+ CPUDBG_VCR
,
497 LOG_ERROR("Failed to read VCR register\n");
502 vcr
|= DBG_VCR_SVC_MASK
;
504 vcr
&= ~DBG_VCR_SVC_MASK
;
506 ret
= mem_ap_write_atomic_u32(armv7a
->debug_ap
,
507 armv7a
->debug_base
+ CPUDBG_VCR
,
510 LOG_ERROR("Failed to write VCR register\n");
515 int armv7a_init_arch_info(struct target
*target
, struct armv7a_common
*armv7a
)
517 struct arm
*arm
= &armv7a
->arm
;
518 arm
->arch_info
= armv7a
;
519 target
->arch_info
= &armv7a
->arm
;
520 arm
->setup_semihosting
= armv7a_setup_semihosting
;
521 /* target is useful in all function arm v4 5 compatible */
522 armv7a
->arm
.target
= target
;
523 armv7a
->arm
.common_magic
= ARM_COMMON_MAGIC
;
524 armv7a
->common_magic
= ARMV7_COMMON_MAGIC
;
525 armv7a
->armv7a_mmu
.armv7a_cache
.info
= -1;
526 armv7a
->armv7a_mmu
.armv7a_cache
.outer_cache
= NULL
;
527 armv7a
->armv7a_mmu
.armv7a_cache
.flush_all_data_cache
= NULL
;
528 armv7a
->armv7a_mmu
.armv7a_cache
.auto_cache_enabled
= 1;
532 int armv7a_arch_state(struct target
*target
)
534 static const char *state
[] = {
535 "disabled", "enabled"
538 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
539 struct arm
*arm
= &armv7a
->arm
;
541 if (armv7a
->common_magic
!= ARMV7_COMMON_MAGIC
) {
542 LOG_ERROR("BUG: called for a non-ARMv7A target");
543 return ERROR_COMMAND_SYNTAX_ERROR
;
546 arm_arch_state(target
);
548 if (armv7a
->is_armv7r
) {
549 LOG_USER("D-Cache: %s, I-Cache: %s",
550 state
[armv7a
->armv7a_mmu
.armv7a_cache
.d_u_cache_enabled
],
551 state
[armv7a
->armv7a_mmu
.armv7a_cache
.i_cache_enabled
]);
553 LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
554 state
[armv7a
->armv7a_mmu
.mmu_enabled
],
555 state
[armv7a
->armv7a_mmu
.armv7a_cache
.d_u_cache_enabled
],
556 state
[armv7a
->armv7a_mmu
.armv7a_cache
.i_cache_enabled
]);
559 if (arm
->core_mode
== ARM_MODE_ABT
)
560 armv7a_show_fault_registers(target
);
565 static const struct command_registration l2_cache_commands
[] = {
568 .handler
= handle_cache_l2x
,
569 .mode
= COMMAND_EXEC
,
570 .help
= "configure l2x cache",
571 .usage
= "[base_addr] [number_of_way]",
573 COMMAND_REGISTRATION_DONE
577 static const struct command_registration l2x_cache_command_handlers
[] = {
579 .name
= "cache_config",
580 .mode
= COMMAND_EXEC
,
581 .help
= "cache configuration for a target",
583 .chain
= l2_cache_commands
,
585 COMMAND_REGISTRATION_DONE
588 const struct command_registration armv7a_command_handlers
[] = {
590 .chain
= l2x_cache_command_handlers
,
593 .chain
= arm7a_cache_command_handlers
,
595 COMMAND_REGISTRATION_DONE