aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/microcode.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/microcode.c')
-rw-r--r--arch/i386/kernel/microcode.c774
1 files changed, 511 insertions, 263 deletions
diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c
index 40b44cc0d14b..9b9479768d5e 100644
--- a/arch/i386/kernel/microcode.c
+++ b/arch/i386/kernel/microcode.c
@@ -2,6 +2,7 @@
2 * Intel CPU Microcode Update Driver for Linux 2 * Intel CPU Microcode Update Driver for Linux
3 * 3 *
4 * Copyright (C) 2000-2004 Tigran Aivazian 4 * Copyright (C) 2000-2004 Tigran Aivazian
5 * 2006 Shaohua Li <shaohua.li@intel.com>
5 * 6 *
6 * This driver allows to upgrade microcode on Intel processors 7 * This driver allows to upgrade microcode on Intel processors
7 * belonging to IA-32 family - PentiumPro, Pentium II, 8 * belonging to IA-32 family - PentiumPro, Pentium II,
@@ -82,6 +83,9 @@
82#include <linux/spinlock.h> 83#include <linux/spinlock.h>
83#include <linux/mm.h> 84#include <linux/mm.h>
84#include <linux/mutex.h> 85#include <linux/mutex.h>
86#include <linux/cpu.h>
87#include <linux/firmware.h>
88#include <linux/platform_device.h>
85 89
86#include <asm/msr.h> 90#include <asm/msr.h>
87#include <asm/uaccess.h> 91#include <asm/uaccess.h>
@@ -91,9 +95,6 @@ MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
91MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>"); 95MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
92MODULE_LICENSE("GPL"); 96MODULE_LICENSE("GPL");
93 97
94static int verbose;
95module_param(verbose, int, 0644);
96
97#define MICROCODE_VERSION "1.14a" 98#define MICROCODE_VERSION "1.14a"
98 99
99#define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */ 100#define DEFAULT_UCODE_DATASIZE (2000) /* 2000 bytes */
@@ -120,55 +121,40 @@ static DEFINE_SPINLOCK(microcode_update_lock);
120/* no concurrent ->write()s are allowed on /dev/cpu/microcode */ 121/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
121static DEFINE_MUTEX(microcode_mutex); 122static DEFINE_MUTEX(microcode_mutex);
122 123
123static void __user *user_buffer; /* user area microcode data buffer */
124static unsigned int user_buffer_size; /* it's size */
125
126typedef enum mc_error_code {
127 MC_SUCCESS = 0,
128 MC_IGNORED = 1,
129 MC_NOTFOUND = 2,
130 MC_MARKED = 3,
131 MC_ALLOCATED = 4,
132} mc_error_code_t;
133
134static struct ucode_cpu_info { 124static struct ucode_cpu_info {
125 int valid;
135 unsigned int sig; 126 unsigned int sig;
136 unsigned int pf, orig_pf; 127 unsigned int pf;
137 unsigned int rev; 128 unsigned int rev;
138 unsigned int cksum;
139 mc_error_code_t err;
140 microcode_t *mc; 129 microcode_t *mc;
141} ucode_cpu_info[NR_CPUS]; 130} ucode_cpu_info[NR_CPUS];
142
143static int microcode_open (struct inode *unused1, struct file *unused2)
144{
145 return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
146}
147 131
148static void collect_cpu_info (void *unused) 132static void collect_cpu_info(int cpu_num)
149{ 133{
150 int cpu_num = smp_processor_id();
151 struct cpuinfo_x86 *c = cpu_data + cpu_num; 134 struct cpuinfo_x86 *c = cpu_data + cpu_num;
152 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 135 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
153 unsigned int val[2]; 136 unsigned int val[2];
154 137
155 uci->sig = uci->pf = uci->rev = uci->cksum = 0; 138 /* We should bind the task to the CPU */
156 uci->err = MC_NOTFOUND; 139 BUG_ON(raw_smp_processor_id() != cpu_num);
140 uci->pf = uci->rev = 0;
157 uci->mc = NULL; 141 uci->mc = NULL;
142 uci->valid = 1;
158 143
159 if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || 144 if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
160 cpu_has(c, X86_FEATURE_IA64)) { 145 cpu_has(c, X86_FEATURE_IA64)) {
161 printk(KERN_ERR "microcode: CPU%d not a capable Intel processor\n", cpu_num); 146 printk(KERN_ERR "microcode: CPU%d not a capable Intel "
147 "processor\n", cpu_num);
148 uci->valid = 0;
162 return; 149 return;
163 } else { 150 }
164 uci->sig = cpuid_eax(0x00000001);
165 151
166 if ((c->x86_model >= 5) || (c->x86 > 6)) { 152 uci->sig = cpuid_eax(0x00000001);
167 /* get processor flags from MSR 0x17 */ 153
168 rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); 154 if ((c->x86_model >= 5) || (c->x86 > 6)) {
169 uci->pf = 1 << ((val[1] >> 18) & 7); 155 /* get processor flags from MSR 0x17 */
170 } 156 rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
171 uci->orig_pf = uci->pf; 157 uci->pf = 1 << ((val[1] >> 18) & 7);
172 } 158 }
173 159
174 wrmsr(MSR_IA32_UCODE_REV, 0, 0); 160 wrmsr(MSR_IA32_UCODE_REV, 0, 0);
@@ -180,218 +166,159 @@ static void collect_cpu_info (void *unused)
180 uci->sig, uci->pf, uci->rev); 166 uci->sig, uci->pf, uci->rev);
181} 167}
182 168
183static inline void mark_microcode_update (int cpu_num, microcode_header_t *mc_header, int sig, int pf, int cksum) 169static inline int microcode_update_match(int cpu_num,
170 microcode_header_t *mc_header, int sig, int pf)
184{ 171{
185 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 172 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
186 173
187 pr_debug("Microcode Found.\n"); 174 if (!sigmatch(sig, uci->sig, pf, uci->pf)
188 pr_debug(" Header Revision 0x%x\n", mc_header->hdrver); 175 || mc_header->rev <= uci->rev)
189 pr_debug(" Loader Revision 0x%x\n", mc_header->ldrver); 176 return 0;
190 pr_debug(" Revision 0x%x \n", mc_header->rev); 177 return 1;
191 pr_debug(" Date %x/%x/%x\n",
192 ((mc_header->date >> 24 ) & 0xff),
193 ((mc_header->date >> 16 ) & 0xff),
194 (mc_header->date & 0xFFFF));
195 pr_debug(" Signature 0x%x\n", sig);
196 pr_debug(" Type 0x%x Family 0x%x Model 0x%x Stepping 0x%x\n",
197 ((sig >> 12) & 0x3),
198 ((sig >> 8) & 0xf),
199 ((sig >> 4) & 0xf),
200 ((sig & 0xf)));
201 pr_debug(" Processor Flags 0x%x\n", pf);
202 pr_debug(" Checksum 0x%x\n", cksum);
203
204 if (mc_header->rev < uci->rev) {
205 if (uci->err == MC_NOTFOUND) {
206 uci->err = MC_IGNORED;
207 uci->cksum = mc_header->rev;
208 } else if (uci->err == MC_IGNORED && uci->cksum < mc_header->rev)
209 uci->cksum = mc_header->rev;
210 } else if (mc_header->rev == uci->rev) {
211 if (uci->err < MC_MARKED) {
212 /* notify the caller of success on this cpu */
213 uci->err = MC_SUCCESS;
214 }
215 } else if (uci->err != MC_ALLOCATED || mc_header->rev > uci->mc->hdr.rev) {
216 pr_debug("microcode: CPU%d found a matching microcode update with "
217 " revision 0x%x (current=0x%x)\n", cpu_num, mc_header->rev, uci->rev);
218 uci->cksum = cksum;
219 uci->pf = pf; /* keep the original mc pf for cksum calculation */
220 uci->err = MC_MARKED; /* found the match */
221 for_each_online_cpu(cpu_num) {
222 if (ucode_cpu_info + cpu_num != uci
223 && ucode_cpu_info[cpu_num].mc == uci->mc) {
224 uci->mc = NULL;
225 break;
226 }
227 }
228 if (uci->mc != NULL) {
229 vfree(uci->mc);
230 uci->mc = NULL;
231 }
232 }
233 return;
234} 178}
235 179
236static int find_matching_ucodes (void) 180static int microcode_sanity_check(void *mc)
237{ 181{
238 int cursor = 0; 182 microcode_header_t *mc_header = mc;
239 int error = 0; 183 struct extended_sigtable *ext_header = NULL;
240 184 struct extended_signature *ext_sig;
241 while (cursor + MC_HEADER_SIZE < user_buffer_size) { 185 unsigned long total_size, data_size, ext_table_size;
242 microcode_header_t mc_header; 186 int sum, orig_sum, ext_sigcount = 0, i;
243 void *newmc = NULL; 187
244 int i, sum, cpu_num, allocated_flag, total_size, data_size, ext_table_size; 188 total_size = get_totalsize(mc_header);
189 data_size = get_datasize(mc_header);
190 if (data_size + MC_HEADER_SIZE > total_size) {
191 printk(KERN_ERR "microcode: error! "
192 "Bad data size in microcode data file\n");
193 return -EINVAL;
194 }
245 195
246 if (copy_from_user(&mc_header, user_buffer + cursor, MC_HEADER_SIZE)) { 196 if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
247 printk(KERN_ERR "microcode: error! Can not read user data\n"); 197 printk(KERN_ERR "microcode: error! "
248 error = -EFAULT; 198 "Unknown microcode update format\n");
249 goto out; 199 return -EINVAL;
200 }
201 ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
202 if (ext_table_size) {
203 if ((ext_table_size < EXT_HEADER_SIZE)
204 || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
205 printk(KERN_ERR "microcode: error! "
206 "Small exttable size in microcode data file\n");
207 return -EINVAL;
250 } 208 }
251 209 ext_header = mc + MC_HEADER_SIZE + data_size;
252 total_size = get_totalsize(&mc_header); 210 if (ext_table_size != exttable_size(ext_header)) {
253 if ((cursor + total_size > user_buffer_size) || (total_size < DEFAULT_UCODE_TOTALSIZE)) { 211 printk(KERN_ERR "microcode: error! "
254 printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); 212 "Bad exttable size in microcode data file\n");
255 error = -EINVAL; 213 return -EFAULT;
256 goto out;
257 } 214 }
215 ext_sigcount = ext_header->count;
216 }
258 217
259 data_size = get_datasize(&mc_header); 218 /* check extended table checksum */
260 if ((data_size + MC_HEADER_SIZE > total_size) || (data_size < DEFAULT_UCODE_DATASIZE)) { 219 if (ext_table_size) {
261 printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); 220 int ext_table_sum = 0;
262 error = -EINVAL; 221 int *ext_tablep = (int *)ext_header;
263 goto out; 222
223 i = ext_table_size / DWSIZE;
224 while (i--)
225 ext_table_sum += ext_tablep[i];
226 if (ext_table_sum) {
227 printk(KERN_WARNING "microcode: aborting, "
228 "bad extended signature table checksum\n");
229 return -EINVAL;
264 } 230 }
231 }
265 232
266 if (mc_header.ldrver != 1 || mc_header.hdrver != 1) { 233 /* calculate the checksum */
267 printk(KERN_ERR "microcode: error! Unknown microcode update format\n"); 234 orig_sum = 0;
268 error = -EINVAL; 235 i = (MC_HEADER_SIZE + data_size) / DWSIZE;
269 goto out; 236 while (i--)
237 orig_sum += ((int *)mc)[i];
238 if (orig_sum) {
239 printk(KERN_ERR "microcode: aborting, bad checksum\n");
240 return -EINVAL;
241 }
242 if (!ext_table_size)
243 return 0;
244 /* check extended signature checksum */
245 for (i = 0; i < ext_sigcount; i++) {
246 ext_sig = (struct extended_signature *)((void *)ext_header
247 + EXT_HEADER_SIZE + EXT_SIGNATURE_SIZE * i);
248 sum = orig_sum
249 - (mc_header->sig + mc_header->pf + mc_header->cksum)
250 + (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
251 if (sum) {
252 printk(KERN_ERR "microcode: aborting, bad checksum\n");
253 return -EINVAL;
270 } 254 }
255 }
256 return 0;
257}
271 258
272 for_each_online_cpu(cpu_num) { 259/*
273 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 260 * return 0 - no update found
274 261 * return 1 - found update
275 if (sigmatch(mc_header.sig, uci->sig, mc_header.pf, uci->orig_pf)) 262 * return < 0 - error
276 mark_microcode_update(cpu_num, &mc_header, mc_header.sig, mc_header.pf, mc_header.cksum); 263 */
277 } 264static int get_maching_microcode(void *mc, int cpu)
265{
266 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
267 microcode_header_t *mc_header = mc;
268 struct extended_sigtable *ext_header;
269 unsigned long total_size = get_totalsize(mc_header);
270 int ext_sigcount, i;
271 struct extended_signature *ext_sig;
272 void *new_mc;
273
274 if (microcode_update_match(cpu, mc_header,
275 mc_header->sig, mc_header->pf))
276 goto find;
277
278 if (total_size <= get_datasize(mc_header) + MC_HEADER_SIZE)
279 return 0;
280
281 ext_header = (struct extended_sigtable *)(mc +
282 get_datasize(mc_header) + MC_HEADER_SIZE);
283 ext_sigcount = ext_header->count;
284 ext_sig = (struct extended_signature *)((void *)ext_header
285 + EXT_HEADER_SIZE);
286 for (i = 0; i < ext_sigcount; i++) {
287 if (microcode_update_match(cpu, mc_header,
288 ext_sig->sig, ext_sig->pf))
289 goto find;
290 ext_sig++;
291 }
292 return 0;
293find:
294 pr_debug("microcode: CPU %d found a matching microcode update with"
295 " version 0x%x (current=0x%x)\n", cpu, mc_header->rev,uci->rev);
296 new_mc = vmalloc(total_size);
297 if (!new_mc) {
298 printk(KERN_ERR "microcode: error! Can not allocate memory\n");
299 return -ENOMEM;
300 }
278 301
279 ext_table_size = total_size - (MC_HEADER_SIZE + data_size); 302 /* free previous update file */
280 if (ext_table_size) { 303 vfree(uci->mc);
281 struct extended_sigtable ext_header;
282 struct extended_signature ext_sig;
283 int ext_sigcount;
284 304
285 if ((ext_table_size < EXT_HEADER_SIZE) 305 memcpy(new_mc, mc, total_size);
286 || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) { 306 uci->mc = new_mc;
287 printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); 307 return 1;
288 error = -EINVAL;
289 goto out;
290 }
291 if (copy_from_user(&ext_header, user_buffer + cursor
292 + MC_HEADER_SIZE + data_size, EXT_HEADER_SIZE)) {
293 printk(KERN_ERR "microcode: error! Can not read user data\n");
294 error = -EFAULT;
295 goto out;
296 }
297 if (ext_table_size != exttable_size(&ext_header)) {
298 printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
299 error = -EFAULT;
300 goto out;
301 }
302
303 ext_sigcount = ext_header.count;
304
305 for (i = 0; i < ext_sigcount; i++) {
306 if (copy_from_user(&ext_sig, user_buffer + cursor + MC_HEADER_SIZE + data_size + EXT_HEADER_SIZE
307 + EXT_SIGNATURE_SIZE * i, EXT_SIGNATURE_SIZE)) {
308 printk(KERN_ERR "microcode: error! Can not read user data\n");
309 error = -EFAULT;
310 goto out;
311 }
312 for_each_online_cpu(cpu_num) {
313 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
314
315 if (sigmatch(ext_sig.sig, uci->sig, ext_sig.pf, uci->orig_pf)) {
316 mark_microcode_update(cpu_num, &mc_header, ext_sig.sig, ext_sig.pf, ext_sig.cksum);
317 }
318 }
319 }
320 }
321 /* now check if any cpu has matched */
322 allocated_flag = 0;
323 sum = 0;
324 for_each_online_cpu(cpu_num) {
325 if (ucode_cpu_info[cpu_num].err == MC_MARKED) {
326 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
327 if (!allocated_flag) {
328 allocated_flag = 1;
329 newmc = vmalloc(total_size);
330 if (!newmc) {
331 printk(KERN_ERR "microcode: error! Can not allocate memory\n");
332 error = -ENOMEM;
333 goto out;
334 }
335 if (copy_from_user(newmc + MC_HEADER_SIZE,
336 user_buffer + cursor + MC_HEADER_SIZE,
337 total_size - MC_HEADER_SIZE)) {
338 printk(KERN_ERR "microcode: error! Can not read user data\n");
339 vfree(newmc);
340 error = -EFAULT;
341 goto out;
342 }
343 memcpy(newmc, &mc_header, MC_HEADER_SIZE);
344 /* check extended table checksum */
345 if (ext_table_size) {
346 int ext_table_sum = 0;
347 int * ext_tablep = (((void *) newmc) + MC_HEADER_SIZE + data_size);
348 i = ext_table_size / DWSIZE;
349 while (i--) ext_table_sum += ext_tablep[i];
350 if (ext_table_sum) {
351 printk(KERN_WARNING "microcode: aborting, bad extended signature table checksum\n");
352 vfree(newmc);
353 error = -EINVAL;
354 goto out;
355 }
356 }
357
358 /* calculate the checksum */
359 i = (MC_HEADER_SIZE + data_size) / DWSIZE;
360 while (i--) sum += ((int *)newmc)[i];
361 sum -= (mc_header.sig + mc_header.pf + mc_header.cksum);
362 }
363 ucode_cpu_info[cpu_num].mc = newmc;
364 ucode_cpu_info[cpu_num].err = MC_ALLOCATED; /* mc updated */
365 if (sum + uci->sig + uci->pf + uci->cksum != 0) {
366 printk(KERN_ERR "microcode: CPU%d aborting, bad checksum\n", cpu_num);
367 error = -EINVAL;
368 goto out;
369 }
370 }
371 }
372 cursor += total_size; /* goto the next update patch */
373 } /* end of while */
374out:
375 return error;
376} 308}
377 309
378static void do_update_one (void * unused) 310static void apply_microcode(int cpu)
379{ 311{
380 unsigned long flags; 312 unsigned long flags;
381 unsigned int val[2]; 313 unsigned int val[2];
382 int cpu_num = smp_processor_id(); 314 int cpu_num = raw_smp_processor_id();
383 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num; 315 struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
384 316
385 if (uci->mc == NULL) { 317 /* We should bind the task to the CPU */
386 if (verbose) { 318 BUG_ON(cpu_num != cpu);
387 if (uci->err == MC_SUCCESS) 319
388 printk(KERN_INFO "microcode: CPU%d already at revision 0x%x\n", 320 if (uci->mc == NULL)
389 cpu_num, uci->rev);
390 else
391 printk(KERN_INFO "microcode: No new microcode data for CPU%d\n", cpu_num);
392 }
393 return; 321 return;
394 }
395 322
396 /* serialize access to the physical write to MSR 0x79 */ 323 /* serialize access to the physical write to MSR 0x79 */
397 spin_lock_irqsave(&microcode_update_lock, flags); 324 spin_lock_irqsave(&microcode_update_lock, flags);
@@ -408,68 +335,107 @@ static void do_update_one (void * unused)
408 /* get the current revision from MSR 0x8B */ 335 /* get the current revision from MSR 0x8B */
409 rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); 336 rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
410 337
411 /* notify the caller of success on this cpu */
412 uci->err = MC_SUCCESS;
413 spin_unlock_irqrestore(&microcode_update_lock, flags); 338 spin_unlock_irqrestore(&microcode_update_lock, flags);
414 printk(KERN_INFO "microcode: CPU%d updated from revision " 339 if (val[1] != uci->mc->hdr.rev) {
340 printk(KERN_ERR "microcode: CPU%d updated from revision "
341 "0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]);
342 return;
343 }
344 pr_debug("microcode: CPU%d updated from revision "
415 "0x%x to 0x%x, date = %08x \n", 345 "0x%x to 0x%x, date = %08x \n",
416 cpu_num, uci->rev, val[1], uci->mc->hdr.date); 346 cpu_num, uci->rev, val[1], uci->mc->hdr.date);
417 return; 347 uci->rev = val[1];
418} 348}
419 349
420static int do_microcode_update (void) 350#ifdef CONFIG_MICROCODE_OLD_INTERFACE
421{ 351static void __user *user_buffer; /* user area microcode data buffer */
422 int i, error; 352static unsigned int user_buffer_size; /* it's size */
423 353
424 if (on_each_cpu(collect_cpu_info, NULL, 1, 1) != 0) { 354static long get_next_ucode(void **mc, long offset)
425 printk(KERN_ERR "microcode: Error! Could not run on all processors\n"); 355{
426 error = -EIO; 356 microcode_header_t mc_header;
427 goto out; 357 unsigned long total_size;
358
359 /* No more data */
360 if (offset >= user_buffer_size)
361 return 0;
362 if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) {
363 printk(KERN_ERR "microcode: error! Can not read user data\n");
364 return -EFAULT;
428 } 365 }
429 366 total_size = get_totalsize(&mc_header);
430 if ((error = find_matching_ucodes())) { 367 if (offset + total_size > user_buffer_size) {
431 printk(KERN_ERR "microcode: Error in the microcode data\n"); 368 printk(KERN_ERR "microcode: error! Bad total size in microcode "
432 goto out_free; 369 "data file\n");
370 return -EINVAL;
433 } 371 }
434 372 *mc = vmalloc(total_size);
435 if (on_each_cpu(do_update_one, NULL, 1, 1) != 0) { 373 if (!*mc)
436 printk(KERN_ERR "microcode: Error! Could not run on all processors\n"); 374 return -ENOMEM;
437 error = -EIO; 375 if (copy_from_user(*mc, user_buffer + offset, total_size)) {
376 printk(KERN_ERR "microcode: error! Can not read user data\n");
377 vfree(*mc);
378 return -EFAULT;
438 } 379 }
380 return offset + total_size;
381}
382
383static int do_microcode_update (void)
384{
385 long cursor = 0;
386 int error = 0;
387 void *new_mc;
388 int cpu;
389 cpumask_t old;
390
391 old = current->cpus_allowed;
439 392
440out_free: 393 while ((cursor = get_next_ucode(&new_mc, cursor)) > 0) {
441 for_each_online_cpu(i) { 394 error = microcode_sanity_check(new_mc);
442 if (ucode_cpu_info[i].mc) { 395 if (error)
443 int j; 396 goto out;
444 void *tmp = ucode_cpu_info[i].mc; 397 /*
445 vfree(tmp); 398 * It's possible the data file has multiple matching ucode,
446 for_each_online_cpu(j) { 399 * lets keep searching till the latest version
447 if (ucode_cpu_info[j].mc == tmp) 400 */
448 ucode_cpu_info[j].mc = NULL; 401 for_each_online_cpu(cpu) {
449 } 402 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
403
404 if (!uci->valid)
405 continue;
406 set_cpus_allowed(current, cpumask_of_cpu(cpu));
407 error = get_maching_microcode(new_mc, cpu);
408 if (error < 0)
409 goto out;
410 if (error == 1)
411 apply_microcode(cpu);
450 } 412 }
451 if (ucode_cpu_info[i].err == MC_IGNORED && verbose) 413 vfree(new_mc);
452 printk(KERN_WARNING "microcode: CPU%d not 'upgrading' to earlier revision"
453 " 0x%x (current=0x%x)\n", i, ucode_cpu_info[i].cksum, ucode_cpu_info[i].rev);
454 } 414 }
455out: 415out:
416 if (cursor > 0)
417 vfree(new_mc);
418 if (cursor < 0)
419 error = cursor;
420 set_cpus_allowed(current, old);
456 return error; 421 return error;
457} 422}
458 423
424static int microcode_open (struct inode *unused1, struct file *unused2)
425{
426 return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
427}
428
459static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos) 429static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos)
460{ 430{
461 ssize_t ret; 431 ssize_t ret;
462 432
463 if (len < DEFAULT_UCODE_TOTALSIZE) {
464 printk(KERN_ERR "microcode: not enough data\n");
465 return -EINVAL;
466 }
467
468 if ((len >> PAGE_SHIFT) > num_physpages) { 433 if ((len >> PAGE_SHIFT) > num_physpages) {
469 printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages); 434 printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages);
470 return -EINVAL; 435 return -EINVAL;
471 } 436 }
472 437
438 lock_cpu_hotplug();
473 mutex_lock(&microcode_mutex); 439 mutex_lock(&microcode_mutex);
474 440
475 user_buffer = (void __user *) buf; 441 user_buffer = (void __user *) buf;
@@ -480,6 +446,7 @@ static ssize_t microcode_write (struct file *file, const char __user *buf, size_
480 ret = (ssize_t)len; 446 ret = (ssize_t)len;
481 447
482 mutex_unlock(&microcode_mutex); 448 mutex_unlock(&microcode_mutex);
449 unlock_cpu_hotplug();
483 450
484 return ret; 451 return ret;
485} 452}
@@ -496,7 +463,7 @@ static struct miscdevice microcode_dev = {
496 .fops = &microcode_fops, 463 .fops = &microcode_fops,
497}; 464};
498 465
499static int __init microcode_init (void) 466static int __init microcode_dev_init (void)
500{ 467{
501 int error; 468 int error;
502 469
@@ -508,6 +475,280 @@ static int __init microcode_init (void)
508 return error; 475 return error;
509 } 476 }
510 477
478 return 0;
479}
480
481static void __exit microcode_dev_exit (void)
482{
483 misc_deregister(&microcode_dev);
484}
485
486MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);
487#else
488#define microcode_dev_init() 0
489#define microcode_dev_exit() do { } while(0)
490#endif
491
492static long get_next_ucode_from_buffer(void **mc, void *buf,
493 unsigned long size, long offset)
494{
495 microcode_header_t *mc_header;
496 unsigned long total_size;
497
498 /* No more data */
499 if (offset >= size)
500 return 0;
501 mc_header = (microcode_header_t *)(buf + offset);
502 total_size = get_totalsize(mc_header);
503
504 if (offset + total_size > size) {
505 printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
506 return -EINVAL;
507 }
508
509 *mc = vmalloc(total_size);
510 if (!*mc) {
511 printk(KERN_ERR "microcode: error! Can not allocate memory\n");
512 return -ENOMEM;
513 }
514 memcpy(*mc, buf + offset, total_size);
515 return offset + total_size;
516}
517
518/* fake device for request_firmware */
519static struct platform_device *microcode_pdev;
520
521static int cpu_request_microcode(int cpu)
522{
523 char name[30];
524 struct cpuinfo_x86 *c = cpu_data + cpu;
525 const struct firmware *firmware;
526 void *buf;
527 unsigned long size;
528 long offset = 0;
529 int error;
530 void *mc;
531
532 /* We should bind the task to the CPU */
533 BUG_ON(cpu != raw_smp_processor_id());
534 sprintf(name,"intel-ucode/%02x-%02x-%02x",
535 c->x86, c->x86_model, c->x86_mask);
536 error = request_firmware(&firmware, name, &microcode_pdev->dev);
537 if (error) {
538 pr_debug("ucode data file %s load failed\n", name);
539 return error;
540 }
541 buf = (void *)firmware->data;
542 size = firmware->size;
543 while ((offset = get_next_ucode_from_buffer(&mc, buf, size, offset))
544 > 0) {
545 error = microcode_sanity_check(mc);
546 if (error)
547 break;
548 error = get_maching_microcode(mc, cpu);
549 if (error < 0)
550 break;
551 /*
552 * It's possible the data file has multiple matching ucode,
553 * lets keep searching till the latest version
554 */
555 if (error == 1) {
556 apply_microcode(cpu);
557 error = 0;
558 }
559 vfree(mc);
560 }
561 if (offset > 0)
562 vfree(mc);
563 if (offset < 0)
564 error = offset;
565 release_firmware(firmware);
566
567 return error;
568}
569
570static void microcode_init_cpu(int cpu)
571{
572 cpumask_t old;
573 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
574
575 old = current->cpus_allowed;
576
577 set_cpus_allowed(current, cpumask_of_cpu(cpu));
578 mutex_lock(&microcode_mutex);
579 collect_cpu_info(cpu);
580 if (uci->valid)
581 cpu_request_microcode(cpu);
582 mutex_unlock(&microcode_mutex);
583 set_cpus_allowed(current, old);
584}
585
586static void microcode_fini_cpu(int cpu)
587{
588 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
589
590 mutex_lock(&microcode_mutex);
591 uci->valid = 0;
592 vfree(uci->mc);
593 uci->mc = NULL;
594 mutex_unlock(&microcode_mutex);
595}
596
597static ssize_t reload_store(struct sys_device *dev, const char *buf, size_t sz)
598{
599 struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
600 char *end;
601 unsigned long val = simple_strtoul(buf, &end, 0);
602 int err = 0;
603 int cpu = dev->id;
604
605 if (end == buf)
606 return -EINVAL;
607 if (val == 1) {
608 cpumask_t old;
609
610 old = current->cpus_allowed;
611
612 lock_cpu_hotplug();
613 set_cpus_allowed(current, cpumask_of_cpu(cpu));
614
615 mutex_lock(&microcode_mutex);
616 if (uci->valid)
617 err = cpu_request_microcode(cpu);
618 mutex_unlock(&microcode_mutex);
619 unlock_cpu_hotplug();
620 set_cpus_allowed(current, old);
621 }
622 if (err)
623 return err;
624 return sz;
625}
626
627static ssize_t version_show(struct sys_device *dev, char *buf)
628{
629 struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
630
631 return sprintf(buf, "0x%x\n", uci->rev);
632}
633
634static ssize_t pf_show(struct sys_device *dev, char *buf)
635{
636 struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
637
638 return sprintf(buf, "0x%x\n", uci->pf);
639}
640
641static SYSDEV_ATTR(reload, 0200, NULL, reload_store);
642static SYSDEV_ATTR(version, 0400, version_show, NULL);
643static SYSDEV_ATTR(processor_flags, 0400, pf_show, NULL);
644
645static struct attribute *mc_default_attrs[] = {
646 &attr_reload.attr,
647 &attr_version.attr,
648 &attr_processor_flags.attr,
649 NULL
650};
651
652static struct attribute_group mc_attr_group = {
653 .attrs = mc_default_attrs,
654 .name = "microcode",
655};
656
657static int mc_sysdev_add(struct sys_device *sys_dev)
658{
659 int cpu = sys_dev->id;
660 struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
661
662 if (!cpu_online(cpu))
663 return 0;
664 pr_debug("Microcode:CPU %d added\n", cpu);
665 memset(uci, 0, sizeof(*uci));
666 sysfs_create_group(&sys_dev->kobj, &mc_attr_group);
667
668 microcode_init_cpu(cpu);
669 return 0;
670}
671
672static int mc_sysdev_remove(struct sys_device *sys_dev)
673{
674 int cpu = sys_dev->id;
675
676 if (!cpu_online(cpu))
677 return 0;
678 pr_debug("Microcode:CPU %d removed\n", cpu);
679 microcode_fini_cpu(cpu);
680 sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
681 return 0;
682}
683
684static int mc_sysdev_resume(struct sys_device *dev)
685{
686 int cpu = dev->id;
687
688 if (!cpu_online(cpu))
689 return 0;
690 pr_debug("Microcode:CPU %d resumed\n", cpu);
691 /* only CPU 0 will apply ucode here */
692 apply_microcode(0);
693 return 0;
694}
695
696static struct sysdev_driver mc_sysdev_driver = {
697 .add = mc_sysdev_add,
698 .remove = mc_sysdev_remove,
699 .resume = mc_sysdev_resume,
700};
701
702#ifdef CONFIG_HOTPLUG_CPU
703static __cpuinit int
704mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
705{
706 unsigned int cpu = (unsigned long)hcpu;
707 struct sys_device *sys_dev;
708
709 sys_dev = get_cpu_sysdev(cpu);
710 switch (action) {
711 case CPU_ONLINE:
712 case CPU_DOWN_FAILED:
713 mc_sysdev_add(sys_dev);
714 break;
715 case CPU_DOWN_PREPARE:
716 mc_sysdev_remove(sys_dev);
717 break;
718 }
719 return NOTIFY_OK;
720}
721
722static struct notifier_block mc_cpu_notifier = {
723 .notifier_call = mc_cpu_callback,
724};
725#endif
726
727static int __init microcode_init (void)
728{
729 int error;
730
731 error = microcode_dev_init();
732 if (error)
733 return error;
734 microcode_pdev = platform_device_register_simple("microcode", -1,
735 NULL, 0);
736 if (IS_ERR(microcode_pdev)) {
737 microcode_dev_exit();
738 return PTR_ERR(microcode_pdev);
739 }
740
741 lock_cpu_hotplug();
742 error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver);
743 unlock_cpu_hotplug();
744 if (error) {
745 microcode_dev_exit();
746 platform_device_unregister(microcode_pdev);
747 return error;
748 }
749
750 register_hotcpu_notifier(&mc_cpu_notifier);
751
511 printk(KERN_INFO 752 printk(KERN_INFO
512 "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@veritas.com>\n"); 753 "IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@veritas.com>\n");
513 return 0; 754 return 0;
@@ -515,9 +756,16 @@ static int __init microcode_init (void)
515 756
516static void __exit microcode_exit (void) 757static void __exit microcode_exit (void)
517{ 758{
518 misc_deregister(&microcode_dev); 759 microcode_dev_exit();
760
761 unregister_hotcpu_notifier(&mc_cpu_notifier);
762
763 lock_cpu_hotplug();
764 sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver);
765 unlock_cpu_hotplug();
766
767 platform_device_unregister(microcode_pdev);
519} 768}
520 769
521module_init(microcode_init) 770module_init(microcode_init)
522module_exit(microcode_exit) 771module_exit(microcode_exit)
523MODULE_ALIAS_MISCDEV(MICROCODE_MINOR);