| From d996a8d18c72a9cd3ed58ab98e3a06db064ac520 Mon Sep 17 00:00:00 2001 |
| From: Thomas Gleixner <tglx@linutronix.de> |
| Date: Mon, 2 Oct 2023 14:00:01 +0200 |
| Subject: x86/microcode: Add per CPU control field |
| |
| From: Thomas Gleixner <tglx@linutronix.de> |
| |
| commit ba3aeb97cb2c53025356f31c5a0a294385194115 upstream |
| |
| Add a per CPU control field to ucode_ctrl and define constants for it |
| which are going to be used to control the loading state machine. |
| |
| In theory this could be a global control field, but a global control does |
| not cover the following case: |
| |
| 15 primary CPUs load microcode successfully |
| 1 primary CPU fails and returns with an error code |
| |
| With global control the sibling of the failed CPU would either try again or |
| the whole operation would be aborted with the consequence that the 15 |
| siblings do not invoke the apply path and end up with inconsistent software |
| state. The result in dmesg would be inconsistent too. |
| |
| There are two additional fields added and initialized: |
| |
| ctrl_cpu and secondaries. ctrl_cpu is the CPU number of the primary thread |
| for now, but with the upcoming uniform loading at package or system scope |
| this will be one CPU per package or just one CPU. Secondaries hands the |
| control CPU a CPU mask which will be required to release the secondary CPUs |
| out of the wait loop. |
| |
| Preparatory change for implementing a properly split control flow for |
| primary and secondary CPUs. |
| |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> |
| Link: https://lore.kernel.org/r/20231002115903.319959519@linutronix.de |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| arch/x86/kernel/cpu/microcode/core.c | 20 ++++++++++++++++++-- |
| 1 file changed, 18 insertions(+), 2 deletions(-) |
| |
| --- a/arch/x86/kernel/cpu/microcode/core.c |
| +++ b/arch/x86/kernel/cpu/microcode/core.c |
| @@ -252,8 +252,19 @@ static struct platform_device *microcode |
| * requirement can be relaxed in the future. Right now, this is conservative |
| * and good. |
| */ |
| +enum sibling_ctrl { |
| + /* Spinwait with timeout */ |
| + SCTRL_WAIT, |
| + /* Invoke the microcode_apply() callback */ |
| + SCTRL_APPLY, |
| + /* Proceed without invoking the microcode_apply() callback */ |
| + SCTRL_DONE, |
| +}; |
| + |
| struct microcode_ctrl { |
| + enum sibling_ctrl ctrl; |
| enum ucode_state result; |
| + unsigned int ctrl_cpu; |
| }; |
| |
| static DEFINE_PER_CPU(struct microcode_ctrl, ucode_ctrl); |
| @@ -398,7 +409,7 @@ static int load_late_stop_cpus(void) |
| */ |
| static bool setup_cpus(void) |
| { |
| - struct microcode_ctrl ctrl = { .result = -1, }; |
| + struct microcode_ctrl ctrl = { .ctrl = SCTRL_WAIT, .result = -1, }; |
| unsigned int cpu; |
| |
| for_each_cpu_and(cpu, cpu_present_mask, &cpus_booted_once_mask) { |
| @@ -408,7 +419,12 @@ static bool setup_cpus(void) |
| return false; |
| } |
| } |
| - /* Initialize the per CPU state */ |
| + |
| + /* |
| + * Initialize the per CPU state. This is core scope for now, |
| + * but prepared to take package or system scope into account. |
| + */ |
| + ctrl.ctrl_cpu = cpumask_first(topology_sibling_cpumask(cpu)); |
| per_cpu(ucode_ctrl, cpu) = ctrl; |
| } |
| return true; |