2019-05-29 17:18:00 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2017-07-11 04:07:09 +03:00
/*
* Copyright ( C ) 2012 Regents of the University of California
* Copyright ( C ) 2014 Darius Rad < darius @ bluespec . com >
* Copyright ( C ) 2017 SiFive
*/
# include <linux/syscalls.h>
# include <asm/unistd.h>
2017-10-26 00:32:16 +03:00
# include <asm/cacheflush.h>
2017-07-11 04:07:09 +03:00
static long riscv_sys_mmap ( unsigned long addr , unsigned long len ,
unsigned long prot , unsigned long flags ,
unsigned long fd , off_t offset ,
unsigned long page_shift_offset )
{
if ( unlikely ( offset & ( ~ PAGE_MASK > > page_shift_offset ) ) )
return - EINVAL ;
2018-03-11 13:34:46 +03:00
return ksys_mmap_pgoff ( addr , len , prot , flags , fd ,
offset > > ( PAGE_SHIFT - page_shift_offset ) ) ;
2017-07-11 04:07:09 +03:00
}
# ifdef CONFIG_64BIT
SYSCALL_DEFINE6 ( mmap , unsigned long , addr , unsigned long , len ,
unsigned long , prot , unsigned long , flags ,
unsigned long , fd , off_t , offset )
{
return riscv_sys_mmap ( addr , len , prot , flags , fd , offset , 0 ) ;
}
# else
SYSCALL_DEFINE6 ( mmap2 , unsigned long , addr , unsigned long , len ,
unsigned long , prot , unsigned long , flags ,
unsigned long , fd , off_t , offset )
{
/*
* Note that the shift for mmap2 is constant ( 12 ) ,
* regardless of PAGE_SIZE
*/
return riscv_sys_mmap ( addr , len , prot , flags , fd , offset , 12 ) ;
}
# endif /* !CONFIG_64BIT */
2017-10-26 00:32:16 +03:00
/*
* Allows the instruction cache to be flushed from userspace . Despite RISC - V
* having a direct ' fence . i ' instruction available to userspace ( which we
* can ' t trap ! ) , that ' s not actually viable when running on Linux because the
* kernel might schedule a process on another hart . There is no way for
* userspace to handle this without invoking the kernel ( as it doesn ' t know the
* thread - > hart mappings ) , so we ' ve defined a RISC - V specific system call to
* flush the instruction cache .
*
* sys_riscv_flush_icache ( ) is defined to flush the instruction cache over an
* address range , with the flush applying to either all threads or just the
* caller . We don ' t currently do anything with the address range , that ' s just
* in there for forwards compatibility .
*/
SYSCALL_DEFINE3 ( riscv_flush_icache , uintptr_t , start , uintptr_t , end ,
uintptr_t , flags )
{
/* Check the reserved flags. */
2017-12-09 14:49:14 +03:00
if ( unlikely ( flags & ~ SYS_RISCV_FLUSH_ICACHE_ALL ) )
2017-10-26 00:32:16 +03:00
return - EINVAL ;
2018-08-28 19:37:16 +03:00
flush_icache_mm ( current - > mm , flags & SYS_RISCV_FLUSH_ICACHE_LOCAL ) ;
2017-10-26 00:32:16 +03:00
return 0 ;
}