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 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
20 ***************************************************************************/
25 #include <helper/replacements.h>
28 #include "arm_disassembler.h"
31 #include <helper/binarybuffer.h>
32 #include <helper/command.h>
38 #include "arm_opcodes.h"
40 #include "target_type.h"
42 static void armv7a_show_fault_registers(struct target
*target
)
44 uint32_t dfsr
, ifsr
, dfar
, ifar
;
45 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
46 struct arm_dpm
*dpm
= armv7a
->armv4_5_common
.dpm
;
49 retval
= dpm
->prepare(dpm
);
50 if (retval
!= ERROR_OK
)
53 /* ARMV4_5_MRC(cpnum, op1, r0, CRn, CRm, op2) */
55 /* c5/c0 - {data, instruction} fault status registers */
56 retval
= dpm
->instr_read_data_r0(dpm
,
57 ARMV4_5_MRC(15, 0, 0, 5, 0, 0),
59 if (retval
!= ERROR_OK
)
62 retval
= dpm
->instr_read_data_r0(dpm
,
63 ARMV4_5_MRC(15, 0, 0, 5, 0, 1),
65 if (retval
!= ERROR_OK
)
68 /* c6/c0 - {data, instruction} fault address registers */
69 retval
= dpm
->instr_read_data_r0(dpm
,
70 ARMV4_5_MRC(15, 0, 0, 6, 0, 0),
72 if (retval
!= ERROR_OK
)
75 retval
= dpm
->instr_read_data_r0(dpm
,
76 ARMV4_5_MRC(15, 0, 0, 6, 0, 2),
78 if (retval
!= ERROR_OK
)
81 LOG_USER("Data fault registers DFSR: %8.8" PRIx32
82 ", DFAR: %8.8" PRIx32
, dfsr
, dfar
);
83 LOG_USER("Instruction fault registers IFSR: %8.8" PRIx32
84 ", IFAR: %8.8" PRIx32
, ifsr
, ifar
);
87 /* (void) */ dpm
->finish(dpm
);
90 int armv7a_read_ttbcr(struct target
*target
)
92 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
93 struct arm_dpm
*dpm
= armv7a
->armv4_5_common
.dpm
;
95 int retval
= dpm
->prepare(dpm
);
96 if (retval
!=ERROR_OK
) goto done
;
97 /* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
98 retval
= dpm
->instr_read_data_r0(dpm
,
99 ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
101 if (retval
!=ERROR_OK
) goto done
;
102 armv7a
->armv7a_mmu
.ttbr1_used
= ((ttbcr
& 0x7)!=0)? 1: 0;
103 armv7a
->armv7a_mmu
.ttbr0_mask
= 7 << (32 -((ttbcr
& 0x7)));
105 LOG_INFO("ttb1 %s ,ttb0_mask %x",
106 armv7a
->armv7a_mmu
.ttbr1_used
? "used":"not used",
107 armv7a
->armv7a_mmu
.ttbr0_mask
);
109 if (armv7a
->armv7a_mmu
.ttbr1_used
== 1)
111 LOG_INFO("SVC access above %x",
112 (0xffffffff & armv7a
->armv7a_mmu
.ttbr0_mask
));
113 armv7a
->armv7a_mmu
.os_border
= 0xffffffff & armv7a
->armv7a_mmu
.ttbr0_mask
;
117 /* fix me , default is hard coded LINUX border */
118 armv7a
->armv7a_mmu
.os_border
= 0xc0000000;
126 /* method adapted to cortex A : reused arm v4 v5 method*/
127 int armv7a_mmu_translate_va(struct target
*target
, uint32_t va
, uint32_t *val
)
129 uint32_t first_lvl_descriptor
= 0x0;
130 uint32_t second_lvl_descriptor
= 0x0;
132 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
133 struct arm_dpm
*dpm
= armv7a
->armv4_5_common
.dpm
;
134 uint32_t ttb
= 0; /* default ttb0 */
135 if (armv7a
->armv7a_mmu
.ttbr1_used
== -1) armv7a_read_ttbcr(target
);
136 if ((armv7a
->armv7a_mmu
.ttbr1_used
) &&
137 (va
> (0xffffffff & armv7a
->armv7a_mmu
.ttbr0_mask
)))
142 retval
= dpm
->prepare(dpm
);
143 if (retval
!= ERROR_OK
)
146 /* MRC p15,0,<Rt>,c2,c0,ttb */
147 retval
= dpm
->instr_read_data_r0(dpm
,
148 ARMV4_5_MRC(15, 0, 0, 2, 0, ttb
),
150 retval
= armv7a
->armv7a_mmu
.read_physical_memory(target
,
151 (ttb
& 0xffffc000) | ((va
& 0xfff00000) >> 18),
152 4, 1, (uint8_t*)&first_lvl_descriptor
);
153 if (retval
!= ERROR_OK
)
155 first_lvl_descriptor
= target_buffer_get_u32(target
, (uint8_t*)
156 &first_lvl_descriptor
);
157 /* reuse armv4_5 piece of code, specific armv7a changes may come later */
158 LOG_DEBUG("1st lvl desc: %8.8" PRIx32
"", first_lvl_descriptor
);
160 if ((first_lvl_descriptor
& 0x3) == 0)
162 LOG_ERROR("Address translation failure");
163 return ERROR_TARGET_TRANSLATION_FAULT
;
167 if ((first_lvl_descriptor
& 0x3) == 2)
169 /* section descriptor */
170 *val
= (first_lvl_descriptor
& 0xfff00000) | (va
& 0x000fffff);
174 if ((first_lvl_descriptor
& 0x3) == 1)
176 /* coarse page table */
177 retval
= armv7a
->armv7a_mmu
.read_physical_memory(target
,
178 (first_lvl_descriptor
& 0xfffffc00) | ((va
& 0x000ff000) >> 10),
179 4, 1, (uint8_t*)&second_lvl_descriptor
);
180 if (retval
!= ERROR_OK
)
183 else if ((first_lvl_descriptor
& 0x3) == 3)
185 /* fine page table */
186 retval
= armv7a
->armv7a_mmu
.read_physical_memory(target
,
187 (first_lvl_descriptor
& 0xfffff000) | ((va
& 0x000ffc00) >> 8),
188 4, 1, (uint8_t*)&second_lvl_descriptor
);
189 if (retval
!= ERROR_OK
)
193 second_lvl_descriptor
= target_buffer_get_u32(target
, (uint8_t*)
194 &second_lvl_descriptor
);
196 LOG_DEBUG("2nd lvl desc: %8.8" PRIx32
"", second_lvl_descriptor
);
198 if ((second_lvl_descriptor
& 0x3) == 0)
200 LOG_ERROR("Address translation failure");
201 return ERROR_TARGET_TRANSLATION_FAULT
;
204 if ((second_lvl_descriptor
& 0x3) == 1)
206 /* large page descriptor */
207 *val
= (second_lvl_descriptor
& 0xffff0000) | (va
& 0x0000ffff);
211 if ((second_lvl_descriptor
& 0x3) == 2)
213 /* small page descriptor */
214 *val
= (second_lvl_descriptor
& 0xfffff000) | (va
& 0x00000fff);
218 if ((second_lvl_descriptor
& 0x3) == 3)
220 *val
= (second_lvl_descriptor
& 0xfffffc00) | (va
& 0x000003ff);
224 /* should not happen */
225 LOG_ERROR("Address translation failure");
226 return ERROR_TARGET_TRANSLATION_FAULT
;
233 /* V7 method VA TO PA */
234 int armv7a_mmu_translate_va_pa(struct target
*target
, uint32_t va
,
235 uint32_t *val
, int meminfo
)
237 int retval
= ERROR_FAIL
;
238 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
239 struct arm_dpm
*dpm
= armv7a
->armv4_5_common
.dpm
;
240 uint32_t virt
= va
& ~0xfff;
241 uint32_t NOS
,NS
,INNER
,OUTER
;
243 retval
= dpm
->prepare(dpm
);
244 if (retval
!= ERROR_OK
)
246 /* mmu must be enable in order to get a correct translation */
247 /* use VA to PA CP15 register for conversion */
248 retval
= dpm
->instr_write_data_r0(dpm
,
249 ARMV4_5_MCR(15, 0, 0, 7, 8, 0),
251 if (retval
!=ERROR_OK
) goto done
;
252 retval
= dpm
->instr_read_data_r0(dpm
,
253 ARMV4_5_MRC(15, 0, 0, 7, 4, 0),
255 /* decode memory attribute */
256 NOS
= (*val
>> 10) & 1; /* Not Outer shareable */
257 NS
= (*val
>> 9) & 1; /* Non secure */
258 INNER
= (*val
>> 4) & 0x7;
259 OUTER
= (*val
>> 2) & 0x3;
261 if (retval
!=ERROR_OK
) goto done
;
262 *val
= (*val
& ~0xfff) + (va
& 0xfff);
264 LOG_WARNING("virt = phys : MMU disable !!");
267 LOG_INFO("%x : %x %s outer shareable %s secured",
269 NOS
== 1 ? "not" : " ",
270 NS
== 1 ? "not" :"");
272 case 0 : LOG_INFO("outer: Non-Cacheable");
274 case 1 : LOG_INFO("outer: Write-Back, Write-Allocate");
276 case 2 : LOG_INFO("outer: Write-Through, No Write-Allocate");
278 case 3 : LOG_INFO("outer: Write-Back, no Write-Allocate");
282 case 0 : LOG_INFO("inner: Non-Cacheable");
284 case 1 : LOG_INFO("inner: Strongly-ordered");
286 case 3 : LOG_INFO("inner: Device");
288 case 5 : LOG_INFO("inner: Write-Back, Write-Allocate");
290 case 6 : LOG_INFO("inner: Write-Through");
292 case 7 : LOG_INFO("inner: Write-Back, no Write-Allocate");
294 default: LOG_INFO("inner: %x ???",INNER
);
304 static int armv7a_handle_inner_cache_info_command(struct command_context
*cmd_ctx
,
305 struct armv7a_cache_common
*armv7a_cache
)
307 if (armv7a_cache
->ctype
== -1)
309 command_print(cmd_ctx
, "cache not yet identified");
313 command_print(cmd_ctx
,
314 "D-Cache: linelen %i, associativity %i, nsets %i, cachesize %d KBytes",
315 armv7a_cache
->d_u_size
.linelen
,
316 armv7a_cache
->d_u_size
.associativity
,
317 armv7a_cache
->d_u_size
.nsets
,
318 armv7a_cache
->d_u_size
.cachesize
);
320 command_print(cmd_ctx
,
321 "I-Cache: linelen %i, associativity %i, nsets %i, cachesize %d KBytes",
322 armv7a_cache
->i_size
.linelen
,
323 armv7a_cache
->i_size
.associativity
,
324 armv7a_cache
->i_size
.nsets
,
325 armv7a_cache
->i_size
.cachesize
);
330 static int _armv7a_flush_all_data(struct target
*target
)
332 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
333 struct arm_dpm
*dpm
= armv7a
->armv4_5_common
.dpm
;
334 struct armv7a_cachesize
*d_u_size
=
335 &(armv7a
->armv7a_mmu
.armv7a_cache
.d_u_size
);
336 int32_t c_way
, c_index
= d_u_size
->index
;
338 /* check that cache data is on at target halt */
339 if (!armv7a
->armv7a_mmu
.armv7a_cache
.d_u_cache_enabled
)
341 LOG_INFO("flushed not performed :cache not on at target halt");
344 retval
= dpm
->prepare(dpm
);
345 if (retval
!= ERROR_OK
) goto done
;
347 c_way
= d_u_size
->way
;
349 uint32_t value
= (c_index
<< d_u_size
->index_shift
)
350 | (c_way
<< d_u_size
->way_shift
);
352 //LOG_INFO ("%d %d %x",c_way,c_index,value);
353 retval
= dpm
->instr_write_data_r0(dpm
,
354 ARMV4_5_MCR(15, 0, 0, 7, 14, 2),
356 if (retval
!= ERROR_OK
) goto done
;
360 } while (c_index
>=0);
363 LOG_ERROR("flushed failed");
368 static int armv7a_flush_all_data( struct target
* target
)
370 int retval
= ERROR_FAIL
;
371 /* check that armv7a_cache is correctly identify */
372 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
373 if (armv7a
->armv7a_mmu
.armv7a_cache
.ctype
== -1)
375 LOG_ERROR("trying to flush un-identified cache");
381 /* look if all the other target have been flushed in order to flush level
383 struct target_list
*head
;
386 while(head
!= (struct target_list
*)NULL
)
389 if ((curr
->state
== TARGET_HALTED
))
390 { LOG_INFO("Wait flushing data l1 on core %d",curr
->coreid
);
391 retval
= _armv7a_flush_all_data(curr
);
396 else retval
= _armv7a_flush_all_data(target
);
401 /* L2 is not specific to armv7a a specific file is needed */
402 static int armv7a_l2x_flush_all_data(struct target
* target
)
405 #define L2X0_CLEAN_INV_WAY 0x7FC
406 int retval
= ERROR_FAIL
;
407 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
408 struct armv7a_l2x_cache
*l2x_cache
= (struct armv7a_l2x_cache
*)
409 (armv7a
->armv7a_mmu
.armv7a_cache
.l2_cache
);
410 uint32_t base
= l2x_cache
->base
;
411 uint32_t l2_way
= l2x_cache
->way
;
412 uint32_t l2_way_val
= (1<<l2_way
) -1;
413 retval
= armv7a_flush_all_data(target
);
414 if (retval
!=ERROR_OK
) return retval
;
415 retval
= target
->type
->write_phys_memory(target
,
416 (uint32_t)(base
+(uint32_t)L2X0_CLEAN_INV_WAY
),
419 (uint8_t*)&l2_way_val
);
423 static int armv7a_handle_l2x_cache_info_command(struct command_context
*cmd_ctx
,
424 struct armv7a_cache_common
*armv7a_cache
)
427 struct armv7a_l2x_cache
*l2x_cache
= (struct armv7a_l2x_cache
*)
428 (armv7a_cache
->l2_cache
);
430 if (armv7a_cache
->ctype
== -1)
432 command_print(cmd_ctx
, "cache not yet identified");
436 command_print(cmd_ctx
,
437 "L1 D-Cache: linelen %i, associativity %i, nsets %i, cachesize %d KBytes",
438 armv7a_cache
->d_u_size
.linelen
,
439 armv7a_cache
->d_u_size
.associativity
,
440 armv7a_cache
->d_u_size
.nsets
,
441 armv7a_cache
->d_u_size
.cachesize
);
443 command_print(cmd_ctx
,
444 "L1 I-Cache: linelen %i, associativity %i, nsets %i, cachesize %d KBytes",
445 armv7a_cache
->i_size
.linelen
,
446 armv7a_cache
->i_size
.associativity
,
447 armv7a_cache
->i_size
.nsets
,
448 armv7a_cache
->i_size
.cachesize
);
449 command_print(cmd_ctx
, "L2 unified cache Base Address 0x%x, %d ways",
450 l2x_cache
->base
, l2x_cache
->way
);
457 int armv7a_l2x_cache_init(struct target
*target
, uint32_t base
, uint32_t way
)
459 struct armv7a_l2x_cache
*l2x_cache
;
460 struct target_list
*head
= target
->head
;
463 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
465 LOG_ERROR("not an armv7a target");
466 l2x_cache
= calloc(1, sizeof(struct armv7a_l2x_cache
));
467 l2x_cache
->base
= base
;
468 l2x_cache
->way
= way
;
469 /*LOG_INFO("cache l2 initialized base %x way %d",
470 l2x_cache->base,l2x_cache->way);*/
471 if (armv7a
->armv7a_mmu
.armv7a_cache
.l2_cache
)
473 LOG_INFO("cache l2 already initialized\n");
475 armv7a
->armv7a_mmu
.armv7a_cache
.l2_cache
= (void*) l2x_cache
;
476 /* initialize l1 / l2x cache function */
477 armv7a
->armv7a_mmu
.armv7a_cache
.flush_all_data_cache
478 = armv7a_l2x_flush_all_data
;
479 armv7a
->armv7a_mmu
.armv7a_cache
.display_cache_info
=
480 armv7a_handle_l2x_cache_info_command
;
481 /* initialize all target in this cluster (smp target)*/
482 /* l2 cache must be configured after smp declaration */
483 while(head
!= (struct target_list
*)NULL
)
488 armv7a
= target_to_armv7a(curr
);
489 if (armv7a
->armv7a_mmu
.armv7a_cache
.l2_cache
)
491 LOG_ERROR("smp target : cache l2 already initialized\n");
493 armv7a
->armv7a_mmu
.armv7a_cache
.l2_cache
= (void*) l2x_cache
;
494 armv7a
->armv7a_mmu
.armv7a_cache
.flush_all_data_cache
=
495 armv7a_l2x_flush_all_data
;
496 armv7a
->armv7a_mmu
.armv7a_cache
.display_cache_info
=
497 armv7a_handle_l2x_cache_info_command
;
504 COMMAND_HANDLER(handle_cache_l2x
)
506 struct target
*target
= get_current_target(CMD_CTX
);
510 return ERROR_COMMAND_SYNTAX_ERROR
;
513 //command_print(CMD_CTX, "%s %s", CMD_ARGV[0], CMD_ARGV[1]);
516 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], base
);
517 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], way
);
519 /* AP address is in bits 31:24 of DP_SELECT */
520 armv7a_l2x_cache_init(target
, base
, way
);
523 return ERROR_COMMAND_SYNTAX_ERROR
;
529 int armv7a_handle_cache_info_command(struct command_context
*cmd_ctx
,
530 struct armv7a_cache_common
*armv7a_cache
)
532 if (armv7a_cache
->ctype
== -1)
534 command_print(cmd_ctx
, "cache not yet identified");
538 if (armv7a_cache
->display_cache_info
)
539 armv7a_cache
->display_cache_info(cmd_ctx
, armv7a_cache
);
544 /* retrieve core id cluster id */
545 int arnv7a_read_mpidr(struct target
*target
)
547 int retval
= ERROR_FAIL
;
548 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
549 struct arm_dpm
*dpm
= armv7a
->armv4_5_common
.dpm
;
551 retval
= dpm
->prepare(dpm
);
552 if (retval
!=ERROR_OK
) goto done
;
553 /* MRC p15,0,<Rd>,c0,c0,5; read Multiprocessor ID register*/
555 retval
= dpm
->instr_read_data_r0(dpm
,
556 ARMV4_5_MRC(15, 0, 0, 0, 0, 5),
558 if (retval
!=ERROR_OK
) goto done
;
561 armv7a
->multi_processor_system
= (mpidr
>> 30) & 1;
562 armv7a
->cluster_id
= (mpidr
>> 8) & 0xf;
563 armv7a
->cpu_id
= mpidr
& 0x3;
564 LOG_INFO("%s cluster %x core %x %s", target
->cmd_name
,
567 armv7a
->multi_processor_system
== 0 ? "multi core": "mono core");
571 LOG_ERROR("mpdir not in multiprocessor format");
581 int armv7a_identify_cache(struct target
*target
)
583 /* read cache descriptor */
584 int retval
= ERROR_FAIL
;
585 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
586 struct arm_dpm
*dpm
= armv7a
->armv4_5_common
.dpm
;
587 uint32_t cache_selected
,clidr
;
588 uint32_t cache_i_reg
, cache_d_reg
;
589 struct armv7a_cache_common
*cache
= &(armv7a
->armv7a_mmu
.armv7a_cache
);
590 armv7a_read_ttbcr(target
);
591 retval
= dpm
->prepare(dpm
);
593 if (retval
!=ERROR_OK
) goto done
;
595 /* mrc p15, 1, r0, c0, c0, 1 @ read clidr */
596 retval
= dpm
->instr_read_data_r0(dpm
,
597 ARMV4_5_MRC(15, 1, 0, 0, 0, 1),
599 if (retval
!=ERROR_OK
) goto done
;
600 clidr
= (clidr
& 0x7000000) >> 23;
601 LOG_INFO("number of cache level %d",clidr
/2 );
604 // FIXME not supported present in cortex A8 and later
606 LOG_ERROR("cache l2 present :not supported");
608 /* retrieve selected cache */
609 /* MRC p15, 2,<Rd>, c0, c0, 0; Read CSSELR */
610 retval
= dpm
->instr_read_data_r0(dpm
,
611 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
613 if (retval
!=ERROR_OK
) goto done
;
615 retval
= armv7a
->armv4_5_common
.mrc(target
, 15,
619 /* select instruction cache*/
620 /* MCR p15, 2,<Rd>, c0, c0, 0; Write CSSELR */
621 /* [0] : 1 instruction cache selection , 0 data cache selection */
622 retval
= dpm
->instr_write_data_r0(dpm
,
623 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
625 if (retval
!=ERROR_OK
) goto done
;
628 /* MRC P15,1,<RT>,C0, C0,0 ;on cortex A9 read CCSIDR */
629 /* [2:0] line size 001 eight word per line */
630 /* [27:13] NumSet 0x7f 16KB, 0xff 32Kbytes, 0x1ff 64Kbytes */
631 retval
= dpm
->instr_read_data_r0(dpm
,
632 ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
634 if (retval
!=ERROR_OK
) goto done
;
636 /* select data cache*/
637 retval
= dpm
->instr_write_data_r0(dpm
,
638 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
640 if (retval
!=ERROR_OK
) goto done
;
642 retval
= dpm
->instr_read_data_r0(dpm
,
643 ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
645 if (retval
!=ERROR_OK
) goto done
;
647 /* restore selected cache */
648 dpm
->instr_write_data_r0(dpm
,
649 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
652 if (retval
!= ERROR_OK
) goto done
;
656 cache
->d_u_size
.linelen
= 16 << (cache_d_reg
& 0x7);
657 cache
->d_u_size
.cachesize
= (((cache_d_reg
>> 13) & 0x7fff)+1)/8;
658 cache
->d_u_size
.nsets
= (cache_d_reg
>> 13) & 0x7fff;
659 cache
->d_u_size
.associativity
= ((cache_d_reg
>> 3) & 0x3ff) +1;
660 /* compute info for set way operation on cache */
661 cache
->d_u_size
.index_shift
= (cache_d_reg
& 0x7) + 4;
662 cache
->d_u_size
.index
= (cache_d_reg
>> 13) & 0x7fff;
663 cache
->d_u_size
.way
= ((cache_d_reg
>> 3) & 0x3ff);
664 cache
->d_u_size
.way_shift
= cache
->d_u_size
.way
+1;
667 while(((cache
->d_u_size
.way_shift
>> i
) & 1)!=1) i
++;
668 cache
->d_u_size
.way_shift
= 32-i
;
670 /*LOG_INFO("data cache index %d << %d, way %d << %d",
671 cache->d_u_size.index, cache->d_u_size.index_shift,
672 cache->d_u_size.way, cache->d_u_size.way_shift);
674 LOG_INFO("data cache %d bytes %d KBytes asso %d ways",
675 cache->d_u_size.linelen,
676 cache->d_u_size.cachesize,
677 cache->d_u_size.associativity
679 cache
->i_size
.linelen
= 16 << (cache_i_reg
& 0x7);
680 cache
->i_size
.associativity
= ((cache_i_reg
>> 3) & 0x3ff) +1;
681 cache
->i_size
.nsets
= (cache_i_reg
>> 13) & 0x7fff;
682 cache
->i_size
.cachesize
= (((cache_i_reg
>> 13) & 0x7fff)+1)/8;
683 /* compute info for set way operation on cache */
684 cache
->i_size
.index_shift
= (cache_i_reg
& 0x7) + 4;
685 cache
->i_size
.index
= (cache_i_reg
>> 13) & 0x7fff;
686 cache
->i_size
.way
= ((cache_i_reg
>> 3) & 0x3ff);
687 cache
->i_size
.way_shift
= cache
->i_size
.way
+1;
690 while(((cache
->i_size
.way_shift
>> i
) & 1)!=1) i
++;
691 cache
->i_size
.way_shift
= 32-i
;
693 /*LOG_INFO("instruction cache index %d << %d, way %d << %d",
694 cache->i_size.index, cache->i_size.index_shift,
695 cache->i_size.way, cache->i_size.way_shift);
697 LOG_INFO("instruction cache %d bytes %d KBytes asso %d ways",
698 cache->i_size.linelen,
699 cache->i_size.cachesize,
700 cache->i_size.associativity
702 /* if no l2 cache initialize l1 data cache flush function function */
703 if (armv7a
->armv7a_mmu
.armv7a_cache
.flush_all_data_cache
== NULL
)
705 armv7a
->armv7a_mmu
.armv7a_cache
.display_cache_info
=
706 armv7a_handle_inner_cache_info_command
;
707 armv7a
->armv7a_mmu
.armv7a_cache
.flush_all_data_cache
=
708 armv7a_flush_all_data
;
710 armv7a
->armv7a_mmu
.armv7a_cache
.ctype
= 0;
714 arnv7a_read_mpidr(target
);
721 int armv7a_init_arch_info(struct target
*target
, struct armv7a_common
*armv7a
)
723 struct arm
*armv4_5
= &armv7a
->armv4_5_common
;
724 armv4_5
->arch_info
= armv7a
;
725 target
->arch_info
= &armv7a
->armv4_5_common
;
726 /* target is useful in all function arm v4 5 compatible */
727 armv7a
->armv4_5_common
.target
= target
;
728 armv7a
->armv4_5_common
.common_magic
= ARM_COMMON_MAGIC
;
729 armv7a
->common_magic
= ARMV7_COMMON_MAGIC
;
730 armv7a
->armv7a_mmu
.armv7a_cache
.l2_cache
= NULL
;
731 armv7a
->armv7a_mmu
.armv7a_cache
.ctype
= -1;
732 armv7a
->armv7a_mmu
.armv7a_cache
.flush_all_data_cache
= NULL
;
733 armv7a
->armv7a_mmu
.armv7a_cache
.display_cache_info
= NULL
;
737 int armv7a_arch_state(struct target
*target
)
739 static const char *state
[] =
741 "disabled", "enabled"
744 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
745 struct arm
*armv4_5
= &armv7a
->armv4_5_common
;
747 if (armv7a
->common_magic
!= ARMV7_COMMON_MAGIC
)
749 LOG_ERROR("BUG: called for a non-ARMv7A target");
750 return ERROR_INVALID_ARGUMENTS
;
753 arm_arch_state(target
);
755 LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
756 state
[armv7a
->armv7a_mmu
.mmu_enabled
],
757 state
[armv7a
->armv7a_mmu
.armv7a_cache
.d_u_cache_enabled
],
758 state
[armv7a
->armv7a_mmu
.armv7a_cache
.i_cache_enabled
]);
760 if (armv4_5
->core_mode
== ARM_MODE_ABT
)
761 armv7a_show_fault_registers(target
);
762 if (target
->debug_reason
== DBG_REASON_WATCHPOINT
)
763 LOG_USER("Watchpoint triggered at PC %#08x",
764 (unsigned) armv7a
->dpm
.wp_pc
);
769 static const struct command_registration l2_cache_commands
[] = {
772 .handler
= handle_cache_l2x
,
773 .mode
= COMMAND_EXEC
,
774 .help
= "configure l2x cache "
776 .usage
= "[base_addr] [number_of_way]",
778 COMMAND_REGISTRATION_DONE
782 const struct command_registration l2x_cache_command_handlers
[] = {
784 .name
= "cache_config",
785 .mode
= COMMAND_EXEC
,
786 .help
= "cache configuation for a target",
787 .chain
= l2_cache_commands
,
789 COMMAND_REGISTRATION_DONE
793 const struct command_registration armv7a_command_handlers
[] = {
795 .chain
= dap_command_handlers
,
798 .chain
= l2x_cache_command_handlers
,
800 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)