The mask of the T0SZ in the VTSZ was incorrect. We never used the VTCR_MASK that we define, and the calculation of the desired T0SZ field was incorrect. There is no need to save that single page for the stage-2 PGD, so let's just support the full 40-bit input address space to the stage-2 translation. Also move the memory defines from kvm_mmu.h to kvm_arm.h to have a single place where we define both the VTCR constants and the corresponding physical memory size defines needed. Signed-off-by: Christoffer Dall <c.dall@xxxxxxxxxxxxxxxxxxxxxx> --- arch/arm/include/asm/kvm_arm.h | 33 +++++++++++++++++++++++++-------- arch/arm/include/asm/kvm_mmu.h | 12 ------------ arch/arm/kvm/init.S | 7 ++++--- arch/arm/kvm/mmu.c | 3 +++ 4 files changed, 32 insertions(+), 23 deletions(-) diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h index 8f5dd22..8d31a08 100644 --- a/arch/arm/include/asm/kvm_arm.h +++ b/arch/arm/include/asm/kvm_arm.h @@ -125,24 +125,41 @@ #define HDCR_TPMCR (1 << 5) #define HDCR_HPMN_MASK (0x1F) +/* + * The architecture supports 40-bit IPA as input to the 2nd stage translations + * and PTRS_PER_PGD2 becomes 1024, because each entry covers 1GB of address + * space. + */ +#define KVM_PHYS_SHIFT (40) +#define KVM_PHYS_SIZE (1ULL << KVM_PHYS_SHIFT) +#define KVM_PHYS_MASK (KVM_PHYS_SIZE - 1ULL) +#define PTRS_PER_PGD2 (1ULL << (KVM_PHYS_SHIFT - 30)) +#define PGD2_ORDER get_order(PTRS_PER_PGD2 * sizeof(pgd_t)) +#define PGD2_SIZE (1 << PGD2_ORDER) + /* Virtualization Translation Control Register (VTCR) bits */ #define VTCR_SH0 (3 << 12) #define VTCR_ORGN0 (3 << 10) #define VTCR_IRGN0 (3 << 8) #define VTCR_SL0 (3 << 6) #define VTCR_S (1 << 4) -#define VTCR_T0SZ 3 +#define VTCR_T0SZ (0xf) #define VTCR_MASK (VTCR_SH0 | VTCR_ORGN0 | VTCR_IRGN0 | VTCR_SL0 | \ - VTCR_S | VTCR_T0SZ | VTCR_MASK) + VTCR_S | VTCR_T0SZ) #define VTCR_HTCR_SH (VTCR_SH0 | VTCR_ORGN0 | VTCR_IRGN0) -#define VTCR_SL_L2 0 /* Starting-level: 2 */ +#define VTCR_SL_L2 (0 << 6) /* Starting-level: 2 */ #define VTCR_SL_L1 (1 << 6) /* Starting-level: 1 */ -#define VTCR_GUEST_SL VTCR_SL_L1 -#define VTCR_GUEST_T0SZ 0 -#if VTCR_GUEST_SL == 0 -#define VTTBR_X (14 - VTCR_GUEST_T0SZ) +#define KVM_VTCR_SL0 VTCR_SL_L1 +/* stage-2 input address range defined as 2^(32-T0SZ) */ +#define KVM_T0SZ (32 - KVM_PHYS_SHIFT) +#define KVM_VTCR_T0SZ (KVM_T0SZ & VTCR_T0SZ) +#define KVM_VTCR_S ((KVM_VTCR_T0SZ << 1) & VTCR_S) + +/* Virtualization Translation Table Base Register (VTTBR) bits */ +#if KVM_VTCR_SL0 == VTCR_SL_L2 /* see ARM DDI 0406C: B4-1720 */ +#define VTTBR_X (14 - KVM_T0SZ) #else -#define VTTBR_X (5 - VTCR_GUEST_T0SZ) +#define VTTBR_X (5 - KVM_T0SZ) #endif #define VTTBR_BADDR_SHIFT (VTTBR_X - 1) #define VTTBR_BADDR_MASK (((1LLU << (40 - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT) diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h index 0800531..4d55218 100644 --- a/arch/arm/include/asm/kvm_mmu.h +++ b/arch/arm/include/asm/kvm_mmu.h @@ -19,18 +19,6 @@ #ifndef __ARM_KVM_MMU_H__ #define __ARM_KVM_MMU_H__ -/* - * The architecture supports 40-bit IPA as input to the 2nd stage translations - * and PTRS_PER_PGD2 could therefore be 1024. - * - * To save a bit of memory and to avoid alignment issues we assume 39-bit IPA - * for now, but remember that the level-1 table must be aligned to its size. - */ -#define KVM_PHYS_SHIFT (38) -#define KVM_PHYS_MASK ((1ULL << KVM_PHYS_SHIFT) - 1) -#define PTRS_PER_PGD2 512 -#define PGD2_ORDER get_order(PTRS_PER_PGD2 * sizeof(pgd_t)) - int create_hyp_mappings(void *from, void *to); int create_hyp_io_mappings(void *from, void *to, phys_addr_t); void free_hyp_pmds(void); diff --git a/arch/arm/kvm/init.S b/arch/arm/kvm/init.S index 3e0690b..5b52851 100644 --- a/arch/arm/kvm/init.S +++ b/arch/arm/kvm/init.S @@ -70,10 +70,11 @@ THUMB( adr r12, __kvm_init_sp ) mcr p15, 4, r0, c2, c0, 2 @ HTCR mrc p15, 4, r1, c2, c1, 2 @ VTCR - bic r1, r1, #(VTCR_HTCR_SH | VTCR_SL0) - bic r0, r0, #(~VTCR_HTCR_SH) + ldr r2, =VTCR_MASK + bic r1, r1, r2 + bic r0, r0, #(~VTCR_HTCR_SH) @ clear non-reusable HTCR bits orr r1, r0, r1 - orr r1, r1, #(VTCR_SL_L1 | VTCR_GUEST_T0SZ) + orr r1, r1, #(KVM_VTCR_SL0 | KVM_VTCR_T0SZ | KVM_VTCR_S) mcr p15, 4, r1, c2, c1, 2 @ VTCR @ Use the same memory attributes for hyp. accesses as the kernel diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c index c7226fe..f593a1a 100644 --- a/arch/arm/kvm/mmu.c +++ b/arch/arm/kvm/mmu.c @@ -280,6 +280,9 @@ int kvm_alloc_stage2_pgd(struct kvm *kvm) if (!pgd) return -ENOMEM; + /* stage-2 pgd must be aligned to its size */ + VM_BUG_ON((unsigned long)pgd & (PGD2_SIZE - 1)); + memset(pgd, 0, PTRS_PER_PGD2 * sizeof(pgd_t)); clean_dcache_area(pgd, PTRS_PER_PGD2 * sizeof(pgd_t)); kvm->arch.pgd = pgd; -- 1.7.9.5 _______________________________________________ kvmarm mailing list kvmarm@xxxxxxxxxxxxxxxxxxxxx https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm