arm: move gd handling outside of C code
As of gcc 5.2.1 for Thumb-1, it is not possible any more to assign gd from C code, as gd is mapped to r9, and r9 may now be saved in the prolog sequence, and restored in the epilog sequence, of any C functions. Therefore arch_setup_gd(), which is supposed to set r9, may actually have no effect, causing U-Boot to use a bad address to access GD. Fix this by never calling arch_setup_gd() for ARM, and instead setting r9 in arch/arm/lib/crt0.S, to the value returned by board_init_f_alloc_reserve(). Signed-off-by: Albert ARIBAUD <albert.u.boot@aribaud.net> Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
		
							parent
							
								
									ecc306639e
								
							
						
					
					
						commit
						adc421e4ce
					
				| 
						 | 
				
			
			@ -85,6 +85,8 @@ ENTRY(_main)
 | 
			
		|||
	mov	r0, sp
 | 
			
		||||
	bl	board_init_f_alloc_reserve
 | 
			
		||||
	mov	sp, r0
 | 
			
		||||
	/* set up gd here, outside any C code */
 | 
			
		||||
	mov	r9, r0
 | 
			
		||||
	bl	board_init_f_init_reserve
 | 
			
		||||
 | 
			
		||||
	mov	r0, #0
 | 
			
		||||
| 
						 | 
				
			
			@ -134,6 +136,7 @@ here:
 | 
			
		|||
	bl	spl_relocate_stack_gd
 | 
			
		||||
	cmp	r0, #0
 | 
			
		||||
	movne	sp, r0
 | 
			
		||||
	movne	r9, r0
 | 
			
		||||
# endif
 | 
			
		||||
	ldr	r0, =__bss_start	/* this is auto-relocated! */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,13 +21,13 @@ DECLARE_GLOBAL_DATA_PTR;
 | 
			
		|||
#define _USE_MEMCPY
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Unfortunately x86 can't compile this code as gd cannot be assigned */
 | 
			
		||||
#ifndef CONFIG_X86
 | 
			
		||||
/* Unfortunately x86 or ARM can't compile this code as gd cannot be assigned */
 | 
			
		||||
#if !defined(CONFIG_X86) && !defined(CONFIG_ARM)
 | 
			
		||||
__weak void arch_setup_gd(struct global_data *gd_ptr)
 | 
			
		||||
{
 | 
			
		||||
	gd = gd_ptr;
 | 
			
		||||
}
 | 
			
		||||
#endif /* !CONFIG_X86 */
 | 
			
		||||
#endif /* !CONFIG_X86 && !CONFIG_ARM */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Allocate reserved space for use as 'globals' from 'top' address and
 | 
			
		||||
| 
						 | 
				
			
			@ -128,7 +128,7 @@ void board_init_f_init_reserve(ulong base)
 | 
			
		|||
		*ptr++ = 0;
 | 
			
		||||
#endif
 | 
			
		||||
	/* set GD unless architecture did it already */
 | 
			
		||||
#ifndef CONFIG_X86
 | 
			
		||||
#if !defined(CONFIG_X86) && !defined(CONFIG_ARM)
 | 
			
		||||
	arch_setup_gd(gd_ptr);
 | 
			
		||||
#endif
 | 
			
		||||
	/* next alloc will be higher by one GD plus 16-byte alignment */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -431,8 +431,13 @@ void preloader_console_init(void)
 | 
			
		|||
 * 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.
 | 
			
		||||
 * place, sets the new gd (except for ARM, for which setting GD within a C
 | 
			
		||||
 * function may not always work) and returns the new stack position. The
 | 
			
		||||
 * caller is responsible for setting up the sp register and, in the case
 | 
			
		||||
 * of ARM, setting up gd.
 | 
			
		||||
 *
 | 
			
		||||
 * All of this is done using the same layout and alignments as done in
 | 
			
		||||
 * board_init_f_init_reserve() / board_init_f_alloc_reserve().
 | 
			
		||||
 *
 | 
			
		||||
 * @return new stack location, or 0 to use the same stack
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -440,14 +445,7 @@ 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_ADDR - sizeof(gd_t);
 | 
			
		||||
	ptr &= ~7;
 | 
			
		||||
	new_gd = (gd_t *)ptr;
 | 
			
		||||
	memcpy(new_gd, (void *)gd, sizeof(gd_t));
 | 
			
		||||
	gd = new_gd;
 | 
			
		||||
	ulong ptr = CONFIG_SPL_STACK_R_ADDR;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_SPL_SYS_MALLOC_SIMPLE
 | 
			
		||||
	if (CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN) {
 | 
			
		||||
| 
						 | 
				
			
			@ -460,7 +458,13 @@ ulong spl_relocate_stack_gd(void)
 | 
			
		|||
		gd->malloc_ptr = 0;
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	/* Get stack position: use 8-byte alignment for ABI compliance */
 | 
			
		||||
	ptr = CONFIG_SPL_STACK_R_ADDR - roundup(sizeof(gd_t),16);
 | 
			
		||||
	new_gd = (gd_t *)ptr;
 | 
			
		||||
	memcpy(new_gd, (void *)gd, sizeof(gd_t));
 | 
			
		||||
#if !defined(CONFIG_ARM)
 | 
			
		||||
	gd = new_gd;
 | 
			
		||||
#endif
 | 
			
		||||
	return ptr;
 | 
			
		||||
#else
 | 
			
		||||
	return 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue