aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel
diff options
context:
space:
mode:
authorPeter Oruba <peter.oruba@amd.com>2008-07-28 12:44:21 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-28 13:57:57 -0400
commit8d86f390d9bb5b39f0a315838d1616de6363e1b9 (patch)
treef3857d76d029b87571ac5cb4e3c1bd9965c859f8 /arch/x86/kernel
parent26bf7a48c33906cc3415a4492aa9ead7a75f1353 (diff)
x86: major refactoring
Refactored code by introducing a two-module solution. There is one general module in which vendor specific modules can hook into. However, that is exclusive, there is only one vendor specific module allowed at a time. A CPU vendor check makes sure only the correct module for the underlying system gets called. Functinally in terms of patch loading itself there are no changes. This refactoring provides a basis for future implementations of other vendors' patch loaders. Signed-off-by: Peter Oruba <peter.oruba@amd.com> Cc: Tigran Aivazian <tigran@aivazian.fsnet.co.uk> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r--arch/x86/kernel/Makefile4
-rw-r--r--arch/x86/kernel/microcode.c80
-rw-r--r--arch/x86/kernel/microcode_intel.c50
3 files changed, 89 insertions, 45 deletions
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index abb32aed7f4b..f2f9f6da8c18 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -51,8 +51,8 @@ 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) += ucode.o 54obj-$(CONFIG_MICROCODE) += microcode.o
55ucode-objs := microcode.o microcode_intel.o 55obj-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o
56obj-$(CONFIG_PCI) += early-quirks.o 56obj-$(CONFIG_PCI) += early-quirks.o
57apm-y := apm_32.o 57apm-y := apm_32.o
58obj-$(CONFIG_APM) += apm.o 58obj-$(CONFIG_APM) += apm.o
diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c
index c1047d7f7ede..1e42e79ca694 100644
--- a/arch/x86/kernel/microcode.c
+++ b/arch/x86/kernel/microcode.c
@@ -99,25 +99,22 @@ MODULE_DESCRIPTION("Microcode Update Driver");
99MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>"); 99MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
100MODULE_LICENSE("GPL"); 100MODULE_LICENSE("GPL");
101 101
102#define MICROCODE_VERSION "1.14a" 102#define MICROCODE_VERSION "2.00"
103 103
104/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ 104struct microcode_ops *microcode_ops;
105DEFINE_MUTEX(microcode_mutex);
106 105
107struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; 106/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
107static DEFINE_MUTEX(microcode_mutex);
108EXPORT_SYMBOL_GPL(microcode_mutex);
108 109
109extern long get_next_ucode(void **mc, long offset); 110static struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
110extern int microcode_sanity_check(void *mc); 111EXPORT_SYMBOL_GPL(ucode_cpu_info);
111extern int get_matching_microcode(void *mc, int cpu);
112extern void collect_cpu_info(int cpu_num);
113extern int cpu_request_microcode(int cpu);
114extern void microcode_fini_cpu(int cpu);
115extern void apply_microcode(int cpu);
116extern int apply_microcode_check_cpu(int cpu);
117 112
118#ifdef CONFIG_MICROCODE_OLD_INTERFACE 113#ifdef CONFIG_MICROCODE_OLD_INTERFACE
119void __user *user_buffer; /* user area microcode data buffer */ 114static void __user *user_buffer; /* user area microcode data buffer */
120unsigned int user_buffer_size; /* it's size */ 115EXPORT_SYMBOL_GPL(user_buffer);
116static unsigned int user_buffer_size; /* it's size */
117EXPORT_SYMBOL_GPL(user_buffer_size);
121 118
122static int do_microcode_update (void) 119static int do_microcode_update (void)
123{ 120{
@@ -130,8 +127,8 @@ static int do_microcode_update (void)
130 127
131 old = current->cpus_allowed; 128 old = current->cpus_allowed;
132 129
133 while ((cursor = get_next_ucode(&new_mc, cursor)) > 0) { 130 while ((cursor = microcode_ops->get_next_ucode(&new_mc, cursor)) > 0) {
134 error = microcode_sanity_check(new_mc); 131 error = microcode_ops->microcode_sanity_check(new_mc);
135 if (error) 132 if (error)
136 goto out; 133 goto out;
137 /* 134 /*
@@ -145,11 +142,12 @@ static int do_microcode_update (void)
145 continue; 142 continue;
146 cpumask_of_cpu_ptr_next(newmask, cpu); 143 cpumask_of_cpu_ptr_next(newmask, cpu);
147 set_cpus_allowed_ptr(current, newmask); 144 set_cpus_allowed_ptr(current, newmask);
148 error = get_maching_microcode(new_mc, cpu); 145 error = microcode_ops->get_matching_microcode(new_mc,
146 cpu);
149 if (error < 0) 147 if (error < 0)
150 goto out; 148 goto out;
151 if (error == 1) 149 if (error == 1)
152 apply_microcode(cpu); 150 microcode_ops->apply_microcode(cpu);
153 } 151 }
154 vfree(new_mc); 152 vfree(new_mc);
155 } 153 }
@@ -232,7 +230,8 @@ MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
232#endif 230#endif
233 231
234/* fake device for request_firmware */ 232/* fake device for request_firmware */
235struct platform_device *microcode_pdev; 233static struct platform_device *microcode_pdev;
234EXPORT_SYMBOL_GPL(microcode_pdev);
236 235
237static void microcode_init_cpu(int cpu, int resume) 236static void microcode_init_cpu(int cpu, int resume)
238{ 237{
@@ -244,9 +243,9 @@ static void microcode_init_cpu(int cpu, int resume)
244 243
245 set_cpus_allowed_ptr(current, newmask); 244 set_cpus_allowed_ptr(current, newmask);
246 mutex_lock(&microcode_mutex); 245 mutex_lock(&microcode_mutex);
247 collect_cpu_info(cpu); 246 microcode_ops->collect_cpu_info(cpu);
248 if (uci->valid && system_state == SYSTEM_RUNNING && !resume) 247 if (uci->valid && system_state == SYSTEM_RUNNING && !resume)
249 cpu_request_microcode(cpu); 248 microcode_ops->cpu_request_microcode(cpu);
250 mutex_unlock(&microcode_mutex); 249 mutex_unlock(&microcode_mutex);
251 set_cpus_allowed_ptr(current, &old); 250 set_cpus_allowed_ptr(current, &old);
252} 251}
@@ -274,7 +273,7 @@ static ssize_t reload_store(struct sys_device *dev,
274 273
275 mutex_lock(&microcode_mutex); 274 mutex_lock(&microcode_mutex);
276 if (uci->valid) 275 if (uci->valid)
277 err = cpu_request_microcode(cpu); 276 err = microcode_ops->cpu_request_microcode(cpu);
278 mutex_unlock(&microcode_mutex); 277 mutex_unlock(&microcode_mutex);
279 put_online_cpus(); 278 put_online_cpus();
280 set_cpus_allowed_ptr(current, &old); 279 set_cpus_allowed_ptr(current, &old);
@@ -349,7 +348,7 @@ static int mc_sysdev_remove(struct sys_device *sys_dev)
349 return 0; 348 return 0;
350 349
351 pr_debug("microcode: CPU%d removed\n", cpu); 350 pr_debug("microcode: CPU%d removed\n", cpu);
352 microcode_fini_cpu(cpu); 351 microcode_ops->microcode_fini_cpu(cpu);
353 sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); 352 sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
354 return 0; 353 return 0;
355} 354}
@@ -362,7 +361,7 @@ static int mc_sysdev_resume(struct sys_device *dev)
362 return 0; 361 return 0;
363 pr_debug("microcode: CPU%d resumed\n", cpu); 362 pr_debug("microcode: CPU%d resumed\n", cpu);
364 /* only CPU 0 will apply ucode here */ 363 /* only CPU 0 will apply ucode here */
365 apply_microcode(0); 364 microcode_ops->apply_microcode(0);
366 return 0; 365 return 0;
367} 366}
368 367
@@ -382,7 +381,7 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
382 switch (action) { 381 switch (action) {
383 case CPU_UP_CANCELED_FROZEN: 382 case CPU_UP_CANCELED_FROZEN:
384 /* The CPU refused to come up during a system resume */ 383 /* The CPU refused to come up during a system resume */
385 microcode_fini_cpu(cpu); 384 microcode_ops->microcode_fini_cpu(cpu);
386 break; 385 break;
387 case CPU_ONLINE: 386 case CPU_ONLINE:
388 case CPU_DOWN_FAILED: 387 case CPU_DOWN_FAILED:
@@ -390,9 +389,9 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
390 break; 389 break;
391 case CPU_ONLINE_FROZEN: 390 case CPU_ONLINE_FROZEN:
392 /* System-wide resume is in progress, try to apply microcode */ 391 /* System-wide resume is in progress, try to apply microcode */
393 if (apply_microcode_check_cpu(cpu)) { 392 if (microcode_ops->apply_microcode_check_cpu(cpu)) {
394 /* The application of microcode failed */ 393 /* The application of microcode failed */
395 microcode_fini_cpu(cpu); 394 microcode_ops->microcode_fini_cpu(cpu);
396 __mc_sysdev_add(sys_dev, 1); 395 __mc_sysdev_add(sys_dev, 1);
397 break; 396 break;
398 } 397 }
@@ -416,12 +415,17 @@ static struct notifier_block __refdata mc_cpu_notifier = {
416 .notifier_call = mc_cpu_callback, 415 .notifier_call = mc_cpu_callback,
417}; 416};
418 417
419static int __init microcode_init (void) 418static int microcode_init(void *opaque, struct module *module)
420{ 419{
420 struct microcode_ops *ops = (struct microcode_ops *)opaque;
421 int error; 421 int error;
422 422
423 printk(KERN_INFO 423 if (microcode_ops) {
424 "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@aivazian.fsnet.co.uk>\n"); 424 printk(KERN_ERR "microcode: already loaded the other module\n");
425 return -EEXIST;
426 }
427
428 microcode_ops = ops;
425 429
426 error = microcode_dev_init(); 430 error = microcode_dev_init();
427 if (error) 431 if (error)
@@ -443,8 +447,15 @@ static int __init microcode_init (void)
443 } 447 }
444 448
445 register_hotcpu_notifier(&mc_cpu_notifier); 449 register_hotcpu_notifier(&mc_cpu_notifier);
450
451 printk(KERN_INFO
452 "Microcode Update Driver: v" MICROCODE_VERSION
453 " <tigran@aivazian.fsnet.co.uk>"
454 " <peter.oruba@amd.com>\n");
455
446 return 0; 456 return 0;
447} 457}
458EXPORT_SYMBOL_GPL(microcode_init);
448 459
449static void __exit microcode_exit (void) 460static void __exit microcode_exit (void)
450{ 461{
@@ -457,7 +468,10 @@ static void __exit microcode_exit (void)
457 put_online_cpus(); 468 put_online_cpus();
458 469
459 platform_device_unregister(microcode_pdev); 470 platform_device_unregister(microcode_pdev);
460}
461 471
462module_init(microcode_init) 472 microcode_ops = NULL;
463module_exit(microcode_exit) 473
474 printk(KERN_INFO
475 "Microcode Update Driver: v" MICROCODE_VERSION " removed.\n");
476}
477EXPORT_SYMBOL_GPL(microcode_exit);
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c
index ca9861bf067e..831db5363dba 100644
--- a/arch/x86/kernel/microcode_intel.c
+++ b/arch/x86/kernel/microcode_intel.c
@@ -127,7 +127,7 @@ extern struct mutex microcode_mutex;
127 127
128extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; 128extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
129 129
130void collect_cpu_info(int cpu_num) 130static void collect_cpu_info(int cpu_num)
131{ 131{
132 struct cpuinfo_x86 *c = &cpu_data(cpu_num); 132 struct cpuinfo_x86 *c = &cpu_data(cpu_num);
133 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 133 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
@@ -175,7 +175,7 @@ static inline int microcode_update_match(int cpu_num,
175 return 1; 175 return 1;
176} 176}
177 177
178int microcode_sanity_check(void *mc) 178static int microcode_sanity_check(void *mc)
179{ 179{
180 struct microcode_header_intel *mc_header = mc; 180 struct microcode_header_intel *mc_header = mc;
181 struct extended_sigtable *ext_header = NULL; 181 struct extended_sigtable *ext_header = NULL;
@@ -259,7 +259,7 @@ int microcode_sanity_check(void *mc)
259 * return 1 - found update 259 * return 1 - found update
260 * return < 0 - error 260 * return < 0 - error
261 */ 261 */
262int get_matching_microcode(void *mc, int cpu) 262static int get_matching_microcode(void *mc, int cpu)
263{ 263{
264 struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 264 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
265 struct microcode_header_intel *mc_header = mc; 265 struct microcode_header_intel *mc_header = mc;
@@ -288,7 +288,8 @@ int get_matching_microcode(void *mc, int cpu)
288 return 0; 288 return 0;
289find: 289find:
290 pr_debug("microcode: CPU%d found a matching microcode update with" 290 pr_debug("microcode: CPU%d found a matching microcode update with"
291 " version 0x%x (current=0x%x)\n", cpu, mc_header->rev, uci->rev); 291 " version 0x%x (current=0x%x)\n",
292 cpu, mc_header->rev, uci->rev);
292 new_mc = vmalloc(total_size); 293 new_mc = vmalloc(total_size);
293 if (!new_mc) { 294 if (!new_mc) {
294 printk(KERN_ERR "microcode: error! Can not allocate memory\n"); 295 printk(KERN_ERR "microcode: error! Can not allocate memory\n");
@@ -303,7 +304,7 @@ find:
303 return 1; 304 return 1;
304} 305}
305 306
306void apply_microcode(int cpu) 307static void apply_microcode(int cpu)
307{ 308{
308 unsigned long flags; 309 unsigned long flags;
309 unsigned int val[2]; 310 unsigned int val[2];
@@ -347,7 +348,7 @@ void apply_microcode(int cpu)
347extern void __user *user_buffer; /* user area microcode data buffer */ 348extern void __user *user_buffer; /* user area microcode data buffer */
348extern unsigned int user_buffer_size; /* it's size */ 349extern unsigned int user_buffer_size; /* it's size */
349 350
350long get_next_ucode(void **mc, long offset) 351static long get_next_ucode(void **mc, long offset)
351{ 352{
352 struct microcode_header_intel mc_header; 353 struct microcode_header_intel mc_header;
353 unsigned long total_size; 354 unsigned long total_size;
@@ -406,7 +407,7 @@ static long get_next_ucode_from_buffer(void **mc, const u8 *buf,
406/* fake device for request_firmware */ 407/* fake device for request_firmware */
407extern struct platform_device *microcode_pdev; 408extern struct platform_device *microcode_pdev;
408 409
409int cpu_request_microcode(int cpu) 410static int cpu_request_microcode(int cpu)
410{ 411{
411 char name[30]; 412 char name[30];
412 struct cpuinfo_x86 *c = &cpu_data(cpu); 413 struct cpuinfo_x86 *c = &cpu_data(cpu);
@@ -455,7 +456,7 @@ int cpu_request_microcode(int cpu)
455 return error; 456 return error;
456} 457}
457 458
458int apply_microcode_check_cpu(int cpu) 459static int apply_microcode_check_cpu(int cpu)
459{ 460{
460 struct cpuinfo_x86 *c = &cpu_data(cpu); 461 struct cpuinfo_x86 *c = &cpu_data(cpu);
461 struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 462 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
@@ -504,13 +505,42 @@ int apply_microcode_check_cpu(int cpu)
504 return err; 505 return err;
505} 506}
506 507
507void microcode_fini_cpu(int cpu) 508static void microcode_fini_cpu(int cpu)
508{ 509{
509 struct ucode_cpu_info *uci = ucode_cpu_info + cpu; 510 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
510 511
511 mutex_lock(&microcode_mutex); 512 mutex_lock(&microcode_mutex);
512 uci->valid = 0; 513 uci->valid = 0;
513 kfree(uci->mc.mc_intel); 514 vfree(uci->mc.mc_intel);
514 uci->mc.mc_intel = NULL; 515 uci->mc.mc_intel = NULL;
515 mutex_unlock(&microcode_mutex); 516 mutex_unlock(&microcode_mutex);
516} 517}
518
519static struct microcode_ops microcode_intel_ops = {
520 .get_next_ucode = get_next_ucode,
521 .get_matching_microcode = get_matching_microcode,
522 .microcode_sanity_check = microcode_sanity_check,
523 .apply_microcode_check_cpu = apply_microcode_check_cpu,
524 .cpu_request_microcode = cpu_request_microcode,
525 .collect_cpu_info = collect_cpu_info,
526 .apply_microcode = apply_microcode,
527 .microcode_fini_cpu = microcode_fini_cpu,
528};
529
530static int __init microcode_intel_module_init(void)
531{
532 struct cpuinfo_x86 *c = &cpu_data(get_cpu());
533
534 if (c->x86_vendor == X86_VENDOR_INTEL)
535 return microcode_init(&microcode_intel_ops, THIS_MODULE);
536 else
537 return -ENODEV;
538}
539
540static void __exit microcode_intel_module_exit(void)
541{
542 microcode_exit();
543}
544
545module_init(microcode_intel_module_init)
546module_exit(microcode_intel_module_exit)