Add support for riscv64
Change-Id: Icf8e7adc033339b538310a819f5001d480de0288
Reviewed-on: https://chromium-review.googlesource.com/c/linux-syscall-support/+/3599251
Reviewed-by: Mike Frysinger <vapier@chromium.org>
diff --git a/linux_syscall_support.h b/linux_syscall_support.h
index d3791cd..a48e6fe 100644
--- a/linux_syscall_support.h
+++ b/linux_syscall_support.h
@@ -88,7 +88,8 @@
*/
#if (defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) || \
defined(__mips__) || defined(__PPC__) || defined(__ARM_EABI__) || \
- defined(__aarch64__) || defined(__s390__) || defined(__e2k__)) \
+ defined(__aarch64__) || defined(__s390__) || defined(__e2k__) || \
+ (defined(__riscv) && __riscv_xlen == 64)) \
&& (defined(__linux) || defined(__ANDROID__))
#ifndef SYS_CPLUSPLUS
@@ -302,8 +303,8 @@
} __attribute__((packed,aligned(4)));
#elif (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32)
#define kernel_old_sigaction kernel_sigaction
-#elif defined(__aarch64__)
- // No kernel_old_sigaction defined for arm64.
+#elif defined(__aarch64__) || defined(__riscv)
+ // No kernel_old_sigaction defined for arm64 or riscv.
#endif
/* Some kernel functions (e.g. sigaction() in 2.6.23) require that the
@@ -342,7 +343,9 @@
void (*sa_sigaction_)(int, siginfo_t *, void *);
};
unsigned long sa_flags;
+#ifndef __riscv
void (*sa_restorer)(void);
+#endif
struct kernel_sigset_t sa_mask;
#endif
};
@@ -542,7 +545,7 @@
int st_blocks;
int st_pad4[14];
};
-#elif defined(__aarch64__)
+#elif defined(__aarch64__) || defined(__riscv)
struct kernel_stat {
unsigned long st_dev;
unsigned long st_ino;
@@ -1110,7 +1113,7 @@
#define __NR_getrandom (__NR_SYSCALL_BASE + 384)
#endif
/* End of ARM 3/EABI definitions */
-#elif defined(__aarch64__)
+#elif defined(__aarch64__) || defined(__riscv)
#ifndef __NR_setxattr
#define __NR_setxattr 5
#endif
@@ -1926,7 +1929,7 @@
#undef LSS_RETURN
#if defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) \
|| defined(__ARM_EABI__) || defined(__aarch64__) || defined(__s390__) \
- || defined(__e2k__)
+ || defined(__e2k__) || defined(__riscv)
/* Failing system calls return a negative result in the range of
* -1..-4095. These are "errno" values with the sign inverted.
*/
@@ -3419,6 +3422,122 @@
}
LSS_RETURN(int, __ret);
}
+ #elif defined(__riscv) && __riscv_xlen == 64
+ #undef LSS_REG
+ #define LSS_REG(r,a) register int64_t __r##r __asm__("a"#r) = (int64_t)a
+ #undef LSS_BODY
+ #define LSS_BODY(type,name,args...) \
+ register int64_t __res_a0 __asm__("a0"); \
+ register int64_t __a7 __asm__("a7") = __NR_##name; \
+ int64_t __res; \
+ __asm__ __volatile__ ("scall\n" \
+ : "=r"(__res_a0) \
+ : "r"(__a7) , ## args \
+ : "memory"); \
+ __res = __res_a0; \
+ LSS_RETURN(type, __res)
+ #undef _syscall0
+ #define _syscall0(type, name) \
+ type LSS_NAME(name)(void) { \
+ LSS_BODY(type, name); \
+ }
+ #undef _syscall1
+ #define _syscall1(type, name, type1, arg1) \
+ type LSS_NAME(name)(type1 arg1) { \
+ LSS_REG(0, arg1); LSS_BODY(type, name, "r"(__r0)); \
+ }
+ #undef _syscall2
+ #define _syscall2(type, name, type1, arg1, type2, arg2) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2) { \
+ LSS_REG(0, arg1); LSS_REG(1, arg2); \
+ LSS_BODY(type, name, "r"(__r0), "r"(__r1)); \
+ }
+ #undef _syscall3
+ #define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \
+ LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \
+ LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2)); \
+ }
+ #undef _syscall4
+ #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
+ LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \
+ LSS_REG(3, arg4); \
+ LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3)); \
+ }
+ #undef _syscall5
+ #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+ type5,arg5) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+ type5 arg5) { \
+ LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \
+ LSS_REG(3, arg4); LSS_REG(4, arg5); \
+ LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3), \
+ "r"(__r4)); \
+ }
+ #undef _syscall6
+ #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+ type5,arg5,type6,arg6) \
+ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+ type5 arg5, type6 arg6) { \
+ LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3); \
+ LSS_REG(3, arg4); LSS_REG(4, arg5); LSS_REG(5, arg6); \
+ LSS_BODY(type, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3), \
+ "r"(__r4), "r"(__r5)); \
+ }
+
+ LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack,
+ int flags, void *arg, int *parent_tidptr,
+ void *newtls, int *child_tidptr) {
+ int64_t __res;
+ {
+ register int64_t __res_a0 __asm__("a0");
+ register uint64_t __flags __asm__("a0") = flags;
+ register void *__stack __asm__("a1") = child_stack;
+ register void *__ptid __asm__("a2") = parent_tidptr;
+ register void *__tls __asm__("a3") = newtls;
+ register int *__ctid __asm__("a4") = child_tidptr;
+ __asm__ __volatile__(/* Push "arg" and "fn" onto the stack that will be
+ * used by the child.
+ */
+ "addi %2,%2,-16\n"
+ "sd %1, 0(%2)\n"
+ "sd %4, 8(%2)\n"
+
+ /* %a0 = syscall(%a0 = flags,
+ * %a1 = child_stack,
+ * %a2 = parent_tidptr,
+ * %a3 = newtls,
+ * %a4 = child_tidptr)
+ */
+ "li a7, %8\n"
+ "scall\n"
+
+ /* if (%a0 != 0)
+ * return %a0;
+ */
+ "bnez %0, 1f\n"
+
+ /* In the child, now. Call "fn(arg)".
+ */
+ "ld a1, 0(sp)\n"
+ "ld a0, 8(sp)\n"
+ "jalr a1\n"
+
+ /* Call _exit(%a0).
+ */
+ "li a7, %9\n"
+ "scall\n"
+ "1:\n"
+ : "=r" (__res_a0)
+ : "r"(fn), "r"(__stack), "r"(__flags), "r"(arg),
+ "r"(__ptid), "r"(__tls), "r"(__ctid),
+ "i"(__NR_clone), "i"(__NR_exit)
+ : "cc", "memory");
+ __res = __res_a0;
+ }
+ LSS_RETURN(int, __res);
+ }
#elif defined(__e2k__)
#undef _LSS_BODY
@@ -4484,7 +4603,7 @@
LSS_SC_BODY(4, int, 8, d, type, protocol, sv);
}
#endif
- #if defined(__ARM_EABI__) || defined (__aarch64__)
+ #if defined(__ARM_EABI__) || defined (__aarch64__) || defined(__riscv)
LSS_INLINE _syscall3(ssize_t, recvmsg, int, s, struct kernel_msghdr*, msg,
int, flags)
LSS_INLINE _syscall3(ssize_t, sendmsg, int, s, const struct kernel_msghdr*,
@@ -4812,7 +4931,7 @@
// TODO: define this in an arch-independant way instead of inlining the clone
// syscall body.
-# if defined(__aarch64__)
+# if defined(__aarch64__) || defined(__riscv)
LSS_INLINE pid_t LSS_NAME(fork)(void) {
// No fork syscall on aarch64 - implement by means of the clone syscall.
// Note that this does not reset glibc's cached view of the PID/TID, so