diff options
author | Peter Oruba <peter.oruba@amd.com> | 2008-07-28 12:44:21 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-28 13:57:57 -0400 |
commit | 8d86f390d9bb5b39f0a315838d1616de6363e1b9 (patch) | |
tree | f3857d76d029b87571ac5cb4e3c1bd9965c859f8 /arch | |
parent | 26bf7a48c33906cc3415a4492aa9ead7a75f1353 (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')
-rw-r--r-- | arch/x86/Kconfig | 25 | ||||
-rw-r--r-- | arch/x86/kernel/Makefile | 4 | ||||
-rw-r--r-- | arch/x86/kernel/microcode.c | 80 | ||||
-rw-r--r-- | arch/x86/kernel/microcode_intel.c | 50 |
4 files changed, 109 insertions, 50 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index b6fa2877b173..6b0b885cf47a 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -782,7 +782,7 @@ config X86_REBOOTFIXUPS | |||
782 | Say N otherwise. | 782 | Say N otherwise. |
783 | 783 | ||
784 | config MICROCODE | 784 | config MICROCODE |
785 | tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support" | 785 | tristate "/dev/cpu/microcode - microcode support" |
786 | select FW_LOADER | 786 | select FW_LOADER |
787 | ---help--- | 787 | ---help--- |
788 | If you say Y here, you will be able to update the microcode on | 788 | If you say Y here, you will be able to update the microcode on |
@@ -791,14 +791,29 @@ config MICROCODE | |||
791 | actual microcode binary data itself which is not shipped with the | 791 | actual microcode binary data itself which is not shipped with the |
792 | Linux kernel. | 792 | Linux kernel. |
793 | 793 | ||
794 | For latest news and information on obtaining all the required | 794 | This option selects the general module only, you need to select |
795 | ingredients for this driver, check: | 795 | at least one vendor specific module as well. |
796 | <http://www.urbanmyth.org/microcode/>. | ||
797 | 796 | ||
798 | To compile this driver as a module, choose M here: the | 797 | To compile this driver as a module, choose M here: the |
799 | module will be called microcode. | 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 | def_bool y | 817 | def_bool y |
803 | depends on MICROCODE | 818 | depends on MICROCODE |
804 | 819 | ||
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 | |||
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) += ucode.o | 54 | obj-$(CONFIG_MICROCODE) += microcode.o |
55 | ucode-objs := microcode.o microcode_intel.o | 55 | obj-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o |
56 | obj-$(CONFIG_PCI) += early-quirks.o | 56 | obj-$(CONFIG_PCI) += early-quirks.o |
57 | apm-y := apm_32.o | 57 | apm-y := apm_32.o |
58 | obj-$(CONFIG_APM) += apm.o | 58 | obj-$(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"); | |||
99 | MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>"); | 99 | MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>"); |
100 | MODULE_LICENSE("GPL"); | 100 | MODULE_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 */ | 104 | struct microcode_ops *microcode_ops; |
105 | DEFINE_MUTEX(microcode_mutex); | ||
106 | 105 | ||
107 | struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; | 106 | /* no concurrent ->write()s are allowed on /dev/cpu/microcode */ |
107 | static DEFINE_MUTEX(microcode_mutex); | ||
108 | EXPORT_SYMBOL_GPL(microcode_mutex); | ||
108 | 109 | ||
109 | extern long get_next_ucode(void **mc, long offset); | 110 | static struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; |
110 | extern int microcode_sanity_check(void *mc); | 111 | EXPORT_SYMBOL_GPL(ucode_cpu_info); |
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 | 112 | ||
118 | #ifdef CONFIG_MICROCODE_OLD_INTERFACE | 113 | #ifdef CONFIG_MICROCODE_OLD_INTERFACE |
119 | void __user *user_buffer; /* user area microcode data buffer */ | 114 | static void __user *user_buffer; /* user area microcode data buffer */ |
120 | unsigned int user_buffer_size; /* it's size */ | 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 | static int do_microcode_update (void) | 119 | static 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 */ |
235 | struct platform_device *microcode_pdev; | 233 | static struct platform_device *microcode_pdev; |
234 | EXPORT_SYMBOL_GPL(microcode_pdev); | ||
236 | 235 | ||
237 | static void microcode_init_cpu(int cpu, int resume) | 236 | static 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(µcode_mutex); | 245 | mutex_lock(µcode_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(µcode_mutex); | 249 | mutex_unlock(µcode_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(µcode_mutex); | 274 | mutex_lock(µcode_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(µcode_mutex); | 277 | mutex_unlock(µcode_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 | ||
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 | 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 | } |
458 | EXPORT_SYMBOL_GPL(microcode_init); | ||
448 | 459 | ||
449 | static void __exit microcode_exit (void) | 460 | static 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 | ||
462 | module_init(microcode_init) | 472 | microcode_ops = NULL; |
463 | module_exit(microcode_exit) | 473 | |
474 | printk(KERN_INFO | ||
475 | "Microcode Update Driver: v" MICROCODE_VERSION " removed.\n"); | ||
476 | } | ||
477 | EXPORT_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 | ||
128 | extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS]; | 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 | 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 | ||
178 | int microcode_sanity_check(void *mc) | 178 | static 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 | */ |
262 | int get_matching_microcode(void *mc, int cpu) | 262 | static 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; |
289 | find: | 289 | find: |
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 | ||
306 | void apply_microcode(int cpu) | 307 | static 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) | |||
347 | extern void __user *user_buffer; /* user area microcode data buffer */ | 348 | extern void __user *user_buffer; /* user area microcode data buffer */ |
348 | extern unsigned int user_buffer_size; /* it's size */ | 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 | 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 */ |
407 | extern struct platform_device *microcode_pdev; | 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 | 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 | ||
458 | int apply_microcode_check_cpu(int cpu) | 459 | static 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 | ||
507 | void microcode_fini_cpu(int cpu) | 508 | static 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(µcode_mutex); | 512 | mutex_lock(µcode_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(µcode_mutex); | 516 | mutex_unlock(µcode_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(µcode_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) | ||