diff mbox

[U-Boot,v6,4/6] arm: spl: Allow board_init_r() to run with a larger stack

Message ID 1425394982-16196-5-git-send-email-sjg@chromium.org
State Accepted
Delegated to: Tom Rini
Headers show

Commit Message

Simon Glass March 3, 2015, 3:03 p.m. UTC
At present SPL uses a single stack, either CONFIG_SPL_STACK or
CONFIG_SYS_INIT_SP_ADDR. Since some SPL features (such as MMC and
environment) require a lot of stack, some boards set CONFIG_SPL_STACK to
point into SDRAM. They then set up SDRAM very early, before board_init_f(),
so that the larger stack can be used.

This is an abuse of lowlevel_init(). That function should only be used for
essential start-up code which cannot be delayed. An example of a valid use is
when only part of the SPL code is visible/executable, and the SoC must be set
up so that board_init_f() can be reached. It should not be used for SDRAM
init, console init, etc.

Add a CONFIG_SPL_STACK_R option, which allows the stack to be moved to a new
address before board_init_r() is called in SPL.

The expected SPL flow (for CONFIG_SPL_FRAMEWORK) is documented in the README.

Signed-off-by: Simon Glass <sjg@chromium.org>
For version 1:
Acked-by: Albert ARIBAUD <albert.u.boot@aribaud.net>
Reviewed-by: Stefan Roese <sr@denx.de>
Tested-by: Bo Shen <voice.shen@atmel.com>
Acked-by: Bo Shen <voice.shen@atmel.com>
Acked-by: Heiko Schocher <hs@denx.de>
Tested-by: Heiko Schocher <hs@denx.de>
---

Changes in v6: None
Changes in v5:
- Rebase to master

Changes in v4:
- Adjust README to mention that lowlevel_init() should have no stack

Changes in v3: None
Changes in v2:
- Move docs to top-level README file and expand them to cover U-Boot proper
- Add Kconfig settings

 Kconfig             | 18 ++++++++++++++
 README              | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 arch/arm/lib/crt0.S | 13 +++++++---
 common/spl/spl.c    | 35 +++++++++++++++++++++++++++
 4 files changed, 132 insertions(+), 3 deletions(-)

Comments

Tom Rini March 3, 2015, 5:49 p.m. UTC | #1
On Tue, Mar 03, 2015 at 08:03:00AM -0700, Simon Glass wrote:

> At present SPL uses a single stack, either CONFIG_SPL_STACK or
> CONFIG_SYS_INIT_SP_ADDR. Since some SPL features (such as MMC and
> environment) require a lot of stack, some boards set CONFIG_SPL_STACK to
> point into SDRAM. They then set up SDRAM very early, before board_init_f(),
> so that the larger stack can be used.
> 
> This is an abuse of lowlevel_init(). That function should only be used for
> essential start-up code which cannot be delayed. An example of a valid use is
> when only part of the SPL code is visible/executable, and the SoC must be set
> up so that board_init_f() can be reached. It should not be used for SDRAM
> init, console init, etc.
> 
> Add a CONFIG_SPL_STACK_R option, which allows the stack to be moved to a new
> address before board_init_r() is called in SPL.
> 
> The expected SPL flow (for CONFIG_SPL_FRAMEWORK) is documented in the README.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> For version 1:
> Acked-by: Albert ARIBAUD <albert.u.boot@aribaud.net>
> Reviewed-by: Stefan Roese <sr@denx.de>
> Tested-by: Bo Shen <voice.shen@atmel.com>
> Acked-by: Bo Shen <voice.shen@atmel.com>
> Acked-by: Heiko Schocher <hs@denx.de>
> Tested-by: Heiko Schocher <hs@denx.de>
> ---
> 
> Changes in v6: None
> Changes in v5:
> - Rebase to master
> 
> Changes in v4:
> - Adjust README to mention that lowlevel_init() should have no stack
> 
> Changes in v3: None
> Changes in v2:
> - Move docs to top-level README file and expand them to cover U-Boot proper
> - Add Kconfig settings
> 
>  Kconfig             | 18 ++++++++++++++
>  README              | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  arch/arm/lib/crt0.S | 13 +++++++---
>  common/spl/spl.c    | 35 +++++++++++++++++++++++++++
>  4 files changed, 132 insertions(+), 3 deletions(-)
[snip]
> diff --git a/arch/arm/lib/crt0.S b/arch/arm/lib/crt0.S
> index 22df3e5..7939ced 100644
> --- a/arch/arm/lib/crt0.S
> +++ b/arch/arm/lib/crt0.S
> @@ -113,7 +113,14 @@ here:
>  /* Set up final (full) environment */
>  
>  	bl	c_runtime_cpu_setup	/* we still call old routine here */
> -
> +#endif
> +#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK)
> +# ifdef CONFIG_SPL_BUILD
> +	/* Use a DRAM stack for the rest of SPL, if requested */
> +	bl	spl_relocate_stack_gd
> +	cmp	r0, #0
> +	movne	sp, r0
> +# endif
>  	ldr	r0, =__bss_start	/* this is auto-relocated! */
>  	ldr	r1, =__bss_end		/* this is auto-relocated! */
>  
> @@ -124,9 +131,10 @@ clbss_l:cmp	r0, r1			/* while not at end of BSS */
>  	addlo	r0, r0, #4		/* move to next */
>  	blo	clbss_l
>  
> +#if ! defined(CONFIG_SPL_BUILD)
>  	bl coloured_LED_init
>  	bl red_led_on
> -
> +#endif
>  	/* call board_init_r(gd_t *id, ulong dest_addr) */
>  	mov     r0, r9                  /* gd_t */
>  	ldr	r1, [r9, #GD_RELOCADDR]	/* dest_addr */
> @@ -134,7 +142,6 @@ clbss_l:cmp	r0, r1			/* while not at end of BSS */
>  	ldr	pc, =board_init_r	/* this is auto-relocated! */
>  
>  	/* we should not return here. */
> -
>  #endif
>  
>  ENDPROC(_main)
> diff --git a/common/spl/spl.c b/common/spl/spl.c
> index ded0f30..cd75bbc 100644
> --- a/common/spl/spl.c
> +++ b/common/spl/spl.c
> @@ -281,3 +281,38 @@ void preloader_console_init(void)
>  	spl_display_print();
>  #endif
>  }
> +
> +/**
> + * spl_relocate_stack_gd() - Relocate stack ready for board_init_r() execution
> + *
> + * Sometimes board_init_f() runs with a stack in SRAM but we want to use SDRAM
> + * for the main board_init_r() execution. This is typically because we need
> + * more stack space for things like the MMC sub-system.
> + *
> + * This function calculates the stack position, copies the global_data into
> + * place and returns the new stack position. The caller is responsible for
> + * setting up the sp register.
> + *
> + * @return new stack location, or 0 to use the same stack
> + */
> +ulong spl_relocate_stack_gd(void)
> +{
> +#ifdef CONFIG_SPL_STACK_R
> +	gd_t *new_gd;
> +	ulong ptr;
> +
> +	/* Get stack position: use 8-byte alignment for ABI compliance */
> +	ptr = CONFIG_SPL_STACK_R - sizeof(gd_t);
> +	ptr &= ~7;
> +	new_gd = (gd_t *)ptr;
> +	memcpy(new_gd, (void *)gd, sizeof(gd_t));
> +	gd = new_gd;
> +
> +	/* Clear the BSS. */
> +	memset(__bss_start, 0, __bss_end - __bss_start);
> +
> +	return ptr;
> +#else
> +	return 0;
> +#endif
> +}

All of this _does_ move gd into where CONFIG_SPL_STACK_R points.  It
does _not_ move the stack itself into where CONFIG_SPL_STACK_R points so
the big use case (am335x_boneblack for example where
CONFIG_SPL_ENV_SUPPORT is set) doesn't work and blows up as we overflow
the area for stack.
Simon Glass March 3, 2015, 7:04 p.m. UTC | #2
Hi Tom,

On 3 March 2015 at 10:49, Tom Rini <trini@konsulko.com> wrote:
> On Tue, Mar 03, 2015 at 08:03:00AM -0700, Simon Glass wrote:
>
>> At present SPL uses a single stack, either CONFIG_SPL_STACK or
>> CONFIG_SYS_INIT_SP_ADDR. Since some SPL features (such as MMC and
>> environment) require a lot of stack, some boards set CONFIG_SPL_STACK to
>> point into SDRAM. They then set up SDRAM very early, before board_init_f(),
>> so that the larger stack can be used.
>>
>> This is an abuse of lowlevel_init(). That function should only be used for
>> essential start-up code which cannot be delayed. An example of a valid use is
>> when only part of the SPL code is visible/executable, and the SoC must be set
>> up so that board_init_f() can be reached. It should not be used for SDRAM
>> init, console init, etc.
>>
>> Add a CONFIG_SPL_STACK_R option, which allows the stack to be moved to a new
>> address before board_init_r() is called in SPL.
>>
>> The expected SPL flow (for CONFIG_SPL_FRAMEWORK) is documented in the README.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>> For version 1:
>> Acked-by: Albert ARIBAUD <albert.u.boot@aribaud.net>
>> Reviewed-by: Stefan Roese <sr@denx.de>
>> Tested-by: Bo Shen <voice.shen@atmel.com>
>> Acked-by: Bo Shen <voice.shen@atmel.com>
>> Acked-by: Heiko Schocher <hs@denx.de>
>> Tested-by: Heiko Schocher <hs@denx.de>
>> ---
>>
>> Changes in v6: None
>> Changes in v5:
>> - Rebase to master
>>
>> Changes in v4:
>> - Adjust README to mention that lowlevel_init() should have no stack
>>
>> Changes in v3: None
>> Changes in v2:
>> - Move docs to top-level README file and expand them to cover U-Boot proper
>> - Add Kconfig settings
>>
>>  Kconfig             | 18 ++++++++++++++
>>  README              | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  arch/arm/lib/crt0.S | 13 +++++++---
>>  common/spl/spl.c    | 35 +++++++++++++++++++++++++++
>>  4 files changed, 132 insertions(+), 3 deletions(-)
> [snip]
>> diff --git a/arch/arm/lib/crt0.S b/arch/arm/lib/crt0.S
>> index 22df3e5..7939ced 100644
>> --- a/arch/arm/lib/crt0.S
>> +++ b/arch/arm/lib/crt0.S
>> @@ -113,7 +113,14 @@ here:
>>  /* Set up final (full) environment */
>>
>>       bl      c_runtime_cpu_setup     /* we still call old routine here */
>> -
>> +#endif
>> +#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK)
>> +# ifdef CONFIG_SPL_BUILD
>> +     /* Use a DRAM stack for the rest of SPL, if requested */
>> +     bl      spl_relocate_stack_gd
>> +     cmp     r0, #0
>> +     movne   sp, r0
>> +# endif
>>       ldr     r0, =__bss_start        /* this is auto-relocated! */
>>       ldr     r1, =__bss_end          /* this is auto-relocated! */
>>
>> @@ -124,9 +131,10 @@ clbss_l:cmp      r0, r1                  /* while not at end of BSS */
>>       addlo   r0, r0, #4              /* move to next */
>>       blo     clbss_l
>>
>> +#if ! defined(CONFIG_SPL_BUILD)
>>       bl coloured_LED_init
>>       bl red_led_on
>> -
>> +#endif
>>       /* call board_init_r(gd_t *id, ulong dest_addr) */
>>       mov     r0, r9                  /* gd_t */
>>       ldr     r1, [r9, #GD_RELOCADDR] /* dest_addr */
>> @@ -134,7 +142,6 @@ clbss_l:cmp       r0, r1                  /* while not at end of BSS */
>>       ldr     pc, =board_init_r       /* this is auto-relocated! */
>>
>>       /* we should not return here. */
>> -
>>  #endif
>>
>>  ENDPROC(_main)
>> diff --git a/common/spl/spl.c b/common/spl/spl.c
>> index ded0f30..cd75bbc 100644
>> --- a/common/spl/spl.c
>> +++ b/common/spl/spl.c
>> @@ -281,3 +281,38 @@ void preloader_console_init(void)
>>       spl_display_print();
>>  #endif
>>  }
>> +
>> +/**
>> + * spl_relocate_stack_gd() - Relocate stack ready for board_init_r() execution
>> + *
>> + * Sometimes board_init_f() runs with a stack in SRAM but we want to use SDRAM
>> + * for the main board_init_r() execution. This is typically because we need
>> + * more stack space for things like the MMC sub-system.
>> + *
>> + * This function calculates the stack position, copies the global_data into
>> + * place and returns the new stack position. The caller is responsible for
>> + * setting up the sp register.
>> + *
>> + * @return new stack location, or 0 to use the same stack
>> + */
>> +ulong spl_relocate_stack_gd(void)
>> +{
>> +#ifdef CONFIG_SPL_STACK_R
>> +     gd_t *new_gd;
>> +     ulong ptr;
>> +
>> +     /* Get stack position: use 8-byte alignment for ABI compliance */
>> +     ptr = CONFIG_SPL_STACK_R - sizeof(gd_t);
>> +     ptr &= ~7;
>> +     new_gd = (gd_t *)ptr;
>> +     memcpy(new_gd, (void *)gd, sizeof(gd_t));
>> +     gd = new_gd;
>> +
>> +     /* Clear the BSS. */
>> +     memset(__bss_start, 0, __bss_end - __bss_start);
>> +
>> +     return ptr;
>> +#else
>> +     return 0;
>> +#endif
>> +}
>
> All of this _does_ move gd into where CONFIG_SPL_STACK_R points.  It
> does _not_ move the stack itself into where CONFIG_SPL_STACK_R points so
> the big use case (am335x_boneblack for example where
> CONFIG_SPL_ENV_SUPPORT is set) doesn't work and blows up as we overflow
> the area for stack.

OK I'll have to test more. What sort of problem should i see?

The return value from spl_relocate_stack_gd() should be shoved into
sp. Does that not happen?

Regards,
Simon
Tom Rini March 3, 2015, 8:14 p.m. UTC | #3
On Tue, Mar 03, 2015 at 12:04:16PM -0700, Simon Glass wrote:
> Hi Tom,
> 
> On 3 March 2015 at 10:49, Tom Rini <trini@konsulko.com> wrote:
> > On Tue, Mar 03, 2015 at 08:03:00AM -0700, Simon Glass wrote:
> >
> >> At present SPL uses a single stack, either CONFIG_SPL_STACK or
> >> CONFIG_SYS_INIT_SP_ADDR. Since some SPL features (such as MMC and
> >> environment) require a lot of stack, some boards set CONFIG_SPL_STACK to
> >> point into SDRAM. They then set up SDRAM very early, before board_init_f(),
> >> so that the larger stack can be used.
> >>
> >> This is an abuse of lowlevel_init(). That function should only be used for
> >> essential start-up code which cannot be delayed. An example of a valid use is
> >> when only part of the SPL code is visible/executable, and the SoC must be set
> >> up so that board_init_f() can be reached. It should not be used for SDRAM
> >> init, console init, etc.
> >>
> >> Add a CONFIG_SPL_STACK_R option, which allows the stack to be moved to a new
> >> address before board_init_r() is called in SPL.
> >>
> >> The expected SPL flow (for CONFIG_SPL_FRAMEWORK) is documented in the README.
> >>
> >> Signed-off-by: Simon Glass <sjg@chromium.org>
> >> For version 1:
> >> Acked-by: Albert ARIBAUD <albert.u.boot@aribaud.net>
> >> Reviewed-by: Stefan Roese <sr@denx.de>
> >> Tested-by: Bo Shen <voice.shen@atmel.com>
> >> Acked-by: Bo Shen <voice.shen@atmel.com>
> >> Acked-by: Heiko Schocher <hs@denx.de>
> >> Tested-by: Heiko Schocher <hs@denx.de>
> >> ---
> >>
> >> Changes in v6: None
> >> Changes in v5:
> >> - Rebase to master
> >>
> >> Changes in v4:
> >> - Adjust README to mention that lowlevel_init() should have no stack
> >>
> >> Changes in v3: None
> >> Changes in v2:
> >> - Move docs to top-level README file and expand them to cover U-Boot proper
> >> - Add Kconfig settings
> >>
> >>  Kconfig             | 18 ++++++++++++++
> >>  README              | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> >>  arch/arm/lib/crt0.S | 13 +++++++---
> >>  common/spl/spl.c    | 35 +++++++++++++++++++++++++++
> >>  4 files changed, 132 insertions(+), 3 deletions(-)
> > [snip]
> >> diff --git a/arch/arm/lib/crt0.S b/arch/arm/lib/crt0.S
> >> index 22df3e5..7939ced 100644
> >> --- a/arch/arm/lib/crt0.S
> >> +++ b/arch/arm/lib/crt0.S
> >> @@ -113,7 +113,14 @@ here:
> >>  /* Set up final (full) environment */
> >>
> >>       bl      c_runtime_cpu_setup     /* we still call old routine here */
> >> -
> >> +#endif
> >> +#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK)
> >> +# ifdef CONFIG_SPL_BUILD
> >> +     /* Use a DRAM stack for the rest of SPL, if requested */
> >> +     bl      spl_relocate_stack_gd
> >> +     cmp     r0, #0
> >> +     movne   sp, r0
> >> +# endif
> >>       ldr     r0, =__bss_start        /* this is auto-relocated! */
> >>       ldr     r1, =__bss_end          /* this is auto-relocated! */
> >>
> >> @@ -124,9 +131,10 @@ clbss_l:cmp      r0, r1                  /* while not at end of BSS */
> >>       addlo   r0, r0, #4              /* move to next */
> >>       blo     clbss_l
> >>
> >> +#if ! defined(CONFIG_SPL_BUILD)
> >>       bl coloured_LED_init
> >>       bl red_led_on
> >> -
> >> +#endif
> >>       /* call board_init_r(gd_t *id, ulong dest_addr) */
> >>       mov     r0, r9                  /* gd_t */
> >>       ldr     r1, [r9, #GD_RELOCADDR] /* dest_addr */
> >> @@ -134,7 +142,6 @@ clbss_l:cmp       r0, r1                  /* while not at end of BSS */
> >>       ldr     pc, =board_init_r       /* this is auto-relocated! */
> >>
> >>       /* we should not return here. */
> >> -
> >>  #endif
> >>
> >>  ENDPROC(_main)
> >> diff --git a/common/spl/spl.c b/common/spl/spl.c
> >> index ded0f30..cd75bbc 100644
> >> --- a/common/spl/spl.c
> >> +++ b/common/spl/spl.c
> >> @@ -281,3 +281,38 @@ void preloader_console_init(void)
> >>       spl_display_print();
> >>  #endif
> >>  }
> >> +
> >> +/**
> >> + * spl_relocate_stack_gd() - Relocate stack ready for board_init_r() execution
> >> + *
> >> + * Sometimes board_init_f() runs with a stack in SRAM but we want to use SDRAM
> >> + * for the main board_init_r() execution. This is typically because we need
> >> + * more stack space for things like the MMC sub-system.
> >> + *
> >> + * This function calculates the stack position, copies the global_data into
> >> + * place and returns the new stack position. The caller is responsible for
> >> + * setting up the sp register.
> >> + *
> >> + * @return new stack location, or 0 to use the same stack
> >> + */
> >> +ulong spl_relocate_stack_gd(void)
> >> +{
> >> +#ifdef CONFIG_SPL_STACK_R
> >> +     gd_t *new_gd;
> >> +     ulong ptr;
> >> +
> >> +     /* Get stack position: use 8-byte alignment for ABI compliance */
> >> +     ptr = CONFIG_SPL_STACK_R - sizeof(gd_t);
> >> +     ptr &= ~7;
> >> +     new_gd = (gd_t *)ptr;
> >> +     memcpy(new_gd, (void *)gd, sizeof(gd_t));
> >> +     gd = new_gd;
> >> +
> >> +     /* Clear the BSS. */
> >> +     memset(__bss_start, 0, __bss_end - __bss_start);
> >> +
> >> +     return ptr;
> >> +#else
> >> +     return 0;
> >> +#endif
> >> +}
> >
> > All of this _does_ move gd into where CONFIG_SPL_STACK_R points.  It
> > does _not_ move the stack itself into where CONFIG_SPL_STACK_R points so
> > the big use case (am335x_boneblack for example where
> > CONFIG_SPL_ENV_SUPPORT is set) doesn't work and blows up as we overflow
> > the area for stack.
> 
> OK I'll have to test more. What sort of problem should i see?

We hang on entering env_reloc_spec() which is what puts some big sized
variables on the stack.

> The return value from spl_relocate_stack_gd() should be shoved into
> sp. Does that not happen?

It doesn't appear to be.  I hadn't broken out the BBB with JTAG tho.
Simon Glass March 4, 2015, 3:23 a.m. UTC | #4
Hi Tom,

On 3 March 2015 at 13:14, Tom Rini <trini@konsulko.com> wrote:
> On Tue, Mar 03, 2015 at 12:04:16PM -0700, Simon Glass wrote:
>> Hi Tom,
>>
>> On 3 March 2015 at 10:49, Tom Rini <trini@konsulko.com> wrote:
>> > On Tue, Mar 03, 2015 at 08:03:00AM -0700, Simon Glass wrote:
>> >
>> >> At present SPL uses a single stack, either CONFIG_SPL_STACK or
>> >> CONFIG_SYS_INIT_SP_ADDR. Since some SPL features (such as MMC and
>> >> environment) require a lot of stack, some boards set CONFIG_SPL_STACK to
>> >> point into SDRAM. They then set up SDRAM very early, before board_init_f(),
>> >> so that the larger stack can be used.
>> >>
>> >> This is an abuse of lowlevel_init(). That function should only be used for
>> >> essential start-up code which cannot be delayed. An example of a valid use is
>> >> when only part of the SPL code is visible/executable, and the SoC must be set
>> >> up so that board_init_f() can be reached. It should not be used for SDRAM
>> >> init, console init, etc.
>> >>
>> >> Add a CONFIG_SPL_STACK_R option, which allows the stack to be moved to a new
>> >> address before board_init_r() is called in SPL.
>> >>
>> >> The expected SPL flow (for CONFIG_SPL_FRAMEWORK) is documented in the README.
>> >>
>> >> Signed-off-by: Simon Glass <sjg@chromium.org>
>> >> For version 1:
>> >> Acked-by: Albert ARIBAUD <albert.u.boot@aribaud.net>
>> >> Reviewed-by: Stefan Roese <sr@denx.de>
>> >> Tested-by: Bo Shen <voice.shen@atmel.com>
>> >> Acked-by: Bo Shen <voice.shen@atmel.com>
>> >> Acked-by: Heiko Schocher <hs@denx.de>
>> >> Tested-by: Heiko Schocher <hs@denx.de>
>> >> ---
>> >>
>> >> Changes in v6: None
>> >> Changes in v5:
>> >> - Rebase to master
>> >>
>> >> Changes in v4:
>> >> - Adjust README to mention that lowlevel_init() should have no stack
>> >>
>> >> Changes in v3: None
>> >> Changes in v2:
>> >> - Move docs to top-level README file and expand them to cover U-Boot proper
>> >> - Add Kconfig settings
>> >>
>> >>  Kconfig             | 18 ++++++++++++++
>> >>  README              | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>> >>  arch/arm/lib/crt0.S | 13 +++++++---
>> >>  common/spl/spl.c    | 35 +++++++++++++++++++++++++++
>> >>  4 files changed, 132 insertions(+), 3 deletions(-)
>> > [snip]
>> >> diff --git a/arch/arm/lib/crt0.S b/arch/arm/lib/crt0.S
>> >> index 22df3e5..7939ced 100644
>> >> --- a/arch/arm/lib/crt0.S
>> >> +++ b/arch/arm/lib/crt0.S
>> >> @@ -113,7 +113,14 @@ here:
>> >>  /* Set up final (full) environment */
>> >>
>> >>       bl      c_runtime_cpu_setup     /* we still call old routine here */
>> >> -
>> >> +#endif
>> >> +#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK)
>> >> +# ifdef CONFIG_SPL_BUILD
>> >> +     /* Use a DRAM stack for the rest of SPL, if requested */
>> >> +     bl      spl_relocate_stack_gd
>> >> +     cmp     r0, #0
>> >> +     movne   sp, r0
>> >> +# endif
>> >>       ldr     r0, =__bss_start        /* this is auto-relocated! */
>> >>       ldr     r1, =__bss_end          /* this is auto-relocated! */
>> >>
>> >> @@ -124,9 +131,10 @@ clbss_l:cmp      r0, r1                  /* while not at end of BSS */
>> >>       addlo   r0, r0, #4              /* move to next */
>> >>       blo     clbss_l
>> >>
>> >> +#if ! defined(CONFIG_SPL_BUILD)
>> >>       bl coloured_LED_init
>> >>       bl red_led_on
>> >> -
>> >> +#endif
>> >>       /* call board_init_r(gd_t *id, ulong dest_addr) */
>> >>       mov     r0, r9                  /* gd_t */
>> >>       ldr     r1, [r9, #GD_RELOCADDR] /* dest_addr */
>> >> @@ -134,7 +142,6 @@ clbss_l:cmp       r0, r1                  /* while not at end of BSS */
>> >>       ldr     pc, =board_init_r       /* this is auto-relocated! */
>> >>
>> >>       /* we should not return here. */
>> >> -
>> >>  #endif
>> >>
>> >>  ENDPROC(_main)
>> >> diff --git a/common/spl/spl.c b/common/spl/spl.c
>> >> index ded0f30..cd75bbc 100644
>> >> --- a/common/spl/spl.c
>> >> +++ b/common/spl/spl.c
>> >> @@ -281,3 +281,38 @@ void preloader_console_init(void)
>> >>       spl_display_print();
>> >>  #endif
>> >>  }
>> >> +
>> >> +/**
>> >> + * spl_relocate_stack_gd() - Relocate stack ready for board_init_r() execution
>> >> + *
>> >> + * Sometimes board_init_f() runs with a stack in SRAM but we want to use SDRAM
>> >> + * for the main board_init_r() execution. This is typically because we need
>> >> + * more stack space for things like the MMC sub-system.
>> >> + *
>> >> + * This function calculates the stack position, copies the global_data into
>> >> + * place and returns the new stack position. The caller is responsible for
>> >> + * setting up the sp register.
>> >> + *
>> >> + * @return new stack location, or 0 to use the same stack
>> >> + */
>> >> +ulong spl_relocate_stack_gd(void)
>> >> +{
>> >> +#ifdef CONFIG_SPL_STACK_R
>> >> +     gd_t *new_gd;
>> >> +     ulong ptr;
>> >> +
>> >> +     /* Get stack position: use 8-byte alignment for ABI compliance */
>> >> +     ptr = CONFIG_SPL_STACK_R - sizeof(gd_t);
>> >> +     ptr &= ~7;
>> >> +     new_gd = (gd_t *)ptr;
>> >> +     memcpy(new_gd, (void *)gd, sizeof(gd_t));
>> >> +     gd = new_gd;
>> >> +
>> >> +     /* Clear the BSS. */
>> >> +     memset(__bss_start, 0, __bss_end - __bss_start);
>> >> +
>> >> +     return ptr;
>> >> +#else
>> >> +     return 0;
>> >> +#endif
>> >> +}
>> >
>> > All of this _does_ move gd into where CONFIG_SPL_STACK_R points.  It
>> > does _not_ move the stack itself into where CONFIG_SPL_STACK_R points so
>> > the big use case (am335x_boneblack for example where
>> > CONFIG_SPL_ENV_SUPPORT is set) doesn't work and blows up as we overflow
>> > the area for stack.
>>
>> OK I'll have to test more. What sort of problem should i see?
>
> We hang on entering env_reloc_spec() which is what puts some big sized
> variables on the stack.
>
>> The return value from spl_relocate_stack_gd() should be shoved into
>> sp. Does that not happen?
>
> It doesn't appear to be.  I hadn't broken out the BBB with JTAG tho.

I printed out the stack in board_init_r() and it looks right: 32MB
above the base of SDRAM.

Also I don't seem to get a crash in SPL. How do I make that happen? If
I define CONFIG_SPL_USBETH_SUPPORT I get an error about the .data
section not fitin in .sram for u-boot-spl.

Regards,
Simon
Tom Rini March 4, 2015, 1:38 p.m. UTC | #5
On Tue, Mar 03, 2015 at 08:23:23PM -0700, Simon Glass wrote:
> Hi Tom,
> 
> On 3 March 2015 at 13:14, Tom Rini <trini@konsulko.com> wrote:
> > On Tue, Mar 03, 2015 at 12:04:16PM -0700, Simon Glass wrote:
> >> Hi Tom,
> >>
> >> On 3 March 2015 at 10:49, Tom Rini <trini@konsulko.com> wrote:
> >> > On Tue, Mar 03, 2015 at 08:03:00AM -0700, Simon Glass wrote:
> >> >
> >> >> At present SPL uses a single stack, either CONFIG_SPL_STACK or
> >> >> CONFIG_SYS_INIT_SP_ADDR. Since some SPL features (such as MMC and
> >> >> environment) require a lot of stack, some boards set CONFIG_SPL_STACK to
> >> >> point into SDRAM. They then set up SDRAM very early, before board_init_f(),
> >> >> so that the larger stack can be used.
> >> >>
> >> >> This is an abuse of lowlevel_init(). That function should only be used for
> >> >> essential start-up code which cannot be delayed. An example of a valid use is
> >> >> when only part of the SPL code is visible/executable, and the SoC must be set
> >> >> up so that board_init_f() can be reached. It should not be used for SDRAM
> >> >> init, console init, etc.
> >> >>
> >> >> Add a CONFIG_SPL_STACK_R option, which allows the stack to be moved to a new
> >> >> address before board_init_r() is called in SPL.
> >> >>
> >> >> The expected SPL flow (for CONFIG_SPL_FRAMEWORK) is documented in the README.
> >> >>
> >> >> Signed-off-by: Simon Glass <sjg@chromium.org>
> >> >> For version 1:
> >> >> Acked-by: Albert ARIBAUD <albert.u.boot@aribaud.net>
> >> >> Reviewed-by: Stefan Roese <sr@denx.de>
> >> >> Tested-by: Bo Shen <voice.shen@atmel.com>
> >> >> Acked-by: Bo Shen <voice.shen@atmel.com>
> >> >> Acked-by: Heiko Schocher <hs@denx.de>
> >> >> Tested-by: Heiko Schocher <hs@denx.de>
> >> >> ---
> >> >>
> >> >> Changes in v6: None
> >> >> Changes in v5:
> >> >> - Rebase to master
> >> >>
> >> >> Changes in v4:
> >> >> - Adjust README to mention that lowlevel_init() should have no stack
> >> >>
> >> >> Changes in v3: None
> >> >> Changes in v2:
> >> >> - Move docs to top-level README file and expand them to cover U-Boot proper
> >> >> - Add Kconfig settings
> >> >>
> >> >>  Kconfig             | 18 ++++++++++++++
> >> >>  README              | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> >> >>  arch/arm/lib/crt0.S | 13 +++++++---
> >> >>  common/spl/spl.c    | 35 +++++++++++++++++++++++++++
> >> >>  4 files changed, 132 insertions(+), 3 deletions(-)
> >> > [snip]
> >> >> diff --git a/arch/arm/lib/crt0.S b/arch/arm/lib/crt0.S
> >> >> index 22df3e5..7939ced 100644
> >> >> --- a/arch/arm/lib/crt0.S
> >> >> +++ b/arch/arm/lib/crt0.S
> >> >> @@ -113,7 +113,14 @@ here:
> >> >>  /* Set up final (full) environment */
> >> >>
> >> >>       bl      c_runtime_cpu_setup     /* we still call old routine here */
> >> >> -
> >> >> +#endif
> >> >> +#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK)
> >> >> +# ifdef CONFIG_SPL_BUILD
> >> >> +     /* Use a DRAM stack for the rest of SPL, if requested */
> >> >> +     bl      spl_relocate_stack_gd
> >> >> +     cmp     r0, #0
> >> >> +     movne   sp, r0
> >> >> +# endif
> >> >>       ldr     r0, =__bss_start        /* this is auto-relocated! */
> >> >>       ldr     r1, =__bss_end          /* this is auto-relocated! */
> >> >>
> >> >> @@ -124,9 +131,10 @@ clbss_l:cmp      r0, r1                  /* while not at end of BSS */
> >> >>       addlo   r0, r0, #4              /* move to next */
> >> >>       blo     clbss_l
> >> >>
> >> >> +#if ! defined(CONFIG_SPL_BUILD)
> >> >>       bl coloured_LED_init
> >> >>       bl red_led_on
> >> >> -
> >> >> +#endif
> >> >>       /* call board_init_r(gd_t *id, ulong dest_addr) */
> >> >>       mov     r0, r9                  /* gd_t */
> >> >>       ldr     r1, [r9, #GD_RELOCADDR] /* dest_addr */
> >> >> @@ -134,7 +142,6 @@ clbss_l:cmp       r0, r1                  /* while not at end of BSS */
> >> >>       ldr     pc, =board_init_r       /* this is auto-relocated! */
> >> >>
> >> >>       /* we should not return here. */
> >> >> -
> >> >>  #endif
> >> >>
> >> >>  ENDPROC(_main)
> >> >> diff --git a/common/spl/spl.c b/common/spl/spl.c
> >> >> index ded0f30..cd75bbc 100644
> >> >> --- a/common/spl/spl.c
> >> >> +++ b/common/spl/spl.c
> >> >> @@ -281,3 +281,38 @@ void preloader_console_init(void)
> >> >>       spl_display_print();
> >> >>  #endif
> >> >>  }
> >> >> +
> >> >> +/**
> >> >> + * spl_relocate_stack_gd() - Relocate stack ready for board_init_r() execution
> >> >> + *
> >> >> + * Sometimes board_init_f() runs with a stack in SRAM but we want to use SDRAM
> >> >> + * for the main board_init_r() execution. This is typically because we need
> >> >> + * more stack space for things like the MMC sub-system.
> >> >> + *
> >> >> + * This function calculates the stack position, copies the global_data into
> >> >> + * place and returns the new stack position. The caller is responsible for
> >> >> + * setting up the sp register.
> >> >> + *
> >> >> + * @return new stack location, or 0 to use the same stack
> >> >> + */
> >> >> +ulong spl_relocate_stack_gd(void)
> >> >> +{
> >> >> +#ifdef CONFIG_SPL_STACK_R
> >> >> +     gd_t *new_gd;
> >> >> +     ulong ptr;
> >> >> +
> >> >> +     /* Get stack position: use 8-byte alignment for ABI compliance */
> >> >> +     ptr = CONFIG_SPL_STACK_R - sizeof(gd_t);
> >> >> +     ptr &= ~7;
> >> >> +     new_gd = (gd_t *)ptr;
> >> >> +     memcpy(new_gd, (void *)gd, sizeof(gd_t));
> >> >> +     gd = new_gd;
> >> >> +
> >> >> +     /* Clear the BSS. */
> >> >> +     memset(__bss_start, 0, __bss_end - __bss_start);
> >> >> +
> >> >> +     return ptr;
> >> >> +#else
> >> >> +     return 0;
> >> >> +#endif
> >> >> +}
> >> >
> >> > All of this _does_ move gd into where CONFIG_SPL_STACK_R points.  It
> >> > does _not_ move the stack itself into where CONFIG_SPL_STACK_R points so
> >> > the big use case (am335x_boneblack for example where
> >> > CONFIG_SPL_ENV_SUPPORT is set) doesn't work and blows up as we overflow
> >> > the area for stack.
> >>
> >> OK I'll have to test more. What sort of problem should i see?
> >
> > We hang on entering env_reloc_spec() which is what puts some big sized
> > variables on the stack.
> >
> >> The return value from spl_relocate_stack_gd() should be shoved into
> >> sp. Does that not happen?
> >
> > It doesn't appear to be.  I hadn't broken out the BBB with JTAG tho.
> 
> I printed out the stack in board_init_r() and it looks right: 32MB
> above the base of SDRAM.
> 
> Also I don't seem to get a crash in SPL. How do I make that happen? If
> I define CONFIG_SPL_USBETH_SUPPORT I get an error about the .data
> section not fitin in .sram for u-boot-spl.

With v5 at least, am335x_boneblack_config running on a BBB does it.
I'll try v6 this morning and see what's going on..
Tom Rini March 4, 2015, 3:10 p.m. UTC | #6
On Wed, Mar 04, 2015 at 08:38:33AM -0500, Tom Rini wrote:
> On Tue, Mar 03, 2015 at 08:23:23PM -0700, Simon Glass wrote:
> > Hi Tom,
> > 
> > On 3 March 2015 at 13:14, Tom Rini <trini@konsulko.com> wrote:
> > > On Tue, Mar 03, 2015 at 12:04:16PM -0700, Simon Glass wrote:
> > >> Hi Tom,
> > >>
> > >> On 3 March 2015 at 10:49, Tom Rini <trini@konsulko.com> wrote:
> > >> > On Tue, Mar 03, 2015 at 08:03:00AM -0700, Simon Glass wrote:
> > >> >
> > >> >> At present SPL uses a single stack, either CONFIG_SPL_STACK or
> > >> >> CONFIG_SYS_INIT_SP_ADDR. Since some SPL features (such as MMC and
> > >> >> environment) require a lot of stack, some boards set CONFIG_SPL_STACK to
> > >> >> point into SDRAM. They then set up SDRAM very early, before board_init_f(),
> > >> >> so that the larger stack can be used.
> > >> >>
> > >> >> This is an abuse of lowlevel_init(). That function should only be used for
> > >> >> essential start-up code which cannot be delayed. An example of a valid use is
> > >> >> when only part of the SPL code is visible/executable, and the SoC must be set
> > >> >> up so that board_init_f() can be reached. It should not be used for SDRAM
> > >> >> init, console init, etc.
> > >> >>
> > >> >> Add a CONFIG_SPL_STACK_R option, which allows the stack to be moved to a new
> > >> >> address before board_init_r() is called in SPL.
> > >> >>
> > >> >> The expected SPL flow (for CONFIG_SPL_FRAMEWORK) is documented in the README.
> > >> >>
> > >> >> Signed-off-by: Simon Glass <sjg@chromium.org>
> > >> >> For version 1:
> > >> >> Acked-by: Albert ARIBAUD <albert.u.boot@aribaud.net>
> > >> >> Reviewed-by: Stefan Roese <sr@denx.de>
> > >> >> Tested-by: Bo Shen <voice.shen@atmel.com>
> > >> >> Acked-by: Bo Shen <voice.shen@atmel.com>
> > >> >> Acked-by: Heiko Schocher <hs@denx.de>
> > >> >> Tested-by: Heiko Schocher <hs@denx.de>
> > >> >> ---
> > >> >>
> > >> >> Changes in v6: None
> > >> >> Changes in v5:
> > >> >> - Rebase to master
> > >> >>
> > >> >> Changes in v4:
> > >> >> - Adjust README to mention that lowlevel_init() should have no stack
> > >> >>
> > >> >> Changes in v3: None
> > >> >> Changes in v2:
> > >> >> - Move docs to top-level README file and expand them to cover U-Boot proper
> > >> >> - Add Kconfig settings
> > >> >>
> > >> >>  Kconfig             | 18 ++++++++++++++
> > >> >>  README              | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >> >>  arch/arm/lib/crt0.S | 13 +++++++---
> > >> >>  common/spl/spl.c    | 35 +++++++++++++++++++++++++++
> > >> >>  4 files changed, 132 insertions(+), 3 deletions(-)
> > >> > [snip]
> > >> >> diff --git a/arch/arm/lib/crt0.S b/arch/arm/lib/crt0.S
> > >> >> index 22df3e5..7939ced 100644
> > >> >> --- a/arch/arm/lib/crt0.S
> > >> >> +++ b/arch/arm/lib/crt0.S
> > >> >> @@ -113,7 +113,14 @@ here:
> > >> >>  /* Set up final (full) environment */
> > >> >>
> > >> >>       bl      c_runtime_cpu_setup     /* we still call old routine here */
> > >> >> -
> > >> >> +#endif
> > >> >> +#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK)
> > >> >> +# ifdef CONFIG_SPL_BUILD
> > >> >> +     /* Use a DRAM stack for the rest of SPL, if requested */
> > >> >> +     bl      spl_relocate_stack_gd
> > >> >> +     cmp     r0, #0
> > >> >> +     movne   sp, r0
> > >> >> +# endif
> > >> >>       ldr     r0, =__bss_start        /* this is auto-relocated! */
> > >> >>       ldr     r1, =__bss_end          /* this is auto-relocated! */
> > >> >>
> > >> >> @@ -124,9 +131,10 @@ clbss_l:cmp      r0, r1                  /* while not at end of BSS */
> > >> >>       addlo   r0, r0, #4              /* move to next */
> > >> >>       blo     clbss_l
> > >> >>
> > >> >> +#if ! defined(CONFIG_SPL_BUILD)
> > >> >>       bl coloured_LED_init
> > >> >>       bl red_led_on
> > >> >> -
> > >> >> +#endif
> > >> >>       /* call board_init_r(gd_t *id, ulong dest_addr) */
> > >> >>       mov     r0, r9                  /* gd_t */
> > >> >>       ldr     r1, [r9, #GD_RELOCADDR] /* dest_addr */
> > >> >> @@ -134,7 +142,6 @@ clbss_l:cmp       r0, r1                  /* while not at end of BSS */
> > >> >>       ldr     pc, =board_init_r       /* this is auto-relocated! */
> > >> >>
> > >> >>       /* we should not return here. */
> > >> >> -
> > >> >>  #endif
> > >> >>
> > >> >>  ENDPROC(_main)
> > >> >> diff --git a/common/spl/spl.c b/common/spl/spl.c
> > >> >> index ded0f30..cd75bbc 100644
> > >> >> --- a/common/spl/spl.c
> > >> >> +++ b/common/spl/spl.c
> > >> >> @@ -281,3 +281,38 @@ void preloader_console_init(void)
> > >> >>       spl_display_print();
> > >> >>  #endif
> > >> >>  }
> > >> >> +
> > >> >> +/**
> > >> >> + * spl_relocate_stack_gd() - Relocate stack ready for board_init_r() execution
> > >> >> + *
> > >> >> + * Sometimes board_init_f() runs with a stack in SRAM but we want to use SDRAM
> > >> >> + * for the main board_init_r() execution. This is typically because we need
> > >> >> + * more stack space for things like the MMC sub-system.
> > >> >> + *
> > >> >> + * This function calculates the stack position, copies the global_data into
> > >> >> + * place and returns the new stack position. The caller is responsible for
> > >> >> + * setting up the sp register.
> > >> >> + *
> > >> >> + * @return new stack location, or 0 to use the same stack
> > >> >> + */
> > >> >> +ulong spl_relocate_stack_gd(void)
> > >> >> +{
> > >> >> +#ifdef CONFIG_SPL_STACK_R
> > >> >> +     gd_t *new_gd;
> > >> >> +     ulong ptr;
> > >> >> +
> > >> >> +     /* Get stack position: use 8-byte alignment for ABI compliance */
> > >> >> +     ptr = CONFIG_SPL_STACK_R - sizeof(gd_t);
> > >> >> +     ptr &= ~7;
> > >> >> +     new_gd = (gd_t *)ptr;
> > >> >> +     memcpy(new_gd, (void *)gd, sizeof(gd_t));
> > >> >> +     gd = new_gd;
> > >> >> +
> > >> >> +     /* Clear the BSS. */
> > >> >> +     memset(__bss_start, 0, __bss_end - __bss_start);
> > >> >> +
> > >> >> +     return ptr;
> > >> >> +#else
> > >> >> +     return 0;
> > >> >> +#endif
> > >> >> +}
> > >> >
> > >> > All of this _does_ move gd into where CONFIG_SPL_STACK_R points.  It
> > >> > does _not_ move the stack itself into where CONFIG_SPL_STACK_R points so
> > >> > the big use case (am335x_boneblack for example where
> > >> > CONFIG_SPL_ENV_SUPPORT is set) doesn't work and blows up as we overflow
> > >> > the area for stack.
> > >>
> > >> OK I'll have to test more. What sort of problem should i see?
> > >
> > > We hang on entering env_reloc_spec() which is what puts some big sized
> > > variables on the stack.
> > >
> > >> The return value from spl_relocate_stack_gd() should be shoved into
> > >> sp. Does that not happen?
> > >
> > > It doesn't appear to be.  I hadn't broken out the BBB with JTAG tho.
> > 
> > I printed out the stack in board_init_r() and it looks right: 32MB
> > above the base of SDRAM.
> > 
> > Also I don't seem to get a crash in SPL. How do I make that happen? If
> > I define CONFIG_SPL_USBETH_SUPPORT I get an error about the .data
> > section not fitin in .sram for u-boot-spl.
> 
> With v5 at least, am335x_boneblack_config running on a BBB does it.
> I'll try v6 this morning and see what's going on..

With your v6 as-is, things are working.  So I'll go track down what's
hopefully some problem with what I was doing from here, thanks!
Tom Rini March 4, 2015, 3:42 p.m. UTC | #7
On Tue, Mar 03, 2015 at 08:03:00AM -0700, Simon Glass wrote:

> At present SPL uses a single stack, either CONFIG_SPL_STACK or
> CONFIG_SYS_INIT_SP_ADDR. Since some SPL features (such as MMC and
> environment) require a lot of stack, some boards set CONFIG_SPL_STACK to
> point into SDRAM. They then set up SDRAM very early, before board_init_f(),
> so that the larger stack can be used.
> 
> This is an abuse of lowlevel_init(). That function should only be used for
> essential start-up code which cannot be delayed. An example of a valid use is
> when only part of the SPL code is visible/executable, and the SoC must be set
> up so that board_init_f() can be reached. It should not be used for SDRAM
> init, console init, etc.
> 
> Add a CONFIG_SPL_STACK_R option, which allows the stack to be moved to a new
> address before board_init_r() is called in SPL.
> 
> The expected SPL flow (for CONFIG_SPL_FRAMEWORK) is documented in the README.
[snip]
> diff --git a/Kconfig b/Kconfig
> index 91a0618..8de731d 100644
> --- a/Kconfig
> +++ b/Kconfig
> @@ -96,6 +96,24 @@ config SPL
>  	help
>  	  If you want to build SPL as well as the normal image, say Y.
>  
> +config CONFIG_SPL_STACK_R
> +	depends on SPL
> +	bool "Enable SDRAM location for SPL stack"
> +	help
> +	  SPL starts off execution in SRAM and thus typically has only a small
> +	  stack available. Since SPL sets up DRAM while in its board_init_f()
> +	  function, it is possible for the stack to move there before
> +	  board_init_r() is reached. This option enables a special SDRAM
> +	  location for the SPL stack. U-Boot SPL switches to this after
> +	  board_init_f() completes, and before board_init_r() starts.
> +
> +config CONFIG_SPL_STACK_R_ADDR
> +	depends on CONFIG_SPL_STACK_R

I found my problem!  Incorrect Kconfig syntax, no CONFIG_ in 'config' or
'depends' lines only help lines.  So I was right in that my stack wasn't
moving because I was doing it via the defconfig and that was broken :)

I'm just going to pick up 1-5 (with this fixed) and send out my own 6
after I test it on omap3 and omap4/5 which also need a similar
conversion.
Simon Glass March 4, 2015, 7:14 p.m. UTC | #8
Hi Tom,

On 4 March 2015 at 08:42, Tom Rini <trini@konsulko.com> wrote:
> On Tue, Mar 03, 2015 at 08:03:00AM -0700, Simon Glass wrote:
>
>> At present SPL uses a single stack, either CONFIG_SPL_STACK or
>> CONFIG_SYS_INIT_SP_ADDR. Since some SPL features (such as MMC and
>> environment) require a lot of stack, some boards set CONFIG_SPL_STACK to
>> point into SDRAM. They then set up SDRAM very early, before board_init_f(),
>> so that the larger stack can be used.
>>
>> This is an abuse of lowlevel_init(). That function should only be used for
>> essential start-up code which cannot be delayed. An example of a valid use is
>> when only part of the SPL code is visible/executable, and the SoC must be set
>> up so that board_init_f() can be reached. It should not be used for SDRAM
>> init, console init, etc.
>>
>> Add a CONFIG_SPL_STACK_R option, which allows the stack to be moved to a new
>> address before board_init_r() is called in SPL.
>>
>> The expected SPL flow (for CONFIG_SPL_FRAMEWORK) is documented in the README.
> [snip]
>> diff --git a/Kconfig b/Kconfig
>> index 91a0618..8de731d 100644
>> --- a/Kconfig
>> +++ b/Kconfig
>> @@ -96,6 +96,24 @@ config SPL
>>       help
>>         If you want to build SPL as well as the normal image, say Y.
>>
>> +config CONFIG_SPL_STACK_R
>> +     depends on SPL
>> +     bool "Enable SDRAM location for SPL stack"
>> +     help
>> +       SPL starts off execution in SRAM and thus typically has only a small
>> +       stack available. Since SPL sets up DRAM while in its board_init_f()
>> +       function, it is possible for the stack to move there before
>> +       board_init_r() is reached. This option enables a special SDRAM
>> +       location for the SPL stack. U-Boot SPL switches to this after
>> +       board_init_f() completes, and before board_init_r() starts.
>> +
>> +config CONFIG_SPL_STACK_R_ADDR
>> +     depends on CONFIG_SPL_STACK_R
>
> I found my problem!  Incorrect Kconfig syntax, no CONFIG_ in 'config' or
> 'depends' lines only help lines.  So I was right in that my stack wasn't
> moving because I was doing it via the defconfig and that was broken :)
>
> I'm just going to pick up 1-5 (with this fixed) and send out my own 6
> after I test it on omap3 and omap4/5 which also need a similar
> conversion.

Great, thanks for doing this!

Regards,
Simon
Tom Rini March 4, 2015, 10:16 p.m. UTC | #9
On Tue, Mar 03, 2015 at 08:03:00AM -0700, Simon Glass wrote:

> At present SPL uses a single stack, either CONFIG_SPL_STACK or
> CONFIG_SYS_INIT_SP_ADDR. Since some SPL features (such as MMC and
> environment) require a lot of stack, some boards set CONFIG_SPL_STACK to
> point into SDRAM. They then set up SDRAM very early, before board_init_f(),
> so that the larger stack can be used.
> 
> This is an abuse of lowlevel_init(). That function should only be used for
> essential start-up code which cannot be delayed. An example of a valid use is
> when only part of the SPL code is visible/executable, and the SoC must be set
> up so that board_init_f() can be reached. It should not be used for SDRAM
> init, console init, etc.
> 
> Add a CONFIG_SPL_STACK_R option, which allows the stack to be moved to a new
> address before board_init_r() is called in SPL.
> 
> The expected SPL flow (for CONFIG_SPL_FRAMEWORK) is documented in the README.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> For version 1:
> Acked-by: Albert ARIBAUD <albert.u.boot@aribaud.net>
> Reviewed-by: Stefan Roese <sr@denx.de>
> Tested-by: Bo Shen <voice.shen@atmel.com>
> Acked-by: Bo Shen <voice.shen@atmel.com>
> Acked-by: Heiko Schocher <hs@denx.de>
> Tested-by: Heiko Schocher <hs@denx.de>

After fixing the Kconfig part to not have 'CONFIG_' in the 'config' and
'depends' lines, applied to u-boot/master, thanks!
diff mbox

Patch

diff --git a/Kconfig b/Kconfig
index 91a0618..8de731d 100644
--- a/Kconfig
+++ b/Kconfig
@@ -96,6 +96,24 @@  config SPL
 	help
 	  If you want to build SPL as well as the normal image, say Y.
 
+config CONFIG_SPL_STACK_R
+	depends on SPL
+	bool "Enable SDRAM location for SPL stack"
+	help
+	  SPL starts off execution in SRAM and thus typically has only a small
+	  stack available. Since SPL sets up DRAM while in its board_init_f()
+	  function, it is possible for the stack to move there before
+	  board_init_r() is reached. This option enables a special SDRAM
+	  location for the SPL stack. U-Boot SPL switches to this after
+	  board_init_f() completes, and before board_init_r() starts.
+
+config CONFIG_SPL_STACK_R_ADDR
+	depends on CONFIG_SPL_STACK_R
+	hex "SDRAM location for SPL stack"
+	help
+	  Specify the address in SDRAM for the SPL stack. This will be set up
+	  before board_init_r() is called.
+
 config TPL
 	bool
 	depends on SPL && SUPPORT_TPL
diff --git a/README b/README
index febefb5..3547ead 100644
--- a/README
+++ b/README
@@ -273,6 +273,75 @@  run some of U-Boot's tests.
 See board/sandbox/README.sandbox for more details.
 
 
+Board Initialisation Flow:
+--------------------------
+
+This is the intended start-up flow for boards. This should apply for both
+SPL and U-Boot proper (i.e. they both follow the same rules). At present SPL
+mostly uses a separate code path, but the funtion names and roles of each
+function are the same. Some boards or architectures may not conform to this.
+At least most ARM boards which use CONFIG_SPL_FRAMEWORK conform to this.
+
+Execution starts with start.S with three functions called during init after
+that. The purpose and limitations of each is described below.
+
+lowlevel_init():
+	- purpose: essential init to permit execution to reach board_init_f()
+	- no global_data or BSS
+	- there is no stack (ARMv7 may have one but it will soon be removed)
+	- must not set up SDRAM or use console
+	- must only do the bare minimum to allow execution to continue to
+		board_init_f()
+	- this is almost never needed
+	- return normally from this function
+
+board_init_f():
+	- purpose: set up the machine ready for running board_init_r():
+		i.e. SDRAM and serial UART
+	- global_data is available
+	- stack is in SRAM
+	- BSS is not available, so you cannot use global/static variables,
+		only stack variables and global_data
+
+	Non-SPL-specific notes:
+	- dram_init() is called to set up DRAM. If already done in SPL this
+		can do nothing
+
+	SPL-specific notes:
+	- you can override the entire board_init_f() function with your own
+		version as needed.
+	- preloader_console_init() can be called here in extremis
+	- should set up SDRAM, and anything needed to make the UART work
+	- these is no need to clear BSS, it will be done by crt0.S
+	- must return normally from this function (don't call board_init_r()
+		directly)
+
+Here the BSS is cleared. For SPL, if CONFIG_SPL_STACK_R is defined, then at
+this point the stack and global_data are relocated to below
+CONFIG_SPL_STACK_R_ADDR. For non-SPL, U-Boot is relocated to run at the top of
+memory.
+
+board_init_r():
+	- purpose: main execution, common code
+	- global_data is available
+	- SDRAM is available
+	- BSS is available, all static/global variables can be used
+	- execution eventually continues to main_loop()
+
+	Non-SPL-specific notes:
+	- U-Boot is relocated to the top of memory and is now running from
+		there.
+
+	SPL-specific notes:
+	- stack is optionally in SDRAM, if CONFIG_SPL_STACK_R is defined and
+		CONFIG_SPL_STACK_R_ADDR points into SDRAM
+	- preloader_console_init() can be called here - typically this is
+		done by defining CONFIG_SPL_BOARD_INIT and then supplying a
+		spl_board_init() function containing this call
+	- loads U-Boot or (in falcon mode) Linux
+
+
+
 Configuration Options:
 ----------------------
 
diff --git a/arch/arm/lib/crt0.S b/arch/arm/lib/crt0.S
index 22df3e5..7939ced 100644
--- a/arch/arm/lib/crt0.S
+++ b/arch/arm/lib/crt0.S
@@ -113,7 +113,14 @@  here:
 /* Set up final (full) environment */
 
 	bl	c_runtime_cpu_setup	/* we still call old routine here */
-
+#endif
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_FRAMEWORK)
+# ifdef CONFIG_SPL_BUILD
+	/* Use a DRAM stack for the rest of SPL, if requested */
+	bl	spl_relocate_stack_gd
+	cmp	r0, #0
+	movne	sp, r0
+# endif
 	ldr	r0, =__bss_start	/* this is auto-relocated! */
 	ldr	r1, =__bss_end		/* this is auto-relocated! */
 
@@ -124,9 +131,10 @@  clbss_l:cmp	r0, r1			/* while not at end of BSS */
 	addlo	r0, r0, #4		/* move to next */
 	blo	clbss_l
 
+#if ! defined(CONFIG_SPL_BUILD)
 	bl coloured_LED_init
 	bl red_led_on
-
+#endif
 	/* call board_init_r(gd_t *id, ulong dest_addr) */
 	mov     r0, r9                  /* gd_t */
 	ldr	r1, [r9, #GD_RELOCADDR]	/* dest_addr */
@@ -134,7 +142,6 @@  clbss_l:cmp	r0, r1			/* while not at end of BSS */
 	ldr	pc, =board_init_r	/* this is auto-relocated! */
 
 	/* we should not return here. */
-
 #endif
 
 ENDPROC(_main)
diff --git a/common/spl/spl.c b/common/spl/spl.c
index ded0f30..cd75bbc 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -281,3 +281,38 @@  void preloader_console_init(void)
 	spl_display_print();
 #endif
 }
+
+/**
+ * spl_relocate_stack_gd() - Relocate stack ready for board_init_r() execution
+ *
+ * Sometimes board_init_f() runs with a stack in SRAM but we want to use SDRAM
+ * for the main board_init_r() execution. This is typically because we need
+ * more stack space for things like the MMC sub-system.
+ *
+ * This function calculates the stack position, copies the global_data into
+ * place and returns the new stack position. The caller is responsible for
+ * setting up the sp register.
+ *
+ * @return new stack location, or 0 to use the same stack
+ */
+ulong spl_relocate_stack_gd(void)
+{
+#ifdef CONFIG_SPL_STACK_R
+	gd_t *new_gd;
+	ulong ptr;
+
+	/* Get stack position: use 8-byte alignment for ABI compliance */
+	ptr = CONFIG_SPL_STACK_R - sizeof(gd_t);
+	ptr &= ~7;
+	new_gd = (gd_t *)ptr;
+	memcpy(new_gd, (void *)gd, sizeof(gd_t));
+	gd = new_gd;
+
+	/* Clear the BSS. */
+	memset(__bss_start, 0, __bss_end - __bss_start);
+
+	return ptr;
+#else
+	return 0;
+#endif
+}