xref: /linux/arch/alpha/include/asm/syscall.h (revision 278de0f04816c97f701456b72af4f59d36440249)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _ASM_ALPHA_SYSCALL_H
3 #define _ASM_ALPHA_SYSCALL_H
4 
5 #include <uapi/linux/audit.h>
6 #include <linux/audit.h>
7 #include <linux/sched.h>
8 #include <linux/types.h>
9 #include <asm/ptrace.h>
10 
11 extern void *sys_call_table[];
12 
13 static inline int syscall_get_arch(struct task_struct *task)
14 {
15 	return AUDIT_ARCH_ALPHA;
16 }
17 
18 static inline long syscall_get_return_value(struct task_struct *task,
19 					    struct pt_regs *regs)
20 {
21 	return regs->r19 ? -(long)regs->r0 : (long)regs->r0;
22 }
23 
24 static inline long syscall_get_error(struct task_struct *task,
25 				     struct pt_regs *regs)
26 {
27 	return regs->r19 ? -(long)regs->r0 : 0;
28 }
29 
30 
31 /*
32  * Alpha syscall ABI / kernel conventions:
33  *  - PAL provides syscall number in r0 on entry.
34  *  - The kernel tracks the active syscall number in regs->r1 (mutable) and
35  *    preserves the original syscall number in regs->r2 for rollback/restart.
36  *  - Return value is in regs->r0, with regs->r19 ("a3") as the error flag
37  *    (0=success, 1=error; on error regs->r0 holds positive errno).
38  */
39 
40 static inline long syscall_get_nr(struct task_struct *task,
41 				struct pt_regs *regs)
42 {
43 	return (long)regs->r1;
44 }
45 
46 static inline void syscall_set_nr(struct task_struct *task,
47 				struct pt_regs *regs,
48 				long nr)
49 {
50 	regs->r1 = (unsigned long)nr;
51 }
52 
53 /*
54  * Syscall arguments:
55  *   regs->r16..regs->r21 carry up to 6 syscall arguments on entry.
56  *   Note: regs->r19 is also used as "a3" (error flag) on syscall return.
57  */
58 
59 static inline void syscall_get_arguments(struct task_struct *task,
60 					struct pt_regs *regs,
61 					unsigned long *args)
62 {
63 	args[0] = regs->r16;
64 	args[1] = regs->r17;
65 	args[2] = regs->r18;
66 	args[3] = regs->r19;
67 	args[4] = regs->r20;
68 	args[5] = regs->r21;
69 }
70 
71 static inline void syscall_set_arguments(struct task_struct *task,
72 					struct pt_regs *regs,
73 					const unsigned long *args)
74 {
75 	regs->r16 = args[0];
76 	regs->r17 = args[1];
77 	regs->r18 = args[2];
78 	regs->r19 = args[3];
79 	regs->r20 = args[4];
80 	regs->r21 = args[5];
81 }
82 /*
83  * Set return value for a syscall.
84  * Alpha uses r0 for return value and r19 ("a3") as the error indicator:
85  *   a3 = 0 => success
86  *   a3 = 1 => error, and userspace interprets r0 as errno (positive).
87  *
88  * The kernel reports errors to userspace by setting a3=1 and placing a
89  * positive errno value in r0. Some syscall paths do this in entry.S,
90  * while others (e.g. seccomp/ptrace helpers) use syscall_set_return_value().
91  */
92 
93 static inline void syscall_set_return_value(struct task_struct *task,
94 					struct pt_regs *regs,
95 					int error, long val)
96 {
97 
98 	if (error) {
99 		/* error is negative errno in this tree */
100 		regs->r0  = (unsigned long)(-error);  /* positive errno */
101 		regs->r19 = 1;                        /* a3 = error */
102 	} else {
103 		regs->r0  = (unsigned long)val;
104 		regs->r19 = 0;                        /* a3 = success */
105 	}
106 }
107 
108 /* Restore the original syscall nr after seccomp/ptrace modified regs->r1. */
109 
110 static inline void syscall_rollback(struct task_struct *task,
111 					struct pt_regs *regs)
112 {
113 	unsigned long nr = task_thread_info(task)->syscall_saved_nr;
114 
115 	regs->r1 = nr;
116 }
117 
118 static inline bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs)
119 {
120 	return false;
121 }
122 #endif	/* _ASM_ALPHA_SYSCALL_H */
123