aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS5
-rw-r--r--arch/x86/Kconfig46
-rw-r--r--arch/x86/kernel/Makefile2
-rw-r--r--arch/x86/kernel/microcode.c480
-rw-r--r--arch/x86/kernel/microcode_amd.c520
-rw-r--r--arch/x86/kernel/microcode_intel.c545
-rw-r--r--include/asm-x86/microcode.h87
-rw-r--r--include/asm-x86/processor.h35
8 files changed, 1245 insertions, 475 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index deedc0d827b5..4bfa468ceae2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -384,6 +384,11 @@ M: joerg.roedel@amd.com
384L: iommu@lists.linux-foundation.org 384L: iommu@lists.linux-foundation.org
385S: Supported 385S: Supported
386 386
387AMD MICROCODE UPDATE SUPPORT
388P: Peter Oruba
389M: peter.oruba@amd.com
390S: Supported
391
387AMS (Apple Motion Sensor) DRIVER 392AMS (Apple Motion Sensor) DRIVER
388P: Stelian Pop 393P: Stelian Pop
389M: stelian@popies.net 394M: stelian@popies.net
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 3d0f2b6a5a16..0e5bf1eddcea 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -783,23 +783,51 @@ config X86_REBOOTFIXUPS
783 Say N otherwise. 783 Say N otherwise.
784 784
785config MICROCODE 785config MICROCODE
786 tristate "/dev/cpu/microcode - Intel IA32 CPU microcode support" 786 tristate "/dev/cpu/microcode - microcode support"
787 select FW_LOADER 787 select FW_LOADER
788 ---help--- 788 ---help---
789 If you say Y here, you will be able to update the microcode on 789 If you say Y here, you will be able to update the microcode on
790 Intel processors in the IA32 family, e.g. Pentium Pro, Pentium II, 790 certain Intel and AMD processors. The Intel support is for the
791 Pentium III, Pentium 4, Xeon etc. You will obviously need the 791 IA32 family, e.g. Pentium Pro, Pentium II, Pentium III,
792 actual microcode binary data itself which is not shipped with the 792 Pentium 4, Xeon etc. The AMD support is for family 0x10 and
793 Linux kernel. 793 0x11 processors, e.g. Opteron, Phenom and Turion 64 Ultra.
794 You will obviously need the actual microcode binary data itself
795 which is not shipped with the Linux kernel.
794 796
795 For latest news and information on obtaining all the required 797 This option selects the general module only, you need to select
796 ingredients for this driver, check: 798 at least one vendor specific module as well.
797 <http://www.urbanmyth.org/microcode/>.
798 799
799 To compile this driver as a module, choose M here: the 800 To compile this driver as a module, choose M here: the
800 module will be called microcode. 801 module will be called microcode.
801 802
802config MICROCODE_OLD_INTERFACE 803config MICROCODE_INTEL
804 tristate "Intel microcode patch loading support"
805 depends on MICROCODE
806 default MICROCODE
807 select FW_LOADER
808 --help---
809 This options enables microcode patch loading support for Intel
810 processors.
811
812 For latest news and information on obtaining all the required
813 Intel ingredients for this driver, check:
814 <http://www.urbanmyth.org/microcode/>.
815
816 This driver is only available as a module: the module
817 will be called microcode_intel.
818
819config MICROCODE_AMD
820 tristate "AMD microcode patch loading support"
821 depends on MICROCODE
822 select FW_LOADER
823 --help---
824 If you select this option, microcode patch loading support for AMD
825 processors will be enabled.
826
827 This driver is only available as a module: the module
828 will be called microcode_amd.
829
830 config MICROCODE_OLD_INTERFACE
803 def_bool y 831 def_bool y
804 depends on MICROCODE 832 depends on MICROCODE
805 833
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 3db651fc8ec5..be454f348c3b 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -52,6 +52,8 @@ obj-$(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) += microcode.o 54obj-$(CONFIG_MICROCODE) += microcode.o
55obj-$(CONFIG_MICROCODE_INTEL) += microcode_intel.o
56obj-$(CONFIG_MICROCODE_AMD) += microcode_amd.o
55obj-$(CONFIG_PCI) += early-quirks.o 57obj-$(CONFIG_PCI) += early-quirks.o
56apm-y := apm_32.o 58apm-y := apm_32.o
57obj-$(CONFIG_APM) += apm.o 59obj-$(CONFIG_APM) += apm.o
diff --git a/arch/x86/kernel/microcode.c b/arch/x86/kernel/microcode.c
index 652fa5c38ebe..28dba1a6e4aa 100644
--- a/arch/x86/kernel/microcode.c
+++ b/arch/x86/kernel/microcode.c
@@ -93,293 +93,28 @@
93#include <asm/msr.h> 93#include <asm/msr.h>
94#include <asm/uaccess.h> 94#include <asm/uaccess.h>
95#include <asm/processor.h> 95#include <asm/processor.h>
96#include <asm/microcode.h>
96 97
97MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver"); 98MODULE_DESCRIPTION("Microcode Update Driver");
98MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>"); 99MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
99MODULE_LICENSE("GPL"); 100MODULE_LICENSE("GPL");
100 101
101#define MICROCODE_VERSION "1.14a" 102#define MICROCODE_VERSION "2.00"
102 103
103#define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ 104struct microcode_ops *microcode_ops;
104#define MC_HEADER_SIZE (sizeof (microcode_header_t)) /* 48 bytes */
105#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */
106#define EXT_HEADER_SIZE (sizeof (struct extended_sigtable)) /* 20 bytes */
107#define EXT_SIGNATURE_SIZE (sizeof (struct extended_signature)) /* 12 bytes */
108#define DWSIZE (sizeof (u32))
109#define get_totalsize(mc) \
110 (((microcode_t *)mc)->hdr.totalsize ? \
111 ((microcode_t *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE)
112#define get_datasize(mc) \
113 (((microcode_t *)mc)->hdr.datasize ? \
114 ((microcode_t *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE)
115
116#define sigmatch(s1, s2, p1, p2) \
117 (((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0))))
118
119#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
120
121/* serialize access to the physical write to MSR 0x79 */
122static DEFINE_SPINLOCK(microcode_update_lock);
123 105
124/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ 106/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
125static DEFINE_MUTEX(microcode_mutex); 107DEFINE_MUTEX(microcode_mutex);
126 108EXPORT_SYMBOL_GPL(microcode_mutex);
127static struct ucode_cpu_info {
128 int valid;
129 unsigned int sig;
130 unsigned int pf;
131 unsigned int rev;
132 microcode_t *mc;
133} ucode_cpu_info[NR_CPUS];
134
135static void collect_cpu_info(int cpu_num)
136{
137 struct cpuinfo_x86 *c = &cpu_data(cpu_num);
138 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
139 unsigned int val[2];
140
141 /* We should bind the task to the CPU */
142 BUG_ON(raw_smp_processor_id() != cpu_num);
143 uci->pf = uci->rev = 0;
144 uci->mc = NULL;
145 uci->valid = 1;
146
147 if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
148 cpu_has(c, X86_FEATURE_IA64)) {
149 printk(KERN_ERR "microcode: CPU%d not a capable Intel "
150 "processor\n", cpu_num);
151 uci->valid = 0;
152 return;
153 }
154
155 uci->sig = cpuid_eax(0x00000001);
156
157 if ((c->x86_model >= 5) || (c->x86 > 6)) {
158 /* get processor flags from MSR 0x17 */
159 rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
160 uci->pf = 1 << ((val[1] >> 18) & 7);
161 }
162
163 wrmsr(MSR_IA32_UCODE_REV, 0, 0);
164 /* see notes above for revision 1.07. Apparent chip bug */
165 sync_core();
166 /* get the current revision from MSR 0x8B */
167 rdmsr(MSR_IA32_UCODE_REV, val[0], uci->rev);
168 pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n",
169 uci->sig, uci->pf, uci->rev);
170}
171
172static inline int microcode_update_match(int cpu_num,
173 microcode_header_t *mc_header, int sig, int pf)
174{
175 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
176
177 if (!sigmatch(sig, uci->sig, pf, uci->pf)
178 || mc_header->rev <= uci->rev)
179 return 0;
180 return 1;
181}
182
183static int microcode_sanity_check(void *mc)
184{
185 microcode_header_t *mc_header = mc;
186 struct extended_sigtable *ext_header = NULL;
187 struct extended_signature *ext_sig;
188 unsigned long total_size, data_size, ext_table_size;
189 int sum, orig_sum, ext_sigcount = 0, i;
190
191 total_size = get_totalsize(mc_header);
192 data_size = get_datasize(mc_header);
193 if (data_size + MC_HEADER_SIZE > total_size) {
194 printk(KERN_ERR "microcode: error! "
195 "Bad data size in microcode data file\n");
196 return -EINVAL;
197 }
198
199 if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
200 printk(KERN_ERR "microcode: error! "
201 "Unknown microcode update format\n");
202 return -EINVAL;
203 }
204 ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
205 if (ext_table_size) {
206 if ((ext_table_size < EXT_HEADER_SIZE)
207 || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
208 printk(KERN_ERR "microcode: error! "
209 "Small exttable size in microcode data file\n");
210 return -EINVAL;
211 }
212 ext_header = mc + MC_HEADER_SIZE + data_size;
213 if (ext_table_size != exttable_size(ext_header)) {
214 printk(KERN_ERR "microcode: error! "
215 "Bad exttable size in microcode data file\n");
216 return -EFAULT;
217 }
218 ext_sigcount = ext_header->count;
219 }
220
221 /* check extended table checksum */
222 if (ext_table_size) {
223 int ext_table_sum = 0;
224 int *ext_tablep = (int *)ext_header;
225
226 i = ext_table_size / DWSIZE;
227 while (i--)
228 ext_table_sum += ext_tablep[i];
229 if (ext_table_sum) {
230 printk(KERN_WARNING "microcode: aborting, "
231 "bad extended signature table checksum\n");
232 return -EINVAL;
233 }
234 }
235
236 /* calculate the checksum */
237 orig_sum = 0;
238 i = (MC_HEADER_SIZE + data_size) / DWSIZE;
239 while (i--)
240 orig_sum += ((int *)mc)[i];
241 if (orig_sum) {
242 printk(KERN_ERR "microcode: aborting, bad checksum\n");
243 return -EINVAL;
244 }
245 if (!ext_table_size)
246 return 0;
247 /* check extended signature checksum */
248 for (i = 0; i < ext_sigcount; i++) {
249 ext_sig = (void *)ext_header + EXT_HEADER_SIZE +
250 EXT_SIGNATURE_SIZE * i;
251 sum = orig_sum
252 - (mc_header->sig + mc_header->pf + mc_header->cksum)
253 + (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
254 if (sum) {
255 printk(KERN_ERR "microcode: aborting, bad checksum\n");
256 return -EINVAL;
257 }
258 }
259 return 0;
260}
261
262/*
263 * return 0 - no update found
264 * return 1 - found update
265 * return < 0 - error
266 */
267static int get_maching_microcode(void *mc, int cpu)
268{
269 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
270 microcode_header_t *mc_header = mc;
271 struct extended_sigtable *ext_header;
272 unsigned long total_size = get_totalsize(mc_header);
273 int ext_sigcount, i;
274 struct extended_signature *ext_sig;
275 void *new_mc;
276
277 if (microcode_update_match(cpu, mc_header,
278 mc_header->sig, mc_header->pf))
279 goto find;
280
281 if (total_size <= get_datasize(mc_header) + MC_HEADER_SIZE)
282 return 0;
283
284 ext_header = mc + get_datasize(mc_header) + MC_HEADER_SIZE;
285 ext_sigcount = ext_header->count;
286 ext_sig = (void *)ext_header + EXT_HEADER_SIZE;
287 for (i = 0; i < ext_sigcount; i++) {
288 if (microcode_update_match(cpu, mc_header,
289 ext_sig->sig, ext_sig->pf))
290 goto find;
291 ext_sig++;
292 }
293 return 0;
294find:
295 pr_debug("microcode: CPU%d found a matching microcode update with"
296 " version 0x%x (current=0x%x)\n", cpu, mc_header->rev,uci->rev);
297 new_mc = vmalloc(total_size);
298 if (!new_mc) {
299 printk(KERN_ERR "microcode: error! Can not allocate memory\n");
300 return -ENOMEM;
301 }
302
303 /* free previous update file */
304 vfree(uci->mc);
305
306 memcpy(new_mc, mc, total_size);
307 uci->mc = new_mc;
308 return 1;
309}
310 109
311static void apply_microcode(int cpu) 110struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
312{ 111EXPORT_SYMBOL_GPL(ucode_cpu_info);
313 unsigned long flags;
314 unsigned int val[2];
315 int cpu_num = raw_smp_processor_id();
316 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
317
318 /* We should bind the task to the CPU */
319 BUG_ON(cpu_num != cpu);
320
321 if (uci->mc == NULL)
322 return;
323
324 /* serialize access to the physical write to MSR 0x79 */
325 spin_lock_irqsave(&microcode_update_lock, flags);
326
327 /* write microcode via MSR 0x79 */
328 wrmsr(MSR_IA32_UCODE_WRITE,
329 (unsigned long) uci->mc->bits,
330 (unsigned long) uci->mc->bits >> 16 >> 16);
331 wrmsr(MSR_IA32_UCODE_REV, 0, 0);
332
333 /* see notes above for revision 1.07. Apparent chip bug */
334 sync_core();
335
336 /* get the current revision from MSR 0x8B */
337 rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
338
339 spin_unlock_irqrestore(&microcode_update_lock, flags);
340 if (val[1] != uci->mc->hdr.rev) {
341 printk(KERN_ERR "microcode: CPU%d update from revision "
342 "0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]);
343 return;
344 }
345 printk(KERN_INFO "microcode: CPU%d updated from revision "
346 "0x%x to 0x%x, date = %08x \n",
347 cpu_num, uci->rev, val[1], uci->mc->hdr.date);
348 uci->rev = val[1];
349}
350 112
351#ifdef CONFIG_MICROCODE_OLD_INTERFACE 113#ifdef CONFIG_MICROCODE_OLD_INTERFACE
352static void __user *user_buffer; /* user area microcode data buffer */ 114void __user *user_buffer; /* user area microcode data buffer */
353static unsigned int user_buffer_size; /* it's size */ 115EXPORT_SYMBOL_GPL(user_buffer);
354 116unsigned int user_buffer_size; /* it's size */
355static long get_next_ucode(void **mc, long offset) 117EXPORT_SYMBOL_GPL(user_buffer_size);
356{
357 microcode_header_t mc_header;
358 unsigned long total_size;
359
360 /* No more data */
361 if (offset >= user_buffer_size)
362 return 0;
363 if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) {
364 printk(KERN_ERR "microcode: error! Can not read user data\n");
365 return -EFAULT;
366 }
367 total_size = get_totalsize(&mc_header);
368 if (offset + total_size > user_buffer_size) {
369 printk(KERN_ERR "microcode: error! Bad total size in microcode "
370 "data file\n");
371 return -EINVAL;
372 }
373 *mc = vmalloc(total_size);
374 if (!*mc)
375 return -ENOMEM;
376 if (copy_from_user(*mc, user_buffer + offset, total_size)) {
377 printk(KERN_ERR "microcode: error! Can not read user data\n");
378 vfree(*mc);
379 return -EFAULT;
380 }
381 return offset + total_size;
382}
383 118
384static int do_microcode_update (void) 119static int do_microcode_update (void)
385{ 120{
@@ -391,8 +126,8 @@ static int do_microcode_update (void)
391 126
392 old = current->cpus_allowed; 127 old = current->cpus_allowed;
393 128
394 while ((cursor = get_next_ucode(&new_mc, cursor)) > 0) { 129 while ((cursor = microcode_ops->get_next_ucode(&new_mc, cursor)) > 0) {
395 error = microcode_sanity_check(new_mc); 130 error = microcode_ops->microcode_sanity_check(new_mc);
396 if (error) 131 if (error)
397 goto out; 132 goto out;
398 /* 133 /*
@@ -405,11 +140,12 @@ static int do_microcode_update (void)
405 if (!uci->valid) 140 if (!uci->valid)
406 continue; 141 continue;
407 set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); 142 set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
408 error = get_maching_microcode(new_mc, cpu); 143 error = microcode_ops->get_matching_microcode(new_mc,
144 cpu);
409 if (error < 0) 145 if (error < 0)
410 goto out; 146 goto out;
411 if (error == 1) 147 if (error == 1)
412 apply_microcode(cpu); 148 microcode_ops->apply_microcode(cpu);
413 } 149 }
414 vfree(new_mc); 150 vfree(new_mc);
415 } 151 }
@@ -491,131 +227,9 @@ MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
491#define microcode_dev_exit() do { } while(0) 227#define microcode_dev_exit() do { } while(0)
492#endif 228#endif
493 229
494static long get_next_ucode_from_buffer(void **mc, const u8 *buf,
495 unsigned long size, long offset)
496{
497 microcode_header_t *mc_header;
498 unsigned long total_size;
499
500 /* No more data */
501 if (offset >= size)
502 return 0;
503 mc_header = (microcode_header_t *)(buf + offset);
504 total_size = get_totalsize(mc_header);
505
506 if (offset + total_size > size) {
507 printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
508 return -EINVAL;
509 }
510
511 *mc = vmalloc(total_size);
512 if (!*mc) {
513 printk(KERN_ERR "microcode: error! Can not allocate memory\n");
514 return -ENOMEM;
515 }
516 memcpy(*mc, buf + offset, total_size);
517 return offset + total_size;
518}
519
520/* fake device for request_firmware */ 230/* fake device for request_firmware */
521static struct platform_device *microcode_pdev; 231struct platform_device *microcode_pdev;
522 232EXPORT_SYMBOL_GPL(microcode_pdev);
523static int cpu_request_microcode(int cpu)
524{
525 char name[30];
526 struct cpuinfo_x86 *c = &cpu_data(cpu);
527 const struct firmware *firmware;
528 const u8 *buf;
529 unsigned long size;
530 long offset = 0;
531 int error;
532 void *mc;
533
534 /* We should bind the task to the CPU */
535 BUG_ON(cpu != raw_smp_processor_id());
536 sprintf(name,"intel-ucode/%02x-%02x-%02x",
537 c->x86, c->x86_model, c->x86_mask);
538 error = request_firmware(&firmware, name, &microcode_pdev->dev);
539 if (error) {
540 pr_debug("microcode: data file %s load failed\n", name);
541 return error;
542 }
543 buf = firmware->data;
544 size = firmware->size;
545 while ((offset = get_next_ucode_from_buffer(&mc, buf, size, offset))
546 > 0) {
547 error = microcode_sanity_check(mc);
548 if (error)
549 break;
550 error = get_maching_microcode(mc, cpu);
551 if (error < 0)
552 break;
553 /*
554 * It's possible the data file has multiple matching ucode,
555 * lets keep searching till the latest version
556 */
557 if (error == 1) {
558 apply_microcode(cpu);
559 error = 0;
560 }
561 vfree(mc);
562 }
563 if (offset > 0)
564 vfree(mc);
565 if (offset < 0)
566 error = offset;
567 release_firmware(firmware);
568
569 return error;
570}
571
572static int apply_microcode_check_cpu(int cpu)
573{
574 struct cpuinfo_x86 *c = &cpu_data(cpu);
575 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
576 cpumask_t old;
577 unsigned int val[2];
578 int err = 0;
579
580 /* Check if the microcode is available */
581 if (!uci->mc)
582 return 0;
583
584 old = current->cpus_allowed;
585 set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
586
587 /* Check if the microcode we have in memory matches the CPU */
588 if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
589 cpu_has(c, X86_FEATURE_IA64) || uci->sig != cpuid_eax(0x00000001))
590 err = -EINVAL;
591
592 if (!err && ((c->x86_model >= 5) || (c->x86 > 6))) {
593 /* get processor flags from MSR 0x17 */
594 rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
595 if (uci->pf != (1 << ((val[1] >> 18) & 7)))
596 err = -EINVAL;
597 }
598
599 if (!err) {
600 wrmsr(MSR_IA32_UCODE_REV, 0, 0);
601 /* see notes above for revision 1.07. Apparent chip bug */
602 sync_core();
603 /* get the current revision from MSR 0x8B */
604 rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
605 if (uci->rev != val[1])
606 err = -EINVAL;
607 }
608
609 if (!err)
610 apply_microcode(cpu);
611 else
612 printk(KERN_ERR "microcode: Could not apply microcode to CPU%d:"
613 " sig=0x%x, pf=0x%x, rev=0x%x\n",
614 cpu, uci->sig, uci->pf, uci->rev);
615
616 set_cpus_allowed_ptr(current, &old);
617 return err;
618}
619 233
620static void microcode_init_cpu(int cpu, int resume) 234static void microcode_init_cpu(int cpu, int resume)
621{ 235{
@@ -626,24 +240,13 @@ static void microcode_init_cpu(int cpu, int resume)
626 240
627 set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu)); 241 set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
628 mutex_lock(&microcode_mutex); 242 mutex_lock(&microcode_mutex);
629 collect_cpu_info(cpu); 243 microcode_ops->collect_cpu_info(cpu);
630 if (uci->valid && system_state == SYSTEM_RUNNING && !resume) 244 if (uci->valid && system_state == SYSTEM_RUNNING && !resume)
631 cpu_request_microcode(cpu); 245 microcode_ops->cpu_request_microcode(cpu);
632 mutex_unlock(&microcode_mutex); 246 mutex_unlock(&microcode_mutex);
633 set_cpus_allowed_ptr(current, &old); 247 set_cpus_allowed_ptr(current, &old);
634} 248}
635 249
636static void microcode_fini_cpu(int cpu)
637{
638 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
639
640 mutex_lock(&microcode_mutex);
641 uci->valid = 0;
642 vfree(uci->mc);
643 uci->mc = NULL;
644 mutex_unlock(&microcode_mutex);
645}
646
647static ssize_t reload_store(struct sys_device *dev, 250static ssize_t reload_store(struct sys_device *dev,
648 struct sysdev_attribute *attr, 251 struct sysdev_attribute *attr,
649 const char *buf, size_t sz) 252 const char *buf, size_t sz)
@@ -664,7 +267,7 @@ static ssize_t reload_store(struct sys_device *dev,
664 267
665 mutex_lock(&microcode_mutex); 268 mutex_lock(&microcode_mutex);
666 if (uci->valid) 269 if (uci->valid)
667 err = cpu_request_microcode(cpu); 270 err = microcode_ops->cpu_request_microcode(cpu);
668 mutex_unlock(&microcode_mutex); 271 mutex_unlock(&microcode_mutex);
669 put_online_cpus(); 272 put_online_cpus();
670 set_cpus_allowed_ptr(current, &old); 273 set_cpus_allowed_ptr(current, &old);
@@ -739,7 +342,7 @@ static int mc_sysdev_remove(struct sys_device *sys_dev)
739 return 0; 342 return 0;
740 343
741 pr_debug("microcode: CPU%d removed\n", cpu); 344 pr_debug("microcode: CPU%d removed\n", cpu);
742 microcode_fini_cpu(cpu); 345 microcode_ops->microcode_fini_cpu(cpu);
743 sysfs_remove_group(&sys_dev->kobj, &mc_attr_group); 346 sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
744 return 0; 347 return 0;
745} 348}
@@ -752,7 +355,7 @@ static int mc_sysdev_resume(struct sys_device *dev)
752 return 0; 355 return 0;
753 pr_debug("microcode: CPU%d resumed\n", cpu); 356 pr_debug("microcode: CPU%d resumed\n", cpu);
754 /* only CPU 0 will apply ucode here */ 357 /* only CPU 0 will apply ucode here */
755 apply_microcode(0); 358 microcode_ops->apply_microcode(0);
756 return 0; 359 return 0;
757} 360}
758 361
@@ -772,7 +375,7 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
772 switch (action) { 375 switch (action) {
773 case CPU_UP_CANCELED_FROZEN: 376 case CPU_UP_CANCELED_FROZEN:
774 /* The CPU refused to come up during a system resume */ 377 /* The CPU refused to come up during a system resume */
775 microcode_fini_cpu(cpu); 378 microcode_ops->microcode_fini_cpu(cpu);
776 break; 379 break;
777 case CPU_ONLINE: 380 case CPU_ONLINE:
778 case CPU_DOWN_FAILED: 381 case CPU_DOWN_FAILED:
@@ -780,9 +383,9 @@ mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
780 break; 383 break;
781 case CPU_ONLINE_FROZEN: 384 case CPU_ONLINE_FROZEN:
782 /* System-wide resume is in progress, try to apply microcode */ 385 /* System-wide resume is in progress, try to apply microcode */
783 if (apply_microcode_check_cpu(cpu)) { 386 if (microcode_ops->apply_microcode_check_cpu(cpu)) {
784 /* The application of microcode failed */ 387 /* The application of microcode failed */
785 microcode_fini_cpu(cpu); 388 microcode_ops->microcode_fini_cpu(cpu);
786 __mc_sysdev_add(sys_dev, 1); 389 __mc_sysdev_add(sys_dev, 1);
787 break; 390 break;
788 } 391 }
@@ -806,12 +409,17 @@ static struct notifier_block __refdata mc_cpu_notifier = {
806 .notifier_call = mc_cpu_callback, 409 .notifier_call = mc_cpu_callback,
807}; 410};
808 411
809static int __init microcode_init (void) 412int microcode_init(void *opaque, struct module *module)
810{ 413{
414 struct microcode_ops *ops = (struct microcode_ops *)opaque;
811 int error; 415 int error;
812 416
813 printk(KERN_INFO 417 if (microcode_ops) {
814 "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@aivazian.fsnet.co.uk>\n"); 418 printk(KERN_ERR "microcode: already loaded the other module\n");
419 return -EEXIST;
420 }
421
422 microcode_ops = ops;
815 423
816 error = microcode_dev_init(); 424 error = microcode_dev_init();
817 if (error) 425 if (error)
@@ -833,10 +441,17 @@ static int __init microcode_init (void)
833 } 441 }
834 442
835 register_hotcpu_notifier(&mc_cpu_notifier); 443 register_hotcpu_notifier(&mc_cpu_notifier);
444
445 printk(KERN_INFO
446 "Microcode Update Driver: v" MICROCODE_VERSION
447 " <tigran@aivazian.fsnet.co.uk>"
448 " <peter.oruba@amd.com>\n");
449
836 return 0; 450 return 0;
837} 451}
452EXPORT_SYMBOL_GPL(microcode_init);
838 453
839static void __exit microcode_exit (void) 454void __exit microcode_exit (void)
840{ 455{
841 microcode_dev_exit(); 456 microcode_dev_exit();
842 457
@@ -847,7 +462,10 @@ static void __exit microcode_exit (void)
847 put_online_cpus(); 462 put_online_cpus();
848 463
849 platform_device_unregister(microcode_pdev); 464 platform_device_unregister(microcode_pdev);
850}
851 465
852module_init(microcode_init) 466 microcode_ops = NULL;
853module_exit(microcode_exit) 467
468 printk(KERN_INFO
469 "Microcode Update Driver: v" MICROCODE_VERSION " removed.\n");
470}
471EXPORT_SYMBOL_GPL(microcode_exit);
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
new file mode 100644
index 000000000000..07e52beacb44
--- /dev/null
+++ b/arch/x86/kernel/microcode_amd.c
@@ -0,0 +1,520 @@
1/*
2 * AMD CPU Microcode Update Driver for Linux
3 * Copyright (C) 2008 Advanced Micro Devices Inc.
4 *
5 * Author: Peter Oruba <peter.oruba@amd.com>
6 *
7 * Based on work by:
8 * Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
9 *
10 * This driver allows to upgrade microcode on AMD
11 * family 0x10 and 0x11 processors.
12 *
13 * Licensed unter the terms of the GNU General Public
14 * License version 2. See file COPYING for details.
15*/
16
17#include <linux/capability.h>
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/sched.h>
21#include <linux/cpumask.h>
22#include <linux/module.h>
23#include <linux/slab.h>
24#include <linux/vmalloc.h>
25#include <linux/miscdevice.h>
26#include <linux/spinlock.h>
27#include <linux/mm.h>
28#include <linux/fs.h>
29#include <linux/mutex.h>
30#include <linux/cpu.h>
31#include <linux/firmware.h>
32#include <linux/platform_device.h>
33#include <linux/pci.h>
34#include <linux/pci_ids.h>
35
36#include <asm/msr.h>
37#include <asm/uaccess.h>
38#include <asm/processor.h>
39#include <asm/microcode.h>
40
41MODULE_DESCRIPTION("AMD Microcode Update Driver");
42MODULE_AUTHOR("Peter Oruba <peter.oruba@amd.com>");
43MODULE_LICENSE("GPL v2");
44
45#define UCODE_MAGIC 0x00414d44
46#define UCODE_EQUIV_CPU_TABLE_TYPE 0x00000000
47#define UCODE_UCODE_TYPE 0x00000001
48
49#define UCODE_MAX_SIZE (2048)
50#define DEFAULT_UCODE_DATASIZE (896) /* 896 bytes */
51#define MC_HEADER_SIZE (sizeof(struct microcode_header_amd)) /* 64 bytes */
52#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 960 bytes */
53#define DWSIZE (sizeof(u32))
54/* For now we support a fixed ucode total size only */
55#define get_totalsize(mc) \
56 ((((struct microcode_amd *)mc)->hdr.mc_patch_data_len * 28) \
57 + MC_HEADER_SIZE)
58
59extern int microcode_init(void *opaque, struct module *module);
60extern void microcode_exit(void);
61
62/* serialize access to the physical write */
63static DEFINE_SPINLOCK(microcode_update_lock);
64
65/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
66extern struct mutex (microcode_mutex);
67
68struct equiv_cpu_entry *equiv_cpu_table;
69
70extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
71
72static void collect_cpu_info_amd(int cpu)
73{
74 struct cpuinfo_x86 *c = &cpu_data(cpu);
75 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
76
77 /* We should bind the task to the CPU */
78 BUG_ON(raw_smp_processor_id() != cpu);
79 uci->rev = 0;
80 uci->pf = 0;
81 uci->mc.mc_amd = NULL;
82 uci->valid = 1;
83
84 if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) {
85 printk(KERN_ERR "microcode: CPU%d not a capable AMD processor\n",
86 cpu);
87 uci->valid = 0;
88 return;
89 }
90
91 asm volatile("movl %1, %%ecx; rdmsr"
92 : "=a" (uci->rev)
93 : "i" (0x0000008B) : "ecx");
94
95 printk(KERN_INFO "microcode: collect_cpu_info_amd : patch_id=0x%x\n",
96 uci->rev);
97}
98
99static int get_matching_microcode_amd(void *mc, int cpu)
100{
101 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
102 struct microcode_header_amd *mc_header = mc;
103 unsigned long total_size = get_totalsize(mc_header);
104 void *new_mc;
105 struct pci_dev *nb_pci_dev, *sb_pci_dev;
106 unsigned int current_cpu_id;
107 unsigned int equiv_cpu_id = 0x00;
108 unsigned int i = 0;
109
110 /* We should bind the task to the CPU */
111 BUG_ON(cpu != raw_smp_processor_id());
112
113 /* This is a tricky part. We might be called from a write operation */
114 /* to the device file instead of the usual process of firmware */
115 /* loading. This routine needs to be able to distinguish both */
116/* cases. This is done by checking if there alread is a equivalent */
117 /* CPU table installed. If not, we're written through */
118 /* /dev/cpu/microcode. */
119/* Since we ignore all checks. The error case in which going through */
120/* firmware loading and that table is not loaded has already been */
121 /* checked earlier. */
122 if (equiv_cpu_table == NULL) {
123 printk(KERN_INFO "microcode: CPU%d microcode update with "
124 "version 0x%x (current=0x%x)\n",
125 cpu, mc_header->patch_id, uci->rev);
126 goto out;
127 }
128
129 current_cpu_id = cpuid_eax(0x00000001);
130
131 while (equiv_cpu_table[i].installed_cpu != 0) {
132 if (current_cpu_id == equiv_cpu_table[i].installed_cpu) {
133 equiv_cpu_id = equiv_cpu_table[i].equiv_cpu;
134 break;
135 }
136 i++;
137 }
138
139 if (!equiv_cpu_id) {
140 printk(KERN_ERR "microcode: CPU%d cpu_id "
141 "not found in equivalent cpu table \n", cpu);
142 return 0;
143 }
144
145 if ((mc_header->processor_rev_id[0]) != (equiv_cpu_id & 0xff)) {
146 printk(KERN_ERR
147 "microcode: CPU%d patch does not match "
148 "(patch is %x, cpu extended is %x) \n",
149 cpu, mc_header->processor_rev_id[0],
150 (equiv_cpu_id & 0xff));
151 return 0;
152 }
153
154 if ((mc_header->processor_rev_id[1]) != ((equiv_cpu_id >> 16) & 0xff)) {
155 printk(KERN_ERR "microcode: CPU%d patch does not match "
156 "(patch is %x, cpu base id is %x) \n",
157 cpu, mc_header->processor_rev_id[1],
158 ((equiv_cpu_id >> 16) & 0xff));
159
160 return 0;
161 }
162
163 /* ucode may be northbridge specific */
164 if (mc_header->nb_dev_id) {
165 nb_pci_dev = pci_get_device(PCI_VENDOR_ID_AMD,
166 (mc_header->nb_dev_id & 0xff),
167 NULL);
168 if ((!nb_pci_dev) ||
169 (mc_header->nb_rev_id != nb_pci_dev->revision)) {
170 printk(KERN_ERR "microcode: CPU%d NB mismatch \n", cpu);
171 pci_dev_put(nb_pci_dev);
172 return 0;
173 }
174 pci_dev_put(nb_pci_dev);
175 }
176
177 /* ucode may be southbridge specific */
178 if (mc_header->sb_dev_id) {
179 sb_pci_dev = pci_get_device(PCI_VENDOR_ID_AMD,
180 (mc_header->sb_dev_id & 0xff),
181 NULL);
182 if ((!sb_pci_dev) ||
183 (mc_header->sb_rev_id != sb_pci_dev->revision)) {
184 printk(KERN_ERR "microcode: CPU%d SB mismatch \n", cpu);
185 pci_dev_put(sb_pci_dev);
186 return 0;
187 }
188 pci_dev_put(sb_pci_dev);
189 }
190
191 if (mc_header->patch_id <= uci->rev)
192 return 0;
193
194 printk(KERN_INFO "microcode: CPU%d found a matching microcode "
195 "update with version 0x%x (current=0x%x)\n",
196 cpu, mc_header->patch_id, uci->rev);
197
198out:
199 new_mc = vmalloc(UCODE_MAX_SIZE);
200 if (!new_mc) {
201 printk(KERN_ERR "microcode: error, can't allocate memory\n");
202 return -ENOMEM;
203 }
204 memset(new_mc, 0, UCODE_MAX_SIZE);
205
206 /* free previous update file */
207 vfree(uci->mc.mc_amd);
208
209 memcpy(new_mc, mc, total_size);
210
211 uci->mc.mc_amd = new_mc;
212 return 1;
213}
214
215static void apply_microcode_amd(int cpu)
216{
217 unsigned long flags;
218 unsigned int eax, edx;
219 unsigned int rev;
220 int cpu_num = raw_smp_processor_id();
221 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
222
223 /* We should bind the task to the CPU */
224 BUG_ON(cpu_num != cpu);
225
226 if (uci->mc.mc_amd == NULL)
227 return;
228
229 spin_lock_irqsave(&microcode_update_lock, flags);
230
231 edx = (unsigned int)(((unsigned long)
232 &(uci->mc.mc_amd->hdr.data_code)) >> 32);
233 eax = (unsigned int)(((unsigned long)
234 &(uci->mc.mc_amd->hdr.data_code)) & 0xffffffffL);
235
236 asm volatile("movl %0, %%ecx; wrmsr" :
237 : "i" (0xc0010020), "a" (eax), "d" (edx) : "ecx");
238
239 /* get patch id after patching */
240 asm volatile("movl %1, %%ecx; rdmsr"
241 : "=a" (rev)
242 : "i" (0x0000008B) : "ecx");
243
244 spin_unlock_irqrestore(&microcode_update_lock, flags);
245
246 /* check current patch id and patch's id for match */
247 if (rev != uci->mc.mc_amd->hdr.patch_id) {
248 printk(KERN_ERR "microcode: CPU%d update from revision "
249 "0x%x to 0x%x failed\n", cpu_num,
250 uci->mc.mc_amd->hdr.patch_id, rev);
251 return;
252 }
253
254 printk(KERN_INFO "microcode: CPU%d updated from revision "
255 "0x%x to 0x%x \n",
256 cpu_num, uci->rev, uci->mc.mc_amd->hdr.patch_id);
257
258 uci->rev = rev;
259}
260
261#ifdef CONFIG_MICROCODE_OLD_INTERFACE
262extern void __user *user_buffer; /* user area microcode data buffer */
263extern unsigned int user_buffer_size; /* it's size */
264
265static long get_next_ucode_amd(void **mc, long offset)
266{
267 struct microcode_header_amd mc_header;
268 unsigned long total_size;
269
270 /* No more data */
271 if (offset >= user_buffer_size)
272 return 0;
273 if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) {
274 printk(KERN_ERR "microcode: error! Can not read user data\n");
275 return -EFAULT;
276 }
277 total_size = get_totalsize(&mc_header);
278 if (offset + total_size > user_buffer_size) {
279 printk(KERN_ERR "microcode: error! Bad total size in microcode "
280 "data file\n");
281 return -EINVAL;
282 }
283 *mc = vmalloc(UCODE_MAX_SIZE);
284 if (!*mc)
285 return -ENOMEM;
286 memset(*mc, 0, UCODE_MAX_SIZE);
287
288 if (copy_from_user(*mc, user_buffer + offset, total_size)) {
289 printk(KERN_ERR "microcode: error! Can not read user data\n");
290 vfree(*mc);
291 return -EFAULT;
292 }
293 return offset + total_size;
294}
295#else
296#define get_next_ucode_amd() NULL
297#endif
298
299static long get_next_ucode_from_buffer_amd(void **mc, void *buf,
300 unsigned long size, long offset)
301{
302 struct microcode_header_amd *mc_header;
303 unsigned long total_size;
304 unsigned char *buf_pos = buf;
305
306 /* No more data */
307 if (offset >= size)
308 return 0;
309
310 if (buf_pos[offset] != UCODE_UCODE_TYPE) {
311 printk(KERN_ERR "microcode: error! "
312 "Wrong microcode payload type field\n");
313 return -EINVAL;
314 }
315
316 mc_header = (struct microcode_header_amd *)(&buf_pos[offset+8]);
317
318 total_size = (unsigned long) (buf_pos[offset+4] +
319 (buf_pos[offset+5] << 8));
320
321 printk(KERN_INFO "microcode: size %lu, total_size %lu, offset %ld\n",
322 size, total_size, offset);
323
324 if (offset + total_size > size) {
325 printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
326 return -EINVAL;
327 }
328
329 *mc = vmalloc(UCODE_MAX_SIZE);
330 if (!*mc) {
331 printk(KERN_ERR "microcode: error! "
332 "Can not allocate memory for microcode patch\n");
333 return -ENOMEM;
334 }
335
336 memset(*mc, 0, UCODE_MAX_SIZE);
337 memcpy(*mc, buf + offset + 8, total_size);
338
339 return offset + total_size + 8;
340}
341
342static long install_equiv_cpu_table(void *buf, unsigned long size, long offset)
343{
344 unsigned int *buf_pos = buf;
345
346 /* No more data */
347 if (offset >= size)
348 return 0;
349
350 if (buf_pos[1] != UCODE_EQUIV_CPU_TABLE_TYPE) {
351 printk(KERN_ERR "microcode: error! "
352 "Wrong microcode equivalnet cpu table type field\n");
353 return 0;
354 }
355
356 if (size == 0) {
357 printk(KERN_ERR "microcode: error! "
358 "Wrong microcode equivalnet cpu table length\n");
359 return 0;
360 }
361
362 equiv_cpu_table = (struct equiv_cpu_entry *) vmalloc(size);
363 if (!equiv_cpu_table) {
364 printk(KERN_ERR "microcode: error, can't allocate memory for equiv CPU table\n");
365 return 0;
366 }
367
368 memset(equiv_cpu_table, 0, size);
369 memcpy(equiv_cpu_table, &buf_pos[3], size);
370
371 return size + 12; /* add header length */
372}
373
374/* fake device for request_firmware */
375extern struct platform_device *microcode_pdev;
376
377static int cpu_request_microcode_amd(int cpu)
378{
379 char name[30];
380 const struct firmware *firmware;
381 void *buf;
382 unsigned int *buf_pos;
383 unsigned long size;
384 long offset = 0;
385 int error;
386 void *mc;
387
388 /* We should bind the task to the CPU */
389 BUG_ON(cpu != raw_smp_processor_id());
390
391 sprintf(name, "amd-ucode/microcode_amd.bin");
392 error = request_firmware(&firmware, "amd-ucode/microcode_amd.bin",
393 &microcode_pdev->dev);
394 if (error) {
395 printk(KERN_ERR "microcode: ucode data file %s load failed\n",
396 name);
397 return error;
398 }
399
400 buf_pos = buf = firmware->data;
401 size = firmware->size;
402
403 if (buf_pos[0] != UCODE_MAGIC) {
404 printk(KERN_ERR "microcode: error! Wrong microcode patch file magic\n");
405 return -EINVAL;
406 }
407
408 offset = install_equiv_cpu_table(buf, buf_pos[2], offset);
409
410 if (!offset) {
411 printk(KERN_ERR "microcode: installing equivalent cpu table failed\n");
412 return -EINVAL;
413 }
414
415 while ((offset =
416 get_next_ucode_from_buffer_amd(&mc, buf, size, offset)) > 0) {
417 error = get_matching_microcode_amd(mc, cpu);
418 if (error < 0)
419 break;
420 /*
421 * It's possible the data file has multiple matching ucode,
422 * lets keep searching till the latest version
423 */
424 if (error == 1) {
425 apply_microcode_amd(cpu);
426 error = 0;
427 }
428 vfree(mc);
429 }
430 if (offset > 0) {
431 vfree(mc);
432 vfree(equiv_cpu_table);
433 equiv_cpu_table = NULL;
434 }
435 if (offset < 0)
436 error = offset;
437 release_firmware(firmware);
438
439 return error;
440}
441
442static int apply_microcode_check_cpu_amd(int cpu)
443{
444 struct cpuinfo_x86 *c = &cpu_data(cpu);
445 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
446 unsigned int rev;
447 cpumask_t old;
448 int err = 0;
449
450 /* Check if the microcode is available */
451 if (!uci->mc.mc_amd)
452 return 0;
453
454 old = current->cpus_allowed;
455 set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
456
457 /* Check if the microcode we have in memory matches the CPU */
458 if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 16)
459 err = -EINVAL;
460
461 if (!err) {
462 asm volatile("movl %1, %%ecx; rdmsr"
463 : "=a" (rev)
464 : "i" (0x0000008B) : "ecx");
465
466 if (uci->rev != rev)
467 err = -EINVAL;
468 }
469
470 if (!err)
471 apply_microcode_amd(cpu);
472 else
473 printk(KERN_ERR "microcode: Could not apply microcode to CPU%d:"
474 " rev=0x%x\n",
475 cpu, uci->rev);
476
477 set_cpus_allowed(current, old);
478 return err;
479}
480
481static void microcode_fini_cpu_amd(int cpu)
482{
483 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
484
485 mutex_lock(&microcode_mutex);
486 uci->valid = 0;
487 vfree(uci->mc.mc_amd);
488 uci->mc.mc_amd = NULL;
489 mutex_unlock(&microcode_mutex);
490}
491
492static struct microcode_ops microcode_amd_ops = {
493 .get_next_ucode = get_next_ucode_amd,
494 .get_matching_microcode = get_matching_microcode_amd,
495 .microcode_sanity_check = NULL,
496 .apply_microcode_check_cpu = apply_microcode_check_cpu_amd,
497 .cpu_request_microcode = cpu_request_microcode_amd,
498 .collect_cpu_info = collect_cpu_info_amd,
499 .apply_microcode = apply_microcode_amd,
500 .microcode_fini_cpu = microcode_fini_cpu_amd,
501};
502
503static int __init microcode_amd_module_init(void)
504{
505 struct cpuinfo_x86 *c = &cpu_data(get_cpu());
506
507 equiv_cpu_table = NULL;
508 if (c->x86_vendor == X86_VENDOR_AMD)
509 return microcode_init(&microcode_amd_ops, THIS_MODULE);
510 else
511 return -ENODEV;
512}
513
514static void __exit microcode_amd_module_exit(void)
515{
516 microcode_exit();
517}
518
519module_init(microcode_amd_module_init)
520module_exit(microcode_amd_module_exit)
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c
new file mode 100644
index 000000000000..6da4a85ff465
--- /dev/null
+++ b/arch/x86/kernel/microcode_intel.c
@@ -0,0 +1,545 @@
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 speculative
59 * 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
74//#define DEBUG /* pr_debug */
75#include <linux/capability.h>
76#include <linux/kernel.h>
77#include <linux/init.h>
78#include <linux/sched.h>
79#include <linux/smp_lock.h>
80#include <linux/cpumask.h>
81#include <linux/module.h>
82#include <linux/slab.h>
83#include <linux/vmalloc.h>
84#include <linux/miscdevice.h>
85#include <linux/spinlock.h>
86#include <linux/mm.h>
87#include <linux/fs.h>
88#include <linux/mutex.h>
89#include <linux/cpu.h>
90#include <linux/firmware.h>
91#include <linux/platform_device.h>
92
93#include <asm/msr.h>
94#include <asm/uaccess.h>
95#include <asm/processor.h>
96#include <asm/microcode.h>
97
98MODULE_DESCRIPTION("Microcode Update Driver");
99MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
100MODULE_LICENSE("GPL");
101
102#define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */
103#define MC_HEADER_SIZE (sizeof(struct microcode_header_intel)) /* 48 bytes */
104#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */
105#define EXT_HEADER_SIZE (sizeof(struct extended_sigtable)) /* 20 bytes */
106#define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature)) /* 12 bytes */
107#define DWSIZE (sizeof(u32))
108#define get_totalsize(mc) \
109 (((struct microcode_intel *)mc)->hdr.totalsize ? \
110 ((struct microcode_intel *)mc)->hdr.totalsize : \
111 DEFAULT_UCODE_TOTALSIZE)
112
113#define get_datasize(mc) \
114 (((struct microcode_intel *)mc)->hdr.datasize ? \
115 ((struct microcode_intel *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE)
116
117#define sigmatch(s1, s2, p1, p2) \
118 (((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0))))
119
120#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
121
122/* serialize access to the physical write to MSR 0x79 */
123static DEFINE_SPINLOCK(microcode_update_lock);
124
125/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
126extern struct mutex microcode_mutex;
127
128extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
129
130static void collect_cpu_info(int cpu_num)
131{
132 struct cpuinfo_x86 *c = &cpu_data(cpu_num);
133 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
134 unsigned int val[2];
135
136 /* We should bind the task to the CPU */
137 BUG_ON(raw_smp_processor_id() != cpu_num);
138 uci->pf = uci->rev = 0;
139 uci->mc.mc_intel = NULL;
140 uci->valid = 1;
141
142 if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
143 cpu_has(c, X86_FEATURE_IA64)) {
144 printk(KERN_ERR "microcode: CPU%d not a capable Intel "
145 "processor\n", cpu_num);
146 uci->valid = 0;
147 return;
148 }
149
150 uci->sig = cpuid_eax(0x00000001);
151
152 if ((c->x86_model >= 5) || (c->x86 > 6)) {
153 /* get processor flags from MSR 0x17 */
154 rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
155 uci->pf = 1 << ((val[1] >> 18) & 7);
156 }
157
158 wrmsr(MSR_IA32_UCODE_REV, 0, 0);
159 /* see notes above for revision 1.07. Apparent chip bug */
160 sync_core();
161 /* get the current revision from MSR 0x8B */
162 rdmsr(MSR_IA32_UCODE_REV, val[0], uci->rev);
163 pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n",
164 uci->sig, uci->pf, uci->rev);
165}
166
167static inline int microcode_update_match(int cpu_num,
168 struct microcode_header_intel *mc_header, int sig, int pf)
169{
170 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
171
172 if (!sigmatch(sig, uci->sig, pf, uci->pf)
173 || mc_header->rev <= uci->rev)
174 return 0;
175 return 1;
176}
177
178static int microcode_sanity_check(void *mc)
179{
180 struct microcode_header_intel *mc_header = mc;
181 struct extended_sigtable *ext_header = NULL;
182 struct extended_signature *ext_sig;
183 unsigned long total_size, data_size, ext_table_size;
184 int sum, orig_sum, ext_sigcount = 0, i;
185
186 total_size = get_totalsize(mc_header);
187 data_size = get_datasize(mc_header);
188 if (data_size + MC_HEADER_SIZE > total_size) {
189 printk(KERN_ERR "microcode: error! "
190 "Bad data size in microcode data file\n");
191 return -EINVAL;
192 }
193
194 if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
195 printk(KERN_ERR "microcode: error! "
196 "Unknown microcode update format\n");
197 return -EINVAL;
198 }
199 ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
200 if (ext_table_size) {
201 if ((ext_table_size < EXT_HEADER_SIZE)
202 || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
203 printk(KERN_ERR "microcode: error! "
204 "Small exttable size in microcode data file\n");
205 return -EINVAL;
206 }
207 ext_header = mc + MC_HEADER_SIZE + data_size;
208 if (ext_table_size != exttable_size(ext_header)) {
209 printk(KERN_ERR "microcode: error! "
210 "Bad exttable size in microcode data file\n");
211 return -EFAULT;
212 }
213 ext_sigcount = ext_header->count;
214 }
215
216 /* check extended table checksum */
217 if (ext_table_size) {
218 int ext_table_sum = 0;
219 int *ext_tablep = (int *)ext_header;
220
221 i = ext_table_size / DWSIZE;
222 while (i--)
223 ext_table_sum += ext_tablep[i];
224 if (ext_table_sum) {
225 printk(KERN_WARNING "microcode: aborting, "
226 "bad extended signature table checksum\n");
227 return -EINVAL;
228 }
229 }
230
231 /* calculate the checksum */
232 orig_sum = 0;
233 i = (MC_HEADER_SIZE + data_size) / DWSIZE;
234 while (i--)
235 orig_sum += ((int *)mc)[i];
236 if (orig_sum) {
237 printk(KERN_ERR "microcode: aborting, bad checksum\n");
238 return -EINVAL;
239 }
240 if (!ext_table_size)
241 return 0;
242 /* check extended signature checksum */
243 for (i = 0; i < ext_sigcount; i++) {
244 ext_sig = (void *)ext_header + EXT_HEADER_SIZE +
245 EXT_SIGNATURE_SIZE * i;
246 sum = orig_sum
247 - (mc_header->sig + mc_header->pf + mc_header->cksum)
248 + (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
249 if (sum) {
250 printk(KERN_ERR "microcode: aborting, bad checksum\n");
251 return -EINVAL;
252 }
253 }
254 return 0;
255}
256
257/*
258 * return 0 - no update found
259 * return 1 - found update
260 * return < 0 - error
261 */
262static int get_matching_microcode(void *mc, int cpu)
263{
264 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
265 struct microcode_header_intel *mc_header = mc;
266 struct extended_sigtable *ext_header;
267 unsigned long total_size = get_totalsize(mc_header);
268 int ext_sigcount, i;
269 struct extended_signature *ext_sig;
270 void *new_mc;
271
272 if (microcode_update_match(cpu, mc_header,
273 mc_header->sig, mc_header->pf))
274 goto find;
275
276 if (total_size <= get_datasize(mc_header) + MC_HEADER_SIZE)
277 return 0;
278
279 ext_header = mc + get_datasize(mc_header) + MC_HEADER_SIZE;
280 ext_sigcount = ext_header->count;
281 ext_sig = (void *)ext_header + EXT_HEADER_SIZE;
282 for (i = 0; i < ext_sigcount; i++) {
283 if (microcode_update_match(cpu, mc_header,
284 ext_sig->sig, ext_sig->pf))
285 goto find;
286 ext_sig++;
287 }
288 return 0;
289find:
290 pr_debug("microcode: CPU%d found a matching microcode update with"
291 " version 0x%x (current=0x%x)\n",
292 cpu, mc_header->rev, uci->rev);
293 new_mc = vmalloc(total_size);
294 if (!new_mc) {
295 printk(KERN_ERR "microcode: error! Can not allocate memory\n");
296 return -ENOMEM;
297 }
298
299 /* free previous update file */
300 vfree(uci->mc.mc_intel);
301
302 memcpy(new_mc, mc, total_size);
303 uci->mc.mc_intel = new_mc;
304 return 1;
305}
306
307static void apply_microcode(int cpu)
308{
309 unsigned long flags;
310 unsigned int val[2];
311 int cpu_num = raw_smp_processor_id();
312 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
313
314 /* We should bind the task to the CPU */
315 BUG_ON(cpu_num != cpu);
316
317 if (uci->mc.mc_intel == NULL)
318 return;
319
320 /* serialize access to the physical write to MSR 0x79 */
321 spin_lock_irqsave(&microcode_update_lock, flags);
322
323 /* write microcode via MSR 0x79 */
324 wrmsr(MSR_IA32_UCODE_WRITE,
325 (unsigned long) uci->mc.mc_intel->bits,
326 (unsigned long) uci->mc.mc_intel->bits >> 16 >> 16);
327 wrmsr(MSR_IA32_UCODE_REV, 0, 0);
328
329 /* see notes above for revision 1.07. Apparent chip bug */
330 sync_core();
331
332 /* get the current revision from MSR 0x8B */
333 rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
334
335 spin_unlock_irqrestore(&microcode_update_lock, flags);
336 if (val[1] != uci->mc.mc_intel->hdr.rev) {
337 printk(KERN_ERR "microcode: CPU%d update from revision "
338 "0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]);
339 return;
340 }
341 printk(KERN_INFO "microcode: CPU%d updated from revision "
342 "0x%x to 0x%x, date = %08x \n",
343 cpu_num, uci->rev, val[1], uci->mc.mc_intel->hdr.date);
344 uci->rev = val[1];
345}
346
347#ifdef CONFIG_MICROCODE_OLD_INTERFACE
348extern void __user *user_buffer; /* user area microcode data buffer */
349extern unsigned int user_buffer_size; /* it's size */
350
351static long get_next_ucode(void **mc, long offset)
352{
353 struct microcode_header_intel mc_header;
354 unsigned long total_size;
355
356 /* No more data */
357 if (offset >= user_buffer_size)
358 return 0;
359 if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) {
360 printk(KERN_ERR "microcode: error! Can not read user data\n");
361 return -EFAULT;
362 }
363 total_size = get_totalsize(&mc_header);
364 if (offset + total_size > user_buffer_size) {
365 printk(KERN_ERR "microcode: error! Bad total size in microcode "
366 "data file\n");
367 return -EINVAL;
368 }
369 *mc = vmalloc(total_size);
370 if (!*mc)
371 return -ENOMEM;
372 if (copy_from_user(*mc, user_buffer + offset, total_size)) {
373 printk(KERN_ERR "microcode: error! Can not read user data\n");
374 vfree(*mc);
375 return -EFAULT;
376 }
377 return offset + total_size;
378}
379#endif
380
381static long get_next_ucode_from_buffer(void **mc, const u8 *buf,
382 unsigned long size, long offset)
383{
384 struct microcode_header_intel *mc_header;
385 unsigned long total_size;
386
387 /* No more data */
388 if (offset >= size)
389 return 0;
390 mc_header = (struct microcode_header_intel *)(buf + offset);
391 total_size = get_totalsize(mc_header);
392
393 if (offset + total_size > size) {
394 printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
395 return -EINVAL;
396 }
397
398 *mc = vmalloc(total_size);
399 if (!*mc) {
400 printk(KERN_ERR "microcode: error! Can not allocate memory\n");
401 return -ENOMEM;
402 }
403 memcpy(*mc, buf + offset, total_size);
404 return offset + total_size;
405}
406
407/* fake device for request_firmware */
408extern struct platform_device *microcode_pdev;
409
410static int cpu_request_microcode(int cpu)
411{
412 char name[30];
413 struct cpuinfo_x86 *c = &cpu_data(cpu);
414 const struct firmware *firmware;
415 const u8 *buf;
416 unsigned long size;
417 long offset = 0;
418 int error;
419 void *mc;
420
421 /* We should bind the task to the CPU */
422 BUG_ON(cpu != raw_smp_processor_id());
423 sprintf(name, "intel-ucode/%02x-%02x-%02x",
424 c->x86, c->x86_model, c->x86_mask);
425 error = request_firmware(&firmware, name, &microcode_pdev->dev);
426 if (error) {
427 pr_debug("microcode: data file %s load failed\n", name);
428 return error;
429 }
430 buf = firmware->data;
431 size = firmware->size;
432 while ((offset = get_next_ucode_from_buffer(&mc, buf, size, offset))
433 > 0) {
434 error = microcode_sanity_check(mc);
435 if (error)
436 break;
437 error = get_matching_microcode(mc, cpu);
438 if (error < 0)
439 break;
440 /*
441 * It's possible the data file has multiple matching ucode,
442 * lets keep searching till the latest version
443 */
444 if (error == 1) {
445 apply_microcode(cpu);
446 error = 0;
447 }
448 vfree(mc);
449 }
450 if (offset > 0)
451 vfree(mc);
452 if (offset < 0)
453 error = offset;
454 release_firmware(firmware);
455
456 return error;
457}
458
459static int apply_microcode_check_cpu(int cpu)
460{
461 struct cpuinfo_x86 *c = &cpu_data(cpu);
462 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
463 cpumask_t old;
464 unsigned int val[2];
465 int err = 0;
466
467 /* Check if the microcode is available */
468 if (!uci->mc.mc_intel)
469 return 0;
470
471 old = current->cpus_allowed;
472 set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
473
474 /* Check if the microcode we have in memory matches the CPU */
475 if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
476 cpu_has(c, X86_FEATURE_IA64) || uci->sig != cpuid_eax(0x00000001))
477 err = -EINVAL;
478
479 if (!err && ((c->x86_model >= 5) || (c->x86 > 6))) {
480 /* get processor flags from MSR 0x17 */
481 rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
482 if (uci->pf != (1 << ((val[1] >> 18) & 7)))
483 err = -EINVAL;
484 }
485
486 if (!err) {
487 wrmsr(MSR_IA32_UCODE_REV, 0, 0);
488 /* see notes above for revision 1.07. Apparent chip bug */
489 sync_core();
490 /* get the current revision from MSR 0x8B */
491 rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
492 if (uci->rev != val[1])
493 err = -EINVAL;
494 }
495
496 if (!err)
497 apply_microcode(cpu);
498 else
499 printk(KERN_ERR "microcode: Could not apply microcode to CPU%d:"
500 " sig=0x%x, pf=0x%x, rev=0x%x\n",
501 cpu, uci->sig, uci->pf, uci->rev);
502
503 set_cpus_allowed_ptr(current, &old);
504 return err;
505}
506
507static void microcode_fini_cpu(int cpu)
508{
509 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
510
511 mutex_lock(&microcode_mutex);
512 uci->valid = 0;
513 vfree(uci->mc.mc_intel);
514 uci->mc.mc_intel = NULL;
515 mutex_unlock(&microcode_mutex);
516}
517
518static struct microcode_ops microcode_intel_ops = {
519 .get_next_ucode = get_next_ucode,
520 .get_matching_microcode = get_matching_microcode,
521 .microcode_sanity_check = microcode_sanity_check,
522 .apply_microcode_check_cpu = apply_microcode_check_cpu,
523 .cpu_request_microcode = cpu_request_microcode,
524 .collect_cpu_info = collect_cpu_info,
525 .apply_microcode = apply_microcode,
526 .microcode_fini_cpu = microcode_fini_cpu,
527};
528
529static int __init microcode_intel_module_init(void)
530{
531 struct cpuinfo_x86 *c = &cpu_data(get_cpu());
532
533 if (c->x86_vendor == X86_VENDOR_INTEL)
534 return microcode_init(&microcode_intel_ops, THIS_MODULE);
535 else
536 return -ENODEV;
537}
538
539static void __exit microcode_intel_module_exit(void)
540{
541 microcode_exit();
542}
543
544module_init(microcode_intel_module_init)
545module_exit(microcode_intel_module_exit)
diff --git a/include/asm-x86/microcode.h b/include/asm-x86/microcode.h
new file mode 100644
index 000000000000..18b2aeec2adf
--- /dev/null
+++ b/include/asm-x86/microcode.h
@@ -0,0 +1,87 @@
1extern int microcode_init(void *opaque, struct module *module);
2extern void microcode_exit(void);
3
4struct microcode_ops {
5 long (*get_next_ucode)(void **mc, long offset);
6 long (*microcode_get_next_ucode)(void **mc, long offset);
7 int (*get_matching_microcode)(void *mc, int cpu);
8 int (*apply_microcode_check_cpu)(int cpu);
9 int (*microcode_sanity_check)(void *mc);
10 int (*cpu_request_microcode)(int cpu);
11 void (*collect_cpu_info)(int cpu_num);
12 void (*apply_microcode)(int cpu);
13 void (*microcode_fini_cpu)(int cpu);
14 void (*clear_patch)(void *data);
15};
16
17struct microcode_header_intel {
18 unsigned int hdrver;
19 unsigned int rev;
20 unsigned int date;
21 unsigned int sig;
22 unsigned int cksum;
23 unsigned int ldrver;
24 unsigned int pf;
25 unsigned int datasize;
26 unsigned int totalsize;
27 unsigned int reserved[3];
28};
29
30struct microcode_intel {
31 struct microcode_header_intel hdr;
32 unsigned int bits[0];
33};
34
35/* microcode format is extended from prescott processors */
36struct extended_signature {
37 unsigned int sig;
38 unsigned int pf;
39 unsigned int cksum;
40};
41
42struct extended_sigtable {
43 unsigned int count;
44 unsigned int cksum;
45 unsigned int reserved[3];
46 struct extended_signature sigs[0];
47};
48
49struct 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
56struct 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
73struct microcode_amd {
74 struct microcode_header_amd hdr;
75 unsigned int mpb[0];
76};
77
78struct ucode_cpu_info {
79 int valid;
80 unsigned int sig;
81 unsigned int pf;
82 unsigned int rev;
83 union {
84 struct microcode_intel *mc_intel;
85 struct microcode_amd *mc_amd;
86 } mc;
87};
diff --git a/include/asm-x86/processor.h b/include/asm-x86/processor.h
index 5f58da401b43..58a76f69ee31 100644
--- a/include/asm-x86/processor.h
+++ b/include/asm-x86/processor.h
@@ -561,41 +561,6 @@ static inline void clear_in_cr4(unsigned long mask)
561 write_cr4(cr4); 561 write_cr4(cr4);
562} 562}
563 563
564struct microcode_header {
565 unsigned int hdrver;
566 unsigned int rev;
567 unsigned int date;
568 unsigned int sig;
569 unsigned int cksum;
570 unsigned int ldrver;
571 unsigned int pf;
572 unsigned int datasize;
573 unsigned int totalsize;
574 unsigned int reserved[3];
575};
576
577struct microcode {
578 struct microcode_header hdr;
579 unsigned int bits[0];
580};
581
582typedef struct microcode microcode_t;
583typedef struct microcode_header microcode_header_t;
584
585/* microcode format is extended from prescott processors */
586struct extended_signature {
587 unsigned int sig;
588 unsigned int pf;
589 unsigned int cksum;
590};
591
592struct extended_sigtable {
593 unsigned int count;
594 unsigned int cksum;
595 unsigned int reserved[3];
596 struct extended_signature sigs[0];
597};
598
599typedef struct { 564typedef struct {
600 unsigned long seg; 565 unsigned long seg;
601} mm_segment_t; 566} mm_segment_t;