summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Gjenero <boris.gjenero@gmail.com>2012-10-27 12:24:14 -0400
committerMarcin Bukat <marcin.bukat@gmail.com>2013-01-24 11:26:23 +0100
commit0fec8414a35d980665e5bc47183f9f888158e087 (patch)
tree8484dd2be3f824f924537c6896a66463103a09ac
parent1789b717bab157a03ed5fcf448df035c59729cf7 (diff)
downloadrockbox-0fec8414a35d980665e5bc47183f9f888158e087.tar.gz
rockbox-0fec8414a35d980665e5bc47183f9f888158e087.zip
Fix FS#12391 : Memory corruption on PP502x after commit_discard_idcache()
In commit_discard_idcache(), cache lines were marked as invalid. When some cache lines are marked as invalid, memory corruption can occur. This caused instability when using PP502x ATA DMA because of the many more calls to that function. Here, commit_discard_idcache() is changed to avoid the problem. Also, the cache is filled after being enabled to to ensure there are never any cache lines that aren't marked as valid. Change-Id: Ia26300acef6b0573c1f40299c496ee5cbda3dac8 Reviewed-on: http://gerrit.rockbox.org/339 Reviewed-by: Szymon Dziok <b0hoon@o2.pl> Tested-by: Szymon Dziok <b0hoon@o2.pl> Reviewed-by: Marcin Bukat <marcin.bukat@gmail.com>
-rw-r--r--firmware/target/arm/pp/system-pp502x.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/firmware/target/arm/pp/system-pp502x.c b/firmware/target/arm/pp/system-pp502x.c
index bb083a5d16..d3331bf9f4 100644
--- a/firmware/target/arm/pp/system-pp502x.c
+++ b/firmware/target/arm/pp/system-pp502x.c
@@ -219,9 +219,26 @@ void ICODE_ATTR commit_discard_idcache(void)
219{ 219{
220 if (CACHE_CTL & CACHE_CTL_ENABLE) 220 if (CACHE_CTL & CACHE_CTL_ENABLE)
221 { 221 {
222 CACHE_OPERATION |= CACHE_OP_FLUSH | CACHE_OP_INVALIDATE; 222 register int istat = disable_interrupt_save(IRQ_FIQ_STATUS);
223 while ((CACHE_CTL & CACHE_CTL_BUSY) != 0); 223
224 nop; nop; nop; nop; 224 commit_dcache();
225
226 /* Cache lines which are not marked as valid can cause memory
227 * corruption when there are many writes to and code fetches from
228 * cached memory. This workaround points all cache status words past
229 * end of RAM and marks them as valid, but not dirty. Since that area
230 * is never accessed, the cache lines don't affect anything, and
231 * they're effectively discarded. Interrupts must be disabled here
232 * because any change they make to cached memory could be discarded.
233 */
234
235 register volatile unsigned long *p;
236 for (p = &CACHE_STATUS_BASE;
237 p < (&CACHE_STATUS_BASE) + 512*16/sizeof(*p);
238 p += 16/sizeof(*p))
239 *p = ((MEMORYSIZE*0x100000) >> 11) | 0x800000;
240
241 restore_interrupt(istat);
225 } 242 }
226} 243}
227 244
@@ -253,6 +270,13 @@ static void init_cache(void)
253 /* enable cache */ 270 /* enable cache */
254 CACHE_CTL |= CACHE_CTL_INIT | CACHE_CTL_ENABLE | CACHE_CTL_RUN; 271 CACHE_CTL |= CACHE_CTL_INIT | CACHE_CTL_ENABLE | CACHE_CTL_RUN;
255 nop; nop; nop; nop; 272 nop; nop; nop; nop;
273
274 /* Ensure all cache lines are valid for the next flush. Since this
275 * can run from cached RAM, rewriting of cache status words may not
276 * be safe and the cache is filled instead by reading. */
277 register volatile char *p;
278 for (p = (volatile char *)0; p < (volatile char *)0x2000; p += 0x10)
279 (void)*p;
256} 280}
257#endif /* BOOTLOADER || HAVE_BOOTLOADER_USB_MODE */ 281#endif /* BOOTLOADER || HAVE_BOOTLOADER_USB_MODE */
258 282