From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-ot1-f41.google.com (mail-ot1-f41.google.com [209.85.210.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A934833D6E1 for ; Thu, 23 Apr 2026 20:34:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.41 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776976492; cv=none; b=MKoViNmz6kvla+f5P/mxsncZZ9u8K3O0cM+nFm+DufMIISP+8++qpHkEG5et7GuPFBov+5N77q4gFUaq9BaR/lU3pyhKmUVadKm57KjeQ6m6zVnLD+HQOwhx6B0yGdcTEhKhjbHac+pphGnMOJZhuWiWVwODe3jLx8IerPe5UXg= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776976492; c=relaxed/simple; bh=d3NfjxKJKnmjOlirCDp9bag4Xf0ihYUqzIbZOP4xA14=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UHK1YcNdpKKzqq8QxjigFJrLKIPIh3HqJhErMSZqqMptN5euJ62ZpNS42d9cwxU5B2Ns3VoyvaiDJr6VECAQQz3LRbdHabY1EZySNWHwVyHexWYt+xrIKLzZyXRRelk6d92OvWNNwA/knfHq8ScIbVMJEbrLK0FH3Tbf0sU/TuA= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=gt8ZKoB4; arc=none smtp.client-ip=209.85.210.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="gt8ZKoB4" Received: by mail-ot1-f41.google.com with SMTP id 46e09a7af769-7de4a9cb8eeso1113864a34.0 for ; Thu, 23 Apr 2026 13:34:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776976489; x=1777581289; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=/Sc+ZsDjiZEjytSKxuIVGQ3PUb0Eu41iRMSui9hW2VQ=; b=gt8ZKoB423MNdjBgXh8+SG5CEitH1yT4UmjImBzOG58PswWZ0Ty9+8OHyUC6qrugcZ 9URtzFoAoY5gCv+NJxtTS2hhCzKTJeNY8b/3zdVR5/6lCMt7cvZJR4ZZw6JvzZOs5f59 giapSFMnCVS1qmEqJWBs4sC6q51F0d+X9rvQxkZBv2fJaEJDfSLIoGZTVULghNSHlAbe jy1C1FP55WDy6ASPVxyxTmXJtV5ET58thB6vdlI6/kporIhBcpSF51KEVTtj/KBvMyPr PMtNXcQeJHcnVOw2zG11W0sSEfo46ivS4uNbZrg8zi53nZT93neyAyimAfSUQHFv22xn QcfA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776976489; x=1777581289; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=/Sc+ZsDjiZEjytSKxuIVGQ3PUb0Eu41iRMSui9hW2VQ=; b=ZoNeJdBS9wMoI/bkiAkteXpyEc6VgtE3XL9jS5/XgRi7f7ILuxYhvPC17kNmXHe9fG Ue5Q26aTnHFjY2Krx22LuNpa34bEwiG8RlYJyBNogAk2uR48VVqg6RzXsB7Kebxs6Kbi lIMxctHWzZU8KfHcOnzpqsBUtA8UEWO14tGheqfVL/amuiB4UkP+0/7Dnq3AwTM3sbds m3QULVC7cFqIJlQjfZQGaFBypO4n8+fCEHxCV8R+zMNTSyhtPWJE/fZcMF/xwtnoirFU TGMe8QyjEy3hgVBC2FbQzZvTei2/crdmvKumTPFtY3dbucHvtvLrlpqlHaoXKTCREQ2R xelw== X-Forwarded-Encrypted: i=1; AFNElJ/vPqlZkN7fu+9EUidxXyNnog+VD95b6COwnr/ofjFBFZZ7UzEfLQEqUsNY6B5uv94QHDOvDpcmACWBBsI=@vger.kernel.org X-Gm-Message-State: AOJu0YwH2J4oy+h6HzleBWZ5xc+fTlECm8tFOSyXguJK8MsNWXbFJ9tn ZrtdC/bCRRmkvTb0YzLm2pU1ayfgv3KqWjdeRi2GnOpfRqWZR55PgnEf X-Gm-Gg: AeBDiesMD4o7ecYotGvWr92jiF/90Rxxs0h0QC9zcDWbWffKBNYXfIlUEE5QaTnLDzA k36v0cdogjnU+cVLKwKMi4kcZHQoX9ThrUmTdDij1xrFJ7DRJ+w+HQKGkBXmb4uSuBBImbTSiMn 9z8UEcvQnL4NIsFrMHHSrOrToNJYuprqZNYwnYU3XeiHctRExQfZ249z2yllPIGvAEPJTYB0oQV q8Nh3CyXVaiYVWsuI9N68Sd/iQi8Nnn8zSgquWQ35/CbywQ91fDkvQ3vqKwbqWMOHLx/WjhmtVP eqNXvO4zuzpyXVhe2rll/eNZeWlyBvHKJVIg7PQxl4O5Q2AlUR+8M7xKkBY+C5xT3JgQostfs4E I7bNEegw9sFx4I/5VRf0yvieS6eSQwciYAJjApkD/DAdHwU18tvVv99i98L7uEYxj/IlWi4uw0p +N7mGShuPY7IOvCTFknCbD7dQHbYmXheU= X-Received: by 2002:a05:6830:6a91:b0:7d9:d2b6:1568 with SMTP id 46e09a7af769-7dc9518bb34mr18578777a34.17.1776976489633; Thu, 23 Apr 2026 13:34:49 -0700 (PDT) Received: from localhost ([2a03:2880:10ff:5::]) by smtp.gmail.com with ESMTPSA id 46e09a7af769-7dc975034e7sm17408211a34.6.2026.04.23.13.34.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Apr 2026 13:34:49 -0700 (PDT) From: Joshua Hahn To: linux-mm@kvack.org Cc: Andrew Morton , David Hildenbrand , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , linux-kernel@vger.kernel.org, kernel-team@meta.com Subject: [RFC PATCH 2/9 v2] mm/memory-tiers: Introduce toptier utility functions Date: Thu, 23 Apr 2026 13:34:36 -0700 Message-ID: <20260423203445.2914963-3-joshua.hahnjy@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260423203445.2914963-1-joshua.hahnjy@gmail.com> References: <20260423203445.2914963-1-joshua.hahnjy@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit This patch introduces two toptier-related utility functions, get_toptier_nodemask() and mt_scale_by_toptier(). Tier aware limits will introduce new memcg thresholds on toptier nodes for systems with multiple memory tiers. To simplify the calculation for these new thresholds, introduce a function mt_scale_by_toptier to scale memory limits by the ratio of toptier capacity and total capacity available on the system. For single-node / single-tier systems, the scaling operation will be a no-op since capacity updates are hooked into establish_demotion_targets. Note that the ratio is static for the entire system. Explicitly, it does not take cgroups' cpuset.mems into consideration, meaning even cgroups limited to toptier nodes only will still get a scaled down toptier limit. This is to ensure that all cgroups are limited to their fair share of toptier memory, regardless of what nodes they are restricted to. This also has the added benefit of preventing accidental /unintentional overcommitting of toptier memory, since every cgroup shares the same toptier ratio. get_toptier_nodemask() extends the existing node_is_toptier check to return a nodemask of all N_MEMORY nodes living on toptier. For !CONFIG_NUMA_MIGRATION or !CONFIG_NUMA systems, it will just return all N_MEMORY nodes. Signed-off-by: Joshua Hahn --- include/linux/memory-tiers.h | 17 ++++++++++++++++ mm/memory-tiers.c | 38 ++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/include/linux/memory-tiers.h b/include/linux/memory-tiers.h index 7999c58629eeb..f21525c50a5ff 100644 --- a/include/linux/memory-tiers.h +++ b/include/linux/memory-tiers.h @@ -52,10 +52,12 @@ int mt_perf_to_adistance(struct access_coordinate *perf, int *adist); struct memory_dev_type *mt_find_alloc_memory_type(int adist, struct list_head *memory_types); void mt_put_memory_types(struct list_head *memory_types); +unsigned long mt_scale_by_toptier(unsigned long val); #ifdef CONFIG_NUMA_MIGRATION int next_demotion_node(int node, const nodemask_t *allowed_mask); void node_get_allowed_targets(pg_data_t *pgdat, nodemask_t *targets); bool node_is_toptier(int node); +void get_toptier_nodemask(nodemask_t *mask); #else static inline int next_demotion_node(int node, const nodemask_t *allowed_mask) { @@ -71,6 +73,11 @@ static inline bool node_is_toptier(int node) { return true; } + +static inline void get_toptier_nodemask(nodemask_t *mask) +{ + *mask = node_states[N_MEMORY]; +} #endif #else @@ -116,6 +123,11 @@ static inline bool node_is_toptier(int node) return true; } +static inline void get_toptier_nodemask(nodemask_t *mask) +{ + *mask = node_states[N_MEMORY]; +} + static inline int register_mt_adistance_algorithm(struct notifier_block *nb) { return 0; @@ -151,5 +163,10 @@ static inline struct memory_dev_type *mt_find_alloc_memory_type(int adist, static inline void mt_put_memory_types(struct list_head *memory_types) { } + +static inline unsigned long mt_scale_by_toptier(unsigned long val) +{ + return val; +} #endif /* CONFIG_NUMA */ #endif /* _LINUX_MEMORY_TIERS_H */ diff --git a/mm/memory-tiers.c b/mm/memory-tiers.c index 54851d8a195b0..acc02679e312d 100644 --- a/mm/memory-tiers.c +++ b/mm/memory-tiers.c @@ -46,6 +46,8 @@ static struct node_memory_type_map node_memory_types[MAX_NUMNODES]; struct memory_dev_type *default_dram_type; nodemask_t default_dram_nodes __initdata = NODE_MASK_NONE; +static unsigned long toptier_capacity; + static const struct bus_type memory_tier_subsys = { .name = "memory_tiering", .dev_name = "memory_tier", @@ -299,6 +301,17 @@ bool node_is_toptier(int node) return toptier; } +void get_toptier_nodemask(nodemask_t *mask) +{ + int node; + + nodes_clear(*mask); + for_each_node_state(node, N_MEMORY) { + if (node_is_toptier(node)) + node_set(node, *mask); + } +} + void node_get_allowed_targets(pg_data_t *pgdat, nodemask_t *targets) { struct memory_tier *memtier; @@ -428,6 +441,7 @@ static void establish_demotion_targets(void) struct demotion_nodes *nd; int target = NUMA_NO_NODE, node; int distance, best_distance; + int i; nodemask_t tier_nodes, lower_tier; lockdep_assert_held_once(&memory_tier_lock); @@ -496,6 +510,19 @@ static void establish_demotion_targets(void) break; } } + + toptier_capacity = 0; + for_each_node_state(node, N_MEMORY) { + if (!node_is_toptier(node)) + continue; + + for (i = 0; i < MAX_NR_ZONES; i++) { + struct zone *z = &NODE_DATA(node)->node_zones[i]; + + toptier_capacity += zone_managed_pages(z); + } + } + /* * Now build the lower_tier mask for each node collecting node mask from * all memory tier below it. This allows us to fallback demotion page @@ -878,6 +905,16 @@ int mt_calc_adistance(int node, int *adist) } EXPORT_SYMBOL_GPL(mt_calc_adistance); +unsigned long mt_scale_by_toptier(unsigned long val) +{ + unsigned long total_capacity = totalram_pages(); + + if (!total_capacity) + return 0; + + return mult_frac(val, toptier_capacity, total_capacity); +} + static int __meminit memtier_hotplug_callback(struct notifier_block *self, unsigned long action, void *_arg) { @@ -932,6 +969,7 @@ static int __init memory_tier_init(void) node_states[N_CPU]); hotplug_node_notifier(memtier_hotplug_callback, MEMTIER_HOTPLUG_PRI); + toptier_capacity = totalram_pages(); return 0; } subsys_initcall(memory_tier_init); -- 2.52.0