bootmem: Keep OS memory map separate from the start

The patch series ending in 64049be (lib/bootmem: Add method to walk OS
POV memory tables) expanded the bootmem framework to also keep track of
memory regions that are only relevant while coreboot is still executing,
such as the ramstage code and data. Mixing this into the exsting bootmem
ranges has already caused an issue on CONFIG_RELOCATEABLE_RAMSTAGE
boards, because the ramstage code in CBMEM is marked as BM_RAMSTAGE
which ends up getting translated back to LB_RAM in the OS tables. This
was fixed in 1ecec5f (lib/bootmem: ensure ramstage memory isn't given to
OS) for this specific case, but unfortunately Arm boards can have a
similar problem where their stack space is sometimes located in an SRAM
region that should not be made available as RAM to the OS.

Since both the resources made available to the OS and the regions
reserved for coreboot can be different for each platform, we should find
a generic solution to this rather than trying to deal with each issue
individually. This patch solves the problem by keeping the OS point of
view and the coreboot-specific ranges separate from the start, rather
than cloning it out later. Ranges only relevant to the coreboot view
will never touch the OS-specific layout, to avoid the problem of losing
information about the original memory type of the underlying region that
needs to be restored for the OS view. This both supersedes the
RELOCATABLE_RAMSTAGE fix and resolves the problems on Arm boards.

Change-Id: I7bb018456b58ad9b0cfb0b8da8c26b791b487fbb
Signed-off-by: Julius Werner <jwerner@chromium.org>
Reviewed-on: https://review.coreboot.org/26182
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-by: Nico Huber <nico.h@gmx.de>
Reviewed-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Julius Werner 2018-05-08 17:09:57 -07:00
parent 40e6d2ebbd
commit ae05d095b3
2 changed files with 12 additions and 26 deletions

View File

@ -38,6 +38,8 @@ enum bootmem_type {
BM_MEM_UNUSABLE, /* Unusable address space */
BM_MEM_VENDOR_RSVD, /* Vendor Reserved */
BM_MEM_TABLE, /* Ram configuration tables are kept in */
/* Tags below this point are ignored for the OS table. */
BM_MEM_OS_CUTOFF = BM_MEM_TABLE,
BM_MEM_RAMSTAGE,
BM_MEM_PAYLOAD,
BM_MEM_LAST, /* Last entry in this list */

View File

@ -67,17 +67,6 @@ static uint32_t bootmem_to_lb_tag(const enum bootmem_type tag)
}
}
static void bootmem_convert_ranges(void)
{
/**
* Convert BM_MEM_RAMSTAGE and BM_MEM_PAYLOAD to BM_MEM_RAM and
* merge ranges. The payload doesn't care about memory used by firmware.
*/
memranges_clone(&bootmem_os, &bootmem);
memranges_update_tag(&bootmem_os, BM_MEM_RAMSTAGE, BM_MEM_RAM);
memranges_update_tag(&bootmem_os, BM_MEM_PAYLOAD, BM_MEM_RAM);
}
static void bootmem_init(void)
{
const unsigned long cacheable = IORESOURCE_CACHEABLE;
@ -93,24 +82,16 @@ static void bootmem_init(void)
*/
memranges_init(bm, cacheable, cacheable, BM_MEM_RAM);
memranges_add_resources(bm, reserved, reserved, BM_MEM_RESERVED);
memranges_clone(&bootmem_os, bm);
/* Add memory used by CBMEM. */
cbmem_add_bootmem();
/* Add memory used by coreboot -- only if RELOCATABLE_RAMSTAGE is not
* used. When RELOCATABLE_RAMSTAGE is employed ramstage lives in cbmem
* so cbmem_add_bootmem() takes care of that memory region. */
if (!IS_ENABLED(CONFIG_RELOCATABLE_RAMSTAGE)) {
bootmem_add_range((uintptr_t)_stack, _stack_size,
BM_MEM_RAMSTAGE);
bootmem_add_range((uintptr_t)_program, _program_size,
BM_MEM_RAMSTAGE);
}
bootmem_add_range((uintptr_t)_stack, _stack_size, BM_MEM_RAMSTAGE);
bootmem_add_range((uintptr_t)_program, _program_size, BM_MEM_RAMSTAGE);
bootmem_arch_add_ranges();
bootmem_platform_add_ranges();
bootmem_convert_ranges();
}
void bootmem_add_range(uint64_t start, uint64_t size,
@ -118,10 +99,13 @@ void bootmem_add_range(uint64_t start, uint64_t size,
{
assert(tag > BM_MEM_FIRST && tag < BM_MEM_LAST);
assert(bootmem_is_initialized());
assert(!bootmem_memory_table_written() || tag == BM_MEM_RAMSTAGE ||
tag == BM_MEM_PAYLOAD);
memranges_insert(&bootmem, start, size, tag);
if (tag <= BM_MEM_OS_CUTOFF) {
/* Can't change OS tables anymore after they are written out. */
assert(!bootmem_memory_table_written());
memranges_insert(&bootmem_os, start, size, tag);
};
}
void bootmem_write_memory_table(struct lb_memory *mem)
@ -159,8 +143,8 @@ static const struct range_strings type_strings[] = {
{ BM_MEM_UNUSABLE, "UNUSABLE" },
{ BM_MEM_VENDOR_RSVD, "VENDOR RESERVED" },
{ BM_MEM_TABLE, "CONFIGURATION TABLES" },
{ BM_MEM_RAMSTAGE, "RAM, RAMSTAGE" },
{ BM_MEM_PAYLOAD, "RAM, PAYLOAD" },
{ BM_MEM_RAMSTAGE, "RAMSTAGE" },
{ BM_MEM_PAYLOAD, "PAYLOAD" },
};
static const char *bootmem_range_string(const enum bootmem_type tag)