From patchwork Thu Mar 20 05:39:37 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: SeongJae Park X-Patchwork-Id: 14023453 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id E3D74C28B30 for ; Thu, 20 Mar 2025 05:39:56 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id C0446280007; Thu, 20 Mar 2025 01:39:50 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id B60CF280004; Thu, 20 Mar 2025 01:39:50 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 9B7CB280007; Thu, 20 Mar 2025 01:39:50 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0015.hostedemail.com [216.40.44.15]) by kanga.kvack.org (Postfix) with ESMTP id 6DC2A280004 for ; Thu, 20 Mar 2025 01:39:50 -0400 (EDT) Received: from smtpin20.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id 5D8B9AA92B for ; Thu, 20 Mar 2025 05:39:51 +0000 (UTC) X-FDA: 83240827782.20.76E6ECB Received: from sea.source.kernel.org (sea.source.kernel.org [172.234.252.31]) by imf26.hostedemail.com (Postfix) with ESMTP id A12D214000B for ; Thu, 20 Mar 2025 05:39:49 +0000 (UTC) Authentication-Results: imf26.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=LilgjRVh; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf26.hostedemail.com: domain of sj@kernel.org designates 172.234.252.31 as permitted sender) smtp.mailfrom=sj@kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1742449189; a=rsa-sha256; cv=none; b=gmkoIlTGLXJsBBnBPhYmvM/of7oU54SeJVIp45POeveN0AfvYHtbRzmwJ7db/4qYpWSCrg 2LhXc1FkeFV3RTrDrCb57KpZWp0CDPTTgqVjpotsMcqrBhM2Np41zAAGKj4S7eIQf8cn6n HG+iFYYmtdI7NjLe+R3Pt2a9HKxfz1c= ARC-Authentication-Results: i=1; imf26.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=LilgjRVh; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf26.hostedemail.com: domain of sj@kernel.org designates 172.234.252.31 as permitted sender) smtp.mailfrom=sj@kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1742449189; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=vuv0OhORYu/of6BSIAmiI7Qh3ttGQoHiIwJSqXYJ70E=; b=DSHemM0JZUx1gC/aSZXlMwlvdTZOKINwziS1AjxL9jSUH3gxC57dbYZl8pgko69O/VXwF7 zd6oM/QZzLrtAPpSgXr0ZMxu113aPsTa/nYW24dCz4dXdnADLIG0C/vDvlv5sIviGCwIKg AVOURmbCcgKkdLXrJoSQAT6hPKxHv60= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sea.source.kernel.org (Postfix) with ESMTP id 379FA43AB7; Thu, 20 Mar 2025 05:39:48 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 58F54C4CEEC; Thu, 20 Mar 2025 05:39:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1742449188; bh=Y3dAxBX8HTBcmXTfevqW10FoZFkNzFdE4brVy2x1Zu4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=LilgjRVhZdDVtaHBAl9itceBOPwxnAvSmvhS6PZXVbHgxEzIcjHc4vFP7D0GiZrVO +LZ9eFcFZ/zRtvsBixms6OOo2kwhSGNd3TehNj5kvsNyHby1iHdHPgGg9FU6d7i43b wVYX8eTWHtL/vQNl9spze8dsiAbz34eISctHWv+eCE2IWCtymRxUtGDkO4kHLlVM9J WgOSsB9D4oCG+4RtWDoHMPL4a5lqG7BlCMullmYhfZQpZtudLBT9BR02Ld76zjGoRw yjRsO2Ua0C8AelEeCJvdgcl8A2h5PAbM1sxtAxDrYrS5yLSiutkfqa4XnchIY+Fp3d KqvZC0/4zxFSQ== From: SeongJae Park To: Cc: SeongJae Park , damon@lists.linux.dev, kernel-team@meta.com, linux-kernel@vger.kernel.org, linux-mm@kvack.org Subject: [RFC PATCH 4/4] samples/damon: implement a DAMON module for memory tiering Date: Wed, 19 Mar 2025 22:39:37 -0700 Message-Id: <20250320053937.57734-5-sj@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250320053937.57734-1-sj@kernel.org> References: <20250320053937.57734-1-sj@kernel.org> MIME-Version: 1.0 X-Rspamd-Server: rspam07 X-Rspam-User: X-Stat-Signature: baof9qmqqcu4axiqc795jb6ubf7dctua X-Rspamd-Queue-Id: A12D214000B X-HE-Tag: 1742449189-878553 X-HE-Meta: U2FsdGVkX19rEf4PAy/AFuHWLIOeHikD/yKVxmD7zkRorW3U+p1/KchVL8lQVJgb2HkJkNvcpnKG6uIK2iHV+XcLRc9XSoOAFVvKMqTFpYbrusfhgkUvwLnHyqUnmidXwhtGynrA1Ecbc4LGM3DIO3EjqdBmW4wlA5Z7Z6GEOI2oZ+vyXQsnsbMOnMDsLlNX0A2xlacE7o0lrWnpyXlcZzuo5GRWdxNrbtyu07MTlyMX3v6PjiGGxBja8gn2IMQ7hgkGNbsk8CGpiJbTHNpLH9u0jUHI6/Ga1J6gRudgsvSLkkMIC7xgTSuLBaJHrGr0+QQyzR/UOez7WWWGk10iFbs8OfaK6fjwRe4Hc4jpsEXZag47jxh4yoIT/GE1eJya5w2k0D3wC+bwUIyzhyU6NE2jwELbUNKbfoi+kQ4LNWmXnmp/eIsGhclUgNqvlokBPCYpz4UiL0Wz4h/Y9jVD27jlQ6yq43H4t4ztuFk479N4zoMYUOe2lnppRYB1IScdFVM/vhtQVqpctS57UL/Pptko9vHPexhqJQnZ9j9WGGpWCk4TOPKOGJssnY7RMFrUUMZHnKh9APcL8khcSLk7bsbQ/EJEUv6qJAl7Fe+6LfKkwTX8+cAgWG1D/Y9BrL1N/l1gl4wY8ogB5gOOQ+yYrsMyZiMKolgUk90YWEoRSoJlYNI1kD2LXJblmAEXOKzkCb4IWV6TB+rV7Wb6O7NFa2+Kz0b/XGSJ3DoiHm9hFZt2zU2unqHoMJDT2TlwVmK72TFHuIsP0Y8cyhi2tKKgeWRnM8PaR52cQyFT6zQY1kx/pAHGf5ZhKDeUZ54LOSWFuVjFB31ohxJ0ZsD7E1Cb+9iz8dQjU+DJ+RgdPBi/0lY3Ka2XXAyywSxGFDyzBG+EwlQiPGTwbzxHi+Eda4nK39wDANUCJC3lFJQPfK+Qk8A8golQ3EH64YhjNWX0UmG4+kuyluH7y0lR5hjSFco Q/JRvDN/ Krcqo5RVOMCmIHYwgwKY+ZuPKhgwriGnVWEOhblGQmYe3E/LEtmSmaGwOYyEUrOxS71I5kFhqdIuJgs/nauo8fzo+Y66p0cRjjzkbSDTA6Bpa34LFDk1aDlZZgsS7Gnv1c+WhW/wczLU9WRg/+eAajA1hxQuvti8qwTHjP0xqt/HCPTZTTNw0T9xx9kLcOJQaD2Fg4cKuUmHHxtugcM4GQbW4CRCIiB5reR8g7yeTa4vAJqE= 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: List-Subscribe: List-Unsubscribe: Implement a sample DAMON module that shows how self-tuned DAMON-based memory tiering can be written. It is a sample since the purpose is to gives an idea about how it can be implemented, rather than be used as is. Especially, the production purpose module would need to find memory tiers and set the scheme target address ranges automatically. Signed-off-by: SeongJae Park --- samples/damon/Kconfig | 13 ++++ samples/damon/Makefile | 1 + samples/damon/mtier.c | 167 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 181 insertions(+) create mode 100644 samples/damon/mtier.c diff --git a/samples/damon/Kconfig b/samples/damon/Kconfig index 564c49ed69a2..cbf96fd8a8bf 100644 --- a/samples/damon/Kconfig +++ b/samples/damon/Kconfig @@ -27,4 +27,17 @@ config SAMPLE_DAMON_PRCL If unsure, say N. +config SAMPLE_DAMON_MTIER + bool "DAMON sample module for memory tiering" + depends on DAMON && DAMON_PADDR + help + Thps builds DAMON sample module for memory tierign. + + The module assumes the system is constructed with two NUMA nodes, + which seems as local and remote nodes to all CPUs. For example, + node0 is for DDR5 DRAMs connected via DIMM, while node1 is for DDR4 + DRAMs connected via CXL. + + If unsure, say N. + endmenu diff --git a/samples/damon/Makefile b/samples/damon/Makefile index 7f155143f237..72f68cbf422a 100644 --- a/samples/damon/Makefile +++ b/samples/damon/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_SAMPLE_DAMON_WSSE) += wsse.o obj-$(CONFIG_SAMPLE_DAMON_PRCL) += prcl.o +obj-$(CONFIG_SAMPLE_DAMON_MTIER) += mtier.o diff --git a/samples/damon/mtier.c b/samples/damon/mtier.c new file mode 100644 index 000000000000..3390b7d30c26 --- /dev/null +++ b/samples/damon/mtier.c @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * memory tiering: migrate cold pages in node 0 and hot pages in node 1 to node + * 1 and node 0, respectively. Adjust the hotness/coldness threshold aiming + * resulting 99.6 % node 0 utilization ratio. + */ + +#define pr_fmt(fmt) "damon_sample_mtier: " fmt + +#include +#include +#include +#include + +static unsigned long node0_start_addr __read_mostly; +module_param(node0_start_addr, ulong, 0600); + +static unsigned long node0_end_addr __read_mostly; +module_param(node0_end_addr, ulong, 0600); + +static unsigned long node1_start_addr __read_mostly; +module_param(node1_start_addr, ulong, 0600); + +static unsigned long node1_end_addr __read_mostly; +module_param(node1_end_addr, ulong, 0600); + +static int damon_sample_mtier_enable_store( + const char *val, const struct kernel_param *kp); + +static const struct kernel_param_ops enable_param_ops = { + .set = damon_sample_mtier_enable_store, + .get = param_get_bool, +}; + +static bool enable __read_mostly; +module_param_cb(enable, &enable_param_ops, &enable, 0600); +MODULE_PARM_DESC(enable, "Enable of disable DAMON_SAMPLE_MTIER"); + +static struct damon_ctx *ctxs[2]; + +static struct damon_ctx *damon_sample_mtier_build_ctx(bool promote) +{ + struct damon_ctx *ctx; + struct damon_target *target; + struct damon_region *region; + struct damos *scheme; + struct damos_quota_goal *quota_goal; + struct damos_filter *filter; + + ctx = damon_new_ctx(); + if (!ctx) + return NULL; + /* + * auto-tune sampling and aggregation interval aiming 4% DAMON-observed + * accesses ratio, keeping sampling interval in [5ms, 10s] range. + */ + ctx->attrs.intervals_goal = (struct damon_intervals_goal) { + .access_bp = 400, .aggrs = 3, + .min_sample_us = 5000, .max_sample_us = 10000000, + }; + if (damon_select_ops(ctx, DAMON_OPS_PADDR)) + goto free_out; + + target = damon_new_target(); + if (!target) + goto free_out; + damon_add_target(ctx, target); + region = damon_new_region( + promote ? node1_start_addr : node0_start_addr, + promote ? node1_end_addr : node0_end_addr); + if (!region) + goto free_out; + damon_add_region(region, target); + + scheme = damon_new_scheme( + /* access pattern */ + &(struct damos_access_pattern) { + .min_sz_region = PAGE_SIZE, + .max_sz_region = ULONG_MAX, + .min_nr_accesses = promote ? 1 : 0, + .max_nr_accesses = promote ? UINT_MAX : 0, + .min_age_region = 0, + .max_age_region = UINT_MAX}, + /* action */ + promote ? DAMOS_MIGRATE_HOT : DAMOS_MIGRATE_COLD, + 1000000, /* apply interval (1s) */ + &(struct damos_quota){ + /* 200 MiB per sec by most */ + .reset_interval = 1000, + .sz = 200 * 1024 * 1024, + /* ignore size of region when prioritizing */ + .weight_sz = 0, + .weight_nr_accesses = 100, + .weight_age = 100, + }, + &(struct damos_watermarks){}, + promote ? 0 : 1); /* migrate target node id */ + if (!scheme) + goto free_out; + damon_set_schemes(ctx, &scheme, 1); + quota_goal = damos_new_quota_goal( + promote ? DAMOS_QUOTA_NODE_MEM_USED_BP : + DAMOS_QUOTA_NODE_MEM_FREE_BP, + promote ? 9970 : 50); + if (!quota_goal) + goto free_out; + quota_goal->nid = 0; + damos_add_quota_goal(&scheme->quota, quota_goal); + filter = damos_new_filter(DAMOS_FILTER_TYPE_YOUNG, true, promote); + if (!filter) + goto free_out; + damos_add_filter(scheme, filter); + return ctx; +free_out: + damon_destroy_ctx(ctx); + return NULL; +} + +static int damon_sample_mtier_start(void) +{ + struct damon_ctx *ctx; + + ctx = damon_sample_mtier_build_ctx(true); + if (!ctx) + return -ENOMEM; + ctxs[0] = ctx; + ctx = damon_sample_mtier_build_ctx(false); + if (!ctx) { + damon_destroy_ctx(ctxs[0]); + return -ENOMEM; + } + ctxs[1] = ctx; + return damon_start(ctxs, 2, true); +} + +static void damon_sample_mtier_stop(void) +{ + damon_stop(ctxs, 2); + damon_destroy_ctx(ctxs[0]); + damon_destroy_ctx(ctxs[1]); +} + +static int damon_sample_mtier_enable_store( + const char *val, const struct kernel_param *kp) +{ + bool enabled = enable; + int err; + + err = kstrtobool(val, &enable); + if (err) + return err; + + if (enable == enabled) + return 0; + + if (enable) + return damon_sample_mtier_start(); + damon_sample_mtier_stop(); + return 0; +} + +static int __init damon_sample_mtier_init(void) +{ + return 0; +} + +module_init(damon_sample_mtier_init);