Skip to contentSkip to conversation

ARM1136: Fix cache_flush() error and correct cpu_init_crit() comments

PATCH New George G. Davis 4 participants 10 messages May 5, 2010 – Jun 2, 2010 Arm (32-bit)

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 ARM1136: Fix cache_flush() error and correct cpu_init_crit() comments

The ARM1136 cache_flush() function uses the "mcr p15, 0, rn, c7, c7, 0" instruction which means "Invalidate Both Caches" when in fact the intent is to "Clean and Invalidate Entire Data Cache". So change the ARM1136 cache_flush() function to use the "mcr p15, 0, rn, c7, c7, 0 @ Clean & invalidate D-Cache" instruction to insure that memory is consistent with any dirty cache lines.

Also fix a couple of "flush v*" comments in ARM1136 cpu_init_crit() so that they correctly describe the actual ARM1136 CP15 C7 Cache Operations used.

---
 arch/arm/cpu/arm1136/cpu.c   |    8 ++++----
 arch/arm/cpu/arm1136/start.S |    4 ++--
 2 files changed, 6 insertions(+), 6 deletions(-)
arch/arm/cpu/arm1136/cpu.c +4 -4
index ade7f46..a00698f 100644
@@ -69,8 +69,8 @@ int cleanup_before_linux (void)
 
 static void cache_flush(void)
 {
-	unsigned long i = 0;
-
-	asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i));  /* invalidate both caches and flush btb */
-	asm ("mcr p15, 0, %0, c7, c10, 4": :"r" (i)); /* mem barrier to sync things */
+	asm (
+	"	mcr p15, 0, %0, c7, c14, 0	@ Clean & invalidate D-Cache\n"
+	"	mcr p15, 0, %0, c7, c10, 4	@ DSB\n"
+		: : "r" (0) : "memory");
 }
arch/arm/cpu/arm1136/start.S +2 -2
index 957f438..922d01c 100644
@@ -226,8 +226,8 @@ cpu_init_crit:
 	 * flush v4 I/D caches
 	 */
 	mov	r0, #0
-	mcr	p15, 0, r0, c7, c7, 0	/* flush v3/v4 cache */
-	mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */
+	mcr	p15, 0, r0, c7, c7, 0	/* Invalidate I+D+BTB caches */
+	mcr	p15, 0, r0, c8, c7, 0	/* Invalidate Unified TLB */
 
 	/*
 	 * disable MMU stuff and caches
Signature · 1 line
1.6.3.3.328.ga9ee94
#1 lore raw

PATCH 1/1 ARM1136: Fix cache_flush() error and correct cpu_init_crit() comments

Hi George,

Quoted 2 lines · George G. Davis

The ARM1136 cache_flush() function uses the "mcr p15, 0, rn, c7, c7, 0" instruction which means "Invalidate Both Caches

... Also flushes the branch target cache"

Quoted 2 lines

" when in fact the intent
is to "Clean and Invalidate Entire Data Cache".

Why don't we have to invalidate/flush the I- and BT-Cache here? I.e. why is it sufficient to clean & invalidate the D-Cache here, only, and remove the existing I- and BT-Cache invalidation/flushing?

What's about just adding an additional clean of the data cache before the 'invalidate all':

+ asm ("mcr p15, 0, %0, c7, c10, 0": :"r" (i)); /* clean entire data cache */
asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i)); /* invalidate both caches and flush btb */
asm ("mcr p15, 0, %0, c7, c10, 4": :"r" (i)); /* mem barrier to sync things */

?

Thanks for finding this and best regards

Dirk

#2 lore raw

PATCH 1/1 ARM1136: Fix cache_flush() error and correct cpu_init_crit() comments

Hello Dirk,

Quoted 8 lines · Dirk Behme

Hi George,

Quoted 3 lines · George G. Davis

The ARM1136 cache_flush() function uses the "mcr p15, 0, rn, c7, c7, 0" instruction which means "Invalidate Both Caches

Quoted 6 lines

... Also flushes the branch target cache"

Quoted 2 lines

" when in fact the intent
is to "Clean and Invalidate Entire Data Cache".

Why don't we have to invalidate/flush the I- and BT-Cache here? I.e. why is it sufficient to clean & invalidate the D-Cache here, only, and remove the existing I- and BT-Cache invalidation/flushing?

Quite frankly I thought for sure that it was handled elsewhere but now that I look I see that it's not. Meanwhile, I don't think U-Boot is typically susceptible to self-modifying-code issues anyway (?) and this isn't likely required but I suppose lack of I+BTB invalidation could be an issue in some cases, e.g. loading and running a new version of U-Boot from RAM? So better to be safe and restore the I+BTB invalidation here.

Quoted 8 lines

What's about just adding an additional clean of the data cache before the 'invalidate all':

+ asm ("mcr p15, 0, %0, c7, c10, 0": :"r" (i)); ?/* clean entire data cache */ asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i)); ?/* invalidate both caches and flush btb */ asm ("mcr p15, 0, %0, c7, c10, 4": :"r" (i)); /* mem barrier to sync things */

?

That works for me.

If there is no more feedback, I'll resubmit an updated patch.

Thansk!

--
Regards,
George

Quoted 4 lines

Thanks for finding this and best regards

Dirk

#3 lore raw

PATCH 1/1 ARM1136: Fix cache_flush() error and correct cpu_init_crit() comments

Dear "George G. Davis",

Quoted 8 lines · In message <[email protected]> you…
Quoted 2 lines

Why don't we have to invalidate/flush the I- and BT-Cache here? I.e. why

is it sufficient to clean & invalidate the D-Cache here, only, and remove the existing I- and BT-Cache invalidation/flushing?

Quite frankly I thought for sure that it was handled elsewhere but now that I look I see that it's not. Meanwhile, I don't think U-Boot is typically susceptible to self-modifying-code issues anyway (?) and

What has self-modifying-code to do with it? Proper cache handling is mandatory in manyother siutuations as well, including when you load code (Linux kernel, standalone applications) and then try to execute these, or when dealing with I/O buffers, DMA, etc.

Quoted 1 line

this isn't likely required but I suppose lack of I+BTB invalidation

I think it is mandatory.

Best regards,

Wolfgang Denk

Signature · 5 lines
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de
A direct quote from the Boss: "We passed over a lot of good people to
get the ones we hired."
#4 lore raw

PATCH 1/1 ARM1136: Fix cache_flush() error and correct cpu_init_crit() comments

Hello Wolfgang,

Quoted 14 lines · Wolfgang Denk

Dear "George G. Davis",

In message <[email protected]>

Quoted 2 lines · you
Quoted 2 lines

Why don't we have to invalidate/flush the I- and BT-Cache here? I.e.

why

Quoted 6 lines

is it sufficient to clean & invalidate the D-Cache here, only, and remove the existing I- and BT-Cache invalidation/flushing?

Quite frankly I thought for sure that it was handled elsewhere but now that I look I see that it's not. Meanwhile, I don't think U-Boot is typically susceptible to self-modifying-code issues anyway (?) and

Quoted 9 lines

What has self-modifying-code to do with it? Proper cache handling is mandatory in manyother siutuations as well, including when you load code (Linux kernel, standalone applications) and then try to execute these, or when dealing with I/O buffers, DMA, etc.

Quoted 1 line

this isn't likely required but I suppose lack of I+BTB invalidation

I think it is mandatory.

Yes, you're right. New patch on the way shortly...

--
Regards,
George

Quoted 13 lines

Best regards,

Wolfgang Denk

--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de A direct quote from the Boss: "We passed over a lot of good people to get the ones we hired."

#5 lore raw

PATCH v2 1/1 ARM1136: Fix cache_flush() error and correct cpu_init_crit() comments

In reply to George G. Davis

From: George G. Davis <[email protected]>

The ARM1136 cache_flush() function uses the "mcr p15, 0, rn, c7, c7, 0" instruction which means "Invalidate Both Caches" when in fact the intent is to clean and invalidate all caches. So add an "mcr p15, 0, %0, c7, c10, 0" instruction to "Clean Entire Data Cache" prior to the "Invalidate Both Caches" instruction to insure that memory is consistent with any dirty cache lines.

Also fix a couple of "flush v*" comments in ARM1136 cpu_init_crit() so that they correctly describe the actual ARM1136 CP15 C7 Cache Operations used.

---
 arch/arm/cpu/arm1136/cpu.c   |    1 +
 arch/arm/cpu/arm1136/start.S |    4 ++--
 2 files changed, 3 insertions(+), 2 deletions(-)
arch/arm/cpu/arm1136/cpu.c +1 -0
index ade7f46..2b91631 100644
@@ -71,6 +71,7 @@ static void cache_flush(void)
 {
 	unsigned long i = 0;
 
+	asm ("mcr p15, 0, %0, c7, c10, 0": :"r" (i)); /* clean entire data cache */
 	asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i));  /* invalidate both caches and flush btb */
 	asm ("mcr p15, 0, %0, c7, c10, 4": :"r" (i)); /* mem barrier to sync things */
 }
arch/arm/cpu/arm1136/start.S +2 -2
index 957f438..922d01c 100644
@@ -226,8 +226,8 @@ cpu_init_crit:
 	 * flush v4 I/D caches
 	 */
 	mov	r0, #0
-	mcr	p15, 0, r0, c7, c7, 0	/* flush v3/v4 cache */
-	mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */
+	mcr	p15, 0, r0, c7, c7, 0	/* Invalidate I+D+BTB caches */
+	mcr	p15, 0, r0, c8, c7, 0	/* Invalidate Unified TLB */
 
 	/*
 	 * disable MMU stuff and caches
Signature · 1 line
1.6.3.3.328.ga9ee94
#6 lore raw

PATCH v2 1/1 ARM1136: Fix cache_flush() error and correct cpu_init_crit() comments

Quoted 9 lines · gdavis at mvista.com

From: George G. Davis<[email protected]>

The ARM1136 cache_flush() function uses the "mcr p15, 0, rn, c7, c7, 0" instruction which means "Invalidate Both Caches" when in fact the intent is to clean and invalidate all caches. So add an "mcr p15, 0, %0, c7, c10, 0" instruction to "Clean Entire Data Cache" prior to the "Invalidate Both Caches" instruction to insure that memory is consistent with any dirty cache lines.

Quoted 5 lines

Also fix a couple of "flush v*" comments in ARM1136 cpu_init_crit() so that they correctly describe the actual ARM1136 CP15 C7 Cache Operations used.

Thanks

Dirk

Quoted 32 lines
---
  arch/arm/cpu/arm1136/cpu.c   |    1 +
  arch/arm/cpu/arm1136/start.S |    4 ++--
  2 files changed, 3 insertions(+), 2 deletions(-)
arch/arm/cpu/arm1136/cpu.c +1 -0
index ade7f46..2b91631 100644
@@ -71,6 +71,7 @@ static void cache_flush(void)
  {
  	unsigned long i = 0;
 
+	asm ("mcr p15, 0, %0, c7, c10, 0": :"r" (i)); /* clean entire data cache */
  	asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i));  /* invalidate both caches and flush btb */
  	asm ("mcr p15, 0, %0, c7, c10, 4": :"r" (i)); /* mem barrier to sync things */
  }
arch/arm/cpu/arm1136/start.S +2 -2
index 957f438..922d01c 100644
@@ -226,8 +226,8 @@ cpu_init_crit:
  	 * flush v4 I/D caches
  	 */
  	mov	r0, #0
-	mcr	p15, 0, r0, c7, c7, 0	/* flush v3/v4 cache */
-	mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */
+	mcr	p15, 0, r0, c7, c7, 0	/* Invalidate I+D+BTB caches */
+	mcr	p15, 0, r0, c8, c7, 0	/* Invalidate Unified TLB */
 
  	/*
  	 * disable MMU stuff and caches
#7 lore raw

PATCH v2 1/1 ARM1136: Fix cache_flush() error and correct cpu_init_crit() comments

Ping,

Quoted 10 lines · Dirk Behme
Quoted 9 lines · gdavis at mvista.com

From: George G. Davis<[email protected]>

The ARM1136 cache_flush() function uses the "mcr p15, 0, rn, c7, c7, 0" instruction which means "Invalidate Both Caches" when in fact the intent is to clean and invalidate all caches. So add an "mcr p15, 0, %0, c7, c10, 0" instruction to "Clean Entire Data Cache" prior to the "Invalidate Both Caches" instruction to insure that memory is consistent with any dirty cache lines.

Quoted 7 lines
Quoted 5 lines

Also fix a couple of "flush v*" comments in ARM1136 cpu_init_crit() so that they correctly describe the actual ARM1136 CP15 C7 Cache Operations used.

Is this OK now or does it need more work? Perhaps I should CC the u-boot/u-boot-arm.git fork maintainer?

TIA!

--
Regards,
George

Quoted 37 lines

Thanks

Dirk

Quoted 32 lines
---
 arch/arm/cpu/arm1136/cpu.c   |    1 +
 arch/arm/cpu/arm1136/start.S |    4 ++--
 2 files changed, 3 insertions(+), 2 deletions(-)
arch/arm/cpu/arm1136/cpu.c +1 -0
index ade7f46..2b91631 100644
@@ -71,6 +71,7 @@ static void cache_flush(void)
 {
 	unsigned long i = 0;
 
+	asm ("mcr p15, 0, %0, c7, c10, 0": :"r" (i)); /* clean entire data cache */
 	asm ("mcr p15, 0, %0, c7, c7, 0": :"r" (i));  /* invalidate both caches and flush btb */
 	asm ("mcr p15, 0, %0, c7, c10, 4": :"r" (i)); /* mem barrier to sync things */
 }
arch/arm/cpu/arm1136/start.S +2 -2
index 957f438..922d01c 100644
@@ -226,8 +226,8 @@ cpu_init_crit:
 	 * flush v4 I/D caches
 	 */
 	mov	r0, #0
-	mcr	p15, 0, r0, c7, c7, 0	/* flush v3/v4 cache */
-	mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */
+	mcr	p15, 0, r0, c7, c7, 0	/* Invalidate I+D+BTB caches */
+	mcr	p15, 0, r0, c8, c7, 0	/* Invalidate Unified TLB */
 
 	/*
 	 * disable MMU stuff and caches
Applied
#8 lore raw

PATCH v2 1/1 ARM1136: Fix cache_flush() error and correct cpu_init_crit() comments

In reply to gdavis at mvista.com
Quoted 9 lines · gdavis at mvista.com

From: George G. Davis <[email protected]>

The ARM1136 cache_flush() function uses the "mcr p15, 0, rn, c7, c7, 0" instruction which means "Invalidate Both Caches" when in fact the intent is to clean and invalidate all caches. So add an "mcr p15, 0, %0, c7, c10, 0" instruction to "Clean Entire Data Cache" prior to the "Invalidate Both Caches" instruction to insure that memory is consistent with any dirty cache lines.

Quoted 5 lines

Also fix a couple of "flush v*" comments in ARM1136 cpu_init_crit() so that they correctly describe the actual ARM1136 CP15 C7 Cache Operations used.

Applied to arm/master
Thanks
Tom

#9 lore raw

PATCH v2 1/1 ARM1136: Fix cache_flush() error and correct cpu_init_crit() comments

Hi Tom,

Quoted 10 lines · Tom Rix
Quoted 9 lines · gdavis at mvista.com

From: George G. Davis <[email protected]>

The ARM1136 cache_flush() function uses the "mcr p15, 0, rn, c7, c7, 0" instruction which means "Invalidate Both Caches" when in fact the intent is to clean and invalidate all caches. So add an "mcr p15, 0, %0, c7, c10, 0" instruction to "Clean Entire Data Cache" prior to the "Invalidate Both Caches" instruction to insure that memory is consistent with any dirty cache lines.

Quoted 6 lines
Quoted 5 lines

Also fix a couple of "flush v*" comments in ARM1136 cpu_init_crit() so that they correctly describe the actual ARM1136 CP15 C7 Cache Operations used.

Applied to arm/master

Er, woops, Dirk's Acked-by was not included. I reckon I should have resumitted with that included but to late now.

Thanks!

--
Regards,
George

Quoted 2 lines

Thanks
Tom