1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * Author: Hanlu Li <lihanlu@loongson.cn> |
4 | * Huacai Chen <chenhuacai@loongson.cn> |
5 | * |
6 | * Copyright (C) 2020-2022 Loongson Technology Corporation Limited |
7 | */ |
8 | #include <linux/capability.h> |
9 | #include <linux/entry-common.h> |
10 | #include <linux/errno.h> |
11 | #include <linux/linkage.h> |
12 | #include <linux/syscalls.h> |
13 | #include <linux/unistd.h> |
14 | |
15 | #include <asm/asm.h> |
16 | #include <asm/exception.h> |
17 | #include <asm/signal.h> |
18 | #include <asm/switch_to.h> |
19 | #include <asm-generic/syscalls.h> |
20 | |
21 | #undef __SYSCALL |
22 | #define __SYSCALL(nr, call) [nr] = (call), |
23 | |
24 | SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, unsigned long, |
25 | prot, unsigned long, flags, unsigned long, fd, off_t, offset) |
26 | { |
27 | if (offset & ~PAGE_MASK) |
28 | return -EINVAL; |
29 | |
30 | return ksys_mmap_pgoff(addr, len, prot, flags, fd, pgoff: offset >> PAGE_SHIFT); |
31 | } |
32 | |
33 | void *sys_call_table[__NR_syscalls] = { |
34 | [0 ... __NR_syscalls - 1] = sys_ni_syscall, |
35 | #include <asm/unistd.h> |
36 | }; |
37 | |
38 | typedef long (*sys_call_fn)(unsigned long, unsigned long, |
39 | unsigned long, unsigned long, unsigned long, unsigned long); |
40 | |
41 | void noinstr do_syscall(struct pt_regs *regs) |
42 | { |
43 | unsigned long nr; |
44 | sys_call_fn syscall_fn; |
45 | |
46 | nr = regs->regs[11]; |
47 | /* Set for syscall restarting */ |
48 | if (nr < NR_syscalls) |
49 | regs->regs[0] = nr + 1; |
50 | |
51 | regs->csr_era += 4; |
52 | regs->orig_a0 = regs->regs[4]; |
53 | regs->regs[4] = -ENOSYS; |
54 | |
55 | nr = syscall_enter_from_user_mode(regs, syscall: nr); |
56 | |
57 | if (nr < NR_syscalls) { |
58 | syscall_fn = sys_call_table[nr]; |
59 | regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6], |
60 | regs->regs[7], regs->regs[8], regs->regs[9]); |
61 | } |
62 | |
63 | syscall_exit_to_user_mode(regs); |
64 | } |
65 | |