[PATCH 4/6] KVM: ARM: Fix VTCR and VTTBR initialization

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

 



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


[Index of Archives]     [Linux KVM]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux