diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2009-03-30 23:03:50 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2009-03-30 23:03:50 -0400 |
commit | 558f6ab9106e6be701acb0257e7171df1bbccf04 (patch) | |
tree | 6e811633baeb676693c493f6c82bf785cab2771d /arch/x86/kernel/microcode_intel.c | |
parent | 15f7176eb1cccec0a332541285ee752b935c1c85 (diff) | |
parent | 65fb0d23fcddd8697c871047b700c78817bdaa43 (diff) |
Merge branch 'cpumask-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
Conflicts:
arch/x86/include/asm/topology.h
drivers/oprofile/buffer_sync.c
(Both cases: changed in Linus' tree, removed in Ingo's).
Diffstat (limited to 'arch/x86/kernel/microcode_intel.c')
-rw-r--r-- | arch/x86/kernel/microcode_intel.c | 83 |
1 files changed, 48 insertions, 35 deletions
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index 5e9f4fc51385..149b9ec7c1ab 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c | |||
@@ -70,28 +70,28 @@ | |||
70 | * Fix sigmatch() macro to handle old CPUs with pf == 0. | 70 | * Fix sigmatch() macro to handle old CPUs with pf == 0. |
71 | * Thanks to Stuart Swales for pointing out this bug. | 71 | * Thanks to Stuart Swales for pointing out this bug. |
72 | */ | 72 | */ |
73 | #include <linux/platform_device.h> | ||
73 | #include <linux/capability.h> | 74 | #include <linux/capability.h> |
74 | #include <linux/kernel.h> | 75 | #include <linux/miscdevice.h> |
75 | #include <linux/init.h> | 76 | #include <linux/firmware.h> |
76 | #include <linux/sched.h> | ||
77 | #include <linux/smp_lock.h> | 77 | #include <linux/smp_lock.h> |
78 | #include <linux/spinlock.h> | ||
78 | #include <linux/cpumask.h> | 79 | #include <linux/cpumask.h> |
79 | #include <linux/module.h> | 80 | #include <linux/uaccess.h> |
80 | #include <linux/slab.h> | ||
81 | #include <linux/vmalloc.h> | 81 | #include <linux/vmalloc.h> |
82 | #include <linux/miscdevice.h> | 82 | #include <linux/kernel.h> |
83 | #include <linux/spinlock.h> | 83 | #include <linux/module.h> |
84 | #include <linux/mm.h> | ||
85 | #include <linux/fs.h> | ||
86 | #include <linux/mutex.h> | 84 | #include <linux/mutex.h> |
85 | #include <linux/sched.h> | ||
86 | #include <linux/init.h> | ||
87 | #include <linux/slab.h> | ||
87 | #include <linux/cpu.h> | 88 | #include <linux/cpu.h> |
88 | #include <linux/firmware.h> | 89 | #include <linux/fs.h> |
89 | #include <linux/platform_device.h> | 90 | #include <linux/mm.h> |
90 | #include <linux/uaccess.h> | ||
91 | 91 | ||
92 | #include <asm/msr.h> | ||
93 | #include <asm/processor.h> | ||
94 | #include <asm/microcode.h> | 92 | #include <asm/microcode.h> |
93 | #include <asm/processor.h> | ||
94 | #include <asm/msr.h> | ||
95 | 95 | ||
96 | MODULE_DESCRIPTION("Microcode Update Driver"); | 96 | MODULE_DESCRIPTION("Microcode Update Driver"); |
97 | MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>"); | 97 | MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>"); |
@@ -129,12 +129,13 @@ struct extended_sigtable { | |||
129 | struct extended_signature sigs[0]; | 129 | struct extended_signature sigs[0]; |
130 | }; | 130 | }; |
131 | 131 | ||
132 | #define DEFAULT_UCODE_DATASIZE (2000) | 132 | #define DEFAULT_UCODE_DATASIZE (2000) |
133 | #define MC_HEADER_SIZE (sizeof(struct microcode_header_intel)) | 133 | #define MC_HEADER_SIZE (sizeof(struct microcode_header_intel)) |
134 | #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) | 134 | #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) |
135 | #define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) | 135 | #define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) |
136 | #define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature)) | 136 | #define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature)) |
137 | #define DWSIZE (sizeof(u32)) | 137 | #define DWSIZE (sizeof(u32)) |
138 | |||
138 | #define get_totalsize(mc) \ | 139 | #define get_totalsize(mc) \ |
139 | (((struct microcode_intel *)mc)->hdr.totalsize ? \ | 140 | (((struct microcode_intel *)mc)->hdr.totalsize ? \ |
140 | ((struct microcode_intel *)mc)->hdr.totalsize : \ | 141 | ((struct microcode_intel *)mc)->hdr.totalsize : \ |
@@ -197,30 +198,31 @@ static inline int update_match_cpu(struct cpu_signature *csig, int sig, int pf) | |||
197 | } | 198 | } |
198 | 199 | ||
199 | static inline int | 200 | static inline int |
200 | update_match_revision(struct microcode_header_intel *mc_header, int rev) | 201 | update_match_revision(struct microcode_header_intel *mc_header, int rev) |
201 | { | 202 | { |
202 | return (mc_header->rev <= rev) ? 0 : 1; | 203 | return (mc_header->rev <= rev) ? 0 : 1; |
203 | } | 204 | } |
204 | 205 | ||
205 | static int microcode_sanity_check(void *mc) | 206 | static int microcode_sanity_check(void *mc) |
206 | { | 207 | { |
208 | unsigned long total_size, data_size, ext_table_size; | ||
207 | struct microcode_header_intel *mc_header = mc; | 209 | struct microcode_header_intel *mc_header = mc; |
208 | struct extended_sigtable *ext_header = NULL; | 210 | struct extended_sigtable *ext_header = NULL; |
209 | struct extended_signature *ext_sig; | ||
210 | unsigned long total_size, data_size, ext_table_size; | ||
211 | int sum, orig_sum, ext_sigcount = 0, i; | 211 | int sum, orig_sum, ext_sigcount = 0, i; |
212 | struct extended_signature *ext_sig; | ||
212 | 213 | ||
213 | total_size = get_totalsize(mc_header); | 214 | total_size = get_totalsize(mc_header); |
214 | data_size = get_datasize(mc_header); | 215 | data_size = get_datasize(mc_header); |
216 | |||
215 | if (data_size + MC_HEADER_SIZE > total_size) { | 217 | if (data_size + MC_HEADER_SIZE > total_size) { |
216 | printk(KERN_ERR "microcode: error! " | 218 | printk(KERN_ERR "microcode: error! " |
217 | "Bad data size in microcode data file\n"); | 219 | "Bad data size in microcode data file\n"); |
218 | return -EINVAL; | 220 | return -EINVAL; |
219 | } | 221 | } |
220 | 222 | ||
221 | if (mc_header->ldrver != 1 || mc_header->hdrver != 1) { | 223 | if (mc_header->ldrver != 1 || mc_header->hdrver != 1) { |
222 | printk(KERN_ERR "microcode: error! " | 224 | printk(KERN_ERR "microcode: error! " |
223 | "Unknown microcode update format\n"); | 225 | "Unknown microcode update format\n"); |
224 | return -EINVAL; | 226 | return -EINVAL; |
225 | } | 227 | } |
226 | ext_table_size = total_size - (MC_HEADER_SIZE + data_size); | 228 | ext_table_size = total_size - (MC_HEADER_SIZE + data_size); |
@@ -318,11 +320,15 @@ get_matching_microcode(struct cpu_signature *cpu_sig, void *mc, int rev) | |||
318 | 320 | ||
319 | static void apply_microcode(int cpu) | 321 | static void apply_microcode(int cpu) |
320 | { | 322 | { |
323 | struct microcode_intel *mc_intel; | ||
324 | struct ucode_cpu_info *uci; | ||
321 | unsigned long flags; | 325 | unsigned long flags; |
322 | unsigned int val[2]; | 326 | unsigned int val[2]; |
323 | int cpu_num = raw_smp_processor_id(); | 327 | int cpu_num; |
324 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | 328 | |
325 | struct microcode_intel *mc_intel = uci->mc; | 329 | cpu_num = raw_smp_processor_id(); |
330 | uci = ucode_cpu_info + cpu; | ||
331 | mc_intel = uci->mc; | ||
326 | 332 | ||
327 | /* We should bind the task to the CPU */ | 333 | /* We should bind the task to the CPU */ |
328 | BUG_ON(cpu_num != cpu); | 334 | BUG_ON(cpu_num != cpu); |
@@ -348,15 +354,17 @@ static void apply_microcode(int cpu) | |||
348 | spin_unlock_irqrestore(µcode_update_lock, flags); | 354 | spin_unlock_irqrestore(µcode_update_lock, flags); |
349 | if (val[1] != mc_intel->hdr.rev) { | 355 | if (val[1] != mc_intel->hdr.rev) { |
350 | printk(KERN_ERR "microcode: CPU%d update from revision " | 356 | printk(KERN_ERR "microcode: CPU%d update from revision " |
351 | "0x%x to 0x%x failed\n", cpu_num, uci->cpu_sig.rev, val[1]); | 357 | "0x%x to 0x%x failed\n", |
358 | cpu_num, uci->cpu_sig.rev, val[1]); | ||
352 | return; | 359 | return; |
353 | } | 360 | } |
354 | printk(KERN_INFO "microcode: CPU%d updated from revision " | 361 | printk(KERN_INFO "microcode: CPU%d updated from revision " |
355 | "0x%x to 0x%x, date = %04x-%02x-%02x \n", | 362 | "0x%x to 0x%x, date = %04x-%02x-%02x \n", |
356 | cpu_num, uci->cpu_sig.rev, val[1], | 363 | cpu_num, uci->cpu_sig.rev, val[1], |
357 | mc_intel->hdr.date & 0xffff, | 364 | mc_intel->hdr.date & 0xffff, |
358 | mc_intel->hdr.date >> 24, | 365 | mc_intel->hdr.date >> 24, |
359 | (mc_intel->hdr.date >> 16) & 0xff); | 366 | (mc_intel->hdr.date >> 16) & 0xff); |
367 | |||
360 | uci->cpu_sig.rev = val[1]; | 368 | uci->cpu_sig.rev = val[1]; |
361 | } | 369 | } |
362 | 370 | ||
@@ -404,18 +412,23 @@ static int generic_load_microcode(int cpu, void *data, size_t size, | |||
404 | leftover -= mc_size; | 412 | leftover -= mc_size; |
405 | } | 413 | } |
406 | 414 | ||
407 | if (new_mc) { | 415 | if (!new_mc) |
408 | if (!leftover) { | 416 | goto out; |
409 | if (uci->mc) | 417 | |
410 | vfree(uci->mc); | 418 | if (leftover) { |
411 | uci->mc = (struct microcode_intel *)new_mc; | 419 | vfree(new_mc); |
412 | pr_debug("microcode: CPU%d found a matching microcode update with" | 420 | goto out; |
413 | " version 0x%x (current=0x%x)\n", | ||
414 | cpu, new_rev, uci->cpu_sig.rev); | ||
415 | } else | ||
416 | vfree(new_mc); | ||
417 | } | 421 | } |
418 | 422 | ||
423 | if (uci->mc) | ||
424 | vfree(uci->mc); | ||
425 | uci->mc = (struct microcode_intel *)new_mc; | ||
426 | |||
427 | pr_debug("microcode: CPU%d found a matching microcode update with" | ||
428 | " version 0x%x (current=0x%x)\n", | ||
429 | cpu, new_rev, uci->cpu_sig.rev); | ||
430 | |||
431 | out: | ||
419 | return (int)leftover; | 432 | return (int)leftover; |
420 | } | 433 | } |
421 | 434 | ||