X86 microcode updates:
- Disable late microcode loading by default. Unless the HW people get their act together and provide a required minimum version in the microcode header for making a halfways informed decision its just lottery and broken. - Warn and taint the kernel when microcode is loaded late - Remove the old unused microcode loader interface - Remove a redundant perf callback from the microcode loader -----BEGIN PGP SIGNATURE----- iQJHBAABCgAxFiEEQp8+kY+LLUocC4bMphj1TA10mKEFAmKcdjETHHRnbHhAbGlu dXRyb25peC5kZQAKCRCmGPVMDXSYoUUTD/92cLMB0g7XP8yFN+ZiHl7uoaDtE0UR WfapnMNL3tKKVnuwEMg83AjtyQ+O1JNZ6iS5K8jmiBnBByg6EQccz8pfe3jUQ6Ar gOLWV1F4tRbJD2NqqiWOo/l5qs5hJaz/QeE+oyCP0fvw6DOZixepG5RzveFSSwAa G2Q03GsGEu84SXlVAjagMSU6tYlBnlZBfKRB8NiNxkW8CLcJY0NfDCunbN6icEbH AQHXeviM3GWMKJA9R9DeSvYq9PbN5o2UVmcFQWsDAzZ8Ne2qCqskjoGNjuQ9s+72 G35fm5d7dtIcrYg4PSJN0JDJP4HbcfSjhUrbdH4iAClTkGnNQERfuDV9O92/lYJE hd9c8yCegD0NWQ4dMNNrM5PSbWbQK7ajqRYVvqqouJZpH+IDtajA1jxEe+1msB8P xmXQDcdSMOyVs+Bw3Djf3tt8Qqhu4jxnf3y711oLklPwwh9lq9SvaWiX9ZFoYgdn 1HVtQUAOdgDmncs5BQ8dpuwtoYXH5p31n0wh57emyFXl7wA93eWouuFczQ6mSol9 LLdd9c+q9mBFIo0ult+fVhEOTDJF+27s3YXOpge6BAqei/SQIU4c5oq51CukV7ap TPzWAayq0lsAwXn1k6r86Zkewh1C2SQTyk1J3zMehZlSVpwSWbEQASYlKywmh6YB N+6/0XtHDAVK5Q== =DQjr -----END PGP SIGNATURE----- Merge tag 'x86-microcode-2022-06-05' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip Pull x86 microcode updates from Thomas Gleixner: - Disable late microcode loading by default. Unless the HW people get their act together and provide a required minimum version in the microcode header for making a halfways informed decision its just lottery and broken. - Warn and taint the kernel when microcode is loaded late - Remove the old unused microcode loader interface - Remove a redundant perf callback from the microcode loader * tag 'x86-microcode-2022-06-05' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/microcode: Remove unnecessary perf callback x86/microcode: Taint and warn on late loading x86/microcode: Default-disable late loading x86/microcode: Rip out the OLD_INTERFACE
This commit is contained in:
commit
9784edd73a
@ -1358,17 +1358,16 @@ config MICROCODE_AMD
|
|||||||
If you select this option, microcode patch loading support for AMD
|
If you select this option, microcode patch loading support for AMD
|
||||||
processors will be enabled.
|
processors will be enabled.
|
||||||
|
|
||||||
config MICROCODE_OLD_INTERFACE
|
config MICROCODE_LATE_LOADING
|
||||||
bool "Ancient loading interface (DEPRECATED)"
|
bool "Late microcode loading (DANGEROUS)"
|
||||||
default n
|
default n
|
||||||
depends on MICROCODE
|
depends on MICROCODE
|
||||||
help
|
help
|
||||||
DO NOT USE THIS! This is the ancient /dev/cpu/microcode interface
|
Loading microcode late, when the system is up and executing instructions
|
||||||
which was used by userspace tools like iucode_tool and microcode.ctl.
|
is a tricky business and should be avoided if possible. Just the sequence
|
||||||
It is inadequate because it runs too late to be able to properly
|
of synchronizing all cores and SMT threads is one fragile dance which does
|
||||||
load microcode on a machine and it needs special tools. Instead, you
|
not guarantee that cores might not softlock after the loading. Therefore,
|
||||||
should've switched to the early loading method with the initrd or
|
use this at your own risk. Late loading taints the kernel too.
|
||||||
builtin microcode by now: Documentation/x86/microcode.rst
|
|
||||||
|
|
||||||
config X86_MSR
|
config X86_MSR
|
||||||
tristate "/dev/cpu/*/msr - Model-specific register support"
|
tristate "/dev/cpu/*/msr - Model-specific register support"
|
||||||
|
@ -2222,6 +2222,7 @@ void cpu_init_secondary(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_MICROCODE_LATE_LOADING
|
||||||
/*
|
/*
|
||||||
* The microcode loader calls this upon late microcode load to recheck features,
|
* The microcode loader calls this upon late microcode load to recheck features,
|
||||||
* only when microcode has been updated. Caller holds microcode_mutex and CPU
|
* only when microcode has been updated. Caller holds microcode_mutex and CPU
|
||||||
@ -2251,6 +2252,7 @@ void microcode_check(void)
|
|||||||
pr_warn("x86/CPU: CPU features have changed after loading microcode, but might not take effect.\n");
|
pr_warn("x86/CPU: CPU features have changed after loading microcode, but might not take effect.\n");
|
||||||
pr_warn("x86/CPU: Please consider either early loading through initrd/built-in or a potential BIOS update.\n");
|
pr_warn("x86/CPU: Please consider either early loading through initrd/built-in or a potential BIOS update.\n");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Invoked from core CPU hotplug code after hotplug operations
|
* Invoked from core CPU hotplug code after hotplug operations
|
||||||
|
@ -373,101 +373,10 @@ static int apply_microcode_on_target(int cpu)
|
|||||||
return ret;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
cpus_read_lock();
|
|
||||||
mutex_lock(µcode_mutex);
|
|
||||||
|
|
||||||
if (do_microcode_update(buf, len) == 0)
|
|
||||||
ret = (ssize_t)len;
|
|
||||||
|
|
||||||
if (ret > 0)
|
|
||||||
perf_check_microcode();
|
|
||||||
|
|
||||||
mutex_unlock(µcode_mutex);
|
|
||||||
cpus_read_unlock();
|
|
||||||
|
|
||||||
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 = µcode_fops,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int __init microcode_dev_init(void)
|
|
||||||
{
|
|
||||||
int error;
|
|
||||||
|
|
||||||
error = misc_register(µcode_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(µcode_dev);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define microcode_dev_init() 0
|
|
||||||
#define microcode_dev_exit() do { } while (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* fake device for request_firmware */
|
/* fake device for request_firmware */
|
||||||
static struct platform_device *microcode_pdev;
|
static struct platform_device *microcode_pdev;
|
||||||
|
|
||||||
|
#ifdef CONFIG_MICROCODE_LATE_LOADING
|
||||||
/*
|
/*
|
||||||
* Late loading dance. Why the heavy-handed stomp_machine effort?
|
* Late loading dance. Why the heavy-handed stomp_machine effort?
|
||||||
*
|
*
|
||||||
@ -584,6 +493,9 @@ static int microcode_reload_late(void)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
pr_err("Attempting late microcode loading - it is dangerous and taints the kernel.\n");
|
||||||
|
pr_err("You should switch to early loading, if possible.\n");
|
||||||
|
|
||||||
atomic_set(&late_cpus_in, 0);
|
atomic_set(&late_cpus_in, 0);
|
||||||
atomic_set(&late_cpus_out, 0);
|
atomic_set(&late_cpus_out, 0);
|
||||||
|
|
||||||
@ -632,9 +544,14 @@ put:
|
|||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
ret = size;
|
ret = size;
|
||||||
|
|
||||||
|
add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR_WO(reload);
|
||||||
|
#endif
|
||||||
|
|
||||||
static ssize_t version_show(struct device *dev,
|
static ssize_t version_show(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
@ -651,7 +568,6 @@ static ssize_t pf_show(struct device *dev,
|
|||||||
return sprintf(buf, "0x%x\n", uci->cpu_sig.pf);
|
return sprintf(buf, "0x%x\n", uci->cpu_sig.pf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEVICE_ATTR_WO(reload);
|
|
||||||
static DEVICE_ATTR(version, 0444, version_show, NULL);
|
static DEVICE_ATTR(version, 0444, version_show, NULL);
|
||||||
static DEVICE_ATTR(processor_flags, 0444, pf_show, NULL);
|
static DEVICE_ATTR(processor_flags, 0444, pf_show, NULL);
|
||||||
|
|
||||||
@ -804,7 +720,9 @@ static int mc_cpu_down_prep(unsigned int cpu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct attribute *cpu_root_microcode_attrs[] = {
|
static struct attribute *cpu_root_microcode_attrs[] = {
|
||||||
|
#ifdef CONFIG_MICROCODE_LATE_LOADING
|
||||||
&dev_attr_reload.attr,
|
&dev_attr_reload.attr,
|
||||||
|
#endif
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -838,10 +756,7 @@ static int __init microcode_init(void)
|
|||||||
|
|
||||||
cpus_read_lock();
|
cpus_read_lock();
|
||||||
mutex_lock(µcode_mutex);
|
mutex_lock(µcode_mutex);
|
||||||
|
|
||||||
error = subsys_interface_register(&mc_cpu_interface);
|
error = subsys_interface_register(&mc_cpu_interface);
|
||||||
if (!error)
|
|
||||||
perf_check_microcode();
|
|
||||||
mutex_unlock(µcode_mutex);
|
mutex_unlock(µcode_mutex);
|
||||||
cpus_read_unlock();
|
cpus_read_unlock();
|
||||||
|
|
||||||
@ -856,10 +771,6 @@ static int __init microcode_init(void)
|
|||||||
goto out_driver;
|
goto out_driver;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = microcode_dev_init();
|
|
||||||
if (error)
|
|
||||||
goto out_ucode_group;
|
|
||||||
|
|
||||||
register_syscore_ops(&mc_syscore_ops);
|
register_syscore_ops(&mc_syscore_ops);
|
||||||
cpuhp_setup_state_nocalls(CPUHP_AP_MICROCODE_LOADER, "x86/microcode:starting",
|
cpuhp_setup_state_nocalls(CPUHP_AP_MICROCODE_LOADER, "x86/microcode:starting",
|
||||||
mc_cpu_starting, NULL);
|
mc_cpu_starting, NULL);
|
||||||
@ -870,10 +781,6 @@ static int __init microcode_init(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_ucode_group:
|
|
||||||
sysfs_remove_group(&cpu_subsys.dev_root->kobj,
|
|
||||||
&cpu_root_microcode_group);
|
|
||||||
|
|
||||||
out_driver:
|
out_driver:
|
||||||
cpus_read_lock();
|
cpus_read_lock();
|
||||||
mutex_lock(µcode_mutex);
|
mutex_lock(µcode_mutex);
|
||||||
|
Loading…
Reference in New Issue
Block a user