diff options
author | Aaron Durbin <adurbin@chromium.org> | 2017-10-17 14:33:05 -0600 |
---|---|---|
committer | Aaron Durbin <adurbin@chromium.org> | 2017-10-18 19:56:21 +0000 |
commit | f46a9a0d3ad3157de3e354b4314fe9c5c3b69dd2 (patch) | |
tree | 44a006b52578155e632db4b7304cb61bb486e850 /src/arch | |
parent | c672043766dabc2bbaebc770fb20e0f63e5eedcb (diff) |
arch/x86: restore forwarding table on resume for EARLY_EBDA_INIT
In commit c06a3f72 (arch/x86: initialize EBDA in S3 and S0/S5 path)
the BDA and EBDA are wiped in the resume path. However, the coreboot
table forwarding entry wasn't taken into account so that was wiped
which resulted in cbmem not working on the resume path. Fix this
by stashing the forwarding table in cbmem and restoring it on
the resume path.
Change-Id: I142503535a78635fbb1c698fc7d032c1a2921813
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: https://review.coreboot.org/22078
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Matt DeVillier <matt.devillier@gmail.com>
Reviewed-by: Furquan Shaikh <furquan@google.com>
Diffstat (limited to 'src/arch')
-rw-r--r-- | src/arch/x86/tables.c | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/src/arch/x86/tables.c b/src/arch/x86/tables.c index 7b06550cc5..fc5870d9f4 100644 --- a/src/arch/x86/tables.c +++ b/src/arch/x86/tables.c @@ -18,6 +18,7 @@ #include <console/console.h> #include <cpu/cpu.h> #include <bootmem.h> +#include <bootstate.h> #include <boot/tables.h> #include <boot/coreboot_tables.h> #include <arch/pirq_routing.h> @@ -194,7 +195,45 @@ static unsigned long write_smbios_table(unsigned long rom_table_end) * in case our data structures grow beyond 0x400. Only GDT * and the coreboot table use low_tables. */ -static uintptr_t forwarding_table = 0x500; +#define FORWARDING_TABLE_ADDR ((uintptr_t)0x500) +static uintptr_t forwarding_table = FORWARDING_TABLE_ADDR; + +/* + * For EARLY_EBDA_INIT the BDA area will be wiped on the resume path which + * has the forwarding table entry. Therefore, when tables are written an + * entry is placed in cbmem that can be restored on OS resume to the proper + * location. + */ +static void stash_forwarding_table(uintptr_t addr, size_t sz) +{ + void *cbmem_addr = cbmem_add(CBMEM_ID_CBTABLE_FWD, sz); + + if (cbmem_addr == NULL) { + printk(BIOS_ERR, "Unable to allocate CBMEM forwarding entry.\n"); + return; + } + + memcpy(cbmem_addr, (void *)addr, sz); +} + +#if IS_ENABLED(CONFIG_EARLY_EBDA_INIT) +static void restore_forwarding_table(void *dest) +{ + const struct cbmem_entry *fwd_entry; + + fwd_entry = cbmem_entry_find(CBMEM_ID_CBTABLE_FWD); + + if (fwd_entry == NULL) { + printk(BIOS_ERR, "Unable to restore CBMEM forwarding entry.\n"); + return; + } + + memcpy(dest, cbmem_entry_start(fwd_entry), cbmem_entry_size(fwd_entry)); +} + +BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, + restore_forwarding_table, (void *)FORWARDING_TABLE_ADDR); +#endif void arch_write_tables(uintptr_t coreboot_table) { @@ -217,6 +256,9 @@ void arch_write_tables(uintptr_t coreboot_table) sz = write_coreboot_forwarding_table(forwarding_table, coreboot_table); + if (IS_ENABLED(CONFIG_EARLY_EBDA_INIT)) + stash_forwarding_table(forwarding_table, sz); + forwarding_table += sz; /* Align up to page boundary for historical consistency. */ forwarding_table = ALIGN_UP(forwarding_table, 4*KiB); |