Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e55cac5b authored by Suzuki K Poulose's avatar Suzuki K Poulose Committed by Marc Zyngier
Browse files

kvm: arm/arm64: Prepare for VM specific stage2 translations



Right now the stage2 page table for a VM is hard coded, assuming
an IPA of 40bits. As we are about to add support for per VM IPA,
prepare the stage2 page table helpers to accept the kvm instance
to make the right decision for the VM. No functional changes.
Adds stage2_pgd_size(kvm) to replace S2_PGD_SIZE. Also, moves
some of the definitions in arm32 to align with the arm64.
Also drop the _AC() specifier constants wherever possible.

Cc: Christoffer Dall <cdall@kernel.org>
Acked-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
Reviewed-by: default avatarEric Auger <eric.auger@redhat.com>
Signed-off-by: default avatarSuzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
parent 7665f3a8
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -133,8 +133,7 @@
 * space.
 */
#define KVM_PHYS_SHIFT	(40)
#define KVM_PHYS_SIZE	(_AC(1, ULL) << KVM_PHYS_SHIFT)
#define KVM_PHYS_MASK	(KVM_PHYS_SIZE - _AC(1, ULL))

#define PTRS_PER_S2_PGD	(_AC(1, ULL) << (KVM_PHYS_SHIFT - 30))

/* Virtualization Translation Control Register (VTCR) bits */
+8 −5
Original line number Diff line number Diff line
@@ -35,16 +35,12 @@
		addr;							\
	})

/*
 * KVM_MMU_CACHE_MIN_PAGES is the number of stage2 page table translation levels.
 */
#define KVM_MMU_CACHE_MIN_PAGES	2

#ifndef __ASSEMBLY__

#include <linux/highmem.h>
#include <asm/cacheflush.h>
#include <asm/cputype.h>
#include <asm/kvm_arm.h>
#include <asm/kvm_hyp.h>
#include <asm/pgalloc.h>
#include <asm/stage2_pgtable.h>
@@ -52,6 +48,13 @@
/* Ensure compatibility with arm64 */
#define VA_BITS			32

#define kvm_phys_shift(kvm)		KVM_PHYS_SHIFT
#define kvm_phys_size(kvm)		(1ULL << kvm_phys_shift(kvm))
#define kvm_phys_mask(kvm)		(kvm_phys_size(kvm) - 1ULL)
#define kvm_vttbr_baddr_mask(kvm)	VTTBR_BADDR_MASK

#define stage2_pgd_size(kvm)		(PTRS_PER_S2_PGD * sizeof(pgd_t))

int create_hyp_mappings(void *from, void *to, pgprot_t prot);
int create_hyp_io_mappings(phys_addr_t phys_addr, size_t size,
			   void __iomem **kaddr,
+32 −22
Original line number Diff line number Diff line
@@ -19,43 +19,53 @@
#ifndef __ARM_S2_PGTABLE_H_
#define __ARM_S2_PGTABLE_H_

#define stage2_pgd_none(pgd)			pgd_none(pgd)
#define stage2_pgd_clear(pgd)			pgd_clear(pgd)
#define stage2_pgd_present(pgd)			pgd_present(pgd)
#define stage2_pgd_populate(pgd, pud)		pgd_populate(NULL, pgd, pud)
#define stage2_pud_offset(pgd, address)		pud_offset(pgd, address)
#define stage2_pud_free(pud)			pud_free(NULL, pud)

#define stage2_pud_none(pud)			pud_none(pud)
#define stage2_pud_clear(pud)			pud_clear(pud)
#define stage2_pud_present(pud)			pud_present(pud)
#define stage2_pud_populate(pud, pmd)		pud_populate(NULL, pud, pmd)
#define stage2_pmd_offset(pud, address)		pmd_offset(pud, address)
#define stage2_pmd_free(pmd)			pmd_free(NULL, pmd)

#define stage2_pud_huge(pud)			pud_huge(pud)
/*
 * kvm_mmu_cache_min_pages() is the number of pages required
 * to install a stage-2 translation. We pre-allocate the entry
 * level table at VM creation. Since we have a 3 level page-table,
 * we need only two pages to add a new mapping.
 */
#define kvm_mmu_cache_min_pages(kvm)	2

#define stage2_pgd_none(kvm, pgd)		pgd_none(pgd)
#define stage2_pgd_clear(kvm, pgd)		pgd_clear(pgd)
#define stage2_pgd_present(kvm, pgd)		pgd_present(pgd)
#define stage2_pgd_populate(kvm, pgd, pud)	pgd_populate(NULL, pgd, pud)
#define stage2_pud_offset(kvm, pgd, address)	pud_offset(pgd, address)
#define stage2_pud_free(kvm, pud)		pud_free(NULL, pud)

#define stage2_pud_none(kvm, pud)		pud_none(pud)
#define stage2_pud_clear(kvm, pud)		pud_clear(pud)
#define stage2_pud_present(kvm, pud)		pud_present(pud)
#define stage2_pud_populate(kvm, pud, pmd)	pud_populate(NULL, pud, pmd)
#define stage2_pmd_offset(kvm, pud, address)	pmd_offset(pud, address)
#define stage2_pmd_free(kvm, pmd)		pmd_free(NULL, pmd)

#define stage2_pud_huge(kvm, pud)		pud_huge(pud)

/* Open coded p*d_addr_end that can deal with 64bit addresses */
static inline phys_addr_t stage2_pgd_addr_end(phys_addr_t addr, phys_addr_t end)
static inline phys_addr_t
stage2_pgd_addr_end(struct kvm *kvm, phys_addr_t addr, phys_addr_t end)
{
	phys_addr_t boundary = (addr + PGDIR_SIZE) & PGDIR_MASK;

	return (boundary - 1 < end - 1) ? boundary : end;
}

#define stage2_pud_addr_end(addr, end)		(end)
#define stage2_pud_addr_end(kvm, addr, end)	(end)

static inline phys_addr_t stage2_pmd_addr_end(phys_addr_t addr, phys_addr_t end)
static inline phys_addr_t
stage2_pmd_addr_end(struct kvm *kvm, phys_addr_t addr, phys_addr_t end)
{
	phys_addr_t boundary = (addr + PMD_SIZE) & PMD_MASK;

	return (boundary - 1 < end - 1) ? boundary : end;
}

#define stage2_pgd_index(addr)				pgd_index(addr)
#define stage2_pgd_index(kvm, addr)		pgd_index(addr)

#define stage2_pte_table_empty(ptep)			kvm_page_empty(ptep)
#define stage2_pmd_table_empty(pmdp)			kvm_page_empty(pmdp)
#define stage2_pud_table_empty(pudp)			false
#define stage2_pte_table_empty(kvm, ptep)	kvm_page_empty(ptep)
#define stage2_pmd_table_empty(kvm, pmdp)	kvm_page_empty(pmdp)
#define stage2_pud_table_empty(kvm, pudp)	false

#endif	/* __ARM_S2_PGTABLE_H_ */
+5 −2
Original line number Diff line number Diff line
@@ -141,8 +141,11 @@ static inline unsigned long __kern_hyp_va(unsigned long v)
 * We currently only support a 40bit IPA.
 */
#define KVM_PHYS_SHIFT	(40)
#define KVM_PHYS_SIZE	(1UL << KVM_PHYS_SHIFT)
#define KVM_PHYS_MASK	(KVM_PHYS_SIZE - 1UL)

#define kvm_phys_shift(kvm)		KVM_PHYS_SHIFT
#define kvm_phys_size(kvm)		(_AC(1, ULL) << kvm_phys_shift(kvm))
#define kvm_phys_mask(kvm)		(kvm_phys_size(kvm) - _AC(1, ULL))
#define kvm_vttbr_baddr_mask(kvm)	VTTBR_BADDR_MASK

#include <asm/stage2_pgtable.h>

+9 −9
Original line number Diff line number Diff line
@@ -26,17 +26,17 @@
#define S2_PMD_SIZE		(1UL << S2_PMD_SHIFT)
#define S2_PMD_MASK		(~(S2_PMD_SIZE-1))

#define stage2_pud_none(pud)			(0)
#define stage2_pud_present(pud)			(1)
#define stage2_pud_clear(pud)			do { } while (0)
#define stage2_pud_populate(pud, pmd)		do { } while (0)
#define stage2_pmd_offset(pud, address)		((pmd_t *)(pud))
#define stage2_pud_none(kvm, pud)		(0)
#define stage2_pud_present(kvm, pud)		(1)
#define stage2_pud_clear(kvm, pud)		do { } while (0)
#define stage2_pud_populate(kvm, pud, pmd)	do { } while (0)
#define stage2_pmd_offset(kvm, pud, address)	((pmd_t *)(pud))

#define stage2_pmd_free(pmd)			do { } while (0)
#define stage2_pmd_free(kvm, pmd)		do { } while (0)

#define stage2_pmd_addr_end(addr, end)		(end)
#define stage2_pmd_addr_end(kvm, addr, end)	(end)

#define stage2_pud_huge(pud)			(0)
#define stage2_pmd_table_empty(pmdp)		(0)
#define stage2_pud_huge(kvm, pud)		(0)
#define stage2_pmd_table_empty(kvm, pmdp)	(0)

#endif
Loading