| From d14ee681bd82970f11fa3fe6e3fd4d8eca53b09c Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 19 Mar 2021 09:55:15 -0700 |
| Subject: x86/microcode: Check for offline CPUs before requesting new microcode |
| |
| From: Otavio Pontes <otavio.pontes@intel.com> |
| |
| [ Upstream commit 7189b3c11903667808029ec9766a6e96de5012a5 ] |
| |
| Currently, the late microcode loading mechanism checks whether any CPUs |
| are offlined, and, in such a case, aborts the load attempt. |
| |
| However, this must be done before the kernel caches new microcode from |
| the filesystem. Otherwise, when offlined CPUs are onlined later, those |
| cores are going to be updated through the CPU hotplug notifier callback |
| with the new microcode, while CPUs previously onine will continue to run |
| with the older microcode. |
| |
| For example: |
| |
| Turn off one core (2 threads): |
| |
| echo 0 > /sys/devices/system/cpu/cpu3/online |
| echo 0 > /sys/devices/system/cpu/cpu1/online |
| |
| Install the ucode fails because a primary SMT thread is offline: |
| |
| cp intel-ucode/06-8e-09 /lib/firmware/intel-ucode/ |
| echo 1 > /sys/devices/system/cpu/microcode/reload |
| bash: echo: write error: Invalid argument |
| |
| Turn the core back on |
| |
| echo 1 > /sys/devices/system/cpu/cpu3/online |
| echo 1 > /sys/devices/system/cpu/cpu1/online |
| cat /proc/cpuinfo |grep microcode |
| microcode : 0x30 |
| microcode : 0xde |
| microcode : 0x30 |
| microcode : 0xde |
| |
| The rationale for why the update is aborted when at least one primary |
| thread is offline is because even if that thread is soft-offlined |
| and idle, it will still have to participate in broadcasted MCE's |
| synchronization dance or enter SMM, and in both examples it will execute |
| instructions so it better have the same microcode revision as the other |
| cores. |
| |
| [ bp: Heavily edit and extend commit message with the reasoning behind all |
| this. ] |
| |
| Fixes: 30ec26da9967 ("x86/microcode: Do not upload microcode if CPUs are offline") |
| Signed-off-by: Otavio Pontes <otavio.pontes@intel.com> |
| Signed-off-by: Borislav Petkov <bp@suse.de> |
| Reviewed-by: Tony Luck <tony.luck@intel.com> |
| Acked-by: Ashok Raj <ashok.raj@intel.com> |
| Link: https://lkml.kernel.org/r/20210319165515.9240-2-otavio.pontes@intel.com |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| arch/x86/kernel/cpu/microcode/core.c | 8 ++++---- |
| 1 file changed, 4 insertions(+), 4 deletions(-) |
| |
| diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c |
| index ec6f0415bc6d..bbbd248fe913 100644 |
| --- a/arch/x86/kernel/cpu/microcode/core.c |
| +++ b/arch/x86/kernel/cpu/microcode/core.c |
| @@ -629,16 +629,16 @@ static ssize_t reload_store(struct device *dev, |
| if (val != 1) |
| return size; |
| |
| - tmp_ret = microcode_ops->request_microcode_fw(bsp, µcode_pdev->dev, true); |
| - if (tmp_ret != UCODE_NEW) |
| - return size; |
| - |
| get_online_cpus(); |
| |
| ret = check_online_cpus(); |
| if (ret) |
| goto put; |
| |
| + tmp_ret = microcode_ops->request_microcode_fw(bsp, µcode_pdev->dev, true); |
| + if (tmp_ret != UCODE_NEW) |
| + goto put; |
| + |
| mutex_lock(µcode_mutex); |
| ret = microcode_reload_late(); |
| mutex_unlock(µcode_mutex); |
| -- |
| 2.30.2 |
| |