[PATCH v2 09/20] hugetlb_vmemmap: Allow architectures to make HVO enablement boot-time only

From: James Houghton

Date: Fri Oct 02 2026 - 20:24:34 EST


arm64 needs all CPUs to support hardware updates of the access flag to
safely update the vmemmap in place, and it will need to refuse to online
CPUs that lack it, but only if HVO may be used. This only works if HVO
cannot be dynamically enabled, otherwise incompatible CPUs may have
already been onlined at enable time.

Add CONFIG_ARCH_WANT_HUGETLB_VMEMMAP_RO_AFTER_INIT for architectures to
select. When selected, vmemmap_optimize_enabled is __ro_after_init, so
it can only be set with the hugetlb_free_vmemmap= kernel command line
parameter, and the sysctl is made read-only.

Signed-off-by: James Houghton <jthoughton@xxxxxxxxxx>
---
Documentation/admin-guide/sysctl/vm.rst | 3 +++
fs/Kconfig | 3 ++-
mm/Kconfig | 9 +++++++++
mm/hugetlb_vmemmap.c | 17 +++++++++++++++--
4 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/Documentation/admin-guide/sysctl/vm.rst b/Documentation/admin-guide/sysctl/vm.rst
index 5b318d17aa4b..d962d563cfd4 100644
--- a/Documentation/admin-guide/sysctl/vm.rst
+++ b/Documentation/admin-guide/sysctl/vm.rst
@@ -692,6 +692,9 @@ pages. So, those surplus pages are still optimized until they are no longer
in use. You would need to wait for those surplus pages to be released before
there are no optimized pages in the system.

+On some architectures, this knob is read-only, and HVO can only be enabled or
+disabled with the hugetlb_free_vmemmap= kernel command line parameter.
+

nr_hugepages_mempolicy
======================
diff --git a/fs/Kconfig b/fs/Kconfig
index 1454b7fe9641..4222db17ba02 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -267,7 +267,8 @@ config HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON
help
The HugeTLB Vmemmap Optimization (HVO) defaults to off. Say Y here to
enable HVO by default. It can be disabled via hugetlb_free_vmemmap=off
- (boot command line) or hugetlb_optimize_vmemmap (sysctl).
+ (boot command line) or hugetlb_optimize_vmemmap (sysctl, if the
+ architecture allows changing it at runtime).
endif # HUGETLBFS

config HUGETLB_PAGE
diff --git a/mm/Kconfig b/mm/Kconfig
index acefc994d9a8..ad313fddc9da 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -475,6 +475,15 @@ config ARCH_WANT_OPTIMIZE_DAX_VMEMMAP
config ARCH_WANT_OPTIMIZE_HUGETLB_VMEMMAP
bool

+#
+# Select this config option from the architecture Kconfig if HugeTLB vmemmap
+# optimization may only be enabled or disabled on the kernel command line, e.g.
+# because the architecture configures the system at boot based on whether it
+# is enabled. This makes the hugetlb_optimize_vmemmap sysctl read-only.
+#
+config ARCH_WANT_HUGETLB_VMEMMAP_RO_AFTER_INIT
+ bool
+
config HAVE_MEMBLOCK_PHYS_MAP
bool

diff --git a/mm/hugetlb_vmemmap.c b/mm/hugetlb_vmemmap.c
index 817ce39d4cf3..de4148a8aabf 100644
--- a/mm/hugetlb_vmemmap.c
+++ b/mm/hugetlb_vmemmap.c
@@ -428,7 +428,20 @@ static int vmemmap_remap_alloc(const struct hstate *h, struct folio *folio,
return ret;
}

-static bool vmemmap_optimize_enabled = IS_ENABLED(CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON);
+/*
+ * Architectures selecting CONFIG_ARCH_WANT_HUGETLB_VMEMMAP_RO_AFTER_INIT rely on
+ * HVO only being enabled or disabled on the kernel command line.
+ */
+#ifdef CONFIG_ARCH_WANT_HUGETLB_VMEMMAP_RO_AFTER_INIT
+#define __vmemmap_optimize_enabled_attr __ro_after_init
+#define HUGETLB_VMEMMAP_SYSCTL_MODE 0444
+#else
+#define __vmemmap_optimize_enabled_attr
+#define HUGETLB_VMEMMAP_SYSCTL_MODE 0644
+#endif
+
+static bool vmemmap_optimize_enabled __vmemmap_optimize_enabled_attr =
+ IS_ENABLED(CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON);
static int __init hugetlb_vmemmap_optimize_param(char *buf)
{
return kstrtobool(buf, &vmemmap_optimize_enabled);
@@ -751,7 +764,7 @@ static const struct ctl_table hugetlb_vmemmap_sysctls[] = {
.procname = "hugetlb_optimize_vmemmap",
.data = &vmemmap_optimize_enabled,
.maxlen = sizeof(vmemmap_optimize_enabled),
- .mode = 0644,
+ .mode = HUGETLB_VMEMMAP_SYSCTL_MODE,
.proc_handler = proc_dobool,
},
};
--
2.56.0.rc1.315.gc6ed9934b7-goog