[U-Boot] [PATCH 3/8] armv7: integrate cache maintenance support

Albert ARIBAUD albert.aribaud at free.fr
Sat Jan 8 07:54:49 CET 2011


Hi Aneesh,

Le 22/12/2010 12:54, Aneesh V a écrit :
> - Enable I-cache on bootup
> - Enable MMU and D-cache immediately after relocation
> 	- Do necessary initialization before enabling d-cache and MMU
> - Changes to cleanup_before_linux()
> 	- Make changes according to the new framework
>
> Signed-off-by: Aneesh V<aneesh at ti.com>
> ---
>   arch/arm/cpu/armv7/cpu.c   |   47 +++++++++++++++++++------------------------
>   arch/arm/cpu/armv7/start.S |   18 +++++++++++++++-
>   arch/arm/lib/board.c       |    6 +++++
>   arch/arm/lib/cache-cp15.c  |    9 ++++++++
>   4 files changed, 53 insertions(+), 27 deletions(-)
>
> diff --git a/arch/arm/cpu/armv7/cpu.c b/arch/arm/cpu/armv7/cpu.c
> index a01e0d6..b418304 100644
> --- a/arch/arm/cpu/armv7/cpu.c
> +++ b/arch/arm/cpu/armv7/cpu.c
> @@ -38,13 +38,10 @@
>   #ifndef CONFIG_L2_OFF
>   #include<asm/arch/sys_proto.h>
>   #endif
> -
> -static void cache_flush(void);
> +#include<asm/armv7.h>
>
>   int cleanup_before_linux(void)
>   {
> -	unsigned int i;
> -
>   	/*
>   	 * this function is called just before we call linux
>   	 * it prepares the processor for linux
> @@ -53,31 +50,29 @@ int cleanup_before_linux(void)
>   	 */
>   	disable_interrupts();
>
> -	/* turn off I/D-cache */
> +	/*
> +	 * Turn off I-cache and invalidate it
> +	 */
>   	icache_disable();
> -	dcache_disable();

(1) -- see below

> +	invalidate_icache_all();
>
> -	/* invalidate I-cache */
> -	cache_flush();

(2) -- see below

> -
> -#ifndef CONFIG_L2_OFF
> -	/* turn off L2 cache */
> -	l2_cache_disable();
> -	/* invalidate L2 cache also */
> -	invalidate_dcache(get_device_type());
> -#endif
> -	i = 0;
> -	/* mem barrier to sync up things */
> -	asm("mcr p15, 0, %0, c7, c10, 4": :"r"(i));
> +	/*
> +	 * turn off D-cache
> +	 * dcache_disable() in turn flushes the d-cache and disables MMU
> +	 */
> +	dcache_disable();

(3) -- see below

> -#ifndef CONFIG_L2_OFF
> -	l2_cache_enable();
> -#endif
> +	/*
> +	 * After D-cache is flushed and before it is disabled there may
> +	 * be some new valid entries brought into the cache. We are sure
> +	 * that these lines are not dirty and will not affect our execution.
> +	 * (because unwinding the call-stack and setting a bit in CP15 SCTRL
> +	 * is all we did during this. We have not pushed anything on to the
> +	 * stack. Neither have we affected any static data)
> +	 * So just invalidate the entire d-cache again to avoid coherency
> +	 * problems for kernel
> +	 */
> +	invalidate_dcache_all();

I'm not sure about the logic here, but I am no cache guru, so don't 
hesitate to make me... flush... with shame. If dcache_disable stayed in 
(1) instead of being moved to (3), wouldn't the cache_flush in (2) 
ensure the no new valid entries would appear in the dcache?
  Put another way, I'd have naively thought the sequence would be:

- disable L2 cache
- disable L1 I and D cache
- invalidate L1 I cache and flush L1 D cache
- flush L2 D cache

>   	return 0;
>   }
> -
> -static void cache_flush(void)
> -{
> -	asm ("mcr p15, 0, %0, c7, c5, 0": :"r" (0));
> -}
> diff --git a/arch/arm/cpu/armv7/start.S b/arch/arm/cpu/armv7/start.S
> index 684f2d2..7d17f1e 100644
> --- a/arch/arm/cpu/armv7/start.S
> +++ b/arch/arm/cpu/armv7/start.S
> @@ -241,6 +241,14 @@ clbss_l:str	r2, [r0]		/* clear loop...		    */
>    * initialization, now running from RAM.
>    */
>   jump_2_ram:
> +/*
> + * If I-cache is enabled invalidate it
> + */
> +#ifndef CONFIG_SYS_NO_ICACHE
> +	mcr	p15, 0, r0, c7, c5, 0	@ invalidate icache
> +	dsb
> +	isb
> +#endif
>   	ldr	r0, _board_init_r_ofs
>   	adr	r1, _start
>   	add	lr, r0, r1
> @@ -276,6 +284,9 @@ cpu_init_crit:
>   	mov	r0, #0			@ set up for MCR
>   	mcr	p15, 0, r0, c8, c7, 0	@ invalidate TLBs
>   	mcr	p15, 0, r0, c7, c5, 0	@ invalidate icache
> +	mcr	p15, 0, r0, c7, c5, 6  /* invalidate BP array */
> +	dsb
> +	isb
>
>   	/*
>   	 * disable MMU stuff and caches
> @@ -284,7 +295,12 @@ cpu_init_crit:
>   	bic	r0, r0, #0x00002000	@ clear bits 13 (--V-)
>   	bic	r0, r0, #0x00000007	@ clear bits 2:0 (-CAM)
>   	orr	r0, r0, #0x00000002	@ set bit 1 (--A-) Align
> -	orr	r0, r0, #0x00000800	@ set bit 12 (Z---) BTB
> +	orr	r0, r0, #0x00000800	@ set bit 11 (Z---) BTB
> +#ifdef CONFIG_SYS_NO_ICACHE
> +	bic	r0, r0, #0x00001000	@ clear bit 12 (I) I-cache
> +#else
> +	orr	r0, r0, #0x00001000	@ set bit 12 (I) I-cache
> +#endif
>   	mcr	p15, 0, r0, c1, c0, 0
>
>   	/*
> diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
> index 7266381..bef32a6 100644
> --- a/arch/arm/lib/board.c
> +++ b/arch/arm/lib/board.c
> @@ -459,6 +459,12 @@ void board_init_r (gd_t *id, ulong dest_addr)
>
>   	gd->flags |= GD_FLG_RELOC;	/* tell others: relocation done */
>
> +	/*
> +	 * Enable D$:
> +	 * I$, if needed, must be already enabled in start.S
> +	 */
> +	dcache_enable();
> +
>   	monitor_flash_len = _bss_start_ofs;
>   	debug ("monitor flash len: %08lX\n", monitor_flash_len);
>   	board_init();	/* Setup chipselects */
> diff --git a/arch/arm/lib/cache-cp15.c b/arch/arm/lib/cache-cp15.c
> index d9175f0..ca526fb 100644
> --- a/arch/arm/lib/cache-cp15.c
> +++ b/arch/arm/lib/cache-cp15.c
> @@ -34,6 +34,14 @@
>
>   DECLARE_GLOBAL_DATA_PTR;
>
> +void __arm_init_before_mmu(void)
> +{
> +	puts("__arm_init_before_mmu: dummy implementation! "
> +	     "real implementation missing!!\n");
> +}

If the function is absolutely needed, please make sure booting does not 
continue. If the function is not absolutely needed, please rewrite 
message since nothing would actually be 'missing', but rather 'could be 
added'.

> +void arm_init_before_mmu(void)
> +	__attribute__((weak, alias("__arm_init_before_mmu")));
> +
>   static void cp_delay (void)
>   {
>   	volatile int i;
> @@ -65,6 +73,7 @@ static inline void mmu_setup(void)
>   	int i;
>   	u32 reg;
>
> +	arm_init_before_mmu();
>   	/* Set up an identity-mapping for all 4GB, rw for everyone */
>   	for (i = 0; i<  4096; i++)
>   		page_table[i] = i<<  20 | (3<<  10) | 0x12;

Amicalement,
-- 
Albert.


More information about the U-Boot mailing list