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.10 of Volume III, Intel Pentium 4 Manual,
12 *	Order Number 245472 or free download from:
13 *
14 *	http://developer.intel.com/design/pentium4/manuals/245472.htm
15 *
16 *	For more information, go to http://www.urbanmyth.org/microcode
17 *
18 *	This program is free software; you can redistribute it and/or
19 *	modify it under the terms of the GNU General Public License
20 *	as published by the Free Software Foundation; either version
21 *	2 of the License, or (at your option) any later version.
22 *
23 *	1.0	16 Feb 2000, Tigran Aivazian <tigran@sco.com>
24 *		Initial release.
25 *	1.01	18 Feb 2000, Tigran Aivazian <tigran@sco.com>
26 *		Added read() support + cleanups.
27 *	1.02	21 Feb 2000, Tigran Aivazian <tigran@sco.com>
28 *		Added 'device trimming' support. open(O_WRONLY) zeroes
29 *		and frees the saved copy of applied microcode.
30 *	1.03	29 Feb 2000, Tigran Aivazian <tigran@sco.com>
31 *		Made to use devfs (/dev/cpu/microcode) + cleanups.
32 *	1.04	06 Jun 2000, Simon Trimmer <simon@veritas.com>
33 *		Added misc device support (now uses both devfs and misc).
34 *		Added MICROCODE_IOCFREE ioctl to clear memory.
35 *	1.05	09 Jun 2000, Simon Trimmer <simon@veritas.com>
36 *		Messages for error cases (non Intel & no suitable microcode).
37 *	1.06	03 Aug 2000, Tigran Aivazian <tigran@veritas.com>
38 *		Removed ->release(). Removed exclusive open and status bitmap.
39 *		Added microcode_rwsem to serialize read()/write()/ioctl().
40 *		Removed global kernel lock usage.
41 *	1.07	07 Sep 2000, Tigran Aivazian <tigran@veritas.com>
42 *		Write 0 to 0x8B msr and then cpuid before reading revision,
43 *		so that it works even if there were no update done by the
44 *		BIOS. Otherwise, reading from 0x8B gives junk (which happened
45 *		to be 0 on my machine which is why it worked even when I
46 *		disabled update by the BIOS)
47 *		Thanks to Eric W. Biederman <ebiederman@lnxi.com> for the fix.
48 *	1.08	11 Dec 2000, Richard Schaal <richard.schaal@intel.com> and
49 *			     Tigran Aivazian <tigran@veritas.com>
50 *		Intel Pentium 4 processor support and bugfixes.
51 *	1.09	30 Oct 2001, Tigran Aivazian <tigran@veritas.com>
52 *		Bugfix for HT (Hyper-Threading) enabled processors
53 *		whereby processor resources are shared by all logical processors
54 *		in a single CPU package.
55 *	1.10	28 Feb 2002 Asit K Mallick <asit.k.mallick@intel.com> and
56 *		Tigran Aivazian <tigran@veritas.com>,
57 *		Serialize updates as required on HT processors due to speculative
58 *		nature of implementation.
59 *	1.11	22 Mar 2002 Tigran Aivazian <tigran@veritas.com>
60 *		Fix the panic when writing zero-length microcode chunk.
61 *	1.12	29 Sep 2003 Nitin Kamble <nitin.a.kamble@intel.com>,
62 *		Jun Nakajima <jun.nakajima@intel.com>
63 *		Support for the microcode updates in the new format.
64 *	1.13	10 Oct 2003 Tigran Aivazian <tigran@veritas.com>
65 *		Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl
66 *		because we no longer hold a copy of applied microcode
67 *		in kernel memory.
68 *	1.14	25 Jun 2004 Tigran Aivazian <tigran@veritas.com>
69 *		Fix sigmatch() macro to handle old CPUs with pf == 0.
70 *		Thanks to Stuart Swales for pointing out this bug.
71 */
72
73//#define DEBUG /* pr_debug */
74#include <linux/capability.h>
75#include <linux/kernel.h>
76#include <linux/init.h>
77#include <linux/sched.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/mutex.h>
86#include <linux/cpu.h>
87#include <linux/firmware.h>
88#include <linux/platform_device.h>
89
90#include <asm/msr.h>
91#include <asm/uaccess.h>
92#include <asm/processor.h>
93
94MODULE_DESCRIPTION("Intel CPU (IA-32) Microcode Update Driver");
95MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
96MODULE_LICENSE("GPL");
97
98#define MICROCODE_VERSION 	"1.14a"
99
100#define DEFAULT_UCODE_DATASIZE 	(2000) 	  /* 2000 bytes */
101#define MC_HEADER_SIZE		(sizeof (microcode_header_t))  	  /* 48 bytes */
102#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */
103#define EXT_HEADER_SIZE		(sizeof (struct extended_sigtable)) /* 20 bytes */
104#define EXT_SIGNATURE_SIZE	(sizeof (struct extended_signature)) /* 12 bytes */
105#define DWSIZE			(sizeof (u32))
106#define get_totalsize(mc) \
107	(((microcode_t *)mc)->hdr.totalsize ? \
108	 ((microcode_t *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE)
109#define get_datasize(mc) \
110	(((microcode_t *)mc)->hdr.datasize ? \
111	 ((microcode_t *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE)
112
113#define sigmatch(s1, s2, p1, p2) \
114	(((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0))))
115
116#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)
117
118/* serialize access to the physical write to MSR 0x79 */
119static DEFINE_SPINLOCK(microcode_update_lock);
120
121/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
122static DEFINE_MUTEX(microcode_mutex);
123
124static struct ucode_cpu_info {
125	int valid;
126	unsigned int sig;
127	unsigned int pf;
128	unsigned int rev;
129	microcode_t *mc;
130} ucode_cpu_info[NR_CPUS];
131
132static void collect_cpu_info(int cpu_num)
133{
134	struct cpuinfo_x86 *c = cpu_data + cpu_num;
135	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
136	unsigned int val[2];
137
138	/* We should bind the task to the CPU */
139	BUG_ON(raw_smp_processor_id() != cpu_num);
140	uci->pf = uci->rev = 0;
141	uci->mc = NULL;
142	uci->valid = 1;
143
144	if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
145	    	cpu_has(c, X86_FEATURE_IA64)) {
146		printk(KERN_ERR "microcode: CPU%d not a capable Intel "
147			"processor\n", cpu_num);
148		uci->valid = 0;
149		return;
150	}
151
152	uci->sig = cpuid_eax(0x00000001);
153
154	if ((c->x86_model >= 5) || (c->x86 > 6)) {
155		/* get processor flags from MSR 0x17 */
156		rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
157		uci->pf = 1 << ((val[1] >> 18) & 7);
158	}
159
160	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
161	/* see notes above for revision 1.07.  Apparent chip bug */
162	sync_core();
163	/* get the current revision from MSR 0x8B */
164	rdmsr(MSR_IA32_UCODE_REV, val[0], uci->rev);
165	pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n",
166			uci->sig, uci->pf, uci->rev);
167}
168
169static inline int microcode_update_match(int cpu_num,
170	microcode_header_t *mc_header, int sig, int pf)
171{
172	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
173
174	if (!sigmatch(sig, uci->sig, pf, uci->pf)
175		|| mc_header->rev <= uci->rev)
176		return 0;
177	return 1;
178}
179
180static int microcode_sanity_check(void *mc)
181{
182	microcode_header_t *mc_header = mc;
183	struct extended_sigtable *ext_header = NULL;
184	struct extended_signature *ext_sig;
185	unsigned long total_size, data_size, ext_table_size;
186	int sum, orig_sum, ext_sigcount = 0, i;
187
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	}
195
196	if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
197		printk(KERN_ERR "microcode: error! "
198			"Unknown microcode update format\n");
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;
208		}
209		ext_header = mc + MC_HEADER_SIZE + data_size;
210		if (ext_table_size != exttable_size(ext_header)) {
211			printk(KERN_ERR "microcode: error! "
212				"Bad exttable size in microcode data file\n");
213			return -EFAULT;
214		}
215		ext_sigcount = ext_header->count;
216	}
217
218	/* check extended table checksum */
219	if (ext_table_size) {
220		int ext_table_sum = 0;
221		int *ext_tablep = (int *)ext_header;
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;
230		}
231	}
232
233	/* calculate the checksum */
234	orig_sum = 0;
235	i = (MC_HEADER_SIZE + data_size) / DWSIZE;
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;
254		}
255	}
256	return 0;
257}
258
259/*
260 * return 0 - no update found
261 * return 1 - found update
262 * return < 0 - error
263 */
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	}
301
302	/* free previous update file */
303	vfree(uci->mc);
304
305	memcpy(new_mc, mc, total_size);
306	uci->mc = new_mc;
307	return 1;
308}
309
310static void apply_microcode(int cpu)
311{
312	unsigned long flags;
313	unsigned int val[2];
314	int cpu_num = raw_smp_processor_id();
315	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
316
317	/* We should bind the task to the CPU */
318	BUG_ON(cpu_num != cpu);
319
320	if (uci->mc == NULL)
321		return;
322
323	/* serialize access to the physical write to MSR 0x79 */
324	spin_lock_irqsave(&microcode_update_lock, flags);
325
326	/* write microcode via MSR 0x79 */
327	wrmsr(MSR_IA32_UCODE_WRITE,
328		(unsigned long) uci->mc->bits,
329		(unsigned long) uci->mc->bits >> 16 >> 16);
330	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
331
332	/* see notes above for revision 1.07.  Apparent chip bug */
333	sync_core();
334
335	/* get the current revision from MSR 0x8B */
336	rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
337
338	spin_unlock_irqrestore(&microcode_update_lock, flags);
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 "
345	       "0x%x to 0x%x, date = %08x \n",
346	       cpu_num, uci->rev, val[1], uci->mc->hdr.date);
347	uci->rev = val[1];
348}
349
350#ifdef CONFIG_MICROCODE_OLD_INTERFACE
351static void __user *user_buffer;	/* user area microcode data buffer */
352static unsigned int user_buffer_size;	/* it's size */
353
354static long get_next_ucode(void **mc, long offset)
355{
356	microcode_header_t mc_header;
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;
365	}
366	total_size = get_totalsize(&mc_header);
367	if (offset + total_size > user_buffer_size) {
368		printk(KERN_ERR "microcode: error! Bad total size in microcode "
369				"data file\n");
370		return -EINVAL;
371	}
372	*mc = vmalloc(total_size);
373	if (!*mc)
374		return -ENOMEM;
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;
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 = NULL;
388	int cpu;
389	cpumask_t old;
390
391	old = current->cpus_allowed;
392
393	while ((cursor = get_next_ucode(&new_mc, cursor)) > 0) {
394		error = microcode_sanity_check(new_mc);
395		if (error)
396			goto out;
397		/*
398		 * It's possible the data file has multiple matching ucode,
399		 * lets keep searching till the latest version
400		 */
401		for_each_online_cpu(cpu) {
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);
412		}
413		vfree(new_mc);
414	}
415out:
416	if (cursor > 0)
417		vfree(new_mc);
418	if (cursor < 0)
419		error = cursor;
420	set_cpus_allowed(current, old);
421	return error;
422}
423
424static int microcode_open (struct inode *unused1, struct file *unused2)
425{
426	return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
427}
428
429static ssize_t microcode_write (struct file *file, const char __user *buf, size_t len, loff_t *ppos)
430{
431	ssize_t ret;
432
433	if ((len >> PAGE_SHIFT) > num_physpages) {
434		printk(KERN_ERR "microcode: too much data (max %ld pages)\n", num_physpages);
435		return -EINVAL;
436	}
437
438	lock_cpu_hotplug();
439	mutex_lock(&microcode_mutex);
440
441	user_buffer = (void __user *) buf;
442	user_buffer_size = (int) len;
443
444	ret = do_microcode_update();
445	if (!ret)
446		ret = (ssize_t)len;
447
448	mutex_unlock(&microcode_mutex);
449	unlock_cpu_hotplug();
450
451	return ret;
452}
453
454static const struct file_operations microcode_fops = {
455	.owner		= THIS_MODULE,
456	.write		= microcode_write,
457	.open		= microcode_open,
458};
459
460static struct miscdevice microcode_dev = {
461	.minor		= MICROCODE_MINOR,
462	.name		= "microcode",
463	.fops		= &microcode_fops,
464};
465
466static int __init microcode_dev_init (void)
467{
468	int error;
469
470	error = misc_register(&microcode_dev);
471	if (error) {
472		printk(KERN_ERR
473			"microcode: can't misc_register on minor=%d\n",
474			MICROCODE_MINOR);
475		return error;
476	}
477
478	return 0;
479}
480
481static void 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 int apply_microcode_check_cpu(int cpu)
571{
572	struct cpuinfo_x86 *c = cpu_data + cpu;
573	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
574	cpumask_t old;
575	unsigned int val[2];
576	int err = 0;
577
578	/* Check if the microcode is available */
579	if (!uci->mc)
580		return 0;
581
582	old = current->cpus_allowed;
583	set_cpus_allowed(current, cpumask_of_cpu(cpu));
584
585	/* Check if the microcode we have in memory matches the CPU */
586	if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
587	    cpu_has(c, X86_FEATURE_IA64) || uci->sig != cpuid_eax(0x00000001))
588		err = -EINVAL;
589
590	if (!err && ((c->x86_model >= 5) || (c->x86 > 6))) {
591		/* get processor flags from MSR 0x17 */
592		rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
593		if (uci->pf != (1 << ((val[1] >> 18) & 7)))
594			err = -EINVAL;
595	}
596
597	if (!err) {
598		wrmsr(MSR_IA32_UCODE_REV, 0, 0);
599		/* see notes above for revision 1.07.  Apparent chip bug */
600		sync_core();
601		/* get the current revision from MSR 0x8B */
602		rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
603		if (uci->rev != val[1])
604			err = -EINVAL;
605	}
606
607	if (!err)
608		apply_microcode(cpu);
609	else
610		printk(KERN_ERR "microcode: Could not apply microcode to CPU%d:"
611			" sig=0x%x, pf=0x%x, rev=0x%x\n",
612			cpu, uci->sig, uci->pf, uci->rev);
613
614	set_cpus_allowed(current, old);
615	return err;
616}
617
618static void microcode_init_cpu(int cpu, int resume)
619{
620	cpumask_t old;
621	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
622
623	old = current->cpus_allowed;
624
625	set_cpus_allowed(current, cpumask_of_cpu(cpu));
626	mutex_lock(&microcode_mutex);
627	collect_cpu_info(cpu);
628	if (uci->valid && system_state == SYSTEM_RUNNING && !resume)
629		cpu_request_microcode(cpu);
630	mutex_unlock(&microcode_mutex);
631	set_cpus_allowed(current, old);
632}
633
634static void microcode_fini_cpu(int cpu)
635{
636	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
637
638	mutex_lock(&microcode_mutex);
639	uci->valid = 0;
640	vfree(uci->mc);
641	uci->mc = NULL;
642	mutex_unlock(&microcode_mutex);
643}
644
645static ssize_t reload_store(struct sys_device *dev, const char *buf, size_t sz)
646{
647	struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
648	char *end;
649	unsigned long val = simple_strtoul(buf, &end, 0);
650	int err = 0;
651	int cpu = dev->id;
652
653	if (end == buf)
654		return -EINVAL;
655	if (val == 1) {
656		cpumask_t old;
657
658		old = current->cpus_allowed;
659
660		lock_cpu_hotplug();
661		set_cpus_allowed(current, cpumask_of_cpu(cpu));
662
663		mutex_lock(&microcode_mutex);
664		if (uci->valid)
665			err = cpu_request_microcode(cpu);
666		mutex_unlock(&microcode_mutex);
667		unlock_cpu_hotplug();
668		set_cpus_allowed(current, old);
669	}
670	if (err)
671		return err;
672	return sz;
673}
674
675static ssize_t version_show(struct sys_device *dev, char *buf)
676{
677	struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
678
679	return sprintf(buf, "0x%x\n", uci->rev);
680}
681
682static ssize_t pf_show(struct sys_device *dev, char *buf)
683{
684	struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;
685
686	return sprintf(buf, "0x%x\n", uci->pf);
687}
688
689static SYSDEV_ATTR(reload, 0200, NULL, reload_store);
690static SYSDEV_ATTR(version, 0400, version_show, NULL);
691static SYSDEV_ATTR(processor_flags, 0400, pf_show, NULL);
692
693static struct attribute *mc_default_attrs[] = {
694	&attr_reload.attr,
695	&attr_version.attr,
696	&attr_processor_flags.attr,
697	NULL
698};
699
700static struct attribute_group mc_attr_group = {
701	.attrs = mc_default_attrs,
702	.name = "microcode",
703};
704
705static int __mc_sysdev_add(struct sys_device *sys_dev, int resume)
706{
707	int err, cpu = sys_dev->id;
708	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
709
710	if (!cpu_online(cpu))
711		return 0;
712
713	pr_debug("Microcode:CPU %d added\n", cpu);
714	memset(uci, 0, sizeof(*uci));
715
716	err = sysfs_create_group(&sys_dev->kobj, &mc_attr_group);
717	if (err)
718		return err;
719
720	microcode_init_cpu(cpu, resume);
721
722	return 0;
723}
724
725static int mc_sysdev_add(struct sys_device *sys_dev)
726{
727	return __mc_sysdev_add(sys_dev, 0);
728}
729
730static int mc_sysdev_remove(struct sys_device *sys_dev)
731{
732	int cpu = sys_dev->id;
733
734	if (!cpu_online(cpu))
735		return 0;
736
737	pr_debug("Microcode:CPU %d removed\n", cpu);
738	microcode_fini_cpu(cpu);
739	sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
740	return 0;
741}
742
743static int mc_sysdev_resume(struct sys_device *dev)
744{
745	int cpu = dev->id;
746
747	if (!cpu_online(cpu))
748		return 0;
749	pr_debug("Microcode:CPU %d resumed\n", cpu);
750	/* only CPU 0 will apply ucode here */
751	apply_microcode(0);
752	return 0;
753}
754
755static struct sysdev_driver mc_sysdev_driver = {
756	.add = mc_sysdev_add,
757	.remove = mc_sysdev_remove,
758	.resume = mc_sysdev_resume,
759};
760
761static __cpuinit int
762mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu)
763{
764	unsigned int cpu = (unsigned long)hcpu;
765	struct sys_device *sys_dev;
766
767	sys_dev = get_cpu_sysdev(cpu);
768	switch (action) {
769	case CPU_UP_CANCELED_FROZEN:
770		/* The CPU refused to come up during a system resume */
771		microcode_fini_cpu(cpu);
772		break;
773	case CPU_ONLINE:
774	case CPU_DOWN_FAILED:
775		mc_sysdev_add(sys_dev);
776		break;
777	case CPU_ONLINE_FROZEN:
778		/* System-wide resume is in progress, try to apply microcode */
779		if (apply_microcode_check_cpu(cpu)) {
780			/* The application of microcode failed */
781			microcode_fini_cpu(cpu);
782			__mc_sysdev_add(sys_dev, 1);
783			break;
784		}
785	case CPU_DOWN_FAILED_FROZEN:
786		if (sysfs_create_group(&sys_dev->kobj, &mc_attr_group))
787			printk(KERN_ERR "Microcode: Failed to create the sysfs "
788				"group for CPU%d\n", cpu);
789		break;
790	case CPU_DOWN_PREPARE:
791		mc_sysdev_remove(sys_dev);
792		break;
793	case CPU_DOWN_PREPARE_FROZEN:
794		/* Suspend is in progress, only remove the interface */
795		sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
796		break;
797	}
798	return NOTIFY_OK;
799}
800
801static struct notifier_block __cpuinitdata mc_cpu_notifier = {
802	.notifier_call = mc_cpu_callback,
803};
804
805static int __init microcode_init (void)
806{
807	int error;
808
809	error = microcode_dev_init();
810	if (error)
811		return error;
812	microcode_pdev = platform_device_register_simple("microcode", -1,
813							 NULL, 0);
814	if (IS_ERR(microcode_pdev)) {
815		microcode_dev_exit();
816		return PTR_ERR(microcode_pdev);
817	}
818
819	lock_cpu_hotplug();
820	error = sysdev_driver_register(&cpu_sysdev_class, &mc_sysdev_driver);
821	unlock_cpu_hotplug();
822	if (error) {
823		microcode_dev_exit();
824		platform_device_unregister(microcode_pdev);
825		return error;
826	}
827
828	register_hotcpu_notifier(&mc_cpu_notifier);
829
830	printk(KERN_INFO
831		"IA-32 Microcode Update Driver: v" MICROCODE_VERSION " <tigran@aivazian.fsnet.co.uk>\n");
832	return 0;
833}
834
835static void __exit microcode_exit (void)
836{
837	microcode_dev_exit();
838
839	unregister_hotcpu_notifier(&mc_cpu_notifier);
840
841	lock_cpu_hotplug();
842	sysdev_driver_unregister(&cpu_sysdev_class, &mc_sysdev_driver);
843	unlock_cpu_hotplug();
844
845	platform_device_unregister(microcode_pdev);
846}
847
848module_init(microcode_init)
849module_exit(microcode_exit)
850