[U-Boot] [RFC PATCH] arm: arm926ejs: flush cache before disable it

Albert ARIBAUD
2013-07-08T10:22:57Z

Hi Bo,

On Mon, 08 Jul 2013 07:33:18 +0800, Bo Shen <voice.shen@gmail.com>
wrote:

> Hi Albert,
>
> ? 7/6/2013 5:02 AM, Albert ARIBAUD ??:
> > Hi Bo,
> >
> > On Tue, 2 Jul 2013 12:35:54 +0000, Bo Shen <voice.shen@gmail.com>
> > wrote:
> >
> >> flush cache before disable it
> >>
> >> Signed-off-by: Bo Shen <voice.shen@gmail.com>
> >> ---
> >> arch/arm/cpu/arm926ejs/cpu.c | 5 ++---
> >> 1 file changed, 2 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/arch/arm/cpu/arm926ejs/cpu.c b/arch/arm/cpu/arm926ejs/cpu.c
> >> index 626384c..10aa165 100644
> >> --- a/arch/arm/cpu/arm926ejs/cpu.c
> >> +++ b/arch/arm/cpu/arm926ejs/cpu.c
> >> @@ -46,15 +46,14 @@ int cleanup_before_linux (void)
> >>
> >> disable_interrupts ();
> >>
> >> + /* flush I/D-cache */
> >> + cache_flush();
> >>
> >> /* turn off I/D-cache */
> >> icache_disable();
> >> dcache_disable();
> >> l2_cache_disable();
> >>
> >> - /* flush I/D-cache */
> >> - cache_flush();
> >> -
> >> return 0;
> >> }
> >
> > What is this change supposed to fix?
>
> Actually, this is not a issue fix. Maybe my understanding wrong. I think
> this is just a logic issue. If the cache is disable, then we flush it,
> will the contents in the cache corrupted?
>
> > There is no need to flush before
> > disabling, and actually, flushing before disabling runs the risk that
> > between the two, some cache lines be dirtied again so that cache and
> > memory won't be coherent any more.
>
> I am not fully understand this. In my mind, I think flush cache (writing
> the dirty data back to memory) is used to keep the coherence. If my
> understanding is not correct, please help give more explaination or some
> reference document to me for understanding.

Maybe you're thinking that "disabling" a cache means turning it off,
losing all its content? Actually, disabling does not affect the cache
lines' content or state; it only 'bypasses' the cache until enabled
again. While the cache is disabled, all dirty lines remain dirty, and
all non-empty lines remain non-empty.

That being said, yes, flushing is used to keep cache and memory
coherent, and this is precisely why the flush must happen after the
cache is disabled, not before.

It you flush first then disable, you leave a time window between the
two where a write to the cache can happen (either because your code
does one, or because the compiler optimized one in). If it happens,
then you disable a cache which is still dirty -- IOW, your flushing
has failed its mission, and your cache and memory are still not
coherent.

Now, if you disable then flush, then any write between the two will go
straight to memory without dirtying the cache, and once it is flushed,
you end up with coherent cache and memory.

Note that the same time window reason, the cache must be invalidated
before it is enabled, not after; invalidating after enabling could
cause reads to take old, stale values from the cache rather than fetch
the current, fresh ones from memory and caching them.

> Thanks.

You're welcome.

> Best Regards,
> Bo Shen

Amicalement,
--
Albert.