feat(syscall): add x86_64 raw syscall layer, errno, internal ABI headers
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
#ifndef VLIBC_INTERNAL_ARCH_X86_64_SYSCALL_ARCH_H
|
||||
#define VLIBC_INTERNAL_ARCH_X86_64_SYSCALL_ARCH_H
|
||||
|
||||
/*
|
||||
* vlibc — x86_64 raw syscall entry (arch layer).
|
||||
*
|
||||
* The System V AMD64 kernel ABI: the syscall number goes in rax, arguments in
|
||||
* rdi, rsi, rdx, r10, r8, r9 (this order; the fourth argument is r10, NOT
|
||||
* rcx), and the kernel clobbers rcx and r11. The kernel returns the raw
|
||||
* result in rax: a non-negative value on success, or -errno on error. Callers
|
||||
* funnel rax through syscall_ret() (see src/internal/syscall.h), which
|
||||
* translates the negative-errno convention into C return/-1 + errno.
|
||||
*
|
||||
* These wrappers take `long` arguments and return `long` so that pointer-sized
|
||||
* syscall arguments (addresses, off_t) pass through without truncation; the
|
||||
* kernel reads exactly the low 64 bits of each register, so the upper bits of
|
||||
* `long` arguments are irrelevant.
|
||||
*
|
||||
* Each wrapper is `always_inline` so that even a -O0 build collapses to a
|
||||
* bare `syscall` instruction with no call frame. The "memory" clobber tells
|
||||
* the compiler the syscall may read or write anything the caller can see,
|
||||
* which is always the safe assumption.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The __syscall<n> names sit in the implementation-reserved namespace (they
|
||||
* are this libc's private kernel-ABI seam, never public API), and every
|
||||
* argument is a `long` because that is the shape of the x86_64 syscall
|
||||
* register file — both properties are intentional, so the corresponding
|
||||
* bugprone checks are waived per function.
|
||||
*/
|
||||
|
||||
// NOLINTBEGIN(bugprone-easily-swappable-parameters,bugprone-reserved-identifier)
|
||||
|
||||
static inline long __attribute__((always_inline))
|
||||
__syscall0(long n)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
__asm__ volatile("syscall" : "=a"(ret) : "a"(n) : "rcx", "r11", "memory");
|
||||
return (long)ret;
|
||||
}
|
||||
|
||||
static inline long __attribute__((always_inline))
|
||||
__syscall1(long n, long a)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
__asm__ volatile("syscall" : "=a"(ret) : "a"(n), "D"(a) : "rcx", "r11", "memory");
|
||||
return (long)ret;
|
||||
}
|
||||
|
||||
static inline long __attribute__((always_inline))
|
||||
__syscall2(long n, long a, long b)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
__asm__ volatile("syscall" : "=a"(ret) : "a"(n), "D"(a), "S"(b) : "rcx", "r11", "memory");
|
||||
return (long)ret;
|
||||
}
|
||||
|
||||
static inline long __attribute__((always_inline))
|
||||
__syscall3(long n, long a, long b, long c)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
__asm__ volatile("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(n), "D"(a), "S"(b), "d"(c)
|
||||
: "rcx", "r11", "memory");
|
||||
return (long)ret;
|
||||
}
|
||||
|
||||
static inline long __attribute__((always_inline))
|
||||
__syscall4(long n, long a, long b, long c, long d)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
__asm__ volatile("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(n), "D"(a), "S"(b), "d"(c), "r"(d)
|
||||
: "rcx", "r11", "memory");
|
||||
return (long)ret;
|
||||
}
|
||||
|
||||
static inline long __attribute__((always_inline))
|
||||
__syscall5(long n, long a, long b, long c, long d, long e)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
__asm__ volatile("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(n), "D"(a), "S"(b), "d"(c), "r"(d), "r"(e)
|
||||
: "rcx", "r11", "memory");
|
||||
return (long)ret;
|
||||
}
|
||||
|
||||
static inline long __attribute__((always_inline))
|
||||
__syscall6(long n, long a, long b, long c, long d, long e, long f)
|
||||
{
|
||||
unsigned long ret;
|
||||
register long r10 __asm__("r10") = d;
|
||||
register long r8 __asm__("r8") = e;
|
||||
register long r9 __asm__("r9") = f;
|
||||
|
||||
__asm__ volatile("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(n), "D"(a), "S"(b), "d"(c), "r"(r10), "r"(r8), "r"(r9)
|
||||
: "rcx", "r11", "memory");
|
||||
return (long)ret;
|
||||
}
|
||||
|
||||
// NOLINTEND(bugprone-easily-swappable-parameters,bugprone-reserved-identifier)
|
||||
|
||||
#endif /* VLIBC_INTERNAL_ARCH_X86_64_SYSCALL_ARCH_H */
|
||||
Reference in New Issue
Block a user