From nobody Sat Apr 4 01:47:51 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B871B2D3A60; Fri, 20 Mar 2026 22:13:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044828; cv=none; b=ZV8cBVPrRkQseuK3/bpTFD4BssAmAzySuJ3wUKrCEFHHNz3Mtwd3ZeMdJT6mG0nghNwKJZylq/htlzZxdjbo5MlooFsF+0O6Clmv6Q6cZ2qaT2yMFI3UuihQ7CQgKl4n7463Y52sIvJd4pNGCXAhe8DX5Hh4xSH9nhcyI0dshVk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044828; c=relaxed/simple; bh=nHbTHkZVPmgr07xrNZlc6QBoO7DF8u1xsHWbyTYeiTQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=NokfG8qybjZnpnXev8ugd5/jcDkB3QADIAHVvFraNoQCNikUvheORWvEZSl6Kv17dHifOOTvOl8yhy6ZjEONx5kanXvqw44NRJljz8EDhrYlgAhf46c5dA7tAd+v9+ooJ0vKy0P5aNgHUEpcM/AbICcwUTbELfM8RtZOdBqSs2w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=tQfW0O52; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="tQfW0O52" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B74D4C4CEF7; Fri, 20 Mar 2026 22:13:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774044828; bh=nHbTHkZVPmgr07xrNZlc6QBoO7DF8u1xsHWbyTYeiTQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=tQfW0O52ZtyktIiPAk6j94DCE/TASe1TGKNwSCHH/AqiVoKikGBfFF3W4UcBK/nfw 8V7Vb27Vcmrr0XvfznjhmwdnhGVPlZCBt7c1tUzBlzwi7wYWY0KR84ObQEtEz6uESv dRzL5KUAy9mEFD4GI/QVpkY+cklyuLv1v1lmUNE7D7i6zqVl2H/QaLAOr83tthbwZl jIT3N5KVDUM3OYBhJFn5GCC1nY/SIvLbps9ZcbkHdoN80Bzuh8s1eM7pV8Bva0XXDY h8kXTpPAdxsUhuyQ3Sg8Xd7BkRgiNQ4pgqYN84AN08nzdlaoP9hShigTqDXP9QruqH SbtczXznDUijA== From: "David Hildenbrand (Arm)" Date: Fri, 20 Mar 2026 23:13:33 +0100 Subject: [PATCH v2 01/15] mm/memory_hotplug: fix possible race in scan_movable_pages() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260320-sparsemem_cleanups-v2-1-096addc8800d@kernel.org> References: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> In-Reply-To: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> To: linux-kernel@vger.kernel.org Cc: Andrew Morton , Oscar Salvador , Axel Rasmussen , Yuanchu Xie , Wei Xu , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Sidhartha Kumar , linux-mm@kvack.org, linux-cxl@vger.kernel.org, linux-riscv@lists.infradead.org, "David Hildenbrand (Arm)" X-Mailer: b4 0.13.0 If a hugetlb folio gets freed while we are in scan_movable_pages(), folio_nr_pages() could return 0, resulting in or'ing "0 - 1 =3D -1" to the PFN, resulting in PFN =3D -1. We're not holding any locks or references that would prevent that. for_each_valid_pfn() would then search for the next valid PFN, and could return a PFN that is outside of the range of the original requested range. do_migrate_page() would then try to migrate quite a big range, which is certainly undesirable. To fix it, simply test for valid folio_nr_pages() values. While at it, as PageHuge() really just does a page_folio() internally, we can just use folio_test_hugetlb() on the folio directly. scan_movable_pages() is expected to be fast, and we try to avoid taking locks or grabbing references. We cannot use folio_try_get() as that does not work for free hugetlb folios. We could grab the hugetlb_lock, but that just adds complexity. The race is unlikely to trigger in practice, so we won't be CCing stable. Fixes: 16540dae959d ("mm/hugetlb: mm/memory_hotplug: use a folio in scan_mo= vable_pages()") Signed-off-by: David Hildenbrand (Arm) Reviewed-by: Lorenzo Stoakes (Oracle) --- mm/memory_hotplug.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 86d3faf50453..969cd7ddf68f 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -1747,6 +1747,7 @@ static int scan_movable_pages(unsigned long start, un= signed long end, unsigned long pfn; =20 for_each_valid_pfn(pfn, start, end) { + unsigned long nr_pages; struct page *page; struct folio *folio; =20 @@ -1763,9 +1764,9 @@ static int scan_movable_pages(unsigned long start, un= signed long end, if (PageOffline(page) && page_count(page)) return -EBUSY; =20 - if (!PageHuge(page)) - continue; folio =3D page_folio(page); + if (!folio_test_hugetlb(folio)) + continue; /* * This test is racy as we hold no reference or lock. The * hugetlb page could have been free'ed and head is no longer @@ -1775,7 +1776,11 @@ static int scan_movable_pages(unsigned long start, u= nsigned long end, */ if (folio_test_hugetlb_migratable(folio)) goto found; - pfn |=3D folio_nr_pages(folio) - 1; + nr_pages =3D folio_nr_pages(folio); + if (unlikely(nr_pages < 1 || nr_pages > MAX_FOLIO_NR_PAGES || + !is_power_of_2(nr_pages))) + continue; + pfn |=3D nr_pages - 1; } return -ENOENT; found: --=20 2.43.0 From nobody Sat Apr 4 01:47:51 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C5D9C3358A7; Fri, 20 Mar 2026 22:13:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044832; cv=none; b=R9riHJlsxO/QRK7JbhgVMMtzoKA/DHrHVxUeNhDbGxOw66pLJ7j/TK7gPdpVI4bJFKUmKeqe0W3ALS9p5WGp5WFoSJso65RpfLs0sGQNtH7vdU9s2Atw2PGmefAeDidPBOk/PvXelS6aRZKyaAybH76NfdlGM9ti2ROPfoIUD2Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044832; c=relaxed/simple; bh=XBR2EPoKpXeNjq1txkLBTh/DgkCJHtoC1PlnginQxtA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=N5XsaxTEW5H7FruIhvRf8p9ruUF/0GiTPKGzHfe3Fmj/FLs7hYC2yiDBNWF0/i/A4n0x5rUNL8mxm99ni+NM2lMtHsvBBYG08Uh8aNOWqya0UsC8g9x3/pvM8JQxGzJBVnqpDyLd8MzZjpthlP7AgIoTeMyyBmtCjOVrL/l3YPU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=tInuY984; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="tInuY984" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CECA5C2BC87; Fri, 20 Mar 2026 22:13:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774044832; bh=XBR2EPoKpXeNjq1txkLBTh/DgkCJHtoC1PlnginQxtA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=tInuY984yzdIEuaZJXpPPAPu/jx6o88MxmPXqoEhhmH9XAKSJMbP9JmVw7KDYMdYI cYFzrC3mXShUxMELrJRAOb8iFHCYRFYnMXADOypUly2tPI5LhdRJAlx6Y7vIsodwEE Tb8WTg9dueCXRj24fln2u12nVVjS4oL3Ny2O8BgKFv5WAfttURT/QkCV02wu1LukEt +WqU5eLPOYBtokHGt2yPjG/XvcY29bKMFzXiTW0vweT3cJdrcDYhDTgUwEXHa4yEL4 Ov9DFUt9eHboVve5zoTrH8Bv9mnM+yD+kzQ6+YJzB4D+h8DGu8XFoU9yIoZlUTet3N 5V0hxSVsZnYcA== From: "David Hildenbrand (Arm)" Date: Fri, 20 Mar 2026 23:13:34 +0100 Subject: [PATCH v2 02/15] mm/memory_hotplug: remove for_each_valid_pfn() usage Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260320-sparsemem_cleanups-v2-2-096addc8800d@kernel.org> References: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> In-Reply-To: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> To: linux-kernel@vger.kernel.org Cc: Andrew Morton , Oscar Salvador , Axel Rasmussen , Yuanchu Xie , Wei Xu , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Sidhartha Kumar , linux-mm@kvack.org, linux-cxl@vger.kernel.org, linux-riscv@lists.infradead.org, "David Hildenbrand (Arm)" X-Mailer: b4 0.13.0 When offlining memory, we know that the memory range has no holes. Checking for valid pfns is not required. Reviewed-by: Lorenzo Stoakes (Oracle) Reviewed-by: Mike Rapoport (Microsoft) Signed-off-by: David Hildenbrand (Arm) --- mm/memory_hotplug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 969cd7ddf68f..0c26b1f2be6e 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -1746,7 +1746,7 @@ static int scan_movable_pages(unsigned long start, un= signed long end, { unsigned long pfn; =20 - for_each_valid_pfn(pfn, start, end) { + for (pfn =3D start; pfn < end; pfn++) { unsigned long nr_pages; struct page *page; struct folio *folio; @@ -1796,7 +1796,7 @@ static void do_migrate_range(unsigned long start_pfn,= unsigned long end_pfn) static DEFINE_RATELIMIT_STATE(migrate_rs, DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST); =20 - for_each_valid_pfn(pfn, start_pfn, end_pfn) { + for (pfn =3D start_pfn; pfn < end_pfn; pfn++) { struct page *page; =20 page =3D pfn_to_page(pfn); --=20 2.43.0 From nobody Sat Apr 4 01:47:51 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F22E33446A6; Fri, 20 Mar 2026 22:13:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044837; cv=none; b=TAU0WzhgGcYniEFvkPmDlEd8GEOZXDEFjKMiaw+SQ5rG5EKlCjj6p+DRG5n76kOsiU2seRz9cr3Yf1rZTQfEYbhqKikTsTPm7EoaMlcWSzabOaBNX/doYexL21/C37VTG7/IlFS1gVPfwbFvWSDfSQOPj2wImhjRZ6k+v5KDlGw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044837; c=relaxed/simple; bh=qGQ4S0Dk5OWFFlnh6q01L6aeYnQdqeH7CkkASIBS58U=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=CTm0CM+um450/LCrmpdHf/hyXVv17a4mjBmLkNdsEss9/yG2cdBvtGpYFGbHIImgIE7kP1HOxxNE20/QWHCrZfKXVb+KOHlbBlV+KzRKKJKnJ3qwPALcYbIR0tl/52GrJJRIN7R+5AbmZSlpISuWSmuD4IBsgK0poLHSz9A0U+I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ax+3vlpI; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Ax+3vlpI" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E915EC2BC87; Fri, 20 Mar 2026 22:13:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774044836; bh=qGQ4S0Dk5OWFFlnh6q01L6aeYnQdqeH7CkkASIBS58U=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Ax+3vlpIZDyDFxIGzU4ohpjnZ07lb6mXpCmB5SmtxOCikYKHnwhZR+rhhZ3Ots9Bn vHSVkAjBM3wfALykYjhp/MkzWzNvKTEd9sUM3Tw4byVmrY6/sDQ9Ob/KzLPVV38hHy ivcccHnThBm+RNKbO79irp0quB1fH4ydlStXcOe0Wg8BDnojiIJshFcUy5lL2kBMkJ ItQMpEA4sP1pRzpMZBjhJ9DCJmiw+MmjRupYS7CRNoQxTOeMI+PVLfKqkHhVNAvBZe WYFhpaCfdn1jTQT6GaVjgORf7rnYt4myxTj3ldG0Zr25VPkt2/Jzbu6xvGk8fc9FDq WP0dgVm9VXsdA== From: "David Hildenbrand (Arm)" Date: Fri, 20 Mar 2026 23:13:35 +0100 Subject: [PATCH v2 03/15] mm/sparse: remove WARN_ONs from (online|offline)_mem_sections() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260320-sparsemem_cleanups-v2-3-096addc8800d@kernel.org> References: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> In-Reply-To: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> To: linux-kernel@vger.kernel.org Cc: Andrew Morton , Oscar Salvador , Axel Rasmussen , Yuanchu Xie , Wei Xu , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Sidhartha Kumar , linux-mm@kvack.org, linux-cxl@vger.kernel.org, linux-riscv@lists.infradead.org, "David Hildenbrand (Arm)" X-Mailer: b4 0.13.0 We do not allow offlining of memory with memory holes, and always hotplug memory without holes. Consequently, we cannot end up onlining or offlining memory sections that have holes (including invalid sections). That's also why these WARN_ONs never fired. Let's remove the WARN_ONs along with the TODO regarding double-checking. Reviewed-by: Lorenzo Stoakes (Oracle) Reviewed-by: Mike Rapoport (Microsoft) Signed-off-by: David Hildenbrand (Arm) --- mm/sparse.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/mm/sparse.c b/mm/sparse.c index dfabe554adf8..93252112860e 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -638,13 +638,8 @@ void online_mem_sections(unsigned long start_pfn, unsi= gned long end_pfn) =20 for (pfn =3D start_pfn; pfn < end_pfn; pfn +=3D PAGES_PER_SECTION) { unsigned long section_nr =3D pfn_to_section_nr(pfn); - struct mem_section *ms; - - /* onlining code should never touch invalid ranges */ - if (WARN_ON(!valid_section_nr(section_nr))) - continue; + struct mem_section *ms =3D __nr_to_section(section_nr); =20 - ms =3D __nr_to_section(section_nr); ms->section_mem_map |=3D SECTION_IS_ONLINE; } } @@ -656,16 +651,8 @@ void offline_mem_sections(unsigned long start_pfn, uns= igned long end_pfn) =20 for (pfn =3D start_pfn; pfn < end_pfn; pfn +=3D PAGES_PER_SECTION) { unsigned long section_nr =3D pfn_to_section_nr(pfn); - struct mem_section *ms; + struct mem_section *ms =3D __nr_to_section(section_nr); =20 - /* - * TODO this needs some double checking. Offlining code makes - * sure to check pfn_valid but those checks might be just bogus - */ - if (WARN_ON(!valid_section_nr(section_nr))) - continue; - - ms =3D __nr_to_section(section_nr); ms->section_mem_map &=3D ~SECTION_IS_ONLINE; } } --=20 2.43.0 From nobody Sat Apr 4 01:47:51 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1A683341065; Fri, 20 Mar 2026 22:14:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044841; cv=none; b=mGBcWTXEPQO2gmBHi44Y9ZmhnJ3DhJ60PsjV/dD9h+TBM9c9cG45JKP7Iov0cJumInL0KifqcddWhANQY9U18XwS9hdhXaQ+Rt9H2zAwqebSyyibTRW/9Vvd7tzlm46pzWUn5cA2N7UZnKhCkY35k4wUpN+bTm/TiAWglLYZg34= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044841; c=relaxed/simple; bh=mvXhiGTn6tZZYnNOOoiRbg2GgcaMPiyLXwyjxmdxo84=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ttEzB9UWMy2kWm7lbj1FdgMW9kHNgrDd3CLG/dkvMHytcM0cnxN2be9yh1dOUw8105eRliI4Snkr85x8u6cONMTjq1RwKdg+9ImXJh3imHtMs/6/8bXjNOYohmNjRSabGOJdPfTU3mY2uFBMXCGZXmbskwBtPBC4dFU95Qg3VaU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=X/uB2w7D; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="X/uB2w7D" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 22BC5C2BC87; Fri, 20 Mar 2026 22:13:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774044840; bh=mvXhiGTn6tZZYnNOOoiRbg2GgcaMPiyLXwyjxmdxo84=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=X/uB2w7DSbxaqWWZI0SFouAEqRYt5ziW1QewNaYsFL+YJCSIra6vwkHxw1G9GGCh4 BIg7cd7GsHXYGOKUNs0MzTHjHG60jQ69wHz78GZiVzLl9CYVKK8mKlaJBjYPupxasS g+bH6a1n9UMg+IiOGJihFzUSK7KfYpQoRfoiR5xltvNtvoFnAacVxiUXKk85xWL8c9 muE+/XC1RcriPyCEgQuzM4jbHkE9K1Cv3yzKRDknP/UJEsuMIMFvejFsVGjnmVpp4O pbmnmWeUm1R8FQmqFTejFLSSs151sXs6nnngVkaakFF4+Yn2aN1kiPBhn3e/pwFWuy w+3VzFUlJqhAg== From: "David Hildenbrand (Arm)" Date: Fri, 20 Mar 2026 23:13:36 +0100 Subject: [PATCH v2 04/15] mm/Kconfig: make CONFIG_MEMORY_HOTPLUG depend on CONFIG_SPARSEMEM_VMEMMAP Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260320-sparsemem_cleanups-v2-4-096addc8800d@kernel.org> References: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> In-Reply-To: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> To: linux-kernel@vger.kernel.org Cc: Andrew Morton , Oscar Salvador , Axel Rasmussen , Yuanchu Xie , Wei Xu , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Sidhartha Kumar , linux-mm@kvack.org, linux-cxl@vger.kernel.org, linux-riscv@lists.infradead.org, "David Hildenbrand (Arm)" X-Mailer: b4 0.13.0 Ever since commit f8f03eb5f0f9 ("mm: stop making SPARSEMEM_VMEMMAP user-selectable"), an architecture that supports CONFIG_SPARSEMEM_VMEMMAP (by selecting SPARSEMEM_VMEMMAP_ENABLE) can no longer enable CONFIG_SPARSEMEM without CONFIG_SPARSEMEM_VMEMMAP. Right now, CONFIG_MEMORY_HOTPLUG is guarded by CONFIG_SPARSEMEM. However, CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG is only enabled by * arm64: which selects SPARSEMEM_VMEMMAP_ENABLE * loongarch: which selects SPARSEMEM_VMEMMAP_ENABLE * powerpc (64bit): which selects SPARSEMEM_VMEMMAP_ENABLE * riscv (64bit): which selects SPARSEMEM_VMEMMAP_ENABLE * s390 with SPARSEMEM: which selects SPARSEMEM_VMEMMAP_ENABLE * x86 (64bit): which selects SPARSEMEM_VMEMMAP_ENABLE So, we can make CONFIG_MEMORY_HOTPLUG depend on CONFIG_SPARSEMEM_VMEMMAP without affecting any setups. Reviewed-by: Lorenzo Stoakes (Oracle) Reviewed-by: Mike Rapoport (Microsoft) Signed-off-by: David Hildenbrand (Arm) --- mm/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/Kconfig b/mm/Kconfig index ebd8ea353687..c012944938a7 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -472,7 +472,7 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE menuconfig MEMORY_HOTPLUG bool "Memory hotplug" select MEMORY_ISOLATION - depends on SPARSEMEM + depends on SPARSEMEM_VMEMMAP depends on ARCH_ENABLE_MEMORY_HOTPLUG depends on 64BIT select NUMA_KEEP_MEMINFO if NUMA --=20 2.43.0 From nobody Sat Apr 4 01:47:51 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 30C52341065; Fri, 20 Mar 2026 22:14:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044845; cv=none; b=Jhc1sMQ9qbllZ2ZMcsJfZxN7aKRhsh48bejl1rzpB0cCY11H0i7hfJmXUo77fTzT2zmQbjig9PYYuq+CNC7K+rL3J7zn97YK7enpiY326mPs/X4UZomvVRhbVUJLpVfZf+NmnkCiTrheURSh7TzCMZMc+oRkD4fisawpLa33aFY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044845; c=relaxed/simple; bh=IA23Gy39M2F3BrgjRU1645p2gPCHoKr3S7Gd6stw5xY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ahFAGSLTzATzYmavn2LEqif4zP2itYfHbUcrUxwGiBxarY1ZQ4XpDv95fUXIH0pW/t2h4I6mVrfXuWc4MM0SOMWfrj/JUjz9FP8/v4kB+htD3TKIKqywDvNoKWbNNTI32EBcssX6UPX0yqUNlrMaf8TGd2NsHxzs637OrQyMY4U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ITuTXaTR; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ITuTXaTR" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 533C1C4CEF7; Fri, 20 Mar 2026 22:14:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774044845; bh=IA23Gy39M2F3BrgjRU1645p2gPCHoKr3S7Gd6stw5xY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ITuTXaTR5d3MLfnoE8tiWvMk3cJVFd3Gn4KFKc27ZUXry5hmpyQELFB1C+kYArpwP E68SqIwWSExdhJKLtwAb8/MnDcxtEzcli+cyl8rEOVXy7QUJttlz4Cs/vtHelyYvP3 MhBm0AMFhp9AV1a/Rp0cp6DluC2ISIen3+X7xuRxf5M//eU6B65u8yZDbBBB/9fk5o CzhinwrYTx4Pr2gD4mtFdMumrSj2a/MequJzUXzrkLsZ+sT/qMEvLquBZzaeByDTBP SNOXBPB7LC6GIlWCEKYfJoDyoNHCpxCA98DY3irXB4tVAUChm6T+w8VsIuqcwuBd1l 0psq2Gp2a4cIg== From: "David Hildenbrand (Arm)" Date: Fri, 20 Mar 2026 23:13:37 +0100 Subject: [PATCH v2 05/15] mm/memory_hotplug: simplify check_pfn_span() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260320-sparsemem_cleanups-v2-5-096addc8800d@kernel.org> References: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> In-Reply-To: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> To: linux-kernel@vger.kernel.org Cc: Andrew Morton , Oscar Salvador , Axel Rasmussen , Yuanchu Xie , Wei Xu , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Sidhartha Kumar , linux-mm@kvack.org, linux-cxl@vger.kernel.org, linux-riscv@lists.infradead.org, "David Hildenbrand (Arm)" X-Mailer: b4 0.13.0 We now always have CONFIG_SPARSEMEM_VMEMMAP, so remove the dead code. Reviewed-by: Lorenzo Stoakes (Oracle) Reviewed-by: Mike Rapoport (Microsoft) Signed-off-by: David Hildenbrand (Arm) --- mm/memory_hotplug.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 0c26b1f2be6e..ef2b03eb1873 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -320,21 +320,13 @@ static void release_memory_resource(struct resource *= res) static int check_pfn_span(unsigned long pfn, unsigned long nr_pages) { /* - * Disallow all operations smaller than a sub-section and only - * allow operations smaller than a section for - * SPARSEMEM_VMEMMAP. Note that check_hotplug_memory_range() - * enforces a larger memory_block_size_bytes() granularity for - * memory that will be marked online, so this check should only - * fire for direct arch_{add,remove}_memory() users outside of - * add_memory_resource(). + * Disallow all operations smaller than a sub-section. + * Note that check_hotplug_memory_range() enforces a larger + * memory_block_size_bytes() granularity for memory that will be marked + * online, so this check should only fire for direct + * arch_{add,remove}_memory() users outside of add_memory_resource(). */ - unsigned long min_align; - - if (IS_ENABLED(CONFIG_SPARSEMEM_VMEMMAP)) - min_align =3D PAGES_PER_SUBSECTION; - else - min_align =3D PAGES_PER_SECTION; - if (!IS_ALIGNED(pfn | nr_pages, min_align)) + if (!IS_ALIGNED(pfn | nr_pages, PAGES_PER_SUBSECTION)) return -EINVAL; return 0; } --=20 2.43.0 From nobody Sat Apr 4 01:47:51 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6A2EE2D3A60; Fri, 20 Mar 2026 22:14:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044849; cv=none; b=IZnZksdSky0vtxysphwXb/siAn8lYO5IjBuOLI6sQnDkPpmgl71gSPqpc6rdq5Eg1E3fqa3BPr7FLtrJNE3AkZgjwNlp0ddGiPcTzXI8zmrd0pmkj48uKcDcPjF4T2N6cctcPsQIJ2s4xsOHZixc2xMIzkXOivObIaDJVbiz5cE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044849; c=relaxed/simple; bh=nPM2xDzamc7ofaCScsG410PR/QQBsQ3DvwZZV+9GS1k=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=WfOjjm6Rvd9+A+H9dxkZ2UgkM5lugEA4MLYdV2lxX609jn0MPee7dEL49PwwBLcbzNVXNqzBCPqOrPkJt17KusxDRJPv30D9xokxXSQ0BL1r0qRtHEzJ57wIENaRtVT4lAlRwgTAUnAvkft0zBUm1AxKPi1CTXtG5IjftMC4pL4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=HnHEJaPx; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="HnHEJaPx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9C2FCC2BC87; Fri, 20 Mar 2026 22:14:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774044849; bh=nPM2xDzamc7ofaCScsG410PR/QQBsQ3DvwZZV+9GS1k=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=HnHEJaPxDsHVIvGrxzHc285TLNol1z8REyKULttk7LBtwRgQ91PH1mTrO85MXJHyY WFH/wxwqXRjfho6tYaOu2/MfwuotmjfCmsEnGZtWR9t6ddUZxpBVOs9QOWmQvmwy0a aFiJ6oT7939CIJexqKYA2dnTf44yStx0+tux37YlR4l3yBmoRPT7k27uWmfAUQuEcD 8geni0LfN+9k7qbtbxB0ex+mCUMy825GfgzDnLOwZ/nRtaXSOeBKYzFzhArxXXxAIu Gh3l9X4y5slBiaPioaYF/8CdnkJvSUALoiieyOcpGKKd5h1bKtCyau0asJSb7OVFP4 OpoN99xFHbZpg== From: "David Hildenbrand (Arm)" Date: Fri, 20 Mar 2026 23:13:38 +0100 Subject: [PATCH v2 06/15] mm/sparse: remove !CONFIG_SPARSEMEM_VMEMMAP leftovers for CONFIG_MEMORY_HOTPLUG Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260320-sparsemem_cleanups-v2-6-096addc8800d@kernel.org> References: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> In-Reply-To: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> To: linux-kernel@vger.kernel.org Cc: Andrew Morton , Oscar Salvador , Axel Rasmussen , Yuanchu Xie , Wei Xu , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Sidhartha Kumar , linux-mm@kvack.org, linux-cxl@vger.kernel.org, linux-riscv@lists.infradead.org, "David Hildenbrand (Arm)" X-Mailer: b4 0.13.0 CONFIG_MEMORY_HOTPLUG now depends on CONFIG_SPARSEMEM_VMEMMAP. So let's remove the !CONFIG_SPARSEMEM_VMEMMAP leftovers that are dead code. Adjust the comment above fill_subsection_map() accordingly. Reviewed-by: Lorenzo Stoakes (Oracle) Reviewed-by: Mike Rapoport (Microsoft) Signed-off-by: David Hildenbrand (Arm) --- mm/sparse.c | 69 ++-------------------------------------------------------= ---- 1 file changed, 2 insertions(+), 67 deletions(-) diff --git a/mm/sparse.c b/mm/sparse.c index 93252112860e..875f718a4c79 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -657,7 +657,6 @@ void offline_mem_sections(unsigned long start_pfn, unsi= gned long end_pfn) } } =20 -#ifdef CONFIG_SPARSEMEM_VMEMMAP static struct page * __meminit populate_section_memmap(unsigned long pfn, unsigned long nr_pages, int nid, struct vmem_altmap *altmap, struct dev_pagemap *pgmap) @@ -729,73 +728,11 @@ static int fill_subsection_map(unsigned long pfn, uns= igned long nr_pages) =20 return rc; } -#else -static struct page * __meminit populate_section_memmap(unsigned long pfn, - unsigned long nr_pages, int nid, struct vmem_altmap *altmap, - struct dev_pagemap *pgmap) -{ - return kvmalloc_node(array_size(sizeof(struct page), - PAGES_PER_SECTION), GFP_KERNEL, nid); -} - -static void depopulate_section_memmap(unsigned long pfn, unsigned long nr_= pages, - struct vmem_altmap *altmap) -{ - kvfree(pfn_to_page(pfn)); -} - -static void free_map_bootmem(struct page *memmap) -{ - unsigned long maps_section_nr, removing_section_nr, i; - unsigned long type, nr_pages; - struct page *page =3D virt_to_page(memmap); - - nr_pages =3D PAGE_ALIGN(PAGES_PER_SECTION * sizeof(struct page)) - >> PAGE_SHIFT; - - for (i =3D 0; i < nr_pages; i++, page++) { - type =3D bootmem_type(page); - - BUG_ON(type =3D=3D NODE_INFO); - - maps_section_nr =3D pfn_to_section_nr(page_to_pfn(page)); - removing_section_nr =3D bootmem_info(page); - - /* - * When this function is called, the removing section is - * logical offlined state. This means all pages are isolated - * from page allocator. If removing section's memmap is placed - * on the same section, it must not be freed. - * If it is freed, page allocator may allocate it which will - * be removed physically soon. - */ - if (maps_section_nr !=3D removing_section_nr) - put_page_bootmem(page); - } -} - -static int clear_subsection_map(unsigned long pfn, unsigned long nr_pages) -{ - return 0; -} - -static bool is_subsection_map_empty(struct mem_section *ms) -{ - return true; -} - -static int fill_subsection_map(unsigned long pfn, unsigned long nr_pages) -{ - return 0; -} -#endif /* CONFIG_SPARSEMEM_VMEMMAP */ =20 /* - * To deactivate a memory region, there are 3 cases to handle across - * two configurations (SPARSEMEM_VMEMMAP=3D{y,n}): + * To deactivate a memory region, there are 3 cases to handle: * - * 1. deactivation of a partial hot-added section (only possible in - * the SPARSEMEM_VMEMMAP=3Dy case). + * 1. deactivation of a partial hot-added section: * a) section was present at memory init. * b) section was hot-added post memory init. * 2. deactivation of a complete hot-added section. @@ -803,8 +740,6 @@ static int fill_subsection_map(unsigned long pfn, unsig= ned long nr_pages) * * For 1, when subsection_map does not empty we will not be freeing the * usage map, but still need to free the vmemmap range. - * - * For 2 and 3, the SPARSEMEM_VMEMMAP=3D{y,n} cases are unified */ static void section_deactivate(unsigned long pfn, unsigned long nr_pages, struct vmem_altmap *altmap) --=20 2.43.0 From nobody Sat Apr 4 01:47:51 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B882A34575A; Fri, 20 Mar 2026 22:14:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044853; cv=none; b=FLUvxR2PVgSObVUtxID6lZTvJTlYghqr6iQ8Hm/+X2xDNyLdeB7z0+nrALOzL3RVy9p/6BVktaqopqhrX0DmFWYUhRFH0irLOHNT0nuEpTyrW5dpCu1pFPS2eZvmF56kk1vE1gJ5aS/f++/COSuRD1iiSby4MpncVrddBG/mTCI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044853; c=relaxed/simple; bh=QZECcZOo9XU6VE0O+G1ptFNqIVCOuWAko6C1OasJr/U=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=O5r9+5KCvkKHwOA5rmbT+3+4PR9d/Iw6+XxNMKBWiQxTaaX5bohE2qNm25W/2haWECvHu2GeFNA6Dn8p67So1pyjNWULqw0+wzYst1huHbDT690KsBSWlbI79uAuUo52z/DJ6pLL3l0tjY0BAo5fAMyW1H+3J6eWK3TDDa3/EwY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BYJKP7zl; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="BYJKP7zl" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CD735C2BCB6; Fri, 20 Mar 2026 22:14:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774044853; bh=QZECcZOo9XU6VE0O+G1ptFNqIVCOuWAko6C1OasJr/U=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=BYJKP7zlv4jBTvu80a24WL8Ct5aU4DcbuPl7DomVKZQywcFSHmDul15sUSZzpOS9w VGpkVDDKudEKjzp330WynQpTZJarltWaw0dHJ3u7eeAic+bRO3z2vaoJXKeKE8CzXJ Hlir4vVzCgO/f2OKDKqS8rRg5eQw0Vi39t7NMLD4x1kMCvNqs1ghvWraXEpRmdgbkJ ouDmSeYe65LVeauMLiEz99LE6nUEBfU2ntRObRZhG73T8ceIv43bw4PDm71NWkHgYS M2POdUrqX1hIGxGX4jWTxYwJH7i/lYl4bma2SJk/M0epQ5B85WZGwtmdA9RUsRNrzD BZVwwK53Fv3qA== From: "David Hildenbrand (Arm)" Date: Fri, 20 Mar 2026 23:13:39 +0100 Subject: [PATCH v2 07/15] mm/bootmem_info: remove handling for !CONFIG_SPARSEMEM_VMEMMAP Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260320-sparsemem_cleanups-v2-7-096addc8800d@kernel.org> References: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> In-Reply-To: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> To: linux-kernel@vger.kernel.org Cc: Andrew Morton , Oscar Salvador , Axel Rasmussen , Yuanchu Xie , Wei Xu , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Sidhartha Kumar , linux-mm@kvack.org, linux-cxl@vger.kernel.org, linux-riscv@lists.infradead.org, "David Hildenbrand (Arm)" X-Mailer: b4 0.13.0 It is not immediately obvious that CONFIG_HAVE_BOOTMEM_INFO_NODE is only selected from CONFIG_MEMORY_HOTREMOVE, which itself depends on CONFIG_MEMORY_HOTPLUG that ... depends on CONFIG_SPARSEMEM_VMEMMAP. Let's remove the !CONFIG_SPARSEMEM_VMEMMAP leftovers that are dead code. Reviewed-by: Lorenzo Stoakes (Oracle) Reviewed-by: Mike Rapoport (Microsoft) Signed-off-by: David Hildenbrand (Arm) --- mm/bootmem_info.c | 37 ------------------------------------- 1 file changed, 37 deletions(-) diff --git a/mm/bootmem_info.c b/mm/bootmem_info.c index b0e2a9fa641f..e61e08e24924 100644 --- a/mm/bootmem_info.c +++ b/mm/bootmem_info.c @@ -40,42 +40,6 @@ void put_page_bootmem(struct page *page) } } =20 -#ifndef CONFIG_SPARSEMEM_VMEMMAP -static void __init register_page_bootmem_info_section(unsigned long start_= pfn) -{ - unsigned long mapsize, section_nr, i; - struct mem_section *ms; - struct page *page, *memmap; - struct mem_section_usage *usage; - - section_nr =3D pfn_to_section_nr(start_pfn); - ms =3D __nr_to_section(section_nr); - - /* Get section's memmap address */ - memmap =3D sparse_decode_mem_map(ms->section_mem_map, section_nr); - - /* - * Get page for the memmap's phys address - * XXX: need more consideration for sparse_vmemmap... - */ - page =3D virt_to_page(memmap); - mapsize =3D sizeof(struct page) * PAGES_PER_SECTION; - mapsize =3D PAGE_ALIGN(mapsize) >> PAGE_SHIFT; - - /* remember memmap's page */ - for (i =3D 0; i < mapsize; i++, page++) - get_page_bootmem(section_nr, page, SECTION_INFO); - - usage =3D ms->usage; - page =3D virt_to_page(usage); - - mapsize =3D PAGE_ALIGN(mem_section_usage_size()) >> PAGE_SHIFT; - - for (i =3D 0; i < mapsize; i++, page++) - get_page_bootmem(section_nr, page, MIX_SECTION_INFO); - -} -#else /* CONFIG_SPARSEMEM_VMEMMAP */ static void __init register_page_bootmem_info_section(unsigned long start_= pfn) { unsigned long mapsize, section_nr, i; @@ -100,7 +64,6 @@ static void __init register_page_bootmem_info_section(un= signed long start_pfn) for (i =3D 0; i < mapsize; i++, page++) get_page_bootmem(section_nr, page, MIX_SECTION_INFO); } -#endif /* !CONFIG_SPARSEMEM_VMEMMAP */ =20 void __init register_page_bootmem_info_node(struct pglist_data *pgdat) { --=20 2.43.0 From nobody Sat Apr 4 01:47:51 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AA75435AC11; Fri, 20 Mar 2026 22:14:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044857; cv=none; b=nHRtDARj9Zp99CUptJVSaQR39UHpbBLIdOk3gOZ8eLUeEw9EKOaO8mrJjARrwjva6OvEZtxfZ6Ah6Pi8cYJ4RRFiYamRLhhNeRt8FV+NaTNbh+/og9lyIk7xuqXd4IRYhHIfkgm9xbyHuygIQ9JqZEwzFjXo6i9rYBPdaLIZphE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044857; c=relaxed/simple; bh=0oSe+G0ox51l+rDc5XWCPrdWsQFUFWnEkGK5VjFVki8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=NLFEWWA2NMhe+sNR0ztJMp9EP8p+pL+AT3yI9YpVaUAwObXr56m3djaLRxLzbZlYZRO8d0qK3yUrW7kuEv5X8PQuft6IYbZbz6+xIsRRCiVd2Ycsl9BR+9kF/qmTG2+l7CDNZOYkmrWAo+1wJYa97Q2hS4VOzt8a8T2dPZXgAcw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=H0/W1BGD; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="H0/W1BGD" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E2CEAC2BC9E; Fri, 20 Mar 2026 22:14:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774044857; bh=0oSe+G0ox51l+rDc5XWCPrdWsQFUFWnEkGK5VjFVki8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=H0/W1BGD21v37hv/vshpWeZPJIUG7Z+PAKpQpegkE2rMSL3nV8vmemwLkEqmGAqKE aIJLxod5bPaIFhk0JEsIr2N4weldzrcc3Zw0DZ3mmlFMdtwYshMcQDTU2fV+pEaEhl ZxWCkhqP3o9gcshisQvElHE8kAh8IjNxbkSoQ9R9CtK3DOCzidXm/vTlDvzpBAi59j 6vFWDdibKp6aLhEqrtJX9ezac64PXtpbT0N87txVKuXyOR009EjU+zhfmYKViMllk5 vce7g6QiPvGzq04BJqmkHud3AcOGsiQQsI7+czklwG/3ApFXHs15UsEjogrRFAzOBr KTMrQCRHHzHxQ== From: "David Hildenbrand (Arm)" Date: Fri, 20 Mar 2026 23:13:40 +0100 Subject: [PATCH v2 08/15] mm/bootmem_info: avoid using sparse_decode_mem_map() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260320-sparsemem_cleanups-v2-8-096addc8800d@kernel.org> References: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> In-Reply-To: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> To: linux-kernel@vger.kernel.org Cc: Andrew Morton , Oscar Salvador , Axel Rasmussen , Yuanchu Xie , Wei Xu , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Sidhartha Kumar , linux-mm@kvack.org, linux-cxl@vger.kernel.org, linux-riscv@lists.infradead.org, "David Hildenbrand (Arm)" X-Mailer: b4 0.13.0 With SPARSEMEM_VMEMMAP, we can just do a pfn_to_page(). It is not super clear whether the start_pfn is properly aligned ... so let's just make sure it is properly aligned to the start of the section. We will soon might try to remove the bootmem info completely, for now, just keep it working as is. Reviewed-by: Lorenzo Stoakes (Oracle) Reviewed-by: Mike Rapoport (Microsoft) Signed-off-by: David Hildenbrand (Arm) --- mm/bootmem_info.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/mm/bootmem_info.c b/mm/bootmem_info.c index e61e08e24924..3d7675a3ae04 100644 --- a/mm/bootmem_info.c +++ b/mm/bootmem_info.c @@ -44,17 +44,16 @@ static void __init register_page_bootmem_info_section(u= nsigned long start_pfn) { unsigned long mapsize, section_nr, i; struct mem_section *ms; - struct page *page, *memmap; struct mem_section_usage *usage; + struct page *page; =20 + start_pfn =3D SECTION_ALIGN_DOWN(start_pfn); section_nr =3D pfn_to_section_nr(start_pfn); ms =3D __nr_to_section(section_nr); =20 - memmap =3D sparse_decode_mem_map(ms->section_mem_map, section_nr); - if (!preinited_vmemmap_section(ms)) - register_page_bootmem_memmap(section_nr, memmap, - PAGES_PER_SECTION); + register_page_bootmem_memmap(section_nr, pfn_to_page(start_pfn), + PAGES_PER_SECTION); =20 usage =3D ms->usage; page =3D virt_to_page(usage); --=20 2.43.0 From nobody Sat Apr 4 01:47:51 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C3D8E34DCC8; Fri, 20 Mar 2026 22:14:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044861; cv=none; b=baMI1L8SRWlGYrC716JI8NOHHEJdxy6bRTuJQeCAx6HIeR0wDbqALOaKFu45w2OphkOD3lJNbS8zK0N3QavuHj0t16zPQj7Rb15i/49jZMXUKozJdDJjUmbrulq3R8pH5iFu1iIq9QkwyVZkjflVRhzBiQPzccbdw5kmSQItKWA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044861; c=relaxed/simple; bh=Vtv/qpTDQk/7inFFI0u5qucQjzvddf+x5J6ke/XAmFA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=oR8drS/KJlKNGgfT9GqTT9uozSXDf7pZ/5LDIpz3XELfutFd+yX3jjYCkfn6rSGgJS+DvkCH1uDkMxicH4JrpIa9ffaicfn9++kHaELTQwH1u7fqpasnV2CVIYjw+6y0b7cCkhZkATuPGYORGDKfqQPcXLJN+aSD+okwpLSpsgg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Q/60OwKZ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Q/60OwKZ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 076F1C2BC9E; Fri, 20 Mar 2026 22:14:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774044861; bh=Vtv/qpTDQk/7inFFI0u5qucQjzvddf+x5J6ke/XAmFA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Q/60OwKZJgZGnc4cuE408V8PndBf1ubURGRU3pC92Bz5GciFz+8dzq+3HsnIocd0n gxzy4ohI3Ime2QOU8SrTS3Kw9GahO4smn/TxyBflFuU5M9GxtyE1t8d1tpjZ7wKhx3 Iuos+t8Rdy0j6ZwSK5llN27ldgM6i2wHL2f/4eYNoM92JypVg4++ZRszDwNpxWBpWo K3XYvT9MoB0uuCrCf8OsJHhhnoc+FTuFI24fdT08ifh1HNPsxqtzBSaxC7e0oLpMBO oRACyLlddYQzfCjcLx2utXgz9aRZIzmsdiqbULKAwd2U8r728s+/99zYbP9sf3IgQ3 9/vkIovCOHohQ== From: "David Hildenbrand (Arm)" Date: Fri, 20 Mar 2026 23:13:41 +0100 Subject: [PATCH v2 09/15] mm/sparse: remove sparse_decode_mem_map() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260320-sparsemem_cleanups-v2-9-096addc8800d@kernel.org> References: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> In-Reply-To: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> To: linux-kernel@vger.kernel.org Cc: Andrew Morton , Oscar Salvador , Axel Rasmussen , Yuanchu Xie , Wei Xu , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Sidhartha Kumar , linux-mm@kvack.org, linux-cxl@vger.kernel.org, linux-riscv@lists.infradead.org, "David Hildenbrand (Arm)" X-Mailer: b4 0.13.0 section_deactivate() applies to CONFIG_SPARSEMEM_VMEMMAP only. So we can just use pfn_to_page() (after making sure we have the start PFN of the section), and remove sparse_decode_mem_map(). Reviewed-by: Lorenzo Stoakes (Oracle) Reviewed-by: Mike Rapoport (Microsoft) Signed-off-by: David Hildenbrand (Arm) --- include/linux/memory_hotplug.h | 2 -- mm/sparse.c | 16 +--------------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h index e77ef3d7ff73..815e908c4135 100644 --- a/include/linux/memory_hotplug.h +++ b/include/linux/memory_hotplug.h @@ -308,8 +308,6 @@ extern int sparse_add_section(int nid, unsigned long pf= n, struct dev_pagemap *pgmap); extern void sparse_remove_section(unsigned long pfn, unsigned long nr_page= s, struct vmem_altmap *altmap); -extern struct page *sparse_decode_mem_map(unsigned long coded_mem_map, - unsigned long pnum); extern struct zone *zone_for_pfn_range(enum mmop online_type, int nid, struct memory_group *group, unsigned long start_pfn, unsigned long nr_pages); diff --git a/mm/sparse.c b/mm/sparse.c index 875f718a4c79..b5825c9ee2f2 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -274,18 +274,6 @@ static unsigned long sparse_encode_mem_map(struct page= *mem_map, unsigned long p return coded_mem_map; } =20 -#ifdef CONFIG_MEMORY_HOTPLUG -/* - * Decode mem_map from the coded memmap - */ -struct page *sparse_decode_mem_map(unsigned long coded_mem_map, unsigned l= ong pnum) -{ - /* mask off the extra low bits of information */ - coded_mem_map &=3D SECTION_MAP_MASK; - return ((struct page *)coded_mem_map) + section_nr_to_pfn(pnum); -} -#endif /* CONFIG_MEMORY_HOTPLUG */ - static void __meminit sparse_init_one_section(struct mem_section *ms, unsigned long pnum, struct page *mem_map, struct mem_section_usage *usage, unsigned long flags) @@ -754,8 +742,6 @@ static void section_deactivate(unsigned long pfn, unsig= ned long nr_pages, =20 empty =3D is_subsection_map_empty(ms); if (empty) { - unsigned long section_nr =3D pfn_to_section_nr(pfn); - /* * Mark the section invalid so that valid_section() * return false. This prevents code from dereferencing @@ -774,7 +760,7 @@ static void section_deactivate(unsigned long pfn, unsig= ned long nr_pages, kfree_rcu(ms->usage, rcu); WRITE_ONCE(ms->usage, NULL); } - memmap =3D sparse_decode_mem_map(ms->section_mem_map, section_nr); + memmap =3D pfn_to_page(SECTION_ALIGN_DOWN(pfn)); } =20 /* --=20 2.43.0 From nobody Sat Apr 4 01:47:51 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1A64734B1A8; Fri, 20 Mar 2026 22:14:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044866; cv=none; b=rcibrkDHX9wCCDgEhKPeY2SHG8j0NdvbT43xn16nmI7lenn9vSm4ar7a6gRecpXpratn+pMwW1g5j5N1PVzrniJ3XRhxPVunfmTIl1f+tFU7p0WbIecOa/gJlWcTsPc5OVr6QdpCSqRta1TymAT03hdDNQWzAGt/9BjmvbykkAE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044866; c=relaxed/simple; bh=GbRJKi/UL19LjXb/zj2tspEF8IAz0ieC/2fklwT44sM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=JW/CMW7G6Zc0o8MIKF7Mq0rHw5G/rkjI4mU51fIgnn7Mib+q6q/te5Cin7Pwk6uVyCLS5mltfijo3rwrByJeubF8FBz73mr1nqmh3f28LgztyJx4BB/9vKz0VidVrXBzEHFdwPwb+UhTUOELnRbRu10YN6NmY7URqZLgk//i0iM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=g5I2WfVK; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="g5I2WfVK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3A917C2BC9E; Fri, 20 Mar 2026 22:14:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774044865; bh=GbRJKi/UL19LjXb/zj2tspEF8IAz0ieC/2fklwT44sM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=g5I2WfVK3kWIJW4Y7drVtMvENCcnoLxj1B0PMuN70dK6hIX0GLgNOQLITSZrmehJu eKLUowungftOUVOX4vo8v+M+qb4q74EIXld1PkuprCqDmAoednhpf2FjVWqYA8Sec0 64rQUWNlzhXHAAPTdNOSjB4TlKctYxJ1WeIgEpcmZRwNC1Wu0MiEEwaMnUgaZyIw2y X7vltLf2qCsp/TOD5FRvRm9LJ59Jqnyi5VLa6mP2STHCoAARya4QfoZjTaLjndiZCC 9Z/btgNOBl5E9pR6v53StvvyO5c9y9Vge+kRCJmVqoP6AQfAtr8PnMK80mlX42rC83 IC4qzcyUWrMvA== From: "David Hildenbrand (Arm)" Date: Fri, 20 Mar 2026 23:13:42 +0100 Subject: [PATCH v2 10/15] mm/sparse: remove CONFIG_MEMORY_HOTPLUG-specific usemap allocation handling Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260320-sparsemem_cleanups-v2-10-096addc8800d@kernel.org> References: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> In-Reply-To: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> To: linux-kernel@vger.kernel.org Cc: Andrew Morton , Oscar Salvador , Axel Rasmussen , Yuanchu Xie , Wei Xu , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Sidhartha Kumar , linux-mm@kvack.org, linux-cxl@vger.kernel.org, linux-riscv@lists.infradead.org, "David Hildenbrand (Arm)" X-Mailer: b4 0.13.0 In 2008, we added through commit 48c906823f39 ("memory hotplug: allocate usemap on the section with pgdat") quite some complexity to try allocating memory for the "usemap" (storing pageblock information per memory section) for a memory section close to the memory of the "pgdat" of the node. The goal was to make memory hotunplug of boot memory more likely to succeed. That commit also added some checks for circular dependencies between two memory sections, whereby two memory sections would contain each others usemap, turning both boot memory sections un-removable. However, in 2010, commit a4322e1bad91 ("sparsemem: Put usemap for one node together") started allocating the usemap for multiple memory sections on the same node in one chunk, effectively grouping all usemap allocations of the same node in a single memblock allocation. We don't really give guarantees about memory hotunplug of boot memory, and with the change in 2010, it is impossible in practice to get any circular dependencies. So let's simply remove this complexity. Reviewed-by: Lorenzo Stoakes (Oracle) Reviewed-by: Mike Rapoport (Microsoft) Signed-off-by: David Hildenbrand (Arm) --- mm/sparse.c | 100 +-------------------------------------------------------= ---- 1 file changed, 1 insertion(+), 99 deletions(-) diff --git a/mm/sparse.c b/mm/sparse.c index b5825c9ee2f2..e2048b1fbf5f 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -294,102 +294,6 @@ size_t mem_section_usage_size(void) return sizeof(struct mem_section_usage) + usemap_size(); } =20 -#ifdef CONFIG_MEMORY_HOTREMOVE -static inline phys_addr_t pgdat_to_phys(struct pglist_data *pgdat) -{ -#ifndef CONFIG_NUMA - VM_BUG_ON(pgdat !=3D &contig_page_data); - return __pa_symbol(&contig_page_data); -#else - return __pa(pgdat); -#endif -} - -static struct mem_section_usage * __init -sparse_early_usemaps_alloc_pgdat_section(struct pglist_data *pgdat, - unsigned long size) -{ - struct mem_section_usage *usage; - unsigned long goal, limit; - int nid; - /* - * A page may contain usemaps for other sections preventing the - * page being freed and making a section unremovable while - * other sections referencing the usemap remain active. Similarly, - * a pgdat can prevent a section being removed. If section A - * contains a pgdat and section B contains the usemap, both - * sections become inter-dependent. This allocates usemaps - * from the same section as the pgdat where possible to avoid - * this problem. - */ - goal =3D pgdat_to_phys(pgdat) & (PAGE_SECTION_MASK << PAGE_SHIFT); - limit =3D goal + (1UL << PA_SECTION_SHIFT); - nid =3D early_pfn_to_nid(goal >> PAGE_SHIFT); -again: - usage =3D memblock_alloc_try_nid(size, SMP_CACHE_BYTES, goal, limit, nid); - if (!usage && limit) { - limit =3D MEMBLOCK_ALLOC_ACCESSIBLE; - goto again; - } - return usage; -} - -static void __init check_usemap_section_nr(int nid, - struct mem_section_usage *usage) -{ - unsigned long usemap_snr, pgdat_snr; - static unsigned long old_usemap_snr; - static unsigned long old_pgdat_snr; - struct pglist_data *pgdat =3D NODE_DATA(nid); - int usemap_nid; - - /* First call */ - if (!old_usemap_snr) { - old_usemap_snr =3D NR_MEM_SECTIONS; - old_pgdat_snr =3D NR_MEM_SECTIONS; - } - - usemap_snr =3D pfn_to_section_nr(__pa(usage) >> PAGE_SHIFT); - pgdat_snr =3D pfn_to_section_nr(pgdat_to_phys(pgdat) >> PAGE_SHIFT); - if (usemap_snr =3D=3D pgdat_snr) - return; - - if (old_usemap_snr =3D=3D usemap_snr && old_pgdat_snr =3D=3D pgdat_snr) - /* skip redundant message */ - return; - - old_usemap_snr =3D usemap_snr; - old_pgdat_snr =3D pgdat_snr; - - usemap_nid =3D sparse_early_nid(__nr_to_section(usemap_snr)); - if (usemap_nid !=3D nid) { - pr_info("node %d must be removed before remove section %ld\n", - nid, usemap_snr); - return; - } - /* - * There is a circular dependency. - * Some platforms allow un-removable section because they will just - * gather other removable sections for dynamic partitioning. - * Just notify un-removable section's number here. - */ - pr_info("Section %ld and %ld (node %d) have a circular dependency on usem= ap and pgdat allocations\n", - usemap_snr, pgdat_snr, nid); -} -#else -static struct mem_section_usage * __init -sparse_early_usemaps_alloc_pgdat_section(struct pglist_data *pgdat, - unsigned long size) -{ - return memblock_alloc_node(size, SMP_CACHE_BYTES, pgdat->node_id); -} - -static void __init check_usemap_section_nr(int nid, - struct mem_section_usage *usage) -{ -} -#endif /* CONFIG_MEMORY_HOTREMOVE */ - #ifdef CONFIG_SPARSEMEM_VMEMMAP unsigned long __init section_map_size(void) { @@ -486,7 +390,6 @@ void __init sparse_init_early_section(int nid, struct p= age *map, unsigned long pnum, unsigned long flags) { BUG_ON(!sparse_usagebuf || sparse_usagebuf >=3D sparse_usagebuf_end); - check_usemap_section_nr(nid, sparse_usagebuf); sparse_init_one_section(__nr_to_section(pnum), pnum, map, sparse_usagebuf, SECTION_IS_EARLY | flags); sparse_usagebuf =3D (void *)sparse_usagebuf + mem_section_usage_size(); @@ -497,8 +400,7 @@ static int __init sparse_usage_init(int nid, unsigned l= ong map_count) unsigned long size; =20 size =3D mem_section_usage_size() * map_count; - sparse_usagebuf =3D sparse_early_usemaps_alloc_pgdat_section( - NODE_DATA(nid), size); + sparse_usagebuf =3D memblock_alloc_node(size, SMP_CACHE_BYTES, nid); if (!sparse_usagebuf) { sparse_usagebuf_end =3D NULL; return -ENOMEM; --=20 2.43.0 From nobody Sat Apr 4 01:47:51 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 41D2D34B1A8; Fri, 20 Mar 2026 22:14:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044870; cv=none; b=THE824UjPlDxeBoRWI8JfogKPQKRXoq9Hvr8xEIyLrGz6qvzCBM4sqKrvamqf9hgt0BIC/XKMHJkfaeCVx6Xy2UNAuLCWSuLUi3W1pWrifNlaZVw00GYYeRWWqSjnx40oHhSqX76i7obn+wgC/r1/ZkISLsxBla24PnQQGICdS8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044870; c=relaxed/simple; bh=96Y5hAnwqjZz29h98raybd4EwBxokxu/LgenBd+sLbQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=LYPXydDzWo1Va3wCVfR1ksvZYR16yJspGqBv3cYYo2SwmsHnQMYtz6ePVn01rX+U7fZS+2gQwqdyqx/deTKivSD8EmRSrCb1kY5ZfGQOliJ3q1aJg/mOwNn6q5DQ9knfKFNgZfZDEXB3AeUAvfOFe5NTRE3PUNUeZky7TeugOqM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IHLJ7uy8; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="IHLJ7uy8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4FBCBC2BC87; Fri, 20 Mar 2026 22:14:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774044870; bh=96Y5hAnwqjZz29h98raybd4EwBxokxu/LgenBd+sLbQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=IHLJ7uy8oSWAv0WFrwtVAb5aqpsuUpirtjWzxOOeikkn8Cnj9WwzIvvRij484C45D sDFL5mLdqScUm2fzsvdEC1JdLzvfsyk36kWc35PHmbWLs9cVbdiJLPGF62cKICafDO FvnFCZhQ8o637F4GYescmIZk/JpTP9gIjiPNGg/V4UZUriDHGypjOdxwvdW0FCR0K/ 1WFbCMNsgJnoktrK7x7yyswl4f1lMAvZ7eR9vfmwjEr8qzpMoFgMx8wbw1VC/InmpH XRuHYmRJ+fUci09hGRGZwOpykKU7rmJk/cRic01Os9XnQTPnJfW0X7UsPtpQ+w+21D OWMtzKPIBKBBg== From: "David Hildenbrand (Arm)" Date: Fri, 20 Mar 2026 23:13:43 +0100 Subject: [PATCH v2 11/15] mm: prepare to move subsection_map_init() to mm/sparse-vmemmap.c Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260320-sparsemem_cleanups-v2-11-096addc8800d@kernel.org> References: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> In-Reply-To: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> To: linux-kernel@vger.kernel.org Cc: Andrew Morton , Oscar Salvador , Axel Rasmussen , Yuanchu Xie , Wei Xu , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Sidhartha Kumar , linux-mm@kvack.org, linux-cxl@vger.kernel.org, linux-riscv@lists.infradead.org, "David Hildenbrand (Arm)" X-Mailer: b4 0.13.0 We want to move subsection_map_init() to mm/sparse-vmemmap.c. To prepare for getting rid of subsection_map_init() in mm/sparse.c completely, use a static inline function for !CONFIG_SPARSEMEM_VMEMMAP. While at it, move the declaration to internal.h and rename it to "sparse_init_subsection_map()". Reviewed-by: Lorenzo Stoakes (Oracle) Reviewed-by: Mike Rapoport (Microsoft) Signed-off-by: David Hildenbrand (Arm) --- include/linux/mmzone.h | 3 --- mm/internal.h | 12 ++++++++++++ mm/mm_init.c | 2 +- mm/sparse.c | 6 +----- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 7bd0134c241c..b694c69dee04 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -2002,8 +2002,6 @@ struct mem_section_usage { unsigned long pageblock_flags[0]; }; =20 -void subsection_map_init(unsigned long pfn, unsigned long nr_pages); - struct page; struct page_ext; struct mem_section { @@ -2396,7 +2394,6 @@ static inline unsigned long next_present_section_nr(u= nsigned long section_nr) #define sparse_vmemmap_init_nid_early(_nid) do {} while (0) #define sparse_vmemmap_init_nid_late(_nid) do {} while (0) #define pfn_in_present_section pfn_valid -#define subsection_map_init(_pfn, _nr_pages) do {} while (0) #endif /* CONFIG_SPARSEMEM */ =20 /* diff --git a/mm/internal.h b/mm/internal.h index f98f4746ac41..5f5c45d80aca 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -960,12 +960,24 @@ void memmap_init_range(unsigned long, int, unsigned l= ong, unsigned long, unsigned long, enum meminit_context, struct vmem_altmap *, int, bool); =20 +/* + * mm/sparse.c + */ #ifdef CONFIG_SPARSEMEM void sparse_init(void); #else static inline void sparse_init(void) {} #endif /* CONFIG_SPARSEMEM */ =20 +#ifdef CONFIG_SPARSEMEM_VMEMMAP +void sparse_init_subsection_map(unsigned long pfn, unsigned long nr_pages); +#else +static inline void sparse_init_subsection_map(unsigned long pfn, + unsigned long nr_pages) +{ +} +#endif /* CONFIG_SPARSEMEM_VMEMMAP */ + #if defined CONFIG_COMPACTION || defined CONFIG_CMA =20 /* diff --git a/mm/mm_init.c b/mm/mm_init.c index 969048f9b320..3c5f18537cd1 100644 --- a/mm/mm_init.c +++ b/mm/mm_init.c @@ -1898,7 +1898,7 @@ static void __init free_area_init(void) pr_info(" node %3d: [mem %#018Lx-%#018Lx]\n", nid, (u64)start_pfn << PAGE_SHIFT, ((u64)end_pfn << PAGE_SHIFT) - 1); - subsection_map_init(start_pfn, end_pfn - start_pfn); + sparse_init_subsection_map(start_pfn, end_pfn - start_pfn); } =20 /* Initialise every node */ diff --git a/mm/sparse.c b/mm/sparse.c index e2048b1fbf5f..c96ac5e70c22 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -185,7 +185,7 @@ static void subsection_mask_set(unsigned long *map, uns= igned long pfn, bitmap_set(map, idx, end - idx + 1); } =20 -void __init subsection_map_init(unsigned long pfn, unsigned long nr_pages) +void __init sparse_init_subsection_map(unsigned long pfn, unsigned long nr= _pages) { int end_sec_nr =3D pfn_to_section_nr(pfn + nr_pages - 1); unsigned long nr, start_sec_nr =3D pfn_to_section_nr(pfn); @@ -207,10 +207,6 @@ void __init subsection_map_init(unsigned long pfn, uns= igned long nr_pages) nr_pages -=3D pfns; } } -#else -void __init subsection_map_init(unsigned long pfn, unsigned long nr_pages) -{ -} #endif =20 /* Record a memory area against a node. */ --=20 2.43.0 From nobody Sat Apr 4 01:47:51 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 81BD23446A6; Fri, 20 Mar 2026 22:14:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044874; cv=none; b=FpKKE/3PuyomjzDMiFvdVzqZnJ3GVD4sEHO1irEFNmoaEs9eXD4au/5Ts9b6iTmfXKgt0BiVEAQcA3oS5OVA2HcvvN+MFojoIWbiXHG/uwQO5dEBUaPZNzFYJ2jl3uMch1IE85ahgpETfItUomPoNILhENDAgvXYUqMT/0TMYkI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044874; c=relaxed/simple; bh=XAHrKqjSHvtKR09gmzZ7AHRzSFFlyVf9ZATZwJh+JJg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ehYuBgGdQjzbVDRPkPhe4FB9WF4m/648DhuLELwuGKT+9+uS341MveD4pO8ad5NnqZUQvu6E1mTgYYngS/hHGy8If5thkJKjgWnF2S3eFZys0h2C6M5iRm3a08FNsa6NLGQViPyVdpnBNVdgx0oOb264Je/GF+MmKNWnsKCnp6E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=he83wHJ6; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="he83wHJ6" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 80082C2BC87; Fri, 20 Mar 2026 22:14:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774044874; bh=XAHrKqjSHvtKR09gmzZ7AHRzSFFlyVf9ZATZwJh+JJg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=he83wHJ6PtaTiQddZeECQUCHe56n6mKcu8hA4rCvY8qPeiTp9pvI0nuQaIgKVVheS fwqIjKoF6a2O37LFplX2/a8iqRJ2y5b88VJmAJjAexMzHSr/d+OXTwuH0/n/aw/2kG pe8AoJbYZCphhAsSJt9zKgebzodTB5GHH/Koby6PCMOF8Iu1iXweiApBOX/ngZQOY8 Ut4FR3P0CEhcyvu0plHJrghUEKD+R8c6gIhegpQU8Pn0h1NNnXjHlTCsHWDRdaxfCX tzIzJ9xom8PLs1C920nHcEa68Y4UbWrSPDJXagKphEeyEcTAcA/nAsU3gkKICSeI50 plec3jOq8bwZQ== From: "David Hildenbrand (Arm)" Date: Fri, 20 Mar 2026 23:13:44 +0100 Subject: [PATCH v2 12/15] mm/sparse: drop set_section_nid() from sparse_add_section() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260320-sparsemem_cleanups-v2-12-096addc8800d@kernel.org> References: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> In-Reply-To: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> To: linux-kernel@vger.kernel.org Cc: Andrew Morton , Oscar Salvador , Axel Rasmussen , Yuanchu Xie , Wei Xu , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Sidhartha Kumar , linux-mm@kvack.org, linux-cxl@vger.kernel.org, linux-riscv@lists.infradead.org, "David Hildenbrand (Arm)" X-Mailer: b4 0.13.0 CONFIG_MEMORY_HOTPLUG is CONFIG_SPARSEMEM_VMEMMAP-only. And CONFIG_SPARSEMEM_VMEMMAP implies that NODE_NOT_IN_PAGE_FLAGS cannot be set: see include/linux/page-flags-layout.h ... #elif defined(CONFIG_SPARSEMEM_VMEMMAP) #error "Vmemmap: No space for nodes field in page flags" ... Which implies that the node is always stored in page flags and NODE_NOT_IN_PAGE_FLAGS cannot be set. Therefore, set_section_nid() is a NOP on CONFIG_SPARSEMEM_VMEMMAP. So let's remove the set_section_nid() call to prepare for moving CONFIG_MEMORY_HOTPLUG to mm/sparse-vmemmap.c Reviewed-by: Lorenzo Stoakes (Oracle) Reviewed-by: Mike Rapoport (Microsoft) Signed-off-by: David Hildenbrand (Arm) --- mm/sparse.c | 1 - 1 file changed, 1 deletion(-) diff --git a/mm/sparse.c b/mm/sparse.c index c96ac5e70c22..5c9cad390282 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -765,7 +765,6 @@ int __meminit sparse_add_section(int nid, unsigned long= start_pfn, page_init_poison(memmap, sizeof(struct page) * nr_pages); =20 ms =3D __nr_to_section(section_nr); - set_section_nid(section_nr, nid); __section_mark_present(ms, section_nr); =20 /* Align memmap to section boundary in the subsection case */ --=20 2.43.0 From nobody Sat Apr 4 01:47:51 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B94C735A925; Fri, 20 Mar 2026 22:14:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044878; cv=none; b=DI7Z/iEzyJ5q21uTDOonO7dfBf4Og5GrKI3gg8bZmG5eiJaf+1IlOQrVAYNQ1wQZzoepRm+hhRDc8pIG+XVmzD3QU5uIysSnLE7kHkLBZgGcdcjJflSvdgHsjHSvzJlTf/DKg1qNKqTCjNvh6NroMZpbMQf8GktAASPtpqUUYeM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044878; c=relaxed/simple; bh=y3sgZkTrQ7ucF18Vg7qRa+O7aPCnDHgstTSd5M9UBOY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=eXqjvE/bj9nqxXcZKHF/v7b1vIQy3pRlSyxkx6jDffqN4owTLtC/jRp5s1M5aYDldawV5vlWOH+EVDiiadL/6GmkPvi8rfFSH0QRn0yLIKZx5dSV945uTuS8Se1UhddK3QXnnd5fo+ice0OdOQg3nBIXnA5KgeI2YLCEhJliCoI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TslszDhS; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="TslszDhS" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B066CC4CEF7; Fri, 20 Mar 2026 22:14:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774044878; bh=y3sgZkTrQ7ucF18Vg7qRa+O7aPCnDHgstTSd5M9UBOY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=TslszDhSAzMDVRIyuMv6paGVgSsd2CzTi2m+XDZauLL+oMPD8nN2y19WOg5QAxcN8 MJkxnPJI13xWM/TQBuUVFa8i2WBfcrPqP1pN4JyiIYxzvSpK68kow0YUXzxMwjLIvA PZfMcLRp38aeBp/XZ/scY6XOVW8u6R2Vl2bxg7ZCjPYl5+Zw1cWeOJK9ueZjsjOuBI /f+WZSPbGmI8Ms+0wdaf/gI3Ef6Dwbp58ZS76mf9o54sv2J4dxehoWLmTRoayHRyve UXsBVGWUjpn8Bff33KBzLTvQ6RK33x76NgUJDEqM9svExTt2X8h0wOTNQ+4FrOCJLF 6X7zc7Xpdr5tg== From: "David Hildenbrand (Arm)" Date: Fri, 20 Mar 2026 23:13:45 +0100 Subject: [PATCH v2 13/15] mm/sparse: move sparse_init_one_section() to internal.h Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260320-sparsemem_cleanups-v2-13-096addc8800d@kernel.org> References: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> In-Reply-To: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> To: linux-kernel@vger.kernel.org Cc: Andrew Morton , Oscar Salvador , Axel Rasmussen , Yuanchu Xie , Wei Xu , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Sidhartha Kumar , linux-mm@kvack.org, linux-cxl@vger.kernel.org, linux-riscv@lists.infradead.org, "David Hildenbrand (Arm)" X-Mailer: b4 0.13.0 While at it, convert the BUG_ON to a VM_WARN_ON_ONCE, avoid long lines, and merge sparse_encode_mem_map() into its only caller sparse_init_one_section(). Clarify the comment a bit, pointing at page_to_pfn(). Reviewed-by: Lorenzo Stoakes (Oracle) Reviewed-by: Mike Rapoport (Microsoft) Signed-off-by: David Hildenbrand (Arm) --- include/linux/mmzone.h | 2 +- mm/internal.h | 22 ++++++++++++++++++++++ mm/sparse.c | 24 ------------------------ 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index b694c69dee04..dcbbf36ed88c 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -2008,7 +2008,7 @@ struct mem_section { /* * This is, logically, a pointer to an array of struct * pages. However, it is stored with some other magic. - * (see sparse.c::sparse_init_one_section()) + * (see sparse_init_one_section()) * * Additionally during early boot we encode node id of * the location of the section here to guide allocation. diff --git a/mm/internal.h b/mm/internal.h index 5f5c45d80aca..2f188f7702f7 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -965,6 +965,28 @@ void memmap_init_range(unsigned long, int, unsigned lo= ng, unsigned long, */ #ifdef CONFIG_SPARSEMEM void sparse_init(void); + +static inline void sparse_init_one_section(struct mem_section *ms, + unsigned long pnum, struct page *mem_map, + struct mem_section_usage *usage, unsigned long flags) +{ + unsigned long coded_mem_map; + + BUILD_BUG_ON(SECTION_MAP_LAST_BIT > PFN_SECTION_SHIFT); + + /* + * We encode the start PFN of the section into the mem_map such that + * page_to_pfn() on !CONFIG_SPARSEMEM_VMEMMAP can simply subtract it + * from the page pointer to obtain the PFN. + */ + coded_mem_map =3D (unsigned long)(mem_map - section_nr_to_pfn(pnum)); + VM_WARN_ON(coded_mem_map & ~SECTION_MAP_MASK); + + ms->section_mem_map &=3D ~SECTION_MAP_MASK; + ms->section_mem_map |=3D coded_mem_map; + ms->section_mem_map |=3D flags | SECTION_HAS_MEM_MAP; + ms->usage =3D usage; +} #else static inline void sparse_init(void) {} #endif /* CONFIG_SPARSEMEM */ diff --git a/mm/sparse.c b/mm/sparse.c index 5c9cad390282..ed5de1a25f04 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -256,30 +256,6 @@ static void __init memblocks_present(void) memory_present(nid, start, end); } =20 -/* - * Subtle, we encode the real pfn into the mem_map such that - * the identity pfn - section_mem_map will return the actual - * physical page frame number. - */ -static unsigned long sparse_encode_mem_map(struct page *mem_map, unsigned = long pnum) -{ - unsigned long coded_mem_map =3D - (unsigned long)(mem_map - (section_nr_to_pfn(pnum))); - BUILD_BUG_ON(SECTION_MAP_LAST_BIT > PFN_SECTION_SHIFT); - BUG_ON(coded_mem_map & ~SECTION_MAP_MASK); - return coded_mem_map; -} - -static void __meminit sparse_init_one_section(struct mem_section *ms, - unsigned long pnum, struct page *mem_map, - struct mem_section_usage *usage, unsigned long flags) -{ - ms->section_mem_map &=3D ~SECTION_MAP_MASK; - ms->section_mem_map |=3D sparse_encode_mem_map(mem_map, pnum) - | SECTION_HAS_MEM_MAP | flags; - ms->usage =3D usage; -} - static unsigned long usemap_size(void) { return BITS_TO_LONGS(SECTION_BLOCKFLAGS_BITS) * sizeof(unsigned long); --=20 2.43.0 From nobody Sat Apr 4 01:47:51 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C9D703815CD; Fri, 20 Mar 2026 22:14:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044882; cv=none; b=atESqivwmDMUhzPvRNSiMJdrFxwMS01BBltjOFrfM4g9vR8S11MqCv7C+ea815tTTODa9X1IesOqqKg2KUzzyo8i2oT7hRdURz3mmlaWDX3W5UTFhd9xRz7/9S/v8v+RUCuqLSQ93d09yV1toPBQ4vDui0lYAkzRf14J/6LTgdM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044882; c=relaxed/simple; bh=nAADk4O++zlIdaSsGnqecpm2JFYNOEQEolE0epkoJXM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=KsqHB0+wPU0iFqhBKyd/u4PSLj1reXEkJyxLxeUjBqIghsPc5aGiddReEd13hrXeHtabwEPd0K7b1c1rlvAbJyv6ZruAThUXJ5cO2mn5QVXhRP3JZmtH5s6OjDoGkK8BzaprjD1ORb4ee8PRmLjuMwNfsKufVGiAb6z7E3ZFBWk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Cx1QfJei; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Cx1QfJei" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E0CE7C2BCAF; Fri, 20 Mar 2026 22:14:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774044882; bh=nAADk4O++zlIdaSsGnqecpm2JFYNOEQEolE0epkoJXM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Cx1QfJeiw+fJiVi+TEUgbrb9326n7iVHjUNLjnMKlj6iprB7t2rO+Imn/dWGqdEq7 YfNIyImYbgavmRQUEAmCNUElbh5Kg1BFoe5ptLbRuN7ZuReCZI4rDY2a5jP7YFa8px 3Dok4Agv9vTrsTBNtsOBpywS0B05t15ubKY0+5O73+1FriKKgr5AGs+05Tvmqv7AdU RyCJAM88Hs+79PzvgYeXn5SyIVMvqyy3JQ8WpvMDwEKL4HxAu0dR37XakI55NSR2rh eRrtwzRqU4cSFG1lF8DErPwB1lfPA7mQ94KCMiW+AgFVXhOqgZu5WkrNADCZ1pDXHB SiY7M3MEQJVBQ== From: "David Hildenbrand (Arm)" Date: Fri, 20 Mar 2026 23:13:46 +0100 Subject: [PATCH v2 14/15] mm/sparse: move __section_mark_present() to internal.h Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260320-sparsemem_cleanups-v2-14-096addc8800d@kernel.org> References: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> In-Reply-To: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> To: linux-kernel@vger.kernel.org Cc: Andrew Morton , Oscar Salvador , Axel Rasmussen , Yuanchu Xie , Wei Xu , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Sidhartha Kumar , linux-mm@kvack.org, linux-cxl@vger.kernel.org, linux-riscv@lists.infradead.org, "David Hildenbrand (Arm)" X-Mailer: b4 0.13.0 Let's prepare for moving memory hotplug handling from sparse.c to sparse-vmemmap.c by moving __section_mark_present() to internal.h. Reviewed-by: Mike Rapoport (Microsoft) Reviewed-by: Lorenzo Stoakes (Oracle) Signed-off-by: David Hildenbrand (Arm) --- mm/internal.h | 9 +++++++++ mm/sparse.c | 8 -------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/mm/internal.h b/mm/internal.h index 2f188f7702f7..b002c91e40a5 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -987,6 +987,15 @@ static inline void sparse_init_one_section(struct mem_= section *ms, ms->section_mem_map |=3D flags | SECTION_HAS_MEM_MAP; ms->usage =3D usage; } + +static inline void __section_mark_present(struct mem_section *ms, + unsigned long section_nr) +{ + if (section_nr > __highest_present_section_nr) + __highest_present_section_nr =3D section_nr; + + ms->section_mem_map |=3D SECTION_MARKED_PRESENT; +} #else static inline void sparse_init(void) {} #endif /* CONFIG_SPARSEMEM */ diff --git a/mm/sparse.c b/mm/sparse.c index ed5de1a25f04..ecd4c41c0ff0 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -161,14 +161,6 @@ static void __meminit mminit_validate_memmodel_limits(= unsigned long *start_pfn, * those loops early. */ unsigned long __highest_present_section_nr; -static void __section_mark_present(struct mem_section *ms, - unsigned long section_nr) -{ - if (section_nr > __highest_present_section_nr) - __highest_present_section_nr =3D section_nr; - - ms->section_mem_map |=3D SECTION_MARKED_PRESENT; -} =20 static inline unsigned long first_present_section_nr(void) { --=20 2.43.0 From nobody Sat Apr 4 01:47:51 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 04B6A3815CD; Fri, 20 Mar 2026 22:14:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044887; cv=none; b=ZKz+P6Lvh6FT0BsAg484DjA811O7JOz73K56uFFKHw3mM/74qEkW8MLlxUKRewz6/ypP85ZsSqNYIodySHBSATZ3SYe3L8kfSbOqZ+C7vsXBwgLZ+Fnmzz5Igx1yo8HVQIkjpGisqysA271233tMYEhSOytO+qsFGbI+Q9v2GBE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774044887; c=relaxed/simple; bh=eJ5LJmBygj38sotSWrTqqnRQBxx9S09xuHHuoQllTf4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=fbIh51PPuHK0GmuS2ewz0h6GMZRKT5KJBzFw7ZrL4v1fZpLoUREW9iL9kKcXZRHVFZqQTvYhJZP7zAEPpqc+5T8gLHurFLTnpyXuTAGmpYp6YfLljgOu635gvLQL5xM2sIQI3AR8C8eONQWiq3PYBpa+tDBgLexHfSncuKThqfE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fOZqms56; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="fOZqms56" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0415BC2BC9E; Fri, 20 Mar 2026 22:14:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774044886; bh=eJ5LJmBygj38sotSWrTqqnRQBxx9S09xuHHuoQllTf4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=fOZqms56Detoy7Ovql6hpqyFtIeGu2lGm8UYHQTWjXWW07wX+NrF400TJE7KR77iF 9iCuUdABYnU76QMfikTfpFzS/Hvt6CBqZniMNHd19YOw1xDd5XMqF14wdMiaekrhhz qhnwaetcd3jJkelgH1rnPvfWuZFFqGIbxeENC9nn/Kr3ltIHWKUzBzTZ+CaB2kf7lZ 1xKdVDw2rqCl0Pjlqj0t4KrOwpm43JEyKX/DBfvImIOe2FHRCwwvZG0Ldi6xHpAoUN Mnl5e4sno4aqrQ87l6rQMAXZF4brrhoHmbWYxQ5CAjXrgaVbepoHy29TJZ3Es+E1n9 Sh9ug6YAQ3Iog== From: "David Hildenbrand (Arm)" Date: Fri, 20 Mar 2026 23:13:47 +0100 Subject: [PATCH v2 15/15] mm/sparse: move memory hotplug bits to sparse-vmemmap.c Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260320-sparsemem_cleanups-v2-15-096addc8800d@kernel.org> References: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> In-Reply-To: <20260320-sparsemem_cleanups-v2-0-096addc8800d@kernel.org> To: linux-kernel@vger.kernel.org Cc: Andrew Morton , Oscar Salvador , Axel Rasmussen , Yuanchu Xie , Wei Xu , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Sidhartha Kumar , linux-mm@kvack.org, linux-cxl@vger.kernel.org, linux-riscv@lists.infradead.org, "David Hildenbrand (Arm)" X-Mailer: b4 0.13.0 Let's move all memory hoptplug related code to sparse-vmemmap.c. We only have to expose sparse_index_init(). While at it, drop the definition of sparse_index_init() for !CONFIG_SPARSEMEM, which is unused, and place the declaration in internal.h. Reviewed-by: Lorenzo Stoakes (Oracle) Reviewed-by: Mike Rapoport (Microsoft) Signed-off-by: David Hildenbrand (Arm) --- include/linux/mmzone.h | 1 - mm/internal.h | 4 + mm/sparse-vmemmap.c | 304 +++++++++++++++++++++++++++++++++++++++++++++= +++ mm/sparse.c | 310 +--------------------------------------------= ---- 4 files changed, 310 insertions(+), 309 deletions(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index dcbbf36ed88c..e11513f581eb 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -2390,7 +2390,6 @@ static inline unsigned long next_present_section_nr(u= nsigned long section_nr) #endif =20 #else -#define sparse_index_init(_sec, _nid) do {} while (0) #define sparse_vmemmap_init_nid_early(_nid) do {} while (0) #define sparse_vmemmap_init_nid_late(_nid) do {} while (0) #define pfn_in_present_section pfn_valid diff --git a/mm/internal.h b/mm/internal.h index b002c91e40a5..83e781147a28 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -965,6 +965,7 @@ void memmap_init_range(unsigned long, int, unsigned lon= g, unsigned long, */ #ifdef CONFIG_SPARSEMEM void sparse_init(void); +int sparse_index_init(unsigned long section_nr, int nid); =20 static inline void sparse_init_one_section(struct mem_section *ms, unsigned long pnum, struct page *mem_map, @@ -1000,6 +1001,9 @@ static inline void __section_mark_present(struct mem_= section *ms, static inline void sparse_init(void) {} #endif /* CONFIG_SPARSEMEM */ =20 +/* + * mm/sparse-vmemmap.c + */ #ifdef CONFIG_SPARSEMEM_VMEMMAP void sparse_init_subsection_map(unsigned long pfn, unsigned long nr_pages); #else diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c index f0690797667f..08fef7b5c8b0 100644 --- a/mm/sparse-vmemmap.c +++ b/mm/sparse-vmemmap.c @@ -591,3 +591,307 @@ void __init sparse_vmemmap_init_nid_late(int nid) hugetlb_vmemmap_init_late(nid); } #endif + +static void subsection_mask_set(unsigned long *map, unsigned long pfn, + unsigned long nr_pages) +{ + int idx =3D subsection_map_index(pfn); + int end =3D subsection_map_index(pfn + nr_pages - 1); + + bitmap_set(map, idx, end - idx + 1); +} + +void __init sparse_init_subsection_map(unsigned long pfn, unsigned long nr= _pages) +{ + int end_sec_nr =3D pfn_to_section_nr(pfn + nr_pages - 1); + unsigned long nr, start_sec_nr =3D pfn_to_section_nr(pfn); + + for (nr =3D start_sec_nr; nr <=3D end_sec_nr; nr++) { + struct mem_section *ms; + unsigned long pfns; + + pfns =3D min(nr_pages, PAGES_PER_SECTION + - (pfn & ~PAGE_SECTION_MASK)); + ms =3D __nr_to_section(nr); + subsection_mask_set(ms->usage->subsection_map, pfn, pfns); + + pr_debug("%s: sec: %lu pfns: %lu set(%d, %d)\n", __func__, nr, + pfns, subsection_map_index(pfn), + subsection_map_index(pfn + pfns - 1)); + + pfn +=3D pfns; + nr_pages -=3D pfns; + } +} + +#ifdef CONFIG_MEMORY_HOTPLUG + +/* Mark all memory sections within the pfn range as online */ +void online_mem_sections(unsigned long start_pfn, unsigned long end_pfn) +{ + unsigned long pfn; + + for (pfn =3D start_pfn; pfn < end_pfn; pfn +=3D PAGES_PER_SECTION) { + unsigned long section_nr =3D pfn_to_section_nr(pfn); + struct mem_section *ms =3D __nr_to_section(section_nr); + + ms->section_mem_map |=3D SECTION_IS_ONLINE; + } +} + +/* Mark all memory sections within the pfn range as offline */ +void offline_mem_sections(unsigned long start_pfn, unsigned long end_pfn) +{ + unsigned long pfn; + + for (pfn =3D start_pfn; pfn < end_pfn; pfn +=3D PAGES_PER_SECTION) { + unsigned long section_nr =3D pfn_to_section_nr(pfn); + struct mem_section *ms =3D __nr_to_section(section_nr); + + ms->section_mem_map &=3D ~SECTION_IS_ONLINE; + } +} + +static struct page * __meminit populate_section_memmap(unsigned long pfn, + unsigned long nr_pages, int nid, struct vmem_altmap *altmap, + struct dev_pagemap *pgmap) +{ + return __populate_section_memmap(pfn, nr_pages, nid, altmap, pgmap); +} + +static void depopulate_section_memmap(unsigned long pfn, unsigned long nr_= pages, + struct vmem_altmap *altmap) +{ + unsigned long start =3D (unsigned long) pfn_to_page(pfn); + unsigned long end =3D start + nr_pages * sizeof(struct page); + + vmemmap_free(start, end, altmap); +} +static void free_map_bootmem(struct page *memmap) +{ + unsigned long start =3D (unsigned long)memmap; + unsigned long end =3D (unsigned long)(memmap + PAGES_PER_SECTION); + + vmemmap_free(start, end, NULL); +} + +static int clear_subsection_map(unsigned long pfn, unsigned long nr_pages) +{ + DECLARE_BITMAP(map, SUBSECTIONS_PER_SECTION) =3D { 0 }; + DECLARE_BITMAP(tmp, SUBSECTIONS_PER_SECTION) =3D { 0 }; + struct mem_section *ms =3D __pfn_to_section(pfn); + unsigned long *subsection_map =3D ms->usage + ? &ms->usage->subsection_map[0] : NULL; + + subsection_mask_set(map, pfn, nr_pages); + if (subsection_map) + bitmap_and(tmp, map, subsection_map, SUBSECTIONS_PER_SECTION); + + if (WARN(!subsection_map || !bitmap_equal(tmp, map, SUBSECTIONS_PER_SECTI= ON), + "section already deactivated (%#lx + %ld)\n", + pfn, nr_pages)) + return -EINVAL; + + bitmap_xor(subsection_map, map, subsection_map, SUBSECTIONS_PER_SECTION); + return 0; +} + +static bool is_subsection_map_empty(struct mem_section *ms) +{ + return bitmap_empty(&ms->usage->subsection_map[0], + SUBSECTIONS_PER_SECTION); +} + +static int fill_subsection_map(unsigned long pfn, unsigned long nr_pages) +{ + struct mem_section *ms =3D __pfn_to_section(pfn); + DECLARE_BITMAP(map, SUBSECTIONS_PER_SECTION) =3D { 0 }; + unsigned long *subsection_map; + int rc =3D 0; + + subsection_mask_set(map, pfn, nr_pages); + + subsection_map =3D &ms->usage->subsection_map[0]; + + if (bitmap_empty(map, SUBSECTIONS_PER_SECTION)) + rc =3D -EINVAL; + else if (bitmap_intersects(map, subsection_map, SUBSECTIONS_PER_SECTION)) + rc =3D -EEXIST; + else + bitmap_or(subsection_map, map, subsection_map, + SUBSECTIONS_PER_SECTION); + + return rc; +} + +/* + * To deactivate a memory region, there are 3 cases to handle: + * + * 1. deactivation of a partial hot-added section: + * a) section was present at memory init. + * b) section was hot-added post memory init. + * 2. deactivation of a complete hot-added section. + * 3. deactivation of a complete section from memory init. + * + * For 1, when subsection_map does not empty we will not be freeing the + * usage map, but still need to free the vmemmap range. + */ +static void section_deactivate(unsigned long pfn, unsigned long nr_pages, + struct vmem_altmap *altmap) +{ + struct mem_section *ms =3D __pfn_to_section(pfn); + bool section_is_early =3D early_section(ms); + struct page *memmap =3D NULL; + bool empty; + + if (clear_subsection_map(pfn, nr_pages)) + return; + + empty =3D is_subsection_map_empty(ms); + if (empty) { + /* + * Mark the section invalid so that valid_section() + * return false. This prevents code from dereferencing + * ms->usage array. + */ + ms->section_mem_map &=3D ~SECTION_HAS_MEM_MAP; + + /* + * When removing an early section, the usage map is kept (as the + * usage maps of other sections fall into the same page). It + * will be re-used when re-adding the section - which is then no + * longer an early section. If the usage map is PageReserved, it + * was allocated during boot. + */ + if (!PageReserved(virt_to_page(ms->usage))) { + kfree_rcu(ms->usage, rcu); + WRITE_ONCE(ms->usage, NULL); + } + memmap =3D pfn_to_page(SECTION_ALIGN_DOWN(pfn)); + } + + /* + * The memmap of early sections is always fully populated. See + * section_activate() and pfn_valid() . + */ + if (!section_is_early) { + memmap_pages_add(-1L * (DIV_ROUND_UP(nr_pages * sizeof(struct page), PAG= E_SIZE))); + depopulate_section_memmap(pfn, nr_pages, altmap); + } else if (memmap) { + memmap_boot_pages_add(-1L * (DIV_ROUND_UP(nr_pages * sizeof(struct page), + PAGE_SIZE))); + free_map_bootmem(memmap); + } + + if (empty) + ms->section_mem_map =3D (unsigned long)NULL; +} + +static struct page * __meminit section_activate(int nid, unsigned long pfn, + unsigned long nr_pages, struct vmem_altmap *altmap, + struct dev_pagemap *pgmap) +{ + struct mem_section *ms =3D __pfn_to_section(pfn); + struct mem_section_usage *usage =3D NULL; + struct page *memmap; + int rc; + + if (!ms->usage) { + usage =3D kzalloc(mem_section_usage_size(), GFP_KERNEL); + if (!usage) + return ERR_PTR(-ENOMEM); + ms->usage =3D usage; + } + + rc =3D fill_subsection_map(pfn, nr_pages); + if (rc) { + if (usage) + ms->usage =3D NULL; + kfree(usage); + return ERR_PTR(rc); + } + + /* + * The early init code does not consider partially populated + * initial sections, it simply assumes that memory will never be + * referenced. If we hot-add memory into such a section then we + * do not need to populate the memmap and can simply reuse what + * is already there. + */ + if (nr_pages < PAGES_PER_SECTION && early_section(ms)) + return pfn_to_page(pfn); + + memmap =3D populate_section_memmap(pfn, nr_pages, nid, altmap, pgmap); + if (!memmap) { + section_deactivate(pfn, nr_pages, altmap); + return ERR_PTR(-ENOMEM); + } + memmap_pages_add(DIV_ROUND_UP(nr_pages * sizeof(struct page), PAGE_SIZE)); + + return memmap; +} + +/** + * sparse_add_section - add a memory section, or populate an existing one + * @nid: The node to add section on + * @start_pfn: start pfn of the memory range + * @nr_pages: number of pfns to add in the section + * @altmap: alternate pfns to allocate the memmap backing store + * @pgmap: alternate compound page geometry for devmap mappings + * + * This is only intended for hotplug. + * + * Note that only VMEMMAP supports sub-section aligned hotplug, + * the proper alignment and size are gated by check_pfn_span(). + * + * + * Return: + * * 0 - On success. + * * -EEXIST - Section has been present. + * * -ENOMEM - Out of memory. + */ +int __meminit sparse_add_section(int nid, unsigned long start_pfn, + unsigned long nr_pages, struct vmem_altmap *altmap, + struct dev_pagemap *pgmap) +{ + unsigned long section_nr =3D pfn_to_section_nr(start_pfn); + struct mem_section *ms; + struct page *memmap; + int ret; + + ret =3D sparse_index_init(section_nr, nid); + if (ret < 0) + return ret; + + memmap =3D section_activate(nid, start_pfn, nr_pages, altmap, pgmap); + if (IS_ERR(memmap)) + return PTR_ERR(memmap); + + /* + * Poison uninitialized struct pages in order to catch invalid flags + * combinations. + */ + page_init_poison(memmap, sizeof(struct page) * nr_pages); + + ms =3D __nr_to_section(section_nr); + __section_mark_present(ms, section_nr); + + /* Align memmap to section boundary in the subsection case */ + if (section_nr_to_pfn(section_nr) !=3D start_pfn) + memmap =3D pfn_to_page(section_nr_to_pfn(section_nr)); + sparse_init_one_section(ms, section_nr, memmap, ms->usage, 0); + + return 0; +} + +void sparse_remove_section(unsigned long pfn, unsigned long nr_pages, + struct vmem_altmap *altmap) +{ + struct mem_section *ms =3D __pfn_to_section(pfn); + + if (WARN_ON_ONCE(!valid_section(ms))) + return; + + section_deactivate(pfn, nr_pages, altmap); +} +#endif /* CONFIG_MEMORY_HOTPLUG */ diff --git a/mm/sparse.c b/mm/sparse.c index ecd4c41c0ff0..007fd52c621e 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -79,7 +79,7 @@ static noinline struct mem_section __ref *sparse_index_al= loc(int nid) return section; } =20 -static int __meminit sparse_index_init(unsigned long section_nr, int nid) +int __meminit sparse_index_init(unsigned long section_nr, int nid) { unsigned long root =3D SECTION_NR_TO_ROOT(section_nr); struct mem_section *section; @@ -103,7 +103,7 @@ static int __meminit sparse_index_init(unsigned long se= ction_nr, int nid) return 0; } #else /* !SPARSEMEM_EXTREME */ -static inline int sparse_index_init(unsigned long section_nr, int nid) +int sparse_index_init(unsigned long section_nr, int nid) { return 0; } @@ -167,40 +167,6 @@ static inline unsigned long first_present_section_nr(v= oid) return next_present_section_nr(-1); } =20 -#ifdef CONFIG_SPARSEMEM_VMEMMAP -static void subsection_mask_set(unsigned long *map, unsigned long pfn, - unsigned long nr_pages) -{ - int idx =3D subsection_map_index(pfn); - int end =3D subsection_map_index(pfn + nr_pages - 1); - - bitmap_set(map, idx, end - idx + 1); -} - -void __init sparse_init_subsection_map(unsigned long pfn, unsigned long nr= _pages) -{ - int end_sec_nr =3D pfn_to_section_nr(pfn + nr_pages - 1); - unsigned long nr, start_sec_nr =3D pfn_to_section_nr(pfn); - - for (nr =3D start_sec_nr; nr <=3D end_sec_nr; nr++) { - struct mem_section *ms; - unsigned long pfns; - - pfns =3D min(nr_pages, PAGES_PER_SECTION - - (pfn & ~PAGE_SECTION_MASK)); - ms =3D __nr_to_section(nr); - subsection_mask_set(ms->usage->subsection_map, pfn, pfns); - - pr_debug("%s: sec: %lu pfns: %lu set(%d, %d)\n", __func__, nr, - pfns, subsection_map_index(pfn), - subsection_map_index(pfn + pfns - 1)); - - pfn +=3D pfns; - nr_pages -=3D pfns; - } -} -#endif - /* Record a memory area against a node. */ static void __init memory_present(int nid, unsigned long start, unsigned l= ong end) { @@ -482,275 +448,3 @@ void __init sparse_init(void) sparse_init_nid(nid_begin, pnum_begin, pnum_end, map_count); vmemmap_populate_print_last(); } - -#ifdef CONFIG_MEMORY_HOTPLUG - -/* Mark all memory sections within the pfn range as online */ -void online_mem_sections(unsigned long start_pfn, unsigned long end_pfn) -{ - unsigned long pfn; - - for (pfn =3D start_pfn; pfn < end_pfn; pfn +=3D PAGES_PER_SECTION) { - unsigned long section_nr =3D pfn_to_section_nr(pfn); - struct mem_section *ms =3D __nr_to_section(section_nr); - - ms->section_mem_map |=3D SECTION_IS_ONLINE; - } -} - -/* Mark all memory sections within the pfn range as offline */ -void offline_mem_sections(unsigned long start_pfn, unsigned long end_pfn) -{ - unsigned long pfn; - - for (pfn =3D start_pfn; pfn < end_pfn; pfn +=3D PAGES_PER_SECTION) { - unsigned long section_nr =3D pfn_to_section_nr(pfn); - struct mem_section *ms =3D __nr_to_section(section_nr); - - ms->section_mem_map &=3D ~SECTION_IS_ONLINE; - } -} - -static struct page * __meminit populate_section_memmap(unsigned long pfn, - unsigned long nr_pages, int nid, struct vmem_altmap *altmap, - struct dev_pagemap *pgmap) -{ - return __populate_section_memmap(pfn, nr_pages, nid, altmap, pgmap); -} - -static void depopulate_section_memmap(unsigned long pfn, unsigned long nr_= pages, - struct vmem_altmap *altmap) -{ - unsigned long start =3D (unsigned long) pfn_to_page(pfn); - unsigned long end =3D start + nr_pages * sizeof(struct page); - - vmemmap_free(start, end, altmap); -} -static void free_map_bootmem(struct page *memmap) -{ - unsigned long start =3D (unsigned long)memmap; - unsigned long end =3D (unsigned long)(memmap + PAGES_PER_SECTION); - - vmemmap_free(start, end, NULL); -} - -static int clear_subsection_map(unsigned long pfn, unsigned long nr_pages) -{ - DECLARE_BITMAP(map, SUBSECTIONS_PER_SECTION) =3D { 0 }; - DECLARE_BITMAP(tmp, SUBSECTIONS_PER_SECTION) =3D { 0 }; - struct mem_section *ms =3D __pfn_to_section(pfn); - unsigned long *subsection_map =3D ms->usage - ? &ms->usage->subsection_map[0] : NULL; - - subsection_mask_set(map, pfn, nr_pages); - if (subsection_map) - bitmap_and(tmp, map, subsection_map, SUBSECTIONS_PER_SECTION); - - if (WARN(!subsection_map || !bitmap_equal(tmp, map, SUBSECTIONS_PER_SECTI= ON), - "section already deactivated (%#lx + %ld)\n", - pfn, nr_pages)) - return -EINVAL; - - bitmap_xor(subsection_map, map, subsection_map, SUBSECTIONS_PER_SECTION); - return 0; -} - -static bool is_subsection_map_empty(struct mem_section *ms) -{ - return bitmap_empty(&ms->usage->subsection_map[0], - SUBSECTIONS_PER_SECTION); -} - -static int fill_subsection_map(unsigned long pfn, unsigned long nr_pages) -{ - struct mem_section *ms =3D __pfn_to_section(pfn); - DECLARE_BITMAP(map, SUBSECTIONS_PER_SECTION) =3D { 0 }; - unsigned long *subsection_map; - int rc =3D 0; - - subsection_mask_set(map, pfn, nr_pages); - - subsection_map =3D &ms->usage->subsection_map[0]; - - if (bitmap_empty(map, SUBSECTIONS_PER_SECTION)) - rc =3D -EINVAL; - else if (bitmap_intersects(map, subsection_map, SUBSECTIONS_PER_SECTION)) - rc =3D -EEXIST; - else - bitmap_or(subsection_map, map, subsection_map, - SUBSECTIONS_PER_SECTION); - - return rc; -} - -/* - * To deactivate a memory region, there are 3 cases to handle: - * - * 1. deactivation of a partial hot-added section: - * a) section was present at memory init. - * b) section was hot-added post memory init. - * 2. deactivation of a complete hot-added section. - * 3. deactivation of a complete section from memory init. - * - * For 1, when subsection_map does not empty we will not be freeing the - * usage map, but still need to free the vmemmap range. - */ -static void section_deactivate(unsigned long pfn, unsigned long nr_pages, - struct vmem_altmap *altmap) -{ - struct mem_section *ms =3D __pfn_to_section(pfn); - bool section_is_early =3D early_section(ms); - struct page *memmap =3D NULL; - bool empty; - - if (clear_subsection_map(pfn, nr_pages)) - return; - - empty =3D is_subsection_map_empty(ms); - if (empty) { - /* - * Mark the section invalid so that valid_section() - * return false. This prevents code from dereferencing - * ms->usage array. - */ - ms->section_mem_map &=3D ~SECTION_HAS_MEM_MAP; - - /* - * When removing an early section, the usage map is kept (as the - * usage maps of other sections fall into the same page). It - * will be re-used when re-adding the section - which is then no - * longer an early section. If the usage map is PageReserved, it - * was allocated during boot. - */ - if (!PageReserved(virt_to_page(ms->usage))) { - kfree_rcu(ms->usage, rcu); - WRITE_ONCE(ms->usage, NULL); - } - memmap =3D pfn_to_page(SECTION_ALIGN_DOWN(pfn)); - } - - /* - * The memmap of early sections is always fully populated. See - * section_activate() and pfn_valid() . - */ - if (!section_is_early) { - memmap_pages_add(-1L * (DIV_ROUND_UP(nr_pages * sizeof(struct page), PAG= E_SIZE))); - depopulate_section_memmap(pfn, nr_pages, altmap); - } else if (memmap) { - memmap_boot_pages_add(-1L * (DIV_ROUND_UP(nr_pages * sizeof(struct page), - PAGE_SIZE))); - free_map_bootmem(memmap); - } - - if (empty) - ms->section_mem_map =3D (unsigned long)NULL; -} - -static struct page * __meminit section_activate(int nid, unsigned long pfn, - unsigned long nr_pages, struct vmem_altmap *altmap, - struct dev_pagemap *pgmap) -{ - struct mem_section *ms =3D __pfn_to_section(pfn); - struct mem_section_usage *usage =3D NULL; - struct page *memmap; - int rc; - - if (!ms->usage) { - usage =3D kzalloc(mem_section_usage_size(), GFP_KERNEL); - if (!usage) - return ERR_PTR(-ENOMEM); - ms->usage =3D usage; - } - - rc =3D fill_subsection_map(pfn, nr_pages); - if (rc) { - if (usage) - ms->usage =3D NULL; - kfree(usage); - return ERR_PTR(rc); - } - - /* - * The early init code does not consider partially populated - * initial sections, it simply assumes that memory will never be - * referenced. If we hot-add memory into such a section then we - * do not need to populate the memmap and can simply reuse what - * is already there. - */ - if (nr_pages < PAGES_PER_SECTION && early_section(ms)) - return pfn_to_page(pfn); - - memmap =3D populate_section_memmap(pfn, nr_pages, nid, altmap, pgmap); - if (!memmap) { - section_deactivate(pfn, nr_pages, altmap); - return ERR_PTR(-ENOMEM); - } - memmap_pages_add(DIV_ROUND_UP(nr_pages * sizeof(struct page), PAGE_SIZE)); - - return memmap; -} - -/** - * sparse_add_section - add a memory section, or populate an existing one - * @nid: The node to add section on - * @start_pfn: start pfn of the memory range - * @nr_pages: number of pfns to add in the section - * @altmap: alternate pfns to allocate the memmap backing store - * @pgmap: alternate compound page geometry for devmap mappings - * - * This is only intended for hotplug. - * - * Note that only VMEMMAP supports sub-section aligned hotplug, - * the proper alignment and size are gated by check_pfn_span(). - * - * - * Return: - * * 0 - On success. - * * -EEXIST - Section has been present. - * * -ENOMEM - Out of memory. - */ -int __meminit sparse_add_section(int nid, unsigned long start_pfn, - unsigned long nr_pages, struct vmem_altmap *altmap, - struct dev_pagemap *pgmap) -{ - unsigned long section_nr =3D pfn_to_section_nr(start_pfn); - struct mem_section *ms; - struct page *memmap; - int ret; - - ret =3D sparse_index_init(section_nr, nid); - if (ret < 0) - return ret; - - memmap =3D section_activate(nid, start_pfn, nr_pages, altmap, pgmap); - if (IS_ERR(memmap)) - return PTR_ERR(memmap); - - /* - * Poison uninitialized struct pages in order to catch invalid flags - * combinations. - */ - page_init_poison(memmap, sizeof(struct page) * nr_pages); - - ms =3D __nr_to_section(section_nr); - __section_mark_present(ms, section_nr); - - /* Align memmap to section boundary in the subsection case */ - if (section_nr_to_pfn(section_nr) !=3D start_pfn) - memmap =3D pfn_to_page(section_nr_to_pfn(section_nr)); - sparse_init_one_section(ms, section_nr, memmap, ms->usage, 0); - - return 0; -} - -void sparse_remove_section(unsigned long pfn, unsigned long nr_pages, - struct vmem_altmap *altmap) -{ - struct mem_section *ms =3D __pfn_to_section(pfn); - - if (WARN_ON_ONCE(!valid_section(ms))) - return; - - section_deactivate(pfn, nr_pages, altmap); -} -#endif /* CONFIG_MEMORY_HOTPLUG */ --=20 2.43.0