summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cpu/amd/pi/00730F01/Kconfig2
-rw-r--r--src/cpu/amd/pi/00730F01/Makefile.inc4
-rw-r--r--src/cpu/amd/pi/00730F01/microcode_fam16h.c169
-rw-r--r--src/cpu/amd/pi/00730F01/model_16_init.c3
-rw-r--r--src/cpu/amd/pi/00730F01/update_microcode.c58
5 files changed, 236 insertions, 0 deletions
diff --git a/src/cpu/amd/pi/00730F01/Kconfig b/src/cpu/amd/pi/00730F01/Kconfig
index 054523ee37..f3f488d2dd 100644
--- a/src/cpu/amd/pi/00730F01/Kconfig
+++ b/src/cpu/amd/pi/00730F01/Kconfig
@@ -16,6 +16,8 @@
config CPU_AMD_PI_00730F01
bool
select X86_AMD_FIXED_MTRRS
+ select SUPPORT_CPU_UCODE_IN_CBFS
+ select MICROCODE_BLOB_UNDISCLOSED
if CPU_AMD_PI_00730F01
diff --git a/src/cpu/amd/pi/00730F01/Makefile.inc b/src/cpu/amd/pi/00730F01/Makefile.inc
index 9367b458a3..99b6ef33a9 100644
--- a/src/cpu/amd/pi/00730F01/Makefile.inc
+++ b/src/cpu/amd/pi/00730F01/Makefile.inc
@@ -14,10 +14,14 @@
#
romstage-y += fixme.c
+romstage-y += update_microcode.c
+romstage-y += microcode_fam16h.c
ramstage-y += fixme.c
ramstage-y += chip_name.c
ramstage-y += model_16_init.c
+ramstage-y += update_microcode.c
+ramstage-y += microcode_fam16h.c
subdirs-y += ../../mtrr
subdirs-y += ../../../x86/tsc
diff --git a/src/cpu/amd/pi/00730F01/microcode_fam16h.c b/src/cpu/amd/pi/00730F01/microcode_fam16h.c
new file mode 100644
index 0000000000..ad951242a7
--- /dev/null
+++ b/src/cpu/amd/pi/00730F01/microcode_fam16h.c
@@ -0,0 +1,169 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 Advanced Micro Devices, Inc.
+ * Copyright (C) 2015 Raptor Engineering
+ * Copyright (C) 2019 PC Engines GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <stdint.h>
+#include <console/console.h>
+#include <cpu/x86/msr.h>
+#include <cpu/amd/microcode.h>
+#include <cbfs.h>
+#include <arch/io.h>
+#include <smp/spinlock.h>
+
+/*
+ * Values and header structure from:
+ * BKDG for AMD Family 16h Models 30h-3Fh Processors
+ * 52740 Rev 3.06 - March 18, 2016
+ */
+
+#define F16H_MPB_MAX_SIZE 3458
+#define F16H_MPB_DATA_OFFSET 32
+
+ /*
+ * STRUCTURE OF A MICROCODE (UCODE) FILE FOR FAM16h
+ * Microcode Patch Block
+ * Microcode Header
+ * Microcode "Blob"
+ * ...
+ * ...
+ * (end of file)
+ *
+ *
+ * MICROCODE HEADER (offset 0 bytes from start of file)
+ * Total size = 32 bytes
+ * [0:3] Date code (32 bits)
+ * [4:7] Patch level (32 bits)
+ * [8:9] Microcode patch data ID (16 bits)
+ * [10:15] Reserved (48 bits)
+ * [16:19] Chipset 1 device ID (32 bits)
+ * [20:23] Chipset 2 device ID (32 bits)
+ * [24:25] Processor Revisions ID (16 bits)
+ * [26] Chipset 1 revision ID (8 bits)
+ * [27] Chipset 2 revision ID (8 bits)
+ * [28:31] Reserved (32 bits)
+ *
+ * MICROCODE BLOB (offset += 32)
+ * Total size = m bytes
+ *
+ */
+
+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[F16H_MPB_MAX_SIZE-F16H_MPB_DATA_OFFSET];
+
+};
+
+static void apply_microcode_patch(const struct microcode *m)
+{
+ uint32_t new_patch_id;
+ msr_t msr;
+
+ /* apply patch */
+ msr.hi = 0;
+ msr.lo = (uint32_t)m;
+
+ wrmsr(0xc0010020, msr);
+
+ printk(BIOS_DEBUG, "microcode: patch id to apply = 0x%08x\n",
+ m->patch_id);
+
+ /* patch authentication */
+ msr = rdmsr(0x8b);
+ new_patch_id = msr.lo;
+
+ printk(BIOS_DEBUG, "microcode: updated to patch id = 0x%08x %s\n",
+ new_patch_id,
+ (new_patch_id == m->patch_id) ? "success" : "fail");
+}
+
+static void amd_update_microcode(const void *ucode, size_t ucode_len,
+ uint32_t equivalent_processor_rev_id)
+{
+ const struct microcode *m;
+ const uint8_t *c = ucode;
+
+ m = (struct microcode *)c;
+
+ if (m->processor_rev_id == equivalent_processor_rev_id)
+ apply_microcode_patch(m);
+}
+
+void amd_update_microcode_from_cbfs(uint32_t equivalent_processor_rev_id)
+{
+ const void *ucode;
+ size_t ucode_len;
+
+ if (equivalent_processor_rev_id == 0) {
+ printk(BIOS_DEBUG, "microcode: rev id not found. "
+ "Skipping microcode patch!\n");
+ return;
+ }
+#ifdef __PRE_RAM__
+#if CONFIG(HAVE_ROMSTAGE_MICROCODE_CBFS_SPINLOCK)
+ spin_lock(romstage_microcode_cbfs_lock());
+#endif
+#endif
+ ucode = cbfs_boot_map_with_leak("cpu_microcode_blob.bin",
+ CBFS_TYPE_MICROCODE,
+ &ucode_len);
+ if (!ucode) {
+ printk(BIOS_DEBUG, "cpu_microcode_blob.bin not found. "
+ "Skipping updates.\n");
+#ifdef __PRE_RAM__
+#if CONFIG(HAVE_ROMSTAGE_MICROCODE_CBFS_SPINLOCK)
+ spin_unlock(romstage_microcode_cbfs_lock());
+#endif
+#endif
+ return;
+ }
+
+ if (ucode_len > F16H_MPB_MAX_SIZE ||
+ ucode_len < F16H_MPB_DATA_OFFSET) {
+ printk(BIOS_DEBUG, "microcode file invalid. Skipping "
+ "updates.\n");
+#ifdef __PRE_RAM__
+#if CONFIG(HAVE_ROMSTAGE_MICROCODE_CBFS_SPINLOCK)
+ spin_unlock(romstage_microcode_cbfs_lock());
+#endif
+#endif
+ return;
+ }
+
+ amd_update_microcode(ucode, ucode_len,
+ equivalent_processor_rev_id);
+
+#ifdef __PRE_RAM__
+#if CONFIG(HAVE_ROMSTAGE_MICROCODE_CBFS_SPINLOCK)
+ spin_unlock(romstage_microcode_cbfs_lock());
+#endif
+#endif
+
+}
diff --git a/src/cpu/amd/pi/00730F01/model_16_init.c b/src/cpu/amd/pi/00730F01/model_16_init.c
index fe828900fc..b0449a73b2 100644
--- a/src/cpu/amd/pi/00730F01/model_16_init.c
+++ b/src/cpu/amd/pi/00730F01/model_16_init.c
@@ -14,6 +14,7 @@
*/
#include <console/console.h>
+#include <cpu/amd/microcode.h>
#include <cpu/x86/msr.h>
#include <cpu/amd/msr.h>
#include <cpu/x86/mtrr.h>
@@ -98,6 +99,8 @@ static void model_16_init(struct device *dev)
msr = rdmsr(HWCR_MSR);
msr.lo |= (1 << 0);
wrmsr(HWCR_MSR, msr);
+
+ update_microcode(cpuid_eax(1));
}
static struct device_operations cpu_dev_ops = {
diff --git a/src/cpu/amd/pi/00730F01/update_microcode.c b/src/cpu/amd/pi/00730F01/update_microcode.c
new file mode 100644
index 0000000000..6acf13a6ef
--- /dev/null
+++ b/src/cpu/amd/pi/00730F01/update_microcode.c
@@ -0,0 +1,58 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
+ * Copyright (C) 2007 Advanced Micro Devices, Inc.
+ * Copyright (C) 2019 PC Engines GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <stdint.h>
+#include <cpu/amd/microcode.h>
+
+struct id_mapping {
+ uint32_t orig_id;
+ uint16_t new_id;
+};
+
+static u16 get_equivalent_processor_rev_id(u32 orig_id)
+{
+ static const struct id_mapping id_mapping_table[] = {
+ /* Family 16h */
+
+ /* TODO This equivalent processor revisions ID needs verification */
+ { 0x730f01, 0x7301 },
+
+ /* Array terminator */
+ { 0xffffff, 0x0000 },
+ };
+
+ u32 new_id;
+ int i;
+
+ new_id = 0;
+
+ for (i = 0; id_mapping_table[i].orig_id != 0xffffff; i++) {
+ if (id_mapping_table[i].orig_id == orig_id) {
+ new_id = id_mapping_table[i].new_id;
+ break;
+ }
+ }
+
+ return new_id;
+}
+
+void update_microcode(u32 cpu_deviceid)
+{
+ u32 equivalent_processor_rev_id =
+ get_equivalent_processor_rev_id(cpu_deviceid);
+ amd_update_microcode_from_cbfs(equivalent_processor_rev_id);
+}