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); } } 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 #define PAGE_SIZE CONFIG_PAGE_SIZE #if PAGE_SIZE == 65536 Thanks, Alex