
On 15/11/10 07:05, Albert ARIBAUD wrote:
Le 14/11/2010 20:34, Graeme Russ a écrit :
On 15/11/10 06:23, Wolfgang Denk wrote:
Dear Albert ARIBAUD,
In message4CE0221A.7030502@free.fr you wrote:
Alright, then I think we should document how we comply, or do not comply, with GNU EABI / AAPCS (maybe a README.arm that people could read up) -- and I think if there is a way to access GD both before and after relocation without making a register unavailable to the whole u-boot code, then we should use it.
By the way - it should be not difficult to use a normal extern pointer to reference the global data; see "arch/powerpc/include/asm/global_data.h":
194 #if 1 195 #define DECLARE_GLOBAL_DATA_PTR register volatile gd_t *gd asm ("r2") 196 #else /* We could use plain global data, but the resulting code is bigger */ 197 #define XTRN_DECLARE_GLOBAL_DATA_PTR extern 198 #define DECLARE_GLOBAL_DATA_PTR XTRN_DECLARE_GLOBAL_DATA_PTR \ 199 gd_t *gd 200 #endif
I think you will find this peculiar to PowerPC
I don't think Wolfgang's idea is actually processor-specific.
Each processor has a way to define globals, which end up in the initialized data or bss area. BSS is not available before relocation, but initialized data is, and remains so after relocation.
So if we define gd as an initialized pointer (residing in the initialized data area), it will be available both before and after relocation.
Before relocation, this pointer will be read-only. We can set it at compile time if we know for each arch (or board) a good address in RAM or IRAM where gd can exist.
After relocation, the pointer becomes read-write: we can copy gd content from (I)RAM to RAM if necessary and then update the gd pointer.
What you are talking about is exactly how x86 defines gd, but for x86, gd is not accessible until after relocation
Could it become accessible with the idea I expose above?
Yes - The following patch uses CONFIG_SYS_INIT_SP_ADDR as a temporary global data area which is copied to a permanent global data structure located in the data section.
I honestly don't know where I stand on this solution though. By using FS, I can emulate the 'global register variable' and the initial global data structure can end up anywhere it needs to be without needing to define CONFIG_SYS_INIT_SP_ADDR but it will involve self-modifying code I would prefer not to re-introduce.
However, this method requires CONFIG_SYS_INIT_SP_ADDR which is casting a certain memory location (in RAM) in stone. Now the eNET has some battery backed SRAM on board which I can point CONFIG_SYS_INIT_SP_ADDR. So I could move SDRAM initialisation into C code, but this is not guaranteed for every x86 board (and for the eNET, it reduces the amount of battery-backed configuration memory available). I am looking to port U-Boot to a VIA EPIA EN15000 single board computer. This has no SRAM.
The VIA board has a C7 processor which coreboot has a 'Cache-as-RAM' (CAR) implementation for, and the SC520 might support CAR (still looking). If this is the case, I think I can unequivocally support the solution based on CONFIG_SYS_INIT_SP_ADDR and move low-level init into board_init_f() in line with the other arches.
For now, consider it a +0.5 vote for the patch below :)
Regards,
Graeme
commit e38af43f0246335578b8c207e8097fd0c5fca520 Author: Graeme Russ graeme.russ@gmail.com Date: Mon Nov 15 21:15:52 2010 +1100
x86 Global Data Mods
diff --git a/arch/i386/cpu/start.S b/arch/i386/cpu/start.S index aaf9dba..4c04a5a 100644 --- a/arch/i386/cpu/start.S +++ b/arch/i386/cpu/start.S @@ -127,14 +127,14 @@ mem_ok: /* Set the upper memory limit parameter */ subl $CONFIG_SYS_STACK_SIZE, %eax
- /* Reserve space for global data */ - subl $(GD_SIZE * 4), %eax - - /* %eax points to the global data structure */ + /* Load some required values into the global data structure */ + movl $CONFIG_SYS_INIT_SP_ADDR, %eax movl %esp, (GD_RAM_SIZE * 4)(%eax) - movl %ebx, (GD_FLAGS * 4)(%eax) movl %ecx, (GD_LOAD_OFF * 4)(%eax)
+ /* Setup bootflags parameter to board_init_f() */ + movl %ebx, %eax + call board_init_f /* Enter, U-boot! */
/* indicate (lack of) progress */ diff --git a/arch/i386/include/asm/global_data.h b/arch/i386/include/asm/global_data.h index e9000c3..03ecc3c 100644 --- a/arch/i386/include/asm/global_data.h +++ b/arch/i386/include/asm/global_data.h @@ -88,6 +88,12 @@ extern gd_t *gd; #define GD_FLG_WARM_BOOT 0x00200 /* Warm Boot */
+#if 0 #define DECLARE_GLOBAL_DATA_PTR +#else +#define XTRN_DECLARE_GLOBAL_DATA_PTR extern +#define DECLARE_GLOBAL_DATA_PTR XTRN_DECLARE_GLOBAL_DATA_PTR \ +gd_t *gd +#endif
#endif /* __ASM_GBL_DATA_H */ diff --git a/arch/i386/lib/board.c b/arch/i386/lib/board.c index 1a962d3..11e6569 100644 --- a/arch/i386/lib/board.c +++ b/arch/i386/lib/board.c @@ -45,7 +45,24 @@ #include <miiphy.h> #endif
-DECLARE_GLOBAL_DATA_PTR; +#if 1 /* We could use plain global data, but the resulting code is bigger */ +/* + * Pointer to initial global data area + * + * Here we initialize it. + */ +#undef XTRN_DECLARE_GLOBAL_DATA_PTR +#define XTRN_DECLARE_GLOBAL_DATA_PTR /* empty = allocate here */ +DECLARE_GLOBAL_DATA_PTR = (gd_t *) (CONFIG_SYS_INIT_SP_ADDR); +#endif /* 0 */ + +static inline gd_t *get_gd_ptr(void) +{ + gd_t *gd_ptr; + + asm volatile("gs mov 0, %0\n" : "=r" (gd_ptr)); + return gd_ptr; +}
/* Exports from the Linker Script */ extern ulong __text_start; @@ -163,12 +180,10 @@ init_fnc_t *init_sequence[] = { NULL, };
-gd_t *gd; - /* * Load U-Boot into RAM, initialize BSS, perform relocation adjustments */ -void board_init_f (ulong gdp) +void board_init_f (ulong bootflag) { void *text_start = &__text_start; void *data_end = &__data_end; @@ -186,12 +201,14 @@ void board_init_f (ulong gdp) Elf32_Rel *re_src; Elf32_Rel *re_end;
+ gd->flags = bootflag; + /* Calculate destination RAM Address and relocation offset */ - dest_addr = (void *)gdp - (bss_end - text_start); + dest_addr = (void *)gd->ram_size - (bss_end - text_start); rel_offset = dest_addr - text_start;
/* Perform low-level initialization only when cold booted */ - if (((gd_t *)gdp)->flags & GD_FLG_COLD_BOOT) { + if (gd->flags & GD_FLG_COLD_BOOT) { /* First stage CPU initialization */ if (cpu_init_f() != 0) hang(); @@ -203,8 +220,8 @@ void board_init_f (ulong gdp)
/* Copy U-Boot into RAM */ dst_addr = (ulong *)dest_addr; - src_addr = (ulong *)(text_start + ((gd_t *)gdp)->load_off); - end_addr = (ulong *)(data_end + ((gd_t *)gdp)->load_off); + src_addr = (ulong *)(text_start + gd->load_off); + end_addr = (ulong *)(data_end + gd->load_off);
while (src_addr < end_addr) *dst_addr++ = *src_addr++; @@ -217,8 +234,8 @@ void board_init_f (ulong gdp) *dst_addr++ = 0x00000000;
/* Perform relocation adjustments */ - re_src = (Elf32_Rel *)(rel_dyn_start + ((gd_t *)gdp)->load_off); - re_end = (Elf32_Rel *)(rel_dyn_end + ((gd_t *)gdp)->load_off); + re_src = (Elf32_Rel *)(rel_dyn_start + gd->load_off); + re_end = (Elf32_Rel *)(rel_dyn_end + gd->load_off);
do { if (re_src->r_offset >= CONFIG_SYS_TEXT_BASE) @@ -226,11 +243,11 @@ void board_init_f (ulong gdp) *(Elf32_Addr *)(re_src->r_offset + rel_offset) += rel_offset; } while (re_src++ < re_end);
- ((gd_t *)gdp)->reloc_off = rel_offset; - ((gd_t *)gdp)->flags |= GD_FLG_RELOC; + gd->reloc_off = rel_offset; + gd->flags |= GD_FLG_RELOC;
/* Enter the relocated U-Boot! */ - (board_init_r + rel_offset)((gd_t *)gdp, (ulong)dest_addr); + (board_init_r + rel_offset)(gd, (ulong)dest_addr);
/* NOTREACHED - board_init_f() does not return */ while(1); @@ -242,11 +259,15 @@ void board_init_r(gd_t *id, ulong dest_addr) int i; ulong size; static bd_t bd_data; + static gd_t static_gd; + init_fnc_t **init_fnc_ptr;
show_boot_progress(0x21);
- gd = id; + memcpy (&static_gd, id, sizeof static_gd); + gd = &static_gd; + /* compiler optimization barrier needed for GCC >= 3.4 */ __asm__ __volatile__("": : :"memory");
diff --git a/include/configs/eNET.h b/include/configs/eNET.h index a04cc9a..b821e2d 100644 --- a/include/configs/eNET.h +++ b/include/configs/eNET.h @@ -172,6 +172,7 @@ * Memory organization */ #define CONFIG_SYS_STACK_SIZE 0x8000 /* Size of bootloader stack */ +#define CONFIG_SYS_INIT_SP_ADDR 0x1000000 #define CONFIG_SYS_BL_START_FLASH 0x38040000 /* Address of relocated code */ #define CONFIG_SYS_BL_START_RAM 0x03fd0000 /* Address of relocated code */ #define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE