From efe5792ad833ff0cf0457fa3961ec76d70262300 Mon Sep 17 00:00:00 2001
From: Alexei Pososin <m09123874@bk.ru>
Date: Thu, 11 May 2017 14:49:44 +0100
Subject: [PATCH v2 2/2] Fix cache invalidate behavior.
In cases where the buffer is not aligned to line boundary at the beginning or the end, the invalidate operation would lose modifications done on the adjacent data. This applies to both L1 and L2 caches.
See #3007.
---
c/src/lib/libbsp/arm/shared/arm-l2c-310/cache_.h | 23 +++++++++++-----
c/src/lib/libbsp/arm/shared/include/arm-cache-l1.h | 31 +++++++++++++++-------
2 files changed, 38 insertions(+), 16 deletions(-)
diff --git a/c/src/lib/libbsp/arm/shared/arm-l2c-310/cache_.h b/c/src/lib/libbsp/arm/shared/arm-l2c-310/cache_.h
index 81b34a62fa..e773cb5003 100644
a
|
b
|
l2c_310_invalidate_1_line( const void *d_addr ) |
932 | 932 | static inline void |
933 | 933 | l2c_310_invalidate_range( const void* d_addr, const size_t n_bytes ) |
934 | 934 | { |
935 | | /* Back starting address up to start of a line and invalidate until ADDR_LAST */ |
936 | | uint32_t adx = (uint32_t)d_addr |
937 | | & ~L2C_310_DATA_LINE_MASK; |
938 | | const uint32_t ADDR_LAST = |
939 | | (uint32_t)( (size_t)d_addr + n_bytes - 1 ); |
| 935 | uint32_t adx = (uint32_t)d_addr; |
| 936 | uint32_t end = |
| 937 | (uint32_t)( (size_t)d_addr + n_bytes ); |
940 | 938 | volatile L2CC *l2cc = (volatile L2CC *) BSP_ARM_L2C_310_BASE; |
941 | 939 | |
942 | 940 | if ( n_bytes == 0 ) { |
943 | 941 | return; |
944 | 942 | } |
945 | 943 | |
946 | | for (; adx <= ADDR_LAST; adx += CPU_DATA_CACHE_ALIGNMENT ) { |
| 944 | if ( adx & L2C_310_DATA_LINE_MASK ) { |
| 945 | /* flush start line in case of misalignment */ |
| 946 | adx &= ~L2C_310_DATA_LINE_MASK; |
| 947 | l2c_310_flush_1_line( l2cc, adx ); |
| 948 | adx += CPU_DATA_CACHE_ALIGNMENT; |
| 949 | } |
| 950 | |
| 951 | if ( end & L2C_310_DATA_LINE_MASK ) { |
| 952 | /* flush end line in case of misalignment */ |
| 953 | end &= ~L2C_310_DATA_LINE_MASK; |
| 954 | l2c_310_flush_1_line( l2cc, end ); |
| 955 | } |
| 956 | |
| 957 | for (; adx < end; adx += CPU_DATA_CACHE_ALIGNMENT ) { |
947 | 958 | /* Invalidate L2 cache line */ |
948 | 959 | l2cc->inv_pa = adx; |
949 | 960 | } |
diff --git a/c/src/lib/libbsp/arm/shared/include/arm-cache-l1.h b/c/src/lib/libbsp/arm/shared/include/arm-cache-l1.h
index 9caa2685bc..f2927a2766 100644
a
|
b
|
static inline void arm_cache_l1_invalidate_data_range( |
268 | 268 | ) |
269 | 269 | { |
270 | 270 | if ( n_bytes != 0 ) { |
271 | | uint32_t adx = (uint32_t) d_addr |
272 | | & ~ARM_CACHE_L1_DATA_LINE_MASK; |
273 | | const uint32_t end = |
274 | | (uint32_t)( (size_t)d_addr + n_bytes -1); |
| 271 | uint32_t adx = (uint32_t) d_addr; |
| 272 | uint32_t end = |
| 273 | (uint32_t)( (size_t)d_addr + n_bytes ); |
275 | 274 | |
276 | 275 | arm_cache_l1_errata_764369_handler(); |
277 | 276 | |
278 | | /* Back starting address up to start of a line and invalidate until end */ |
279 | | for (; |
280 | | adx <= end; |
281 | | adx += ARM_CACHE_L1_CPU_DATA_ALIGNMENT ) { |
282 | | /* Invalidate the Instruction cache line */ |
283 | | arm_cp15_data_cache_invalidate_line( (void*)adx ); |
| 277 | if (adx & ARM_CACHE_L1_DATA_LINE_MASK) { |
| 278 | /* flush start line in case of misalignment */ |
| 279 | adx &= ~ARM_CACHE_L1_DATA_LINE_MASK; |
| 280 | arm_cp15_data_cache_clean_and_invalidate_line( (void*)adx ); |
| 281 | adx += ARM_CACHE_L1_CPU_DATA_ALIGNMENT; |
284 | 282 | } |
| 283 | |
| 284 | if (end & ARM_CACHE_L1_DATA_LINE_MASK) { |
| 285 | /* flush end line in case of misalignment */ |
| 286 | end &= ~ARM_CACHE_L1_DATA_LINE_MASK; |
| 287 | arm_cp15_data_cache_clean_and_invalidate_line( (void*)end ); |
| 288 | } |
| 289 | |
| 290 | while (adx < end) { |
| 291 | /* Invalidate the Data cache line */ |
| 292 | arm_cp15_data_cache_invalidate_line( (void*)adx ); |
| 293 | adx += ARM_CACHE_L1_CPU_DATA_ALIGNMENT; |
| 294 | } |
| 295 | |
285 | 296 | /* Wait for L1 invalidate to complete */ |
286 | 297 | _ARM_Data_synchronization_barrier(); |
287 | 298 | } |