microcode_intel.c 16.3 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
 *
 *	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>,
58 59
 *		Serialize updates as required on HT processors due to
 *		speculative nature of implementation.
L
Linus Torvalds 已提交
60 61
 *	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
 *		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.
 */

74
/* #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
MODULE_LICENSE("GPL");

102 103 104 105 106
#define DEFAULT_UCODE_DATASIZE 	(2000)
#define MC_HEADER_SIZE		(sizeof(struct microcode_header_intel))
#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE)
#define EXT_HEADER_SIZE		(sizeof(struct extended_sigtable))
#define EXT_SIGNATURE_SIZE	(sizeof(struct extended_signature))
P
Peter Oruba 已提交
107
#define DWSIZE			(sizeof(u32))
L
Linus Torvalds 已提交
108
#define get_totalsize(mc) \
109 110 111 112
	(((struct microcode_intel *)mc)->hdr.totalsize ? \
	 ((struct microcode_intel *)mc)->hdr.totalsize : \
	 DEFAULT_UCODE_TOTALSIZE)

L
Linus Torvalds 已提交
113
#define get_datasize(mc) \
114 115
	(((struct microcode_intel *)mc)->hdr.datasize ? \
	 ((struct microcode_intel *)mc)->hdr.datasize : DEFAULT_UCODE_DATASIZE)
L
Linus Torvalds 已提交
116 117 118 119 120 121 122 123 124 125

#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 已提交
126
extern struct mutex microcode_mutex;
L
Linus Torvalds 已提交
127

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

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

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

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

150 151 152 153 154 155
	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 已提交
156 157 158
	}

	wrmsr(MSR_IA32_UCODE_REV, 0, 0);
159
	/* see notes above for revision 1.07.  Apparent chip bug */
160
	sync_core();
L
Linus Torvalds 已提交
161 162 163 164 165 166
	/* 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);
}

167
static inline int microcode_update_match(int cpu_num,
168
	struct microcode_header_intel *mc_header, int sig, int pf)
L
Linus Torvalds 已提交
169 170 171
{
	struct ucode_cpu_info *uci = ucode_cpu_info + cpu_num;

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

P
Peter Oruba 已提交
178
static int microcode_sanity_check(void *mc)
L
Linus Torvalds 已提交
179
{
180
	struct microcode_header_intel *mc_header = mc;
181 182 183 184 185 186 187
	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);
188
	if (data_size + MC_HEADER_SIZE > total_size) {
189 190 191 192
		printk(KERN_ERR "microcode: error! "
			"Bad data size in microcode data file\n");
		return -EINVAL;
	}
L
Linus Torvalds 已提交
193

194 195 196 197 198 199 200 201 202 203 204 205
	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 已提交
206
		}
207 208 209 210 211
		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 已提交
212
		}
213 214
		ext_sigcount = ext_header->count;
	}
L
Linus Torvalds 已提交
215

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

		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 已提交
228
		}
229
	}
L
Linus Torvalds 已提交
230

231 232 233 234 235 236 237 238 239 240 241 242 243
	/* 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 已提交
244 245
		ext_sig = (void *)ext_header + EXT_HEADER_SIZE +
			  EXT_SIGNATURE_SIZE * i;
246 247 248 249 250 251
		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 已提交
252
		}
253 254 255
	}
	return 0;
}
256

257 258 259 260 261
/*
 * return 0 - no update found
 * return 1 - found update
 * return < 0 - error
 */
P
Peter Oruba 已提交
262
static int get_matching_microcode(void *mc, int cpu)
263 264
{
	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
265
	struct microcode_header_intel *mc_header = mc;
266 267 268 269 270 271 272 273 274 275 276 277 278
	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 已提交
279
	ext_header = mc + get_datasize(mc_header) + MC_HEADER_SIZE;
280
	ext_sigcount = ext_header->count;
J
Jan Engelhardt 已提交
281
	ext_sig = (void *)ext_header + EXT_HEADER_SIZE;
282 283 284 285 286 287 288 289
	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:
290
	pr_debug("microcode: CPU%d found a matching microcode update with"
P
Peter Oruba 已提交
291 292
		 " version 0x%x (current=0x%x)\n",
		 cpu, mc_header->rev, uci->rev);
293 294 295 296 297
	new_mc = vmalloc(total_size);
	if (!new_mc) {
		printk(KERN_ERR "microcode: error! Can not allocate memory\n");
		return -ENOMEM;
	}
L
Linus Torvalds 已提交
298

299
	/* free previous update file */
300
	vfree(uci->mc.mc_intel);
L
Linus Torvalds 已提交
301

302
	memcpy(new_mc, mc, total_size);
303
	uci->mc.mc_intel = new_mc;
304
	return 1;
L
Linus Torvalds 已提交
305 306
}

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

314 315 316
	/* We should bind the task to the CPU */
	BUG_ON(cpu_num != cpu);

317
	if (uci->mc.mc_intel == NULL)
L
Linus Torvalds 已提交
318 319 320
		return;

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

	/* write microcode via MSR 0x79 */
	wrmsr(MSR_IA32_UCODE_WRITE,
325 326
	      (unsigned long) uci->mc.mc_intel->bits,
	      (unsigned long) uci->mc.mc_intel->bits >> 16 >> 16);
L
Linus Torvalds 已提交
327 328
	wrmsr(MSR_IA32_UCODE_REV, 0, 0);

329
	/* see notes above for revision 1.07.  Apparent chip bug */
330
	sync_core();
331

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

	spin_unlock_irqrestore(&microcode_update_lock, flags);
336
	if (val[1] != uci->mc.mc_intel->hdr.rev) {
337
		printk(KERN_ERR "microcode: CPU%d update from revision "
338 339 340
			"0x%x to 0x%x failed\n", cpu_num, uci->rev, val[1]);
		return;
	}
341
	printk(KERN_INFO "microcode: CPU%d updated from revision "
342 343 344 345 346
	       "0x%x to 0x%x, date = %04x-%02x-%02x \n",
		cpu_num, uci->rev, val[1],
		uci->mc.mc_intel->hdr.date & 0xffff,
		uci->mc.mc_intel->hdr.date >> 24,
		(uci->mc.mc_intel->hdr.date >> 16) & 0xff);
347
	uci->rev = val[1];
L
Linus Torvalds 已提交
348 349
}

350
#ifdef CONFIG_MICROCODE_OLD_INTERFACE
P
Peter Oruba 已提交
351 352
extern void __user *user_buffer;        /* user area microcode data buffer */
extern unsigned int user_buffer_size;   /* it's size */
L
Linus Torvalds 已提交
353

P
Peter Oruba 已提交
354
static long get_next_ucode(void **mc, long offset)
355
{
356
	struct microcode_header_intel mc_header;
357 358 359 360 361 362 363 364
	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 已提交
365
	}
366
	total_size = get_totalsize(&mc_header);
367
	if (offset + total_size > user_buffer_size) {
368 369 370
		printk(KERN_ERR "microcode: error! Bad total size in microcode "
				"data file\n");
		return -EINVAL;
L
Linus Torvalds 已提交
371
	}
372 373 374 375 376 377 378
	*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 已提交
379
	}
380 381 382 383
	return offset + total_size;
}
#endif

384
static long get_next_ucode_from_buffer(void **mc, const u8 *buf,
385 386
	unsigned long size, long offset)
{
387
	struct microcode_header_intel *mc_header;
388 389 390 391 392
	unsigned long total_size;

	/* No more data */
	if (offset >= size)
		return 0;
393
	mc_header = (struct microcode_header_intel *)(buf + offset);
394 395
	total_size = get_totalsize(mc_header);

396
	if (offset + total_size > size) {
397 398 399 400 401 402 403 404 405 406 407 408 409 410
		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 已提交
411
extern struct platform_device *microcode_pdev;
412

P
Peter Oruba 已提交
413
static int cpu_request_microcode(int cpu)
414 415
{
	char name[30];
416
	struct cpuinfo_x86 *c = &cpu_data(cpu);
417
	const struct firmware *firmware;
418
	const u8 *buf;
419 420 421 422 423 424 425
	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 已提交
426
	sprintf(name, "intel-ucode/%02x-%02x-%02x",
427 428 429
		c->x86, c->x86_model, c->x86_mask);
	error = request_firmware(&firmware, name, &microcode_pdev->dev);
	if (error) {
B
Ben Castricum 已提交
430
		pr_debug("microcode: data file %s load failed\n", name);
431 432
		return error;
	}
J
Jan Engelhardt 已提交
433
	buf = firmware->data;
434 435 436 437 438 439
	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 已提交
440
		error = get_matching_microcode(mc, cpu);
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
		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 已提交
462
static int apply_microcode_check_cpu(int cpu)
463
{
464
	struct cpuinfo_x86 *c = &cpu_data(cpu);
465 466 467 468 469
	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
	cpumask_t old;
	unsigned int val[2];
	int err = 0;

470
	/* Check if the microcode is available */
471
	if (!uci->mc.mc_intel)
472
		return 0;
473 474

	old = current->cpus_allowed;
475
	set_cpus_allowed_ptr(current, &cpumask_of_cpu(cpu));
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 501 502 503 504 505

	/* 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);

506
	set_cpus_allowed_ptr(current, &old);
507 508 509
	return err;
}

P
Peter Oruba 已提交
510
static void microcode_fini_cpu(int cpu)
511 512 513 514 515
{
	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;

	mutex_lock(&microcode_mutex);
	uci->valid = 0;
P
Peter Oruba 已提交
516
	vfree(uci->mc.mc_intel);
517
	uci->mc.mc_intel = NULL;
518 519
	mutex_unlock(&microcode_mutex);
}
P
Peter Oruba 已提交
520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548

static struct microcode_ops microcode_intel_ops = {
	.get_next_ucode                   = get_next_ucode,
	.get_matching_microcode           = get_matching_microcode,
	.microcode_sanity_check           = microcode_sanity_check,
	.apply_microcode_check_cpu        = apply_microcode_check_cpu,
	.cpu_request_microcode            = cpu_request_microcode,
	.collect_cpu_info                 = collect_cpu_info,
	.apply_microcode                  = apply_microcode,
	.microcode_fini_cpu               = microcode_fini_cpu,
};

static int __init microcode_intel_module_init(void)
{
	struct cpuinfo_x86 *c = &cpu_data(get_cpu());

	if (c->x86_vendor == X86_VENDOR_INTEL)
		return microcode_init(&microcode_intel_ops, THIS_MODULE);
	else
		return -ENODEV;
}

static void __exit microcode_intel_module_exit(void)
{
	microcode_exit();
}

module_init(microcode_intel_module_init)
module_exit(microcode_intel_module_exit)