All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] x86/microcode: Add a microcode loader callback
@ 2018-02-16 11:26 Borislav Petkov
  2018-02-16 11:26 ` [PATCH 1/3] x86/microcode: Propagate return value from updating functions Borislav Petkov
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Borislav Petkov @ 2018-02-16 11:26 UTC (permalink / raw)
  To: Ashok Raj; +Cc: X86 ML, LKML

From: Borislav Petkov <bp@suse.de>

Add a callback which the microcode loader calls after microcode has been
upgraded late to let the user know that any CPUID changes potentially
won't take effect.

One possible example for this is that late loading happens after
alternatives have run and thus patching which relies on those new CPUID
features won't happen.

@Ashok: I haven't added your tags yet because I did a small change to
run the callback only when no error has been encountered during loading.
Please run them on your setup to confirm everything's still fine.

Thanks.

Borislav Petkov (3):
  x86/microcode: Propagate return value from updating functions
  x86/CPU: Add a microcode loader callback
  x86/CPU: Check CPU feature bits after microcode upgrade

 arch/x86/include/asm/microcode.h      |  9 ++++++--
 arch/x86/include/asm/processor.h      |  1 +
 arch/x86/kernel/cpu/common.c          | 30 +++++++++++++++++++++++++++
 arch/x86/kernel/cpu/microcode/amd.c   | 10 ++++-----
 arch/x86/kernel/cpu/microcode/core.c  | 39 ++++++++++++++++++++---------------
 arch/x86/kernel/cpu/microcode/intel.c | 10 ++++-----
 6 files changed, 70 insertions(+), 29 deletions(-)

-- 
2.13.0

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/3] x86/microcode: Propagate return value from updating functions
  2018-02-16 11:26 [PATCH 0/3] x86/microcode: Add a microcode loader callback Borislav Petkov
@ 2018-02-16 11:26 ` Borislav Petkov
  2018-02-17 10:12   ` [tip:x86/pti] " tip-bot for Borislav Petkov
  2018-02-16 11:26 ` [PATCH 2/3] x86/CPU: Add a microcode loader callback Borislav Petkov
  2018-02-16 11:26 ` [PATCH 3/3] x86/CPU: Check CPU feature bits after microcode upgrade Borislav Petkov
  2 siblings, 1 reply; 10+ messages in thread
From: Borislav Petkov @ 2018-02-16 11:26 UTC (permalink / raw)
  To: Ashok Raj; +Cc: X86 ML, LKML

From: Borislav Petkov <bp@suse.de>

... so that callers can know when microcode was updated and act
accordingly.

Signed-off-by: Borislav Petkov <bp@suse.de>
---
 arch/x86/include/asm/microcode.h      |  9 +++++++--
 arch/x86/kernel/cpu/microcode/amd.c   | 10 +++++-----
 arch/x86/kernel/cpu/microcode/core.c  | 33 +++++++++++++++++----------------
 arch/x86/kernel/cpu/microcode/intel.c | 10 +++++-----
 4 files changed, 34 insertions(+), 28 deletions(-)

diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h
index 55520cec8b27..7fb1047d61c7 100644
--- a/arch/x86/include/asm/microcode.h
+++ b/arch/x86/include/asm/microcode.h
@@ -37,7 +37,12 @@ struct cpu_signature {
 
 struct device;
 
-enum ucode_state { UCODE_ERROR, UCODE_OK, UCODE_NFOUND };
+enum ucode_state {
+	UCODE_OK	= 0,
+	UCODE_UPDATED,
+	UCODE_NFOUND,
+	UCODE_ERROR,
+};
 
 struct microcode_ops {
 	enum ucode_state (*request_microcode_user) (int cpu,
@@ -54,7 +59,7 @@ struct microcode_ops {
 	 * are being called.
 	 * See also the "Synchronization" section in microcode_core.c.
 	 */
-	int (*apply_microcode) (int cpu);
+	enum ucode_state (*apply_microcode) (int cpu);
 	int (*collect_cpu_info) (int cpu, struct cpu_signature *csig);
 };
 
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
index 330b8462d426..a998e1a7d46f 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -498,7 +498,7 @@ static unsigned int verify_patch_size(u8 family, u32 patch_size,
 	return patch_size;
 }
 
-static int apply_microcode_amd(int cpu)
+static enum ucode_state apply_microcode_amd(int cpu)
 {
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
 	struct microcode_amd *mc_amd;
@@ -512,7 +512,7 @@ static int apply_microcode_amd(int cpu)
 
 	p = find_patch(cpu);
 	if (!p)
-		return 0;
+		return UCODE_NFOUND;
 
 	mc_amd  = p->data;
 	uci->mc = p->data;
@@ -523,13 +523,13 @@ static int apply_microcode_amd(int cpu)
 	if (rev >= mc_amd->hdr.patch_id) {
 		c->microcode = rev;
 		uci->cpu_sig.rev = rev;
-		return 0;
+		return UCODE_OK;
 	}
 
 	if (__apply_microcode_amd(mc_amd)) {
 		pr_err("CPU%d: update failed for patch_level=0x%08x\n",
 			cpu, mc_amd->hdr.patch_id);
-		return -1;
+		return UCODE_ERROR;
 	}
 	pr_info("CPU%d: new patch_level=0x%08x\n", cpu,
 		mc_amd->hdr.patch_id);
@@ -537,7 +537,7 @@ static int apply_microcode_amd(int cpu)
 	uci->cpu_sig.rev = mc_amd->hdr.patch_id;
 	c->microcode = mc_amd->hdr.patch_id;
 
-	return 0;
+	return UCODE_UPDATED;
 }
 
 static int install_equiv_cpu_table(const u8 *buf)
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 319dd65f98a2..6fdaf7cf3182 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -374,7 +374,7 @@ static int collect_cpu_info(int cpu)
 }
 
 struct apply_microcode_ctx {
-	int err;
+	enum ucode_state err;
 };
 
 static void apply_microcode_local(void *arg)
@@ -489,31 +489,29 @@ static void __exit microcode_dev_exit(void)
 /* fake device for request_firmware */
 static struct platform_device	*microcode_pdev;
 
-static int reload_for_cpu(int cpu)
+static enum ucode_state reload_for_cpu(int cpu)
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 	enum ucode_state ustate;
-	int err = 0;
 
 	if (!uci->valid)
-		return err;
+		return UCODE_OK;
 
 	ustate = microcode_ops->request_microcode_fw(cpu, &microcode_pdev->dev, true);
-	if (ustate == UCODE_OK)
-		apply_microcode_on_target(cpu);
-	else
-		if (ustate == UCODE_ERROR)
-			err = -EINVAL;
-	return err;
+	if (ustate != UCODE_OK)
+		return ustate;
+
+	return apply_microcode_on_target(cpu);
 }
 
 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;
 	unsigned long val;
+	ssize_t ret = 0;
 	int cpu;
-	ssize_t ret = 0, tmp_ret;
 
 	ret = kstrtoul(buf, 0, &val);
 	if (ret)
@@ -526,15 +524,18 @@ static ssize_t reload_store(struct device *dev,
 	mutex_lock(&microcode_mutex);
 	for_each_online_cpu(cpu) {
 		tmp_ret = reload_for_cpu(cpu);
-		if (tmp_ret != 0)
+		if (tmp_ret > UCODE_NFOUND) {
 			pr_warn("Error reloading microcode on CPU %d\n", cpu);
 
-		/* save retval of the first encountered reload error */
-		if (!ret)
-			ret = tmp_ret;
+			/* set retval for the first encountered reload error */
+			if (!ret)
+				ret = -EINVAL;
+		}
 	}
-	if (!ret)
+
+	if (!ret && tmp_ret == UCODE_UPDATED)
 		perf_check_microcode();
+
 	mutex_unlock(&microcode_mutex);
 	put_online_cpus();
 
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index f7c55b0e753a..09b95a7b5dff 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -772,7 +772,7 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
 	return 0;
 }
 
-static int apply_microcode_intel(int cpu)
+static enum ucode_state apply_microcode_intel(int cpu)
 {
 	struct microcode_intel *mc;
 	struct ucode_cpu_info *uci;
@@ -782,7 +782,7 @@ static int apply_microcode_intel(int cpu)
 
 	/* We should bind the task to the CPU */
 	if (WARN_ON(raw_smp_processor_id() != cpu))
-		return -1;
+		return UCODE_ERROR;
 
 	uci = ucode_cpu_info + cpu;
 	mc = uci->mc;
@@ -790,7 +790,7 @@ static int apply_microcode_intel(int cpu)
 		/* Look for a newer patch in our cache: */
 		mc = find_patch(uci);
 		if (!mc)
-			return 0;
+			return UCODE_NFOUND;
 	}
 
 	/* write microcode via MSR 0x79 */
@@ -801,7 +801,7 @@ static int apply_microcode_intel(int cpu)
 	if (rev != mc->hdr.rev) {
 		pr_err("CPU%d update to revision 0x%x failed\n",
 		       cpu, mc->hdr.rev);
-		return -1;
+		return UCODE_ERROR;
 	}
 
 	if (rev != prev_rev) {
@@ -818,7 +818,7 @@ static int apply_microcode_intel(int cpu)
 	uci->cpu_sig.rev = rev;
 	c->microcode = rev;
 
-	return 0;
+	return UCODE_UPDATED;
 }
 
 static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
-- 
2.13.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/3] x86/CPU: Add a microcode loader callback
  2018-02-16 11:26 [PATCH 0/3] x86/microcode: Add a microcode loader callback Borislav Petkov
  2018-02-16 11:26 ` [PATCH 1/3] x86/microcode: Propagate return value from updating functions Borislav Petkov
@ 2018-02-16 11:26 ` Borislav Petkov
  2018-02-17 10:12   ` [tip:x86/pti] " tip-bot for Borislav Petkov
  2018-02-17 13:07   ` [PATCH 2/3] " Raj, Ashok
  2018-02-16 11:26 ` [PATCH 3/3] x86/CPU: Check CPU feature bits after microcode upgrade Borislav Petkov
  2 siblings, 2 replies; 10+ messages in thread
From: Borislav Petkov @ 2018-02-16 11:26 UTC (permalink / raw)
  To: Ashok Raj; +Cc: X86 ML, LKML

From: Borislav Petkov <bp@suse.de>

Add a callback function which the microcode loader calls when microcode
has been updated to a newer revision. Do the callback only when no error
was encountered during loading.

Signed-off-by: Borislav Petkov <bp@suse.de>
---
 arch/x86/include/asm/processor.h     |  1 +
 arch/x86/kernel/cpu/common.c         | 10 ++++++++++
 arch/x86/kernel/cpu/microcode/core.c |  8 ++++++--
 3 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 23fdaf4ec925..856669b90a0c 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -977,4 +977,5 @@ bool xen_set_default_idle(void);
 
 void stop_this_cpu(void *dummy);
 void df_debug(struct pt_regs *regs, long error_code);
+void microcode_check(void);
 #endif /* _ASM_X86_PROCESSOR_H */
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index d63f4b5706e4..82c142b33bf3 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1749,3 +1749,13 @@ static int __init init_cpu_syscore(void)
 	return 0;
 }
 core_initcall(init_cpu_syscore);
+
+/*
+ * 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.
+ */
+void microcode_check(void)
+{
+	perf_check_microcode();
+}
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 6fdaf7cf3182..aa1b9a422f2b 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -509,6 +509,7 @@ static ssize_t reload_store(struct device *dev,
 			    const char *buf, size_t size)
 {
 	enum ucode_state tmp_ret = UCODE_OK;
+	bool do_callback = false;
 	unsigned long val;
 	ssize_t ret = 0;
 	int cpu;
@@ -531,10 +532,13 @@ static ssize_t reload_store(struct device *dev,
 			if (!ret)
 				ret = -EINVAL;
 		}
+
+		if (tmp_ret == UCODE_UPDATED)
+			do_callback = true;
 	}
 
-	if (!ret && tmp_ret == UCODE_UPDATED)
-		perf_check_microcode();
+	if (!ret && do_callback)
+		microcode_check();
 
 	mutex_unlock(&microcode_mutex);
 	put_online_cpus();
-- 
2.13.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/3] x86/CPU: Check CPU feature bits after microcode upgrade
  2018-02-16 11:26 [PATCH 0/3] x86/microcode: Add a microcode loader callback Borislav Petkov
  2018-02-16 11:26 ` [PATCH 1/3] x86/microcode: Propagate return value from updating functions Borislav Petkov
  2018-02-16 11:26 ` [PATCH 2/3] x86/CPU: Add a microcode loader callback Borislav Petkov
@ 2018-02-16 11:26 ` Borislav Petkov
  2018-02-17 10:13   ` [tip:x86/pti] " tip-bot for Borislav Petkov
  2 siblings, 1 reply; 10+ messages in thread
From: Borislav Petkov @ 2018-02-16 11:26 UTC (permalink / raw)
  To: Ashok Raj; +Cc: X86 ML, LKML

From: Borislav Petkov <bp@suse.de>

With some microcode upgrades, new CPUID features can become visible on
the CPU. Check what the kernel has mirrored now and issue a warning
hinting at possible things the user/admin can do to make use of the
newly visible features.

Originally-by: Ashok Raj <ashok.raj@intel.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
---
 arch/x86/kernel/cpu/common.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 82c142b33bf3..768eb680db8d 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1757,5 +1757,25 @@ core_initcall(init_cpu_syscore);
  */
 void microcode_check(void)
 {
+	struct cpuinfo_x86 info;
+
 	perf_check_microcode();
+
+	/* Reload CPUID max function as it might've changed. */
+	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));
+
+	get_cpu_cap(&info);
+
+	if (!memcmp(&info.x86_capability, &boot_cpu_data.x86_capability, sizeof(info.x86_capability)))
+		return;
+
+	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");
 }
-- 
2.13.0

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [tip:x86/pti] x86/microcode: Propagate return value from updating functions
  2018-02-16 11:26 ` [PATCH 1/3] x86/microcode: Propagate return value from updating functions Borislav Petkov
@ 2018-02-17 10:12   ` tip-bot for Borislav Petkov
  0 siblings, 0 replies; 10+ messages in thread
From: tip-bot for Borislav Petkov @ 2018-02-17 10:12 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: dan.j.williams, peterz, jpoimboe, bp, tglx, linux-kernel, dwmw2,
	bp, arjan, torvalds, gregkh, mingo, ashok.raj, dave.hansen, luto,
	hpa

Commit-ID:  3f1f576a195aa266813cbd4ca70291deb61e0129
Gitweb:     https://git.kernel.org/tip/3f1f576a195aa266813cbd4ca70291deb61e0129
Author:     Borislav Petkov <bp@suse.de>
AuthorDate: Fri, 16 Feb 2018 12:26:38 +0100
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Sat, 17 Feb 2018 08:43:55 +0100

x86/microcode: Propagate return value from updating functions

... so that callers can know when microcode was updated and act
accordingly.

Tested-by: Ashok Raj <ashok.raj@intel.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Ashok Raj <ashok.raj@intel.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20180216112640.11554-2-bp@alien8.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/include/asm/microcode.h      |  9 +++++++--
 arch/x86/kernel/cpu/microcode/amd.c   | 10 +++++-----
 arch/x86/kernel/cpu/microcode/core.c  | 33 +++++++++++++++++----------------
 arch/x86/kernel/cpu/microcode/intel.c | 10 +++++-----
 4 files changed, 34 insertions(+), 28 deletions(-)

diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h
index 55520cec..7fb1047 100644
--- a/arch/x86/include/asm/microcode.h
+++ b/arch/x86/include/asm/microcode.h
@@ -37,7 +37,12 @@ struct cpu_signature {
 
 struct device;
 
-enum ucode_state { UCODE_ERROR, UCODE_OK, UCODE_NFOUND };
+enum ucode_state {
+	UCODE_OK	= 0,
+	UCODE_UPDATED,
+	UCODE_NFOUND,
+	UCODE_ERROR,
+};
 
 struct microcode_ops {
 	enum ucode_state (*request_microcode_user) (int cpu,
@@ -54,7 +59,7 @@ struct microcode_ops {
 	 * are being called.
 	 * See also the "Synchronization" section in microcode_core.c.
 	 */
-	int (*apply_microcode) (int cpu);
+	enum ucode_state (*apply_microcode) (int cpu);
 	int (*collect_cpu_info) (int cpu, struct cpu_signature *csig);
 };
 
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
index 330b846..a998e1a 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -498,7 +498,7 @@ static unsigned int verify_patch_size(u8 family, u32 patch_size,
 	return patch_size;
 }
 
-static int apply_microcode_amd(int cpu)
+static enum ucode_state apply_microcode_amd(int cpu)
 {
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
 	struct microcode_amd *mc_amd;
@@ -512,7 +512,7 @@ static int apply_microcode_amd(int cpu)
 
 	p = find_patch(cpu);
 	if (!p)
-		return 0;
+		return UCODE_NFOUND;
 
 	mc_amd  = p->data;
 	uci->mc = p->data;
@@ -523,13 +523,13 @@ static int apply_microcode_amd(int cpu)
 	if (rev >= mc_amd->hdr.patch_id) {
 		c->microcode = rev;
 		uci->cpu_sig.rev = rev;
-		return 0;
+		return UCODE_OK;
 	}
 
 	if (__apply_microcode_amd(mc_amd)) {
 		pr_err("CPU%d: update failed for patch_level=0x%08x\n",
 			cpu, mc_amd->hdr.patch_id);
-		return -1;
+		return UCODE_ERROR;
 	}
 	pr_info("CPU%d: new patch_level=0x%08x\n", cpu,
 		mc_amd->hdr.patch_id);
@@ -537,7 +537,7 @@ static int apply_microcode_amd(int cpu)
 	uci->cpu_sig.rev = mc_amd->hdr.patch_id;
 	c->microcode = mc_amd->hdr.patch_id;
 
-	return 0;
+	return UCODE_UPDATED;
 }
 
 static int install_equiv_cpu_table(const u8 *buf)
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 319dd65..6fdaf7c 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -374,7 +374,7 @@ static int collect_cpu_info(int cpu)
 }
 
 struct apply_microcode_ctx {
-	int err;
+	enum ucode_state err;
 };
 
 static void apply_microcode_local(void *arg)
@@ -489,31 +489,29 @@ static void __exit microcode_dev_exit(void)
 /* fake device for request_firmware */
 static struct platform_device	*microcode_pdev;
 
-static int reload_for_cpu(int cpu)
+static enum ucode_state reload_for_cpu(int cpu)
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 	enum ucode_state ustate;
-	int err = 0;
 
 	if (!uci->valid)
-		return err;
+		return UCODE_OK;
 
 	ustate = microcode_ops->request_microcode_fw(cpu, &microcode_pdev->dev, true);
-	if (ustate == UCODE_OK)
-		apply_microcode_on_target(cpu);
-	else
-		if (ustate == UCODE_ERROR)
-			err = -EINVAL;
-	return err;
+	if (ustate != UCODE_OK)
+		return ustate;
+
+	return apply_microcode_on_target(cpu);
 }
 
 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;
 	unsigned long val;
+	ssize_t ret = 0;
 	int cpu;
-	ssize_t ret = 0, tmp_ret;
 
 	ret = kstrtoul(buf, 0, &val);
 	if (ret)
@@ -526,15 +524,18 @@ static ssize_t reload_store(struct device *dev,
 	mutex_lock(&microcode_mutex);
 	for_each_online_cpu(cpu) {
 		tmp_ret = reload_for_cpu(cpu);
-		if (tmp_ret != 0)
+		if (tmp_ret > UCODE_NFOUND) {
 			pr_warn("Error reloading microcode on CPU %d\n", cpu);
 
-		/* save retval of the first encountered reload error */
-		if (!ret)
-			ret = tmp_ret;
+			/* set retval for the first encountered reload error */
+			if (!ret)
+				ret = -EINVAL;
+		}
 	}
-	if (!ret)
+
+	if (!ret && tmp_ret == UCODE_UPDATED)
 		perf_check_microcode();
+
 	mutex_unlock(&microcode_mutex);
 	put_online_cpus();
 
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index a15db2b..923054a 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -772,7 +772,7 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
 	return 0;
 }
 
-static int apply_microcode_intel(int cpu)
+static enum ucode_state apply_microcode_intel(int cpu)
 {
 	struct microcode_intel *mc;
 	struct ucode_cpu_info *uci;
@@ -782,7 +782,7 @@ static int apply_microcode_intel(int cpu)
 
 	/* We should bind the task to the CPU */
 	if (WARN_ON(raw_smp_processor_id() != cpu))
-		return -1;
+		return UCODE_ERROR;
 
 	uci = ucode_cpu_info + cpu;
 	mc = uci->mc;
@@ -790,7 +790,7 @@ static int apply_microcode_intel(int cpu)
 		/* Look for a newer patch in our cache: */
 		mc = find_patch(uci);
 		if (!mc)
-			return 0;
+			return UCODE_NFOUND;
 	}
 
 	/* write microcode via MSR 0x79 */
@@ -801,7 +801,7 @@ static int apply_microcode_intel(int cpu)
 	if (rev != mc->hdr.rev) {
 		pr_err("CPU%d update to revision 0x%x failed\n",
 		       cpu, mc->hdr.rev);
-		return -1;
+		return UCODE_ERROR;
 	}
 
 	if (rev != prev_rev) {
@@ -818,7 +818,7 @@ static int apply_microcode_intel(int cpu)
 	uci->cpu_sig.rev = rev;
 	c->microcode = rev;
 
-	return 0;
+	return UCODE_UPDATED;
 }
 
 static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [tip:x86/pti] x86/CPU: Add a microcode loader callback
  2018-02-16 11:26 ` [PATCH 2/3] x86/CPU: Add a microcode loader callback Borislav Petkov
@ 2018-02-17 10:12   ` tip-bot for Borislav Petkov
  2018-02-17 13:07   ` [PATCH 2/3] " Raj, Ashok
  1 sibling, 0 replies; 10+ messages in thread
From: tip-bot for Borislav Petkov @ 2018-02-17 10:12 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: bp, ashok.raj, luto, bp, arjan, gregkh, hpa, dwmw2,
	dan.j.williams, torvalds, peterz, tglx, mingo, jpoimboe,
	linux-kernel, dave.hansen

Commit-ID:  1008c52c09dcb23d93f8e0ea83a6246265d2cce0
Gitweb:     https://git.kernel.org/tip/1008c52c09dcb23d93f8e0ea83a6246265d2cce0
Author:     Borislav Petkov <bp@suse.de>
AuthorDate: Fri, 16 Feb 2018 12:26:39 +0100
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Sat, 17 Feb 2018 08:43:55 +0100

x86/CPU: Add a microcode loader callback

Add a callback function which the microcode loader calls when microcode
has been updated to a newer revision. Do the callback only when no error
was encountered during loading.

Tested-by: Ashok Raj <ashok.raj@intel.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Ashok Raj <ashok.raj@intel.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20180216112640.11554-3-bp@alien8.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/include/asm/processor.h     |  1 +
 arch/x86/kernel/cpu/common.c         | 10 ++++++++++
 arch/x86/kernel/cpu/microcode/core.c |  8 ++++++--
 3 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 1bd9ed8..b0ccd48 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -977,4 +977,5 @@ bool xen_set_default_idle(void);
 
 void stop_this_cpu(void *dummy);
 void df_debug(struct pt_regs *regs, long error_code);
+void microcode_check(void);
 #endif /* _ASM_X86_PROCESSOR_H */
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 824aee0..84f1cd8 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1749,3 +1749,13 @@ static int __init init_cpu_syscore(void)
 	return 0;
 }
 core_initcall(init_cpu_syscore);
+
+/*
+ * 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.
+ */
+void microcode_check(void)
+{
+	perf_check_microcode();
+}
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 6fdaf7c..aa1b9a4 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -509,6 +509,7 @@ static ssize_t reload_store(struct device *dev,
 			    const char *buf, size_t size)
 {
 	enum ucode_state tmp_ret = UCODE_OK;
+	bool do_callback = false;
 	unsigned long val;
 	ssize_t ret = 0;
 	int cpu;
@@ -531,10 +532,13 @@ static ssize_t reload_store(struct device *dev,
 			if (!ret)
 				ret = -EINVAL;
 		}
+
+		if (tmp_ret == UCODE_UPDATED)
+			do_callback = true;
 	}
 
-	if (!ret && tmp_ret == UCODE_UPDATED)
-		perf_check_microcode();
+	if (!ret && do_callback)
+		microcode_check();
 
 	mutex_unlock(&microcode_mutex);
 	put_online_cpus();

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [tip:x86/pti] x86/CPU: Check CPU feature bits after microcode upgrade
  2018-02-16 11:26 ` [PATCH 3/3] x86/CPU: Check CPU feature bits after microcode upgrade Borislav Petkov
@ 2018-02-17 10:13   ` tip-bot for Borislav Petkov
  0 siblings, 0 replies; 10+ messages in thread
From: tip-bot for Borislav Petkov @ 2018-02-17 10:13 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: arjan, dan.j.williams, mingo, luto, bp, gregkh, hpa, dwmw2,
	linux-kernel, torvalds, ashok.raj, dave.hansen, bp, peterz,
	jpoimboe, tglx

Commit-ID:  42ca8082e260dcfd8afa2afa6ec1940b9d41724c
Gitweb:     https://git.kernel.org/tip/42ca8082e260dcfd8afa2afa6ec1940b9d41724c
Author:     Borislav Petkov <bp@suse.de>
AuthorDate: Fri, 16 Feb 2018 12:26:40 +0100
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Sat, 17 Feb 2018 08:43:55 +0100

x86/CPU: Check CPU feature bits after microcode upgrade

With some microcode upgrades, new CPUID features can become visible on
the CPU. Check what the kernel has mirrored now and issue a warning
hinting at possible things the user/admin can do to make use of the
newly visible features.

Originally-by: Ashok Raj <ashok.raj@intel.com>
Tested-by: Ashok Raj <ashok.raj@intel.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Ashok Raj <ashok.raj@intel.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20180216112640.11554-4-bp@alien8.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/kernel/cpu/common.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 84f1cd8..348cf48 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1757,5 +1757,25 @@ core_initcall(init_cpu_syscore);
  */
 void microcode_check(void)
 {
+	struct cpuinfo_x86 info;
+
 	perf_check_microcode();
+
+	/* Reload CPUID max function as it might've changed. */
+	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));
+
+	get_cpu_cap(&info);
+
+	if (!memcmp(&info.x86_capability, &boot_cpu_data.x86_capability, sizeof(info.x86_capability)))
+		return;
+
+	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");
 }

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] x86/CPU: Add a microcode loader callback
  2018-02-16 11:26 ` [PATCH 2/3] x86/CPU: Add a microcode loader callback Borislav Petkov
  2018-02-17 10:12   ` [tip:x86/pti] " tip-bot for Borislav Petkov
@ 2018-02-17 13:07   ` Raj, Ashok
  2018-02-17 13:28     ` Borislav Petkov
  1 sibling, 1 reply; 10+ messages in thread
From: Raj, Ashok @ 2018-02-17 13:07 UTC (permalink / raw)
  To: Borislav Petkov; +Cc: X86 ML, LKML, Ingo Molnar, Ashok Raj

Hi Boris

Sorry this is coming late... Thought i mentioned it earlier.

On Fri, Feb 16, 2018 at 12:26:39PM +0100, Borislav Petkov wrote:
>  3 files changed, 17 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
> index 23fdaf4ec925..856669b90a0c 100644
> --- a/arch/x86/include/asm/processor.h
> +++ b/arch/x86/include/asm/processor.h
> @@ -977,4 +977,5 @@ bool xen_set_default_idle(void);
>  
>  void stop_this_cpu(void *dummy);
>  void df_debug(struct pt_regs *regs, long error_code);
> +void microcode_check(void);

microcode_check() is only called from microcode/core.c

Could you only list it there instead? common.c has no other
microcode related functions other than this.?

Cheers,
Ashok

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] x86/CPU: Add a microcode loader callback
  2018-02-17 13:07   ` [PATCH 2/3] " Raj, Ashok
@ 2018-02-17 13:28     ` Borislav Petkov
  2018-02-17 17:06       ` Raj, Ashok
  0 siblings, 1 reply; 10+ messages in thread
From: Borislav Petkov @ 2018-02-17 13:28 UTC (permalink / raw)
  To: Raj, Ashok; +Cc: X86 ML, LKML, Ingo Molnar

On Sat, Feb 17, 2018 at 05:07:53AM -0800, Raj, Ashok wrote:
> Could you only list it there instead? common.c has no other
> microcode related functions other than this.?

I already explained that to you: this function is called by the loader
but it uses facilities which are closer to cpu/common.c - get_cpu_cap(),
etc.

Also, this file will be split eventually after the CPUID cleanup.

So it could just as well be called recheck_cpu_caps(), without the
"microcode" prefix.

So no need to do anything now.

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] x86/CPU: Add a microcode loader callback
  2018-02-17 13:28     ` Borislav Petkov
@ 2018-02-17 17:06       ` Raj, Ashok
  0 siblings, 0 replies; 10+ messages in thread
From: Raj, Ashok @ 2018-02-17 17:06 UTC (permalink / raw)
  To: Borislav Petkov; +Cc: X86 ML, LKML, Ingo Molnar

On Sat, Feb 17, 2018 at 02:28:00PM +0100, Borislav Petkov wrote:
> On Sat, Feb 17, 2018 at 05:07:53AM -0800, Raj, Ashok wrote:
> > Could you only list it there instead? common.c has no other
> > microcode related functions other than this.?
> 
> I already explained that to you: this function is called by the loader
> but it uses facilities which are closer to cpu/common.c - get_cpu_cap(),
> etc.
> 
> Also, this file will be split eventually after the CPUID cleanup.
> 
> So it could just as well be called recheck_cpu_caps(), without the
> "microcode" prefix.

Never mind.. now that rings a bell :-)

> 
> So no need to do anything now.
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2018-02-17 17:06 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-16 11:26 [PATCH 0/3] x86/microcode: Add a microcode loader callback Borislav Petkov
2018-02-16 11:26 ` [PATCH 1/3] x86/microcode: Propagate return value from updating functions Borislav Petkov
2018-02-17 10:12   ` [tip:x86/pti] " tip-bot for Borislav Petkov
2018-02-16 11:26 ` [PATCH 2/3] x86/CPU: Add a microcode loader callback Borislav Petkov
2018-02-17 10:12   ` [tip:x86/pti] " tip-bot for Borislav Petkov
2018-02-17 13:07   ` [PATCH 2/3] " Raj, Ashok
2018-02-17 13:28     ` Borislav Petkov
2018-02-17 17:06       ` Raj, Ashok
2018-02-16 11:26 ` [PATCH 3/3] x86/CPU: Check CPU feature bits after microcode upgrade Borislav Petkov
2018-02-17 10:13   ` [tip:x86/pti] " tip-bot for Borislav Petkov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.