diff options
-rw-r--r-- | arch/x86/Kconfig | 10 | ||||
-rw-r--r-- | arch/x86/kernel/Makefile | 8 | ||||
-rw-r--r-- | arch/x86/kernel/microcode_amd.c | 72 | ||||
-rw-r--r-- | arch/x86/kernel/microcode_core.c (renamed from arch/x86/kernel/microcode.c) | 26 | ||||
-rw-r--r-- | arch/x86/kernel/microcode_intel.c | 79 | ||||
-rw-r--r-- | include/asm-x86/microcode.h | 99 |
6 files changed, 138 insertions, 156 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 0e5bf1eddcea..2e6080951350 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -801,7 +801,7 @@ config MICROCODE | |||
801 | module will be called microcode. | 801 | module will be called microcode. |
802 | 802 | ||
803 | config MICROCODE_INTEL | 803 | config MICROCODE_INTEL |
804 | tristate "Intel microcode patch loading support" | 804 | bool "Intel microcode patch loading support" |
805 | depends on MICROCODE | 805 | depends on MICROCODE |
806 | default MICROCODE | 806 | default MICROCODE |
807 | select FW_LOADER | 807 | select FW_LOADER |
@@ -813,20 +813,14 @@ config MICROCODE_INTEL | |||
813 | Intel ingredients for this driver, check: | 813 | Intel ingredients for this driver, check: |
814 | <http://www.urbanmyth.org/microcode/>. | 814 | <http://www.urbanmyth.org/microcode/>. |
815 | 815 | ||
816 | This driver is only available as a module: the module | ||
817 | will be called microcode_intel. | ||
818 | |||
819 | config MICROCODE_AMD | 816 | config MICROCODE_AMD |
820 | tristate "AMD microcode patch loading support" | 817 | bool "AMD microcode patch loading support" |
821 | depends on MICROCODE | 818 | depends on MICROCODE |
822 | select FW_LOADER | 819 | select FW_LOADER |
823 | --help--- | 820 | --help--- |
824 | If you select this option, microcode patch loading support for AMD | 821 | If you select this option, microcode patch loading support for AMD |
825 | processors will be enabled. | 822 | processors will be enabled. |
826 | 823 | ||
827 | This driver is only available as a module: the module | ||
828 | will be called microcode_amd. | ||
829 | |||
830 | config MICROCODE_OLD_INTERFACE | 824 | config MICROCODE_OLD_INTERFACE |
831 | def_bool y | 825 | def_bool y |
832 | depends on MICROCODE | 826 | depends on MICROCODE |
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index be454f348c3b..f891996f6849 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
@@ -51,9 +51,6 @@ obj-$(CONFIG_X86_BIOS_REBOOT) += reboot.o | |||
51 | obj-$(CONFIG_MCA) += mca_32.o | 51 | obj-$(CONFIG_MCA) += mca_32.o |
52 | obj-$(CONFIG_X86_MSR) += msr.o | 52 | obj-$(CONFIG_X86_MSR) += msr.o |
53 | obj-$(CONFIG_X86_CPUID) += cpuid.o | 53 | obj-$(CONFIG_X86_CPUID) += cpuid.o |
54 | obj-$(CONFIG_MICROCODE) += microcode.o | ||
55 | obj-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o | ||
56 | obj-$(CONFIG_MICROCODE_AMD) += microcode_amd.o | ||
57 | obj-$(CONFIG_PCI) += early-quirks.o | 54 | obj-$(CONFIG_PCI) += early-quirks.o |
58 | apm-y := apm_32.o | 55 | apm-y := apm_32.o |
59 | obj-$(CONFIG_APM) += apm.o | 56 | obj-$(CONFIG_APM) += apm.o |
@@ -101,6 +98,11 @@ scx200-y += scx200_32.o | |||
101 | 98 | ||
102 | obj-$(CONFIG_OLPC) += olpc.o | 99 | obj-$(CONFIG_OLPC) += olpc.o |
103 | 100 | ||
101 | microcode-y := microcode_core.o | ||
102 | microcode-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o | ||
103 | microcode-$(CONFIG_MICROCODE_AMD) += microcode_amd.o | ||
104 | obj-$(CONFIG_MICROCODE) += microcode.o | ||
105 | |||
104 | ### | 106 | ### |
105 | # 64 bit specific files | 107 | # 64 bit specific files |
106 | ifeq ($(CONFIG_X86_64),y) | 108 | ifeq ($(CONFIG_X86_64),y) |
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 48aec9f48e4f..03ea4e52e87a 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c | |||
@@ -46,6 +46,35 @@ MODULE_LICENSE("GPL v2"); | |||
46 | #define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000 | 46 | #define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000 |
47 | #define UCODE_UCODE_TYPE 0x00000001 | 47 | #define UCODE_UCODE_TYPE 0x00000001 |
48 | 48 | ||
49 | struct equiv_cpu_entry { | ||
50 | unsigned int installed_cpu; | ||
51 | unsigned int fixed_errata_mask; | ||
52 | unsigned int fixed_errata_compare; | ||
53 | unsigned int equiv_cpu; | ||
54 | }; | ||
55 | |||
56 | struct microcode_header_amd { | ||
57 | unsigned int data_code; | ||
58 | unsigned int patch_id; | ||
59 | unsigned char mc_patch_data_id[2]; | ||
60 | unsigned char mc_patch_data_len; | ||
61 | unsigned char init_flag; | ||
62 | unsigned int mc_patch_data_checksum; | ||
63 | unsigned int nb_dev_id; | ||
64 | unsigned int sb_dev_id; | ||
65 | unsigned char processor_rev_id[2]; | ||
66 | unsigned char nb_rev_id; | ||
67 | unsigned char sb_rev_id; | ||
68 | unsigned char bios_api_rev; | ||
69 | unsigned char reserved1[3]; | ||
70 | unsigned int match_reg[8]; | ||
71 | }; | ||
72 | |||
73 | struct microcode_amd { | ||
74 | struct microcode_header_amd hdr; | ||
75 | unsigned int mpb[0]; | ||
76 | }; | ||
77 | |||
49 | #define UCODE_MAX_SIZE (2048) | 78 | #define UCODE_MAX_SIZE (2048) |
50 | #define DEFAULT_UCODE_DATASIZE (896) | 79 | #define DEFAULT_UCODE_DATASIZE (896) |
51 | #define MC_HEADER_SIZE (sizeof(struct microcode_header_amd)) | 80 | #define MC_HEADER_SIZE (sizeof(struct microcode_header_amd)) |
@@ -189,17 +218,18 @@ static void apply_microcode_amd(int cpu) | |||
189 | unsigned int rev; | 218 | unsigned int rev; |
190 | int cpu_num = raw_smp_processor_id(); | 219 | int cpu_num = raw_smp_processor_id(); |
191 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; | 220 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; |
221 | struct microcode_amd *mc_amd = uci->mc; | ||
192 | unsigned long addr; | 222 | unsigned long addr; |
193 | 223 | ||
194 | /* We should bind the task to the CPU */ | 224 | /* We should bind the task to the CPU */ |
195 | BUG_ON(cpu_num != cpu); | 225 | BUG_ON(cpu_num != cpu); |
196 | 226 | ||
197 | if (uci->mc.mc_amd == NULL) | 227 | if (mc_amd == NULL) |
198 | return; | 228 | return; |
199 | 229 | ||
200 | spin_lock_irqsave(µcode_update_lock, flags); | 230 | spin_lock_irqsave(µcode_update_lock, flags); |
201 | 231 | ||
202 | addr = (unsigned long)&uci->mc.mc_amd->hdr.data_code; | 232 | addr = (unsigned long)&mc_amd->hdr.data_code; |
203 | edx = (unsigned int)(((unsigned long)upper_32_bits(addr))); | 233 | edx = (unsigned int)(((unsigned long)upper_32_bits(addr))); |
204 | eax = (unsigned int)(((unsigned long)lower_32_bits(addr))); | 234 | eax = (unsigned int)(((unsigned long)lower_32_bits(addr))); |
205 | 235 | ||
@@ -214,16 +244,16 @@ static void apply_microcode_amd(int cpu) | |||
214 | spin_unlock_irqrestore(µcode_update_lock, flags); | 244 | spin_unlock_irqrestore(µcode_update_lock, flags); |
215 | 245 | ||
216 | /* check current patch id and patch's id for match */ | 246 | /* check current patch id and patch's id for match */ |
217 | if (rev != uci->mc.mc_amd->hdr.patch_id) { | 247 | if (rev != mc_amd->hdr.patch_id) { |
218 | printk(KERN_ERR "microcode: CPU%d update from revision " | 248 | printk(KERN_ERR "microcode: CPU%d update from revision " |
219 | "0x%x to 0x%x failed\n", cpu_num, | 249 | "0x%x to 0x%x failed\n", cpu_num, |
220 | uci->mc.mc_amd->hdr.patch_id, rev); | 250 | mc_amd->hdr.patch_id, rev); |
221 | return; | 251 | return; |
222 | } | 252 | } |
223 | 253 | ||
224 | printk(KERN_INFO "microcode: CPU%d updated from revision " | 254 | printk(KERN_INFO "microcode: CPU%d updated from revision " |
225 | "0x%x to 0x%x \n", | 255 | "0x%x to 0x%x \n", |
226 | cpu_num, uci->cpu_sig.rev, uci->mc.mc_amd->hdr.patch_id); | 256 | cpu_num, uci->cpu_sig.rev, mc_amd->hdr.patch_id); |
227 | 257 | ||
228 | uci->cpu_sig.rev = rev; | 258 | uci->cpu_sig.rev = rev; |
229 | } | 259 | } |
@@ -355,12 +385,12 @@ static int generic_load_microcode(int cpu, void *data, size_t size, | |||
355 | 385 | ||
356 | if (new_mc) { | 386 | if (new_mc) { |
357 | if (!leftover) { | 387 | if (!leftover) { |
358 | if (uci->mc.mc_amd) | 388 | if (uci->mc) |
359 | vfree(uci->mc.mc_amd); | 389 | vfree(uci->mc); |
360 | uci->mc.mc_amd = (struct microcode_amd *)new_mc; | 390 | uci->mc = new_mc; |
361 | pr_debug("microcode: CPU%d found a matching microcode update with" | 391 | pr_debug("microcode: CPU%d found a matching microcode update with" |
362 | " version 0x%x (current=0x%x)\n", | 392 | " version 0x%x (current=0x%x)\n", |
363 | cpu, uci->mc.mc_amd->hdr.patch_id, uci->cpu_sig.rev); | 393 | cpu, new_rev, uci->cpu_sig.rev); |
364 | } else | 394 | } else |
365 | vfree(new_mc); | 395 | vfree(new_mc); |
366 | } | 396 | } |
@@ -416,8 +446,8 @@ static void microcode_fini_cpu_amd(int cpu) | |||
416 | { | 446 | { |
417 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | 447 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
418 | 448 | ||
419 | vfree(uci->mc.mc_amd); | 449 | vfree(uci->mc); |
420 | uci->mc.mc_amd = NULL; | 450 | uci->mc = NULL; |
421 | } | 451 | } |
422 | 452 | ||
423 | static struct microcode_ops microcode_amd_ops = { | 453 | static struct microcode_ops microcode_amd_ops = { |
@@ -428,23 +458,7 @@ static struct microcode_ops microcode_amd_ops = { | |||
428 | .microcode_fini_cpu = microcode_fini_cpu_amd, | 458 | .microcode_fini_cpu = microcode_fini_cpu_amd, |
429 | }; | 459 | }; |
430 | 460 | ||
431 | static int __init microcode_amd_module_init(void) | 461 | struct microcode_ops * __init init_amd_microcode(void) |
432 | { | 462 | { |
433 | struct cpuinfo_x86 *c = &cpu_data(0); | 463 | return µcode_amd_ops; |
434 | |||
435 | equiv_cpu_table = NULL; | ||
436 | if (c->x86_vendor != X86_VENDOR_AMD) { | ||
437 | printk(KERN_ERR "microcode: CPU platform is not AMD-capable\n"); | ||
438 | return -ENODEV; | ||
439 | } | ||
440 | |||
441 | return microcode_init(µcode_amd_ops, THIS_MODULE); | ||
442 | } | ||
443 | |||
444 | static void __exit microcode_amd_module_exit(void) | ||
445 | { | ||
446 | microcode_exit(); | ||
447 | } | 464 | } |
448 | |||
449 | module_init(microcode_amd_module_init) | ||
450 | module_exit(microcode_amd_module_exit) | ||
diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode_core.c index 0c2634f4fd7c..ff031dbccdf6 100644 --- a/arch/x86/kernel/microcode.c +++ b/arch/x86/kernel/microcode_core.c | |||
@@ -298,7 +298,7 @@ static int microcode_resume_cpu(int cpu) | |||
298 | 298 | ||
299 | pr_debug("microcode: CPU%d resumed\n", cpu); | 299 | pr_debug("microcode: CPU%d resumed\n", cpu); |
300 | 300 | ||
301 | if (!uci->mc.valid_mc) | 301 | if (!uci->mc) |
302 | return 1; | 302 | return 1; |
303 | 303 | ||
304 | /* | 304 | /* |
@@ -443,17 +443,20 @@ static struct notifier_block __refdata mc_cpu_notifier = { | |||
443 | .notifier_call = mc_cpu_callback, | 443 | .notifier_call = mc_cpu_callback, |
444 | }; | 444 | }; |
445 | 445 | ||
446 | int microcode_init(void *opaque, struct module *module) | 446 | static int __init microcode_init(void) |
447 | { | 447 | { |
448 | struct microcode_ops *ops = (struct microcode_ops *)opaque; | 448 | struct cpuinfo_x86 *c = &cpu_data(0); |
449 | int error; | 449 | int error; |
450 | 450 | ||
451 | if (microcode_ops) { | 451 | if (c->x86_vendor == X86_VENDOR_INTEL) |
452 | printk(KERN_ERR "microcode: already loaded the other module\n"); | 452 | microcode_ops = init_intel_microcode(); |
453 | return -EEXIST; | 453 | else if (c->x86_vendor != X86_VENDOR_AMD) |
454 | } | 454 | microcode_ops = init_amd_microcode(); |
455 | 455 | ||
456 | microcode_ops = ops; | 456 | if (!microcode_ops) { |
457 | printk(KERN_ERR "microcode: no support for this CPU vendor\n"); | ||
458 | return -ENODEV; | ||
459 | } | ||
457 | 460 | ||
458 | error = microcode_dev_init(); | 461 | error = microcode_dev_init(); |
459 | if (error) | 462 | if (error) |
@@ -483,9 +486,8 @@ int microcode_init(void *opaque, struct module *module) | |||
483 | 486 | ||
484 | return 0; | 487 | return 0; |
485 | } | 488 | } |
486 | EXPORT_SYMBOL_GPL(microcode_init); | ||
487 | 489 | ||
488 | void __exit microcode_exit(void) | 490 | static void __exit microcode_exit(void) |
489 | { | 491 | { |
490 | microcode_dev_exit(); | 492 | microcode_dev_exit(); |
491 | 493 | ||
@@ -502,4 +504,6 @@ void __exit microcode_exit(void) | |||
502 | printk(KERN_INFO | 504 | printk(KERN_INFO |
503 | "Microcode Update Driver: v" MICROCODE_VERSION " removed.\n"); | 505 | "Microcode Update Driver: v" MICROCODE_VERSION " removed.\n"); |
504 | } | 506 | } |
505 | EXPORT_SYMBOL_GPL(microcode_exit); | 507 | |
508 | module_init(microcode_init); | ||
509 | module_exit(microcode_exit); | ||
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index 48ed3cef58c1..622dc4a21784 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c | |||
@@ -97,6 +97,38 @@ 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>"); |
98 | MODULE_LICENSE("GPL"); | 98 | MODULE_LICENSE("GPL"); |
99 | 99 | ||
100 | struct microcode_header_intel { | ||
101 | unsigned int hdrver; | ||
102 | unsigned int rev; | ||
103 | unsigned int date; | ||
104 | unsigned int sig; | ||
105 | unsigned int cksum; | ||
106 | unsigned int ldrver; | ||
107 | unsigned int pf; | ||
108 | unsigned int datasize; | ||
109 | unsigned int totalsize; | ||
110 | unsigned int reserved[3]; | ||
111 | }; | ||
112 | |||
113 | struct microcode_intel { | ||
114 | struct microcode_header_intel hdr; | ||
115 | unsigned int bits[0]; | ||
116 | }; | ||
117 | |||
118 | /* microcode format is extended from prescott processors */ | ||
119 | struct extended_signature { | ||
120 | unsigned int sig; | ||
121 | unsigned int pf; | ||
122 | unsigned int cksum; | ||
123 | }; | ||
124 | |||
125 | struct extended_sigtable { | ||
126 | unsigned int count; | ||
127 | unsigned int cksum; | ||
128 | unsigned int reserved[3]; | ||
129 | struct extended_signature sigs[0]; | ||
130 | }; | ||
131 | |||
100 | #define DEFAULT_UCODE_DATASIZE (2000) | 132 | #define DEFAULT_UCODE_DATASIZE (2000) |
101 | #define MC_HEADER_SIZE (sizeof(struct microcode_header_intel)) | 133 | #define MC_HEADER_SIZE (sizeof(struct microcode_header_intel)) |
102 | #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) | 134 | #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) |
@@ -284,11 +316,12 @@ static void apply_microcode(int cpu) | |||
284 | unsigned int val[2]; | 316 | unsigned int val[2]; |
285 | int cpu_num = raw_smp_processor_id(); | 317 | int cpu_num = raw_smp_processor_id(); |
286 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | 318 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
319 | struct microcode_intel *mc_intel = uci->mc; | ||
287 | 320 | ||
288 | /* We should bind the task to the CPU */ | 321 | /* We should bind the task to the CPU */ |
289 | BUG_ON(cpu_num != cpu); | 322 | BUG_ON(cpu_num != cpu); |
290 | 323 | ||
291 | if (uci->mc.mc_intel == NULL) | 324 | if (mc_intel == NULL) |
292 | return; | 325 | return; |
293 | 326 | ||
294 | /* serialize access to the physical write to MSR 0x79 */ | 327 | /* serialize access to the physical write to MSR 0x79 */ |
@@ -296,8 +329,8 @@ static void apply_microcode(int cpu) | |||
296 | 329 | ||
297 | /* write microcode via MSR 0x79 */ | 330 | /* write microcode via MSR 0x79 */ |
298 | wrmsr(MSR_IA32_UCODE_WRITE, | 331 | wrmsr(MSR_IA32_UCODE_WRITE, |
299 | (unsigned long) uci->mc.mc_intel->bits, | 332 | (unsigned long) mc_intel->bits, |
300 | (unsigned long) uci->mc.mc_intel->bits >> 16 >> 16); | 333 | (unsigned long) mc_intel->bits >> 16 >> 16); |
301 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); | 334 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); |
302 | 335 | ||
303 | /* see notes above for revision 1.07. Apparent chip bug */ | 336 | /* see notes above for revision 1.07. Apparent chip bug */ |
@@ -307,7 +340,7 @@ static void apply_microcode(int cpu) | |||
307 | rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); | 340 | rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); |
308 | 341 | ||
309 | spin_unlock_irqrestore(µcode_update_lock, flags); | 342 | spin_unlock_irqrestore(µcode_update_lock, flags); |
310 | if (val[1] != uci->mc.mc_intel->hdr.rev) { | 343 | if (val[1] != mc_intel->hdr.rev) { |
311 | printk(KERN_ERR "microcode: CPU%d update from revision " | 344 | printk(KERN_ERR "microcode: CPU%d update from revision " |
312 | "0x%x to 0x%x failed\n", cpu_num, uci->cpu_sig.rev, val[1]); | 345 | "0x%x to 0x%x failed\n", cpu_num, uci->cpu_sig.rev, val[1]); |
313 | return; | 346 | return; |
@@ -315,9 +348,9 @@ static void apply_microcode(int cpu) | |||
315 | printk(KERN_INFO "microcode: CPU%d updated from revision " | 348 | printk(KERN_INFO "microcode: CPU%d updated from revision " |
316 | "0x%x to 0x%x, date = %04x-%02x-%02x \n", | 349 | "0x%x to 0x%x, date = %04x-%02x-%02x \n", |
317 | cpu_num, uci->cpu_sig.rev, val[1], | 350 | cpu_num, uci->cpu_sig.rev, val[1], |
318 | uci->mc.mc_intel->hdr.date & 0xffff, | 351 | mc_intel->hdr.date & 0xffff, |
319 | uci->mc.mc_intel->hdr.date >> 24, | 352 | mc_intel->hdr.date >> 24, |
320 | (uci->mc.mc_intel->hdr.date >> 16) & 0xff); | 353 | (mc_intel->hdr.date >> 16) & 0xff); |
321 | uci->cpu_sig.rev = val[1]; | 354 | uci->cpu_sig.rev = val[1]; |
322 | } | 355 | } |
323 | 356 | ||
@@ -367,12 +400,12 @@ static int generic_load_microcode(int cpu, void *data, size_t size, | |||
367 | 400 | ||
368 | if (new_mc) { | 401 | if (new_mc) { |
369 | if (!leftover) { | 402 | if (!leftover) { |
370 | if (uci->mc.mc_intel) | 403 | if (uci->mc) |
371 | vfree(uci->mc.mc_intel); | 404 | vfree(uci->mc); |
372 | uci->mc.mc_intel = (struct microcode_intel *)new_mc; | 405 | uci->mc = (struct microcode_intel *)new_mc; |
373 | pr_debug("microcode: CPU%d found a matching microcode update with" | 406 | pr_debug("microcode: CPU%d found a matching microcode update with" |
374 | " version 0x%x (current=0x%x)\n", | 407 | " version 0x%x (current=0x%x)\n", |
375 | cpu, uci->mc.mc_intel->hdr.rev, uci->cpu_sig.rev); | 408 | cpu, new_rev, uci->cpu_sig.rev); |
376 | } else | 409 | } else |
377 | vfree(new_mc); | 410 | vfree(new_mc); |
378 | } | 411 | } |
@@ -428,11 +461,11 @@ static void microcode_fini_cpu(int cpu) | |||
428 | { | 461 | { |
429 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | 462 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
430 | 463 | ||
431 | vfree(uci->mc.mc_intel); | 464 | vfree(uci->mc); |
432 | uci->mc.mc_intel = NULL; | 465 | uci->mc = NULL; |
433 | } | 466 | } |
434 | 467 | ||
435 | static struct microcode_ops microcode_intel_ops = { | 468 | struct microcode_ops microcode_intel_ops = { |
436 | .request_microcode_user = request_microcode_user, | 469 | .request_microcode_user = request_microcode_user, |
437 | .request_microcode_fw = request_microcode_fw, | 470 | .request_microcode_fw = request_microcode_fw, |
438 | .collect_cpu_info = collect_cpu_info, | 471 | .collect_cpu_info = collect_cpu_info, |
@@ -440,22 +473,8 @@ static struct microcode_ops microcode_intel_ops = { | |||
440 | .microcode_fini_cpu = microcode_fini_cpu, | 473 | .microcode_fini_cpu = microcode_fini_cpu, |
441 | }; | 474 | }; |
442 | 475 | ||
443 | static int __init microcode_intel_module_init(void) | 476 | struct microcode_ops * __init init_intel_microcode(void) |
444 | { | ||
445 | struct cpuinfo_x86 *c = &cpu_data(0); | ||
446 | |||
447 | if (c->x86_vendor != X86_VENDOR_INTEL) { | ||
448 | printk(KERN_ERR "microcode: CPU platform is not Intel-capable\n"); | ||
449 | return -ENODEV; | ||
450 | } | ||
451 | |||
452 | return microcode_init(µcode_intel_ops, THIS_MODULE); | ||
453 | } | ||
454 | |||
455 | static void __exit microcode_intel_module_exit(void) | ||
456 | { | 477 | { |
457 | microcode_exit(); | 478 | return µcode_intel_ops; |
458 | } | 479 | } |
459 | 480 | ||
460 | module_init(microcode_intel_module_init) | ||
461 | module_exit(microcode_intel_module_exit) | ||
diff --git a/include/asm-x86/microcode.h b/include/asm-x86/microcode.h index e2887facdb4a..62c793bb70ca 100644 --- a/include/asm-x86/microcode.h +++ b/include/asm-x86/microcode.h | |||
@@ -1,10 +1,12 @@ | |||
1 | #ifndef ASM_X86__MICROCODE_H | 1 | #ifndef ASM_X86__MICROCODE_H |
2 | #define ASM_X86__MICROCODE_H | 2 | #define ASM_X86__MICROCODE_H |
3 | 3 | ||
4 | extern int microcode_init(void *opaque, struct module *module); | 4 | struct cpu_signature { |
5 | extern void microcode_exit(void); | 5 | unsigned int sig; |
6 | unsigned int pf; | ||
7 | unsigned int rev; | ||
8 | }; | ||
6 | 9 | ||
7 | struct cpu_signature; | ||
8 | struct device; | 10 | struct device; |
9 | 11 | ||
10 | struct microcode_ops { | 12 | struct microcode_ops { |
@@ -17,82 +19,29 @@ struct microcode_ops { | |||
17 | void (*microcode_fini_cpu) (int cpu); | 19 | void (*microcode_fini_cpu) (int cpu); |
18 | }; | 20 | }; |
19 | 21 | ||
20 | struct microcode_header_intel { | ||
21 | unsigned int hdrver; | ||
22 | unsigned int rev; | ||
23 | unsigned int date; | ||
24 | unsigned int sig; | ||
25 | unsigned int cksum; | ||
26 | unsigned int ldrver; | ||
27 | unsigned int pf; | ||
28 | unsigned int datasize; | ||
29 | unsigned int totalsize; | ||
30 | unsigned int reserved[3]; | ||
31 | }; | ||
32 | |||
33 | struct microcode_intel { | ||
34 | struct microcode_header_intel hdr; | ||
35 | unsigned int bits[0]; | ||
36 | }; | ||
37 | |||
38 | /* microcode format is extended from prescott processors */ | ||
39 | struct extended_signature { | ||
40 | unsigned int sig; | ||
41 | unsigned int pf; | ||
42 | unsigned int cksum; | ||
43 | }; | ||
44 | |||
45 | struct extended_sigtable { | ||
46 | unsigned int count; | ||
47 | unsigned int cksum; | ||
48 | unsigned int reserved[3]; | ||
49 | struct extended_signature sigs[0]; | ||
50 | }; | ||
51 | |||
52 | struct equiv_cpu_entry { | ||
53 | unsigned int installed_cpu; | ||
54 | unsigned int fixed_errata_mask; | ||
55 | unsigned int fixed_errata_compare; | ||
56 | unsigned int equiv_cpu; | ||
57 | }; | ||
58 | |||
59 | struct microcode_header_amd { | ||
60 | unsigned int data_code; | ||
61 | unsigned int patch_id; | ||
62 | unsigned char mc_patch_data_id[2]; | ||
63 | unsigned char mc_patch_data_len; | ||
64 | unsigned char init_flag; | ||
65 | unsigned int mc_patch_data_checksum; | ||
66 | unsigned int nb_dev_id; | ||
67 | unsigned int sb_dev_id; | ||
68 | unsigned char processor_rev_id[2]; | ||
69 | unsigned char nb_rev_id; | ||
70 | unsigned char sb_rev_id; | ||
71 | unsigned char bios_api_rev; | ||
72 | unsigned char reserved1[3]; | ||
73 | unsigned int match_reg[8]; | ||
74 | }; | ||
75 | |||
76 | struct microcode_amd { | ||
77 | struct microcode_header_amd hdr; | ||
78 | unsigned int mpb[0]; | ||
79 | }; | ||
80 | |||
81 | struct cpu_signature { | ||
82 | unsigned int sig; | ||
83 | unsigned int pf; | ||
84 | unsigned int rev; | ||
85 | }; | ||
86 | |||
87 | struct ucode_cpu_info { | 22 | struct ucode_cpu_info { |
88 | struct cpu_signature cpu_sig; | 23 | struct cpu_signature cpu_sig; |
89 | int valid; | 24 | int valid; |
90 | union { | 25 | void *mc; |
91 | struct microcode_intel *mc_intel; | ||
92 | struct microcode_amd *mc_amd; | ||
93 | void *valid_mc; | ||
94 | } mc; | ||
95 | }; | 26 | }; |
96 | extern struct ucode_cpu_info ucode_cpu_info[]; | 27 | extern struct ucode_cpu_info ucode_cpu_info[]; |
97 | 28 | ||
29 | #ifdef CONFIG_MICROCODE_INTEL | ||
30 | extern struct microcode_ops * __init init_intel_microcode(void); | ||
31 | #else | ||
32 | static inline struct microcode_ops * __init init_intel_microcode(void) | ||
33 | { | ||
34 | return NULL; | ||
35 | } | ||
36 | #endif /* CONFIG_MICROCODE_INTEL */ | ||
37 | |||
38 | #ifdef CONFIG_MICROCODE_AMD | ||
39 | extern struct microcode_ops * __init init_amd_microcode(void); | ||
40 | #else | ||
41 | static inline struct microcode_ops * __init init_amd_microcode(void) | ||
42 | { | ||
43 | return NULL; | ||
44 | } | ||
45 | #endif | ||
46 | |||
98 | #endif /* ASM_X86__MICROCODE_H */ | 47 | #endif /* ASM_X86__MICROCODE_H */ |