From ae05d095b36ac835a6b1a221e6858065e5486888 Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Tue, 8 May 2018 17:09:57 -0700 Subject: 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 Reviewed-on: https://review.coreboot.org/26182 Reviewed-by: Aaron Durbin Reviewed-by: Nico Huber Reviewed-by: Patrick Rudolph Tested-by: build bot (Jenkins) --- src/include/bootmem.h | 2 ++ src/lib/bootmem.c | 36 ++++++++++-------------------------- 2 files changed, 12 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/include/bootmem.h b/src/include/bootmem.h index 7503306167..0a960c992a 100644 --- a/src/include/bootmem.h +++ b/src/include/bootmem.h @@ -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 */ diff --git a/src/lib/bootmem.c b/src/lib/bootmem.c index fd9195aa96..90f4970d52 100644 --- a/src/lib/bootmem.c +++ b/src/lib/bootmem.c @@ -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) -- cgit v1.2.3