linux/arch/riscv/kernel/sys_riscv.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2012 Regents of the University of California
   3 * Copyright (C) 2014 Darius Rad <darius@bluespec.com>
   4 * Copyright (C) 2017 SiFive
   5 *
   6 *   This program is free software; you can redistribute it and/or
   7 *   modify it under the terms of the GNU General Public License
   8 *   as published by the Free Software Foundation, version 2.
   9 *
  10 *   This program is distributed in the hope that it will be useful,
  11 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 *   GNU General Public License for more details.
  14 */
  15
  16#include <linux/syscalls.h>
  17#include <asm/unistd.h>
  18#include <asm/cacheflush.h>
  19
  20static long riscv_sys_mmap(unsigned long addr, unsigned long len,
  21                           unsigned long prot, unsigned long flags,
  22                           unsigned long fd, off_t offset,
  23                           unsigned long page_shift_offset)
  24{
  25        if (unlikely(offset & (~PAGE_MASK >> page_shift_offset)))
  26                return -EINVAL;
  27        return ksys_mmap_pgoff(addr, len, prot, flags, fd,
  28                               offset >> (PAGE_SHIFT - page_shift_offset));
  29}
  30
  31#ifdef CONFIG_64BIT
  32SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
  33        unsigned long, prot, unsigned long, flags,
  34        unsigned long, fd, off_t, offset)
  35{
  36        return riscv_sys_mmap(addr, len, prot, flags, fd, offset, 0);
  37}
  38#else
  39SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
  40        unsigned long, prot, unsigned long, flags,
  41        unsigned long, fd, off_t, offset)
  42{
  43        /*
  44         * Note that the shift for mmap2 is constant (12),
  45         * regardless of PAGE_SIZE
  46         */
  47        return riscv_sys_mmap(addr, len, prot, flags, fd, offset, 12);
  48}
  49#endif /* !CONFIG_64BIT */
  50
  51#ifdef CONFIG_SMP
  52/*
  53 * Allows the instruction cache to be flushed from userspace.  Despite RISC-V
  54 * having a direct 'fence.i' instruction available to userspace (which we
  55 * can't trap!), that's not actually viable when running on Linux because the
  56 * kernel might schedule a process on another hart.  There is no way for
  57 * userspace to handle this without invoking the kernel (as it doesn't know the
  58 * thread->hart mappings), so we've defined a RISC-V specific system call to
  59 * flush the instruction cache.
  60 *
  61 * sys_riscv_flush_icache() is defined to flush the instruction cache over an
  62 * address range, with the flush applying to either all threads or just the
  63 * caller.  We don't currently do anything with the address range, that's just
  64 * in there for forwards compatibility.
  65 */
  66SYSCALL_DEFINE3(riscv_flush_icache, uintptr_t, start, uintptr_t, end,
  67        uintptr_t, flags)
  68{
  69        struct mm_struct *mm = current->mm;
  70        bool local = (flags & SYS_RISCV_FLUSH_ICACHE_LOCAL) != 0;
  71
  72        /* Check the reserved flags. */
  73        if (unlikely(flags & ~SYS_RISCV_FLUSH_ICACHE_ALL))
  74                return -EINVAL;
  75
  76        flush_icache_mm(mm, local);
  77
  78        return 0;
  79}
  80#endif
  81