From 35e27b34f5c9cbab2044a47bf2d6a025ccf7948e Mon Sep 17 00:00:00 2001 From: Raul E Rangel Date: Wed, 30 Jun 2021 14:39:29 -0600 Subject: 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 Change-Id: I98b9d4ce8290a1f08063176809e903e671663208 Reviewed-on: https://review.coreboot.org/c/coreboot/+/55987 Tested-by: build bot (Jenkins) Reviewed-by: Furquan Shaikh Reviewed-by: Karthik Ramasubramanian --- src/soc/amd/common/block/cpu/update_microcode.c | 48 ++++++++++++++++++------- 1 file changed, 36 insertions(+), 12 deletions(-) (limited to 'src/soc/amd/common') 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); } -- cgit v1.2.3