Attention is currently required from: Jason Glenesk, Marshall Dawson, Felix Held. Raul Rangel has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/56232 )
Change subject: soc/amd/common/apob: Add support for asynchronously reading APOB ......................................................................
soc/amd/common/apob: Add support for asynchronously reading APOB
This CL adds a method that can starts the processes of reading the APOB from SPI. It does require more RAM in ramstage since we no longer mmap the buffer in the async happy path. This will allow us to reduce our boot time by 10ms.
BUG=b:179699789 TEST=With this and the patches above I can see a 10 ms reduction in boot time on guybrush.
Signed-off-by: Raul E Rangel rrangel@chromium.org Change-Id: I930d58b76eb4558bc4f48ed928c4d6538fefb1e5 --- M src/soc/amd/common/block/apob/apob_cache.c 1 file changed, 62 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/32/56232/1
diff --git a/src/soc/amd/common/block/apob/apob_cache.c b/src/soc/amd/common/block/apob/apob_cache.c index c41627b..ecb7ea5 100644 --- a/src/soc/amd/common/block/apob/apob_cache.c +++ b/src/soc/amd/common/block/apob/apob_cache.c @@ -7,10 +7,13 @@ #include <bootstate.h> #include <commonlib/region.h> #include <console/console.h> +#include <delay.h> #include <fmap.h> #include <spi_flash.h> #include <stdint.h> #include <string.h> +#include <thread.h> +#include <timer.h> #include <timestamp.h>
#define DEFAULT_MRC_CACHE "RW_MRC_CACHE" @@ -72,11 +75,65 @@ return 0; }
+struct apob_thread_context { + uint8_t buffer[DEFAULT_MRC_CACHE_SIZE] __attribute__((aligned(64))); + struct thread_handle handle; + struct region_device apob_rdev; +} global_apob_thread; + +static enum cb_err apob_thread_entry(void *arg) +{ + ssize_t size; + struct apob_thread_context *thread = arg; + + printk(BIOS_ERR, "APOB thread running\n"); + size = rdev_readat(&thread->apob_rdev, thread->buffer, 0, + region_device_sz(&thread->apob_rdev)); + + if (size == region_device_sz(&thread->apob_rdev)) + return CB_SUCCESS; + + return CB_ERR; +} + +static void start_apob_cache_read(void *arg) +{ + struct region region; + struct apob_thread_context *thread = arg; + + /* We don't perform any comparison on S3 resume */ + if (acpi_is_wakeup_s3()) + return; + + if (get_nv_region(®ion) != 0) + return; + + if (boot_device_ro_subregion(®ion, &thread->apob_rdev) < 0) { + printk(BIOS_ERR, "Failed boot_device_ro_subregion\n"); + return; + } + + assert(ARRAY_SIZE(thread->buffer) == region_device_sz(&thread->apob_rdev)); + + printk(BIOS_INFO, "Starting APOB preload\n"); + if (thread_run_until(&thread->handle, apob_thread_entry, thread, BS_PAYLOAD_LOAD, + BS_ON_ENTRY)) + printk(BIOS_ERR, "Failed to start APOB preload thread\n"); +} + static void *get_apob_from_nv_region(struct region *region) { struct region_device read_rdev; struct apob_base_header apob_header;
+ if (wait_for_thread(&global_apob_thread.handle) == CB_SUCCESS) { + if (apob_header_valid((struct apob_base_header *)&global_apob_thread.buffer, + "ROM (Cached)")) + return global_apob_thread.buffer; + else + return NULL; + } + if (boot_device_ro_subregion(region, &read_rdev) < 0) { printk(BIOS_ERR, "Failed boot_device_ro_subregion\n"); return NULL; @@ -184,4 +241,9 @@ */ return get_apob_nv_address(); } + +#if CONFIG(COOP_MULTITASKING) +BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, start_apob_cache_read, &global_apob_thread); +#endif + BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, soc_update_apob_cache, NULL);