Commit-ID: bd9a0c97e53c3d7a56b2751179903ddc5da42683 Gitweb: https://git.kernel.org/tip/bd9a0c97e53c3d7a56b2751179903ddc5da42683 Author: Fenghua Yu <[email protected]> AuthorDate: Wed, 19 Jun 2019 18:33:57 -0700 Committer: Thomas Gleixner <[email protected]> CommitDate: Mon, 24 Jun 2019 01:44:20 +0200
x86/umwait: Add sysfs interface to control umwait maximum time IA32_UMWAIT_CONTROL[31:2] determines the maximum time in TSC-quanta that processor can stay in C0.1 or C0.2. A zero value means no maximum time. Each instruction sets its own deadline in the instruction's implicit input EDX:EAX value. The instruction wakes up if the time-stamp counter reaches or exceeds the specified deadline, or the umwait maximum time expires, or a store happens in the monitored address range in umwait. The administrator can write an unsigned 32-bit number to /sys/devices/system/cpu/umwait_control/max_time to change the default value. Note that a value of zero means there is no limit. The lower two bits of the value must be zero. [ tglx: Simplify the write function. Massage changelog ] Signed-off-by: Fenghua Yu <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Ashok Raj <[email protected]> Reviewed-by: Tony Luck <[email protected]> Cc: "Borislav Petkov" <[email protected]> Cc: "H Peter Anvin" <[email protected]> Cc: "Andy Lutomirski" <[email protected]> Cc: "Peter Zijlstra" <[email protected]> Cc: "Ravi V Shankar" <[email protected]> Link: https://lkml.kernel.org/r/[email protected] --- arch/x86/kernel/cpu/umwait.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/arch/x86/kernel/cpu/umwait.c b/arch/x86/kernel/cpu/umwait.c index 56149d630e35..6a204e7336c1 100644 --- a/arch/x86/kernel/cpu/umwait.c +++ b/arch/x86/kernel/cpu/umwait.c @@ -131,8 +131,44 @@ static ssize_t enable_c02_store(struct device *dev, } static DEVICE_ATTR_RW(enable_c02); +static ssize_t +max_time_show(struct device *kobj, struct device_attribute *attr, char *buf) +{ + u32 ctrl = READ_ONCE(umwait_control_cached); + + return sprintf(buf, "%u\n", umwait_ctrl_max_time(ctrl)); +} + +static ssize_t max_time_store(struct device *kobj, + struct device_attribute *attr, + const char *buf, size_t count) +{ + u32 max_time, ctrl; + int ret; + + ret = kstrtou32(buf, 0, &max_time); + if (ret) + return ret; + + /* bits[1:0] must be zero */ + if (max_time & ~MSR_IA32_UMWAIT_CONTROL_TIME_MASK) + return -EINVAL; + + mutex_lock(&umwait_lock); + + ctrl = READ_ONCE(umwait_control_cached); + if (max_time != umwait_ctrl_max_time(ctrl)) + umwait_update_control(max_time, umwait_ctrl_c02_enabled(ctrl)); + + mutex_unlock(&umwait_lock); + + return count; +} +static DEVICE_ATTR_RW(max_time); + static struct attribute *umwait_attrs[] = { &dev_attr_enable_c02.attr, + &dev_attr_max_time.attr, NULL };

