From: Usama Arif <usama.arif@linux.dev>
To: Sourav Panda <souravpanda@google.com>
Cc: Usama Arif <usama.arif@linux.dev>,
muchun.song@linux.dev, osalvador@suse.de,
akpm@linux-foundation.org, david@kernel.org, surenb@google.com,
fvdl@google.com, gthelen@google.com, rientjes@google.com,
linux-mm@kvack.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2] mm/hugetlb_cma: support percentage-based hugetlb_cma reservation
Date: Tue, 30 Jun 2026 10:39:51 -0700 [thread overview]
Message-ID: <20260630173953.642186-1-usama.arif@linux.dev> (raw)
In-Reply-To: <20260628190155.3655895-1-souravpanda@google.com>
On Sun, 28 Jun 2026 19:01:55 +0000 Sourav Panda <souravpanda@google.com> wrote:
> Currently, hugetlb_cma reservation only supports absolute sizes (e.g.,
> hugetlb_cma=2G or hugetlb_cma=0:1G,1:1G). This can be restrictive in
> heterogeneous environments or when deploying common kernel command lines
> across machines with different memory capacities.
>
> Add support for percentage-based hugetlb_cma reservation (e.g.,
> hugetlb_cma=20% or hugetlb_cma=0:20%,1:10%).
>
> The percentage is calculated against the total memory (for global
> settings) or against the node-specific memory (for node-specific
> settings) using memblock APIs during early boot.
>
> Signed-off-by: Sourav Panda <souravpanda@google.com>
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202606262023.IKUrn01I-lkp@intel.com/
> ---
> Link: https://lore.kernel.org/linux-mm/20260625215900.2151690-1-souravpanda@google.com/ [v1]
>
> v2:
> - Use mul_u64_u32_div() instead of mult_frac() to avoid 64-bit division on 32-bit architectures (Reported by kernel test robot).
> - Fix physical memory size truncation on 32-bit PAE by using phys_addr_t in memblock_node_memory_size() (Sashiko).
> - Fix boot parameter override logic to respect standard last-one-wins precedence by clearing opposite values during parsing and clearing node-specific values when global values are parsed.
> .../admin-guide/kernel-parameters.txt | 7 +-
> mm/hugetlb_cma.c | 96 ++++++++++++++++++-
> 2 files changed, 97 insertions(+), 6 deletions(-)
>
> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index 5a05b48d1684..846940ce2858 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -2064,8 +2064,11 @@ Kernel parameters
> hugetlb_cma= [HW,CMA,EARLY] The size of a CMA area used for allocation
> of gigantic hugepages. Or using node format, the size
> of a CMA area per node can be specified.
> - Format: nn[KMGTPE] or (node format)
> - <node>:nn[KMGTPE][,<node>:nn[KMGTPE]]
> + The size can be an absolute value (e.g., 2G) or a
> + percentage of the total memory or node memory (e.g., 20%).
> + Format: nn[KMGTPE] or nn% or (node format)
> + <node>:nn[KMGTPE][,<node>:nn[KMGTPE]] or
> + <node>:nn%[,<node>:nn%]
>
> Reserve a CMA area of given size and allocate gigantic
> hugepages using the CMA allocator. If enabled, the
> diff --git a/mm/hugetlb_cma.c b/mm/hugetlb_cma.c
> index 7693ccefd0c6..684ffa3537d2 100644
> --- a/mm/hugetlb_cma.c
> +++ b/mm/hugetlb_cma.c
> @@ -9,6 +9,9 @@
> #include <asm/setup.h>
>
> #include <linux/hugetlb.h>
> +#include <linux/memblock.h>
> +#include <linux/math.h>
> +#include <linux/math64.h>
> #include "internal.h"
> #include "hugetlb_cma.h"
>
> @@ -18,6 +21,28 @@ static unsigned long hugetlb_cma_size_in_node[MAX_NUMNODES] __initdata;
> static bool hugetlb_cma_only __ro_after_init;
> static unsigned long hugetlb_cma_size __ro_after_init;
>
> +static unsigned int hugetlb_cma_percent __initdata;
> +static unsigned int hugetlb_cma_percent_in_node[MAX_NUMNODES] __initdata;
> +
> +#ifdef CONFIG_NUMA
> +static phys_addr_t __init memblock_node_memory_size(int nid)
> +{
> + struct memblock_region *reg;
> + phys_addr_t size = 0;
> +
> + for_each_mem_region(reg) {
> + if (reg->nid == nid)
> + size += reg->size;
> + }
> + return size;
> +}
> +#else
> +static phys_addr_t __init memblock_node_memory_size(int nid)
> +{
> + return memblock_phys_mem_size();
> +}
> +#endif
> +
> void hugetlb_cma_free_frozen_folio(struct folio *folio)
> {
> WARN_ON_ONCE(!cma_release_frozen(hugetlb_cma[folio_nid(folio)],
> @@ -100,14 +125,28 @@ static int __init cmdline_parse_hugetlb_cma(char *p)
> break;
>
> if (s[count] == ':') {
> + char *next;
> +
> if (tmp >= MAX_NUMNODES)
> break;
> nid = array_index_nospec(tmp, MAX_NUMNODES);
>
> s += count + 1;
> - tmp = memparse(s, &s);
> - hugetlb_cma_size_in_node[nid] = tmp;
> - hugetlb_cma_size += tmp;
> + tmp = memparse(s, &next);
> + if (*next == '%') {
> + if (tmp > 100) {
> + pr_warn("hugetlb_cma: invalid percentage %lu for node %d\n",
> + tmp, nid);
> + break;
> + }
> + hugetlb_cma_percent_in_node[nid] = tmp;
> + hugetlb_cma_size_in_node[nid] = 0;
> + s = next + 1;
> + } else {
> + hugetlb_cma_size_in_node[nid] = tmp;
> + hugetlb_cma_percent_in_node[nid] = 0;
> + s = next;
> + }
>
> /*
> * Skip the separator if have one, otherwise
> @@ -118,7 +157,28 @@ static int __init cmdline_parse_hugetlb_cma(char *p)
> else
> break;
> } else {
> - hugetlb_cma_size = memparse(p, &p);
> + char *next;
> +
> + tmp = memparse(p, &next);
> + if (*next == '%') {
> + if (tmp > 100) {
> + pr_warn("hugetlb_cma: invalid percentage %lu\n", tmp);
> + } else {
> + hugetlb_cma_percent = tmp;
> + hugetlb_cma_size = 0;
> + for (nid = 0; nid < MAX_NUMNODES; nid++) {
> + hugetlb_cma_size_in_node[nid] = 0;
> + hugetlb_cma_percent_in_node[nid] = 0;
> + }
> + }
> + } else {
> + hugetlb_cma_size = tmp;
> + hugetlb_cma_percent = 0;
> + for (nid = 0; nid < MAX_NUMNODES; nid++) {
> + hugetlb_cma_size_in_node[nid] = 0;
> + hugetlb_cma_percent_in_node[nid] = 0;
> + }
> + }
> break;
> }
> }
> @@ -144,8 +204,36 @@ void __init hugetlb_cma_reserve(void)
> {
> unsigned long size, reserved, per_node, order;
> bool node_specific_cma_alloc = false;
> + bool has_node_specific_param = false;
> int nid;
>
> + for (nid = 0; nid < MAX_NUMNODES; nid++) {
> + if (hugetlb_cma_size_in_node[nid] || hugetlb_cma_percent_in_node[nid]) {
> + has_node_specific_param = true;
> + break;
> + }
> + }
> +
> + if (has_node_specific_param) {
> + hugetlb_cma_size = 0;
> + for (nid = 0; nid < MAX_NUMNODES; nid++) {
> + if (hugetlb_cma_percent_in_node[nid]) {
> + phys_addr_t node_gfp_mem = memblock_node_memory_size(nid);
> + u64 s;
> +
> + s = mul_u64_u32_div((u64)node_gfp_mem,
> + hugetlb_cma_percent_in_node[nid],
> + 100);
> +
> + hugetlb_cma_size_in_node[nid] = s;
> + }
> + hugetlb_cma_size += hugetlb_cma_size_in_node[nid];
> + }
> + } else if (hugetlb_cma_percent) {
> + hugetlb_cma_size = mul_u64_u32_div((u64)memblock_phys_mem_size(),
> + hugetlb_cma_percent, 100);
> + }
> +
> if (!hugetlb_cma_size)
> return;
Can this round percentage-derived sizes to the gigantic page size before the
existing alignment checks run?
For example, on an x86_64 machine with 64 GiB of memory, hugetlb_cma=20%
computes 12.8 GiB. The later hugetlb_cma_reserve() alignment check requires
the total to be a multiple of the gigantic_page_size, so the documented 20%
example is rejected and the reservation is disabled?
>
> --
> 2.55.0.rc0.799.gd6f94ed593-goog
>
>
next prev parent reply other threads:[~2026-06-30 17:40 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-28 19:01 [PATCH v2] mm/hugetlb_cma: support percentage-based hugetlb_cma reservation Sourav Panda
2026-06-28 19:38 ` Andrew Morton
2026-06-28 19:42 ` Sourav Panda
2026-06-30 17:39 ` Usama Arif [this message]
2026-07-02 18:18 ` Sourav Panda
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260630173953.642186-1-usama.arif@linux.dev \
--to=usama.arif@linux.dev \
--cc=akpm@linux-foundation.org \
--cc=david@kernel.org \
--cc=fvdl@google.com \
--cc=gthelen@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=muchun.song@linux.dev \
--cc=osalvador@suse.de \
--cc=rientjes@google.com \
--cc=souravpanda@google.com \
--cc=surenb@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.