Skip to contentSkip to conversation

Add a microcode disable chicken bit

PATCH New Borislav Petkov 2 participants 5 messages May 19, 2014 – May 21, 2014

Subsystems (2)
lore
Share & tools
lore

Borislav Petkov

author maintainer
#0 lore raw

cover Add a microcode disable chicken bit

From: Borislav Petkov <[email protected]>

Hi,

so there are situations where we want to be able to turn off the microcode loader, especially the early part, to rule out any possible influence from it accessing ucode blobs early from the initrd and/or having other effects on the system.

These patches add a "dis_ucode_ldr" (when early loading is not built in, use with the prefix, i.e. "microcode.dis_ucode_ldr") which enables that.

For that we needed a fairly self-contained cmdline parsing function which we almost copied from arch/x86/boot/cmdline.c

The dancing in check_loader_disabled_*() variants is needed because on 32-bit we're running before paging is enabled and there we need to deal with physical addresses.

As always, any comments and suggestions are appreciated.

Thanks.

Borislav Petkov (2):
x86: Carve out cmdline parsing function
x86, microcode: Add a disable chicken bit

 arch/x86/include/asm/cmdline.h             |  6 +++
 arch/x86/include/asm/microcode.h           |  1 +
 arch/x86/kernel/cpu/microcode/core.c       |  6 +++
 arch/x86/kernel/cpu/microcode/core_early.c | 37 +++++++++++++
 arch/x86/lib/Makefile                      |  2 +-
 arch/x86/lib/cmdline.c                     | 84 ++++++++++++++++++++++++++++++
 6 files changed, 135 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/include/asm/cmdline.h
 create mode 100644 arch/x86/lib/cmdline.c
Signature · 1 line
1.9.0
author maintainer
#1 lore raw

PATCH 1/2 x86: Carve out cmdline parsing function

From: Borislav Petkov <[email protected]>

into .../lib/cmdline.c to use by kernel proper too.

Adapted from arch/x86/boot/cmdline.c.

---
 arch/x86/include/asm/cmdline.h |  6 +++
 arch/x86/lib/Makefile          |  2 +-
 arch/x86/lib/cmdline.c         | 84 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 91 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/include/asm/cmdline.h
 create mode 100644 arch/x86/lib/cmdline.c
arch/x86/include/asm/cmdline.h new file +6 -0
new file mode 100644
index 000000000000..e01f7f7ccb0c
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_CMDLINE_H
+#define _ASM_X86_CMDLINE_H
+
+int cmdline_find_option_bool(const char *cmdline_ptr, const char *option);
+
+#endif /* _ASM_X86_CMDLINE_H */
arch/x86/lib/Makefile +1 -1
index eabcb6e6a900..4d4f96a27638 100644
@@ -16,7 +16,7 @@ clean-files := inat-tables.c
 
 obj-$(CONFIG_SMP) += msr-smp.o cache-smp.o
 
-lib-y := delay.o misc.o
+lib-y := delay.o misc.o cmdline.o
 lib-y += thunk_$(BITS).o
 lib-y += usercopy_$(BITS).o usercopy.o getuser.o putuser.o
 lib-y += memcpy_$(BITS).o
arch/x86/lib/cmdline.c new file +84 -0

84 lines not on this page · raw message

Signature · 1 line
1.9.0
#2 lore raw

[tip:x86/microcode] x86, boot: Carve out early cmdline parsing function

x86, boot: Carve out early cmdline parsing function
Commit-ID:  1b1ded57a4f2f4420b4de7c395d1b841d8b3c41a
Gitweb:     http://git.kernel.org/tip/1b1ded57a4f2f4420b4de7c395d1b841d8b3c41a
Author:     Borislav Petkov <[email protected]>
AuthorDate: Mon, 19 May 2014 20:59:16 +0200
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Tue, 20 May 2014 20:21:24 -0700

x86, boot: Carve out early cmdline parsing function

Carve out early cmdline parsing function into .../lib/cmdline.c so it can be used by early code in the kernel proper as well.

Adapted from arch/x86/boot/cmdline.c.

---
 arch/x86/include/asm/cmdline.h |  6 +++
 arch/x86/lib/Makefile          |  2 +-
 arch/x86/lib/cmdline.c         | 84 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 91 insertions(+), 1 deletion(-)
arch/x86/include/asm/cmdline.h new file +6 -0
new file mode 100644
index 0000000..e01f7f7
@@ -0,0 +1,6 @@
+#ifndef _ASM_X86_CMDLINE_H
+#define _ASM_X86_CMDLINE_H
+
+int cmdline_find_option_bool(const char *cmdline_ptr, const char *option);
+
+#endif /* _ASM_X86_CMDLINE_H */
arch/x86/lib/Makefile +1 -1
index eabcb6e..4d4f96a 100644
@@ -16,7 +16,7 @@ clean-files := inat-tables.c
 
 obj-$(CONFIG_SMP) += msr-smp.o cache-smp.o
 
-lib-y := delay.o misc.o
+lib-y := delay.o misc.o cmdline.o
 lib-y += thunk_$(BITS).o
 lib-y += usercopy_$(BITS).o usercopy.o getuser.o putuser.o
 lib-y += memcpy_$(BITS).o
arch/x86/lib/cmdline.c new file +84 -0

84 lines not on this page · raw message

author maintainer
#3 lore raw

PATCH 2/2 x86, microcode: Add a disable chicken bit

In reply to Borislav Petkov

From: Borislav Petkov <[email protected]>

Add a cmdline param which disables the microcode loader. This is useful mostly in debugging situations where we want to turn off microcode loading, both early from the initrd and late, as a means to be able to rule out its influence on the machine.

---
 arch/x86/include/asm/microcode.h           |  1 +
 arch/x86/kernel/cpu/microcode/core.c       |  6 +++++
 arch/x86/kernel/cpu/microcode/core_early.c | 37 ++++++++++++++++++++++++++++++
 3 files changed, 44 insertions(+)
arch/x86/include/asm/microcode.h +1 -0
index b59827e76529..64dc362506b7 100644
@@ -25,6 +25,7 @@ struct cpu_signature {
 struct device;
 
 enum ucode_state { UCODE_ERROR, UCODE_OK, UCODE_NFOUND };
+extern bool dis_ucode_ldr;
 
 struct microcode_ops {
 	enum ucode_state (*request_microcode_user) (int cpu,
arch/x86/kernel/cpu/microcode/core.c +6 -0
index 15c987698b0f..dd9d6190b08d 100644
@@ -97,6 +97,9 @@ MODULE_LICENSE("GPL");
 
 static struct microcode_ops	*microcode_ops;
 
+bool dis_ucode_ldr;
+module_param(dis_ucode_ldr, bool, 0);
+
 /*
  * Synchronization.
  *
@@ -546,6 +549,9 @@ static int __init microcode_init(void)
 	struct cpuinfo_x86 *c = &cpu_data(0);
 	int error;
 
+	if (dis_ucode_ldr)
+		return 0;
+
 	if (c->x86_vendor == X86_VENDOR_INTEL)
 		microcode_ops = init_intel_microcode();
 	else if (c->x86_vendor == X86_VENDOR_AMD)
arch/x86/kernel/cpu/microcode/core_early.c +37 -0
index be7f8514f577..5f28a64e71ea 100644
@@ -17,9 +17,11 @@
  *	2 of the License, or (at your option) any later version.
  */
 #include <linux/module.h>
+#include <asm/microcode.h>
 #include <asm/microcode_intel.h>
 #include <asm/microcode_amd.h>
 #include <asm/processor.h>
+#include <asm/cmdline.h>
 
 #define QCHAR(a, b, c, d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24))
 #define CPUID_INTEL1 QCHAR('G', 'e', 'n', 'u')
@@ -72,10 +74,33 @@ static int x86_family(void)
 	return x86;
 }
 
+static bool __init check_loader_disabled_bsp(void)
+{
+#ifdef CONFIG_X86_32
+	const char *cmdline = (const char *)__pa_nodebug(boot_command_line);
+	const char *opt	    = "dis_ucode_ldr";
+	const char *option  = (const char *)__pa_nodebug(opt);
+	bool *res = (bool *)__pa_nodebug(&dis_ucode_ldr);
+
+#else /* CONFIG_X86_64 */
+	const char *cmdline = boot_command_line;
+	const char *option  = "dis_ucode_ldr";
+	bool *res = &dis_ucode_ldr;
+#endif
+
+	if (cmdline_find_option_bool(cmdline, option))
+		*res = true;
+
+	return *res;
+}
+
 void __init load_ucode_bsp(void)
 {
 	int vendor, x86;
 
+	if (check_loader_disabled_bsp())
+		return;
+
 	if (!have_cpuid_p())
 		return;
 
@@ -96,10 +121,22 @@ void __init load_ucode_bsp(void)
 	}
 }
 
+static bool check_loader_disabled_ap(void)
+{
+#ifdef CONFIG_X86_32
+	return __pa_nodebug(dis_ucode_ldr);
+#else
+	return dis_ucode_ldr;
+#endif
+}
+
 void load_ucode_ap(void)
 {
 	int vendor, x86;
 
+	if (check_loader_disabled_ap())
+		return;
+
 	if (!have_cpuid_p())
 		return;
 
Signature · 1 line
1.9.0
#4 lore raw

[tip:x86/microcode] x86, microcode: Add a disable chicken bit

x86, microcode: Add a disable chicken bit
Commit-ID:  65cef1311d5d212fd3d48a43678536dc878ca288
Gitweb:     http://git.kernel.org/tip/65cef1311d5d212fd3d48a43678536dc878ca288
Author:     Borislav Petkov <[email protected]>
AuthorDate: Mon, 19 May 2014 20:59:17 +0200
Committer:  H. Peter Anvin <[email protected]>
CommitDate: Tue, 20 May 2014 20:21:27 -0700

x86, microcode: Add a disable chicken bit

Add a cmdline param which disables the microcode loader. This is useful mostly in debugging situations where we want to turn off microcode loading, both early from the initrd and late, as a means to be able to rule out its influence on the machine.

---
 arch/x86/include/asm/microcode.h           |  1 +
 arch/x86/kernel/cpu/microcode/core.c       |  6 +++++
 arch/x86/kernel/cpu/microcode/core_early.c | 37 ++++++++++++++++++++++++++++++
 3 files changed, 44 insertions(+)
arch/x86/include/asm/microcode.h +1 -0
index b59827e..64dc362 100644
@@ -25,6 +25,7 @@ struct cpu_signature {
 struct device;
 
 enum ucode_state { UCODE_ERROR, UCODE_OK, UCODE_NFOUND };
+extern bool dis_ucode_ldr;
 
 struct microcode_ops {
 	enum ucode_state (*request_microcode_user) (int cpu,
arch/x86/kernel/cpu/microcode/core.c +6 -0
index 15c9876..dd9d619 100644
@@ -97,6 +97,9 @@ MODULE_LICENSE("GPL");
 
 static struct microcode_ops	*microcode_ops;
 
+bool dis_ucode_ldr;
+module_param(dis_ucode_ldr, bool, 0);
+
 /*
  * Synchronization.
  *
@@ -546,6 +549,9 @@ static int __init microcode_init(void)
 	struct cpuinfo_x86 *c = &cpu_data(0);
 	int error;
 
+	if (dis_ucode_ldr)
+		return 0;
+
 	if (c->x86_vendor == X86_VENDOR_INTEL)
 		microcode_ops = init_intel_microcode();
 	else if (c->x86_vendor == X86_VENDOR_AMD)
arch/x86/kernel/cpu/microcode/core_early.c +37 -0
index be7f851..5f28a64 100644
@@ -17,9 +17,11 @@
  *	2 of the License, or (at your option) any later version.
  */
 #include <linux/module.h>
+#include <asm/microcode.h>
 #include <asm/microcode_intel.h>
 #include <asm/microcode_amd.h>
 #include <asm/processor.h>
+#include <asm/cmdline.h>
 
 #define QCHAR(a, b, c, d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24))
 #define CPUID_INTEL1 QCHAR('G', 'e', 'n', 'u')
@@ -72,10 +74,33 @@ static int x86_family(void)
 	return x86;
 }
 
+static bool __init check_loader_disabled_bsp(void)
+{
+#ifdef CONFIG_X86_32
+	const char *cmdline = (const char *)__pa_nodebug(boot_command_line);
+	const char *opt	    = "dis_ucode_ldr";
+	const char *option  = (const char *)__pa_nodebug(opt);
+	bool *res = (bool *)__pa_nodebug(&dis_ucode_ldr);
+
+#else /* CONFIG_X86_64 */
+	const char *cmdline = boot_command_line;
+	const char *option  = "dis_ucode_ldr";
+	bool *res = &dis_ucode_ldr;
+#endif
+
+	if (cmdline_find_option_bool(cmdline, option))
+		*res = true;
+
+	return *res;
+}
+
 void __init load_ucode_bsp(void)
 {
 	int vendor, x86;
 
+	if (check_loader_disabled_bsp())
+		return;
+
 	if (!have_cpuid_p())
 		return;
 
@@ -96,10 +121,22 @@ void __init load_ucode_bsp(void)
 	}
 }
 
+static bool check_loader_disabled_ap(void)
+{
+#ifdef CONFIG_X86_32
+	return __pa_nodebug(dis_ucode_ldr);
+#else
+	return dis_ucode_ldr;
+#endif
+}
+
 void load_ucode_ap(void)
 {
 	int vendor, x86;
 
+	if (check_loader_disabled_ap())
+		return;
+
 	if (!have_cpuid_p())
 		return;