diff options
-rw-r--r-- | src/cpu/amd/pi/00730F01/Kconfig | 2 | ||||
-rw-r--r-- | src/cpu/amd/pi/00730F01/Makefile.inc | 4 | ||||
-rw-r--r-- | src/cpu/amd/pi/00730F01/microcode_fam16h.c | 169 | ||||
-rw-r--r-- | src/cpu/amd/pi/00730F01/model_16_init.c | 3 | ||||
-rw-r--r-- | src/cpu/amd/pi/00730F01/update_microcode.c | 58 |
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); +} |