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