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
 | 
						mov	r0, sp
 | 
				
			||||||
	bl	board_init_f_alloc_reserve
 | 
						bl	board_init_f_alloc_reserve
 | 
				
			||||||
	mov	sp, r0
 | 
						mov	sp, r0
 | 
				
			||||||
 | 
						/* set up gd here, outside any C code */
 | 
				
			||||||
 | 
						mov	r9, r0
 | 
				
			||||||
	bl	board_init_f_init_reserve
 | 
						bl	board_init_f_init_reserve
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mov	r0, #0
 | 
						mov	r0, #0
 | 
				
			||||||
| 
						 | 
					@ -134,6 +136,7 @@ here:
 | 
				
			||||||
	bl	spl_relocate_stack_gd
 | 
						bl	spl_relocate_stack_gd
 | 
				
			||||||
	cmp	r0, #0
 | 
						cmp	r0, #0
 | 
				
			||||||
	movne	sp, r0
 | 
						movne	sp, r0
 | 
				
			||||||
 | 
						movne	r9, r0
 | 
				
			||||||
# endif
 | 
					# endif
 | 
				
			||||||
	ldr	r0, =__bss_start	/* this is auto-relocated! */
 | 
						ldr	r0, =__bss_start	/* this is auto-relocated! */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,13 +21,13 @@ DECLARE_GLOBAL_DATA_PTR;
 | 
				
			||||||
#define _USE_MEMCPY
 | 
					#define _USE_MEMCPY
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Unfortunately x86 can't compile this code as gd cannot be assigned */
 | 
					/* Unfortunately x86 or ARM can't compile this code as gd cannot be assigned */
 | 
				
			||||||
#ifndef CONFIG_X86
 | 
					#if !defined(CONFIG_X86) && !defined(CONFIG_ARM)
 | 
				
			||||||
__weak void arch_setup_gd(struct global_data *gd_ptr)
 | 
					__weak void arch_setup_gd(struct global_data *gd_ptr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	gd = gd_ptr;
 | 
						gd = gd_ptr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif /* !CONFIG_X86 */
 | 
					#endif /* !CONFIG_X86 && !CONFIG_ARM */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Allocate reserved space for use as 'globals' from 'top' address and
 | 
					 * 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;
 | 
							*ptr++ = 0;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	/* set GD unless architecture did it already */
 | 
						/* set GD unless architecture did it already */
 | 
				
			||||||
#ifndef CONFIG_X86
 | 
					#if !defined(CONFIG_X86) && !defined(CONFIG_ARM)
 | 
				
			||||||
	arch_setup_gd(gd_ptr);
 | 
						arch_setup_gd(gd_ptr);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	/* next alloc will be higher by one GD plus 16-byte alignment */
 | 
						/* 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.
 | 
					 * more stack space for things like the MMC sub-system.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * This function calculates the stack position, copies the global_data into
 | 
					 * This function calculates the stack position, copies the global_data into
 | 
				
			||||||
 * place and returns the new stack position. The caller is responsible for
 | 
					 * place, sets the new gd (except for ARM, for which setting GD within a C
 | 
				
			||||||
 * setting up the sp register.
 | 
					 * 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
 | 
					 * @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
 | 
					#ifdef CONFIG_SPL_STACK_R
 | 
				
			||||||
	gd_t *new_gd;
 | 
						gd_t *new_gd;
 | 
				
			||||||
	ulong ptr;
 | 
						ulong ptr = CONFIG_SPL_STACK_R_ADDR;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* 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;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_SPL_SYS_MALLOC_SIMPLE
 | 
					#ifdef CONFIG_SPL_SYS_MALLOC_SIMPLE
 | 
				
			||||||
	if (CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN) {
 | 
						if (CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN) {
 | 
				
			||||||
| 
						 | 
					@ -460,7 +458,13 @@ ulong spl_relocate_stack_gd(void)
 | 
				
			||||||
		gd->malloc_ptr = 0;
 | 
							gd->malloc_ptr = 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif
 | 
					#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;
 | 
						return ptr;
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue