diff options
author | Alexander Graf <agraf@suse.de> | 2012-08-03 07:56:33 -0400 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2012-08-16 08:14:53 -0400 |
commit | 249ba1ee0f8fcb4e40caa5fbea11dafde201cc46 (patch) | |
tree | cbe2fcf2c4e0c966afb3a7cacc785b608304a40c | |
parent | 04f995a544d1289ffb8108849cd71b1325c5af6a (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.h | 1 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_ppc.h | 12 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_32_mmu_host.c | 3 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_64_mmu_host.c | 2 | ||||
-rw-r--r-- | arch/powerpc/kvm/e500_tlb.c | 3 | ||||
-rw-r--r-- | arch/powerpc/mm/mem.c | 1 |
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); | |||
219 | void kvmppc_free_lpid(long lpid); | 219 | void kvmppc_free_lpid(long lpid); |
220 | void kvmppc_init_lpid(unsigned long nr_lpids); | 220 | void kvmppc_init_lpid(unsigned long nr_lpids); |
221 | 221 | ||
222 | static 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 | } |
472 | EXPORT_SYMBOL(flush_dcache_icache_page); | ||
472 | 473 | ||
473 | void clear_user_page(void *page, unsigned long vaddr, struct page *pg) | 474 | void clear_user_page(void *page, unsigned long vaddr, struct page *pg) |
474 | { | 475 | { |