Le 01/07/2020 à 09:22, Aneesh Kumar K.V a écrit :
Start using dcbstps; phwsync; sequence for flushing persistent memory range.
The new instructions are implemented as a variant of dcbf and hwsync and on
P8 and P9 they will be executed as those instructions. We avoid using them on
older hardware. This helps to avoid difficult to debug bugs.


Before this patch, the flush was done for all.
After this patch, IIUC the flush is done only on CPUs having feature CPU_FTR_ARCH_207S.

What about other CPUs ?

I don't know much about PMEM, my concern is about the UACCESS_FLUSHCACHE API introduced by commit 6c44741d75a2 ("powerpc/lib: Implement UACCESS_FLUSHCACHE API")

After your patch, __copy_from_user_flushcache() and memcpy_flushcache() are not doing cache flush anymore.

Is that intended ?

I'm trying to optimise some ALSA driver that does copy_from_user + cache_flush for DMA, and I was wondering if using __copy_from_user_flushcache() was an alternative.

Or is it __copy_from_user_inatomic_nocache() which has to be done for that ?

Thanks
Christophe


Signed-off-by: Aneesh Kumar K.V <aneesh.ku...@linux.ibm.com>
---
  arch/powerpc/include/asm/cacheflush.h |  1 +
  arch/powerpc/lib/pmem.c               | 50 ++++++++++++++++++++++++---
  2 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/include/asm/cacheflush.h 
b/arch/powerpc/include/asm/cacheflush.h
index de600b915a3c..54764c6e922d 100644
--- a/arch/powerpc/include/asm/cacheflush.h
+++ b/arch/powerpc/include/asm/cacheflush.h
@@ -6,6 +6,7 @@
#include <linux/mm.h>
  #include <asm/cputable.h>
+#include <asm/cpu_has_feature.h>
#ifdef CONFIG_PPC_BOOK3S_64
  /*
diff --git a/arch/powerpc/lib/pmem.c b/arch/powerpc/lib/pmem.c
index 0666a8d29596..5a61aaeb6930 100644
--- a/arch/powerpc/lib/pmem.c
+++ b/arch/powerpc/lib/pmem.c
@@ -9,20 +9,62 @@
#include <asm/cacheflush.h> +static inline void __clean_pmem_range(unsigned long start, unsigned long stop)
+{
+       unsigned long shift = l1_dcache_shift();
+       unsigned long bytes = l1_dcache_bytes();
+       void *addr = (void *)(start & ~(bytes - 1));
+       unsigned long size = stop - (unsigned long)addr + (bytes - 1);
+       unsigned long i;
+
+       for (i = 0; i < size >> shift; i++, addr += bytes)
+               asm volatile(PPC_DCBSTPS(%0, %1): :"i"(0), "r"(addr): "memory");
+
+
+       asm volatile(PPC_PHWSYNC ::: "memory");
+}
+
+static inline void __flush_pmem_range(unsigned long start, unsigned long stop)
+{
+       unsigned long shift = l1_dcache_shift();
+       unsigned long bytes = l1_dcache_bytes();
+       void *addr = (void *)(start & ~(bytes - 1));
+       unsigned long size = stop - (unsigned long)addr + (bytes - 1);
+       unsigned long i;
+
+       for (i = 0; i < size >> shift; i++, addr += bytes)
+               asm volatile(PPC_DCBFPS(%0, %1): :"i"(0), "r"(addr): "memory");
+
+
+       asm volatile(PPC_PHWSYNC ::: "memory");
+}
+
+static inline void clean_pmem_range(unsigned long start, unsigned long stop)
+{
+       if (cpu_has_feature(CPU_FTR_ARCH_207S))
+               return __clean_pmem_range(start, stop);
+}
+
+static inline void flush_pmem_range(unsigned long start, unsigned long stop)
+{
+       if (cpu_has_feature(CPU_FTR_ARCH_207S))
+               return __flush_pmem_range(start, stop);
+}
+
  /*
   * CONFIG_ARCH_HAS_PMEM_API symbols
   */
  void arch_wb_cache_pmem(void *addr, size_t size)
  {
        unsigned long start = (unsigned long) addr;
-       flush_dcache_range(start, start + size);
+       clean_pmem_range(start, start + size);
  }
  EXPORT_SYMBOL_GPL(arch_wb_cache_pmem);
void arch_invalidate_pmem(void *addr, size_t size)
  {
        unsigned long start = (unsigned long) addr;
-       flush_dcache_range(start, start + size);
+       flush_pmem_range(start, start + size);
  }
  EXPORT_SYMBOL_GPL(arch_invalidate_pmem);
@@ -35,7 +77,7 @@ long __copy_from_user_flushcache(void *dest, const void __user *src,
        unsigned long copied, start = (unsigned long) dest;
copied = __copy_from_user(dest, src, size);
-       flush_dcache_range(start, start + size);
+       clean_pmem_range(start, start + size);
return copied;
  }
@@ -45,7 +87,7 @@ void *memcpy_flushcache(void *dest, const void *src, size_t 
size)
        unsigned long start = (unsigned long) dest;
memcpy(dest, src, size);
-       flush_dcache_range(start, start + size);
+       clean_pmem_range(start, start + size);
return dest;
  }

Reply via email to