From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 568D7379C41 for ; Fri, 22 May 2026 07:15:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779434122; cv=none; b=ocCpXocYgSxPrQ0bxVGIVqWzD8YqZ+BAWa07BNCpAGpwdpjTIwTOrZ8DWEsv9bL8OoAFiXKh4zqMj5Lfe6JqEUk4AeXf/vt/BjqDdgVRWpm84x7fx2UXgraF0/kfrWYinyUOhnLrTbAbf/eeyECJePFibPdnGI6rAQmOywVu8T4= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779434122; c=relaxed/simple; bh=sxkqiabCo2k72yVa+eyY8IbkpWPy8a6prfz7sHqkQ6c=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=MzgWhlUOmrX0oK0DQM3xSYSUJa1dk66CBgXiM11MGVsdE5bWIZg04/WUhm7YPu5PKLi5lZdkRi4vusVadJkeRwOFbRw2n8blX4eC+Gess2SVyXASFYVULLHwU16aIFjNZaKj3bImFN6tZq8Rv/0/z7xXTvcxMviYnXwKU3JaSYs= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b=BhjWQb5h; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.b="BhjWQb5h" Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 527B94A92; Fri, 22 May 2026 00:15:07 -0700 (PDT) Received: from arm.com (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 48AC93F7B4; Fri, 22 May 2026 00:15:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1779434112; bh=sxkqiabCo2k72yVa+eyY8IbkpWPy8a6prfz7sHqkQ6c=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=BhjWQb5hw/wbqsSAir1eL+5L46+NeXRW3tS40bUfAX7q6JagmMsOkMLU3ep7w6UJF XdrXdzUZ626I7QZdHMplHAwyHaboMYra+7Eh2CIdV5iXzRlIZDvplr4IrfM+Ee7XBl 0y8z0sFmeoU/gP6cJGzj2R/6UlEmIAr+7vQ8K5M8= Date: Fri, 22 May 2026 08:15:09 +0100 From: Catalin Marinas To: Andrew Morton Cc: Alistair Popple , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, will@kernel.org, david@kernel.org Subject: Re: [PATCH] arm64: mm: call pagetable dtor when freeing hot-removed page tables Message-ID: References: <20260521032730.2104017-1-apopple@nvidia.com> <20260521153130.d7d5cd060f7522f894252333@linux-foundation.org> 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=us-ascii Content-Disposition: inline In-Reply-To: <20260521153130.d7d5cd060f7522f894252333@linux-foundation.org> On Thu, May 21, 2026 at 03:31:30PM -0700, Andrew Morton wrote: > On Thu, 21 May 2026 13:27:30 +1000 Alistair Popple wrote: > > Since 5e8eb9aeeda3 ("arm64: mm: always call PTE/PMD ctor in > > __create_pgd_mapping()") page-table allocation on ARM64 always > > calls pagetable_{pte,pmd,pud,p4d}_ctor(). This sets the page_type > > to PGTY_table, increments NR_PAGETABLE and possible allocates a PTL. > > However the matching pagetable_dtor() calls were never added. > > > > With DEBUG_VM enabled on kernel versions prior to v6.17 without > > 2dfcd1608f3a9 ("mm/page_alloc: let page freeing clear any set page > > type") this leads to the following warning when freeing these pages due > > to page->page_type sharing page->_mapcount: > > > > BUG: Bad page state in process ... pfn:284fbb > > page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x284fbb > > flags: 0x17fffc000000000(node=0|zone=2|lastcpupid=0x1ffff) > > page_type: f2(table) > > page dumped because: nonzero mapcount > > Call trace: > > bad_page+0x13c/0x160 > > __free_frozen_pages+0x6cc/0x860 > > ___free_pages+0xf4/0x180 > > free_pages+0x54/0x80 > > free_hotplug_page_range.part.0+0x58/0x90 > > free_empty_tables+0x438/0x500 > > __remove_pgd_mapping.constprop.0+0x60/0xa8 > > arch_remove_memory+0x48/0x80 > > try_remove_memory+0x158/0x1d8 > > offline_and_remove_memory+0x138/0x180 > > > > It can also lead to leaking the ptl allocation if ALLOC_SPLIT_PTLOCKS > > is defined and incorrect NR_PAGETABLE stats. Fix this by calling > > pagetable_dtor() in free_hotplug_pgtable_page() prior to freeing the > > page to undo the effects of calling pagetable_*_ctor(). > > > > Fixes: 5e8eb9aeeda3 ("arm64: mm: always call PTE/PMD ctor in __create_pgd_mapping()") > > 6.16+, so I assume we want cc:stable here. > > > arch/arm64/mm/mmu.c | 1 + > > 1 file changed, 1 insertion(+) > > > > diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c > > index 8e1d80a7033e..0c24fe650e95 100644 > > --- a/arch/arm64/mm/mmu.c > > +++ b/arch/arm64/mm/mmu.c > > @@ -1422,6 +1422,7 @@ static void free_hotplug_page_range(struct page *page, size_t size, > > > > static void free_hotplug_pgtable_page(struct page *page) > > { > > + pagetable_dtor(page_ptdesc(page)); > > free_hotplug_page_range(page, PAGE_SIZE, NULL); > > } > > I'd of course prefer that arm maintainers handle this. But > 5e8eb9aeeda3 came via myself so convention kinda-dictates that I get to > fix it. That's fine but Sashiko has some points: https://sashiko.dev/#/patchset/20260521032730.2104017-1-apopple@nvidia.com The __remove_pgd_mapping() path is fine but we also have the vmemmap_free() path where the constructor was never called. We could pass around a bool dtor argument but I wonder whether we could just check it's a pgtable page: diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 4c8959153ac4..9d42cbddce27 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -1441,6 +1441,9 @@ static void free_hotplug_page_range(struct page *page, size_t size, static void free_hotplug_pgtable_page(struct page *page) { + if (folio_test_pgtable(page_folio(page))) + pagetable_dtor(page_ptdesc(page)); + free_hotplug_page_range(page, PAGE_SIZE, NULL); } -- Catalin