aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2012-08-03 07:56:33 -0400
committerAlexander Graf <agraf@suse.de>2012-08-16 08:14:53 -0400
commit249ba1ee0f8fcb4e40caa5fbea11dafde201cc46 (patch)
treecbe2fcf2c4e0c966afb3a7cacc785b608304a40c
parent04f995a544d1289ffb8108849cd71b1325c5af6a (diff)
KVM: PPC: Add cache flush on page map
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>
-rw-r--r--arch/powerpc/include/asm/kvm_host.h1
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h12
-rw-r--r--arch/powerpc/kvm/book3s_32_mmu_host.c3
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu_host.c2
-rw-r--r--arch/powerpc/kvm/e500_tlb.c3
-rw-r--r--arch/powerpc/mm/mem.c1
6 files changed, 22 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 50ea12fd7bf5..a8bf5c673a3c 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -33,6 +33,7 @@
33#include <asm/kvm_asm.h> 33#include <asm/kvm_asm.h>
34#include <asm/processor.h> 34#include <asm/processor.h>
35#include <asm/page.h> 35#include <asm/page.h>
36#include <asm/cacheflush.h>
36 37
37#define KVM_MAX_VCPUS NR_CPUS 38#define KVM_MAX_VCPUS NR_CPUS
38#define KVM_MAX_VCORES NR_CPUS 39#define KVM_MAX_VCORES NR_CPUS
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 0124937a23b9..e006f0bdea95 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -219,4 +219,16 @@ void kvmppc_claim_lpid(long lpid);
219void kvmppc_free_lpid(long lpid); 219void kvmppc_free_lpid(long lpid);
220void kvmppc_init_lpid(unsigned long nr_lpids); 220void kvmppc_init_lpid(unsigned long nr_lpids);
221 221
222static inline void kvmppc_mmu_flush_icache(pfn_t pfn)
223{
224 /* Clear i-cache for new pages */
225 struct page *page;
226 page = pfn_to_page(pfn);
227 if (!test_bit(PG_arch_1, &page->flags)) {
228 flush_dcache_icache_page(page);
229 set_bit(PG_arch_1, &page->flags);
230 }
231}
232
233
222#endif /* __POWERPC_KVM_PPC_H__ */ 234#endif /* __POWERPC_KVM_PPC_H__ */
diff --git a/arch/powerpc/kvm/book3s_32_mmu_host.c b/arch/powerpc/kvm/book3s_32_mmu_host.c
index f922c29bb234..837f13e7b6bf 100644
--- a/arch/powerpc/kvm/book3s_32_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_32_mmu_host.c
@@ -211,6 +211,9 @@ next_pteg:
211 pteg1 |= PP_RWRX; 211 pteg1 |= PP_RWRX;
212 } 212 }
213 213
214 if (orig_pte->may_execute)
215 kvmppc_mmu_flush_icache(hpaddr >> PAGE_SHIFT);
216
214 local_irq_disable(); 217 local_irq_disable();
215 218
216 if (pteg[rr]) { 219 if (pteg[rr]) {
diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c
index 10fc8ec9d2a8..0688b6b39585 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_host.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_host.c
@@ -126,6 +126,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
126 126
127 if (!orig_pte->may_execute) 127 if (!orig_pte->may_execute)
128 rflags |= HPTE_R_N; 128 rflags |= HPTE_R_N;
129 else
130 kvmppc_mmu_flush_icache(hpaddr >> PAGE_SHIFT);
129 131
130 hash = hpt_hash(va, PTE_SIZE, MMU_SEGSIZE_256M); 132 hash = hpt_hash(va, PTE_SIZE, MMU_SEGSIZE_256M);
131 133
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index c510fc961302..fb3bb3ad8b3c 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -539,6 +539,9 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
539 539
540 kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize, 540 kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize,
541 ref, gvaddr, stlbe); 541 ref, gvaddr, stlbe);
542
543 /* Clear i-cache for new pages */
544 kvmppc_mmu_flush_icache(pfn);
542} 545}
543 546
544/* XXX only map the one-one case, for now use TLB0 */ 547/* XXX only map the one-one case, for now use TLB0 */
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index baaafde7d135..fbdad0e3929a 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -469,6 +469,7 @@ void flush_dcache_icache_page(struct page *page)
469 __flush_dcache_icache_phys(page_to_pfn(page) << PAGE_SHIFT); 469 __flush_dcache_icache_phys(page_to_pfn(page) << PAGE_SHIFT);
470#endif 470#endif
471} 471}
472EXPORT_SYMBOL(flush_dcache_icache_page);
472 473
473void clear_user_page(void *page, unsigned long vaddr, struct page *pg) 474void clear_user_page(void *page, unsigned long vaddr, struct page *pg)
474{ 475{