mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-28 21:45:01 +08:00
be769645a2
Add system call support and related uaccess.h for LoongArch. Q: Why keep _ARCH_WANT_SYS_CLONE definition while there is clone3: A: The latest glibc release has some basic support for clone3 but it is not complete. E.g., pthread_create() and spawni() have converted to use clone3 but fork() will still use clone. Moreover, some seccomp related applications can still not work perfectly with clone3. E.g., Chromium sandbox cannot work at all and there is no solution for it, which is more terrible than the fork() story [1]. [1] https://chromium-review.googlesource.com/c/chromium/src/+/2936184 Reviewed-by: WANG Xuerui <git@xen0n.name> Reviewed-by: Jiaxun Yang <jiaxun.yang@flygoat.com> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
64 lines
1.6 KiB
C
64 lines
1.6 KiB
C
// SPDX-License-Identifier: GPL-2.0+
|
|
/*
|
|
* Author: Hanlu Li <lihanlu@loongson.cn>
|
|
* Huacai Chen <chenhuacai@loongson.cn>
|
|
*
|
|
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
|
*/
|
|
#include <linux/capability.h>
|
|
#include <linux/entry-common.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/linkage.h>
|
|
#include <linux/syscalls.h>
|
|
#include <linux/unistd.h>
|
|
|
|
#include <asm/asm.h>
|
|
#include <asm/signal.h>
|
|
#include <asm/switch_to.h>
|
|
#include <asm-generic/syscalls.h>
|
|
|
|
#undef __SYSCALL
|
|
#define __SYSCALL(nr, call) [nr] = (call),
|
|
|
|
SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, unsigned long,
|
|
prot, unsigned long, flags, unsigned long, fd, off_t, offset)
|
|
{
|
|
if (offset & ~PAGE_MASK)
|
|
return -EINVAL;
|
|
|
|
return ksys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
|
|
}
|
|
|
|
void *sys_call_table[__NR_syscalls] = {
|
|
[0 ... __NR_syscalls - 1] = sys_ni_syscall,
|
|
#include <asm/unistd.h>
|
|
};
|
|
|
|
typedef long (*sys_call_fn)(unsigned long, unsigned long,
|
|
unsigned long, unsigned long, unsigned long, unsigned long);
|
|
|
|
void noinstr do_syscall(struct pt_regs *regs)
|
|
{
|
|
unsigned long nr;
|
|
sys_call_fn syscall_fn;
|
|
|
|
nr = regs->regs[11];
|
|
/* Set for syscall restarting */
|
|
if (nr < NR_syscalls)
|
|
regs->regs[0] = nr + 1;
|
|
|
|
regs->csr_era += 4;
|
|
regs->orig_a0 = regs->regs[4];
|
|
regs->regs[4] = -ENOSYS;
|
|
|
|
nr = syscall_enter_from_user_mode(regs, nr);
|
|
|
|
if (nr < NR_syscalls) {
|
|
syscall_fn = sys_call_table[nr];
|
|
regs->regs[4] = syscall_fn(regs->orig_a0, regs->regs[5], regs->regs[6],
|
|
regs->regs[7], regs->regs[8], regs->regs[9]);
|
|
}
|
|
|
|
syscall_exit_to_user_mode(regs);
|
|
}
|