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:
parent
749f5bd333
commit
96f7b96866
|
@ -300,6 +300,6 @@ apu/amdfw_b-position := $(AMD_FW_AB_POSITION)
|
||||||
apu/amdfw_b-type := raw
|
apu/amdfw_b-type := raw
|
||||||
endif
|
endif
|
||||||
|
|
||||||
cpu_microcode_bins += $(wildcard ${FIRMWARE_LOCATION}/UcodePatch_*.bin)
|
amd_microcode_bins += $(wildcard ${FIRMWARE_LOCATION}/UcodePatch_*.bin)
|
||||||
|
|
||||||
endif # ($(CONFIG_SOC_AMD_CEZANNE),y)
|
endif # ($(CONFIG_SOC_AMD_CEZANNE),y)
|
||||||
|
|
|
@ -73,7 +73,6 @@ config SOC_AMD_COMMON_BLOCK_TSC_FAM17H_19H
|
||||||
|
|
||||||
config SOC_AMD_COMMON_BLOCK_UCODE
|
config SOC_AMD_COMMON_BLOCK_UCODE
|
||||||
bool
|
bool
|
||||||
select SUPPORT_CPU_UCODE_IN_CBFS
|
|
||||||
help
|
help
|
||||||
Builds in support for loading uCode.
|
Builds in support for loading uCode.
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,18 @@
|
||||||
subdirs-y += ./*
|
subdirs-y += ./*
|
||||||
ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_UCODE) += update_microcode.c
|
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
|
||||||
|
|
|
@ -1,22 +1,18 @@
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
#include <arch/cpu.h>
|
#include <arch/cpu.h>
|
||||||
#include <stdint.h>
|
#include <types.h>
|
||||||
#include <cpu/amd/microcode.h>
|
#include <cpu/amd/microcode.h>
|
||||||
#include <commonlib/helpers.h>
|
#include <commonlib/helpers.h>
|
||||||
#include <console/console.h>
|
#include <console/console.h>
|
||||||
#include <cpu/x86/msr.h>
|
#include <cpu/x86/msr.h>
|
||||||
#include <cpu/amd/msr.h>
|
#include <cpu/amd/msr.h>
|
||||||
#include <cbfs.h>
|
#include <cbfs.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <timestamp.h>
|
#include <timestamp.h>
|
||||||
|
|
||||||
#define CPU_MICROCODE_BLOB_NAME "cpu_microcode_blob.bin"
|
#define CPU_MICROCODE_BLOB_NAME "cpu_microcode_XXXX.bin"
|
||||||
|
#define CPU_MICROCODE_BLOB_FORMAT "cpu_microcode_%04x.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
|
|
||||||
|
|
||||||
struct microcode {
|
struct microcode {
|
||||||
uint32_t date_code;
|
uint32_t date_code;
|
||||||
|
@ -34,12 +30,8 @@ struct microcode {
|
||||||
uint8_t chipset2_rev_id;
|
uint8_t chipset2_rev_id;
|
||||||
|
|
||||||
uint8_t reserved2[4];
|
uint8_t reserved2[4];
|
||||||
|
|
||||||
uint8_t m_patch_data[MPB_MAX_SIZE-MPB_DATA_OFFSET];
|
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
_Static_assert(sizeof(struct microcode) == MPB_MAX_SIZE, "microcode size is invalid");
|
|
||||||
|
|
||||||
static void apply_microcode_patch(const struct microcode *m)
|
static void apply_microcode_patch(const struct microcode *m)
|
||||||
{
|
{
|
||||||
uint32_t new_patch_id;
|
uint32_t new_patch_id;
|
||||||
|
@ -50,8 +42,7 @@ static void apply_microcode_patch(const struct microcode *m)
|
||||||
|
|
||||||
wrmsr(MSR_PATCH_LOADER, msr);
|
wrmsr(MSR_PATCH_LOADER, msr);
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "microcode: patch id to apply = 0x%08x\n",
|
printk(BIOS_DEBUG, "microcode: patch id to apply = 0x%08x\n", m->patch_id);
|
||||||
m->patch_id);
|
|
||||||
|
|
||||||
msr = rdmsr(IA32_BIOS_SIGN_ID);
|
msr = rdmsr(IA32_BIOS_SIGN_ID);
|
||||||
new_patch_id = msr.lo;
|
new_patch_id = msr.lo;
|
||||||
|
@ -71,15 +62,11 @@ static uint16_t get_equivalent_processor_rev_id(void)
|
||||||
return (uint16_t)((cpuid_family & 0xff0000) >> 8 | (cpuid_family & 0xff));
|
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();
|
if (ucode->processor_rev_id == equivalent_processor_rev_id)
|
||||||
const struct microcode *m;
|
return ucode;
|
||||||
|
|
||||||
for (m = ucode; m < ucode + ucode_len / MPB_MAX_SIZE; m++) {
|
|
||||||
if (m->processor_rev_id == equivalent_processor_rev_id)
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
printk(BIOS_WARNING, "Failed to find microcode for processor rev: %hx.\n",
|
printk(BIOS_WARNING, "Failed to find microcode for processor rev: %hx.\n",
|
||||||
equivalent_processor_rev_id);
|
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)
|
void amd_update_microcode_from_cbfs(void)
|
||||||
{
|
{
|
||||||
static struct microcode ucode_cache;
|
static const struct microcode *ucode_cache;
|
||||||
static bool cache_valid;
|
static bool cache_valid;
|
||||||
|
|
||||||
struct microcode *ucode_list;
|
struct microcode *ucode;
|
||||||
const struct microcode *matching_ucode;
|
char name[] = CPU_MICROCODE_BLOB_NAME;
|
||||||
size_t ucode_len;
|
uint16_t equivalent_processor_rev_id;
|
||||||
|
|
||||||
/* Cache the buffer so each CPU doesn't need to read the uCode from flash */
|
/* 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) {
|
if (!cache_valid) {
|
||||||
timestamp_add_now(TS_READ_UCODE_START);
|
timestamp_add_now(TS_READ_UCODE_START);
|
||||||
ucode_list = cbfs_map(CPU_MICROCODE_BLOB_NAME, &ucode_len);
|
equivalent_processor_rev_id = get_equivalent_processor_rev_id();
|
||||||
if (!ucode_list) {
|
snprintf(name, sizeof(name), CPU_MICROCODE_BLOB_FORMAT, equivalent_processor_rev_id);
|
||||||
printk(BIOS_WARNING,
|
ucode = cbfs_map(name, NULL);
|
||||||
CPU_MICROCODE_BLOB_NAME " not found. Skipping updates.\n");
|
if (!ucode) {
|
||||||
|
printk(BIOS_WARNING, "%s not found. Skipping updates.\n", name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
matching_ucode = find_microcode(ucode_list, ucode_len);
|
ucode_cache = find_microcode(ucode, equivalent_processor_rev_id);
|
||||||
|
|
||||||
if (!matching_ucode) {
|
if (!ucode_cache) {
|
||||||
cbfs_unmap(ucode_list);
|
cbfs_unmap(ucode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ucode_cache = *matching_ucode;
|
|
||||||
cache_valid = true;
|
cache_valid = true;
|
||||||
|
|
||||||
cbfs_unmap(ucode_list);
|
|
||||||
|
|
||||||
timestamp_add_now(TS_READ_UCODE_END);
|
timestamp_add_now(TS_READ_UCODE_END);
|
||||||
}
|
}
|
||||||
|
|
||||||
apply_microcode_patch(&ucode_cache);
|
apply_microcode_patch(ucode_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
void preload_microcode(void)
|
void preload_microcode(void)
|
||||||
|
@ -129,6 +114,10 @@ void preload_microcode(void)
|
||||||
if (!CONFIG(CBFS_PRELOAD))
|
if (!CONFIG(CBFS_PRELOAD))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "Preloading microcode %s\n", CPU_MICROCODE_BLOB_NAME);
|
char name[] = CPU_MICROCODE_BLOB_NAME;
|
||||||
cbfs_preload(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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -292,6 +292,6 @@ apu/amdfw_b-position := $(AMD_FW_AB_POSITION)
|
||||||
apu/amdfw_b-type := raw
|
apu/amdfw_b-type := raw
|
||||||
endif
|
endif
|
||||||
|
|
||||||
cpu_microcode_bins += $(wildcard ${FIRMWARE_LOCATION}/UcodePatch_*.bin)
|
amd_microcode_bins := $(wildcard ${FIRMWARE_LOCATION}/UcodePatch_*.bin)
|
||||||
|
|
||||||
endif # ($(CONFIG_SOC_AMD_PICASSO),y)
|
endif # ($(CONFIG_SOC_AMD_PICASSO),y)
|
||||||
|
|
|
@ -291,6 +291,6 @@ apu/amdfw_b-position := $(AMD_FW_AB_POSITION)
|
||||||
apu/amdfw_b-type := raw
|
apu/amdfw_b-type := raw
|
||||||
endif
|
endif
|
||||||
|
|
||||||
cpu_microcode_bins += $(wildcard ${FIRMWARE_LOCATION}/UcodePatch_*.bin)
|
amd_microcode_bins += $(wildcard ${FIRMWARE_LOCATION}/UcodePatch_*.bin)
|
||||||
|
|
||||||
endif # ($(CONFIG_SOC_AMD_SABRINA),y)
|
endif # ($(CONFIG_SOC_AMD_SABRINA),y)
|
||||||
|
|
Loading…
Reference in New Issue