soc/amd/common/block/cpu/: Make ucode update more generic

Use the equivalent cpuid in the microcode header to name the update file
in cbfs. This allows the SOC to directly locate its microcode file when
there are multiple processor revisions.

TEST: Loaded a chausie with sabrina, cezanne, and picasso microcode
files and booted. Verified that only the sabrina microcode file was
successfully loaded

Change-Id: I84a2480cf8274d53ffdab7864135c1bf001241e6
Signed-off-by: Fred Reitberger <reitbergerfred@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/63589
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
This commit is contained in:
Fred Reitberger 2022-04-12 13:44:34 -04:00 committed by Felix Held
parent 749f5bd333
commit 96f7b96866
6 changed files with 50 additions and 46 deletions

View File

@ -300,6 +300,6 @@ apu/amdfw_b-position := $(AMD_FW_AB_POSITION)
apu/amdfw_b-type := raw
endif
cpu_microcode_bins += $(wildcard ${FIRMWARE_LOCATION}/UcodePatch_*.bin)
amd_microcode_bins += $(wildcard ${FIRMWARE_LOCATION}/UcodePatch_*.bin)
endif # ($(CONFIG_SOC_AMD_CEZANNE),y)

View File

@ -73,7 +73,6 @@ config SOC_AMD_COMMON_BLOCK_TSC_FAM17H_19H
config SOC_AMD_COMMON_BLOCK_UCODE
bool
select SUPPORT_CPU_UCODE_IN_CBFS
help
Builds in support for loading uCode.

View File

@ -1,2 +1,18 @@
subdirs-y += ./*
ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_UCODE) += update_microcode.c
ifeq ($(CONFIG_SOC_AMD_COMMON_BLOCK_UCODE),y)
define add-ucode-as-cbfs
cbfs-files-y += cpu_microcode_$(2).bin
cpu_microcode_$(2).bin-file := $(1)
cpu_microcode_$(2).bin-type := microcode
ifeq ($(CONFIG_SOC_AMD_COMMON_BLOCK_LPC_SPI_DMA),y)
cpu_microcode_$(2).bin-align := 64
else
cpu_microcode_$(2).bin-align := 16
endif
endef
$(foreach ucode,$(amd_microcode_bins),$(eval $(call add-ucode-as-cbfs,$(ucode),$(shell hexdump -n 2 -s 0x18 -e '"%x"' $(ucode)))))
endif

View File

@ -1,22 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <arch/cpu.h>
#include <stdint.h>
#include <types.h>
#include <cpu/amd/microcode.h>
#include <commonlib/helpers.h>
#include <console/console.h>
#include <cpu/x86/msr.h>
#include <cpu/amd/msr.h>
#include <cbfs.h>
#include <stdio.h>
#include <timestamp.h>
#define CPU_MICROCODE_BLOB_NAME "cpu_microcode_blob.bin"
_Static_assert(CONFIG_SOC_AMD_COMMON_BLOCK_UCODE_SIZE > 0,
"SOC_AMD_COMMON_BLOCK_UCODE_SIZE is not set");
#define MPB_MAX_SIZE CONFIG_SOC_AMD_COMMON_BLOCK_UCODE_SIZE
#define MPB_DATA_OFFSET 32
#define CPU_MICROCODE_BLOB_NAME "cpu_microcode_XXXX.bin"
#define CPU_MICROCODE_BLOB_FORMAT "cpu_microcode_%04x.bin"
struct microcode {
uint32_t date_code;
@ -34,12 +30,8 @@ struct microcode {
uint8_t chipset2_rev_id;
uint8_t reserved2[4];
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;
@ -50,18 +42,17 @@ static void apply_microcode_patch(const struct microcode *m)
wrmsr(MSR_PATCH_LOADER, msr);
printk(BIOS_DEBUG, "microcode: patch id to apply = 0x%08x\n",
m->patch_id);
printk(BIOS_DEBUG, "microcode: patch id to apply = 0x%08x\n", m->patch_id);
msr = rdmsr(IA32_BIOS_SIGN_ID);
new_patch_id = msr.lo;
if (new_patch_id == m->patch_id)
printk(BIOS_INFO, "microcode: being updated to patch id = 0x%08x succeeded\n",
new_patch_id);
new_patch_id);
else
printk(BIOS_ERR, "microcode: being updated to patch id = 0x%08x failed\n",
new_patch_id);
new_patch_id);
}
static uint16_t get_equivalent_processor_rev_id(void)
@ -71,15 +62,11 @@ static uint16_t get_equivalent_processor_rev_id(void)
return (uint16_t)((cpuid_family & 0xff0000) >> 8 | (cpuid_family & 0xff));
}
static const struct microcode *find_microcode(const struct microcode *ucode, size_t ucode_len)
static const struct microcode *find_microcode(const struct microcode *ucode,
uint16_t equivalent_processor_rev_id)
{
uint16_t equivalent_processor_rev_id = get_equivalent_processor_rev_id();
const struct microcode *m;
for (m = ucode; m < ucode + ucode_len / MPB_MAX_SIZE; m++) {
if (m->processor_rev_id == equivalent_processor_rev_id)
return m;
}
if (ucode->processor_rev_id == equivalent_processor_rev_id)
return ucode;
printk(BIOS_WARNING, "Failed to find microcode for processor rev: %hx.\n",
equivalent_processor_rev_id);
@ -89,39 +76,37 @@ static const struct microcode *find_microcode(const struct microcode *ucode, siz
void amd_update_microcode_from_cbfs(void)
{
static struct microcode ucode_cache;
static const struct microcode *ucode_cache;
static bool cache_valid;
struct microcode *ucode_list;
const struct microcode *matching_ucode;
size_t ucode_len;
struct microcode *ucode;
char name[] = CPU_MICROCODE_BLOB_NAME;
uint16_t equivalent_processor_rev_id;
/* Cache the buffer so each CPU doesn't need to read the uCode from flash */
/* Note that this code assumes all cores are the same */
if (!cache_valid) {
timestamp_add_now(TS_READ_UCODE_START);
ucode_list = cbfs_map(CPU_MICROCODE_BLOB_NAME, &ucode_len);
if (!ucode_list) {
printk(BIOS_WARNING,
CPU_MICROCODE_BLOB_NAME " not found. Skipping updates.\n");
equivalent_processor_rev_id = get_equivalent_processor_rev_id();
snprintf(name, sizeof(name), CPU_MICROCODE_BLOB_FORMAT, equivalent_processor_rev_id);
ucode = cbfs_map(name, NULL);
if (!ucode) {
printk(BIOS_WARNING, "%s not found. Skipping updates.\n", name);
return;
}
matching_ucode = find_microcode(ucode_list, ucode_len);
ucode_cache = find_microcode(ucode, equivalent_processor_rev_id);
if (!matching_ucode) {
cbfs_unmap(ucode_list);
if (!ucode_cache) {
cbfs_unmap(ucode);
return;
}
ucode_cache = *matching_ucode;
cache_valid = true;
cbfs_unmap(ucode_list);
timestamp_add_now(TS_READ_UCODE_END);
}
apply_microcode_patch(&ucode_cache);
apply_microcode_patch(ucode_cache);
}
void preload_microcode(void)
@ -129,6 +114,10 @@ void preload_microcode(void)
if (!CONFIG(CBFS_PRELOAD))
return;
printk(BIOS_DEBUG, "Preloading microcode %s\n", CPU_MICROCODE_BLOB_NAME);
cbfs_preload(CPU_MICROCODE_BLOB_NAME);
char name[] = CPU_MICROCODE_BLOB_NAME;
uint16_t equivalent_processor_rev_id = get_equivalent_processor_rev_id();
snprintf(name, sizeof(name), CPU_MICROCODE_BLOB_FORMAT, equivalent_processor_rev_id);
printk(BIOS_DEBUG, "Preloading microcode %s\n", name);
cbfs_preload(name);
}

View File

@ -292,6 +292,6 @@ apu/amdfw_b-position := $(AMD_FW_AB_POSITION)
apu/amdfw_b-type := raw
endif
cpu_microcode_bins += $(wildcard ${FIRMWARE_LOCATION}/UcodePatch_*.bin)
amd_microcode_bins := $(wildcard ${FIRMWARE_LOCATION}/UcodePatch_*.bin)
endif # ($(CONFIG_SOC_AMD_PICASSO),y)

View File

@ -291,6 +291,6 @@ apu/amdfw_b-position := $(AMD_FW_AB_POSITION)
apu/amdfw_b-type := raw
endif
cpu_microcode_bins += $(wildcard ${FIRMWARE_LOCATION}/UcodePatch_*.bin)
amd_microcode_bins += $(wildcard ${FIRMWARE_LOCATION}/UcodePatch_*.bin)
endif # ($(CONFIG_SOC_AMD_SABRINA),y)