amd/00730F01: Clean the Microcode updating
According to the comments of https://review.coreboot.org/c/coreboot/+/41719 , which is about Microcode patch for amd/picasso. Change the code with the same way. The changes include: 1. combine the microcode_xxx.c and update_microcode.c into one source. 2. Redefine the microcode updating function to eliminate the parameter. Get the revision ID in the black box. Reduce the depth of function calls. 3. Get the revision ID by bitwise calculation instead of lookup table. 4. Reduce the confusing type casts. 5. Squash some lines. We do not change the way it used to be. The code assume only one microcode is integrated in CBFS. If needed in future, 41719 is the example of integrating multiple binaries. And, 41719 depends on the definition in this patch. Change-Id: I8b0da99db0d3189058f75e199f05492c4e6c5881 Signed-off-by: Zheng Bao <zheng.bao@amd.com> Signed-off-by: Zheng Bao <fishbaozi@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/42094 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
This commit is contained in:
parent
306e8930a7
commit
b8c473e32f
|
@ -6,7 +6,6 @@ ramstage-y += fixme.c
|
||||||
ramstage-y += chip_name.c
|
ramstage-y += chip_name.c
|
||||||
ramstage-y += model_16_init.c
|
ramstage-y += model_16_init.c
|
||||||
ramstage-y += update_microcode.c
|
ramstage-y += update_microcode.c
|
||||||
ramstage-y += microcode_fam16h.c
|
|
||||||
|
|
||||||
subdirs-y += ../../mtrr
|
subdirs-y += ../../mtrr
|
||||||
subdirs-y += ../../../x86/tsc
|
subdirs-y += ../../../x86/tsc
|
||||||
|
|
|
@ -1,129 +0,0 @@
|
||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <console/console.h>
|
|
||||||
#include <cpu/x86/msr.h>
|
|
||||||
#include <cpu/amd/microcode.h>
|
|
||||||
#include <cbfs.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,
|
|
||||||
uint16_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(uint16_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;
|
|
||||||
}
|
|
||||||
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");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ucode_len > F16H_MPB_MAX_SIZE ||
|
|
||||||
ucode_len < F16H_MPB_DATA_OFFSET) {
|
|
||||||
printk(BIOS_DEBUG, "microcode file invalid. Skipping "
|
|
||||||
"updates.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
amd_update_microcode(ucode, ucode_len, equivalent_processor_rev_id);
|
|
||||||
}
|
|
|
@ -87,7 +87,7 @@ static void model_16_init(struct device *dev)
|
||||||
msr.lo |= (1 << 0);
|
msr.lo |= (1 << 0);
|
||||||
wrmsr(HWCR_MSR, msr);
|
wrmsr(HWCR_MSR, msr);
|
||||||
|
|
||||||
update_microcode(cpuid_eax(1));
|
amd_update_microcode_from_cbfs();
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct device_operations cpu_dev_ops = {
|
static struct device_operations cpu_dev_ops = {
|
||||||
|
|
|
@ -2,42 +2,131 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <cpu/amd/microcode.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>
|
||||||
|
|
||||||
struct id_mapping {
|
/*
|
||||||
uint32_t orig_id;
|
* Values and header structure from:
|
||||||
uint16_t new_id;
|
* BKDG for AMD Family 16h Models 30h-3Fh Processors
|
||||||
};
|
* 52740 Rev 3.06 - March 18, 2016
|
||||||
|
*/
|
||||||
|
|
||||||
static u16 get_equivalent_processor_rev_id(u32 orig_id)
|
#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];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
static void apply_microcode_patch(const struct microcode *m)
|
||||||
{
|
{
|
||||||
static const struct id_mapping id_mapping_table[] = {
|
uint32_t new_patch_id;
|
||||||
/* Family 16h */
|
msr_t msr;
|
||||||
|
|
||||||
/* TODO This equivalent processor revisions ID needs verification */
|
msr.hi = (uint64_t)(uintptr_t)m >> 32;
|
||||||
{ 0x730f01, 0x7301 },
|
msr.lo = (uintptr_t)m & 0xffffffff;
|
||||||
|
|
||||||
/* Array terminator */
|
wrmsr(MSR_PATCH_LOADER, msr);
|
||||||
{ 0xffffff, 0x0000 },
|
|
||||||
};
|
|
||||||
|
|
||||||
u32 new_id;
|
printk(BIOS_DEBUG, "microcode: patch id to apply = 0x%08x\n",
|
||||||
int i;
|
m->patch_id);
|
||||||
|
|
||||||
new_id = 0;
|
msr = rdmsr(MSR_PATCH_LEVEL);
|
||||||
|
new_patch_id = msr.lo;
|
||||||
|
|
||||||
for (i = 0; id_mapping_table[i].orig_id != 0xffffff; i++) {
|
if (new_patch_id == m->patch_id)
|
||||||
if (id_mapping_table[i].orig_id == orig_id) {
|
printk(BIOS_INFO, "microcode: being updated to patch id = 0x%08x succeeded\n",
|
||||||
new_id = id_mapping_table[i].new_id;
|
new_patch_id);
|
||||||
break;
|
else
|
||||||
}
|
printk(BIOS_ERR, "microcode: being updated to patch id = 0x%08x failed\n",
|
||||||
|
new_patch_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new_id;
|
static uint16_t get_equivalent_processor_rev_id(void)
|
||||||
}
|
|
||||||
|
|
||||||
void update_microcode(u32 cpu_deviceid)
|
|
||||||
{
|
{
|
||||||
u16 equivalent_processor_rev_id =
|
uint32_t cpuid_family = cpuid_eax(1);
|
||||||
get_equivalent_processor_rev_id(cpu_deviceid);
|
|
||||||
amd_update_microcode_from_cbfs(equivalent_processor_rev_id);
|
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;
|
||||||
|
const uint8_t *c = ucode;
|
||||||
|
|
||||||
|
m = (struct microcode *)c;
|
||||||
|
|
||||||
|
/* Assume cpu_microcode_blob only contains one microcode. */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ucode_len > F16H_MPB_MAX_SIZE ||
|
||||||
|
ucode_len < F16H_MPB_DATA_OFFSET) {
|
||||||
|
printk(BIOS_DEBUG, "microcode file invalid. Skipping updates.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
amd_update_microcode(ucode, ucode_len, equivalent_processor_rev_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#ifndef CPU_AMD_MICROCODE_H
|
#ifndef CPU_AMD_MICROCODE_H
|
||||||
#define CPU_AMD_MICROCODE_H
|
#define CPU_AMD_MICROCODE_H
|
||||||
|
|
||||||
void update_microcode(u32 cpu_deviceid);
|
void amd_update_microcode_from_cbfs(void);
|
||||||
void amd_update_microcode_from_cbfs(u16 equivalent_processor_rev_id);
|
|
||||||
|
|
||||||
#endif /* CPU_AMD_MICROCODE_H */
|
#endif /* CPU_AMD_MICROCODE_H */
|
||||||
|
|
Loading…
Reference in New Issue