From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 5BF684BF941; Mon, 21 Sep 2026 16:21:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.137.202.133 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790007681; cv=none; b=WtN7u9yR5/gmhwCaIIZghF15XiVyxGETZ3Pz0S2klyT0ydOJaBlbi81F0h5hmE9WERPSlfsFxIDae1YX+qI5WfE8b6g921cIgPEP76wCpoKlYpvAwF2t5DuujFpKVminVgS5qsGIdsuN+cys5yMz3PZ0Ywy6PC7uGaUmEBYLHhw= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790007681; c=relaxed/simple; bh=oGrCEH101JYJ0TwgVUxNMjImKrJahWj0BvTmscqgBZ8=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=Tb0peq0Q/dwMLkrjlTv3DbfBIYdIyKKyoavgHH5JcG69s7baHNhxmxeHyFe+H+DZhf6J/odPIxyBn647gcjbBaHwtNjPHtW8hlT187KwSMJPNKHBVZOw3JxNp1SoPa59VoeO7OxKa+rwYfBURahz/Xs0fGSDEAI/Ms637ksKAXY= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=infradead.org; spf=pass smtp.mailfrom=infradead.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b=pUf8M6np; arc=none smtp.client-ip=198.137.202.133 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=infradead.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=infradead.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=infradead.org header.i=@infradead.org header.b="pUf8M6np" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Transfer-Encoding: Content-Type:In-Reply-To:From:References:Cc:To:Subject:MIME-Version:Date: Message-ID:Sender:Reply-To:Content-ID:Content-Description; bh=/p/wcPtAYiIR16GkUrLsbGWfaNUG1APNWwlFrFY+MPk=; b=pUf8M6npYUllN36pF1Jjui7cUH 0cJnXOLLz8IMSoZFJYPgc5lro6QvvcAllD8kT8yvE2oXFQprRQN7QLqZcTyDV+/8rFVjXMhuvVI4c mWHFSIlZyvQAbCSPpjRnrW7h03Dt13F+2Qa/Di9V411h9xwD421wQBb0B8hrQkPwEnoZSwLlA8b3c Kfkv8In7DpmocmZwhpAHIvZc9azVaZuBZ7uGZh5Y7LrzlnECHlH4ORj71wjsVVkvIkxXQY7w3Ow7z 53Tv7T57hxQw+gODKEoIK9DtM5Pxbl1EDRuIQGHtUrD4gv23z7yDTkKGm1qzW6a6kZ4r/O3ZyUV15 Yc6W3yIg==; Received: from [50.53.43.113] (helo=[192.168.254.34]) by bombadil.infradead.org with esmtpsa (Exim 4.99.1 #2 (Red Hat Linux)) id 1x8gl0-00000002oNa-486R; Mon, 21 Sep 2026 16:20:43 +0000 Message-ID: Date: Mon, 21 Sep 2026 09:20:40 -0700 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH 21/21] Documentation: mm: clarify behaviour of compile-time folded page tables To: Yeoreum Yun , Russell King , Huacai Chen , WANG Xuerui , Thomas Bogendoerfer , Catalin Marinas , Will Deacon , Arnd Bergmann , Andrew Morton , Kairui Song , Qi Zheng , Shakeel Butt , Barry Song , Axel Rasmussen , Yuanchu Xie , Wei Xu , Johannes Weiner , David Hildenbrand , Michal Hocko , Lorenzo Stoakes , Tianrui Zhao , Bibo Mao , Anup Patel , Atish Patra , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Dave Hansen , Andy Lutomirski , Peter Zijlstra , Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H. Peter Anvin" , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Jonas Bonn , Stefan Kristiansson , Stafford Horne Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, loongarch@lists.linux.dev, linux-mips@vger.kernel.org, linux-arch@vger.kernel.org, linux-mm@kvack.org, kvm@vger.kernel.org, kvm-riscv@lists.infradead.org, linux-riscv@lists.infradead.org, linux-openrisc@vger.kernel.org References: <20260921-dummy_ptxp3-v1-0-cd40cf68242e@arm.com> <20260921-dummy_ptxp3-v1-21-cd40cf68242e@arm.com> Content-Language: en-US From: Randy Dunlap In-Reply-To: <20260921-dummy_ptxp3-v1-21-cd40cf68242e@arm.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit On 9/21/26 3:55 AM, Yeoreum Yun wrote: > From: "David Hildenbrand (Arm)" > > Compile-time folded page tables are not necessarily easy to understand, and even > people the were once familiar with the concept might need to refresh their memory. > > Add proper documentation, including a nice diagram, for the current design. > Mention details about dummy functions, including the recently changed pXdp_get() > helpers. > > Signed-off-by: David Hildenbrand (Arm) Documentation/mm/page_tables.rst:197: WARNING: Bullet list ends without a blank line; unexpected unindent. [docutils] See below for a fix. > --- > Documentation/mm/page_tables.rst | 84 +++++++++++++++++++++++++++++++++++----- > 1 file changed, 75 insertions(+), 9 deletions(-) > > diff --git a/Documentation/mm/page_tables.rst b/Documentation/mm/page_tables.rst > index 126c876282509..84f2715c7de0a 100644 > --- a/Documentation/mm/page_tables.rst > +++ b/Documentation/mm/page_tables.rst > @@ -143,15 +143,81 @@ pointers on each level is architecture-defined.:: > Page Table Folding > ================== > > -If the architecture does not use all the page table levels, they can be *folded* > -which means skipped, and all operations performed on page tables will be > -compile-time augmented to just skip a level when accessing the next lower > -level. > - > -Page table handling code that wishes to be architecture-neutral, such as the > -virtual memory manager, will need to be written so that it traverses all of the > -currently five levels. This style should also be preferred for > -architecture-specific code, so as to be robust to future changes. > +Not all architectures support 5-level page tables; while for some of them > +the exact number of supported page table levels is known at compile time, > +others can determine the number of page table levels at runtime based on > +hardware support and address space sizes. > + > +Generic page table walking code always assumes that 5 levels of page table > +exist. To make page table walking code not have to worry about that, > +`compile-time folding` and `runtime folding` of page tables are used. > +Compile-time folding is mostly handled in common code, whereas runtime folding > +is exclusively handled in architecture code. > + > +This description focuses on generic compile-time folded page tables; for > +architecture-specific variants, some details can vary, however, without > +affecting common page table walkers. > + > +When walking folded page tables, all upper page table levels up to the supported > +level are skipped in page table walkers: this is achieved by (a) treating > +entries in upper page table levels as present and pointing at a page table; and > +(b) having page table walkers cast the entry pointer to the next-level entry > +instead of dereferencing that table. From the perspective of a page table > +walker, the entry points at itself. > + > +Assuming compile-time folded 4-level page tables, to achieve (a), pgd_present() > +and pgd_leaf() are hard-coded to indicate a present page table entry that > +points at a page table, and to achieve (b) p4d_offset() and > +p4d_offset_lockless() simply cast the page table entry pointer to the next > +lower level. > + > +In the current design, this is further modeled by having the P4D have a > +single page table entry:: > + > + PGD > + --> +------+ NOP4D > + | ptr0 |-------> +------+ PUD > + | ptr1 |- | ptr0 |-------> +-----+ > + | ptr2 | \ +------+ | ptr |-------> ... > + | ptr3 | \ | ptr | > + ... \ .. > + \ NOP4D > + +----> +------+ PUD > + | ptr1 |-------> +-----+ > + +------+ | ptr |-------> ... > + | ptr | > + ... > + > +Note that the arrows from PGD to NOP4D represent page-table-walker > +transitions, not pointers stored in the pgd entries. > + > +Using p4d as an example, `nop4d`/`p4d folded` translates to the following: > + > +- p4d is considered folded into pgd; both are operating on the same page > + table. table. (add one more prefix space to align the indentation) > + > +- Most pgd_* helpers are hard-coded dummy functions that ignore the passed > + pgd_t values entirely. Exceptions are pgd_val() and low-level helpers > + set_pgd() + pgd_page_vaddr(), which effectively translate to set_p4d()/ > + p4d_pgtable() to keep existing arch code working. > + > + Architectures must provide p4d_* helpers (unless further common > + compile-time folding applies). > + > +- PTRS_PER_P4D is hard-coded to 1. Architectures must define PTRS_PER_PGD. > + > +To avoid reading a value that will never be used but cannot be entirely > +optimized out, compile-time folded page table code also makes pXdp_get() > +return a constant dummy value. > + > +In common code, this only affects pXd_val() when used for printing page > +table entries for debugging purposes. As we don't want architecture code > +that uses set_pXd(), pgd_page_vaddr() or pXd_pgtable() to accidentally > +operate on dummy values, the compiler will error out if it detects that the > +helpers are used with dummy values. For a folded level, pXd_page() must not > +be used and unconditionally triggers a compiler error. Architecture code must > +instead call the helpers on the proper first page table level: e.g., set_p4d() > +instead of set_pgd(). > > > MMU, TLB, and Page Faults > -- ~Randy