[PATCH] x86 microcode driver update
[opensuse:kernel.git] / arch / i386 / kernel / microcode.c
1 /*
2  *      Intel CPU Microcode Update driver for Linux
3  *
4  *      Copyright (C) 2000 Tigran Aivazian
5  *
6  *      This driver allows to upgrade microcode on Intel processors
7  *      belonging to IA-32 family - PentiumPro, Pentium II, 
8  *      Pentium III, Xeon, Pentium 4, etc.
9  *
10  *      Reference: Section 8.10 of Volume III, Intel Pentium 4 Manual, 
11  *      Order Number 245472 or free download from:
12  *              
13  *      http://developer.intel.com/design/pentium4/manuals/245472.htm
14  *
15  *      For more information, go to http://www.urbanmyth.org/microcode
16  *
17  *      This program is free software; you can redistribute it and/or
18  *      modify it under the terms of the GNU General Public License
19  *      as published by the Free Software Foundation; either version
20  *      2 of the License, or (at your option) any later version.
21  *
22  *      1.0     16 Feb 2000, Tigran Aivazian <tigran@sco.com>
23  *              Initial release.
24  *      1.01    18 Feb 2000, Tigran Aivazian <tigran@sco.com>
25  *              Added read() support + cleanups.
26  *      1.02    21 Feb 2000, Tigran Aivazian <tigran@sco.com>
27  *              Added 'device trimming' support. open(O_WRONLY) zeroes
28  *              and frees the saved copy of applied microcode.
29  *      1.03    29 Feb 2000, Tigran Aivazian <tigran@sco.com>
30  *              Made to use devfs (/dev/cpu/microcode) + cleanups.
31  *      1.04    06 Jun 2000, Simon Trimmer <simon@veritas.com>
32  *              Added misc device support (now uses both devfs and misc).
33  *              Added MICROCODE_IOCFREE ioctl to clear memory.
34  *      1.05    09 Jun 2000, Simon Trimmer <simon@veritas.com>
35  *              Messages for error cases (non intel & no suitable microcode).
36  *      1.06    03 Aug 2000, Tigran Aivazian <tigran@veritas.com>
37  *              Removed ->release(). Removed exclusive open and status bitmap.
38  *              Added microcode_rwsem to serialize read()/write()/ioctl().
39  *              Removed global kernel lock usage.
40  *      1.07    07 Sep 2000, Tigran Aivazian <tigran@veritas.com>
41  *              Write 0 to 0x8B msr and then cpuid before reading revision,
42  *              so that it works even if there were no update done by the
43  *              BIOS. Otherwise, reading from 0x8B gives junk (which happened
44  *              to be 0 on my machine which is why it worked even when I
45  *              disabled update by the BIOS)
46  *              Thanks to Eric W. Biederman <ebiederman@lnxi.com> for the fix.
47  *      1.08    11 Dec 2000, Richard Schaal <richard.schaal@intel.com> and
48  *                           Tigran Aivazian <tigran@veritas.com>
49  *              Intel Pentium 4 processor support and bugfixes.
50  *      1.09    30 Oct 2001, Tigran Aivazian <tigran@veritas.com>
51  *              Bugfix for HT (Hyper-Threading) enabled processors
52  *              whereby processor resources are shared by all logical processors
53  *              in a single CPU package.
54  *      1.10    28 Feb 2002 Asit K Mallick <asit.k.mallick@intel.com> and
55  *              Tigran Aivazian <tigran@veritas.com>,
56  *              Serialize updates as required on HT processors due to speculative
57  *              nature of implementation.
58  *      1.11    22 Mar 2001 Tigran Aivazian <tigran@veritas.com>
59  *              Fix the panic when writing zero-length microcode chunk.
60  */
61
62 #include <linux/init.h>
63 #include <linux/sched.h>
64 #include <linux/module.h>
65 #include <linux/slab.h>
66 #include <linux/vmalloc.h>
67 #include <linux/miscdevice.h>
68 #include <linux/devfs_fs_kernel.h>
69 #include <linux/spinlock.h>
70
71 #include <asm/msr.h>
72 #include <asm/uaccess.h>
73 #include <asm/processor.h>
74
75
76 static spinlock_t microcode_update_lock = SPIN_LOCK_UNLOCKED;
77
78 #define MICROCODE_VERSION       "1.11"
79
80 MODULE_DESCRIPTION("Intel CPU (IA-32) microcode update driver");
81 MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
82 MODULE_LICENSE("GPL");
83 EXPORT_NO_SYMBOLS;
84
85 #define MICRO_DEBUG 0
86
87 #if MICRO_DEBUG
88 #define printf(x...) printk(##x)
89 #else
90 #define printf(x...)
91 #endif
92
93 /* VFS interface */
94 static int microcode_open(struct inode *, struct file *);
95 static ssize_t microcode_read(struct file *, char *, size_t, loff_t *);
96 static ssize_t microcode_write(struct file *, const char *, size_t, loff_t *);
97 static int microcode_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
98
99 static int do_microcode_update(void);
100 static void do_update_one(void *);
101
102 /* read()/write()/ioctl() are serialized on this */
103 static DECLARE_RWSEM(microcode_rwsem);
104
105 static struct microcode *microcode; /* array of 2048byte microcode blocks */
106 static unsigned int microcode_num;  /* number of chunks in microcode */
107 static char *mc_applied;            /* array of applied microcode blocks */
108 static unsigned int mc_fsize;       /* file size of /dev/cpu/microcode */
109
110 /* we share file_operations between misc and devfs mechanisms */
111 static struct file_operations microcode_fops = {
112         owner:          THIS_MODULE,
113         read:           microcode_read,
114         write:          microcode_write,
115         ioctl:          microcode_ioctl,
116         open:           microcode_open,
117 };
118
119 static struct miscdevice microcode_dev = {
120         minor: MICROCODE_MINOR,
121         name:   "microcode",
122         fops:   &microcode_fops,
123 };
124
125 static devfs_handle_t devfs_handle;
126
127 static int __init microcode_init(void)
128 {
129         int error;
130
131         error = misc_register(&microcode_dev);
132         if (error)
133                 printk(KERN_WARNING 
134                         "microcode: can't misc_register on minor=%d\n",
135                         MICROCODE_MINOR);
136
137         devfs_handle = devfs_register(NULL, "cpu/microcode",
138                         DEVFS_FL_DEFAULT, 0, 0, S_IFREG | S_IRUSR | S_IWUSR, 
139                         &microcode_fops, NULL);
140         if (devfs_handle == NULL && error) {
141                 printk(KERN_ERR "microcode: failed to devfs_register()\n");
142                 goto out;
143         }
144         error = 0;
145         printk(KERN_INFO 
146                 "IA-32 Microcode Update Driver: v%s <tigran@veritas.com>\n", 
147                 MICROCODE_VERSION);
148
149 out:
150         return error;
151 }
152
153 static void __exit microcode_exit(void)
154 {
155         misc_deregister(&microcode_dev);
156         devfs_unregister(devfs_handle);
157         if (mc_applied)
158                 kfree(mc_applied);
159         printk(KERN_INFO "IA-32 Microcode Update Driver v%s unregistered\n", 
160                         MICROCODE_VERSION);
161 }
162
163 module_init(microcode_init)
164 module_exit(microcode_exit)
165
166 static int microcode_open(struct inode *unused1, struct file *unused2)
167 {
168         return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
169 }
170
171 /*
172  * update_req[cpu].err is set to 1 if update failed on 'cpu', 0 otherwise
173  * if err==0, microcode[update_req[cpu].slot] points to applied block of microcode
174  */
175 struct update_req {
176         int err;
177         int slot;
178 } update_req[NR_CPUS];
179
180 static int do_microcode_update(void)
181 {
182         int i, error = 0, err;
183         struct microcode *m;
184
185         if (smp_call_function(do_update_one, NULL, 1, 1) != 0) {
186                 printk(KERN_ERR "microcode: IPI timeout, giving up\n");
187                 return -EIO;
188         }
189         do_update_one(NULL);
190
191         for (i=0; i<smp_num_cpus; i++) {
192                 err = update_req[i].err;
193                 error += err;
194                 if (!err) {
195                         m = (struct microcode *)mc_applied + i;
196                         memcpy(m, &microcode[update_req[i].slot], sizeof(struct microcode));
197                 }
198         }
199         return error;
200 }
201
202 static void do_update_one(void *unused)
203 {
204         int cpu_num = smp_processor_id();
205         struct cpuinfo_x86 *c = cpu_data + cpu_num;
206         struct update_req *req = update_req + cpu_num;
207         unsigned int pf = 0, val[2], rev, sig;
208         unsigned long flags;
209         int i;
210
211         req->err = 1; /* assume update will fail on this cpu */
212
213         if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
214                 test_bit(X86_FEATURE_IA64, &c->x86_capability)){
215                 printk(KERN_ERR "microcode: CPU%d not a capable Intel processor\n", cpu_num);
216                 return;
217         }
218
219         sig = c->x86_mask + (c->x86_model<<4) + (c->x86<<8);
220
221         if ((c->x86_model >= 5) || (c->x86 > 6)) {
222                 /* get processor flags from MSR 0x17 */
223                 rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
224                 pf = 1 << ((val[1] >> 18) & 7);
225         }
226
227         for (i=0; i<microcode_num; i++)
228                 if (microcode[i].sig == sig && microcode[i].pf == pf &&
229                     microcode[i].ldrver == 1 && microcode[i].hdrver == 1) {
230                         int sum = 0;
231                         struct microcode *m = &microcode[i];
232                         unsigned int *sump = (unsigned int *)(m+1);
233
234                         printf("Microcode\n");
235                         printf("   Header Revision %d\n",microcode[i].hdrver);
236                         printf("   Date %x/%x/%x\n",
237                                 ((microcode[i].date >> 24 ) & 0xff),
238                                 ((microcode[i].date >> 16 ) & 0xff),
239                                 (microcode[i].date & 0xFFFF));
240                         printf("   Type %x Family %x Model %x Stepping %x\n",
241                                 ((microcode[i].sig >> 12) & 0x3),
242                                 ((microcode[i].sig >> 8) & 0xf),
243                                 ((microcode[i].sig >> 4) & 0xf),
244                                 ((microcode[i].sig & 0xf)));
245                         printf("   Checksum %x\n",microcode[i].cksum);
246                         printf("   Loader Revision %x\n",microcode[i].ldrver);
247                         printf("   Processor Flags %x\n\n",microcode[i].pf);
248
249                         req->slot = i;
250
251                         /* serialize access to update decision */
252                         spin_lock_irqsave(&microcode_update_lock, flags);          
253
254                         /* trick, to work even if there was no prior update by the BIOS */
255                         wrmsr(MSR_IA32_UCODE_REV, 0, 0);
256                         __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
257
258                         /* get current (on-cpu) revision into rev (ignore val[0]) */
259                         rdmsr(MSR_IA32_UCODE_REV, val[0], rev);
260                         
261                         if (microcode[i].rev < rev) {
262                                 spin_unlock_irqrestore(&microcode_update_lock, flags);
263                                 printk(KERN_ERR 
264                                        "microcode: CPU%d not 'upgrading' to earlier revision"
265                                        " %d (current=%d)\n", cpu_num, microcode[i].rev, rev);
266                                 return;
267                         } else if (microcode[i].rev == rev) {
268                                 /* notify the caller of success on this cpu */
269                                 req->err = 0;
270                                 spin_unlock_irqrestore(&microcode_update_lock, flags);
271                                 printk(KERN_ERR 
272                                         "microcode: CPU%d already at revision"
273                                         " %d (current=%d)\n", cpu_num, microcode[i].rev, rev);
274                                 return;
275                         }
276
277                         /* Verify the checksum */
278                         while (--sump >= (unsigned int *)m)
279                                 sum += *sump;
280                         if (sum != 0) {
281                                 req->err = 1;
282                                 spin_unlock_irqrestore(&microcode_update_lock, flags);
283                                 printk(KERN_ERR "microcode: CPU%d aborting, "
284                                        "bad checksum\n", cpu_num);
285                                 return;
286                         }
287                         
288                         /* write microcode via MSR 0x79 */
289                         wrmsr(MSR_IA32_UCODE_WRITE, (unsigned int)(m->bits), 0);
290
291                         /* serialize */
292                         __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
293
294                         /* get the current revision from MSR 0x8B */
295                         rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
296
297                         /* notify the caller of success on this cpu */
298                         req->err = 0;
299                         spin_unlock_irqrestore(&microcode_update_lock, flags);
300                         printk(KERN_INFO "microcode: CPU%d updated from revision "
301                                "%d to %d, date=%08x\n", 
302                                cpu_num, rev, val[1], microcode[i].date);
303                         return;
304                 }
305         
306         printk(KERN_ERR
307                "microcode: CPU%d no microcode found! (sig=%x, pflags=%d)\n", 
308                cpu_num, sig, pf);
309 }
310
311
312 static ssize_t microcode_read(struct file *file, char *buf, size_t len, loff_t *ppos)
313 {
314         ssize_t ret = 0;
315
316         down_read(&microcode_rwsem);
317         if (*ppos >= mc_fsize)
318                 goto out;
319         if (*ppos + len > mc_fsize)
320                 len = mc_fsize - *ppos;
321         ret = -EFAULT;
322         if (copy_to_user(buf, mc_applied + *ppos, len))
323                 goto out;
324         *ppos += len;
325         ret = len;
326 out:
327         up_read(&microcode_rwsem);
328         return ret;
329 }
330
331 static ssize_t microcode_write(struct file *file, const char *buf, size_t len, loff_t *ppos)
332 {
333         ssize_t ret;
334
335         if (!len || len % sizeof(struct microcode) != 0) {
336                 printk(KERN_ERR "microcode: can only write in N*%d bytes units\n", 
337                         sizeof(struct microcode));
338                 return -EINVAL;
339         }
340         if ((len >> PAGE_SHIFT) > num_physpages) {
341                 printk(KERN_ERR "microcode: too much data (max %d pages)\n", num_physpages);
342                 return -EINVAL;
343         }
344         down_write(&microcode_rwsem);
345         if (!mc_applied) {
346                 mc_applied = kmalloc(smp_num_cpus*sizeof(struct microcode),
347                                 GFP_KERNEL);
348                 if (!mc_applied) {
349                         up_write(&microcode_rwsem);
350                         printk(KERN_ERR "microcode: out of memory for saved microcode\n");
351                         return -ENOMEM;
352                 }
353         }
354         
355         microcode_num = len/sizeof(struct microcode);
356         microcode = vmalloc(len);
357         if (!microcode) {
358                 ret = -ENOMEM;
359                 goto out_unlock;
360         }
361
362         if (copy_from_user(microcode, buf, len)) {
363                 ret = -EFAULT;
364                 goto out_fsize;
365         }
366
367         if(do_microcode_update()) {
368                 ret = -EIO;
369                 goto out_fsize;
370         } else {
371                 mc_fsize = smp_num_cpus * sizeof(struct microcode);
372                 ret = (ssize_t)len;
373         }
374 out_fsize:
375         devfs_set_file_size(devfs_handle, mc_fsize);
376         vfree(microcode);
377 out_unlock:
378         up_write(&microcode_rwsem);
379         return ret;
380 }
381
382 static int microcode_ioctl(struct inode *inode, struct file *file, 
383                 unsigned int cmd, unsigned long arg)
384 {
385         switch(cmd) {
386                 case MICROCODE_IOCFREE:
387                         down_write(&microcode_rwsem);
388                         if (mc_applied) {
389                                 int bytes = smp_num_cpus * sizeof(struct microcode);
390
391                                 devfs_set_file_size(devfs_handle, 0);
392                                 kfree(mc_applied);
393                                 mc_applied = NULL;
394                                 printk(KERN_INFO "microcode: freed %d bytes\n", bytes);
395                                 mc_fsize = 0;
396                                 up_write(&microcode_rwsem);
397                                 return 0;
398                         }
399                         up_write(&microcode_rwsem);
400                         return -ENODATA;
401
402                 default:
403                         printk(KERN_ERR "microcode: unknown ioctl cmd=%d\n", cmd);
404                         return -EINVAL;
405         }
406         return -EINVAL;
407 }