xref: /linux/arch/nios2/include/asm/syscall.h (revision 93df8a1ed6231727c5db94a80b1a6bd5ee67cec3)
1 /*
2  * Copyright Altera Corporation (C) <2014>. All rights reserved
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms and conditions of the GNU General Public License,
6  * version 2, as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  * more details.
12  *
13  * You should have received a copy of the GNU General Public License along with
14  * this program.  If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 #ifndef __ASM_NIOS2_SYSCALL_H__
18 #define __ASM_NIOS2_SYSCALL_H__
19 
20 #include <linux/err.h>
21 #include <linux/sched.h>
22 
23 static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
24 {
25 	return regs->r2;
26 }
27 
28 static inline void syscall_rollback(struct task_struct *task,
29 				struct pt_regs *regs)
30 {
31 	regs->r2 = regs->orig_r2;
32 	regs->r7 = regs->orig_r7;
33 }
34 
35 static inline long syscall_get_error(struct task_struct *task,
36 				struct pt_regs *regs)
37 {
38 	return regs->r7 ? regs->r2 : 0;
39 }
40 
41 static inline long syscall_get_return_value(struct task_struct *task,
42 	struct pt_regs *regs)
43 {
44 	return regs->r2;
45 }
46 
47 static inline void syscall_set_return_value(struct task_struct *task,
48 	struct pt_regs *regs, int error, long val)
49 {
50 	if (error) {
51 		/* error < 0, but nios2 uses > 0 return value */
52 		regs->r2 = -error;
53 		regs->r7 = 1;
54 	} else {
55 		regs->r2 = val;
56 		regs->r7 = 0;
57 	}
58 }
59 
60 static inline void syscall_get_arguments(struct task_struct *task,
61 	struct pt_regs *regs, unsigned int i, unsigned int n,
62 	unsigned long *args)
63 {
64 	BUG_ON(i + n > 6);
65 
66 	switch (i) {
67 	case 0:
68 		if (!n--)
69 			break;
70 		*args++ = regs->r4;
71 	case 1:
72 		if (!n--)
73 			break;
74 		*args++ = regs->r5;
75 	case 2:
76 		if (!n--)
77 			break;
78 		*args++ = regs->r6;
79 	case 3:
80 		if (!n--)
81 			break;
82 		*args++ = regs->r7;
83 	case 4:
84 		if (!n--)
85 			break;
86 		*args++ = regs->r8;
87 	case 5:
88 		if (!n--)
89 			break;
90 		*args++ = regs->r9;
91 	case 6:
92 		if (!n--)
93 			break;
94 	default:
95 		BUG();
96 	}
97 }
98 
99 static inline void syscall_set_arguments(struct task_struct *task,
100 	struct pt_regs *regs, unsigned int i, unsigned int n,
101 	const unsigned long *args)
102 {
103 	BUG_ON(i + n > 6);
104 
105 	switch (i) {
106 	case 0:
107 		if (!n--)
108 			break;
109 		regs->r4 = *args++;
110 	case 1:
111 		if (!n--)
112 			break;
113 		regs->r5 = *args++;
114 	case 2:
115 		if (!n--)
116 			break;
117 		regs->r6 = *args++;
118 	case 3:
119 		if (!n--)
120 			break;
121 		regs->r7 = *args++;
122 	case 4:
123 		if (!n--)
124 			break;
125 		regs->r8 = *args++;
126 	case 5:
127 		if (!n--)
128 			break;
129 		regs->r9 = *args++;
130 	case 6:
131 		if (!n)
132 			break;
133 	default:
134 		BUG();
135 	}
136 }
137 
138 #endif
139