Commit 18dbc9160507dc7df998e00cd1dcd7889557307b

Authored by Dmitry Adamushko
Committed by Ingo Molnar
1 parent a1c75cc501

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>

Showing 7 changed files with 632 additions and 650 deletions Side-by-side Diff

... ... @@ -801,7 +801,7 @@
801 801 module will be called microcode.
802 802  
803 803 config MICROCODE_INTEL
804   - tristate "Intel microcode patch loading support"
  804 + bool "Intel microcode patch loading support"
805 805 depends on MICROCODE
806 806 default MICROCODE
807 807 select FW_LOADER
808 808  
809 809  
... ... @@ -813,19 +813,13 @@
813 813 Intel ingredients for this driver, check:
814 814 <http://www.urbanmyth.org/microcode/>.
815 815  
816   - This driver is only available as a module: the module
817   - will be called microcode_intel.
818   -
819 816 config MICROCODE_AMD
820   - tristate "AMD microcode patch loading support"
  817 + bool "AMD microcode patch loading support"
821 818 depends on MICROCODE
822 819 select FW_LOADER
823 820 --help---
824 821 If you select this option, microcode patch loading support for AMD
825 822 processors will be enabled.
826   -
827   - This driver is only available as a module: the module
828   - will be called microcode_amd.
829 823  
830 824 config MICROCODE_OLD_INTERFACE
831 825 def_bool y
arch/x86/kernel/Makefile
... ... @@ -51,9 +51,6 @@
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) += microcode.o
55   -obj-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o
56   -obj-$(CONFIG_MICROCODE_AMD) += microcode_amd.o
57 54 obj-$(CONFIG_PCI) += early-quirks.o
58 55 apm-y := apm_32.o
59 56 obj-$(CONFIG_APM) += apm.o
... ... @@ -100,6 +97,11 @@
100 97 scx200-y += scx200_32.o
101 98  
102 99 obj-$(CONFIG_OLPC) += olpc.o
  100 +
  101 +microcode-y := microcode_core.o
  102 +microcode-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o
  103 +microcode-$(CONFIG_MICROCODE_AMD) += microcode_amd.o
  104 +obj-$(CONFIG_MICROCODE) += microcode.o
103 105  
104 106 ###
105 107 # 64 bit specific files
arch/x86/kernel/microcode.c
1   -/*
2   - * Intel CPU Microcode Update Driver for Linux
3   - *
4   - * Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
5   - * 2006 Shaohua Li <shaohua.li@intel.com>
6   - *
7   - * This driver allows to upgrade microcode on Intel processors
8   - * belonging to IA-32 family - PentiumPro, Pentium II,
9   - * Pentium III, Xeon, Pentium 4, etc.
10   - *
11   - * Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture
12   - * Software Developer's Manual
13   - * Order Number 253668 or free download from:
14   - *
15   - * http://developer.intel.com/design/pentium4/manuals/253668.htm
16   - *
17   - * For more information, go to http://www.urbanmyth.org/microcode
18   - *
19   - * This program is free software; you can redistribute it and/or
20   - * modify it under the terms of the GNU General Public License
21   - * as published by the Free Software Foundation; either version
22   - * 2 of the License, or (at your option) any later version.
23   - *
24   - * 1.0 16 Feb 2000, Tigran Aivazian <tigran@sco.com>
25   - * Initial release.
26   - * 1.01 18 Feb 2000, Tigran Aivazian <tigran@sco.com>
27   - * Added read() support + cleanups.
28   - * 1.02 21 Feb 2000, Tigran Aivazian <tigran@sco.com>
29   - * Added 'device trimming' support. open(O_WRONLY) zeroes
30   - * and frees the saved copy of applied microcode.
31   - * 1.03 29 Feb 2000, Tigran Aivazian <tigran@sco.com>
32   - * Made to use devfs (/dev/cpu/microcode) + cleanups.
33   - * 1.04 06 Jun 2000, Simon Trimmer <simon@veritas.com>
34   - * Added misc device support (now uses both devfs and misc).
35   - * Added MICROCODE_IOCFREE ioctl to clear memory.
36   - * 1.05 09 Jun 2000, Simon Trimmer <simon@veritas.com>
37   - * Messages for error cases (non Intel & no suitable microcode).
38   - * 1.06 03 Aug 2000, Tigran Aivazian <tigran@veritas.com>
39   - * Removed ->release(). Removed exclusive open and status bitmap.
40   - * Added microcode_rwsem to serialize read()/write()/ioctl().
41   - * Removed global kernel lock usage.
42   - * 1.07 07 Sep 2000, Tigran Aivazian <tigran@veritas.com>
43   - * Write 0 to 0x8B msr and then cpuid before reading revision,
44   - * so that it works even if there were no update done by the
45   - * BIOS. Otherwise, reading from 0x8B gives junk (which happened
46   - * to be 0 on my machine which is why it worked even when I
47   - * disabled update by the BIOS)
48   - * Thanks to Eric W. Biederman <ebiederman@lnxi.com> for the fix.
49   - * 1.08 11 Dec 2000, Richard Schaal <richard.schaal@intel.com> and
50   - * Tigran Aivazian <tigran@veritas.com>
51   - * Intel Pentium 4 processor support and bugfixes.
52   - * 1.09 30 Oct 2001, Tigran Aivazian <tigran@veritas.com>
53   - * Bugfix for HT (Hyper-Threading) enabled processors
54   - * whereby processor resources are shared by all logical processors
55   - * in a single CPU package.
56   - * 1.10 28 Feb 2002 Asit K Mallick <asit.k.mallick@intel.com> and
57   - * Tigran Aivazian <tigran@veritas.com>,
58   - * Serialize updates as required on HT processors due to
59   - * speculative nature of implementation.
60   - * 1.11 22 Mar 2002 Tigran Aivazian <tigran@veritas.com>
61   - * Fix the panic when writing zero-length microcode chunk.
62   - * 1.12 29 Sep 2003 Nitin Kamble <nitin.a.kamble@intel.com>,
63   - * Jun Nakajima <jun.nakajima@intel.com>
64   - * Support for the microcode updates in the new format.
65   - * 1.13 10 Oct 2003 Tigran Aivazian <tigran@veritas.com>
66   - * Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl
67   - * because we no longer hold a copy of applied microcode
68   - * in kernel memory.
69   - * 1.14 25 Jun 2004 Tigran Aivazian <tigran@veritas.com>
70   - * Fix sigmatch() macro to handle old CPUs with pf == 0.
71   - * Thanks to Stuart Swales for pointing out this bug.
72   - */
73   -#include <linux/capability.h>
74   -#include <linux/kernel.h>
75   -#include <linux/init.h>
76   -#include <linux/sched.h>
77   -#include <linux/smp_lock.h>
78   -#include <linux/cpumask.h>
79   -#include <linux/module.h>
80   -#include <linux/slab.h>
81   -#include <linux/vmalloc.h>
82   -#include <linux/miscdevice.h>
83   -#include <linux/spinlock.h>
84   -#include <linux/mm.h>
85   -#include <linux/fs.h>
86   -#include <linux/mutex.h>
87   -#include <linux/cpu.h>
88   -#include <linux/firmware.h>
89   -#include <linux/platform_device.h>
90   -
91   -#include <asm/msr.h>
92   -#include <asm/uaccess.h>
93   -#include <asm/processor.h>
94   -#include <asm/microcode.h>
95   -
96   -MODULE_DESCRIPTION("Microcode Update Driver");
97   -MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
98   -MODULE_LICENSE("GPL");
99   -
100   -#define MICROCODE_VERSION "2.00"
101   -
102   -struct microcode_ops *microcode_ops;
103   -
104   -/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
105   -static DEFINE_MUTEX(microcode_mutex);
106   -
107   -struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
108   -EXPORT_SYMBOL_GPL(ucode_cpu_info);
109   -
110   -#ifdef CONFIG_MICROCODE_OLD_INTERFACE
111   -static int do_microcode_update(const void __user *buf, size_t size)
112   -{
113   - cpumask_t old;
114   - int error = 0;
115   - int cpu;
116   -
117   - old = current->cpus_allowed;
118   -
119   - for_each_online_cpu(cpu) {
120   - struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
121   -
122   - if (!uci->valid)
123   - continue;
124   -
125   - set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
126   - error = microcode_ops->request_microcode_user(cpu, buf, size);
127   - if (error < 0)
128   - goto out;
129   - if (!error)
130   - microcode_ops->apply_microcode(cpu);
131   - }
132   -out:
133   - set_cpus_allowed_ptr(current, &old);
134   - return error;
135   -}
136   -
137   -static int microcode_open(struct inode *unused1, struct file *unused2)
138   -{
139   - cycle_kernel_lock();
140   - return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
141   -}
142   -
143   -static ssize_t microcode_write(struct file *file, const char __user *buf,
144   - size_t len, loff_t *ppos)
145   -{
146   - ssize_t ret;
147   -
148   - if ((len >> PAGE_SHIFT) > num_physpages) {
149   - printk(KERN_ERR "microcode: too much data (max %ld pages)\n",
150   - num_physpages);
151   - return -EINVAL;
152   - }
153   -
154   - get_online_cpus();
155   - mutex_lock(&microcode_mutex);
156   -
157   - ret = do_microcode_update(buf, len);
158   - if (!ret)
159   - ret = (ssize_t)len;
160   -
161   - mutex_unlock(&microcode_mutex);
162   - put_online_cpus();
163   -
164   - return ret;
165   -}
166   -
167   -static const struct file_operations microcode_fops = {
168   - .owner = THIS_MODULE,
169   - .write = microcode_write,
170   - .open = microcode_open,
171   -};
172   -
173   -static struct miscdevice microcode_dev = {
174   - .minor = MICROCODE_MINOR,
175   - .name = "microcode",
176   - .fops = &microcode_fops,
177   -};
178   -
179   -static int __init microcode_dev_init(void)
180   -{
181   - int error;
182   -
183   - error = misc_register(&microcode_dev);
184   - if (error) {
185   - printk(KERN_ERR
186   - "microcode: can't misc_register on minor=%d\n",
187   - MICROCODE_MINOR);
188   - return error;
189   - }
190   -
191   - return 0;
192   -}
193   -
194   -static void microcode_dev_exit(void)
195   -{
196   - misc_deregister(&microcode_dev);
197   -}
198   -
199   -MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
200   -#else
201   -#define microcode_dev_init() 0
202   -#define microcode_dev_exit() do { } while (0)
203   -#endif
204   -
205   -/* fake device for request_firmware */
206   -struct platform_device *microcode_pdev;
207   -
208   -static ssize_t reload_store(struct sys_device *dev,
209   - struct sysdev_attribute *attr,
210   - const char *buf, size_t sz)
211   -{
212   - struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
213   - char *end;
214   - unsigned long val = simple_strtoul(buf, &end, 0);
215   - int err = 0;
216   - int cpu = dev->id;
217   -
218   - if (end == buf)
219   - return -EINVAL;
220   - if (val == 1) {
221   - cpumask_t old = current->cpus_allowed;
222   -
223   - get_online_cpus();
224   - if (cpu_online(cpu)) {
225   - set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
226   - mutex_lock(&microcode_mutex);
227   - if (uci->valid) {
228   - err = microcode_ops->request_microcode_fw(cpu,
229   - &microcode_pdev->dev);
230   - if (!err)
231   - microcode_ops->apply_microcode(cpu);
232   - }
233   - mutex_unlock(&microcode_mutex);
234   - set_cpus_allowed_ptr(current, &old);
235   - }
236   - put_online_cpus();
237   - }
238   - if (err)
239   - return err;
240   - return sz;
241   -}
242   -
243   -static ssize_t version_show(struct sys_device *dev,
244   - struct sysdev_attribute *attr, char *buf)
245   -{
246   - struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
247   -
248   - return sprintf(buf, "0x%x\n", uci->cpu_sig.rev);
249   -}
250   -
251   -static ssize_t pf_show(struct sys_device *dev,
252   - struct sysdev_attribute *attr, char *buf)
253   -{
254   - struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
255   -
256   - return sprintf(buf, "0x%x\n", uci->cpu_sig.pf);
257   -}
258   -
259   -static SYSDEV_ATTR(reload, 0200, NULL, reload_store);
260   -static SYSDEV_ATTR(version, 0400, version_show, NULL);
261   -static SYSDEV_ATTR(processor_flags, 0400, pf_show, NULL);
262   -
263   -static struct attribute *mc_default_attrs[] = {
264   - &attr_reload.attr,
265   - &attr_version.attr,
266   - &attr_processor_flags.attr,
267   - NULL
268   -};
269   -
270   -static struct attribute_group mc_attr_group = {
271   - .attrs = mc_default_attrs,
272   - .name = "microcode",
273   -};
274   -
275   -static void microcode_fini_cpu(int cpu)
276   -{
277   - struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
278   -
279   - mutex_lock(&microcode_mutex);
280   - microcode_ops->microcode_fini_cpu(cpu);
281   - uci->valid = 0;
282   - mutex_unlock(&microcode_mutex);
283   -}
284   -
285   -static void collect_cpu_info(int cpu)
286   -{
287   - struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
288   -
289   - memset(uci, 0, sizeof(*uci));
290   - if (!microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig))
291   - uci->valid = 1;
292   -}
293   -
294   -static int microcode_resume_cpu(int cpu)
295   -{
296   - struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
297   - struct cpu_signature nsig;
298   -
299   - pr_debug("microcode: CPU%d resumed\n", cpu);
300   -
301   - if (!uci->mc.valid_mc)
302   - return 1;
303   -
304   - /*
305   - * Let's verify that the 'cached' ucode does belong
306   - * to this cpu (a bit of paranoia):
307   - */
308   - if (microcode_ops->collect_cpu_info(cpu, &nsig)) {
309   - microcode_fini_cpu(cpu);
310   - return -1;
311   - }
312   -
313   - if (memcmp(&nsig, &uci->cpu_sig, sizeof(nsig))) {
314   - microcode_fini_cpu(cpu);
315   - /* Should we look for a new ucode here? */
316   - return 1;
317   - }
318   -
319   - return 0;
320   -}
321   -
322   -void microcode_update_cpu(int cpu)
323   -{
324   - struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
325   - int err = 0;
326   -
327   - /* We should bind the task to the CPU */
328   - BUG_ON(raw_smp_processor_id() != cpu);
329   -
330   - mutex_lock(&microcode_mutex);
331   - /*
332   - * Check if the system resume is in progress (uci->valid != NULL),
333   - * otherwise just request a firmware:
334   - */
335   - if (uci->valid) {
336   - err = microcode_resume_cpu(cpu);
337   - } else {
338   - collect_cpu_info(cpu);
339   - if (uci->valid && system_state == SYSTEM_RUNNING)
340   - err = microcode_ops->request_microcode_fw(cpu,
341   - &microcode_pdev->dev);
342   - }
343   -
344   - if (!err)
345   - microcode_ops->apply_microcode(cpu);
346   -
347   - mutex_unlock(&microcode_mutex);
348   -}
349   -
350   -static void microcode_init_cpu(int cpu)
351   -{
352   - cpumask_t old = current->cpus_allowed;
353   -
354   - set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
355   - microcode_update_cpu(cpu);
356   - set_cpus_allowed_ptr(current, &old);
357   -}
358   -
359   -static int mc_sysdev_add(struct sys_device *sys_dev)
360   -{
361   - int err, cpu = sys_dev->id;
362   - struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
363   -
364   - if (!cpu_online(cpu))
365   - return 0;
366   -
367   - pr_debug("microcode: CPU%d added\n", cpu);
368   - memset(uci, 0, sizeof(*uci));
369   -
370   - err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group);
371   - if (err)
372   - return err;
373   -
374   - microcode_init_cpu(cpu);
375   - return 0;
376   -}
377   -
378   -static int mc_sysdev_remove(struct sys_device *sys_dev)
379   -{
380   - int cpu = sys_dev->id;
381   -
382   - if (!cpu_online(cpu))
383   - return 0;
384   -
385   - pr_debug("microcode: CPU%d removed\n", cpu);
386   - microcode_fini_cpu(cpu);
387   - sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
388   - return 0;
389   -}
390   -
391   -static int mc_sysdev_resume(struct sys_device *dev)
392   -{
393   - int cpu = dev->id;
394   -
395   - if (!cpu_online(cpu))
396   - return 0;
397   -
398   - /* only CPU 0 will apply ucode here */
399   - microcode_update_cpu(0);
400   - return 0;
401   -}
402   -
403   -static struct sysdev_driver mc_sysdev_driver = {
404   - .add = mc_sysdev_add,
405   - .remove = mc_sysdev_remove,
406   - .resume = mc_sysdev_resume,
407   -};
408   -
409   -static __cpuinit int
410   -mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
411   -{
412   - unsigned int cpu = (unsigned long)hcpu;
413   - struct sys_device *sys_dev;
414   -
415   - sys_dev = get_cpu_sysdev(cpu);
416   - switch (action) {
417   - case CPU_ONLINE:
418   - case CPU_ONLINE_FROZEN:
419   - microcode_init_cpu(cpu);
420   - case CPU_DOWN_FAILED:
421   - case CPU_DOWN_FAILED_FROZEN:
422   - pr_debug("microcode: CPU%d added\n", cpu);
423   - if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group))
424   - printk(KERN_ERR "microcode: Failed to create the sysfs "
425   - "group for CPU%d\n", cpu);
426   - break;
427   - case CPU_DOWN_PREPARE:
428   - case CPU_DOWN_PREPARE_FROZEN:
429   - /* Suspend is in progress, only remove the interface */
430   - sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
431   - pr_debug("microcode: CPU%d removed\n", cpu);
432   - break;
433   - case CPU_DEAD:
434   - case CPU_UP_CANCELED_FROZEN:
435   - /* The CPU refused to come up during a system resume */
436   - microcode_fini_cpu(cpu);
437   - break;
438   - }
439   - return NOTIFY_OK;
440   -}
441   -
442   -static struct notifier_block __refdata mc_cpu_notifier = {
443   - .notifier_call = mc_cpu_callback,
444   -};
445   -
446   -int microcode_init(void *opaque, struct module *module)
447   -{
448   - struct microcode_ops *ops = (struct microcode_ops *)opaque;
449   - int error;
450   -
451   - if (microcode_ops) {
452   - printk(KERN_ERR "microcode: already loaded the other module\n");
453   - return -EEXIST;
454   - }
455   -
456   - microcode_ops = ops;
457   -
458   - error = microcode_dev_init();
459   - if (error)
460   - return error;
461   - microcode_pdev = platform_device_register_simple("microcode", -1,
462   - NULL, 0);
463   - if (IS_ERR(microcode_pdev)) {
464   - microcode_dev_exit();
465   - return PTR_ERR(microcode_pdev);
466   - }
467   -
468   - get_online_cpus();
469   - error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver);
470   - put_online_cpus();
471   - if (error) {
472   - microcode_dev_exit();
473   - platform_device_unregister(microcode_pdev);
474   - return error;
475   - }
476   -
477   - register_hotcpu_notifier(&mc_cpu_notifier);
478   -
479   - printk(KERN_INFO
480   - "Microcode Update Driver: v" MICROCODE_VERSION
481   - " <tigran@aivazian.fsnet.co.uk>"
482   - " <peter.oruba@amd.com>\n");
483   -
484   - return 0;
485   -}
486   -EXPORT_SYMBOL_GPL(microcode_init);
487   -
488   -void __exit microcode_exit(void)
489   -{
490   - microcode_dev_exit();
491   -
492   - unregister_hotcpu_notifier(&mc_cpu_notifier);
493   -
494   - get_online_cpus();
495   - sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver);
496   - put_online_cpus();
497   -
498   - platform_device_unregister(microcode_pdev);
499   -
500   - microcode_ops = NULL;
501   -
502   - printk(KERN_INFO
503   - "Microcode Update Driver: v" MICROCODE_VERSION " removed.\n");
504   -}
505   -EXPORT_SYMBOL_GPL(microcode_exit);
arch/x86/kernel/microcode_amd.c
... ... @@ -46,6 +46,35 @@
46 46 #define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000
47 47 #define UCODE_UCODE_TYPE 0x00000001
48 48  
  49 +struct 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 +
  56 +struct 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 +
  73 +struct microcode_amd {
  74 + struct microcode_header_amd hdr;
  75 + unsigned int mpb[0];
  76 +};
  77 +
49 78 #define UCODE_MAX_SIZE (2048)
50 79 #define DEFAULT_UCODE_DATASIZE (896)
51 80 #define MC_HEADER_SIZE (sizeof(struct microcode_header_amd))
52 81  
53 82  
... ... @@ -189,17 +218,18 @@
189 218 unsigned int rev;
190 219 int cpu_num = raw_smp_processor_id();
191 220 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
  221 + struct microcode_amd *mc_amd = uci->mc;
192 222 unsigned long addr;
193 223  
194 224 /* We should bind the task to the CPU */
195 225 BUG_ON(cpu_num != cpu);
196 226  
197   - if (uci->mc.mc_amd == NULL)
  227 + if (mc_amd == NULL)
198 228 return;
199 229  
200 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 233 edx = (unsigned int)(((unsigned long)upper_32_bits(addr)));
204 234 eax = (unsigned int)(((unsigned long)lower_32_bits(addr)));
205 235  
206 236  
207 237  
... ... @@ -214,16 +244,16 @@
214 244 spin_unlock_irqrestore(&microcode_update_lock, flags);
215 245  
216 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 248 printk(KERN_ERR "microcode: CPU%d update from revision "
219 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 251 return;
222 252 }
223 253  
224 254 printk(KERN_INFO "microcode: CPU%d updated from revision "
225 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 258 uci->cpu_sig.rev = rev;
229 259 }
230 260  
... ... @@ -355,12 +385,12 @@
355 385  
356 386 if (new_mc) {
357 387 if (!leftover) {
358   - if (uci->mc.mc_amd)
359   - vfree(uci->mc.mc_amd);
360   - uci->mc.mc_amd = (struct microcode_amd *)new_mc;
  388 + if (uci->mc)
  389 + vfree(uci->mc);
  390 + uci->mc = new_mc;
361 391 pr_debug("microcode: CPU%d found a matching microcode update with"
362 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 394 } else
365 395 vfree(new_mc);
366 396 }
... ... @@ -416,8 +446,8 @@
416 446 {
417 447 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
418 448  
419   - vfree(uci->mc.mc_amd);
420   - uci->mc.mc_amd = NULL;
  449 + vfree(uci->mc);
  450 + uci->mc = NULL;
421 451 }
422 452  
423 453 static struct microcode_ops microcode_amd_ops = {
424 454  
425 455  
... ... @@ -428,24 +458,8 @@
428 458 .microcode_fini_cpu = microcode_fini_cpu_amd,
429 459 };
430 460  
431   -static int __init microcode_amd_module_init(void)
  461 +struct microcode_ops * __init init_amd_microcode(void)
432 462 {
433   - struct cpuinfo_x86 *c = &cpu_data(0);
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);
  463 + return &microcode_amd_ops;
442 464 }
443   -
444   -static void __exit microcode_amd_module_exit(void)
445   -{
446   - microcode_exit();
447   -}
448   -
449   -module_init(microcode_amd_module_init)
450   -module_exit(microcode_amd_module_exit)
arch/x86/kernel/microcode_core.c
  1 +/*
  2 + * Intel CPU Microcode Update Driver for Linux
  3 + *
  4 + * Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
  5 + * 2006 Shaohua Li <shaohua.li@intel.com>
  6 + *
  7 + * This driver allows to upgrade microcode on Intel processors
  8 + * belonging to IA-32 family - PentiumPro, Pentium II,
  9 + * Pentium III, Xeon, Pentium 4, etc.
  10 + *
  11 + * Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture
  12 + * Software Developer's Manual
  13 + * Order Number 253668 or free download from:
  14 + *
  15 + * http://developer.intel.com/design/pentium4/manuals/253668.htm
  16 + *
  17 + * For more information, go to http://www.urbanmyth.org/microcode
  18 + *
  19 + * This program is free software; you can redistribute it and/or
  20 + * modify it under the terms of the GNU General Public License
  21 + * as published by the Free Software Foundation; either version
  22 + * 2 of the License, or (at your option) any later version.
  23 + *
  24 + * 1.0 16 Feb 2000, Tigran Aivazian <tigran@sco.com>
  25 + * Initial release.
  26 + * 1.01 18 Feb 2000, Tigran Aivazian <tigran@sco.com>
  27 + * Added read() support + cleanups.
  28 + * 1.02 21 Feb 2000, Tigran Aivazian <tigran@sco.com>
  29 + * Added 'device trimming' support. open(O_WRONLY) zeroes
  30 + * and frees the saved copy of applied microcode.
  31 + * 1.03 29 Feb 2000, Tigran Aivazian <tigran@sco.com>
  32 + * Made to use devfs (/dev/cpu/microcode) + cleanups.
  33 + * 1.04 06 Jun 2000, Simon Trimmer <simon@veritas.com>
  34 + * Added misc device support (now uses both devfs and misc).
  35 + * Added MICROCODE_IOCFREE ioctl to clear memory.
  36 + * 1.05 09 Jun 2000, Simon Trimmer <simon@veritas.com>
  37 + * Messages for error cases (non Intel & no suitable microcode).
  38 + * 1.06 03 Aug 2000, Tigran Aivazian <tigran@veritas.com>
  39 + * Removed ->release(). Removed exclusive open and status bitmap.
  40 + * Added microcode_rwsem to serialize read()/write()/ioctl().
  41 + * Removed global kernel lock usage.
  42 + * 1.07 07 Sep 2000, Tigran Aivazian <tigran@veritas.com>
  43 + * Write 0 to 0x8B msr and then cpuid before reading revision,
  44 + * so that it works even if there were no update done by the
  45 + * BIOS. Otherwise, reading from 0x8B gives junk (which happened
  46 + * to be 0 on my machine which is why it worked even when I
  47 + * disabled update by the BIOS)
  48 + * Thanks to Eric W. Biederman <ebiederman@lnxi.com> for the fix.
  49 + * 1.08 11 Dec 2000, Richard Schaal <richard.schaal@intel.com> and
  50 + * Tigran Aivazian <tigran@veritas.com>
  51 + * Intel Pentium 4 processor support and bugfixes.
  52 + * 1.09 30 Oct 2001, Tigran Aivazian <tigran@veritas.com>
  53 + * Bugfix for HT (Hyper-Threading) enabled processors
  54 + * whereby processor resources are shared by all logical processors
  55 + * in a single CPU package.
  56 + * 1.10 28 Feb 2002 Asit K Mallick <asit.k.mallick@intel.com> and
  57 + * Tigran Aivazian <tigran@veritas.com>,
  58 + * Serialize updates as required on HT processors due to
  59 + * speculative nature of implementation.
  60 + * 1.11 22 Mar 2002 Tigran Aivazian <tigran@veritas.com>
  61 + * Fix the panic when writing zero-length microcode chunk.
  62 + * 1.12 29 Sep 2003 Nitin Kamble <nitin.a.kamble@intel.com>,
  63 + * Jun Nakajima <jun.nakajima@intel.com>
  64 + * Support for the microcode updates in the new format.
  65 + * 1.13 10 Oct 2003 Tigran Aivazian <tigran@veritas.com>
  66 + * Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl
  67 + * because we no longer hold a copy of applied microcode
  68 + * in kernel memory.
  69 + * 1.14 25 Jun 2004 Tigran Aivazian <tigran@veritas.com>
  70 + * Fix sigmatch() macro to handle old CPUs with pf == 0.
  71 + * Thanks to Stuart Swales for pointing out this bug.
  72 + */
  73 +#include <linux/capability.h>
  74 +#include <linux/kernel.h>
  75 +#include <linux/init.h>
  76 +#include <linux/sched.h>
  77 +#include <linux/smp_lock.h>
  78 +#include <linux/cpumask.h>
  79 +#include <linux/module.h>
  80 +#include <linux/slab.h>
  81 +#include <linux/vmalloc.h>
  82 +#include <linux/miscdevice.h>
  83 +#include <linux/spinlock.h>
  84 +#include <linux/mm.h>
  85 +#include <linux/fs.h>
  86 +#include <linux/mutex.h>
  87 +#include <linux/cpu.h>
  88 +#include <linux/firmware.h>
  89 +#include <linux/platform_device.h>
  90 +
  91 +#include <asm/msr.h>
  92 +#include <asm/uaccess.h>
  93 +#include <asm/processor.h>
  94 +#include <asm/microcode.h>
  95 +
  96 +MODULE_DESCRIPTION("Microcode Update Driver");
  97 +MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
  98 +MODULE_LICENSE("GPL");
  99 +
  100 +#define MICROCODE_VERSION "2.00"
  101 +
  102 +struct microcode_ops *microcode_ops;
  103 +
  104 +/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
  105 +static DEFINE_MUTEX(microcode_mutex);
  106 +
  107 +struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
  108 +EXPORT_SYMBOL_GPL(ucode_cpu_info);
  109 +
  110 +#ifdef CONFIG_MICROCODE_OLD_INTERFACE
  111 +static int do_microcode_update(const void __user *buf, size_t size)
  112 +{
  113 + cpumask_t old;
  114 + int error = 0;
  115 + int cpu;
  116 +
  117 + old = current->cpus_allowed;
  118 +
  119 + for_each_online_cpu(cpu) {
  120 + struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
  121 +
  122 + if (!uci->valid)
  123 + continue;
  124 +
  125 + set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
  126 + error = microcode_ops->request_microcode_user(cpu, buf, size);
  127 + if (error < 0)
  128 + goto out;
  129 + if (!error)
  130 + microcode_ops->apply_microcode(cpu);
  131 + }
  132 +out:
  133 + set_cpus_allowed_ptr(current, &old);
  134 + return error;
  135 +}
  136 +
  137 +static int microcode_open(struct inode *unused1, struct file *unused2)
  138 +{
  139 + cycle_kernel_lock();
  140 + return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
  141 +}
  142 +
  143 +static ssize_t microcode_write(struct file *file, const char __user *buf,
  144 + size_t len, loff_t *ppos)
  145 +{
  146 + ssize_t ret;
  147 +
  148 + if ((len >> PAGE_SHIFT) > num_physpages) {
  149 + printk(KERN_ERR "microcode: too much data (max %ld pages)\n",
  150 + num_physpages);
  151 + return -EINVAL;
  152 + }
  153 +
  154 + get_online_cpus();
  155 + mutex_lock(&microcode_mutex);
  156 +
  157 + ret = do_microcode_update(buf, len);
  158 + if (!ret)
  159 + ret = (ssize_t)len;
  160 +
  161 + mutex_unlock(&microcode_mutex);
  162 + put_online_cpus();
  163 +
  164 + return ret;
  165 +}
  166 +
  167 +static const struct file_operations microcode_fops = {
  168 + .owner = THIS_MODULE,
  169 + .write = microcode_write,
  170 + .open = microcode_open,
  171 +};
  172 +
  173 +static struct miscdevice microcode_dev = {
  174 + .minor = MICROCODE_MINOR,
  175 + .name = "microcode",
  176 + .fops = &microcode_fops,
  177 +};
  178 +
  179 +static int __init microcode_dev_init(void)
  180 +{
  181 + int error;
  182 +
  183 + error = misc_register(&microcode_dev);
  184 + if (error) {
  185 + printk(KERN_ERR
  186 + "microcode: can't misc_register on minor=%d\n",
  187 + MICROCODE_MINOR);
  188 + return error;
  189 + }
  190 +
  191 + return 0;
  192 +}
  193 +
  194 +static void microcode_dev_exit(void)
  195 +{
  196 + misc_deregister(&microcode_dev);
  197 +}
  198 +
  199 +MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
  200 +#else
  201 +#define microcode_dev_init() 0
  202 +#define microcode_dev_exit() do { } while (0)
  203 +#endif
  204 +
  205 +/* fake device for request_firmware */
  206 +struct platform_device *microcode_pdev;
  207 +
  208 +static ssize_t reload_store(struct sys_device *dev,
  209 + struct sysdev_attribute *attr,
  210 + const char *buf, size_t sz)
  211 +{
  212 + struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
  213 + char *end;
  214 + unsigned long val = simple_strtoul(buf, &end, 0);
  215 + int err = 0;
  216 + int cpu = dev->id;
  217 +
  218 + if (end == buf)
  219 + return -EINVAL;
  220 + if (val == 1) {
  221 + cpumask_t old = current->cpus_allowed;
  222 +
  223 + get_online_cpus();
  224 + if (cpu_online(cpu)) {
  225 + set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
  226 + mutex_lock(&microcode_mutex);
  227 + if (uci->valid) {
  228 + err = microcode_ops->request_microcode_fw(cpu,
  229 + &microcode_pdev->dev);
  230 + if (!err)
  231 + microcode_ops->apply_microcode(cpu);
  232 + }
  233 + mutex_unlock(&microcode_mutex);
  234 + set_cpus_allowed_ptr(current, &old);
  235 + }
  236 + put_online_cpus();
  237 + }
  238 + if (err)
  239 + return err;
  240 + return sz;
  241 +}
  242 +
  243 +static ssize_t version_show(struct sys_device *dev,
  244 + struct sysdev_attribute *attr, char *buf)
  245 +{
  246 + struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
  247 +
  248 + return sprintf(buf, "0x%x\n", uci->cpu_sig.rev);
  249 +}
  250 +
  251 +static ssize_t pf_show(struct sys_device *dev,
  252 + struct sysdev_attribute *attr, char *buf)
  253 +{
  254 + struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
  255 +
  256 + return sprintf(buf, "0x%x\n", uci->cpu_sig.pf);
  257 +}
  258 +
  259 +static SYSDEV_ATTR(reload, 0200, NULL, reload_store);
  260 +static SYSDEV_ATTR(version, 0400, version_show, NULL);
  261 +static SYSDEV_ATTR(processor_flags, 0400, pf_show, NULL);
  262 +
  263 +static struct attribute *mc_default_attrs[] = {
  264 + &attr_reload.attr,
  265 + &attr_version.attr,
  266 + &attr_processor_flags.attr,
  267 + NULL
  268 +};
  269 +
  270 +static struct attribute_group mc_attr_group = {
  271 + .attrs = mc_default_attrs,
  272 + .name = "microcode",
  273 +};
  274 +
  275 +static void microcode_fini_cpu(int cpu)
  276 +{
  277 + struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
  278 +
  279 + mutex_lock(&microcode_mutex);
  280 + microcode_ops->microcode_fini_cpu(cpu);
  281 + uci->valid = 0;
  282 + mutex_unlock(&microcode_mutex);
  283 +}
  284 +
  285 +static void collect_cpu_info(int cpu)
  286 +{
  287 + struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
  288 +
  289 + memset(uci, 0, sizeof(*uci));
  290 + if (!microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig))
  291 + uci->valid = 1;
  292 +}
  293 +
  294 +static int microcode_resume_cpu(int cpu)
  295 +{
  296 + struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
  297 + struct cpu_signature nsig;
  298 +
  299 + pr_debug("microcode: CPU%d resumed\n", cpu);
  300 +
  301 + if (!uci->mc)
  302 + return 1;
  303 +
  304 + /*
  305 + * Let's verify that the 'cached' ucode does belong
  306 + * to this cpu (a bit of paranoia):
  307 + */
  308 + if (microcode_ops->collect_cpu_info(cpu, &nsig)) {
  309 + microcode_fini_cpu(cpu);
  310 + return -1;
  311 + }
  312 +
  313 + if (memcmp(&nsig, &uci->cpu_sig, sizeof(nsig))) {
  314 + microcode_fini_cpu(cpu);
  315 + /* Should we look for a new ucode here? */
  316 + return 1;
  317 + }
  318 +
  319 + return 0;
  320 +}
  321 +
  322 +void microcode_update_cpu(int cpu)
  323 +{
  324 + struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
  325 + int err = 0;
  326 +
  327 + /* We should bind the task to the CPU */
  328 + BUG_ON(raw_smp_processor_id() != cpu);
  329 +
  330 + mutex_lock(&microcode_mutex);
  331 + /*
  332 + * Check if the system resume is in progress (uci->valid != NULL),
  333 + * otherwise just request a firmware:
  334 + */
  335 + if (uci->valid) {
  336 + err = microcode_resume_cpu(cpu);
  337 + } else {
  338 + collect_cpu_info(cpu);
  339 + if (uci->valid && system_state == SYSTEM_RUNNING)
  340 + err = microcode_ops->request_microcode_fw(cpu,
  341 + &microcode_pdev->dev);
  342 + }
  343 +
  344 + if (!err)
  345 + microcode_ops->apply_microcode(cpu);
  346 +
  347 + mutex_unlock(&microcode_mutex);
  348 +}
  349 +
  350 +static void microcode_init_cpu(int cpu)
  351 +{
  352 + cpumask_t old = current->cpus_allowed;
  353 +
  354 + set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
  355 + microcode_update_cpu(cpu);
  356 + set_cpus_allowed_ptr(current, &old);
  357 +}
  358 +
  359 +static int mc_sysdev_add(struct sys_device *sys_dev)
  360 +{
  361 + int err, cpu = sys_dev->id;
  362 + struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
  363 +
  364 + if (!cpu_online(cpu))
  365 + return 0;
  366 +
  367 + pr_debug("microcode: CPU%d added\n", cpu);
  368 + memset(uci, 0, sizeof(*uci));
  369 +
  370 + err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group);
  371 + if (err)
  372 + return err;
  373 +
  374 + microcode_init_cpu(cpu);
  375 + return 0;
  376 +}
  377 +
  378 +static int mc_sysdev_remove(struct sys_device *sys_dev)
  379 +{
  380 + int cpu = sys_dev->id;
  381 +
  382 + if (!cpu_online(cpu))
  383 + return 0;
  384 +
  385 + pr_debug("microcode: CPU%d removed\n", cpu);
  386 + microcode_fini_cpu(cpu);
  387 + sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
  388 + return 0;
  389 +}
  390 +
  391 +static int mc_sysdev_resume(struct sys_device *dev)
  392 +{
  393 + int cpu = dev->id;
  394 +
  395 + if (!cpu_online(cpu))
  396 + return 0;
  397 +
  398 + /* only CPU 0 will apply ucode here */
  399 + microcode_update_cpu(0);
  400 + return 0;
  401 +}
  402 +
  403 +static struct sysdev_driver mc_sysdev_driver = {
  404 + .add = mc_sysdev_add,
  405 + .remove = mc_sysdev_remove,
  406 + .resume = mc_sysdev_resume,
  407 +};
  408 +
  409 +static __cpuinit int
  410 +mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
  411 +{
  412 + unsigned int cpu = (unsigned long)hcpu;
  413 + struct sys_device *sys_dev;
  414 +
  415 + sys_dev = get_cpu_sysdev(cpu);
  416 + switch (action) {
  417 + case CPU_ONLINE:
  418 + case CPU_ONLINE_FROZEN:
  419 + microcode_init_cpu(cpu);
  420 + case CPU_DOWN_FAILED:
  421 + case CPU_DOWN_FAILED_FROZEN:
  422 + pr_debug("microcode: CPU%d added\n", cpu);
  423 + if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group))
  424 + printk(KERN_ERR "microcode: Failed to create the sysfs "
  425 + "group for CPU%d\n", cpu);
  426 + break;
  427 + case CPU_DOWN_PREPARE:
  428 + case CPU_DOWN_PREPARE_FROZEN:
  429 + /* Suspend is in progress, only remove the interface */
  430 + sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
  431 + pr_debug("microcode: CPU%d removed\n", cpu);
  432 + break;
  433 + case CPU_DEAD:
  434 + case CPU_UP_CANCELED_FROZEN:
  435 + /* The CPU refused to come up during a system resume */
  436 + microcode_fini_cpu(cpu);
  437 + break;
  438 + }
  439 + return NOTIFY_OK;
  440 +}
  441 +
  442 +static struct notifier_block __refdata mc_cpu_notifier = {
  443 + .notifier_call = mc_cpu_callback,
  444 +};
  445 +
  446 +static int __init microcode_init(void)
  447 +{
  448 + struct cpuinfo_x86 *c = &cpu_data(0);
  449 + int error;
  450 +
  451 + if (c->x86_vendor == X86_VENDOR_INTEL)
  452 + microcode_ops = init_intel_microcode();
  453 + else if (c->x86_vendor != X86_VENDOR_AMD)
  454 + microcode_ops = init_amd_microcode();
  455 +
  456 + if (!microcode_ops) {
  457 + printk(KERN_ERR "microcode: no support for this CPU vendor\n");
  458 + return -ENODEV;
  459 + }
  460 +
  461 + error = microcode_dev_init();
  462 + if (error)
  463 + return error;
  464 + microcode_pdev = platform_device_register_simple("microcode", -1,
  465 + NULL, 0);
  466 + if (IS_ERR(microcode_pdev)) {
  467 + microcode_dev_exit();
  468 + return PTR_ERR(microcode_pdev);
  469 + }
  470 +
  471 + get_online_cpus();
  472 + error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver);
  473 + put_online_cpus();
  474 + if (error) {
  475 + microcode_dev_exit();
  476 + platform_device_unregister(microcode_pdev);
  477 + return error;
  478 + }
  479 +
  480 + register_hotcpu_notifier(&mc_cpu_notifier);
  481 +
  482 + printk(KERN_INFO
  483 + "Microcode Update Driver: v" MICROCODE_VERSION
  484 + " <tigran@aivazian.fsnet.co.uk>"
  485 + " <peter.oruba@amd.com>\n");
  486 +
  487 + return 0;
  488 +}
  489 +
  490 +static void __exit microcode_exit(void)
  491 +{
  492 + microcode_dev_exit();
  493 +
  494 + unregister_hotcpu_notifier(&mc_cpu_notifier);
  495 +
  496 + get_online_cpus();
  497 + sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver);
  498 + put_online_cpus();
  499 +
  500 + platform_device_unregister(microcode_pdev);
  501 +
  502 + microcode_ops = NULL;
  503 +
  504 + printk(KERN_INFO
  505 + "Microcode Update Driver: v" MICROCODE_VERSION " removed.\n");
  506 +}
  507 +
  508 +module_init(microcode_init);
  509 +module_exit(microcode_exit);
arch/x86/kernel/microcode_intel.c
... ... @@ -97,6 +97,38 @@
97 97 MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
98 98 MODULE_LICENSE("GPL");
99 99  
  100 +struct 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 +
  113 +struct microcode_intel {
  114 + struct microcode_header_intel hdr;
  115 + unsigned int bits[0];
  116 +};
  117 +
  118 +/* microcode format is extended from prescott processors */
  119 +struct extended_signature {
  120 + unsigned int sig;
  121 + unsigned int pf;
  122 + unsigned int cksum;
  123 +};
  124 +
  125 +struct extended_sigtable {
  126 + unsigned int count;
  127 + unsigned int cksum;
  128 + unsigned int reserved[3];
  129 + struct extended_signature sigs[0];
  130 +};
  131 +
100 132 #define DEFAULT_UCODE_DATASIZE (2000)
101 133 #define MC_HEADER_SIZE (sizeof(struct microcode_header_intel))
102 134 #define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE)
103 135  
... ... @@ -284,11 +316,12 @@
284 316 unsigned int val[2];
285 317 int cpu_num = raw_smp_processor_id();
286 318 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
  319 + struct microcode_intel *mc_intel = uci->mc;
287 320  
288 321 /* We should bind the task to the CPU */
289 322 BUG_ON(cpu_num != cpu);
290 323  
291   - if (uci->mc.mc_intel == NULL)
  324 + if (mc_intel == NULL)
292 325 return;
293 326  
294 327 /* serialize access to the physical write to MSR 0x79 */
... ... @@ -296,8 +329,8 @@
296 329  
297 330 /* write microcode via MSR 0x79 */
298 331 wrmsr(MSR_IA32_UCODE_WRITE,
299   - (unsigned long) uci->mc.mc_intel->bits,
300   - (unsigned long) uci->mc.mc_intel->bits >> 16 >> 16);
  332 + (unsigned long) mc_intel->bits,
  333 + (unsigned long) mc_intel->bits >> 16 >> 16);
301 334 wrmsr(MSR_IA32_UCODE_REV, 0, 0);
302 335  
303 336 /* see notes above for revision 1.07. Apparent chip bug */
... ... @@ -307,7 +340,7 @@
307 340 rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
308 341  
309 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 344 printk(KERN_ERR "microcode: CPU%d update from revision "
312 345 "0x%x to 0x%x failed\n", cpu_num, uci->cpu_sig.rev, val[1]);
313 346 return;
... ... @@ -315,9 +348,9 @@
315 348 printk(KERN_INFO "microcode: CPU%d updated from revision "
316 349 "0x%x to 0x%x, date = %04x-%02x-%02x \n",
317 350 cpu_num, uci->cpu_sig.rev, val[1],
318   - uci->mc.mc_intel->hdr.date & 0xffff,
319   - uci->mc.mc_intel->hdr.date >> 24,
320   - (uci->mc.mc_intel->hdr.date >> 16) & 0xff);
  351 + mc_intel->hdr.date & 0xffff,
  352 + mc_intel->hdr.date >> 24,
  353 + (mc_intel->hdr.date >> 16) & 0xff);
321 354 uci->cpu_sig.rev = val[1];
322 355 }
323 356  
324 357  
... ... @@ -367,12 +400,12 @@
367 400  
368 401 if (new_mc) {
369 402 if (!leftover) {
370   - if (uci->mc.mc_intel)
371   - vfree(uci->mc.mc_intel);
372   - uci->mc.mc_intel = (struct microcode_intel *)new_mc;
  403 + if (uci->mc)
  404 + vfree(uci->mc);
  405 + uci->mc = (struct microcode_intel *)new_mc;
373 406 pr_debug("microcode: CPU%d found a matching microcode update with"
374 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 409 } else
377 410 vfree(new_mc);
378 411 }
379 412  
... ... @@ -428,11 +461,11 @@
428 461 {
429 462 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
430 463  
431   - vfree(uci->mc.mc_intel);
432   - uci->mc.mc_intel = NULL;
  464 + vfree(uci->mc);
  465 + uci->mc = NULL;
433 466 }
434 467  
435   -static struct microcode_ops microcode_intel_ops = {
  468 +struct microcode_ops microcode_intel_ops = {
436 469 .request_microcode_user = request_microcode_user,
437 470 .request_microcode_fw = request_microcode_fw,
438 471 .collect_cpu_info = collect_cpu_info,
439 472  
440 473  
... ... @@ -440,23 +473,8 @@
440 473 .microcode_fini_cpu = microcode_fini_cpu,
441 474 };
442 475  
443   -static int __init microcode_intel_module_init(void)
  476 +struct microcode_ops * __init init_intel_microcode(void)
444 477 {
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);
  478 + return &microcode_intel_ops;
453 479 }
454   -
455   -static void __exit microcode_intel_module_exit(void)
456   -{
457   - microcode_exit();
458   -}
459   -
460   -module_init(microcode_intel_module_init)
461   -module_exit(microcode_intel_module_exit)
include/asm-x86/microcode.h
1 1 #ifndef ASM_X86__MICROCODE_H
2 2 #define ASM_X86__MICROCODE_H
3 3  
4   -extern int microcode_init(void *opaque, struct module *module);
5   -extern void microcode_exit(void);
  4 +struct cpu_signature {
  5 + unsigned int sig;
  6 + unsigned int pf;
  7 + unsigned int rev;
  8 +};
6 9  
7   -struct cpu_signature;
8 10 struct device;
9 11  
10 12 struct microcode_ops {
11 13  
12 14  
... ... @@ -17,83 +19,30 @@
17 19 void (*microcode_fini_cpu) (int cpu);
18 20 };
19 21  
20   -struct microcode_header_intel {
21   - unsigned int hdrver;
22   - unsigned int rev;
23   - unsigned int date;
24   - unsigned int sig;
25   - unsigned int cksum;
26   - unsigned int ldrver;
27   - unsigned int pf;
28   - unsigned int datasize;
29   - unsigned int totalsize;
30   - unsigned int reserved[3];
31   -};
32   -
33   -struct microcode_intel {
34   - struct microcode_header_intel hdr;
35   - unsigned int bits[0];
36   -};
37   -
38   -/* microcode format is extended from prescott processors */
39   -struct extended_signature {
40   - unsigned int sig;
41   - unsigned int pf;
42   - unsigned int cksum;
43   -};
44   -
45   -struct extended_sigtable {
46   - unsigned int count;
47   - unsigned int cksum;
48   - unsigned int reserved[3];
49   - struct extended_signature sigs[0];
50   -};
51   -
52   -struct equiv_cpu_entry {
53   - unsigned int installed_cpu;
54   - unsigned int fixed_errata_mask;
55   - unsigned int fixed_errata_compare;
56   - unsigned int equiv_cpu;
57   -};
58   -
59   -struct microcode_header_amd {
60   - unsigned int data_code;
61   - unsigned int patch_id;
62   - unsigned char mc_patch_data_id[2];
63   - unsigned char mc_patch_data_len;
64   - unsigned char init_flag;
65   - unsigned int mc_patch_data_checksum;
66   - unsigned int nb_dev_id;
67   - unsigned int sb_dev_id;
68   - unsigned char processor_rev_id[2];
69   - unsigned char nb_rev_id;
70   - unsigned char sb_rev_id;
71   - unsigned char bios_api_rev;
72   - unsigned char reserved1[3];
73   - unsigned int match_reg[8];
74   -};
75   -
76   -struct microcode_amd {
77   - struct microcode_header_amd hdr;
78   - unsigned int mpb[0];
79   -};
80   -
81   -struct cpu_signature {
82   - unsigned int sig;
83   - unsigned int pf;
84   - unsigned int rev;
85   -};
86   -
87 22 struct ucode_cpu_info {
88 23 struct cpu_signature cpu_sig;
89 24 int valid;
90   - union {
91   - struct microcode_intel *mc_intel;
92   - struct microcode_amd *mc_amd;
93   - void *valid_mc;
94   - } mc;
  25 + void *mc;
95 26 };
96 27 extern struct ucode_cpu_info ucode_cpu_info[];
  28 +
  29 +#ifdef CONFIG_MICROCODE_INTEL
  30 +extern struct microcode_ops * __init init_intel_microcode(void);
  31 +#else
  32 +static inline struct microcode_ops * __init init_intel_microcode(void)
  33 +{
  34 + return NULL;
  35 +}
  36 +#endif /* CONFIG_MICROCODE_INTEL */
  37 +
  38 +#ifdef CONFIG_MICROCODE_AMD
  39 +extern struct microcode_ops * __init init_amd_microcode(void);
  40 +#else
  41 +static inline struct microcode_ops * __init init_amd_microcode(void)
  42 +{
  43 + return NULL;
  44 +}
  45 +#endif
97 46  
98 47 #endif /* ASM_X86__MICROCODE_H */