124 lines · 3.1 KB · C
RawDownload
/* SPDX-License-Identifier: GPL-2.0 *//* * Access to user system call parameters and results * * See asm-generic/syscall.h for descriptions of what we must do here. */ #ifndef _ASM_ARM_SYSCALL_H#define _ASM_ARM_SYSCALL_H #include <uapi/linux/audit.h> /* for AUDIT_ARCH_* */#include <linux/elf.h> /* for ELF_EM */#include <linux/err.h>#include <linux/sched.h> #include <asm/unistd.h> #define NR_syscalls (__NR_syscalls) extern const unsigned long sys_call_table[]; static inline int syscall_get_nr(struct task_struct *task,				 struct pt_regs *regs){	if (IS_ENABLED(CONFIG_AEABI) && !IS_ENABLED(CONFIG_OABI_COMPAT))		return task_thread_info(task)->abi_syscall; 	if (task_thread_info(task)->abi_syscall == -1)		return -1; 	return task_thread_info(task)->abi_syscall & __NR_SYSCALL_MASK;} static inline bool __in_oabi_syscall(struct task_struct *task){	return IS_ENABLED(CONFIG_OABI_COMPAT) &&		(task_thread_info(task)->abi_syscall & __NR_OABI_SYSCALL_BASE);} static inline bool in_oabi_syscall(void){	return __in_oabi_syscall(current);} static inline void syscall_rollback(struct task_struct *task,				    struct pt_regs *regs){	regs->ARM_r0 = regs->ARM_ORIG_r0;} static inline long syscall_get_error(struct task_struct *task,				     struct pt_regs *regs){	unsigned long error = regs->ARM_r0;	return IS_ERR_VALUE(error) ? error : 0;} static inline long syscall_get_return_value(struct task_struct *task,					    struct pt_regs *regs){	return regs->ARM_r0;} static inline void syscall_set_return_value(struct task_struct *task,					    struct pt_regs *regs,					    int error, long val){	regs->ARM_r0 = (long) error ? error : val;} static inline void syscall_set_nr(struct task_struct *task,				  struct pt_regs *regs,				  int nr){	if (nr == -1) {		task_thread_info(task)->abi_syscall = -1;		/*		 * When the syscall number is set to -1, the syscall will be		 * skipped.  In this case the syscall return value has to be		 * set explicitly, otherwise the first syscall argument is		 * returned as the syscall return value.		 */		syscall_set_return_value(task, regs, -ENOSYS, 0);		return;	}	if ((IS_ENABLED(CONFIG_AEABI) && !IS_ENABLED(CONFIG_OABI_COMPAT))) {		task_thread_info(task)->abi_syscall = nr;		return;	}	task_thread_info(task)->abi_syscall =		(task_thread_info(task)->abi_syscall & ~__NR_SYSCALL_MASK) |		(nr & __NR_SYSCALL_MASK);} static inline void syscall_get_arguments(struct task_struct *task,					 struct pt_regs *regs,					 unsigned long *args){	args[0] = regs->ARM_ORIG_r0;	args++; 	memcpy(args, &regs->ARM_r0 + 1, 5 * sizeof(args[0]));} static inline void syscall_set_arguments(struct task_struct *task,					 struct pt_regs *regs,					 const unsigned long *args){	memcpy(&regs->ARM_r0, args, 6 * sizeof(args[0]));	/*	 * Also copy the first argument into ARM_ORIG_r0	 * so that syscall_get_arguments() would return it	 * instead of the previous value.	 */	regs->ARM_ORIG_r0 = regs->ARM_r0;} static inline int syscall_get_arch(struct task_struct *task){	/* ARM tasks don't change audit architectures on the fly. */	return AUDIT_ARCH_ARM;} #endif /* _ASM_ARM_SYSCALL_H */