microcode_intel.c 15.2 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3
/*
 *	Intel CPU Microcode Update Driver for Linux
 *
4
 *	Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
5
 *		      2006	Shaohua Li <shaohua.li@intel.com>
L
Linus Torvalds 已提交
6 7
 *
 *	This driver allows to upgrade microcode on Intel processors
B
Ben Castricum 已提交
8
 *	belonging to IA-32 family - PentiumPro, Pentium II,
L
Linus Torvalds 已提交
9 10
 *	Pentium III, Xeon, Pentium 4, etc.
 *
B
Ben Castricum 已提交
11 12 13 14 15
 *	Reference: Section 8.11 of Volume 3a, IA-32 Intel? Architecture
 *	Software Developer's Manual
 *	Order Number 253668 or free download from:
 *
 *	http://developer.intel.com/design/pentium4/manuals/253668.htm
L
Linus Torvalds 已提交
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
 *
 *	For more information, go to http://www.urbanmyth.org/microcode
 *
 *	This program is free software; you can redistribute it and/or
 *	modify it under the terms of the GNU General Public License
 *	as published by the Free Software Foundation; either version
 *	2 of the License, or (at your option) any later version.
 *
 *	1.0	16 Feb 2000, Tigran Aivazian <tigran@sco.com>
 *		Initial release.
 *	1.01	18 Feb 2000, Tigran Aivazian <tigran@sco.com>
 *		Added read() support + cleanups.
 *	1.02	21 Feb 2000, Tigran Aivazian <tigran@sco.com>
 *		Added 'device trimming' support. open(O_WRONLY) zeroes
 *		and frees the saved copy of applied microcode.
 *	1.03	29 Feb 2000, Tigran Aivazian <tigran@sco.com>
 *		Made to use devfs (/dev/cpu/microcode) + cleanups.
 *	1.04	06 Jun 2000, Simon Trimmer <simon@veritas.com>
 *		Added misc device support (now uses both devfs and misc).
 *		Added MICROCODE_IOCFREE ioctl to clear memory.
 *	1.05	09 Jun 2000, Simon Trimmer <simon@veritas.com>
 *		Messages for error cases (non Intel & no suitable microcode).
 *	1.06	03 Aug 2000, Tigran Aivazian <tigran@veritas.com>
 *		Removed ->release(). Removed exclusive open and status bitmap.
 *		Added microcode_rwsem to serialize read()/write()/ioctl().
 *		Removed global kernel lock usage.
 *	1.07	07 Sep 2000, Tigran Aivazian <tigran@veritas.com>
 *		Write 0 to 0x8B msr and then cpuid before reading revision,
 *		so that it works even if there were no update done by the
 *		BIOS. Otherwise, reading from 0x8B gives junk (which happened
 *		to be 0 on my machine which is why it worked even when I
 *		disabled update by the BIOS)
 *		Thanks to Eric W. Biederman <ebiederman@lnxi.com> for the fix.
 *	1.08	11 Dec 2000, Richard Schaal <richard.schaal@intel.com> and
 *			     Tigran Aivazian <tigran@veritas.com>
 *		Intel Pentium 4 processor support and bugfixes.
 *	1.09	30 Oct 2001, Tigran Aivazian <tigran@veritas.com>
 *		Bugfix for HT (Hyper-Threading) enabled processors
 *		whereby processor resources are shared by all logical processors
 *		in a single CPU package.
 *	1.10	28 Feb 2002 Asit K Mallick <asit.k.mallick@intel.com> and
 *		Tigran Aivazian <tigran@veritas.com>,
 *		Serialize updates as required on HT processors due to speculative
 *		nature of implementation.
 *	1.11	22 Mar 2002 Tigran Aivazian <tigran@veritas.com>
 *		Fix the panic when writing zero-length microcode chunk.
B
Ben Castricum 已提交
62
 *	1.12	29 Sep 2003 Nitin Kamble <nitin.a.kamble@intel.com>,
L
Linus Torvalds 已提交
63 64 65 66
 *		Jun Nakajima <jun.nakajima@intel.com>
 *		Support for the microcode updates in the new format.
 *	1.13	10 Oct 2003 Tigran Aivazian <tigran@veritas.com>
 *		Removed ->read() method and obsoleted MICROCODE_IOCFREE ioctl
B
Ben Castricum 已提交
67
 *		because we no longer hold a copy of applied microcode
L
Linus Torvalds 已提交
68 69 70 71 72 73 74
 *		in kernel memory.
 *	1.14	25 Jun 2004 Tigran Aivazian <tigran@veritas.com>
 *		Fix sigmatch() macro to handle old CPUs with pf == 0.
 *		Thanks to Stuart Swales for pointing out this bug.
 */

//#define DEBUG /* pr_debug */
75
#include <linux/capability.h>
L
Linus Torvalds 已提交
76 77 78
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
A
Arnd Bergmann 已提交
79
#include <linux/smp_lock.h>
80
#include <linux/cpumask.h>
L
Linus Torvalds 已提交
81 82 83 84 85 86
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/miscdevice.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
A
Alexey Dobriyan 已提交
87
#include <linux/fs.h>
88
#include <linux/mutex.h>
89 90 91
#include <linux/cpu.h>
#include <linux/firmware.h>
#include <linux/platform_device.h>
L
Linus Torvalds 已提交
92 93 94 95

#include <asm/msr.h>
#include <asm/uaccess.h>
#include <asm/processor.h>
96
#include <asm/microcode.h>
L
Linus Torvalds 已提交
97

P
Peter Oruba 已提交
98
MODULE_DESCRIPTION("Microcode Update Driver");
99
MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
L
Linus Torvalds 已提交
100 101 102
MODULE_LICENSE("GPL");

#define DEFAULT_UCODE_DATASIZE 	(2000) 	  /* 2000 bytes */
P
Peter Oruba 已提交
103
#define MC_HEADER_SIZE		(sizeof(struct microcode_header))  	  /* 48 bytes */
L
Linus Torvalds 已提交
104
#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE) /* 2048 bytes */
P
Peter Oruba 已提交
105 106 107
#define EXT_HEADER_SIZE		(sizeof(struct extended_sigtable)) /* 20 bytes */
#define EXT_SIGNATURE_SIZE	(sizeof(struct extended_signature)) /* 12 bytes */
#define DWSIZE			(sizeof(u32))
L
Linus Torvalds 已提交
108
#define get_totalsize(mc) \
P
Peter Oruba 已提交
109 110
	(((struct microcode *)mc)->hdr.totalsize ? \
	 ((struct microcode *)mc)->hdr.totalsize : DEFAULT_UCODE_TOTALSIZE)
L
Linus Torvalds 已提交
111
#define get_datasize(mc) \
P
Peter Oruba 已提交
112 113
	(((struct microcode *)mc)->hdr.datasize ? \
	 ((struct microcode *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE)
L
Linus Torvalds 已提交
114 115 116 117 118 119 120 121 122 123

#define sigmatch(s1, s2, p1, p2) \
	(((s1) == (s2)) && (((p1) & (p2)) || (((p1) == 0) && ((p2) == 0))))

#define exttable_size(et) ((et)->count * EXT_SIGNATURE_SIZE + EXT_HEADER_SIZE)

/* serialize access to the physical write to MSR 0x79 */
static DEFINE_SPINLOCK(microcode_update_lock);

/* no concurrent ->write()s are allowed on /dev/cpu/microcode */
P
Peter Oruba 已提交
124
extern struct mutex microcode_mutex;
L
Linus Torvalds 已提交
125

P
Peter Oruba 已提交
126
extern struct ucode_cpu_info ucode_cpu_info[NR_CPUS];
L
Linus Torvalds 已提交
127

P
Peter Oruba 已提交
128
void collect_cpu_info(int cpu_num)
L
Linus Torvalds 已提交
129
{
130
	struct cpuinfo_x86 *c = &cpu_data(cpu_num);
L
Linus Torvalds 已提交
131 132 133
	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;
	unsigned int val[2];

134 135 136
	/* We should bind the task to the CPU */
	BUG_ON(raw_smp_processor_id() != cpu_num);
	uci->pf = uci->rev = 0;
L
Linus Torvalds 已提交
137
	uci->mc = NULL;
138
	uci->valid = 1;
L
Linus Torvalds 已提交
139 140

	if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
P
Peter Oruba 已提交
141
	    cpu_has(c, X86_FEATURE_IA64)) {
142 143 144
		printk(KERN_ERR "microcode: CPU%d not a capable Intel "
			"processor\n", cpu_num);
		uci->valid = 0;
L
Linus Torvalds 已提交
145
		return;
146
	}
L
Linus Torvalds 已提交
147

148 149 150 151 152 153
	uci->sig = cpuid_eax(0x00000001);

	if ((c->x86_model >= 5) || (c->x86 > 6)) {
		/* get processor flags from MSR 0x17 */
		rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
		uci->pf = 1 << ((val[1] >> 18) & 7);
L
Linus Torvalds 已提交
154 155 156
	}

	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
157
	/* see notes above for revision 1.07.  Apparent chip bug */
158
	sync_core();
L
Linus Torvalds 已提交
159 160 161 162 163 164
	/* get the current revision from MSR 0x8B */
	rdmsr(MSR_IA32_UCODE_REV, val[0], uci->rev);
	pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n",
			uci->sig, uci->pf, uci->rev);
}

165
static inline int microcode_update_match(int cpu_num,
P
Peter Oruba 已提交
166
	struct microcode_header *mc_header, int sig, int pf)
L
Linus Torvalds 已提交
167 168 169
{
	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;

170 171 172 173
	if (!sigmatch(sig, uci->sig, pf, uci->pf)
		|| mc_header->rev <= uci->rev)
		return 0;
	return 1;
L
Linus Torvalds 已提交
174 175
}

P
Peter Oruba 已提交
176
int microcode_sanity_check(void *mc)
L
Linus Torvalds 已提交
177
{
P
Peter Oruba 已提交
178
	struct microcode_header *mc_header = mc;
179 180 181 182 183 184 185
	struct extended_sigtable *ext_header = NULL;
	struct extended_signature *ext_sig;
	unsigned long total_size, data_size, ext_table_size;
	int sum, orig_sum, ext_sigcount = 0, i;

	total_size = get_totalsize(mc_header);
	data_size = get_datasize(mc_header);
186
	if (data_size + MC_HEADER_SIZE > total_size) {
187 188 189 190
		printk(KERN_ERR "microcode: error! "
			"Bad data size in microcode data file\n");
		return -EINVAL;
	}
L
Linus Torvalds 已提交
191

192 193 194 195 196 197 198 199 200 201 202 203
	if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
		printk(KERN_ERR "microcode: error! "
			"Unknown microcode update format\n");
		return -EINVAL;
	}
	ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
	if (ext_table_size) {
		if ((ext_table_size < EXT_HEADER_SIZE)
		 || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
			printk(KERN_ERR "microcode: error! "
				"Small exttable size in microcode data file\n");
			return -EINVAL;
L
Linus Torvalds 已提交
204
		}
205 206 207 208 209
		ext_header = mc + MC_HEADER_SIZE + data_size;
		if (ext_table_size != exttable_size(ext_header)) {
			printk(KERN_ERR "microcode: error! "
				"Bad exttable size in microcode data file\n");
			return -EFAULT;
L
Linus Torvalds 已提交
210
		}
211 212
		ext_sigcount = ext_header->count;
	}
L
Linus Torvalds 已提交
213

214 215 216
	/* check extended table checksum */
	if (ext_table_size) {
		int ext_table_sum = 0;
217
		int *ext_tablep = (int *)ext_header;
218 219 220 221 222 223 224 225

		i = ext_table_size / DWSIZE;
		while (i--)
			ext_table_sum += ext_tablep[i];
		if (ext_table_sum) {
			printk(KERN_WARNING "microcode: aborting, "
				"bad extended signature table checksum\n");
			return -EINVAL;
L
Linus Torvalds 已提交
226
		}
227
	}
L
Linus Torvalds 已提交
228

229 230 231 232 233 234 235 236 237 238 239 240 241
	/* calculate the checksum */
	orig_sum = 0;
	i = (MC_HEADER_SIZE + data_size) / DWSIZE;
	while (i--)
		orig_sum += ((int *)mc)[i];
	if (orig_sum) {
		printk(KERN_ERR "microcode: aborting, bad checksum\n");
		return -EINVAL;
	}
	if (!ext_table_size)
		return 0;
	/* check extended signature checksum */
	for (i = 0; i < ext_sigcount; i++) {
J
Jan Engelhardt 已提交
242 243
		ext_sig = (void *)ext_header + EXT_HEADER_SIZE +
			  EXT_SIGNATURE_SIZE * i;
244 245 246 247 248 249
		sum = orig_sum
			- (mc_header->sig + mc_header->pf + mc_header->cksum)
			+ (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
		if (sum) {
			printk(KERN_ERR "microcode: aborting, bad checksum\n");
			return -EINVAL;
L
Linus Torvalds 已提交
250
		}
251 252 253
	}
	return 0;
}
254

255 256 257 258 259
/*
 * return 0 - no update found
 * return 1 - found update
 * return < 0 - error
 */
P
Peter Oruba 已提交
260
int get_matching_microcode(void *mc, int cpu)
261 262
{
	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
P
Peter Oruba 已提交
263
	struct microcode_header *mc_header = mc;
264 265 266 267 268 269 270 271 272 273 274 275 276
	struct extended_sigtable *ext_header;
	unsigned long total_size = get_totalsize(mc_header);
	int ext_sigcount, i;
	struct extended_signature *ext_sig;
	void *new_mc;

	if (microcode_update_match(cpu, mc_header,
			mc_header->sig, mc_header->pf))
		goto find;

	if (total_size <= get_datasize(mc_header) + MC_HEADER_SIZE)
		return 0;

J
Jan Engelhardt 已提交
277
	ext_header = mc + get_datasize(mc_header) + MC_HEADER_SIZE;
278
	ext_sigcount = ext_header->count;
J
Jan Engelhardt 已提交
279
	ext_sig = (void *)ext_header + EXT_HEADER_SIZE;
280 281 282 283 284 285 286 287
	for (i = 0; i < ext_sigcount; i++) {
		if (microcode_update_match(cpu, mc_header,
				ext_sig->sig, ext_sig->pf))
			goto find;
		ext_sig++;
	}
	return 0;
find:
288
	pr_debug("microcode: CPU%d found a matching microcode update with"
P
Peter Oruba 已提交
289
		 " version 0x%x (current=0x%x)\n", cpu, mc_header->rev, uci->rev);
290 291 292 293 294
	new_mc = vmalloc(total_size);
	if (!new_mc) {
		printk(KERN_ERR "microcode: error! Can not allocate memory\n");
		return -ENOMEM;
	}
L
Linus Torvalds 已提交
295

296 297
	/* free previous update file */
	vfree(uci->mc);
L
Linus Torvalds 已提交
298

299 300 301
	memcpy(new_mc, mc, total_size);
	uci->mc = new_mc;
	return 1;
L
Linus Torvalds 已提交
302 303
}

P
Peter Oruba 已提交
304
void apply_microcode(int cpu)
L
Linus Torvalds 已提交
305 306 307
{
	unsigned long flags;
	unsigned int val[2];
308
	int cpu_num = raw_smp_processor_id();
L
Linus Torvalds 已提交
309 310
	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;

311 312 313 314
	/* We should bind the task to the CPU */
	BUG_ON(cpu_num != cpu);

	if (uci->mc == NULL)
L
Linus Torvalds 已提交
315 316 317
		return;

	/* serialize access to the physical write to MSR 0x79 */
B
Ben Castricum 已提交
318
	spin_lock_irqsave(&microcode_update_lock, flags);
L
Linus Torvalds 已提交
319 320 321

	/* write microcode via MSR 0x79 */
	wrmsr(MSR_IA32_UCODE_WRITE,
B
Ben Castricum 已提交
322
		(unsigned long) uci->mc->bits,
L
Linus Torvalds 已提交
323 324 325
		(unsigned long) uci->mc->bits >> 16 >> 16);
	wrmsr(MSR_IA32_UCODE_REV, 0, 0);

326
	/* see notes above for revision 1.07.  Apparent chip bug */
327
	sync_core();
328

L
Linus Torvalds 已提交
329 330 331 332
	/* get the current revision from MSR 0x8B */
	rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);

	spin_unlock_irqrestore(&microcode_update_lock, flags);
333
	if (val[1] != uci->mc->hdr.rev) {
334
		printk(KERN_ERR "microcode: CPU%d update from revision "
335 336 337
			"0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]);
		return;
	}
338
	printk(KERN_INFO "microcode: CPU%d updated from revision "
B
Ben Castricum 已提交
339
	       "0x%x to 0x%x, date = %08x \n",
L
Linus Torvalds 已提交
340
	       cpu_num, uci->rev, val[1], uci->mc->hdr.date);
341
	uci->rev = val[1];
L
Linus Torvalds 已提交
342 343
}

344
#ifdef CONFIG_MICROCODE_OLD_INTERFACE
P
Peter Oruba 已提交
345 346
extern void __user *user_buffer;        /* user area microcode data buffer */
extern unsigned int user_buffer_size;   /* it's size */
L
Linus Torvalds 已提交
347

P
Peter Oruba 已提交
348
long get_next_ucode(void **mc, long offset)
349
{
P
Peter Oruba 已提交
350
	struct microcode_header mc_header;
351 352 353 354 355 356 357 358
	unsigned long total_size;

	/* No more data */
	if (offset >= user_buffer_size)
		return 0;
	if (copy_from_user(&mc_header, user_buffer + offset, MC_HEADER_SIZE)) {
		printk(KERN_ERR "microcode: error! Can not read user data\n");
		return -EFAULT;
L
Linus Torvalds 已提交
359
	}
360
	total_size = get_totalsize(&mc_header);
361
	if (offset + total_size > user_buffer_size) {
362 363 364
		printk(KERN_ERR "microcode: error! Bad total size in microcode "
				"data file\n");
		return -EINVAL;
L
Linus Torvalds 已提交
365
	}
366 367 368 369 370 371 372
	*mc = vmalloc(total_size);
	if (!*mc)
		return -ENOMEM;
	if (copy_from_user(*mc, user_buffer + offset, total_size)) {
		printk(KERN_ERR "microcode: error! Can not read user data\n");
		vfree(*mc);
		return -EFAULT;
L
Linus Torvalds 已提交
373
	}
374 375 376 377
	return offset + total_size;
}
#endif

378
static long get_next_ucode_from_buffer(void **mc, const u8 *buf,
379 380
	unsigned long size, long offset)
{
P
Peter Oruba 已提交
381
	struct microcode_header *mc_header;
382 383 384 385 386
	unsigned long total_size;

	/* No more data */
	if (offset >= size)
		return 0;
P
Peter Oruba 已提交
387
	mc_header = (struct microcode_header *)(buf + offset);
388 389
	total_size = get_totalsize(mc_header);

390
	if (offset + total_size > size) {
391 392 393 394 395 396 397 398 399 400 401 402 403 404
		printk(KERN_ERR "microcode: error! Bad data in microcode data file\n");
		return -EINVAL;
	}

	*mc = vmalloc(total_size);
	if (!*mc) {
		printk(KERN_ERR "microcode: error! Can not allocate memory\n");
		return -ENOMEM;
	}
	memcpy(*mc, buf + offset, total_size);
	return offset + total_size;
}

/* fake device for request_firmware */
P
Peter Oruba 已提交
405
extern struct platform_device *microcode_pdev;
406

P
Peter Oruba 已提交
407
int cpu_request_microcode(int cpu)
408 409
{
	char name[30];
410
	struct cpuinfo_x86 *c = &cpu_data(cpu);
411
	const struct firmware *firmware;
412
	const u8 *buf;
413 414 415 416 417 418 419
	unsigned long size;
	long offset = 0;
	int error;
	void *mc;

	/* We should bind the task to the CPU */
	BUG_ON(cpu != raw_smp_processor_id());
P
Peter Oruba 已提交
420
	sprintf(name, "intel-ucode/%02x-%02x-%02x",
421 422 423
		c->x86, c->x86_model, c->x86_mask);
	error = request_firmware(&firmware, name, &microcode_pdev->dev);
	if (error) {
B
Ben Castricum 已提交
424
		pr_debug("microcode: data file %s load failed\n", name);
425 426
		return error;
	}
J
Jan Engelhardt 已提交
427
	buf = firmware->data;
428 429 430 431 432 433
	size = firmware->size;
	while ((offset = get_next_ucode_from_buffer(&mc, buf, size, offset))
			> 0) {
		error = microcode_sanity_check(mc);
		if (error)
			break;
P
Peter Oruba 已提交
434
		error = get_matching_microcode(mc, cpu);
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
		if (error < 0)
			break;
		/*
		 * It's possible the data file has multiple matching ucode,
		 * lets keep searching till the latest version
		 */
		if (error == 1) {
			apply_microcode(cpu);
			error = 0;
		}
		vfree(mc);
	}
	if (offset > 0)
		vfree(mc);
	if (offset < 0)
		error = offset;
	release_firmware(firmware);

	return error;
}

P
Peter Oruba 已提交
456
int apply_microcode_check_cpu(int cpu)
457
{
458
	struct cpuinfo_x86 *c = &cpu_data(cpu);
459 460
	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
	cpumask_t old;
461
	cpumask_of_cpu_ptr(newmask, cpu);
462 463 464
	unsigned int val[2];
	int err = 0;

465
	/* Check if the microcode is available */
466
	if (!uci->mc)
467
		return 0;
468 469

	old = current->cpus_allowed;
470
	set_cpus_allowed_ptr(current, newmask);
471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500

	/* Check if the microcode we have in memory matches the CPU */
	if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 ||
	    cpu_has(c, X86_FEATURE_IA64) || uci->sig != cpuid_eax(0x00000001))
		err = -EINVAL;

	if (!err && ((c->x86_model >= 5) || (c->x86 > 6))) {
		/* get processor flags from MSR 0x17 */
		rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]);
		if (uci->pf != (1 << ((val[1] >> 18) & 7)))
			err = -EINVAL;
	}

	if (!err) {
		wrmsr(MSR_IA32_UCODE_REV, 0, 0);
		/* see notes above for revision 1.07.  Apparent chip bug */
		sync_core();
		/* get the current revision from MSR 0x8B */
		rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]);
		if (uci->rev != val[1])
			err = -EINVAL;
	}

	if (!err)
		apply_microcode(cpu);
	else
		printk(KERN_ERR "microcode: Could not apply microcode to CPU%d:"
			" sig=0x%x, pf=0x%x, rev=0x%x\n",
			cpu, uci->sig, uci->pf, uci->rev);

501
	set_cpus_allowed_ptr(current, &old);
502 503 504
	return err;
}

P
Peter Oruba 已提交
505
void microcode_fini_cpu(int cpu)
506 507 508 509 510
{
	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;

	mutex_lock(&microcode_mutex);
	uci->valid = 0;
P
Peter Oruba 已提交
511
	kfree(uci->mc);
512 513 514
	uci->mc = NULL;
	mutex_unlock(&microcode_mutex);
}