Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Access to user system call parameters and results
4 *
5 * See asm-generic/syscall.h for descriptions of what we must do here.
6 */
7
8#ifndef _ASM_ARM_SYSCALL_H
9#define _ASM_ARM_SYSCALL_H
10
11#include <uapi/linux/audit.h> /* for AUDIT_ARCH_* */
12#include <linux/elf.h> /* for ELF_EM */
13#include <linux/err.h>
14#include <linux/sched.h>
15
16#include <asm/unistd.h>
17
18#define NR_syscalls (__NR_syscalls)
19
20extern const unsigned long sys_call_table[];
21
22static inline int syscall_get_nr(struct task_struct *task,
23 struct pt_regs *regs)
24{
25 if (IS_ENABLED(CONFIG_AEABI) && !IS_ENABLED(CONFIG_OABI_COMPAT))
26 return task_thread_info(task)->abi_syscall;
27
28 if (task_thread_info(task)->abi_syscall == -1)
29 return -1;
30
31 return task_thread_info(task)->abi_syscall & __NR_SYSCALL_MASK;
32}
33
34static inline bool __in_oabi_syscall(struct task_struct *task)
35{
36 return IS_ENABLED(CONFIG_OABI_COMPAT) &&
37 (task_thread_info(task)->abi_syscall & __NR_OABI_SYSCALL_BASE);
38}
39
40static inline bool in_oabi_syscall(void)
41{
42 return __in_oabi_syscall(current);
43}
44
45static inline void syscall_rollback(struct task_struct *task,
46 struct pt_regs *regs)
47{
48 regs->ARM_r0 = regs->ARM_ORIG_r0;
49}
50
51static inline long syscall_get_error(struct task_struct *task,
52 struct pt_regs *regs)
53{
54 unsigned long error = regs->ARM_r0;
55 return IS_ERR_VALUE(error) ? error : 0;
56}
57
58static inline long syscall_get_return_value(struct task_struct *task,
59 struct pt_regs *regs)
60{
61 return regs->ARM_r0;
62}
63
64static inline void syscall_set_return_value(struct task_struct *task,
65 struct pt_regs *regs,
66 int error, long val)
67{
68 regs->ARM_r0 = (long) error ? error : val;
69}
70
71static inline void syscall_set_nr(struct task_struct *task,
72 struct pt_regs *regs,
73 int nr)
74{
75 if (nr == -1) {
76 task_thread_info(task)->abi_syscall = -1;
77 /*
78 * When the syscall number is set to -1, the syscall will be
79 * skipped. In this case the syscall return value has to be
80 * set explicitly, otherwise the first syscall argument is
81 * returned as the syscall return value.
82 */
83 syscall_set_return_value(task, regs, -ENOSYS, 0);
84 return;
85 }
86 if ((IS_ENABLED(CONFIG_AEABI) && !IS_ENABLED(CONFIG_OABI_COMPAT))) {
87 task_thread_info(task)->abi_syscall = nr;
88 return;
89 }
90 task_thread_info(task)->abi_syscall =
91 (task_thread_info(task)->abi_syscall & ~__NR_SYSCALL_MASK) |
92 (nr & __NR_SYSCALL_MASK);
93}
94
95#define SYSCALL_MAX_ARGS 7
96
97static inline void syscall_get_arguments(struct task_struct *task,
98 struct pt_regs *regs,
99 unsigned long *args)
100{
101 args[0] = regs->ARM_ORIG_r0;
102 args++;
103
104 memcpy(args, ®s->ARM_r0 + 1, 5 * sizeof(args[0]));
105}
106
107static inline void syscall_set_arguments(struct task_struct *task,
108 struct pt_regs *regs,
109 const unsigned long *args)
110{
111 memcpy(®s->ARM_r0, args, 6 * sizeof(args[0]));
112 /*
113 * Also copy the first argument into ARM_ORIG_r0
114 * so that syscall_get_arguments() would return it
115 * instead of the previous value.
116 */
117 regs->ARM_ORIG_r0 = regs->ARM_r0;
118}
119
120static inline int syscall_get_arch(struct task_struct *task)
121{
122 /* ARM tasks don't change audit architectures on the fly. */
123 return AUDIT_ARCH_ARM;
124}
125
126#endif /* _ASM_ARM_SYSCALL_H */