Patchwork [8/8] KVM: PPC: Add cache flush on page map

login
register
mail settings
Submitter Alexander Graf
Date Aug. 7, 2012, 10:57 a.m.
Message ID <1344337036-22244-9-git-send-email-agraf@suse.de>
Download mbox | patch
Permalink /patch/175587/
State New
Headers show

Comments

Alexander Graf - Aug. 7, 2012, 10:57 a.m.
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.

What we really would need is a method to flush the icache only when we
actually map a page executable for the guest. But with the current
abstraction that is hard to do, and this way we don't have a huge performance
penalty, so better be safe now and micro optimize things later.

Signed-off-by: Alexander Graf <agraf@suse.de>
---
 arch/powerpc/include/asm/kvm_host.h |   10 ++++++++++
 arch/powerpc/mm/mem.c               |    1 +
 2 files changed, 11 insertions(+), 0 deletions(-)
Scott Wood - Aug. 7, 2012, 9:01 p.m.
On 08/07/2012 05:57 AM, Alexander Graf wrote:
> 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.
> 
> What we really would need is a method to flush the icache only when we
> actually map a page executable for the guest. But with the current
> abstraction that is hard to do, and this way we don't have a huge performance
> penalty, so better be safe now and micro optimize things later.
> 
> Signed-off-by: Alexander Graf <agraf@suse.de>
> ---
>  arch/powerpc/include/asm/kvm_host.h |   10 ++++++++++
>  arch/powerpc/mm/mem.c               |    1 +
>  2 files changed, 11 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
> index ed75bc9..c0a2fc1 100644
> --- a/arch/powerpc/include/asm/kvm_host.h
> +++ b/arch/powerpc/include/asm/kvm_host.h
> @@ -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
> @@ -550,5 +551,14 @@ struct kvm_vcpu_arch {
>  #define KVM_MMIO_REG_FQPR	0x0060
>  
>  #define __KVM_HAVE_ARCH_WQP
> +#define __KVM_HAVE_ARCH_MAP_PAGE
> +static inline void kvm_arch_map_page(struct page *page)
> +{
> +	/* Need to invalidate the icache for new pages */
> +	if (!test_bit(PG_arch_1, &page->flags)) {
> +		flush_dcache_icache_page(page);
> +		set_bit(PG_arch_1, &page->flags);
> +	}
> +}

Shouldn't this test CPU_FTR_COHERENT_ICACHE?

-Scott


--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alexander Graf - Aug. 8, 2012, 7:59 a.m.
On 07.08.2012, at 23:01, Scott Wood <scottwood@freescale.com> wrote:

> On 08/07/2012 05:57 AM, Alexander Graf wrote:
>> 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.
>> 
>> What we really would need is a method to flush the icache only when we
>> actually map a page executable for the guest. But with the current
>> abstraction that is hard to do, and this way we don't have a huge performance
>> penalty, so better be safe now and micro optimize things later.
>> 
>> Signed-off-by: Alexander Graf <agraf@suse.de>
>> ---
>> arch/powerpc/include/asm/kvm_host.h |   10 ++++++++++
>> arch/powerpc/mm/mem.c               |    1 +
>> 2 files changed, 11 insertions(+), 0 deletions(-)
>> 
>> diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
>> index ed75bc9..c0a2fc1 100644
>> --- a/arch/powerpc/include/asm/kvm_host.h
>> +++ b/arch/powerpc/include/asm/kvm_host.h
>> @@ -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
>> @@ -550,5 +551,14 @@ struct kvm_vcpu_arch {
>> #define KVM_MMIO_REG_FQPR    0x0060
>> 
>> #define __KVM_HAVE_ARCH_WQP
>> +#define __KVM_HAVE_ARCH_MAP_PAGE
>> +static inline void kvm_arch_map_page(struct page *page)
>> +{
>> +    /* Need to invalidate the icache for new pages */
>> +    if (!test_bit(PG_arch_1, &page->flags)) {
>> +        flush_dcache_icache_page(page);
>> +        set_bit(PG_arch_1, &page->flags);
>> +    }
>> +}
> 
> Shouldn't this test CPU_FTR_COHERENT_ICACHE?

flush_icache_range checks for it a bit further down the code stream. I mostly modeled things the same way as set_pre_filter.


Alex

--
To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index ed75bc9..c0a2fc1 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -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
@@ -550,5 +551,14 @@  struct kvm_vcpu_arch {
 #define KVM_MMIO_REG_FQPR	0x0060
 
 #define __KVM_HAVE_ARCH_WQP
+#define __KVM_HAVE_ARCH_MAP_PAGE
+static inline void kvm_arch_map_page(struct page *page)
+{
+	/* Need to invalidate the icache for new pages */
+	if (!test_bit(PG_arch_1, &page->flags)) {
+		flush_dcache_icache_page(page);
+		set_bit(PG_arch_1, &page->flags);
+	}
+}
 
 #endif /* __POWERPC_KVM_HOST_H__ */
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index baaafde..fbdad0e 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)
 	__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)
 {