mirror of
https://github.com/adulau/aha.git
synced 2024-12-29 12:16:20 +00:00
[AVR32] Fix bug in invalidate_dcache_region()
If (start + size) is not cacheline aligned and (start & mask) > (end & mask), the last but one cacheline won't be invalidated as it should. Fix this by rounding `end' down to the nearest cacheline boundary if it gets adjusted due to misalignment. Also flush the write buffer unconditionally -- if the dcache wrote back a line just before we invalidated it, the dirty data may be sitting in the write buffer waiting to corrupt our buffer later. Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
This commit is contained in:
parent
75154f402e
commit
ab61f7d21a
1 changed files with 5 additions and 9 deletions
|
@ -23,7 +23,6 @@
|
||||||
void invalidate_dcache_region(void *start, size_t size)
|
void invalidate_dcache_region(void *start, size_t size)
|
||||||
{
|
{
|
||||||
unsigned long v, begin, end, linesz, mask;
|
unsigned long v, begin, end, linesz, mask;
|
||||||
int flush = 0;
|
|
||||||
|
|
||||||
linesz = boot_cpu_data.dcache.linesz;
|
linesz = boot_cpu_data.dcache.linesz;
|
||||||
mask = linesz - 1;
|
mask = linesz - 1;
|
||||||
|
@ -32,24 +31,21 @@ void invalidate_dcache_region(void *start, size_t size)
|
||||||
* instead of invalidating ... never discard valid data!
|
* instead of invalidating ... never discard valid data!
|
||||||
*/
|
*/
|
||||||
begin = (unsigned long)start;
|
begin = (unsigned long)start;
|
||||||
end = begin + size - 1;
|
end = begin + size;
|
||||||
|
|
||||||
if (begin & mask) {
|
if (begin & mask) {
|
||||||
flush_dcache_line(start);
|
flush_dcache_line(start);
|
||||||
begin += linesz;
|
begin += linesz;
|
||||||
flush = 1;
|
|
||||||
}
|
}
|
||||||
if ((end & mask) != mask) {
|
if (end & mask) {
|
||||||
flush_dcache_line((void *)end);
|
flush_dcache_line((void *)end);
|
||||||
end -= linesz;
|
end &= ~mask;
|
||||||
flush = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* remaining cachelines only need invalidation */
|
/* remaining cachelines only need invalidation */
|
||||||
for (v = begin; v <= end; v += linesz)
|
for (v = begin; v < end; v += linesz)
|
||||||
invalidate_dcache_line((void *)v);
|
invalidate_dcache_line((void *)v);
|
||||||
if (flush)
|
flush_write_buffer();
|
||||||
flush_write_buffer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void clean_dcache_region(void *start, size_t size)
|
void clean_dcache_region(void *start, size_t size)
|
||||||
|
|
Loading…
Reference in a new issue