summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/amd/picasso/Kconfig1
-rw-r--r--src/soc/amd/picasso/Makefile.inc12
-rw-r--r--src/soc/amd/picasso/cpu.c3
-rw-r--r--src/soc/amd/picasso/update_microcode.c91
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);
+}