2 * CPU Microcode Update interface for Linux
4 * Copyright (C) 2000 Tigran Aivazian
6 * This driver allows to upgrade microcode on Intel processors
7 * belonging to P6 family - PentiumPro, Pentium II, Pentium III etc.
9 * Reference: Section 8.10 of Volume III, Intel Pentium III Manual,
10 * Order Number 243192 or download from:
12 * http://developer.intel.com/design/pentiumii/manuals/243192.htm
14 * For more information, go to http://www.urbanmyth.org/microcode
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version
19 * 2 of the License, or (at your option) any later version.
21 * 1.0 16 February 2000, Tigran Aivazian <tigran@sco.com>
23 * 1.01 18 February 2000, Tigran Aivazian <tigran@sco.com>
24 * Added read() support + cleanups.
25 * 1.02 21 February 2000, Tigran Aivazian <tigran@sco.com>
26 * Added 'device trimming' support. open(O_WRONLY) zeroes
27 * and frees the saved copy of applied microcode.
28 * 1.03 29 February 2000, Tigran Aivazian <tigran@sco.com>
29 * Made to use devfs (/dev/cpu/microcode) + cleanups.
30 * 1.04 06 June 2000, Simon Trimmer <simon@veritas.com>
31 * Added misc device support (now uses both devfs and misc).
32 * Added MICROCODE_IOCFREE ioctl to clear memory.
33 * 1.05 09 June 2000, Simon Trimmer <simon@veritas.com>
34 * Messages for error cases (non intel & no suitable microcode).
37 #include <linux/init.h>
38 #include <linux/slab.h>
39 #include <linux/sched.h>
40 #include <linux/module.h>
41 #include <linux/vmalloc.h>
42 #include <linux/smp_lock.h>
43 #include <linux/miscdevice.h>
44 #include <linux/devfs_fs_kernel.h>
47 #include <asm/uaccess.h>
48 #include <asm/processor.h>
50 #define MICROCODE_VERSION "1.05"
52 MODULE_DESCRIPTION("Intel CPU (P6) microcode update driver");
53 MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
57 static int microcode_open(struct inode
*, struct file
*);
58 static int microcode_release(struct inode
*, struct file
*);
59 static ssize_t
microcode_read(struct file
*, char *, size_t, loff_t
*);
60 static ssize_t
microcode_write(struct file
*, const char *, size_t, loff_t
*);
61 static int microcode_ioctl(struct inode
*, struct file
*, unsigned int, unsigned long);
64 /* internal helpers to do the work */
65 static int do_microcode_update(void);
66 static void do_update_one(void *);
69 * Bits in microcode_status. (31 bits of room for future expansion)
71 #define MICROCODE_IS_OPEN 0 /* set if device is in use */
73 static unsigned long microcode_status
;
75 /* the actual array of microcode blocks, each 2048 bytes */
76 static struct microcode
*microcode
;
77 static unsigned int microcode_num
;
78 static char *mc_applied
; /* holds an array of applied microcode blocks */
79 static unsigned int mc_fsize
;
81 static struct file_operations microcode_fops
= {
84 write
: microcode_write
,
85 ioctl
: microcode_ioctl
,
87 release
: microcode_release
,
90 static struct miscdevice microcode_dev
= {
91 minor
: MICROCODE_MINOR
,
93 fops
: µcode_fops
,
96 static devfs_handle_t devfs_handle
;
98 static int __init
microcode_init(void)
102 if (misc_register(µcode_dev
) < 0) {
104 "microcode: can't misc_register on minor=%d\n",
108 devfs_handle
= devfs_register(NULL
, "cpu/microcode",
109 DEVFS_FL_DEFAULT
, 0, 0, S_IFREG
| S_IRUSR
| S_IWUSR
,
110 µcode_fops
, NULL
);
111 if (devfs_handle
== NULL
&& error
) {
112 printk(KERN_ERR
"microcode: failed to devfs_register()\n");
115 printk(KERN_INFO
"P6 Microcode Update Driver v%s registered\n",
120 static void __exit
microcode_exit(void)
122 misc_deregister(µcode_dev
);
123 devfs_unregister(devfs_handle
);
126 printk(KERN_INFO
"P6 Microcode Update Driver v%s unregistered\n",
130 module_init(microcode_init
);
131 module_exit(microcode_exit
);
134 * We enforce only one user at a time here with open/close.
136 static int microcode_open(struct inode
*inode
, struct file
*file
)
138 if (!capable(CAP_SYS_RAWIO
))
141 /* one at a time, please */
142 if (test_and_set_bit(MICROCODE_IS_OPEN
, µcode_status
))
148 /* our specific f_op->release() method needs no locking */
149 static int microcode_release(struct inode
*inode
, struct file
*file
)
151 clear_bit(MICROCODE_IS_OPEN
, µcode_status
);
155 /* a pointer to 'struct update_req' is passed to the IPI handler = do_update_one()
156 * update_req[cpu].err is set to 1 if update failed on 'cpu', 0 otherwise
157 * if err==0, microcode[update_req[cpu].slot] points to applied block of microcode
162 } update_req
[NR_CPUS
];
164 static int do_microcode_update(void)
166 int i
, error
= 0, err
;
169 if (smp_call_function(do_update_one
, (void *)update_req
, 1, 1) != 0)
170 panic("do_microcode_update(): timed out waiting for other CPUs\n");
171 do_update_one((void *)update_req
);
173 for (i
=0; i
<smp_num_cpus
; i
++) {
174 err
= update_req
[i
].err
;
177 m
= (struct microcode
*)mc_applied
+ i
;
178 memcpy(m
, µcode
[update_req
[i
].slot
], sizeof(struct microcode
));
184 static void do_update_one(void *arg
)
186 int cpu_num
= smp_processor_id();
187 struct cpuinfo_x86
*c
= cpu_data
+ cpu_num
;
188 struct update_req
*req
= (struct update_req
*)arg
+ cpu_num
;
189 unsigned int pf
= 0, val
[2], rev
, sig
;
192 req
->err
= 1; /* be pessimistic */
194 if (c
->x86_vendor
!= X86_VENDOR_INTEL
|| c
->x86
< 6){
195 printk(KERN_ERR
"microcode: CPU%d not an Intel P6\n", cpu_num
);
199 sig
= c
->x86_mask
+ (c
->x86_model
<<4) + (c
->x86
<<8);
201 if (c
->x86_model
>= 5) {
202 /* get processor flags from BBL_CR_OVRD MSR (0x17) */
203 rdmsr(0x17, val
[0], val
[1]);
204 pf
= 1 << ((val
[1] >> 18) & 7);
207 for (i
=0; i
<microcode_num
; i
++)
208 if (microcode
[i
].sig
== sig
&& microcode
[i
].pf
== pf
&&
209 microcode
[i
].ldrver
== 1 && microcode
[i
].hdrver
== 1) {
213 rdmsr(0x8B, val
[0], rev
);
214 if (microcode
[i
].rev
<= rev
) {
216 "microcode: CPU%d not 'upgrading' to earlier revision"
217 " %d (current=%d)\n", cpu_num
, microcode
[i
].rev
, rev
);
220 struct microcode
*m
= µcode
[i
];
221 unsigned int *sump
= (unsigned int *)(m
+1);
223 while (--sump
>= (unsigned int *)m
)
226 printk(KERN_ERR
"microcode: CPU%d aborting, "
227 "bad checksum\n", cpu_num
);
231 wrmsr(0x79, (unsigned int)(m
->bits
), 0);
232 __asm__
__volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
233 rdmsr(0x8B, val
[0], val
[1]);
237 printk(KERN_ERR
"microcode: CPU%d updated from revision "
238 "%d to %d, date=%08x\n",
239 cpu_num
, rev
, val
[1], m
->date
);
245 printk(KERN_ERR
"microcode: found no data for CPU%d (sig=%x, pflags=%d)\n", cpu_num
, sig
, pf
);
248 static ssize_t
microcode_read(struct file
*file
, char *buf
, size_t len
, loff_t
*ppos
)
250 if (*ppos
>= mc_fsize
)
252 if (*ppos
+ len
> mc_fsize
)
253 len
= mc_fsize
- *ppos
;
254 if (copy_to_user(buf
, mc_applied
+ *ppos
, len
))
260 static ssize_t
microcode_write(struct file
*file
, const char *buf
, size_t len
, loff_t
*ppos
)
264 if (len
% sizeof(struct microcode
) != 0) {
265 printk(KERN_ERR
"microcode: can only write in N*%d bytes units\n",
266 sizeof(struct microcode
));
270 mc_applied
= kmalloc(smp_num_cpus
*sizeof(struct microcode
),
273 printk(KERN_ERR
"microcode: out of memory for saved microcode\n");
276 memset(mc_applied
, 0, mc_fsize
);
280 microcode_num
= len
/sizeof(struct microcode
);
281 microcode
= vmalloc(len
);
286 if (copy_from_user(microcode
, buf
, len
)) {
290 if(do_microcode_update()) {
294 mc_fsize
= smp_num_cpus
* sizeof(struct microcode
);
298 devfs_set_file_size(devfs_handle
, mc_fsize
);
305 static int microcode_ioctl(struct inode
*inode
, struct file
*file
,
306 unsigned int cmd
, unsigned long arg
)
309 case MICROCODE_IOCFREE
:
311 devfs_set_file_size(devfs_handle
, 0);
312 memset(mc_applied
, 0, mc_fsize
);
316 "microcode: freed %d bytes\n", mc_fsize
);
323 printk(KERN_ERR
"microcode: unknown ioctl cmd=%d\n",