From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933774AbbEKTE5 (ORCPT ); Mon, 11 May 2015 15:04:57 -0400 Received: from mga01.intel.com ([192.55.52.88]:20783 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933724AbbEKTEp (ORCPT ); Mon, 11 May 2015 15:04:45 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.13,409,1427785200"; d="scan'208";a="693230452" From: Vikas Shivappa To: vikas.shivappa@intel.com Cc: x86@kernel.org, linux-kernel@vger.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, peter.zijlstra@intel.com, h.peter.anvin@intel.com, kanaka.d.juvva@intel.com, mtosatti@redhat.com, vikas.shivappa@linux.intel.com Subject: [PATCH 2/7] x86/intel_rdt: Adds support for Class of service management Date: Mon, 11 May 2015 12:02:51 -0700 Message-Id: <1431370976-31115-3-git-send-email-vikas.shivappa@linux.intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1431370976-31115-1-git-send-email-vikas.shivappa@linux.intel.com> References: <1431370976-31115-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 This patch adds a cgroup subsystem for Intel Resource Director Technology(RDT) feature and Class of service(CLOSid) management which is part of common RDT framework. This cgroup would eventually be used by all sub-features of RDT and hence be associated with the common RDT framework as well as sub-feature specific framework. However current patch series only adds cache allocation sub-feature specific code. 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 cache_mask which represents the L3 cache allocation to the cgroup. Tasks belonging to the cgroup get to fill the cache represented by the cache_mask. 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 cache_mask(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 | 38 +++++++++++++ arch/x86/kernel/cpu/intel_rdt.c | 112 +++++++++++++++++++++++++++++++++++++-- include/linux/cgroup_subsys.h | 4 ++ 3 files changed, 150 insertions(+), 4 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..6f62891 --- /dev/null +++ b/arch/x86/include/asm/intel_rdt.h @@ -0,0 +1,38 @@ +#ifndef _RDT_H_ +#define _RDT_H_ + +#ifdef CONFIG_CGROUP_RDT + +#include + +struct rdt_subsys_info { + /* Clos Bitmap to keep track of available CLOSids.*/ + unsigned long *closmap; +}; + +struct intel_rdt { + struct cgroup_subsys_state css; + /* Class of service for the cgroup.*/ + unsigned int clos; +}; + +struct clos_cbm_map { + unsigned long cache_mask; + 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 f393d3e..e8134a9 100644 --- a/arch/x86/kernel/cpu/intel_rdt.c +++ b/arch/x86/kernel/cpu/intel_rdt.c @@ -24,21 +24,125 @@ #include #include +#include +#include + +/* + * ccmap maintains 1:1 mapping between CLOSid and cache bitmask. + */ +static struct clos_cbm_map *ccmap; +static struct rdt_subsys_info rdtss_info; +static DEFINE_MUTEX(rdt_group_mutex); +struct intel_rdt rdt_root_group; + +static void intel_rdt_free_closid(unsigned int clos) +{ + lockdep_assert_held(&rdt_group_mutex); + + clear_bit(clos, rdtss_info.closmap); +} + +static void __clos_get(unsigned int closid) +{ + struct clos_cbm_map *ccm = &ccmap[closid]; + + lockdep_assert_held(&rdt_group_mutex); + + ccm->clos_refcnt += 1; +} + +static void __clos_put(unsigned int closid) +{ + struct clos_cbm_map *ccm = &ccmap[closid]; + + lockdep_assert_held(&rdt_group_mutex); + WARN_ON(!ccm->clos_refcnt); + + ccm->clos_refcnt -= 1; + if (!ccm->clos_refcnt) + intel_rdt_free_closid(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; + + /* + * Cannot return failure on systems with no Cache Allocation + * as the cgroup_init does not handle failures gracefully. + */ + 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->clos = parent->clos; + __clos_get(ir->clos); + 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); + __clos_put(ir->clos); + kfree(ir); + mutex_unlock(&rdt_group_mutex); +} static int __init intel_rdt_late_init(void) { struct cpuinfo_x86 *c = &boot_cpu_data; - int maxid, max_cbm_len; + static struct clos_cbm_map *ccm; + int maxid, max_cbm_len, err = 0; + size_t sizeb; - 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_rdt_max_closid; max_cbm_len = c->x86_rdt_max_cbm_len; + sizeb = BITS_TO_LONGS(maxid) * sizeof(long); + rdtss_info.closmap = kzalloc(sizeb, GFP_KERNEL); + if (!rdtss_info.closmap) { + err = -ENOMEM; + goto out_err; + } + + sizeb = maxid * sizeof(struct clos_cbm_map); + ccmap = kzalloc(sizeb, GFP_KERNEL); + if (!ccmap) { + kfree(rdtss_info.closmap); + err = -ENOMEM; + goto out_err; + } + + set_bit(0, rdtss_info.closmap); + rdt_root_group.clos = 0; + ccm = &ccmap[0]; + bitmap_set(&ccm->cache_mask, 0, max_cbm_len); + ccm->clos_refcnt = 1; + pr_info("Max bitmask length:%u,Max ClosIds: %u\n", max_cbm_len, maxid); +out_err: - return 0; + 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