summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);
}