Re: [kvm-unit-tests PATCH 1/2] arm64: Add support for configuring the translation granule

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux