summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRaul E Rangel <rrangel@chromium.org>2021-06-25 11:15:41 -0600
committerRaul Rangel <rrangel@chromium.org>2021-07-18 15:17:17 +0000
commitfca58334c8e08427ff9f87e5d121f487d7f45484 (patch)
treeae32ea87ddc66689bb7bdd3e18f023c94be944c5 /src
parentce63dc4daab539b3c4b6d860145f1541854e6d3d (diff)
downloadcoreboot-fca58334c8e08427ff9f87e5d121f487d7f45484.tar.gz
coreboot-fca58334c8e08427ff9f87e5d121f487d7f45484.tar.bz2
coreboot-fca58334c8e08427ff9f87e5d121f487d7f45484.zip
soc/amd/common/apob: Add support for asynchronously reading APOB_NV
This CL adds a method that can start the processes of reading the APOB from SPI. It does require more RAM in ramstage since we no longer mmap the buffer in the happy path. This will allow us to reduce our boot time by ~10ms. The SoC code will need to be updated to call start_apob_cache_read at a point where it makes sense. 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 Reviewed-on: https://review.coreboot.org/c/coreboot/+/56232 Reviewed-by: Karthik Ramasubramanian <kramasub@google.com> Reviewed-by: Paul Menzel <paulepanter@mailbox.org> Reviewed-by: Furquan Shaikh <furquan@google.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src')
-rw-r--r--src/soc/amd/common/block/apob/apob_cache.c59
-rw-r--r--src/soc/amd/common/block/include/amdblocks/apob_cache.h2
2 files changed, 60 insertions, 1 deletions
diff --git a/src/soc/amd/common/block/apob/apob_cache.c b/src/soc/amd/common/block/apob/apob_cache.c
index c2c4908a31b5..f61785dd8ca5 100644
--- a/src/soc/amd/common/block/apob/apob_cache.c
+++ b/src/soc/amd/common/block/apob/apob_cache.c
@@ -5,12 +5,16 @@
#include <assert.h>
#include <boot_device.h>
#include <bootstate.h>
+#include <commonlib/helpers.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,6 +76,50 @@ static int get_nv_rdev(struct region_device *r)
return 0;
}
+static 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_DEBUG, "APOB thread running\n");
+ size = rdev_readat(&thread->apob_rdev, thread->buffer, 0,
+ region_device_sz(&thread->apob_rdev));
+
+ printk(BIOS_DEBUG, "APOB thread done\n");
+
+ if (size == region_device_sz(&thread->apob_rdev))
+ return CB_SUCCESS;
+
+ return CB_ERR;
+}
+
+void start_apob_cache_read(void)
+{
+ struct apob_thread_context *thread = &global_apob_thread;
+
+ if (!CONFIG(COOP_MULTITASKING))
+ return;
+
+ /* We don't perform any comparison on S3 resume */
+ if (acpi_is_wakeup_s3())
+ return;
+
+ if (get_nv_rdev(&thread->apob_rdev) != 0)
+ return;
+
+ assert(ARRAY_SIZE(thread->buffer) == region_device_sz(&thread->apob_rdev));
+
+ printk(BIOS_DEBUG, "Starting APOB preload\n");
+ if (thread_run(&thread->handle, apob_thread_entry, thread))
+ printk(BIOS_ERR, "Failed to start APOB preload thread\n");
+}
+
static void *get_apob_from_nv_rdev(struct region_device *read_rdev)
{
struct apob_base_header apob_header;
@@ -111,7 +159,11 @@ static void soc_update_apob_cache(void *unused)
timestamp_add_now(TS_AMD_APOB_READ_START);
- apob_rom = get_apob_from_nv_rdev(&read_rdev);
+ if (CONFIG(COOP_MULTITASKING) && thread_join(&global_apob_thread.handle) == CB_SUCCESS)
+ apob_rom = (struct apob_base_header *)global_apob_thread.buffer;
+ else
+ apob_rom = get_apob_from_nv_rdev(&read_rdev);
+
if (apob_rom == NULL) {
update_needed = true;
} else if (memcmp(apob_src_ram, apob_rom, apob_src_ram->size)) {
@@ -177,4 +229,9 @@ void *soc_fill_apob_cache(void)
*/
return get_apob_nv_address();
}
+
+/*
+ * BS_POST_DEVICE was chosen because this gives start_apob_cache_read plenty of time to read
+ * the APOB from SPI.
+ */
BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, soc_update_apob_cache, NULL);
diff --git a/src/soc/amd/common/block/include/amdblocks/apob_cache.h b/src/soc/amd/common/block/include/amdblocks/apob_cache.h
index 79228e5de25e..e91720fa61f8 100644
--- a/src/soc/amd/common/block/include/amdblocks/apob_cache.h
+++ b/src/soc/amd/common/block/include/amdblocks/apob_cache.h
@@ -3,6 +3,8 @@
#ifndef AMD_BLOCK_APOB_CACHE_H
#define AMD_BLOCK_APOB_CACHE_H
+/* Start loading the APOB as soon as possible so it is ready by the time we need it. */
+void start_apob_cache_read(void);
void *soc_fill_apob_cache(void);
#endif /* AMD_BLOCK_APOB_CACHE_H */