hugetlb_vmemmap_optimization_try_disable() is used by callers to permanently disable HVO if it becomes impossible to use. If HVO is already actively in use, hugetlb_vmemmap_optimization_try_disable() returns false to inform the caller to take appropriate action (e.g., for arm64, not to online an incompatible late CPU). Signed-off-by: James Houghton --- MAINTAINERS | 1 + include/linux/hugetlb_vmemmap.h | 20 +++++++++++++++++ mm/hugetlb_vmemmap.c | 40 +++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 include/linux/hugetlb_vmemmap.h diff --git a/MAINTAINERS b/MAINTAINERS index ff47013ce995..55bd4c09f494 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12013,6 +12013,7 @@ F: Documentation/mm/hugetlbfs_reserv.rst F: Documentation/mm/vmemmap_dedup.rst F: fs/hugetlbfs/ F: include/linux/hugetlb.h +F: include/linux/hugetlb_vmemmap.h F: include/trace/events/hugetlbfs.h F: mm/hugetlb.c F: mm/hugetlb_cgroup.c diff --git a/include/linux/hugetlb_vmemmap.h b/include/linux/hugetlb_vmemmap.h new file mode 100644 index 000000000000..a671eb4a4ff4 --- /dev/null +++ b/include/linux/hugetlb_vmemmap.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_HUGETLB_VMEMMAP_H +#define _LINUX_HUGETLB_VMEMMAP_H + +#include + +#ifdef CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP + +bool hugetlb_vmemmap_optimization_try_disable(void); + +#else /* CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP */ + +static inline bool hugetlb_vmemmap_optimization_try_disable(void) +{ + return true; +} + +#endif + +#endif /* _LINUX_HUGETLB_VMEMMAP_H */ diff --git a/mm/hugetlb_vmemmap.c b/mm/hugetlb_vmemmap.c index a490a34998d9..7e7f8579cc2a 100644 --- a/mm/hugetlb_vmemmap.c +++ b/mm/hugetlb_vmemmap.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "hugetlb_vmemmap_internal.h" @@ -463,6 +464,39 @@ static int vmemmap_remap_alloc(const struct hstate *h, struct folio *folio, return ret; } +enum hugetlb_hvo_status { + HVO_INACTIVE = 0, + HVO_ACTIVE, + HVO_PERMANENTLY_INACTIVE, +}; +static enum hugetlb_hvo_status hvo_status = HVO_INACTIVE; + +static bool hugetlb_hvo_status_try_set(enum hugetlb_hvo_status status) +{ + enum hugetlb_hvo_status old; + + old = READ_ONCE(hvo_status); + +retry: + /* The current setting is what we want. */ + if (old == status) + return true; + + /* The current setting cannot be changed. */ + if (old != HVO_INACTIVE) + return false; + + if (!try_cmpxchg_relaxed(&hvo_status, &old, status)) + goto retry; + + return true; +} + +bool hugetlb_vmemmap_optimization_try_disable(void) +{ + return hugetlb_hvo_status_try_set(HVO_PERMANENTLY_INACTIVE); +} + static bool vmemmap_optimize_enabled = IS_ENABLED(CONFIG_HUGETLB_PAGE_OPTIMIZE_VMEMMAP_DEFAULT_ON); static int __init hugetlb_vmemmap_optimize_param(char *buf) { @@ -571,6 +605,9 @@ static bool vmemmap_should_optimize_folio(const struct hstate *h, struct folio * if (!hugetlb_vmemmap_optimizable(h)) return false; + if (!hugetlb_hvo_status_try_set(HVO_ACTIVE)) + return false; + return true; } @@ -809,6 +846,9 @@ static bool vmemmap_should_optimize_bootmem_page(struct huge_bootmem_page *m) !IS_ALIGNED(psize, pmd_vmemmap_size)) return false; + if (!hugetlb_hvo_status_try_set(HVO_ACTIVE)) + return false; + return true; } -- 2.55.0.795.g602f6c329a-goog