diff options
author | Laszlo Ersek <lersek@redhat.com> | 2014-11-17 09:58:52 -0500 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2014-11-25 08:57:27 -0500 |
commit | 840f4bfbe03f1ce94ade8fdf84e8cd925ef15a48 (patch) | |
tree | d9d0e1af88829649a866a5605b522053a13e2dc4 /arch/arm | |
parent | 1050dcda3052912984b26fb6d2695a3f41792000 (diff) |
arm, arm64: KVM: allow forced dcache flush on page faults
To allow handling of incoherent memslots in a subsequent patch, this
patch adds a paramater 'ipa_uncached' to cache_coherent_guest_page()
so that we can instruct it to flush the page's contents to DRAM even
if the guest has caching globally enabled.
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/include/asm/kvm_mmu.h | 5 | ||||
-rw-r--r-- | arch/arm/kvm/mmu.c | 9 |
2 files changed, 10 insertions, 4 deletions
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h index acb0d5712716..f867060035ec 100644 --- a/arch/arm/include/asm/kvm_mmu.h +++ b/arch/arm/include/asm/kvm_mmu.h | |||
@@ -161,9 +161,10 @@ static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu) | |||
161 | } | 161 | } |
162 | 162 | ||
163 | static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva, | 163 | static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva, |
164 | unsigned long size) | 164 | unsigned long size, |
165 | bool ipa_uncached) | ||
165 | { | 166 | { |
166 | if (!vcpu_has_cache_enabled(vcpu)) | 167 | if (!vcpu_has_cache_enabled(vcpu) || ipa_uncached) |
167 | kvm_flush_dcache_to_poc((void *)hva, size); | 168 | kvm_flush_dcache_to_poc((void *)hva, size); |
168 | 169 | ||
169 | /* | 170 | /* |
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c index b007438242e2..cb924c6d56a6 100644 --- a/arch/arm/kvm/mmu.c +++ b/arch/arm/kvm/mmu.c | |||
@@ -852,6 +852,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, | |||
852 | struct vm_area_struct *vma; | 852 | struct vm_area_struct *vma; |
853 | pfn_t pfn; | 853 | pfn_t pfn; |
854 | pgprot_t mem_type = PAGE_S2; | 854 | pgprot_t mem_type = PAGE_S2; |
855 | bool fault_ipa_uncached; | ||
855 | 856 | ||
856 | write_fault = kvm_is_write_fault(vcpu); | 857 | write_fault = kvm_is_write_fault(vcpu); |
857 | if (fault_status == FSC_PERM && !write_fault) { | 858 | if (fault_status == FSC_PERM && !write_fault) { |
@@ -918,6 +919,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, | |||
918 | if (!hugetlb && !force_pte) | 919 | if (!hugetlb && !force_pte) |
919 | hugetlb = transparent_hugepage_adjust(&pfn, &fault_ipa); | 920 | hugetlb = transparent_hugepage_adjust(&pfn, &fault_ipa); |
920 | 921 | ||
922 | fault_ipa_uncached = false; | ||
923 | |||
921 | if (hugetlb) { | 924 | if (hugetlb) { |
922 | pmd_t new_pmd = pfn_pmd(pfn, mem_type); | 925 | pmd_t new_pmd = pfn_pmd(pfn, mem_type); |
923 | new_pmd = pmd_mkhuge(new_pmd); | 926 | new_pmd = pmd_mkhuge(new_pmd); |
@@ -925,7 +928,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, | |||
925 | kvm_set_s2pmd_writable(&new_pmd); | 928 | kvm_set_s2pmd_writable(&new_pmd); |
926 | kvm_set_pfn_dirty(pfn); | 929 | kvm_set_pfn_dirty(pfn); |
927 | } | 930 | } |
928 | coherent_cache_guest_page(vcpu, hva & PMD_MASK, PMD_SIZE); | 931 | coherent_cache_guest_page(vcpu, hva & PMD_MASK, PMD_SIZE, |
932 | fault_ipa_uncached); | ||
929 | ret = stage2_set_pmd_huge(kvm, memcache, fault_ipa, &new_pmd); | 933 | ret = stage2_set_pmd_huge(kvm, memcache, fault_ipa, &new_pmd); |
930 | } else { | 934 | } else { |
931 | pte_t new_pte = pfn_pte(pfn, mem_type); | 935 | pte_t new_pte = pfn_pte(pfn, mem_type); |
@@ -933,7 +937,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, | |||
933 | kvm_set_s2pte_writable(&new_pte); | 937 | kvm_set_s2pte_writable(&new_pte); |
934 | kvm_set_pfn_dirty(pfn); | 938 | kvm_set_pfn_dirty(pfn); |
935 | } | 939 | } |
936 | coherent_cache_guest_page(vcpu, hva, PAGE_SIZE); | 940 | coherent_cache_guest_page(vcpu, hva, PAGE_SIZE, |
941 | fault_ipa_uncached); | ||
937 | ret = stage2_set_pte(kvm, memcache, fault_ipa, &new_pte, | 942 | ret = stage2_set_pte(kvm, memcache, fault_ipa, &new_pte, |
938 | pgprot_val(mem_type) == pgprot_val(PAGE_S2_DEVICE)); | 943 | pgprot_val(mem_type) == pgprot_val(PAGE_S2_DEVICE)); |
939 | } | 944 | } |