Include liburing in static build
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef LIBURING_ARCH_AARCH64_LIB_H
|
||||
#define LIBURING_ARCH_AARCH64_LIB_H
|
||||
|
||||
#include <elf.h>
|
||||
#include "../../syscall.h"
|
||||
|
||||
static inline long __get_page_size(void)
|
||||
{
|
||||
Elf64_Off buf[2];
|
||||
long ret = 4096;
|
||||
int fd;
|
||||
|
||||
fd = __sys_open("/proc/self/auxv", O_RDONLY, 0);
|
||||
if (fd < 0)
|
||||
return ret;
|
||||
|
||||
while (1) {
|
||||
ssize_t x;
|
||||
|
||||
x = __sys_read(fd, buf, sizeof(buf));
|
||||
if (x < (long) sizeof(buf))
|
||||
break;
|
||||
|
||||
if (buf[0] == AT_PAGESZ) {
|
||||
ret = buf[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
__sys_close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline long get_page_size(void)
|
||||
{
|
||||
static long cache_val;
|
||||
|
||||
if (cache_val)
|
||||
return cache_val;
|
||||
|
||||
cache_val = __get_page_size();
|
||||
return cache_val;
|
||||
}
|
||||
|
||||
#endif /* #ifndef LIBURING_ARCH_AARCH64_LIB_H */
|
||||
@@ -0,0 +1,91 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef LIBURING_ARCH_AARCH64_SYSCALL_H
|
||||
#define LIBURING_ARCH_AARCH64_SYSCALL_H
|
||||
|
||||
#if defined(__aarch64__)
|
||||
|
||||
#define __do_syscallN(...) ({ \
|
||||
__asm__ volatile ( \
|
||||
"svc 0" \
|
||||
: "=r"(x0) \
|
||||
: __VA_ARGS__ \
|
||||
: "memory", "cc"); \
|
||||
(long) x0; \
|
||||
})
|
||||
|
||||
#define __do_syscall0(__n) ({ \
|
||||
register long x8 __asm__("x8") = __n; \
|
||||
register long x0 __asm__("x0"); \
|
||||
\
|
||||
__do_syscallN("r" (x8)); \
|
||||
})
|
||||
|
||||
#define __do_syscall1(__n, __a) ({ \
|
||||
register long x8 __asm__("x8") = __n; \
|
||||
register __typeof__(__a) x0 __asm__("x0") = __a; \
|
||||
\
|
||||
__do_syscallN("r" (x8), "0" (x0)); \
|
||||
})
|
||||
|
||||
#define __do_syscall2(__n, __a, __b) ({ \
|
||||
register long x8 __asm__("x8") = __n; \
|
||||
register __typeof__(__a) x0 __asm__("x0") = __a; \
|
||||
register __typeof__(__b) x1 __asm__("x1") = __b; \
|
||||
\
|
||||
__do_syscallN("r" (x8), "0" (x0), "r" (x1)); \
|
||||
})
|
||||
|
||||
#define __do_syscall3(__n, __a, __b, __c) ({ \
|
||||
register long x8 __asm__("x8") = __n; \
|
||||
register __typeof__(__a) x0 __asm__("x0") = __a; \
|
||||
register __typeof__(__b) x1 __asm__("x1") = __b; \
|
||||
register __typeof__(__c) x2 __asm__("x2") = __c; \
|
||||
\
|
||||
__do_syscallN("r" (x8), "0" (x0), "r" (x1), "r" (x2)); \
|
||||
})
|
||||
|
||||
#define __do_syscall4(__n, __a, __b, __c, __d) ({ \
|
||||
register long x8 __asm__("x8") = __n; \
|
||||
register __typeof__(__a) x0 __asm__("x0") = __a; \
|
||||
register __typeof__(__b) x1 __asm__("x1") = __b; \
|
||||
register __typeof__(__c) x2 __asm__("x2") = __c; \
|
||||
register __typeof__(__d) x3 __asm__("x3") = __d; \
|
||||
\
|
||||
__do_syscallN("r" (x8), "0" (x0), "r" (x1), "r" (x2), "r" (x3));\
|
||||
})
|
||||
|
||||
#define __do_syscall5(__n, __a, __b, __c, __d, __e) ({ \
|
||||
register long x8 __asm__("x8") = __n; \
|
||||
register __typeof__(__a) x0 __asm__("x0") = __a; \
|
||||
register __typeof__(__b) x1 __asm__("x1") = __b; \
|
||||
register __typeof__(__c) x2 __asm__("x2") = __c; \
|
||||
register __typeof__(__d) x3 __asm__("x3") = __d; \
|
||||
register __typeof__(__e) x4 __asm__("x4") = __e; \
|
||||
\
|
||||
__do_syscallN("r" (x8), "0" (x0), "r" (x1), "r" (x2), "r" (x3), \
|
||||
"r"(x4)); \
|
||||
})
|
||||
|
||||
#define __do_syscall6(__n, __a, __b, __c, __d, __e, __f) ({ \
|
||||
register long x8 __asm__("x8") = __n; \
|
||||
register __typeof__(__a) x0 __asm__("x0") = __a; \
|
||||
register __typeof__(__b) x1 __asm__("x1") = __b; \
|
||||
register __typeof__(__c) x2 __asm__("x2") = __c; \
|
||||
register __typeof__(__d) x3 __asm__("x3") = __d; \
|
||||
register __typeof__(__e) x4 __asm__("x4") = __e; \
|
||||
register __typeof__(__f) x5 __asm__("x5") = __f; \
|
||||
\
|
||||
__do_syscallN("r" (x8), "0" (x0), "r" (x1), "r" (x2), "r" (x3), \
|
||||
"r" (x4), "r"(x5)); \
|
||||
})
|
||||
|
||||
#include "../syscall-defs.h"
|
||||
|
||||
#else /* #if defined(__aarch64__) */
|
||||
|
||||
#include "../generic/syscall.h"
|
||||
|
||||
#endif /* #if defined(__aarch64__) */
|
||||
|
||||
#endif /* #ifndef LIBURING_ARCH_AARCH64_SYSCALL_H */
|
||||
@@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef LIBURING_ARCH_GENERIC_LIB_H
|
||||
#define LIBURING_ARCH_GENERIC_LIB_H
|
||||
|
||||
static inline long get_page_size(void)
|
||||
{
|
||||
long page_size;
|
||||
|
||||
page_size = sysconf(_SC_PAGESIZE);
|
||||
if (page_size < 0)
|
||||
page_size = 4096;
|
||||
|
||||
return page_size;
|
||||
}
|
||||
|
||||
#endif /* #ifndef LIBURING_ARCH_GENERIC_LIB_H */
|
||||
@@ -0,0 +1,100 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef LIBURING_ARCH_GENERIC_SYSCALL_H
|
||||
#define LIBURING_ARCH_GENERIC_SYSCALL_H
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
static inline int __sys_io_uring_register(unsigned int fd, unsigned int opcode,
|
||||
const void *arg, unsigned int nr_args)
|
||||
{
|
||||
int ret;
|
||||
ret = syscall(__NR_io_uring_register, fd, opcode, arg, nr_args);
|
||||
return (ret < 0) ? -errno : ret;
|
||||
}
|
||||
|
||||
static inline int __sys_io_uring_setup(unsigned int entries,
|
||||
struct io_uring_params *p)
|
||||
{
|
||||
int ret;
|
||||
ret = syscall(__NR_io_uring_setup, entries, p);
|
||||
return (ret < 0) ? -errno : ret;
|
||||
}
|
||||
|
||||
static inline int __sys_io_uring_enter2(unsigned int fd, unsigned int to_submit,
|
||||
unsigned int min_complete,
|
||||
unsigned int flags, void *arg,
|
||||
size_t sz)
|
||||
{
|
||||
int ret;
|
||||
ret = syscall(__NR_io_uring_enter, fd, to_submit, min_complete, flags,
|
||||
arg, sz);
|
||||
return (ret < 0) ? -errno : ret;
|
||||
}
|
||||
|
||||
static inline int __sys_io_uring_enter(unsigned int fd, unsigned int to_submit,
|
||||
unsigned int min_complete,
|
||||
unsigned int flags, sigset_t *sig)
|
||||
{
|
||||
return __sys_io_uring_enter2(fd, to_submit, min_complete, flags, sig,
|
||||
_NSIG / 8);
|
||||
}
|
||||
|
||||
static inline int __sys_open(const char *pathname, int flags, mode_t mode)
|
||||
{
|
||||
int ret;
|
||||
ret = open(pathname, flags, mode);
|
||||
return (ret < 0) ? -errno : ret;
|
||||
}
|
||||
|
||||
static inline ssize_t __sys_read(int fd, void *buffer, size_t size)
|
||||
{
|
||||
ssize_t ret;
|
||||
ret = read(fd, buffer, size);
|
||||
return (ret < 0) ? -errno : ret;
|
||||
}
|
||||
|
||||
static inline void *__sys_mmap(void *addr, size_t length, int prot, int flags,
|
||||
int fd, off_t offset)
|
||||
{
|
||||
void *ret;
|
||||
ret = mmap(addr, length, prot, flags, fd, offset);
|
||||
return (ret == MAP_FAILED) ? ERR_PTR(-errno) : ret;
|
||||
}
|
||||
|
||||
static inline int __sys_munmap(void *addr, size_t length)
|
||||
{
|
||||
int ret;
|
||||
ret = munmap(addr, length);
|
||||
return (ret < 0) ? -errno : ret;
|
||||
}
|
||||
|
||||
static inline int __sys_madvise(void *addr, size_t length, int advice)
|
||||
{
|
||||
int ret;
|
||||
ret = madvise(addr, length, advice);
|
||||
return (ret < 0) ? -errno : ret;
|
||||
}
|
||||
|
||||
static inline int __sys_getrlimit(int resource, struct rlimit *rlim)
|
||||
{
|
||||
int ret;
|
||||
ret = getrlimit(resource, rlim);
|
||||
return (ret < 0) ? -errno : ret;
|
||||
}
|
||||
|
||||
static inline int __sys_setrlimit(int resource, const struct rlimit *rlim)
|
||||
{
|
||||
int ret;
|
||||
ret = setrlimit(resource, rlim);
|
||||
return (ret < 0) ? -errno : ret;
|
||||
}
|
||||
|
||||
static inline int __sys_close(int fd)
|
||||
{
|
||||
int ret;
|
||||
ret = close(fd);
|
||||
return (ret < 0) ? -errno : ret;
|
||||
}
|
||||
|
||||
#endif /* #ifndef LIBURING_ARCH_GENERIC_SYSCALL_H */
|
||||
@@ -0,0 +1,48 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef LIBURING_ARCH_RISCV64_LIB_H
|
||||
#define LIBURING_ARCH_RISCV64_LIB_H
|
||||
|
||||
#include <elf.h>
|
||||
#include <sys/auxv.h>
|
||||
#include "../../syscall.h"
|
||||
|
||||
static inline long __get_page_size(void)
|
||||
{
|
||||
Elf64_Off buf[2];
|
||||
long ret = 4096;
|
||||
int fd;
|
||||
|
||||
fd = __sys_open("/proc/self/auxv", O_RDONLY, 0);
|
||||
if (fd < 0)
|
||||
return ret;
|
||||
|
||||
while (1) {
|
||||
ssize_t x;
|
||||
|
||||
x = __sys_read(fd, buf, sizeof(buf));
|
||||
if (x < (long) sizeof(buf))
|
||||
break;
|
||||
|
||||
if (buf[0] == AT_PAGESZ) {
|
||||
ret = buf[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
__sys_close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline long get_page_size(void)
|
||||
{
|
||||
static long cache_val;
|
||||
|
||||
if (cache_val)
|
||||
return cache_val;
|
||||
|
||||
cache_val = __get_page_size();
|
||||
return cache_val;
|
||||
}
|
||||
|
||||
#endif /* #ifndef LIBURING_ARCH_RISCV64_LIB_H */
|
||||
@@ -0,0 +1,100 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef LIBURING_ARCH_RISCV64_SYSCALL_H
|
||||
#define LIBURING_ARCH_RISCV64_SYSCALL_H
|
||||
|
||||
#if defined(__riscv) && __riscv_xlen == 64
|
||||
|
||||
#define __do_syscallM(...) ({ \
|
||||
__asm__ volatile ( \
|
||||
"ecall" \
|
||||
: "=r"(a0) \
|
||||
: __VA_ARGS__ \
|
||||
: "memory", "a1"); \
|
||||
(long) a0; \
|
||||
})
|
||||
|
||||
#define __do_syscallN(...) ({ \
|
||||
__asm__ volatile ( \
|
||||
"ecall" \
|
||||
: "=r"(a0) \
|
||||
: __VA_ARGS__ \
|
||||
: "memory"); \
|
||||
(long) a0; \
|
||||
})
|
||||
|
||||
#define __do_syscall0(__n) ({ \
|
||||
register long a7 __asm__("a7") = __n; \
|
||||
register long a0 __asm__("a0"); \
|
||||
\
|
||||
__do_syscallM("r" (a7)); \
|
||||
})
|
||||
|
||||
#define __do_syscall1(__n, __a) ({ \
|
||||
register long a7 __asm__("a7") = __n; \
|
||||
register __typeof__(__a) a0 __asm__("a0") = __a; \
|
||||
\
|
||||
__do_syscallM("r" (a7), "0" (a0)); \
|
||||
})
|
||||
|
||||
#define __do_syscall2(__n, __a, __b) ({ \
|
||||
register long a7 __asm__("a7") = __n; \
|
||||
register __typeof__(__a) a0 __asm__("a0") = __a; \
|
||||
register __typeof__(__b) a1 __asm__("a1") = __b; \
|
||||
\
|
||||
__do_syscallN("r" (a7), "0" (a0), "r" (a1)); \
|
||||
})
|
||||
|
||||
#define __do_syscall3(__n, __a, __b, __c) ({ \
|
||||
register long a7 __asm__("a7") = __n; \
|
||||
register __typeof__(__a) a0 __asm__("a0") = __a; \
|
||||
register __typeof__(__b) a1 __asm__("a1") = __b; \
|
||||
register __typeof__(__c) a2 __asm__("a2") = __c; \
|
||||
\
|
||||
__do_syscallN("r" (a7), "0" (a0), "r" (a1), "r" (a2)); \
|
||||
})
|
||||
|
||||
#define __do_syscall4(__n, __a, __b, __c, __d) ({ \
|
||||
register long a7 __asm__("a7") = __n; \
|
||||
register __typeof__(__a) a0 __asm__("a0") = __a; \
|
||||
register __typeof__(__b) a1 __asm__("a1") = __b; \
|
||||
register __typeof__(__c) a2 __asm__("a2") = __c; \
|
||||
register __typeof__(__d) a3 __asm__("a3") = __d; \
|
||||
\
|
||||
__do_syscallN("r" (a7), "0" (a0), "r" (a1), "r" (a2), "r" (a3));\
|
||||
})
|
||||
|
||||
#define __do_syscall5(__n, __a, __b, __c, __d, __e) ({ \
|
||||
register long a7 __asm__("a7") = __n; \
|
||||
register __typeof__(__a) a0 __asm__("a0") = __a; \
|
||||
register __typeof__(__b) a1 __asm__("a1") = __b; \
|
||||
register __typeof__(__c) a2 __asm__("a2") = __c; \
|
||||
register __typeof__(__d) a3 __asm__("a3") = __d; \
|
||||
register __typeof__(__e) a4 __asm__("a4") = __e; \
|
||||
\
|
||||
__do_syscallN("r" (a7), "0" (a0), "r" (a1), "r" (a2), "r" (a3), \
|
||||
"r"(a4)); \
|
||||
})
|
||||
|
||||
#define __do_syscall6(__n, __a, __b, __c, __d, __e, __f) ({ \
|
||||
register long a7 __asm__("a7") = __n; \
|
||||
register __typeof__(__a) a0 __asm__("a0") = __a; \
|
||||
register __typeof__(__b) a1 __asm__("a1") = __b; \
|
||||
register __typeof__(__c) a2 __asm__("a2") = __c; \
|
||||
register __typeof__(__d) a3 __asm__("a3") = __d; \
|
||||
register __typeof__(__e) a4 __asm__("a4") = __e; \
|
||||
register __typeof__(__f) a5 __asm__("a5") = __f; \
|
||||
\
|
||||
__do_syscallN("r" (a7), "0" (a0), "r" (a1), "r" (a2), "r" (a3), \
|
||||
"r" (a4), "r"(a5)); \
|
||||
})
|
||||
|
||||
#include "../syscall-defs.h"
|
||||
|
||||
#else /* #if defined(__riscv) && __riscv_xlen == 64 */
|
||||
|
||||
#include "../generic/syscall.h"
|
||||
|
||||
#endif /* #if defined(__riscv) && __riscv_xlen == 64 */
|
||||
|
||||
#endif /* #ifndef LIBURING_ARCH_RISCV64_SYSCALL_H */
|
||||
@@ -0,0 +1,94 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef LIBURING_ARCH_SYSCALL_DEFS_H
|
||||
#define LIBURING_ARCH_SYSCALL_DEFS_H
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
static inline int __sys_open(const char *pathname, int flags, mode_t mode)
|
||||
{
|
||||
/*
|
||||
* Some architectures don't have __NR_open, but __NR_openat.
|
||||
*/
|
||||
#ifdef __NR_open
|
||||
return (int) __do_syscall3(__NR_open, pathname, flags, mode);
|
||||
#else
|
||||
return (int) __do_syscall4(__NR_openat, AT_FDCWD, pathname, flags, mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline ssize_t __sys_read(int fd, void *buffer, size_t size)
|
||||
{
|
||||
return (ssize_t) __do_syscall3(__NR_read, fd, buffer, size);
|
||||
}
|
||||
|
||||
static inline void *__sys_mmap(void *addr, size_t length, int prot, int flags,
|
||||
int fd, off_t offset)
|
||||
{
|
||||
int nr;
|
||||
|
||||
#if defined(__NR_mmap2)
|
||||
nr = __NR_mmap2;
|
||||
offset >>= 12;
|
||||
#else
|
||||
nr = __NR_mmap;
|
||||
#endif
|
||||
return (void *) __do_syscall6(nr, addr, length, prot, flags, fd, offset);
|
||||
}
|
||||
|
||||
static inline int __sys_munmap(void *addr, size_t length)
|
||||
{
|
||||
return (int) __do_syscall2(__NR_munmap, addr, length);
|
||||
}
|
||||
|
||||
static inline int __sys_madvise(void *addr, size_t length, int advice)
|
||||
{
|
||||
return (int) __do_syscall3(__NR_madvise, addr, length, advice);
|
||||
}
|
||||
|
||||
static inline int __sys_getrlimit(int resource, struct rlimit *rlim)
|
||||
{
|
||||
return (int) __do_syscall2(__NR_getrlimit, resource, rlim);
|
||||
}
|
||||
|
||||
static inline int __sys_setrlimit(int resource, const struct rlimit *rlim)
|
||||
{
|
||||
return (int) __do_syscall2(__NR_setrlimit, resource, rlim);
|
||||
}
|
||||
|
||||
static inline int __sys_close(int fd)
|
||||
{
|
||||
return (int) __do_syscall1(__NR_close, fd);
|
||||
}
|
||||
|
||||
static inline int __sys_io_uring_register(unsigned int fd, unsigned int opcode,
|
||||
const void *arg, unsigned int nr_args)
|
||||
{
|
||||
return (int) __do_syscall4(__NR_io_uring_register, fd, opcode, arg,
|
||||
nr_args);
|
||||
}
|
||||
|
||||
static inline int __sys_io_uring_setup(unsigned int entries,
|
||||
struct io_uring_params *p)
|
||||
{
|
||||
return (int) __do_syscall2(__NR_io_uring_setup, entries, p);
|
||||
}
|
||||
|
||||
static inline int __sys_io_uring_enter2(unsigned int fd, unsigned int to_submit,
|
||||
unsigned int min_complete,
|
||||
unsigned int flags, void *arg,
|
||||
size_t sz)
|
||||
{
|
||||
return (int) __do_syscall6(__NR_io_uring_enter, fd, to_submit,
|
||||
min_complete, flags, arg, sz);
|
||||
}
|
||||
|
||||
static inline int __sys_io_uring_enter(unsigned int fd, unsigned int to_submit,
|
||||
unsigned int min_complete,
|
||||
unsigned int flags, sigset_t *sig)
|
||||
{
|
||||
return __sys_io_uring_enter2(fd, to_submit, min_complete, flags, sig,
|
||||
_NSIG / 8);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef LIBURING_ARCH_X86_LIB_H
|
||||
#define LIBURING_ARCH_X86_LIB_H
|
||||
|
||||
static inline long get_page_size(void)
|
||||
{
|
||||
return 4096;
|
||||
}
|
||||
|
||||
#endif /* #ifndef LIBURING_ARCH_X86_LIB_H */
|
||||
@@ -0,0 +1,296 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef LIBURING_ARCH_X86_SYSCALL_H
|
||||
#define LIBURING_ARCH_X86_SYSCALL_H
|
||||
|
||||
#if defined(__x86_64__)
|
||||
/**
|
||||
* Note for syscall registers usage (x86-64):
|
||||
* - %rax is the syscall number.
|
||||
* - %rax is also the return value.
|
||||
* - %rdi is the 1st argument.
|
||||
* - %rsi is the 2nd argument.
|
||||
* - %rdx is the 3rd argument.
|
||||
* - %r10 is the 4th argument (**yes it's %r10, not %rcx!**).
|
||||
* - %r8 is the 5th argument.
|
||||
* - %r9 is the 6th argument.
|
||||
*
|
||||
* `syscall` instruction will clobber %r11 and %rcx.
|
||||
*
|
||||
* After the syscall returns to userspace:
|
||||
* - %r11 will contain %rflags.
|
||||
* - %rcx will contain the return address.
|
||||
*
|
||||
* IOW, after the syscall returns to userspace:
|
||||
* %r11 == %rflags and %rcx == %rip.
|
||||
*/
|
||||
|
||||
#define __do_syscall0(NUM) ({ \
|
||||
intptr_t rax; \
|
||||
\
|
||||
__asm__ volatile( \
|
||||
"syscall" \
|
||||
: "=a"(rax) /* %rax */ \
|
||||
: "a"(NUM) /* %rax */ \
|
||||
: "rcx", "r11", "memory" \
|
||||
); \
|
||||
rax; \
|
||||
})
|
||||
|
||||
#define __do_syscall1(NUM, ARG1) ({ \
|
||||
intptr_t rax; \
|
||||
\
|
||||
__asm__ volatile( \
|
||||
"syscall" \
|
||||
: "=a"(rax) /* %rax */ \
|
||||
: "a"((NUM)), /* %rax */ \
|
||||
"D"((ARG1)) /* %rdi */ \
|
||||
: "rcx", "r11", "memory" \
|
||||
); \
|
||||
rax; \
|
||||
})
|
||||
|
||||
#define __do_syscall2(NUM, ARG1, ARG2) ({ \
|
||||
intptr_t rax; \
|
||||
\
|
||||
__asm__ volatile( \
|
||||
"syscall" \
|
||||
: "=a"(rax) /* %rax */ \
|
||||
: "a"((NUM)), /* %rax */ \
|
||||
"D"((ARG1)), /* %rdi */ \
|
||||
"S"((ARG2)) /* %rsi */ \
|
||||
: "rcx", "r11", "memory" \
|
||||
); \
|
||||
rax; \
|
||||
})
|
||||
|
||||
#define __do_syscall3(NUM, ARG1, ARG2, ARG3) ({ \
|
||||
intptr_t rax; \
|
||||
\
|
||||
__asm__ volatile( \
|
||||
"syscall" \
|
||||
: "=a"(rax) /* %rax */ \
|
||||
: "a"((NUM)), /* %rax */ \
|
||||
"D"((ARG1)), /* %rdi */ \
|
||||
"S"((ARG2)), /* %rsi */ \
|
||||
"d"((ARG3)) /* %rdx */ \
|
||||
: "rcx", "r11", "memory" \
|
||||
); \
|
||||
rax; \
|
||||
})
|
||||
|
||||
#define __do_syscall4(NUM, ARG1, ARG2, ARG3, ARG4) ({ \
|
||||
intptr_t rax; \
|
||||
register __typeof__(ARG4) __r10 __asm__("r10") = (ARG4); \
|
||||
\
|
||||
__asm__ volatile( \
|
||||
"syscall" \
|
||||
: "=a"(rax) /* %rax */ \
|
||||
: "a"((NUM)), /* %rax */ \
|
||||
"D"((ARG1)), /* %rdi */ \
|
||||
"S"((ARG2)), /* %rsi */ \
|
||||
"d"((ARG3)), /* %rdx */ \
|
||||
"r"(__r10) /* %r10 */ \
|
||||
: "rcx", "r11", "memory" \
|
||||
); \
|
||||
rax; \
|
||||
})
|
||||
|
||||
#define __do_syscall5(NUM, ARG1, ARG2, ARG3, ARG4, ARG5) ({ \
|
||||
intptr_t rax; \
|
||||
register __typeof__(ARG4) __r10 __asm__("r10") = (ARG4); \
|
||||
register __typeof__(ARG5) __r8 __asm__("r8") = (ARG5); \
|
||||
\
|
||||
__asm__ volatile( \
|
||||
"syscall" \
|
||||
: "=a"(rax) /* %rax */ \
|
||||
: "a"((NUM)), /* %rax */ \
|
||||
"D"((ARG1)), /* %rdi */ \
|
||||
"S"((ARG2)), /* %rsi */ \
|
||||
"d"((ARG3)), /* %rdx */ \
|
||||
"r"(__r10), /* %r10 */ \
|
||||
"r"(__r8) /* %r8 */ \
|
||||
: "rcx", "r11", "memory" \
|
||||
); \
|
||||
rax; \
|
||||
})
|
||||
|
||||
#define __do_syscall6(NUM, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) ({ \
|
||||
intptr_t rax; \
|
||||
register __typeof__(ARG4) __r10 __asm__("r10") = (ARG4); \
|
||||
register __typeof__(ARG5) __r8 __asm__("r8") = (ARG5); \
|
||||
register __typeof__(ARG6) __r9 __asm__("r9") = (ARG6); \
|
||||
\
|
||||
__asm__ volatile( \
|
||||
"syscall" \
|
||||
: "=a"(rax) /* %rax */ \
|
||||
: "a"((NUM)), /* %rax */ \
|
||||
"D"((ARG1)), /* %rdi */ \
|
||||
"S"((ARG2)), /* %rsi */ \
|
||||
"d"((ARG3)), /* %rdx */ \
|
||||
"r"(__r10), /* %r10 */ \
|
||||
"r"(__r8), /* %r8 */ \
|
||||
"r"(__r9) /* %r9 */ \
|
||||
: "rcx", "r11", "memory" \
|
||||
); \
|
||||
rax; \
|
||||
})
|
||||
|
||||
#include "../syscall-defs.h"
|
||||
|
||||
#else /* #if defined(__x86_64__) */
|
||||
|
||||
#ifdef CONFIG_NOLIBC
|
||||
/**
|
||||
* Note for syscall registers usage (x86, 32-bit):
|
||||
* - %eax is the syscall number.
|
||||
* - %eax is also the return value.
|
||||
* - %ebx is the 1st argument.
|
||||
* - %ecx is the 2nd argument.
|
||||
* - %edx is the 3rd argument.
|
||||
* - %esi is the 4th argument.
|
||||
* - %edi is the 5th argument.
|
||||
* - %ebp is the 6th argument.
|
||||
*/
|
||||
|
||||
#define __do_syscall0(NUM) ({ \
|
||||
intptr_t eax; \
|
||||
\
|
||||
__asm__ volatile( \
|
||||
"int $0x80" \
|
||||
: "=a"(eax) /* %eax */ \
|
||||
: "a"(NUM) /* %eax */ \
|
||||
: "memory" \
|
||||
); \
|
||||
eax; \
|
||||
})
|
||||
|
||||
#define __do_syscall1(NUM, ARG1) ({ \
|
||||
intptr_t eax; \
|
||||
\
|
||||
__asm__ volatile( \
|
||||
"int $0x80" \
|
||||
: "=a"(eax) /* %eax */ \
|
||||
: "a"(NUM), /* %eax */ \
|
||||
"b"((ARG1)) /* %ebx */ \
|
||||
: "memory" \
|
||||
); \
|
||||
eax; \
|
||||
})
|
||||
|
||||
#define __do_syscall2(NUM, ARG1, ARG2) ({ \
|
||||
intptr_t eax; \
|
||||
\
|
||||
__asm__ volatile( \
|
||||
"int $0x80" \
|
||||
: "=a" (eax) /* %eax */ \
|
||||
: "a"(NUM), /* %eax */ \
|
||||
"b"((ARG1)), /* %ebx */ \
|
||||
"c"((ARG2)) /* %ecx */ \
|
||||
: "memory" \
|
||||
); \
|
||||
eax; \
|
||||
})
|
||||
|
||||
#define __do_syscall3(NUM, ARG1, ARG2, ARG3) ({ \
|
||||
intptr_t eax; \
|
||||
\
|
||||
__asm__ volatile( \
|
||||
"int $0x80" \
|
||||
: "=a" (eax) /* %eax */ \
|
||||
: "a"(NUM), /* %eax */ \
|
||||
"b"((ARG1)), /* %ebx */ \
|
||||
"c"((ARG2)), /* %ecx */ \
|
||||
"d"((ARG3)) /* %edx */ \
|
||||
: "memory" \
|
||||
); \
|
||||
eax; \
|
||||
})
|
||||
|
||||
#define __do_syscall4(NUM, ARG1, ARG2, ARG3, ARG4) ({ \
|
||||
intptr_t eax; \
|
||||
\
|
||||
__asm__ volatile( \
|
||||
"int $0x80" \
|
||||
: "=a" (eax) /* %eax */ \
|
||||
: "a"(NUM), /* %eax */ \
|
||||
"b"((ARG1)), /* %ebx */ \
|
||||
"c"((ARG2)), /* %ecx */ \
|
||||
"d"((ARG3)), /* %edx */ \
|
||||
"S"((ARG4)) /* %esi */ \
|
||||
: "memory" \
|
||||
); \
|
||||
eax; \
|
||||
})
|
||||
|
||||
#define __do_syscall5(NUM, ARG1, ARG2, ARG3, ARG4, ARG5) ({ \
|
||||
intptr_t eax; \
|
||||
\
|
||||
__asm__ volatile( \
|
||||
"int $0x80" \
|
||||
: "=a" (eax) /* %eax */ \
|
||||
: "a"(NUM), /* %eax */ \
|
||||
"b"((ARG1)), /* %ebx */ \
|
||||
"c"((ARG2)), /* %ecx */ \
|
||||
"d"((ARG3)), /* %edx */ \
|
||||
"S"((ARG4)), /* %esi */ \
|
||||
"D"((ARG5)) /* %edi */ \
|
||||
: "memory" \
|
||||
); \
|
||||
eax; \
|
||||
})
|
||||
|
||||
|
||||
/*
|
||||
* On i386, the 6th argument of syscall goes in %ebp. However, both Clang
|
||||
* and GCC cannot use %ebp in the clobber list and in the "r" constraint
|
||||
* without using -fomit-frame-pointer. To make it always available for
|
||||
* any kind of compilation, the below workaround is implemented:
|
||||
*
|
||||
* 1) Push the 6-th argument.
|
||||
* 2) Push %ebp.
|
||||
* 3) Load the 6-th argument from 4(%esp) to %ebp.
|
||||
* 4) Do the syscall (int $0x80).
|
||||
* 5) Pop %ebp (restore the old value of %ebp).
|
||||
* 6) Add %esp by 4 (undo the stack pointer).
|
||||
*
|
||||
* WARNING:
|
||||
* Don't use register variables for __do_syscall6(), there is a known
|
||||
* GCC bug that results in an endless loop.
|
||||
*
|
||||
* BugLink: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105032
|
||||
*
|
||||
*/
|
||||
#define __do_syscall6(NUM, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) ({ \
|
||||
intptr_t eax = (intptr_t)(NUM); \
|
||||
intptr_t arg6 = (intptr_t)(ARG6); /* Always in memory */ \
|
||||
__asm__ volatile ( \
|
||||
"pushl %[_arg6]\n\t" \
|
||||
"pushl %%ebp\n\t" \
|
||||
"movl 4(%%esp),%%ebp\n\t" \
|
||||
"int $0x80\n\t" \
|
||||
"popl %%ebp\n\t" \
|
||||
"addl $4,%%esp" \
|
||||
: "+a"(eax) /* %eax */ \
|
||||
: "b"(ARG1), /* %ebx */ \
|
||||
"c"(ARG2), /* %ecx */ \
|
||||
"d"(ARG3), /* %edx */ \
|
||||
"S"(ARG4), /* %esi */ \
|
||||
"D"(ARG5), /* %edi */ \
|
||||
[_arg6]"m"(arg6) /* memory */ \
|
||||
: "memory", "cc" \
|
||||
); \
|
||||
eax; \
|
||||
})
|
||||
|
||||
#include "../syscall-defs.h"
|
||||
|
||||
#else /* #ifdef CONFIG_NOLIBC */
|
||||
|
||||
#include "../generic/syscall.h"
|
||||
|
||||
#endif /* #ifdef CONFIG_NOLIBC */
|
||||
|
||||
#endif /* #if defined(__x86_64__) */
|
||||
|
||||
#endif /* #ifndef LIBURING_ARCH_X86_SYSCALL_H */
|
||||
Reference in New Issue
Block a user