[U-Boot] [PATCH] ARMv8: fix bug for flush data cache by set/way

Scott Wood scottwood at freescale.com
Tue Apr 8 00:24:21 CEST 2014


On Mon, 2014-03-31 at 09:50 +0800, Leo Yan wrote:
> When flush the d$ with set/way instruction, it need calculate the way's
> offset = log2(Associativity); but in current uboot's code, it use below
> formula to calculate the offset: log2(Associativity * 2 - 1), so finally
> it cannot flush data cache properly.

More specifically, the "Associativity" above is actually "Associativity
- 1", and clz isn't quite log2().

> Signed-off-by: Leo Yan <leoy at marvell.com>
> ---
>  arch/arm/cpu/armv8/cache.S |    4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
> 
> diff --git a/arch/arm/cpu/armv8/cache.S b/arch/arm/cpu/armv8/cache.S
> index 546a83e..256d2e2 100644
> --- a/arch/arm/cpu/armv8/cache.S
> +++ b/arch/arm/cpu/armv8/cache.S
> @@ -30,9 +30,7 @@ ENTRY(__asm_flush_dcache_level)
>  	add	x2, x2, #4		/* x2 <- log2(cache line size) */
>  	mov	x3, #0x3ff
>  	and	x3, x3, x6, lsr #3	/* x3 <- max number of #ways */
> -	add	w4, w3, w3
> -	sub	w4, w4, 1		/* round up log2(#ways + 1) */
> -	clz	w5, w4			/* bit position of #ways */
> +	clz	w5, w3			/* bit position of #ways */
>  	mov	x4, #0x7fff
>  	and	x4, x4, x6, lsr #13	/* x4 <- max number of #sets */
>  	/* x1 <- cache level << 1 */

I believe the new code will fail on a cache with associativity 1.  x3
would be 0, since it's actually associativity minus one, and thus w5
would be 32.  w5 is later interpreted as x5, so it would actually do a
32-bit shift rather than whatever behavior ARM specifies for shift
counts larger than the word size.

-Scott




More information about the U-Boot mailing list