]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
KVM: PPC: Add cache flush on page map
authorAlexander Graf <agraf@suse.de>
Fri, 3 Aug 2012 11:56:33 +0000 (13:56 +0200)
committerAlexander Graf <agraf@suse.de>
Tue, 14 Aug 2012 22:29:03 +0000 (00:29 +0200)
When we map a page that wasn't icache cleared before, do so when first
mapping it in KVM using the same information bits as the Linux mapping
logic. That way we are 100% sure that any page we map does not have stale
entries in the icache.

Signed-off-by: Alexander Graf <agraf@suse.de>
---

v1 -> v2:

  - move code to arch/powerpc

arch/powerpc/include/asm/kvm_host.h
arch/powerpc/include/asm/kvm_ppc.h
arch/powerpc/kvm/book3s_32_mmu_host.c
arch/powerpc/kvm/book3s_64_mmu_host.c
arch/powerpc/kvm/e500_tlb.c
arch/powerpc/mm/mem.c

index ff8d51c1958b334318bd807a89340184ae00c3b6..cea9d3aab71c9eaabbf7da6f7acd06ef2556f8bd 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/kvm_asm.h>
 #include <asm/processor.h>
 #include <asm/page.h>
+#include <asm/cacheflush.h>
 
 #define KVM_MAX_VCPUS          NR_CPUS
 #define KVM_MAX_VCORES         NR_CPUS
index c38e82496161c0b7d43a82e417529d461d888492..88de3146838b443e43140d534fb70f1355324a03 100644 (file)
@@ -220,4 +220,16 @@ void kvmppc_claim_lpid(long lpid);
 void kvmppc_free_lpid(long lpid);
 void kvmppc_init_lpid(unsigned long nr_lpids);
 
+static inline void kvmppc_mmu_flush_icache(pfn_t pfn)
+{
+       /* Clear i-cache for new pages */
+       struct page *page;
+       page = pfn_to_page(pfn);
+       if (!test_bit(PG_arch_1, &page->flags)) {
+               flush_dcache_icache_page(page);
+               set_bit(PG_arch_1, &page->flags);
+       }
+}
+
+
 #endif /* __POWERPC_KVM_PPC_H__ */
index f922c29bb234d9bc6f2baf44175e934b63de5f86..837f13e7b6bfc1be3f7ed65a1000964f04825ebe 100644 (file)
@@ -211,6 +211,9 @@ next_pteg:
                pteg1 |= PP_RWRX;
        }
 
+       if (orig_pte->may_execute)
+               kvmppc_mmu_flush_icache(hpaddr >> PAGE_SHIFT);
+
        local_irq_disable();
 
        if (pteg[rr]) {
index 10fc8ec9d2a8b7e1e8e7ad8113e8dce633a5d977..0688b6b3958594fce84a62cfbd2f3564b5650781 100644 (file)
@@ -126,6 +126,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
 
        if (!orig_pte->may_execute)
                rflags |= HPTE_R_N;
+       else
+               kvmppc_mmu_flush_icache(hpaddr >> PAGE_SHIFT);
 
        hash = hpt_hash(va, PTE_SIZE, MMU_SEGSIZE_256M);
 
index 06273a7255bd63379712588c47eeb1829d4ffdcb..a6519ca2861f841021f1c0587d0d5df620db80d2 100644 (file)
@@ -543,6 +543,9 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
        kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize,
                                ref, gvaddr, stlbe);
 
+       /* Clear i-cache for new pages */
+       kvmppc_mmu_flush_icache(pfn);
+
        /* Drop refcount on page, so that mmu notifiers can clear it */
        kvm_release_pfn_clean(pfn);
 }
index baaafde7d13596af850a9d7452e596d84a52935a..fbdad0e3929a8ddfbcb0f714a6480f0ca33ba6f6 100644 (file)
@@ -469,6 +469,7 @@ void flush_dcache_icache_page(struct page *page)
        __flush_dcache_icache_phys(page_to_pfn(page) << PAGE_SHIFT);
 #endif
 }
+EXPORT_SYMBOL(flush_dcache_icache_page);
 
 void clear_user_page(void *page, unsigned long vaddr, struct page *pg)
 {