Re: [RFC PATCH 02/34] ARM: mm: make 2-level pgd_t a scalar
"David Hildenbrand (Arm)" <[email protected]> Mon, 13 Jul 2026 18:04:54 +0200
| Newsgroups | org.kernel.vger.linux-csky,dev.linux.lists.loongarch,org.infradead.lists.kvm-riscv,org.infradead.lists.linux-riscv,org.kernel.vger.linux-arch,org.kernel.vger.linux-kernel,org.kernel.vger.linux-m68k,org.kernel.vger.linux-mips,org.kernel.vger.linux-openrisc,org.kvack.linux-mm |
|---|---|
| Message-ID | <[email protected]> |
On 7/13/26 17:38, Arnd Bergmann wrote: > On Mon, Jul 13, 2026, at 15:55, Yeoreum Yun wrote: >> From: "David Hildenbrand (Arm)" <[email protected]> >> >> We don't want pgd_t to be an array, as it prohibits returning it from a >> function, like pgdp_get(). > > What should pgdp_get() return on ARM 2-stage page tables then? > Does it return just the first entry or concatenate the two? It is rather obscure what we do (below). This patch tries to keep the existing behavior. > >> +typedef u64 pgdval_t; > >> +static inline pmdval_t pgd_val(pgd_t pgd) >> +{ >> + return (*(pmdval_t (*)[2])&pgd)[0]; >> +} > > This could use a comment to explain what this actually > returns and why the second entry is discarded. It's rather crazy. We have two page table levels, but fake that we have 3. There is some documentation in arch/arm/include/asm/pgtable-2level.h /* * Hardware-wise, we have a two level page table structure, where the first * level has 4096 entries, and the second level has 256 entries. Each entry * is one 32-bit word. Most of the bits in the second level entry are used * by hardware, and there aren't any "accessed" and "dirty" bits. * * Linux on the other hand has a three level page table structure, which can * be wrapped to fit a two level page table structure easily - using the PGD * and PTE only. However, Linux also expects one "PTE" table per page, and * at least a "dirty" bit. * * Therefore, we tweak the implementation slightly - we tell Linux that we * have 2048 entries in the first level, each of which is 8 bytes (iow, two * hardware pointers to the second level.) The second level contains two * hardware PTE tables arranged contiguously, preceded by Linux versions * which contain the state information Linux needs. We, therefore, end up * with 512 entries in the "PTE" level. * * This leads to the page tables having the following layout: * * pgd pte * | | * +--------+ * | | +------------+ +0 * +- - - - + | Linux pt 0 | * | | +------------+ +1024 * +--------+ +0 | Linux pt 1 | * | |-----> +------------+ +2048 * +- - - - + +4 | h/w pt 0 | * | |-----> +------------+ +3072 * +--------+ +8 | h/w pt 1 | * | | +------------+ +4096 * So we interpret two 32bit entries as a pair (64bit value). Together they span 2x256 values. Then we make PTRS_PER_PTE = 512, to iterate all of them (both pairs). Let me do some more digging to come up with something I can confidentially document here ... maybe I'll just refer to the comment in pgtable-2level.h. -- Cheers, David