summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaul E Rangel <rrangel@chromium.org>2021-06-30 14:39:29 -0600
committerRaul Rangel <rrangel@chromium.org>2021-07-02 23:12:34 +0000
commit35e27b34f5c9cbab2044a47bf2d6a025ccf7948e (patch)
treea2d8869f95533a778407f647769cf2923520b3e2
parent9942af2b5be306260085289189cb34c8086de733 (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.c48
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);
}