diff options
-rw-r--r-- | src/soc/amd/picasso/Kconfig | 1 | ||||
-rw-r--r-- | src/soc/amd/picasso/Makefile.inc | 12 | ||||
-rw-r--r-- | src/soc/amd/picasso/cpu.c | 3 | ||||
-rw-r--r-- | src/soc/amd/picasso/update_microcode.c | 91 |
4 files changed, 98 insertions, 9 deletions
diff --git a/src/soc/amd/picasso/Kconfig b/src/soc/amd/picasso/Kconfig index 5ba0c1b2e0..2bd9c0975c 100644 --- a/src/soc/amd/picasso/Kconfig +++ b/src/soc/amd/picasso/Kconfig @@ -54,6 +54,7 @@ config CPU_SPECIFIC_OPTIONS select FSP_USES_CB_STACK select UDK_2017_BINDING select HAVE_CF9_RESET + select SUPPORT_CPU_UCODE_IN_CBFS config PRERAM_CBMEM_CONSOLE_SIZE hex diff --git a/src/soc/amd/picasso/Makefile.inc b/src/soc/amd/picasso/Makefile.inc index 8012f973a0..7fce124a5d 100644 --- a/src/soc/amd/picasso/Makefile.inc +++ b/src/soc/amd/picasso/Makefile.inc @@ -64,6 +64,7 @@ ramstage-y += soc_util.c ramstage-y += psp.c ramstage-y += fsp_params.c ramstage-y += config.c +ramstage-y += update_microcode.c all-y += reset.c @@ -281,9 +282,6 @@ OPT_PSP_PMUD_FILE1=$(call add_opt_prefix, $(PSP_PMUD_FILE1), --subprogram 0 --in OPT_PSP_PMUD_FILE2=$(call add_opt_prefix, $(PSP_PMUD_FILE2), --subprogram 0 --instance 4 --pmu-data) OPT_PSP_PMUD_FILE3=$(call add_opt_prefix, $(PSP_PMUD_FILE3), --subprogram 1 --instance 1 --pmu-data) OPT_PSP_PMUD_FILE4=$(call add_opt_prefix, $(PSP_PMUD_FILE4), --subprogram 1 --instance 4 --pmu-data) -OPT_PSP_UCODE_FILE1=$(call add_opt_prefix, $(PSP_UCODE_FILE1), --instance 0 --ucode) -OPT_PSP_UCODE_FILE2=$(call add_opt_prefix, $(PSP_UCODE_FILE2), --instance 1 --ucode) -OPT_PSP_UCODE_FILE3=$(call add_opt_prefix, $(PSP_UCODE_FILE3), --instance 2 --ucode) OPT_MP2CFG_FILE=$(call add_opt_prefix, $(PSP_MP2CFG_FILE), --mp2-config) # Copy prebuild APCBs if they exist @@ -342,9 +340,6 @@ $(obj)/amdfw.rom: $(call strip_quotes, $(CONFIG_AMD_PUBKEY_FILE)) \ $(call strip_quotes, $(PSP_PMUD_FILE2)) \ $(call strip_quotes, $(PSP_PMUD_FILE3)) \ $(call strip_quotes, $(PSP_PMUD_FILE4)) \ - $(call strip_quotes, $(PSP_UCODE_FILE1)) \ - $(call strip_quotes, $(PSP_UCODE_FILE2)) \ - $(call strip_quotes, $(PSP_UCODE_FILE3)) \ $(call strip_quotes, $(PSP_MP2CFG_FILE)) \ $(call strip_quotes, $(PSP_SMUFW1_SUB1_FILE)) \ $(call strip_quotes, $(PSP_SMUFW1_SUB2_FILE)) \ @@ -399,9 +394,6 @@ $(obj)/amdfw.rom: $(call strip_quotes, $(CONFIG_AMD_PUBKEY_FILE)) \ $(OPT_PSP_PMUD_FILE2) \ $(OPT_PSP_PMUD_FILE3) \ $(OPT_PSP_PMUD_FILE4) \ - $(OPT_PSP_UCODE_FILE1) \ - $(OPT_PSP_UCODE_FILE2) \ - $(OPT_PSP_UCODE_FILE3) \ $(OPT_MP2CFG_FILE) \ $(OPT_ABL0_FILE) \ $(OPT_ABL1_FILE) \ @@ -461,4 +453,6 @@ endif # ifeq ($(CONFIG_AMDFW_OUTSIDE_CBFS),y) $(call strip_quotes,$(CONFIG_FSP_M_CBFS))-options := -b $(CONFIG_FSP_M_ADDR) +cpu_microcode_bins += $(wildcard 3rdparty/amd_blobs/picasso/PSP/UcodePatch_*.bin) + endif # ($(CONFIG_SOC_AMD_PICASSO),y) diff --git a/src/soc/amd/picasso/cpu.c b/src/soc/amd/picasso/cpu.c index 96edd70c13..97a1780717 100644 --- a/src/soc/amd/picasso/cpu.c +++ b/src/soc/amd/picasso/cpu.c @@ -16,6 +16,7 @@ #include <soc/smi.h> #include <soc/iomap.h> #include <console/console.h> +#include <cpu/amd/microcode.h> /* * MP and SMM loading initialization. @@ -108,6 +109,8 @@ static void model_17_init(struct device *dev) { check_mca(); setup_lapic(); + + amd_update_microcode_from_cbfs(); } static struct device_operations cpu_dev_ops = { diff --git a/src/soc/amd/picasso/update_microcode.c b/src/soc/amd/picasso/update_microcode.c new file mode 100644 index 0000000000..8f3d3e22b8 --- /dev/null +++ b/src/soc/amd/picasso/update_microcode.c @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <stdint.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> + +#define MPB_MAX_SIZE 3200 +#define MPB_DATA_OFFSET 32 + +struct microcode { + uint32_t date_code; + uint32_t patch_id; + + uint16_t mc_patch_data_id; + uint8_t reserved1[6]; + + uint32_t chipset1_dev_id; + uint32_t chipset2_dev_id; + + uint16_t processor_rev_id; + + uint8_t chipset1_rev_id; + uint8_t chipset2_rev_id; + + uint8_t reserved2[4]; + + uint8_t m_patch_data[MPB_MAX_SIZE-MPB_DATA_OFFSET]; +} __packed; + +static void apply_microcode_patch(const struct microcode *m) +{ + uint32_t new_patch_id; + msr_t msr; + + msr.hi = (uint64_t)(uintptr_t)m >> 32; + msr.lo = (uintptr_t)m & 0xffffffff; + + wrmsr(MSR_PATCH_LOADER, msr); + + printk(BIOS_DEBUG, "microcode: patch id to apply = 0x%08x\n", + m->patch_id); + + msr = rdmsr(MSR_PATCH_LEVEL); + 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); + else + printk(BIOS_ERR, "microcode: being updated to patch id = 0x%08x failed\n", + new_patch_id); +} + +static uint16_t get_equivalent_processor_rev_id(void) +{ + uint32_t cpuid_family = cpuid_eax(1); + + 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) +{ + const struct microcode *m; + + for (m = (struct microcode *)ucode; + m < (struct microcode *)ucode + ucode_len/MPB_MAX_SIZE; m++) { + if (m->processor_rev_id == equivalent_processor_rev_id) + apply_microcode_patch(m); + } +} + +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(); + + ucode = cbfs_boot_map_with_leak("cpu_microcode_blob.bin", + CBFS_TYPE_MICROCODE, &ucode_len); + if (!ucode) { + printk(BIOS_WARNING, "cpu_microcode_blob.bin not found. Skipping updates.\n"); + return; + } + + amd_update_microcode(ucode, ucode_len, equivalent_processor_rev_id); +} |