Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756678AbbHFVzu (ORCPT ); Thu, 6 Aug 2015 17:55:50 -0400 Received: from mga14.intel.com ([192.55.52.115]:28681 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755056AbbHFVzU (ORCPT ); Thu, 6 Aug 2015 17:55:20 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.15,625,1432623600"; d="scan'208";a="743717975" From: Vikas Shivappa To: vikas.shivappa@intel.com Cc: linux-kernel@vger.kernel.org, x86@kernel.org, hpa@zytor.com, tglx@linutronix.de, mingo@kernel.org, tj@kernel.org, peterz@infradead.org, matt.fleming@intel.com, will.auld@intel.com, glenn.p.williamson@intel.com, kanaka.d.juvva@intel.com, vikas.shivappa@linux.intel.com Subject: [PATCH 5/9] x86/intel_rdt: Add new cgroup and Class of service management Date: Thu, 6 Aug 2015 14:55:13 -0700 Message-Id: <1438898117-3692-6-git-send-email-vikas.shivappa@linux.intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1438898117-3692-1-git-send-email-vikas.shivappa@linux.intel.com> References: <1438898117-3692-1-git-send-email-vikas.shivappa@linux.intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6693 Lines: 251 This patch adds a cgroup subsystem for Intel Resource Director Technology (RDT) feature. This cgroup may eventually be used by many sub-features of RDT. Therefore the cgroup may be associated with the common RDT framework as well as sub-feature specific framework. Patch also adds Class of service id (CLOSid) management code for Cache allocation. When a cgroup directory is created it has a CLOSid associated with it which is inherited from its parent. The Closid is mapped to a l3_cbm (capacity bit mask) which represents the L3 cache allocation to the cgroup. Tasks belonging to the cgroup get to fill the cache represented by the l3_cbm. CLOSid is internal to the kernel and not exposed to user. Kernel uses several ways to optimize the allocation of Closid and thereby exposing the available Closids may actually provide wrong information to users as it may be dynamically changing depending on its usage. CLOSid allocation is tracked using a separate bitmap. The maximum number of CLOSids is specified by the h/w during CPUID enumeration and the kernel simply throws an -ENOSPC when it runs out of CLOSids. Each l3_cbm has an associated CLOSid. However if multiple cgroups have the same cache mask they would also have the same CLOSid. The reference count parameter in CLOSid-CBM map keeps track of how many cgroups are using each CLOSid<->CBM mapping. Signed-off-by: Vikas Shivappa --- arch/x86/include/asm/intel_rdt.h | 36 +++++++++++ arch/x86/kernel/cpu/intel_rdt.c | 133 ++++++++++++++++++++++++++++++++++++++- include/linux/cgroup_subsys.h | 4 ++ 3 files changed, 170 insertions(+), 3 deletions(-) create mode 100644 arch/x86/include/asm/intel_rdt.h diff --git a/arch/x86/include/asm/intel_rdt.h b/arch/x86/include/asm/intel_rdt.h new file mode 100644 index 0000000..a887004 --- /dev/null +++ b/arch/x86/include/asm/intel_rdt.h @@ -0,0 +1,36 @@ +#ifndef _RDT_H_ +#define _RDT_H_ + +#ifdef CONFIG_CGROUP_RDT + +#include + +struct rdt_subsys_info { + unsigned long *closmap; +}; + +struct intel_rdt { + struct cgroup_subsys_state css; + u32 closid; +}; + +struct clos_cbm_table { + unsigned long l3_cbm; + unsigned int clos_refcnt; +}; + +/* + * Return rdt group corresponding to this container. + */ +static inline struct intel_rdt *css_rdt(struct cgroup_subsys_state *css) +{ + return css ? container_of(css, struct intel_rdt, css) : NULL; +} + +static inline struct intel_rdt *parent_rdt(struct intel_rdt *ir) +{ + return css_rdt(ir->css.parent); +} + +#endif +#endif diff --git a/arch/x86/kernel/cpu/intel_rdt.c b/arch/x86/kernel/cpu/intel_rdt.c index f49e970..52e1fd6 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -24,17 +24,144 @@ #include #include +#include +#include + +/* + * cctable maintains 1:1 mapping between CLOSid and cache bitmask. + */ +static struct clos_cbm_table *cctable; +static struct rdt_subsys_info rdtss_info; +static DEFINE_MUTEX(rdt_group_mutex); +struct intel_rdt rdt_root_group; + +static inline void closid_get(u32 closid) +{ + struct clos_cbm_table *cct = &cctable[closid]; + + lockdep_assert_held(&rdt_group_mutex); + + cct->clos_refcnt++; +} + +static int closid_alloc(struct intel_rdt *ir) +{ + u32 maxid; + u32 id; + + lockdep_assert_held(&rdt_group_mutex); + + maxid = boot_cpu_data.x86_cache_max_closid; + id = find_first_zero_bit(rdtss_info.closmap, maxid); + if (id == maxid) + return -ENOSPC; + + set_bit(id, rdtss_info.closmap); + closid_get(id); + ir->closid = id; + + return 0; +} + +static inline void closid_free(u32 closid) +{ + clear_bit(closid, rdtss_info.closmap); + cctable[closid].l3_cbm = 0; +} + +static inline void closid_put(u32 closid) +{ + struct clos_cbm_table *cct = &cctable[closid]; + + lockdep_assert_held(&rdt_group_mutex); + if (WARN_ON(!cct->clos_refcnt)) + return; + + if (!--cct->clos_refcnt) + closid_free(closid); +} + +static struct cgroup_subsys_state * +intel_rdt_css_alloc(struct cgroup_subsys_state *parent_css) +{ + struct intel_rdt *parent = css_rdt(parent_css); + struct intel_rdt *ir; + + /* + * cgroup_init cannot handle failures gracefully. + * Return rdt_root_group.css instead of failure + * always even when Cache allocation is not supported. + */ + if (!parent) + return &rdt_root_group.css; + + ir = kzalloc(sizeof(struct intel_rdt), GFP_KERNEL); + if (!ir) + return ERR_PTR(-ENOMEM); + + mutex_lock(&rdt_group_mutex); + ir->closid = parent->closid; + closid_get(ir->closid); + mutex_unlock(&rdt_group_mutex); + + return &ir->css; +} + +static void intel_rdt_css_free(struct cgroup_subsys_state *css) +{ + struct intel_rdt *ir = css_rdt(css); + + mutex_lock(&rdt_group_mutex); + closid_put(ir->closid); + kfree(ir); + mutex_unlock(&rdt_group_mutex); +} static int __init intel_rdt_late_init(void) { struct cpuinfo_x86 *c = &boot_cpu_data; + static struct clos_cbm_table *cct; + u32 maxid, max_cbm_len; + int err = 0, size; - if (!cpu_has(c, X86_FEATURE_CAT_L3)) + if (!cpu_has(c, X86_FEATURE_CAT_L3)) { + rdt_root_group.css.ss->disabled = 1; return -ENODEV; + } + maxid = c->x86_cache_max_closid; + max_cbm_len = c->x86_cache_max_cbm_len; - pr_info("Intel cache allocation detected\n"); + size = BITS_TO_LONGS(maxid) * sizeof(long); + rdtss_info.closmap = kzalloc(size, GFP_KERNEL); + if (!rdtss_info.closmap) { + err = -ENOMEM; + goto out_err; + } - return 0; + size = maxid * sizeof(struct clos_cbm_table); + cctable = kzalloc(size, GFP_KERNEL); + if (!cctable) { + kfree(rdtss_info.closmap); + err = -ENOMEM; + goto out_err; + } + + set_bit(0, rdtss_info.closmap); + rdt_root_group.closid = 0; + cct = &cctable[0]; + cct->l3_cbm = (1ULL << max_cbm_len) - 1; + cct->clos_refcnt = 1; + + pr_info("Intel cache allocation enabled\n"); +out_err: + + return err; } late_initcall(intel_rdt_late_init); + +struct cgroup_subsys intel_rdt_cgrp_subsys = { + .css_alloc = intel_rdt_css_alloc, + .css_free = intel_rdt_css_free, + .early_init = 0, +}; diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h index e4a96fb..0339312 100644 --- a/include/linux/cgroup_subsys.h +++ b/include/linux/cgroup_subsys.h @@ -47,6 +47,10 @@ SUBSYS(net_prio) SUBSYS(hugetlb) #endif +#if IS_ENABLED(CONFIG_CGROUP_RDT) +SUBSYS(intel_rdt) +#endif + /* * The following subsystems are not supported on the default hierarchy. */ -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/