core.c 15.3 KB
Newer Older
P
Peter Oruba 已提交
1
/*
2
 * CPU Microcode Update Driver for Linux
P
Peter Oruba 已提交
3
 *
4 5
 * Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
 *	      2006	Shaohua Li <shaohua.li@intel.com>
6
 *	      2013-2016	Borislav Petkov <bp@alien8.de>
P
Peter Oruba 已提交
7
 *
8 9 10 11 12 13
 * X86 CPU microcode early update for Linux:
 *
 *	Copyright (C) 2012 Fenghua Yu <fenghua.yu@intel.com>
 *			   H Peter Anvin" <hpa@zytor.com>
 *		  (C) 2015 Borislav Petkov <bp@alien8.de>
 *
14
 * This driver allows to upgrade microcode on x86 processors.
P
Peter Oruba 已提交
15
 *
16 17 18 19
 * 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.
P
Peter Oruba 已提交
20
 */
21

22
#define pr_fmt(fmt) "microcode: " fmt
23

I
Ingo Molnar 已提交
24
#include <linux/platform_device.h>
25
#include <linux/syscore_ops.h>
I
Ingo Molnar 已提交
26
#include <linux/miscdevice.h>
27
#include <linux/capability.h>
28
#include <linux/firmware.h>
I
Ingo Molnar 已提交
29
#include <linux/kernel.h>
P
Peter Oruba 已提交
30 31
#include <linux/mutex.h>
#include <linux/cpu.h>
I
Ingo Molnar 已提交
32 33
#include <linux/fs.h>
#include <linux/mm.h>
P
Peter Oruba 已提交
34

35
#include <asm/microcode_intel.h>
36
#include <asm/cpu_device_id.h>
37
#include <asm/microcode_amd.h>
38
#include <asm/perf_event.h>
39 40 41
#include <asm/microcode.h>
#include <asm/processor.h>
#include <asm/cmdline.h>
42
#include <asm/setup.h>
P
Peter Oruba 已提交
43

44
#define DRIVER_VERSION	"2.2"
P
Peter Oruba 已提交
45

I
Ingo Molnar 已提交
46
static struct microcode_ops	*microcode_ops;
47
static bool dis_ucode_ldr = true;
48

49 50
LIST_HEAD(microcode_cache);

51 52 53 54 55 56 57 58 59 60 61 62
/*
 * Synchronization.
 *
 * All non cpu-hotplug-callback call sites use:
 *
 * - microcode_mutex to synchronize with each other;
 * - get/put_online_cpus() to synchronize with
 *   the cpu-hotplug-callback call sites.
 *
 * We guarantee that only a single cpu is being
 * updated at any particular moment of time.
 */
63
static DEFINE_MUTEX(microcode_mutex);
P
Peter Oruba 已提交
64

I
Ingo Molnar 已提交
65
struct ucode_cpu_info		ucode_cpu_info[NR_CPUS];
P
Peter Oruba 已提交
66

67 68 69 70 71 72 73 74 75
/*
 * Operations that are run on a target cpu:
 */

struct cpu_info_ctx {
	struct cpu_signature	*cpu_sig;
	int			err;
};

76 77
static bool __init check_loader_disabled_bsp(void)
{
78
	static const char *__dis_opt_str = "dis_ucode_ldr";
79
	u32 a, b, c, d;
80

81 82
#ifdef CONFIG_X86_32
	const char *cmdline = (const char *)__pa_nodebug(boot_command_line);
83
	const char *option  = (const char *)__pa_nodebug(__dis_opt_str);
84 85 86 87
	bool *res = (bool *)__pa_nodebug(&dis_ucode_ldr);

#else /* CONFIG_X86_64 */
	const char *cmdline = boot_command_line;
88
	const char *option  = __dis_opt_str;
89 90 91
	bool *res = &dis_ucode_ldr;
#endif

92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
	if (!have_cpuid_p())
		return *res;

	a = 1;
	c = 0;
	native_cpuid(&a, &b, &c, &d);

	/*
	 * CPUID(1).ECX[31]: reserved for hypervisor use. This is still not
	 * completely accurate as xen pv guests don't see that CPUID bit set but
	 * that's good enough as they don't land on the BSP path anyway.
	 */
	if (c & BIT(31))
		return *res;

	if (cmdline_find_option_bool(cmdline, option) <= 0)
		*res = false;
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139

	return *res;
}

extern struct builtin_fw __start_builtin_fw[];
extern struct builtin_fw __end_builtin_fw[];

bool get_builtin_firmware(struct cpio_data *cd, const char *name)
{
#ifdef CONFIG_FW_LOADER
	struct builtin_fw *b_fw;

	for (b_fw = __start_builtin_fw; b_fw != __end_builtin_fw; b_fw++) {
		if (!strcmp(name, b_fw->name)) {
			cd->size = b_fw->size;
			cd->data = b_fw->data;
			return true;
		}
	}
#endif
	return false;
}

void __init load_ucode_bsp(void)
{
	int vendor;
	unsigned int family;

	if (check_loader_disabled_bsp())
		return;

140 141
	vendor = x86_cpuid_vendor();
	family = x86_cpuid_family();
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172

	switch (vendor) {
	case X86_VENDOR_INTEL:
		if (family >= 6)
			load_ucode_intel_bsp();
		break;
	case X86_VENDOR_AMD:
		if (family >= 0x10)
			load_ucode_amd_bsp(family);
		break;
	default:
		break;
	}
}

static bool check_loader_disabled_ap(void)
{
#ifdef CONFIG_X86_32
	return *((bool *)__pa_nodebug(&dis_ucode_ldr));
#else
	return dis_ucode_ldr;
#endif
}

void load_ucode_ap(void)
{
	int vendor, family;

	if (check_loader_disabled_ap())
		return;

173 174
	vendor = x86_cpuid_vendor();
	family = x86_cpuid_family();
175 176 177 178 179 180 181 182

	switch (vendor) {
	case X86_VENDOR_INTEL:
		if (family >= 6)
			load_ucode_intel_ap();
		break;
	case X86_VENDOR_AMD:
		if (family >= 0x10)
183
			load_ucode_amd_ap(family);
184 185 186 187 188 189
		break;
	default:
		break;
	}
}

190
static int __init save_microcode_in_initrd(void)
191 192 193 194 195 196
{
	struct cpuinfo_x86 *c = &boot_cpu_data;

	switch (c->x86_vendor) {
	case X86_VENDOR_INTEL:
		if (c->x86 >= 6)
197
			return save_microcode_in_initrd_intel();
198 199 200
		break;
	case X86_VENDOR_AMD:
		if (c->x86 >= 0x10)
201
			return save_microcode_in_initrd_amd(c->x86);
202 203 204 205 206
		break;
	default:
		break;
	}

207
	return -EINVAL;
208 209
}

210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
struct cpio_data find_microcode_in_initrd(const char *path, bool use_pa)
{
#ifdef CONFIG_BLK_DEV_INITRD
	unsigned long start = 0;
	size_t size;

#ifdef CONFIG_X86_32
	struct boot_params *params;

	if (use_pa)
		params = (struct boot_params *)__pa_nodebug(&boot_params);
	else
		params = &boot_params;

	size = params->hdr.ramdisk_size;

	/*
	 * Set start only if we have an initrd image. We cannot use initrd_start
	 * because it is not set that early yet.
	 */
	if (size)
		start = params->hdr.ramdisk_image;

# else /* CONFIG_X86_64 */
	size  = (unsigned long)boot_params.ext_ramdisk_size << 32;
	size |= boot_params.hdr.ramdisk_size;

	if (size) {
		start  = (unsigned long)boot_params.ext_ramdisk_image << 32;
		start |= boot_params.hdr.ramdisk_image;

		start += PAGE_OFFSET;
	}
# endif

	/*
246 247 248 249
	 * Fixup the start address: after reserve_initrd() runs, initrd_start
	 * has the virtual address of the beginning of the initrd. It also
	 * possibly relocates the ramdisk. In either case, initrd_start contains
	 * the updated address so use that instead.
250
	 */
251
	if (!use_pa && initrd_start)
252 253 254 255 256 257 258 259
		start = initrd_start;

	return find_cpio_data(path, (void *)start, size, NULL);
#else /* !CONFIG_BLK_DEV_INITRD */
	return (struct cpio_data){ NULL, 0, "" };
#endif
}

260 261 262 263
void reload_early_microcode(void)
{
	int vendor, family;

264 265
	vendor = x86_cpuid_vendor();
	family = x86_cpuid_family();
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280

	switch (vendor) {
	case X86_VENDOR_INTEL:
		if (family >= 6)
			reload_ucode_intel();
		break;
	case X86_VENDOR_AMD:
		if (family >= 0x10)
			reload_ucode_amd();
		break;
	default:
		break;
	}
}

281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
static void collect_cpu_info_local(void *arg)
{
	struct cpu_info_ctx *ctx = arg;

	ctx->err = microcode_ops->collect_cpu_info(smp_processor_id(),
						   ctx->cpu_sig);
}

static int collect_cpu_info_on_target(int cpu, struct cpu_signature *cpu_sig)
{
	struct cpu_info_ctx ctx = { .cpu_sig = cpu_sig, .err = 0 };
	int ret;

	ret = smp_call_function_single(cpu, collect_cpu_info_local, &ctx, 1);
	if (!ret)
		ret = ctx.err;

	return ret;
}

static int collect_cpu_info(int cpu)
{
	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
	int ret;

	memset(uci, 0, sizeof(*uci));

	ret = collect_cpu_info_on_target(cpu, &uci->cpu_sig);
	if (!ret)
		uci->valid = 1;

	return ret;
}

struct apply_microcode_ctx {
	int err;
};

static void apply_microcode_local(void *arg)
{
	struct apply_microcode_ctx *ctx = arg;

	ctx->err = microcode_ops->apply_microcode(smp_processor_id());
}

static int apply_microcode_on_target(int cpu)
{
	struct apply_microcode_ctx ctx = { .err = 0 };
	int ret;

	ret = smp_call_function_single(cpu, apply_microcode_local, &ctx, 1);
	if (!ret)
		ret = ctx.err;

	return ret;
}

P
Peter Oruba 已提交
338
#ifdef CONFIG_MICROCODE_OLD_INTERFACE
D
Dmitry Adamushko 已提交
339
static int do_microcode_update(const void __user *buf, size_t size)
P
Peter Oruba 已提交
340 341 342
{
	int error = 0;
	int cpu;
343

D
Dmitry Adamushko 已提交
344 345
	for_each_online_cpu(cpu) {
		struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
346
		enum ucode_state ustate;
D
Dmitry Adamushko 已提交
347 348 349

		if (!uci->valid)
			continue;
350

351 352 353 354 355 356
		ustate = microcode_ops->request_microcode_user(cpu, buf, size);
		if (ustate == UCODE_ERROR) {
			error = -1;
			break;
		} else if (ustate == UCODE_OK)
			apply_microcode_on_target(cpu);
P
Peter Oruba 已提交
357
	}
358

P
Peter Oruba 已提交
359 360 361
	return error;
}

362
static int microcode_open(struct inode *inode, struct file *file)
P
Peter Oruba 已提交
363
{
364
	return capable(CAP_SYS_RAWIO) ? nonseekable_open(inode, file) : -EPERM;
P
Peter Oruba 已提交
365 366
}

367 368
static ssize_t microcode_write(struct file *file, const char __user *buf,
			       size_t len, loff_t *ppos)
P
Peter Oruba 已提交
369
{
370
	ssize_t ret = -EINVAL;
P
Peter Oruba 已提交
371

372
	if ((len >> PAGE_SHIFT) > totalram_pages) {
373
		pr_err("too much data (max %ld pages)\n", totalram_pages);
374
		return ret;
P
Peter Oruba 已提交
375 376 377 378 379
	}

	get_online_cpus();
	mutex_lock(&microcode_mutex);

380
	if (do_microcode_update(buf, len) == 0)
P
Peter Oruba 已提交
381 382
		ret = (ssize_t)len;

383 384 385
	if (ret > 0)
		perf_check_microcode();

P
Peter Oruba 已提交
386 387 388 389 390 391 392
	mutex_unlock(&microcode_mutex);
	put_online_cpus();

	return ret;
}

static const struct file_operations microcode_fops = {
393 394 395
	.owner			= THIS_MODULE,
	.write			= microcode_write,
	.open			= microcode_open,
396
	.llseek		= no_llseek,
P
Peter Oruba 已提交
397 398 399
};

static struct miscdevice microcode_dev = {
400 401
	.minor			= MICROCODE_MINOR,
	.name			= "microcode",
402
	.nodename		= "cpu/microcode",
403
	.fops			= &microcode_fops,
P
Peter Oruba 已提交
404 405
};

406
static int __init microcode_dev_init(void)
P
Peter Oruba 已提交
407 408 409 410 411
{
	int error;

	error = misc_register(&microcode_dev);
	if (error) {
412
		pr_err("can't misc_register on minor=%d\n", MICROCODE_MINOR);
P
Peter Oruba 已提交
413 414 415 416 417 418
		return error;
	}

	return 0;
}

419
static void __exit microcode_dev_exit(void)
P
Peter Oruba 已提交
420 421 422 423
{
	misc_deregister(&microcode_dev);
}
#else
I
Ingo Molnar 已提交
424 425
#define microcode_dev_init()	0
#define microcode_dev_exit()	do { } while (0)
P
Peter Oruba 已提交
426 427 428
#endif

/* fake device for request_firmware */
I
Ingo Molnar 已提交
429
static struct platform_device	*microcode_pdev;
P
Peter Oruba 已提交
430

431
static int reload_for_cpu(int cpu)
432
{
433
	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
434
	enum ucode_state ustate;
435 436
	int err = 0;

437 438
	if (!uci->valid)
		return err;
439

440
	ustate = microcode_ops->request_microcode_fw(cpu, &microcode_pdev->dev, true);
441 442 443 444 445
	if (ustate == UCODE_OK)
		apply_microcode_on_target(cpu);
	else
		if (ustate == UCODE_ERROR)
			err = -EINVAL;
446 447 448
	return err;
}

449 450
static ssize_t reload_store(struct device *dev,
			    struct device_attribute *attr,
451
			    const char *buf, size_t size)
P
Peter Oruba 已提交
452
{
453
	unsigned long val;
454 455 456
	int cpu;
	ssize_t ret = 0, tmp_ret;

457 458 459
	ret = kstrtoul(buf, 0, &val);
	if (ret)
		return ret;
460

461 462 463 464
	if (val != 1)
		return size;

	get_online_cpus();
465
	mutex_lock(&microcode_mutex);
466 467 468 469 470 471 472 473
	for_each_online_cpu(cpu) {
		tmp_ret = reload_for_cpu(cpu);
		if (tmp_ret != 0)
			pr_warn("Error reloading microcode on CPU %d\n", cpu);

		/* save retval of the first encountered reload error */
		if (!ret)
			ret = tmp_ret;
P
Peter Oruba 已提交
474
	}
475 476 477
	if (!ret)
		perf_check_microcode();
	mutex_unlock(&microcode_mutex);
478
	put_online_cpus();
479 480 481 482 483

	if (!ret)
		ret = size;

	return ret;
P
Peter Oruba 已提交
484 485
}

486 487
static ssize_t version_show(struct device *dev,
			struct device_attribute *attr, char *buf)
P
Peter Oruba 已提交
488 489 490
{
	struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;

491
	return sprintf(buf, "0x%x\n", uci->cpu_sig.rev);
P
Peter Oruba 已提交
492 493
}

494 495
static ssize_t pf_show(struct device *dev,
			struct device_attribute *attr, char *buf)
P
Peter Oruba 已提交
496 497 498
{
	struct ucode_cpu_info *uci = ucode_cpu_info + dev->id;

499
	return sprintf(buf, "0x%x\n", uci->cpu_sig.pf);
P
Peter Oruba 已提交
500 501
}

502 503 504
static DEVICE_ATTR(reload, 0200, NULL, reload_store);
static DEVICE_ATTR(version, 0400, version_show, NULL);
static DEVICE_ATTR(processor_flags, 0400, pf_show, NULL);
P
Peter Oruba 已提交
505 506

static struct attribute *mc_default_attrs[] = {
507 508
	&dev_attr_version.attr,
	&dev_attr_processor_flags.attr,
P
Peter Oruba 已提交
509 510 511 512
	NULL
};

static struct attribute_group mc_attr_group = {
513 514
	.attrs			= mc_default_attrs,
	.name			= "microcode",
P
Peter Oruba 已提交
515 516
};

517
static void microcode_fini_cpu(int cpu)
518
{
519 520
	if (microcode_ops->microcode_fini_cpu)
		microcode_ops->microcode_fini_cpu(cpu);
521 522
}

523
static enum ucode_state microcode_resume_cpu(int cpu)
524
{
525 526
	if (apply_microcode_on_target(cpu))
		return UCODE_ERROR;
527

528 529
	pr_debug("CPU%d updated upon resume\n", cpu);

530
	return UCODE_OK;
531 532
}

533
static enum ucode_state microcode_init_cpu(int cpu, bool refresh_fw)
534
{
535
	enum ucode_state ustate;
536 537
	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;

538
	if (uci->valid)
539
		return UCODE_OK;
540

541 542
	if (collect_cpu_info(cpu))
		return UCODE_ERROR;
543

544 545 546
	/* --dimm. Trigger a delayed update? */
	if (system_state != SYSTEM_RUNNING)
		return UCODE_NFOUND;
547

548 549
	ustate = microcode_ops->request_microcode_fw(cpu, &microcode_pdev->dev,
						     refresh_fw);
550

551
	if (ustate == UCODE_OK) {
552
		pr_debug("CPU%d updated upon init\n", cpu);
553
		apply_microcode_on_target(cpu);
554 555
	}

556
	return ustate;
557 558
}

559
static enum ucode_state microcode_update_cpu(int cpu)
560
{
561
	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
562

563 564 565
	/* Refresh CPU microcode revision after resume. */
	collect_cpu_info(cpu);

566
	if (uci->valid)
567
		return microcode_resume_cpu(cpu);
568

569
	return microcode_init_cpu(cpu, false);
570 571
}

572
static int mc_device_add(struct device *dev, struct subsys_interface *sif)
P
Peter Oruba 已提交
573
{
574
	int err, cpu = dev->id;
P
Peter Oruba 已提交
575 576 577 578

	if (!cpu_online(cpu))
		return 0;

579
	pr_debug("CPU%d added\n", cpu);
P
Peter Oruba 已提交
580

581
	err = sysfs_create_group(&dev->kobj, &mc_attr_group);
P
Peter Oruba 已提交
582 583 584
	if (err)
		return err;

585
	if (microcode_init_cpu(cpu, true) == UCODE_ERROR)
586
		return -EINVAL;
587 588

	return err;
P
Peter Oruba 已提交
589 590
}

591
static void mc_device_remove(struct device *dev, struct subsys_interface *sif)
P
Peter Oruba 已提交
592
{
593
	int cpu = dev->id;
P
Peter Oruba 已提交
594 595

	if (!cpu_online(cpu))
596
		return;
P
Peter Oruba 已提交
597

598
	pr_debug("CPU%d removed\n", cpu);
599
	microcode_fini_cpu(cpu);
600
	sysfs_remove_group(&dev->kobj, &mc_attr_group);
P
Peter Oruba 已提交
601 602
}

603 604 605 606 607
static struct subsys_interface mc_cpu_interface = {
	.name			= "microcode",
	.subsys			= &cpu_subsys,
	.add_dev		= mc_device_add,
	.remove_dev		= mc_device_remove,
608 609 610 611 612 613
};

/**
 * mc_bp_resume - Update boot CPU microcode during resume.
 */
static void mc_bp_resume(void)
P
Peter Oruba 已提交
614
{
615
	int cpu = smp_processor_id();
616
	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
P
Peter Oruba 已提交
617

618 619
	if (uci->valid && uci->mc)
		microcode_ops->apply_microcode(cpu);
620
	else if (!uci->mc)
621
		reload_early_microcode();
P
Peter Oruba 已提交
622 623
}

624 625
static struct syscore_ops mc_syscore_ops = {
	.resume			= mc_bp_resume,
P
Peter Oruba 已提交
626 627
};

628
static int mc_cpu_online(unsigned int cpu)
P
Peter Oruba 已提交
629
{
630
	struct device *dev;
P
Peter Oruba 已提交
631

632
	dev = get_cpu_device(cpu);
633 634
	microcode_update_cpu(cpu);
	pr_debug("CPU%d added\n", cpu);
635

636 637 638 639
	if (sysfs_create_group(&dev->kobj, &mc_attr_group))
		pr_err("Failed to create group for CPU%d\n", cpu);
	return 0;
}
640

641 642 643
static int mc_cpu_down_prep(unsigned int cpu)
{
	struct device *dev;
644

645 646 647 648
	dev = get_cpu_device(cpu);
	/* Suspend is in progress, only remove the interface */
	sysfs_remove_group(&dev->kobj, &mc_attr_group);
	pr_debug("CPU%d removed\n", cpu);
649

650
	return 0;
P
Peter Oruba 已提交
651 652
}

653 654 655 656 657 658 659 660 661 662
static struct attribute *cpu_root_microcode_attrs[] = {
	&dev_attr_reload.attr,
	NULL
};

static struct attribute_group cpu_root_microcode_group = {
	.name  = "microcode",
	.attrs = cpu_root_microcode_attrs,
};

663
int __init microcode_init(void)
P
Peter Oruba 已提交
664
{
665
	struct cpuinfo_x86 *c = &boot_cpu_data;
P
Peter Oruba 已提交
666 667
	int error;

668
	if (dis_ucode_ldr)
669
		return -EINVAL;
670

671 672
	if (c->x86_vendor == X86_VENDOR_INTEL)
		microcode_ops = init_intel_microcode();
P
Peter Oruba 已提交
673
	else if (c->x86_vendor == X86_VENDOR_AMD)
674
		microcode_ops = init_amd_microcode();
675
	else
676
		pr_err("no support for this CPU vendor\n");
677 678

	if (!microcode_ops)
679
		return -ENODEV;
P
Peter Oruba 已提交
680 681 682

	microcode_pdev = platform_device_register_simple("microcode", -1,
							 NULL, 0);
683
	if (IS_ERR(microcode_pdev))
P
Peter Oruba 已提交
684 685 686
		return PTR_ERR(microcode_pdev);

	get_online_cpus();
687 688
	mutex_lock(&microcode_mutex);

689
	error = subsys_interface_register(&mc_cpu_interface);
690 691
	if (!error)
		perf_check_microcode();
692
	mutex_unlock(&microcode_mutex);
P
Peter Oruba 已提交
693
	put_online_cpus();
694

695 696
	if (error)
		goto out_pdev;
P
Peter Oruba 已提交
697

698 699 700 701 702 703 704 705
	error = sysfs_create_group(&cpu_subsys.dev_root->kobj,
				   &cpu_root_microcode_group);

	if (error) {
		pr_err("Error creating microcode group!\n");
		goto out_driver;
	}

706 707
	error = microcode_dev_init();
	if (error)
708
		goto out_ucode_group;
709

710
	register_syscore_ops(&mc_syscore_ops);
711 712
	cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "x86/microcode:online",
				  mc_cpu_online, mc_cpu_down_prep);
P
Peter Oruba 已提交
713

714
	pr_info("Microcode Update Driver: v%s.", DRIVER_VERSION);
P
Peter Oruba 已提交
715

P
Peter Oruba 已提交
716
	return 0;
717

718 719 720 721 722
 out_ucode_group:
	sysfs_remove_group(&cpu_subsys.dev_root->kobj,
			   &cpu_root_microcode_group);

 out_driver:
723 724 725
	get_online_cpus();
	mutex_lock(&microcode_mutex);

726
	subsys_interface_unregister(&mc_cpu_interface);
727 728 729 730

	mutex_unlock(&microcode_mutex);
	put_online_cpus();

731
 out_pdev:
732 733 734
	platform_device_unregister(microcode_pdev);
	return error;

P
Peter Oruba 已提交
735
}
736
fs_initcall(save_microcode_in_initrd);
737
late_initcall(microcode_init);