Commit 0bb88756 authored by Aichun Shi's avatar Aichun Shi
Browse files

Revert "x86/microcode: Rip out the OLD_INTERFACE"

Intel inclusion
category: feature
feature: Backport Intel In Field Scan(IFS) multi-blob images support
bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I6L337


CVE: N/A
Reference: N/A

Intel-SIG: Revert commit 05a2ea3f ("x86/microcode: Rip out the
OLD_INTERFACE")

-------------------------------------

This reverts commit 05a2ea3f.

This revert is to recover old microcode interface /dev/cpu/microcode.

Signed-off-by: default avatarAichun Shi <aichun.shi@intel.com>
parent 0ccb8568
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -1336,6 +1336,18 @@ config MICROCODE_AMD
	  If you select this option, microcode patch loading support for AMD
	  processors will be enabled.

config MICROCODE_OLD_INTERFACE
	bool "Ancient loading interface (DEPRECATED)"
	default n
	depends on MICROCODE
	help
	  DO NOT USE THIS! This is the ancient /dev/cpu/microcode interface
	  which was used by userspace tools like iucode_tool and microcode.ctl.
	  It is inadequate because it runs too late to be able to properly
	  load microcode on a machine and it needs special tools. Instead, you
	  should've switched to the early loading method with the initrd or
	  builtin microcode by now: Documentation/x86/microcode.rst

config X86_MSR
	tristate "/dev/cpu/*/msr - Model-specific register support"
	help
+100 −0
Original line number Diff line number Diff line
@@ -390,6 +390,98 @@ static int apply_microcode_on_target(int cpu)
	return ret;
}

#ifdef CONFIG_MICROCODE_OLD_INTERFACE
static int do_microcode_update(const void __user *buf, size_t size)
{
	int error = 0;
	int cpu;

	for_each_online_cpu(cpu) {
		struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
		enum ucode_state ustate;

		if (!uci->valid)
			continue;

		ustate = microcode_ops->request_microcode_user(cpu, buf, size);
		if (ustate == UCODE_ERROR) {
			error = -1;
			break;
		} else if (ustate == UCODE_NEW) {
			apply_microcode_on_target(cpu);
		}
	}

	return error;
}

static int microcode_open(struct inode *inode, struct file *file)
{
	return capable(CAP_SYS_RAWIO) ? stream_open(inode, file) : -EPERM;
}

static ssize_t microcode_write(struct file *file, const char __user *buf,
			       size_t len, loff_t *ppos)
{
	ssize_t ret = -EINVAL;
	unsigned long nr_pages = totalram_pages();

	if ((len >> PAGE_SHIFT) > nr_pages) {
		pr_err("too much data (max %ld pages)\n", nr_pages);
		return ret;
	}

	get_online_cpus();
	mutex_lock(&microcode_mutex);

	if (do_microcode_update(buf, len) == 0)
		ret = (ssize_t)len;

	if (ret > 0)
		perf_check_microcode();

	mutex_unlock(&microcode_mutex);
	put_online_cpus();

	return ret;
}

static const struct file_operations microcode_fops = {
	.owner			= THIS_MODULE,
	.write			= microcode_write,
	.open			= microcode_open,
	.llseek		= no_llseek,
};

static struct miscdevice microcode_dev = {
	.minor			= MICROCODE_MINOR,
	.name			= "microcode",
	.nodename		= "cpu/microcode",
	.fops			= &microcode_fops,
};

static int __init microcode_dev_init(void)
{
	int error;

	error = misc_register(&microcode_dev);
	if (error) {
		pr_err("can't misc_register on minor=%d\n", MICROCODE_MINOR);
		return error;
	}

	return 0;
}

static void __exit microcode_dev_exit(void)
{
	misc_deregister(&microcode_dev);
}
#else
#define microcode_dev_init()	0
#define microcode_dev_exit()	do { } while (0)
#endif

/* fake device for request_firmware */
static struct platform_device	*microcode_pdev;

@@ -781,6 +873,10 @@ int __init microcode_init(void)
		goto out_driver;
	}

	error = microcode_dev_init();
	if (error)
		goto out_ucode_group;

	register_syscore_ops(&mc_syscore_ops);
	cpuhp_setup_state_nocalls(CPUHP_AP_MICROCODE_LOADER, "x86/microcode:starting",
				  mc_cpu_starting, NULL);
@@ -791,6 +887,10 @@ int __init microcode_init(void)

	return 0;

 out_ucode_group:
	sysfs_remove_group(&cpu_subsys.dev_root->kobj,
			   &cpu_root_microcode_group);

 out_driver:
	get_online_cpus();
	mutex_lock(&microcode_mutex);