x86/microcode: Clarify the late load logic
authorThomas Gleixner <tglx@linutronix.de>
Mon, 2 Oct 2023 11:59:57 +0000 (13:59 +0200)
committerBorislav Petkov (AMD) <bp@alien8.de>
Tue, 24 Oct 2023 13:05:54 +0000 (15:05 +0200)
reload_store() is way too complicated. Split the inner workings out and
make the following enhancements:

 - Taint the kernel only when the microcode was actually updated. If. e.g.
   the rendezvous fails, then nothing happened and there is no reason for
   tainting.

 - Return useful error codes

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Nikolay Borisov <nik.borisov@suse.com>
Link: https://lore.kernel.org/r/20231002115903.145048840@linutronix.de
arch/x86/kernel/cpu/microcode/core.c

index 7af1b60527ec40f2c03994baa7f75857fa970bc5..63c4e120d7fd35bb10be8015b56de581ff40674e 100644 (file)
@@ -362,11 +362,11 @@ static int microcode_reload_late(void)
                pr_info("Reload succeeded, microcode revision: 0x%x -> 0x%x\n",
                        old, boot_cpu_data.microcode);
                microcode_check(&prev_info);
+               add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
        } else {
                pr_info("Reload failed, current microcode revision: 0x%x\n",
                        boot_cpu_data.microcode);
        }
-
        return ret;
 }
 
@@ -399,40 +399,37 @@ static bool ensure_cpus_are_online(void)
        return true;
 }
 
+static int ucode_load_late_locked(void)
+{
+       if (!ensure_cpus_are_online())
+               return -EBUSY;
+
+       switch (microcode_ops->request_microcode_fw(0, &microcode_pdev->dev)) {
+       case UCODE_NEW:
+               return microcode_reload_late();
+       case UCODE_NFOUND:
+               return -ENOENT;
+       default:
+               return -EBADFD;
+       }
+}
+
 static ssize_t reload_store(struct device *dev,
                            struct device_attribute *attr,
                            const char *buf, size_t size)
 {
-       enum ucode_state tmp_ret = UCODE_OK;
-       int bsp = boot_cpu_data.cpu_index;
        unsigned long val;
-       ssize_t ret = 0;
+       ssize_t ret;
 
        ret = kstrtoul(buf, 0, &val);
        if (ret || val != 1)
                return -EINVAL;
 
        cpus_read_lock();
-
-       if (!ensure_cpus_are_online()) {
-               ret = -EBUSY;
-               goto put;
-       }
-
-       tmp_ret = microcode_ops->request_microcode_fw(bsp, &microcode_pdev->dev);
-       if (tmp_ret != UCODE_NEW)
-               goto put;
-
-       ret = microcode_reload_late();
-put:
+       ret = ucode_load_late_locked();
        cpus_read_unlock();
 
-       if (ret == 0)
-               ret = size;
-
-       add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
-
-       return ret;
+       return ret ? : size;
 }
 
 static DEVICE_ATTR_WO(reload);