summaryrefslogtreecommitdiff
path: root/src/soc/amd/common
diff options
context:
space:
mode:
authorRaul E Rangel <rrangel@chromium.org>2021-02-12 14:37:43 -0700
committerFelix Held <felix-coreboot@felixheld.de>2021-02-14 18:05:17 +0000
commit394c6b092251f0da8f0bd159e0eb08a41a6e4afc (patch)
treee9d347574e889fc911ebe512d2bfc012239a5d73 /src/soc/amd/common
parent844775059d8cb456dec988e6378f3a73ea730001 (diff)
soc/amd: Move update_microcode.c to common/block/cpu
We also want to support uCode loading on cezanne. Signed-off-by: Raul E Rangel <rrangel@chromium.org> Change-Id: I6f10564c93ce72aea7ff52a8565d65d8b56452f3 Reviewed-on: https://review.coreboot.org/c/coreboot/+/50615 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
Diffstat (limited to 'src/soc/amd/common')
-rw-r--r--src/soc/amd/common/block/cpu/Kconfig13
-rw-r--r--src/soc/amd/common/block/cpu/Makefile.inc1
-rw-r--r--src/soc/amd/common/block/cpu/update_microcode.c93
3 files changed, 107 insertions, 0 deletions
diff --git a/src/soc/amd/common/block/cpu/Kconfig b/src/soc/amd/common/block/cpu/Kconfig
index 996605e7f3..f418ee7cc5 100644
--- a/src/soc/amd/common/block/cpu/Kconfig
+++ b/src/soc/amd/common/block/cpu/Kconfig
@@ -44,3 +44,16 @@ config SOC_AMD_COMMON_BLOCK_TSC_FAM17H_19H
Select this option to add the common functions for getting the TSC
frequency of AMD family 17h and 19h CPUs/APUs and to provide TSC-
based monotonic timer functionality to the build.
+
+config SOC_AMD_COMMON_BLOCK_UCODE
+ bool
+ select SUPPORT_CPU_UCODE_IN_CBFS
+ default n
+ help
+ Builds in support for loading uCode.
+
+config SOC_AMD_COMMON_BLOCK_UCODE_SIZE
+ int
+ depends on SOC_AMD_COMMON_BLOCK_UCODE
+ help
+ Defines the size of the uCode binary in bytes.
diff --git a/src/soc/amd/common/block/cpu/Makefile.inc b/src/soc/amd/common/block/cpu/Makefile.inc
index 4c0266396c..f402e703c9 100644
--- a/src/soc/amd/common/block/cpu/Makefile.inc
+++ b/src/soc/amd/common/block/cpu/Makefile.inc
@@ -1 +1,2 @@
subdirs-y += ./*
+ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_UCODE) += update_microcode.c
diff --git a/src/soc/amd/common/block/cpu/update_microcode.c b/src/soc/amd/common/block/cpu/update_microcode.c
new file mode 100644
index 0000000000..2ba180298c
--- /dev/null
+++ b/src/soc/amd/common/block/cpu/update_microcode.c
@@ -0,0 +1,93 @@
+/* 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>
+
+_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 {
+ 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_map("cpu_microcode_blob.bin", &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);
+}