aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladimir Murzin <vladimir.murzin@arm.com>2015-11-16 06:28:18 -0500
committerMarc Zyngier <marc.zyngier@arm.com>2015-12-18 05:15:12 -0500
commit20475f784d29991b3b843c80c38a36f2ebb35ac4 (patch)
treefce9116aeb5f04122e323a240daeb5a018feb360
parent8420dcd37ef34040c8fc5a27bf66887b3b2faf80 (diff)
arm64: KVM: Add support for 16-bit VMID
The ARMv8.1 architecture extension allows to choose between 8-bit and 16-bit of VMID, so use this capability for KVM. Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org> Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
-rw-r--r--arch/arm/include/asm/kvm_arm.h2
-rw-r--r--arch/arm/include/asm/kvm_mmu.h5
-rw-r--r--arch/arm/kvm/arm.c10
-rw-r--r--arch/arm64/include/asm/kvm_arm.h3
-rw-r--r--arch/arm64/include/asm/kvm_mmu.h8
-rw-r--r--arch/arm64/kvm/hyp-init.S9
6 files changed, 33 insertions, 4 deletions
diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h
index 01d4d7abe34e..e22089fb44dc 100644
--- a/arch/arm/include/asm/kvm_arm.h
+++ b/arch/arm/include/asm/kvm_arm.h
@@ -164,7 +164,7 @@
164#define VTTBR_BADDR_SHIFT (VTTBR_X - 1) 164#define VTTBR_BADDR_SHIFT (VTTBR_X - 1)
165#define VTTBR_BADDR_MASK (((_AC(1, ULL) << (40 - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT) 165#define VTTBR_BADDR_MASK (((_AC(1, ULL) << (40 - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT)
166#define VTTBR_VMID_SHIFT _AC(48, ULL) 166#define VTTBR_VMID_SHIFT _AC(48, ULL)
167#define VTTBR_VMID_MASK (_AC(0xff, ULL) << VTTBR_VMID_SHIFT) 167#define VTTBR_VMID_MASK(size) (_AT(u64, (1 << size) - 1) << VTTBR_VMID_SHIFT)
168 168
169/* Hyp Syndrome Register (HSR) bits */ 169/* Hyp Syndrome Register (HSR) bits */
170#define HSR_EC_SHIFT (26) 170#define HSR_EC_SHIFT (26)
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 405aa1883307..9203c21b4673 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -279,6 +279,11 @@ static inline void __kvm_extend_hypmap(pgd_t *boot_hyp_pgd,
279 pgd_t *merged_hyp_pgd, 279 pgd_t *merged_hyp_pgd,
280 unsigned long hyp_idmap_start) { } 280 unsigned long hyp_idmap_start) { }
281 281
282static inline unsigned int kvm_get_vmid_bits(void)
283{
284 return 8;
285}
286
282#endif /* !__ASSEMBLY__ */ 287#endif /* !__ASSEMBLY__ */
283 288
284#endif /* __ARM_KVM_MMU_H__ */ 289#endif /* __ARM_KVM_MMU_H__ */
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 6e35d1d7893e..f6bcc2e4a133 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -59,7 +59,8 @@ static DEFINE_PER_CPU(struct kvm_vcpu *, kvm_arm_running_vcpu);
59 59
60/* The VMID used in the VTTBR */ 60/* The VMID used in the VTTBR */
61static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1); 61static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1);
62static u8 kvm_next_vmid; 62static u32 kvm_next_vmid;
63static unsigned int kvm_vmid_bits __read_mostly;
63static DEFINE_SPINLOCK(kvm_vmid_lock); 64static DEFINE_SPINLOCK(kvm_vmid_lock);
64 65
65static void kvm_arm_set_running_vcpu(struct kvm_vcpu *vcpu) 66static void kvm_arm_set_running_vcpu(struct kvm_vcpu *vcpu)
@@ -434,11 +435,12 @@ static void update_vttbr(struct kvm *kvm)
434 kvm->arch.vmid_gen = atomic64_read(&kvm_vmid_gen); 435 kvm->arch.vmid_gen = atomic64_read(&kvm_vmid_gen);
435 kvm->arch.vmid = kvm_next_vmid; 436 kvm->arch.vmid = kvm_next_vmid;
436 kvm_next_vmid++; 437 kvm_next_vmid++;
438 kvm_next_vmid &= (1 << kvm_vmid_bits) - 1;
437 439
438 /* update vttbr to be used with the new vmid */ 440 /* update vttbr to be used with the new vmid */
439 pgd_phys = virt_to_phys(kvm_get_hwpgd(kvm)); 441 pgd_phys = virt_to_phys(kvm_get_hwpgd(kvm));
440 BUG_ON(pgd_phys & ~VTTBR_BADDR_MASK); 442 BUG_ON(pgd_phys & ~VTTBR_BADDR_MASK);
441 vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK; 443 vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK(kvm_vmid_bits);
442 kvm->arch.vttbr = pgd_phys | vmid; 444 kvm->arch.vttbr = pgd_phys | vmid;
443 445
444 spin_unlock(&kvm_vmid_lock); 446 spin_unlock(&kvm_vmid_lock);
@@ -1135,6 +1137,10 @@ static int init_hyp_mode(void)
1135 1137
1136 kvm_perf_init(); 1138 kvm_perf_init();
1137 1139
1140 /* set size of VMID supported by CPU */
1141 kvm_vmid_bits = kvm_get_vmid_bits();
1142 kvm_info("%d-bit VMID\n", kvm_vmid_bits);
1143
1138 kvm_info("Hyp mode initialized successfully\n"); 1144 kvm_info("Hyp mode initialized successfully\n");
1139 1145
1140 return 0; 1146 return 0;
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 5e6857b6bdc4..738a95f93e49 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -125,6 +125,7 @@
125#define VTCR_EL2_SL0_LVL1 (1 << 6) 125#define VTCR_EL2_SL0_LVL1 (1 << 6)
126#define VTCR_EL2_T0SZ_MASK 0x3f 126#define VTCR_EL2_T0SZ_MASK 0x3f
127#define VTCR_EL2_T0SZ_40B 24 127#define VTCR_EL2_T0SZ_40B 24
128#define VTCR_EL2_VS 19
128 129
129/* 130/*
130 * We configure the Stage-2 page tables to always restrict the IPA space to be 131 * We configure the Stage-2 page tables to always restrict the IPA space to be
@@ -169,7 +170,7 @@
169#define VTTBR_BADDR_SHIFT (VTTBR_X - 1) 170#define VTTBR_BADDR_SHIFT (VTTBR_X - 1)
170#define VTTBR_BADDR_MASK (((UL(1) << (PHYS_MASK_SHIFT - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT) 171#define VTTBR_BADDR_MASK (((UL(1) << (PHYS_MASK_SHIFT - VTTBR_X)) - 1) << VTTBR_BADDR_SHIFT)
171#define VTTBR_VMID_SHIFT (UL(48)) 172#define VTTBR_VMID_SHIFT (UL(48))
172#define VTTBR_VMID_MASK (UL(0xFF) << VTTBR_VMID_SHIFT) 173#define VTTBR_VMID_MASK(size) (_AT(u64, (1 << size) - 1) << VTTBR_VMID_SHIFT)
173 174
174/* Hyp System Trap Register */ 175/* Hyp System Trap Register */
175#define HSTR_EL2_T(x) (1 << x) 176#define HSTR_EL2_T(x) (1 << x)
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 54cba803e2d9..0bf8b4320a91 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -20,6 +20,7 @@
20 20
21#include <asm/page.h> 21#include <asm/page.h>
22#include <asm/memory.h> 22#include <asm/memory.h>
23#include <asm/cpufeature.h>
23 24
24/* 25/*
25 * As we only have the TTBR0_EL2 register, we cannot express 26 * As we only have the TTBR0_EL2 register, we cannot express
@@ -301,5 +302,12 @@ static inline void __kvm_extend_hypmap(pgd_t *boot_hyp_pgd,
301 merged_hyp_pgd[idmap_idx] = __pgd(__pa(boot_hyp_pgd) | PMD_TYPE_TABLE); 302 merged_hyp_pgd[idmap_idx] = __pgd(__pa(boot_hyp_pgd) | PMD_TYPE_TABLE);
302} 303}
303 304
305static inline unsigned int kvm_get_vmid_bits(void)
306{
307 int reg = read_system_reg(SYS_ID_AA64MMFR1_EL1);
308
309 return (cpuid_feature_extract_field(reg, ID_AA64MMFR1_VMIDBITS_SHIFT) == 2) ? 16 : 8;
310}
311
304#endif /* __ASSEMBLY__ */ 312#endif /* __ASSEMBLY__ */
305#endif /* __ARM64_KVM_MMU_H__ */ 313#endif /* __ARM64_KVM_MMU_H__ */
diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S
index 178ba2248a98..3e568dcd907b 100644
--- a/arch/arm64/kvm/hyp-init.S
+++ b/arch/arm64/kvm/hyp-init.S
@@ -94,6 +94,15 @@ __do_hyp_init:
94 */ 94 */
95 mrs x5, ID_AA64MMFR0_EL1 95 mrs x5, ID_AA64MMFR0_EL1
96 bfi x4, x5, #16, #3 96 bfi x4, x5, #16, #3
97 /*
98 * Read the VMIDBits bits from ID_AA64MMFR1_EL1 and set the VS bit in
99 * VTCR_EL2.
100 */
101 mrs x5, ID_AA64MMFR1_EL1
102 ubfx x5, x5, #5, #1
103 lsl x5, x5, #VTCR_EL2_VS
104 orr x4, x4, x5
105
97 msr vtcr_el2, x4 106 msr vtcr_el2, x4
98 107
99 mrs x4, mair_el1 108 mrs x4, mair_el1