2018-09-05 14:25:12 +08:00
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
# include <linux/fs.h>
# include <linux/mm.h>
# include <linux/mman.h>
# include <linux/shm.h>
# include <linux/sched.h>
# include <linux/random.h>
# include <linux/io.h>
2019-08-20 15:31:29 +08:00
# define COLOUR_ALIGN(addr,pgoff) \
( ( ( ( addr ) + SHMLBA - 1 ) & ~ ( SHMLBA - 1 ) ) + \
( ( ( pgoff ) < < PAGE_SHIFT ) & ( SHMLBA - 1 ) ) )
2018-09-05 14:25:12 +08:00
2019-08-20 15:31:29 +08:00
/*
* We need to ensure that shared mappings are correctly aligned to
* avoid aliasing issues with VIPT caches . We need to ensure that
* a specific page of an object is always mapped at a multiple of
* SHMLBA bytes .
*
* We unconditionally provide this function for all cases .
*/
unsigned long
arch_get_unmapped_area ( struct file * filp , unsigned long addr ,
2018-09-05 14:25:12 +08:00
unsigned long len , unsigned long pgoff , unsigned long flags )
{
2019-08-20 15:31:29 +08:00
struct mm_struct * mm = current - > mm ;
struct vm_area_struct * vma ;
int do_align = 0 ;
struct vm_unmapped_area_info info ;
/*
* We only need to do colour alignment if either the I or D
* caches alias .
*/
do_align = filp | | ( flags & MAP_SHARED ) ;
2018-09-05 14:25:12 +08:00
2019-08-20 15:31:29 +08:00
/*
* We enforce the MAP_FIXED case .
*/
2018-09-05 14:25:12 +08:00
if ( flags & MAP_FIXED ) {
2019-08-20 15:31:29 +08:00
if ( flags & MAP_SHARED & &
( addr - ( pgoff < < PAGE_SHIFT ) ) & ( SHMLBA - 1 ) )
2018-09-05 14:25:12 +08:00
return - EINVAL ;
return addr ;
}
if ( len > TASK_SIZE )
return - ENOMEM ;
2019-08-20 15:31:29 +08:00
2018-09-05 14:25:12 +08:00
if ( addr ) {
2019-08-20 15:31:29 +08:00
if ( do_align )
2018-09-05 14:25:12 +08:00
addr = COLOUR_ALIGN ( addr , pgoff ) ;
else
addr = PAGE_ALIGN ( addr ) ;
2019-08-20 15:31:29 +08:00
vma = find_vma ( mm , addr ) ;
2018-09-05 14:25:12 +08:00
if ( TASK_SIZE - len > = addr & &
2019-08-20 15:31:29 +08:00
( ! vma | | addr + len < = vm_start_gap ( vma ) ) )
2018-09-05 14:25:12 +08:00
return addr ;
}
2019-08-20 15:31:29 +08:00
info . flags = 0 ;
info . length = len ;
info . low_limit = mm - > mmap_base ;
info . high_limit = TASK_SIZE ;
info . align_mask = do_align ? ( PAGE_MASK & ( SHMLBA - 1 ) ) : 0 ;
info . align_offset = pgoff < < PAGE_SHIFT ;
return vm_unmapped_area ( & info ) ;
2018-09-05 14:25:12 +08:00
}