From patchwork Tue Jun 7 12:05:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "tarumizu.kohei@fujitsu.com" X-Patchwork-Id: 579488 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4FFDCC43334 for ; Tue, 7 Jun 2022 12:09:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243580AbiFGMIr (ORCPT ); Tue, 7 Jun 2022 08:08:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55402 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243592AbiFGMIq (ORCPT ); Tue, 7 Jun 2022 08:08:46 -0400 Received: from esa9.hc1455-7.c3s2.iphmx.com (esa9.hc1455-7.c3s2.iphmx.com [139.138.36.223]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EC3E78A305 for ; Tue, 7 Jun 2022 05:08:43 -0700 (PDT) X-IronPort-AV: E=McAfee;i="6400,9594,10370"; a="63616613" X-IronPort-AV: E=Sophos;i="5.91,283,1647270000"; d="scan'208";a="63616613" Received: from unknown (HELO oym-r2.gw.nic.fujitsu.com) ([210.162.30.90]) by esa9.hc1455-7.c3s2.iphmx.com with ESMTP; 07 Jun 2022 21:07:36 +0900 Received: from oym-m1.gw.nic.fujitsu.com (oym-nat-oym-m1.gw.nic.fujitsu.com [192.168.87.58]) by oym-r2.gw.nic.fujitsu.com (Postfix) with ESMTP id 58938F3130; Tue, 7 Jun 2022 21:07:35 +0900 (JST) Received: from oym-om4.fujitsu.com (oym-om4.o.css.fujitsu.com [10.85.58.164]) by oym-m1.gw.nic.fujitsu.com (Postfix) with ESMTP id 5CB41D99EF; Tue, 7 Jun 2022 21:07:34 +0900 (JST) Received: from cn-r05-10.example.com (n3235113.np.ts.nmh.cs.fujitsu.co.jp [10.123.235.113]) by oym-om4.fujitsu.com (Postfix) with ESMTP id 1775F4007FE5D; Tue, 7 Jun 2022 21:07:34 +0900 (JST) From: Kohei Tarumizu To: catalin.marinas@arm.com, will@kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, rafael@kernel.org, lenb@kernel.org, gregkh@linuxfoundation.org, mchehab+huawei@kernel.org, eugenis@google.com, tony.luck@intel.com, pcc@google.com, peterz@infradead.org, marcos@orca.pet, marcan@marcan.st, linus.walleij@linaro.org, nicolas.ferre@microchip.com, conor.dooley@microchip.com, arnd@arndb.de, ast@kernel.org, peter.chen@kernel.org, kuba@kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-acpi@vger.kernel.org Cc: tarumizu.kohei@fujitsu.com Subject: [PATCH v5 1/6] soc: fujitsu: Add hardware prefetch control driver for A64FX Date: Tue, 7 Jun 2022 21:05:25 +0900 Message-Id: <20220607120530.2447112-2-tarumizu.kohei@fujitsu.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20220607120530.2447112-1-tarumizu.kohei@fujitsu.com> References: <20220607120530.2447112-1-tarumizu.kohei@fujitsu.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Adds module init/exit code to create sysfs attributes for A64FX with "stream_detect_prefetcher_enable", "stream_detect_prefetcher_strong" and "stream_detect_prefetcher_dist". This driver works only if part number is FUJITSU_CPU_PART_A64FX. The details of the registers to be read and written in this patch are described below. "https://github.com/fujitsu/A64FX/tree/master/doc/" A64FX_Specification_HPC_Extension_v1_EN.pdf Signed-off-by: Kohei Tarumizu --- drivers/soc/fujitsu/a64fx-pfctl.c | 484 ++++++++++++++++++++++++++++++ 1 file changed, 484 insertions(+) create mode 100644 drivers/soc/fujitsu/a64fx-pfctl.c diff --git a/drivers/soc/fujitsu/a64fx-pfctl.c b/drivers/soc/fujitsu/a64fx-pfctl.c new file mode 100644 index 000000000000..1bb45a365c0f --- /dev/null +++ b/drivers/soc/fujitsu/a64fx-pfctl.c @@ -0,0 +1,484 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2022 FUJITSU LIMITED + * + * A64FX Hardware Prefetch Control support + */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Constants for these add the "A64FX_SDPF" prefix to the name described in + * section "1.3.4.2. IMP_PF_STREAM_DETECT_CTRL_EL0" of "A64FX specification". + * (https://github.com/fujitsu/A64FX/tree/master/doc/A64FX_Specification_HPC_Extension_v1_EN.pdf") + * See this document for register specification details. + */ +#define A64FX_SDPF_IMP_PF_STREAM_DETECT_CTRL_EL0 sys_reg(3, 3, 11, 4, 0) +#define A64FX_SDPF_V BIT_ULL(63) +#define A64FX_SDPF_L1PF_DIS BIT_ULL(59) +#define A64FX_SDPF_L2PF_DIS BIT_ULL(58) +#define A64FX_SDPF_L1W BIT_ULL(55) +#define A64FX_SDPF_L2W BIT_ULL(54) +#define A64FX_SDPF_L1_DIST GENMASK_ULL(27, 24) +#define A64FX_SDPF_L2_DIST GENMASK_ULL(19, 16) + +#define PFCTL_MIN_L1_DIST 256 +#define PFCTL_MIN_L2_DIST 1024 +#define PFCTL_DIST_AUTO_VAL 0 +#define PFCTL_STRONG_VAL 0 +#define PFCTL_WEAK_VAL 1 + +/* + * Define bitfield access macros for non-constant mask, because macros such as + * FIELD_FIT defined in include/linux/bitfield.h require constant mask. + */ +#define NC_FIELD_FIT(_mask, _val) \ + !((((typeof(_mask))_val) << __bf_shf(_mask)) & ~(_mask)) + +#define NC_FIELD_PREP(_mask, _val) \ + (((typeof(_mask))(_val) << __bf_shf(_mask)) & (_mask)) + +#define NC_FIELD_GET(_mask, _reg) \ + ((typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask))) + +struct a64fx_pfctl_attr { + struct device_attribute attr; + u64 mask; + void *data; +}; + +struct pfctl_group { + unsigned int level; + enum cache_type type; + const struct attribute_group **groups; +}; + +enum cpuhp_state hp_online; + +static const char strength_strong_string[] = "strong"; +static const char strength_weak_string[] = "weak"; +static const char dist_auto_string[] = "auto"; + +static inline unsigned int pfctl_dev_get_cpu(struct device *pfctl_dev) +{ + return *(u32 *)dev_get_drvdata(pfctl_dev); +} + +/* Enable the value written to the A64FX_SDPF_IMP_PF_STREAM_DETECT_CTRL_EL0 */ +static inline void enable_verify(u64 *reg) +{ + *reg |= NC_FIELD_PREP(A64FX_SDPF_V, 1); +} + +static void _pfctl_read_mask(void *_reg) +{ + u64 *reg = (u64 *)_reg; + + *reg = read_sysreg_s(A64FX_SDPF_IMP_PF_STREAM_DETECT_CTRL_EL0); +} + +static u64 pfctl_read_mask(unsigned int cpu, u64 mask) +{ + u64 reg; + + smp_call_function_single(cpu, _pfctl_read_mask, ®, true); + + return NC_FIELD_GET(mask, reg); +} + +struct write_info { + u64 mask; + u64 val; +}; + +static void _pfctl_write_mask(void *info) +{ + struct write_info *winfo = info; + u64 reg; + + reg = read_sysreg_s(A64FX_SDPF_IMP_PF_STREAM_DETECT_CTRL_EL0); + + reg &= ~winfo->mask; + reg |= NC_FIELD_PREP(winfo->mask, winfo->val); + + enable_verify(®); + + write_sysreg_s(reg, A64FX_SDPF_IMP_PF_STREAM_DETECT_CTRL_EL0); +} + +static int pfctl_write_mask(unsigned int cpu, u64 mask, u64 val) +{ + struct write_info info = { + .mask = mask, + .val = val, + }; + + if (!NC_FIELD_FIT(mask, val)) + return -EINVAL; + + smp_call_function_single(cpu, _pfctl_write_mask, &info, true); + + return 0; +} + +static ssize_t +pfctl_enable_show(struct device *pfctl_dev, struct device_attribute *attr, + char *buf) +{ + unsigned int cpu = pfctl_dev_get_cpu(pfctl_dev); + struct a64fx_pfctl_attr *aa; + bool val; + + aa = container_of(attr, struct a64fx_pfctl_attr, attr); + + val = (bool)pfctl_read_mask(cpu, aa->mask); + + return sysfs_emit(buf, "%d\n", val ? 0 : 1); +} + +static ssize_t +pfctl_enable_store(struct device *pfctl_dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + unsigned int cpu = pfctl_dev_get_cpu(pfctl_dev); + struct a64fx_pfctl_attr *aa; + bool val; + int ret; + + aa = container_of(attr, struct a64fx_pfctl_attr, attr); + + if (strtobool(buf, &val) < 0) + return -EINVAL; + + ret = pfctl_write_mask(cpu, aa->mask, val ? 0 : 1); + if (ret < 0) + return ret; + + return size; +} + +#define A64FX_PFCTL_ENABLE_ATTR(_level, _mask) \ + struct a64fx_pfctl_attr attr_l##_level##_enable = { \ + .attr = __ATTR(stream_detect_prefetcher_enable, 0600, \ + pfctl_enable_show, pfctl_enable_store), \ + .mask = _mask, } + + +static A64FX_PFCTL_ENABLE_ATTR(1, A64FX_SDPF_L1PF_DIS); +static A64FX_PFCTL_ENABLE_ATTR(2, A64FX_SDPF_L2PF_DIS); + +static ssize_t +pfctl_dist_show(struct device *pfctl_dev, struct device_attribute *attr, + char *buf) +{ + unsigned int cpu = pfctl_dev_get_cpu(pfctl_dev); + struct a64fx_pfctl_attr *aa; + u64 val, min_dist; + + aa = container_of(attr, struct a64fx_pfctl_attr, attr); + min_dist = (u64)aa->data; + + val = pfctl_read_mask(cpu, aa->mask); + + if (val == PFCTL_DIST_AUTO_VAL) + return sysfs_emit(buf, "%s\n", dist_auto_string); + else + return sysfs_emit(buf, "%llu\n", val * min_dist); +} + +static ssize_t +pfctl_dist_store(struct device *pfctl_dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + unsigned int cpu = pfctl_dev_get_cpu(pfctl_dev); + struct a64fx_pfctl_attr *aa; + u64 min_dist, val; + int ret; + + aa = container_of(attr, struct a64fx_pfctl_attr, attr); + min_dist = (u64)aa->data; + + if (sysfs_streq(buf, dist_auto_string)) { + val = PFCTL_DIST_AUTO_VAL; + } else { + ret = kstrtoull(buf, 10, &val); + if (ret < 0 || val < 1) + return -EINVAL; + } + + val = roundup(val, min_dist) / min_dist; + + if (!NC_FIELD_FIT(aa->mask, val)) + return -EINVAL; + + ret = pfctl_write_mask(cpu, aa->mask, val); + if (ret < 0) + return ret; + + return size; +} + +#define PFCTL_DIST_ATTR(_level, _mask, _min_dist) \ + struct a64fx_pfctl_attr attr_l##_level##_dist = { \ + .attr = __ATTR(stream_detect_prefetcher_dist, 0600, \ + pfctl_dist_show, pfctl_dist_store), \ + .mask = _mask, \ + .data = (void *)(u64)_min_dist, } + +static PFCTL_DIST_ATTR(1, A64FX_SDPF_L1_DIST, PFCTL_MIN_L1_DIST); +static PFCTL_DIST_ATTR(2, A64FX_SDPF_L2_DIST, PFCTL_MIN_L2_DIST); + +static ssize_t +pfctl_strength_show(struct device *pfctl_dev, struct device_attribute *attr, + char *buf) +{ + unsigned int cpu = pfctl_dev_get_cpu(pfctl_dev); + struct a64fx_pfctl_attr *aa; + u64 val; + + aa = container_of(attr, struct a64fx_pfctl_attr, attr); + + val = pfctl_read_mask(cpu, aa->mask); + + switch (val) { + case PFCTL_STRONG_VAL: + return sysfs_emit(buf, "%s\n", strength_strong_string); + case PFCTL_WEAK_VAL: + return sysfs_emit(buf, "%s\n", strength_weak_string); + default: + return -EINVAL; + } +} + +static ssize_t +pfctl_strength_store(struct device *pfctl_dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + unsigned int cpu = pfctl_dev_get_cpu(pfctl_dev); + struct a64fx_pfctl_attr *aa; + u64 val; + int ret; + + aa = container_of(attr, struct a64fx_pfctl_attr, attr); + + if (sysfs_streq(buf, strength_strong_string)) + val = PFCTL_STRONG_VAL; + else if (sysfs_streq(buf, strength_weak_string)) + val = PFCTL_WEAK_VAL; + else + return -EINVAL; + + ret = pfctl_write_mask(cpu, aa->mask, val); + if (ret < 0) + return ret; + + return size; +} + +#define PFCTL_STRENGTH_ATTR(_level, _mask) \ + struct a64fx_pfctl_attr attr_l##_level##_strength = { \ + .attr = __ATTR(stream_detect_prefetcher_strength, 0600, \ + pfctl_strength_show, \ + pfctl_strength_store), \ + .mask = _mask, } + +static PFCTL_STRENGTH_ATTR(1, A64FX_SDPF_L1W); +static PFCTL_STRENGTH_ATTR(2, A64FX_SDPF_L2W); + +static ssize_t +pfctl_strength_available_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sysfs_emit(buf, "%s %s\n", strength_strong_string, + strength_weak_string); +} + +/* + * A64FX has same kind of available strength for any caches, so define only one + * attribute. + */ +struct a64fx_pfctl_attr attr_strength_available = { + .attr = __ATTR(stream_detect_prefetcher_strength_available, 0400, + pfctl_strength_available_show, NULL), }; + +static struct attribute *l1_attrs[] = { + &attr_l1_enable.attr.attr, + &attr_l1_dist.attr.attr, + &attr_l1_strength.attr.attr, + &attr_strength_available.attr.attr, + NULL, +}; + +static struct attribute *l2_attrs[] = { + &attr_l2_enable.attr.attr, + &attr_l2_dist.attr.attr, + &attr_l2_strength.attr.attr, + &attr_strength_available.attr.attr, + NULL, +}; + +static struct attribute_group l1_group = { + .attrs = l1_attrs, +}; + +static struct attribute_group l2_group = { + .attrs = l2_attrs, +}; + +static const struct attribute_group *l1_groups[] = { + &l1_group, + NULL, +}; + +static const struct attribute_group *l2_groups[] = { + &l2_group, + NULL, +}; + +static const struct pfctl_group pfctl_groups[] = { + { + .level = 1, + .type = CACHE_TYPE_DATA, + .groups = l1_groups, + }, + { + .level = 2, + .type = CACHE_TYPE_UNIFIED, + .groups = l2_groups, + }, + { + .groups = NULL, + }, +}; + +static const struct attribute_group ** +get_pfctl_attribute_groups(unsigned int level, enum cache_type type) +{ + int i; + + for (i = 0; pfctl_groups[i].groups; i++) + if ((level == pfctl_groups[i].level) && + (type == pfctl_groups[i].type)) + return pfctl_groups[i].groups; + + return NULL; +} + +static int create_pfctl_attr(struct device *index_dev, void *data) +{ + struct cacheinfo *leaf = dev_get_drvdata(index_dev); + const struct attribute_group **groups; + struct device *pfctl_dev; + + groups = get_pfctl_attribute_groups(leaf->level, leaf->type); + if (!groups) + return 0; + + pfctl_dev = cpu_device_create(index_dev, data, groups, + "prefetch_control"); + if (IS_ERR(pfctl_dev)) + return PTR_ERR(pfctl_dev); + + return 0; +} + +static int remove_pfctl_attr(struct device *index_dev, void *data) +{ + struct device *pfctl_dev; + + pfctl_dev = device_find_child_by_name(index_dev, "prefetch_control"); + if (!pfctl_dev) + return 0; + + device_unregister(pfctl_dev); + put_device(pfctl_dev); + + return 0; +} + +static int pfctl_online(unsigned int cpu) +{ + struct device *cpu_dev = get_cpu_device(cpu); + struct device *cache_dev; + int ret; + + cache_dev = device_find_child_by_name(cpu_dev, "cache"); + if (!cache_dev) + return -ENODEV; + + ret = device_for_each_child(cache_dev, &cpu_dev->id, create_pfctl_attr); + + put_device(cache_dev); + + return ret; +} + +static int pfctl_prepare_down(unsigned int cpu) +{ + struct device *cpu_dev = get_cpu_device(cpu); + struct device *cache_dev; + + cache_dev = device_find_child_by_name(cpu_dev, "cache"); + if (!cache_dev) + return 0; + + device_for_each_child(cache_dev, NULL, remove_pfctl_attr); + + put_device(cache_dev); + + return 0; +} + +static const struct midr_range pfctl_list[] __initconst = { + MIDR_ALL_VERSIONS(MIDR_FUJITSU_A64FX), +}; + +/* + * This driver returns a negative value if it does not support the Hardware + * Prefetch Control or if it is running on a VM guest. + */ +static int __init a64fx_pfctl_init(void) +{ + int ret; + + if (!is_kernel_in_hyp_mode()) + return -EINVAL; + + if (!is_midr_in_range_list(read_cpuid_id(), pfctl_list)) + return -ENODEV; + + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "soc/a64fx-pfctl:online", + pfctl_online, pfctl_prepare_down); + if (ret < 0) { + pr_err("failed to register hotplug callbacks\n"); + return ret; + } + + hp_online = ret; + + return 0; +} + +static void __exit a64fx_pfctl_exit(void) +{ + cpuhp_remove_state(hp_online); +} + +late_initcall(a64fx_pfctl_init); +module_exit(a64fx_pfctl_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("FUJITSU LIMITED"); +MODULE_DESCRIPTION("A64FX Hardware Prefetch Control Driver"); + +static const struct acpi_device_id fujitsu_acpi_match[] = { + { "FUJI2006", }, + {} +}; +MODULE_DEVICE_TABLE(acpi, fujitsu_acpi_match); From patchwork Tue Jun 7 12:05:26 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "tarumizu.kohei@fujitsu.com" X-Patchwork-Id: 579860 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8A349CCA47C for ; Tue, 7 Jun 2022 12:09:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243551AbiFGMJK (ORCPT ); Tue, 7 Jun 2022 08:09:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55770 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243563AbiFGMIv (ORCPT ); Tue, 7 Jun 2022 08:08:51 -0400 X-Greylist: delayed 67 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Tue, 07 Jun 2022 05:08:50 PDT Received: from esa6.hc1455-7.c3s2.iphmx.com (esa6.hc1455-7.c3s2.iphmx.com [68.232.139.139]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 34FD28B0AD for ; Tue, 7 Jun 2022 05:08:49 -0700 (PDT) X-IronPort-AV: E=McAfee;i="6400,9594,10370"; a="76072289" X-IronPort-AV: E=Sophos;i="5.91,283,1647270000"; d="scan'208";a="76072289" Received: from unknown (HELO oym-r3.gw.nic.fujitsu.com) ([210.162.30.91]) by esa6.hc1455-7.c3s2.iphmx.com with ESMTP; 07 Jun 2022 21:07:40 +0900 Received: from oym-m4.gw.nic.fujitsu.com (oym-nat-oym-m4.gw.nic.fujitsu.com [192.168.87.61]) by oym-r3.gw.nic.fujitsu.com (Postfix) with ESMTP id 1C30FD63BA; Tue, 7 Jun 2022 21:07:38 +0900 (JST) Received: from oym-om4.fujitsu.com (oym-om4.o.css.fujitsu.com [10.85.58.164]) by oym-m4.gw.nic.fujitsu.com (Postfix) with ESMTP id 1B52BD99E4; Tue, 7 Jun 2022 21:07:37 +0900 (JST) Received: from cn-r05-10.example.com (n3235113.np.ts.nmh.cs.fujitsu.co.jp [10.123.235.113]) by oym-om4.fujitsu.com (Postfix) with ESMTP id CCE964007FE5D; Tue, 7 Jun 2022 21:07:36 +0900 (JST) From: Kohei Tarumizu To: catalin.marinas@arm.com, will@kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, rafael@kernel.org, lenb@kernel.org, gregkh@linuxfoundation.org, mchehab+huawei@kernel.org, eugenis@google.com, tony.luck@intel.com, pcc@google.com, peterz@infradead.org, marcos@orca.pet, marcan@marcan.st, linus.walleij@linaro.org, nicolas.ferre@microchip.com, conor.dooley@microchip.com, arnd@arndb.de, ast@kernel.org, peter.chen@kernel.org, kuba@kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-acpi@vger.kernel.org Cc: tarumizu.kohei@fujitsu.com Subject: [PATCH v5 2/6] soc: fujitsu: Add Kconfig/Makefile to build hardware prefetch control driver Date: Tue, 7 Jun 2022 21:05:26 +0900 Message-Id: <20220607120530.2447112-3-tarumizu.kohei@fujitsu.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20220607120530.2447112-1-tarumizu.kohei@fujitsu.com> References: <20220607120530.2447112-1-tarumizu.kohei@fujitsu.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Adds Kconfig/Makefile to build hardware prefetch control driver for A64FX support, and also adds a MAINTAINERS entry. Signed-off-by: Kohei Tarumizu --- MAINTAINERS | 5 +++++ drivers/soc/Kconfig | 1 + drivers/soc/Makefile | 1 + drivers/soc/fujitsu/Kconfig | 26 ++++++++++++++++++++++++++ drivers/soc/fujitsu/Makefile | 2 ++ 5 files changed, 35 insertions(+) create mode 100644 drivers/soc/fujitsu/Kconfig create mode 100644 drivers/soc/fujitsu/Makefile diff --git a/MAINTAINERS b/MAINTAINERS index d6d879cb0afd..b3e920a8a044 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8620,6 +8620,11 @@ F: include/linux/hwmon*.h F: include/trace/events/hwmon*.h K: (devm_)?hwmon_device_(un)?register(|_with_groups|_with_info) +HARDWARE PREFETCH CONTROL DRIVERS +M: Kohei Tarumizu +S: Maintained +F: drivers/soc/fujitsu/a64fx-pfctl.c + HARDWARE RANDOM NUMBER GENERATOR CORE M: Matt Mackall M: Herbert Xu diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig index c5aae42673d3..d87754799d90 100644 --- a/drivers/soc/Kconfig +++ b/drivers/soc/Kconfig @@ -9,6 +9,7 @@ source "drivers/soc/atmel/Kconfig" source "drivers/soc/bcm/Kconfig" source "drivers/soc/canaan/Kconfig" source "drivers/soc/fsl/Kconfig" +source "drivers/soc/fujitsu/Kconfig" source "drivers/soc/imx/Kconfig" source "drivers/soc/ixp4xx/Kconfig" source "drivers/soc/litex/Kconfig" diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index 904eec2a7871..6c8ff1792cda 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_SOC_CANAAN) += canaan/ obj-$(CONFIG_ARCH_DOVE) += dove/ obj-$(CONFIG_MACH_DOVE) += dove/ obj-y += fsl/ +obj-y += fujitsu/ obj-$(CONFIG_ARCH_GEMINI) += gemini/ obj-y += imx/ obj-y += ixp4xx/ diff --git a/drivers/soc/fujitsu/Kconfig b/drivers/soc/fujitsu/Kconfig new file mode 100644 index 000000000000..6c5990b75cc5 --- /dev/null +++ b/drivers/soc/fujitsu/Kconfig @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0-only + +menu "Fujitsu SoC drivers" + +config ALLOW_INCOMPLETE_CACHE_SYSFS + bool + +config A64FX_HWPF_CONTROL + tristate "A64FX Hardware Prefetch Control driver" + depends on ARM64 + select ALLOW_INCOMPLETE_CACHE_SYSFS + help + This provides a sysfs interface to control the Hardware Prefetch + behavior for A64FX. + + A64FX has IMP_PF_STREAM_DETECT_CTRL_EL0, which can control the + hardware prefech behavior. If the processor supports this, the + module can be loaded with the name a64fx-pfctl. + + Depending on the characteristics of the application, this register + parameters improve or degrade performance. + + Please see Documentation/ABI/testing/sysfs-devices-system-cpu for + more information. + +endmenu diff --git a/drivers/soc/fujitsu/Makefile b/drivers/soc/fujitsu/Makefile new file mode 100644 index 000000000000..35e284a548bb --- /dev/null +++ b/drivers/soc/fujitsu/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-$(CONFIG_A64FX_HWPF_CONTROL) += a64fx-pfctl.o From patchwork Tue Jun 7 12:05:27 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "tarumizu.kohei@fujitsu.com" X-Patchwork-Id: 579861 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A95C2C433EF for ; Tue, 7 Jun 2022 12:09:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242324AbiFGMJH (ORCPT ); Tue, 7 Jun 2022 08:09:07 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56248 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243584AbiFGMI7 (ORCPT ); Tue, 7 Jun 2022 08:08:59 -0400 X-Greylist: delayed 70 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Tue, 07 Jun 2022 05:08:55 PDT Received: from esa1.hc1455-7.c3s2.iphmx.com (esa1.hc1455-7.c3s2.iphmx.com [207.54.90.47]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 75AA29157C for ; Tue, 7 Jun 2022 05:08:54 -0700 (PDT) X-IronPort-AV: E=McAfee;i="6400,9594,10370"; a="75590270" X-IronPort-AV: E=Sophos;i="5.91,283,1647270000"; d="scan'208";a="75590270" Received: from unknown (HELO oym-r3.gw.nic.fujitsu.com) ([210.162.30.91]) by esa1.hc1455-7.c3s2.iphmx.com with ESMTP; 07 Jun 2022 21:07:41 +0900 Received: from oym-m2.gw.nic.fujitsu.com (oym-nat-oym-m2.gw.nic.fujitsu.com [192.168.87.59]) by oym-r3.gw.nic.fujitsu.com (Postfix) with ESMTP id E57B4D63B8; Tue, 7 Jun 2022 21:07:40 +0900 (JST) Received: from oym-om4.fujitsu.com (oym-om4.o.css.fujitsu.com [10.85.58.164]) by oym-m2.gw.nic.fujitsu.com (Postfix) with ESMTP id 1C6D5BF4BA; Tue, 7 Jun 2022 21:07:40 +0900 (JST) Received: from cn-r05-10.example.com (n3235113.np.ts.nmh.cs.fujitsu.co.jp [10.123.235.113]) by oym-om4.fujitsu.com (Postfix) with ESMTP id D44CA40080208; Tue, 7 Jun 2022 21:07:39 +0900 (JST) From: Kohei Tarumizu To: catalin.marinas@arm.com, will@kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, rafael@kernel.org, lenb@kernel.org, gregkh@linuxfoundation.org, mchehab+huawei@kernel.org, eugenis@google.com, tony.luck@intel.com, pcc@google.com, peterz@infradead.org, marcos@orca.pet, marcan@marcan.st, linus.walleij@linaro.org, nicolas.ferre@microchip.com, conor.dooley@microchip.com, arnd@arndb.de, ast@kernel.org, peter.chen@kernel.org, kuba@kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-acpi@vger.kernel.org Cc: tarumizu.kohei@fujitsu.com Subject: [PATCH v5 3/6] arm64: Create cache sysfs directory without ACPI PPTT for hardware prefetch control Date: Tue, 7 Jun 2022 21:05:27 +0900 Message-Id: <20220607120530.2447112-4-tarumizu.kohei@fujitsu.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20220607120530.2447112-1-tarumizu.kohei@fujitsu.com> References: <20220607120530.2447112-1-tarumizu.kohei@fujitsu.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Create a cache sysfs directory without ACPI PPTT if the CPU model is A64FX and CONFIG_ALLOW_INCOMPLETE_CACHE_SYSFS is true. Currentry, CONFIG_ALLOW_INCOMPLETE_CACHE_SYSFS is set only when CONFIG_A64FX_HWPF_CONTROL is enabled. Hardware prefetch control driver need cache sysfs directory and cache level/type information. In ARM processor, these information can be obtained from the register even without PPTT. This patch set the cpu_map_populated to true if the machine doesn't have PPTT. It use only the level/type information obtained from CLIDR_EL1, and don't use CCSIDR information. Signed-off-by: Kohei Tarumizu --- arch/arm64/kernel/cacheinfo.c | 27 +++++++++++++++++++++++++++ drivers/acpi/pptt.c | 18 ++++++++++++++++++ include/linux/acpi.h | 5 +++++ include/linux/cacheinfo.h | 10 ++++++++++ 4 files changed, 60 insertions(+) diff --git a/arch/arm64/kernel/cacheinfo.c b/arch/arm64/kernel/cacheinfo.c index 587543c6c51c..3b337a425acb 100644 --- a/arch/arm64/kernel/cacheinfo.c +++ b/arch/arm64/kernel/cacheinfo.c @@ -43,6 +43,30 @@ static void ci_leaf_init(struct cacheinfo *this_leaf, this_leaf->type = type; } +static const struct midr_range allow_list[] = { + MIDR_ALL_VERSIONS(MIDR_FUJITSU_A64FX), +}; + +/* + * This function works only for FUJITSU A64FX processor. + * If CONFIG_ALLOW_INCOMPLETE_CACHE_SYSFS is not defined, do nothing. + * + * Hardware prefetch functions need cache sysfs directory and cache + * level/type information. In ARM processor, these information can be + * obtained from registers even without PPTT. Therefore, we set the + * cpu_map_populated to true to create cache sysfs directory, if the + * machine doesn't have PPTT. + */ +static void allow_incomplete_cache_sysfs(struct cpu_cacheinfo *cpu_ci) +{ + if (!is_midr_in_range_list(read_cpuid_id(), allow_list)) + return; + + if (!acpi_disabled) + if (!acpi_has_pptt()) + enable_cpu_map_populated(cpu_ci); +} + int init_cache_level(unsigned int cpu) { unsigned int ctype, level, leaves, fw_level; @@ -95,5 +119,8 @@ int populate_cache_leaves(unsigned int cpu) ci_leaf_init(this_leaf++, type, level); } } + + allow_incomplete_cache_sysfs(this_cpu_ci); + return 0; } diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c index 701f61c01359..fcd7295b81d7 100644 --- a/drivers/acpi/pptt.c +++ b/drivers/acpi/pptt.c @@ -838,3 +838,21 @@ int find_acpi_cpu_topology_hetero_id(unsigned int cpu) return find_acpi_cpu_topology_tag(cpu, PPTT_ABORT_PACKAGE, ACPI_PPTT_ACPI_IDENTICAL); } + +/** + * acpi_has_pptt() - Determine if ACPI has PPTT table or not + * + * Return: true if ACPI has PPTT, false if ACPI doesn't have PPTT. + */ +bool acpi_has_pptt(void) +{ + struct acpi_table_header *table; + acpi_status status; + + status = acpi_get_table(ACPI_SIG_PPTT, 0, &table); + if (ACPI_FAILURE(status)) + return false; + + acpi_put_table(table); + return true; +} diff --git a/include/linux/acpi.h b/include/linux/acpi.h index d7136d13aa44..9daea11edad7 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -1391,6 +1391,7 @@ int find_acpi_cpu_topology_cluster(unsigned int cpu); int find_acpi_cpu_topology_package(unsigned int cpu); int find_acpi_cpu_topology_hetero_id(unsigned int cpu); int find_acpi_cpu_cache_topology(unsigned int cpu, int level); +bool acpi_has_pptt(void); #else static inline int acpi_pptt_cpu_is_thread(unsigned int cpu) { @@ -1416,6 +1417,10 @@ static inline int find_acpi_cpu_cache_topology(unsigned int cpu, int level) { return -EINVAL; } +static inline bool acpi_has_pptt(void) +{ + return false; +} #endif #ifdef CONFIG_ACPI_PCC diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h index 4ff37cb763ae..71f89da6792b 100644 --- a/include/linux/cacheinfo.h +++ b/include/linux/cacheinfo.h @@ -99,6 +99,16 @@ static inline int acpi_find_last_cache_level(unsigned int cpu) int acpi_find_last_cache_level(unsigned int cpu); #endif +#ifndef CONFIG_ALLOW_INCOMPLETE_CACHE_SYSFS +#define enable_cpu_map_populated(cpu_ci) +#else +static inline void enable_cpu_map_populated(struct cpu_cacheinfo *cpu_ci) +{ + cpu_ci->cpu_map_populated = true; +} +#endif + + const struct attribute_group *cache_get_priv_group(struct cacheinfo *this_leaf); /* From patchwork Tue Jun 7 12:05:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "tarumizu.kohei@fujitsu.com" X-Patchwork-Id: 579486 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7B363C43334 for ; Tue, 7 Jun 2022 12:09:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239513AbiFGMJJ (ORCPT ); Tue, 7 Jun 2022 08:09:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56516 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243598AbiFGMJD (ORCPT ); Tue, 7 Jun 2022 08:09:03 -0400 Received: from esa1.hc1455-7.c3s2.iphmx.com (esa1.hc1455-7.c3s2.iphmx.com [207.54.90.47]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8761C8A305 for ; Tue, 7 Jun 2022 05:08:59 -0700 (PDT) X-IronPort-AV: E=McAfee;i="6400,9594,10370"; a="75590274" X-IronPort-AV: E=Sophos;i="5.91,283,1647270000"; d="scan'208";a="75590274" Received: from unknown (HELO yto-r3.gw.nic.fujitsu.com) ([218.44.52.219]) by esa1.hc1455-7.c3s2.iphmx.com with ESMTP; 07 Jun 2022 21:07:44 +0900 Received: from yto-m1.gw.nic.fujitsu.com (yto-nat-yto-m1.gw.nic.fujitsu.com [192.168.83.64]) by yto-r3.gw.nic.fujitsu.com (Postfix) with ESMTP id 2F22FD5028; Tue, 7 Jun 2022 21:07:43 +0900 (JST) Received: from oym-om4.fujitsu.com (oym-om4.o.css.fujitsu.com [10.85.58.164]) by yto-m1.gw.nic.fujitsu.com (Postfix) with ESMTP id 389EED05F3; Tue, 7 Jun 2022 21:07:42 +0900 (JST) Received: from cn-r05-10.example.com (n3235113.np.ts.nmh.cs.fujitsu.co.jp [10.123.235.113]) by oym-om4.fujitsu.com (Postfix) with ESMTP id D6DFC4008021D; Tue, 7 Jun 2022 21:07:41 +0900 (JST) From: Kohei Tarumizu To: catalin.marinas@arm.com, will@kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, rafael@kernel.org, lenb@kernel.org, gregkh@linuxfoundation.org, mchehab+huawei@kernel.org, eugenis@google.com, tony.luck@intel.com, pcc@google.com, peterz@infradead.org, marcos@orca.pet, marcan@marcan.st, linus.walleij@linaro.org, nicolas.ferre@microchip.com, conor.dooley@microchip.com, arnd@arndb.de, ast@kernel.org, peter.chen@kernel.org, kuba@kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-acpi@vger.kernel.org Cc: tarumizu.kohei@fujitsu.com Subject: [PATCH v5 4/6] x86: Add hardware prefetch control driver for x86 Date: Tue, 7 Jun 2022 21:05:28 +0900 Message-Id: <20220607120530.2447112-5-tarumizu.kohei@fujitsu.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20220607120530.2447112-1-tarumizu.kohei@fujitsu.com> References: <20220607120530.2447112-1-tarumizu.kohei@fujitsu.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org Adds module init/exit code to create sysfs attributes for x86 with "hardware_prefetcher_enable", "ip_prefetcher_enable" and "adjacent_cache_line_prefetcher_enable". This driver works only if a CPU model is mapped to type of register specification(e.g. TYPE_L12_BASE) in pfctl_match[]. The details of the registers(MSR_MISC_FEATURE_CONTROL) to be read and written in this patch are described below: "https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html" Volume 4 Signed-off-by: Kohei Tarumizu --- arch/x86/kernel/cpu/x86-pfctl.c | 363 ++++++++++++++++++++++++++++++++ 1 file changed, 363 insertions(+) create mode 100644 arch/x86/kernel/cpu/x86-pfctl.c diff --git a/arch/x86/kernel/cpu/x86-pfctl.c b/arch/x86/kernel/cpu/x86-pfctl.c new file mode 100644 index 000000000000..154e927d092c --- /dev/null +++ b/arch/x86/kernel/cpu/x86-pfctl.c @@ -0,0 +1,363 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2022 FUJITSU LIMITED + * + * x86 Hardware Prefetch Control support + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * MSR_MISC_FEATURE_CONTROL has three type of register specifications. + * + * The register specification of TYPE_L12_BASE is as follow: + * [0] L2 Hardware Prefetcher Disable (R/W) + * [1] Reserved + * [2] DCU Hardware Prefetcher Disable (R/W) + * [63:3] Reserved + * + * The register specification of TYPE_L12_PLUS is as follow: + * [0] L2 Hardware Prefetcher Disable (R/W) + * [1] L2 Adjacent Cache Line Prefetcher Disable (R/W) + * [2] DCU Hardware Prefetcher Disable (R/W) + * [3] DCU IP Prefetcher Disable (R/W) + * [63:4] Reserved + * + * The register specification of TYPE_L12_XPHI is as follow: + * [0] L2 Hardware Prefetcher Disable (R/W) + * [1] DCU Hardware Prefetcher Disable (R/W) + * [63:2] Reserved + * + * See "Intel 64 and IA-32 Architectures Software Developer's Manual" + * (https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html) + * for register specification details. + */ +enum { + TYPE_L12_BASE, + TYPE_L12_PLUS, + TYPE_L12_XPHI, +}; + +struct x86_pfctl_attr { + struct device_attribute attr; + u64 mask; +}; + +struct pfctl_group { + unsigned int level; + enum cache_type type; + const struct attribute_group **groups; +}; + +enum cpuhp_state hp_online; + +static inline unsigned int pfctl_dev_get_cpu(struct device *pfctl_dev) +{ + return *(u32 *)dev_get_drvdata(pfctl_dev); +} + +static ssize_t +pfctl_show(struct device *pfctl_dev, struct device_attribute *attr, char *buf) +{ + unsigned int cpu = pfctl_dev_get_cpu(pfctl_dev); + struct x86_pfctl_attr *xa; + u64 val; + + xa = container_of(attr, struct x86_pfctl_attr, attr); + + rdmsrl_on_cpu(cpu, MSR_MISC_FEATURE_CONTROL, &val); + return sysfs_emit(buf, "%d\n", val & xa->mask ? 0 : 1); +} + +struct write_info { + u64 mask; + bool enable; +}; + +/* + * wrmsrl() in this patch is only done inside of an interrupt-disabled region + * to avoid a conflict of write access from other drivers, + */ +static void pfctl_write(void *info) +{ + struct write_info *winfo = info; + u64 reg; + + reg = 0; + rdmsrl(MSR_MISC_FEATURE_CONTROL, reg); + + if (winfo->enable) + reg &= ~winfo->mask; + else + reg |= winfo->mask; + + wrmsrl(MSR_MISC_FEATURE_CONTROL, reg); +} + +/* + * MSR_MISC_FEATURE_CONTROL has "core" scope, so define the lock to avoid a + * conflict of write access from different logical processors in the same core. + */ +static DEFINE_MUTEX(pfctl_mutex); + +static ssize_t +pfctl_store(struct device *pfctl_dev, struct device_attribute *attr, + const char *buf, size_t size) +{ + unsigned int cpu = pfctl_dev_get_cpu(pfctl_dev); + struct x86_pfctl_attr *xa; + struct write_info info; + + xa = container_of(attr, struct x86_pfctl_attr, attr); + info.mask = xa->mask; + + if (strtobool(buf, &info.enable) < 0) + return -EINVAL; + + mutex_lock(&pfctl_mutex); + smp_call_function_single(cpu, pfctl_write, &info, true); + mutex_unlock(&pfctl_mutex); + + return size; +} + +#define PFCTL_ATTR(_name, _level, _bit) \ + struct x86_pfctl_attr attr_l##_level##_##_name = { \ + .attr = __ATTR(_name, 0600, pfctl_show, pfctl_store), \ + .mask = BIT_ULL(_bit), } + +static PFCTL_ATTR(hardware_prefetcher_enable, 1, 2); +static PFCTL_ATTR(hardware_prefetcher_enable, 2, 0); +static PFCTL_ATTR(ip_prefetcher_enable, 1, 3); +static PFCTL_ATTR(adjacent_cache_line_prefetcher_enable, 2, 1); + +static struct attribute *l1_attrs[] = { + &attr_l1_hardware_prefetcher_enable.attr.attr, + &attr_l1_ip_prefetcher_enable.attr.attr, + NULL, +}; + +static struct attribute *l2_attrs[] = { + &attr_l2_hardware_prefetcher_enable.attr.attr, + &attr_l2_adjacent_cache_line_prefetcher_enable.attr.attr, + NULL, +}; + +static struct attribute_group l1_group = { + .attrs = l1_attrs, +}; + +static struct attribute_group l2_group = { + .attrs = l2_attrs, +}; + +static const struct attribute_group *l1_groups[] = { + &l1_group, + NULL, +}; + +static const struct attribute_group *l2_groups[] = { + &l2_group, + NULL, +}; + +static const struct pfctl_group pfctl_groups[] = { + { + .level = 1, + .type = CACHE_TYPE_DATA, + .groups = l1_groups, + }, + { + .level = 2, + .type = CACHE_TYPE_UNIFIED, + .groups = l2_groups, + }, + { + .groups = NULL, + }, +}; + +static const struct attribute_group ** +get_pfctl_attribute_groups(unsigned int level, enum cache_type type) +{ + int i; + + for (i = 0; pfctl_groups[i].groups; i++) + if ((level == pfctl_groups[i].level) && + (type == pfctl_groups[i].type)) + return pfctl_groups[i].groups; + + return NULL; +} + +static int remove_pfctl_attr(struct device *index_dev, void *data) +{ + struct device *pfctl_dev; + + pfctl_dev = device_find_child_by_name(index_dev, "prefetch_control"); + if (!pfctl_dev) + return 0; + + device_unregister(pfctl_dev); + put_device(pfctl_dev); + + return 0; +} + +static int create_pfctl_attr(struct device *index_dev, void *data) +{ + struct cacheinfo *leaf = dev_get_drvdata(index_dev); + const struct attribute_group **groups; + struct device *pfctl_dev; + + groups = get_pfctl_attribute_groups(leaf->level, leaf->type); + if (!groups) + return 0; + + pfctl_dev = cpu_device_create(index_dev, data, groups, + "prefetch_control"); + if (IS_ERR(pfctl_dev)) + return PTR_ERR(pfctl_dev); + + return 0; +} + +static int pfctl_online(unsigned int cpu) +{ + struct device *cpu_dev = get_cpu_device(cpu); + struct device *cache_dev; + int ret; + + cache_dev = device_find_child_by_name(cpu_dev, "cache"); + if (!cache_dev) + return -ENODEV; + + ret = device_for_each_child(cache_dev, &cpu_dev->id, create_pfctl_attr); + + put_device(cache_dev); + + return ret; +} + +static int pfctl_prepare_down(unsigned int cpu) +{ + struct device *cpu_dev = get_cpu_device(cpu); + struct device *cache_dev; + + cache_dev = device_find_child_by_name(cpu_dev, "cache"); + if (!cache_dev) + return 0; + + device_for_each_child(cache_dev, NULL, remove_pfctl_attr); + + put_device(cache_dev); + + return 0; +} + +/* + * Only BROADWELL_X has been tested in the actual machine at this point. Other + * models were defined based on the information in the "Intel 64 and IA-32 + * Architectures Software Developer's Manual" + */ +static const struct x86_cpu_id pfctl_match[] __initconst = { + X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT_D, TYPE_L12_BASE), + X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT, TYPE_L12_BASE), + X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT_PLUS, TYPE_L12_BASE), + X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_D, TYPE_L12_BASE), + X86_MATCH_INTEL_FAM6_MODEL(NEHALEM, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_G, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_EP, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(NEHALEM_EX, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(SANDYBRIDGE_X, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(IVYBRIDGE_X, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(HASWELL, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(HASWELL_X, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(HASWELL_L, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(HASWELL_G, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(BROADWELL, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_G, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_X, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(BROADWELL_D, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_L, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(SKYLAKE_X, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE_L, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(KABYLAKE, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE_L, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(CANNONLAKE_L, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_X, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_D, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(ICELAKE, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(ICELAKE_L, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE, TYPE_L12_PLUS), + X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL, TYPE_L12_XPHI), + X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM, TYPE_L12_XPHI), + {}, +}; +MODULE_DEVICE_TABLE(x86cpu, pfctl_match); + +static int __init x86_pfctl_init(void) +{ + const struct x86_cpu_id *m; + int ret; + + if (cpu_feature_enabled(X86_FEATURE_HYPERVISOR)) + return -ENODEV; + + m = x86_match_cpu(pfctl_match); + if (!m) + return -ENODEV; + + switch (m->driver_data) { + case TYPE_L12_BASE: + l1_attrs[1] = NULL; + l2_attrs[1] = NULL; + break; + case TYPE_L12_PLUS: + break; + case TYPE_L12_XPHI: + attr_l1_hardware_prefetcher_enable.mask = BIT_ULL(1); + l1_attrs[1] = NULL; + l2_attrs[1] = NULL; + break; + default: + return -ENODEV; + }; + + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "x86/x86-pfctl:online", + pfctl_online, pfctl_prepare_down); + if (ret < 0) { + pr_err("failed to register hotplug callbacks\n"); + return ret; + } + + hp_online = ret; + + return 0; +} + +static void __exit x86_pfctl_exit(void) +{ + cpuhp_remove_state(hp_online); +} + +late_initcall(x86_pfctl_init); +module_exit(x86_pfctl_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("FUJITSU LIMITED"); +MODULE_DESCRIPTION("x86 Hardware Prefetch Control Driver"); From patchwork Tue Jun 7 12:05:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "tarumizu.kohei@fujitsu.com" X-Patchwork-Id: 579487 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 34427C43334 for ; Tue, 7 Jun 2022 12:09:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243587AbiFGMJG (ORCPT ); Tue, 7 Jun 2022 08:09:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:56246 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243585AbiFGMI7 (ORCPT ); Tue, 7 Jun 2022 08:08:59 -0400 X-Greylist: delayed 63 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Tue, 07 Jun 2022 05:08:55 PDT Received: from esa7.hc1455-7.c3s2.iphmx.com (esa7.hc1455-7.c3s2.iphmx.com [139.138.61.252]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7589E8D6B7 for ; Tue, 7 Jun 2022 05:08:53 -0700 (PDT) X-IronPort-AV: E=McAfee;i="6400,9594,10370"; a="54332932" X-IronPort-AV: E=Sophos;i="5.91,283,1647270000"; d="scan'208";a="54332932" Received: from unknown (HELO yto-r3.gw.nic.fujitsu.com) ([218.44.52.219]) by esa7.hc1455-7.c3s2.iphmx.com with ESMTP; 07 Jun 2022 21:07:48 +0900 Received: from yto-m2.gw.nic.fujitsu.com (yto-nat-yto-m2.gw.nic.fujitsu.com [192.168.83.65]) by yto-r3.gw.nic.fujitsu.com (Postfix) with ESMTP id 51419D5028; Tue, 7 Jun 2022 21:07:47 +0900 (JST) Received: from oym-om4.fujitsu.com (oym-om4.o.css.fujitsu.com [10.85.58.164]) by yto-m2.gw.nic.fujitsu.com (Postfix) with ESMTP id 7901FD35B2; Tue, 7 Jun 2022 21:07:46 +0900 (JST) Received: from cn-r05-10.example.com (n3235113.np.ts.nmh.cs.fujitsu.co.jp [10.123.235.113]) by oym-om4.fujitsu.com (Postfix) with ESMTP id EB3744008021D; Tue, 7 Jun 2022 21:07:45 +0900 (JST) From: Kohei Tarumizu To: catalin.marinas@arm.com, will@kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, rafael@kernel.org, lenb@kernel.org, gregkh@linuxfoundation.org, mchehab+huawei@kernel.org, eugenis@google.com, tony.luck@intel.com, pcc@google.com, peterz@infradead.org, marcos@orca.pet, marcan@marcan.st, linus.walleij@linaro.org, nicolas.ferre@microchip.com, conor.dooley@microchip.com, arnd@arndb.de, ast@kernel.org, peter.chen@kernel.org, kuba@kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-acpi@vger.kernel.org Cc: tarumizu.kohei@fujitsu.com Subject: [PATCH v5 5/6] x86: Add Kconfig/Makefile to build hardware prefetch control driver Date: Tue, 7 Jun 2022 21:05:29 +0900 Message-Id: <20220607120530.2447112-6-tarumizu.kohei@fujitsu.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20220607120530.2447112-1-tarumizu.kohei@fujitsu.com> References: <20220607120530.2447112-1-tarumizu.kohei@fujitsu.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org This adds Kconfig/Makefile to build hardware prefetch control driver for x86 support. This also adds a MAINTAINERS entry. Signed-off-by: Kohei Tarumizu --- MAINTAINERS | 1 + arch/x86/Kconfig | 17 +++++++++++++++++ arch/x86/kernel/cpu/Makefile | 2 ++ 3 files changed, 20 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index b3e920a8a044..4f44bbef2614 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8623,6 +8623,7 @@ K: (devm_)?hwmon_device_(un)?register(|_with_groups|_with_info) HARDWARE PREFETCH CONTROL DRIVERS M: Kohei Tarumizu S: Maintained +F: arch/x86/kernel/cpu/x86-pfctl.c F: drivers/soc/fujitsu/a64fx-pfctl.c HARDWARE RANDOM NUMBER GENERATOR CORE diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 4bed3abf444d..3ee173483f9f 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1359,6 +1359,23 @@ config X86_CPUID with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to /dev/cpu/31/cpuid. +config X86_HWPF_CONTROL + tristate "x86 Hardware Prefetch Control support" + depends on X86_64 + help + This provides a sysfs interface to control the Hardware Prefetch + behavior for X86. + + Some Intel processors have MSR 0x1a4 (MSR_MISC_FEATURE_CONTROL), + which can control the hardware prefech behavior. If the processor + supports this, the module can be loaded with the name x86-pfctl. + + Depending on the characteristics of the application, this register + parameters improve or degrade performance. + + Please see Documentation/ABI/testing/sysfs-devices-system-cpu for + more information. + choice prompt "High Memory Support" default HIGHMEM4G diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index 9661e3e802be..1aa13dad17a3 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -56,6 +56,8 @@ obj-$(CONFIG_X86_LOCAL_APIC) += perfctr-watchdog.o obj-$(CONFIG_HYPERVISOR_GUEST) += vmware.o hypervisor.o mshyperv.o obj-$(CONFIG_ACRN_GUEST) += acrn.o +obj-$(CONFIG_X86_HWPF_CONTROL) += x86-pfctl.o + ifdef CONFIG_X86_FEATURE_NAMES quiet_cmd_mkcapflags = MKCAP $@ cmd_mkcapflags = $(CONFIG_SHELL) $(srctree)/$(src)/mkcapflags.sh $@ $^ From patchwork Tue Jun 7 12:05:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "tarumizu.kohei@fujitsu.com" X-Patchwork-Id: 579863 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 79397C43334 for ; Tue, 7 Jun 2022 12:08:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243461AbiFGMIK (ORCPT ); Tue, 7 Jun 2022 08:08:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51480 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243448AbiFGMH5 (ORCPT ); Tue, 7 Jun 2022 08:07:57 -0400 Received: from esa8.hc1455-7.c3s2.iphmx.com (esa8.hc1455-7.c3s2.iphmx.com [139.138.61.253]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2A2328CB07; Tue, 7 Jun 2022 05:07:52 -0700 (PDT) X-IronPort-AV: E=McAfee;i="6400,9594,10370"; a="63506366" X-IronPort-AV: E=Sophos;i="5.91,283,1647270000"; d="scan'208";a="63506366" Received: from unknown (HELO yto-r2.gw.nic.fujitsu.com) ([218.44.52.218]) by esa8.hc1455-7.c3s2.iphmx.com with ESMTP; 07 Jun 2022 21:07:50 +0900 Received: from yto-m4.gw.nic.fujitsu.com (yto-nat-yto-m4.gw.nic.fujitsu.com [192.168.83.67]) by yto-r2.gw.nic.fujitsu.com (Postfix) with ESMTP id 6843CC68A4; Tue, 7 Jun 2022 21:07:49 +0900 (JST) Received: from oym-om4.fujitsu.com (oym-om4.o.css.fujitsu.com [10.85.58.164]) by yto-m4.gw.nic.fujitsu.com (Postfix) with ESMTP id 90D6CFA56; Tue, 7 Jun 2022 21:07:48 +0900 (JST) Received: from cn-r05-10.example.com (n3235113.np.ts.nmh.cs.fujitsu.co.jp [10.123.235.113]) by oym-om4.fujitsu.com (Postfix) with ESMTP id 3A50640080208; Tue, 7 Jun 2022 21:07:48 +0900 (JST) From: Kohei Tarumizu To: catalin.marinas@arm.com, will@kernel.org, tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, rafael@kernel.org, lenb@kernel.org, gregkh@linuxfoundation.org, mchehab+huawei@kernel.org, eugenis@google.com, tony.luck@intel.com, pcc@google.com, peterz@infradead.org, marcos@orca.pet, marcan@marcan.st, linus.walleij@linaro.org, nicolas.ferre@microchip.com, conor.dooley@microchip.com, arnd@arndb.de, ast@kernel.org, peter.chen@kernel.org, kuba@kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-acpi@vger.kernel.org Cc: tarumizu.kohei@fujitsu.com Subject: [PATCH v5 6/6] docs: ABI: Add sysfs documentation interface of hardware prefetch control driver Date: Tue, 7 Jun 2022 21:05:30 +0900 Message-Id: <20220607120530.2447112-7-tarumizu.kohei@fujitsu.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20220607120530.2447112-1-tarumizu.kohei@fujitsu.com> References: <20220607120530.2447112-1-tarumizu.kohei@fujitsu.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org This describes the sysfs interface implemented by the hardware prefetch control driver. Signed-off-by: Kohei Tarumizu --- .../ABI/testing/sysfs-devices-system-cpu | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu index 2ad01cad7f1c..0da4c1bac51e 100644 --- a/Documentation/ABI/testing/sysfs-devices-system-cpu +++ b/Documentation/ABI/testing/sysfs-devices-system-cpu @@ -688,3 +688,101 @@ Description: (RO) the list of CPUs that are isolated and don't participate in load balancing. These CPUs are set by boot parameter "isolcpus=". + +What: /sys/devices/system/cpu/cpu*/cache/index*/prefetch_control/hardware_prefetcher_enable + /sys/devices/system/cpu/cpu*/cache/index*/prefetch_control/ip_prefetcher_enable + /sys/devices/system/cpu/cpu*/cache/index*/prefetch_control/adjacent_cache_line_prefetcher_enable +Date: March 2022 +Contact: Linux kernel mailing list +Description: Parameters for some Intel CPU's hardware prefetch control + + This sysfs interface provides Hardware Prefetch control + attribute for some Intel processors. Attributes are only + present if the particular cache implements the relevant + prefetcher controls. + + *_prefetcher_enable: + (RW) control this prefetcher's enablement state. + Read returns current status: + 0: this prefetcher is disabled + 1: this prefetcher is enabled + + - Attribute mapping + + Some Intel processors have MSR 0x1a4. This register has several + specifications depending on the model. This interface provides + a one-to-one attribute file to control all the tunable + parameters the CPU provides of the following. + + - "* Hardware Prefetcher Disable (R/W)" + corresponds to the "hardware_prefetcher_enable" + + - "* Adjacent Cache Line Prefetcher Disable (R/W)" + corresponds to the "adjacent_cache_line_prefetcher_enable" + + - "* IP Prefetcher Disable (R/W)" + corresponds to the "ip_prefetcher_enable" + +What: /sys/devices/system/cpu/cpu*/cache/index*/prefetch_control/stream_detect_prefetcher_enable + /sys/devices/system/cpu/cpu*/cache/index*/prefetch_control/stream_detect_prefetcher_strength + /sys/devices/system/cpu/cpu*/cache/index*/prefetch_control/stream_detect_prefetcher_strength_available + /sys/devices/system/cpu/cpu*/cache/index*/prefetch_control/stream_detect_prefetcher_dist +Date: March 2022 +Contact: Linux kernel mailing list +Description: Parameters for A64FX's hardware prefetch control + + This sysfs interface provides Hardware Prefetch control + attribute for the processor A64FX. Attributes are only + present if the particular cache implements the relevant + prefetcher controls. + + stream_detect_prefetcher_enable: + (RW) control the prefetcher's enablement state. + Read returns current status: + 0: this prefetcher is disabled + 1: this prefetcher is enabled + + stream_detect_prefetcher_strength: + (RW) control the prefetcher operation's strongness state. + Read returns current status: + weak: prefetch operation is weak + strong: prefetch operation is strong + + Strong prefetch operation is surely executed, if there is + no corresponding data in cache. + Weak prefetch operation allows the hardware not to execute + operation depending on hardware state. + + + stream_detect_prefetcher_strength_available: + (RO) displays a space separated list of available strongness + state. + + stream_detect_prefetcher_dist: + (RW) control the prefetcher distance value. + Read return current prefetcher distance value in bytes + or the string "auto". + + Write either a value in byte or the string "auto" to this + parameter. If you write a value less than multiples of a + specific value, it is rounded up. + + The string "auto" have a special meaning. This means that + instead of setting dist to a user-specified value, it + operates using hardware-specific values. + + - Attribute mapping + + The processor A64FX has register IMP_PF_STREAM_DETECT_CTRL_EL0 + for Hardware Prefetch Control. This attribute maps each + specification to the following. + + - "L*PF_DIS": enablement of hardware prefetcher + corresponds to the "stream_detect_prefetcher_enable" + + - "L*W": strongness of hardware prefetcher + corresponds to "stream_detect_prefetcher_strength" + and "stream_detect_prefetcher_strength_available" + + - "L*_DIST": distance of hardware prefetcher + corresponds to the "stream_detect_prefetcher_dist"