162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright(c) 2017 IBM Corporation. All rights reserved. 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/string.h> 762306a36Sopenharmony_ci#include <linux/export.h> 862306a36Sopenharmony_ci#include <linux/uaccess.h> 962306a36Sopenharmony_ci#include <linux/libnvdimm.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <asm/cacheflush.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_cistatic inline void __clean_pmem_range(unsigned long start, unsigned long stop) 1462306a36Sopenharmony_ci{ 1562306a36Sopenharmony_ci unsigned long shift = l1_dcache_shift(); 1662306a36Sopenharmony_ci unsigned long bytes = l1_dcache_bytes(); 1762306a36Sopenharmony_ci void *addr = (void *)(start & ~(bytes - 1)); 1862306a36Sopenharmony_ci unsigned long size = stop - (unsigned long)addr + (bytes - 1); 1962306a36Sopenharmony_ci unsigned long i; 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci for (i = 0; i < size >> shift; i++, addr += bytes) 2262306a36Sopenharmony_ci asm volatile(PPC_DCBSTPS(%0, %1): :"i"(0), "r"(addr): "memory"); 2362306a36Sopenharmony_ci} 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic inline void __flush_pmem_range(unsigned long start, unsigned long stop) 2662306a36Sopenharmony_ci{ 2762306a36Sopenharmony_ci unsigned long shift = l1_dcache_shift(); 2862306a36Sopenharmony_ci unsigned long bytes = l1_dcache_bytes(); 2962306a36Sopenharmony_ci void *addr = (void *)(start & ~(bytes - 1)); 3062306a36Sopenharmony_ci unsigned long size = stop - (unsigned long)addr + (bytes - 1); 3162306a36Sopenharmony_ci unsigned long i; 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci for (i = 0; i < size >> shift; i++, addr += bytes) 3462306a36Sopenharmony_ci asm volatile(PPC_DCBFPS(%0, %1): :"i"(0), "r"(addr): "memory"); 3562306a36Sopenharmony_ci} 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic inline void clean_pmem_range(unsigned long start, unsigned long stop) 3862306a36Sopenharmony_ci{ 3962306a36Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_207S)) 4062306a36Sopenharmony_ci return __clean_pmem_range(start, stop); 4162306a36Sopenharmony_ci} 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistatic inline void flush_pmem_range(unsigned long start, unsigned long stop) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci if (cpu_has_feature(CPU_FTR_ARCH_207S)) 4662306a36Sopenharmony_ci return __flush_pmem_range(start, stop); 4762306a36Sopenharmony_ci} 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/* 5062306a36Sopenharmony_ci * CONFIG_ARCH_HAS_PMEM_API symbols 5162306a36Sopenharmony_ci */ 5262306a36Sopenharmony_civoid arch_wb_cache_pmem(void *addr, size_t size) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci unsigned long start = (unsigned long) addr; 5562306a36Sopenharmony_ci clean_pmem_range(start, start + size); 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(arch_wb_cache_pmem); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_civoid arch_invalidate_pmem(void *addr, size_t size) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci unsigned long start = (unsigned long) addr; 6262306a36Sopenharmony_ci flush_pmem_range(start, start + size); 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(arch_invalidate_pmem); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci/* 6762306a36Sopenharmony_ci * CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE symbols 6862306a36Sopenharmony_ci */ 6962306a36Sopenharmony_cilong __copy_from_user_flushcache(void *dest, const void __user *src, 7062306a36Sopenharmony_ci unsigned size) 7162306a36Sopenharmony_ci{ 7262306a36Sopenharmony_ci unsigned long copied, start = (unsigned long) dest; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci copied = __copy_from_user(dest, src, size); 7562306a36Sopenharmony_ci clean_pmem_range(start, start + size); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci return copied; 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_civoid memcpy_flushcache(void *dest, const void *src, size_t size) 8162306a36Sopenharmony_ci{ 8262306a36Sopenharmony_ci unsigned long start = (unsigned long) dest; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci memcpy(dest, src, size); 8562306a36Sopenharmony_ci clean_pmem_range(start, start + size); 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ciEXPORT_SYMBOL(memcpy_flushcache); 88