1 /***************************************************************************
2 * Copyright (C) 2009 by David Brownell *
4 * Copyright (C) ST-Ericsson SA 2011 michel.jaouen@stericsson.com *
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. *
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. *
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 ***************************************************************************/
26 #include <helper/replacements.h>
29 #include "arm_disassembler.h"
32 #include <helper/binarybuffer.h>
33 #include <helper/command.h>
39 #include "arm_opcodes.h"
41 #include "target_type.h"
43 static void armv7a_show_fault_registers(struct target
*target
)
45 uint32_t dfsr
, ifsr
, dfar
, ifar
;
46 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
47 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
50 retval
= dpm
->prepare(dpm
);
51 if (retval
!= ERROR_OK
)
54 /* ARMV4_5_MRC(cpnum, op1, r0, CRn, CRm, op2) */
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),
60 if (retval
!= ERROR_OK
)
63 retval
= dpm
->instr_read_data_r0(dpm
,
64 ARMV4_5_MRC(15, 0, 0, 5, 0, 1),
66 if (retval
!= ERROR_OK
)
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),
73 if (retval
!= ERROR_OK
)
76 retval
= dpm
->instr_read_data_r0(dpm
,
77 ARMV4_5_MRC(15, 0, 0, 6, 0, 2),
79 if (retval
!= ERROR_OK
)
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
);
88 /* (void) */ dpm
->finish(dpm
);
92 /* retrieve main id register */
93 static int armv7a_read_midr(struct target
*target
)
95 int retval
= ERROR_FAIL
;
96 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
97 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
99 retval
= dpm
->prepare(dpm
);
100 if (retval
!= ERROR_OK
)
102 /* MRC p15,0,<Rd>,c0,c0,0; read main id register*/
104 retval
= dpm
->instr_read_data_r0(dpm
,
105 ARMV4_5_MRC(15, 0, 0, 0, 0, 0),
107 if (retval
!= ERROR_OK
)
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
,
122 armv7a
->implementor
);
129 static int armv7a_read_ttbcr(struct target
*target
)
131 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
132 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
134 uint32_t ttbr0
, ttbr1
;
135 int retval
= dpm
->prepare(dpm
);
136 if (retval
!= ERROR_OK
)
138 /* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
139 retval
= dpm
->instr_read_data_r0(dpm
,
140 ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
142 if (retval
!= ERROR_OK
)
145 retval
= dpm
->instr_read_data_r0(dpm
,
146 ARMV4_5_MRC(15, 0, 0, 2, 0, 0),
148 if (retval
!= ERROR_OK
)
151 retval
= dpm
->instr_read_data_r0(dpm
,
152 ARMV4_5_MRC(15, 0, 0, 2, 0, 1),
154 if (retval
!= ERROR_OK
)
157 LOG_INFO("ttbcr %" PRIx32
" ttbr0 %" PRIx32
" ttbr1 %" PRIx32
, ttbcr
, ttbr0
, ttbr1
);
159 armv7a
->armv7a_mmu
.ttbr1_used
= ((ttbcr
& 0x7) != 0) ? 1 : 0;
160 armv7a
->armv7a_mmu
.ttbr0_mask
= 0;
161 armv7a
->armv7a_mmu
.ttbcr
= ttbcr
;
163 retval
= armv7a_read_midr(target
);
164 if (retval
!= ERROR_OK
)
167 if (armv7a
->partnum
& 0xf) {
169 * ARM Architecture Reference Manual (ARMv7-A and ARMv7-Redition),
170 * document # ARM DDI 0406C
172 armv7a
->armv7a_mmu
.ttbr0_mask
= 1 << (14 - ((ttbcr
& 0x7)));
174 /* ARM DDI 0344H , ARM DDI 0407F */
175 armv7a
->armv7a_mmu
.ttbr0_mask
= 7 << (32 - ((ttbcr
& 0x7)));
176 /* fix me , default is hard coded LINUX border */
177 armv7a
->armv7a_mmu
.os_border
= 0xc0000000;
180 LOG_DEBUG("ttbr1 %s, ttbr0_mask %" PRIx32
,
181 armv7a
->armv7a_mmu
.ttbr1_used
? "used" : "not used",
182 armv7a
->armv7a_mmu
.ttbr0_mask
);
184 if (armv7a
->armv7a_mmu
.ttbr1_used
== 1) {
185 LOG_INFO("SVC access above %" PRIx32
,
186 (0xffffffff & armv7a
->armv7a_mmu
.ttbr0_mask
));
187 armv7a
->armv7a_mmu
.os_border
= 0xffffffff & armv7a
->armv7a_mmu
.ttbr0_mask
;
194 /* method adapted to cortex A : reused arm v4 v5 method*/
195 int armv7a_mmu_translate_va(struct target
*target
, uint32_t va
, uint32_t *val
)
197 uint32_t first_lvl_descriptor
= 0x0;
198 uint32_t second_lvl_descriptor
= 0x0;
200 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
201 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
202 uint32_t ttb
= 0; /* default ttb0 */
205 retval
= dpm
->prepare(dpm
);
206 if (retval
!= ERROR_OK
)
209 /* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
210 retval
= dpm
->instr_read_data_r0(dpm
,
211 ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
213 if (retval
!= ERROR_OK
)
216 /* if ttbcr has changed, re-read the information */
217 if (armv7a
->armv7a_mmu
.ttbcr
!= ttbcr
)
218 armv7a_read_ttbcr(target
);
219 if ((armv7a
->armv7a_mmu
.ttbr1_used
) &&
220 (va
> (0xffffffff & armv7a
->armv7a_mmu
.ttbr0_mask
))) {
224 /* MRC p15,0,<Rt>,c2,c0,ttb */
225 retval
= dpm
->instr_read_data_r0(dpm
,
226 ARMV4_5_MRC(15, 0, 0, 2, 0, ttb
),
228 if (retval
!= ERROR_OK
)
230 retval
= armv7a
->armv7a_mmu
.read_physical_memory(target
,
231 (ttb
& 0xffffc000) | ((va
& 0xfff00000) >> 18),
232 4, 1, (uint8_t *)&first_lvl_descriptor
);
233 if (retval
!= ERROR_OK
)
235 first_lvl_descriptor
= target_buffer_get_u32(target
, (uint8_t *)
236 &first_lvl_descriptor
);
237 /* reuse armv4_5 piece of code, specific armv7a changes may come later */
238 LOG_DEBUG("1st lvl desc: %8.8" PRIx32
"", first_lvl_descriptor
);
240 if ((first_lvl_descriptor
& 0x3) == 0) {
241 LOG_ERROR("Address translation failure");
242 return ERROR_TARGET_TRANSLATION_FAULT
;
246 if ((first_lvl_descriptor
& 0x40002) == 2) {
247 /* section descriptor */
248 *val
= (first_lvl_descriptor
& 0xfff00000) | (va
& 0x000fffff);
250 } else if ((first_lvl_descriptor
& 0x40002) == 0x40002) {
251 /* supersection descriptor */
252 if (first_lvl_descriptor
& 0x00f001e0) {
253 LOG_ERROR("Physical address does not fit into 32 bits");
254 return ERROR_TARGET_TRANSLATION_FAULT
;
256 *val
= (first_lvl_descriptor
& 0xff000000) | (va
& 0x00ffffff);
261 retval
= armv7a
->armv7a_mmu
.read_physical_memory(target
,
262 (first_lvl_descriptor
& 0xfffffc00) | ((va
& 0x000ff000) >> 10),
263 4, 1, (uint8_t *)&second_lvl_descriptor
);
264 if (retval
!= ERROR_OK
)
267 second_lvl_descriptor
= target_buffer_get_u32(target
, (uint8_t *)
268 &second_lvl_descriptor
);
270 LOG_DEBUG("2nd lvl desc: %8.8" PRIx32
"", second_lvl_descriptor
);
272 if ((second_lvl_descriptor
& 0x3) == 0) {
273 LOG_ERROR("Address translation failure");
274 return ERROR_TARGET_TRANSLATION_FAULT
;
277 if ((second_lvl_descriptor
& 0x3) == 1) {
278 /* large page descriptor */
279 *val
= (second_lvl_descriptor
& 0xffff0000) | (va
& 0x0000ffff);
281 /* small page descriptor */
282 *val
= (second_lvl_descriptor
& 0xfffff000) | (va
& 0x00000fff);
291 /* V7 method VA TO PA */
292 int armv7a_mmu_translate_va_pa(struct target
*target
, uint32_t va
,
293 uint32_t *val
, int meminfo
)
295 int retval
= ERROR_FAIL
;
296 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
297 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
298 uint32_t virt
= va
& ~0xfff;
299 uint32_t NOS
, NS
, INNER
, OUTER
;
301 retval
= dpm
->prepare(dpm
);
302 if (retval
!= ERROR_OK
)
304 /* mmu must be enable in order to get a correct translation
305 * use VA to PA CP15 register for conversion */
306 retval
= dpm
->instr_write_data_r0(dpm
,
307 ARMV4_5_MCR(15, 0, 0, 7, 8, 0),
309 if (retval
!= ERROR_OK
)
311 retval
= dpm
->instr_read_data_r0(dpm
,
312 ARMV4_5_MRC(15, 0, 0, 7, 4, 0),
314 /* decode memory attribute */
315 NOS
= (*val
>> 10) & 1; /* Not Outer shareable */
316 NS
= (*val
>> 9) & 1; /* Non secure */
317 INNER
= (*val
>> 4) & 0x7;
318 OUTER
= (*val
>> 2) & 0x3;
320 if (retval
!= ERROR_OK
)
322 *val
= (*val
& ~0xfff) + (va
& 0xfff);
324 LOG_WARNING("virt = phys : MMU disable !!");
326 LOG_INFO("%" PRIx32
" : %" PRIx32
" %s outer shareable %s secured",
328 NOS
== 1 ? "not" : " ",
329 NS
== 1 ? "not" : "");
332 LOG_INFO("outer: Non-Cacheable");
335 LOG_INFO("outer: Write-Back, Write-Allocate");
338 LOG_INFO("outer: Write-Through, No Write-Allocate");
341 LOG_INFO("outer: Write-Back, no Write-Allocate");
346 LOG_INFO("inner: Non-Cacheable");
349 LOG_INFO("inner: Strongly-ordered");
352 LOG_INFO("inner: Device");
355 LOG_INFO("inner: Write-Back, Write-Allocate");
358 LOG_INFO("inner: Write-Through");
361 LOG_INFO("inner: Write-Back, no Write-Allocate");
364 LOG_INFO("inner: %" PRIx32
" ???", INNER
);
374 static int armv7a_handle_inner_cache_info_command(struct command_context
*cmd_ctx
,
375 struct armv7a_cache_common
*armv7a_cache
)
377 if (armv7a_cache
->ctype
== -1) {
378 command_print(cmd_ctx
, "cache not yet identified");
382 command_print(cmd_ctx
,
383 "D-Cache: linelen %" PRIi32
", associativity %" PRIi32
", nsets %" PRIi32
", cachesize %" PRId32
" KBytes",
384 armv7a_cache
->d_u_size
.linelen
,
385 armv7a_cache
->d_u_size
.associativity
,
386 armv7a_cache
->d_u_size
.nsets
,
387 armv7a_cache
->d_u_size
.cachesize
);
389 command_print(cmd_ctx
,
390 "I-Cache: linelen %" PRIi32
", associativity %" PRIi32
", nsets %" PRIi32
", cachesize %" PRId32
" KBytes",
391 armv7a_cache
->i_size
.linelen
,
392 armv7a_cache
->i_size
.associativity
,
393 armv7a_cache
->i_size
.nsets
,
394 armv7a_cache
->i_size
.cachesize
);
399 static int _armv7a_flush_all_data(struct target
*target
)
401 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
402 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
403 struct armv7a_cachesize
*d_u_size
=
404 &(armv7a
->armv7a_mmu
.armv7a_cache
.d_u_size
);
405 int32_t c_way
, c_index
= d_u_size
->index
;
407 /* check that cache data is on at target halt */
408 if (!armv7a
->armv7a_mmu
.armv7a_cache
.d_u_cache_enabled
) {
409 LOG_INFO("flushed not performed :cache not on at target halt");
412 retval
= dpm
->prepare(dpm
);
413 if (retval
!= ERROR_OK
)
416 c_way
= d_u_size
->way
;
418 uint32_t value
= (c_index
<< d_u_size
->index_shift
)
419 | (c_way
<< d_u_size
->way_shift
);
421 /* LOG_INFO ("%d %d %x",c_way,c_index,value); */
422 retval
= dpm
->instr_write_data_r0(dpm
,
423 ARMV4_5_MCR(15, 0, 0, 7, 14, 2),
425 if (retval
!= ERROR_OK
)
428 } while (c_way
>= 0);
430 } while (c_index
>= 0);
433 LOG_ERROR("flushed failed");
438 static int armv7a_flush_all_data(struct target
*target
)
440 int retval
= ERROR_FAIL
;
441 /* check that armv7a_cache is correctly identify */
442 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
443 if (armv7a
->armv7a_mmu
.armv7a_cache
.ctype
== -1) {
444 LOG_ERROR("trying to flush un-identified cache");
449 /* look if all the other target have been flushed in order to flush level
451 struct target_list
*head
;
454 while (head
!= (struct target_list
*)NULL
) {
456 if (curr
->state
== TARGET_HALTED
) {
457 LOG_INFO("Wait flushing data l1 on core %" PRId32
, curr
->coreid
);
458 retval
= _armv7a_flush_all_data(curr
);
463 retval
= _armv7a_flush_all_data(target
);
467 /* L2 is not specific to armv7a a specific file is needed */
468 static int armv7a_l2x_flush_all_data(struct target
*target
)
471 #define L2X0_CLEAN_INV_WAY 0x7FC
472 int retval
= ERROR_FAIL
;
473 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
474 struct armv7a_l2x_cache
*l2x_cache
= (struct armv7a_l2x_cache
*)
475 (armv7a
->armv7a_mmu
.armv7a_cache
.l2_cache
);
476 uint32_t base
= l2x_cache
->base
;
477 uint32_t l2_way
= l2x_cache
->way
;
478 uint32_t l2_way_val
= (1 << l2_way
) - 1;
479 retval
= armv7a_flush_all_data(target
);
480 if (retval
!= ERROR_OK
)
482 retval
= target
->type
->write_phys_memory(target
,
483 (uint32_t)(base
+(uint32_t)L2X0_CLEAN_INV_WAY
),
486 (uint8_t *)&l2_way_val
);
490 static int armv7a_handle_l2x_cache_info_command(struct command_context
*cmd_ctx
,
491 struct armv7a_cache_common
*armv7a_cache
)
494 struct armv7a_l2x_cache
*l2x_cache
= (struct armv7a_l2x_cache
*)
495 (armv7a_cache
->l2_cache
);
497 if (armv7a_cache
->ctype
== -1) {
498 command_print(cmd_ctx
, "cache not yet identified");
502 command_print(cmd_ctx
,
503 "L1 D-Cache: linelen %" PRIi32
", associativity %" PRIi32
", nsets %" PRIi32
", cachesize %" PRId32
" KBytes",
504 armv7a_cache
->d_u_size
.linelen
,
505 armv7a_cache
->d_u_size
.associativity
,
506 armv7a_cache
->d_u_size
.nsets
,
507 armv7a_cache
->d_u_size
.cachesize
);
509 command_print(cmd_ctx
,
510 "L1 I-Cache: linelen %" PRIi32
", associativity %" PRIi32
", nsets %" PRIi32
", cachesize %" PRId32
" KBytes",
511 armv7a_cache
->i_size
.linelen
,
512 armv7a_cache
->i_size
.associativity
,
513 armv7a_cache
->i_size
.nsets
,
514 armv7a_cache
->i_size
.cachesize
);
515 command_print(cmd_ctx
, "L2 unified cache Base Address 0x%" PRIx32
", %" PRId32
" ways",
516 l2x_cache
->base
, l2x_cache
->way
);
523 static int armv7a_l2x_cache_init(struct target
*target
, uint32_t base
, uint32_t way
)
525 struct armv7a_l2x_cache
*l2x_cache
;
526 struct target_list
*head
= target
->head
;
529 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
530 l2x_cache
= calloc(1, sizeof(struct armv7a_l2x_cache
));
531 l2x_cache
->base
= base
;
532 l2x_cache
->way
= way
;
533 /*LOG_INFO("cache l2 initialized base %x way %d",
534 l2x_cache->base,l2x_cache->way);*/
535 if (armv7a
->armv7a_mmu
.armv7a_cache
.l2_cache
)
536 LOG_INFO("cache l2 already initialized\n");
537 armv7a
->armv7a_mmu
.armv7a_cache
.l2_cache
= l2x_cache
;
538 /* initialize l1 / l2x cache function */
539 armv7a
->armv7a_mmu
.armv7a_cache
.flush_all_data_cache
540 = armv7a_l2x_flush_all_data
;
541 armv7a
->armv7a_mmu
.armv7a_cache
.display_cache_info
=
542 armv7a_handle_l2x_cache_info_command
;
543 /* initialize all target in this cluster (smp target)
544 * l2 cache must be configured after smp declaration */
545 while (head
!= (struct target_list
*)NULL
) {
547 if (curr
!= target
) {
548 armv7a
= target_to_armv7a(curr
);
549 if (armv7a
->armv7a_mmu
.armv7a_cache
.l2_cache
)
550 LOG_ERROR("smp target : cache l2 already initialized\n");
551 armv7a
->armv7a_mmu
.armv7a_cache
.l2_cache
= l2x_cache
;
552 armv7a
->armv7a_mmu
.armv7a_cache
.flush_all_data_cache
=
553 armv7a_l2x_flush_all_data
;
554 armv7a
->armv7a_mmu
.armv7a_cache
.display_cache_info
=
555 armv7a_handle_l2x_cache_info_command
;
562 COMMAND_HANDLER(handle_cache_l2x
)
564 struct target
*target
= get_current_target(CMD_CTX
);
568 return ERROR_COMMAND_SYNTAX_ERROR
;
570 /* command_print(CMD_CTX, "%s %s", CMD_ARGV[0], CMD_ARGV[1]); */
571 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], base
);
572 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], way
);
574 /* AP address is in bits 31:24 of DP_SELECT */
575 armv7a_l2x_cache_init(target
, base
, way
);
580 int armv7a_handle_cache_info_command(struct command_context
*cmd_ctx
,
581 struct armv7a_cache_common
*armv7a_cache
)
583 if (armv7a_cache
->ctype
== -1) {
584 command_print(cmd_ctx
, "cache not yet identified");
588 if (armv7a_cache
->display_cache_info
)
589 armv7a_cache
->display_cache_info(cmd_ctx
, armv7a_cache
);
593 /* retrieve core id cluster id */
594 static int armv7a_read_mpidr(struct target
*target
)
596 int retval
= ERROR_FAIL
;
597 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
598 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
600 retval
= dpm
->prepare(dpm
);
601 if (retval
!= ERROR_OK
)
603 /* MRC p15,0,<Rd>,c0,c0,5; read Multiprocessor ID register*/
605 retval
= dpm
->instr_read_data_r0(dpm
,
606 ARMV4_5_MRC(15, 0, 0, 0, 0, 5),
608 if (retval
!= ERROR_OK
)
611 /* ARMv7R uses a different format for MPIDR.
612 * When configured uniprocessor (most R cores) it reads as 0.
613 * This will need to be implemented for multiprocessor ARMv7R cores. */
614 if (armv7a
->is_armv7r
) {
616 LOG_ERROR("MPIDR nonzero in ARMv7-R target");
621 armv7a
->multi_processor_system
= (mpidr
>> 30) & 1;
622 armv7a
->cluster_id
= (mpidr
>> 8) & 0xf;
623 armv7a
->cpu_id
= mpidr
& 0x3;
624 LOG_INFO("%s cluster %x core %x %s", target_name(target
),
627 armv7a
->multi_processor_system
== 0 ? "multi core" : "mono core");
630 LOG_ERROR("MPIDR not in multiprocessor format");
639 int armv7a_identify_cache(struct target
*target
)
641 /* read cache descriptor */
642 int retval
= ERROR_FAIL
;
643 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
644 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
645 uint32_t cache_selected
, clidr
;
646 uint32_t cache_i_reg
, cache_d_reg
;
647 struct armv7a_cache_common
*cache
= &(armv7a
->armv7a_mmu
.armv7a_cache
);
648 if (!armv7a
->is_armv7r
)
649 armv7a_read_ttbcr(target
);
650 retval
= dpm
->prepare(dpm
);
652 if (retval
!= ERROR_OK
)
655 * mrc p15, 1, r0, c0, c0, 1 @ read clidr */
656 retval
= dpm
->instr_read_data_r0(dpm
,
657 ARMV4_5_MRC(15, 1, 0, 0, 0, 1),
659 if (retval
!= ERROR_OK
)
661 clidr
= (clidr
& 0x7000000) >> 23;
662 LOG_INFO("number of cache level %" PRIx32
, (uint32_t)(clidr
/ 2));
663 if ((clidr
/ 2) > 1) {
664 /* FIXME not supported present in cortex A8 and later */
665 /* in cortex A7, A15 */
666 LOG_ERROR("cache l2 present :not supported");
668 /* retrieve selected cache
669 * MRC p15, 2,<Rd>, c0, c0, 0; Read CSSELR */
670 retval
= dpm
->instr_read_data_r0(dpm
,
671 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
673 if (retval
!= ERROR_OK
)
676 retval
= armv7a
->arm
.mrc(target
, 15,
680 if (retval
!= ERROR_OK
)
682 /* select instruction cache
683 * MCR p15, 2,<Rd>, c0, c0, 0; Write CSSELR
684 * [0] : 1 instruction cache selection , 0 data cache selection */
685 retval
= dpm
->instr_write_data_r0(dpm
,
686 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
688 if (retval
!= ERROR_OK
)
692 * MRC P15,1,<RT>,C0, C0,0 ;on cortex A9 read CCSIDR
693 * [2:0] line size 001 eight word per line
694 * [27:13] NumSet 0x7f 16KB, 0xff 32Kbytes, 0x1ff 64Kbytes */
695 retval
= dpm
->instr_read_data_r0(dpm
,
696 ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
698 if (retval
!= ERROR_OK
)
701 /* select data cache*/
702 retval
= dpm
->instr_write_data_r0(dpm
,
703 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
705 if (retval
!= ERROR_OK
)
708 retval
= dpm
->instr_read_data_r0(dpm
,
709 ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
711 if (retval
!= ERROR_OK
)
714 /* restore selected cache */
715 dpm
->instr_write_data_r0(dpm
,
716 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
719 if (retval
!= ERROR_OK
)
724 cache
->d_u_size
.linelen
= 16 << (cache_d_reg
& 0x7);
725 cache
->d_u_size
.cachesize
= (((cache_d_reg
>> 13) & 0x7fff)+1)/8;
726 cache
->d_u_size
.nsets
= (cache_d_reg
>> 13) & 0x7fff;
727 cache
->d_u_size
.associativity
= ((cache_d_reg
>> 3) & 0x3ff) + 1;
728 /* compute info for set way operation on cache */
729 cache
->d_u_size
.index_shift
= (cache_d_reg
& 0x7) + 4;
730 cache
->d_u_size
.index
= (cache_d_reg
>> 13) & 0x7fff;
731 cache
->d_u_size
.way
= ((cache_d_reg
>> 3) & 0x3ff);
732 cache
->d_u_size
.way_shift
= cache
->d_u_size
.way
+ 1;
735 while (((cache
->d_u_size
.way_shift
>> i
) & 1) != 1)
737 cache
->d_u_size
.way_shift
= 32-i
;
740 LOG_INFO("data cache index %d << %d, way %d << %d",
741 cache
->d_u_size
.index
, cache
->d_u_size
.index_shift
,
743 cache
->d_u_size
.way_shift
);
745 LOG_INFO("data cache %d bytes %d KBytes asso %d ways",
746 cache
->d_u_size
.linelen
,
747 cache
->d_u_size
.cachesize
,
748 cache
->d_u_size
.associativity
);
750 cache
->i_size
.linelen
= 16 << (cache_i_reg
& 0x7);
751 cache
->i_size
.associativity
= ((cache_i_reg
>> 3) & 0x3ff) + 1;
752 cache
->i_size
.nsets
= (cache_i_reg
>> 13) & 0x7fff;
753 cache
->i_size
.cachesize
= (((cache_i_reg
>> 13) & 0x7fff)+1)/8;
754 /* compute info for set way operation on cache */
755 cache
->i_size
.index_shift
= (cache_i_reg
& 0x7) + 4;
756 cache
->i_size
.index
= (cache_i_reg
>> 13) & 0x7fff;
757 cache
->i_size
.way
= ((cache_i_reg
>> 3) & 0x3ff);
758 cache
->i_size
.way_shift
= cache
->i_size
.way
+ 1;
761 while (((cache
->i_size
.way_shift
>> i
) & 1) != 1)
763 cache
->i_size
.way_shift
= 32-i
;
766 LOG_INFO("instruction cache index %d << %d, way %d << %d",
767 cache
->i_size
.index
, cache
->i_size
.index_shift
,
768 cache
->i_size
.way
, cache
->i_size
.way_shift
);
770 LOG_INFO("instruction cache %d bytes %d KBytes asso %d ways",
771 cache
->i_size
.linelen
,
772 cache
->i_size
.cachesize
,
773 cache
->i_size
.associativity
);
775 /* if no l2 cache initialize l1 data cache flush function function */
776 if (armv7a
->armv7a_mmu
.armv7a_cache
.flush_all_data_cache
== NULL
) {
777 armv7a
->armv7a_mmu
.armv7a_cache
.display_cache_info
=
778 armv7a_handle_inner_cache_info_command
;
779 armv7a
->armv7a_mmu
.armv7a_cache
.flush_all_data_cache
=
780 armv7a_flush_all_data
;
782 armv7a
->armv7a_mmu
.armv7a_cache
.ctype
= 0;
786 armv7a_read_mpidr(target
);
791 int armv7a_init_arch_info(struct target
*target
, struct armv7a_common
*armv7a
)
793 struct arm
*arm
= &armv7a
->arm
;
794 arm
->arch_info
= armv7a
;
795 target
->arch_info
= &armv7a
->arm
;
796 /* target is useful in all function arm v4 5 compatible */
797 armv7a
->arm
.target
= target
;
798 armv7a
->arm
.common_magic
= ARM_COMMON_MAGIC
;
799 armv7a
->common_magic
= ARMV7_COMMON_MAGIC
;
800 armv7a
->armv7a_mmu
.armv7a_cache
.l2_cache
= NULL
;
801 armv7a
->armv7a_mmu
.armv7a_cache
.ctype
= -1;
802 armv7a
->armv7a_mmu
.armv7a_cache
.flush_all_data_cache
= NULL
;
803 armv7a
->armv7a_mmu
.armv7a_cache
.display_cache_info
= NULL
;
807 int armv7a_arch_state(struct target
*target
)
809 static const char *state
[] = {
810 "disabled", "enabled"
813 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
814 struct arm
*arm
= &armv7a
->arm
;
816 if (armv7a
->common_magic
!= ARMV7_COMMON_MAGIC
) {
817 LOG_ERROR("BUG: called for a non-ARMv7A target");
818 return ERROR_COMMAND_SYNTAX_ERROR
;
821 arm_arch_state(target
);
823 if (armv7a
->is_armv7r
) {
824 LOG_USER("D-Cache: %s, I-Cache: %s",
825 state
[armv7a
->armv7a_mmu
.armv7a_cache
.d_u_cache_enabled
],
826 state
[armv7a
->armv7a_mmu
.armv7a_cache
.i_cache_enabled
]);
828 LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
829 state
[armv7a
->armv7a_mmu
.mmu_enabled
],
830 state
[armv7a
->armv7a_mmu
.armv7a_cache
.d_u_cache_enabled
],
831 state
[armv7a
->armv7a_mmu
.armv7a_cache
.i_cache_enabled
]);
834 if (arm
->core_mode
== ARM_MODE_ABT
)
835 armv7a_show_fault_registers(target
);
836 if (target
->debug_reason
== DBG_REASON_WATCHPOINT
)
837 LOG_USER("Watchpoint triggered at PC %#08x",
838 (unsigned) armv7a
->dpm
.wp_pc
);
843 static const struct command_registration l2_cache_commands
[] = {
846 .handler
= handle_cache_l2x
,
847 .mode
= COMMAND_EXEC
,
848 .help
= "configure l2x cache "
850 .usage
= "[base_addr] [number_of_way]",
852 COMMAND_REGISTRATION_DONE
856 const struct command_registration l2x_cache_command_handlers
[] = {
858 .name
= "cache_config",
859 .mode
= COMMAND_EXEC
,
860 .help
= "cache configuration for a target",
862 .chain
= l2_cache_commands
,
864 COMMAND_REGISTRATION_DONE
868 const struct command_registration armv7a_command_handlers
[] = {
870 .chain
= dap_command_handlers
,
873 .chain
= l2x_cache_command_handlers
,
875 COMMAND_REGISTRATION_DONE
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)