When caching the ramstage for suspend/resume, we copy the entire image as it resides in RAM. The last part of that, CONFIG_HEAP_SIZE bytes, is the heap that will be reinitialized when the ramstage is started again. As such, copying doesn't make sense and complicates HEAP_SIZE configuration (because it needs to fit the space-constrained cache location) and costs time and space. Therefore, skip the heap. Side notes: - When building with ASAN, program.ld indicates that it will allocate some more space after the heap. This is not a problem, we just copy an ASAN-sized copy of the heap. - Heap use is managed in src/lib/malloc with statically allocated variables. Because ramstage is cached before it's executed, these values will be reset to their compile-time default values, too. Change-Id: I6553dc8b758196f2476af2e692c0421d0fa2b98e Signed-off-by: Patrick Georgi <patrick@coreboot.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/79525 Reviewed-by: Martin L Roth <gaumless@gmail.com> Reviewed-by: Paul Menzel <paulepanter@mailbox.org> Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
171 lines
3.8 KiB
Text
171 lines
3.8 KiB
Text
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
|
|
#include <memlayout.h>
|
|
|
|
/* This file is included inside a SECTIONS block */
|
|
|
|
/* First we place the code and read only data (typically const declared).
|
|
* This could theoretically be placed in rom.
|
|
* The '.' in '.text . : {' is actually significant to prevent missing some
|
|
* SoC's entry points due to artificial alignment restrictions, see
|
|
* https://sourceware.org/binutils/docs/ld/Output-Section-Address.html
|
|
*/
|
|
.text . : {
|
|
_program = .;
|
|
_text = .;
|
|
#if !(ENV_X86 && ENV_BOOTBLOCK)
|
|
*(.init._start);
|
|
*(.init);
|
|
*(.init.*);
|
|
#endif
|
|
*(.text._start);
|
|
*(.text.stage_entry);
|
|
KEEP(*(.metadata_hash_anchor));
|
|
*(.text);
|
|
*(.text.*);
|
|
|
|
#if ENV_HAS_CBMEM
|
|
. = ALIGN(ARCH_POINTER_ALIGN_SIZE);
|
|
_cbmem_init_hooks = .;
|
|
KEEP(*(.rodata.cbmem_init_hooks_early));
|
|
KEEP(*(.rodata.cbmem_init_hooks));
|
|
_ecbmem_init_hooks = .;
|
|
RECORD_SIZE(cbmem_init_hooks)
|
|
#endif
|
|
|
|
. = ALIGN(ARCH_POINTER_ALIGN_SIZE);
|
|
_rsbe_init_begin = .;
|
|
KEEP(*(.rsbe_init));
|
|
_ersbe_init_begin = .;
|
|
RECORD_SIZE(rsbe_init_begin)
|
|
|
|
#if ENV_RAMSTAGE
|
|
. = ALIGN(ARCH_POINTER_ALIGN_SIZE);
|
|
_pci_drivers = .;
|
|
KEEP(*(.rodata.pci_driver));
|
|
_epci_drivers = .;
|
|
RECORD_SIZE(pci_drivers)
|
|
. = ALIGN(ARCH_POINTER_ALIGN_SIZE);
|
|
_cpu_drivers = .;
|
|
KEEP(*(.rodata.cpu_driver));
|
|
_ecpu_drivers = .;
|
|
RECORD_SIZE(cpu_drivers)
|
|
#endif
|
|
|
|
. = ALIGN(ARCH_POINTER_ALIGN_SIZE);
|
|
*(.rodata);
|
|
*(.rodata.*);
|
|
. = ALIGN(ARCH_POINTER_ALIGN_SIZE);
|
|
_etext = .;
|
|
RECORD_SIZE(text)
|
|
} : to_load
|
|
|
|
#if ENV_RAMSTAGE && (CONFIG(COVERAGE) || CONFIG(ASAN_IN_RAMSTAGE))
|
|
.ctors . : {
|
|
. = ALIGN(0x100);
|
|
__CTOR_LIST__ = .;
|
|
KEEP(*(.ctors));
|
|
LONG(0);
|
|
LONG(0);
|
|
__CTOR_END__ = .;
|
|
}
|
|
#endif
|
|
|
|
/* Include data, bss, and heap in that order. Not defined for all stages. */
|
|
#if !ENV_SEPARATE_DATA_AND_BSS
|
|
.data . : {
|
|
. = ALIGN(ARCH_CACHELINE_ALIGN_SIZE);
|
|
_data = .;
|
|
|
|
/*
|
|
* The postcar phase uses a stack value that is located in the relocatable
|
|
* module section. While the postcar stage could be linked like smm and
|
|
* other rmodules the postcar stage needs similar semantics of the more
|
|
* traditional stages in the coreboot infrastructure. Therefore it's easier
|
|
* to specialize this case.
|
|
*/
|
|
#if ENV_RMODULE || ENV_POSTCAR
|
|
_rmodule_params = .;
|
|
KEEP(*(.module_parameters));
|
|
_ermodule_params = .;
|
|
RECORD_SIZE(rmodule_params)
|
|
#endif
|
|
|
|
*(.data);
|
|
*(.data.*);
|
|
*(.sdata);
|
|
*(.sdata.*);
|
|
|
|
#if ENV_ROMSTAGE_OR_BEFORE
|
|
PROVIDE(_preram_cbmem_console = .);
|
|
PROVIDE(_epreram_cbmem_console = _preram_cbmem_console);
|
|
PROVIDE(_preram_cbmem_console_size = ABSOLUTE(0));
|
|
#elif ENV_RAMSTAGE
|
|
. = ALIGN(ARCH_POINTER_ALIGN_SIZE);
|
|
_bs_init_begin = .;
|
|
KEEP(*(.bs_init));
|
|
LONG(0);
|
|
LONG(0);
|
|
_ebs_init_begin = .;
|
|
RECORD_SIZE(bs_init_begin)
|
|
#endif
|
|
|
|
. = ALIGN(ARCH_POINTER_ALIGN_SIZE);
|
|
_edata = .;
|
|
RECORD_SIZE(data)
|
|
}
|
|
#endif
|
|
|
|
#if !ENV_SEPARATE_DATA_AND_BSS
|
|
.bss . : {
|
|
. = ALIGN(ARCH_POINTER_ALIGN_SIZE);
|
|
_bss = .;
|
|
*(.bss)
|
|
*(.bss.*)
|
|
*(.sbss)
|
|
*(.sbss.*)
|
|
. = ALIGN(ARCH_POINTER_ALIGN_SIZE);
|
|
_ebss = .;
|
|
RECORD_SIZE(bss)
|
|
}
|
|
#endif
|
|
|
|
#if ENV_HAS_HEAP_SECTION
|
|
.heap . : {
|
|
. = ALIGN(ARCH_POINTER_ALIGN_SIZE);
|
|
_heap = .;
|
|
. += (ENV_RMODULE ? __heap_size : CONFIG_HEAP_SIZE);
|
|
. = ALIGN(ARCH_POINTER_ALIGN_SIZE);
|
|
_eheap = .;
|
|
RECORD_SIZE(heap)
|
|
}
|
|
#endif
|
|
|
|
#if ENV_RAMSTAGE && CONFIG(ASAN_IN_RAMSTAGE)
|
|
_shadow_size = (_eheap - _data) >> 3;
|
|
REGION(asan_shadow, ., _shadow_size, ARCH_POINTER_ALIGN_SIZE)
|
|
#endif
|
|
|
|
_eprogram = .;
|
|
RECORD_SIZE(program)
|
|
|
|
/* The stage cache drops CONFIG_HEAP_SIZE bytes from the end of the in-memory
|
|
image of the ramstage, so ensure that when moving that many bytes backwards
|
|
from the program end, we're in the heap (or later), in some region that
|
|
doesn't contain initialized code or data. */
|
|
#if ENV_RAMSTAGE
|
|
_bogus = ASSERT(_eprogram - CONFIG_HEAP_SIZE >= _heap,
|
|
"HEAP_SIZE and heap misaligned");
|
|
#endif
|
|
|
|
/* Discard the sections we don't need/want */
|
|
|
|
zeroptr = 0;
|
|
|
|
/DISCARD/ : {
|
|
*(.comment)
|
|
*(.comment.*)
|
|
*(.note)
|
|
*(.note.*)
|
|
*(.eh_frame);
|
|
}
|