On Tue, Nov 03, 2020 at 04:25:15PM +0000, Alexandru Elisei wrote: > Hi, > > On 11/3/20 4:10 PM, Andrew Jones wrote: > > On Tue, Nov 03, 2020 at 03:49:32PM +0000, Nikos Nikoleris wrote: > >>>> diff --git a/lib/arm64/asm/page.h b/lib/arm64/asm/page.h > >>>> index 46af552..2a06207 100644 > >>>> --- a/lib/arm64/asm/page.h > >>>> +++ b/lib/arm64/asm/page.h > >>>> @@ -10,38 +10,51 @@ > >>>> * This work is licensed under the terms of the GNU GPL, version 2. > >>>> */ > >>>> +#include <config.h> > >>>> #include <linux/const.h> > >>>> -#define PGTABLE_LEVELS 2 > >>>> #define VA_BITS 42 > >>> Let's bump VA_BITS to 48 while we're at it. > > I tried my suggestion to go to 48 VA bits, but it seems to break > > things for 64K pages. > > I believe that is because we end up with PGTABLE_LEVELS=3 and in > mmu_set_ranges_sect() we try to install a block mapping at the PUD level, which is > forbidden by the architecture. > > I think the easiest fix for that is to always try to install block mapping at the > pmd level. The diff below fixed all errors (with 16k and 64k pages): > > diff --git a/lib/arm/mmu.c b/lib/arm/mmu.c > index 6d1c75b00eaa..d33948a8a06a 100644 > --- a/lib/arm/mmu.c > +++ b/lib/arm/mmu.c > @@ -134,20 +134,22 @@ void mmu_set_range_sect(pgd_t *pgtable, uintptr_t virt_offset, > phys_addr_t phys_start, phys_addr_t phys_end, > pgprot_t prot) > { > - phys_addr_t paddr = phys_start & PUD_MASK; > - uintptr_t vaddr = virt_offset & PUD_MASK; > + phys_addr_t paddr = phys_start & PMD_MASK; > + uintptr_t vaddr = virt_offset & PMD_MASK; > uintptr_t virt_end = phys_end - paddr + vaddr; > pgd_t *pgd; > pud_t *pud; > - pud_t entry; > + pmd_t *pmd; > + pmd_t entry; > > - for (; vaddr < virt_end; vaddr += PUD_SIZE, paddr += PUD_SIZE) { > - pud_val(entry) = paddr; > - pud_val(entry) |= PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S; > - pud_val(entry) |= pgprot_val(prot); > + for (; vaddr < virt_end; vaddr += PMD_SIZE, paddr += PMD_SIZE) { > + pmd_val(entry) = paddr; > + pmd_val(entry) |= PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S; > + pmd_val(entry) |= pgprot_val(prot); > pgd = pgd_offset(pgtable, vaddr); > pud = pud_alloc(pgd, vaddr); > - WRITE_ONCE(*pud, entry); > + pmd = pmd_alloc(pud, vaddr); > + WRITE_ONCE(*pmd, entry); > flush_tlb_page(vaddr); Nice work! This resolves my issue as well. And, I can run with 16K pages on my thunderx now too. > } > } > diff --git a/lib/arm64/asm/page.h b/lib/arm64/asm/page.h > index 2a06207444aa..f649f56bf16f 100644 > --- a/lib/arm64/asm/page.h > +++ b/lib/arm64/asm/page.h > @@ -13,7 +13,7 @@ > #include <config.h> > #include <linux/const.h> > > -#define VA_BITS 42 > +#define VA_BITS 46 Let's use 48. > > #define PAGE_SIZE CONFIG_PAGE_SIZE > #if PAGE_SIZE == 65536 > > Thanks, > > Alex > Thanks, drew