From mboxrd@z Thu Jan 1 00:00:00 1970 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 22A2AC369C2 for ; Sun, 20 Apr 2025 19:40:59 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 76E086B0026; Sun, 20 Apr 2025 15:40:47 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 6A9E86B0027; Sun, 20 Apr 2025 15:40:47 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 521FC6B0028; Sun, 20 Apr 2025 15:40:47 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0017.hostedemail.com [216.40.44.17]) by kanga.kvack.org (Postfix) with ESMTP id 376376B0026 for ; Sun, 20 Apr 2025 15:40:47 -0400 (EDT) Received: from smtpin24.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id 5D2048083F for ; Sun, 20 Apr 2025 19:40:47 +0000 (UTC) X-FDA: 83355439734.24.42A083B Received: from tor.source.kernel.org (tor.source.kernel.org [172.105.4.254]) by imf02.hostedemail.com (Postfix) with ESMTP id BE13980008 for ; Sun, 20 Apr 2025 19:40:45 +0000 (UTC) Authentication-Results: imf02.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=YhGGabv2; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf02.hostedemail.com: domain of sj@kernel.org designates 172.105.4.254 as permitted sender) smtp.mailfrom=sj@kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1745178045; a=rsa-sha256; cv=none; b=xR6SiMupXVCZpSc8ZYvwVGZbrW6b9yhjA9Wc4HQwSkPZzlL9ObVEO6CU87JkGF+GApnzmr M1tJIlsCfjrIyCYbEKwPwBx95Miewhdw6EZ44oTOUP+wMe6wqkbxUotxOOJay+7UXN33y+ J/yCDYGZynwgvV0rH1haZ7DtpWG9Z8k= ARC-Authentication-Results: i=1; imf02.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=YhGGabv2; dmarc=pass (policy=quarantine) header.from=kernel.org; spf=pass (imf02.hostedemail.com: domain of sj@kernel.org designates 172.105.4.254 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=1745178045; 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=Kd8Yn5kjNDo0tXioqXQ9OaxZ8G+oKO2Nm8s95ra7qAk=; b=3Hx4SpI/mEaf4dV8aLbPhnpeC7/6Dn2DuYOCHosREnXFTQ3V7d5ZQ10A4MuRqPB8ebcELU FgqrSas72S3FAOEt6CqaIr1aV4MEpYubSKZbuyCiIpBAzzDUYCceY/y0Kcw7DYOoICx+aA ErR36+0LZ/1ITT+L1gQHBNveSj8cEik= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by tor.source.kernel.org (Postfix) with ESMTP id 8837468431; Sun, 20 Apr 2025 19:40:26 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id C2FE0C4CEE9; Sun, 20 Apr 2025 19:40:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1745178045; bh=edQP+KhuArJze7tr3pDlMhuWrs27WlBNlib9Ik5OOrE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YhGGabv2M2JUAiqhb4gaJbHZgrumRy5ZbjCF1j5VoSRJm2Y0zt5bvDcDCYMd1IPef J5/pZeuxMtxo3EZ4YuLqOyARZC0jQKfUlk1Msh5b10JDMw1MS///7VbAX+bYE/fUdC wvSfjyJQUMOgz/ODgJ1YUPHubIVktA6ig5cSySmvqp4SPW4y6/VpXtzH3waeBrLGbV uJu6DsEu1MlsEx5TIang2rIGG8AMtFbjbve62ci8QcA8wJOnWzJTJXebizCsK9rRxo PacxSgFv0P6jAEJdvaU8txIcwEFmFzlrtN7wJ4rmxCqo1JKDe8MdwEnws4S8f1G8t/ ubUD6m20BXi3Q== From: SeongJae Park To: Andrew Morton Cc: SeongJae Park , damon@lists.linux.dev, kernel-team@meta.com, linux-kernel@vger.kernel.org, linux-mm@kvack.org Subject: [PATCH 7/7] samples/damon: implement a DAMON module for memory tiering Date: Sun, 20 Apr 2025 12:40:30 -0700 Message-Id: <20250420194030.75838-8-sj@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250420194030.75838-1-sj@kernel.org> References: <20250420194030.75838-1-sj@kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Rspamd-Server: rspam03 X-Rspamd-Queue-Id: BE13980008 X-Stat-Signature: opja6mp9ypi5h1gbmwgfd898tjcfkn7a X-Rspam-User: X-HE-Tag: 1745178045-656187 X-HE-Meta: U2FsdGVkX1+tgnfGYWXvh7+dbeAsC+h4vAAsAkGDzCo4XznHdFPPlmF5eYGf0TpxoQxADpvVE/6bJf2TuxWItheg/iu/z8kIt+u9+wIDNmj2/cIKiQjxOdTJvIhOP8xHm966AW2wfiR6A4Ve3hKKLKXtBuZ4aht4vIJgAf+2hYBD0kEy17Wcyh5aWTdBU/JIkXyqo+erK0B6/jEYuB2l9BhtTHgNtBV3jztYnuFPBlNdA7jaPq9Hm9ft5/XfxWykEUI9Nq8FuUlDt2H3dJZ9zmP8vfIpW0fVMRVcQSGr/rzmIJfQcPe6ymoLghlHQMkeRX7nBAtQGboGwt8RiMAdcheUJzHYODxHfVcb2LRAB3puSLTRRZX7Bs7/CMoFYuJB/wBpNYtcYT5n8L6aFoAWU1H2ooGZ8Dq8W15eqAfJWvP+NX0JvMYwMhTEnsIc3+XIsWwZnGcRZ/CHttijIZw0KP7BOBJ7jUOq/fMCUvi8zd96qRjKia/m4CYHZBsnJwEmRD5/AnS+f63Jp4JI8CurqIzpTwn/J0skGAeSyfMU590Gx6opnuw0UK//K2TBGEKbAphYlqHsLz7PmrNTw6rFe7hHOYgKJAArjoyd7OfzV/Wn7EZpP4fX1/cH61heGl50ez83F/GOxaQUWAGARvzkOU+cyu89aW2nNR30FLoLRksvEfGjzr1uVNJzUruhGN5Zg3QE7iyhuCKUuByqKfSIzlPHJMlnZ3b833SpvPMDD7w6NwMSMhpR/N8slGNOMMeewmEbfKMH4Y6mOh/BHh5uoWuFhsVYBX7cpcZhm3jLcxtdF4JAnX6cNUpP9jRqARasc/gNenLuGrZSS+4QCnaxtmoG+pTpqxurgRhPWhuoVbXmsg9y90dbI67lgPOZTm3ONjEU6GadWvFgdQi/QORLkfHF1iQFqhqkHaFQk0eYudtwM5tOSp3z4Han47hODlnOrvCEdMKiblZRkFj/yYq WsSvKjVg gQaqrFj8EUDAYuJ6ntnQL/yc2vIjQZZAMpvPDiFZP6KHTWAYcgGW7GzrZJ4Yzo4b3yqLBmdJL2VX6jvIgTxBMCPOEUksnOnAuowv4SBorzZRYTsoXNfBD87/Zq21zjgLQgxlO1kOXc2s8hxBFLpBs8nBgb7u+xhjmCAn3YCWiv5RDBUfY5SWbaMv5He1SOvaUx+hDjnWuEAEwZMndLpB4bYN1wvDnu8dtYrcTho8NtLN8IeU= 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 give an idea about how it can be implemented and perform, rather than be used on general production setups. Especially, it supports only two tiers memory setup having only one CPU-attached NUMA node. 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); -- 2.39.5