Skip processing hugepage kernel arguments (hugepagesz, hugepages, and default_hugepagesz) when hugepages are not supported by the architecture.
Some architectures may need to disable hugepages based on conditions discovered during kernel boot. The hugepages_supported() helper allows architecture code to advertise whether hugepages are supported. Currently, normal hugepage allocation is guarded by hugepages_supported(), but gigantic hugepages are allocated regardless of this check. This causes problems on powerpc for fadump (firmware- assisted dump). In the fadump (firmware-assisted dump) scenario, a production kernel crash causes the system to boot into a special kernel whose sole purpose is to collect the memory dump and reboot. Features such as hugepages are not required in this environment and should be disabled. For example, when the fadump kernel boots with the following kernel arguments: default_hugepagesz=1GB hugepagesz=1GB hugepages=200 Before this patch, the kernel prints the following logs: HugeTLB: allocating 200 of page size 1.00 GiB failed. Only allocated 58 hugepages. HugeTLB support is disabled! HugeTLB: huge pages not supported, ignoring associated command-line parameters hugetlbfs: disabling because there are no supported hugepage sizes Even though the logs state that HugeTLB support is disabled, gigantic hugepages are still allocated. This causes the fadump kernel to run out of memory during boot. After this patch is applied, the kernel prints the following logs for the same command line: HugeTLB: hugepages unsupported, ignoring default_hugepagesz=1GB cmdline HugeTLB: hugepages unsupported, ignoring hugepagesz=1GB cmdline HugeTLB: hugepages unsupported, ignoring hugepages=200 cmdline HugeTLB support is disabled! hugetlbfs: disabling because there are no supported hugepage sizes To fix the issue, gigantic hugepage allocation should be guarded by hugepages_supported(). Previously, two approaches were proposed to bring gigantic hugepage allocation under hugepages_supported(): [1] Check hugepages_supported() in the generic code before allocating gigantic hugepages [2] Make arch_hugetlb_valid_size() return false for all hugetlb sizes Approach [2] has two minor issues: 1. It prints misleading logs about invalid hugepage sizes 2. The kernel still processes hugepage kernel arguments unnecessarily To control gigantic hugepage allocation, skip processing hugepage kernel arguments (default_hugepagesz, hugepagesz and hugepages) when hugepages_supported() returns false. Note for backporting: This fix is a partial retrieval of the commit mentioned in the Fixes tag and is only valid once the change referenced by the Depends-on tag is present. When backporting this patch, the commit mentioned in the Depends-on tag must be included first. Note for backporting: This fix is a partial retrieval of the commit mentioned in the Fixes tag. It is only valid once the change referenced by the Depends-on tag is present. When backporting this patch, the commit mentioned in the Depends-on tag must be included first. Link: https://lore.kernel.org/all/[email protected]/ [1] Link: https://lore.kernel.org/all/[email protected]/ [2] Fixes: c2833a5bf75b ("hugetlbfs: fix changes to command line processing") Depends-on: 2354ad252b66 ("powerpc/mm: Update default hugetlb size early") Cc: Andrew Morton <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Christophe Leroy <[email protected]> Cc: Heiko Carstens <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Madhavan Srinivasan <[email protected]> Cc: Michael Ellerman <[email protected]> Cc: Muchun Song <[email protected]> Cc: Oscar Salvador <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Vasily Gorbik <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Cc: [email protected] Acked-by: David Hildenbrand (Red Hat) <[email protected]> Reviewed-by: Ritesh Harjani (IBM) <[email protected]> Signed-off-by: Sourabh Jain <[email protected]> --- Changelog: v1: https://lore.kernel.org/all/[email protected]/ v2: https://lore.kernel.org/all/[email protected]/ - disable gigantic hugepage in arch code, arch_hugetlb_valid_size() v3: https://lore.kernel.org/all/[email protected]/ - Do not modify the initialization of the shift variable v4: https://lore.kernel.org/all/[email protected]/ - Update commit message to include how hugepages_supported() detects hugepages support when fadump is active - Add Reviewed-by tag - NO functional change v5: https://lore.kernel.org/all/[email protected]/ - Significant change in approach: disable processing of hugepage kernel arguments if hugepages_supported() returns false - Drop a Reviewed-by tag v6: https://lore.kernel.org/all/[email protected]/ - Updated commit message with additional logs and tags - No functional changes v7: - Add a note for backporting this fix in the commit message - Add a Depends-on tag referencing the prerequisite commit - No functional changes --- mm/hugetlb.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 51273baec9e5..e0ab14020513 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -4286,6 +4286,11 @@ static int __init hugepages_setup(char *s) unsigned long tmp; char *p = s; + if (!hugepages_supported()) { + pr_warn("HugeTLB: hugepages unsupported, ignoring hugepages=%s cmdline\n", s); + return 0; + } + if (!parsed_valid_hugepagesz) { pr_warn("HugeTLB: hugepages=%s does not follow a valid hugepagesz, ignoring\n", s); parsed_valid_hugepagesz = true; @@ -4366,6 +4371,11 @@ static int __init hugepagesz_setup(char *s) unsigned long size; struct hstate *h; + if (!hugepages_supported()) { + pr_warn("HugeTLB: hugepages unsupported, ignoring hugepagesz=%s cmdline\n", s); + return 0; + } + parsed_valid_hugepagesz = false; size = (unsigned long)memparse(s, NULL); @@ -4414,6 +4424,12 @@ static int __init default_hugepagesz_setup(char *s) unsigned long size; int i; + if (!hugepages_supported()) { + pr_warn("HugeTLB: hugepages unsupported, ignoring default_hugepagesz=%s cmdline\n", + s); + return 0; + } + parsed_valid_hugepagesz = false; if (parsed_default_hugepagesz) { pr_err("HugeTLB: default_hugepagesz previously specified, ignoring %s\n", s); -- 2.51.1
