diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-15 13:39:22 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-15 13:39:22 -0400 |
commit | 9cf8d6360c1589a97a98313729ed9e5db187f80b (patch) | |
tree | 6724fb3915f5343800460d98d31528e09a445028 /arch/x86/kernel/cpu/microcode | |
parent | ecc026bff6e8444c6b50dcde192e7acdaf42bf82 (diff) | |
parent | 4ace2e7a48ab426eaa9745ace4c50c6a7adb3992 (diff) |
Merge branch 'x86-microcode-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 microcode updates from Ingo Molnar:
"The biggest change in this cycle was the separation of the microcode
loading mechanism from the initrd code plus the support of built-in
microcode images.
There were also lots cleanups and general restructuring (by Borislav
Petkov)"
* 'x86-microcode-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (24 commits)
x86/microcode/intel: Drop orig_sum from ext signature checksum
x86/microcode/intel: Improve microcode sanity-checking error messages
x86/microcode/intel: Merge two consecutive if-statements
x86/microcode/intel: Get rid of DWSIZE
x86/microcode/intel: Change checksum variables to u32
x86/microcode: Use kmemdup() rather than duplicating its implementation
x86/microcode: Remove unnecessary paravirt_enabled check
x86/microcode: Document builtin microcode loading method
x86/microcode/AMD: Issue microcode updated message later
x86/microcode/intel: Cleanup get_matching_model_microcode()
x86/microcode/intel: Remove unused arg of get_matching_model_microcode()
x86/microcode/intel: Rename mc_saved_in_initrd
x86/microcode/intel: Use *wrmsrl variants
x86/microcode/intel: Cleanup apply_microcode_intel()
x86/microcode/intel: Move the BUG_ON up and turn it into WARN_ON
x86/microcode/intel: Rename mc_intel variable to mc
x86/microcode/intel: Rename mc_saved_count to num_saved
x86/microcode/intel: Rename local variables of type struct mc_saved_data
x86/microcode/AMD: Drop redundant printk prefix
x86/microcode: Issue update message only once
...
Diffstat (limited to 'arch/x86/kernel/cpu/microcode')
-rw-r--r-- | arch/x86/kernel/cpu/microcode/amd.c | 15 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/core.c | 19 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/intel.c | 285 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/microcode/intel_lib.c | 58 |
4 files changed, 188 insertions, 189 deletions
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c index 75d3aab5f7b2..8581963894c7 100644 --- a/arch/x86/kernel/cpu/microcode/amd.c +++ b/arch/x86/kernel/cpu/microcode/amd.c | |||
@@ -431,10 +431,6 @@ int __init save_microcode_in_initrd_amd(void) | |||
431 | else | 431 | else |
432 | container = cont_va; | 432 | container = cont_va; |
433 | 433 | ||
434 | if (ucode_new_rev) | ||
435 | pr_info("microcode: updated early to new patch_level=0x%08x\n", | ||
436 | ucode_new_rev); | ||
437 | |||
438 | eax = cpuid_eax(0x00000001); | 434 | eax = cpuid_eax(0x00000001); |
439 | eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff); | 435 | eax = ((eax >> 8) & 0xf) + ((eax >> 20) & 0xff); |
440 | 436 | ||
@@ -469,8 +465,7 @@ void reload_ucode_amd(void) | |||
469 | if (mc && rev < mc->hdr.patch_id) { | 465 | if (mc && rev < mc->hdr.patch_id) { |
470 | if (!__apply_microcode_amd(mc)) { | 466 | if (!__apply_microcode_amd(mc)) { |
471 | ucode_new_rev = mc->hdr.patch_id; | 467 | ucode_new_rev = mc->hdr.patch_id; |
472 | pr_info("microcode: reload patch_level=0x%08x\n", | 468 | pr_info("reload patch_level=0x%08x\n", ucode_new_rev); |
473 | ucode_new_rev); | ||
474 | } | 469 | } |
475 | } | 470 | } |
476 | } | 471 | } |
@@ -793,15 +788,13 @@ static int verify_and_add_patch(u8 family, u8 *fw, unsigned int leftover) | |||
793 | return -EINVAL; | 788 | return -EINVAL; |
794 | } | 789 | } |
795 | 790 | ||
796 | patch->data = kzalloc(patch_size, GFP_KERNEL); | 791 | patch->data = kmemdup(fw + SECTION_HDR_SIZE, patch_size, GFP_KERNEL); |
797 | if (!patch->data) { | 792 | if (!patch->data) { |
798 | pr_err("Patch data allocation failure.\n"); | 793 | pr_err("Patch data allocation failure.\n"); |
799 | kfree(patch); | 794 | kfree(patch); |
800 | return -EINVAL; | 795 | return -EINVAL; |
801 | } | 796 | } |
802 | 797 | ||
803 | /* All looks ok, copy patch... */ | ||
804 | memcpy(patch->data, fw + SECTION_HDR_SIZE, patch_size); | ||
805 | INIT_LIST_HEAD(&patch->plist); | 798 | INIT_LIST_HEAD(&patch->plist); |
806 | patch->patch_id = mc_hdr->patch_id; | 799 | patch->patch_id = mc_hdr->patch_id; |
807 | patch->equiv_cpu = proc_id; | 800 | patch->equiv_cpu = proc_id; |
@@ -957,6 +950,10 @@ struct microcode_ops * __init init_amd_microcode(void) | |||
957 | return NULL; | 950 | return NULL; |
958 | } | 951 | } |
959 | 952 | ||
953 | if (ucode_new_rev) | ||
954 | pr_info_once("microcode updated early to new patch_level=0x%08x\n", | ||
955 | ucode_new_rev); | ||
956 | |||
960 | return µcode_amd_ops; | 957 | return µcode_amd_ops; |
961 | } | 958 | } |
962 | 959 | ||
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c index faec7120c508..ac360bfbbdb6 100644 --- a/arch/x86/kernel/cpu/microcode/core.c +++ b/arch/x86/kernel/cpu/microcode/core.c | |||
@@ -43,16 +43,8 @@ | |||
43 | #define MICROCODE_VERSION "2.01" | 43 | #define MICROCODE_VERSION "2.01" |
44 | 44 | ||
45 | static struct microcode_ops *microcode_ops; | 45 | static struct microcode_ops *microcode_ops; |
46 | |||
47 | static bool dis_ucode_ldr; | 46 | static bool dis_ucode_ldr; |
48 | 47 | ||
49 | static int __init disable_loader(char *str) | ||
50 | { | ||
51 | dis_ucode_ldr = true; | ||
52 | return 1; | ||
53 | } | ||
54 | __setup("dis_ucode_ldr", disable_loader); | ||
55 | |||
56 | /* | 48 | /* |
57 | * Synchronization. | 49 | * Synchronization. |
58 | * | 50 | * |
@@ -81,15 +73,16 @@ struct cpu_info_ctx { | |||
81 | 73 | ||
82 | static bool __init check_loader_disabled_bsp(void) | 74 | static bool __init check_loader_disabled_bsp(void) |
83 | { | 75 | { |
76 | static const char *__dis_opt_str = "dis_ucode_ldr"; | ||
77 | |||
84 | #ifdef CONFIG_X86_32 | 78 | #ifdef CONFIG_X86_32 |
85 | const char *cmdline = (const char *)__pa_nodebug(boot_command_line); | 79 | const char *cmdline = (const char *)__pa_nodebug(boot_command_line); |
86 | const char *opt = "dis_ucode_ldr"; | 80 | const char *option = (const char *)__pa_nodebug(__dis_opt_str); |
87 | const char *option = (const char *)__pa_nodebug(opt); | ||
88 | bool *res = (bool *)__pa_nodebug(&dis_ucode_ldr); | 81 | bool *res = (bool *)__pa_nodebug(&dis_ucode_ldr); |
89 | 82 | ||
90 | #else /* CONFIG_X86_64 */ | 83 | #else /* CONFIG_X86_64 */ |
91 | const char *cmdline = boot_command_line; | 84 | const char *cmdline = boot_command_line; |
92 | const char *option = "dis_ucode_ldr"; | 85 | const char *option = __dis_opt_str; |
93 | bool *res = &dis_ucode_ldr; | 86 | bool *res = &dis_ucode_ldr; |
94 | #endif | 87 | #endif |
95 | 88 | ||
@@ -479,7 +472,7 @@ static enum ucode_state microcode_init_cpu(int cpu, bool refresh_fw) | |||
479 | enum ucode_state ustate; | 472 | enum ucode_state ustate; |
480 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | 473 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
481 | 474 | ||
482 | if (uci && uci->valid) | 475 | if (uci->valid) |
483 | return UCODE_OK; | 476 | return UCODE_OK; |
484 | 477 | ||
485 | if (collect_cpu_info(cpu)) | 478 | if (collect_cpu_info(cpu)) |
@@ -630,7 +623,7 @@ int __init microcode_init(void) | |||
630 | struct cpuinfo_x86 *c = &boot_cpu_data; | 623 | struct cpuinfo_x86 *c = &boot_cpu_data; |
631 | int error; | 624 | int error; |
632 | 625 | ||
633 | if (paravirt_enabled() || dis_ucode_ldr) | 626 | if (dis_ucode_ldr) |
634 | return -EINVAL; | 627 | return -EINVAL; |
635 | 628 | ||
636 | if (c->x86_vendor == X86_VENDOR_INTEL) | 629 | if (c->x86_vendor == X86_VENDOR_INTEL) |
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c index ee81c544ee0d..cbb3cf09b065 100644 --- a/arch/x86/kernel/cpu/microcode/intel.c +++ b/arch/x86/kernel/cpu/microcode/intel.c | |||
@@ -39,9 +39,15 @@ | |||
39 | #include <asm/setup.h> | 39 | #include <asm/setup.h> |
40 | #include <asm/msr.h> | 40 | #include <asm/msr.h> |
41 | 41 | ||
42 | static unsigned long mc_saved_in_initrd[MAX_UCODE_COUNT]; | 42 | /* |
43 | * Temporary microcode blobs pointers storage. We note here the pointers to | ||
44 | * microcode blobs we've got from whatever storage (detached initrd, builtin). | ||
45 | * Later on, we put those into final storage mc_saved_data.mc_saved. | ||
46 | */ | ||
47 | static unsigned long mc_tmp_ptrs[MAX_UCODE_COUNT]; | ||
48 | |||
43 | static struct mc_saved_data { | 49 | static struct mc_saved_data { |
44 | unsigned int mc_saved_count; | 50 | unsigned int num_saved; |
45 | struct microcode_intel **mc_saved; | 51 | struct microcode_intel **mc_saved; |
46 | } mc_saved_data; | 52 | } mc_saved_data; |
47 | 53 | ||
@@ -78,53 +84,50 @@ load_microcode_early(struct microcode_intel **saved, | |||
78 | } | 84 | } |
79 | 85 | ||
80 | static inline void | 86 | static inline void |
81 | copy_initrd_ptrs(struct microcode_intel **mc_saved, unsigned long *initrd, | 87 | copy_ptrs(struct microcode_intel **mc_saved, unsigned long *mc_ptrs, |
82 | unsigned long off, int num_saved) | 88 | unsigned long off, int num_saved) |
83 | { | 89 | { |
84 | int i; | 90 | int i; |
85 | 91 | ||
86 | for (i = 0; i < num_saved; i++) | 92 | for (i = 0; i < num_saved; i++) |
87 | mc_saved[i] = (struct microcode_intel *)(initrd[i] + off); | 93 | mc_saved[i] = (struct microcode_intel *)(mc_ptrs[i] + off); |
88 | } | 94 | } |
89 | 95 | ||
90 | #ifdef CONFIG_X86_32 | 96 | #ifdef CONFIG_X86_32 |
91 | static void | 97 | static void |
92 | microcode_phys(struct microcode_intel **mc_saved_tmp, | 98 | microcode_phys(struct microcode_intel **mc_saved_tmp, struct mc_saved_data *mcs) |
93 | struct mc_saved_data *mc_saved_data) | ||
94 | { | 99 | { |
95 | int i; | 100 | int i; |
96 | struct microcode_intel ***mc_saved; | 101 | struct microcode_intel ***mc_saved; |
97 | 102 | ||
98 | mc_saved = (struct microcode_intel ***) | 103 | mc_saved = (struct microcode_intel ***)__pa_nodebug(&mcs->mc_saved); |
99 | __pa_nodebug(&mc_saved_data->mc_saved); | 104 | |
100 | for (i = 0; i < mc_saved_data->mc_saved_count; i++) { | 105 | for (i = 0; i < mcs->num_saved; i++) { |
101 | struct microcode_intel *p; | 106 | struct microcode_intel *p; |
102 | 107 | ||
103 | p = *(struct microcode_intel **) | 108 | p = *(struct microcode_intel **)__pa_nodebug(mcs->mc_saved + i); |
104 | __pa_nodebug(mc_saved_data->mc_saved + i); | ||
105 | mc_saved_tmp[i] = (struct microcode_intel *)__pa_nodebug(p); | 109 | mc_saved_tmp[i] = (struct microcode_intel *)__pa_nodebug(p); |
106 | } | 110 | } |
107 | } | 111 | } |
108 | #endif | 112 | #endif |
109 | 113 | ||
110 | static enum ucode_state | 114 | static enum ucode_state |
111 | load_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd, | 115 | load_microcode(struct mc_saved_data *mcs, unsigned long *mc_ptrs, |
112 | unsigned long initrd_start, struct ucode_cpu_info *uci) | 116 | unsigned long offset, struct ucode_cpu_info *uci) |
113 | { | 117 | { |
114 | struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT]; | 118 | struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT]; |
115 | unsigned int count = mc_saved_data->mc_saved_count; | 119 | unsigned int count = mcs->num_saved; |
116 | 120 | ||
117 | if (!mc_saved_data->mc_saved) { | 121 | if (!mcs->mc_saved) { |
118 | copy_initrd_ptrs(mc_saved_tmp, initrd, initrd_start, count); | 122 | copy_ptrs(mc_saved_tmp, mc_ptrs, offset, count); |
119 | 123 | ||
120 | return load_microcode_early(mc_saved_tmp, count, uci); | 124 | return load_microcode_early(mc_saved_tmp, count, uci); |
121 | } else { | 125 | } else { |
122 | #ifdef CONFIG_X86_32 | 126 | #ifdef CONFIG_X86_32 |
123 | microcode_phys(mc_saved_tmp, mc_saved_data); | 127 | microcode_phys(mc_saved_tmp, mcs); |
124 | return load_microcode_early(mc_saved_tmp, count, uci); | 128 | return load_microcode_early(mc_saved_tmp, count, uci); |
125 | #else | 129 | #else |
126 | return load_microcode_early(mc_saved_data->mc_saved, | 130 | return load_microcode_early(mcs->mc_saved, count, uci); |
127 | count, uci); | ||
128 | #endif | 131 | #endif |
129 | } | 132 | } |
130 | } | 133 | } |
@@ -175,25 +178,25 @@ matching_model_microcode(struct microcode_header_intel *mc_header, | |||
175 | } | 178 | } |
176 | 179 | ||
177 | static int | 180 | static int |
178 | save_microcode(struct mc_saved_data *mc_saved_data, | 181 | save_microcode(struct mc_saved_data *mcs, |
179 | struct microcode_intel **mc_saved_src, | 182 | struct microcode_intel **mc_saved_src, |
180 | unsigned int mc_saved_count) | 183 | unsigned int num_saved) |
181 | { | 184 | { |
182 | int i, j; | 185 | int i, j; |
183 | struct microcode_intel **saved_ptr; | 186 | struct microcode_intel **saved_ptr; |
184 | int ret; | 187 | int ret; |
185 | 188 | ||
186 | if (!mc_saved_count) | 189 | if (!num_saved) |
187 | return -EINVAL; | 190 | return -EINVAL; |
188 | 191 | ||
189 | /* | 192 | /* |
190 | * Copy new microcode data. | 193 | * Copy new microcode data. |
191 | */ | 194 | */ |
192 | saved_ptr = kcalloc(mc_saved_count, sizeof(struct microcode_intel *), GFP_KERNEL); | 195 | saved_ptr = kcalloc(num_saved, sizeof(struct microcode_intel *), GFP_KERNEL); |
193 | if (!saved_ptr) | 196 | if (!saved_ptr) |
194 | return -ENOMEM; | 197 | return -ENOMEM; |
195 | 198 | ||
196 | for (i = 0; i < mc_saved_count; i++) { | 199 | for (i = 0; i < num_saved; i++) { |
197 | struct microcode_header_intel *mc_hdr; | 200 | struct microcode_header_intel *mc_hdr; |
198 | struct microcode_intel *mc; | 201 | struct microcode_intel *mc; |
199 | unsigned long size; | 202 | unsigned long size; |
@@ -207,20 +210,18 @@ save_microcode(struct mc_saved_data *mc_saved_data, | |||
207 | mc_hdr = &mc->hdr; | 210 | mc_hdr = &mc->hdr; |
208 | size = get_totalsize(mc_hdr); | 211 | size = get_totalsize(mc_hdr); |
209 | 212 | ||
210 | saved_ptr[i] = kmalloc(size, GFP_KERNEL); | 213 | saved_ptr[i] = kmemdup(mc, size, GFP_KERNEL); |
211 | if (!saved_ptr[i]) { | 214 | if (!saved_ptr[i]) { |
212 | ret = -ENOMEM; | 215 | ret = -ENOMEM; |
213 | goto err; | 216 | goto err; |
214 | } | 217 | } |
215 | |||
216 | memcpy(saved_ptr[i], mc, size); | ||
217 | } | 218 | } |
218 | 219 | ||
219 | /* | 220 | /* |
220 | * Point to newly saved microcode. | 221 | * Point to newly saved microcode. |
221 | */ | 222 | */ |
222 | mc_saved_data->mc_saved = saved_ptr; | 223 | mcs->mc_saved = saved_ptr; |
223 | mc_saved_data->mc_saved_count = mc_saved_count; | 224 | mcs->num_saved = num_saved; |
224 | 225 | ||
225 | return 0; | 226 | return 0; |
226 | 227 | ||
@@ -284,22 +285,20 @@ static unsigned int _save_mc(struct microcode_intel **mc_saved, | |||
284 | * BSP can stay in the platform. | 285 | * BSP can stay in the platform. |
285 | */ | 286 | */ |
286 | static enum ucode_state __init | 287 | static enum ucode_state __init |
287 | get_matching_model_microcode(int cpu, unsigned long start, | 288 | get_matching_model_microcode(unsigned long start, void *data, size_t size, |
288 | void *data, size_t size, | 289 | struct mc_saved_data *mcs, unsigned long *mc_ptrs, |
289 | struct mc_saved_data *mc_saved_data, | ||
290 | unsigned long *mc_saved_in_initrd, | ||
291 | struct ucode_cpu_info *uci) | 290 | struct ucode_cpu_info *uci) |
292 | { | 291 | { |
293 | u8 *ucode_ptr = data; | 292 | struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT]; |
294 | unsigned int leftover = size; | 293 | struct microcode_header_intel *mc_header; |
294 | unsigned int num_saved = mcs->num_saved; | ||
295 | enum ucode_state state = UCODE_OK; | 295 | enum ucode_state state = UCODE_OK; |
296 | unsigned int leftover = size; | ||
297 | u8 *ucode_ptr = data; | ||
296 | unsigned int mc_size; | 298 | unsigned int mc_size; |
297 | struct microcode_header_intel *mc_header; | ||
298 | struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT]; | ||
299 | unsigned int mc_saved_count = mc_saved_data->mc_saved_count; | ||
300 | int i; | 299 | int i; |
301 | 300 | ||
302 | while (leftover && mc_saved_count < ARRAY_SIZE(mc_saved_tmp)) { | 301 | while (leftover && num_saved < ARRAY_SIZE(mc_saved_tmp)) { |
303 | 302 | ||
304 | if (leftover < sizeof(mc_header)) | 303 | if (leftover < sizeof(mc_header)) |
305 | break; | 304 | break; |
@@ -318,32 +317,31 @@ get_matching_model_microcode(int cpu, unsigned long start, | |||
318 | * the platform, we need to find and save microcode patches | 317 | * the platform, we need to find and save microcode patches |
319 | * with the same family and model as the BSP. | 318 | * with the same family and model as the BSP. |
320 | */ | 319 | */ |
321 | if (matching_model_microcode(mc_header, uci->cpu_sig.sig) != | 320 | if (matching_model_microcode(mc_header, uci->cpu_sig.sig) != UCODE_OK) { |
322 | UCODE_OK) { | ||
323 | ucode_ptr += mc_size; | 321 | ucode_ptr += mc_size; |
324 | continue; | 322 | continue; |
325 | } | 323 | } |
326 | 324 | ||
327 | mc_saved_count = _save_mc(mc_saved_tmp, ucode_ptr, mc_saved_count); | 325 | num_saved = _save_mc(mc_saved_tmp, ucode_ptr, num_saved); |
328 | 326 | ||
329 | ucode_ptr += mc_size; | 327 | ucode_ptr += mc_size; |
330 | } | 328 | } |
331 | 329 | ||
332 | if (leftover) { | 330 | if (leftover) { |
333 | state = UCODE_ERROR; | 331 | state = UCODE_ERROR; |
334 | goto out; | 332 | return state; |
335 | } | 333 | } |
336 | 334 | ||
337 | if (mc_saved_count == 0) { | 335 | if (!num_saved) { |
338 | state = UCODE_NFOUND; | 336 | state = UCODE_NFOUND; |
339 | goto out; | 337 | return state; |
340 | } | 338 | } |
341 | 339 | ||
342 | for (i = 0; i < mc_saved_count; i++) | 340 | for (i = 0; i < num_saved; i++) |
343 | mc_saved_in_initrd[i] = (unsigned long)mc_saved_tmp[i] - start; | 341 | mc_ptrs[i] = (unsigned long)mc_saved_tmp[i] - start; |
342 | |||
343 | mcs->num_saved = num_saved; | ||
344 | 344 | ||
345 | mc_saved_data->mc_saved_count = mc_saved_count; | ||
346 | out: | ||
347 | return state; | 345 | return state; |
348 | } | 346 | } |
349 | 347 | ||
@@ -373,7 +371,7 @@ static int collect_cpu_info_early(struct ucode_cpu_info *uci) | |||
373 | native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); | 371 | native_rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); |
374 | csig.pf = 1 << ((val[1] >> 18) & 7); | 372 | csig.pf = 1 << ((val[1] >> 18) & 7); |
375 | } | 373 | } |
376 | native_wrmsr(MSR_IA32_UCODE_REV, 0, 0); | 374 | native_wrmsrl(MSR_IA32_UCODE_REV, 0); |
377 | 375 | ||
378 | /* As documented in the SDM: Do a CPUID 1 here */ | 376 | /* As documented in the SDM: Do a CPUID 1 here */ |
379 | sync_core(); | 377 | sync_core(); |
@@ -396,11 +394,11 @@ static void show_saved_mc(void) | |||
396 | unsigned int sig, pf, rev, total_size, data_size, date; | 394 | unsigned int sig, pf, rev, total_size, data_size, date; |
397 | struct ucode_cpu_info uci; | 395 | struct ucode_cpu_info uci; |
398 | 396 | ||
399 | if (mc_saved_data.mc_saved_count == 0) { | 397 | if (!mc_saved_data.num_saved) { |
400 | pr_debug("no microcode data saved.\n"); | 398 | pr_debug("no microcode data saved.\n"); |
401 | return; | 399 | return; |
402 | } | 400 | } |
403 | pr_debug("Total microcode saved: %d\n", mc_saved_data.mc_saved_count); | 401 | pr_debug("Total microcode saved: %d\n", mc_saved_data.num_saved); |
404 | 402 | ||
405 | collect_cpu_info_early(&uci); | 403 | collect_cpu_info_early(&uci); |
406 | 404 | ||
@@ -409,7 +407,7 @@ static void show_saved_mc(void) | |||
409 | rev = uci.cpu_sig.rev; | 407 | rev = uci.cpu_sig.rev; |
410 | pr_debug("CPU: sig=0x%x, pf=0x%x, rev=0x%x\n", sig, pf, rev); | 408 | pr_debug("CPU: sig=0x%x, pf=0x%x, rev=0x%x\n", sig, pf, rev); |
411 | 409 | ||
412 | for (i = 0; i < mc_saved_data.mc_saved_count; i++) { | 410 | for (i = 0; i < mc_saved_data.num_saved; i++) { |
413 | struct microcode_header_intel *mc_saved_header; | 411 | struct microcode_header_intel *mc_saved_header; |
414 | struct extended_sigtable *ext_header; | 412 | struct extended_sigtable *ext_header; |
415 | int ext_sigcount; | 413 | int ext_sigcount; |
@@ -465,7 +463,7 @@ int save_mc_for_early(u8 *mc) | |||
465 | { | 463 | { |
466 | struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT]; | 464 | struct microcode_intel *mc_saved_tmp[MAX_UCODE_COUNT]; |
467 | unsigned int mc_saved_count_init; | 465 | unsigned int mc_saved_count_init; |
468 | unsigned int mc_saved_count; | 466 | unsigned int num_saved; |
469 | struct microcode_intel **mc_saved; | 467 | struct microcode_intel **mc_saved; |
470 | int ret = 0; | 468 | int ret = 0; |
471 | int i; | 469 | int i; |
@@ -476,23 +474,23 @@ int save_mc_for_early(u8 *mc) | |||
476 | */ | 474 | */ |
477 | mutex_lock(&x86_cpu_microcode_mutex); | 475 | mutex_lock(&x86_cpu_microcode_mutex); |
478 | 476 | ||
479 | mc_saved_count_init = mc_saved_data.mc_saved_count; | 477 | mc_saved_count_init = mc_saved_data.num_saved; |
480 | mc_saved_count = mc_saved_data.mc_saved_count; | 478 | num_saved = mc_saved_data.num_saved; |
481 | mc_saved = mc_saved_data.mc_saved; | 479 | mc_saved = mc_saved_data.mc_saved; |
482 | 480 | ||
483 | if (mc_saved && mc_saved_count) | 481 | if (mc_saved && num_saved) |
484 | memcpy(mc_saved_tmp, mc_saved, | 482 | memcpy(mc_saved_tmp, mc_saved, |
485 | mc_saved_count * sizeof(struct microcode_intel *)); | 483 | num_saved * sizeof(struct microcode_intel *)); |
486 | /* | 484 | /* |
487 | * Save the microcode patch mc in mc_save_tmp structure if it's a newer | 485 | * Save the microcode patch mc in mc_save_tmp structure if it's a newer |
488 | * version. | 486 | * version. |
489 | */ | 487 | */ |
490 | mc_saved_count = _save_mc(mc_saved_tmp, mc, mc_saved_count); | 488 | num_saved = _save_mc(mc_saved_tmp, mc, num_saved); |
491 | 489 | ||
492 | /* | 490 | /* |
493 | * Save the mc_save_tmp in global mc_saved_data. | 491 | * Save the mc_save_tmp in global mc_saved_data. |
494 | */ | 492 | */ |
495 | ret = save_microcode(&mc_saved_data, mc_saved_tmp, mc_saved_count); | 493 | ret = save_microcode(&mc_saved_data, mc_saved_tmp, num_saved); |
496 | if (ret) { | 494 | if (ret) { |
497 | pr_err("Cannot save microcode patch.\n"); | 495 | pr_err("Cannot save microcode patch.\n"); |
498 | goto out; | 496 | goto out; |
@@ -536,7 +534,7 @@ static bool __init load_builtin_intel_microcode(struct cpio_data *cp) | |||
536 | 534 | ||
537 | static __initdata char ucode_name[] = "kernel/x86/microcode/GenuineIntel.bin"; | 535 | static __initdata char ucode_name[] = "kernel/x86/microcode/GenuineIntel.bin"; |
538 | static __init enum ucode_state | 536 | static __init enum ucode_state |
539 | scan_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd, | 537 | scan_microcode(struct mc_saved_data *mcs, unsigned long *mc_ptrs, |
540 | unsigned long start, unsigned long size, | 538 | unsigned long start, unsigned long size, |
541 | struct ucode_cpu_info *uci) | 539 | struct ucode_cpu_info *uci) |
542 | { | 540 | { |
@@ -551,14 +549,18 @@ scan_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd, | |||
551 | cd.data = NULL; | 549 | cd.data = NULL; |
552 | cd.size = 0; | 550 | cd.size = 0; |
553 | 551 | ||
554 | cd = find_cpio_data(p, (void *)start, size, &offset); | 552 | /* try built-in microcode if no initrd */ |
555 | if (!cd.data) { | 553 | if (!size) { |
556 | if (!load_builtin_intel_microcode(&cd)) | 554 | if (!load_builtin_intel_microcode(&cd)) |
557 | return UCODE_ERROR; | 555 | return UCODE_ERROR; |
556 | } else { | ||
557 | cd = find_cpio_data(p, (void *)start, size, &offset); | ||
558 | if (!cd.data) | ||
559 | return UCODE_ERROR; | ||
558 | } | 560 | } |
559 | 561 | ||
560 | return get_matching_model_microcode(0, start, cd.data, cd.size, | 562 | return get_matching_model_microcode(start, cd.data, cd.size, |
561 | mc_saved_data, initrd, uci); | 563 | mcs, mc_ptrs, uci); |
562 | } | 564 | } |
563 | 565 | ||
564 | /* | 566 | /* |
@@ -567,14 +569,11 @@ scan_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd, | |||
567 | static void | 569 | static void |
568 | print_ucode_info(struct ucode_cpu_info *uci, unsigned int date) | 570 | print_ucode_info(struct ucode_cpu_info *uci, unsigned int date) |
569 | { | 571 | { |
570 | int cpu = smp_processor_id(); | 572 | pr_info_once("microcode updated early to revision 0x%x, date = %04x-%02x-%02x\n", |
571 | 573 | uci->cpu_sig.rev, | |
572 | pr_info("CPU%d microcode updated early to revision 0x%x, date = %04x-%02x-%02x\n", | 574 | date & 0xffff, |
573 | cpu, | 575 | date >> 24, |
574 | uci->cpu_sig.rev, | 576 | (date >> 16) & 0xff); |
575 | date & 0xffff, | ||
576 | date >> 24, | ||
577 | (date >> 16) & 0xff); | ||
578 | } | 577 | } |
579 | 578 | ||
580 | #ifdef CONFIG_X86_32 | 579 | #ifdef CONFIG_X86_32 |
@@ -603,19 +602,19 @@ void show_ucode_info_early(void) | |||
603 | */ | 602 | */ |
604 | static void print_ucode(struct ucode_cpu_info *uci) | 603 | static void print_ucode(struct ucode_cpu_info *uci) |
605 | { | 604 | { |
606 | struct microcode_intel *mc_intel; | 605 | struct microcode_intel *mc; |
607 | int *delay_ucode_info_p; | 606 | int *delay_ucode_info_p; |
608 | int *current_mc_date_p; | 607 | int *current_mc_date_p; |
609 | 608 | ||
610 | mc_intel = uci->mc; | 609 | mc = uci->mc; |
611 | if (mc_intel == NULL) | 610 | if (!mc) |
612 | return; | 611 | return; |
613 | 612 | ||
614 | delay_ucode_info_p = (int *)__pa_nodebug(&delay_ucode_info); | 613 | delay_ucode_info_p = (int *)__pa_nodebug(&delay_ucode_info); |
615 | current_mc_date_p = (int *)__pa_nodebug(¤t_mc_date); | 614 | current_mc_date_p = (int *)__pa_nodebug(¤t_mc_date); |
616 | 615 | ||
617 | *delay_ucode_info_p = 1; | 616 | *delay_ucode_info_p = 1; |
618 | *current_mc_date_p = mc_intel->hdr.date; | 617 | *current_mc_date_p = mc->hdr.date; |
619 | } | 618 | } |
620 | #else | 619 | #else |
621 | 620 | ||
@@ -630,37 +629,35 @@ static inline void flush_tlb_early(void) | |||
630 | 629 | ||
631 | static inline void print_ucode(struct ucode_cpu_info *uci) | 630 | static inline void print_ucode(struct ucode_cpu_info *uci) |
632 | { | 631 | { |
633 | struct microcode_intel *mc_intel; | 632 | struct microcode_intel *mc; |
634 | 633 | ||
635 | mc_intel = uci->mc; | 634 | mc = uci->mc; |
636 | if (mc_intel == NULL) | 635 | if (!mc) |
637 | return; | 636 | return; |
638 | 637 | ||
639 | print_ucode_info(uci, mc_intel->hdr.date); | 638 | print_ucode_info(uci, mc->hdr.date); |
640 | } | 639 | } |
641 | #endif | 640 | #endif |
642 | 641 | ||
643 | static int apply_microcode_early(struct ucode_cpu_info *uci, bool early) | 642 | static int apply_microcode_early(struct ucode_cpu_info *uci, bool early) |
644 | { | 643 | { |
645 | struct microcode_intel *mc_intel; | 644 | struct microcode_intel *mc; |
646 | unsigned int val[2]; | 645 | unsigned int val[2]; |
647 | 646 | ||
648 | mc_intel = uci->mc; | 647 | mc = uci->mc; |
649 | if (mc_intel == NULL) | 648 | if (!mc) |
650 | return 0; | 649 | return 0; |
651 | 650 | ||
652 | /* write microcode via MSR 0x79 */ | 651 | /* write microcode via MSR 0x79 */ |
653 | native_wrmsr(MSR_IA32_UCODE_WRITE, | 652 | native_wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits); |
654 | (unsigned long) mc_intel->bits, | 653 | native_wrmsrl(MSR_IA32_UCODE_REV, 0); |
655 | (unsigned long) mc_intel->bits >> 16 >> 16); | ||
656 | native_wrmsr(MSR_IA32_UCODE_REV, 0, 0); | ||
657 | 654 | ||
658 | /* As documented in the SDM: Do a CPUID 1 here */ | 655 | /* As documented in the SDM: Do a CPUID 1 here */ |
659 | sync_core(); | 656 | sync_core(); |
660 | 657 | ||
661 | /* get the current revision from MSR 0x8B */ | 658 | /* get the current revision from MSR 0x8B */ |
662 | native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); | 659 | native_rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); |
663 | if (val[1] != mc_intel->hdr.rev) | 660 | if (val[1] != mc->hdr.rev) |
664 | return -1; | 661 | return -1; |
665 | 662 | ||
666 | #ifdef CONFIG_X86_64 | 663 | #ifdef CONFIG_X86_64 |
@@ -672,25 +669,26 @@ static int apply_microcode_early(struct ucode_cpu_info *uci, bool early) | |||
672 | if (early) | 669 | if (early) |
673 | print_ucode(uci); | 670 | print_ucode(uci); |
674 | else | 671 | else |
675 | print_ucode_info(uci, mc_intel->hdr.date); | 672 | print_ucode_info(uci, mc->hdr.date); |
676 | 673 | ||
677 | return 0; | 674 | return 0; |
678 | } | 675 | } |
679 | 676 | ||
680 | /* | 677 | /* |
681 | * This function converts microcode patch offsets previously stored in | 678 | * This function converts microcode patch offsets previously stored in |
682 | * mc_saved_in_initrd to pointers and stores the pointers in mc_saved_data. | 679 | * mc_tmp_ptrs to pointers and stores the pointers in mc_saved_data. |
683 | */ | 680 | */ |
684 | int __init save_microcode_in_initrd_intel(void) | 681 | int __init save_microcode_in_initrd_intel(void) |
685 | { | 682 | { |
686 | unsigned int count = mc_saved_data.mc_saved_count; | 683 | unsigned int count = mc_saved_data.num_saved; |
687 | struct microcode_intel *mc_saved[MAX_UCODE_COUNT]; | 684 | struct microcode_intel *mc_saved[MAX_UCODE_COUNT]; |
688 | int ret = 0; | 685 | int ret = 0; |
689 | 686 | ||
690 | if (count == 0) | 687 | if (!count) |
691 | return ret; | 688 | return ret; |
692 | 689 | ||
693 | copy_initrd_ptrs(mc_saved, mc_saved_in_initrd, initrd_start, count); | 690 | copy_ptrs(mc_saved, mc_tmp_ptrs, get_initrd_start(), count); |
691 | |||
694 | ret = save_microcode(&mc_saved_data, mc_saved, count); | 692 | ret = save_microcode(&mc_saved_data, mc_saved, count); |
695 | if (ret) | 693 | if (ret) |
696 | pr_err("Cannot save microcode patches from initrd.\n"); | 694 | pr_err("Cannot save microcode patches from initrd.\n"); |
@@ -701,8 +699,7 @@ int __init save_microcode_in_initrd_intel(void) | |||
701 | } | 699 | } |
702 | 700 | ||
703 | static void __init | 701 | static void __init |
704 | _load_ucode_intel_bsp(struct mc_saved_data *mc_saved_data, | 702 | _load_ucode_intel_bsp(struct mc_saved_data *mcs, unsigned long *mc_ptrs, |
705 | unsigned long *initrd, | ||
706 | unsigned long start, unsigned long size) | 703 | unsigned long start, unsigned long size) |
707 | { | 704 | { |
708 | struct ucode_cpu_info uci; | 705 | struct ucode_cpu_info uci; |
@@ -710,11 +707,11 @@ _load_ucode_intel_bsp(struct mc_saved_data *mc_saved_data, | |||
710 | 707 | ||
711 | collect_cpu_info_early(&uci); | 708 | collect_cpu_info_early(&uci); |
712 | 709 | ||
713 | ret = scan_microcode(mc_saved_data, initrd, start, size, &uci); | 710 | ret = scan_microcode(mcs, mc_ptrs, start, size, &uci); |
714 | if (ret != UCODE_OK) | 711 | if (ret != UCODE_OK) |
715 | return; | 712 | return; |
716 | 713 | ||
717 | ret = load_microcode(mc_saved_data, initrd, start, &uci); | 714 | ret = load_microcode(mcs, mc_ptrs, start, &uci); |
718 | if (ret != UCODE_OK) | 715 | if (ret != UCODE_OK) |
719 | return; | 716 | return; |
720 | 717 | ||
@@ -728,53 +725,49 @@ void __init load_ucode_intel_bsp(void) | |||
728 | struct boot_params *p; | 725 | struct boot_params *p; |
729 | 726 | ||
730 | p = (struct boot_params *)__pa_nodebug(&boot_params); | 727 | p = (struct boot_params *)__pa_nodebug(&boot_params); |
731 | start = p->hdr.ramdisk_image; | ||
732 | size = p->hdr.ramdisk_size; | 728 | size = p->hdr.ramdisk_size; |
733 | 729 | ||
734 | _load_ucode_intel_bsp( | 730 | /* |
735 | (struct mc_saved_data *)__pa_nodebug(&mc_saved_data), | 731 | * Set start only if we have an initrd image. We cannot use initrd_start |
736 | (unsigned long *)__pa_nodebug(&mc_saved_in_initrd), | 732 | * because it is not set that early yet. |
737 | start, size); | 733 | */ |
734 | start = (size ? p->hdr.ramdisk_image : 0); | ||
735 | |||
736 | _load_ucode_intel_bsp((struct mc_saved_data *)__pa_nodebug(&mc_saved_data), | ||
737 | (unsigned long *)__pa_nodebug(&mc_tmp_ptrs), | ||
738 | start, size); | ||
738 | #else | 739 | #else |
739 | start = boot_params.hdr.ramdisk_image + PAGE_OFFSET; | ||
740 | size = boot_params.hdr.ramdisk_size; | 740 | size = boot_params.hdr.ramdisk_size; |
741 | start = (size ? boot_params.hdr.ramdisk_image + PAGE_OFFSET : 0); | ||
741 | 742 | ||
742 | _load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, start, size); | 743 | _load_ucode_intel_bsp(&mc_saved_data, mc_tmp_ptrs, start, size); |
743 | #endif | 744 | #endif |
744 | } | 745 | } |
745 | 746 | ||
746 | void load_ucode_intel_ap(void) | 747 | void load_ucode_intel_ap(void) |
747 | { | 748 | { |
748 | struct mc_saved_data *mc_saved_data_p; | 749 | unsigned long *mcs_tmp_p; |
750 | struct mc_saved_data *mcs_p; | ||
749 | struct ucode_cpu_info uci; | 751 | struct ucode_cpu_info uci; |
750 | unsigned long *mc_saved_in_initrd_p; | ||
751 | unsigned long initrd_start_addr; | ||
752 | enum ucode_state ret; | 752 | enum ucode_state ret; |
753 | #ifdef CONFIG_X86_32 | 753 | #ifdef CONFIG_X86_32 |
754 | unsigned long *initrd_start_p; | ||
755 | 754 | ||
756 | mc_saved_in_initrd_p = | 755 | mcs_tmp_p = (unsigned long *)__pa_nodebug(mc_tmp_ptrs); |
757 | (unsigned long *)__pa_nodebug(mc_saved_in_initrd); | 756 | mcs_p = (struct mc_saved_data *)__pa_nodebug(&mc_saved_data); |
758 | mc_saved_data_p = (struct mc_saved_data *)__pa_nodebug(&mc_saved_data); | ||
759 | initrd_start_p = (unsigned long *)__pa_nodebug(&initrd_start); | ||
760 | initrd_start_addr = (unsigned long)__pa_nodebug(*initrd_start_p); | ||
761 | #else | 757 | #else |
762 | mc_saved_data_p = &mc_saved_data; | 758 | mcs_tmp_p = mc_tmp_ptrs; |
763 | mc_saved_in_initrd_p = mc_saved_in_initrd; | 759 | mcs_p = &mc_saved_data; |
764 | initrd_start_addr = initrd_start; | ||
765 | #endif | 760 | #endif |
766 | 761 | ||
767 | /* | 762 | /* |
768 | * If there is no valid ucode previously saved in memory, no need to | 763 | * If there is no valid ucode previously saved in memory, no need to |
769 | * update ucode on this AP. | 764 | * update ucode on this AP. |
770 | */ | 765 | */ |
771 | if (mc_saved_data_p->mc_saved_count == 0) | 766 | if (!mcs_p->num_saved) |
772 | return; | 767 | return; |
773 | 768 | ||
774 | collect_cpu_info_early(&uci); | 769 | collect_cpu_info_early(&uci); |
775 | ret = load_microcode(mc_saved_data_p, mc_saved_in_initrd_p, | 770 | ret = load_microcode(mcs_p, mcs_tmp_p, get_initrd_start_addr(), &uci); |
776 | initrd_start_addr, &uci); | ||
777 | |||
778 | if (ret != UCODE_OK) | 771 | if (ret != UCODE_OK) |
779 | return; | 772 | return; |
780 | 773 | ||
@@ -786,13 +779,13 @@ void reload_ucode_intel(void) | |||
786 | struct ucode_cpu_info uci; | 779 | struct ucode_cpu_info uci; |
787 | enum ucode_state ret; | 780 | enum ucode_state ret; |
788 | 781 | ||
789 | if (!mc_saved_data.mc_saved_count) | 782 | if (!mc_saved_data.num_saved) |
790 | return; | 783 | return; |
791 | 784 | ||
792 | collect_cpu_info_early(&uci); | 785 | collect_cpu_info_early(&uci); |
793 | 786 | ||
794 | ret = load_microcode_early(mc_saved_data.mc_saved, | 787 | ret = load_microcode_early(mc_saved_data.mc_saved, |
795 | mc_saved_data.mc_saved_count, &uci); | 788 | mc_saved_data.num_saved, &uci); |
796 | if (ret != UCODE_OK) | 789 | if (ret != UCODE_OK) |
797 | return; | 790 | return; |
798 | 791 | ||
@@ -825,7 +818,7 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig) | |||
825 | * return 0 - no update found | 818 | * return 0 - no update found |
826 | * return 1 - found update | 819 | * return 1 - found update |
827 | */ | 820 | */ |
828 | static int get_matching_mc(struct microcode_intel *mc_intel, int cpu) | 821 | static int get_matching_mc(struct microcode_intel *mc, int cpu) |
829 | { | 822 | { |
830 | struct cpu_signature cpu_sig; | 823 | struct cpu_signature cpu_sig; |
831 | unsigned int csig, cpf, crev; | 824 | unsigned int csig, cpf, crev; |
@@ -836,39 +829,36 @@ static int get_matching_mc(struct microcode_intel *mc_intel, int cpu) | |||
836 | cpf = cpu_sig.pf; | 829 | cpf = cpu_sig.pf; |
837 | crev = cpu_sig.rev; | 830 | crev = cpu_sig.rev; |
838 | 831 | ||
839 | return has_newer_microcode(mc_intel, csig, cpf, crev); | 832 | return has_newer_microcode(mc, csig, cpf, crev); |
840 | } | 833 | } |
841 | 834 | ||
842 | static int apply_microcode_intel(int cpu) | 835 | static int apply_microcode_intel(int cpu) |
843 | { | 836 | { |
844 | struct microcode_intel *mc_intel; | 837 | struct microcode_intel *mc; |
845 | struct ucode_cpu_info *uci; | 838 | struct ucode_cpu_info *uci; |
839 | struct cpuinfo_x86 *c; | ||
846 | unsigned int val[2]; | 840 | unsigned int val[2]; |
847 | int cpu_num = raw_smp_processor_id(); | ||
848 | struct cpuinfo_x86 *c = &cpu_data(cpu_num); | ||
849 | |||
850 | uci = ucode_cpu_info + cpu; | ||
851 | mc_intel = uci->mc; | ||
852 | 841 | ||
853 | /* We should bind the task to the CPU */ | 842 | /* We should bind the task to the CPU */ |
854 | BUG_ON(cpu_num != cpu); | 843 | if (WARN_ON(raw_smp_processor_id() != cpu)) |
844 | return -1; | ||
855 | 845 | ||
856 | if (mc_intel == NULL) | 846 | uci = ucode_cpu_info + cpu; |
847 | mc = uci->mc; | ||
848 | if (!mc) | ||
857 | return 0; | 849 | return 0; |
858 | 850 | ||
859 | /* | 851 | /* |
860 | * Microcode on this CPU could be updated earlier. Only apply the | 852 | * Microcode on this CPU could be updated earlier. Only apply the |
861 | * microcode patch in mc_intel when it is newer than the one on this | 853 | * microcode patch in mc when it is newer than the one on this |
862 | * CPU. | 854 | * CPU. |
863 | */ | 855 | */ |
864 | if (get_matching_mc(mc_intel, cpu) == 0) | 856 | if (!get_matching_mc(mc, cpu)) |
865 | return 0; | 857 | return 0; |
866 | 858 | ||
867 | /* write microcode via MSR 0x79 */ | 859 | /* write microcode via MSR 0x79 */ |
868 | wrmsr(MSR_IA32_UCODE_WRITE, | 860 | wrmsrl(MSR_IA32_UCODE_WRITE, (unsigned long)mc->bits); |
869 | (unsigned long) mc_intel->bits, | 861 | wrmsrl(MSR_IA32_UCODE_REV, 0); |
870 | (unsigned long) mc_intel->bits >> 16 >> 16); | ||
871 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); | ||
872 | 862 | ||
873 | /* As documented in the SDM: Do a CPUID 1 here */ | 863 | /* As documented in the SDM: Do a CPUID 1 here */ |
874 | sync_core(); | 864 | sync_core(); |
@@ -876,16 +866,19 @@ static int apply_microcode_intel(int cpu) | |||
876 | /* get the current revision from MSR 0x8B */ | 866 | /* get the current revision from MSR 0x8B */ |
877 | rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); | 867 | rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); |
878 | 868 | ||
879 | if (val[1] != mc_intel->hdr.rev) { | 869 | if (val[1] != mc->hdr.rev) { |
880 | pr_err("CPU%d update to revision 0x%x failed\n", | 870 | pr_err("CPU%d update to revision 0x%x failed\n", |
881 | cpu_num, mc_intel->hdr.rev); | 871 | cpu, mc->hdr.rev); |
882 | return -1; | 872 | return -1; |
883 | } | 873 | } |
874 | |||
884 | pr_info("CPU%d updated to revision 0x%x, date = %04x-%02x-%02x\n", | 875 | pr_info("CPU%d updated to revision 0x%x, date = %04x-%02x-%02x\n", |
885 | cpu_num, val[1], | 876 | cpu, val[1], |
886 | mc_intel->hdr.date & 0xffff, | 877 | mc->hdr.date & 0xffff, |
887 | mc_intel->hdr.date >> 24, | 878 | mc->hdr.date >> 24, |
888 | (mc_intel->hdr.date >> 16) & 0xff); | 879 | (mc->hdr.date >> 16) & 0xff); |
880 | |||
881 | c = &cpu_data(cpu); | ||
889 | 882 | ||
890 | uci->cpu_sig.rev = val[1]; | 883 | uci->cpu_sig.rev = val[1]; |
891 | c->microcode = val[1]; | 884 | c->microcode = val[1]; |
diff --git a/arch/x86/kernel/cpu/microcode/intel_lib.c b/arch/x86/kernel/cpu/microcode/intel_lib.c index b96896bcbdaf..2ce1a7dc45b7 100644 --- a/arch/x86/kernel/cpu/microcode/intel_lib.c +++ b/arch/x86/kernel/cpu/microcode/intel_lib.c | |||
@@ -49,7 +49,7 @@ int microcode_sanity_check(void *mc, int print_err) | |||
49 | unsigned long total_size, data_size, ext_table_size; | 49 | unsigned long total_size, data_size, ext_table_size; |
50 | struct microcode_header_intel *mc_header = mc; | 50 | struct microcode_header_intel *mc_header = mc; |
51 | struct extended_sigtable *ext_header = NULL; | 51 | struct extended_sigtable *ext_header = NULL; |
52 | int sum, orig_sum, ext_sigcount = 0, i; | 52 | u32 sum, orig_sum, ext_sigcount = 0, i; |
53 | struct extended_signature *ext_sig; | 53 | struct extended_signature *ext_sig; |
54 | 54 | ||
55 | total_size = get_totalsize(mc_header); | 55 | total_size = get_totalsize(mc_header); |
@@ -57,69 +57,85 @@ int microcode_sanity_check(void *mc, int print_err) | |||
57 | 57 | ||
58 | if (data_size + MC_HEADER_SIZE > total_size) { | 58 | if (data_size + MC_HEADER_SIZE > total_size) { |
59 | if (print_err) | 59 | if (print_err) |
60 | pr_err("error! Bad data size in microcode data file\n"); | 60 | pr_err("Error: bad microcode data file size.\n"); |
61 | return -EINVAL; | 61 | return -EINVAL; |
62 | } | 62 | } |
63 | 63 | ||
64 | if (mc_header->ldrver != 1 || mc_header->hdrver != 1) { | 64 | if (mc_header->ldrver != 1 || mc_header->hdrver != 1) { |
65 | if (print_err) | 65 | if (print_err) |
66 | pr_err("error! Unknown microcode update format\n"); | 66 | pr_err("Error: invalid/unknown microcode update format.\n"); |
67 | return -EINVAL; | 67 | return -EINVAL; |
68 | } | 68 | } |
69 | |||
69 | ext_table_size = total_size - (MC_HEADER_SIZE + data_size); | 70 | ext_table_size = total_size - (MC_HEADER_SIZE + data_size); |
70 | if (ext_table_size) { | 71 | if (ext_table_size) { |
72 | u32 ext_table_sum = 0; | ||
73 | u32 *ext_tablep; | ||
74 | |||
71 | if ((ext_table_size < EXT_HEADER_SIZE) | 75 | if ((ext_table_size < EXT_HEADER_SIZE) |
72 | || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) { | 76 | || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) { |
73 | if (print_err) | 77 | if (print_err) |
74 | pr_err("error! Small exttable size in microcode data file\n"); | 78 | pr_err("Error: truncated extended signature table.\n"); |
75 | return -EINVAL; | 79 | return -EINVAL; |
76 | } | 80 | } |
81 | |||
77 | ext_header = mc + MC_HEADER_SIZE + data_size; | 82 | ext_header = mc + MC_HEADER_SIZE + data_size; |
78 | if (ext_table_size != exttable_size(ext_header)) { | 83 | if (ext_table_size != exttable_size(ext_header)) { |
79 | if (print_err) | 84 | if (print_err) |
80 | pr_err("error! Bad exttable size in microcode data file\n"); | 85 | pr_err("Error: extended signature table size mismatch.\n"); |
81 | return -EFAULT; | 86 | return -EFAULT; |
82 | } | 87 | } |
88 | |||
83 | ext_sigcount = ext_header->count; | 89 | ext_sigcount = ext_header->count; |
84 | } | ||
85 | 90 | ||
86 | /* check extended table checksum */ | 91 | /* |
87 | if (ext_table_size) { | 92 | * Check extended table checksum: the sum of all dwords that |
88 | int ext_table_sum = 0; | 93 | * comprise a valid table must be 0. |
89 | int *ext_tablep = (int *)ext_header; | 94 | */ |
95 | ext_tablep = (u32 *)ext_header; | ||
90 | 96 | ||
91 | i = ext_table_size / DWSIZE; | 97 | i = ext_table_size / sizeof(u32); |
92 | while (i--) | 98 | while (i--) |
93 | ext_table_sum += ext_tablep[i]; | 99 | ext_table_sum += ext_tablep[i]; |
100 | |||
94 | if (ext_table_sum) { | 101 | if (ext_table_sum) { |
95 | if (print_err) | 102 | if (print_err) |
96 | pr_warn("aborting, bad extended signature table checksum\n"); | 103 | pr_warn("Bad extended signature table checksum, aborting.\n"); |
97 | return -EINVAL; | 104 | return -EINVAL; |
98 | } | 105 | } |
99 | } | 106 | } |
100 | 107 | ||
101 | /* calculate the checksum */ | 108 | /* |
109 | * Calculate the checksum of update data and header. The checksum of | ||
110 | * valid update data and header including the extended signature table | ||
111 | * must be 0. | ||
112 | */ | ||
102 | orig_sum = 0; | 113 | orig_sum = 0; |
103 | i = (MC_HEADER_SIZE + data_size) / DWSIZE; | 114 | i = (MC_HEADER_SIZE + data_size) / sizeof(u32); |
104 | while (i--) | 115 | while (i--) |
105 | orig_sum += ((int *)mc)[i]; | 116 | orig_sum += ((u32 *)mc)[i]; |
117 | |||
106 | if (orig_sum) { | 118 | if (orig_sum) { |
107 | if (print_err) | 119 | if (print_err) |
108 | pr_err("aborting, bad checksum\n"); | 120 | pr_err("Bad microcode data checksum, aborting.\n"); |
109 | return -EINVAL; | 121 | return -EINVAL; |
110 | } | 122 | } |
123 | |||
111 | if (!ext_table_size) | 124 | if (!ext_table_size) |
112 | return 0; | 125 | return 0; |
113 | /* check extended signature checksum */ | 126 | |
127 | /* | ||
128 | * Check extended signature checksum: 0 => valid. | ||
129 | */ | ||
114 | for (i = 0; i < ext_sigcount; i++) { | 130 | for (i = 0; i < ext_sigcount; i++) { |
115 | ext_sig = (void *)ext_header + EXT_HEADER_SIZE + | 131 | ext_sig = (void *)ext_header + EXT_HEADER_SIZE + |
116 | EXT_SIGNATURE_SIZE * i; | 132 | EXT_SIGNATURE_SIZE * i; |
117 | sum = orig_sum | 133 | |
118 | - (mc_header->sig + mc_header->pf + mc_header->cksum) | 134 | sum = (mc_header->sig + mc_header->pf + mc_header->cksum) - |
119 | + (ext_sig->sig + ext_sig->pf + ext_sig->cksum); | 135 | (ext_sig->sig + ext_sig->pf + ext_sig->cksum); |
120 | if (sum) { | 136 | if (sum) { |
121 | if (print_err) | 137 | if (print_err) |
122 | pr_err("aborting, bad checksum\n"); | 138 | pr_err("Bad extended signature checksum, aborting.\n"); |
123 | return -EINVAL; | 139 | return -EINVAL; |
124 | } | 140 | } |
125 | } | 141 | } |