diff mbox

[U-Boot,V2,7/9] ARM: OMAP3: Introduce OMAP3 Cortex-A8 revision specific errata

Message ID 1424818672-29501-8-git-send-email-nm@ti.com
State Superseded
Delegated to: Tom Rini
Headers show

Commit Message

Nishanth Menon Feb. 24, 2015, 10:57 p.m. UTC
430973: Stale prediction on replaced inter working branch causes
	Cortex-A8 to execute in the wrong ARM/Thumb state
Impacts: Everything lower than r2p1
Work around: Set IBE to 1

454179: Stale prediction may inhibit target address misprediction on
	next predicted taken branch
Impacts: Everything lower than r2p1
Work around:  Set IBE and disable branch size mispredict to 1

621766: Under a specific set of conditions, executing a sequence of
	NEON or vfp load instructions can cause processor deadlock
Impacts: Everything lower than r2p1
Work around: Set L1NEON to 1

Since the OMAP3 generation of processors have a wide variety of CPU
revisions, it is more logical to enforce an implementation using
revision checks.

Signed-off-by: Nishanth Menon <nm@ti.com>
---
 README                                      |    3 +++
 arch/arm/cpu/armv7/omap3/board.c            |    2 +-
 arch/arm/cpu/armv7/omap3/lowlevel_init.S    |   37 +++++++++++++++++++++++++++
 arch/arm/include/asm/arch-omap3/sys_proto.h |    1 +
 4 files changed, 42 insertions(+), 1 deletion(-)

Comments

Paul Kocialkowski Feb. 25, 2015, 11:15 a.m. UTC | #1
Le mardi 24 février 2015 à 16:57 -0600, Nishanth Menon a écrit :
> 430973: Stale prediction on replaced inter working branch causes
> 	Cortex-A8 to execute in the wrong ARM/Thumb state
> Impacts: Everything lower than r2p1
> Work around: Set IBE to 1

According to the Linux kernel source, this should only affect r1p*
(hence, not r2p0):
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/mm/proc-v7.S#n321

> 454179: Stale prediction may inhibit target address misprediction on
> 	next predicted taken branch
> Impacts: Everything lower than r2p1
> Work around:  Set IBE and disable branch size mispredict to 1
> 
> 621766: Under a specific set of conditions, executing a sequence of
> 	NEON or vfp load instructions can cause processor deadlock
> Impacts: Everything lower than r2p1
> Work around: Set L1NEON to 1

Erratum 458693 also sets L1NEON bit and is said to only affect r2p0
according to the Linux kernel source:
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/mm/proc-v7.S#n321

I'm not sure this is relevant (different erratum but similar
workaround), but it seems odd to me.

> Since the OMAP3 generation of processors have a wide variety of CPU
> revisions, it is more logical to enforce an implementation using
> revision checks.

Anyways, this worked just fine on my omap3630 device (> r2p1) and didn't
trigger the errata workarounds. I reckon someone would have to test on a
device that does require those workarounds (e.g. omap35xx).

> Signed-off-by: Nishanth Menon <nm@ti.com>
> ---
>  README                                      |    3 +++
>  arch/arm/cpu/armv7/omap3/board.c            |    2 +-
>  arch/arm/cpu/armv7/omap3/lowlevel_init.S    |   37 +++++++++++++++++++++++++++
>  arch/arm/include/asm/arch-omap3/sys_proto.h |    1 +
>  4 files changed, 42 insertions(+), 1 deletion(-)
> 
> diff --git a/README b/README
> index d76cdc68d406..f309e27bbd02 100644
> --- a/README
> +++ b/README
> @@ -625,6 +625,9 @@ The following options need to be configured:
>  		with CONFIG_ARM_ARCH_CP15_ERRATA define. These need to have an
>  		SoC specific implementation of the erratum workaround to
>  		function.
> +		CONFIG_ARM_ERRATA_430973
> +		CONFIG_ARM_ERRATA_454179
> +		CONFIG_ARM_ERRATA_621766
>  		CONFIG_ARM_ERRATA_798870
>  
>  - Driver Model
> diff --git a/arch/arm/cpu/armv7/omap3/board.c b/arch/arm/cpu/armv7/omap3/board.c
> index 51abc4b09e36..7ce30949a6c6 100644
> --- a/arch/arm/cpu/armv7/omap3/board.c
> +++ b/arch/arm/cpu/armv7/omap3/board.c
> @@ -408,7 +408,7 @@ static void omap3_emu_romcode_call(u32 service_id, u32 *parameters)
>  	do_omap3_emu_romcode_call(service_id, OMAP3_PUBLIC_SRAM_SCRATCH_AREA);
>  }
>  
> -static void omap3_update_aux_cr_secure(u32 set_bits, u32 clear_bits)
> +void omap3_update_aux_cr_secure(u32 set_bits, u32 clear_bits)
>  {
>  	u32 acr;
>  
> diff --git a/arch/arm/cpu/armv7/omap3/lowlevel_init.S b/arch/arm/cpu/armv7/omap3/lowlevel_init.S
> index 84591b8b5bab..b8e6ebccd4e7 100644
> --- a/arch/arm/cpu/armv7/omap3/lowlevel_init.S
> +++ b/arch/arm/cpu/armv7/omap3/lowlevel_init.S
> @@ -48,6 +48,43 @@ ENTRY(do_omap3_emu_romcode_call)
>  	POP {r4-r12, pc}
>  ENDPROC(do_omap3_emu_romcode_call)
>  
> +#ifdef CONFIG_ARM_ARCH_CP15_ERRATA
> +	.globl  arch_cp15_errata_workaround
> +/*
> + * R0 has MIDR
> + * R1 has CPU Variant (bits 20-23)
> + * R2 has CPU Revision (bits 0-3)
> + * R3 is compbined CPU variant << 4 + CPU revision
> + */
> +ENTRY(arch_cp15_errata_workaround)
> +	push    {r4-r12, lr}		@ save registers - ROM code may pollute
> +
> +	mov r0, #0			@ Nothing to set in ACR
> +	mov r1, #0			@ Nothing to clear in ACR
> +
> +#ifdef CONFIG_ARM_ERRATA_454179
> +	cmp r3, #0x21			@ Only on < r2p1
> +	orrlt r0, r0, #(0x3 << 6)	@ Set DBSM(BIT7) and IBE(BIT6) bits
> +#endif
> +
> +#ifdef CONFIG_ARM_ERRATA_430973
> +	cmp r3, #0x21			@ Only on < r2p1
> +	orrlt r0, r0, #(0x1 << 6)	@ Set IBE bit
> +#endif
> +
> +#ifdef CONFIG_ARM_ERRATA_621766
> +	cmp r3, #0x21			@ Only on < r2p1
> +	orrlt r0, r0, #(0x1 << 5)	@ Set L1NEON bit
> +#endif
> +
> +	add r2, r1, r0
> +	teq r2, #0			@ See if nothing to set or clear
> +	bne	omap3_update_aux_cr_secure	@update as per ROM code configuration needs
> +
> +	pop     {r4-r12, pc}		@restore the registers back.
> +ENDPROC(arch_cp15_errata_workaround)
> +#endif
> +
>  #if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_NAND_BOOT)
>  /**************************************************************************
>   * cpy_clk_code: relocates clock code into SRAM where its safer to execute
> diff --git a/arch/arm/include/asm/arch-omap3/sys_proto.h b/arch/arm/include/asm/arch-omap3/sys_proto.h
> index c06605d533d3..56126fe8e863 100644
> --- a/arch/arm/include/asm/arch-omap3/sys_proto.h
> +++ b/arch/arm/include/asm/arch-omap3/sys_proto.h
> @@ -74,5 +74,6 @@ void dieid_num_r(void);
>  void get_dieid(u32 *id);
>  void do_omap3_emu_romcode_call(u32 service_id, u32 parameters);
>  void omap_smc1(u32 service, u32 val);
> +void omap3_update_aux_cr_secure(u32 set_bits, u32 clear_bits);
>  u32 warm_reset(void);
>  #endif
Nishanth Menon Feb. 25, 2015, 7:49 p.m. UTC | #2
On 02/25/2015 05:15 AM, Paul Kocialkowski wrote:
> Le mardi 24 février 2015 à 16:57 -0600, Nishanth Menon a écrit :
>> 430973: Stale prediction on replaced inter working branch causes
>> 	Cortex-A8 to execute in the wrong ARM/Thumb state
>> Impacts: Everything lower than r2p1
>> Work around: Set IBE to 1
> 
> According to the Linux kernel source, this should only affect r1p*
> (hence, not r2p0):
> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/mm/proc-v7.S#n321

I did look at the official Cortex-A8 errata doc (I think this is under
NDA at least under TI).. Doc revision 20.0

This has a "Errata Summary Table" where "X" indicates the revision
impacted. As per that, I see:
r1p1, r1p2, r1p3, r1p7 impacted. the first not impacted is r2p1.

Hence the cmp r3, #0x21	(and orrlt).

Can someone from ARM ltd comment if there could be a better
implementation? I will post a V3 based on latest documentation on my hand.

> 
>> 454179: Stale prediction may inhibit target address misprediction on
>> 	next predicted taken branch
>> Impacts: Everything lower than r2p1
>> Work around:  Set IBE and disable branch size mispredict to 1
>>
>> 621766: Under a specific set of conditions, executing a sequence of
>> 	NEON or vfp load instructions can cause processor deadlock
>> Impacts: Everything lower than r2p1
>> Work around: Set L1NEON to 1
> 
> Erratum 458693 also sets L1NEON bit and is said to only affect r2p0
> according to the Linux kernel source:
> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/mm/proc-v7.S#n321
> 
> I'm not sure this is relevant (different erratum but similar
> workaround), but it seems odd to me.
> 
>> Since the OMAP3 generation of processors have a wide variety of CPU
>> revisions, it is more logical to enforce an implementation using
>> revision checks.
> 
> Anyways, this worked just fine on my omap3630 device (> r2p1) and didn't
> trigger the errata workarounds. I reckon someone would have to test on a
> device that does require those workarounds (e.g. omap35xx).
> 
>> Signed-off-by: Nishanth Menon <nm@ti.com>
>> ---
>>  README                                      |    3 +++
>>  arch/arm/cpu/armv7/omap3/board.c            |    2 +-
>>  arch/arm/cpu/armv7/omap3/lowlevel_init.S    |   37 +++++++++++++++++++++++++++
>>  arch/arm/include/asm/arch-omap3/sys_proto.h |    1 +
>>  4 files changed, 42 insertions(+), 1 deletion(-)
>>
>> diff --git a/README b/README
>> index d76cdc68d406..f309e27bbd02 100644
>> --- a/README
>> +++ b/README
>> @@ -625,6 +625,9 @@ The following options need to be configured:
>>  		with CONFIG_ARM_ARCH_CP15_ERRATA define. These need to have an
>>  		SoC specific implementation of the erratum workaround to
>>  		function.
>> +		CONFIG_ARM_ERRATA_430973
>> +		CONFIG_ARM_ERRATA_454179
>> +		CONFIG_ARM_ERRATA_621766
>>  		CONFIG_ARM_ERRATA_798870
>>  
>>  - Driver Model
>> diff --git a/arch/arm/cpu/armv7/omap3/board.c b/arch/arm/cpu/armv7/omap3/board.c
>> index 51abc4b09e36..7ce30949a6c6 100644
>> --- a/arch/arm/cpu/armv7/omap3/board.c
>> +++ b/arch/arm/cpu/armv7/omap3/board.c
>> @@ -408,7 +408,7 @@ static void omap3_emu_romcode_call(u32 service_id, u32 *parameters)
>>  	do_omap3_emu_romcode_call(service_id, OMAP3_PUBLIC_SRAM_SCRATCH_AREA);
>>  }
>>  
>> -static void omap3_update_aux_cr_secure(u32 set_bits, u32 clear_bits)
>> +void omap3_update_aux_cr_secure(u32 set_bits, u32 clear_bits)
>>  {
>>  	u32 acr;
>>  
>> diff --git a/arch/arm/cpu/armv7/omap3/lowlevel_init.S b/arch/arm/cpu/armv7/omap3/lowlevel_init.S
>> index 84591b8b5bab..b8e6ebccd4e7 100644
>> --- a/arch/arm/cpu/armv7/omap3/lowlevel_init.S
>> +++ b/arch/arm/cpu/armv7/omap3/lowlevel_init.S
>> @@ -48,6 +48,43 @@ ENTRY(do_omap3_emu_romcode_call)
>>  	POP {r4-r12, pc}
>>  ENDPROC(do_omap3_emu_romcode_call)
>>  
>> +#ifdef CONFIG_ARM_ARCH_CP15_ERRATA
>> +	.globl  arch_cp15_errata_workaround
>> +/*
>> + * R0 has MIDR
>> + * R1 has CPU Variant (bits 20-23)
>> + * R2 has CPU Revision (bits 0-3)
>> + * R3 is compbined CPU variant << 4 + CPU revision
>> + */
>> +ENTRY(arch_cp15_errata_workaround)
>> +	push    {r4-r12, lr}		@ save registers - ROM code may pollute
>> +
>> +	mov r0, #0			@ Nothing to set in ACR
>> +	mov r1, #0			@ Nothing to clear in ACR
>> +
>> +#ifdef CONFIG_ARM_ERRATA_454179
>> +	cmp r3, #0x21			@ Only on < r2p1
>> +	orrlt r0, r0, #(0x3 << 6)	@ Set DBSM(BIT7) and IBE(BIT6) bits
>> +#endif
>> +
>> +#ifdef CONFIG_ARM_ERRATA_430973
>> +	cmp r3, #0x21			@ Only on < r2p1
>> +	orrlt r0, r0, #(0x1 << 6)	@ Set IBE bit
>> +#endif
>> +
>> +#ifdef CONFIG_ARM_ERRATA_621766
>> +	cmp r3, #0x21			@ Only on < r2p1
>> +	orrlt r0, r0, #(0x1 << 5)	@ Set L1NEON bit
>> +#endif
>> +
>> +	add r2, r1, r0
>> +	teq r2, #0			@ See if nothing to set or clear
>> +	bne	omap3_update_aux_cr_secure	@update as per ROM code configuration needs
>> +
>> +	pop     {r4-r12, pc}		@restore the registers back.
>> +ENDPROC(arch_cp15_errata_workaround)
>> +#endif
>> +
>>  #if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_NAND_BOOT)
>>  /**************************************************************************
>>   * cpy_clk_code: relocates clock code into SRAM where its safer to execute
>> diff --git a/arch/arm/include/asm/arch-omap3/sys_proto.h b/arch/arm/include/asm/arch-omap3/sys_proto.h
>> index c06605d533d3..56126fe8e863 100644
>> --- a/arch/arm/include/asm/arch-omap3/sys_proto.h
>> +++ b/arch/arm/include/asm/arch-omap3/sys_proto.h
>> @@ -74,5 +74,6 @@ void dieid_num_r(void);
>>  void get_dieid(u32 *id);
>>  void do_omap3_emu_romcode_call(u32 service_id, u32 parameters);
>>  void omap_smc1(u32 service, u32 val);
>> +void omap3_update_aux_cr_secure(u32 set_bits, u32 clear_bits);
>>  u32 warm_reset(void);
>>  #endif
>
Siarhei Siamashka March 3, 2015, 7:30 a.m. UTC | #3
On Wed, 25 Feb 2015 13:49:52 -0600
Nishanth Menon <nm@ti.com> wrote:

> On 02/25/2015 05:15 AM, Paul Kocialkowski wrote:
> > Le mardi 24 février 2015 à 16:57 -0600, Nishanth Menon a écrit :
> >> 430973: Stale prediction on replaced inter working branch causes
> >> 	Cortex-A8 to execute in the wrong ARM/Thumb state
> >> Impacts: Everything lower than r2p1
> >> Work around: Set IBE to 1
> > 
> > According to the Linux kernel source, this should only affect r1p*
> > (hence, not r2p0):
> > https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/mm/proc-v7.S#n321
> 
> I did look at the official Cortex-A8 errata doc (I think this is under
> NDA at least under TI).. Doc revision 20.0

The errata list is not that much secret. But more like all the
documents that you get from your employer are just under NDA by
default. Even though they might be also available from the other
sources.

I had the same problem. And specifically requested and obtained my
own personal copy of the Cortex-A8 errata list from ARM as a private
individual (to my gmail address, and clearly stating that I wanted it
for the purposes *not* related to my corporate job) :-)

I'm not allowed to share my copy with the other people though, so
everyone has to get it directly from ARM. I believe that that this
only requires filling in the registration form on the ARM website
and agreeing with the conditions.

There are also PDF documents from Freescale in public access, which
contain some Cortex-A8 errata information too:

    http://cache.freescale.com/files/32bit/doc/errata/IMX50CE.pdf
    http://www.freescale.com/docs/pcn_attachments/15760_IMX53CE_Rev4.pdf
diff mbox

Patch

diff --git a/README b/README
index d76cdc68d406..f309e27bbd02 100644
--- a/README
+++ b/README
@@ -625,6 +625,9 @@  The following options need to be configured:
 		with CONFIG_ARM_ARCH_CP15_ERRATA define. These need to have an
 		SoC specific implementation of the erratum workaround to
 		function.
+		CONFIG_ARM_ERRATA_430973
+		CONFIG_ARM_ERRATA_454179
+		CONFIG_ARM_ERRATA_621766
 		CONFIG_ARM_ERRATA_798870
 
 - Driver Model
diff --git a/arch/arm/cpu/armv7/omap3/board.c b/arch/arm/cpu/armv7/omap3/board.c
index 51abc4b09e36..7ce30949a6c6 100644
--- a/arch/arm/cpu/armv7/omap3/board.c
+++ b/arch/arm/cpu/armv7/omap3/board.c
@@ -408,7 +408,7 @@  static void omap3_emu_romcode_call(u32 service_id, u32 *parameters)
 	do_omap3_emu_romcode_call(service_id, OMAP3_PUBLIC_SRAM_SCRATCH_AREA);
 }
 
-static void omap3_update_aux_cr_secure(u32 set_bits, u32 clear_bits)
+void omap3_update_aux_cr_secure(u32 set_bits, u32 clear_bits)
 {
 	u32 acr;
 
diff --git a/arch/arm/cpu/armv7/omap3/lowlevel_init.S b/arch/arm/cpu/armv7/omap3/lowlevel_init.S
index 84591b8b5bab..b8e6ebccd4e7 100644
--- a/arch/arm/cpu/armv7/omap3/lowlevel_init.S
+++ b/arch/arm/cpu/armv7/omap3/lowlevel_init.S
@@ -48,6 +48,43 @@  ENTRY(do_omap3_emu_romcode_call)
 	POP {r4-r12, pc}
 ENDPROC(do_omap3_emu_romcode_call)
 
+#ifdef CONFIG_ARM_ARCH_CP15_ERRATA
+	.globl  arch_cp15_errata_workaround
+/*
+ * R0 has MIDR
+ * R1 has CPU Variant (bits 20-23)
+ * R2 has CPU Revision (bits 0-3)
+ * R3 is compbined CPU variant << 4 + CPU revision
+ */
+ENTRY(arch_cp15_errata_workaround)
+	push    {r4-r12, lr}		@ save registers - ROM code may pollute
+
+	mov r0, #0			@ Nothing to set in ACR
+	mov r1, #0			@ Nothing to clear in ACR
+
+#ifdef CONFIG_ARM_ERRATA_454179
+	cmp r3, #0x21			@ Only on < r2p1
+	orrlt r0, r0, #(0x3 << 6)	@ Set DBSM(BIT7) and IBE(BIT6) bits
+#endif
+
+#ifdef CONFIG_ARM_ERRATA_430973
+	cmp r3, #0x21			@ Only on < r2p1
+	orrlt r0, r0, #(0x1 << 6)	@ Set IBE bit
+#endif
+
+#ifdef CONFIG_ARM_ERRATA_621766
+	cmp r3, #0x21			@ Only on < r2p1
+	orrlt r0, r0, #(0x1 << 5)	@ Set L1NEON bit
+#endif
+
+	add r2, r1, r0
+	teq r2, #0			@ See if nothing to set or clear
+	bne	omap3_update_aux_cr_secure	@update as per ROM code configuration needs
+
+	pop     {r4-r12, pc}		@restore the registers back.
+ENDPROC(arch_cp15_errata_workaround)
+#endif
+
 #if !defined(CONFIG_SYS_NAND_BOOT) && !defined(CONFIG_SYS_NAND_BOOT)
 /**************************************************************************
  * cpy_clk_code: relocates clock code into SRAM where its safer to execute
diff --git a/arch/arm/include/asm/arch-omap3/sys_proto.h b/arch/arm/include/asm/arch-omap3/sys_proto.h
index c06605d533d3..56126fe8e863 100644
--- a/arch/arm/include/asm/arch-omap3/sys_proto.h
+++ b/arch/arm/include/asm/arch-omap3/sys_proto.h
@@ -74,5 +74,6 @@  void dieid_num_r(void);
 void get_dieid(u32 *id);
 void do_omap3_emu_romcode_call(u32 service_id, u32 parameters);
 void omap_smc1(u32 service, u32 val);
+void omap3_update_aux_cr_secure(u32 set_bits, u32 clear_bits);
 u32 warm_reset(void);
 #endif