aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel
diff options
context:
space:
mode:
authorDmitry Adamushko <dmitry.adamushko@gmail.com>2008-09-23 06:08:44 -0400
committerIngo Molnar <mingo@elte.hu>2008-09-23 06:21:42 -0400
commit18dbc9160507dc7df998e00cd1dcd7889557307b (patch)
tree81262b57db5de63267762083a54a37558d8555f0 /arch/x86/kernel
parenta1c75cc5018f17ff6d80ce45a13435b1536f76db (diff)
x86: moved microcode.c to microcode_intel.c
Combine both generic and arch-specific parts of microcode into a single module (arch-specific parts are config-dependent). Also while we are at it, move arch-specific parts from microcode.h into their respective arch-specific .c files. Signed-off-by: Dmitry Adamushko <dmitry.adamushko@gmail.com> Cc: "Peter Oruba" <peter.oruba@amd.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r--arch/x86/kernel/Makefile8
-rw-r--r--arch/x86/kernel/microcode_amd.c72
-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.c79
4 files changed, 112 insertions, 73 deletions
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
51obj-$(CONFIG_MCA) += mca_32.o 51obj-$(CONFIG_MCA) += mca_32.o
52obj-$(CONFIG_X86_MSR) += msr.o 52obj-$(CONFIG_X86_MSR) += msr.o
53obj-$(CONFIG_X86_CPUID) += cpuid.o 53obj-$(CONFIG_X86_CPUID) += cpuid.o
54obj-$(CONFIG_MICROCODE) += microcode.o
55obj-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o
56obj-$(CONFIG_MICROCODE_AMD) += microcode_amd.o
57obj-$(CONFIG_PCI) += early-quirks.o 54obj-$(CONFIG_PCI) += early-quirks.o
58apm-y := apm_32.o 55apm-y := apm_32.o
59obj-$(CONFIG_APM) += apm.o 56obj-$(CONFIG_APM) += apm.o
@@ -101,6 +98,11 @@ scx200-y += scx200_32.o
101 98
102obj-$(CONFIG_OLPC) += olpc.o 99obj-$(CONFIG_OLPC) += olpc.o
103 100
101microcode-y := microcode_core.o
102microcode-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o
103microcode-$(CONFIG_MICROCODE_AMD) += microcode_amd.o
104obj-$(CONFIG_MICROCODE) += microcode.o
105
104### 106###
105# 64 bit specific files 107# 64 bit specific files
106ifeq ($(CONFIG_X86_64),y) 108ifeq ($(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
49struct 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
56struct 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
73struct 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(&microcode_update_lock, flags); 230 spin_lock_irqsave(&microcode_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(&microcode_update_lock, flags); 244 spin_unlock_irqrestore(&microcode_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
423static struct microcode_ops microcode_amd_ops = { 453static 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
431static int __init microcode_amd_module_init(void) 461struct microcode_ops * __init init_amd_microcode(void)
432{ 462{
433 struct cpuinfo_x86 *c = &cpu_data(0); 463 return &microcode_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(&microcode_amd_ops, THIS_MODULE);
442}
443
444static void __exit microcode_amd_module_exit(void)
445{
446 microcode_exit();
447} 464}
448
449module_init(microcode_amd_module_init)
450module_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
446int microcode_init(void *opaque, struct module *module) 446static 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}
486EXPORT_SYMBOL_GPL(microcode_init);
487 489
488void __exit microcode_exit(void) 490static 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}
505EXPORT_SYMBOL_GPL(microcode_exit); 507
508module_init(microcode_init);
509module_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");
97MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>"); 97MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
98MODULE_LICENSE("GPL"); 98MODULE_LICENSE("GPL");
99 99
100struct 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
113struct microcode_intel {
114 struct microcode_header_intel hdr;
115 unsigned int bits[0];
116};
117
118/* microcode format is extended from prescott processors */
119struct extended_signature {
120 unsigned int sig;
121 unsigned int pf;
122 unsigned int cksum;
123};
124
125struct 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(&microcode_update_lock, flags); 342 spin_unlock_irqrestore(&microcode_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
435static struct microcode_ops microcode_intel_ops = { 468struct 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
443static int __init microcode_intel_module_init(void) 476struct 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(&microcode_intel_ops, THIS_MODULE);
453}
454
455static void __exit microcode_intel_module_exit(void)
456{ 477{
457 microcode_exit(); 478 return &microcode_intel_ops;
458} 479}
459 480
460module_init(microcode_intel_module_init)
461module_exit(microcode_intel_module_exit)