Skip to content

Commit

Permalink
KVM: arm/arm64: fix HYP ID map extension to 52 bits
Browse files Browse the repository at this point in the history
Commit fa2a844 incorrectly masks the index of the HYP ID map pgd
entry, causing a non-VHE kernel to hang during boot. This happens when
VA_BITS=48 and the ID map text is in 52-bit physical memory. In this
case we don't need an extra table level but need more entries in the
top-level table, so we need to map into hyp_pgd and need to use
__kvm_idmap_ptrs_per_pgd to mask in the extra bits. However,
__create_hyp_mappings currently masks by PTRS_PER_PGD instead.

Fix it so that we always use __kvm_idmap_ptrs_per_pgd for the HYP ID
map. This ensures that we use the larger mask for the top-level ID map
table when it has more entries. In all other cases, PTRS_PER_PGD is used
as normal.

Fixes: fa2a844 ("arm64: allow ID map to be extended to 52 bits")
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Kristina Martsenko <kristina.martsenko@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
  • Loading branch information
kristina-martsenko authored and ctmarinas committed Jan 15, 2018
1 parent 6a20542 commit 98732d1
Showing 1 changed file with 6 additions and 12 deletions.
18 changes: 6 additions & 12 deletions virt/kvm/arm/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -623,21 +623,15 @@ static int create_hyp_pud_mappings(pgd_t *pgd, unsigned long start,
return 0;
}

static int __create_hyp_mappings(pgd_t *pgdp,
static int __create_hyp_mappings(pgd_t *pgdp, unsigned long ptrs_per_pgd,
unsigned long start, unsigned long end,
unsigned long pfn, pgprot_t prot)
{
pgd_t *pgd;
pud_t *pud;
unsigned long addr, next, ptrs_per_pgd = PTRS_PER_PGD;
unsigned long addr, next;
int err = 0;

/*
* If it's not the hyp_pgd, fall back to the kvm idmap layout.
*/
if (pgdp != hyp_pgd)
ptrs_per_pgd = __kvm_idmap_ptrs_per_pgd();

mutex_lock(&kvm_hyp_pgd_mutex);
addr = start & PAGE_MASK;
end = PAGE_ALIGN(end);
Expand Down Expand Up @@ -705,8 +699,8 @@ int create_hyp_mappings(void *from, void *to, pgprot_t prot)
int err;

phys_addr = kvm_kaddr_to_phys(from + virt_addr - start);
err = __create_hyp_mappings(hyp_pgd, virt_addr,
virt_addr + PAGE_SIZE,
err = __create_hyp_mappings(hyp_pgd, PTRS_PER_PGD,
virt_addr, virt_addr + PAGE_SIZE,
__phys_to_pfn(phys_addr),
prot);
if (err)
Expand Down Expand Up @@ -737,7 +731,7 @@ int create_hyp_io_mappings(void *from, void *to, phys_addr_t phys_addr)
if (!is_vmalloc_addr(from) || !is_vmalloc_addr(to - 1))
return -EINVAL;

return __create_hyp_mappings(hyp_pgd, start, end,
return __create_hyp_mappings(hyp_pgd, PTRS_PER_PGD, start, end,
__phys_to_pfn(phys_addr), PAGE_HYP_DEVICE);
}

Expand Down Expand Up @@ -1743,7 +1737,7 @@ static int kvm_map_idmap_text(pgd_t *pgd)
int err;

/* Create the idmap in the boot page tables */
err = __create_hyp_mappings(pgd,
err = __create_hyp_mappings(pgd, __kvm_idmap_ptrs_per_pgd(),
hyp_idmap_start, hyp_idmap_end,
__phys_to_pfn(hyp_idmap_start),
PAGE_HYP_EXEC);
Expand Down

0 comments on commit 98732d1

Please sign in to comment.