diff options
author | Thomas Gleixner <[email protected]> | 2023-10-02 14:00:05 +0200 |
---|---|---|
committer | Borislav Petkov (AMD) <[email protected]> | 2023-10-24 15:05:55 +0200 |
commit | 7eb314a22800457396f541c655697dabd71e44a7 (patch) | |
tree | 381820e5f0cf90a0bf7a88a6b9f908aede78b516 /arch/x86/kernel/cpu/microcode/internal.h | |
parent | 0bf871651211b58c7b19f40b746b646d5311e2ec (diff) |
x86/microcode: Rendezvous and load in NMI
stop_machine() does not prevent the spin-waiting sibling from handling
an NMI, which is obviously violating the whole concept of rendezvous.
Implement a static branch right in the beginning of the NMI handler
which is nopped out except when enabled by the late loading mechanism.
The late loader enables the static branch before stop_machine() is
invoked. Each CPU has an nmi_enable in its control structure which
indicates whether the CPU should go into the update routine.
This is required to bridge the gap between enabling the branch and
actually being at the point where it is required to enter the loader
wait loop.
Each CPU which arrives in the stopper thread function sets that flag and
issues a self NMI right after that. If the NMI function sees the flag
clear, it returns. If it's set it clears the flag and enters the
rendezvous.
This is safe against a real NMI which hits in between setting the flag
and sending the NMI to itself. The real NMI will be swallowed by the
microcode update and the self NMI will then let stuff continue.
Otherwise this would end up with a spurious NMI.
Signed-off-by: Thomas Gleixner <[email protected]>
Signed-off-by: Borislav Petkov (AMD) <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Diffstat (limited to 'arch/x86/kernel/cpu/microcode/internal.h')
-rw-r--r-- | arch/x86/kernel/cpu/microcode/internal.h | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/arch/x86/kernel/cpu/microcode/internal.h b/arch/x86/kernel/cpu/microcode/internal.h index c6990431b5de..627d23809b89 100644 --- a/arch/x86/kernel/cpu/microcode/internal.h +++ b/arch/x86/kernel/cpu/microcode/internal.h @@ -31,7 +31,8 @@ struct microcode_ops { enum ucode_state (*apply_microcode)(int cpu); int (*collect_cpu_info)(int cpu, struct cpu_signature *csig); void (*finalize_late_load)(int result); - unsigned int nmi_safe : 1; + unsigned int nmi_safe : 1, + use_nmi : 1; }; extern struct ucode_cpu_info ucode_cpu_info[]; |