Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757297AbcJGXrG (ORCPT ); Fri, 7 Oct 2016 19:47:06 -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 S1754830AbcJGXpF (ORCPT ); Fri, 7 Oct 2016 19:45:05 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.31,457,1473145200"; d="scan'208";a="17405519" 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 14/18] x86/intel_rdt: Add cpus file Date: Fri, 7 Oct 2016 19:45:59 -0700 Message-Id: <1475894763-64683-15-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: 7795 Lines: 271 From: Tony Luck Now we populate each directory with a read/write (mode 0644) file named "cpus". This is used to over-ride the resources available to processes in the default resource group when running on specific CPUs. Each "cpus" file reads as a cpumask showing which CPUs belong to this resource group. Initially all online CPUs are assigned to the default group. They can be added to other groups by writing a cpumask to the "cpus" file in the directory for the resource group (which will remove them from the previous group to which they were assigned). CPU online/offline operations will delete CPUs that go offline from whatever group they are in and add new CPUs to the default group. If there are CPUs assigned to a group when the directory is removed, they are returned to the default group. Signed-off-by: Fenghua Yu Signed-off-by: Tony Luck --- arch/x86/include/asm/intel_rdt.h | 5 ++ arch/x86/kernel/cpu/intel_rdt.c | 12 +++ arch/x86/kernel/cpu/intel_rdt_rdtgroup.c | 127 +++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+) diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h index 99d8d14..7c74272 100644 --- a/arch/x86/include/asm/intel_rdt.h +++ b/arch/x86/include/asm/intel_rdt.h @@ -6,13 +6,16 @@ * @kn: kernfs node * @rdtgroup_list: linked list for all rdtgroups * @closid: closid for this rdtgroup + * @cpu_mask: CPUs assigned to this rdtgroup * @flags: status bits * @waitcount: how many cpus expect to find this + * group when they acquire rdtgroup_mutex */ struct rdtgroup { struct kernfs_node *kn; struct list_head rdtgroup_list; int closid; + struct cpumask cpu_mask; int flags; atomic_t waitcount; }; @@ -147,6 +150,8 @@ union cpuid_0x10_1_edx { unsigned int full; }; +DECLARE_PER_CPU_READ_MOSTLY(int, cpu_closid); + void rdt_cbm_update(void *arg); struct rdtgroup *rdtgroup_kn_lock_live(struct kernfs_node *kn); void rdtgroup_kn_unlock(struct kernfs_node *kn); diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index f6caabd..0b076d0 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -38,6 +38,8 @@ DEFINE_MUTEX(rdtgroup_mutex); int rdt_max_closid; +DEFINE_PER_CPU_READ_MOSTLY(int, cpu_closid); + #define domain_init(name) LIST_HEAD_INIT(rdt_resources_all[name].domains) struct rdt_resource rdt_resources_all[] = { @@ -227,8 +229,11 @@ static int intel_rdt_online_cpu(unsigned int cpu) struct rdt_resource *r; mutex_lock(&rdtgroup_mutex); + per_cpu(cpu_closid, cpu) = 0; for_each_rdt_resource(r) update_domain(cpu, r, 1); + /* The cpu is set in default rdtgroup after online. */ + cpumask_set_cpu(cpu, &rdtgroup_default.cpu_mask); smp_call_function_single(cpu, rdt_reset_pqr_assoc_closid, NULL, 1); mutex_unlock(&rdtgroup_mutex); @@ -238,10 +243,17 @@ static int intel_rdt_online_cpu(unsigned int cpu) static int intel_rdt_offline_cpu(unsigned int cpu) { struct rdt_resource *r; + struct rdtgroup *rdtgrp; + struct list_head *l; mutex_lock(&rdtgroup_mutex); for_each_rdt_resource(r) update_domain(cpu, r, 0); + list_for_each(l, &rdt_all_groups) { + rdtgrp = list_entry(l, struct rdtgroup, rdtgroup_list); + if (cpumask_test_and_clear_cpu(cpu, &rdtgrp->cpu_mask)) + break; + } mutex_unlock(&rdtgroup_mutex); return 0; diff --git a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c index efcbfe7..2a4e78a 100644 --- a/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c +++ b/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c @@ -20,6 +20,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include @@ -163,6 +164,117 @@ static struct kernfs_ops rdtgroup_kf_single_ops = { .seq_show = rdtgroup_seqfile_show, }; +static int rdtgroup_cpus_show(struct kernfs_open_file *of, + struct seq_file *s, void *v) +{ + struct rdtgroup *rdtgrp; + int ret = 0; + + rdtgrp = rdtgroup_kn_lock_live(of->kn); + + if (rdtgrp) + seq_printf(s, "%*pb\n", cpumask_pr_args(&rdtgrp->cpu_mask)); + else + ret = -ENOENT; + rdtgroup_kn_unlock(of->kn); + + return ret; +} + +static ssize_t rdtgroup_cpus_write(struct kernfs_open_file *of, + char *buf, size_t nbytes, loff_t off) +{ + struct rdtgroup *rdtgrp, *r; + cpumask_var_t tmpmask, newmask; + int ret, cpu; + + if (!buf) + return -EINVAL; + + if (!alloc_cpumask_var(&tmpmask, GFP_KERNEL)) + return -ENOMEM; + if (!alloc_cpumask_var(&newmask, GFP_KERNEL)) { + free_cpumask_var(tmpmask); + return -ENOMEM; + } + rdtgrp = rdtgroup_kn_lock_live(of->kn); + if (!rdtgrp) { + ret = -ENOENT; + goto unlock; + } + + ret = cpumask_parse(buf, newmask); + if (ret) + goto unlock; + + get_online_cpus(); + /* check that user didn't specify any offline cpus */ + cpumask_andnot(tmpmask, newmask, cpu_online_mask); + if (cpumask_weight(tmpmask)) { + ret = -EINVAL; + goto end; + } + + /* Are trying to drop some cpus from this group? */ + cpumask_andnot(tmpmask, &rdtgrp->cpu_mask, newmask); + if (cpumask_weight(tmpmask)) { + /* Can't drop from default group */ + if (rdtgrp == &rdtgroup_default) { + ret = -EINVAL; + goto end; + } + /* Give any dropped cpus to rdtgroup_default */ + cpumask_or(&rdtgroup_default.cpu_mask, + &rdtgroup_default.cpu_mask, tmpmask); + for_each_cpu(cpu, tmpmask) + per_cpu(cpu_closid, cpu) = 0; + } + + /* + * If we added cpus, remove them from previous group that owned them + * and update per-cpu rdtgroup pointers to refer to us + */ + cpumask_andnot(tmpmask, newmask, &rdtgrp->cpu_mask); + if (cpumask_weight(tmpmask)) { + struct list_head *l; + + list_for_each(l, &rdt_all_groups) { + r = list_entry(l, struct rdtgroup, rdtgroup_list); + if (r == rdtgrp) + continue; + cpumask_andnot(&r->cpu_mask, &r->cpu_mask, tmpmask); + } + for_each_cpu(cpu, tmpmask) + per_cpu(cpu_closid, cpu) = rdtgrp->closid; + } + + /* Done pushing/pulling - update this group with new mask */ + cpumask_copy(&rdtgrp->cpu_mask, newmask); + +end: + put_online_cpus(); +unlock: + rdtgroup_kn_unlock(of->kn); + free_cpumask_var(tmpmask); + free_cpumask_var(newmask); + + return ret ?: nbytes; +} + +/* Files in each rdtgroup */ +static struct rftype rdtgroup_base_files[] = { + { + .name = "cpus", + .mode = 0644, + .kf_ops = &rdtgroup_kf_single_ops, + .write = rdtgroup_cpus_write, + .seq_show = rdtgroup_cpus_show, + }, + { + /* NULL terminated */ + } +}; + static int rdt_num_closid_show(struct kernfs_open_file *of, struct seq_file *seq, void *v) { @@ -511,6 +623,10 @@ static int rdtgroup_mkdir(struct kernfs_node *parent_kn, const char *name, if (ret) goto out_destroy; + ret = rdtgroup_add_files(kn, rdtgroup_base_files); + if (ret) + goto out_destroy; + kernfs_activate(kn); ret = 0; @@ -548,6 +664,10 @@ static int rdtgroup_rmdir(struct kernfs_node *kn) return -EPERM; } + /* Give any CPUs back to the default group */ + cpumask_or(&rdtgroup_default.cpu_mask, + &rdtgroup_default.cpu_mask, &rdtgrp->cpu_mask); + rdtgrp->flags = RDT_DELETED; closid_free(rdtgrp->closid); list_del(&rdtgrp->rdtgroup_list); @@ -584,11 +704,18 @@ static int __init rdtgroup_setup_root(void) rdtgroup_default.closid = 0; list_add(&rdtgroup_default.rdtgroup_list, &rdt_all_groups); + ret = rdtgroup_add_files(rdt_root->kn, rdtgroup_base_files); + if (ret) { + kernfs_destroy_root(rdt_root); + goto out; + } + rdtgroup_default.kn = rdt_root->kn; ret = rdtgroup_create_info_dir(rdtgroup_default.kn); if (!ret) kernfs_activate(rdtgroup_default.kn); +out: mutex_unlock(&rdtgroup_mutex); return ret; -- 2.5.0