1 /***************************************************************************
2 * Copyright (C) 2015 by Oleksij Rempel *
3 * linux@rempel-privat.de *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
23 #include "jtag/interface.h"
26 #include "armv7a_cache.h"
27 #include <helper/time_support.h>
28 #include "arm_opcodes.h"
30 static int armv7a_l1_d_cache_sanity_check(struct target
*target
)
32 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
34 if (target
->state
!= TARGET_HALTED
) {
35 LOG_ERROR("%s: target not halted", __func__
);
36 return ERROR_TARGET_NOT_HALTED
;
39 /* check that cache data is on at target halt */
40 if (!armv7a
->armv7a_mmu
.armv7a_cache
.d_u_cache_enabled
) {
41 LOG_DEBUG("data cache is not enabled");
42 return ERROR_TARGET_INVALID
;
48 static int armv7a_l1_i_cache_sanity_check(struct target
*target
)
50 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
52 if (target
->state
!= TARGET_HALTED
) {
53 LOG_ERROR("%s: target not halted", __func__
);
54 return ERROR_TARGET_NOT_HALTED
;
57 /* check that cache data is on at target halt */
58 if (!armv7a
->armv7a_mmu
.armv7a_cache
.i_cache_enabled
) {
59 LOG_DEBUG("instruction cache is not enabled");
60 return ERROR_TARGET_INVALID
;
66 static int armv7a_l1_d_cache_flush_level(struct arm_dpm
*dpm
, struct armv7a_cachesize
*size
, int cl
)
68 int retval
= ERROR_OK
;
69 int32_t c_way
, c_index
= size
->index
;
71 LOG_DEBUG("cl %" PRId32
, cl
);
75 uint32_t value
= (c_index
<< size
->index_shift
)
76 | (c_way
<< size
->way_shift
) | (cl
<< 1);
78 * DCCISW - Clean and invalidate data cache
81 retval
= dpm
->instr_write_data_r0(dpm
,
82 ARMV4_5_MCR(15, 0, 0, 7, 14, 2),
84 if (retval
!= ERROR_OK
)
89 } while (c_index
>= 0);
95 static int armv7a_l1_d_cache_clean_inval_all(struct target
*target
)
97 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
98 struct armv7a_cache_common
*cache
= &(armv7a
->armv7a_mmu
.armv7a_cache
);
99 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
103 retval
= armv7a_l1_d_cache_sanity_check(target
);
104 if (retval
!= ERROR_OK
)
107 retval
= dpm
->prepare(dpm
);
108 if (retval
!= ERROR_OK
)
111 for (cl
= 0; cl
< cache
->loc
; cl
++) {
112 /* skip i-only caches */
113 if (cache
->arch
[cl
].ctype
< CACHE_LEVEL_HAS_D_CACHE
)
116 armv7a_l1_d_cache_flush_level(dpm
, &cache
->arch
[cl
].d_u_size
, cl
);
119 retval
= dpm
->finish(dpm
);
123 LOG_ERROR("clean invalidate failed");
129 int armv7a_cache_auto_flush_all_data(struct target
*target
)
131 int retval
= ERROR_FAIL
;
132 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
134 if (!armv7a
->armv7a_mmu
.armv7a_cache
.auto_cache_enabled
)
138 struct target_list
*head
;
141 while (head
!= (struct target_list
*)NULL
) {
143 if (curr
->state
== TARGET_HALTED
)
144 retval
= armv7a_l1_d_cache_clean_inval_all(curr
);
149 retval
= armv7a_l1_d_cache_clean_inval_all(target
);
151 if (retval
!= ERROR_OK
)
154 /* do outer cache flushing after inner caches have been flushed */
155 return arm7a_l2x_flush_all_data(target
);
159 int armv7a_l1_d_cache_inval_virt(struct target
*target
, uint32_t virt
,
162 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
163 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
164 struct armv7a_cache_common
*armv7a_cache
= &armv7a
->armv7a_mmu
.armv7a_cache
;
165 uint32_t linelen
= armv7a_cache
->dminline
;
166 uint32_t va_line
, va_end
;
169 retval
= armv7a_l1_d_cache_sanity_check(target
);
170 if (retval
!= ERROR_OK
)
173 retval
= dpm
->prepare(dpm
);
174 if (retval
!= ERROR_OK
)
177 va_line
= virt
& (-linelen
);
178 va_end
= virt
+ size
;
180 /* handle unaligned start */
181 if (virt
!= va_line
) {
183 retval
= dpm
->instr_write_data_r0(dpm
,
184 ARMV4_5_MCR(15, 0, 0, 7, 14, 1), va_line
);
185 if (retval
!= ERROR_OK
)
190 /* handle unaligned end */
191 if ((va_end
& (linelen
-1)) != 0) {
192 va_end
&= (-linelen
);
194 retval
= dpm
->instr_write_data_r0(dpm
,
195 ARMV4_5_MCR(15, 0, 0, 7, 14, 1), va_end
);
196 if (retval
!= ERROR_OK
)
200 while (va_line
< va_end
) {
201 /* DCIMVAC - Invalidate data cache line by VA to PoC. */
202 retval
= dpm
->instr_write_data_r0(dpm
,
203 ARMV4_5_MCR(15, 0, 0, 7, 6, 1), va_line
);
204 if (retval
!= ERROR_OK
)
213 LOG_ERROR("d-cache invalidate failed");
219 int armv7a_l1_d_cache_clean_virt(struct target
*target
, uint32_t virt
,
222 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
223 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
224 struct armv7a_cache_common
*armv7a_cache
= &armv7a
->armv7a_mmu
.armv7a_cache
;
225 uint32_t linelen
= armv7a_cache
->dminline
;
226 uint32_t va_line
, va_end
;
229 retval
= armv7a_l1_d_cache_sanity_check(target
);
230 if (retval
!= ERROR_OK
)
233 retval
= dpm
->prepare(dpm
);
234 if (retval
!= ERROR_OK
)
237 va_line
= virt
& (-linelen
);
238 va_end
= virt
+ size
;
240 while (va_line
< va_end
) {
241 /* DCCMVAC - Data Cache Clean by MVA to PoC */
242 retval
= dpm
->instr_write_data_r0(dpm
,
243 ARMV4_5_MCR(15, 0, 0, 7, 10, 1), va_line
);
244 if (retval
!= ERROR_OK
)
253 LOG_ERROR("d-cache invalidate failed");
259 int armv7a_l1_d_cache_flush_virt(struct target
*target
, uint32_t virt
,
262 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
263 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
264 struct armv7a_cache_common
*armv7a_cache
= &armv7a
->armv7a_mmu
.armv7a_cache
;
265 uint32_t linelen
= armv7a_cache
->dminline
;
266 uint32_t va_line
, va_end
;
269 retval
= armv7a_l1_d_cache_sanity_check(target
);
270 if (retval
!= ERROR_OK
)
273 retval
= dpm
->prepare(dpm
);
274 if (retval
!= ERROR_OK
)
277 va_line
= virt
& (-linelen
);
278 va_end
= virt
+ size
;
280 while (va_line
< va_end
) {
282 retval
= dpm
->instr_write_data_r0(dpm
,
283 ARMV4_5_MCR(15, 0, 0, 7, 14, 1), va_line
);
284 if (retval
!= ERROR_OK
)
293 LOG_ERROR("d-cache invalidate failed");
299 int armv7a_l1_i_cache_inval_all(struct target
*target
)
301 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
302 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
305 retval
= armv7a_l1_i_cache_sanity_check(target
);
306 if (retval
!= ERROR_OK
)
309 retval
= dpm
->prepare(dpm
);
310 if (retval
!= ERROR_OK
)
315 retval
= dpm
->instr_write_data_r0(dpm
,
316 ARMV4_5_MCR(15, 0, 0, 7, 1, 0), 0);
319 retval
= dpm
->instr_write_data_r0(dpm
,
320 ARMV4_5_MCR(15, 0, 0, 7, 5, 0), 0);
323 if (retval
!= ERROR_OK
)
330 LOG_ERROR("i-cache invalidate failed");
336 int armv7a_l1_i_cache_inval_virt(struct target
*target
, uint32_t virt
,
339 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
340 struct arm_dpm
*dpm
= armv7a
->arm
.dpm
;
341 struct armv7a_cache_common
*armv7a_cache
=
342 &armv7a
->armv7a_mmu
.armv7a_cache
;
343 uint32_t linelen
= armv7a_cache
->iminline
;
344 uint32_t va_line
, va_end
;
347 retval
= armv7a_l1_i_cache_sanity_check(target
);
348 if (retval
!= ERROR_OK
)
351 retval
= dpm
->prepare(dpm
);
352 if (retval
!= ERROR_OK
)
355 va_line
= virt
& (-linelen
);
356 va_end
= virt
+ size
;
358 while (va_line
< va_end
) {
359 /* ICIMVAU - Invalidate instruction cache by VA to PoU. */
360 retval
= dpm
->instr_write_data_r0(dpm
,
361 ARMV4_5_MCR(15, 0, 0, 7, 5, 1), va_line
);
362 if (retval
!= ERROR_OK
)
365 retval
= dpm
->instr_write_data_r0(dpm
,
366 ARMV4_5_MCR(15, 0, 0, 7, 5, 7), va_line
);
367 if (retval
!= ERROR_OK
)
374 LOG_ERROR("i-cache invalidate failed");
380 int armv7a_cache_flush_virt(struct target
*target
, uint32_t virt
,
383 armv7a_l1_d_cache_flush_virt(target
, virt
, size
);
384 armv7a_l2x_cache_flush_virt(target
, virt
, size
);
390 * We assume that target core was chosen correctly. It means if same data
391 * was handled by two cores, other core will loose the changes. Since it
392 * is impossible to know (FIXME) which core has correct data, keep in mind
393 * that some kind of data lost or korruption is possible.
395 * - core1 loaded and changed data on 0x12345678
396 * - we halted target and modified same data on core0
397 * - data on core1 will be lost.
399 int armv7a_cache_auto_flush_on_write(struct target
*target
, uint32_t virt
,
402 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
404 if (!armv7a
->armv7a_mmu
.armv7a_cache
.auto_cache_enabled
)
407 return armv7a_cache_flush_virt(target
, virt
, size
);
410 COMMAND_HANDLER(arm7a_l1_cache_info_cmd
)
412 struct target
*target
= get_current_target(CMD_CTX
);
413 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
415 return armv7a_handle_cache_info_command(CMD_CTX
,
416 &armv7a
->armv7a_mmu
.armv7a_cache
);
419 COMMAND_HANDLER(armv7a_l1_d_cache_clean_inval_all_cmd
)
421 struct target
*target
= get_current_target(CMD_CTX
);
423 armv7a_l1_d_cache_clean_inval_all(target
);
428 COMMAND_HANDLER(arm7a_l1_d_cache_inval_virt_cmd
)
430 struct target
*target
= get_current_target(CMD_CTX
);
433 if (CMD_ARGC
== 0 || CMD_ARGC
> 2)
434 return ERROR_COMMAND_SYNTAX_ERROR
;
437 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], size
);
441 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], virt
);
443 return armv7a_l1_d_cache_inval_virt(target
, virt
, size
);
446 COMMAND_HANDLER(arm7a_l1_d_cache_clean_virt_cmd
)
448 struct target
*target
= get_current_target(CMD_CTX
);
451 if (CMD_ARGC
== 0 || CMD_ARGC
> 2)
452 return ERROR_COMMAND_SYNTAX_ERROR
;
455 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], size
);
459 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], virt
);
461 return armv7a_l1_d_cache_clean_virt(target
, virt
, size
);
464 COMMAND_HANDLER(armv7a_i_cache_clean_inval_all_cmd
)
466 struct target
*target
= get_current_target(CMD_CTX
);
468 armv7a_l1_i_cache_inval_all(target
);
473 COMMAND_HANDLER(arm7a_l1_i_cache_inval_virt_cmd
)
475 struct target
*target
= get_current_target(CMD_CTX
);
478 if (CMD_ARGC
== 0 || CMD_ARGC
> 2)
479 return ERROR_COMMAND_SYNTAX_ERROR
;
482 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], size
);
486 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], virt
);
488 return armv7a_l1_i_cache_inval_virt(target
, virt
, size
);
491 COMMAND_HANDLER(arm7a_cache_disable_auto_cmd
)
493 struct target
*target
= get_current_target(CMD_CTX
);
494 struct armv7a_common
*armv7a
= target_to_armv7a(target
);
497 command_print(CMD_CTX
, "auto cache is %s",
498 armv7a
->armv7a_mmu
.armv7a_cache
.auto_cache_enabled
? "enabled" : "disabled");
505 COMMAND_PARSE_ENABLE(CMD_ARGV
[0], set
);
506 armv7a
->armv7a_mmu
.armv7a_cache
.auto_cache_enabled
= !!set
;
510 return ERROR_COMMAND_SYNTAX_ERROR
;
513 static const struct command_registration arm7a_l1_d_cache_commands
[] = {
516 .handler
= armv7a_l1_d_cache_clean_inval_all_cmd
,
518 .help
= "flush (clean and invalidate) complete l1 d-cache",
523 .handler
= arm7a_l1_d_cache_inval_virt_cmd
,
525 .help
= "invalidate l1 d-cache by virtual address offset and range size",
526 .usage
= "<virt_addr> [size]",
530 .handler
= arm7a_l1_d_cache_clean_virt_cmd
,
532 .help
= "clean l1 d-cache by virtual address address offset and range size",
533 .usage
= "<virt_addr> [size]",
535 COMMAND_REGISTRATION_DONE
538 static const struct command_registration arm7a_l1_i_cache_commands
[] = {
541 .handler
= armv7a_i_cache_clean_inval_all_cmd
,
543 .help
= "invalidate complete l1 i-cache",
548 .handler
= arm7a_l1_i_cache_inval_virt_cmd
,
550 .help
= "invalidate l1 i-cache by virtual address offset and range size",
551 .usage
= "<virt_addr> [size]",
553 COMMAND_REGISTRATION_DONE
556 const struct command_registration arm7a_l1_di_cache_group_handlers
[] = {
559 .handler
= arm7a_l1_cache_info_cmd
,
561 .help
= "print cache realted information",
567 .help
= "l1 d-cache command group",
569 .chain
= arm7a_l1_d_cache_commands
,
574 .help
= "l1 i-cache command group",
576 .chain
= arm7a_l1_i_cache_commands
,
578 COMMAND_REGISTRATION_DONE
581 const struct command_registration arm7a_cache_group_handlers
[] = {
584 .handler
= arm7a_cache_disable_auto_cmd
,
586 .help
= "disable or enable automatic cache handling.",
592 .help
= "l1 cache command group",
594 .chain
= arm7a_l1_di_cache_group_handlers
,
597 .chain
= arm7a_l2x_cache_command_handler
,
599 COMMAND_REGISTRATION_DONE
602 const struct command_registration arm7a_cache_command_handlers
[] = {
606 .help
= "cache command group",
608 .chain
= arm7a_cache_group_handlers
,
610 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)