diff options
author | Borislav Petkov <bp@suse.de> | 2014-05-19 14:59:17 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2014-05-20 23:21:27 -0400 |
commit | 65cef1311d5d212fd3d48a43678536dc878ca288 (patch) | |
tree | 016bff3b97650be35dc3fac764116734a5d1d803 | |
parent | 1b1ded57a4f2f4420b4de7c395d1b841d8b3c41a (diff) |
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.
Signed-off-by: Borislav Petkov <bp@suse.de>
Link: http://lkml.kernel.org/r/1400525957-11525-3-git-send-email-bp@alien8.de
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r-- | arch/x86/include/asm/microcode.h | 1 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/core.c | 6 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/core_early.c | 37 |
3 files changed, 44 insertions, 0 deletions
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h index b59827e76529..64dc362506b7 100644 --- a/arch/x86/include/asm/microcode.h +++ b/arch/x86/include/asm/microcode.h | |||
@@ -25,6 +25,7 @@ struct cpu_signature { | |||
25 | struct device; | 25 | struct device; |
26 | 26 | ||
27 | enum ucode_state { UCODE_ERROR, UCODE_OK, UCODE_NFOUND }; | 27 | enum ucode_state { UCODE_ERROR, UCODE_OK, UCODE_NFOUND }; |
28 | extern bool dis_ucode_ldr; | ||
28 | 29 | ||
29 | struct microcode_ops { | 30 | struct microcode_ops { |
30 | enum ucode_state (*request_microcode_user) (int cpu, | 31 | enum ucode_state (*request_microcode_user) (int cpu, |
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index 15c987698b0f..dd9d6190b08d 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c | |||
@@ -97,6 +97,9 @@ MODULE_LICENSE("GPL"); | |||
97 | 97 | ||
98 | static struct microcode_ops *microcode_ops; | 98 | static struct microcode_ops *microcode_ops; |
99 | 99 | ||
100 | bool dis_ucode_ldr; | ||
101 | module_param(dis_ucode_ldr, bool, 0); | ||
102 | |||
100 | /* | 103 | /* |
101 | * Synchronization. | 104 | * Synchronization. |
102 | * | 105 | * |
@@ -546,6 +549,9 @@ static int __init microcode_init(void) | |||
546 | struct cpuinfo_x86 *c = &cpu_data(0); | 549 | struct cpuinfo_x86 *c = &cpu_data(0); |
547 | int error; | 550 | int error; |
548 | 551 | ||
552 | if (dis_ucode_ldr) | ||
553 | return 0; | ||
554 | |||
549 | if (c->x86_vendor == X86_VENDOR_INTEL) | 555 | if (c->x86_vendor == X86_VENDOR_INTEL) |
550 | microcode_ops = init_intel_microcode(); | 556 | microcode_ops = init_intel_microcode(); |
551 | else if (c->x86_vendor == X86_VENDOR_AMD) | 557 | else if (c->x86_vendor == X86_VENDOR_AMD) |
diff --git a/arch/x86/kernel/cpu/microcode/core_early.c b/arch/x86/kernel/cpu/microcode/core_early.c index be7f8514f577..5f28a64e71ea 100644 --- a/arch/x86/kernel/cpu/microcode/core_early.c +++ b/arch/x86/kernel/cpu/microcode/core_early.c | |||
@@ -17,9 +17,11 @@ | |||
17 | * 2 of the License, or (at your option) any later version. | 17 | * 2 of the License, or (at your option) any later version. |
18 | */ | 18 | */ |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <asm/microcode.h> | ||
20 | #include <asm/microcode_intel.h> | 21 | #include <asm/microcode_intel.h> |
21 | #include <asm/microcode_amd.h> | 22 | #include <asm/microcode_amd.h> |
22 | #include <asm/processor.h> | 23 | #include <asm/processor.h> |
24 | #include <asm/cmdline.h> | ||
23 | 25 | ||
24 | #define QCHAR(a, b, c, d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24)) | 26 | #define QCHAR(a, b, c, d) ((a) + ((b) << 8) + ((c) << 16) + ((d) << 24)) |
25 | #define CPUID_INTEL1 QCHAR('G', 'e', 'n', 'u') | 27 | #define CPUID_INTEL1 QCHAR('G', 'e', 'n', 'u') |
@@ -72,10 +74,33 @@ static int x86_family(void) | |||
72 | return x86; | 74 | return x86; |
73 | } | 75 | } |
74 | 76 | ||
77 | static bool __init check_loader_disabled_bsp(void) | ||
78 | { | ||
79 | #ifdef CONFIG_X86_32 | ||
80 | const char *cmdline = (const char *)__pa_nodebug(boot_command_line); | ||
81 | const char *opt = "dis_ucode_ldr"; | ||
82 | const char *option = (const char *)__pa_nodebug(opt); | ||
83 | bool *res = (bool *)__pa_nodebug(&dis_ucode_ldr); | ||
84 | |||
85 | #else /* CONFIG_X86_64 */ | ||
86 | const char *cmdline = boot_command_line; | ||
87 | const char *option = "dis_ucode_ldr"; | ||
88 | bool *res = &dis_ucode_ldr; | ||
89 | #endif | ||
90 | |||
91 | if (cmdline_find_option_bool(cmdline, option)) | ||
92 | *res = true; | ||
93 | |||
94 | return *res; | ||
95 | } | ||
96 | |||
75 | void __init load_ucode_bsp(void) | 97 | void __init load_ucode_bsp(void) |
76 | { | 98 | { |
77 | int vendor, x86; | 99 | int vendor, x86; |
78 | 100 | ||
101 | if (check_loader_disabled_bsp()) | ||
102 | return; | ||
103 | |||
79 | if (!have_cpuid_p()) | 104 | if (!have_cpuid_p()) |
80 | return; | 105 | return; |
81 | 106 | ||
@@ -96,10 +121,22 @@ void __init load_ucode_bsp(void) | |||
96 | } | 121 | } |
97 | } | 122 | } |
98 | 123 | ||
124 | static bool check_loader_disabled_ap(void) | ||
125 | { | ||
126 | #ifdef CONFIG_X86_32 | ||
127 | return __pa_nodebug(dis_ucode_ldr); | ||
128 | #else | ||
129 | return dis_ucode_ldr; | ||
130 | #endif | ||
131 | } | ||
132 | |||
99 | void load_ucode_ap(void) | 133 | void load_ucode_ap(void) |
100 | { | 134 | { |
101 | int vendor, x86; | 135 | int vendor, x86; |
102 | 136 | ||
137 | if (check_loader_disabled_ap()) | ||
138 | return; | ||
139 | |||
103 | if (!have_cpuid_p()) | 140 | if (!have_cpuid_p()) |
104 | return; | 141 | return; |
105 | 142 | ||