Received: by 2002:a25:f815:0:0:0:0:0 with SMTP id u21csp1083211ybd; Wed, 26 Jun 2019 10:54:12 -0700 (PDT) X-Google-Smtp-Source: APXvYqxUHCt8a+7fBnwOJxyyMLMdWFmtps0rWBR5sH0pexGe/ftrZkN+ph4hnQqPLuE9tRuIrUwY X-Received: by 2002:a63:d4c:: with SMTP id 12mr4273731pgn.30.1561571651979; Wed, 26 Jun 2019 10:54:11 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1561571651; cv=none; d=google.com; s=arc-20160816; b=cXMII4ncnke5eqWC0kMVyeeLvO1OEFGVP5G0URjbELg3aEPrkHZi3vR4Vs24kM7hZl lG3vVH8o8l/RJzvLH/9IeKC9a6GKDssfEl20hIhq5CuBYef5yy57chcz8ot3potviID5 5dt8pNRMvNEZTa+5tI7R3hff9q4vGQInptqFx15W5lzQh5e3l9Xofp+dBE50Xy3ej+cO 2YwEoeFHxbEE3lhRiShKmaiglKeN2ZIYjK3760WjEd3fEK6pP0woda21q2+oAubrq26M P7eufJwl8BbSHNWlm3FrXt9WaYuS6s1RWIWysB2UNON9t0Z7bgbFMDlh405RbXvx/8e/ z4aw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from; bh=KoIVjZE33a5VZ6R1GJybd3+X3P4tnNBWcIW8of9tjK8=; b=sjbZg8RdOLxymHGl2i3MWp+Cr/U0RwULaIUwn9R2Kx1G82MpxxXH8eQLyWDQTkNr/c LQeqw5brzF9tXfsBWuVg5jy5RIUMsa/FQpyVS98gVnHxQYrKBPXOQLGR8JH6P4mmFnvx efNqR8rGH/fELentX77Ro8g4xY+XuEgLmP4d3ASQNwO/kd3IBBLsE+Utg+VENzF6vYMO zd/52MVvJ2S9GsF+eNxOnN5fcVYH1mcDuIzQXQXJNA7BY4IrjJqe9F7TglhvAJJAWhq0 2bMLHEpoOE5Ra4rQpM1p11QnIGZ/rgbtdI5jzcq4pOGAzh5GRTjugxQD79qBwC2ssOji DqsQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id w10si3873166plz.48.2019.06.26.10.53.56; Wed, 26 Jun 2019 10:54:11 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726779AbfFZRvw (ORCPT + 99 others); Wed, 26 Jun 2019 13:51:52 -0400 Received: from mga12.intel.com ([192.55.52.136]:19497 "EHLO mga12.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726514AbfFZRvK (ORCPT ); Wed, 26 Jun 2019 13:51:10 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 26 Jun 2019 10:51:09 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.63,420,1557212400"; d="scan'208";a="337288608" Received: from rchatre-s.jf.intel.com ([10.54.70.76]) by orsmga005.jf.intel.com with ESMTP; 26 Jun 2019 10:51:08 -0700 From: Reinette Chatre To: tglx@linutronix.de, fenghua.yu@intel.com, bp@alien8.de, tony.luck@intel.com Cc: mingo@redhat.com, hpa@zytor.com, x86@kernel.org, linux-kernel@vger.kernel.org, Reinette Chatre Subject: [PATCH 09/10] x86/resctrl: Pseudo-lock portions of multiple resources Date: Wed, 26 Jun 2019 10:48:48 -0700 Message-Id: <918552f95d59d20fb9a09dd3b6666ad2f82bdf0c.1561569068.git.reinette.chatre@intel.com> X-Mailer: git-send-email 2.17.2 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org A cache pseudo-locked region may span more than one level of cache. A part of the pseudo-locked region that falls on one cache level is referred to as a pseudo-lock portion that was introduced previously. Now a pseudo-locked region is allowed to have two portions instead of the previous limit of one. When a pseudo-locked region consists out of two portions it can only span a L2 and L3 resctrl resource. When a pseudo-locked region consists out of a L2 and L3 portion then there are some requirements: - the L2 and L3 cache has to be in same cache hierarchy - the L3 portion must be same size or larger than L2 portion As documented in previous changes the list of portions are maintained so that the L2 portion would always appear first in the list to simplify any information retrieval. Signed-off-by: Reinette Chatre --- arch/x86/kernel/cpu/resctrl/pseudo_lock.c | 142 +++++++++++++++++++++- 1 file changed, 139 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/cpu/resctrl/pseudo_lock.c b/arch/x86/kernel/cpu/resctrl/pseudo_lock.c index a7fe53447a7e..4e47ad582db6 100644 --- a/arch/x86/kernel/cpu/resctrl/pseudo_lock.c +++ b/arch/x86/kernel/cpu/resctrl/pseudo_lock.c @@ -339,13 +339,104 @@ static int pseudo_lock_single_portion_valid(struct pseudo_lock_region *plr, return -1; } +/** + * pseudo_lock_l2_l3_portions_valid - Verify region across L2 and L3 + * @plr: Pseudo-Locked region + * @l2_portion: L2 Cache portion of pseudo-locked region + * @l3_portion: L3 Cache portion of pseudo-locked region + * + * User requested a pseudo-locked region consisting of a L2 as well as L3 + * cache portion. The portions are tested as follows: + * - L2 and L3 cache instances have to be in the same cache hierarchy. + * This is tested by ensuring that the L2 portion's cpumask is a + * subset of the L3 portion's cpumask. + * - L3 portion must be same size or larger than L2 portion. + * + * Return: -1 if the portions are unable to be used for a pseudo-locked + * region, 0 if the portions could be used for a pseudo-locked + * region. When returning 0: + * - the pseudo-locked region's size, line_size (cache line length) + * and CPU on which locking thread will be run are set. + * - CPUs associated with L2 cache portion are constrained from + * entering C-state that will affect the pseudo-locked region. + */ +static int pseudo_lock_l2_l3_portions_valid(struct pseudo_lock_region *plr, + struct pseudo_lock_portion *l2_p, + struct pseudo_lock_portion *l3_p) +{ + struct rdt_domain *l2_d, *l3_d; + unsigned int l2_size, l3_size; + + l2_d = rdt_find_domain(l2_p->r, l2_p->d_id, NULL); + if (IS_ERR_OR_NULL(l2_d)) { + rdt_last_cmd_puts("Cannot locate L2 cache domain\n"); + return -1; + } + + l3_d = rdt_find_domain(l3_p->r, l3_p->d_id, NULL); + if (IS_ERR_OR_NULL(l3_d)) { + rdt_last_cmd_puts("Cannot locate L3 cache domain\n"); + return -1; + } + + if (!cpumask_subset(&l2_d->cpu_mask, &l3_d->cpu_mask)) { + rdt_last_cmd_puts("L2 and L3 caches need to be in same hierarchy\n"); + return -1; + } + + if (pseudo_lock_cstates_constrain(plr, &l2_d->cpu_mask)) { + rdt_last_cmd_puts("Cannot limit C-states\n"); + return -1; + } + + l2_size = rdtgroup_cbm_to_size(l2_p->r, l2_d, l2_p->cbm); + l3_size = rdtgroup_cbm_to_size(l3_p->r, l3_d, l3_p->cbm); + + if (l2_size > l3_size) { + rdt_last_cmd_puts("L3 cache portion has to be same size or larger than L2 cache portion\n"); + goto err_size; + } + + plr->size = l2_size; + + l2_size = get_cache_line_size(cpumask_first(&l2_d->cpu_mask), + l2_p->r->cache_level); + l3_size = get_cache_line_size(cpumask_first(&l3_d->cpu_mask), + l3_p->r->cache_level); + if (l2_size != l3_size) { + rdt_last_cmd_puts("L2 and L3 caches have different coherency cache line sizes\n"); + goto err_line; + } + + plr->line_size = l2_size; + + plr->cpu = cpumask_first(&l2_d->cpu_mask); + + if (!cpu_online(plr->cpu)) { + rdt_last_cmd_printf("CPU %u associated with cache not online\n", + plr->cpu); + goto err_cpu; + } + + return 0; + +err_cpu: + plr->line_size = 0; + plr->cpu = 0; +err_line: + plr->size = 0; +err_size: + pseudo_lock_cstates_relax(plr); + return -1; +} + /** * pseudo_lock_region_init - Initialize pseudo-lock region information * @plr: pseudo-lock region * * Called after user provided a schemata to be pseudo-locked. From the * schemata the &struct pseudo_lock_region is on entry already initialized - * with the resource, domain, and capacity bitmask. Here the + * with the resource(s), domain(s), and capacity bitmask(s). Here the * provided data is validated and information required for pseudo-locking * deduced, and &struct pseudo_lock_region initialized further. This * information includes: @@ -355,13 +446,24 @@ static int pseudo_lock_single_portion_valid(struct pseudo_lock_region *plr, * - a cpu associated with the cache instance on which the pseudo-locking * flow can be executed * + * A user provides a schemata for a pseudo-locked region. This schemata may + * contain portions that span different resources, for example, a cache + * pseudo-locked region that spans L2 and L3 cache. After the schemata is + * parsed into portions it needs to be verified that the provided portions + * are valid with the following tests: + * + * - L2 only portion on system that has only L2 resource - OK + * - L3 only portion on any system that supports it - OK + * - L2 portion on system that has L3 resource - require L3 portion + ** + * * Return: 0 on success, <0 on failure. Descriptive error will be written * to last_cmd_status buffer. */ static int pseudo_lock_region_init(struct pseudo_lock_region *plr) { struct rdt_resource *l3_resource = &rdt_resources_all[RDT_RESOURCE_L3]; - struct pseudo_lock_portion *p; + struct pseudo_lock_portion *p, *n_p, *tmp; int ret; if (list_empty(&plr->portions)) { @@ -397,8 +499,42 @@ static int pseudo_lock_region_init(struct pseudo_lock_region *plr) rdt_last_cmd_puts("Invalid resource or just L2 provided when L3 is required\n"); goto out_region; } + } + + /* + * List is neither empty nor singular, process first and second portions + */ + p = list_first_entry(&plr->portions, struct pseudo_lock_portion, list); + n_p = list_next_entry(p, list); + + /* + * If the second portion is not also the last portion user provided + * more portions than can be supported. + */ + tmp = list_last_entry(&plr->portions, struct pseudo_lock_portion, list); + if (n_p != tmp) { + rdt_last_cmd_puts("Only two pseudo-lock portions supported\n"); + goto out_region; + } + + if (p->r->rid == RDT_RESOURCE_L2 && n_p->r->rid == RDT_RESOURCE_L3) { + ret = pseudo_lock_l2_l3_portions_valid(plr, p, n_p); + if (ret < 0) + goto out_region; + return 0; + } else if (p->r->rid == RDT_RESOURCE_L3 && + n_p->r->rid == RDT_RESOURCE_L2) { + if (pseudo_lock_l2_l3_portions_valid(plr, n_p, p) == 0) { + /* + * Let L2 and L3 portions appear in order in the + * portions list in support of consistent output to + * user space. + */ + list_rotate_left(&plr->portions); + return 0; + } } else { - rdt_last_cmd_puts("Multiple pseudo-lock portions unsupported\n"); + rdt_last_cmd_puts("Invalid combination of resources\n"); } out_region: -- 2.17.2