Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757538AbcJGXrg (ORCPT ); Fri, 7 Oct 2016 19:47:36 -0400 Received: from mga05.intel.com ([192.55.52.43]:19336 "EHLO mga05.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932911AbcJGXpC (ORCPT ); Fri, 7 Oct 2016 19:45:02 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.31,457,1473145200"; d="scan'208";a="17405508" From: "Fenghua Yu" To: "Thomas Gleixner" Cc: "H. Peter Anvin" , "Ingo Molnar" , "Tony Luck" , "Peter Zijlstra" , "Stephane Eranian" , "Borislav Petkov" , "Dave Hansen" , "Nilay Vaish" , "Shaohua Li" , "David Carrillo-Cisneros" , "Ravi V Shankar" , "Sai Prakhya" , "Vikas Shivappa" , "linux-kernel" , "x86" , "Fenghua Yu" Subject: [PATCH v3 11/18] x86/intel_rdt: Add basic resctrl filesystem support Date: Fri, 7 Oct 2016 19:45:56 -0700 Message-Id: <1475894763-64683-12-git-send-email-fenghua.yu@intel.com> X-Mailer: git-send-email 1.8.0.1 In-Reply-To: <1475894763-64683-1-git-send-email-fenghua.yu@intel.com> References: <1475894763-64683-1-git-send-email-fenghua.yu@intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 9335 Lines: 351 From: Fenghua Yu Use kernfs as basis for our user interface filesystem. This patch supports mount/umount, and one mount parameter "cdp" to enable code/data prioritization (though all we do at this point is ensure that the system can support CDP). The file system is not populated yet in this patch. Signed-off-by: Fenghua Yu Signed-off-by: Tony Luck --- arch/x86/include/asm/intel_rdt.h | 20 ++- arch/x86/kernel/cpu/Makefile | 2 +- arch/x86/kernel/cpu/intel_rdt.c | 8 ++ arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 236 +++++++++++++++++++++++++++++++ include/uapi/linux/magic.h | 1 + 5 files changed, 265 insertions(+), 2 deletions(-) create mode 100644 arch/x86/kernel/cpu/intel_rdt_rdtgroup.c diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h index bad8dc7..f63815c 100644 --- a/arch/x86/include/asm/intel_rdt.h +++ b/arch/x86/include/asm/intel_rdt.h @@ -2,6 +2,23 @@ #define _ASM_X86_INTEL_RDT_H /** + * struct rdtgroup - store rdtgroup's data in resctrl file system. + * @kn: kernfs node + * @rdtgroup_list: linked list for all rdtgroups + * @closid: closid for this rdtgroup + */ +struct rdtgroup { + struct kernfs_node *kn; + struct list_head rdtgroup_list; + int closid; +}; + +/* List of all resource groups */ +extern struct list_head rdt_all_groups; + +int __init rdtgroup_init(void); + +/** * struct rdt_resource - attributes of an RDT resource * @enabled: Is this feature enabled on this machine * @name: Name to use in "schemata" file @@ -39,6 +56,7 @@ struct rdt_resource { for (r = rdt_resources_all; r->name; r++) \ if (r->enabled) +#define IA32_L3_QOS_CFG 0xc81 #define IA32_L3_CBM_BASE 0xc90 /** @@ -72,7 +90,7 @@ extern struct mutex rdtgroup_mutex; int __init rdtgroup_init(void); -extern struct rdtgroup *rdtgroup_default; +extern struct rdtgroup rdtgroup_default; extern struct rdt_resource rdt_resources_all[]; enum { diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index 5a791c8..963c54a 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -34,7 +34,7 @@ obj-$(CONFIG_CPU_SUP_CENTAUR) += centaur.o obj-$(CONFIG_CPU_SUP_TRANSMETA_32) += transmeta.o obj-$(CONFIG_CPU_SUP_UMC_32) += umc.o -obj-$(CONFIG_INTEL_RDT) += intel_rdt.o +obj-$(CONFIG_INTEL_RDT) += intel_rdt.o intel_rdt_rdtgroup.o obj-$(CONFIG_X86_MCE) += mcheck/ obj-$(CONFIG_MTRR) += mtrr/ diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index 76b7476..f6caabd 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -265,6 +265,14 @@ static int __init intel_rdt_late_init(void) for_each_rdt_resource(r) rdt_max_closid = max(rdt_max_closid, r->max_closid); + /* limitation of our allocator, but h/w is more limited */ + if (rdt_max_closid > 32) { + pr_warn("Only using 32/%d CLOSIDs\n", rdt_max_closid); + rdt_max_closid = 32; + } + + rdtgroup_init(); + for_each_rdt_resource(r) pr_info("Intel %s allocation %s detected\n", r->name, r->cdp_capable ? " (with CDP)" : ""); diff --git a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c new file mode 100644 index 0000000..c99d3a0 --- /dev/null +++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c @@ -0,0 +1,236 @@ +/* + * User interface for Resource Alloction in Resource Director Technology(RDT) + * + * Copyright (C) 2016 Intel Corporation + * + * Author: Fenghua Yu + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * More information about RDT be found in the Intel (R) x86 Architecture + * Software Developer Manual. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include + +#include + +#include + +DEFINE_STATIC_KEY_FALSE(rdt_enable_key); +struct kernfs_root *rdt_root; +struct rdtgroup rdtgroup_default; +LIST_HEAD(rdt_all_groups); + +static void l3_qos_cfg_update(void *arg) +{ + struct rdt_resource *r = arg; + + wrmsrl(IA32_L3_QOS_CFG, r->cdp_enabled); +} + +static void set_l3_qos_cfg(struct rdt_resource *r) +{ + struct list_head *l; + struct rdt_domain *d; + struct cpumask cpu_mask; + + cpumask_clear(&cpu_mask); + list_for_each(l, &r->domains) { + d = list_entry(l, struct rdt_domain, list); + cpumask_set_cpu(cpumask_any(&d->cpu_mask), &cpu_mask); + } + smp_call_function_many(&cpu_mask, l3_qos_cfg_update, r, 1); +} + +static int parse_rdtgroupfs_options(char *data, struct rdt_resource *r) +{ + char *token, *o = data; + + while ((token = strsep(&o, ",")) != NULL) { + if (!*token) + return -EINVAL; + + if (!strcmp(token, "cdp")) + if (r->enabled && r->cdp_capable) + r->cdp_enabled = true; + } + + return 0; +} + +static struct dentry *rdt_mount(struct file_system_type *fs_type, + int flags, const char *unused_dev_name, + void *data) +{ + struct dentry *dentry; + int ret; + bool new_sb; + struct rdt_resource *r = &rdt_resources_all[RDT_RESOURCE_L3]; + + mutex_lock(&rdtgroup_mutex); + /* + * resctrl file system can only be mounted once. + */ + if (static_branch_unlikely(&rdt_enable_key)) { + dentry = ERR_PTR(-EBUSY); + goto out; + } + + r->cdp_enabled = false; + ret = parse_rdtgroupfs_options(data, r); + if (ret) { + dentry = ERR_PTR(ret); + goto out; + } + if (r->cdp_enabled) + r->num_closid = r->max_closid / 2; + else + r->num_closid = r->max_closid; + + /* Recompute rdt_max_closid because CDP may have changed things. */ + rdt_max_closid = 0; + for_each_rdt_resource(r) + rdt_max_closid = max(rdt_max_closid, r->num_closid); + if (rdt_max_closid > 32) + rdt_max_closid = 32; + + dentry = kernfs_mount(fs_type, flags, rdt_root, + RDTGROUP_SUPER_MAGIC, &new_sb); + if (IS_ERR(dentry)) + goto out; + if (!new_sb) { + dentry = ERR_PTR(-EINVAL); + goto out; + } + r = &rdt_resources_all[RDT_RESOURCE_L3]; + if (r->cdp_capable) + set_l3_qos_cfg(r); + static_branch_enable(&rdt_enable_key); + +out: + mutex_unlock(&rdtgroup_mutex); + + return dentry; +} + +static void reset_all_cbms(struct rdt_resource *r) +{ + struct list_head *l; + struct rdt_domain *d; + struct msr_param msr_param; + struct cpumask cpu_mask; + int i; + + cpumask_clear(&cpu_mask); + msr_param.res = r; + msr_param.low = 0; + msr_param.high = r->max_closid; + + list_for_each(l, &r->domains) { + d = list_entry(l, struct rdt_domain, list); + cpumask_set_cpu(cpumask_any(&d->cpu_mask), &cpu_mask); + + for (i = 0; i < r->max_closid; i++) + d->cbm[i] = r->max_cbm; + } + smp_call_function_many(&cpu_mask, rdt_cbm_update, &msr_param, 1); +} + +static void rdt_kill_sb(struct super_block *sb) +{ + struct rdt_resource *r; + + mutex_lock(&rdtgroup_mutex); + + /*Put everything back to default values. */ + for_each_rdt_resource(r) + reset_all_cbms(r); + r = &rdt_resources_all[RDT_RESOURCE_L3]; + if (r->cdp_capable) { + r->cdp_enabled = 0; + set_l3_qos_cfg(r); + } + + static_branch_disable(&rdt_enable_key); + kernfs_kill_sb(sb); + mutex_unlock(&rdtgroup_mutex); +} + +static struct file_system_type rdt_fs_type = { + .name = "resctrl", + .mount = rdt_mount, + .kill_sb = rdt_kill_sb, +}; + +static struct kernfs_syscall_ops rdtgroup_kf_syscall_ops = { +}; + +static int __init rdtgroup_setup_root(void) +{ + int ret; + + rdt_root = kernfs_create_root(&rdtgroup_kf_syscall_ops, + KERNFS_ROOT_CREATE_DEACTIVATED, + &rdtgroup_default); + if (IS_ERR(rdt_root)) + return PTR_ERR(rdt_root); + + mutex_lock(&rdtgroup_mutex); + + rdtgroup_default.closid = 0; + list_add(&rdtgroup_default.rdtgroup_list, &rdt_all_groups); + + rdtgroup_default.kn = rdt_root->kn; + kernfs_activate(rdtgroup_default.kn); + + mutex_unlock(&rdtgroup_mutex); + + return ret; +} + +/* + * rdtgroup_init - rdtgroup initialization + * + * Setup resctrl file system including set up root, create mount point, + * register rdtgroup filesystem, and initialize files under root directory. + * + * Return: 0 on success or -errno + */ +int __init rdtgroup_init(void) +{ + int ret = 0; + + ret = rdtgroup_setup_root(); + if (ret) + return ret; + + ret = sysfs_create_mount_point(fs_kobj, "resctrl"); + if (ret) + goto cleanup_root; + + ret = register_filesystem(&rdt_fs_type); + if (ret) + goto cleanup_mountpoint; + + return 0; + +cleanup_mountpoint: + sysfs_remove_mount_point(fs_kobj, "resctrl"); +cleanup_root: + kernfs_destroy_root(rdt_root); + + return ret; +} diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h index e398bea..27ef03d 100644 --- a/include/uapi/linux/magic.h +++ b/include/uapi/linux/magic.h @@ -57,6 +57,7 @@ #define CGROUP_SUPER_MAGIC 0x27e0eb #define CGROUP2_SUPER_MAGIC 0x63677270 +#define RDTGROUP_SUPER_MAGIC 0x7655821 #define STACK_END_MAGIC 0x57AC6E9D -- 2.5.0