diff mbox

[U-Boot,v2,11/23] sunxi: A64: do an RMR switch if started in AArch32 mode

Message ID 1480902750-839-12-git-send-email-andre.przywara@arm.com
State Superseded
Delegated to: Jagannadha Sutradharudu Teki
Headers show

Commit Message

Andre Przywara Dec. 5, 2016, 1:52 a.m. UTC
The Allwinner A64 SoC starts execution in AArch32 mode, and both
the boot ROM and Allwinner's boot0 keep running in this mode.
So U-Boot gets entered in 32-bit, although we want it to run in AArch64.

By using a "magic" instruction, which happens to be an almost-NOP in
AArch64 and a branch in AArch32, we differentiate between being
entered in 64-bit or 32-bit mode.
If in 64-bit mode, we proceed with the branch to reset, but in 32-bit
mode we trigger an RMR write to bring the core into AArch64/EL3 and
re-enter U-Boot at CONFIG_SYS_TEXT_BASE.
This allows a 64-bit U-Boot to be both entered in 32 and 64-bit mode,
so we can use the same start code for the SPL and the U-Boot proper.

We use the existing custom header (boot0.h) functionality, but restrict
the existing boot0 header reservation to the non-SPL build now. A SPL
wouldn't need such header anyway. This allows to have both options
defined and lets us use one for the SPL and the other for U-Boot proper.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
 arch/arm/include/asm/arch-sunxi/boot0.h | 27 +++++++++++++++++++++++++++
 board/sunxi/Kconfig                     |  5 +++++
 2 files changed, 32 insertions(+)

Comments

Simon Glass Dec. 5, 2016, 6:25 a.m. UTC | #1
Hi Andre,

On 4 December 2016 at 18:52, Andre Przywara <andre.przywara@arm.com> wrote:
> The Allwinner A64 SoC starts execution in AArch32 mode, and both
> the boot ROM and Allwinner's boot0 keep running in this mode.
> So U-Boot gets entered in 32-bit, although we want it to run in AArch64.
>
> By using a "magic" instruction, which happens to be an almost-NOP in
> AArch64 and a branch in AArch32, we differentiate between being
> entered in 64-bit or 32-bit mode.
> If in 64-bit mode, we proceed with the branch to reset, but in 32-bit
> mode we trigger an RMR write to bring the core into AArch64/EL3 and
> re-enter U-Boot at CONFIG_SYS_TEXT_BASE.
> This allows a 64-bit U-Boot to be both entered in 32 and 64-bit mode,
> so we can use the same start code for the SPL and the U-Boot proper.
>
> We use the existing custom header (boot0.h) functionality, but restrict
> the existing boot0 header reservation to the non-SPL build now. A SPL
> wouldn't need such header anyway. This allows to have both options
> defined and lets us use one for the SPL and the other for U-Boot proper.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
>  arch/arm/include/asm/arch-sunxi/boot0.h | 27 +++++++++++++++++++++++++++
>  board/sunxi/Kconfig                     |  5 +++++
>  2 files changed, 32 insertions(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

>
> diff --git a/arch/arm/include/asm/arch-sunxi/boot0.h b/arch/arm/include/asm/arch-sunxi/boot0.h
> index 6a13db5..7799a03 100644
> --- a/arch/arm/include/asm/arch-sunxi/boot0.h
> +++ b/arch/arm/include/asm/arch-sunxi/boot0.h
> @@ -4,6 +4,33 @@
>   * SPDX-License-Identifier:    GPL-2.0+
>   */
>
> +#if defined(CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER) && !defined(CONFIG_SPL_BUILD)
>  /* reserve space for BOOT0 header information */
>         b       reset
>         .space  1532
> +#elif defined(CONFIG_ARM_BOOT_HOOK_RMR)
> +/* switch into AArch64 if needed */
> +       tst     x0, x0                  // this is "b #0x84" in ARM
> +       b       reset
> +       .space  0x7c
> +       .word   0xe59f1024      // ldr     r1, [pc, #36] ; 0x170000a0
> +       .word   0xe59f0024      // ldr     r0, [pc, #36] ; CONFIG_*_TEXT_BASE
> +       .word   0xe5810000      // str     r0, [r1]
> +       .word   0xf57ff04f      // dsb     sy
> +       .word   0xf57ff06f      // isb     sy
> +       .word   0xee1c0f50      // mrc     15, 0, r0, cr12, cr0, {2} ; RMR
> +       .word   0xe3800003      // orr     r0, r0, #3
> +       .word   0xee0c0f50      // mcr     15, 0, r0, cr12, cr0, {2} ; RMR
> +       .word   0xf57ff06f      // isb     sy
> +       .word   0xe320f003      // wfi
> +       .word   0xeafffffd      // b       @wfi
> +       .word   0x017000a0      // writeable RVBAR mapping address

How come you cannot use the assembler here?

> +#ifdef CONFIG_SPL_BUILD
> +       .word   CONFIG_SPL_TEXT_BASE
> +#else
> +       .word   CONFIG_SYS_TEXT_BASE
> +#endif
> +#else
> +/* normal execution */
> +       b       reset
> +#endif
> diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig
> index 0cd57a2..ba72e76 100644
> --- a/board/sunxi/Kconfig
> +++ b/board/sunxi/Kconfig
> @@ -142,6 +142,11 @@ config RESERVE_ALLWINNER_BOOT0_HEADER
>         blob relies on this information to load and execute U-Boot.
>         Only needed on 64-bit Allwinner boards so far when using boot0.
>
> +config ARM_BOOT_HOOK_RMR
> +       bool
> +       default y if ARM64
> +       select ENABLE_ARM_SOC_BOOT0_HOOK

help?

> +
>  config DRAM_TYPE
>         int "sunxi dram type"
>         depends on MACH_SUN8I_A83T
> --
> 2.8.2
>

Regards,
Simon
Andre Przywara Dec. 5, 2016, 10:41 a.m. UTC | #2
Hi Simon,

thanks a lot for looking at this!

On 05/12/16 06:25, Simon Glass wrote:
> Hi Andre,
> 
> On 4 December 2016 at 18:52, Andre Przywara <andre.przywara@arm.com> wrote:
>> The Allwinner A64 SoC starts execution in AArch32 mode, and both
>> the boot ROM and Allwinner's boot0 keep running in this mode.
>> So U-Boot gets entered in 32-bit, although we want it to run in AArch64.
>>
>> By using a "magic" instruction, which happens to be an almost-NOP in
>> AArch64 and a branch in AArch32, we differentiate between being
>> entered in 64-bit or 32-bit mode.
>> If in 64-bit mode, we proceed with the branch to reset, but in 32-bit
>> mode we trigger an RMR write to bring the core into AArch64/EL3 and
>> re-enter U-Boot at CONFIG_SYS_TEXT_BASE.
>> This allows a 64-bit U-Boot to be both entered in 32 and 64-bit mode,
>> so we can use the same start code for the SPL and the U-Boot proper.
>>
>> We use the existing custom header (boot0.h) functionality, but restrict
>> the existing boot0 header reservation to the non-SPL build now. A SPL
>> wouldn't need such header anyway. This allows to have both options
>> defined and lets us use one for the SPL and the other for U-Boot proper.
>>
>> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
>> ---
>>  arch/arm/include/asm/arch-sunxi/boot0.h | 27 +++++++++++++++++++++++++++
>>  board/sunxi/Kconfig                     |  5 +++++
>>  2 files changed, 32 insertions(+)
> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> 
>>
>> diff --git a/arch/arm/include/asm/arch-sunxi/boot0.h b/arch/arm/include/asm/arch-sunxi/boot0.h
>> index 6a13db5..7799a03 100644
>> --- a/arch/arm/include/asm/arch-sunxi/boot0.h
>> +++ b/arch/arm/include/asm/arch-sunxi/boot0.h
>> @@ -4,6 +4,33 @@
>>   * SPDX-License-Identifier:    GPL-2.0+
>>   */
>>
>> +#if defined(CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER) && !defined(CONFIG_SPL_BUILD)
>>  /* reserve space for BOOT0 header information */
>>         b       reset
>>         .space  1532
>> +#elif defined(CONFIG_ARM_BOOT_HOOK_RMR)
>> +/* switch into AArch64 if needed */
>> +       tst     x0, x0                  // this is "b #0x84" in ARM
>> +       b       reset
>> +       .space  0x7c
>> +       .word   0xe59f1024      // ldr     r1, [pc, #36] ; 0x170000a0
>> +       .word   0xe59f0024      // ldr     r0, [pc, #36] ; CONFIG_*_TEXT_BASE
>> +       .word   0xe5810000      // str     r0, [r1]
>> +       .word   0xf57ff04f      // dsb     sy
>> +       .word   0xf57ff06f      // isb     sy
>> +       .word   0xee1c0f50      // mrc     15, 0, r0, cr12, cr0, {2} ; RMR
>> +       .word   0xe3800003      // orr     r0, r0, #3
>> +       .word   0xee0c0f50      // mcr     15, 0, r0, cr12, cr0, {2} ; RMR
>> +       .word   0xf57ff06f      // isb     sy
>> +       .word   0xe320f003      // wfi
>> +       .word   0xeafffffd      // b       @wfi
>> +       .word   0x017000a0      // writeable RVBAR mapping address
> 
> How come you cannot use the assembler here?

Because this is ARM code, whereas this file is included in an AArch64
build. In contrast to x86 the AArch64 toolchain does not support both
bitnesses in one build, mostly because the two architectures are really
different.

The actual reason for this exercise is that the Allwinner boot ROM
enters the payload in AArch32 mode, but we want to compile and run the
SPL in AArch64. So we need some small ARM(32) stub to enter AArch64.

Running the whole SPL in 32-bit is the other option which the later
patches enable, but I didn't want to call some 32-bit ARM
(cross-)compiler just for this handful of instructions in this case here.

>> +#ifdef CONFIG_SPL_BUILD
>> +       .word   CONFIG_SPL_TEXT_BASE
>> +#else
>> +       .word   CONFIG_SYS_TEXT_BASE
>> +#endif
>> +#else
>> +/* normal execution */
>> +       b       reset
>> +#endif
>> diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig
>> index 0cd57a2..ba72e76 100644
>> --- a/board/sunxi/Kconfig
>> +++ b/board/sunxi/Kconfig
>> @@ -142,6 +142,11 @@ config RESERVE_ALLWINNER_BOOT0_HEADER
>>         blob relies on this information to load and execute U-Boot.
>>         Only needed on 64-bit Allwinner boards so far when using boot0.
>>
>> +config ARM_BOOT_HOOK_RMR
>> +       bool
>> +       default y if ARM64
>> +       select ENABLE_ARM_SOC_BOOT0_HOOK
> 
> help?

Good point, I can copy some parts of the commit message into here.

Cheers,
Andre.

> 
>> +
>>  config DRAM_TYPE
>>         int "sunxi dram type"
>>         depends on MACH_SUN8I_A83T
>> --
>> 2.8.2
>>
> 
> Regards,
> Simon
>
Maxime Ripard Dec. 6, 2016, 10:56 a.m. UTC | #3
On Mon, Dec 05, 2016 at 10:41:27AM +0000, Andre Przywara wrote:
> Hi Simon,
> 
> thanks a lot for looking at this!
> 
> On 05/12/16 06:25, Simon Glass wrote:
> > Hi Andre,
> > 
> > On 4 December 2016 at 18:52, Andre Przywara <andre.przywara@arm.com> wrote:
> >> The Allwinner A64 SoC starts execution in AArch32 mode, and both
> >> the boot ROM and Allwinner's boot0 keep running in this mode.
> >> So U-Boot gets entered in 32-bit, although we want it to run in AArch64.
> >>
> >> By using a "magic" instruction, which happens to be an almost-NOP in
> >> AArch64 and a branch in AArch32, we differentiate between being
> >> entered in 64-bit or 32-bit mode.
> >> If in 64-bit mode, we proceed with the branch to reset, but in 32-bit
> >> mode we trigger an RMR write to bring the core into AArch64/EL3 and
> >> re-enter U-Boot at CONFIG_SYS_TEXT_BASE.
> >> This allows a 64-bit U-Boot to be both entered in 32 and 64-bit mode,
> >> so we can use the same start code for the SPL and the U-Boot proper.
> >>
> >> We use the existing custom header (boot0.h) functionality, but restrict
> >> the existing boot0 header reservation to the non-SPL build now. A SPL
> >> wouldn't need such header anyway. This allows to have both options
> >> defined and lets us use one for the SPL and the other for U-Boot proper.
> >>
> >> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> >> ---
> >>  arch/arm/include/asm/arch-sunxi/boot0.h | 27 +++++++++++++++++++++++++++
> >>  board/sunxi/Kconfig                     |  5 +++++
> >>  2 files changed, 32 insertions(+)
> > 
> > Reviewed-by: Simon Glass <sjg@chromium.org>
> > 
> >>
> >> diff --git a/arch/arm/include/asm/arch-sunxi/boot0.h b/arch/arm/include/asm/arch-sunxi/boot0.h
> >> index 6a13db5..7799a03 100644
> >> --- a/arch/arm/include/asm/arch-sunxi/boot0.h
> >> +++ b/arch/arm/include/asm/arch-sunxi/boot0.h
> >> @@ -4,6 +4,33 @@
> >>   * SPDX-License-Identifier:    GPL-2.0+
> >>   */
> >>
> >> +#if defined(CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER) && !defined(CONFIG_SPL_BUILD)
> >>  /* reserve space for BOOT0 header information */
> >>         b       reset
> >>         .space  1532
> >> +#elif defined(CONFIG_ARM_BOOT_HOOK_RMR)
> >> +/* switch into AArch64 if needed */
> >> +       tst     x0, x0                  // this is "b #0x84" in ARM
> >> +       b       reset
> >> +       .space  0x7c
> >> +       .word   0xe59f1024      // ldr     r1, [pc, #36] ; 0x170000a0
> >> +       .word   0xe59f0024      // ldr     r0, [pc, #36] ; CONFIG_*_TEXT_BASE
> >> +       .word   0xe5810000      // str     r0, [r1]
> >> +       .word   0xf57ff04f      // dsb     sy
> >> +       .word   0xf57ff06f      // isb     sy
> >> +       .word   0xee1c0f50      // mrc     15, 0, r0, cr12, cr0, {2} ; RMR
> >> +       .word   0xe3800003      // orr     r0, r0, #3
> >> +       .word   0xee0c0f50      // mcr     15, 0, r0, cr12, cr0, {2} ; RMR
> >> +       .word   0xf57ff06f      // isb     sy
> >> +       .word   0xe320f003      // wfi
> >> +       .word   0xeafffffd      // b       @wfi
> >> +       .word   0x017000a0      // writeable RVBAR mapping address
> > 
> > How come you cannot use the assembler here?
> 
> Because this is ARM code, whereas this file is included in an AArch64
> build. In contrast to x86 the AArch64 toolchain does not support both
> bitnesses in one build, mostly because the two architectures are really
> different.
> 
> The actual reason for this exercise is that the Allwinner boot ROM
> enters the payload in AArch32 mode, but we want to compile and run the
> SPL in AArch64. So we need some small ARM(32) stub to enter AArch64.
> 
> Running the whole SPL in 32-bit is the other option which the later
> patches enable, but I didn't want to call some 32-bit ARM
> (cross-)compiler just for this handful of instructions in this case here.

A comment stating that, and how to regenerate that part from a actual
assembly source would be great.

Maxime
diff mbox

Patch

diff --git a/arch/arm/include/asm/arch-sunxi/boot0.h b/arch/arm/include/asm/arch-sunxi/boot0.h
index 6a13db5..7799a03 100644
--- a/arch/arm/include/asm/arch-sunxi/boot0.h
+++ b/arch/arm/include/asm/arch-sunxi/boot0.h
@@ -4,6 +4,33 @@ 
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
+#if defined(CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER) && !defined(CONFIG_SPL_BUILD)
 /* reserve space for BOOT0 header information */
 	b	reset
 	.space	1532
+#elif defined(CONFIG_ARM_BOOT_HOOK_RMR)
+/* switch into AArch64 if needed */
+	tst     x0, x0                  // this is "b #0x84" in ARM
+	b       reset
+	.space  0x7c
+	.word	0xe59f1024	// ldr     r1, [pc, #36] ; 0x170000a0
+	.word	0xe59f0024	// ldr     r0, [pc, #36] ; CONFIG_*_TEXT_BASE
+	.word	0xe5810000	// str     r0, [r1]
+	.word	0xf57ff04f	// dsb     sy
+	.word	0xf57ff06f	// isb     sy
+	.word	0xee1c0f50	// mrc     15, 0, r0, cr12, cr0, {2} ; RMR
+	.word	0xe3800003	// orr     r0, r0, #3
+	.word	0xee0c0f50	// mcr     15, 0, r0, cr12, cr0, {2} ; RMR
+	.word	0xf57ff06f	// isb     sy
+	.word	0xe320f003	// wfi
+	.word	0xeafffffd	// b       @wfi
+	.word	0x017000a0	// writeable RVBAR mapping address
+#ifdef CONFIG_SPL_BUILD
+	.word	CONFIG_SPL_TEXT_BASE
+#else
+	.word   CONFIG_SYS_TEXT_BASE
+#endif
+#else
+/* normal execution */
+	b	reset
+#endif
diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig
index 0cd57a2..ba72e76 100644
--- a/board/sunxi/Kconfig
+++ b/board/sunxi/Kconfig
@@ -142,6 +142,11 @@  config RESERVE_ALLWINNER_BOOT0_HEADER
 	blob relies on this information to load and execute U-Boot.
 	Only needed on 64-bit Allwinner boards so far when using boot0.
 
+config ARM_BOOT_HOOK_RMR
+	bool
+	default y if ARM64
+	select ENABLE_ARM_SOC_BOOT0_HOOK
+
 config DRAM_TYPE
 	int "sunxi dram type"
 	depends on MACH_SUN8I_A83T