Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp1607304imu; Wed, 16 Jan 2019 23:51:36 -0800 (PST) X-Google-Smtp-Source: ALg8bN5ASJkswTVd3an/pmCUf3j5T0RvIDnxUYdvtNFDF9cVOWZEflhLX1YKPiq2hWmKdQZq3m6G X-Received: by 2002:aa7:83c6:: with SMTP id j6mr13930054pfn.91.1547711496003; Wed, 16 Jan 2019 23:51:36 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1547711495; cv=none; d=google.com; s=arc-20160816; b=DopEqEozoPLgYUB5LfsMHvJA5e8geMU+AI0HPJUZkBsmlQQXvGSZWCjdMX3TeEM81h 3tx+twPg1zkiFlWH6w7Ch2d6T0sJCDwKYn7/DPlE1Xx1Y2x1ModEQsBDLXIfY9Jmwtdk vUKGWeNRTzj6Il0kgDeQug4qnsCZxK9hX2pJedEAM6Ucs7xBIl9Ie/wJXtCedhUp84L1 PDk1Aj6MhK9iMB3XgnFsA7AwK9uJpNO+FiHYB/KMXgf59xGCgR1vg+SE896Jfvik4s7L d1ZFlrcMGgz3Ygyp5NoIo3y3Se5MpuvGLSm8pK8aDuF0b/9x/u6NcwVIVitSkl4rczWI 3U6g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=CI64EwttL1IxavYwjjo1wTwUR3Q+8oL4c52O/8oomR0=; b=zAfED3LFCYFIbmrPCTG8BUZ3VhMhe4jWYB88+V4coku9/UJzntpKJcBEDq25QNgWVK zUCYg71KWCsS9F1X+f87JRrwz86Pu6rGHqMWYQSGAJ1cCqVyXhtEkmOakFG4Sp7WwHZ2 vV2PXaO4f1OH7H4QhmD5FE4qIlus19d90Y1ONDrtpg2db+RJdXZLorfs3OqaU+WBSOZD v9ZlQdSuLCkB9Pvz2TOyIt+h6yEF8ZHQxU2STBOJNMS5VgArwJH3UbaQThd79kVxxb1e 8MItj2aIdiv8OJZM61LArC8UiLgs/w0Lf/Kj3s5Z5wCMM/Y9bDSBBj3W7poPm7L5Jji6 LEkQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id j1si974274pff.42.2019.01.16.23.51.20; Wed, 16 Jan 2019 23:51:35 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729945AbfAPVZP (ORCPT + 99 others); Wed, 16 Jan 2019 16:25:15 -0500 Received: from mga11.intel.com ([192.55.52.93]:32307 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729479AbfAPVYf (ORCPT ); Wed, 16 Jan 2019 16:24:35 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 16 Jan 2019 13:24:35 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,487,1539673200"; d="scan'208";a="117269588" Received: from romley-ivt3.sc.intel.com ([172.25.110.60]) by fmsmga008.fm.intel.com with ESMTP; 16 Jan 2019 13:24:34 -0800 From: Fenghua Yu To: "Thomas Gleixner" , "Borislav Petkov" , "Ingo Molnar" , "H Peter Anvin" , "Andy Lutomirski" , "Andrew Cooper" , "Ashok Raj" , "Ravi V Shankar" Cc: "linux-kernel" , "x86" , Fenghua Yu Subject: [PATCH v2 2/3] x86/umwait: Setup umwait C0.2 state Date: Wed, 16 Jan 2019 13:18:37 -0800 Message-Id: <1547673522-226408-3-git-send-email-fenghua.yu@intel.com> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1547673522-226408-1-git-send-email-fenghua.yu@intel.com> References: <1547673522-226408-1-git-send-email-fenghua.yu@intel.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org UMWAIT or TPAUSE called by user process makes processor to reside in a light-weight power/performance optimized state (C0.1 state) or an improved power/performance optimized state (C0.2 state). IA32_UMWAIT_CONTROL MSR register allows OS to set global maximum umwait time and disable C0.2 on the processor. By default C0.2 is enabled so user wait instructions can enter the state if user wants to save more power but wakeup time is slower. In some cases e.g. real time, user wants to disable C0.2 and all C0.2 requests revert to C0.1. A new "/sys/devices/system/cpu/umwait_control/umwait_enable_c0_2" file is created to allow user to check if C0.2 is enabled or disabled and also allow user to enable or disable C0.2. Value "0" in the file means C0.2 is disabled. Value "1" means C0.2 is enabled. Signed-off-by: Fenghua Yu --- arch/x86/include/asm/msr-index.h | 4 ++ arch/x86/power/Makefile | 1 + arch/x86/power/umwait.c | 114 +++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 arch/x86/power/umwait.c diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 8e40c2446fd1..b56bfecae0de 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -59,6 +59,10 @@ #define MSR_PLATFORM_INFO_CPUID_FAULT_BIT 31 #define MSR_PLATFORM_INFO_CPUID_FAULT BIT_ULL(MSR_PLATFORM_INFO_CPUID_FAULT_BIT) +#define MSR_IA32_UMWAIT_CONTROL 0xe1 +#define UMWAIT_CONTROL_C02_BIT 0x0 +#define UMWAIT_CONTROL_C02_MASK 0x00000001 + #define MSR_PKG_CST_CONFIG_CONTROL 0x000000e2 #define NHM_C3_AUTO_DEMOTE (1UL << 25) #define NHM_C1_AUTO_DEMOTE (1UL << 26) diff --git a/arch/x86/power/Makefile b/arch/x86/power/Makefile index 37923d715741..62e2c609d1fe 100644 --- a/arch/x86/power/Makefile +++ b/arch/x86/power/Makefile @@ -8,3 +8,4 @@ CFLAGS_cpu.o := $(nostackp) obj-$(CONFIG_PM_SLEEP) += cpu.o obj-$(CONFIG_HIBERNATION) += hibernate_$(BITS).o hibernate_asm_$(BITS).o hibernate.o +obj-y += umwait.o diff --git a/arch/x86/power/umwait.c b/arch/x86/power/umwait.c new file mode 100644 index 000000000000..95b3867aac1e --- /dev/null +++ b/arch/x86/power/umwait.c @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Sysfs interface for umwait control + * + * Copyright (C) 2018, Intel Corporation. + * + * Author: Fenghua Yu + */ +#include +#include + +static int umwait_enable_c0_2 = 1; /* 0: disable C0.2. 1: enable C0.2. */ +static DEFINE_MUTEX(umwait_lock); + +/* Return value that will be used to set umwait control MSR */ +static inline u32 umwait_control_val(void) +{ + /* + * Enable or disable C0.2 (bit 0) based on global setting on all CPUs. + * When bit 0 is 1, C0.2 is disabled. Otherwise, C0.2 is enabled. + * So value in bit 0 is opposite of umwait_enable_c0_2. + */ + return ~umwait_enable_c0_2 & UMWAIT_CONTROL_C02_MASK; +} + +static ssize_t umwait_enable_c0_2_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", umwait_enable_c0_2); +} + +static ssize_t umwait_enable_c0_2_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int enable_c0_2, cpu, ret; + u32 msr_val; + + ret = kstrtou32(buf, 10, &enable_c0_2); + if (ret) + return ret; + + if (enable_c0_2 != 1 && enable_c0_2 != 0) + return -EINVAL; + + mutex_lock(&umwait_lock); + + umwait_enable_c0_2 = enable_c0_2; + msr_val = umwait_control_val(); + get_online_cpus(); + /* All CPUs have same umwait control setting */ + for_each_online_cpu(cpu) + wrmsr_on_cpu(cpu, MSR_IA32_UMWAIT_CONTROL, msr_val, 0); + put_online_cpus(); + + mutex_unlock(&umwait_lock); + + return count; +} + +static DEVICE_ATTR_RW(umwait_enable_c0_2); + +static struct attribute *umwait_attrs[] = { + &dev_attr_umwait_enable_c0_2.attr, + NULL +}; + +static struct attribute_group umwait_attr_group = { + .attrs = umwait_attrs, + .name = "umwait_control", +}; + +/* Set up umwait control MSR on this CPU using the current global setting. */ +static int umwait_cpu_online(unsigned int cpu) +{ + u32 msr_val; + + mutex_lock(&umwait_lock); + + msr_val = umwait_control_val(); + wrmsr(MSR_IA32_UMWAIT_CONTROL, msr_val, 0); + + mutex_unlock(&umwait_lock); + + return 0; +} + +static int __init umwait_init(void) +{ + struct device *dev; + int ret; + + if (!boot_cpu_has(X86_FEATURE_WAITPKG)) + return -ENODEV; + + /* Add CPU global user wait interface to control umwait. */ + dev = cpu_subsys.dev_root; + ret = sysfs_create_group(&dev->kobj, &umwait_attr_group); + if (ret) + return ret; + + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "umwait/intel:online", + umwait_cpu_online, NULL); + if (ret < 0) + goto out_group; + + return 0; +out_group: + sysfs_remove_group(&dev->kobj, &umwait_attr_group); + + return ret; +} +device_initcall(umwait_init); -- 2.19.1