From patchwork Tue Dec 11 01:03:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Keith Busch X-Patchwork-Id: 10722921 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 457ED112E for ; Tue, 11 Dec 2018 01:06:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 347F02A170 for ; Tue, 11 Dec 2018 01:06:11 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 28E892A50D; Tue, 11 Dec 2018 01:06:11 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7739E2A170 for ; Tue, 11 Dec 2018 01:06:10 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 897DE8E0072; Mon, 10 Dec 2018 20:05:54 -0500 (EST) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 81CC98E006F; Mon, 10 Dec 2018 20:05:54 -0500 (EST) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 69A1C8E0072; Mon, 10 Dec 2018 20:05:54 -0500 (EST) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from mail-pf1-f198.google.com (mail-pf1-f198.google.com [209.85.210.198]) by kanga.kvack.org (Postfix) with ESMTP id 2550F8E006F for ; Mon, 10 Dec 2018 20:05:54 -0500 (EST) Received: by mail-pf1-f198.google.com with SMTP id h11so11241000pfj.13 for ; Mon, 10 Dec 2018 17:05:54 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-original-authentication-results:x-gm-message-state:from:to:cc :subject:date:message-id:in-reply-to:references; bh=RvwSly8zCurQLlyc3Yp2CVbVJb5LFpRKZ82Dh9r7Kp4=; b=palkS5GqUF5uIvHNKH7XwOQCAIAYfl/OEcQc04xIyvkGNFnQUDujD3O+qQDAfZcHH+ Q3vWGh7Oz4e1OkU1i9a5vQ7gQ1qjfAEgwDhzusR9Uy1qpNB3en+0XzYZ/cJ9lLACm4zY crRHKYtNeGOAFBr7FbaL6CmlouA6LnqXlPRSMrmHcr8LyQeTrS9AG+apugNHBLi2p4Xy NDeV78dnMvGSPEjN9Hq15xjvXk41zhig6GfXOJHDLBwKuMDcu6nD4K4HyrEaJ5BoXlVW a+6w015VNpcJo1jt9jwDtjb1cOaT+g0wGR2bBM0DJP8k46kSdLDO9lTar8bufEmsjq9H lCfA== X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of keith.busch@intel.com designates 192.55.52.43 as permitted sender) smtp.mailfrom=keith.busch@intel.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com X-Gm-Message-State: AA+aEWaPiLXt12N6zCvmy1FBMf7A2tqnvb21WMnLLotvpEtrGsNtealf hoEIKCC00jDV5RsrAoko8Rn/sVPgWOb9toIDfVKWq+ozvGZygAETOcUl54deLDYGIGT8ClGxew/ 7q9ZgXA9zuRKNggwNPgZxGpOlv3vadp9G7lyK8IxoVF4EKUxwC/zrkK41Jlg9mgbW3w== X-Received: by 2002:a17:902:584:: with SMTP id f4mr14619917plf.28.1544490353787; Mon, 10 Dec 2018 17:05:53 -0800 (PST) X-Google-Smtp-Source: AFSGD/U6HD/7/mq5D3QWge0a0p51+7sAQ7inpv63rkZff8v0oriqWi1lIrGS6bQFiykK4ckEaKee X-Received: by 2002:a17:902:584:: with SMTP id f4mr14619881plf.28.1544490352846; Mon, 10 Dec 2018 17:05:52 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544490352; cv=none; d=google.com; s=arc-20160816; b=FeUQNTmPiuZ22ppoLqSZtw1ygAR/qa22d4bzWYfwHkee0dV3NQlux465I3g/mCeJYN u+v4b0bgWviJGkVEGbtf1QzY2b8DIJ7A/9aFJgtSfbq0N0tfeFZzjCdT/sgpGOe6E/+w P3k8/Z9uJBaAR7E+pw8CYwLbpnOPih+5saKCAMsFLFBKHzIzsBpqvIDZgTXhzQp5huAS 347KAEsgbIN9Oegzot3UjnsYlx8l79mfr+HEacfwbhQ6cBMFSUVhswR8a2Qs5r8NF6FQ PitIE/dhb3QYnFYg5skN/udLVURXKkLGEzqGuF6xXExmSLyoudwYHHmsfIVEINRpvS0d LhOg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from; bh=RvwSly8zCurQLlyc3Yp2CVbVJb5LFpRKZ82Dh9r7Kp4=; b=BjmQ36/s0mpsfjZ6uzs3EDZlt/XWTjDhEfLUPtZ+b4QYlfzSAYRtyQ+DpIru1zo7Pk S6A5wVy7eCzVnYOSEzjw2nqW5+TdEiLUvC2Il5SJ0J8hOk6hU3jLsGGdb35v6EQOAzM1 IbQQVcEa7i/1as0+WAqk1bnWNxs79uNrNojNY3xNrv+gLkdEC3YDvsga/ml2VyuXLohz LcebDmKErDohHf/74LLUVQxIDKcDa2vVpp+u+eX5clfV2H/AjD16xVFbeFd5Bdfhq8g6 J5NZpULtHwSrgBDACl0VpB3e5mM6YWUOdL3fIn6JswN+D6It7NhXnmvMHOzDV5Z7uRqL Joig== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of keith.busch@intel.com designates 192.55.52.43 as permitted sender) smtp.mailfrom=keith.busch@intel.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from mga05.intel.com (mga05.intel.com. [192.55.52.43]) by mx.google.com with ESMTPS id i1si11402278pfj.276.2018.12.10.17.05.52 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 10 Dec 2018 17:05:52 -0800 (PST) Received-SPF: pass (google.com: domain of keith.busch@intel.com designates 192.55.52.43 as permitted sender) client-ip=192.55.52.43; Authentication-Results: mx.google.com; spf=pass (google.com: domain of keith.busch@intel.com designates 192.55.52.43 as permitted sender) smtp.mailfrom=keith.busch@intel.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 10 Dec 2018 17:05:52 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.56,340,1539673200"; d="scan'208";a="117705208" Received: from unknown (HELO localhost.lm.intel.com) ([10.232.112.69]) by orsmga001.jf.intel.com with ESMTP; 10 Dec 2018 17:05:51 -0800 From: Keith Busch To: linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, linux-mm@kvack.org Cc: Greg Kroah-Hartman , Rafael Wysocki , Dave Hansen , Dan Williams , Keith Busch Subject: [PATCHv2 09/12] node: Add memory caching attributes Date: Mon, 10 Dec 2018 18:03:07 -0700 Message-Id: <20181211010310.8551-10-keith.busch@intel.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20181211010310.8551-1-keith.busch@intel.com> References: <20181211010310.8551-1-keith.busch@intel.com> X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: X-Virus-Scanned: ClamAV using ClamSMTP System memory may have side caches to help improve access speed. While the system provided cache is transparent to the software accessing these memory ranges, applications can optimize their own access based on cache attributes. Provide a new API for the kernel to register these memory side caches under the memory node that provides it. The kernel's sysfs representation is modeled from the cpu cacheinfo attributes, as seen from /sys/devices/system/cpu/cpuX/side_cache/. Unlike CPU cacheinfo, though, the node cache level is reported from the view of the memory. A higher number is nearer to the CPU, while lower levels are closer to the backing memory. Also unlike CPU cache, it is assumed the system will handle flushing any dirty cached memory to the last level the memory on a power failure if the range is persistent memory. The attributes we export are the cache size, the line size, associativity, and write back policy. Signed-off-by: Keith Busch --- drivers/base/node.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/node.h | 23 +++++++++ 2 files changed, 163 insertions(+) diff --git a/drivers/base/node.c b/drivers/base/node.c index 768612c06c56..54184424ca7f 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -141,6 +142,143 @@ void node_set_perf_attrs(unsigned int nid, struct node_hmem_attrs *hmem_attrs) pr_info("failed to add performance attribute group to node %d\n", nid); } + +struct node_cache_info { + struct device dev; + struct list_head node; + struct node_cache_attrs cache_attrs; +}; +#define to_cache_info(device) container_of(device, struct node_cache_info, dev) + +#define CACHE_ATTR(name, fmt) \ +static ssize_t name##_show(struct device *dev, \ + struct device_attribute *attr, \ + char *buf) \ +{ \ + return sprintf(buf, fmt "\n", to_cache_info(dev)->cache_attrs.name); \ +} \ +DEVICE_ATTR_RO(name); + +CACHE_ATTR(size, "%lld") +CACHE_ATTR(level, "%d") +CACHE_ATTR(line_size, "%d") +CACHE_ATTR(associativity, "%d") +CACHE_ATTR(write_policy, "%d") + +static struct attribute *cache_attrs[] = { + &dev_attr_level.attr, + &dev_attr_associativity.attr, + &dev_attr_size.attr, + &dev_attr_line_size.attr, + &dev_attr_write_policy.attr, + NULL, +}; + +const struct attribute_group node_cache_attrs_group = { + .attrs = cache_attrs, +}; + +const struct attribute_group *node_cache_attrs_groups[] = { + &node_cache_attrs_group, + NULL, +}; + +static void node_release(struct device *dev) +{ + kfree(dev); +} + +static void node_cache_release(struct device *dev) +{ + struct node_cache_info *info = to_cache_info(dev); + kfree(info); +} + +static void node_init_cache_dev(struct node *node) +{ + struct device *dev; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return; + + dev->parent = &node->dev; + dev->release = node_release; + dev_set_name(dev, "side_cache"); + + if (device_register(dev)) { + kfree(dev); + return; + } + pm_runtime_no_callbacks(dev); + node->cache_dev = dev; +} + +void node_add_cache(unsigned int nid, struct node_cache_attrs *cache_attrs) +{ + struct node_cache_info *info; + struct device *dev; + struct node *node; + + if (!node_online(nid) || !node_devices[nid]) + return; + + node = node_devices[nid]; + list_for_each_entry(info, &node->cache_attrs, node) { + if (info->cache_attrs.level == cache_attrs->level) { + dev_warn(&node->dev, + "attempt to add duplicate cache level:%d\n", + cache_attrs->level); + return; + } + } + + if (!node->cache_dev) + node_init_cache_dev(node); + if (!node->cache_dev) + return; + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return; + + dev = &info->dev; + dev->parent = node->cache_dev; + dev->release = node_cache_release; + dev->groups = node_cache_attrs_groups; + dev_set_name(dev, "index%d", cache_attrs->level); + info->cache_attrs = *cache_attrs; + if (device_register(dev)) { + dev_warn(&node->dev, "failed to add cache level:%d\n", + cache_attrs->level); + kfree(info); + return; + } + pm_runtime_no_callbacks(dev); + list_add_tail(&info->node, &node->cache_attrs); +} + +static void node_remove_caches(struct node *node) +{ + struct node_cache_info *info, *next; + + if (!node->cache_dev) + return; + + list_for_each_entry_safe(info, next, &node->cache_attrs, node) { + list_del(&info->node); + device_unregister(&info->dev); + } + device_unregister(node->cache_dev); +} + +static void node_init_caches(unsigned int nid) +{ + INIT_LIST_HEAD(&node_devices[nid]->cache_attrs); +} +#else +static void node_init_caches(unsigned int nid) { } +static void node_remove_caches(struct node *node) { } #endif #define K(x) ((x) << (PAGE_SHIFT - 10)) @@ -389,6 +527,7 @@ static void node_device_release(struct device *dev) */ flush_work(&node->node_work); #endif + node_remove_caches(node); kfree(node); } @@ -711,6 +850,7 @@ int __register_one_node(int nid) /* initialize work queue for memory hot plug */ init_node_hugetlb_work(nid); + node_init_caches(nid); return error; } diff --git a/include/linux/node.h b/include/linux/node.h index 71abaf0d4f4b..897e04e99e80 100644 --- a/include/linux/node.h +++ b/include/linux/node.h @@ -36,6 +36,27 @@ struct node_hmem_attrs { unsigned int write_latency; }; void node_set_perf_attrs(unsigned int nid, struct node_hmem_attrs *hmem_attrs); + +enum cache_associativity { + NODE_CACHE_DIRECT_MAP, + NODE_CACHE_INDEXED, + NODE_CACHE_OTHER, +}; + +enum cache_write_policy { + NODE_CACHE_WRITE_BACK, + NODE_CACHE_WRITE_THROUGH, + NODE_CACHE_WRITE_OTHER, +}; + +struct node_cache_attrs { + enum cache_associativity associativity; + enum cache_write_policy write_policy; + u64 size; + u16 line_size; + u8 level; +}; +void node_add_cache(unsigned int nid, struct node_cache_attrs *cache_attrs); #endif struct node { @@ -48,6 +69,8 @@ struct node { #endif #ifdef CONFIG_HMEM_REPORTING struct node_hmem_attrs hmem_attrs; + struct list_head cache_attrs; + struct device *cache_dev; #endif };