diff options
author | Aidan MacDonald <amachronic@protonmail.com> | 2021-03-03 17:54:38 +0000 |
---|---|---|
committer | Solomon Peachy <pizza@shaftnet.org> | 2021-03-03 20:50:28 +0000 |
commit | 74a3d1f5be2d364a33f37e0ad621538df1bfba4b (patch) | |
tree | 8989db6f499d53384645a7a6c6ee84933764f7fd /firmware | |
parent | f906df017dd7e82f8452cc479373a1b341a02bd9 (diff) | |
download | rockbox-74a3d1f5be2d364a33f37e0ad621538df1bfba4b.tar.gz rockbox-74a3d1f5be2d364a33f37e0ad621538df1bfba4b.zip |
Fix MIPS cache operations and enable HAVE_CPU_CACHE_ALIGN on MIPS
- The range-based cache operations on MIPS were broken and only worked
properly when BOTH the address and size were multiples of the cache
line size. If this was not the case, the last cache line of the range
would not be touched!
Fix is to align start/end pointers to cache lines before iterating.
- To my knowledge all MIPS processors have a cache, so I enabled
HAVE_CPU_CACHE_ALIGN by default. This also allows mmu-mips.c to use
the CACHEALIGN_UP/DOWN macros.
- Make jz4760/system-target.h define its cache line size properly.
Change-Id: I1fcd04a59791daa233b9699f04d5ac1cc6bacee7
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/export/system.h | 4 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/system-target.h | 2 | ||||
-rw-r--r-- | firmware/target/mips/mmu-mips.c | 39 |
3 files changed, 29 insertions, 16 deletions
diff --git a/firmware/export/system.h b/firmware/export/system.h index f9a074349b..f554ac7cf1 100644 --- a/firmware/export/system.h +++ b/firmware/export/system.h | |||
@@ -253,6 +253,10 @@ static inline void cpu_boost_unlock(void) | |||
253 | #define MIN_STACK_ALIGN 8 | 253 | #define MIN_STACK_ALIGN 8 |
254 | #endif | 254 | #endif |
255 | 255 | ||
256 | #ifdef CPU_MIPS | ||
257 | #define HAVE_CPU_CACHE_ALIGN | ||
258 | #endif | ||
259 | |||
256 | /* Define this if target has support for generating backtraces */ | 260 | /* Define this if target has support for generating backtraces */ |
257 | #ifdef CPU_ARM | 261 | #ifdef CPU_ARM |
258 | #define HAVE_RB_BACKTRACE | 262 | #define HAVE_RB_BACKTRACE |
diff --git a/firmware/target/mips/ingenic_jz47xx/system-target.h b/firmware/target/mips/ingenic_jz47xx/system-target.h index 9dc1a5c8c8..862ec403d2 100644 --- a/firmware/target/mips/ingenic_jz47xx/system-target.h +++ b/firmware/target/mips/ingenic_jz47xx/system-target.h | |||
@@ -29,7 +29,7 @@ | |||
29 | #include "mipsregs.h" | 29 | #include "mipsregs.h" |
30 | 30 | ||
31 | #define CACHE_SIZE 16*1024 | 31 | #define CACHE_SIZE 16*1024 |
32 | #define CACHE_LINE_SIZE 32 | 32 | #define CACHEALIGN_BITS 5 |
33 | #include "mmu-mips.h" | 33 | #include "mmu-mips.h" |
34 | 34 | ||
35 | #define CFG_UART_BASE UART1_BASE /* Base of the UART channel */ | 35 | #define CFG_UART_BASE UART1_BASE /* Base of the UART channel */ |
diff --git a/firmware/target/mips/mmu-mips.c b/firmware/target/mips/mmu-mips.c index eb7004952e..f4ffbfa6ee 100644 --- a/firmware/target/mips/mmu-mips.c +++ b/firmware/target/mips/mmu-mips.c | |||
@@ -192,10 +192,11 @@ void commit_discard_dcache(void) | |||
192 | */ | 192 | */ |
193 | void commit_discard_dcache_range(const void *base, unsigned int size) | 193 | void commit_discard_dcache_range(const void *base, unsigned int size) |
194 | { | 194 | { |
195 | register char *s; | 195 | char *ptr = CACHEALIGN_DOWN((char*)base); |
196 | char *end = CACHEALIGN_UP((char*)base + size); | ||
196 | 197 | ||
197 | for (s=(char *)base; s<(char *)base+size; s+=CACHEALIGN_SIZE) | 198 | for(; ptr != end; ptr += CACHEALIGN_SIZE) |
198 | __CACHE_OP(DCHitWBInv, s); | 199 | __CACHE_OP(DCHitWBInv, ptr); |
199 | 200 | ||
200 | SYNC_WB(); | 201 | SYNC_WB(); |
201 | } | 202 | } |
@@ -204,10 +205,11 @@ void commit_discard_dcache_range(const void *base, unsigned int size) | |||
204 | */ | 205 | */ |
205 | void commit_dcache_range(const void *base, unsigned int size) | 206 | void commit_dcache_range(const void *base, unsigned int size) |
206 | { | 207 | { |
207 | register char *s; | 208 | char *ptr = CACHEALIGN_DOWN((char*)base); |
209 | char *end = CACHEALIGN_UP((char*)base + size); | ||
208 | 210 | ||
209 | for (s=(char *)base; s<(char *)base+size; s+=CACHEALIGN_SIZE) | 211 | for(; ptr != end; ptr += CACHEALIGN_SIZE) |
210 | __CACHE_OP(DCHitWB, s); | 212 | __CACHE_OP(DCHitWB, ptr); |
211 | 213 | ||
212 | SYNC_WB(); | 214 | SYNC_WB(); |
213 | } | 215 | } |
@@ -217,17 +219,24 @@ void commit_dcache_range(const void *base, unsigned int size) | |||
217 | */ | 219 | */ |
218 | void discard_dcache_range(const void *base, unsigned int size) | 220 | void discard_dcache_range(const void *base, unsigned int size) |
219 | { | 221 | { |
220 | register char *s; | 222 | char *ptr = CACHEALIGN_DOWN((char*)base); |
223 | char *end = CACHEALIGN_UP((char*)base + size); | ||
221 | 224 | ||
222 | if (((int)base & CACHEALIGN_SIZE - 1) || | 225 | if(ptr != base) { |
223 | (((int)base + size) & CACHEALIGN_SIZE - 1)) { | 226 | /* Start of region not cache aligned */ |
224 | /* Overlapping sections, so we need to write back instead */ | 227 | __CACHE_OP(DCHitWBInv, ptr); |
225 | commit_discard_dcache_range(base, size); | 228 | ptr += CACHEALIGN_SIZE; |
226 | return; | 229 | } |
227 | }; | 230 | |
231 | if(base+size != end) { | ||
232 | /* End of region not cache aligned */ | ||
233 | end -= CACHEALIGN_SIZE; | ||
234 | __CACHE_OP(DCHitWBInv, end); | ||
235 | } | ||
228 | 236 | ||
229 | for (s=(char *)base; s<(char *)base+size; s+=CACHEALIGN_SIZE) | 237 | /* Interior of region is safe to discard */ |
230 | __CACHE_OP(DCHitInv, s); | 238 | for(; ptr != end; ptr += CACHEALIGN_SIZE) |
239 | __CACHE_OP(DCHitInv, ptr); | ||
231 | 240 | ||
232 | SYNC_WB(); | 241 | SYNC_WB(); |
233 | } | 242 | } |