From b7832de0260b042c25bf8f53abcb32e20a29ae9c Mon Sep 17 00:00:00 2001 From: Jeremy Compostella Date: Wed, 30 Aug 2023 15:42:09 -0700 Subject: 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 Reviewed-on: https://review.coreboot.org/c/coreboot/+/77289 Tested-by: build bot (Jenkins) Reviewed-by: Arthur Heymans --- src/cpu/intel/car/core2/cache_as_ram.S | 3 +++ src/cpu/intel/car/non-evict/cache_as_ram.S | 3 +++ src/cpu/intel/car/p3/cache_as_ram.S | 3 +++ src/cpu/intel/car/p4-netburst/cache_as_ram.S | 3 +++ src/cpu/qemu-x86/cache_as_ram_bootblock.S | 3 +++ src/cpu/x86/copy_data_section.inc | 38 ++++++++++++++++++++++++++++ 6 files changed, 53 insertions(+) create mode 100644 src/cpu/x86/copy_data_section.inc (limited to 'src/cpu') diff --git a/src/cpu/intel/car/core2/cache_as_ram.S b/src/cpu/intel/car/core2/cache_as_ram.S index 9c60308b28..e134717b40 100644 --- a/src/cpu/intel/car/core2/cache_as_ram.S +++ b/src/cpu/intel/car/core2/cache_as_ram.S @@ -180,6 +180,9 @@ addrsize_set_high: pushl %eax /* tsc[31:0] */ #endif + /* Copy .data section content to Cache-As-Ram */ +#include + before_c_entry: post_code(POSTCODE_BOOTBLOCK_BEFORE_C_ENTRY) call bootblock_c_entry_bist diff --git a/src/cpu/intel/car/non-evict/cache_as_ram.S b/src/cpu/intel/car/non-evict/cache_as_ram.S index 18ac07036e..76986ff68e 100644 --- a/src/cpu/intel/car/non-evict/cache_as_ram.S +++ b/src/cpu/intel/car/non-evict/cache_as_ram.S @@ -233,6 +233,9 @@ end_microcode_update: pushl %eax /* tsc[31:0] */ #endif + /* Copy .data section content to Cache-As-Ram */ +#include + before_c_entry: post_code(POSTCODE_BOOTBLOCK_BEFORE_C_ENTRY) call bootblock_c_entry_bist diff --git a/src/cpu/intel/car/p3/cache_as_ram.S b/src/cpu/intel/car/p3/cache_as_ram.S index 779dbcca8a..623cf41e73 100644 --- a/src/cpu/intel/car/p3/cache_as_ram.S +++ b/src/cpu/intel/car/p3/cache_as_ram.S @@ -155,6 +155,9 @@ addrsize_set_high: movd %mm1, %eax pushl %eax /* tsc[31:0] */ + /* Copy .data section content to Cache-As-Ram */ +#include + before_c_entry: post_code(POSTCODE_BOOTBLOCK_BEFORE_C_ENTRY) call bootblock_c_entry_bist diff --git a/src/cpu/intel/car/p4-netburst/cache_as_ram.S b/src/cpu/intel/car/p4-netburst/cache_as_ram.S index 9f514ef592..f7c023b402 100644 --- a/src/cpu/intel/car/p4-netburst/cache_as_ram.S +++ b/src/cpu/intel/car/p4-netburst/cache_as_ram.S @@ -380,6 +380,9 @@ fill_cache: pushl %eax /* tsc[31:0] */ #endif + /* Copy .data section content to Cache-As-Ram */ +#include + before_c_entry: post_code(POSTCODE_BOOTBLOCK_BEFORE_C_ENTRY) call bootblock_c_entry_bist diff --git a/src/cpu/qemu-x86/cache_as_ram_bootblock.S b/src/cpu/qemu-x86/cache_as_ram_bootblock.S index fe872debea..0943e356da 100644 --- a/src/cpu/qemu-x86/cache_as_ram_bootblock.S +++ b/src/cpu/qemu-x86/cache_as_ram_bootblock.S @@ -100,6 +100,9 @@ pages_done: pushl %eax #endif + /* Copy .data section content to Cache-As-Ram */ +#include + before_c_entry: call bootblock_c_entry_bist /* Never returns */ diff --git a/src/cpu/x86/copy_data_section.inc b/src/cpu/x86/copy_data_section.inc new file mode 100644 index 0000000000..dccb8d3975 --- /dev/null +++ b/src/cpu/x86/copy_data_section.inc @@ -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 */ -- cgit v1.2.3