1/* Copyright (C) 2001-2020 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C 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.1 of the License, or (at your option) any later version.
8
9 The GNU C 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 the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
17
18#ifndef _LINUX_X86_64_SYSDEP_H
19#define _LINUX_X86_64_SYSDEP_H 1
20
21/* There is some commonality. */
22#include <sysdeps/unix/sysv/linux/sysdep.h>
23#include <sysdeps/unix/x86_64/sysdep.h>
24#include <tls.h>
25
26/* Defines RTLD_PRIVATE_ERRNO. */
27#include <dl-sysdep.h>
28
29/* For Linux we can use the system call table in the header file
30 /usr/include/asm/unistd.h
31 of the kernel. But these symbols do not follow the SYS_* syntax
32 so we have to redefine the `SYS_ify' macro here. */
33#undef SYS_ify
34#define SYS_ify(syscall_name) __NR_##syscall_name
35
36/* This is to help the old kernel headers where __NR_semtimedop is not
37 available. */
38#ifndef __NR_semtimedop
39# define __NR_semtimedop 220
40#endif
41
42
43#ifdef __ASSEMBLER__
44
45/* Linux uses a negative return value to indicate syscall errors,
46 unlike most Unices, which use the condition codes' carry flag.
47
48 Since version 2.1 the return value of a system call might be
49 negative even if the call succeeded. E.g., the `lseek' system call
50 might return a large offset. Therefore we must not anymore test
51 for < 0, but test for a real error by making sure the value in %eax
52 is a real error number. Linus said he will make sure the no syscall
53 returns a value in -1 .. -4095 as a valid result so we can savely
54 test with -4095. */
55
56/* We don't want the label for the error handle to be global when we define
57 it here. */
58# ifdef PIC
59# define SYSCALL_ERROR_LABEL 0f
60# else
61# define SYSCALL_ERROR_LABEL syscall_error
62# endif
63
64# undef PSEUDO
65# define PSEUDO(name, syscall_name, args) \
66 .text; \
67 ENTRY (name) \
68 DO_CALL (syscall_name, args); \
69 cmpq $-4095, %rax; \
70 jae SYSCALL_ERROR_LABEL
71
72# undef PSEUDO_END
73# define PSEUDO_END(name) \
74 SYSCALL_ERROR_HANDLER \
75 END (name)
76
77# undef PSEUDO_NOERRNO
78# define PSEUDO_NOERRNO(name, syscall_name, args) \
79 .text; \
80 ENTRY (name) \
81 DO_CALL (syscall_name, args)
82
83# undef PSEUDO_END_NOERRNO
84# define PSEUDO_END_NOERRNO(name) \
85 END (name)
86
87# define ret_NOERRNO ret
88
89# undef PSEUDO_ERRVAL
90# define PSEUDO_ERRVAL(name, syscall_name, args) \
91 .text; \
92 ENTRY (name) \
93 DO_CALL (syscall_name, args); \
94 negq %rax
95
96# undef PSEUDO_END_ERRVAL
97# define PSEUDO_END_ERRVAL(name) \
98 END (name)
99
100# define ret_ERRVAL ret
101
102# if defined PIC && RTLD_PRIVATE_ERRNO
103# define SYSCALL_SET_ERRNO \
104 lea rtld_errno(%rip), %RCX_LP; \
105 neg %eax; \
106 movl %eax, (%rcx)
107# else
108# if IS_IN (libc)
109# define SYSCALL_ERROR_ERRNO __libc_errno
110# else
111# define SYSCALL_ERROR_ERRNO errno
112# endif
113# define SYSCALL_SET_ERRNO \
114 movq SYSCALL_ERROR_ERRNO@GOTTPOFF(%rip), %rcx;\
115 neg %eax; \
116 movl %eax, %fs:(%rcx);
117# endif
118
119# ifndef PIC
120# define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */
121# else
122# define SYSCALL_ERROR_HANDLER \
1230: \
124 SYSCALL_SET_ERRNO; \
125 or $-1, %RAX_LP; \
126 ret;
127# endif /* PIC */
128
129/* The Linux/x86-64 kernel expects the system call parameters in
130 registers according to the following table:
131
132 syscall number rax
133 arg 1 rdi
134 arg 2 rsi
135 arg 3 rdx
136 arg 4 r10
137 arg 5 r8
138 arg 6 r9
139
140 The Linux kernel uses and destroys internally these registers:
141 return address from
142 syscall rcx
143 eflags from syscall r11
144
145 Normal function call, including calls to the system call stub
146 functions in the libc, get the first six parameters passed in
147 registers and the seventh parameter and later on the stack. The
148 register use is as follows:
149
150 system call number in the DO_CALL macro
151 arg 1 rdi
152 arg 2 rsi
153 arg 3 rdx
154 arg 4 rcx
155 arg 5 r8
156 arg 6 r9
157
158 We have to take care that the stack is aligned to 16 bytes. When
159 called the stack is not aligned since the return address has just
160 been pushed.
161
162
163 Syscalls of more than 6 arguments are not supported. */
164
165# undef DO_CALL
166# define DO_CALL(syscall_name, args) \
167 DOARGS_##args \
168 movl $SYS_ify (syscall_name), %eax; \
169 syscall;
170
171# define DOARGS_0 /* nothing */
172# define DOARGS_1 /* nothing */
173# define DOARGS_2 /* nothing */
174# define DOARGS_3 /* nothing */
175# define DOARGS_4 movq %rcx, %r10;
176# define DOARGS_5 DOARGS_4
177# define DOARGS_6 DOARGS_5
178
179#else /* !__ASSEMBLER__ */
180/* Define a macro which expands inline into the wrapper code for a system
181 call. */
182# undef INLINE_SYSCALL
183# define INLINE_SYSCALL(name, nr, args...) \
184 ({ \
185 unsigned long int resultvar = INTERNAL_SYSCALL (name, , nr, args); \
186 if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (resultvar, ))) \
187 { \
188 __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, )); \
189 resultvar = (unsigned long int) -1; \
190 } \
191 (long int) resultvar; })
192
193/* Define a macro with explicit types for arguments, which expands inline
194 into the wrapper code for a system call. It should be used when size
195 of any argument > size of long int. */
196# undef INLINE_SYSCALL_TYPES
197# define INLINE_SYSCALL_TYPES(name, nr, args...) \
198 ({ \
199 unsigned long int resultvar = INTERNAL_SYSCALL_TYPES (name, , nr, args); \
200 if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (resultvar, ))) \
201 { \
202 __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, )); \
203 resultvar = (unsigned long int) -1; \
204 } \
205 (long int) resultvar; })
206
207# undef INTERNAL_SYSCALL_DECL
208# define INTERNAL_SYSCALL_DECL(err) do { } while (0)
209
210/* Registers clobbered by syscall. */
211# define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx"
212
213/* Create a variable 'name' based on type 'X' to avoid explicit types.
214 This is mainly used set use 64-bits arguments in x32. */
215#define TYPEFY(X, name) __typeof__ ((X) - (X)) name
216/* Explicit cast the argument to avoid integer from pointer warning on
217 x32. */
218#define ARGIFY(X) ((__typeof__ ((X) - (X))) (X))
219
220#undef INTERNAL_SYSCALL
221#define INTERNAL_SYSCALL(name, err, nr, args...) \
222 internal_syscall##nr (SYS_ify (name), err, args)
223
224#undef INTERNAL_SYSCALL_NCS
225#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
226 internal_syscall##nr (number, err, args)
227
228#undef internal_syscall0
229#define internal_syscall0(number, err, dummy...) \
230({ \
231 unsigned long int resultvar; \
232 asm volatile ( \
233 "syscall\n\t" \
234 : "=a" (resultvar) \
235 : "0" (number) \
236 : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
237 (long int) resultvar; \
238})
239
240#undef internal_syscall1
241#define internal_syscall1(number, err, arg1) \
242({ \
243 unsigned long int resultvar; \
244 TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
245 register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
246 asm volatile ( \
247 "syscall\n\t" \
248 : "=a" (resultvar) \
249 : "0" (number), "r" (_a1) \
250 : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
251 (long int) resultvar; \
252})
253
254#undef internal_syscall2
255#define internal_syscall2(number, err, arg1, arg2) \
256({ \
257 unsigned long int resultvar; \
258 TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
259 TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
260 register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
261 register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
262 asm volatile ( \
263 "syscall\n\t" \
264 : "=a" (resultvar) \
265 : "0" (number), "r" (_a1), "r" (_a2) \
266 : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
267 (long int) resultvar; \
268})
269
270#undef internal_syscall3
271#define internal_syscall3(number, err, arg1, arg2, arg3) \
272({ \
273 unsigned long int resultvar; \
274 TYPEFY (arg3, __arg3) = ARGIFY (arg3); \
275 TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
276 TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
277 register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \
278 register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
279 register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
280 asm volatile ( \
281 "syscall\n\t" \
282 : "=a" (resultvar) \
283 : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3) \
284 : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
285 (long int) resultvar; \
286})
287
288#undef internal_syscall4
289#define internal_syscall4(number, err, arg1, arg2, arg3, arg4) \
290({ \
291 unsigned long int resultvar; \
292 TYPEFY (arg4, __arg4) = ARGIFY (arg4); \
293 TYPEFY (arg3, __arg3) = ARGIFY (arg3); \
294 TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
295 TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
296 register TYPEFY (arg4, _a4) asm ("r10") = __arg4; \
297 register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \
298 register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
299 register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
300 asm volatile ( \
301 "syscall\n\t" \
302 : "=a" (resultvar) \
303 : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4) \
304 : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
305 (long int) resultvar; \
306})
307
308#undef internal_syscall5
309#define internal_syscall5(number, err, arg1, arg2, arg3, arg4, arg5) \
310({ \
311 unsigned long int resultvar; \
312 TYPEFY (arg5, __arg5) = ARGIFY (arg5); \
313 TYPEFY (arg4, __arg4) = ARGIFY (arg4); \
314 TYPEFY (arg3, __arg3) = ARGIFY (arg3); \
315 TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
316 TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
317 register TYPEFY (arg5, _a5) asm ("r8") = __arg5; \
318 register TYPEFY (arg4, _a4) asm ("r10") = __arg4; \
319 register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \
320 register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
321 register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
322 asm volatile ( \
323 "syscall\n\t" \
324 : "=a" (resultvar) \
325 : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4), \
326 "r" (_a5) \
327 : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
328 (long int) resultvar; \
329})
330
331#undef internal_syscall6
332#define internal_syscall6(number, err, arg1, arg2, arg3, arg4, arg5, arg6) \
333({ \
334 unsigned long int resultvar; \
335 TYPEFY (arg6, __arg6) = ARGIFY (arg6); \
336 TYPEFY (arg5, __arg5) = ARGIFY (arg5); \
337 TYPEFY (arg4, __arg4) = ARGIFY (arg4); \
338 TYPEFY (arg3, __arg3) = ARGIFY (arg3); \
339 TYPEFY (arg2, __arg2) = ARGIFY (arg2); \
340 TYPEFY (arg1, __arg1) = ARGIFY (arg1); \
341 register TYPEFY (arg6, _a6) asm ("r9") = __arg6; \
342 register TYPEFY (arg5, _a5) asm ("r8") = __arg5; \
343 register TYPEFY (arg4, _a4) asm ("r10") = __arg4; \
344 register TYPEFY (arg3, _a3) asm ("rdx") = __arg3; \
345 register TYPEFY (arg2, _a2) asm ("rsi") = __arg2; \
346 register TYPEFY (arg1, _a1) asm ("rdi") = __arg1; \
347 asm volatile ( \
348 "syscall\n\t" \
349 : "=a" (resultvar) \
350 : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4), \
351 "r" (_a5), "r" (_a6) \
352 : "memory", REGISTERS_CLOBBERED_BY_SYSCALL); \
353 (long int) resultvar; \
354})
355
356# undef INTERNAL_SYSCALL_ERROR_P
357# define INTERNAL_SYSCALL_ERROR_P(val, err) \
358 ((unsigned long int) (long int) (val) >= -4095L)
359
360# undef INTERNAL_SYSCALL_ERRNO
361# define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))
362
363# define VDSO_NAME "LINUX_2.6"
364# define VDSO_HASH 61765110
365
366/* List of system calls which are supported as vsyscalls. */
367# define HAVE_CLOCK_GETTIME64_VSYSCALL "__vdso_clock_gettime"
368# define HAVE_GETTIMEOFDAY_VSYSCALL "__vdso_gettimeofday"
369# define HAVE_TIME_VSYSCALL "__vdso_time"
370# define HAVE_GETCPU_VSYSCALL "__vdso_getcpu"
371# define HAVE_CLOCK_GETRES64_VSYSCALL "__vdso_clock_getres"
372
373# define SINGLE_THREAD_BY_GLOBAL 1
374
375#endif /* __ASSEMBLER__ */
376
377
378/* Pointer mangling support. */
379#if IS_IN (rtld)
380/* We cannot use the thread descriptor because in ld.so we use setjmp
381 earlier than the descriptor is initialized. */
382# ifdef __ASSEMBLER__
383# define PTR_MANGLE(reg) xor __pointer_chk_guard_local(%rip), reg; \
384 rol $2*LP_SIZE+1, reg
385# define PTR_DEMANGLE(reg) ror $2*LP_SIZE+1, reg; \
386 xor __pointer_chk_guard_local(%rip), reg
387# else
388# define PTR_MANGLE(reg) asm ("xor __pointer_chk_guard_local(%%rip), %0\n" \
389 "rol $2*" LP_SIZE "+1, %0" \
390 : "=r" (reg) : "0" (reg))
391# define PTR_DEMANGLE(reg) asm ("ror $2*" LP_SIZE "+1, %0\n" \
392 "xor __pointer_chk_guard_local(%%rip), %0" \
393 : "=r" (reg) : "0" (reg))
394# endif
395#else
396# ifdef __ASSEMBLER__
397# define PTR_MANGLE(reg) xor %fs:POINTER_GUARD, reg; \
398 rol $2*LP_SIZE+1, reg
399# define PTR_DEMANGLE(reg) ror $2*LP_SIZE+1, reg; \
400 xor %fs:POINTER_GUARD, reg
401# else
402# define PTR_MANGLE(var) asm ("xor %%fs:%c2, %0\n" \
403 "rol $2*" LP_SIZE "+1, %0" \
404 : "=r" (var) \
405 : "0" (var), \
406 "i" (offsetof (tcbhead_t, \
407 pointer_guard)))
408# define PTR_DEMANGLE(var) asm ("ror $2*" LP_SIZE "+1, %0\n" \
409 "xor %%fs:%c2, %0" \
410 : "=r" (var) \
411 : "0" (var), \
412 "i" (offsetof (tcbhead_t, \
413 pointer_guard)))
414# endif
415#endif
416
417/* How to pass the off{64}_t argument on p{readv,writev}{64}. */
418#undef LO_HI_LONG
419#define LO_HI_LONG(val) (val), 0
420
421/* Each shadow stack slot takes 8 bytes. Assuming that each stack
422 frame takes 256 bytes, this is used to compute shadow stack size
423 from stack size. */
424#define STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT 5
425
426#endif /* linux/x86_64/sysdep.h */
427