2018-09-05 09:25:10 +03:00
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
# include <linux/kernel.h>
# include <linux/mm.h>
# include <linux/fs.h>
# include <linux/syscalls.h>
# include <linux/spinlock.h>
# include <asm/page.h>
# include <asm/cache.h>
# include <asm/cacheflush.h>
# include <asm/cachectl.h>
2019-08-20 07:47:24 +03:00
# define PG_dcache_clean PG_arch_1
2018-09-05 09:25:10 +03:00
void flush_dcache_page ( struct page * page )
{
2019-08-20 07:47:24 +03:00
struct address_space * mapping ;
2018-09-05 09:25:10 +03:00
2019-08-20 07:47:24 +03:00
if ( page = = ZERO_PAGE ( 0 ) )
2018-09-05 09:25:10 +03:00
return ;
2019-08-20 07:47:24 +03:00
mapping = page_mapping_file ( page ) ;
if ( mapping & & ! page_mapcount ( page ) )
clear_bit ( PG_dcache_clean , & page - > flags ) ;
else {
dcache_wbinv_all ( ) ;
if ( mapping )
icache_inv_all ( ) ;
set_bit ( PG_dcache_clean , & page - > flags ) ;
}
2018-09-05 09:25:10 +03:00
}
2019-08-20 07:47:24 +03:00
EXPORT_SYMBOL ( flush_dcache_page ) ;
2018-09-05 09:25:10 +03:00
2019-08-20 07:47:24 +03:00
void update_mmu_cache ( struct vm_area_struct * vma , unsigned long addr ,
pte_t * ptep )
2018-09-05 09:25:10 +03:00
{
2019-08-20 07:47:24 +03:00
unsigned long pfn = pte_pfn ( * ptep ) ;
2018-09-05 09:25:10 +03:00
struct page * page ;
2019-08-20 07:47:24 +03:00
if ( ! pfn_valid ( pfn ) )
2018-09-05 09:25:10 +03:00
return ;
page = pfn_to_page ( pfn ) ;
2019-08-20 07:47:24 +03:00
if ( page = = ZERO_PAGE ( 0 ) )
return ;
2018-09-05 09:25:10 +03:00
2019-08-20 07:47:24 +03:00
if ( ! test_and_set_bit ( PG_dcache_clean , & page - > flags ) )
dcache_wbinv_all ( ) ;
2018-09-05 09:25:10 +03:00
2019-08-20 07:47:24 +03:00
if ( page_mapping_file ( page ) ) {
if ( vma - > vm_flags & VM_EXEC )
icache_inv_all ( ) ;
}
2018-09-05 09:25:10 +03:00
}
2019-08-21 14:15:52 +03:00
void flush_kernel_dcache_page ( struct page * page )
{
struct address_space * mapping ;
mapping = page_mapping_file ( page ) ;
if ( ! mapping | | mapping_mapped ( mapping ) )
dcache_wbinv_all ( ) ;
}
EXPORT_SYMBOL ( flush_kernel_dcache_page ) ;
void flush_cache_range ( struct vm_area_struct * vma , unsigned long start ,
unsigned long end )
{
dcache_wbinv_all ( ) ;
if ( vma - > vm_flags & VM_EXEC )
icache_inv_all ( ) ;
}