Xenomai  3.1
syscall.h
1 /*
2  * Copyright (C) 2001,2002,2003,2007 Philippe Gerum <rpm@xenomai.org>.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18 #ifndef _LIB_COBALT_POWERPC_SYSCALL_H
19 #define _LIB_COBALT_POWERPC_SYSCALL_H
20 
21 #include <xeno_config.h>
22 #include <cobalt/uapi/syscall.h>
23 
24 /* Some code pulled from glibc's inline syscalls. */
25 
26 #ifdef __i386__
27 
28 #ifdef CONFIG_XENO_X86_VSYSCALL
29 /*
30  * This form relies on the kernel's vsyscall support in order to use
31  * the most appropriate syscall entry instruction the CPU supports. We
32  * also depend on the NPTL providing us a pointer to the vsyscall DSO
33  * entry point, to which we branch to instead of issuing a trap.
34  * We assume this pointer to be available at %gs:0x10.
35  */
36 #define DOSYSCALL "call *%%gs:0x10\n\t"
37 #else /* CONFIG_XENO_X86_VSYSCALL */
38 #define DOSYSCALL "int $0x80\n\t"
39 #endif /* CONFIG_XENO_X86_VSYSCALL */
40 
41 /* The one that cannot fail. */
42 #define DOSYSCALLSAFE "int $0x80\n\t"
43 
44 asm (".L__X'%ebx = 1\n\t"
45  ".L__X'%ecx = 2\n\t"
46  ".L__X'%edx = 2\n\t"
47  ".L__X'%eax = 3\n\t"
48  ".L__X'%esi = 3\n\t"
49  ".L__X'%edi = 3\n\t"
50  ".L__X'%ebp = 3\n\t"
51  ".L__X'%esp = 3\n\t"
52  ".macro bpushl name reg\n\t"
53  ".if 1 - \\name\n\t"
54  ".if 2 - \\name\n\t"
55  "pushl %ebx\n\t"
56  ".else\n\t"
57  "xchgl \\reg, %ebx\n\t"
58  ".endif\n\t"
59  ".endif\n\t"
60  ".endm\n\t"
61  ".macro bpopl name reg\n\t"
62  ".if 1 - \\name\n\t"
63  ".if 2 - \\name\n\t"
64  "popl %ebx\n\t"
65  ".else\n\t"
66  "xchgl \\reg, %ebx\n\t"
67  ".endif\n\t"
68  ".endif\n\t"
69  ".endm\n\t"
70  ".macro bmovl name reg\n\t"
71  ".if 1 - \\name\n\t"
72  ".if 2 - \\name\n\t"
73  "movl \\reg, %ebx\n\t"
74  ".endif\n\t"
75  ".endif\n\t"
76  ".endm\n\t");
77 
78 #define XENOMAI_DO_SYSCALL(nr, op, args...) \
79 ({ \
80  unsigned __resultvar; \
81  asm volatile ( \
82  LOADARGS_##nr \
83  "movl %1, %%eax\n\t" \
84  DOSYSCALL \
85  RESTOREARGS_##nr \
86  : "=a" (__resultvar) \
87  : "i" (__xn_syscode(op)) ASMFMT_##nr(args) \
88  : "memory", "cc"); \
89  (int) __resultvar; \
90 })
91 
92 #define XENOMAI_DO_SYSCALL_SAFE(nr, op, args...) \
93 ({ \
94  unsigned __resultvar; \
95  asm volatile ( \
96  LOADARGS_##nr \
97  "movl %1, %%eax\n\t" \
98  DOSYSCALLSAFE \
99  RESTOREARGS_##nr \
100  : "=a" (__resultvar) \
101  : "i" (__xn_syscode(op)) ASMFMT_##nr(args) \
102  : "memory", "cc"); \
103  (int) __resultvar; \
104 })
105 
106 #define LOADARGS_0
107 #define LOADARGS_1 \
108  "bpushl .L__X'%k2, %k2\n\t" \
109  "bmovl .L__X'%k2, %k2\n\t"
110 #define LOADARGS_2 LOADARGS_1
111 #define LOADARGS_3 LOADARGS_1
112 #define LOADARGS_4 LOADARGS_1
113 #define LOADARGS_5 LOADARGS_1
114 
115 #define RESTOREARGS_0
116 #define RESTOREARGS_1 \
117  "bpopl .L__X'%k2, %k2\n\t"
118 #define RESTOREARGS_2 RESTOREARGS_1
119 #define RESTOREARGS_3 RESTOREARGS_1
120 #define RESTOREARGS_4 RESTOREARGS_1
121 #define RESTOREARGS_5 RESTOREARGS_1
122 
123 #define ASMFMT_0()
124 #define ASMFMT_1(arg1) \
125  , "acdSD" (arg1)
126 #define ASMFMT_2(arg1, arg2) \
127  , "adSD" (arg1), "c" (arg2)
128 #define ASMFMT_3(arg1, arg2, arg3) \
129  , "aSD" (arg1), "c" (arg2), "d" (arg3)
130 #define ASMFMT_4(arg1, arg2, arg3, arg4) \
131  , "aD" (arg1), "c" (arg2), "d" (arg3), "S" (arg4)
132 #define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \
133  , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5)
134 
135 #define XENOMAI_SYSBIND(breq) \
136  XENOMAI_DO_SYSCALL_SAFE(1, sc_cobalt_bind, breq)
137 
138 #else /* x86_64 */
139 
140 #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3)
141 #define LOAD_ARGS_0() asm volatile ("" : /* */ : /* */ : "memory");
142 #else
143 #define LOAD_ARGS_0()
144 #endif
145 #define LOAD_REGS_0
146 #define ASM_ARGS_0
147 
148 #define LOAD_ARGS_1(a1) \
149  long int __arg1 = (long) (a1); \
150  LOAD_ARGS_0()
151 #define LOAD_REGS_1 \
152  register long int _a1 asm ("rdi") = __arg1; \
153  LOAD_REGS_0
154 #define ASM_ARGS_1 ASM_ARGS_0, "r" (_a1)
155 
156 #define LOAD_ARGS_2(a1, a2) \
157  long int __arg2 = (long) (a2); \
158  LOAD_ARGS_1(a1)
159 #define LOAD_REGS_2 \
160  register long int _a2 asm ("rsi") = __arg2; \
161  LOAD_REGS_1
162 #define ASM_ARGS_2 ASM_ARGS_1, "r" (_a2)
163 
164 #define LOAD_ARGS_3(a1, a2, a3) \
165  long int __arg3 = (long) (a3); \
166  LOAD_ARGS_2 (a1, a2)
167 #define LOAD_REGS_3 \
168  register long int _a3 asm ("rdx") = __arg3; \
169  LOAD_REGS_2
170 #define ASM_ARGS_3 ASM_ARGS_2, "r" (_a3)
171 
172 #define LOAD_ARGS_4(a1, a2, a3, a4) \
173  long int __arg4 = (long) (a4); \
174  LOAD_ARGS_3 (a1, a2, a3)
175 #define LOAD_REGS_4 \
176  register long int _a4 asm ("r10") = __arg4; \
177  LOAD_REGS_3
178 #define ASM_ARGS_4 ASM_ARGS_3, "r" (_a4)
179 
180 #define LOAD_ARGS_5(a1, a2, a3, a4, a5) \
181  long int __arg5 = (long) (a5); \
182  LOAD_ARGS_4 (a1, a2, a3, a4)
183 #define LOAD_REGS_5 \
184  register long int _a5 asm ("r8") = __arg5; \
185  LOAD_REGS_4
186 #define ASM_ARGS_5 ASM_ARGS_4, "r" (_a5)
187 
188 #define DO_SYSCALL(name, nr, args...) \
189 ({ \
190  unsigned long __resultvar; \
191  LOAD_ARGS_##nr(args) \
192  LOAD_REGS_##nr \
193  asm volatile ( \
194  "syscall\n\t" \
195  : "=a" (__resultvar) \
196  : "0" (name) ASM_ARGS_##nr \
197  : "memory", "cc", "r11", "cx"); \
198  (int) __resultvar; \
199 })
200 
201 #define XENOMAI_DO_SYSCALL(nr, op, args...) \
202  DO_SYSCALL(__xn_syscode(op), nr, args)
203 
204 #define XENOMAI_SYSBIND(breq) \
205  XENOMAI_DO_SYSCALL(1, sc_cobalt_bind, breq)
206 
207 #endif /* x86_64 */
208 
209 #define XENOMAI_SYSCALL0(op) XENOMAI_DO_SYSCALL(0,op)
210 #define XENOMAI_SYSCALL1(op,a1) XENOMAI_DO_SYSCALL(1,op,a1)
211 #define XENOMAI_SYSCALL2(op,a1,a2) XENOMAI_DO_SYSCALL(2,op,a1,a2)
212 #define XENOMAI_SYSCALL3(op,a1,a2,a3) XENOMAI_DO_SYSCALL(3,op,a1,a2,a3)
213 #define XENOMAI_SYSCALL4(op,a1,a2,a3,a4) XENOMAI_DO_SYSCALL(4,op,a1,a2,a3,a4)
214 #define XENOMAI_SYSCALL5(op,a1,a2,a3,a4,a5) XENOMAI_DO_SYSCALL(5,op,a1,a2,a3,a4,a5)
215 
216 #endif /* !_LIB_COBALT_POWERPC_SYSCALL_H */