From 0345b3753ac4e078e7f02808e08861cece8ce222 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Wed, 25 May 2022 18:12:30 +0200 Subject: [PATCH 1/5] x86/microcode: Default-disable late loading stable inclusion from stable-v5.10.173 commit e6230806681fa25b7a3829c021d5b33d68c9bd09 category: feature bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I873BU CVE: N/A Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=e6230806681fa25b7a3829c021d5b33d68c9bd09 ------------------------------------- Intel-SIG: commit e6230806681f x86/microcode: Default-disable late loading. Backport x86/microcode related patches from 5.10.173 upstream. ------------------------------------- [ Upstream commit a77a94f86273ce42a39cb479217dd8d68acfe0ff ] It is dangerous and it should not be used anyway - there's a nice early loading already. Requested-by: Peter Zijlstra (Intel) Signed-off-by: Borislav Petkov Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/r/20220525161232.14924-3-bp@alien8.de Stable-dep-of: c0dd9245aa9e ("x86/microcode: Check CPU capabilities after late microcode update correctly") Signed-off-by: Sasha Levin [ Aichun Shi: amend commit log ] Signed-off-by: Aichun Shi --- arch/x86/Kconfig | 11 +++++++++++ arch/x86/kernel/cpu/common.c | 2 ++ arch/x86/kernel/cpu/microcode/core.c | 7 ++++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 236b510b2352..31c69ee9b5d6 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1357,6 +1357,17 @@ config MICROCODE_OLD_INTERFACE should've switched to the early loading method with the initrd or builtin microcode by now: Documentation/x86/microcode.rst +config MICROCODE_LATE_LOADING + bool "Late microcode loading (DANGEROUS)" + default n + depends on MICROCODE + help + Loading microcode late, when the system is up and executing instructions + is a tricky business and should be avoided if possible. Just the sequence + of synchronizing all cores and SMT threads is one fragile dance which does + not guarantee that cores might not softlock after the loading. Therefore, + use this at your own risk. Late loading taints the kernel too. + config X86_MSR tristate "/dev/cpu/*/msr - Model-specific register support" help diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 6bf8290eaf7a..e3575082c74f 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -2163,6 +2163,7 @@ void cpu_init_secondary(void) } #endif +#ifdef CONFIG_MICROCODE_LATE_LOADING /* * The microcode loader calls this upon late microcode load to recheck features, * only when microcode has been updated. Caller holds microcode_mutex and CPU @@ -2193,6 +2194,7 @@ void microcode_check(void) pr_warn("x86/CPU: CPU features have changed after loading microcode, but might not take effect.\n"); pr_warn("x86/CPU: Please consider either early loading through initrd/built-in or a potential BIOS update.\n"); } +#endif /* * Invoked from core CPU hotplug code after hotplug operations diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index f9e4e17e4bad..ad1d9bc39a07 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c @@ -503,6 +503,7 @@ static void __exit microcode_dev_exit(void) /* fake device for request_firmware */ static struct platform_device *microcode_pdev; +#ifdef CONFIG_MICROCODE_LATE_LOADING /* * Late loading dance. Why the heavy-handed stomp_machine effort? * @@ -671,6 +672,9 @@ static ssize_t reload_store(struct device *dev, return ret; } +static DEVICE_ATTR_WO(reload); +#endif + static ssize_t version_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -687,7 +691,6 @@ static ssize_t pf_show(struct device *dev, return sprintf(buf, "0x%x\n", uci->cpu_sig.pf); } -static DEVICE_ATTR_WO(reload); static DEVICE_ATTR(version, 0444, version_show, NULL); static DEVICE_ATTR(processor_flags, 0444, pf_show, NULL); @@ -840,7 +843,9 @@ static int mc_cpu_down_prep(unsigned int cpu) } static struct attribute *cpu_root_microcode_attrs[] = { +#ifdef CONFIG_MICROCODE_LATE_LOADING &dev_attr_reload.attr, +#endif NULL }; -- Gitee From 94aa4d3f9f72744105698663cdd1e31dd761fa1a Mon Sep 17 00:00:00 2001 From: Ashok Raj Date: Mon, 9 Jan 2023 07:35:50 -0800 Subject: [PATCH 2/5] x86/microcode: Add a parameter to microcode_check() to store CPU capabilities stable inclusion from stable-v5.10.173 commit 89e848bb4aa140e701eb0d017736ce5d1ee198da category: feature bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I873BU CVE: N/A Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=89e848bb4aa140e701eb0d017736ce5d1ee198da ------------------------------------- Intel-SIG: commit 89e848bb4aa1 x86/microcode: Add a parameter to microcode_check() to store CPU capabilities. Backport x86/microcode related patches from 5.10.173 upstream. ------------------------------------- [ Upstream commit ab31c74455c64e69342ddab21fd9426fcbfefde7 ] Add a parameter to store CPU capabilities before performing a microcode update so that CPU capabilities can be compared before and after update. [ bp: Massage. ] Signed-off-by: Ashok Raj Signed-off-by: Borislav Petkov (AMD) Link: https://lore.kernel.org/r/20230109153555.4986-2-ashok.raj@intel.com Stable-dep-of: c0dd9245aa9e ("x86/microcode: Check CPU capabilities after late microcode update correctly") Signed-off-by: Sasha Levin [ Aichun Shi: amend commit log ] Signed-off-by: Aichun Shi --- arch/x86/include/asm/processor.h | 2 +- arch/x86/kernel/cpu/common.c | 21 +++++++++++++-------- arch/x86/kernel/cpu/microcode/core.c | 3 ++- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 014a5d982cd2..52a551a6376e 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -869,7 +869,7 @@ bool xen_set_default_idle(void); #endif void __noreturn stop_this_cpu(void *dummy); -void microcode_check(void); +void microcode_check(struct cpuinfo_x86 *prev_info); enum l1tf_mitigations { L1TF_MITIGATION_OFF, diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index e3575082c74f..8ef6a5fb0853 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -2164,31 +2164,36 @@ void cpu_init_secondary(void) #endif #ifdef CONFIG_MICROCODE_LATE_LOADING -/* +/** + * microcode_check() - Check if any CPU capabilities changed after an update. + * @prev_info: CPU capabilities stored before an update. + * * The microcode loader calls this upon late microcode load to recheck features, * only when microcode has been updated. Caller holds microcode_mutex and CPU * hotplug lock. + * + * Return: None */ -void microcode_check(void) +void microcode_check(struct cpuinfo_x86 *prev_info) { - struct cpuinfo_x86 info; - perf_check_microcode(); amd_check_microcode(); /* Reload CPUID max function as it might've changed. */ - info.cpuid_level = cpuid_eax(0); + prev_info->cpuid_level = cpuid_eax(0); /* * Copy all capability leafs to pick up the synthetic ones so that * memcmp() below doesn't fail on that. The ones coming from CPUID will * get overwritten in get_cpu_cap(). */ - memcpy(&info.x86_capability, &boot_cpu_data.x86_capability, sizeof(info.x86_capability)); + memcpy(&prev_info->x86_capability, &boot_cpu_data.x86_capability, + sizeof(prev_info->x86_capability)); - get_cpu_cap(&info); + get_cpu_cap(prev_info); - if (!memcmp(&info.x86_capability, &boot_cpu_data.x86_capability, sizeof(info.x86_capability))) + if (!memcmp(&prev_info->x86_capability, &boot_cpu_data.x86_capability, + sizeof(prev_info->x86_capability))) return; pr_warn("x86/CPU: CPU features have changed after loading microcode, but might not take effect.\n"); diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index ad1d9bc39a07..d59998b9e9db 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c @@ -619,13 +619,14 @@ static int __reload_late(void *info) static int microcode_reload_late(void) { int old = boot_cpu_data.microcode, ret; + struct cpuinfo_x86 prev_info; atomic_set(&late_cpus_in, 0); atomic_set(&late_cpus_out, 0); ret = stop_machine_cpuslocked(__reload_late, NULL, cpu_online_mask); if (ret == 0) - microcode_check(); + microcode_check(&prev_info); pr_info("Reload completed, microcode revision: 0x%x -> 0x%x\n", old, boot_cpu_data.microcode); -- Gitee From 3bb001b6eb46e49c25c6504bb442a37ac19d2559 Mon Sep 17 00:00:00 2001 From: Ashok Raj Date: Mon, 9 Jan 2023 07:35:51 -0800 Subject: [PATCH 3/5] x86/microcode: Check CPU capabilities after late microcode update correctly stable inclusion from stable-v5.10.173 commit 511e27e5fdd658e6cb06b4947fb0d3ac76163776 category: feature bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I873BU CVE: N/A Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=511e27e5fdd658e6cb06b4947fb0d3ac76163776 ------------------------------------- Intel-SIG: commit 511e27e5fdd6 x86/microcode: Check CPU capabilities after late microcode update correctly. Backport x86/microcode related patches from 5.10.173 upstream. ------------------------------------- [ Upstream commit c0dd9245aa9e25a697181f6085692272c9ec61bc ] The kernel caches each CPU's feature bits at boot in an x86_capability[] structure. However, the capabilities in the BSP's copy can be turned off as a result of certain command line parameters or configuration restrictions, for example the SGX bit. This can cause a mismatch when comparing the values before and after the microcode update. Another example is X86_FEATURE_SRBDS_CTRL which gets added only after microcode update: ^^^ and which proves for a gazillionth time that late loading is a bad bad idea. microcode_check() is called after an update to report any previously cached CPUID bits which might have changed due to the update. Therefore, store the cached CPU caps before the update and compare them with the CPU caps after the microcode update has succeeded. Thus, the comparison is done between the CPUID *hardware* bits before and after the upgrade instead of using the cached, possibly runtime modified values in BSP's boot_cpu_data copy. As a result, false warnings about CPUID bits changes are avoided. [ bp: - Massage. - Add SRBDS_CTRL example. - Add kernel-doc. - Incorporate forgotten review feedback from dhansen. ] Fixes: 1008c52c09dc ("x86/CPU: Add a microcode loader callback") Signed-off-by: Ashok Raj Signed-off-by: Borislav Petkov (AMD) Link: https://lore.kernel.org/r/20230109153555.4986-3-ashok.raj@intel.com Signed-off-by: Sasha Levin [ Aichun Shi: amend commit log ] Signed-off-by: Aichun Shi --- arch/x86/include/asm/processor.h | 1 + arch/x86/kernel/cpu/common.c | 35 ++++++++++++++++++---------- arch/x86/kernel/cpu/microcode/core.c | 6 +++++ 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 52a551a6376e..cedd2fb34654 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -870,6 +870,7 @@ bool xen_set_default_idle(void); void __noreturn stop_this_cpu(void *dummy); void microcode_check(struct cpuinfo_x86 *prev_info); +void store_cpu_caps(struct cpuinfo_x86 *info); enum l1tf_mitigations { L1TF_MITIGATION_OFF, diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 8ef6a5fb0853..ddc5e7cc40b9 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -2164,6 +2164,25 @@ void cpu_init_secondary(void) #endif #ifdef CONFIG_MICROCODE_LATE_LOADING +/** + * store_cpu_caps() - Store a snapshot of CPU capabilities + * @curr_info: Pointer where to store it + * + * Returns: None + */ +void store_cpu_caps(struct cpuinfo_x86 *curr_info) +{ + /* Reload CPUID max function as it might've changed. */ + curr_info->cpuid_level = cpuid_eax(0); + + /* Copy all capability leafs and pick up the synthetic ones. */ + memcpy(&curr_info->x86_capability, &boot_cpu_data.x86_capability, + sizeof(curr_info->x86_capability)); + + /* Get the hardware CPUID leafs */ + get_cpu_cap(curr_info); +} + /** * microcode_check() - Check if any CPU capabilities changed after an update. * @prev_info: CPU capabilities stored before an update. @@ -2176,23 +2195,15 @@ void cpu_init_secondary(void) */ void microcode_check(struct cpuinfo_x86 *prev_info) { + struct cpuinfo_x86 curr_info; + perf_check_microcode(); amd_check_microcode(); - /* Reload CPUID max function as it might've changed. */ - prev_info->cpuid_level = cpuid_eax(0); - - /* - * Copy all capability leafs to pick up the synthetic ones so that - * memcmp() below doesn't fail on that. The ones coming from CPUID will - * get overwritten in get_cpu_cap(). - */ - memcpy(&prev_info->x86_capability, &boot_cpu_data.x86_capability, - sizeof(prev_info->x86_capability)); - get_cpu_cap(prev_info); + store_cpu_caps(&curr_info); - if (!memcmp(&prev_info->x86_capability, &boot_cpu_data.x86_capability, + if (!memcmp(&prev_info->x86_capability, &curr_info.x86_capability, sizeof(prev_info->x86_capability))) return; diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index d59998b9e9db..101c12c1d2fd 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c @@ -624,6 +624,12 @@ static int microcode_reload_late(void) atomic_set(&late_cpus_in, 0); atomic_set(&late_cpus_out, 0); + /* + * Take a snapshot before the microcode update in order to compare and + * check whether any bits changed after an update. + */ + store_cpu_caps(&prev_info); + ret = stop_machine_cpuslocked(__reload_late, NULL, cpu_online_mask); if (ret == 0) microcode_check(&prev_info); -- Gitee From 6ff8de76128b8fe441ab3c5bd34f550d07e48e74 Mon Sep 17 00:00:00 2001 From: Ashok Raj Date: Mon, 9 Jan 2023 07:35:52 -0800 Subject: [PATCH 4/5] x86/microcode: Adjust late loading result reporting message stable inclusion from stable-v5.10.173 commit 8e83e1619fac9151b1515177f5066ae67b0cbda2 category: feature bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I873BU CVE: N/A Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=8e83e1619fac9151b1515177f5066ae67b0cbda2 ------------------------------------- Intel-SIG: commit 8e83e1619fac x86/microcode: Adjust late loading result reporting message. Backport x86/microcode related patches from 5.10.173 upstream. ------------------------------------- [ Upstream commit 6eab3abac7043226e5375e9ead0c7607ced6767b ] During late microcode loading, the "Reload completed" message is issued unconditionally, regardless of success or failure. Adjust the message to report the result of the update. [ bp: Massage. ] Fixes: 9bd681251b7c ("x86/microcode: Announce reload operation's completion") Suggested-by: Thomas Gleixner Signed-off-by: Ashok Raj Signed-off-by: Borislav Petkov (AMD) Reviewed-by: Tony Luck Link: https://lore.kernel.org/lkml/874judpqqd.ffs@tglx/ Signed-off-by: Sasha Levin [ Aichun Shi: amend commit log ] Signed-off-by: Aichun Shi --- arch/x86/kernel/cpu/microcode/core.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index 101c12c1d2fd..259be1d775e0 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c @@ -631,11 +631,14 @@ static int microcode_reload_late(void) store_cpu_caps(&prev_info); ret = stop_machine_cpuslocked(__reload_late, NULL, cpu_online_mask); - if (ret == 0) + if (!ret) { + pr_info("Reload succeeded, microcode revision: 0x%x -> 0x%x\n", + old, boot_cpu_data.microcode); microcode_check(&prev_info); - - pr_info("Reload completed, microcode revision: 0x%x -> 0x%x\n", - old, boot_cpu_data.microcode); + } else { + pr_info("Reload failed, current microcode revision: 0x%x\n", + boot_cpu_data.microcode); + } return ret; } -- Gitee From 9ed60efca182117c77204c65384653cd5a773995 Mon Sep 17 00:00:00 2001 From: Aichun Shi Date: Wed, 11 Oct 2023 21:21:57 +0800 Subject: [PATCH 5/5] Enabled microcode late loading as default for x86 in openeuler_defconfig Intel inclusion category: feature bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I873BU CVE: N/A ------------------------------------- Intel-SIG: openeuler_defconfig: Enabled microcode late loading as default for x86 in openeuler_defconfig. Backport x86/microcode related patches from 5.10.173 upstream. ------------------------------------- Enabled microcode late loading as default for x86 in openeuler_defconfig Signed-off-by: Aichun Shi --- arch/x86/configs/openeuler_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/configs/openeuler_defconfig b/arch/x86/configs/openeuler_defconfig index 203c5e353d94..70750263854e 100644 --- a/arch/x86/configs/openeuler_defconfig +++ b/arch/x86/configs/openeuler_defconfig @@ -414,6 +414,7 @@ CONFIG_MICROCODE=y CONFIG_MICROCODE_INTEL=y CONFIG_MICROCODE_AMD=y CONFIG_MICROCODE_OLD_INTERFACE=y +CONFIG_MICROCODE_LATE_LOADING=y CONFIG_X86_MSR=y CONFIG_X86_CPUID=y CONFIG_X86_5LEVEL=y -- Gitee