From: Baoquan He <baoquan.he@linux.dev>
To: Xiaolei Wang <xiaolei.wang@windriver.com>
Cc: k-hagio-ab@nec.com, yamazaki-msmt@nec.com, bhe@redhat.com,
kexec@lists.infradead.org, xiaoleiwangxiaolei@gmail.com
Subject: Re: [PATCH] arm64: Add 5-level page table support for 4K pages with 52-bit VA
Date: Wed, 10 Jun 2026 08:46:26 +0800 [thread overview]
Message-ID: <aiiy7aYG8dITSyQo@MiWiFi-R3L-srv> (raw)
In-Reply-To: <e1611077-48de-441f-b86c-4b4e221fbd27@windriver.com>
On 06/09/26 at 01:34pm, Xiaolei Wang wrote:
> Humble ping...
>
> Can anyone help review this patch?
Are you posting a patch for makedumpfile utility? If yes, you should
indicate that in patch subject, such as
[PATCH][makedumpfile] arm64: Add 5-level page table support for 4K pages with
I thought it's an arm64 kernel patch.
>
> thanks
>
> xiaolei
>
> On 5/19/26 11:17, Xiaolei Wang wrote:
> > From: Xiaolei wang <xiaolei.wang@windriver.com>
> >
> > makedumpfile fails with "PAGE SIZE 0x1000 and VA Bits 52 not supported"
> > on ARM64 systems configured with CONFIG_ARM64_VA_BITS_52=y and 4KB page
> > size. This combination requires 5-level page tables, which makedumpfile
> > does not currently support.
> >
> > Add support for 5-level page tables on ARM64 by:
> > - Adding the P4D page table level definitions and helpers
> > - Updating pud_t to contain p4d_t (reflecting the correct hierarchy)
> > - Extending calculate_plat_config() to recognize 4K + 52-bit VA as
> > pgtable_level=5, and 16K + 52-bit VA as pgtable_level=4
> > - Adding p4d_offset() to handle the additional translation level
> > - Updating vaddr_to_paddr_arm64() to walk through PGD->P4D->PUD->PMD->PTE
> > - Using vabits_actual instead of va_bits in calculate_plat_config() and
> > PTRS_PER_PGD to correctly handle the case where the kernel is compiled
> > with VA_BITS=52 but the hardware only supports 48-bit VA (runtime
> > fallback to 4-level)
> >
> > The pgtable_level assignments follow arch/arm64/Kconfig:
> > - 4K + 52-bit VA → 5-level (the only 5-level configuration)
> > - 16K + 52-bit VA → 4-level
> > - 4K + 48-bit VA → 4-level
> > - 16K + 48-bit VA → 4-level
> >
> > Fixes: https://github.com/makedumpfile/makedumpfile/issues/18
> > Signed-off-by: Xiaolei Wang <xiaolei.wang@windriver.com>
> > ---
> > arch/arm64.c | 89 +++++++++++++++++++++++++++++++++++++++++++---------
> > 1 file changed, 74 insertions(+), 15 deletions(-)
> >
> > diff --git a/arch/arm64.c b/arch/arm64.c
> > index 1072178..f3f33e4 100644
> > --- a/arch/arm64.c
> > +++ b/arch/arm64.c
> > @@ -29,6 +29,10 @@ typedef struct {
> > typedef struct {
> > pgd_t pgd;
> > +} p4d_t;
> > +
> > +typedef struct {
> > + p4d_t p4d;
> > } pud_t;
> > typedef struct {
> > @@ -42,6 +46,7 @@ typedef struct {
> > #define __pte(x) ((pte_t) { (x) } )
> > #define __pmd(x) ((pmd_t) { (x) } )
> > #define __pud(x) ((pud_t) { (x) } )
> > +#define __p4d(x) ((p4d_t) { (x) } )
> > #define __pgd(x) ((pgd_t) { (x) } )
> > static int lpa_52_bit_support_available;
> > @@ -62,7 +67,8 @@ static unsigned long kimage_voffset;
> > #define PAGE_OFFSET_48 ((0xffffffffffffffffUL) << 48)
> > #define pgd_val(x) ((x).pgd)
> > -#define pud_val(x) (pgd_val((x).pgd))
> > +#define p4d_val(x) (pgd_val((x).pgd))
> > +#define pud_val(x) (p4d_val((x).p4d))
> > #define pmd_val(x) (pud_val((x).pud))
> > #define pte_val(x) ((x).pte)
> > @@ -75,6 +81,7 @@ static unsigned long kimage_voffset;
> > typedef unsigned long pteval_t;
> > typedef unsigned long pmdval_t;
> > typedef unsigned long pudval_t;
> > +typedef unsigned long p4dval_t;
> > typedef unsigned long pgdval_t;
> > #define PAGE_SHIFT PAGESHIFT()
> > @@ -101,6 +108,14 @@ typedef unsigned long pgdval_t;
> > #define PUD_MASK (~(PUD_SIZE-1))
> > #define PTRS_PER_PUD PTRS_PER_PTE
> > +/*
> > + * P4D_SHIFT determines the size a level 0 page table entry can map.
> > + */
> > +#define P4D_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(0)
> > +#define P4D_SIZE (_AC(1, UL) << P4D_SHIFT)
> > +#define P4D_MASK (~(P4D_SIZE-1))
> > +#define PTRS_PER_P4D PTRS_PER_PTE
> > +
> > /*
> > * PGDIR_SHIFT determines the size a top-level page table entry can map
> > * (depending on the configuration, this level can be 0, 1 or 2).
> > @@ -108,7 +123,7 @@ typedef unsigned long pgdval_t;
> > #define PGDIR_SHIFT ARM64_HW_PGTABLE_LEVEL_SHIFT(4 - (pgtable_level))
> > #define PGDIR_SIZE (_AC(1, UL) << PGDIR_SHIFT)
> > #define PGDIR_MASK (~(PGDIR_SIZE-1))
> > -#define PTRS_PER_PGD (1 << ((va_bits) - PGDIR_SHIFT))
> > +#define PTRS_PER_PGD (1 << ((vabits_actual) - PGDIR_SHIFT))
> > /*
> > * Section address mask and size definitions.
> > @@ -178,6 +193,22 @@ pgd_pte(pgd_t pgd)
> > #define __pgd_to_phys(pgd) __pte_to_phys(pgd_pte(pgd))
> > #define pgd_offset(pgd, vaddr) ((pgd_t *)(pgd) + pgd_index(vaddr))
> > +/* P4D */
> > +#define p4d_index(vaddr) (((vaddr) >> P4D_SHIFT) & (PTRS_PER_P4D - 1))
> > +
> > +static inline pte_t p4d_pte(p4d_t p4d)
> > +{
> > + return __pte(p4d_val(p4d));
> > +}
> > +
> > +#define __p4d_to_phys(p4d) __pte_to_phys(p4d_pte(p4d))
> > +
> > +static inline unsigned long
> > +p4d_page_paddr(p4d_t p4d)
> > +{
> > + return __p4d_to_phys(p4d);
> > +}
> > +
> > static inline pte_t pud_pte(pud_t pud)
> > {
> > return __pte(pud_val(pud));
> > @@ -237,13 +268,22 @@ __pa(unsigned long vaddr)
> > return (vaddr - kimage_voffset);
> > }
> > +static p4d_t *
> > +p4d_offset(pgd_t *pgda, pgd_t *pgdv, unsigned long vaddr)
> > +{
> > + if (pgtable_level > 4)
> > + return (p4d_t *)(pgd_page_paddr(*pgdv) + p4d_index(vaddr) * sizeof(p4d_t));
> > + else
> > + return (p4d_t *)(pgda);
> > +}
> > +
> > static pud_t *
> > -pud_offset(pgd_t *pgda, pgd_t *pgdv, unsigned long vaddr)
> > +pud_offset(p4d_t *p4da, p4d_t *p4dv, unsigned long vaddr)
> > {
> > if (pgtable_level > 3)
> > - return (pud_t *)(pgd_page_paddr(*pgdv) + pud_index(vaddr) * sizeof(pud_t));
> > + return (pud_t *)(p4d_page_paddr(*p4dv) + pud_index(vaddr) * sizeof(pud_t));
> > else
> > - return (pud_t *)(pgda);
> > + return (pud_t *)(p4da);
> > }
> > static pmd_t *
> > @@ -257,20 +297,32 @@ pmd_offset(pud_t *puda, pud_t *pudv, unsigned long vaddr)
> > static int calculate_plat_config(void)
> > {
> > - /* derive pgtable_level as per arch/arm64/Kconfig */
> > - if ((PAGESIZE() == SZ_16K && va_bits == 36) ||
> > - (PAGESIZE() == SZ_64K && va_bits == 42)) {
> > + /*
> > + * Derive pgtable_level as per arch/arm64/Kconfig.
> > + * Use vabits_actual (runtime VA size) rather than va_bits (compile-time)
> > + * because the kernel may reduce the VA space at boot if the hardware
> > + * does not support 52-bit VA (LVA). In that case va_bits=52 but
> > + * vabits_actual=48, and the page tables are 4-level, not 5-level.
> > + */
> > + int va = vabits_actual;
> > +
> > + if ((PAGESIZE() == SZ_16K && va == 36) ||
> > + (PAGESIZE() == SZ_64K && va == 42)) {
> > pgtable_level = 2;
> > - } else if ((PAGESIZE() == SZ_64K && va_bits == 48) ||
> > - (PAGESIZE() == SZ_64K && va_bits == 52) ||
> > - (PAGESIZE() == SZ_4K && va_bits == 39) ||
> > - (PAGESIZE() == SZ_16K && va_bits == 47)) {
> > + } else if ((PAGESIZE() == SZ_64K && va == 48) ||
> > + (PAGESIZE() == SZ_64K && va == 52) ||
> > + (PAGESIZE() == SZ_4K && va == 39) ||
> > + (PAGESIZE() == SZ_16K && va == 47)) {
> > pgtable_level = 3;
> > - } else if ((PAGESIZE() != SZ_64K && va_bits == 48)) {
> > + } else if ((PAGESIZE() == SZ_4K && va == 48) ||
> > + (PAGESIZE() == SZ_16K && va == 48) ||
> > + (PAGESIZE() == SZ_16K && va == 52)) {
> > pgtable_level = 4;
> > + } else if (PAGESIZE() == SZ_4K && va == 52) {
> > + pgtable_level = 5;
> > } else {
> > ERRMSG("PAGE SIZE %#lx and VA Bits %d not supported\n",
> > - PAGESIZE(), va_bits);
> > + PAGESIZE(), va);
> > return FALSE;
> > }
> > DEBUG_MSG("pgtable_level: %d\n", pgtable_level);
> > @@ -548,6 +600,7 @@ vaddr_to_paddr_arm64(unsigned long vaddr)
> > unsigned long long paddr = NOT_PADDR;
> > unsigned long long swapper_phys;
> > pgd_t *pgda, pgdv;
> > + p4d_t *p4da, p4dv;
> > pud_t *puda, pudv;
> > pmd_t *pmda, pmdv;
> > pte_t *ptea, ptev;
> > @@ -565,7 +618,13 @@ vaddr_to_paddr_arm64(unsigned long vaddr)
> > return NOT_PADDR;
> > }
> > - puda = pud_offset(pgda, &pgdv, vaddr);
> > + p4da = p4d_offset(pgda, &pgdv, vaddr);
> > + if (!readmem(PADDR, (unsigned long long)p4da, &p4dv, sizeof(p4dv))) {
> > + ERRMSG("Can't read p4d\n");
> > + return NOT_PADDR;
> > + }
> > +
> > + puda = pud_offset(p4da, &p4dv, vaddr);
> > if (!readmem(PADDR, (unsigned long long)puda, &pudv, sizeof(pudv))) {
> > ERRMSG("Can't read pud\n");
> > return NOT_PADDR;
>
next prev parent reply other threads:[~2026-06-10 0:46 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-19 3:17 [PATCH] arm64: Add 5-level page table support for 4K pages with 52-bit VA Xiaolei Wang
2026-06-09 5:34 ` Xiaolei Wang
2026-06-10 0:46 ` Baoquan He [this message]
2026-06-10 2:13 ` HAGIO KAZUHITO(萩尾 一仁)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aiiy7aYG8dITSyQo@MiWiFi-R3L-srv \
--to=baoquan.he@linux.dev \
--cc=bhe@redhat.com \
--cc=k-hagio-ab@nec.com \
--cc=kexec@lists.infradead.org \
--cc=xiaolei.wang@windriver.com \
--cc=xiaoleiwangxiaolei@gmail.com \
--cc=yamazaki-msmt@nec.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.