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
;
133 uint32_t ttbcr
, ttbcr_n
;
134 int retval
= dpm
->prepare(dpm
);
135 if (retval
!= ERROR_OK
)
137 /* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
138 retval
= dpm
->instr_read_data_r0(dpm
,
139 ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
141 if (retval
!= ERROR_OK
)
144 LOG_DEBUG("ttbcr %" PRIx32
, ttbcr
);
146 ttbcr_n
= ttbcr
& 0x7;
147 armv7a
->armv7a_mmu
.ttbcr
= ttbcr
;
148 armv7a
->armv7a_mmu
.cached
= 1;
151 * ARM Architecture Reference Manual (ARMv7-A and ARMv7-Redition),
152 * document # ARM DDI 0406C
154 armv7a
->armv7a_mmu
.ttbr_range
[0] = 0xffffffff >> ttbcr_n
;
155 armv7a
->armv7a_mmu
.ttbr_range
[1] = 0xffffffff;
156 armv7a
->armv7a_mmu
.ttbr_mask
[0] = 0xffffffff << (14 - ttbcr_n
);
157 armv7a
->armv7a_mmu
.ttbr_mask
[1] = 0xffffffff << 14;
158 armv7a
->armv7a_mmu
.cached
= 1;
160 retval
= armv7a_read_midr(target
);
161 if (retval
!= ERROR_OK
)
164 /* FIXME: why this special case based on part number? */
165 if ((armv7a
->partnum
& 0xf) == 0) {
166 /* ARM DDI 0344H , ARM DDI 0407F */
167 armv7a
->armv7a_mmu
.ttbr_mask
[0] = 7 << (32 - ttbcr_n
);
170 LOG_DEBUG("ttbr1 %s, ttbr0_mask %" PRIx32
" ttbr1_mask %" PRIx32
,
171 (ttbcr_n
!= 0) ? "used" : "not used",
172 armv7a
->armv7a_mmu
.ttbr_mask
[0],
173 armv7a
->armv7a_mmu
.ttbr_mask
[1]);
175 /* FIXME: default is hard coded LINUX border */
176 armv7a
->armv7a_mmu
.os_border
= 0xc0000000;
178 LOG_INFO("SVC access above %" PRIx32
,
179 armv7a
->armv7a_mmu
.ttbr_range
[0] + 1);
180 armv7a
->armv7a_mmu
.os_border
= armv7a
->armv7a_mmu
.ttbr_range
[0] + 1;
187 /* method adapted to cortex A : reused arm v4 v5 method*/
188 int armv7a_mmu_translate_va(struct target
*target
, uint32_t va
, uint32_t *val
)
190 uint32_t first_lvl_descriptor
= 0x0;
191 uint32_t second_lvl_descriptor
= 0x0;
193 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
194 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
195 uint32_t ttbidx
= 0; /* default to ttbr0 */
201 retval
= dpm
->prepare(dpm
);
202 if (retval
!= ERROR_OK
)
205 /* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
206 retval
= dpm
->instr_read_data_r0(dpm
,
207 ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
209 if (retval
!= ERROR_OK
)
212 /* if ttbcr has changed or was not read before, re-read the information */
213 if ((armv7a
->armv7a_mmu
.cached
== 0) ||
214 (armv7a
->armv7a_mmu
.ttbcr
!= ttbcr
)) {
215 armv7a_read_ttbcr(target
);
218 /* if va is above the range handled by ttbr0, select ttbr1 */
219 if (va
> armv7a
->armv7a_mmu
.ttbr_range
[0]) {
223 /* MRC p15,0,<Rt>,c2,c0,ttbidx */
224 retval
= dpm
->instr_read_data_r0(dpm
,
225 ARMV4_5_MRC(15, 0, 0, 2, 0, ttbidx
),
227 if (retval
!= ERROR_OK
)
230 ttb_mask
= armv7a
->armv7a_mmu
.ttbr_mask
[ttbidx
];
231 va_mask
= 0xfff00000 & armv7a
->armv7a_mmu
.ttbr_range
[ttbidx
];
233 LOG_DEBUG("ttb_mask %" PRIx32
" va_mask %" PRIx32
" ttbidx %i",
234 ttb_mask
, va_mask
, ttbidx
);
235 retval
= armv7a
->armv7a_mmu
.read_physical_memory(target
,
236 (ttb
& ttb_mask
) | ((va
& va_mask
) >> 18),
237 4, 1, (uint8_t *)&first_lvl_descriptor
);
238 if (retval
!= ERROR_OK
)
240 first_lvl_descriptor
= target_buffer_get_u32(target
, (uint8_t *)
241 &first_lvl_descriptor
);
242 /* reuse armv4_5 piece of code, specific armv7a changes may come later */
243 LOG_DEBUG("1st lvl desc: %8.8" PRIx32
"", first_lvl_descriptor
);
245 if ((first_lvl_descriptor
& 0x3) == 0) {
246 LOG_ERROR("Address translation failure");
247 return ERROR_TARGET_TRANSLATION_FAULT
;
251 if ((first_lvl_descriptor
& 0x40002) == 2) {
252 /* section descriptor */
253 *val
= (first_lvl_descriptor
& 0xfff00000) | (va
& 0x000fffff);
255 } else if ((first_lvl_descriptor
& 0x40002) == 0x40002) {
256 /* supersection descriptor */
257 if (first_lvl_descriptor
& 0x00f001e0) {
258 LOG_ERROR("Physical address does not fit into 32 bits");
259 return ERROR_TARGET_TRANSLATION_FAULT
;
261 *val
= (first_lvl_descriptor
& 0xff000000) | (va
& 0x00ffffff);
266 retval
= armv7a
->armv7a_mmu
.read_physical_memory(target
,
267 (first_lvl_descriptor
& 0xfffffc00) | ((va
& 0x000ff000) >> 10),
268 4, 1, (uint8_t *)&second_lvl_descriptor
);
269 if (retval
!= ERROR_OK
)
272 second_lvl_descriptor
= target_buffer_get_u32(target
, (uint8_t *)
273 &second_lvl_descriptor
);
275 LOG_DEBUG("2nd lvl desc: %8.8" PRIx32
"", second_lvl_descriptor
);
277 if ((second_lvl_descriptor
& 0x3) == 0) {
278 LOG_ERROR("Address translation failure");
279 return ERROR_TARGET_TRANSLATION_FAULT
;
282 if ((second_lvl_descriptor
& 0x3) == 1) {
283 /* large page descriptor */
284 *val
= (second_lvl_descriptor
& 0xffff0000) | (va
& 0x0000ffff);
286 /* small page descriptor */
287 *val
= (second_lvl_descriptor
& 0xfffff000) | (va
& 0x00000fff);
296 /* V7 method VA TO PA */
297 int armv7a_mmu_translate_va_pa(struct target
*target
, uint32_t va
,
298 uint32_t *val
, int meminfo
)
300 int retval
= ERROR_FAIL
;
301 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
302 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
303 uint32_t virt
= va
& ~0xfff;
304 uint32_t NOS
, NS
, INNER
, OUTER
;
306 retval
= dpm
->prepare(dpm
);
307 if (retval
!= ERROR_OK
)
309 /* mmu must be enable in order to get a correct translation
310 * use VA to PA CP15 register for conversion */
311 retval
= dpm
->instr_write_data_r0(dpm
,
312 ARMV4_5_MCR(15, 0, 0, 7, 8, 0),
314 if (retval
!= ERROR_OK
)
316 retval
= dpm
->instr_read_data_r0(dpm
,
317 ARMV4_5_MRC(15, 0, 0, 7, 4, 0),
319 /* decode memory attribute */
320 NOS
= (*val
>> 10) & 1; /* Not Outer shareable */
321 NS
= (*val
>> 9) & 1; /* Non secure */
322 INNER
= (*val
>> 4) & 0x7;
323 OUTER
= (*val
>> 2) & 0x3;
325 if (retval
!= ERROR_OK
)
327 *val
= (*val
& ~0xfff) + (va
& 0xfff);
329 LOG_WARNING("virt = phys : MMU disable !!");
331 LOG_INFO("%" PRIx32
" : %" PRIx32
" %s outer shareable %s secured",
333 NOS
== 1 ? "not" : " ",
334 NS
== 1 ? "not" : "");
337 LOG_INFO("outer: Non-Cacheable");
340 LOG_INFO("outer: Write-Back, Write-Allocate");
343 LOG_INFO("outer: Write-Through, No Write-Allocate");
346 LOG_INFO("outer: Write-Back, no Write-Allocate");
351 LOG_INFO("inner: Non-Cacheable");
354 LOG_INFO("inner: Strongly-ordered");
357 LOG_INFO("inner: Device");
360 LOG_INFO("inner: Write-Back, Write-Allocate");
363 LOG_INFO("inner: Write-Through");
366 LOG_INFO("inner: Write-Back, no Write-Allocate");
369 LOG_INFO("inner: %" PRIx32
" ???", INNER
);
379 static int armv7a_handle_inner_cache_info_command(struct command_context
*cmd_ctx
,
380 struct armv7a_cache_common
*armv7a_cache
)
382 if (armv7a_cache
->ctype
== -1) {
383 command_print(cmd_ctx
, "cache not yet identified");
387 command_print(cmd_ctx
,
388 "D-Cache: linelen %" PRIi32
", associativity %" PRIi32
", nsets %" PRIi32
", cachesize %" PRId32
" KBytes",
389 armv7a_cache
->d_u_size
.linelen
,
390 armv7a_cache
->d_u_size
.associativity
,
391 armv7a_cache
->d_u_size
.nsets
,
392 armv7a_cache
->d_u_size
.cachesize
);
394 command_print(cmd_ctx
,
395 "I-Cache: linelen %" PRIi32
", associativity %" PRIi32
", nsets %" PRIi32
", cachesize %" PRId32
" KBytes",
396 armv7a_cache
->i_size
.linelen
,
397 armv7a_cache
->i_size
.associativity
,
398 armv7a_cache
->i_size
.nsets
,
399 armv7a_cache
->i_size
.cachesize
);
404 /* L2 is not specific to armv7a a specific file is needed */
405 static int armv7a_l2x_flush_all_data(struct target
*target
)
408 #define L2X0_CLEAN_INV_WAY 0x7FC
409 int retval
= ERROR_FAIL
;
410 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
411 struct armv7a_l2x_cache
*l2x_cache
= (struct armv7a_l2x_cache
*)
412 (armv7a
->armv7a_mmu
.armv7a_cache
.outer_cache
);
413 uint32_t base
= l2x_cache
->base
;
414 uint32_t l2_way
= l2x_cache
->way
;
415 uint32_t l2_way_val
= (1 << l2_way
) - 1;
416 retval
= armv7a_cache_auto_flush_all_data(target
);
417 if (retval
!= ERROR_OK
)
419 retval
= target
->type
->write_phys_memory(target
,
420 (uint32_t)(base
+(uint32_t)L2X0_CLEAN_INV_WAY
),
423 (uint8_t *)&l2_way_val
);
427 static int armv7a_handle_l2x_cache_info_command(struct command_context
*cmd_ctx
,
428 struct armv7a_cache_common
*armv7a_cache
)
431 struct armv7a_l2x_cache
*l2x_cache
= (struct armv7a_l2x_cache
*)
432 (armv7a_cache
->outer_cache
);
434 if (armv7a_cache
->ctype
== -1) {
435 command_print(cmd_ctx
, "cache not yet identified");
439 command_print(cmd_ctx
,
440 "L1 D-Cache: linelen %" PRIi32
", associativity %" PRIi32
", nsets %" PRIi32
", cachesize %" PRId32
" KBytes",
441 armv7a_cache
->d_u_size
.linelen
,
442 armv7a_cache
->d_u_size
.associativity
,
443 armv7a_cache
->d_u_size
.nsets
,
444 armv7a_cache
->d_u_size
.cachesize
);
446 command_print(cmd_ctx
,
447 "L1 I-Cache: linelen %" PRIi32
", associativity %" PRIi32
", nsets %" PRIi32
", cachesize %" PRId32
" KBytes",
448 armv7a_cache
->i_size
.linelen
,
449 armv7a_cache
->i_size
.associativity
,
450 armv7a_cache
->i_size
.nsets
,
451 armv7a_cache
->i_size
.cachesize
);
452 command_print(cmd_ctx
, "L2 unified cache Base Address 0x%" PRIx32
", %" PRId32
" ways",
453 l2x_cache
->base
, l2x_cache
->way
);
459 /* FIXME: remove it */
460 static int armv7a_l2x_cache_init(struct target
*target
, uint32_t base
, uint32_t way
)
462 struct armv7a_l2x_cache
*l2x_cache
;
463 struct target_list
*head
= target
->head
;
466 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
467 l2x_cache
= calloc(1, sizeof(struct armv7a_l2x_cache
));
468 l2x_cache
->base
= base
;
469 l2x_cache
->way
= way
;
470 /*LOG_INFO("cache l2 initialized base %x way %d",
471 l2x_cache->base,l2x_cache->way);*/
472 if (armv7a
->armv7a_mmu
.armv7a_cache
.outer_cache
)
473 LOG_INFO("outer cache already initialized\n");
474 armv7a
->armv7a_mmu
.armv7a_cache
.outer_cache
= l2x_cache
;
475 /* initialize l1 / l2x cache function */
476 armv7a
->armv7a_mmu
.armv7a_cache
.flush_all_data_cache
477 = armv7a_l2x_flush_all_data
;
478 armv7a
->armv7a_mmu
.armv7a_cache
.display_cache_info
=
479 armv7a_handle_l2x_cache_info_command
;
480 /* initialize all target in this cluster (smp target)
481 * l2 cache must be configured after smp declaration */
482 while (head
!= (struct target_list
*)NULL
) {
484 if (curr
!= target
) {
485 armv7a
= target_to_armv7a(curr
);
486 if (armv7a
->armv7a_mmu
.armv7a_cache
.outer_cache
)
487 LOG_ERROR("smp target : outer cache already initialized\n");
488 armv7a
->armv7a_mmu
.armv7a_cache
.outer_cache
= l2x_cache
;
489 armv7a
->armv7a_mmu
.armv7a_cache
.flush_all_data_cache
=
490 armv7a_l2x_flush_all_data
;
491 armv7a
->armv7a_mmu
.armv7a_cache
.display_cache_info
=
492 armv7a_handle_l2x_cache_info_command
;
499 /* FIXME: remove it */
500 COMMAND_HANDLER(handle_cache_l2x
)
502 struct target
*target
= get_current_target(CMD_CTX
);
506 return ERROR_COMMAND_SYNTAX_ERROR
;
508 /* command_print(CMD_CTX, "%s %s", CMD_ARGV[0], CMD_ARGV[1]); */
509 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], base
);
510 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], way
);
512 /* AP address is in bits 31:24 of DP_SELECT */
513 armv7a_l2x_cache_init(target
, base
, way
);
518 int armv7a_handle_cache_info_command(struct command_context
*cmd_ctx
,
519 struct armv7a_cache_common
*armv7a_cache
)
521 if (armv7a_cache
->ctype
== -1) {
522 command_print(cmd_ctx
, "cache not yet identified");
526 if (armv7a_cache
->display_cache_info
)
527 armv7a_cache
->display_cache_info(cmd_ctx
, armv7a_cache
);
531 /* retrieve core id cluster id */
532 static int armv7a_read_mpidr(struct target
*target
)
534 int retval
= ERROR_FAIL
;
535 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
536 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
538 retval
= dpm
->prepare(dpm
);
539 if (retval
!= ERROR_OK
)
541 /* MRC p15,0,<Rd>,c0,c0,5; read Multiprocessor ID register*/
543 retval
= dpm
->instr_read_data_r0(dpm
,
544 ARMV4_5_MRC(15, 0, 0, 0, 0, 5),
546 if (retval
!= ERROR_OK
)
549 /* ARMv7R uses a different format for MPIDR.
550 * When configured uniprocessor (most R cores) it reads as 0.
551 * This will need to be implemented for multiprocessor ARMv7R cores. */
552 if (armv7a
->is_armv7r
) {
554 LOG_ERROR("MPIDR nonzero in ARMv7-R target");
559 armv7a
->multi_processor_system
= (mpidr
>> 30) & 1;
560 armv7a
->cluster_id
= (mpidr
>> 8) & 0xf;
561 armv7a
->cpu_id
= mpidr
& 0x3;
562 LOG_INFO("%s cluster %x core %x %s", target_name(target
),
565 armv7a
->multi_processor_system
== 0 ? "multi core" : "mono core");
568 LOG_ERROR("MPIDR not in multiprocessor format");
577 int armv7a_identify_cache(struct target
*target
)
579 /* read cache descriptor */
580 int retval
= ERROR_FAIL
;
581 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
582 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
583 uint32_t cache_selected
, clidr
, ctr
;
584 uint32_t cache_i_reg
, cache_d_reg
;
585 struct armv7a_cache_common
*cache
= &(armv7a
->armv7a_mmu
.armv7a_cache
);
586 if (!armv7a
->is_armv7r
)
587 armv7a_read_ttbcr(target
);
588 retval
= dpm
->prepare(dpm
);
589 if (retval
!= ERROR_OK
)
593 * mrc p15, 0, r0, c0, c0, 1 @ read ctr */
594 retval
= dpm
->instr_read_data_r0(dpm
,
595 ARMV4_5_MRC(15, 0, 0, 0, 0, 1),
597 if (retval
!= ERROR_OK
)
600 cache
->iminline
= 4UL << (ctr
& 0xf);
601 cache
->dminline
= 4UL << ((ctr
& 0xf0000) >> 16);
602 LOG_DEBUG("ctr %" PRIx32
" ctr.iminline %" PRId32
" ctr.dminline %" PRId32
,
603 ctr
, cache
->iminline
, cache
->dminline
);
606 * mrc p15, 1, r0, c0, c0, 1 @ read clidr */
607 retval
= dpm
->instr_read_data_r0(dpm
,
608 ARMV4_5_MRC(15, 1, 0, 0, 0, 1),
610 if (retval
!= ERROR_OK
)
612 clidr
= (clidr
& 0x7000000) >> 23;
613 LOG_INFO("number of cache level %" PRIx32
, (uint32_t)(clidr
/ 2));
614 if ((clidr
/ 2) > 1) {
615 /* FIXME not supported present in cortex A8 and later */
616 /* in cortex A7, A15 */
617 LOG_ERROR("cache l2 present :not supported");
619 /* retrieve selected cache
620 * MRC p15, 2,<Rd>, c0, c0, 0; Read CSSELR */
621 retval
= dpm
->instr_read_data_r0(dpm
,
622 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
624 if (retval
!= ERROR_OK
)
627 retval
= armv7a
->arm
.mrc(target
, 15,
631 if (retval
!= ERROR_OK
)
633 /* select instruction cache
634 * MCR p15, 2,<Rd>, c0, c0, 0; Write CSSELR
635 * [0] : 1 instruction cache selection , 0 data cache selection */
636 retval
= dpm
->instr_write_data_r0(dpm
,
637 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
639 if (retval
!= ERROR_OK
)
643 * MRC P15,1,<RT>,C0, C0,0 ;on cortex A9 read CCSIDR
644 * [2:0] line size 001 eight word per line
645 * [27:13] NumSet 0x7f 16KB, 0xff 32Kbytes, 0x1ff 64Kbytes */
646 retval
= dpm
->instr_read_data_r0(dpm
,
647 ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
649 if (retval
!= ERROR_OK
)
652 /* select data cache*/
653 retval
= dpm
->instr_write_data_r0(dpm
,
654 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
656 if (retval
!= ERROR_OK
)
659 retval
= dpm
->instr_read_data_r0(dpm
,
660 ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
662 if (retval
!= ERROR_OK
)
665 /* restore selected cache */
666 dpm
->instr_write_data_r0(dpm
,
667 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
670 if (retval
!= ERROR_OK
)
675 cache
->d_u_size
.linelen
= 16 << (cache_d_reg
& 0x7);
676 cache
->d_u_size
.cachesize
= (((cache_d_reg
>> 13) & 0x7fff)+1)/8;
677 cache
->d_u_size
.nsets
= (cache_d_reg
>> 13) & 0x7fff;
678 cache
->d_u_size
.associativity
= ((cache_d_reg
>> 3) & 0x3ff) + 1;
679 /* compute info for set way operation on cache */
680 cache
->d_u_size
.index_shift
= (cache_d_reg
& 0x7) + 4;
681 cache
->d_u_size
.index
= (cache_d_reg
>> 13) & 0x7fff;
682 cache
->d_u_size
.way
= ((cache_d_reg
>> 3) & 0x3ff);
683 cache
->d_u_size
.way_shift
= cache
->d_u_size
.way
+ 1;
686 while (((cache
->d_u_size
.way_shift
>> i
) & 1) != 1)
688 cache
->d_u_size
.way_shift
= 32-i
;
691 LOG_INFO("data cache index %d << %d, way %d << %d",
692 cache
->d_u_size
.index
, cache
->d_u_size
.index_shift
,
694 cache
->d_u_size
.way_shift
);
696 LOG_INFO("data cache %d bytes %d KBytes asso %d ways",
697 cache
->d_u_size
.linelen
,
698 cache
->d_u_size
.cachesize
,
699 cache
->d_u_size
.associativity
);
701 cache
->i_size
.linelen
= 16 << (cache_i_reg
& 0x7);
702 cache
->i_size
.associativity
= ((cache_i_reg
>> 3) & 0x3ff) + 1;
703 cache
->i_size
.nsets
= (cache_i_reg
>> 13) & 0x7fff;
704 cache
->i_size
.cachesize
= (((cache_i_reg
>> 13) & 0x7fff)+1)/8;
705 /* compute info for set way operation on cache */
706 cache
->i_size
.index_shift
= (cache_i_reg
& 0x7) + 4;
707 cache
->i_size
.index
= (cache_i_reg
>> 13) & 0x7fff;
708 cache
->i_size
.way
= ((cache_i_reg
>> 3) & 0x3ff);
709 cache
->i_size
.way_shift
= cache
->i_size
.way
+ 1;
712 while (((cache
->i_size
.way_shift
>> i
) & 1) != 1)
714 cache
->i_size
.way_shift
= 32-i
;
717 LOG_INFO("instruction cache index %d << %d, way %d << %d",
718 cache
->i_size
.index
, cache
->i_size
.index_shift
,
719 cache
->i_size
.way
, cache
->i_size
.way_shift
);
721 LOG_INFO("instruction cache %d bytes %d KBytes asso %d ways",
722 cache
->i_size
.linelen
,
723 cache
->i_size
.cachesize
,
724 cache
->i_size
.associativity
);
726 /* if no l2 cache initialize l1 data cache flush function function */
727 if (armv7a
->armv7a_mmu
.armv7a_cache
.flush_all_data_cache
== NULL
) {
728 armv7a
->armv7a_mmu
.armv7a_cache
.display_cache_info
=
729 armv7a_handle_inner_cache_info_command
;
730 armv7a
->armv7a_mmu
.armv7a_cache
.flush_all_data_cache
=
731 armv7a_cache_auto_flush_all_data
;
733 armv7a
->armv7a_mmu
.armv7a_cache
.ctype
= 0;
737 armv7a_read_mpidr(target
);
742 int armv7a_init_arch_info(struct target
*target
, struct armv7a_common
*armv7a
)
744 struct arm
*arm
= &armv7a
->arm
;
745 arm
->arch_info
= armv7a
;
746 target
->arch_info
= &armv7a
->arm
;
747 /* target is useful in all function arm v4 5 compatible */
748 armv7a
->arm
.target
= target
;
749 armv7a
->arm
.common_magic
= ARM_COMMON_MAGIC
;
750 armv7a
->common_magic
= ARMV7_COMMON_MAGIC
;
751 armv7a
->armv7a_mmu
.armv7a_cache
.ctype
= -1;
752 armv7a
->armv7a_mmu
.armv7a_cache
.outer_cache
= NULL
;
753 armv7a
->armv7a_mmu
.armv7a_cache
.flush_all_data_cache
= NULL
;
754 armv7a
->armv7a_mmu
.armv7a_cache
.display_cache_info
= NULL
;
755 armv7a
->armv7a_mmu
.armv7a_cache
.auto_cache_enabled
= 1;
759 int armv7a_arch_state(struct target
*target
)
761 static const char *state
[] = {
762 "disabled", "enabled"
765 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
766 struct arm
*arm
= &armv7a
->arm
;
768 if (armv7a
->common_magic
!= ARMV7_COMMON_MAGIC
) {
769 LOG_ERROR("BUG: called for a non-ARMv7A target");
770 return ERROR_COMMAND_SYNTAX_ERROR
;
773 arm_arch_state(target
);
775 if (armv7a
->is_armv7r
) {
776 LOG_USER("D-Cache: %s, I-Cache: %s",
777 state
[armv7a
->armv7a_mmu
.armv7a_cache
.d_u_cache_enabled
],
778 state
[armv7a
->armv7a_mmu
.armv7a_cache
.i_cache_enabled
]);
780 LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
781 state
[armv7a
->armv7a_mmu
.mmu_enabled
],
782 state
[armv7a
->armv7a_mmu
.armv7a_cache
.d_u_cache_enabled
],
783 state
[armv7a
->armv7a_mmu
.armv7a_cache
.i_cache_enabled
]);
786 if (arm
->core_mode
== ARM_MODE_ABT
)
787 armv7a_show_fault_registers(target
);
788 if (target
->debug_reason
== DBG_REASON_WATCHPOINT
)
789 LOG_USER("Watchpoint triggered at PC %#08x",
790 (unsigned) armv7a
->dpm
.wp_pc
);
795 static const struct command_registration l2_cache_commands
[] = {
798 .handler
= handle_cache_l2x
,
799 .mode
= COMMAND_EXEC
,
800 .help
= "configure l2x cache "
802 .usage
= "[base_addr] [number_of_way]",
804 COMMAND_REGISTRATION_DONE
808 const struct command_registration l2x_cache_command_handlers
[] = {
810 .name
= "cache_config",
811 .mode
= COMMAND_EXEC
,
812 .help
= "cache configuration for a target",
814 .chain
= l2_cache_commands
,
816 COMMAND_REGISTRATION_DONE
819 const struct command_registration armv7a_command_handlers
[] = {
821 .chain
= dap_command_handlers
,
824 .chain
= l2x_cache_command_handlers
,
827 .chain
= arm7a_cache_command_handlers
,
829 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)