2019-05-29 07:18:09 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2017-10-19 18:13:54 +11:00
/*
* Copyright ( c ) 2017 IBM Corporation . All rights reserved .
*/
# include <linux/string.h>
# include <linux/export.h>
2017-10-19 18:13:55 +11:00
# include <linux/uaccess.h>
2021-01-04 15:31:48 +01:00
# include <linux/libnvdimm.h>
2017-10-19 18:13:54 +11:00
# include <asm/cacheflush.h>
2020-07-01 12:52:31 +05:30
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 " ) ;
}
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 " ) ;
}
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 ) ;
}
2017-10-19 18:13:54 +11:00
/*
* CONFIG_ARCH_HAS_PMEM_API symbols
*/
void arch_wb_cache_pmem ( void * addr , size_t size )
{
unsigned long start = ( unsigned long ) addr ;
2020-07-01 12:52:31 +05:30
clean_pmem_range ( start , start + size ) ;
2017-10-19 18:13:54 +11:00
}
2019-12-02 12:10:18 +05:30
EXPORT_SYMBOL_GPL ( arch_wb_cache_pmem ) ;
2017-10-19 18:13:54 +11:00
void arch_invalidate_pmem ( void * addr , size_t size )
{
unsigned long start = ( unsigned long ) addr ;
2020-07-01 12:52:31 +05:30
flush_pmem_range ( start , start + size ) ;
2017-10-19 18:13:54 +11:00
}
2019-12-02 12:10:18 +05:30
EXPORT_SYMBOL_GPL ( arch_invalidate_pmem ) ;
2017-10-19 18:13:55 +11:00
/*
* CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE symbols
*/
long __copy_from_user_flushcache ( void * dest , const void __user * src ,
unsigned size )
{
unsigned long copied , start = ( unsigned long ) dest ;
copied = __copy_from_user ( dest , src , size ) ;
2020-07-01 12:52:31 +05:30
clean_pmem_range ( start , start + size ) ;
2017-10-19 18:13:55 +11:00
return copied ;
}
2019-04-26 19:36:30 +08:00
void memcpy_flushcache ( void * dest , const void * src , size_t size )
2017-10-19 18:13:55 +11:00
{
unsigned long start = ( unsigned long ) dest ;
memcpy ( dest , src , size ) ;
2020-07-01 12:52:31 +05:30
clean_pmem_range ( start , start + size ) ;
2017-10-19 18:13:55 +11:00
}
EXPORT_SYMBOL ( memcpy_flushcache ) ;
void memcpy_page_flushcache ( char * to , struct page * page , size_t offset ,
size_t len )
{
memcpy_flushcache ( to , page_to_virt ( page ) + offset , len ) ;
}
EXPORT_SYMBOL ( memcpy_page_flushcache ) ;