x86: Add .data section support for pre-memory stages
x86 pre-memory stages do not support the `.data` section and as a
result developers are required to include runtime initialization code
instead of relying on C global variable definition.
To illustrate the impact of this lack of `.data` section support, here
are two limitations I personally ran into:
1. The inclusion of libgfxinit in romstage for Raptor Lake has
   required some changes in libgfxinit to ensure data is initialized at
   runtime. In addition, we had to manually map some `.data` symbols in
   the `_bss` region.
2. CBFS cache is currently not supported in pre-memory stages and
   enabling it would require to add an initialization function and
   find a generic spot to call it.
Other platforms do not have that limitation. Hence, resolving it would
help to align code and reduce compilation based restriction (cf. the
use of `ENV_HAS_DATA_SECTION` compilation flag in various places of
coreboot code).
We identified three cases to consider:
1. eXecute-In-Place pre-memory stages
   - code is in SPINOR
   - data is also stored in SPINOR but must be linked in Cache-As-RAM
     and copied there at runtime
2. `bootblock` stage is a bit different as it uses Cache-As-Ram but
   the memory mapping and its entry code different
3. pre-memory stages loaded in and executed from
   Cache-As-RAM (cf. `CONFIG_NO_XIP_EARLY_STAGES`).
eXecute-In-Place pre-memory stages (#1) require the creation of a new
ELF segment as the code segment Virtual Memory Address and Load Memory
Address are identical but the data needs to be linked in
cache-As-RAM (VMA) but to be stored right after the code (LMA).
Here is the output `readelf --segments` on a `romstage.debug` ELF
binary.
    Program Headers:
      Type    Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
      LOAD    0x000080 0x02000000 0x02000000 0x21960 0x21960 R E 0x20
      LOAD    0x0219e0 0xfefb1640 0x02021960 0x00018 0x00018 RW  0x4
     Section to Segment mapping:
      Segment Sections...
       00     .text
       01     .data
Segment 0 `VirtAddr` and `PhysAddr` are at the same address while they
are totally different for the Segment 1 holding the `.data`
section. Since we need the data section `VirtAddr` to be in the
Cache-As-Ram and its `PhysAddr` right after the `.text` section, the
use of a new segment is mandatory.
`bootblock` (#2) also uses this new segment to store the data right
after the code and load it to Cache-As-RAM at runtime. However, the
code involved is different.
Not eXecute-In-Place pre-memory stages (#3) do not really need any
special work other than enabling a data section as the code and data
VMA / LMA translation vector is the same.
TEST=#1 and #2 verified on rex and qemu 32 and 64 bits:
     - The `bootblock.debug`, `romstage.debug` and
       `verstage.debug` all have data stored at the end of the `.text`
       section and code to copy the data content to the Cache-As-RAM.
     - The CBFS stages included in the final image has not improperly
       relocated any of the `.data` section symbol.
     - Test purposes global data symbols we added in bootblock,
       romstage and verstage are properly accessible at runtime
     #3: for "Intel Apollolake DDR3 RVP1" board, we verified that the
     generated romstage ELF includes a .data section similarly to a
     regular memory enabled stage.
Change-Id: I030407fcc72776e59def476daa5b86ad0495debe
Signed-off-by: Jeremy Compostella <jeremy.compostella@intel.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/77289
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
			
			
This commit is contained in:
		
				
					committed by
					
						 Julius Werner
						Julius Werner
					
				
			
			
				
	
			
			
			
						parent
						
							79f2e1fc8b
						
					
				
				
					commit
					b7832de026
				
			| @@ -180,6 +180,9 @@ addrsize_set_high: | ||||
| 	pushl	%eax	/* tsc[31:0] */ | ||||
| #endif | ||||
|  | ||||
| 	/* Copy .data section content to Cache-As-Ram */ | ||||
| #include <cpu/x86/copy_data_section.inc> | ||||
|  | ||||
| before_c_entry: | ||||
| 	post_code(POSTCODE_BOOTBLOCK_BEFORE_C_ENTRY) | ||||
| 	call	bootblock_c_entry_bist | ||||
|   | ||||
| @@ -233,6 +233,9 @@ end_microcode_update: | ||||
| 	pushl	%eax	/* tsc[31:0] */ | ||||
| #endif | ||||
|  | ||||
| 	/* Copy .data section content to Cache-As-Ram */ | ||||
| #include <cpu/x86/copy_data_section.inc> | ||||
|  | ||||
| before_c_entry: | ||||
| 	post_code(POSTCODE_BOOTBLOCK_BEFORE_C_ENTRY) | ||||
| 	call	bootblock_c_entry_bist | ||||
|   | ||||
| @@ -155,6 +155,9 @@ addrsize_set_high: | ||||
| 	movd	%mm1, %eax | ||||
| 	pushl	%eax	/* tsc[31:0] */ | ||||
|  | ||||
| 	/* Copy .data section content to Cache-As-Ram */ | ||||
| #include <cpu/x86/copy_data_section.inc> | ||||
|  | ||||
| before_c_entry: | ||||
| 	post_code(POSTCODE_BOOTBLOCK_BEFORE_C_ENTRY) | ||||
| 	call	bootblock_c_entry_bist | ||||
|   | ||||
| @@ -380,6 +380,9 @@ fill_cache: | ||||
| 	pushl	%eax	/* tsc[31:0] */ | ||||
| #endif | ||||
|  | ||||
| 	/* Copy .data section content to Cache-As-Ram */ | ||||
| #include <cpu/x86/copy_data_section.inc> | ||||
|  | ||||
| before_c_entry: | ||||
| 	post_code(POSTCODE_BOOTBLOCK_BEFORE_C_ENTRY) | ||||
| 	call	bootblock_c_entry_bist | ||||
|   | ||||
| @@ -100,6 +100,9 @@ pages_done: | ||||
| 	pushl	%eax | ||||
| #endif | ||||
|  | ||||
| 	/* Copy .data section content to Cache-As-Ram */ | ||||
| #include <cpu/x86/copy_data_section.inc> | ||||
|  | ||||
| before_c_entry: | ||||
| 	call	bootblock_c_entry_bist | ||||
| 	/* Never returns */ | ||||
|   | ||||
							
								
								
									
										38
									
								
								src/cpu/x86/copy_data_section.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/cpu/x86/copy_data_section.inc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| /* SPDX-License-Identifier: GPL-2.0-only */ | ||||
|  | ||||
| #if ENV_SEPARATE_DATA_AND_BSS | ||||
|  | ||||
| /* | ||||
|  * Copy .data section content to Cache-As-Ram. | ||||
|  * This code can be included from 32 bits or 64 bits code. It also preserves | ||||
|  * registers. | ||||
|  */ | ||||
| copy_data_section: | ||||
| #if ENV_X86_64 | ||||
| 	push	%rcx | ||||
| 	push	%rdi | ||||
| 	push	%rsi | ||||
| #else | ||||
| 	pushl	%ecx | ||||
| 	pushl	%edi | ||||
| 	pushl	%esi | ||||
| #endif | ||||
|  | ||||
| 	movl	$(_edata), %ecx | ||||
| 	movl	$(_data), %edi | ||||
| 	sub	%edi, %ecx | ||||
| 	movl	$(_data_load),%esi | ||||
| 	shrl	$2, %ecx | ||||
| 	rep	movsl | ||||
|  | ||||
| #if ENV_X86_64 | ||||
| 	pop	%rsi | ||||
| 	pop	%rdi | ||||
| 	pop	%rcx | ||||
| #else | ||||
| 	popl	%esi | ||||
| 	popl	%edi | ||||
| 	popl	%ecx | ||||
| #endif | ||||
|  | ||||
| #endif	/* ENV_SEPARATE_DATA_AND_BSS */ | ||||
		Reference in New Issue
	
	Block a user