2016-04-29 23:26:25 +10:00
# include <linux/mm.h>
# include <linux/hugetlb.h>
# include <asm/pgtable.h>
# include <asm/pgalloc.h>
# include <asm/cacheflush.h>
# include <asm/machdep.h>
# include <asm/mman.h>
2016-07-13 15:06:42 +05:30
# include <asm/tlb.h>
2016-04-29 23:26:25 +10:00
void radix__flush_hugetlb_page ( struct vm_area_struct * vma , unsigned long vmaddr )
{
2016-07-13 15:06:42 +05:30
int psize ;
2016-04-29 23:26:25 +10:00
struct hstate * hstate = hstate_file ( vma - > vm_file ) ;
2016-07-13 15:06:42 +05:30
psize = hstate_get_psize ( hstate ) ;
radix__flush_tlb_page_psize ( vma - > vm_mm , vmaddr , psize ) ;
2016-04-29 23:26:25 +10:00
}
void radix__local_flush_hugetlb_page ( struct vm_area_struct * vma , unsigned long vmaddr )
{
2016-07-13 15:06:42 +05:30
int psize ;
2016-04-29 23:26:25 +10:00
struct hstate * hstate = hstate_file ( vma - > vm_file ) ;
2016-07-13 15:06:42 +05:30
psize = hstate_get_psize ( hstate ) ;
radix__local_flush_tlb_page_psize ( vma - > vm_mm , vmaddr , psize ) ;
2016-04-29 23:26:25 +10:00
}
2016-07-13 15:06:43 +05:30
void radix__flush_hugetlb_tlb_range ( struct vm_area_struct * vma , unsigned long start ,
unsigned long end )
{
int psize ;
struct hstate * hstate = hstate_file ( vma - > vm_file ) ;
psize = hstate_get_psize ( hstate ) ;
radix__flush_tlb_range_psize ( vma - > vm_mm , start , end , psize ) ;
}
2016-04-29 23:26:25 +10:00
/*
* A vairant of hugetlb_get_unmapped_area doing topdown search
* FIXME ! ! should we do as x86 does or non hugetlb area does ?
* ie , use topdown or not based on mmap_is_legacy check ?
*/
unsigned long
radix__hugetlb_get_unmapped_area ( struct file * file , unsigned long addr ,
unsigned long len , unsigned long pgoff ,
unsigned long flags )
{
struct mm_struct * mm = current - > mm ;
struct vm_area_struct * vma ;
struct hstate * h = hstate_file ( file ) ;
struct vm_unmapped_area_info info ;
2017-03-30 16:35:21 +05:30
if ( unlikely ( addr > mm - > context . addr_limit & & addr < TASK_SIZE ) )
mm - > context . addr_limit = TASK_SIZE ;
2016-04-29 23:26:25 +10:00
if ( len & ~ huge_page_mask ( h ) )
return - EINVAL ;
2017-04-14 00:48:21 +05:30
if ( len > mm - > task_size )
2016-04-29 23:26:25 +10:00
return - ENOMEM ;
if ( flags & MAP_FIXED ) {
if ( prepare_hugepage_range ( file , addr , len ) )
return - EINVAL ;
return addr ;
}
if ( addr ) {
addr = ALIGN ( addr , huge_page_size ( h ) ) ;
vma = find_vma ( mm , addr ) ;
2017-04-14 00:48:21 +05:30
if ( mm - > task_size - len > = addr & &
2016-04-29 23:26:25 +10:00
( ! vma | | addr + len < = vma - > vm_start ) )
return addr ;
}
/*
* We are always doing an topdown search here . Slice code
* does that too .
*/
info . flags = VM_UNMAPPED_AREA_TOPDOWN ;
info . length = len ;
info . low_limit = PAGE_SIZE ;
info . high_limit = current - > mm - > mmap_base ;
info . align_mask = PAGE_MASK & ~ huge_page_mask ( h ) ;
info . align_offset = 0 ;
2017-03-30 16:35:21 +05:30
if ( addr > DEFAULT_MAP_WINDOW )
info . high_limit + = mm - > context . addr_limit - DEFAULT_MAP_WINDOW ;
2016-04-29 23:26:25 +10:00
return vm_unmapped_area ( & info ) ;
}