diff options
| -rw-r--r-- | arch/arm/include/asm/kvm_emulate.h | 10 | ||||
| -rw-r--r-- | arch/arm/include/asm/kvm_host.h | 3 | ||||
| -rw-r--r-- | arch/arm/include/asm/kvm_mmu.h | 77 | ||||
| -rw-r--r-- | arch/arm/kvm/arm.c | 10 | ||||
| -rw-r--r-- | arch/arm/kvm/coproc.c | 70 | ||||
| -rw-r--r-- | arch/arm/kvm/coproc.h | 6 | ||||
| -rw-r--r-- | arch/arm/kvm/coproc_a15.c | 2 | ||||
| -rw-r--r-- | arch/arm/kvm/coproc_a7.c | 2 | ||||
| -rw-r--r-- | arch/arm/kvm/mmu.c | 164 | ||||
| -rw-r--r-- | arch/arm/kvm/trace.h | 39 | ||||
| -rw-r--r-- | arch/arm64/include/asm/kvm_emulate.h | 10 | ||||
| -rw-r--r-- | arch/arm64/include/asm/kvm_host.h | 3 | ||||
| -rw-r--r-- | arch/arm64/include/asm/kvm_mmu.h | 34 | ||||
| -rw-r--r-- | arch/arm64/kvm/sys_regs.c | 75 | ||||
| -rw-r--r-- | arch/x86/kvm/lapic.c | 3 |
15 files changed, 330 insertions, 178 deletions
diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h index 66ce17655bb9..7b0152321b20 100644 --- a/arch/arm/include/asm/kvm_emulate.h +++ b/arch/arm/include/asm/kvm_emulate.h | |||
| @@ -38,6 +38,16 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) | |||
| 38 | vcpu->arch.hcr = HCR_GUEST_MASK; | 38 | vcpu->arch.hcr = HCR_GUEST_MASK; |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | static inline unsigned long vcpu_get_hcr(struct kvm_vcpu *vcpu) | ||
| 42 | { | ||
| 43 | return vcpu->arch.hcr; | ||
| 44 | } | ||
| 45 | |||
| 46 | static inline void vcpu_set_hcr(struct kvm_vcpu *vcpu, unsigned long hcr) | ||
| 47 | { | ||
| 48 | vcpu->arch.hcr = hcr; | ||
| 49 | } | ||
| 50 | |||
| 41 | static inline bool vcpu_mode_is_32bit(struct kvm_vcpu *vcpu) | 51 | static inline bool vcpu_mode_is_32bit(struct kvm_vcpu *vcpu) |
| 42 | { | 52 | { |
| 43 | return 1; | 53 | return 1; |
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 254e0650e48b..04b4ea0b550a 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h | |||
| @@ -125,9 +125,6 @@ struct kvm_vcpu_arch { | |||
| 125 | * Anything that is not used directly from assembly code goes | 125 | * Anything that is not used directly from assembly code goes |
| 126 | * here. | 126 | * here. |
| 127 | */ | 127 | */ |
| 128 | /* dcache set/way operation pending */ | ||
| 129 | int last_pcpu; | ||
| 130 | cpumask_t require_dcache_flush; | ||
| 131 | 128 | ||
| 132 | /* Don't run the guest on this vcpu */ | 129 | /* Don't run the guest on this vcpu */ |
| 133 | bool pause; | 130 | bool pause; |
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h index 63e0ecc04901..1bca8f8af442 100644 --- a/arch/arm/include/asm/kvm_mmu.h +++ b/arch/arm/include/asm/kvm_mmu.h | |||
| @@ -44,6 +44,7 @@ | |||
| 44 | 44 | ||
| 45 | #ifndef __ASSEMBLY__ | 45 | #ifndef __ASSEMBLY__ |
| 46 | 46 | ||
| 47 | #include <linux/highmem.h> | ||
| 47 | #include <asm/cacheflush.h> | 48 | #include <asm/cacheflush.h> |
| 48 | #include <asm/pgalloc.h> | 49 | #include <asm/pgalloc.h> |
| 49 | 50 | ||
| @@ -161,13 +162,10 @@ static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu) | |||
| 161 | return (vcpu->arch.cp15[c1_SCTLR] & 0b101) == 0b101; | 162 | return (vcpu->arch.cp15[c1_SCTLR] & 0b101) == 0b101; |
| 162 | } | 163 | } |
| 163 | 164 | ||
| 164 | static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva, | 165 | static inline void __coherent_cache_guest_page(struct kvm_vcpu *vcpu, pfn_t pfn, |
| 165 | unsigned long size, | 166 | unsigned long size, |
| 166 | bool ipa_uncached) | 167 | bool ipa_uncached) |
| 167 | { | 168 | { |
| 168 | if (!vcpu_has_cache_enabled(vcpu) || ipa_uncached) | ||
| 169 | kvm_flush_dcache_to_poc((void *)hva, size); | ||
| 170 | |||
| 171 | /* | 169 | /* |
| 172 | * If we are going to insert an instruction page and the icache is | 170 | * If we are going to insert an instruction page and the icache is |
| 173 | * either VIPT or PIPT, there is a potential problem where the host | 171 | * either VIPT or PIPT, there is a potential problem where the host |
| @@ -179,18 +177,77 @@ static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva, | |||
| 179 | * | 177 | * |
| 180 | * VIVT caches are tagged using both the ASID and the VMID and doesn't | 178 | * VIVT caches are tagged using both the ASID and the VMID and doesn't |
| 181 | * need any kind of flushing (DDI 0406C.b - Page B3-1392). | 179 | * need any kind of flushing (DDI 0406C.b - Page B3-1392). |
| 180 | * | ||
| 181 | * We need to do this through a kernel mapping (using the | ||
| 182 | * user-space mapping has proved to be the wrong | ||
| 183 | * solution). For that, we need to kmap one page at a time, | ||
| 184 | * and iterate over the range. | ||
| 182 | */ | 185 | */ |
| 183 | if (icache_is_pipt()) { | 186 | |
| 184 | __cpuc_coherent_user_range(hva, hva + size); | 187 | bool need_flush = !vcpu_has_cache_enabled(vcpu) || ipa_uncached; |
| 185 | } else if (!icache_is_vivt_asid_tagged()) { | 188 | |
| 189 | VM_BUG_ON(size & PAGE_MASK); | ||
| 190 | |||
| 191 | if (!need_flush && !icache_is_pipt()) | ||
| 192 | goto vipt_cache; | ||
| 193 | |||
| 194 | while (size) { | ||
| 195 | void *va = kmap_atomic_pfn(pfn); | ||
| 196 | |||
| 197 | if (need_flush) | ||
| 198 | kvm_flush_dcache_to_poc(va, PAGE_SIZE); | ||
| 199 | |||
| 200 | if (icache_is_pipt()) | ||
| 201 | __cpuc_coherent_user_range((unsigned long)va, | ||
| 202 | (unsigned long)va + PAGE_SIZE); | ||
| 203 | |||
| 204 | size -= PAGE_SIZE; | ||
| 205 | pfn++; | ||
| 206 | |||
| 207 | kunmap_atomic(va); | ||
| 208 | } | ||
| 209 | |||
| 210 | vipt_cache: | ||
| 211 | if (!icache_is_pipt() && !icache_is_vivt_asid_tagged()) { | ||
| 186 | /* any kind of VIPT cache */ | 212 | /* any kind of VIPT cache */ |
| 187 | __flush_icache_all(); | 213 | __flush_icache_all(); |
| 188 | } | 214 | } |
| 189 | } | 215 | } |
| 190 | 216 | ||
| 217 | static inline void __kvm_flush_dcache_pte(pte_t pte) | ||
| 218 | { | ||
| 219 | void *va = kmap_atomic(pte_page(pte)); | ||
| 220 | |||
| 221 | kvm_flush_dcache_to_poc(va, PAGE_SIZE); | ||
| 222 | |||
| 223 | kunmap_atomic(va); | ||
| 224 | } | ||
| 225 | |||
| 226 | static inline void __kvm_flush_dcache_pmd(pmd_t pmd) | ||
| 227 | { | ||
| 228 | unsigned long size = PMD_SIZE; | ||
| 229 | pfn_t pfn = pmd_pfn(pmd); | ||
| 230 | |||
| 231 | while (size) { | ||
| 232 | void *va = kmap_atomic_pfn(pfn); | ||
| 233 | |||
| 234 | kvm_flush_dcache_to_poc(va, PAGE_SIZE); | ||
| 235 | |||
| 236 | pfn++; | ||
| 237 | size -= PAGE_SIZE; | ||
| 238 | |||
| 239 | kunmap_atomic(va); | ||
| 240 | } | ||
| 241 | } | ||
| 242 | |||
| 243 | static inline void __kvm_flush_dcache_pud(pud_t pud) | ||
| 244 | { | ||
| 245 | } | ||
| 246 | |||
| 191 | #define kvm_virt_to_phys(x) virt_to_idmap((unsigned long)(x)) | 247 | #define kvm_virt_to_phys(x) virt_to_idmap((unsigned long)(x)) |
| 192 | 248 | ||
| 193 | void stage2_flush_vm(struct kvm *kvm); | 249 | void kvm_set_way_flush(struct kvm_vcpu *vcpu); |
| 250 | void kvm_toggle_cache(struct kvm_vcpu *vcpu, bool was_enabled); | ||
| 194 | 251 | ||
| 195 | #endif /* !__ASSEMBLY__ */ | 252 | #endif /* !__ASSEMBLY__ */ |
| 196 | 253 | ||
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 2d6d91001062..0b0d58a905c4 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c | |||
| @@ -281,15 +281,6 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | |||
| 281 | vcpu->cpu = cpu; | 281 | vcpu->cpu = cpu; |
| 282 | vcpu->arch.host_cpu_context = this_cpu_ptr(kvm_host_cpu_state); | 282 | vcpu->arch.host_cpu_context = this_cpu_ptr(kvm_host_cpu_state); |
| 283 | 283 | ||
| 284 | /* | ||
| 285 | * Check whether this vcpu requires the cache to be flushed on | ||
| 286 | * this physical CPU. This is a consequence of doing dcache | ||
| 287 | * operations by set/way on this vcpu. We do it here to be in | ||
| 288 | * a non-preemptible section. | ||
| 289 | */ | ||
| 290 | if (cpumask_test_and_clear_cpu(cpu, &vcpu->arch.require_dcache_flush)) | ||
| 291 | flush_cache_all(); /* We'd really want v7_flush_dcache_all() */ | ||
| 292 | |||
| 293 | kvm_arm_set_running_vcpu(vcpu); | 284 | kvm_arm_set_running_vcpu(vcpu); |
| 294 | } | 285 | } |
| 295 | 286 | ||
| @@ -541,7 +532,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
| 541 | ret = kvm_call_hyp(__kvm_vcpu_run, vcpu); | 532 | ret = kvm_call_hyp(__kvm_vcpu_run, vcpu); |
| 542 | 533 | ||
