mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-10-10 08:03:04 -04:00
rk27xx: invalidate the cache with the cache controller off
commit_discard_idcache() invalidated both cache ways while running from cached SDRAM. When the loop polling for the invalidate to finish starts on a cache line of its own, it is fetched through the ways being invalidated and the CPU takes a data abort, reported at the loop's branch. Whether it crashed thus depended on where the linker put the function. usb_storage calls it on every USB connect. On rk27generic a jpeg change that grew clip_jpeg_fd by 8 bytes moved the loop onto a new line, and the firmware crashed as the USB screen came up, with an empty backtrace. Turn the cache controller off around the invalidate, as crt0.S does at start-up. The cache is write-through, so no data is lost. Tested on a generic rk2705 with the function padded so the poll loop starts a new cache line: without this change it crashes at the first USB connect, with it the device enumerates as a mass storage device. The normally linked build works too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Change-Id: I319b811fdef30717999b60132000e70f410001fc
This commit is contained in:
parent
70c546113d
commit
0e1952a4d1
1 changed files with 10 additions and 0 deletions
|
|
@ -208,11 +208,21 @@ static void cache_invalidate_way(int way)
|
||||||
void commit_discard_idcache(void)
|
void commit_discard_idcache(void)
|
||||||
{
|
{
|
||||||
int old_irq = disable_irq_save();
|
int old_irq = disable_irq_save();
|
||||||
|
unsigned long devid = DEVID;
|
||||||
|
|
||||||
|
/* Invalidate with the cache off, as crt0 does. This code runs from
|
||||||
|
* cached SDRAM: invalidating the ways while fetching through them fails
|
||||||
|
* when the poll loop starts on a cache line of its own, depending on
|
||||||
|
* where the linker happened to put it. The cache is write-through, so
|
||||||
|
* nothing is lost by turning it off. */
|
||||||
|
DEVID = devid & ~(1UL << 31);
|
||||||
|
|
||||||
cache_invalidate_way(0);
|
cache_invalidate_way(0);
|
||||||
|
|
||||||
cache_invalidate_way(1);
|
cache_invalidate_way(1);
|
||||||
|
|
||||||
|
DEVID = devid;
|
||||||
|
|
||||||
restore_irq(old_irq);
|
restore_irq(old_irq);
|
||||||
}
|
}
|
||||||
void commit_discard_dcache (void) __attribute__((alias("commit_discard_idcache")));
|
void commit_discard_dcache (void) __attribute__((alias("commit_discard_idcache")));
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue