diff options
author | Raul E Rangel <rrangel@chromium.org> | 2021-06-30 14:39:29 -0600 |
---|---|---|
committer | Raul Rangel <rrangel@chromium.org> | 2021-07-02 23:12:34 +0000 |
commit | 35e27b34f5c9cbab2044a47bf2d6a025ccf7948e (patch) | |
tree | a2d8869f95533a778407f647769cf2923520b3e2 | |
parent | 9942af2b5be306260085289189cb34c8086de733 (diff) |
soc/amd/common/block/cpu: Cache the uCode to avoid multiple SPI reads
We are currently reading the uCode for each CPU. This is unnecessary
since the uCode never changes.
BUG=b:177909625
TEST=Boot guybrush and see "microcode: being updated to patch id" for
each CPU. I no longer see CBFS access for each CPU. This drops device
initialization time by 32 ms.
Also boot Ezkinil and verify microcode was also updated.
Signed-off-by: Raul E Rangel <rrangel@chromium.org>
Change-Id: I98b9d4ce8290a1f08063176809e903e671663208
Reviewed-on: https://review.coreboot.org/c/coreboot/+/55987
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
Reviewed-by: Karthik Ramasubramanian <kramasub@google.com>
-rw-r--r-- | src/soc/amd/common/block/cpu/update_microcode.c | 48 |
1 files changed, 36 insertions, 12 deletions
diff --git a/src/soc/amd/common/block/cpu/update_microcode.c b/src/soc/amd/common/block/cpu/update_microcode.c index 2ba180298c..2822d2f355 100644 --- a/src/soc/amd/common/block/cpu/update_microcode.c +++ b/src/soc/amd/common/block/cpu/update_microcode.c @@ -34,6 +34,8 @@ struct microcode { uint8_t m_patch_data[MPB_MAX_SIZE-MPB_DATA_OFFSET]; } __packed; +_Static_assert(sizeof(struct microcode) == MPB_MAX_SIZE, "microcode size is invalid"); + static void apply_microcode_patch(const struct microcode *m) { uint32_t new_patch_id; @@ -65,29 +67,51 @@ static uint16_t get_equivalent_processor_rev_id(void) return (uint16_t)((cpuid_family & 0xff0000) >> 8 | (cpuid_family & 0xff)); } -static void amd_update_microcode(const void *ucode, size_t ucode_len, - uint16_t equivalent_processor_rev_id) +static const struct microcode *find_microcode(const struct microcode *ucode, size_t ucode_len) { + uint16_t equivalent_processor_rev_id = get_equivalent_processor_rev_id(); const struct microcode *m; - for (m = (struct microcode *)ucode; - m < (struct microcode *)ucode + ucode_len/MPB_MAX_SIZE; m++) { + for (m = ucode; m < ucode + ucode_len / MPB_MAX_SIZE; m++) { if (m->processor_rev_id == equivalent_processor_rev_id) - apply_microcode_patch(m); + return m; } + + printk(BIOS_WARNING, "Failed to find microcode for processor rev: %hx.\n", + equivalent_processor_rev_id); + + return NULL; } void amd_update_microcode_from_cbfs(void) { - const void *ucode; + static struct microcode ucode_cache; + static bool cache_valid; + + struct microcode *ucode_list; + const struct microcode *matching_ucode; size_t ucode_len; - uint16_t equivalent_processor_rev_id = get_equivalent_processor_rev_id(); - ucode = cbfs_map("cpu_microcode_blob.bin", &ucode_len); - if (!ucode) { - printk(BIOS_WARNING, "cpu_microcode_blob.bin not found. Skipping updates.\n"); - return; + /* Cache the buffer so each CPU doesn't need to read the uCode from flash */ + if (!cache_valid) { + ucode_list = cbfs_map("cpu_microcode_blob.bin", &ucode_len); + if (!ucode_list) { + printk(BIOS_WARNING, "cpu_microcode_blob.bin not found. Skipping updates.\n"); + return; + } + + matching_ucode = find_microcode(ucode_list, ucode_len); + + if (!matching_ucode) { + cbfs_unmap(ucode_list); + return; + } + + ucode_cache = *matching_ucode; + cache_valid = true; + + cbfs_unmap(ucode_list); } - amd_update_microcode(ucode, ucode_len, equivalent_processor_rev_id); + apply_microcode_patch(&ucode_cache); } |