powerpc: purge all the prefetched instructions for the coherent icache flush
authorKevin Hao <haokexin@gmail.com>
Thu, 22 Aug 2013 01:30:35 +0000 (09:30 +0800)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Mon, 2 Dec 2013 03:13:47 +0000 (14:13 +1100)
As Benjamin Herrenschmidt has indicated, we still need a dummy icbi to
purge all the prefetched instructions from the ifetch buffers for the
snooping icache. We also need a sync before the icbi to order the
actual stores to memory that might have modified instructions with
the icbi.

Signed-off-by: Kevin Hao <haokexin@gmail.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/include/asm/cache.h
arch/powerpc/kernel/misc_32.S
arch/powerpc/kernel/misc_64.S

index 9e495c9a6a889d68bca11e1575ee82c3422b7348..ed0afc1e44a43324a31fb59994b42a768ecb8e33 100644 (file)
@@ -41,8 +41,20 @@ struct ppc64_caches {
 extern struct ppc64_caches ppc64_caches;
 #endif /* __powerpc64__ && ! __ASSEMBLY__ */
 
-#if !defined(__ASSEMBLY__)
+#if defined(__ASSEMBLY__)
+/*
+ * For a snooping icache, we still need a dummy icbi to purge all the
+ * prefetched instructions from the ifetch buffers. We also need a sync
+ * before the icbi to order the the actual stores to memory that might
+ * have modified instructions with the icbi.
+ */
+#define PURGE_PREFETCHED_INS   \
+       sync;                   \
+       icbi    0,r3;           \
+       sync;                   \
+       isync
 
+#else
 #define __read_mostly __attribute__((__section__(".data..read_mostly")))
 
 #ifdef CONFIG_6xx
index e47d268727a4a8ed87948a4d3ab5f87ad00793b1..879f09620f8341e27dbfd1ed6be47fe242eab812 100644 (file)
@@ -344,7 +344,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_UNIFIED_ID_CACHE)
  */
 _KPROBE(flush_icache_range)
 BEGIN_FTR_SECTION
-       isync
+       PURGE_PREFETCHED_INS
        blr                             /* for 601, do nothing */
 END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
        li      r5,L1_CACHE_BYTES-1
@@ -448,6 +448,7 @@ _GLOBAL(invalidate_dcache_range)
  */
 _GLOBAL(__flush_dcache_icache)
 BEGIN_FTR_SECTION
+       PURGE_PREFETCHED_INS
        blr
 END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
        rlwinm  r3,r3,0,0,31-PAGE_SHIFT         /* Get page base address */
@@ -489,6 +490,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_44x)
  */
 _GLOBAL(__flush_dcache_icache_phys)
 BEGIN_FTR_SECTION
+       PURGE_PREFETCHED_INS
        blr                                     /* for 601, do nothing */
 END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
        mfmsr   r10
index e59caf874d05ed60e500579b06bfcdf38bd85125..a9f7a79a3a405b5cc7836adf060269bdfd45c219 100644 (file)
@@ -67,6 +67,7 @@ PPC64_CACHES:
 
 _KPROBE(flush_icache_range)
 BEGIN_FTR_SECTION
+       PURGE_PREFETCHED_INS
        blr
 END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
 /*
@@ -211,6 +212,11 @@ _GLOBAL(__flush_dcache_icache)
  * Different systems have different cache line sizes
  */
 
+BEGIN_FTR_SECTION
+       PURGE_PREFETCHED_INS
+       blr
+END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)
+
 /* Flush the dcache */
        ld      r7,PPC64_CACHES@toc(r2)
        clrrdi  r3,r3,PAGE_SHIFT                    /* Page align */