67c563e67e17bf202174e9888d4045cce76dd26d
[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, write to the *
18 * Free Software Foundation, Inc., *
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
20 ***************************************************************************/
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <helper/replacements.h>
26
27 #include "armv7a.h"
28 #include "arm_disassembler.h"
29
30 #include "register.h"
31 #include <helper/binarybuffer.h>
32 #include <helper/command.h>
33
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37
38 #include "arm_opcodes.h"
39 #include "target.h"
40 #include "target_type.h"
41
42 static void armv7a_show_fault_registers(struct target *target)
43 {
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;
47 int retval;
48
49 retval = dpm->prepare(dpm);
50 if (retval != ERROR_OK)
51 return;
52
53 /* ARMV4_5_MRC(cpnum, op1, r0, CRn, CRm, op2) */
54
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),
58 &dfsr);
59 if (retval != ERROR_OK)
60 goto done;
61
62 retval = dpm->instr_read_data_r0(dpm,
63 ARMV4_5_MRC(15, 0, 0, 5, 0, 1),
64 &ifsr);
65 if (retval != ERROR_OK)
66 goto done;
67
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),
71 &dfar);
72 if (retval != ERROR_OK)
73 goto done;
74
75 retval = dpm->instr_read_data_r0(dpm,
76 ARMV4_5_MRC(15, 0, 0, 6, 0, 2),
77 &ifar);
78 if (retval != ERROR_OK)
79 goto done;
80
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);
85
86 done:
87 /* (void) */ dpm->finish(dpm);
88 }
89
90 static int armv7a_read_ttbcr(struct target *target)
91 {
92 struct armv7a_common *armv7a = target_to_armv7a(target);
93 struct arm_dpm *dpm = armv7a->armv4_5_common.dpm;
94 uint32_t ttbcr;
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),
100 &ttbcr);
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)));
104 #if 0
105 LOG_INFO("ttb1 %s ,ttb0_mask %x",
106 armv7a->armv7a_mmu.ttbr1_used ? "used":"not used",
107 armv7a->armv7a_mmu.ttbr0_mask);
108 #endif
109 if (armv7a->armv7a_mmu.ttbr1_used == 1)
110 {
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;
114 }
115 else
116 {
117 /* fix me , default is hard coded LINUX border */
118 armv7a->armv7a_mmu.os_border = 0xc0000000;
119 }
120 done:
121 dpm->finish(dpm);
122 return retval;
123 }
124
125
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)
128 {
129 uint32_t first_lvl_descriptor = 0x0;
130 uint32_t second_lvl_descriptor = 0x0;
131 int retval;
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)))
138 {
139 /* select ttb 1 */
140 ttb = 1;
141 }
142 retval = dpm->prepare(dpm);
143 if (retval != ERROR_OK)
144 goto done;
145
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),
149 &ttb);
150 if (retval != ERROR_OK)
151 return retval;
152 retval = armv7a->armv7a_mmu.read_physical_memory(target,
153 (ttb & 0xffffc000) | ((va & 0xfff00000) >> 18),
154 4, 1, (uint8_t*)&first_lvl_descriptor);
155 if (retval != ERROR_OK)
156 return retval;
157 first_lvl_descriptor = target_buffer_get_u32(target, (uint8_t*)
158 &first_lvl_descriptor);
159 /* reuse armv4_5 piece of code, specific armv7a changes may come later */
160 LOG_DEBUG("1st lvl desc: %8.8" PRIx32 "", first_lvl_descriptor);
161
162 if ((first_lvl_descriptor & 0x3) == 0)
163 {
164 LOG_ERROR("Address translation failure");
165 return ERROR_TARGET_TRANSLATION_FAULT;
166 }
167
168
169 if ((first_lvl_descriptor & 0x3) == 2)
170 {
171 /* section descriptor */
172 *val = (first_lvl_descriptor & 0xfff00000) | (va & 0x000fffff);
173 return ERROR_OK;
174 }
175
176 if ((first_lvl_descriptor & 0x3) == 1)
177 {
178 /* coarse page table */
179 retval = armv7a->armv7a_mmu.read_physical_memory(target,
180 (first_lvl_descriptor & 0xfffffc00) | ((va & 0x000ff000) >> 10),
181 4, 1, (uint8_t*)&second_lvl_descriptor);
182 if (retval != ERROR_OK)
183 return retval;
184 }
185 else if ((first_lvl_descriptor & 0x3) == 3)
186 {
187 /* fine page table */
188 retval = armv7a->armv7a_mmu.read_physical_memory(target,
189 (first_lvl_descriptor & 0xfffff000) | ((va & 0x000ffc00) >> 8),
190 4, 1, (uint8_t*)&second_lvl_descriptor);
191 if (retval != ERROR_OK)
192 return retval;
193 }
194
195 second_lvl_descriptor = target_buffer_get_u32(target, (uint8_t*)
196 &second_lvl_descriptor);
197
198 LOG_DEBUG("2nd lvl desc: %8.8" PRIx32 "", second_lvl_descriptor);
199
200 if ((second_lvl_descriptor & 0x3) == 0)
201 {
202 LOG_ERROR("Address translation failure");
203 return ERROR_TARGET_TRANSLATION_FAULT;
204 }
205
206 if ((second_lvl_descriptor & 0x3) == 1)
207 {
208 /* large page descriptor */
209 *val = (second_lvl_descriptor & 0xffff0000) | (va & 0x0000ffff);
210 return ERROR_OK;
211 }
212
213 if ((second_lvl_descriptor & 0x3) == 2)
214 {
215 /* small page descriptor */
216 *val = (second_lvl_descriptor & 0xfffff000) | (va & 0x00000fff);
217 return ERROR_OK;
218 }
219
220 if ((second_lvl_descriptor & 0x3) == 3)
221 {
222 *val = (second_lvl_descriptor & 0xfffffc00) | (va & 0x000003ff);
223 return ERROR_OK;
224 }
225
226 /* should not happen */
227 LOG_ERROR("Address translation failure");
228 return ERROR_TARGET_TRANSLATION_FAULT;
229
230 done:
231 return retval;
232 }
233
234
235 /* V7 method VA TO PA */
236 int armv7a_mmu_translate_va_pa(struct target *target, uint32_t va,
237 uint32_t *val, int meminfo)
238 {
239 int retval = ERROR_FAIL;
240 struct armv7a_common *armv7a = target_to_armv7a(target);
241 struct arm_dpm *dpm = armv7a->armv4_5_common.dpm;
242 uint32_t virt = va & ~0xfff;
243 uint32_t NOS,NS,INNER,OUTER;
244 *val = 0xdeadbeef;
245 retval = dpm->prepare(dpm);
246 if (retval != ERROR_OK)
247 goto done;
248 /* mmu must be enable in order to get a correct translation */
249 /* use VA to PA CP15 register for conversion */
250 retval = dpm->instr_write_data_r0(dpm,
251 ARMV4_5_MCR(15, 0, 0, 7, 8, 0),
252 virt);
253 if (retval!=ERROR_OK) goto done;
254 retval = dpm->instr_read_data_r0(dpm,
255 ARMV4_5_MRC(15, 0, 0, 7, 4, 0),
256 val);
257 /* decode memory attribute */
258 NOS = (*val >> 10) & 1; /* Not Outer shareable */
259 NS = (*val >> 9) & 1; /* Non secure */
260 INNER = (*val >> 4) & 0x7;
261 OUTER = (*val >> 2) & 0x3;
262
263 if (retval!=ERROR_OK) goto done;
264 *val = (*val & ~0xfff) + (va & 0xfff);
265 if (*val == va)
266 LOG_WARNING("virt = phys : MMU disable !!");
267 if (meminfo)
268 {
269 LOG_INFO("%x : %x %s outer shareable %s secured",
270 va, *val,
271 NOS == 1 ? "not" : " ",
272 NS == 1 ? "not" :"");
273 switch (OUTER) {
274 case 0 : LOG_INFO("outer: Non-Cacheable");
275 break;
276 case 1 : LOG_INFO("outer: Write-Back, Write-Allocate");
277 break;
278 case 2 : LOG_INFO("outer: Write-Through, No Write-Allocate");
279 break;
280 case 3 : LOG_INFO("outer: Write-Back, no Write-Allocate");
281 break;
282 }
283 switch (INNER) {
284 case 0 : LOG_INFO("inner: Non-Cacheable");
285 break;
286 case 1 : LOG_INFO("inner: Strongly-ordered");
287 break;
288 case 3 : LOG_INFO("inner: Device");
289 break;
290 case 5 : LOG_INFO("inner: Write-Back, Write-Allocate");
291 break;
292 case 6 : LOG_INFO("inner: Write-Through");
293 break;
294 case 7 : LOG_INFO("inner: Write-Back, no Write-Allocate");
295
296 default: LOG_INFO("inner: %x ???",INNER);
297 }
298 }
299
300 done:
301 dpm->finish(dpm);
302
303 return retval;
304 }
305
306 static int armv7a_handle_inner_cache_info_command(struct command_context *cmd_ctx,
307 struct armv7a_cache_common *armv7a_cache)
308 {
309 if (armv7a_cache->ctype == -1)
310 {
311 command_print(cmd_ctx, "cache not yet identified");
312 return ERROR_OK;
313 }
314
315 command_print(cmd_ctx,
316 "D-Cache: linelen %i, associativity %i, nsets %i, cachesize %d KBytes",
317 armv7a_cache->d_u_size.linelen,
318 armv7a_cache->d_u_size.associativity,
319 armv7a_cache->d_u_size.nsets,
320 armv7a_cache->d_u_size.cachesize);
321
322 command_print(cmd_ctx,
323 "I-Cache: linelen %i, associativity %i, nsets %i, cachesize %d KBytes",
324 armv7a_cache->i_size.linelen,
325 armv7a_cache->i_size.associativity,
326 armv7a_cache->i_size.nsets,
327 armv7a_cache->i_size.cachesize);
328
329 return ERROR_OK;
330 }
331
332 static int _armv7a_flush_all_data(struct target *target)
333 {
334 struct armv7a_common *armv7a = target_to_armv7a(target);
335 struct arm_dpm *dpm = armv7a->armv4_5_common.dpm;
336 struct armv7a_cachesize *d_u_size =
337 &(armv7a->armv7a_mmu.armv7a_cache.d_u_size);
338 int32_t c_way, c_index = d_u_size->index;
339 int retval;
340 /* check that cache data is on at target halt */
341 if (!armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled)
342 {
343 LOG_INFO("flushed not performed :cache not on at target halt");
344 return ERROR_OK;
345 }
346 retval = dpm->prepare(dpm);
347 if (retval != ERROR_OK) goto done;
348 do {
349 c_way = d_u_size->way;
350 do {
351 uint32_t value = (c_index << d_u_size->index_shift)
352 | (c_way << d_u_size->way_shift);
353 /* DCCISW */
354 //LOG_INFO ("%d %d %x",c_way,c_index,value);
355 retval = dpm->instr_write_data_r0(dpm,
356 ARMV4_5_MCR(15, 0, 0, 7, 14, 2),
357 value);
358 if (retval!= ERROR_OK) goto done;
359 c_way -= 1;
360 } while (c_way >=0);
361 c_index -= 1;
362 } while (c_index >=0);
363 return retval;
364 done:
365 LOG_ERROR("flushed failed");
366 dpm->finish(dpm);
367 return retval;
368 }
369
370 static int armv7a_flush_all_data( struct target * target)
371 {
372 int retval = ERROR_FAIL;
373 /* check that armv7a_cache is correctly identify */
374 struct armv7a_common *armv7a = target_to_armv7a(target);
375 if (armv7a->armv7a_mmu.armv7a_cache.ctype == -1)
376 {
377 LOG_ERROR("trying to flush un-identified cache");
378 return retval;
379 }
380
381 if (target->smp)
382 {
383 /* look if all the other target have been flushed in order to flush level
384 * 2 */
385 struct target_list *head;
386 struct target *curr;
387 head = target->head;
388 while(head != (struct target_list*)NULL)
389 {
390 curr = head->target;
391 if ((curr->state == TARGET_HALTED))
392 { LOG_INFO("Wait flushing data l1 on core %d",curr->coreid);
393 retval = _armv7a_flush_all_data(curr);
394 }
395 head = head->next;
396 }
397 }
398 else retval = _armv7a_flush_all_data(target);
399 return retval;
400 }
401
402
403 /* L2 is not specific to armv7a a specific file is needed */
404 static int armv7a_l2x_flush_all_data(struct target * target)
405 {
406
407 #define L2X0_CLEAN_INV_WAY 0x7FC
408 int retval = ERROR_FAIL;
409 struct armv7a_common *armv7a = target_to_armv7a(target);
410 struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache*)
411 (armv7a->armv7a_mmu.armv7a_cache.l2_cache);
412 uint32_t base = l2x_cache->base;
413 uint32_t l2_way = l2x_cache->way;
414 uint32_t l2_way_val = (1<<l2_way) -1;
415 retval = armv7a_flush_all_data(target);
416 if (retval!=ERROR_OK) return retval;
417 retval = target->type->write_phys_memory(target,
418 (uint32_t)(base+(uint32_t)L2X0_CLEAN_INV_WAY),
419 (uint32_t)4,
420 (uint32_t)1,
421 (uint8_t*)&l2_way_val);
422 return retval;
423 }
424
425 static int armv7a_handle_l2x_cache_info_command(struct command_context *cmd_ctx,
426 struct armv7a_cache_common *armv7a_cache)
427 {
428
429 struct armv7a_l2x_cache *l2x_cache = (struct armv7a_l2x_cache*)
430 (armv7a_cache->l2_cache);
431
432 if (armv7a_cache->ctype == -1)
433 {
434 command_print(cmd_ctx, "cache not yet identified");
435 return ERROR_OK;
436 }
437
438 command_print(cmd_ctx,
439 "L1 D-Cache: linelen %i, associativity %i, nsets %i, cachesize %d KBytes",
440 armv7a_cache->d_u_size.linelen,
441 armv7a_cache->d_u_size.associativity,
442 armv7a_cache->d_u_size.nsets,
443 armv7a_cache->d_u_size.cachesize);
444
445 command_print(cmd_ctx,
446 "L1 I-Cache: linelen %i, associativity %i, nsets %i, cachesize %d KBytes",
447 armv7a_cache->i_size.linelen,
448 armv7a_cache->i_size.associativity,
449 armv7a_cache->i_size.nsets,
450 armv7a_cache->i_size.cachesize);
451 command_print(cmd_ctx, "L2 unified cache Base Address 0x%x, %d ways",
452 l2x_cache->base, l2x_cache->way);
453
454
455 return ERROR_OK;
456 }
457
458
459 static int armv7a_l2x_cache_init(struct target *target, uint32_t base, uint32_t way)
460 {
461 struct armv7a_l2x_cache *l2x_cache;
462 struct target_list *head = target->head;
463 struct target *curr;
464
465 struct armv7a_common *armv7a = target_to_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)
472 {
473 LOG_INFO("cache l2 already initialized\n");
474 }
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)
484 {
485 curr = head->target;
486 if (curr != target)
487 {
488 armv7a = target_to_armv7a(curr);
489 if (armv7a->armv7a_mmu.armv7a_cache.l2_cache)
490 {
491 LOG_ERROR("smp target : cache l2 already initialized\n");
492 }
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;
498 }
499 head = head -> next;
500 }
501 return JIM_OK;
502 }
503
504 COMMAND_HANDLER(handle_cache_l2x)
505 {
506 struct target *target = get_current_target(CMD_CTX);
507 uint32_t base, way;
508 switch (CMD_ARGC) {
509 case 0:
510 return ERROR_COMMAND_SYNTAX_ERROR;
511 break;
512 case 2:
513 //command_print(CMD_CTX, "%s %s", CMD_ARGV[0], CMD_ARGV[1]);
514
515
516 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], base);
517 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], way);
518
519 /* AP address is in bits 31:24 of DP_SELECT */
520 armv7a_l2x_cache_init(target, base, way);
521 break;
522 default:
523 return ERROR_COMMAND_SYNTAX_ERROR;
524 }
525 return ERROR_OK;
526 }
527
528
529 int armv7a_handle_cache_info_command(struct command_context *cmd_ctx,
530 struct armv7a_cache_common *armv7a_cache)
531 {
532 if (armv7a_cache->ctype == -1)
533 {
534 command_print(cmd_ctx, "cache not yet identified");
535 return ERROR_OK;
536 }
537
538 if (armv7a_cache->display_cache_info)
539 armv7a_cache->display_cache_info(cmd_ctx, armv7a_cache);
540 return ERROR_OK;
541 }
542
543
544 /* retrieve core id cluster id */
545 static int armv7a_read_mpidr(struct target *target)
546 {
547 int retval = ERROR_FAIL;
548 struct armv7a_common *armv7a = target_to_armv7a(target);
549 struct arm_dpm *dpm = armv7a->armv4_5_common.dpm;
550 uint32_t mpidr;
551 retval = dpm->prepare(dpm);
552 if (retval!=ERROR_OK) goto done;
553 /* MRC p15,0,<Rd>,c0,c0,5; read Multiprocessor ID register*/
554
555 retval = dpm->instr_read_data_r0(dpm,
556 ARMV4_5_MRC(15, 0, 0, 0, 0, 5),
557 &mpidr);
558 if (retval!=ERROR_OK) goto done;
559 if (mpidr & 1<<31)
560 {
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,
565 armv7a->cluster_id,
566 armv7a->cpu_id,
567 armv7a->multi_processor_system == 0 ? "multi core": "mono core");
568
569 }
570 else
571 LOG_ERROR("mpdir not in multiprocessor format");
572
573 done:
574 dpm->finish(dpm);
575 return retval;
576
577
578 }
579
580
581 int armv7a_identify_cache(struct target *target)
582 {
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);
592
593 if (retval!=ERROR_OK) goto done;
594 /* retrieve CLIDR */
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),
598 &clidr);
599 if (retval!=ERROR_OK) goto done;
600 clidr = (clidr & 0x7000000) >> 23;
601 LOG_INFO("number of cache level %d",clidr /2 );
602 if ((clidr /2) > 1)
603 {
604 // FIXME not supported present in cortex A8 and later
605 // in cortex A7, A15
606 LOG_ERROR("cache l2 present :not supported");
607 }
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),
612 &cache_selected);
613 if (retval!=ERROR_OK) goto done;
614
615 retval = armv7a->armv4_5_common.mrc(target, 15,
616 2, 0, /* op1, op2 */
617 0, 0, /* CRn, CRm */
618 &cache_selected);
619 if (retval!=ERROR_OK) goto done;
620 /* select instruction cache*/
621 /* MCR p15, 2,<Rd>, c0, c0, 0; Write CSSELR */
622 /* [0] : 1 instruction cache selection , 0 data cache selection */
623 retval = dpm->instr_write_data_r0(dpm,
624 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
625 1);
626 if (retval!=ERROR_OK) goto done;
627
628 /* read CCSIDR*/
629 /* MRC P15,1,<RT>,C0, C0,0 ;on cortex A9 read CCSIDR */
630 /* [2:0] line size 001 eight word per line */
631 /* [27:13] NumSet 0x7f 16KB, 0xff 32Kbytes, 0x1ff 64Kbytes */
632 retval = dpm->instr_read_data_r0(dpm,
633 ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
634 &cache_i_reg);
635 if (retval!=ERROR_OK) goto done;
636
637 /* select data cache*/
638 retval = dpm->instr_write_data_r0(dpm,
639 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
640 0);
641 if (retval!=ERROR_OK) goto done;
642
643 retval = dpm->instr_read_data_r0(dpm,
644 ARMV4_5_MRC(15, 1, 0, 0, 0, 0),
645 &cache_d_reg);
646 if (retval!=ERROR_OK) goto done;
647
648 /* restore selected cache */
649 dpm->instr_write_data_r0(dpm,
650 ARMV4_5_MRC(15, 2, 0, 0, 0, 0),
651 cache_selected);
652
653 if (retval != ERROR_OK) goto done;
654 dpm->finish(dpm);
655
656 // put fake type
657 cache->d_u_size.linelen = 16 << (cache_d_reg & 0x7);
658 cache->d_u_size.cachesize = (((cache_d_reg >> 13) & 0x7fff)+1)/8;
659 cache->d_u_size.nsets = (cache_d_reg >> 13) & 0x7fff;
660 cache->d_u_size.associativity = ((cache_d_reg >> 3) & 0x3ff) +1;
661 /* compute info for set way operation on cache */
662 cache->d_u_size.index_shift = (cache_d_reg & 0x7) + 4;
663 cache->d_u_size.index = (cache_d_reg >> 13) & 0x7fff;
664 cache->d_u_size.way = ((cache_d_reg >> 3) & 0x3ff);
665 cache->d_u_size.way_shift = cache->d_u_size.way+1;
666 {
667 int i=0;
668 while(((cache->d_u_size.way_shift >> i) & 1)!=1) i++;
669 cache->d_u_size.way_shift = 32-i;
670 }
671 /*LOG_INFO("data cache index %d << %d, way %d << %d",
672 cache->d_u_size.index, cache->d_u_size.index_shift,
673 cache->d_u_size.way, cache->d_u_size.way_shift);
674
675 LOG_INFO("data cache %d bytes %d KBytes asso %d ways",
676 cache->d_u_size.linelen,
677 cache->d_u_size.cachesize,
678 cache->d_u_size.associativity
679 );*/
680 cache->i_size.linelen = 16 << (cache_i_reg & 0x7);
681 cache->i_size.associativity = ((cache_i_reg >> 3) & 0x3ff) +1;
682 cache->i_size.nsets = (cache_i_reg >> 13) & 0x7fff;
683 cache->i_size.cachesize = (((cache_i_reg >> 13) & 0x7fff)+1)/8;
684 /* compute info for set way operation on cache */
685 cache->i_size.index_shift = (cache_i_reg & 0x7) + 4;
686 cache->i_size.index = (cache_i_reg >> 13) & 0x7fff;
687 cache->i_size.way = ((cache_i_reg >> 3) & 0x3ff);
688 cache->i_size.way_shift = cache->i_size.way+1;
689 {
690 int i=0;
691 while(((cache->i_size.way_shift >> i) & 1)!=1) i++;
692 cache->i_size.way_shift = 32-i;
693 }
694 /*LOG_INFO("instruction cache index %d << %d, way %d << %d",
695 cache->i_size.index, cache->i_size.index_shift,
696 cache->i_size.way, cache->i_size.way_shift);
697
698 LOG_INFO("instruction cache %d bytes %d KBytes asso %d ways",
699 cache->i_size.linelen,
700 cache->i_size.cachesize,
701 cache->i_size.associativity
702 );*/
703 /* if no l2 cache initialize l1 data cache flush function function */
704 if (armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache == NULL)
705 {
706 armv7a->armv7a_mmu.armv7a_cache.display_cache_info =
707 armv7a_handle_inner_cache_info_command;
708 armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache =
709 armv7a_flush_all_data;
710 }
711 armv7a->armv7a_mmu.armv7a_cache.ctype = 0;
712
713 done:
714 dpm->finish(dpm);
715 armv7a_read_mpidr(target);
716 return retval;
717
718 }
719
720
721
722 int armv7a_init_arch_info(struct target *target, struct armv7a_common *armv7a)
723 {
724 struct arm *armv4_5 = &armv7a->armv4_5_common;
725 armv4_5->arch_info = armv7a;
726 target->arch_info = &armv7a->armv4_5_common;
727 /* target is useful in all function arm v4 5 compatible */
728 armv7a->armv4_5_common.target = target;
729 armv7a->armv4_5_common.common_magic = ARM_COMMON_MAGIC;
730 armv7a->common_magic = ARMV7_COMMON_MAGIC;
731 armv7a->armv7a_mmu.armv7a_cache.l2_cache = NULL;
732 armv7a->armv7a_mmu.armv7a_cache.ctype = -1;
733 armv7a->armv7a_mmu.armv7a_cache.flush_all_data_cache = NULL;
734 armv7a->armv7a_mmu.armv7a_cache.display_cache_info = NULL;
735 return ERROR_OK;
736 }
737
738 int armv7a_arch_state(struct target *target)
739 {
740 static const char *state[] =
741 {
742 "disabled", "enabled"
743 };
744
745 struct armv7a_common *armv7a = target_to_armv7a(target);
746 struct arm *armv4_5 = &armv7a->armv4_5_common;
747
748 if (armv7a->common_magic != ARMV7_COMMON_MAGIC)
749 {
750 LOG_ERROR("BUG: called for a non-ARMv7A target");
751 return ERROR_INVALID_ARGUMENTS;
752 }
753
754 arm_arch_state(target);
755
756 LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s",
757 state[armv7a->armv7a_mmu.mmu_enabled],
758 state[armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled],
759 state[armv7a->armv7a_mmu.armv7a_cache.i_cache_enabled]);
760
761 if (armv4_5->core_mode == ARM_MODE_ABT)
762 armv7a_show_fault_registers(target);
763 if (target->debug_reason == DBG_REASON_WATCHPOINT)
764 LOG_USER("Watchpoint triggered at PC %#08x",
765 (unsigned) armv7a->dpm.wp_pc);
766
767 return ERROR_OK;
768 }
769
770 static const struct command_registration l2_cache_commands[] = {
771 {
772 .name = "l2x",
773 .handler = handle_cache_l2x,
774 .mode = COMMAND_EXEC,
775 .help = "configure l2x cache "
776 "",
777 .usage = "[base_addr] [number_of_way]",
778 },
779 COMMAND_REGISTRATION_DONE
780
781 };
782
783 const struct command_registration l2x_cache_command_handlers[] = {
784 {
785 .name = "cache_config",
786 .mode = COMMAND_EXEC,
787 .help = "cache configuation for a target",
788 .chain = l2_cache_commands,
789 },
790 COMMAND_REGISTRATION_DONE
791 };
792
793
794 const struct command_registration armv7a_command_handlers[] = {
795 {
796 .chain = dap_command_handlers,
797 },
798 {
799 .chain = l2x_cache_command_handlers,
800 },
801 COMMAND_REGISTRATION_DONE
802 };
803

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)