Skip to content
Snippets Groups Projects
Commit fbb0de08 authored by Marek Vasut's avatar Marek Vasut Committed by Daniel Schwierzeck
Browse files

mips: cache: Bulletproof the code against cornercases


This patch makes sure that the flush/invalidate_dcache_range() functions
can handle corner-case calls like this -- invalidate_dcache_range(0, 0, 0);
This call is valid and is happily produced by USB EHCI code for example.
The expected behavior of the cache function(s) in this case is that they
will do no operation, since the size is zero.

The current implementation though has a problem where such invocation will
result in a hard CPU hang. This is because under such conditions, where the
start_addr = 0 and stop = 0, the addr = 0 and aend = 0xffffffe0 . The loop
will then try to iterate over the entire address space, which in itself is
wrong. But iterating over the entire address space might also hit some odd
address which will cause bus hang. The later happens on the Atheros MIPS.

Signed-off-by: default avatarMarek Vasut <marex@denx.de>
Cc: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
Cc: Hans de Goede <hdegoede@redhat.com>
parent e26e8dc8
No related branches found
No related tags found
No related merge requests found
...@@ -95,6 +95,10 @@ void flush_dcache_range(ulong start_addr, ulong stop) ...@@ -95,6 +95,10 @@ void flush_dcache_range(ulong start_addr, ulong stop)
const void *addr = (const void *)(start_addr & ~(lsize - 1)); const void *addr = (const void *)(start_addr & ~(lsize - 1));
const void *aend = (const void *)((stop - 1) & ~(lsize - 1)); const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
/* aend will be miscalculated when size is zero, so we return here */
if (start_addr == stop)
return;
while (1) { while (1) {
mips_cache(HIT_WRITEBACK_INV_D, addr); mips_cache(HIT_WRITEBACK_INV_D, addr);
if (addr == aend) if (addr == aend)
...@@ -109,6 +113,10 @@ void invalidate_dcache_range(ulong start_addr, ulong stop) ...@@ -109,6 +113,10 @@ void invalidate_dcache_range(ulong start_addr, ulong stop)
const void *addr = (const void *)(start_addr & ~(lsize - 1)); const void *addr = (const void *)(start_addr & ~(lsize - 1));
const void *aend = (const void *)((stop - 1) & ~(lsize - 1)); const void *aend = (const void *)((stop - 1) & ~(lsize - 1));
/* aend will be miscalculated when size is zero, so we return here */
if (start_addr == stop)
return;
while (1) { while (1) {
mips_cache(HIT_INVALIDATE_D, addr); mips_cache(HIT_INVALIDATE_D, addr);
if (addr == aend) if (addr == aend)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment