aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/microcode.c
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/microcode.c
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/microcode.c')
-rw-r--r--arch/x86/kernel/microcode.c80
1 files changed, 47 insertions, 33 deletions
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);