Commit 8d86f390d9bb5b39f0a315838d1616de6363e1b9

Authored by Peter Oruba
Committed by Ingo Molnar
1 parent 26bf7a48c3

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>

Showing 5 changed files with 112 additions and 50 deletions Side-by-side Diff

... ... @@ -782,7 +782,7 @@
782 782 Say N otherwise.
783 783  
784 784 config MICROCODE
785   - tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support"
  785 + tristate "/dev/cpu/microcode - microcode support"
786 786 select FW_LOADER
787 787 ---help---
788 788 If you say Y here, you will be able to update the microcode on
789 789  
... ... @@ -791,14 +791,29 @@
791 791 actual microcode binary data itself which is not shipped with the
792 792 Linux kernel.
793 793  
794   - For latest news and information on obtaining all the required
795   - ingredients for this driver, check:
796   - <http://www.urbanmyth.org/microcode/>.
  794 + This option selects the general module only, you need to select
  795 + at least one vendor specific module as well.
797 796  
798 797 To compile this driver as a module, choose M here: the
799 798 module will be called microcode.
800 799  
801   -config MICROCODE_OLD_INTERFACE
  800 +config MICROCODE_INTEL
  801 + tristate "Intel microcode patch loading support"
  802 + depends on MICROCODE
  803 + default MICROCODE
  804 + select FW_LOADER
  805 + --help---
  806 + This options enables microcode patch loading support for Intel
  807 + processors.
  808 +
  809 + For latest news and information on obtaining all the required
  810 + Intel ingredients for this driver, check:
  811 + <http://www.urbanmyth.org/microcode/>.
  812 +
  813 + This driver is only available as a module: the module
  814 + will be called microcode_intel.
  815 +
  816 + config MICROCODE_OLD_INTERFACE
802 817 def_bool y
803 818 depends on MICROCODE
804 819  
arch/x86/kernel/Makefile
... ... @@ -51,8 +51,8 @@
51 51 obj-$(CONFIG_MCA) += mca_32.o
52 52 obj-$(CONFIG_X86_MSR) += msr.o
53 53 obj-$(CONFIG_X86_CPUID) += cpuid.o
54   -obj-$(CONFIG_MICROCODE) += ucode.o
55   -ucode-objs := microcode.o microcode_intel.o
  54 +obj-$(CONFIG_MICROCODE) += microcode.o
  55 +obj-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o
56 56 obj-$(CONFIG_PCI) += early-quirks.o
57 57 apm-y := apm_32.o
58 58 obj-$(CONFIG_APM) += apm.o
arch/x86/kernel/microcode.c
... ... @@ -99,25 +99,22 @@
99 99 MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
100 100 MODULE_LICENSE("GPL");
101 101  
102   -#define MICROCODE_VERSION "1.14a"
  102 +#define MICROCODE_VERSION "2.00"
103 103  
  104 +struct microcode_ops *microcode_ops;
  105 +
104 106 /* no concurrent ->write()s are allowed on /dev/cpu/microcode */
105   -DEFINE_MUTEX(microcode_mutex);
  107 +static DEFINE_MUTEX(microcode_mutex);
  108 +EXPORT_SYMBOL_GPL(microcode_mutex);
106 109  
107   -struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
  110 +static struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
  111 +EXPORT_SYMBOL_GPL(ucode_cpu_info);
108 112  
109   -extern long get_next_ucode(void **mc, long offset);
110   -extern int microcode_sanity_check(void *mc);
111   -extern int get_matching_microcode(void *mc, int cpu);
112   -extern void collect_cpu_info(int cpu_num);
113   -extern int cpu_request_microcode(int cpu);
114   -extern void microcode_fini_cpu(int cpu);
115   -extern void apply_microcode(int cpu);
116   -extern int apply_microcode_check_cpu(int cpu);
117   -
118 113 #ifdef CONFIG_MICROCODE_OLD_INTERFACE
119   -void __user *user_buffer; /* user area microcode data buffer */
120   -unsigned int user_buffer_size; /* it's size */
  114 +static void __user *user_buffer; /* user area microcode data buffer */
  115 +EXPORT_SYMBOL_GPL(user_buffer);
  116 +static unsigned int user_buffer_size; /* it's size */
  117 +EXPORT_SYMBOL_GPL(user_buffer_size);
121 118  
122 119 static int do_microcode_update (void)
123 120 {
... ... @@ -130,8 +127,8 @@
130 127  
131 128 old = current->cpus_allowed;
132 129  
133   - while ((cursor = get_next_ucode(&new_mc, cursor)) > 0) {
134   - error = microcode_sanity_check(new_mc);
  130 + while ((cursor = microcode_ops->get_next_ucode(&new_mc, cursor)) > 0) {
  131 + error = microcode_ops->microcode_sanity_check(new_mc);
135 132 if (error)
136 133 goto out;
137 134 /*
138 135  
... ... @@ -145,11 +142,12 @@
145 142 continue;
146 143 cpumask_of_cpu_ptr_next(newmask, cpu);
147 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 147 if (error < 0)
150 148 goto out;
151 149 if (error == 1)
152   - apply_microcode(cpu);
  150 + microcode_ops->apply_microcode(cpu);
153 151 }
154 152 vfree(new_mc);
155 153 }
... ... @@ -232,7 +230,8 @@
232 230 #endif
233 231  
234 232 /* fake device for request_firmware */
235   -struct platform_device *microcode_pdev;
  233 +static struct platform_device *microcode_pdev;
  234 +EXPORT_SYMBOL_GPL(microcode_pdev);
236 235  
237 236 static void microcode_init_cpu(int cpu, int resume)
238 237 {
239 238  
... ... @@ -244,9 +243,9 @@
244 243  
245 244 set_cpus_allowed_ptr(current, newmask);
246 245 mutex_lock(&microcode_mutex);
247   - collect_cpu_info(cpu);
  246 + microcode_ops->collect_cpu_info(cpu);
248 247 if (uci->valid && system_state == SYSTEM_RUNNING && !resume)
249   - cpu_request_microcode(cpu);
  248 + microcode_ops->cpu_request_microcode(cpu);
250 249 mutex_unlock(&microcode_mutex);
251 250 set_cpus_allowed_ptr(current, &old);
252 251 }
... ... @@ -274,7 +273,7 @@
274 273  
275 274 mutex_lock(&microcode_mutex);
276 275 if (uci->valid)
277   - err = cpu_request_microcode(cpu);
  276 + err = microcode_ops->cpu_request_microcode(cpu);
278 277 mutex_unlock(&microcode_mutex);
279 278 put_online_cpus();
280 279 set_cpus_allowed_ptr(current, &old);
... ... @@ -349,7 +348,7 @@
349 348 return 0;
350 349  
351 350 pr_debug("microcode: CPU%d removed\n", cpu);
352   - microcode_fini_cpu(cpu);
  351 + microcode_ops->microcode_fini_cpu(cpu);
353 352 sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
354 353 return 0;
355 354 }
... ... @@ -362,7 +361,7 @@
362 361 return 0;
363 362 pr_debug("microcode: CPU%d resumed\n", cpu);
364 363 /* only CPU 0 will apply ucode here */
365   - apply_microcode(0);
  364 + microcode_ops->apply_microcode(0);
366 365 return 0;
367 366 }
368 367  
... ... @@ -382,7 +381,7 @@
382 381 switch (action) {
383 382 case CPU_UP_CANCELED_FROZEN:
384 383 /* The CPU refused to come up during a system resume */
385   - microcode_fini_cpu(cpu);
  384 + microcode_ops->microcode_fini_cpu(cpu);
386 385 break;
387 386 case CPU_ONLINE:
388 387 case CPU_DOWN_FAILED:
389 388  
... ... @@ -390,9 +389,9 @@
390 389 break;
391 390 case CPU_ONLINE_FROZEN:
392 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 393 /* The application of microcode failed */
395   - microcode_fini_cpu(cpu);
  394 + microcode_ops->microcode_fini_cpu(cpu);
396 395 __mc_sysdev_add(sys_dev, 1);
397 396 break;
398 397 }
399 398  
400 399  
401 400  
... ... @@ -416,13 +415,18 @@
416 415 .notifier_call = mc_cpu_callback,
417 416 };
418 417  
419   -static int __init microcode_init (void)
  418 +static int microcode_init(void *opaque, struct module *module)
420 419 {
  420 + struct microcode_ops *ops = (struct microcode_ops *)opaque;
421 421 int error;
422 422  
423   - printk(KERN_INFO
424   - "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@aivazian.fsnet.co.uk>\n");
  423 + if (microcode_ops) {
  424 + printk(KERN_ERR "microcode: already loaded the other module\n");
  425 + return -EEXIST;
  426 + }
425 427  
  428 + microcode_ops = ops;
  429 +
426 430 error = microcode_dev_init();
427 431 if (error)
428 432 return error;
429 433  
... ... @@ -443,8 +447,15 @@
443 447 }
444 448  
445 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 456 return 0;
447 457 }
  458 +EXPORT_SYMBOL_GPL(microcode_init);
448 459  
449 460 static void __exit microcode_exit (void)
450 461 {
451 462  
... ... @@ -457,8 +468,11 @@
457 468 put_online_cpus();
458 469  
459 470 platform_device_unregister(microcode_pdev);
460   -}
461 471  
462   -module_init(microcode_init)
463   -module_exit(microcode_exit)
  472 + microcode_ops = NULL;
  473 +
  474 + printk(KERN_INFO
  475 + "Microcode Update Driver: v" MICROCODE_VERSION " removed.\n");
  476 +}
  477 +EXPORT_SYMBOL_GPL(microcode_exit);
arch/x86/kernel/microcode_intel.c
... ... @@ -127,7 +127,7 @@
127 127  
128 128 extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
129 129  
130   -void collect_cpu_info(int cpu_num)
  130 +static void collect_cpu_info(int cpu_num)
131 131 {
132 132 struct cpuinfo_x86 *c = &cpu_data(cpu_num);
133 133 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
... ... @@ -175,7 +175,7 @@
175 175 return 1;
176 176 }
177 177  
178   -int microcode_sanity_check(void *mc)
  178 +static int microcode_sanity_check(void *mc)
179 179 {
180 180 struct microcode_header_intel *mc_header = mc;
181 181 struct extended_sigtable *ext_header = NULL;
... ... @@ -259,7 +259,7 @@
259 259 * return 1 - found update
260 260 * return < 0 - error
261 261 */
262   -int get_matching_microcode(void *mc, int cpu)
  262 +static int get_matching_microcode(void *mc, int cpu)
263 263 {
264 264 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
265 265 struct microcode_header_intel *mc_header = mc;
... ... @@ -288,7 +288,8 @@
288 288 return 0;
289 289 find:
290 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 293 new_mc = vmalloc(total_size);
293 294 if (!new_mc) {
294 295 printk(KERN_ERR "microcode: error! Can not allocate memory\n");
... ... @@ -303,7 +304,7 @@
303 304 return 1;
304 305 }
305 306  
306   -void apply_microcode(int cpu)
  307 +static void apply_microcode(int cpu)
307 308 {
308 309 unsigned long flags;
309 310 unsigned int val[2];
... ... @@ -347,7 +348,7 @@
347 348 extern void __user *user_buffer; /* user area microcode data buffer */
348 349 extern unsigned int user_buffer_size; /* it's size */
349 350  
350   -long get_next_ucode(void **mc, long offset)
  351 +static long get_next_ucode(void **mc, long offset)
351 352 {
352 353 struct microcode_header_intel mc_header;
353 354 unsigned long total_size;
... ... @@ -406,7 +407,7 @@
406 407 /* fake device for request_firmware */
407 408 extern struct platform_device *microcode_pdev;
408 409  
409   -int cpu_request_microcode(int cpu)
  410 +static int cpu_request_microcode(int cpu)
410 411 {
411 412 char name[30];
412 413 struct cpuinfo_x86 *c = &cpu_data(cpu);
... ... @@ -455,7 +456,7 @@
455 456 return error;
456 457 }
457 458  
458   -int apply_microcode_check_cpu(int cpu)
  459 +static int apply_microcode_check_cpu(int cpu)
459 460 {
460 461 struct cpuinfo_x86 *c = &cpu_data(cpu);
461 462 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
462 463  
463 464  
... ... @@ -504,14 +505,43 @@
504 505 return err;
505 506 }
506 507  
507   -void microcode_fini_cpu(int cpu)
  508 +static void microcode_fini_cpu(int cpu)
508 509 {
509 510 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
510 511  
511 512 mutex_lock(&microcode_mutex);
512 513 uci->valid = 0;
513   - kfree(uci->mc.mc_intel);
  514 + vfree(uci->mc.mc_intel);
514 515 uci->mc.mc_intel = NULL;
515 516 mutex_unlock(&microcode_mutex);
516 517 }
  518 +
  519 +static 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 +
  530 +static 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 +
  540 +static void __exit microcode_intel_module_exit(void)
  541 +{
  542 + microcode_exit();
  543 +}
  544 +
  545 +module_init(microcode_intel_module_init)
  546 +module_exit(microcode_intel_module_exit)
include/asm-x86/microcode.h
  1 +extern int microcode_init(void *opaque, struct module *module);
  2 +extern void microcode_exit(void);
  3 +
1 4 struct microcode_ops {
2 5 long (*get_next_ucode)(void **mc, long offset);
3 6 long (*microcode_get_next_ucode)(void **mc, long offset);