mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-26 20:38:12 +00:00
x86/microcode/intel: Unify microcode apply() functions
Deduplicate the early and late apply() functions. [ bp: Rename the function which does the actual application to __apply_microcode() to differentiate it from microcode_ops.apply_microcode(). ] Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lore.kernel.org/r/20231017211722.795508212@linutronix.de
This commit is contained in:
parent
f24f204405
commit
3973718cff
1 changed files with 36 additions and 68 deletions
|
@ -307,12 +307,12 @@ static __init struct microcode_intel *scan_microcode(void *data, size_t size,
|
||||||
return size ? NULL : patch;
|
return size ? NULL : patch;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum ucode_state apply_microcode_early(struct ucode_cpu_info *uci)
|
static enum ucode_state __apply_microcode(struct ucode_cpu_info *uci,
|
||||||
|
struct microcode_intel *mc,
|
||||||
|
u32 *cur_rev)
|
||||||
{
|
{
|
||||||
struct microcode_intel *mc;
|
u32 rev;
|
||||||
u32 rev, old_rev, date;
|
|
||||||
|
|
||||||
mc = uci->mc;
|
|
||||||
if (!mc)
|
if (!mc)
|
||||||
return UCODE_NFOUND;
|
return UCODE_NFOUND;
|
||||||
|
|
||||||
|
@ -321,14 +321,12 @@ static enum ucode_state apply_microcode_early(struct ucode_cpu_info *uci)
|
||||||
* operation - when the other hyperthread has updated the microcode
|
* operation - when the other hyperthread has updated the microcode
|
||||||
* already.
|
* already.
|
||||||
*/
|
*/
|
||||||
rev = intel_get_microcode_revision();
|
*cur_rev = intel_get_microcode_revision();
|
||||||
if (rev >= mc->hdr.rev) {
|
if (*cur_rev >= mc->hdr.rev) {
|
||||||
uci->cpu_sig.rev = rev;
|
uci->cpu_sig.rev = *cur_rev;
|
||||||
return UCODE_OK;
|
return UCODE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
old_rev = rev;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Writeback and invalidate caches before updating microcode to avoid
|
* Writeback and invalidate caches before updating microcode to avoid
|
||||||
* internal issues depending on what the microcode is updating.
|
* internal issues depending on what the microcode is updating.
|
||||||
|
@ -343,13 +341,24 @@ static enum ucode_state apply_microcode_early(struct ucode_cpu_info *uci)
|
||||||
return UCODE_ERROR;
|
return UCODE_ERROR;
|
||||||
|
|
||||||
uci->cpu_sig.rev = rev;
|
uci->cpu_sig.rev = rev;
|
||||||
|
|
||||||
date = mc->hdr.date;
|
|
||||||
pr_info_once("updated early: 0x%x -> 0x%x, date = %04x-%02x-%02x\n",
|
|
||||||
old_rev, rev, date & 0xffff, date >> 24, (date >> 16) & 0xff);
|
|
||||||
return UCODE_UPDATED;
|
return UCODE_UPDATED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static enum ucode_state apply_microcode_early(struct ucode_cpu_info *uci)
|
||||||
|
{
|
||||||
|
struct microcode_intel *mc = uci->mc;
|
||||||
|
enum ucode_state ret;
|
||||||
|
u32 cur_rev, date;
|
||||||
|
|
||||||
|
ret = __apply_microcode(uci, mc, &cur_rev);
|
||||||
|
if (ret == UCODE_UPDATED) {
|
||||||
|
date = mc->hdr.date;
|
||||||
|
pr_info_once("updated early: 0x%x -> 0x%x, date = %04x-%02x-%02x\n",
|
||||||
|
cur_rev, mc->hdr.rev, date & 0xffff, date >> 24, (date >> 16) & 0xff);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static __init bool load_builtin_intel_microcode(struct cpio_data *cp)
|
static __init bool load_builtin_intel_microcode(struct cpio_data *cp)
|
||||||
{
|
{
|
||||||
unsigned int eax = 1, ebx, ecx = 0, edx;
|
unsigned int eax = 1, ebx, ecx = 0, edx;
|
||||||
|
@ -459,70 +468,29 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum ucode_state apply_microcode_intel(int cpu)
|
static enum ucode_state apply_microcode_late(int cpu)
|
||||||
{
|
{
|
||||||
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
|
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
|
||||||
struct cpuinfo_x86 *c = &cpu_data(cpu);
|
struct microcode_intel *mc = ucode_patch_late;
|
||||||
bool bsp = c->cpu_index == boot_cpu_data.cpu_index;
|
|
||||||
struct microcode_intel *mc;
|
|
||||||
enum ucode_state ret;
|
enum ucode_state ret;
|
||||||
static int prev_rev;
|
u32 cur_rev;
|
||||||
u32 rev;
|
|
||||||
|
|
||||||
/* We should bind the task to the CPU */
|
if (WARN_ON_ONCE(smp_processor_id() != cpu))
|
||||||
if (WARN_ON(raw_smp_processor_id() != cpu))
|
|
||||||
return UCODE_ERROR;
|
return UCODE_ERROR;
|
||||||
|
|
||||||
mc = ucode_patch_late;
|
ret = __apply_microcode(uci, mc, &cur_rev);
|
||||||
if (!mc)
|
if (ret != UCODE_UPDATED && ret != UCODE_OK)
|
||||||
return UCODE_NFOUND;
|
return ret;
|
||||||
|
|
||||||
/*
|
if (!cpu && uci->cpu_sig.rev != cur_rev) {
|
||||||
* Save us the MSR write below - which is a particular expensive
|
pr_info("Updated to revision 0x%x, date = %04x-%02x-%02x\n",
|
||||||
* operation - when the other hyperthread has updated the microcode
|
uci->cpu_sig.rev, mc->hdr.date & 0xffff, mc->hdr.date >> 24,
|
||||||
* already.
|
|
||||||
*/
|
|
||||||
rev = intel_get_microcode_revision();
|
|
||||||
if (rev >= mc->hdr.rev) {
|
|
||||||
ret = UCODE_OK;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Writeback and invalidate caches before updating microcode to avoid
|
|
||||||
* internal issues depending on what the microcode is updating.
|
|
||||||
*/
|
|
||||||
native_wbinvd();
|
|
||||||
|
|
||||||
/* write microcode via MSR 0x79 */
|
|
||||||
wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits);
|
|
||||||
|
|
||||||
rev = intel_get_microcode_revision();
|
|
||||||
|
|
||||||
if (rev != mc->hdr.rev) {
|
|
||||||
pr_err("CPU%d update to revision 0x%x failed\n",
|
|
||||||
cpu, mc->hdr.rev);
|
|
||||||
return UCODE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bsp && rev != prev_rev) {
|
|
||||||
pr_info("updated to revision 0x%x, date = %04x-%02x-%02x\n",
|
|
||||||
rev,
|
|
||||||
mc->hdr.date & 0xffff,
|
|
||||||
mc->hdr.date >> 24,
|
|
||||||
(mc->hdr.date >> 16) & 0xff);
|
(mc->hdr.date >> 16) & 0xff);
|
||||||
prev_rev = rev;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = UCODE_UPDATED;
|
cpu_data(cpu).microcode = uci->cpu_sig.rev;
|
||||||
|
if (!cpu)
|
||||||
out:
|
boot_cpu_data.microcode = uci->cpu_sig.rev;
|
||||||
uci->cpu_sig.rev = rev;
|
|
||||||
c->microcode = rev;
|
|
||||||
|
|
||||||
/* Update boot_cpu_data's revision too, if we're on the BSP: */
|
|
||||||
if (bsp)
|
|
||||||
boot_cpu_data.microcode = rev;
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -663,7 +631,7 @@ static void finalize_late_load(int result)
|
||||||
static struct microcode_ops microcode_intel_ops = {
|
static struct microcode_ops microcode_intel_ops = {
|
||||||
.request_microcode_fw = request_microcode_fw,
|
.request_microcode_fw = request_microcode_fw,
|
||||||
.collect_cpu_info = collect_cpu_info,
|
.collect_cpu_info = collect_cpu_info,
|
||||||
.apply_microcode = apply_microcode_intel,
|
.apply_microcode = apply_microcode_late,
|
||||||
.finalize_late_load = finalize_late_load,
|
.finalize_late_load = finalize_late_load,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue