From d305ed56ae6008be975e029740f8338f8f66587a Mon Sep 17 00:00:00 2001 From: Michal Biesek Date: Wed, 23 Aug 2023 12:41:13 +0200 Subject: [PATCH] Add nolibc riscv64 support Add `lgcc` to avoid undefined reference to `__clzdi2' Signed-off-by: Michal Biesek --- configure | 4 +- src/Makefile | 2 +- src/arch/riscv64/lib.h | 48 ++++++++++++++++++ src/arch/riscv64/syscall.h | 100 +++++++++++++++++++++++++++++++++++++ src/lib.h | 2 + src/syscall.h | 2 + test/nolibc.c | 8 +-- 7 files changed, 160 insertions(+), 6 deletions(-) create mode 100644 src/arch/riscv64/lib.h create mode 100644 src/arch/riscv64/syscall.h diff --git a/configure b/configure index 079017bb3..88b8ee7d8 100755 --- a/configure +++ b/configure @@ -389,11 +389,11 @@ liburing_nolibc="no" if test "$use_libc" != "yes"; then # - # Currently, CONFIG_NOLIBC only supports x86-64, x86 (32-bit) and aarch64. + # Currently, CONFIG_NOLIBC only supports x86-64, x86 (32-bit), aarch64 and riscv64. # cat > $TMPC << EOF int main(void){ -#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) +#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || (defined(__riscv) && __riscv_xlen == 64) return 0; #else #error libc is needed diff --git a/src/Makefile b/src/Makefile index 7832095be..1a79b5907 100644 --- a/src/Makefile +++ b/src/Makefile @@ -47,7 +47,7 @@ ifeq ($(CONFIG_NOLIBC),y) liburing_srcs += nolibc.c override CFLAGS += -nostdlib -nodefaultlibs -ffreestanding -fno-builtin -fno-stack-protector override CPPFLAGS += -nostdlib -nodefaultlibs -ffreestanding -fno-builtin -fno-stack-protector - override LINK_FLAGS += -nostdlib -nodefaultlibs + override LINK_FLAGS += -nostdlib -nodefaultlibs -lgcc endif override CPPFLAGS += -MT "$@" -MMD -MP -MF "$@.d" diff --git a/src/arch/riscv64/lib.h b/src/arch/riscv64/lib.h new file mode 100644 index 000000000..ef66d764d --- /dev/null +++ b/src/arch/riscv64/lib.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: MIT */ + +#ifndef LIBURING_ARCH_RISCV64_LIB_H +#define LIBURING_ARCH_RISCV64_LIB_H + +#include +#include +#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 */ diff --git a/src/arch/riscv64/syscall.h b/src/arch/riscv64/syscall.h new file mode 100644 index 000000000..42cc6be9a --- /dev/null +++ b/src/arch/riscv64/syscall.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 */ diff --git a/src/lib.h b/src/lib.h index a3081dac0..ab1f0952f 100644 --- a/src/lib.h +++ b/src/lib.h @@ -10,6 +10,8 @@ #include "arch/x86/lib.h" #elif defined(__aarch64__) #include "arch/aarch64/lib.h" +#elif defined(__riscv) && __riscv_xlen == 64 +#include "arch/riscv64/lib.h" #else /* * We don't have nolibc support for this arch. Must use libc! diff --git a/src/syscall.h b/src/syscall.h index 8f03dfc5f..6327f0fa1 100644 --- a/src/syscall.h +++ b/src/syscall.h @@ -37,6 +37,8 @@ static inline bool IS_ERR(const void *ptr) #include "arch/x86/syscall.h" #elif defined(__aarch64__) #include "arch/aarch64/syscall.h" +#elif defined(__riscv) && __riscv_xlen == 64 +#include "arch/riscv64/syscall.h" #else /* * We don't have native syscall wrappers diff --git a/test/nolibc.c b/test/nolibc.c index e996f4009..3b0c4c014 100644 --- a/test/nolibc.c +++ b/test/nolibc.c @@ -6,11 +6,13 @@ * 1) x86 * 2) x86-64 * 3) aarch64 + * 4) riscv64 * */ #include "helpers.h" -#if !defined(__x86_64__) && !defined(__i386__) && !defined(__aarch64__) +#if !defined(__x86_64__) && !defined(__i386__) && !defined(__aarch64__) && (!defined(__riscv) && __riscv_xlen != 64) + /* * This arch doesn't support nolibc. @@ -20,7 +22,7 @@ int main(void) return T_EXIT_SKIP; } -#else /* #if !defined(__x86_64__) && !defined(__i386__) && !defined(__aarch64__) */ +#else /* #if !defined(__x86_64__) && !defined(__i386__) && !defined(__aarch64__) && (!defined(__riscv) && __riscv_xlen != 64) */ #ifndef CONFIG_NOLIBC #define CONFIG_NOLIBC @@ -57,4 +59,4 @@ int main(int argc, char *argv[]) return T_EXIT_PASS; } -#endif /* #if !defined(__x86_64__) && !defined(__i386__) && !defined(__aarch64__) */ +#endif /* #if !defined(__x86_64__) && !defined(__i386__) && !defined(__aarch64__) && (!defined(__riscv) && __riscv_xlen != 64) */