xref: /openbmc/linux/arch/arm64/include/asm/syscall.h (revision 7d8b31b7)
1caab277bSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
2f27bb139SMarc Zyngier /*
3f27bb139SMarc Zyngier  * Copyright (C) 2012 ARM Ltd.
4f27bb139SMarc Zyngier  */
5f27bb139SMarc Zyngier #ifndef __ASM_SYSCALL_H
6f27bb139SMarc Zyngier #define __ASM_SYSCALL_H
7f27bb139SMarc Zyngier 
8875cbf3eSAKASHI Takahiro #include <uapi/linux/audit.h>
9875cbf3eSAKASHI Takahiro #include <linux/compat.h>
10f27bb139SMarc Zyngier #include <linux/err.h>
11f27bb139SMarc Zyngier 
128ef8f368SSami Tolvanen typedef long (*syscall_fn_t)(const struct pt_regs *regs);
1327d83e68SMark Rutland 
1427d83e68SMark Rutland extern const syscall_fn_t sys_call_table[];
15f27bb139SMarc Zyngier 
163b714275SMark Rutland #ifdef CONFIG_COMPAT
173b714275SMark Rutland extern const syscall_fn_t compat_sys_call_table[];
183b714275SMark Rutland #endif
193b714275SMark Rutland 
syscall_get_nr(struct task_struct * task,struct pt_regs * regs)20f27bb139SMarc Zyngier static inline int syscall_get_nr(struct task_struct *task,
21f27bb139SMarc Zyngier 				 struct pt_regs *regs)
22f27bb139SMarc Zyngier {
23f27bb139SMarc Zyngier 	return regs->syscallno;
24f27bb139SMarc Zyngier }
25f27bb139SMarc Zyngier 
syscall_rollback(struct task_struct * task,struct pt_regs * regs)26f27bb139SMarc Zyngier static inline void syscall_rollback(struct task_struct *task,
27f27bb139SMarc Zyngier 				    struct pt_regs *regs)
28f27bb139SMarc Zyngier {
29f27bb139SMarc Zyngier 	regs->regs[0] = regs->orig_x0;
30f27bb139SMarc Zyngier }
31f27bb139SMarc Zyngier 
syscall_get_return_value(struct task_struct * task,struct pt_regs * regs)32e30e8d46SMark Rutland static inline long syscall_get_return_value(struct task_struct *task,
33e30e8d46SMark Rutland 					    struct pt_regs *regs)
34e30e8d46SMark Rutland {
35e30e8d46SMark Rutland 	unsigned long val = regs->regs[0];
36e30e8d46SMark Rutland 
37e30e8d46SMark Rutland 	if (is_compat_thread(task_thread_info(task)))
38e30e8d46SMark Rutland 		val = sign_extend64(val, 31);
39e30e8d46SMark Rutland 
40e30e8d46SMark Rutland 	return val;
41e30e8d46SMark Rutland }
42f27bb139SMarc Zyngier 
syscall_get_error(struct task_struct * task,struct pt_regs * regs)43f27bb139SMarc Zyngier static inline long syscall_get_error(struct task_struct *task,
44f27bb139SMarc Zyngier 				     struct pt_regs *regs)
45f27bb139SMarc Zyngier {
46e30e8d46SMark Rutland 	unsigned long error = syscall_get_return_value(task, regs);
4715956689SWill Deacon 
48f27bb139SMarc Zyngier 	return IS_ERR_VALUE(error) ? error : 0;
49f27bb139SMarc Zyngier }
50f27bb139SMarc Zyngier 
syscall_set_return_value(struct task_struct * task,struct pt_regs * regs,int error,long val)51f27bb139SMarc Zyngier static inline void syscall_set_return_value(struct task_struct *task,
52f27bb139SMarc Zyngier 					    struct pt_regs *regs,
53f27bb139SMarc Zyngier 					    int error, long val)
54f27bb139SMarc Zyngier {
5515956689SWill Deacon 	if (error)
5615956689SWill Deacon 		val = error;
5715956689SWill Deacon 
5815956689SWill Deacon 	if (is_compat_thread(task_thread_info(task)))
5915956689SWill Deacon 		val = lower_32_bits(val);
6015956689SWill Deacon 
6115956689SWill Deacon 	regs->regs[0] = val;
62f27bb139SMarc Zyngier }
63f27bb139SMarc Zyngier 
64f27bb139SMarc Zyngier #define SYSCALL_MAX_ARGS 6
65f27bb139SMarc Zyngier 
syscall_get_arguments(struct task_struct * task,struct pt_regs * regs,unsigned long * args)66f27bb139SMarc Zyngier static inline void syscall_get_arguments(struct task_struct *task,
67f27bb139SMarc Zyngier 					 struct pt_regs *regs,
68f27bb139SMarc Zyngier 					 unsigned long *args)
69f27bb139SMarc Zyngier {
70f27bb139SMarc Zyngier 	args[0] = regs->orig_x0;
71f27bb139SMarc Zyngier 	args++;
72f27bb139SMarc Zyngier 
73b35f549dSSteven Rostedt (Red Hat) 	memcpy(args, &regs->regs[1], 5 * sizeof(args[0]));
74f27bb139SMarc Zyngier }
75f27bb139SMarc Zyngier 
76875cbf3eSAKASHI Takahiro /*
77875cbf3eSAKASHI Takahiro  * We don't care about endianness (__AUDIT_ARCH_LE bit) here because
78875cbf3eSAKASHI Takahiro  * AArch64 has the same system calls both on little- and big- endian.
79875cbf3eSAKASHI Takahiro  */
syscall_get_arch(struct task_struct * task)8016add411SDmitry V. Levin static inline int syscall_get_arch(struct task_struct *task)
81875cbf3eSAKASHI Takahiro {
8216add411SDmitry V. Levin 	if (is_compat_thread(task_thread_info(task)))
83875cbf3eSAKASHI Takahiro 		return AUDIT_ARCH_ARM;
84875cbf3eSAKASHI Takahiro 
85875cbf3eSAKASHI Takahiro 	return AUDIT_ARCH_AARCH64;
86875cbf3eSAKASHI Takahiro }
87875cbf3eSAKASHI Takahiro 
88*7d8b31b7SArnd Bergmann int syscall_trace_enter(struct pt_regs *regs);
89*7d8b31b7SArnd Bergmann void syscall_trace_exit(struct pt_regs *regs);
90*7d8b31b7SArnd Bergmann 
91f27bb139SMarc Zyngier #endif	/* __ASM_SYSCALL_H */
92