diff options
author | Jeremy Compostella <jeremy.compostella@intel.com> | 2023-08-30 15:42:09 -0700 |
---|---|---|
committer | Julius Werner <jwerner@chromium.org> | 2023-09-14 21:02:07 +0000 |
commit | b7832de0260b042c25bf8f53abcb32e20a29ae9c (patch) | |
tree | dea12cf2118d848e1681254d52fa26a15fc008b4 /src/include | |
parent | 79f2e1fc8b6192e96f99c05f71baeb77d4633d40 (diff) |
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>
Diffstat (limited to 'src/include')
-rw-r--r-- | src/include/rules.h | 12 | ||||
-rw-r--r-- | src/include/symbols.h | 5 |
2 files changed, 11 insertions, 6 deletions
diff --git a/src/include/rules.h b/src/include/rules.h index ae8118ebb4..02c36f2b25 100644 --- a/src/include/rules.h +++ b/src/include/rules.h @@ -274,16 +274,16 @@ #if ENV_X86 /* Indicates memory layout is determined with arch/x86/car.ld. */ #define ENV_CACHE_AS_RAM (ENV_ROMSTAGE_OR_BEFORE && !CONFIG(RESET_VECTOR_IN_RAM)) -/* No .data sections with execute-in-place from ROM. */ -#define ENV_HAS_DATA_SECTION !ENV_CACHE_AS_RAM #else -/* Both .data and .bss, sometimes SRAM not DRAM. */ -#define ENV_HAS_DATA_SECTION 1 #define ENV_CACHE_AS_RAM 0 #endif -/* Indicates if the stage uses the _bss region defined in arch/x86/car.ld */ -#define ENV_SEPARATE_BSS (ENV_CACHE_AS_RAM && (ENV_BOOTBLOCK || !CONFIG(NO_XIP_EARLY_STAGES))) +/* Indicates .data section support. */ +#define ENV_HAS_DATA_SECTION 1 + +/* Indicates if the stage uses the _data and _bss regions defined in + * arch/x86/car.ld */ +#define ENV_SEPARATE_DATA_AND_BSS (ENV_CACHE_AS_RAM && (ENV_BOOTBLOCK || !CONFIG(NO_XIP_EARLY_STAGES))) /* Currently rmodules, ramstage and smm have heap. */ #define ENV_HAS_HEAP_SECTION (ENV_RMODULE || ENV_RAMSTAGE || ENV_SMM) diff --git a/src/include/symbols.h b/src/include/symbols.h index a03af08463..5410798f06 100644 --- a/src/include/symbols.h +++ b/src/include/symbols.h @@ -50,6 +50,11 @@ DECLARE_REGION(heap) DECLARE_REGION(asan_shadow) #endif +#if ENV_SEPARATE_DATA_AND_BSS +DECLARE_REGION(data) +DECLARE_REGION(data_load) +#endif + /* Regions for execution units. */ DECLARE_REGION(payload) |