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>
This commit is contained in:
parent
9942af2b5b
commit
35e27b34f5
|
@ -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;
|
||||
size_t ucode_len;
|
||||
uint16_t equivalent_processor_rev_id = get_equivalent_processor_rev_id();
|
||||
static struct microcode ucode_cache;
|
||||
static bool cache_valid;
|
||||
|
||||
ucode = cbfs_map("cpu_microcode_blob.bin", &ucode_len);
|
||||
if (!ucode) {
|
||||
printk(BIOS_WARNING, "cpu_microcode_blob.bin not found. Skipping updates.\n");
|
||||
return;
|
||||
struct microcode *ucode_list;
|
||||
const struct microcode *matching_ucode;
|
||||
size_t ucode_len;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue