/* * Cache IA32_UMWAIT_CONTROL MSR. This is a systemwide control. By default, * umwait max time is 100000 in TSC-quanta and C0.2 is enabled
*/ static u32 umwait_control_cached = UMWAIT_CTRL_VAL(100000, UMWAIT_C02_ENABLE);
/* * Cache the original IA32_UMWAIT_CONTROL MSR value which is configured by * hardware or BIOS before kernel boot.
*/ static u32 orig_umwait_control_cached __ro_after_init;
/* * Serialize access to umwait_control_cached and IA32_UMWAIT_CONTROL MSR in * the sysfs write functions.
*/ static DEFINE_MUTEX(umwait_lock);
/* * The CPU hotplug callback sets the control MSR to the global control * value. * * Disable interrupts so the read of umwait_control_cached and the WRMSR * are protected against a concurrent sysfs write. Otherwise the sysfs * write could update the cached value after it had been read on this CPU * and issue the IPI before the old value had been written. The IPI would * interrupt, write the new value and after return from IPI the previous * value would be written by this CPU. * * With interrupts disabled the upcoming CPU either sees the new control * value or the IPI is updating this CPU to the new control value after * interrupts have been reenabled.
*/ staticint umwait_cpu_online(unsignedint cpu)
{
local_irq_disable();
umwait_update_control_msr(NULL);
local_irq_enable(); return 0;
}
/* * The CPU hotplug callback sets the control MSR to the original control * value.
*/ staticint umwait_cpu_offline(unsignedint cpu)
{ /* * This code is protected by the CPU hotplug already and * orig_umwait_control_cached is never changed after it caches * the original control MSR value in umwait_init(). So there * is no race condition here.
*/
wrmsrq(MSR_IA32_UMWAIT_CONTROL, orig_umwait_control_cached);
return 0;
}
/* * On resume, restore IA32_UMWAIT_CONTROL MSR on the boot processor which * is the only active CPU at this time. The MSR is set up on the APs via the * CPU hotplug callback. * * This function is invoked on resume from suspend and hibernation. On * resume from suspend the restore should be not required, but we neither * trust the firmware nor does it matter if the same value is written * again.
*/ staticvoid umwait_syscore_resume(void)
{
umwait_update_control_msr(NULL);
}
/* * When bit 0 in IA32_UMWAIT_CONTROL MSR is 1, C0.2 is disabled. * Otherwise, C0.2 is enabled.
*/ staticinlinebool umwait_ctrl_c02_enabled(u32 ctrl)
{ return !(ctrl & MSR_IA32_UMWAIT_CONTROL_C02_DISABLE);
}
staticint __init umwait_init(void)
{ struct device *dev; int ret;
if (!boot_cpu_has(X86_FEATURE_WAITPKG)) return -ENODEV;
/* * Cache the original control MSR value before the control MSR is * changed. This is the only place where orig_umwait_control_cached * is modified.
*/
rdmsrq(MSR_IA32_UMWAIT_CONTROL, orig_umwait_control_cached);
ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "umwait:online",
umwait_cpu_online, umwait_cpu_offline); if (ret < 0) { /* * On failure, the control MSR on all CPUs has the * original control value.
*/ return ret;
}
register_syscore_ops(&umwait_syscore_ops);
/* * Add umwait control interface. Ignore failure, so at least the * default values are set up in case the machine manages to boot.
*/
dev = bus_get_dev_root(&cpu_subsys); if (dev) {
ret = sysfs_create_group(&dev->kobj, &umwait_attr_group);
put_device(dev);
} return ret;
}
device_initcall(umwait_init);
Messung V0.5
¤ Dauer der Verarbeitung: 0.21 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.