From nobody Mon Jun 8 17:56:02 2026 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (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 383E93ED13C; Wed, 27 May 2026 18:43:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779907405; cv=none; b=cgoL+flIC0oAdtP0SehhMGA+47h22zXIVJcn9nvJSfau4Ifmkil3I6vh3QgxCi4+1507EFuEV1HarzpoHJMoSG3OPW/xFNGumR8DynOQn0VzwEgBaDhBQ97bqf/Kp0v83kCABtmoBuiqj7tdl1CgduVelQhcfjaS0gW3FuAhiiA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779907405; c=relaxed/simple; bh=GWsqIkMxJUskl2ZuDoXcNiMWTnjDCSlTIAx/pcmHgYY=; h=Date:From:To:Subject:Cc:In-Reply-To:References:MIME-Version: Message-ID:Content-Type; b=QywODlKQfve/dgg1BqfitVEJL4ek5Uy2QOMylDU5y9FxBl4wp+Jud0vZb3Ls6TefiCfeIHtLAGFCU8NwQxlkKsVPUWillGsLhr4tSGRLZDMuwMdT5XUcGdis0VsKJhVj/m46sCU1AbhPkVUw4eW3gF6U0qooAkkOVP/jGqaV1BU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=zekRCMt6; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=N14xsR6n; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="zekRCMt6"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="N14xsR6n" Date: Wed, 27 May 2026 18:43:19 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1779907401; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=prZvr4xUS4O6kqiNvqd+Z/SAJZUCnwdIViPA7pz9SsM=; b=zekRCMt6pqoVR57ML+ophgg7pIgBO2Qvuo1Yx/A6KAvZCO/kyWDXgO1mPrUSekcHFiQzdW fJyyv74HFhmKeurL57iVJbNjI6uNddr3nDQ9lQlY7eLJmU7Uv8MdKZV7Qy4AVtyQUN7gqM kayvIBdEIRCk6TZpg3rT2YwGaQj4bt2Pg1NtRnOJInr0FyGD4GgVMJIb1AkWW79crLC4NK UZfCbZFtb76S0kNGllwKziQDSooFpobVdiGBJoBQkjEZLhdK9gFLVWsuWGh0XLzoTX0uKF EySo6h+yNdWFewIoHShHDS/B9/NirC8aw9S8RhkewOZHqOk3F0Hl5pQlE1+ewQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1779907401; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=prZvr4xUS4O6kqiNvqd+Z/SAJZUCnwdIViPA7pz9SsM=; b=N14xsR6nnfKiWARLAsqnMgdErHSreo+oo2D3yxH/t5IKzf7+vY/dOBNELQmb6nQ8ILZbFl SGHUzxMaWGCFYhAw== From: "tip-bot2 for David Hildenbrand (Arm)" Sender: tip-bot2@linutronix.de Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: x86/mm] x86/mm: Fix freeing of PMD-sized vmemmap pages Cc: "David Hildenbrand (Arm)" , Andrew Morton , Dave Hansen , "Mike Rapoport (Microsoft)" , Lance Yang , stable@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org In-Reply-To: <20260429-vmemmap-v2-1-8dfcacffd877@kernel.org> References: <20260429-vmemmap-v2-1-8dfcacffd877@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <177990739970.1039918.11842540756710822689.tip-bot2@tip-bot2> Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails Precedence: bulk Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable The following commit has been merged into the x86/mm branch of tip: Commit-ID: 39406c05f8f150f1685839acd38ffdd69ff92031 Gitweb: https://git.kernel.org/tip/39406c05f8f150f1685839acd38ffdd69= ff92031 Author: David Hildenbrand (Arm) AuthorDate: Wed, 29 Apr 2026 12:49:14 +02:00 Committer: Dave Hansen CommitterDate: Wed, 27 May 2026 11:39:38 -07:00 x86/mm: Fix freeing of PMD-sized vmemmap pages Commit bf9e4e30f353 ("x86/mm: use pagetable_free()"), switched from freeing non-boot page tables through __free_pages() to pagetable_free(). However, the function is also called to free vmemmap pages. Given that vmemmap pages are not page tables, already the page_ptdesc(page) is wrong. But worse, pagetable_free() calls: __free_pages(page, compound_order(page)); Since vmemmap pages are not compound pages (see vmemmap_alloc_block()) -- except for HVO, which doesn't apply here -- only first page of a PMD-sized vmemmap page is freed, leaking the other ones. Fix it by properly decoupling pagetable and vmemmap freeing. free_pagetable() no longer has to mess with SECTION_INFO, as only the vmemmap is marked like that in register_page_bootmem_memmap(). The indentation in remove_pmd_table() is messed up. Fix that while touching it. Bootmem info handling will soon be fixed up. For now, handle it similar to free_pagetable(), just avoiding the ifdef. [ dhansen: changelog munging. More imperative voice ] Fixes: bf9e4e30f353 ("x86/mm: use pagetable_free()") Signed-off-by: David Hildenbrand (Arm) Signed-off-by: Andrew Morton Signed-off-by: Dave Hansen Acked-by: Mike Rapoport (Microsoft) Tested-by: Lance Yang Link: https://lore.kernel.org/20260429-vmemmap-v2-1-8dfcacffd877@kernel.org Link: https://patch.msgid.link/20260429-vmemmap-v2-1-8dfcacffd877@kernel.org Cc: stable@vger.kernel.org --- arch/x86/mm/init_64.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index df2261f..7e20b22 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -1014,7 +1014,7 @@ static void __meminit free_pagetable(struct page *pag= e, int order) #ifdef CONFIG_HAVE_BOOTMEM_INFO_NODE enum bootmem_type type =3D bootmem_type(page); =20 - if (type =3D=3D SECTION_INFO || type =3D=3D MIX_SECTION_INFO) { + if (type =3D=3D MIX_SECTION_INFO) { while (nr_pages--) put_page_bootmem(page++); } else { @@ -1028,13 +1028,24 @@ static void __meminit free_pagetable(struct page *p= age, int order) } } =20 -static void __meminit free_hugepage_table(struct page *page, +static void __meminit free_vmemmap_pages(struct page *page, unsigned int o= rder, struct vmem_altmap *altmap) { - if (altmap) - vmem_altmap_free(altmap, PMD_SIZE / PAGE_SIZE); - else - free_pagetable(page, get_order(PMD_SIZE)); + unsigned long nr_pages =3D 1u << order; + + if (altmap) { + vmem_altmap_free(altmap, nr_pages); + } else if (PageReserved(page)) { + if (IS_ENABLED(CONFIG_HAVE_BOOTMEM_INFO_NODE) && + bootmem_type(page) =3D=3D SECTION_INFO) { + while (nr_pages--) + put_page_bootmem(page++); + } else { + free_reserved_pages(page, nr_pages); + } + } else { + __free_pages(page, order); + } } =20 static void __meminit free_pte_table(pte_t *pte_start, pmd_t *pmd) @@ -1118,7 +1129,8 @@ remove_pte_table(pte_t *pte_start, unsigned long addr= , unsigned long end, return; =20 if (!direct) - free_pagetable(pte_page(*pte), 0); + /* We never populate base pages from the altmap. */ + free_vmemmap_pages(pte_page(*pte), 0, NULL); =20 spin_lock(&init_mm.page_table_lock); pte_clear(&init_mm, addr, pte); @@ -1153,19 +1165,19 @@ remove_pmd_table(pmd_t *pmd_start, unsigned long ad= dr, unsigned long end, if (IS_ALIGNED(addr, PMD_SIZE) && IS_ALIGNED(next, PMD_SIZE)) { if (!direct) - free_hugepage_table(pmd_page(*pmd), - altmap); + free_vmemmap_pages(pmd_page(*pmd), + PMD_ORDER, altmap); =20 spin_lock(&init_mm.page_table_lock); pmd_clear(pmd); spin_unlock(&init_mm.page_table_lock); pages++; } else if (vmemmap_pmd_is_unused(addr, next)) { - free_hugepage_table(pmd_page(*pmd), - altmap); - spin_lock(&init_mm.page_table_lock); - pmd_clear(pmd); - spin_unlock(&init_mm.page_table_lock); + free_vmemmap_pages(pmd_page(*pmd), PMD_ORDER, + altmap); + spin_lock(&init_mm.page_table_lock); + pmd_clear(pmd); + spin_unlock(&init_mm.page_table_lock); } continue; }