arch:cache_invalidate: fix unalign cacheline invalidate

Only invalidate may corrupt data in unalign start and end.
Use writeback and invalidate instead.

Signed-off-by: zhuyanlin <zhuyanlin1@xiaomi.com>
This commit is contained in:
zhuyanlin 2021-11-23 20:27:32 +08:00 committed by Xiang Xiao
parent 4db5016d83
commit 1b3005accf
4 changed files with 74 additions and 34 deletions

View File

@ -123,7 +123,16 @@ up_invalidate_icache_all:
.type up_invalidate_dcache, function
up_invalidate_dcache:
bic r0, r0, #CACHE_DLINESIZE - 1
mov r2, #CACHE_DLINESIZE - 1
tst r0, r2
bic r0, r0, r2 /* R0=aligned start address */
mcrne p15, 0, r0, c7, c14, 1 /* Clean & invalidate D entry */
tst r1, r2
bic r1, r1, r2 /* R1=aligned end address */
mcrne p15, 0, r1, c7, c14, 1 /* Clean & invalidate D entry */
1: mcr p15, 0, r0, c7, c6, 1 /* Invalidate D entry */
add r0, r0, #CACHE_DLINESIZE
cmp r0, r1

View File

@ -404,10 +404,16 @@ void up_invalidate_dcache(uintptr_t start, uintptr_t end)
* (ssize - 1) = 0x007f : Mask of the set field
*/
start &= ~(ssize - 1);
ARM_DSB();
do
if (start & (ssize - 1))
{
start &= ~(ssize - 1);
putreg32(start, NVIC_DCCIMVAC);
start += ssize;
}
while (start + ssize <= end)
{
/* The below store causes the cache to check its directory and
* determine if this address is contained in the cache. If so, it
@ -422,7 +428,11 @@ void up_invalidate_dcache(uintptr_t start, uintptr_t end)
start += ssize;
}
while (start < end);
if (start < end)
{
putreg32(start, NVIC_DCCIMVAC);
}
ARM_DSB();
ARM_ISB();

View File

@ -404,10 +404,16 @@ void up_invalidate_dcache(uintptr_t start, uintptr_t end)
* (ssize - 1) = 0x007f : Mask of the set field
*/
start &= ~(ssize - 1);
ARM_DSB();
do
if (start & (ssize - 1))
{
start &= ~(ssize - 1);
putreg32(start, NVIC_DCCIMVAC);
start += ssize;
}
while (start + ssize <= end)
{
/* The below store causes the cache to check its directory and
* determine if this address is contained in the cache. If so, it
@ -422,7 +428,11 @@ void up_invalidate_dcache(uintptr_t start, uintptr_t end)
start += ssize;
}
while (start < end);
if (start < end)
{
putreg32(start, NVIC_DCCIMVAC);
}
ARM_DSB();
ARM_ISB();

View File

@ -116,11 +116,11 @@ void up_invalidate_icache(uintptr_t start, uintptr_t end)
{
/* align to XCHAL_ICACHE_LINESIZE */
uint32_t addr = start - (start & (XCHAL_ICACHE_LINESIZE - 1));
start &= ~(XCHAL_ICACHE_LINESIZE - 1);
for (; addr < end; addr += XCHAL_ICACHE_LINESIZE)
for (; start < end; start += XCHAL_ICACHE_LINESIZE)
{
__asm__ __volatile__ ("ihi %0, 0\n" : : "r"(addr));
__asm__ __volatile__ ("ihi %0, 0\n" : : "r"(start));
}
__asm__ __volatile__ ("isync\n");
@ -175,11 +175,11 @@ void up_lock_icache(uintptr_t start, uintptr_t end)
{
/* align to XCHAL_ICACHE_LINESIZE */
uint32_t addr = start - (start & (XCHAL_ICACHE_LINESIZE - 1));
start &= ~(XCHAL_ICACHE_LINESIZE - 1);
for (; addr < end; addr += XCHAL_ICACHE_LINESIZE)
for (; start < end; start += XCHAL_ICACHE_LINESIZE)
{
__asm__ __volatile__ ("ipfl %0, 0\n": : "r"(addr));
__asm__ __volatile__ ("ipfl %0, 0\n": : "r"(start));
};
__asm__ __volatile__ ("isync\n");
@ -206,11 +206,11 @@ void up_unlock_icache(uintptr_t start, uintptr_t end)
{
/* align to XCHAL_ICACHE_LINESIZE */
uint32_t addr = start - (start & (XCHAL_ICACHE_LINESIZE - 1));
start &= ~(XCHAL_ICACHE_LINESIZE - 1);
for (; addr < end; addr += XCHAL_ICACHE_LINESIZE)
for (; start < end; start += XCHAL_ICACHE_LINESIZE)
{
__asm__ __volatile__ ("ihu %0, 0\n": : "r"(addr));
__asm__ __volatile__ ("ihu %0, 0\n": : "r"(start));
};
__asm__ __volatile__ ("isync\n");
@ -335,13 +335,24 @@ void up_disable_dcache(void)
#ifdef CONFIG_XTENSA_DCACHE
void up_invalidate_dcache(uintptr_t start, uintptr_t end)
{
/* Align to XCHAL_DCACHE_LINESIZE */
uint32_t addr = start - (start & (XCHAL_DCACHE_LINESIZE - 1));
for (; addr < end; addr += XCHAL_DCACHE_LINESIZE)
if (start & (XCHAL_DCACHE_LINESIZE - 1))
{
__asm__ __volatile__ ("dhi %0, 0\n" : : "r"(addr));
/* Align to XCHAL_DCACHE_LINESIZE */
start &= ~(XCHAL_DCACHE_LINESIZE - 1);
__asm__ __volatile__ ("dhwbi %0, 0\n" : : "r"(start));
start += XCHAL_DCACHE_LINESIZE;
}
for (; start + XCHAL_DCACHE_LINESIZE <= end;
start += XCHAL_DCACHE_LINESIZE)
{
__asm__ __volatile__ ("dhi %0, 0\n" : : "r"(start));
}
if (start != end)
{
__asm__ __volatile__ ("dhwbi %0, 0\n" : : "r"(start));
}
__asm__ __volatile__ ("dsync\n");
@ -405,11 +416,11 @@ void up_clean_dcache(uintptr_t start, uintptr_t end)
{
/* Align to XCHAL_DCACHE_SIZE */
uint32_t addr = start - (start & (XCHAL_DCACHE_LINESIZE - 1));
start &= ~(XCHAL_DCACHE_LINESIZE - 1);
for (; addr < end; addr += XCHAL_DCACHE_LINESIZE)
for (; start < end; start += XCHAL_DCACHE_LINESIZE)
{
__asm__ __volatile__ ("dhwb %0, 0\n" : : "r"(addr));
__asm__ __volatile__ ("dhwb %0, 0\n" : : "r"(start));
}
__asm__ __volatile__ ("dsync\n");
@ -482,11 +493,11 @@ void up_flush_dcache(uintptr_t start, uintptr_t end)
{
/* Align to XCHAL_DCACHE_LINESIZE */
uint32_t addr = start - (start & (XCHAL_DCACHE_LINESIZE - 1));
start &= ~(XCHAL_DCACHE_LINESIZE - 1);
for (; addr < end; addr += XCHAL_DCACHE_LINESIZE)
for (; start < end; start += XCHAL_DCACHE_LINESIZE)
{
__asm__ __volatile__ ("dhwbi %0, 0\n" : : "r"(addr));
__asm__ __volatile__ ("dhwbi %0, 0\n" : : "r"(start));
}
__asm__ __volatile__ ("dsync\n");
@ -549,11 +560,11 @@ void up_lock_dcache(uintptr_t start, uintptr_t end)
{
/* align to XCHAL_DCACHE_LINESIZE */
uint32_t addr = start - (start & (XCHAL_DCACHE_LINESIZE - 1));
start &= ~(XCHAL_DCACHE_LINESIZE - 1);
for (; addr < end; addr += XCHAL_DCACHE_LINESIZE)
for (; start < end; start += XCHAL_DCACHE_LINESIZE)
{
__asm__ __volatile__ ("dpfl %0, 0\n": : "r"(addr));
__asm__ __volatile__ ("dpfl %0, 0\n": : "r"(start));
};
__asm__ __volatile__ ("dsync\n");
@ -580,11 +591,11 @@ void up_unlock_dcache(uintptr_t start, uintptr_t end)
{
/* align to XCHAL_DCACHE_LINESIZE */
uint32_t addr = start - (start & (XCHAL_DCACHE_LINESIZE - 1));
start &= ~(XCHAL_DCACHE_LINESIZE - 1);
for (; addr < end; addr += XCHAL_DCACHE_LINESIZE)
for (; start < end; start += XCHAL_DCACHE_LINESIZE)
{
__asm__ __volatile__ ("dhu %0, 0\n": : "r"(addr));
__asm__ __volatile__ ("dhu %0, 0\n": : "r"(start));
};
__asm__ __volatile__ ("dsync\n");