riscv port for review

Submitted by Rich Felker on Sept. 28, 2018, 2:24 a.m.

Details

Message ID 20180928022404.GQ17995@brightrain.aerifal.cx
State New
Series "riscv port for review"
Headers show

Commit Message

Rich Felker Sept. 28, 2018, 2:24 a.m.
Pulled from here:
https://github.com/riscv/riscv-musl/commit/6a4f4a9c774608add4b02f95322518bd2f5f51ee

Attached for review.
From 6a4f4a9c774608add4b02f95322518bd2f5f51ee Mon Sep 17 00:00:00 2001
From: Aric Belsito <lluixhi@gmail.com>
Date: Tue, 5 Jan 2016 16:12:18 -0800
Subject: [PATCH] RISC-V: add riscv32 and riscv64 architecture support

Author: Alex Suykov <alex.suykov@gmail.com>
Author: Aric Belsito <lluixhi@gmail.com>
Author: Michael Clark <mjc@sifive.com>
---
 arch/riscv32/atomic_arch.h             |  35 +++++
 arch/riscv32/bits/alltypes.h.in        |  26 +++
 arch/riscv32/bits/endian.h             |   5 +
 arch/riscv32/bits/fcntl.h              |  38 +++++
 arch/riscv32/bits/fenv.h               |  18 +++
 arch/riscv32/bits/float.h              |  16 ++
 arch/riscv32/bits/ipc.h                |  14 ++
 arch/riscv32/bits/limits.h             |   7 +
 arch/riscv32/bits/msg.h                |  13 ++
 arch/riscv32/bits/posix.h              |   2 +
 arch/riscv32/bits/reg.h                |   8 +
 arch/riscv32/bits/sem.h                |   9 ++
 arch/riscv32/bits/setjmp.h             |   1 +
 arch/riscv32/bits/shm.h                |  26 +++
 arch/riscv32/bits/signal.h             | 113 ++++++++++++++
 arch/riscv32/bits/socket.h             |  33 ++++
 arch/riscv32/bits/stat.h               |  18 +++
 arch/riscv32/bits/stdint.h             |  20 +++
 arch/riscv32/bits/syscall.h.in         | 278 +++++++++++++++++++++++++++++++++
 arch/riscv32/bits/user.h               |  43 +++++
 arch/riscv32/crt_arch.h                |  18 +++
 arch/riscv32/pthread_arch.h            |  12 ++
 arch/riscv32/reloc.h                   |  27 ++++
 arch/riscv32/syscall_arch.h            |  78 +++++++++
 arch/riscv64/atomic_arch.h             |  66 ++++++++
 arch/riscv64/bits/alltypes.h.in        |  29 ++++
 arch/riscv64/bits/endian.h             |   5 +
 arch/riscv64/bits/fcntl.h              |  38 +++++
 arch/riscv64/bits/fenv.h               |  17 ++
 arch/riscv64/bits/float.h              |  16 ++
 arch/riscv64/bits/ipc.h                |  14 ++
 arch/riscv64/bits/limits.h             |   7 +
 arch/riscv64/bits/mman.h               |   1 +
 arch/riscv64/bits/msg.h                |  13 ++
 arch/riscv64/bits/posix.h              |   2 +
 arch/riscv64/bits/reg.h                |   8 +
 arch/riscv64/bits/sem.h                |   9 ++
 arch/riscv64/bits/setjmp.h             |   1 +
 arch/riscv64/bits/shm.h                |  26 +++
 arch/riscv64/bits/signal.h             | 113 ++++++++++++++
 arch/riscv64/bits/socket.h             |  33 ++++
 arch/riscv64/bits/stat.h               |  18 +++
 arch/riscv64/bits/stdint.h             |  20 +++
 arch/riscv64/bits/syscall.h.in         | 278 +++++++++++++++++++++++++++++++++
 arch/riscv64/bits/user.h               |  43 +++++
 arch/riscv64/crt_arch.h                |  18 +++
 arch/riscv64/pthread_arch.h            |  12 ++
 arch/riscv64/reloc.h                   |  27 ++++
 arch/riscv64/syscall_arch.h            |  76 +++++++++
 configure                              |   7 +
 crt/riscv32/crti.s                     |  11 ++
 crt/riscv32/crtn.s                     |   0
 crt/riscv64/crti.s                     |  11 ++
 crt/riscv64/crtn.s                     |   0
 include/elf.h                          |  56 +++++++
 src/fenv/riscv32/fenv-sf.c             |   3 +
 src/fenv/riscv32/fenv.S                |  53 +++++++
 src/fenv/riscv64/fenv-sf.c             |   3 +
 src/fenv/riscv64/fenv.S                |  53 +++++++
 src/internal/riscv32/syscall.s         |  15 ++
 src/internal/riscv64/syscall.s         |  15 ++
 src/ldso/riscv32/dlsym.s               |   6 +
 src/ldso/riscv64/dlsym.s               |   6 +
 src/math/riscv32/copysign.s            |   5 +
 src/math/riscv32/copysignf.s           |   5 +
 src/math/riscv32/fabs.s                |   5 +
 src/math/riscv32/fabsf.s               |   5 +
 src/math/riscv32/fma.s                 |   5 +
 src/math/riscv32/fmaf.s                |   5 +
 src/math/riscv32/fmax.s                |   5 +
 src/math/riscv32/fmaxf.s               |   5 +
 src/math/riscv32/fmin.s                |   5 +
 src/math/riscv32/fminf.s               |   5 +
 src/math/riscv32/sqrt.s                |   5 +
 src/math/riscv32/sqrtf.s               |   5 +
 src/math/riscv64/copysign.s            |   5 +
 src/math/riscv64/copysignf.s           |   5 +
 src/math/riscv64/fabs.s                |   5 +
 src/math/riscv64/fabsf.s               |   5 +
 src/math/riscv64/fma.s                 |   5 +
 src/math/riscv64/fmaf.s                |   5 +
 src/math/riscv64/fmax.s                |   5 +
 src/math/riscv64/fmaxf.s               |   5 +
 src/math/riscv64/fmin.s                |   5 +
 src/math/riscv64/fminf.s               |   5 +
 src/math/riscv64/sqrt.s                |   5 +
 src/math/riscv64/sqrtf.s               |   5 +
 src/setjmp/riscv32/longjmp.S           |  44 ++++++
 src/setjmp/riscv32/setjmp.S            |  42 +++++
 src/setjmp/riscv64/longjmp.S           |  44 ++++++
 src/setjmp/riscv64/setjmp.S            |  42 +++++
 src/signal/riscv32/restore.s           |   8 +
 src/signal/riscv32/sigsetjmp.s         |  21 +++
 src/signal/riscv64/restore.s           |   8 +
 src/signal/riscv64/sigsetjmp.s         |  21 +++
 src/thread/riscv32/__set_thread_area.s |   6 +
 src/thread/riscv32/__unmapself.s       |   7 +
 src/thread/riscv32/clone.s             |  34 ++++
 src/thread/riscv32/syscall_cp.s        |  29 ++++
 src/thread/riscv64/__set_thread_area.s |   6 +
 src/thread/riscv64/__unmapself.s       |   7 +
 src/thread/riscv64/clone.s             |  34 ++++
 src/thread/riscv64/syscall_cp.s        |  29 ++++
 103 files changed, 2489 insertions(+)
 create mode 100644 arch/riscv32/atomic_arch.h
 create mode 100644 arch/riscv32/bits/alltypes.h.in
 create mode 100644 arch/riscv32/bits/endian.h
 create mode 100644 arch/riscv32/bits/fcntl.h
 create mode 100644 arch/riscv32/bits/fenv.h
 create mode 100644 arch/riscv32/bits/float.h
 create mode 100644 arch/riscv32/bits/ipc.h
 create mode 100644 arch/riscv32/bits/limits.h
 create mode 100644 arch/riscv32/bits/msg.h
 create mode 100644 arch/riscv32/bits/posix.h
 create mode 100644 arch/riscv32/bits/reg.h
 create mode 100644 arch/riscv32/bits/sem.h
 create mode 100644 arch/riscv32/bits/setjmp.h
 create mode 100644 arch/riscv32/bits/shm.h
 create mode 100644 arch/riscv32/bits/signal.h
 create mode 100644 arch/riscv32/bits/socket.h
 create mode 100644 arch/riscv32/bits/stat.h
 create mode 100644 arch/riscv32/bits/stdint.h
 create mode 100644 arch/riscv32/bits/syscall.h.in
 create mode 100644 arch/riscv32/bits/user.h
 create mode 100644 arch/riscv32/crt_arch.h
 create mode 100644 arch/riscv32/pthread_arch.h
 create mode 100644 arch/riscv32/reloc.h
 create mode 100644 arch/riscv32/syscall_arch.h
 create mode 100644 arch/riscv64/atomic_arch.h
 create mode 100644 arch/riscv64/bits/alltypes.h.in
 create mode 100644 arch/riscv64/bits/endian.h
 create mode 100644 arch/riscv64/bits/fcntl.h
 create mode 100644 arch/riscv64/bits/fenv.h
 create mode 100644 arch/riscv64/bits/float.h
 create mode 100644 arch/riscv64/bits/ipc.h
 create mode 100644 arch/riscv64/bits/limits.h
 create mode 100644 arch/riscv64/bits/mman.h
 create mode 100644 arch/riscv64/bits/msg.h
 create mode 100644 arch/riscv64/bits/posix.h
 create mode 100644 arch/riscv64/bits/reg.h
 create mode 100644 arch/riscv64/bits/sem.h
 create mode 100644 arch/riscv64/bits/setjmp.h
 create mode 100644 arch/riscv64/bits/shm.h
 create mode 100644 arch/riscv64/bits/signal.h
 create mode 100644 arch/riscv64/bits/socket.h
 create mode 100644 arch/riscv64/bits/stat.h
 create mode 100644 arch/riscv64/bits/stdint.h
 create mode 100644 arch/riscv64/bits/syscall.h.in
 create mode 100644 arch/riscv64/bits/user.h
 create mode 100644 arch/riscv64/crt_arch.h
 create mode 100644 arch/riscv64/pthread_arch.h
 create mode 100644 arch/riscv64/reloc.h
 create mode 100644 arch/riscv64/syscall_arch.h
 create mode 100644 crt/riscv32/crti.s
 create mode 100644 crt/riscv32/crtn.s
 create mode 100644 crt/riscv64/crti.s
 create mode 100644 crt/riscv64/crtn.s
 create mode 100644 src/fenv/riscv32/fenv-sf.c
 create mode 100644 src/fenv/riscv32/fenv.S
 create mode 100644 src/fenv/riscv64/fenv-sf.c
 create mode 100644 src/fenv/riscv64/fenv.S
 create mode 100644 src/internal/riscv32/syscall.s
 create mode 100644 src/internal/riscv64/syscall.s
 create mode 100644 src/ldso/riscv32/dlsym.s
 create mode 100644 src/ldso/riscv64/dlsym.s
 create mode 100644 src/math/riscv32/copysign.s
 create mode 100644 src/math/riscv32/copysignf.s
 create mode 100644 src/math/riscv32/fabs.s
 create mode 100644 src/math/riscv32/fabsf.s
 create mode 100644 src/math/riscv32/fma.s
 create mode 100644 src/math/riscv32/fmaf.s
 create mode 100644 src/math/riscv32/fmax.s
 create mode 100644 src/math/riscv32/fmaxf.s
 create mode 100644 src/math/riscv32/fmin.s
 create mode 100644 src/math/riscv32/fminf.s
 create mode 100644 src/math/riscv32/sqrt.s
 create mode 100644 src/math/riscv32/sqrtf.s
 create mode 100644 src/math/riscv64/copysign.s
 create mode 100644 src/math/riscv64/copysignf.s
 create mode 100644 src/math/riscv64/fabs.s
 create mode 100644 src/math/riscv64/fabsf.s
 create mode 100644 src/math/riscv64/fma.s
 create mode 100644 src/math/riscv64/fmaf.s
 create mode 100644 src/math/riscv64/fmax.s
 create mode 100644 src/math/riscv64/fmaxf.s
 create mode 100644 src/math/riscv64/fmin.s
 create mode 100644 src/math/riscv64/fminf.s
 create mode 100644 src/math/riscv64/sqrt.s
 create mode 100644 src/math/riscv64/sqrtf.s
 create mode 100644 src/setjmp/riscv32/longjmp.S
 create mode 100644 src/setjmp/riscv32/setjmp.S
 create mode 100644 src/setjmp/riscv64/longjmp.S
 create mode 100644 src/setjmp/riscv64/setjmp.S
 create mode 100644 src/signal/riscv32/restore.s
 create mode 100644 src/signal/riscv32/sigsetjmp.s
 create mode 100644 src/signal/riscv64/restore.s
 create mode 100644 src/signal/riscv64/sigsetjmp.s
 create mode 100644 src/thread/riscv32/__set_thread_area.s
 create mode 100644 src/thread/riscv32/__unmapself.s
 create mode 100644 src/thread/riscv32/clone.s
 create mode 100644 src/thread/riscv32/syscall_cp.s
 create mode 100644 src/thread/riscv64/__set_thread_area.s
 create mode 100644 src/thread/riscv64/__unmapself.s
 create mode 100644 src/thread/riscv64/clone.s
 create mode 100644 src/thread/riscv64/syscall_cp.s

Patch hide | download patch | download mbox

diff --git a/arch/riscv32/atomic_arch.h b/arch/riscv32/atomic_arch.h
new file mode 100644
index 0000000..93c89cc
--- /dev/null
+++ b/arch/riscv32/atomic_arch.h
@@ -0,0 +1,35 @@ 
+#define a_barrier a_barrier
+static inline void a_barrier()
+{
+	__asm__ __volatile__ ("fence rw,rw" : : : "memory");
+}
+
+#define a_ll a_ll
+static inline int a_ll(volatile int *p)
+{
+	int v;
+	__asm__ __volatile__ ("lr.w %0, (%1)" : "=&r"(v) : "r"(p));
+	return v;
+}
+
+#define a_sc a_sc
+static inline int a_sc(volatile int *p, int v)
+{
+	int r;
+	__asm__ __volatile__ ("sc.w %0, %2, (%1)" : "=&r"(r) : "r"(p), "r"(v) : "memory");
+	return !r;
+}
+
+#define a_cas a_cas
+static inline int a_cas(volatile int *p, int t, int s)
+{
+	int old, tmp;
+	__asm__("1:  lr.w    %0, %2      \n"
+		"    bne     %0, %3, 1f  \n"
+		"    sc.w    %1, %4, %2  \n"
+		"    bnez    %1, 1b      \n"
+		"1:                      \n"
+		: "=&r"(old), "+r"(tmp), "+A"(*p)
+		: "r"(t), "r"(s));
+	return old;
+}
diff --git a/arch/riscv32/bits/alltypes.h.in b/arch/riscv32/bits/alltypes.h.in
new file mode 100644
index 0000000..66ca18a
--- /dev/null
+++ b/arch/riscv32/bits/alltypes.h.in
@@ -0,0 +1,26 @@ 
+#define _Addr int
+#define _Int64 long long
+#define _Reg int
+
+TYPEDEF __builtin_va_list va_list;
+TYPEDEF __builtin_va_list __isoc_va_list;
+
+#ifndef __cplusplus
+TYPEDEF int wchar_t;
+#endif
+
+TYPEDEF float float_t;
+TYPEDEF double double_t;
+
+TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
+
+TYPEDEF long time_t;
+TYPEDEF long suseconds_t;
+
+TYPEDEF struct { union { int __i[9]; volatile int __vi[9]; unsigned __s[9]; } __u; } pthread_attr_t;
+TYPEDEF struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t;
+TYPEDEF struct { union { int __i[6]; volatile int __vi[6]; volatile void *volatile __p[6]; } __u; } mtx_t;
+TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } pthread_cond_t;
+TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[12]; } __u; } cnd_t;
+TYPEDEF struct { union { int __i[8]; volatile int __vi[8]; void *__p[8]; } __u; } pthread_rwlock_t;
+TYPEDEF struct { union { int __i[5]; volatile int __vi[5]; void *__p[5]; } __u; } pthread_barrier_t;
diff --git a/arch/riscv32/bits/endian.h b/arch/riscv32/bits/endian.h
new file mode 100644
index 0000000..7df0e02
--- /dev/null
+++ b/arch/riscv32/bits/endian.h
@@ -0,0 +1,5 @@ 
+#if __RISCVEB__
+#define __BYTE_ORDER __BIG_ENDIAN
+#else
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#endif
diff --git a/arch/riscv32/bits/fcntl.h b/arch/riscv32/bits/fcntl.h
new file mode 100644
index 0000000..9278797
--- /dev/null
+++ b/arch/riscv32/bits/fcntl.h
@@ -0,0 +1,38 @@ 
+#define O_CREAT        0100
+#define O_EXCL         0200
+#define O_NOCTTY       0400
+#define O_TRUNC       01000
+#define O_APPEND      02000
+#define O_NONBLOCK    04000
+#define O_DSYNC      010000
+#define O_SYNC     04010000
+#define O_RSYNC    04010000
+#define O_DIRECTORY  040000
+#define O_NOFOLLOW  0100000
+#define O_CLOEXEC  02000000
+
+#define O_ASYNC      020000
+#define O_DIRECT    0200000
+#define O_LARGEFILE 0400000
+#define O_NOATIME  01000000
+#define O_PATH    010000000
+#define O_TMPFILE 020040000
+#define O_NDELAY O_NONBLOCK
+
+#define F_DUPFD  0
+#define F_GETFD  1
+#define F_SETFD  2
+#define F_GETFL  3
+#define F_SETFL  4
+#define F_GETLK  5
+#define F_SETLK  6
+#define F_SETLKW 7
+#define F_SETOWN 8
+#define F_GETOWN 9
+#define F_SETSIG 10
+#define F_GETSIG 11
+
+#define F_SETOWN_EX 15
+#define F_GETOWN_EX 16
+
+#define F_GETOWNER_UIDS 17
diff --git a/arch/riscv32/bits/fenv.h b/arch/riscv32/bits/fenv.h
new file mode 100644
index 0000000..6ac43e4
--- /dev/null
+++ b/arch/riscv32/bits/fenv.h
@@ -0,0 +1,18 @@ 
+#define FE_INVALID      16
+#define FE_DIVBYZERO    8
+#define FE_OVERFLOW     4
+#define FE_UNDERFLOW    2
+#define FE_INEXACT      1
+
+#define FE_ALL_EXCEPT   31
+
+#define FE_TONEAREST    0
+#define FE_DOWNWARD     2
+#define FE_UPWARD       3
+#define FE_TOWARDZERO   1
+
+typedef unsigned int fexcept_t;
+
+typedef unsigned int fenv_t;
+
+#define FE_DFL_ENV      ((const fenv_t *) -1)
diff --git a/arch/riscv32/bits/float.h b/arch/riscv32/bits/float.h
new file mode 100644
index 0000000..719c790
--- /dev/null
+++ b/arch/riscv32/bits/float.h
@@ -0,0 +1,16 @@ 
+#define FLT_EVAL_METHOD 0
+
+#define LDBL_TRUE_MIN 6.47517511943802511092443895822764655e-4966L
+#define LDBL_MIN 3.36210314311209350626267781732175260e-4932L
+#define LDBL_MAX 1.18973149535723176508575932662800702e+4932L
+#define LDBL_EPSILON 1.92592994438723585305597794258492732e-34L
+
+#define LDBL_MANT_DIG 113
+#define LDBL_MIN_EXP (-16381)
+#define LDBL_MAX_EXP 16384
+
+#define LDBL_DIG 33
+#define LDBL_MIN_10_EXP (-4931)
+#define LDBL_MAX_10_EXP 4932
+
+#define DECIMAL_DIG 36
diff --git a/arch/riscv32/bits/ipc.h b/arch/riscv32/bits/ipc.h
new file mode 100644
index 0000000..6f3328a
--- /dev/null
+++ b/arch/riscv32/bits/ipc.h
@@ -0,0 +1,14 @@ 
+struct ipc_perm {
+	key_t __ipc_perm_key;
+	uid_t uid;
+	gid_t gid;
+	uid_t cuid;
+	gid_t cgid;
+	mode_t mode;
+	unsigned short __ipc_perm_seq;
+
+	unsigned long __pad1;
+	unsigned long __pad2;
+};
+
+#define IPC_64 0
diff --git a/arch/riscv32/bits/limits.h b/arch/riscv32/bits/limits.h
new file mode 100644
index 0000000..fbc6d23
--- /dev/null
+++ b/arch/riscv32/bits/limits.h
@@ -0,0 +1,7 @@ 
+#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+#define LONG_BIT 32
+#endif
+
+#define LONG_MAX  0x7fffffffL
+#define LLONG_MAX  0x7fffffffffffffffLL
diff --git a/arch/riscv32/bits/msg.h b/arch/riscv32/bits/msg.h
new file mode 100644
index 0000000..641e170
--- /dev/null
+++ b/arch/riscv32/bits/msg.h
@@ -0,0 +1,13 @@ 
+struct msqid_ds {
+	struct ipc_perm msg_perm;
+	time_t msg_stime;
+	time_t msg_rtime;
+	time_t msg_ctime;
+	unsigned long msg_cbytes;
+	msgqnum_t msg_qnum;
+	msglen_t msg_qbytes;
+	pid_t msg_lspid;
+	pid_t msg_lrpid;
+	unsigned long __pad1;
+	unsigned long __pad2;
+};
diff --git a/arch/riscv32/bits/posix.h b/arch/riscv32/bits/posix.h
new file mode 100644
index 0000000..7563df5
--- /dev/null
+++ b/arch/riscv32/bits/posix.h
@@ -0,0 +1,2 @@ 
+# define _POSIX_V6_ILP32_OFFBIG 1
+# define _POSIX_V7_ILP32_OFFBIG 1
diff --git a/arch/riscv32/bits/reg.h b/arch/riscv32/bits/reg.h
new file mode 100644
index 0000000..e0bf40d
--- /dev/null
+++ b/arch/riscv32/bits/reg.h
@@ -0,0 +1,8 @@ 
+#undef __WORDSIZE
+#define __WORDSIZE 32
+#define REG_PC 0
+#define REG_RA 1
+#define REG_SP 2
+#define REG_TP 4
+#define REG_S0 8
+#define REG_A0 10
diff --git a/arch/riscv32/bits/sem.h b/arch/riscv32/bits/sem.h
new file mode 100644
index 0000000..5f93c12
--- /dev/null
+++ b/arch/riscv32/bits/sem.h
@@ -0,0 +1,9 @@ 
+struct semid_ds {
+	struct ipc_perm sem_perm;
+	time_t sem_otime;
+	time_t sem_ctime;
+	unsigned short sem_nsems;
+	char __sem_nsems_pad[sizeof(time_t)-sizeof(short)];
+	time_t __unused3;
+	time_t __unused4;
+};
diff --git a/arch/riscv32/bits/setjmp.h b/arch/riscv32/bits/setjmp.h
new file mode 100644
index 0000000..ef6a017
--- /dev/null
+++ b/arch/riscv32/bits/setjmp.h
@@ -0,0 +1 @@ 
+typedef unsigned long __jmp_buf[40];
diff --git a/arch/riscv32/bits/shm.h b/arch/riscv32/bits/shm.h
new file mode 100644
index 0000000..f4b8712
--- /dev/null
+++ b/arch/riscv32/bits/shm.h
@@ -0,0 +1,26 @@ 
+#define SHMLBA 4096
+
+struct shmid_ds
+{
+	struct ipc_perm shm_perm;
+	size_t shm_segsz;
+	time_t shm_atime;
+	time_t shm_dtime;
+	time_t shm_ctime;
+	pid_t shm_cpid;
+	pid_t shm_lpid;
+	unsigned long shm_nattch;
+	unsigned long __pad1;
+	unsigned long __pad2;
+};
+
+struct shminfo {
+	unsigned long shmmax, shmmin, shmmni, shmseg, shmall, __unused[4];
+};
+
+struct shm_info {
+	int __used_ids;
+	unsigned long shm_tot, shm_rss, shm_swp;
+	unsigned long __swap_attempts, __swap_successes;
+};
+
diff --git a/arch/riscv32/bits/signal.h b/arch/riscv32/bits/signal.h
new file mode 100644
index 0000000..8b992cc
--- /dev/null
+++ b/arch/riscv32/bits/signal.h
@@ -0,0 +1,113 @@ 
+#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+
+#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+# define MINSIGSTKSZ 2048
+# define SIGSTKSZ 8192
+#endif
+
+/* gregs[0] holds the program counter. */
+
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+typedef unsigned long greg_t;
+typedef unsigned long gregset_t[32];
+
+struct __riscv_f_ext_state {
+	unsigned int f[32];
+	unsigned int fcsr;
+};
+
+struct __riscv_d_ext_state {
+	unsigned long long f[32];
+	unsigned int fcsr;
+};
+
+struct __riscv_q_ext_state {
+	unsigned long long f[64] __attribute__((aligned(16)));
+	unsigned int fcsr;
+	unsigned int reserved[3];
+};
+
+union __riscv_fp_state {
+	struct __riscv_f_ext_state f;
+	struct __riscv_d_ext_state d;
+	struct __riscv_q_ext_state q;
+};
+
+typedef union __riscv_fp_state fpregset_t;
+
+typedef struct sigcontext {
+	gregset_t gregs;
+	fpregset_t fpregs;
+} mcontext_t;
+
+#else
+typedef struct {
+	unsigned long gregs[32];
+	unsigned long long fpregs[66];
+} mcontext_t;
+#endif
+
+struct sigaltstack {
+	void *ss_sp;
+	int ss_flags;
+	size_t ss_size;
+};
+
+typedef struct __ucontext
+{
+	unsigned long uc_flags;
+	struct __ucontext *uc_link;
+	stack_t uc_stack;
+	sigset_t uc_sigmask;
+	char __unused[1024 / 8 - sizeof(sigset_t)];
+	mcontext_t uc_mcontext;
+} ucontext_t;
+
+#define SA_NOCLDSTOP 1
+#define SA_NOCLDWAIT 2
+#define SA_SIGINFO   4
+#define SA_ONSTACK   0x08000000
+#define SA_RESTART   0x10000000
+#define SA_NODEFER   0x40000000
+#define SA_RESETHAND 0x80000000
+#define SA_RESTORER  0x04000000
+
+#endif
+
+#define SIGHUP     1
+#define SIGINT     2
+#define SIGQUIT    3
+#define SIGILL     4
+#define SIGTRAP    5
+#define SIGABRT    6
+#define SIGIOT     SIGABRT
+#define SIGBUS     7
+#define SIGFPE     8
+#define SIGKILL    9
+#define SIGUSR1   10
+#define SIGSEGV   11
+#define SIGUSR2   12
+#define SIGPIPE   13
+#define SIGALRM   14
+#define SIGTERM   15
+#define SIGSTKFLT 16
+#define SIGCHLD   17
+#define SIGCONT   18
+#define SIGSTOP   19
+#define SIGTSTP   20
+#define SIGTTIN   21
+#define SIGTTOU   22
+#define SIGURG    23
+#define SIGXCPU   24
+#define SIGXFSZ   25
+#define SIGVTALRM 26
+#define SIGPROF   27
+#define SIGWINCH  28
+#define SIGIO     29
+#define SIGPOLL   SIGIO
+#define SIGPWR    30
+#define SIGSYS    31
+#define SIGUNUSED SIGSYS
+
+#define _NSIG     65
diff --git a/arch/riscv32/bits/socket.h b/arch/riscv32/bits/socket.h
new file mode 100644
index 0000000..c11677e
--- /dev/null
+++ b/arch/riscv32/bits/socket.h
@@ -0,0 +1,33 @@ 
+#include <endian.h>
+
+struct msghdr {
+	void *msg_name;
+	socklen_t msg_namelen;
+	struct iovec *msg_iov;
+#if __BYTE_ORDER == __BIG_ENDIAN
+	int __pad1, msg_iovlen;
+#else
+	int msg_iovlen, __pad1;
+#endif
+	void *msg_control;
+#if __BYTE_ORDER == __BIG_ENDIAN
+	int __pad2;
+	socklen_t msg_controllen;
+#else
+	socklen_t msg_controllen;
+	int __pad2;
+#endif
+	int msg_flags;
+};
+
+struct cmsghdr {
+#if __BYTE_ORDER == __BIG_ENDIAN
+	int __pad1;
+	socklen_t cmsg_len;
+#else
+	socklen_t cmsg_len;
+	int __pad1;
+#endif
+	int cmsg_level;
+	int cmsg_type;
+};
diff --git a/arch/riscv32/bits/stat.h b/arch/riscv32/bits/stat.h
new file mode 100644
index 0000000..b7f4221
--- /dev/null
+++ b/arch/riscv32/bits/stat.h
@@ -0,0 +1,18 @@ 
+struct stat {
+	dev_t st_dev;
+	ino_t st_ino;
+	mode_t st_mode;
+	nlink_t st_nlink;
+	uid_t st_uid;
+	gid_t st_gid;
+	dev_t st_rdev;
+	unsigned long __pad;
+	off_t st_size;
+	blksize_t st_blksize;
+	int __pad2;
+	blkcnt_t st_blocks;
+	struct timespec st_atim;
+	struct timespec st_mtim;
+	struct timespec st_ctim;
+	unsigned __unused[2];
+};
diff --git a/arch/riscv32/bits/stdint.h b/arch/riscv32/bits/stdint.h
new file mode 100644
index 0000000..d1b2712
--- /dev/null
+++ b/arch/riscv32/bits/stdint.h
@@ -0,0 +1,20 @@ 
+typedef int32_t int_fast16_t;
+typedef int32_t int_fast32_t;
+typedef uint32_t uint_fast16_t;
+typedef uint32_t uint_fast32_t;
+
+#define INT_FAST16_MIN  INT32_MIN
+#define INT_FAST32_MIN  INT32_MIN
+
+#define INT_FAST16_MAX  INT32_MAX
+#define INT_FAST32_MAX  INT32_MAX
+
+#define UINT_FAST16_MAX UINT32_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+
+#define INTPTR_MIN      INT32_MIN
+#define INTPTR_MAX      INT32_MAX
+#define UINTPTR_MAX     UINT32_MAX
+#define PTRDIFF_MIN     INT32_MIN
+#define PTRDIFF_MAX     INT32_MAX
+#define SIZE_MAX        UINT32_MAX
diff --git a/arch/riscv32/bits/syscall.h.in b/arch/riscv32/bits/syscall.h.in
new file mode 100644
index 0000000..3c81c10
--- /dev/null
+++ b/arch/riscv32/bits/syscall.h.in
@@ -0,0 +1,278 @@ 
+#define __NR_io_setup 0
+#define __NR_io_destroy 1
+#define __NR_io_submit 2
+#define __NR_io_cancel 3
+#define __NR_io_getevents 4
+#define __NR_setxattr 5
+#define __NR_lsetxattr 6
+#define __NR_fsetxattr 7
+#define __NR_getxattr 8
+#define __NR_lgetxattr 9
+#define __NR_fgetxattr 10
+#define __NR_listxattr 11
+#define __NR_llistxattr 12
+#define __NR_flistxattr 13
+#define __NR_removexattr 14
+#define __NR_lremovexattr 15
+#define __NR_fremovexattr 16
+#define __NR_getcwd 17
+#define __NR_lookup_dcookie 18
+#define __NR_eventfd2 19
+#define __NR_epoll_create1 20
+#define __NR_epoll_ctl 21
+#define __NR_epoll_pwait 22
+#define __NR_dup 23
+#define __NR_dup3 24
+#define __NR_fcntl 25
+#define __NR_inotify_init1 26
+#define __NR_inotify_add_watch 27
+#define __NR_inotify_rm_watch 28
+#define __NR_ioctl 29
+#define __NR_ioprio_set 30
+#define __NR_ioprio_get 31
+#define __NR_flock 32
+#define __NR_mknodat 33
+#define __NR_mkdirat 34
+#define __NR_unlinkat 35
+#define __NR_symlinkat 36
+#define __NR_linkat 37
+#define __NR_renameat 38
+#define __NR_umount2 39
+#define __NR_mount 40
+#define __NR_pivot_root 41
+#define __NR_nfsservctl 42
+#define __NR_statfs 43
+#define __NR_fstatfs 44
+#define __NR_truncate 45
+#define __NR_ftruncate 46
+#define __NR_fallocate 47
+#define __NR_faccessat 48
+#define __NR_chdir 49
+#define __NR_fchdir 50
+#define __NR_chroot 51
+#define __NR_fchmod 52
+#define __NR_fchmodat 53
+#define __NR_fchownat 54
+#define __NR_fchown 55
+#define __NR_openat 56
+#define __NR_close 57
+#define __NR_vhangup 58
+#define __NR_pipe2 59
+#define __NR_quotactl 60
+#define __NR_getdents64 61
+#define __NR_lseek 62
+#define __NR_read 63
+#define __NR_write 64
+#define __NR_readv 65
+#define __NR_writev 66
+#define __NR_pread64 67
+#define __NR_pwrite64 68
+#define __NR_preadv 69
+#define __NR_pwritev 70
+#define __NR_sendfile 71
+#define __NR_pselect6 72
+#define __NR_ppoll 73
+#define __NR_signalfd4 74
+#define __NR_vmsplice 75
+#define __NR_splice 76
+#define __NR_tee 77
+#define __NR_readlinkat 78
+#define __NR_fstatat 79
+#define __NR_fstat 80
+#define __NR_sync 81
+#define __NR_fsync 82
+#define __NR_fdatasync 83
+#define __NR_sync_file_range 84
+#define __NR_timerfd_create 85
+#define __NR_timerfd_settime 86
+#define __NR_timerfd_gettime 87
+#define __NR_utimensat 88
+#define __NR_acct 89
+#define __NR_capget 90
+#define __NR_capset 91
+#define __NR_personality 92
+#define __NR_exit 93
+#define __NR_exit_group 94
+#define __NR_waitid 95
+#define __NR_set_tid_address 96
+#define __NR_unshare 97
+#define __NR_futex 98
+#define __NR_set_robust_list 99
+#define __NR_get_robust_list 100
+#define __NR_nanosleep 101
+#define __NR_getitimer 102
+#define __NR_setitimer 103
+#define __NR_kexec_load 104
+#define __NR_init_module 105
+#define __NR_delete_module 106
+#define __NR_timer_create 107
+#define __NR_timer_gettime 108
+#define __NR_timer_getoverrun 109
+#define __NR_timer_settime 110
+#define __NR_timer_delete 111
+#define __NR_clock_settime 112
+#define __NR_clock_gettime 113
+#define __NR_clock_getres 114
+#define __NR_clock_nanosleep 115
+#define __NR_syslog 116
+#define __NR_ptrace 117
+#define __NR_sched_setparam 118
+#define __NR_sched_setscheduler 119
+#define __NR_sched_getscheduler 120
+#define __NR_sched_getparam 121
+#define __NR_sched_setaffinity 122
+#define __NR_sched_getaffinity 123
+#define __NR_sched_yield 124
+#define __NR_sched_get_priority_max 125
+#define __NR_sched_get_priority_min 126
+#define __NR_sched_rr_get_interval 127
+#define __NR_restart_syscall 128
+#define __NR_kill 129
+#define __NR_tkill 130
+#define __NR_tgkill 131
+#define __NR_sigaltstack 132
+#define __NR_rt_sigsuspend 133
+#define __NR_rt_sigaction 134
+#define __NR_rt_sigprocmask 135
+#define __NR_rt_sigpending 136
+#define __NR_rt_sigtimedwait 137
+#define __NR_rt_sigqueueinfo 138
+#define __NR_rt_sigreturn 139
+#define __NR_setpriority 140
+#define __NR_getpriority 141
+#define __NR_reboot 142
+#define __NR_setregid 143
+#define __NR_setgid 144
+#define __NR_setreuid 145
+#define __NR_setuid 146
+#define __NR_setresuid 147
+#define __NR_getresuid 148
+#define __NR_setresgid 149
+#define __NR_getresgid 150
+#define __NR_setfsuid 151
+#define __NR_setfsgid 152
+#define __NR_times 153
+#define __NR_setpgid 154
+#define __NR_getpgid 155
+#define __NR_getsid 156
+#define __NR_setsid 157
+#define __NR_getgroups 158
+#define __NR_setgroups 159
+#define __NR_uname 160
+#define __NR_sethostname 161
+#define __NR_setdomainname 162
+#define __NR_getrlimit 163
+#define __NR_setrlimit 164
+#define __NR_getrusage 165
+#define __NR_umask 166
+#define __NR_prctl 167
+#define __NR_getcpu 168
+#define __NR_gettimeofday 169
+#define __NR_settimeofday 170
+#define __NR_adjtimex 171
+#define __NR_getpid 172
+#define __NR_getppid 173
+#define __NR_getuid 174
+#define __NR_geteuid 175
+#define __NR_getgid 176
+#define __NR_getegid 177
+#define __NR_gettid 178
+#define __NR_sysinfo 179
+#define __NR_mq_open 180
+#define __NR_mq_unlink 181
+#define __NR_mq_timedsend 182
+#define __NR_mq_timedreceive 183
+#define __NR_mq_notify 184
+#define __NR_mq_getsetattr 185
+#define __NR_msgget 186
+#define __NR_msgctl 187
+#define __NR_msgrcv 188
+#define __NR_msgsnd 189
+#define __NR_semget 190
+#define __NR_semctl 191
+#define __NR_semtimedop 192
+#define __NR_semop 193
+#define __NR_shmget 194
+#define __NR_shmctl 195
+#define __NR_shmat 196
+#define __NR_shmdt 197
+#define __NR_socket 198
+#define __NR_socketpair 199
+#define __NR_bind 200
+#define __NR_listen 201
+#define __NR_accept 202
+#define __NR_connect 203
+#define __NR_getsockname 204
+#define __NR_getpeername 205
+#define __NR_sendto 206
+#define __NR_recvfrom 207
+#define __NR_setsockopt 208
+#define __NR_getsockopt 209
+#define __NR_shutdown 210
+#define __NR_sendmsg 211
+#define __NR_recvmsg 212
+#define __NR_readahead 213
+#define __NR_brk 214
+#define __NR_munmap 215
+#define __NR_mremap 216
+#define __NR_add_key 217
+#define __NR_request_key 218
+#define __NR_keyctl 219
+#define __NR_clone 220
+#define __NR_execve 221
+#define __NR_mmap 222
+#define __NR_fadvise64 223
+#define __NR_swapon 224
+#define __NR_swapoff 225
+#define __NR_mprotect 226
+#define __NR_msync 227
+#define __NR_mlock 228
+#define __NR_munlock 229
+#define __NR_mlockall 230
+#define __NR_munlockall 231
+#define __NR_mincore 232
+#define __NR_madvise 233
+#define __NR_remap_file_pages 234
+#define __NR_mbind 235
+#define __NR_get_mempolicy 236
+#define __NR_set_mempolicy 237
+#define __NR_migrate_pages 238
+#define __NR_move_pages 239
+#define __NR_rt_tgsigqueueinfo 240
+#define __NR_perf_event_open 241
+#define __NR_accept4 242
+#define __NR_recvmmsg 243
+#define __NR_arch_specific_syscall 244
+#define __NR_wait4 260
+#define __NR_prlimit64 261
+#define __NR_fanotify_init 262
+#define __NR_fanotify_mark 263
+#define __NR_name_to_handle_at 264
+#define __NR_open_by_handle_at 265
+#define __NR_clock_adjtime 266
+#define __NR_syncfs 267
+#define __NR_setns 268
+#define __NR_sendmmsg 269
+#define __NR_process_vm_readv 270
+#define __NR_process_vm_writev 271
+#define __NR_kcmp 272
+#define __NR_finit_module 273
+#define __NR_sched_setattr 274
+#define __NR_sched_getattr 275
+#define __NR_renameat2 276
+#define __NR_seccomp 277
+#define __NR_getrandom 278
+#define __NR_memfd_create 279
+#define __NR_bpf 280
+#define __NR_execveat 281
+#define __NR_userfaultfd 282
+#define __NR_membarrier 283
+#define __NR_mlock2 284
+#define __NR_copy_file_range 285
+#define __NR_preadv2 286
+#define __NR_pwritev2 287
+#define __NR_pkey_mprotect 288
+#define __NR_pkey_alloc 289
+#define __NR_pkey_free 290
+#define __NR_sysriscv __NR_arch_specific_syscall
+
diff --git a/arch/riscv32/bits/user.h b/arch/riscv32/bits/user.h
new file mode 100644
index 0000000..bd0f0fc
--- /dev/null
+++ b/arch/riscv32/bits/user.h
@@ -0,0 +1,43 @@ 
+struct user_regs_struct {
+	unsigned long pc;
+	unsigned long ra;
+	unsigned long sp;
+	unsigned long gp;
+	unsigned long tp;
+	unsigned long t0;
+	unsigned long t1;
+	unsigned long t2;
+	unsigned long s0;
+	unsigned long s1;
+	unsigned long a0;
+	unsigned long a1;
+	unsigned long a2;
+	unsigned long a3;
+	unsigned long a4;
+	unsigned long a5;
+	unsigned long a6;
+	unsigned long a7;
+	unsigned long s2;
+	unsigned long s3;
+	unsigned long s4;
+	unsigned long s5;
+	unsigned long s6;
+	unsigned long s7;
+	unsigned long s8;
+	unsigned long s9;
+	unsigned long s10;
+	unsigned long s11;
+	unsigned long t3;
+	unsigned long t4;
+	unsigned long t5;
+	unsigned long t6;
+};
+
+struct user_fpregs_struct {
+	double f[32];
+	unsigned int fcsr;
+};
+
+#define ELF_NGREG 32
+typedef unsigned long elf_greg_t, elf_gregset_t[ELF_NGREG];
+typedef struct user_fpregs_struct elf_fpregset_t;
diff --git a/arch/riscv32/crt_arch.h b/arch/riscv32/crt_arch.h
new file mode 100644
index 0000000..65187e1
--- /dev/null
+++ b/arch/riscv32/crt_arch.h
@@ -0,0 +1,18 @@ 
+__asm__(
+".text\n"
+".global " START "\n"
+".type " START ",%function\n"
+START ":\n"
+".weak __global_pointer$\n"
+".hidden __global_pointer$\n\t"
+".option push\n"
+".option norelax\n\t"
+"lla gp, __global_pointer$\n"
+".option pop\n\t"
+"mv a0, sp\n"
+".weak _DYNAMIC\n"
+".hidden _DYNAMIC\n\t"
+"lla a1, _DYNAMIC\n\t"
+"andi sp, sp, -16\n\t"
+"jal " START "_c"
+);
diff --git a/arch/riscv32/pthread_arch.h b/arch/riscv32/pthread_arch.h
new file mode 100644
index 0000000..feffaa4
--- /dev/null
+++ b/arch/riscv32/pthread_arch.h
@@ -0,0 +1,12 @@ 
+static inline struct pthread *__pthread_self()
+{
+	char *tp;
+	__asm__ __volatile__("mv %0, tp" : "=r"(tp));
+	return (void *)(tp - sizeof(struct pthread));
+}
+
+#define TLS_ABOVE_TP
+#define GAP_ABOVE_TP 0
+#define TP_ADJ(p) ((char *)p + sizeof(struct pthread))
+
+#define MC_PC gregs[0]
diff --git a/arch/riscv32/reloc.h b/arch/riscv32/reloc.h
new file mode 100644
index 0000000..d057bbe
--- /dev/null
+++ b/arch/riscv32/reloc.h
@@ -0,0 +1,27 @@ 
+#if defined __riscv_float_abi_soft
+#define RISCV_FP_SUFFIX "-sf"
+#elif defined __riscv_float_abi_single
+#define RISCV_FP_SUFFIX "-sp"
+#elif defined __riscv_float_abi_double
+#define RISCV_FP_SUFFIX ""
+#endif
+
+#define RISCV_LDSO_HELPER(x) "riscv" #x
+#define RISCV_LDSO(x) RISCV_LDSO_HELPER(x)
+
+#define LDSO_ARCH RISCV_LDSO(__riscv_xlen) RISCV_FP_SUFFIX
+
+#define NO_LEGACY_INITFINI
+
+#define TPOFF_K 0
+
+#define REL_SYMBOLIC    R_RISCV_32
+#define REL_PLT         R_RISCV_JUMP_SLOT
+#define REL_RELATIVE    R_RISCV_RELATIVE
+#define REL_COPY        R_RISCV_COPY
+#define REL_DTPMOD      R_RISCV_TLS_DTPMOD32
+#define REL_DTPOFF      R_RISCV_TLS_DTPREL32
+#define REL_TPOFF       R_RISCV_TLS_TPREL32
+
+#define CRTJMP(pc,sp) __asm__ __volatile__( \
+	"mv sp, %1 ; jr %0" : : "r"(pc), "r"(sp) : "memory" )
diff --git a/arch/riscv32/syscall_arch.h b/arch/riscv32/syscall_arch.h
new file mode 100644
index 0000000..bc60d1f
--- /dev/null
+++ b/arch/riscv32/syscall_arch.h
@@ -0,0 +1,78 @@ 
+#define __SYSCALL_LL_E(x) \
+((union { long long ll; long l[2]; }){ .ll = x }).l[0], \
+((union { long long ll; long l[2]; }){ .ll = x }).l[1]
+#define __SYSCALL_LL_O(x) 0, __SYSCALL_LL_E((x))
+
+#define __asm_syscall(...) \
+	__asm__ __volatile__ ("scall\n\t" \
+	: "+r"(a0) : __VA_ARGS__ : "memory"); \
+	return a0; \
+
+static inline long __syscall0(long n)
+{
+	register long a7 __asm__("a7") = n;
+	register long a0 __asm__("a0");
+	__asm_syscall("r"(a7))
+}
+
+static inline long __syscall1(long n, long a)
+{
+	register long a7 __asm__("a7") = n;
+	register long a0 __asm__("a0") = a;
+	__asm_syscall("r"(a7), "0"(a0))
+}
+
+static inline long __syscall2(long n, long a, long b)
+{
+	register long a7 __asm__("a7") = n;
+	register long a0 __asm__("a0") = a;
+	register long a1 __asm__("a1") = b;
+	__asm_syscall("r"(a7), "0"(a0), "r"(a1))
+}
+
+static inline long __syscall3(long n, long a, long b, long c)
+{
+	register long a7 __asm__("a7") = n;
+	register long a0 __asm__("a0") = a;
+	register long a1 __asm__("a1") = b;
+	register long a2 __asm__("a2") = c;
+	__asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2))
+}
+
+static inline long __syscall4(long n, long a, long b, long c, long d)
+{
+	register long a7 __asm__("a7") = n;
+	register long a0 __asm__("a0") = a;
+	register long a1 __asm__("a1") = b;
+	register long a2 __asm__("a2") = c;
+	register long a3 __asm__("a3") = d;
+	__asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3))
+}
+
+static inline long __syscall5(long n, long a, long b, long c, long d, long e)
+{
+	register long a7 __asm__("a7") = n;
+	register long a0 __asm__("a0") = a;
+	register long a1 __asm__("a1") = b;
+	register long a2 __asm__("a2") = c;
+	register long a3 __asm__("a3") = d;
+	register long a4 __asm__("a4") = e;
+	__asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4))
+}
+
+static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
+{
+	register long a7 __asm__("a7") = n;
+	register long a0 __asm__("a0") = a;
+	register long a1 __asm__("a1") = b;
+	register long a2 __asm__("a2") = c;
+	register long a3 __asm__("a3") = d;
+	register long a4 __asm__("a4") = e;
+	register long a5 __asm__("a5") = f;
+	__asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5))
+}
+
+#define VDSO_USEFUL
+/* We don't have a clock_gettime function.
+#define VDSO_CGT_SYM "__vdso_clock_gettime"
+#define VDSO_CGT_VER "LINUX_2.6" */
diff --git a/arch/riscv64/atomic_arch.h b/arch/riscv64/atomic_arch.h
new file mode 100644
index 0000000..018c7fd
--- /dev/null
+++ b/arch/riscv64/atomic_arch.h
@@ -0,0 +1,66 @@ 
+#define a_barrier a_barrier
+static inline void a_barrier()
+{
+	__asm__ __volatile__ ("fence rw,rw" : : : "memory");
+}
+
+#define a_ll a_ll
+static inline int a_ll(volatile int *p)
+{
+	int v;
+	__asm__ __volatile__ ("lr.w %0, %1" : "=&r"(v), "+A"(*p));
+	return v;
+}
+
+#define a_sc a_sc
+static inline int a_sc(volatile int *p, int v)
+{
+	int r;
+	__asm__ __volatile__ ("sc.w %0, %2, %1" : "=&r"(r), "+A"(*p) : "r"(v) : "memory");
+return !r;
+}
+
+#define a_cas a_cas
+static inline int a_cas(volatile int *p, int t, int s)
+{
+	int old, tmp;
+	__asm__("1:  lr.w    %0, %2      \n"
+		"    bne     %0, %3, 1f  \n"
+		"    sc.w    %1, %4, %2  \n"
+		"    bnez    %1, 1b      \n"
+		"1:                      \n"
+		: "=&r"(old), "+r"(tmp), "+A"(*p)
+		: "r"(t), "r"(s));
+	return old;
+}
+
+#define a_ll_p a_ll_p
+static inline void *a_ll_p(volatile void *p)
+{
+	void *v;
+	__asm__ __volatile__ ("lr.d %0, %1" : "=&r"(v), "+A"(*(long *)p));
+	return v;
+}
+
+#define a_sc_p a_sc_p
+static inline int a_sc_p(volatile int *p, void *v)
+{
+	int r;
+	__asm__ __volatile__ ("sc.d %0, %2, %1" : "=&r"(r), "+A"(*(long *)p) : "r"(v) : "memory");
+	return !r;
+}
+
+#define a_cas_p a_cas_p
+static inline void *a_cas_p(volatile void *p, void *t, void *s)
+{
+	void *old;
+	int tmp;
+	__asm__("1:  lr.d    %0, %2      \n"
+		"    bne     %0, %3, 1f  \n"
+		"    sc.d    %1, %4, %2  \n"
+		"    bnez    %1, 1b      \n"
+		"1:                      \n"
+		: "=&r"(old), "+r"(tmp), "+A"(*(long *)p)
+		: "r"(t), "r"(s));
+	return old;
+}
diff --git a/arch/riscv64/bits/alltypes.h.in b/arch/riscv64/bits/alltypes.h.in
new file mode 100644
index 0000000..ae9ba41
--- /dev/null
+++ b/arch/riscv64/bits/alltypes.h.in
@@ -0,0 +1,29 @@ 
+#define _Addr long
+#define _Int64 long
+#define _Reg long
+
+TYPEDEF __builtin_va_list va_list;
+TYPEDEF __builtin_va_list __isoc_va_list;
+
+#ifndef __cplusplus
+TYPEDEF int wchar_t;
+#endif
+
+TYPEDEF int blksize_t;
+TYPEDEF unsigned int nlink_t;
+
+TYPEDEF float float_t;
+TYPEDEF double double_t;
+
+TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
+
+TYPEDEF long time_t;
+TYPEDEF long suseconds_t;
+
+TYPEDEF struct { union { int __i[14]; volatile int __vi[14]; unsigned long __s[7]; } __u; } pthread_attr_t;
+TYPEDEF struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } pthread_mutex_t;
+TYPEDEF struct { union { int __i[10]; volatile int __vi[10]; volatile void *volatile __p[5]; } __u; } mtx_t;
+TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } pthread_cond_t;
+TYPEDEF struct { union { int __i[12]; volatile int __vi[12]; void *__p[6]; } __u; } cnd_t;
+TYPEDEF struct { union { int __i[14]; volatile int __vi[14]; void *__p[7]; } __u; } pthread_rwlock_t;
+TYPEDEF struct { union { int __i[8]; volatile int __vi[8]; void *__p[4]; } __u; } pthread_barrier_t;
diff --git a/arch/riscv64/bits/endian.h b/arch/riscv64/bits/endian.h
new file mode 100644
index 0000000..7df0e02
--- /dev/null
+++ b/arch/riscv64/bits/endian.h
@@ -0,0 +1,5 @@ 
+#if __RISCVEB__
+#define __BYTE_ORDER __BIG_ENDIAN
+#else
+#define __BYTE_ORDER __LITTLE_ENDIAN
+#endif
diff --git a/arch/riscv64/bits/fcntl.h b/arch/riscv64/bits/fcntl.h
new file mode 100644
index 0000000..9278797
--- /dev/null
+++ b/arch/riscv64/bits/fcntl.h
@@ -0,0 +1,38 @@ 
+#define O_CREAT        0100
+#define O_EXCL         0200
+#define O_NOCTTY       0400
+#define O_TRUNC       01000
+#define O_APPEND      02000
+#define O_NONBLOCK    04000
+#define O_DSYNC      010000
+#define O_SYNC     04010000
+#define O_RSYNC    04010000
+#define O_DIRECTORY  040000
+#define O_NOFOLLOW  0100000
+#define O_CLOEXEC  02000000
+
+#define O_ASYNC      020000
+#define O_DIRECT    0200000
+#define O_LARGEFILE 0400000
+#define O_NOATIME  01000000
+#define O_PATH    010000000
+#define O_TMPFILE 020040000
+#define O_NDELAY O_NONBLOCK
+
+#define F_DUPFD  0
+#define F_GETFD  1
+#define F_SETFD  2
+#define F_GETFL  3
+#define F_SETFL  4
+#define F_GETLK  5
+#define F_SETLK  6
+#define F_SETLKW 7
+#define F_SETOWN 8
+#define F_GETOWN 9
+#define F_SETSIG 10
+#define F_GETSIG 11
+
+#define F_SETOWN_EX 15
+#define F_GETOWN_EX 16
+
+#define F_GETOWNER_UIDS 17
diff --git a/arch/riscv64/bits/fenv.h b/arch/riscv64/bits/fenv.h
new file mode 100644
index 0000000..806ec40
--- /dev/null
+++ b/arch/riscv64/bits/fenv.h
@@ -0,0 +1,17 @@ 
+#define FE_INVALID      16
+#define FE_DIVBYZERO    8
+#define FE_OVERFLOW     4
+#define FE_UNDERFLOW    2
+#define FE_INEXACT      1
+
+#define FE_ALL_EXCEPT   31
+
+#define FE_TONEAREST    0
+#define FE_DOWNWARD     2
+#define FE_UPWARD       3
+#define FE_TOWARDZERO   1
+
+typedef unsigned int fexcept_t;
+typedef unsigned int fenv_t;
+
+#define FE_DFL_ENV      ((const fenv_t *) -1)
diff --git a/arch/riscv64/bits/float.h b/arch/riscv64/bits/float.h
new file mode 100644
index 0000000..719c790
--- /dev/null
+++ b/arch/riscv64/bits/float.h
@@ -0,0 +1,16 @@ 
+#define FLT_EVAL_METHOD 0
+
+#define LDBL_TRUE_MIN 6.47517511943802511092443895822764655e-4966L
+#define LDBL_MIN 3.36210314311209350626267781732175260e-4932L
+#define LDBL_MAX 1.18973149535723176508575932662800702e+4932L
+#define LDBL_EPSILON 1.92592994438723585305597794258492732e-34L
+
+#define LDBL_MANT_DIG 113
+#define LDBL_MIN_EXP (-16381)
+#define LDBL_MAX_EXP 16384
+
+#define LDBL_DIG 33
+#define LDBL_MIN_10_EXP (-4931)
+#define LDBL_MAX_10_EXP 4932
+
+#define DECIMAL_DIG 36
diff --git a/arch/riscv64/bits/ipc.h b/arch/riscv64/bits/ipc.h
new file mode 100644
index 0000000..6f3328a
--- /dev/null
+++ b/arch/riscv64/bits/ipc.h
@@ -0,0 +1,14 @@ 
+struct ipc_perm {
+	key_t __ipc_perm_key;
+	uid_t uid;
+	gid_t gid;
+	uid_t cuid;
+	gid_t cgid;
+	mode_t mode;
+	unsigned short __ipc_perm_seq;
+
+	unsigned long __pad1;
+	unsigned long __pad2;
+};
+
+#define IPC_64 0
diff --git a/arch/riscv64/bits/limits.h b/arch/riscv64/bits/limits.h
new file mode 100644
index 0000000..0226588
--- /dev/null
+++ b/arch/riscv64/bits/limits.h
@@ -0,0 +1,7 @@ 
+#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+#define LONG_BIT 64
+#endif
+
+#define LONG_MAX  0x7fffffffffffffffL
+#define LLONG_MAX  0x7fffffffffffffffLL
diff --git a/arch/riscv64/bits/mman.h b/arch/riscv64/bits/mman.h
new file mode 100644
index 0000000..3695057
--- /dev/null
+++ b/arch/riscv64/bits/mman.h
@@ -0,0 +1 @@ 
+#define MAP_32BIT       0x40
diff --git a/arch/riscv64/bits/msg.h b/arch/riscv64/bits/msg.h
new file mode 100644
index 0000000..641e170
--- /dev/null
+++ b/arch/riscv64/bits/msg.h
@@ -0,0 +1,13 @@ 
+struct msqid_ds {
+	struct ipc_perm msg_perm;
+	time_t msg_stime;
+	time_t msg_rtime;
+	time_t msg_ctime;
+	unsigned long msg_cbytes;
+	msgqnum_t msg_qnum;
+	msglen_t msg_qbytes;
+	pid_t msg_lspid;
+	pid_t msg_lrpid;
+	unsigned long __pad1;
+	unsigned long __pad2;
+};
diff --git a/arch/riscv64/bits/posix.h b/arch/riscv64/bits/posix.h
new file mode 100644
index 0000000..8068ce9
--- /dev/null
+++ b/arch/riscv64/bits/posix.h
@@ -0,0 +1,2 @@ 
+#define _POSIX_V6_LP64_OFF64 1
+#define _POSIX_V7_LP64_OFF64 1
diff --git a/arch/riscv64/bits/reg.h b/arch/riscv64/bits/reg.h
new file mode 100644
index 0000000..c800788
--- /dev/null
+++ b/arch/riscv64/bits/reg.h
@@ -0,0 +1,8 @@ 
+#undef __WORDSIZE
+#define __WORDSIZE 64
+#define REG_PC 0
+#define REG_RA 1
+#define REG_SP 2
+#define REG_TP 4
+#define REG_S0 8
+#define REG_A0 10
diff --git a/arch/riscv64/bits/sem.h b/arch/riscv64/bits/sem.h
new file mode 100644
index 0000000..5f93c12
--- /dev/null
+++ b/arch/riscv64/bits/sem.h
@@ -0,0 +1,9 @@ 
+struct semid_ds {
+	struct ipc_perm sem_perm;
+	time_t sem_otime;
+	time_t sem_ctime;
+	unsigned short sem_nsems;
+	char __sem_nsems_pad[sizeof(time_t)-sizeof(short)];
+	time_t __unused3;
+	time_t __unused4;
+};
diff --git a/arch/riscv64/bits/setjmp.h b/arch/riscv64/bits/setjmp.h
new file mode 100644
index 0000000..b6cdc8e
--- /dev/null
+++ b/arch/riscv64/bits/setjmp.h
@@ -0,0 +1 @@ 
+typedef unsigned long __jmp_buf[28];
diff --git a/arch/riscv64/bits/shm.h b/arch/riscv64/bits/shm.h
new file mode 100644
index 0000000..f4b8712
--- /dev/null
+++ b/arch/riscv64/bits/shm.h
@@ -0,0 +1,26 @@ 
+#define SHMLBA 4096
+
+struct shmid_ds
+{
+	struct ipc_perm shm_perm;
+	size_t shm_segsz;
+	time_t shm_atime;
+	time_t shm_dtime;
+	time_t shm_ctime;
+	pid_t shm_cpid;
+	pid_t shm_lpid;
+	unsigned long shm_nattch;
+	unsigned long __pad1;
+	unsigned long __pad2;
+};
+
+struct shminfo {
+	unsigned long shmmax, shmmin, shmmni, shmseg, shmall, __unused[4];
+};
+
+struct shm_info {
+	int __used_ids;
+	unsigned long shm_tot, shm_rss, shm_swp;
+	unsigned long __swap_attempts, __swap_successes;
+};
+
diff --git a/arch/riscv64/bits/signal.h b/arch/riscv64/bits/signal.h
new file mode 100644
index 0000000..8b992cc
--- /dev/null
+++ b/arch/riscv64/bits/signal.h
@@ -0,0 +1,113 @@ 
+#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+
+#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+# define MINSIGSTKSZ 2048
+# define SIGSTKSZ 8192
+#endif
+
+/* gregs[0] holds the program counter. */
+
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+typedef unsigned long greg_t;
+typedef unsigned long gregset_t[32];
+
+struct __riscv_f_ext_state {
+	unsigned int f[32];
+	unsigned int fcsr;
+};
+
+struct __riscv_d_ext_state {
+	unsigned long long f[32];
+	unsigned int fcsr;
+};
+
+struct __riscv_q_ext_state {
+	unsigned long long f[64] __attribute__((aligned(16)));
+	unsigned int fcsr;
+	unsigned int reserved[3];
+};
+
+union __riscv_fp_state {
+	struct __riscv_f_ext_state f;
+	struct __riscv_d_ext_state d;
+	struct __riscv_q_ext_state q;
+};
+
+typedef union __riscv_fp_state fpregset_t;
+
+typedef struct sigcontext {
+	gregset_t gregs;
+	fpregset_t fpregs;
+} mcontext_t;
+
+#else
+typedef struct {
+	unsigned long gregs[32];
+	unsigned long long fpregs[66];
+} mcontext_t;
+#endif
+
+struct sigaltstack {
+	void *ss_sp;
+	int ss_flags;
+	size_t ss_size;
+};
+
+typedef struct __ucontext
+{
+	unsigned long uc_flags;
+	struct __ucontext *uc_link;
+	stack_t uc_stack;
+	sigset_t uc_sigmask;
+	char __unused[1024 / 8 - sizeof(sigset_t)];
+	mcontext_t uc_mcontext;
+} ucontext_t;
+
+#define SA_NOCLDSTOP 1
+#define SA_NOCLDWAIT 2
+#define SA_SIGINFO   4
+#define SA_ONSTACK   0x08000000
+#define SA_RESTART   0x10000000
+#define SA_NODEFER   0x40000000
+#define SA_RESETHAND 0x80000000
+#define SA_RESTORER  0x04000000
+
+#endif
+
+#define SIGHUP     1
+#define SIGINT     2
+#define SIGQUIT    3
+#define SIGILL     4
+#define SIGTRAP    5
+#define SIGABRT    6
+#define SIGIOT     SIGABRT
+#define SIGBUS     7
+#define SIGFPE     8
+#define SIGKILL    9
+#define SIGUSR1   10
+#define SIGSEGV   11
+#define SIGUSR2   12
+#define SIGPIPE   13
+#define SIGALRM   14
+#define SIGTERM   15
+#define SIGSTKFLT 16
+#define SIGCHLD   17
+#define SIGCONT   18
+#define SIGSTOP   19
+#define SIGTSTP   20
+#define SIGTTIN   21
+#define SIGTTOU   22
+#define SIGURG    23
+#define SIGXCPU   24
+#define SIGXFSZ   25
+#define SIGVTALRM 26
+#define SIGPROF   27
+#define SIGWINCH  28
+#define SIGIO     29
+#define SIGPOLL   SIGIO
+#define SIGPWR    30
+#define SIGSYS    31
+#define SIGUNUSED SIGSYS
+
+#define _NSIG     65
diff --git a/arch/riscv64/bits/socket.h b/arch/riscv64/bits/socket.h
new file mode 100644
index 0000000..c11677e
--- /dev/null
+++ b/arch/riscv64/bits/socket.h
@@ -0,0 +1,33 @@ 
+#include <endian.h>
+
+struct msghdr {
+	void *msg_name;
+	socklen_t msg_namelen;
+	struct iovec *msg_iov;
+#if __BYTE_ORDER == __BIG_ENDIAN
+	int __pad1, msg_iovlen;
+#else
+	int msg_iovlen, __pad1;
+#endif
+	void *msg_control;
+#if __BYTE_ORDER == __BIG_ENDIAN
+	int __pad2;
+	socklen_t msg_controllen;
+#else
+	socklen_t msg_controllen;
+	int __pad2;
+#endif
+	int msg_flags;
+};
+
+struct cmsghdr {
+#if __BYTE_ORDER == __BIG_ENDIAN
+	int __pad1;
+	socklen_t cmsg_len;
+#else
+	socklen_t cmsg_len;
+	int __pad1;
+#endif
+	int cmsg_level;
+	int cmsg_type;
+};
diff --git a/arch/riscv64/bits/stat.h b/arch/riscv64/bits/stat.h
new file mode 100644
index 0000000..b7f4221
--- /dev/null
+++ b/arch/riscv64/bits/stat.h
@@ -0,0 +1,18 @@ 
+struct stat {
+	dev_t st_dev;
+	ino_t st_ino;
+	mode_t st_mode;
+	nlink_t st_nlink;
+	uid_t st_uid;
+	gid_t st_gid;
+	dev_t st_rdev;
+	unsigned long __pad;
+	off_t st_size;
+	blksize_t st_blksize;
+	int __pad2;
+	blkcnt_t st_blocks;
+	struct timespec st_atim;
+	struct timespec st_mtim;
+	struct timespec st_ctim;
+	unsigned __unused[2];
+};
diff --git a/arch/riscv64/bits/stdint.h b/arch/riscv64/bits/stdint.h
new file mode 100644
index 0000000..1bb147f
--- /dev/null
+++ b/arch/riscv64/bits/stdint.h
@@ -0,0 +1,20 @@ 
+typedef int32_t int_fast16_t;
+typedef int32_t int_fast32_t;
+typedef uint32_t uint_fast16_t;
+typedef uint32_t uint_fast32_t;
+
+#define INT_FAST16_MIN  INT32_MIN
+#define INT_FAST32_MIN  INT32_MIN
+
+#define INT_FAST16_MAX  INT32_MAX
+#define INT_FAST32_MAX  INT32_MAX
+
+#define UINT_FAST16_MAX UINT32_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+
+#define INTPTR_MIN      INT64_MIN
+#define INTPTR_MAX      INT64_MAX
+#define UINTPTR_MAX     UINT64_MAX
+#define PTRDIFF_MIN     INT64_MIN
+#define PTRDIFF_MAX     INT64_MAX
+#define SIZE_MAX        UINT64_MAX
diff --git a/arch/riscv64/bits/syscall.h.in b/arch/riscv64/bits/syscall.h.in
new file mode 100644
index 0000000..3c81c10
--- /dev/null
+++ b/arch/riscv64/bits/syscall.h.in
@@ -0,0 +1,278 @@ 
+#define __NR_io_setup 0
+#define __NR_io_destroy 1
+#define __NR_io_submit 2
+#define __NR_io_cancel 3
+#define __NR_io_getevents 4
+#define __NR_setxattr 5
+#define __NR_lsetxattr 6
+#define __NR_fsetxattr 7
+#define __NR_getxattr 8
+#define __NR_lgetxattr 9
+#define __NR_fgetxattr 10
+#define __NR_listxattr 11
+#define __NR_llistxattr 12
+#define __NR_flistxattr 13
+#define __NR_removexattr 14
+#define __NR_lremovexattr 15
+#define __NR_fremovexattr 16
+#define __NR_getcwd 17
+#define __NR_lookup_dcookie 18
+#define __NR_eventfd2 19
+#define __NR_epoll_create1 20
+#define __NR_epoll_ctl 21
+#define __NR_epoll_pwait 22
+#define __NR_dup 23
+#define __NR_dup3 24
+#define __NR_fcntl 25
+#define __NR_inotify_init1 26
+#define __NR_inotify_add_watch 27
+#define __NR_inotify_rm_watch 28
+#define __NR_ioctl 29
+#define __NR_ioprio_set 30
+#define __NR_ioprio_get 31
+#define __NR_flock 32
+#define __NR_mknodat 33
+#define __NR_mkdirat 34
+#define __NR_unlinkat 35
+#define __NR_symlinkat 36
+#define __NR_linkat 37
+#define __NR_renameat 38
+#define __NR_umount2 39
+#define __NR_mount 40
+#define __NR_pivot_root 41
+#define __NR_nfsservctl 42
+#define __NR_statfs 43
+#define __NR_fstatfs 44
+#define __NR_truncate 45
+#define __NR_ftruncate 46
+#define __NR_fallocate 47
+#define __NR_faccessat 48
+#define __NR_chdir 49
+#define __NR_fchdir 50
+#define __NR_chroot 51
+#define __NR_fchmod 52
+#define __NR_fchmodat 53
+#define __NR_fchownat 54
+#define __NR_fchown 55
+#define __NR_openat 56
+#define __NR_close 57
+#define __NR_vhangup 58
+#define __NR_pipe2 59
+#define __NR_quotactl 60
+#define __NR_getdents64 61
+#define __NR_lseek 62
+#define __NR_read 63
+#define __NR_write 64
+#define __NR_readv 65
+#define __NR_writev 66
+#define __NR_pread64 67
+#define __NR_pwrite64 68
+#define __NR_preadv 69
+#define __NR_pwritev 70
+#define __NR_sendfile 71
+#define __NR_pselect6 72
+#define __NR_ppoll 73
+#define __NR_signalfd4 74
+#define __NR_vmsplice 75
+#define __NR_splice 76
+#define __NR_tee 77
+#define __NR_readlinkat 78
+#define __NR_fstatat 79
+#define __NR_fstat 80
+#define __NR_sync 81
+#define __NR_fsync 82
+#define __NR_fdatasync 83
+#define __NR_sync_file_range 84
+#define __NR_timerfd_create 85
+#define __NR_timerfd_settime 86
+#define __NR_timerfd_gettime 87
+#define __NR_utimensat 88
+#define __NR_acct 89
+#define __NR_capget 90
+#define __NR_capset 91
+#define __NR_personality 92
+#define __NR_exit 93
+#define __NR_exit_group 94
+#define __NR_waitid 95
+#define __NR_set_tid_address 96
+#define __NR_unshare 97
+#define __NR_futex 98
+#define __NR_set_robust_list 99
+#define __NR_get_robust_list 100
+#define __NR_nanosleep 101
+#define __NR_getitimer 102
+#define __NR_setitimer 103
+#define __NR_kexec_load 104
+#define __NR_init_module 105
+#define __NR_delete_module 106
+#define __NR_timer_create 107
+#define __NR_timer_gettime 108
+#define __NR_timer_getoverrun 109
+#define __NR_timer_settime 110
+#define __NR_timer_delete 111
+#define __NR_clock_settime 112
+#define __NR_clock_gettime 113
+#define __NR_clock_getres 114
+#define __NR_clock_nanosleep 115
+#define __NR_syslog 116
+#define __NR_ptrace 117
+#define __NR_sched_setparam 118
+#define __NR_sched_setscheduler 119
+#define __NR_sched_getscheduler 120
+#define __NR_sched_getparam 121
+#define __NR_sched_setaffinity 122
+#define __NR_sched_getaffinity 123
+#define __NR_sched_yield 124
+#define __NR_sched_get_priority_max 125
+#define __NR_sched_get_priority_min 126
+#define __NR_sched_rr_get_interval 127
+#define __NR_restart_syscall 128
+#define __NR_kill 129
+#define __NR_tkill 130
+#define __NR_tgkill 131
+#define __NR_sigaltstack 132
+#define __NR_rt_sigsuspend 133
+#define __NR_rt_sigaction 134
+#define __NR_rt_sigprocmask 135
+#define __NR_rt_sigpending 136
+#define __NR_rt_sigtimedwait 137
+#define __NR_rt_sigqueueinfo 138
+#define __NR_rt_sigreturn 139
+#define __NR_setpriority 140
+#define __NR_getpriority 141
+#define __NR_reboot 142
+#define __NR_setregid 143
+#define __NR_setgid 144
+#define __NR_setreuid 145
+#define __NR_setuid 146
+#define __NR_setresuid 147
+#define __NR_getresuid 148
+#define __NR_setresgid 149
+#define __NR_getresgid 150
+#define __NR_setfsuid 151
+#define __NR_setfsgid 152
+#define __NR_times 153
+#define __NR_setpgid 154
+#define __NR_getpgid 155
+#define __NR_getsid 156
+#define __NR_setsid 157
+#define __NR_getgroups 158
+#define __NR_setgroups 159
+#define __NR_uname 160
+#define __NR_sethostname 161
+#define __NR_setdomainname 162
+#define __NR_getrlimit 163
+#define __NR_setrlimit 164
+#define __NR_getrusage 165
+#define __NR_umask 166
+#define __NR_prctl 167
+#define __NR_getcpu 168
+#define __NR_gettimeofday 169
+#define __NR_settimeofday 170
+#define __NR_adjtimex 171
+#define __NR_getpid 172
+#define __NR_getppid 173
+#define __NR_getuid 174
+#define __NR_geteuid 175
+#define __NR_getgid 176
+#define __NR_getegid 177
+#define __NR_gettid 178
+#define __NR_sysinfo 179
+#define __NR_mq_open 180
+#define __NR_mq_unlink 181
+#define __NR_mq_timedsend 182
+#define __NR_mq_timedreceive 183
+#define __NR_mq_notify 184
+#define __NR_mq_getsetattr 185
+#define __NR_msgget 186
+#define __NR_msgctl 187
+#define __NR_msgrcv 188
+#define __NR_msgsnd 189
+#define __NR_semget 190
+#define __NR_semctl 191
+#define __NR_semtimedop 192
+#define __NR_semop 193
+#define __NR_shmget 194
+#define __NR_shmctl 195
+#define __NR_shmat 196
+#define __NR_shmdt 197
+#define __NR_socket 198
+#define __NR_socketpair 199
+#define __NR_bind 200
+#define __NR_listen 201
+#define __NR_accept 202
+#define __NR_connect 203
+#define __NR_getsockname 204
+#define __NR_getpeername 205
+#define __NR_sendto 206
+#define __NR_recvfrom 207
+#define __NR_setsockopt 208
+#define __NR_getsockopt 209
+#define __NR_shutdown 210
+#define __NR_sendmsg 211
+#define __NR_recvmsg 212
+#define __NR_readahead 213
+#define __NR_brk 214
+#define __NR_munmap 215
+#define __NR_mremap 216
+#define __NR_add_key 217
+#define __NR_request_key 218
+#define __NR_keyctl 219
+#define __NR_clone 220
+#define __NR_execve 221
+#define __NR_mmap 222
+#define __NR_fadvise64 223
+#define __NR_swapon 224
+#define __NR_swapoff 225
+#define __NR_mprotect 226
+#define __NR_msync 227
+#define __NR_mlock 228
+#define __NR_munlock 229
+#define __NR_mlockall 230
+#define __NR_munlockall 231
+#define __NR_mincore 232
+#define __NR_madvise 233
+#define __NR_remap_file_pages 234
+#define __NR_mbind 235
+#define __NR_get_mempolicy 236
+#define __NR_set_mempolicy 237
+#define __NR_migrate_pages 238
+#define __NR_move_pages 239
+#define __NR_rt_tgsigqueueinfo 240
+#define __NR_perf_event_open 241
+#define __NR_accept4 242
+#define __NR_recvmmsg 243
+#define __NR_arch_specific_syscall 244
+#define __NR_wait4 260
+#define __NR_prlimit64 261
+#define __NR_fanotify_init 262
+#define __NR_fanotify_mark 263
+#define __NR_name_to_handle_at 264
+#define __NR_open_by_handle_at 265
+#define __NR_clock_adjtime 266
+#define __NR_syncfs 267
+#define __NR_setns 268
+#define __NR_sendmmsg 269
+#define __NR_process_vm_readv 270
+#define __NR_process_vm_writev 271
+#define __NR_kcmp 272
+#define __NR_finit_module 273
+#define __NR_sched_setattr 274
+#define __NR_sched_getattr 275
+#define __NR_renameat2 276
+#define __NR_seccomp 277
+#define __NR_getrandom 278
+#define __NR_memfd_create 279
+#define __NR_bpf 280
+#define __NR_execveat 281
+#define __NR_userfaultfd 282
+#define __NR_membarrier 283
+#define __NR_mlock2 284
+#define __NR_copy_file_range 285
+#define __NR_preadv2 286
+#define __NR_pwritev2 287
+#define __NR_pkey_mprotect 288
+#define __NR_pkey_alloc 289
+#define __NR_pkey_free 290
+#define __NR_sysriscv __NR_arch_specific_syscall
+
diff --git a/arch/riscv64/bits/user.h b/arch/riscv64/bits/user.h
new file mode 100644
index 0000000..bd0f0fc
--- /dev/null
+++ b/arch/riscv64/bits/user.h
@@ -0,0 +1,43 @@ 
+struct user_regs_struct {
+	unsigned long pc;
+	unsigned long ra;
+	unsigned long sp;
+	unsigned long gp;
+	unsigned long tp;
+	unsigned long t0;
+	unsigned long t1;
+	unsigned long t2;
+	unsigned long s0;
+	unsigned long s1;
+	unsigned long a0;
+	unsigned long a1;
+	unsigned long a2;
+	unsigned long a3;
+	unsigned long a4;
+	unsigned long a5;
+	unsigned long a6;
+	unsigned long a7;
+	unsigned long s2;
+	unsigned long s3;
+	unsigned long s4;
+	unsigned long s5;
+	unsigned long s6;
+	unsigned long s7;
+	unsigned long s8;
+	unsigned long s9;
+	unsigned long s10;
+	unsigned long s11;
+	unsigned long t3;
+	unsigned long t4;
+	unsigned long t5;
+	unsigned long t6;
+};
+
+struct user_fpregs_struct {
+	double f[32];
+	unsigned int fcsr;
+};
+
+#define ELF_NGREG 32
+typedef unsigned long elf_greg_t, elf_gregset_t[ELF_NGREG];
+typedef struct user_fpregs_struct elf_fpregset_t;
diff --git a/arch/riscv64/crt_arch.h b/arch/riscv64/crt_arch.h
new file mode 100644
index 0000000..d0e32a6
--- /dev/null
+++ b/arch/riscv64/crt_arch.h
@@ -0,0 +1,18 @@ 
+__asm__(
+".text\n"
+".global " START "\n"
+".type " START ",%function\n"
+START ":\n"
+".weak __global_pointer$\n"
+".hidden __global_pointer$\n"
+".option push\n"
+".option norelax\n\t"
+"lla gp, __global_pointer$\n"
+".option pop\n\t"
+"mv a0, sp\n"
+".weak _DYNAMIC\n"
+".hidden _DYNAMIC\n\t"
+"lla a1, _DYNAMIC\n\t"
+"andi sp, sp, -16\n\t"
+"jal " START "_c"
+);
diff --git a/arch/riscv64/pthread_arch.h b/arch/riscv64/pthread_arch.h
new file mode 100644
index 0000000..feffaa4
--- /dev/null
+++ b/arch/riscv64/pthread_arch.h
@@ -0,0 +1,12 @@ 
+static inline struct pthread *__pthread_self()
+{
+	char *tp;
+	__asm__ __volatile__("mv %0, tp" : "=r"(tp));
+	return (void *)(tp - sizeof(struct pthread));
+}
+
+#define TLS_ABOVE_TP
+#define GAP_ABOVE_TP 0
+#define TP_ADJ(p) ((char *)p + sizeof(struct pthread))
+
+#define MC_PC gregs[0]
diff --git a/arch/riscv64/reloc.h b/arch/riscv64/reloc.h
new file mode 100644
index 0000000..8bd90dd
--- /dev/null
+++ b/arch/riscv64/reloc.h
@@ -0,0 +1,27 @@ 
+#if defined __riscv_float_abi_soft
+#define RISCV_FP_SUFFIX "-sf"
+#elif defined __riscv_float_abi_single
+#define RISCV_FP_SUFFIX "-sp"
+#elif defined __riscv_float_abi_double
+#define RISCV_FP_SUFFIX ""
+#endif
+
+#define RISCV_LDSO_HELPER(x) "riscv" #x
+#define RISCV_LDSO(x) RISCV_LDSO_HELPER(x)
+
+#define LDSO_ARCH RISCV_LDSO(__riscv_xlen) RISCV_FP_SUFFIX
+
+#define NO_LEGACY_INITFINI
+
+#define TPOFF_K 0
+
+#define REL_SYMBOLIC    R_RISCV_64
+#define REL_PLT         R_RISCV_JUMP_SLOT
+#define REL_RELATIVE    R_RISCV_RELATIVE
+#define REL_COPY        R_RISCV_COPY
+#define REL_DTPMOD      R_RISCV_TLS_DTPMOD64
+#define REL_DTPOFF      R_RISCV_TLS_DTPREL64
+#define REL_TPOFF       R_RISCV_TLS_TPREL64
+
+#define CRTJMP(pc,sp) __asm__ __volatile__( \
+	"mv sp, %1 ; jr %0" : : "r"(pc), "r"(sp) : "memory" )
diff --git a/arch/riscv64/syscall_arch.h b/arch/riscv64/syscall_arch.h
new file mode 100644
index 0000000..7b6e3fd
--- /dev/null
+++ b/arch/riscv64/syscall_arch.h
@@ -0,0 +1,76 @@ 
+#define __SYSCALL_LL_E(x) (x)
+#define __SYSCALL_LL_O(x) (x)
+
+#define __asm_syscall(...) \
+	__asm__ __volatile__ ("scall\n\t" \
+	: "+r"(a0) : __VA_ARGS__ : "memory"); \
+	return a0; \
+
+static inline long __syscall0(long n)
+{
+	register long a7 __asm__("a7") = n;
+	register long a0 __asm__("a0");
+	__asm_syscall("r"(a7))
+}
+
+static inline long __syscall1(long n, long a)
+{
+	register long a7 __asm__("a7") = n;
+	register long a0 __asm__("a0") = a;
+	__asm_syscall("r"(a7), "0"(a0))
+}
+
+static inline long __syscall2(long n, long a, long b)
+{
+	register long a7 __asm__("a7") = n;
+	register long a0 __asm__("a0") = a;
+	register long a1 __asm__("a1") = b;
+	__asm_syscall("r"(a7), "0"(a0), "r"(a1))
+}
+
+static inline long __syscall3(long n, long a, long b, long c)
+{
+	register long a7 __asm__("a7") = n;
+	register long a0 __asm__("a0") = a;
+	register long a1 __asm__("a1") = b;
+	register long a2 __asm__("a2") = c;
+	__asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2))
+}
+
+static inline long __syscall4(long n, long a, long b, long c, long d)
+{
+	register long a7 __asm__("a7") = n;
+	register long a0 __asm__("a0") = a;
+	register long a1 __asm__("a1") = b;
+	register long a2 __asm__("a2") = c;
+	register long a3 __asm__("a3") = d;
+	__asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3))
+}
+
+static inline long __syscall5(long n, long a, long b, long c, long d, long e)
+{
+	register long a7 __asm__("a7") = n;
+	register long a0 __asm__("a0") = a;
+	register long a1 __asm__("a1") = b;
+	register long a2 __asm__("a2") = c;
+	register long a3 __asm__("a3") = d;
+	register long a4 __asm__("a4") = e;
+	__asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4))
+}
+
+static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
+{
+	register long a7 __asm__("a7") = n;
+	register long a0 __asm__("a0") = a;
+	register long a1 __asm__("a1") = b;
+	register long a2 __asm__("a2") = c;
+	register long a3 __asm__("a3") = d;
+	register long a4 __asm__("a4") = e;
+	register long a5 __asm__("a5") = f;
+	__asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5))
+}
+
+#define VDSO_USEFUL
+/* We don't have a clock_gettime function.
+#define VDSO_CGT_SYM "__vdso_clock_gettime"
+#define VDSO_CGT_VER "LINUX_2.6" */
diff --git a/configure b/configure
index 997e665..4d3d8b4 100755
--- a/configure
+++ b/configure
@@ -322,6 +322,8 @@  microblaze*) ARCH=microblaze ;;
 or1k*) ARCH=or1k ;;
 powerpc64*) ARCH=powerpc64 ;;
 powerpc*) ARCH=powerpc ;;
+riscv64*) ARCH=riscv64 ;;
+riscv*) ARCH=riscv32 ;;
 sh[1-9bel-]*|sh|superh*) ARCH=sh ;;
 s390x*) ARCH=s390x ;;
 unknown) fail "$0: unable to detect target arch; try $0 --target=..." ;;
@@ -640,6 +642,11 @@  trycppif __LITTLE_ENDIAN__ "$t" && SUBARCH=${SUBARCH}le
 trycppif _SOFT_FLOAT "$t" && fail "$0: error: soft-float not supported on powerpc64"
 fi
 
+if test "$ARCH" = "riscv" || test "$ARCH" = "riscv64" ; then
+trycppif "RISCVEB || _RISCVEB || __RISCVEB || __RISCVEB__" "$t" && SUBARCH=${SUBARCH}eb
+trycppif __riscv_soft_float "$t" && SUBARCH=${SUBARCH}-sf
+fi
+
 if test "$ARCH" = "sh" ; then
 tryflag CFLAGS_AUTO -Wa,--isa=any
 trycppif __BIG_ENDIAN__ "$t" && SUBARCH=${SUBARCH}eb
diff --git a/crt/riscv32/crti.s b/crt/riscv32/crti.s
new file mode 100644
index 0000000..6916bfd
--- /dev/null
+++ b/crt/riscv32/crti.s
@@ -0,0 +1,11 @@ 
+.section .init
+.global _init
+.type _init,%function
+_init:
+        ret
+
+.section .fini
+.global _fini
+.type _fini,%function
+_fini:
+        ret
diff --git a/crt/riscv32/crtn.s b/crt/riscv32/crtn.s
new file mode 100644
index 0000000..e69de29
diff --git a/crt/riscv64/crti.s b/crt/riscv64/crti.s
new file mode 100644
index 0000000..8b54a65
--- /dev/null
+++ b/crt/riscv64/crti.s
@@ -0,0 +1,11 @@ 
+.section .init
+.global _init
+.type _init,%function
+_init:
+        ret
+
+.section .fini
+.global _fini
+.type _fini %function
+_fini:
+        ret
diff --git a/crt/riscv64/crtn.s b/crt/riscv64/crtn.s
new file mode 100644
index 0000000..e69de29
diff --git a/include/elf.h b/include/elf.h
index c229735..ec2e8fd 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -3164,6 +3164,62 @@  enum
 #define R_BPF_NONE		0
 #define R_BPF_MAP_FD		1
 
+#define R_RISCV_NONE            0
+#define R_RISCV_32              1
+#define R_RISCV_64              2
+#define R_RISCV_RELATIVE        3
+#define R_RISCV_COPY            4
+#define R_RISCV_JUMP_SLOT       5
+#define R_RISCV_TLS_DTPMOD32    6
+#define R_RISCV_TLS_DTPMOD64    7
+#define R_RISCV_TLS_DTPREL32    8
+#define R_RISCV_TLS_DTPREL64    9
+#define R_RISCV_TLS_TPREL32     10
+#define R_RISCV_TLS_TPREL64     11
+
+#define R_RISCV_BRANCH          16
+#define R_RISCV_JAL             17
+#define R_RISCV_CALL            18
+#define R_RISCV_CALL_PLT        19
+#define R_RISCV_GOT_HI20        20
+#define R_RISCV_TLS_GOT_HI20    21
+#define R_RISCV_TLS_GD_HI20     22
+#define R_RISCV_PCREL_HI20      23
+#define R_RISCV_PCREL_LO12_I    24
+#define R_RISCV_PCREL_LO12_S    25
+#define R_RISCV_HI20            26
+#define R_RISCV_LO12_I          27
+#define R_RISCV_LO12_S          28
+#define R_RISCV_TPREL_HI20      29
+#define R_RISCV_TPREL_LO12_I    30
+#define R_RISCV_TPREL_LO12_S    31
+#define R_RISCV_TPREL_ADD       32
+#define R_RISCV_ADD8            33
+#define R_RISCV_ADD16           34
+#define R_RISCV_ADD32           35
+#define R_RISCV_ADD64           36
+#define R_RISCV_SUB8            37
+#define R_RISCV_SUB16           38
+#define R_RISCV_SUB32           39
+#define R_RISCV_SUB64           40
+#define R_RISCV_GNU_VTINHERIT   41
+#define R_RISCV_GNU_VTENTRY     42
+#define R_RISCV_ALIGN           43
+#define R_RISCV_RVC_BRANCH      44
+#define R_RISCV_RVC_JUMP        45
+#define R_RISCV_RVC_LUI         46
+#define R_RISCV_GPREL_I         47
+#define R_RISCV_GPREL_S         48
+#define R_RISCV_TPREL_I         49
+#define R_RISCV_TPREL_S         50
+#define R_RISCV_RELAX           51
+#define R_RISCV_SUB6            52
+#define R_RISCV_SET6            53
+#define R_RISCV_SET8            54
+#define R_RISCV_SET16           55
+#define R_RISCV_SET32           56
+#define R_RISCV_32_PCREL        57
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/fenv/riscv32/fenv-sf.c b/src/fenv/riscv32/fenv-sf.c
new file mode 100644
index 0000000..9ff7b79
--- /dev/null
+++ b/src/fenv/riscv32/fenv-sf.c
@@ -0,0 +1,3 @@ 
+#ifdef __riscv_soft_float
+#include "../fenv.c"
+#endif
diff --git a/src/fenv/riscv32/fenv.S b/src/fenv/riscv32/fenv.S
new file mode 100644
index 0000000..a55aa4a
--- /dev/null
+++ b/src/fenv/riscv32/fenv.S
@@ -0,0 +1,53 @@ 
+#ifndef __riscv_soft_float
+
+.global feclearexcept
+.type feclearexcept, %function
+feclearexcept:
+        csrc fflags, a0
+        li a0, 0
+        ret
+
+.global feraiseexcept
+.type feraiseexcept, %function
+feraiseexcept:
+        csrs fflags, a0
+        li a0, 0
+        ret
+
+.global fetestexcept
+.type fetestexcept, %function
+fetestexcept:
+        frflags t0
+        and a0, t0, a0
+        ret
+
+.global fegetround
+.type fegetround, %function
+fegetround:
+        frrm a0
+        ret
+
+.global __fesetround
+.type __fesetround, %function
+__fesetround:
+        fsrm t0, a0
+        li a0, 0
+        ret
+
+.global fegetenv
+.type fegetenv, %function
+fegetenv:
+        frcsr t0
+        sw t0, 0(a0)
+        li a0, 0
+        ret
+
+.global fesetenv
+.type fesetenv, %function
+fesetenv:
+        lw t1, 0(a0)
+        fscsr t0, t1
+        li a0, 0
+        ret
+
+#endif
diff --git a/src/fenv/riscv64/fenv-sf.c b/src/fenv/riscv64/fenv-sf.c
new file mode 100644
index 0000000..9ff7b79
--- /dev/null
+++ b/src/fenv/riscv64/fenv-sf.c
@@ -0,0 +1,3 @@ 
+#ifdef __riscv_soft_float
+#include "../fenv.c"
+#endif
diff --git a/src/fenv/riscv64/fenv.S b/src/fenv/riscv64/fenv.S
new file mode 100644
index 0000000..a55aa4a
--- /dev/null
+++ b/src/fenv/riscv64/fenv.S
@@ -0,0 +1,53 @@ 
+#ifndef __riscv_soft_float
+
+.global feclearexcept
+.type feclearexcept, %function
+feclearexcept:
+        csrc fflags, a0
+        li a0, 0
+        ret
+
+.global feraiseexcept
+.type feraiseexcept, %function
+feraiseexcept:
+        csrs fflags, a0
+        li a0, 0
+        ret
+
+.global fetestexcept
+.type fetestexcept, %function
+fetestexcept:
+        frflags t0
+        and a0, t0, a0
+        ret
+
+.global fegetround
+.type fegetround, %function
+fegetround:
+        frrm a0
+        ret
+
+.global __fesetround
+.type __fesetround, %function
+__fesetround:
+        fsrm t0, a0
+        li a0, 0
+        ret
+
+.global fegetenv
+.type fegetenv, %function
+fegetenv:
+        frcsr t0
+        sw t0, 0(a0)
+        li a0, 0
+        ret
+
+.global fesetenv
+.type fesetenv, %function
+fesetenv:
+        lw t1, 0(a0)
+        fscsr t0, t1
+        li a0, 0
+        ret
+
+#endif
diff --git a/src/internal/riscv32/syscall.s b/src/internal/riscv32/syscall.s
new file mode 100644
index 0000000..a7d125a
--- /dev/null
+++ b/src/internal/riscv32/syscall.s
@@ -0,0 +1,15 @@ 
+.global __syscall
+.hidden __syscall
+.type   __syscall,%function
+__syscall:
+        mv t0, a0
+        mv a0, a1
+        mv a1, a2
+        mv a2, a3
+        mv a3, a4
+        mv a4, a5
+        mv a5, a6
+        mv a6, a7
+        mv a7, t0
+        scall
+        ret
diff --git a/src/internal/riscv64/syscall.s b/src/internal/riscv64/syscall.s
new file mode 100644
index 0000000..a7d125a
--- /dev/null
+++ b/src/internal/riscv64/syscall.s
@@ -0,0 +1,15 @@ 
+.global __syscall
+.hidden __syscall
+.type   __syscall,%function
+__syscall:
+        mv t0, a0
+        mv a0, a1
+        mv a1, a2
+        mv a2, a3
+        mv a3, a4
+        mv a4, a5
+        mv a5, a6
+        mv a6, a7
+        mv a7, t0
+        scall
+        ret
diff --git a/src/ldso/riscv32/dlsym.s b/src/ldso/riscv32/dlsym.s
new file mode 100644
index 0000000..ff9109d
--- /dev/null
+++ b/src/ldso/riscv32/dlsym.s
@@ -0,0 +1,6 @@ 
+.global dlsym
+.hidden __dlsym
+.type dlsym, %function
+dlsym:
+        mv a2, ra
+        j __dlsym
diff --git a/src/ldso/riscv64/dlsym.s b/src/ldso/riscv64/dlsym.s
new file mode 100644
index 0000000..ff9109d
--- /dev/null
+++ b/src/ldso/riscv64/dlsym.s
@@ -0,0 +1,6 @@ 
+.global dlsym
+.hidden __dlsym
+.type dlsym, %function
+dlsym:
+        mv a2, ra
+        j __dlsym
diff --git a/src/math/riscv32/copysign.s b/src/math/riscv32/copysign.s
new file mode 100644
index 0000000..81afa8b
--- /dev/null
+++ b/src/math/riscv32/copysign.s
@@ -0,0 +1,5 @@ 
+.global copysign
+.type   copysign, %function
+copysign:
+        fsgnj.d fa0, fa0, fa1
+        ret
diff --git a/src/math/riscv32/copysignf.s b/src/math/riscv32/copysignf.s
new file mode 100644
index 0000000..fe36f90
--- /dev/null
+++ b/src/math/riscv32/copysignf.s
@@ -0,0 +1,5 @@ 
+.global copysignf
+.type   copysignf, %function
+copysignf:
+        fsgnj.s fa0, fa0, fa1
+        ret
diff --git a/src/math/riscv32/fabs.s b/src/math/riscv32/fabs.s
new file mode 100644
index 0000000..27def33
--- /dev/null
+++ b/src/math/riscv32/fabs.s
@@ -0,0 +1,5 @@ 
+.global fabs
+.type   fabs, %function
+fabs:
+        fabs.d fa0, fa0
+        ret
diff --git a/src/math/riscv32/fabsf.s b/src/math/riscv32/fabsf.s
new file mode 100644
index 0000000..8e0b9d6
--- /dev/null
+++ b/src/math/riscv32/fabsf.s
@@ -0,0 +1,5 @@ 
+.global fabsf
+.type   fabsf, %function
+fabsf:
+        fabs.s fa0, fa0
+        ret
diff --git a/src/math/riscv32/fma.s b/src/math/riscv32/fma.s
new file mode 100644
index 0000000..17e1d13
--- /dev/null
+++ b/src/math/riscv32/fma.s
@@ -0,0 +1,5 @@ 
+.global fma
+.type   fma, %function
+fma:
+        fmadd.d fa0, fa0, fa1, fa2
+        ret
diff --git a/src/math/riscv32/fmaf.s b/src/math/riscv32/fmaf.s
new file mode 100644
index 0000000..cfe1710
--- /dev/null
+++ b/src/math/riscv32/fmaf.s
@@ -0,0 +1,5 @@ 
+.global fmaf
+.type   fmaf, %function
+fmaf:
+        fmadd.s fa0, fa0, fa1, fa2
+        ret
diff --git a/src/math/riscv32/fmax.s b/src/math/riscv32/fmax.s
new file mode 100644
index 0000000..40655d3
--- /dev/null
+++ b/src/math/riscv32/fmax.s
@@ -0,0 +1,5 @@ 
+.global fmax
+.type   fmax, %function
+fmax:
+        fmax.d fa0, fa0, fa1
+        ret
diff --git a/src/math/riscv32/fmaxf.s b/src/math/riscv32/fmaxf.s
new file mode 100644
index 0000000..490b6e9
--- /dev/null
+++ b/src/math/riscv32/fmaxf.s
@@ -0,0 +1,5 @@ 
+.global fmaxf
+.type   fmaxf, %function
+fmaxf:
+        fmax.s fa0, fa0, fa1
+        ret
diff --git a/src/math/riscv32/fmin.s b/src/math/riscv32/fmin.s
new file mode 100644
index 0000000..97f72e0
--- /dev/null
+++ b/src/math/riscv32/fmin.s
@@ -0,0 +1,5 @@ 
+.global fmin
+.type   fmin, %function
+fmin:
+        fmin.d fa0, fa0, fa1
+        ret
diff --git a/src/math/riscv32/fminf.s b/src/math/riscv32/fminf.s
new file mode 100644
index 0000000..4f8e55e
--- /dev/null
+++ b/src/math/riscv32/fminf.s
@@ -0,0 +1,5 @@ 
+.global fminf
+.type   fminf, %function
+fminf:
+        fmin.s fa0, fa0, fa1
+        ret
diff --git a/src/math/riscv32/sqrt.s b/src/math/riscv32/sqrt.s
new file mode 100644
index 0000000..a4c8b3e
--- /dev/null
+++ b/src/math/riscv32/sqrt.s
@@ -0,0 +1,5 @@ 
+.global sqrt
+.type   sqrt, %function
+sqrt:
+        fsqrt.d fa0, fa0
+        ret
diff --git a/src/math/riscv32/sqrtf.s b/src/math/riscv32/sqrtf.s
new file mode 100644
index 0000000..ff7abcf
--- /dev/null
+++ b/src/math/riscv32/sqrtf.s
@@ -0,0 +1,5 @@ 
+.global sqrtf
+.type   sqrtf, %function
+sqrtf:
+        fsqrt.s fa0, fa0
+        ret
diff --git a/src/math/riscv64/copysign.s b/src/math/riscv64/copysign.s
new file mode 100644
index 0000000..81afa8b
--- /dev/null
+++ b/src/math/riscv64/copysign.s
@@ -0,0 +1,5 @@ 
+.global copysign
+.type   copysign, %function
+copysign:
+        fsgnj.d fa0, fa0, fa1
+        ret
diff --git a/src/math/riscv64/copysignf.s b/src/math/riscv64/copysignf.s
new file mode 100644
index 0000000..fe36f90
--- /dev/null
+++ b/src/math/riscv64/copysignf.s
@@ -0,0 +1,5 @@ 
+.global copysignf
+.type   copysignf, %function
+copysignf:
+        fsgnj.s fa0, fa0, fa1
+        ret
diff --git a/src/math/riscv64/fabs.s b/src/math/riscv64/fabs.s
new file mode 100644
index 0000000..27def33
--- /dev/null
+++ b/src/math/riscv64/fabs.s
@@ -0,0 +1,5 @@ 
+.global fabs
+.type   fabs, %function
+fabs:
+        fabs.d fa0, fa0
+        ret
diff --git a/src/math/riscv64/fabsf.s b/src/math/riscv64/fabsf.s
new file mode 100644
index 0000000..8e0b9d6
--- /dev/null
+++ b/src/math/riscv64/fabsf.s
@@ -0,0 +1,5 @@ 
+.global fabsf
+.type   fabsf, %function
+fabsf:
+        fabs.s fa0, fa0
+        ret
diff --git a/src/math/riscv64/fma.s b/src/math/riscv64/fma.s
new file mode 100644
index 0000000..17e1d13
--- /dev/null
+++ b/src/math/riscv64/fma.s
@@ -0,0 +1,5 @@ 
+.global fma
+.type   fma, %function
+fma:
+        fmadd.d fa0, fa0, fa1, fa2
+        ret
diff --git a/src/math/riscv64/fmaf.s b/src/math/riscv64/fmaf.s
new file mode 100644
index 0000000..cfe1710
--- /dev/null
+++ b/src/math/riscv64/fmaf.s
@@ -0,0 +1,5 @@ 
+.global fmaf
+.type   fmaf, %function
+fmaf:
+        fmadd.s fa0, fa0, fa1, fa2
+        ret
diff --git a/src/math/riscv64/fmax.s b/src/math/riscv64/fmax.s
new file mode 100644
index 0000000..40655d3
--- /dev/null
+++ b/src/math/riscv64/fmax.s
@@ -0,0 +1,5 @@ 
+.global fmax
+.type   fmax, %function
+fmax:
+        fmax.d fa0, fa0, fa1
+        ret
diff --git a/src/math/riscv64/fmaxf.s b/src/math/riscv64/fmaxf.s
new file mode 100644
index 0000000..490b6e9
--- /dev/null
+++ b/src/math/riscv64/fmaxf.s
@@ -0,0 +1,5 @@ 
+.global fmaxf
+.type   fmaxf, %function
+fmaxf:
+        fmax.s fa0, fa0, fa1
+        ret
diff --git a/src/math/riscv64/fmin.s b/src/math/riscv64/fmin.s
new file mode 100644
index 0000000..97f72e0
--- /dev/null
+++ b/src/math/riscv64/fmin.s
@@ -0,0 +1,5 @@ 
+.global fmin
+.type   fmin, %function
+fmin:
+        fmin.d fa0, fa0, fa1
+        ret
diff --git a/src/math/riscv64/fminf.s b/src/math/riscv64/fminf.s
new file mode 100644
index 0000000..4f8e55e
--- /dev/null
+++ b/src/math/riscv64/fminf.s
@@ -0,0 +1,5 @@ 
+.global fminf
+.type   fminf, %function
+fminf:
+        fmin.s fa0, fa0, fa1
+        ret
diff --git a/src/math/riscv64/sqrt.s b/src/math/riscv64/sqrt.s
new file mode 100644
index 0000000..a4c8b3e
--- /dev/null
+++ b/src/math/riscv64/sqrt.s
@@ -0,0 +1,5 @@ 
+.global sqrt
+.type   sqrt, %function
+sqrt:
+        fsqrt.d fa0, fa0
+        ret
diff --git a/src/math/riscv64/sqrtf.s b/src/math/riscv64/sqrtf.s
new file mode 100644
index 0000000..ff7abcf
--- /dev/null
+++ b/src/math/riscv64/sqrtf.s
@@ -0,0 +1,5 @@ 
+.global sqrtf
+.type   sqrtf, %function
+sqrtf:
+        fsqrt.s fa0, fa0
+        ret
diff --git a/src/setjmp/riscv32/longjmp.S b/src/setjmp/riscv32/longjmp.S
new file mode 100644
index 0000000..fbf2439
--- /dev/null
+++ b/src/setjmp/riscv32/longjmp.S
@@ -0,0 +1,44 @@ 
+.global __longjmp
+.global _longjmp
+.global longjmp
+.type __longjmp, %function
+.type _longjmp,  %function
+.type longjmp,   %function
+__longjmp:
+_longjmp:
+longjmp:
+        lw s0,    0(a0)
+        lw s1,    4(a0)
+        lw s2,    8(a0)
+        lw s3,    12(a0)
+        lw s4,    16(a0)
+        lw s5,    20(a0)
+        lw s6,    24(a0)
+        lw s7,    28(a0)
+        lw s8,    32(a0)
+        lw s9,    36(a0)
+        lw s10,   40(a0)
+        lw s11,   44(a0)
+        lw sp,    48(a0)
+        lw ra,    52(a0)
+
+#ifndef __riscv_soft_float
+        fld fs0,  56(a0)
+        fld fs1,  64(a0)
+        fld fs2,  72(a0)
+        fld fs3,  80(a0)
+        fld fs3,  88(a0)
+        fld fs4,  96(a0)
+        fld fs5,  104(a0)
+        fld fs6,  112(a0)
+        fld fs7,  120(a0)
+        fld fs8,  128(a0)
+        fld fs9,  136(a0)
+        fld fs10, 144(a0)
+        fld fs11, 152(a0)
+#endif
+
+        mv a0, a1
+        bnez a1, 1f
+        li a0, 1
+1:      ret
diff --git a/src/setjmp/riscv32/setjmp.S b/src/setjmp/riscv32/setjmp.S
new file mode 100644
index 0000000..14d5414
--- /dev/null
+++ b/src/setjmp/riscv32/setjmp.S
@@ -0,0 +1,42 @@ 
+.global __setjmp
+.global _setjmp
+.global setjmp
+.type __setjmp, %function
+.type _setjmp,  %function
+.type setjmp,   %function
+__setjmp:
+_setjmp:
+setjmp:
+        sw s0,    0(a0)
+        sw s1,    4(a0)
+        sw s2,    8(a0)
+        sw s3,    12(a0)
+        sw s4,    16(a0)
+        sw s5,    20(a0)
+        sw s6,    24(a0)
+        sw s7,    28(a0)
+        sw s8,    32(a0)
+        sw s9,    36(a0)
+        sw s10,   40(a0)
+        sw s11,   44(a0)
+        sw sp,    48(a0)
+        sw ra,    52(a0)
+
+#ifndef __riscv_soft_float
+        fsd fs0,  56(a0)
+        fsd fs1,  64(a0)
+        fsd fs2,  72(a0)
+        fsd fs3,  80(a0)
+        fsd fs3,  88(a0)
+        fsd fs4,  96(a0)
+        fsd fs5,  104(a0)
+        fsd fs6,  112(a0)
+        fsd fs7,  120(a0)
+        fsd fs8,  128(a0)
+        fsd fs9,  136(a0)
+        fsd fs10, 144(a0)
+        fsd fs11, 152(a0)
+#endif
+
+        li a0, 0
+        ret
diff --git a/src/setjmp/riscv64/longjmp.S b/src/setjmp/riscv64/longjmp.S
new file mode 100644
index 0000000..d87a1af
--- /dev/null
+++ b/src/setjmp/riscv64/longjmp.S
@@ -0,0 +1,44 @@ 
+.global __longjmp
+.global _longjmp
+.global longjmp
+.type __longjmp, %function
+.type _longjmp,  %function
+.type longjmp,   %function
+__longjmp:
+_longjmp:
+longjmp:
+        ld s0,    0(a0)
+        ld s1,    8(a0)
+        ld s2,    16(a0)
+        ld s3,    24(a0)
+        ld s4,    32(a0)
+        ld s5,    40(a0)
+        ld s6,    48(a0)
+        ld s7,    56(a0)
+        ld s8,    64(a0)
+        ld s9,    72(a0)
+        ld s10,   80(a0)
+        ld s11,   88(a0)
+        ld sp,    96(a0)
+        ld ra,    104(a0)
+
+#ifndef __riscv_soft_float
+        fld fs0,  112(a0)
+        fld fs1,  120(a0)
+        fld fs2,  128(a0)
+        fld fs3,  136(a0)
+        fld fs3,  144(a0)
+        fld fs4,  152(a0)
+        fld fs5,  160(a0)
+        fld fs6,  168(a0)
+        fld fs7,  176(a0)
+        fld fs8,  184(a0)
+        fld fs9,  192(a0)
+        fld fs10, 200(a0)
+        fld fs11, 208(a0)
+#endif
+
+        mv a0, a1
+        bnez a1, 1f
+        li a0, 1
+1:      ret
diff --git a/src/setjmp/riscv64/setjmp.S b/src/setjmp/riscv64/setjmp.S
new file mode 100644
index 0000000..abc05aa
--- /dev/null
+++ b/src/setjmp/riscv64/setjmp.S
@@ -0,0 +1,42 @@ 
+.global __setjmp
+.global _setjmp
+.global setjmp
+.type __setjmp, %function
+.type _setjmp,  %function
+.type setjmp,   %function
+__setjmp:
+_setjmp:
+setjmp:
+        sd s0,    0(a0)
+        sd s1,    8(a0)
+        sd s2,    16(a0)
+        sd s3,    24(a0)
+        sd s4,    32(a0)
+        sd s5,    40(a0)
+        sd s6,    48(a0)
+        sd s7,    56(a0)
+        sd s8,    64(a0)
+        sd s9,    72(a0)
+        sd s10,   80(a0)
+        sd s11,   88(a0)
+        sd sp,    96(a0)
+        sd ra,    104(a0)
+
+#ifndef __riscv_soft_float
+        fsd fs0,  112(a0)
+        fsd fs1,  120(a0)
+        fsd fs2,  128(a0)
+        fsd fs3,  136(a0)
+        fsd fs3,  144(a0)
+        fsd fs4,  152(a0)
+        fsd fs5,  160(a0)
+        fsd fs6,  168(a0)
+        fsd fs7,  176(a0)
+        fsd fs8,  184(a0)
+        fsd fs9,  192(a0)
+        fsd fs10, 200(a0)
+        fsd fs11, 208(a0)
+#endif
+
+        li a0, 0
+        ret
diff --git a/src/signal/riscv32/restore.s b/src/signal/riscv32/restore.s
new file mode 100644
index 0000000..732736d
--- /dev/null
+++ b/src/signal/riscv32/restore.s
@@ -0,0 +1,8 @@ 
+.global __restore
+.type __restore, %function
+__restore:
+.global __restore_rt
+.type __restore_rt, %function
+__restore_rt:
+	li a7, 139 # SYS_rt_sigreturn
+	scall
diff --git a/src/signal/riscv32/sigsetjmp.s b/src/signal/riscv32/sigsetjmp.s
new file mode 100644
index 0000000..7e4cb1f
--- /dev/null
+++ b/src/signal/riscv32/sigsetjmp.s
@@ -0,0 +1,21 @@ 
+.global sigsetjmp
+.global __sigsetjmp
+.type sigsetjmp, %function
+.type __sigsetjmp, %function
+sigsetjmp:
+__sigsetjmp:
+        beqz a1, setjmp
+
+        sw ra, 160(a0)
+        sw s0, 164(a0)
+        mv s0, a0
+
+        jal setjmp
+
+        mv a1, a0
+        mv a0, s0
+        lw s0, 164(a0)
+        lw ra, 160(a0)
+
+.hidden __sigsetjmp_tail
+        j __sigsetjmp_tail
diff --git a/src/signal/riscv64/restore.s b/src/signal/riscv64/restore.s
new file mode 100644
index 0000000..732736d
--- /dev/null
+++ b/src/signal/riscv64/restore.s
@@ -0,0 +1,8 @@ 
+.global __restore
+.type __restore, %function
+__restore:
+.global __restore_rt
+.type __restore_rt, %function
+__restore_rt:
+	li a7, 139 # SYS_rt_sigreturn
+	scall
diff --git a/src/signal/riscv64/sigsetjmp.s b/src/signal/riscv64/sigsetjmp.s
new file mode 100644
index 0000000..9ed9500
--- /dev/null
+++ b/src/signal/riscv64/sigsetjmp.s
@@ -0,0 +1,21 @@ 
+.global sigsetjmp
+.global __sigsetjmp
+.type sigsetjmp, %function
+.type __sigsetjmp, %function
+sigsetjmp:
+__sigsetjmp:
+        beqz a1, setjmp
+
+        sd ra, 216(a0)
+        sd s0, 224(a0)
+        mv s0, a0
+
+        jal setjmp
+
+        mv a1, a0
+        mv a0, s0
+        ld s0, 224(a0)
+        ld ra, 216(a0)
+
+.hidden __sigsetjmp_tail
+        j __sigsetjmp_tail
diff --git a/src/thread/riscv32/__set_thread_area.s b/src/thread/riscv32/__set_thread_area.s
new file mode 100644
index 0000000..828154d
--- /dev/null
+++ b/src/thread/riscv32/__set_thread_area.s
@@ -0,0 +1,6 @@ 
+.global __set_thread_area
+.type   __set_thread_area, %function
+__set_thread_area:
+	mv tp, a0
+	li a0, 0
+	ret
diff --git a/src/thread/riscv32/__unmapself.s b/src/thread/riscv32/__unmapself.s
new file mode 100644
index 0000000..98e7881
--- /dev/null
+++ b/src/thread/riscv32/__unmapself.s
@@ -0,0 +1,7 @@ 
+.global __unmapself
+.type __unmapself, %function
+__unmapself:
+       li a7, 215 # SYS_munmap
+       scall
+       li a7, 93  # SYS_exit
+       scall
diff --git a/src/thread/riscv32/clone.s b/src/thread/riscv32/clone.s
new file mode 100644
index 0000000..30126d2
--- /dev/null
+++ b/src/thread/riscv32/clone.s
@@ -0,0 +1,34 @@ 
+# __clone(func, stack, flags, arg, ptid, tls, ctid)
+#           a0,    a1,    a2,  a3,   a4,  a5,   a6
+
+# syscall(SYS_clone, flags, stack, ptid, tls, ctid)
+#                a7     a0,    a1,   a2,  a3,   a4
+
+.global __clone
+.type  __clone, %function
+__clone:
+        # Save func and arg to stack
+        addi a1, a1, -16
+        sw a0, 0(a1)
+        sw a3, 4(a1)
+
+        # Call SYS_clone
+        mv a0, a2
+        mv a2, a4
+        mv a3, a5
+        mv a4, a6
+        li a7, 220 # SYS_clone
+        scall
+
+        beqz a0, 1f
+        # Parent
+        ret
+
+        # Child
+1:      lw a1, 0(sp)
+        lw a0, 4(sp)
+        jalr a1
+
+        # Exit
+        li a7, 93 # SYS_exit
+        scall
diff --git a/src/thread/riscv32/syscall_cp.s b/src/thread/riscv32/syscall_cp.s
new file mode 100644
index 0000000..71bf6d3
--- /dev/null
+++ b/src/thread/riscv32/syscall_cp.s
@@ -0,0 +1,29 @@ 
+.global __cp_begin
+.hidden __cp_begin
+.global __cp_end
+.hidden __cp_end
+.global __cp_cancel
+.hidden __cp_cancel
+.hidden __cancel
+.global __syscall_cp_asm
+.hidden __syscall_cp_asm
+.type __syscall_cp_asm, %function
+__syscall_cp_asm:
+__cp_begin:
+        lw t0, 0(a0)
+        bnez t0, __cp_cancel
+
+        mv t0, a1
+        mv a0, a2
+        mv a1, a3
+        mv a2, a4
+        mv a3, a5
+        mv a4, a6
+        mv a5, a7
+        lw a6, 0(sp)
+        mv a7, t0
+        scall
+__cp_cancel:
+        ret
+__cp_end:
+        j __cancel
diff --git a/src/thread/riscv64/__set_thread_area.s b/src/thread/riscv64/__set_thread_area.s
new file mode 100644
index 0000000..828154d
--- /dev/null
+++ b/src/thread/riscv64/__set_thread_area.s
@@ -0,0 +1,6 @@ 
+.global __set_thread_area
+.type   __set_thread_area, %function
+__set_thread_area:
+	mv tp, a0
+	li a0, 0
+	ret
diff --git a/src/thread/riscv64/__unmapself.s b/src/thread/riscv64/__unmapself.s
new file mode 100644
index 0000000..98e7881
--- /dev/null
+++ b/src/thread/riscv64/__unmapself.s
@@ -0,0 +1,7 @@ 
+.global __unmapself
+.type __unmapself, %function
+__unmapself:
+       li a7, 215 # SYS_munmap
+       scall
+       li a7, 93  # SYS_exit
+       scall
diff --git a/src/thread/riscv64/clone.s b/src/thread/riscv64/clone.s
new file mode 100644
index 0000000..b2d4f02
--- /dev/null
+++ b/src/thread/riscv64/clone.s
@@ -0,0 +1,34 @@ 
+# __clone(func, stack, flags, arg, ptid, tls, ctid)
+#           a0,    a1,    a2,  a3,   a4,  a5,   a6
+
+# syscall(SYS_clone, flags, stack, ptid, tls, ctid)
+#                a7     a0,    a1,   a2,  a3,   a4
+
+.global __clone
+.type  __clone, %function
+__clone:
+        # Save func and arg to stack
+        addi a1, a1, -16
+        sd a0, 0(a1)
+        sd a3, 8(a1)
+
+        # Call SYS_clone
+        mv a0, a2
+        mv a2, a4
+        mv a3, a5
+        mv a4, a6
+        li a7, 220 # SYS_clone
+        scall
+
+        beqz a0, 1f
+        # Parent
+        ret
+
+        # Child
+1:      ld a1, 0(sp)
+        ld a0, 8(sp)
+        jalr a1
+
+        # Exit
+        li a7, 93 # SYS_exit
+        scall
diff --git a/src/thread/riscv64/syscall_cp.s b/src/thread/riscv64/syscall_cp.s
new file mode 100644
index 0000000..c745b32
--- /dev/null
+++ b/src/thread/riscv64/syscall_cp.s
@@ -0,0 +1,29 @@ 
+.global __cp_begin
+.hidden __cp_begin
+.global __cp_end
+.hidden __cp_end
+.global __cp_cancel
+.hidden __cp_cancel
+.hidden __cancel
+.global __syscall_cp_asm
+.hidden __syscall_cp_asm
+.type __syscall_cp_asm, %function
+__syscall_cp_asm:
+__cp_begin:
+        ld t0, 0(a0)
+        bnez t0, __cp_cancel
+
+        mv t0, a1
+        mv a0, a2
+        mv a1, a3
+        mv a2, a4
+        mv a3, a5
+        mv a4, a6
+        mv a5, a7
+        ld a6, 0(sp)
+        mv a7, t0
+        scall
+__cp_cancel:
+        ret
+__cp_end:
+        j __cancel

Comments

Rich Felker Sept. 28, 2018, 2:46 a.m.
On Thu, Sep 27, 2018 at 10:24:04PM -0400, Rich Felker wrote:
> Pulled from here:
> https://github.com/riscv/riscv-musl/commit/6a4f4a9c774608add4b02f95322518bd2f5f51ee
> 
> Attached for review.

Review inline below:

> diff --git a/arch/riscv32/atomic_arch.h b/arch/riscv32/atomic_arch.h
> new file mode 100644
> index 0000000..93c89cc
> --- /dev/null
> +++ b/arch/riscv32/atomic_arch.h
> @@ -0,0 +1,35 @@
> +#define a_barrier a_barrier
> +static inline void a_barrier()
> +{
> +	__asm__ __volatile__ ("fence rw,rw" : : : "memory");
> +}
> +
> +#define a_ll a_ll
> +static inline int a_ll(volatile int *p)
> +{
> +	int v;
> +	__asm__ __volatile__ ("lr.w %0, (%1)" : "=&r"(v) : "r"(p));
> +	return v;
> +}
> +
> +#define a_sc a_sc
> +static inline int a_sc(volatile int *p, int v)
> +{
> +	int r;
> +	__asm__ __volatile__ ("sc.w %0, %2, (%1)" : "=&r"(r) : "r"(p), "r"(v) : "memory");
> +	return !r;
> +}
> +
> +#define a_cas a_cas
> +static inline int a_cas(volatile int *p, int t, int s)
> +{
> +	int old, tmp;
> +	__asm__("1:  lr.w    %0, %2      \n"
> +		"    bne     %0, %3, 1f  \n"
> +		"    sc.w    %1, %4, %2  \n"
> +		"    bnez    %1, 1b      \n"
> +		"1:                      \n"
> +		: "=&r"(old), "+r"(tmp), "+A"(*p)
> +		: "r"(t), "r"(s));
> +	return old;
> +}

Why are both a_ll/a_sc and a_cas defined, and why is a_cas missing
barriers? Normally if a_ll/a_sc/a_barrier are defined, the top-level
atomic.h should be allowed to generate a_cas in terms of them.

> diff --git a/arch/riscv32/bits/signal.h b/arch/riscv32/bits/signal.h
> new file mode 100644
> index 0000000..8b992cc
> --- /dev/null
> +++ b/arch/riscv32/bits/signal.h
> @@ -0,0 +1,113 @@
> +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
> + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
> +
> +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
> +# define MINSIGSTKSZ 2048
> +# define SIGSTKSZ 8192
> +#endif
> +
> +/* gregs[0] holds the program counter. */
> +
> +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
> +typedef unsigned long greg_t;
> +typedef unsigned long gregset_t[32];
> +
> +struct __riscv_f_ext_state {
> +	unsigned int f[32];
> +	unsigned int fcsr;
> +};
> +
> +struct __riscv_d_ext_state {
> +	unsigned long long f[32];
> +	unsigned int fcsr;
> +};
> +
> +struct __riscv_q_ext_state {
> +	unsigned long long f[64] __attribute__((aligned(16)));
> +	unsigned int fcsr;
> +	unsigned int reserved[3];
> +};
> +
> +union __riscv_fp_state {
> +	struct __riscv_f_ext_state f;
> +	struct __riscv_d_ext_state d;
> +	struct __riscv_q_ext_state q;
> +};
> +
> +typedef union __riscv_fp_state fpregset_t;
> +
> +typedef struct sigcontext {
> +	gregset_t gregs;
> +	fpregset_t fpregs;
> +} mcontext_t;
> +
> +#else
> +typedef struct {
> +	unsigned long gregs[32];
> +	unsigned long long fpregs[66];
> +} mcontext_t;
> +#endif

In the namespace-safe version of mcontext_t, the names gregs and
fpregs are not valid here. They would need to be __-prefixed or in
some other reserved namespace.

> +struct sigaltstack {
> +	void *ss_sp;
> +	int ss_flags;
> +	size_t ss_size;
> +};
> +
> +typedef struct __ucontext
> +{
> +	unsigned long uc_flags;
> +	struct __ucontext *uc_link;
> +	stack_t uc_stack;
> +	sigset_t uc_sigmask;
> +	char __unused[1024 / 8 - sizeof(sigset_t)];

This is an invalid array of size zero and should just be removed.

> +	mcontext_t uc_mcontext;
> +} ucontext_t;

...

> diff --git a/arch/riscv32/crt_arch.h b/arch/riscv32/crt_arch.h
> new file mode 100644
> index 0000000..65187e1
> --- /dev/null
> +++ b/arch/riscv32/crt_arch.h
> @@ -0,0 +1,18 @@
> +__asm__(
> +".text\n"
> +".global " START "\n"
> +".type " START ",%function\n"
> +START ":\n"
> +".weak __global_pointer$\n"
> +".hidden __global_pointer$\n\t"
> +".option push\n"
> +".option norelax\n\t"
> +"lla gp, __global_pointer$\n"
> +".option pop\n\t"
> +"mv a0, sp\n"
> +".weak _DYNAMIC\n"
> +".hidden _DYNAMIC\n\t"
> +"lla a1, _DYNAMIC\n\t"
> +"andi sp, sp, -16\n\t"
> +"jal " START "_c"
> +);
> diff --git a/arch/riscv32/pthread_arch.h b/arch/riscv32/pthread_arch.h
> new file mode 100644
> index 0000000..feffaa4
> --- /dev/null
> +++ b/arch/riscv32/pthread_arch.h
> @@ -0,0 +1,12 @@
> +static inline struct pthread *__pthread_self()
> +{
> +	char *tp;
> +	__asm__ __volatile__("mv %0, tp" : "=r"(tp));
> +	return (void *)(tp - sizeof(struct pthread));
> +}
> +
> +#define TLS_ABOVE_TP
> +#define GAP_ABOVE_TP 0
> +#define TP_ADJ(p) ((char *)p + sizeof(struct pthread))
> +
> +#define MC_PC gregs[0]
> diff --git a/arch/riscv32/reloc.h b/arch/riscv32/reloc.h
> new file mode 100644
> index 0000000..d057bbe
> --- /dev/null
> +++ b/arch/riscv32/reloc.h
> @@ -0,0 +1,27 @@
> +#if defined __riscv_float_abi_soft
> +#define RISCV_FP_SUFFIX "-sf"
> +#elif defined __riscv_float_abi_single
> +#define RISCV_FP_SUFFIX "-sp"
> +#elif defined __riscv_float_abi_double
> +#define RISCV_FP_SUFFIX ""
> +#endif
> +
> +#define RISCV_LDSO_HELPER(x) "riscv" #x
> +#define RISCV_LDSO(x) RISCV_LDSO_HELPER(x)
> +
> +#define LDSO_ARCH RISCV_LDSO(__riscv_xlen) RISCV_FP_SUFFIX

Elsewhere it looks like little/big endian are both options, but I see
no endian variant here. If so this needs to be fixed.

Also what is __riscv_xlen? A predefined macro that expands to 32 or
64? Since this file is just for 32-bit it should just be hard-coded
rather than assuming a macro would expand to the token 32 and not
(31+1) or some other expression equal to 32, I think.

> diff --git a/arch/riscv32/syscall_arch.h b/arch/riscv32/syscall_arch.h
> new file mode 100644
> index 0000000..bc60d1f
> --- /dev/null
> +++ b/arch/riscv32/syscall_arch.h
> @@ -0,0 +1,78 @@
> +#define __SYSCALL_LL_E(x) \
> +((union { long long ll; long l[2]; }){ .ll = x }).l[0], \
> +((union { long long ll; long l[2]; }){ .ll = x }).l[1]
> +#define __SYSCALL_LL_O(x) 0, __SYSCALL_LL_E((x))
> +
> +#define __asm_syscall(...) \
> +	__asm__ __volatile__ ("scall\n\t" \
> +	: "+r"(a0) : __VA_ARGS__ : "memory"); \
> +	return a0; \
> +
> +static inline long __syscall0(long n)
> +{
> +	register long a7 __asm__("a7") = n;
> +	register long a0 __asm__("a0");
> +	__asm_syscall("r"(a7))
> +}
> +
> +static inline long __syscall1(long n, long a)
> +{
> +	register long a7 __asm__("a7") = n;
> +	register long a0 __asm__("a0") = a;
> +	__asm_syscall("r"(a7), "0"(a0))
> +}
> +
> +static inline long __syscall2(long n, long a, long b)
> +{
> +	register long a7 __asm__("a7") = n;
> +	register long a0 __asm__("a0") = a;
> +	register long a1 __asm__("a1") = b;
> +	__asm_syscall("r"(a7), "0"(a0), "r"(a1))
> +}
> +
> +static inline long __syscall3(long n, long a, long b, long c)
> +{
> +	register long a7 __asm__("a7") = n;
> +	register long a0 __asm__("a0") = a;
> +	register long a1 __asm__("a1") = b;
> +	register long a2 __asm__("a2") = c;
> +	__asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2))
> +}
> +
> +static inline long __syscall4(long n, long a, long b, long c, long d)
> +{
> +	register long a7 __asm__("a7") = n;
> +	register long a0 __asm__("a0") = a;
> +	register long a1 __asm__("a1") = b;
> +	register long a2 __asm__("a2") = c;
> +	register long a3 __asm__("a3") = d;
> +	__asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3))
> +}
> +
> +static inline long __syscall5(long n, long a, long b, long c, long d, long e)
> +{
> +	register long a7 __asm__("a7") = n;
> +	register long a0 __asm__("a0") = a;
> +	register long a1 __asm__("a1") = b;
> +	register long a2 __asm__("a2") = c;
> +	register long a3 __asm__("a3") = d;
> +	register long a4 __asm__("a4") = e;
> +	__asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4))
> +}
> +
> +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
> +{
> +	register long a7 __asm__("a7") = n;
> +	register long a0 __asm__("a0") = a;
> +	register long a1 __asm__("a1") = b;
> +	register long a2 __asm__("a2") = c;
> +	register long a3 __asm__("a3") = d;
> +	register long a4 __asm__("a4") = e;
> +	register long a5 __asm__("a5") = f;
> +	__asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5))
> +}
> +
> +#define VDSO_USEFUL
> +/* We don't have a clock_gettime function.
> +#define VDSO_CGT_SYM "__vdso_clock_gettime"
> +#define VDSO_CGT_VER "LINUX_2.6" */

In that case VDSO_USEFUL might as well also be omitted for now.

> diff --git a/arch/riscv64/atomic_arch.h b/arch/riscv64/atomic_arch.h
> new file mode 100644
> index 0000000..018c7fd
> --- /dev/null
> +++ b/arch/riscv64/atomic_arch.h
> @@ -0,0 +1,66 @@
> +#define a_barrier a_barrier
> +static inline void a_barrier()
> +{
> +	__asm__ __volatile__ ("fence rw,rw" : : : "memory");
> +}
> +
> +#define a_ll a_ll
> +static inline int a_ll(volatile int *p)
> +{
> +	int v;
> +	__asm__ __volatile__ ("lr.w %0, %1" : "=&r"(v), "+A"(*p));
> +	return v;
> +}
> +
> +#define a_sc a_sc
> +static inline int a_sc(volatile int *p, int v)
> +{
> +	int r;
> +	__asm__ __volatile__ ("sc.w %0, %2, %1" : "=&r"(r), "+A"(*p) : "r"(v) : "memory");
> +return !r;
> +}
> +
> +#define a_cas a_cas
> +static inline int a_cas(volatile int *p, int t, int s)
> +{
> +	int old, tmp;
> +	__asm__("1:  lr.w    %0, %2      \n"
> +		"    bne     %0, %3, 1f  \n"
> +		"    sc.w    %1, %4, %2  \n"
> +		"    bnez    %1, 1b      \n"
> +		"1:                      \n"
> +		: "=&r"(old), "+r"(tmp), "+A"(*p)
> +		: "r"(t), "r"(s));
> +	return old;
> +}
> +
> +#define a_ll_p a_ll_p
> +static inline void *a_ll_p(volatile void *p)
> +{
> +	void *v;
> +	__asm__ __volatile__ ("lr.d %0, %1" : "=&r"(v), "+A"(*(long *)p));
> +	return v;
> +}
> +
> +#define a_sc_p a_sc_p
> +static inline int a_sc_p(volatile int *p, void *v)
> +{
> +	int r;
> +	__asm__ __volatile__ ("sc.d %0, %2, %1" : "=&r"(r), "+A"(*(long *)p) : "r"(v) : "memory");
> +	return !r;
> +}
> +
> +#define a_cas_p a_cas_p
> +static inline void *a_cas_p(volatile void *p, void *t, void *s)
> +{
> +	void *old;
> +	int tmp;
> +	__asm__("1:  lr.d    %0, %2      \n"
> +		"    bne     %0, %3, 1f  \n"
> +		"    sc.d    %1, %4, %2  \n"
> +		"    bnez    %1, 1b      \n"
> +		"1:                      \n"
> +		: "=&r"(old), "+r"(tmp), "+A"(*(long *)p)
> +		: "r"(t), "r"(s));
> +	return old;
> +}

Same comments about cas vs ll/sc, and lack of barrier, as 32-bit version.

> diff --git a/arch/riscv64/bits/signal.h b/arch/riscv64/bits/signal.h
> new file mode 100644
> index 0000000..8b992cc
> --- /dev/null
> +++ b/arch/riscv64/bits/signal.h
> @@ -0,0 +1,113 @@
> +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
> + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
> +
> +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
> +# define MINSIGSTKSZ 2048
> +# define SIGSTKSZ 8192
> +#endif
> +
> +/* gregs[0] holds the program counter. */
> +
> +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
> +typedef unsigned long greg_t;
> +typedef unsigned long gregset_t[32];
> +
> +struct __riscv_f_ext_state {
> +	unsigned int f[32];
> +	unsigned int fcsr;
> +};
> +
> +struct __riscv_d_ext_state {
> +	unsigned long long f[32];
> +	unsigned int fcsr;
> +};
> +
> +struct __riscv_q_ext_state {
> +	unsigned long long f[64] __attribute__((aligned(16)));
> +	unsigned int fcsr;
> +	unsigned int reserved[3];
> +};
> +
> +union __riscv_fp_state {
> +	struct __riscv_f_ext_state f;
> +	struct __riscv_d_ext_state d;
> +	struct __riscv_q_ext_state q;
> +};
> +
> +typedef union __riscv_fp_state fpregset_t;
> +
> +typedef struct sigcontext {
> +	gregset_t gregs;
> +	fpregset_t fpregs;
> +} mcontext_t;
> +
> +#else
> +typedef struct {
> +	unsigned long gregs[32];
> +	unsigned long long fpregs[66];
> +} mcontext_t;
> +#endif
> +
> +struct sigaltstack {
> +	void *ss_sp;
> +	int ss_flags;
> +	size_t ss_size;
> +};
> +
> +typedef struct __ucontext
> +{
> +	unsigned long uc_flags;
> +	struct __ucontext *uc_link;
> +	stack_t uc_stack;
> +	sigset_t uc_sigmask;
> +	char __unused[1024 / 8 - sizeof(sigset_t)];
> +	mcontext_t uc_mcontext;
> +} ucontext_t;

Same issues here as 32-bit.

> diff --git a/arch/riscv64/reloc.h b/arch/riscv64/reloc.h
> new file mode 100644
> index 0000000..8bd90dd
> --- /dev/null
> +++ b/arch/riscv64/reloc.h
> @@ -0,0 +1,27 @@
> +#if defined __riscv_float_abi_soft
> +#define RISCV_FP_SUFFIX "-sf"
> +#elif defined __riscv_float_abi_single
> +#define RISCV_FP_SUFFIX "-sp"
> +#elif defined __riscv_float_abi_double
> +#define RISCV_FP_SUFFIX ""
> +#endif
> +
> +#define RISCV_LDSO_HELPER(x) "riscv" #x
> +#define RISCV_LDSO(x) RISCV_LDSO_HELPER(x)
> +
> +#define LDSO_ARCH RISCV_LDSO(__riscv_xlen) RISCV_FP_SUFFIX

Same here.

> diff --git a/configure b/configure
> index 997e665..4d3d8b4 100755
> --- a/configure
> +++ b/configure
> @@ -322,6 +322,8 @@ microblaze*) ARCH=microblaze ;;
>  or1k*) ARCH=or1k ;;
>  powerpc64*) ARCH=powerpc64 ;;
>  powerpc*) ARCH=powerpc ;;
> +riscv64*) ARCH=riscv64 ;;
> +riscv*) ARCH=riscv32 ;;
>  sh[1-9bel-]*|sh|superh*) ARCH=sh ;;
>  s390x*) ARCH=s390x ;;
>  unknown) fail "$0: unable to detect target arch; try $0 --target=..." ;;
> @@ -640,6 +642,11 @@ trycppif __LITTLE_ENDIAN__ "$t" && SUBARCH=${SUBARCH}le
>  trycppif _SOFT_FLOAT "$t" && fail "$0: error: soft-float not supported on powerpc64"
>  fi
>  
> +if test "$ARCH" = "riscv" || test "$ARCH" = "riscv64" ; then
> +trycppif "RISCVEB || _RISCVEB || __RISCVEB || __RISCVEB__" "$t" && SUBARCH=${SUBARCH}eb

Predefined macros that violate the namespace (RISCVEB) shouldn't be
defined or observed.

> +trycppif __riscv_soft_float "$t" && SUBARCH=${SUBARCH}-sf
> +fi
> +
>  if test "$ARCH" = "sh" ; then
>  tryflag CFLAGS_AUTO -Wa,--isa=any
>  trycppif __BIG_ENDIAN__ "$t" && SUBARCH=${SUBARCH}eb
> diff --git a/crt/riscv32/crti.s b/crt/riscv32/crti.s
> new file mode 100644
> index 0000000..6916bfd
> --- /dev/null
> +++ b/crt/riscv32/crti.s
> @@ -0,0 +1,11 @@
> +.section .init
> +.global _init
> +.type _init,%function
> +_init:
> +        ret
> +
> +.section .fini
> +.global _fini
> +.type _fini,%function
> +_fini:
> +        ret
> diff --git a/crt/riscv32/crtn.s b/crt/riscv32/crtn.s
> new file mode 100644
> index 0000000..e69de29

It looks like these are not used, right?

> diff --git a/include/elf.h b/include/elf.h
> index c229735..ec2e8fd 100644
> --- a/include/elf.h
> +++ b/include/elf.h
> @@ -3164,6 +3164,62 @@ enum
>  #define R_BPF_NONE		0
>  #define R_BPF_MAP_FD		1
>  
> +#define R_RISCV_NONE            0
> +#define R_RISCV_32              1
> +#define R_RISCV_64              2
> +#define R_RISCV_RELATIVE        3
> +#define R_RISCV_COPY            4
> +#define R_RISCV_JUMP_SLOT       5
> +#define R_RISCV_TLS_DTPMOD32    6
> +#define R_RISCV_TLS_DTPMOD64    7
> +#define R_RISCV_TLS_DTPREL32    8
> +#define R_RISCV_TLS_DTPREL64    9
> +#define R_RISCV_TLS_TPREL32     10
> +#define R_RISCV_TLS_TPREL64     11
> +
> +#define R_RISCV_BRANCH          16
> +#define R_RISCV_JAL             17
> +#define R_RISCV_CALL            18
> +#define R_RISCV_CALL_PLT        19
> +#define R_RISCV_GOT_HI20        20
> +#define R_RISCV_TLS_GOT_HI20    21
> +#define R_RISCV_TLS_GD_HI20     22
> +#define R_RISCV_PCREL_HI20      23
> +#define R_RISCV_PCREL_LO12_I    24
> +#define R_RISCV_PCREL_LO12_S    25
> +#define R_RISCV_HI20            26
> +#define R_RISCV_LO12_I          27
> +#define R_RISCV_LO12_S          28
> +#define R_RISCV_TPREL_HI20      29
> +#define R_RISCV_TPREL_LO12_I    30
> +#define R_RISCV_TPREL_LO12_S    31
> +#define R_RISCV_TPREL_ADD       32
> +#define R_RISCV_ADD8            33
> +#define R_RISCV_ADD16           34
> +#define R_RISCV_ADD32           35
> +#define R_RISCV_ADD64           36
> +#define R_RISCV_SUB8            37
> +#define R_RISCV_SUB16           38
> +#define R_RISCV_SUB32           39
> +#define R_RISCV_SUB64           40
> +#define R_RISCV_GNU_VTINHERIT   41
> +#define R_RISCV_GNU_VTENTRY     42
> +#define R_RISCV_ALIGN           43
> +#define R_RISCV_RVC_BRANCH      44
> +#define R_RISCV_RVC_JUMP        45
> +#define R_RISCV_RVC_LUI         46
> +#define R_RISCV_GPREL_I         47
> +#define R_RISCV_GPREL_S         48
> +#define R_RISCV_TPREL_I         49
> +#define R_RISCV_TPREL_S         50
> +#define R_RISCV_RELAX           51
> +#define R_RISCV_SUB6            52
> +#define R_RISCV_SET6            53
> +#define R_RISCV_SET8            54
> +#define R_RISCV_SET16           55
> +#define R_RISCV_SET32           56
> +#define R_RISCV_32_PCREL        57
> +
>  #ifdef __cplusplus
>  }
>  #endif

This should be its own patch independent of the port; I can commit it
earlier.

> diff --git a/src/thread/riscv32/syscall_cp.s b/src/thread/riscv32/syscall_cp.s
> new file mode 100644
> index 0000000..71bf6d3
> --- /dev/null
> +++ b/src/thread/riscv32/syscall_cp.s
> @@ -0,0 +1,29 @@
> +.global __cp_begin
> +.hidden __cp_begin
> +.global __cp_end
> +.hidden __cp_end
> +.global __cp_cancel
> +.hidden __cp_cancel
> +.hidden __cancel
> +.global __syscall_cp_asm
> +.hidden __syscall_cp_asm
> +.type __syscall_cp_asm, %function
> +__syscall_cp_asm:
> +__cp_begin:
> +        lw t0, 0(a0)
> +        bnez t0, __cp_cancel
> +
> +        mv t0, a1
> +        mv a0, a2
> +        mv a1, a3
> +        mv a2, a4
> +        mv a3, a5
> +        mv a4, a6
> +        mv a5, a7
> +        lw a6, 0(sp)
> +        mv a7, t0
> +        scall
> +__cp_cancel:
> +        ret
> +__cp_end:
> +        j __cancel

The labels here are backwards. __cp_end must point immediately after
the syscall instruction, and __cp_end needs to jump to __cancel.

> diff --git a/src/thread/riscv64/syscall_cp.s b/src/thread/riscv64/syscall_cp.s
> new file mode 100644
> index 0000000..c745b32
> --- /dev/null
> +++ b/src/thread/riscv64/syscall_cp.s
> @@ -0,0 +1,29 @@
> +.global __cp_begin
> +.hidden __cp_begin
> +.global __cp_end
> +.hidden __cp_end
> +.global __cp_cancel
> +.hidden __cp_cancel
> +.hidden __cancel
> +.global __syscall_cp_asm
> +.hidden __syscall_cp_asm
> +.type __syscall_cp_asm, %function
> +__syscall_cp_asm:
> +__cp_begin:
> +        ld t0, 0(a0)
> +        bnez t0, __cp_cancel
> +
> +        mv t0, a1
> +        mv a0, a2
> +        mv a1, a3
> +        mv a2, a4
> +        mv a3, a5
> +        mv a4, a6
> +        mv a5, a7
> +        ld a6, 0(sp)
> +        mv a7, t0
> +        scall
> +__cp_cancel:
> +        ret
> +__cp_end:
> +        j __cancel
> -- 
> 2.10.0
> 

Likewise here.

Rich
Rich Felker Sept. 28, 2018, 2:47 a.m.
On Thu, Sep 27, 2018 at 10:24:04PM -0400, Rich Felker wrote:
> Pulled from here:
> https://github.com/riscv/riscv-musl/commit/6a4f4a9c774608add4b02f95322518bd2f5f51ee
> 
> Attached for review.

> diff --git a/arch/riscv32/bits/alltypes.h.in b/arch/riscv32/bits/alltypes.h.in
> new file mode 100644
> index 0000000..66ca18a
> --- /dev/null
> +++ b/arch/riscv32/bits/alltypes.h.in
> @@ -0,0 +1,26 @@
> +#define _Addr int
> +#define _Int64 long long
> +#define _Reg int
> +
> +TYPEDEF __builtin_va_list va_list;
> +TYPEDEF __builtin_va_list __isoc_va_list;
> +
> +#ifndef __cplusplus
> +TYPEDEF int wchar_t;
> +#endif
> +
> +TYPEDEF float float_t;
> +TYPEDEF double double_t;
> +
> +TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
> +
> +TYPEDEF long time_t;

Is riscv32 time_t really 32-bit? If so that's really disappointing,
but presumably unfixable...

Rich
Michael Clark Sept. 28, 2018, 6:33 a.m.
Hi Rich,

> On 28/09/2018, at 2:47 PM, Rich Felker <dalias@libc.org> wrote:
> 
>> On Thu, Sep 27, 2018 at 10:24:04PM -0400, Rich Felker wrote:
>> Pulled from here:
>> https://github.com/riscv/riscv-musl/commit/6a4f4a9c774608add4b02f95322518bd2f5f51ee
>> 
>> Attached for review.
> 
>> diff --git a/arch/riscv32/bits/alltypes.h.in b/arch/riscv32/bits/alltypes.h.in
>> new file mode 100644
>> index 0000000..66ca18a
>> --- /dev/null
>> +++ b/arch/riscv32/bits/alltypes.h.in
>> @@ -0,0 +1,26 @@
>> +#define _Addr int
>> +#define _Int64 long long
>> +#define _Reg int
>> +
>> +TYPEDEF __builtin_va_list va_list;
>> +TYPEDEF __builtin_va_list __isoc_va_list;
>> +
>> +#ifndef __cplusplus
>> +TYPEDEF int wchar_t;
>> +#endif
>> +
>> +TYPEDEF float float_t;
>> +TYPEDEF double double_t;
>> +
>> +TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
>> +
>> +TYPEDEF long time_t;
> 
> Is riscv32 time_t really 32-bit? If so that's really disappointing,
> but presumably unfixable...

This definitely is fixable as the riscv32 Linux ABI is not final. This is the first time a Linux libc ABI expert has looked closely at the musl port, and while riscv32 is present, all of my own testing has been performed on riscv64 Linux.

The RISC-V Glibc port currently only contains riscv64. The riscv32 ABI is still in the process of being finalised. Palmer likely knows the exact status. SiFive doesn’t have any 32-bit cores with MMUs so it hasn’t been high on the list of priorities.

In any case, now is a very good time to do some cross-checking between musl riscv32, qemu-riscv32, the glibc riscv32 port and riscv32 linux-kernel. I think we are just getting the default asm-generic in QEMU as we have not done anything special... yet...

I believe there is still an alignment issue with the stat structure in qemu-riscv32. When we last looked at this issue earlier in the year we didn’t have linux-kernel support for riscv32, as the toolchain/ABI focus this year was on finalising riscv64 in Glibc and Linux.

Debian and Fedora only have riscv64 ports and afaik riscv64 is all that is present in Glibc. Of course linux-kernel is authoritative for the ABI so we need to run tests using riscv32 Linux in full system emulation in qemu-system-riscv32; qemu-riscv32 also needs to be audited. At the time we were submitting qemu upstream we could build riscv32 kernels. This has solved and we need to get regular build and test for riscv32 and riscv64 Linux and QEMU in CI...

There is an open bug on riscv-qemu stat which we can look at now that linux-kernel has initial riscv32 support. We should write a test that prints offsetof and sizeof for the stat structure members using musl, glibc and linux headers to find out what’s happening...

I think there is still some time to nail down any remaining issues with riscv32. We definitely want 64-bit time_t and any other types that should be 64-bit should be audited now. Given the indirection through multiple levels of typedefs it’s not immediately clear without a bit of analysis.

We may do the same thing as was done with glibc and split the port up, first submitting riscv64, which is locked down.

I also had a question regarding whether we needed to #define __ARCH_WANT_STAT64 in linux/arch/riscv/include/asm/unistd.h or whether this is a legacy flag. All of the other 32-bit ports define it, but I do not know if it is necessary for a legacy free 32-bit port:

https://github.com/torvalds/linux/blob/master/arch/riscv/include/asm/unistd.h

BTW Thanks very much for the review... I’ll go through the remainder of the patch review comments and work on another revision... __riscv_xlen contains either 32 or 64 at present and is how RISC-V code distinguishes between riscv32 and riscv64. We can remove references to it from the musl riscv ports due to them not sharing code. Also, there is no official RISC-V big endian so we can remove EB. Big endian may be considered at some point, and it may well have appeared in a previous draft of the ISA manual, but at present, it is not defined in the ISA manual or toolchain, so we’ll remove it.

We’ll do some 32-bit testing... now is a good time. SiFive’s Linux board, the HiFive Unleashed, is riscv64, which likely explains the situation with riscv32.

Thanks,
Michael
Michael Clark Sept. 28, 2018, 6:49 a.m.
> On 28/09/2018, at 6:33 PM, Michael Clark <michaeljclark@mac.com> wrote:
> 
> we could build riscv32 kernels

Typo: we couldn’t build riscv32 kernels. 

We can perhaps use the musl riscv32 port as a good chance to sort out the riscv32 issues. SiFive’s Freedom Unleashed Linux SDK is riscv64 and all of my test kernels have been riscv64.

SiFive’s Freedom Everywhere riscv32 cores are no-MMU and the our riscv32 testing in QEMU has been emulating the HiFive1 board with the E-Series FE310G000 MCU.

It shouldn’t be too hard to sort out riscv32 linux. There have just been other priorities until now...
Szabolcs Nagy Sept. 28, 2018, 10:33 a.m.
* Michael Clark <michaeljclark@mac.com> [2018-09-28 18:33:18 +1200]:
> > On 28/09/2018, at 2:47 PM, Rich Felker <dalias@libc.org> wrote:
> > 
> >> On Thu, Sep 27, 2018 at 10:24:04PM -0400, Rich Felker wrote:
> >> Pulled from here:
> >> https://github.com/riscv/riscv-musl/commit/6a4f4a9c774608add4b02f95322518bd2f5f51ee
> >> 
> >> Attached for review.
> > 
> >> diff --git a/arch/riscv32/bits/alltypes.h.in b/arch/riscv32/bits/alltypes.h.in
> >> new file mode 100644
> >> index 0000000..66ca18a
> >> --- /dev/null
> >> +++ b/arch/riscv32/bits/alltypes.h.in
> >> @@ -0,0 +1,26 @@
> >> +#define _Addr int
> >> +#define _Int64 long long
> >> +#define _Reg int
> >> +
> >> +TYPEDEF __builtin_va_list va_list;
> >> +TYPEDEF __builtin_va_list __isoc_va_list;
> >> +
> >> +#ifndef __cplusplus
> >> +TYPEDEF int wchar_t;
> >> +#endif
> >> +
> >> +TYPEDEF float float_t;
> >> +TYPEDEF double double_t;
> >> +
> >> +TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
> >> +
> >> +TYPEDEF long time_t;
> > 
> > Is riscv32 time_t really 32-bit? If so that's really disappointing,
> > but presumably unfixable...
> 
> This definitely is fixable as the riscv32 Linux ABI is not final.

i think linux is the problem: when x32 tried to do 64bit time_t
on an ilp32 target it turned out to be a disaster, because
various driver and fs code can only deal with 32bit time_t when
long is 32bit (although x32 had other issues too: mixing 64bit
kernel space and 32bit userspace types).

the consensus after x32 was that new 32bit targets will keep
using 32bit time_t and there is an independent project to add
64bit time_t support (by introducing new syscalls, types etc)
that will apply to all 32bit targets once it's done.
Szabolcs Nagy Sept. 28, 2018, 11:43 a.m.
> diff --git a/src/math/riscv64/fmax.s b/src/math/riscv64/fmax.s
> new file mode 100644
> index 0000000..40655d3
> --- /dev/null
> +++ b/src/math/riscv64/fmax.s
> @@ -0,0 +1,5 @@
> +.global fmax
> +.type   fmax, %function
> +fmax:
> +        fmax.d fa0, fa0, fa1
> +        ret

this is ok, but note that

riscv fmax is ieee-754-2018 maximumNumber(x,y)
iso c fmax (with ts 18661) is ieee-754-2008 maxNum(x,y)

(see http://754r.ucbtest.org/drafts/
and http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1778.pdf )

they only differ in snan handling, current iso c (and musl)
does not care about signaling nans, but that might change.
(glibc cares and gcc has flags to make it care.)


musl is moving away from asm to c code with gcc style inline
asm wherever possible (the drawback is the dependency on gcc
asm syntax and constraints, the benefit is that pcs and
prologue/epilogue are handled by the compiler so all sorts of
instrumentations like debug info, -fstack-protector-all, etc
just work).

so i'd prefer to convert all these asm to c code.
(can be done after the port goes in)
Rich Felker Sept. 28, 2018, 2:26 p.m.
On Fri, Sep 28, 2018 at 12:33:54PM +0200, Szabolcs Nagy wrote:
> * Michael Clark <michaeljclark@mac.com> [2018-09-28 18:33:18 +1200]:
> > > On 28/09/2018, at 2:47 PM, Rich Felker <dalias@libc.org> wrote:
> > > 
> > >> On Thu, Sep 27, 2018 at 10:24:04PM -0400, Rich Felker wrote:
> > >> Pulled from here:
> > >> https://github.com/riscv/riscv-musl/commit/6a4f4a9c774608add4b02f95322518bd2f5f51ee
> > >> 
> > >> Attached for review.
> > > 
> > >> diff --git a/arch/riscv32/bits/alltypes.h.in b/arch/riscv32/bits/alltypes.h.in
> > >> new file mode 100644
> > >> index 0000000..66ca18a
> > >> --- /dev/null
> > >> +++ b/arch/riscv32/bits/alltypes.h.in
> > >> @@ -0,0 +1,26 @@
> > >> +#define _Addr int
> > >> +#define _Int64 long long
> > >> +#define _Reg int
> > >> +
> > >> +TYPEDEF __builtin_va_list va_list;
> > >> +TYPEDEF __builtin_va_list __isoc_va_list;
> > >> +
> > >> +#ifndef __cplusplus
> > >> +TYPEDEF int wchar_t;
> > >> +#endif
> > >> +
> > >> +TYPEDEF float float_t;
> > >> +TYPEDEF double double_t;
> > >> +
> > >> +TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
> > >> +
> > >> +TYPEDEF long time_t;
> > > 
> > > Is riscv32 time_t really 32-bit? If so that's really disappointing,
> > > but presumably unfixable...
> > 
> > This definitely is fixable as the riscv32 Linux ABI is not final.
> 
> i think linux is the problem: when x32 tried to do 64bit time_t
> on an ilp32 target it turned out to be a disaster, because
> various driver and fs code can only deal with 32bit time_t when
> long is 32bit (although x32 had other issues too: mixing 64bit
> kernel space and 32bit userspace types).

Are you talking about ioctl interfaces? These need to be fixed at some
point anyway (both for glibc TIME64 profile and musl2) and we can shim
them in userspace with a big list of them. I'd rather do it now than
introduce a new arch/ABI that's broken by design and destined to be
unusable in a few years.

> the consensus after x32 was that new 32bit targets will keep
> using 32bit time_t and there is an independent project to add
> 64bit time_t support (by introducing new syscalls, types etc)
> that will apply to all 32bit targets once it's done.

This is really unfortunate. I'd love it if the rv32 people could
provide some pushback against it.

Rich
Rich Felker Sept. 28, 2018, 2:28 p.m.
On Fri, Sep 28, 2018 at 01:43:24PM +0200, Szabolcs Nagy wrote:
> > diff --git a/src/math/riscv64/fmax.s b/src/math/riscv64/fmax.s
> > new file mode 100644
> > index 0000000..40655d3
> > --- /dev/null
> > +++ b/src/math/riscv64/fmax.s
> > @@ -0,0 +1,5 @@
> > +.global fmax
> > +.type   fmax, %function
> > +fmax:
> > +        fmax.d fa0, fa0, fa1
> > +        ret
> 
> this is ok, but note that
> 
> riscv fmax is ieee-754-2018 maximumNumber(x,y)
> iso c fmax (with ts 18661) is ieee-754-2008 maxNum(x,y)
> 
> (see http://754r.ucbtest.org/drafts/
> and http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1778.pdf )
> 
> they only differ in snan handling, current iso c (and musl)
> does not care about signaling nans, but that might change.
> (glibc cares and gcc has flags to make it care.)

Yes, for now I think it doesn't matter.

> musl is moving away from asm to c code with gcc style inline
> asm wherever possible (the drawback is the dependency on gcc
> asm syntax and constraints, the benefit is that pcs and
> prologue/epilogue are handled by the compiler so all sorts of
> instrumentations like debug info, -fstack-protector-all, etc
> just work).
> 
> so i'd prefer to convert all these asm to c code.
> (can be done after the port goes in)

Indeed, I'd rather do this later as a fixup for all archs at once than
try to work it out now as part of the riscv porting. They're logically
separate tasks.

Rich
Rich Felker Oct. 9, 2018, 6:05 p.m.
Ping.

On Thu, Sep 27, 2018 at 10:46:33PM -0400, Rich Felker wrote:
> On Thu, Sep 27, 2018 at 10:24:04PM -0400, Rich Felker wrote:
> > Pulled from here:
> > https://github.com/riscv/riscv-musl/commit/6a4f4a9c774608add4b02f95322518bd2f5f51ee
> > 
> > Attached for review.
> 
> Review inline below:
> 
> > diff --git a/arch/riscv32/atomic_arch.h b/arch/riscv32/atomic_arch.h
> > new file mode 100644
> > index 0000000..93c89cc
> > --- /dev/null
> > +++ b/arch/riscv32/atomic_arch.h
> > @@ -0,0 +1,35 @@
> > +#define a_barrier a_barrier
> > +static inline void a_barrier()
> > +{
> > +	__asm__ __volatile__ ("fence rw,rw" : : : "memory");
> > +}
> > +
> > +#define a_ll a_ll
> > +static inline int a_ll(volatile int *p)
> > +{
> > +	int v;
> > +	__asm__ __volatile__ ("lr.w %0, (%1)" : "=&r"(v) : "r"(p));
> > +	return v;
> > +}
> > +
> > +#define a_sc a_sc
> > +static inline int a_sc(volatile int *p, int v)
> > +{
> > +	int r;
> > +	__asm__ __volatile__ ("sc.w %0, %2, (%1)" : "=&r"(r) : "r"(p), "r"(v) : "memory");
> > +	return !r;
> > +}
> > +
> > +#define a_cas a_cas
> > +static inline int a_cas(volatile int *p, int t, int s)
> > +{
> > +	int old, tmp;
> > +	__asm__("1:  lr.w    %0, %2      \n"
> > +		"    bne     %0, %3, 1f  \n"
> > +		"    sc.w    %1, %4, %2  \n"
> > +		"    bnez    %1, 1b      \n"
> > +		"1:                      \n"
> > +		: "=&r"(old), "+r"(tmp), "+A"(*p)
> > +		: "r"(t), "r"(s));
> > +	return old;
> > +}
> 
> Why are both a_ll/a_sc and a_cas defined, and why is a_cas missing
> barriers? Normally if a_ll/a_sc/a_barrier are defined, the top-level
> atomic.h should be allowed to generate a_cas in terms of them.
> 
> > diff --git a/arch/riscv32/bits/signal.h b/arch/riscv32/bits/signal.h
> > new file mode 100644
> > index 0000000..8b992cc
> > --- /dev/null
> > +++ b/arch/riscv32/bits/signal.h
> > @@ -0,0 +1,113 @@
> > +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
> > + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
> > +
> > +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
> > +# define MINSIGSTKSZ 2048
> > +# define SIGSTKSZ 8192
> > +#endif
> > +
> > +/* gregs[0] holds the program counter. */
> > +
> > +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
> > +typedef unsigned long greg_t;
> > +typedef unsigned long gregset_t[32];
> > +
> > +struct __riscv_f_ext_state {
> > +	unsigned int f[32];
> > +	unsigned int fcsr;
> > +};
> > +
> > +struct __riscv_d_ext_state {
> > +	unsigned long long f[32];
> > +	unsigned int fcsr;
> > +};
> > +
> > +struct __riscv_q_ext_state {
> > +	unsigned long long f[64] __attribute__((aligned(16)));
> > +	unsigned int fcsr;
> > +	unsigned int reserved[3];
> > +};
> > +
> > +union __riscv_fp_state {
> > +	struct __riscv_f_ext_state f;
> > +	struct __riscv_d_ext_state d;
> > +	struct __riscv_q_ext_state q;
> > +};
> > +
> > +typedef union __riscv_fp_state fpregset_t;
> > +
> > +typedef struct sigcontext {
> > +	gregset_t gregs;
> > +	fpregset_t fpregs;
> > +} mcontext_t;
> > +
> > +#else
> > +typedef struct {
> > +	unsigned long gregs[32];
> > +	unsigned long long fpregs[66];
> > +} mcontext_t;
> > +#endif
> 
> In the namespace-safe version of mcontext_t, the names gregs and
> fpregs are not valid here. They would need to be __-prefixed or in
> some other reserved namespace.
> 
> > +struct sigaltstack {
> > +	void *ss_sp;
> > +	int ss_flags;
> > +	size_t ss_size;
> > +};
> > +
> > +typedef struct __ucontext
> > +{
> > +	unsigned long uc_flags;
> > +	struct __ucontext *uc_link;
> > +	stack_t uc_stack;
> > +	sigset_t uc_sigmask;
> > +	char __unused[1024 / 8 - sizeof(sigset_t)];
> 
> This is an invalid array of size zero and should just be removed.
> 
> > +	mcontext_t uc_mcontext;
> > +} ucontext_t;
> 
> ....
> 
> > diff --git a/arch/riscv32/crt_arch.h b/arch/riscv32/crt_arch.h
> > new file mode 100644
> > index 0000000..65187e1
> > --- /dev/null
> > +++ b/arch/riscv32/crt_arch.h
> > @@ -0,0 +1,18 @@
> > +__asm__(
> > +".text\n"
> > +".global " START "\n"
> > +".type " START ",%function\n"
> > +START ":\n"
> > +".weak __global_pointer$\n"
> > +".hidden __global_pointer$\n\t"
> > +".option push\n"
> > +".option norelax\n\t"
> > +"lla gp, __global_pointer$\n"
> > +".option pop\n\t"
> > +"mv a0, sp\n"
> > +".weak _DYNAMIC\n"
> > +".hidden _DYNAMIC\n\t"
> > +"lla a1, _DYNAMIC\n\t"
> > +"andi sp, sp, -16\n\t"
> > +"jal " START "_c"
> > +);
> > diff --git a/arch/riscv32/pthread_arch.h b/arch/riscv32/pthread_arch.h
> > new file mode 100644
> > index 0000000..feffaa4
> > --- /dev/null
> > +++ b/arch/riscv32/pthread_arch.h
> > @@ -0,0 +1,12 @@
> > +static inline struct pthread *__pthread_self()
> > +{
> > +	char *tp;
> > +	__asm__ __volatile__("mv %0, tp" : "=r"(tp));
> > +	return (void *)(tp - sizeof(struct pthread));
> > +}
> > +
> > +#define TLS_ABOVE_TP
> > +#define GAP_ABOVE_TP 0
> > +#define TP_ADJ(p) ((char *)p + sizeof(struct pthread))
> > +
> > +#define MC_PC gregs[0]
> > diff --git a/arch/riscv32/reloc.h b/arch/riscv32/reloc.h
> > new file mode 100644
> > index 0000000..d057bbe
> > --- /dev/null
> > +++ b/arch/riscv32/reloc.h
> > @@ -0,0 +1,27 @@
> > +#if defined __riscv_float_abi_soft
> > +#define RISCV_FP_SUFFIX "-sf"
> > +#elif defined __riscv_float_abi_single
> > +#define RISCV_FP_SUFFIX "-sp"
> > +#elif defined __riscv_float_abi_double
> > +#define RISCV_FP_SUFFIX ""
> > +#endif
> > +
> > +#define RISCV_LDSO_HELPER(x) "riscv" #x
> > +#define RISCV_LDSO(x) RISCV_LDSO_HELPER(x)
> > +
> > +#define LDSO_ARCH RISCV_LDSO(__riscv_xlen) RISCV_FP_SUFFIX
> 
> Elsewhere it looks like little/big endian are both options, but I see
> no endian variant here. If so this needs to be fixed.
> 
> Also what is __riscv_xlen? A predefined macro that expands to 32 or
> 64? Since this file is just for 32-bit it should just be hard-coded
> rather than assuming a macro would expand to the token 32 and not
> (31+1) or some other expression equal to 32, I think.
> 
> > diff --git a/arch/riscv32/syscall_arch.h b/arch/riscv32/syscall_arch.h
> > new file mode 100644
> > index 0000000..bc60d1f
> > --- /dev/null
> > +++ b/arch/riscv32/syscall_arch.h
> > @@ -0,0 +1,78 @@
> > +#define __SYSCALL_LL_E(x) \
> > +((union { long long ll; long l[2]; }){ .ll = x }).l[0], \
> > +((union { long long ll; long l[2]; }){ .ll = x }).l[1]
> > +#define __SYSCALL_LL_O(x) 0, __SYSCALL_LL_E((x))
> > +
> > +#define __asm_syscall(...) \
> > +	__asm__ __volatile__ ("scall\n\t" \
> > +	: "+r"(a0) : __VA_ARGS__ : "memory"); \
> > +	return a0; \
> > +
> > +static inline long __syscall0(long n)
> > +{
> > +	register long a7 __asm__("a7") = n;
> > +	register long a0 __asm__("a0");
> > +	__asm_syscall("r"(a7))
> > +}
> > +
> > +static inline long __syscall1(long n, long a)
> > +{
> > +	register long a7 __asm__("a7") = n;
> > +	register long a0 __asm__("a0") = a;
> > +	__asm_syscall("r"(a7), "0"(a0))
> > +}
> > +
> > +static inline long __syscall2(long n, long a, long b)
> > +{
> > +	register long a7 __asm__("a7") = n;
> > +	register long a0 __asm__("a0") = a;
> > +	register long a1 __asm__("a1") = b;
> > +	__asm_syscall("r"(a7), "0"(a0), "r"(a1))
> > +}
> > +
> > +static inline long __syscall3(long n, long a, long b, long c)
> > +{
> > +	register long a7 __asm__("a7") = n;
> > +	register long a0 __asm__("a0") = a;
> > +	register long a1 __asm__("a1") = b;
> > +	register long a2 __asm__("a2") = c;
> > +	__asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2))
> > +}
> > +
> > +static inline long __syscall4(long n, long a, long b, long c, long d)
> > +{
> > +	register long a7 __asm__("a7") = n;
> > +	register long a0 __asm__("a0") = a;
> > +	register long a1 __asm__("a1") = b;
> > +	register long a2 __asm__("a2") = c;
> > +	register long a3 __asm__("a3") = d;
> > +	__asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3))
> > +}
> > +
> > +static inline long __syscall5(long n, long a, long b, long c, long d, long e)
> > +{
> > +	register long a7 __asm__("a7") = n;
> > +	register long a0 __asm__("a0") = a;
> > +	register long a1 __asm__("a1") = b;
> > +	register long a2 __asm__("a2") = c;
> > +	register long a3 __asm__("a3") = d;
> > +	register long a4 __asm__("a4") = e;
> > +	__asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4))
> > +}
> > +
> > +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
> > +{
> > +	register long a7 __asm__("a7") = n;
> > +	register long a0 __asm__("a0") = a;
> > +	register long a1 __asm__("a1") = b;
> > +	register long a2 __asm__("a2") = c;
> > +	register long a3 __asm__("a3") = d;
> > +	register long a4 __asm__("a4") = e;
> > +	register long a5 __asm__("a5") = f;
> > +	__asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5))
> > +}
> > +
> > +#define VDSO_USEFUL
> > +/* We don't have a clock_gettime function.
> > +#define VDSO_CGT_SYM "__vdso_clock_gettime"
> > +#define VDSO_CGT_VER "LINUX_2.6" */
> 
> In that case VDSO_USEFUL might as well also be omitted for now.
> 
> > diff --git a/arch/riscv64/atomic_arch.h b/arch/riscv64/atomic_arch.h
> > new file mode 100644
> > index 0000000..018c7fd
> > --- /dev/null
> > +++ b/arch/riscv64/atomic_arch.h
> > @@ -0,0 +1,66 @@
> > +#define a_barrier a_barrier
> > +static inline void a_barrier()
> > +{
> > +	__asm__ __volatile__ ("fence rw,rw" : : : "memory");
> > +}
> > +
> > +#define a_ll a_ll
> > +static inline int a_ll(volatile int *p)
> > +{
> > +	int v;
> > +	__asm__ __volatile__ ("lr.w %0, %1" : "=&r"(v), "+A"(*p));
> > +	return v;
> > +}
> > +
> > +#define a_sc a_sc
> > +static inline int a_sc(volatile int *p, int v)
> > +{
> > +	int r;
> > +	__asm__ __volatile__ ("sc.w %0, %2, %1" : "=&r"(r), "+A"(*p) : "r"(v) : "memory");
> > +return !r;
> > +}
> > +
> > +#define a_cas a_cas
> > +static inline int a_cas(volatile int *p, int t, int s)
> > +{
> > +	int old, tmp;
> > +	__asm__("1:  lr.w    %0, %2      \n"
> > +		"    bne     %0, %3, 1f  \n"
> > +		"    sc.w    %1, %4, %2  \n"
> > +		"    bnez    %1, 1b      \n"
> > +		"1:                      \n"
> > +		: "=&r"(old), "+r"(tmp), "+A"(*p)
> > +		: "r"(t), "r"(s));
> > +	return old;
> > +}
> > +
> > +#define a_ll_p a_ll_p
> > +static inline void *a_ll_p(volatile void *p)
> > +{
> > +	void *v;
> > +	__asm__ __volatile__ ("lr.d %0, %1" : "=&r"(v), "+A"(*(long *)p));
> > +	return v;
> > +}
> > +
> > +#define a_sc_p a_sc_p
> > +static inline int a_sc_p(volatile int *p, void *v)
> > +{
> > +	int r;
> > +	__asm__ __volatile__ ("sc.d %0, %2, %1" : "=&r"(r), "+A"(*(long *)p) : "r"(v) : "memory");
> > +	return !r;
> > +}
> > +
> > +#define a_cas_p a_cas_p
> > +static inline void *a_cas_p(volatile void *p, void *t, void *s)
> > +{
> > +	void *old;
> > +	int tmp;
> > +	__asm__("1:  lr.d    %0, %2      \n"
> > +		"    bne     %0, %3, 1f  \n"
> > +		"    sc.d    %1, %4, %2  \n"
> > +		"    bnez    %1, 1b      \n"
> > +		"1:                      \n"
> > +		: "=&r"(old), "+r"(tmp), "+A"(*(long *)p)
> > +		: "r"(t), "r"(s));
> > +	return old;
> > +}
> 
> Same comments about cas vs ll/sc, and lack of barrier, as 32-bit version.
> 
> > diff --git a/arch/riscv64/bits/signal.h b/arch/riscv64/bits/signal.h
> > new file mode 100644
> > index 0000000..8b992cc
> > --- /dev/null
> > +++ b/arch/riscv64/bits/signal.h
> > @@ -0,0 +1,113 @@
> > +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
> > + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
> > +
> > +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
> > +# define MINSIGSTKSZ 2048
> > +# define SIGSTKSZ 8192
> > +#endif
> > +
> > +/* gregs[0] holds the program counter. */
> > +
> > +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
> > +typedef unsigned long greg_t;
> > +typedef unsigned long gregset_t[32];
> > +
> > +struct __riscv_f_ext_state {
> > +	unsigned int f[32];
> > +	unsigned int fcsr;
> > +};
> > +
> > +struct __riscv_d_ext_state {
> > +	unsigned long long f[32];
> > +	unsigned int fcsr;
> > +};
> > +
> > +struct __riscv_q_ext_state {
> > +	unsigned long long f[64] __attribute__((aligned(16)));
> > +	unsigned int fcsr;
> > +	unsigned int reserved[3];
> > +};
> > +
> > +union __riscv_fp_state {
> > +	struct __riscv_f_ext_state f;
> > +	struct __riscv_d_ext_state d;
> > +	struct __riscv_q_ext_state q;
> > +};
> > +
> > +typedef union __riscv_fp_state fpregset_t;
> > +
> > +typedef struct sigcontext {
> > +	gregset_t gregs;
> > +	fpregset_t fpregs;
> > +} mcontext_t;
> > +
> > +#else
> > +typedef struct {
> > +	unsigned long gregs[32];
> > +	unsigned long long fpregs[66];
> > +} mcontext_t;
> > +#endif
> > +
> > +struct sigaltstack {
> > +	void *ss_sp;
> > +	int ss_flags;
> > +	size_t ss_size;
> > +};
> > +
> > +typedef struct __ucontext
> > +{
> > +	unsigned long uc_flags;
> > +	struct __ucontext *uc_link;
> > +	stack_t uc_stack;
> > +	sigset_t uc_sigmask;
> > +	char __unused[1024 / 8 - sizeof(sigset_t)];
> > +	mcontext_t uc_mcontext;
> > +} ucontext_t;
> 
> Same issues here as 32-bit.
> 
> > diff --git a/arch/riscv64/reloc.h b/arch/riscv64/reloc.h
> > new file mode 100644
> > index 0000000..8bd90dd
> > --- /dev/null
> > +++ b/arch/riscv64/reloc.h
> > @@ -0,0 +1,27 @@
> > +#if defined __riscv_float_abi_soft
> > +#define RISCV_FP_SUFFIX "-sf"
> > +#elif defined __riscv_float_abi_single
> > +#define RISCV_FP_SUFFIX "-sp"
> > +#elif defined __riscv_float_abi_double
> > +#define RISCV_FP_SUFFIX ""
> > +#endif
> > +
> > +#define RISCV_LDSO_HELPER(x) "riscv" #x
> > +#define RISCV_LDSO(x) RISCV_LDSO_HELPER(x)
> > +
> > +#define LDSO_ARCH RISCV_LDSO(__riscv_xlen) RISCV_FP_SUFFIX
> 
> Same here.
> 
> > diff --git a/configure b/configure
> > index 997e665..4d3d8b4 100755
> > --- a/configure
> > +++ b/configure
> > @@ -322,6 +322,8 @@ microblaze*) ARCH=microblaze ;;
> >  or1k*) ARCH=or1k ;;
> >  powerpc64*) ARCH=powerpc64 ;;
> >  powerpc*) ARCH=powerpc ;;
> > +riscv64*) ARCH=riscv64 ;;
> > +riscv*) ARCH=riscv32 ;;
> >  sh[1-9bel-]*|sh|superh*) ARCH=sh ;;
> >  s390x*) ARCH=s390x ;;
> >  unknown) fail "$0: unable to detect target arch; try $0 --target=..." ;;
> > @@ -640,6 +642,11 @@ trycppif __LITTLE_ENDIAN__ "$t" && SUBARCH=${SUBARCH}le
> >  trycppif _SOFT_FLOAT "$t" && fail "$0: error: soft-float not supported on powerpc64"
> >  fi
> >  
> > +if test "$ARCH" = "riscv" || test "$ARCH" = "riscv64" ; then
> > +trycppif "RISCVEB || _RISCVEB || __RISCVEB || __RISCVEB__" "$t" && SUBARCH=${SUBARCH}eb
> 
> Predefined macros that violate the namespace (RISCVEB) shouldn't be
> defined or observed.
> 
> > +trycppif __riscv_soft_float "$t" && SUBARCH=${SUBARCH}-sf
> > +fi
> > +
> >  if test "$ARCH" = "sh" ; then
> >  tryflag CFLAGS_AUTO -Wa,--isa=any
> >  trycppif __BIG_ENDIAN__ "$t" && SUBARCH=${SUBARCH}eb
> > diff --git a/crt/riscv32/crti.s b/crt/riscv32/crti.s
> > new file mode 100644
> > index 0000000..6916bfd
> > --- /dev/null
> > +++ b/crt/riscv32/crti.s
> > @@ -0,0 +1,11 @@
> > +.section .init
> > +.global _init
> > +.type _init,%function
> > +_init:
> > +        ret
> > +
> > +.section .fini
> > +.global _fini
> > +.type _fini,%function
> > +_fini:
> > +        ret
> > diff --git a/crt/riscv32/crtn.s b/crt/riscv32/crtn.s
> > new file mode 100644
> > index 0000000..e69de29
> 
> It looks like these are not used, right?
> 
> > diff --git a/include/elf.h b/include/elf.h
> > index c229735..ec2e8fd 100644
> > --- a/include/elf.h
> > +++ b/include/elf.h
> > @@ -3164,6 +3164,62 @@ enum
> >  #define R_BPF_NONE		0
> >  #define R_BPF_MAP_FD		1
> >  
> > +#define R_RISCV_NONE            0
> > +#define R_RISCV_32              1
> > +#define R_RISCV_64              2
> > +#define R_RISCV_RELATIVE        3
> > +#define R_RISCV_COPY            4
> > +#define R_RISCV_JUMP_SLOT       5
> > +#define R_RISCV_TLS_DTPMOD32    6
> > +#define R_RISCV_TLS_DTPMOD64    7
> > +#define R_RISCV_TLS_DTPREL32    8
> > +#define R_RISCV_TLS_DTPREL64    9
> > +#define R_RISCV_TLS_TPREL32     10
> > +#define R_RISCV_TLS_TPREL64     11
> > +
> > +#define R_RISCV_BRANCH          16
> > +#define R_RISCV_JAL             17
> > +#define R_RISCV_CALL            18
> > +#define R_RISCV_CALL_PLT        19
> > +#define R_RISCV_GOT_HI20        20
> > +#define R_RISCV_TLS_GOT_HI20    21
> > +#define R_RISCV_TLS_GD_HI20     22
> > +#define R_RISCV_PCREL_HI20      23
> > +#define R_RISCV_PCREL_LO12_I    24
> > +#define R_RISCV_PCREL_LO12_S    25
> > +#define R_RISCV_HI20            26
> > +#define R_RISCV_LO12_I          27
> > +#define R_RISCV_LO12_S          28
> > +#define R_RISCV_TPREL_HI20      29
> > +#define R_RISCV_TPREL_LO12_I    30
> > +#define R_RISCV_TPREL_LO12_S    31
> > +#define R_RISCV_TPREL_ADD       32
> > +#define R_RISCV_ADD8            33
> > +#define R_RISCV_ADD16           34
> > +#define R_RISCV_ADD32           35
> > +#define R_RISCV_ADD64           36
> > +#define R_RISCV_SUB8            37
> > +#define R_RISCV_SUB16           38
> > +#define R_RISCV_SUB32           39
> > +#define R_RISCV_SUB64           40
> > +#define R_RISCV_GNU_VTINHERIT   41
> > +#define R_RISCV_GNU_VTENTRY     42
> > +#define R_RISCV_ALIGN           43
> > +#define R_RISCV_RVC_BRANCH      44
> > +#define R_RISCV_RVC_JUMP        45
> > +#define R_RISCV_RVC_LUI         46
> > +#define R_RISCV_GPREL_I         47
> > +#define R_RISCV_GPREL_S         48
> > +#define R_RISCV_TPREL_I         49
> > +#define R_RISCV_TPREL_S         50
> > +#define R_RISCV_RELAX           51
> > +#define R_RISCV_SUB6            52
> > +#define R_RISCV_SET6            53
> > +#define R_RISCV_SET8            54
> > +#define R_RISCV_SET16           55
> > +#define R_RISCV_SET32           56
> > +#define R_RISCV_32_PCREL        57
> > +
> >  #ifdef __cplusplus
> >  }
> >  #endif
> 
> This should be its own patch independent of the port; I can commit it
> earlier.
> 
> > diff --git a/src/thread/riscv32/syscall_cp.s b/src/thread/riscv32/syscall_cp.s
> > new file mode 100644
> > index 0000000..71bf6d3
> > --- /dev/null
> > +++ b/src/thread/riscv32/syscall_cp.s
> > @@ -0,0 +1,29 @@
> > +.global __cp_begin
> > +.hidden __cp_begin
> > +.global __cp_end
> > +.hidden __cp_end
> > +.global __cp_cancel
> > +.hidden __cp_cancel
> > +.hidden __cancel
> > +.global __syscall_cp_asm
> > +.hidden __syscall_cp_asm
> > +.type __syscall_cp_asm, %function
> > +__syscall_cp_asm:
> > +__cp_begin:
> > +        lw t0, 0(a0)
> > +        bnez t0, __cp_cancel
> > +
> > +        mv t0, a1
> > +        mv a0, a2
> > +        mv a1, a3
> > +        mv a2, a4
> > +        mv a3, a5
> > +        mv a4, a6
> > +        mv a5, a7
> > +        lw a6, 0(sp)
> > +        mv a7, t0
> > +        scall
> > +__cp_cancel:
> > +        ret
> > +__cp_end:
> > +        j __cancel
> 
> The labels here are backwards. __cp_end must point immediately after
> the syscall instruction, and __cp_end needs to jump to __cancel.
> 
> > diff --git a/src/thread/riscv64/syscall_cp.s b/src/thread/riscv64/syscall_cp.s
> > new file mode 100644
> > index 0000000..c745b32
> > --- /dev/null
> > +++ b/src/thread/riscv64/syscall_cp.s
> > @@ -0,0 +1,29 @@
> > +.global __cp_begin
> > +.hidden __cp_begin
> > +.global __cp_end
> > +.hidden __cp_end
> > +.global __cp_cancel
> > +.hidden __cp_cancel
> > +.hidden __cancel
> > +.global __syscall_cp_asm
> > +.hidden __syscall_cp_asm
> > +.type __syscall_cp_asm, %function
> > +__syscall_cp_asm:
> > +__cp_begin:
> > +        ld t0, 0(a0)
> > +        bnez t0, __cp_cancel
> > +
> > +        mv t0, a1
> > +        mv a0, a2
> > +        mv a1, a3
> > +        mv a2, a4
> > +        mv a3, a5
> > +        mv a4, a6
> > +        mv a5, a7
> > +        ld a6, 0(sp)
> > +        mv a7, t0
> > +        scall
> > +__cp_cancel:
> > +        ret
> > +__cp_end:
> > +        j __cancel
> > -- 
> > 2.10.0
> > 
> 
> Likewise here.
> 
> Rich
Michael Clark Oct. 9, 2018, 9:36 p.m.
Hi,

I have a status update. I haven’t made any changes to the musl port since last week but I did investigate and fix the stat issue in qemu-riscv32. I ran tests with riscv32 Linux kernel with glibc in QEMU full system emulation as Linux kernel is canonical for the ABI.

riscv32 is indeed a unique port in linux-kernel land. It does not define __ARCH_WANT_STAT64 in arch/riscv/include/asm/unistd.h (unlike all other 32-bit ports which confused me a bit). It does not have fstat64 and its stat structure matches rv64. I’m kind of stubborn so I had to see the test pass/fail so I spent some time getting riscv32 linux to build. I should submit a couple of small patches for riscv-linux.

I fixed riscv32 stat in riscv-qemu: https://github.com/riscv/riscv-qemu

RISC-V QEMU had the 32-bit asm-generic which has a 32-bit stat, but no fstat64. We may have missed a chunk when we rebased the 2016 riscv-qemu baseline. The stat patch is in qemu-for-upstream branch in the riscv-qemu branch.

We need to work on getting our QEMU changes upstream. We have problems with getting code into upstream QEMU as they have very strict code review policy on pull requests. Every commit must have “Reviewed-by:” with a “trusted reviewer”. It doesn’t seem to prevent changes coming from Linaro breaking the RISC-V port but it does prevent our fixes going in. My current focus is working on automated test cases for the fixes in the QEMU queue so we can change the discourse to does it pass an extensive set of tests. Currently the baseline for inclusion is does it compile and passes “make check”, have Reviewed-by and Signed-off-by tags and does it conform to the QEMU coding style (checkpatch.pl). The issue is we are making changes that typically require reading the Privileged ISA manual for verification and we don’t have high test case coverage for the Privileged ISA. The Base ISA has pretty good test coverage.

I would be happy if someone volunteered to help with the RISC-V musl port...

Michael

> On 10/10/2018, at 7:05 AM, Rich Felker <dalias@libc.org> wrote:
> 
> Ping.
> 
>> On Thu, Sep 27, 2018 at 10:46:33PM -0400, Rich Felker wrote:
>>> On Thu, Sep 27, 2018 at 10:24:04PM -0400, Rich Felker wrote:
>>> Pulled from here:
>>> https://github.com/riscv/riscv-musl/commit/6a4f4a9c774608add4b02f95322518bd2f5f51ee
>>> 
>>> Attached for review.
>> 
>> Review inline below:
>> 
>>> diff --git a/arch/riscv32/atomic_arch.h b/arch/riscv32/atomic_arch.h
>>> new file mode 100644
>>> index 0000000..93c89cc
>>> --- /dev/null
>>> +++ b/arch/riscv32/atomic_arch.h
>>> @@ -0,0 +1,35 @@
>>> +#define a_barrier a_barrier
>>> +static inline void a_barrier()
>>> +{
>>> +    __asm__ __volatile__ ("fence rw,rw" : : : "memory");
>>> +}
>>> +
>>> +#define a_ll a_ll
>>> +static inline int a_ll(volatile int *p)
>>> +{
>>> +    int v;
>>> +    __asm__ __volatile__ ("lr.w %0, (%1)" : "=&r"(v) : "r"(p));
>>> +    return v;
>>> +}
>>> +
>>> +#define a_sc a_sc
>>> +static inline int a_sc(volatile int *p, int v)
>>> +{
>>> +    int r;
>>> +    __asm__ __volatile__ ("sc.w %0, %2, (%1)" : "=&r"(r) : "r"(p), "r"(v) : "memory");
>>> +    return !r;
>>> +}
>>> +
>>> +#define a_cas a_cas
>>> +static inline int a_cas(volatile int *p, int t, int s)
>>> +{
>>> +    int old, tmp;
>>> +    __asm__("1:  lr.w    %0, %2      \n"
>>> +        "    bne     %0, %3, 1f  \n"
>>> +        "    sc.w    %1, %4, %2  \n"
>>> +        "    bnez    %1, 1b      \n"
>>> +        "1:                      \n"
>>> +        : "=&r"(old), "+r"(tmp), "+A"(*p)
>>> +        : "r"(t), "r"(s));
>>> +    return old;
>>> +}
>> 
>> Why are both a_ll/a_sc and a_cas defined, and why is a_cas missing
>> barriers? Normally if a_ll/a_sc/a_barrier are defined, the top-level
>> atomic.h should be allowed to generate a_cas in terms of them.
>> 
>>> diff --git a/arch/riscv32/bits/signal.h b/arch/riscv32/bits/signal.h
>>> new file mode 100644
>>> index 0000000..8b992cc
>>> --- /dev/null
>>> +++ b/arch/riscv32/bits/signal.h
>>> @@ -0,0 +1,113 @@
>>> +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
>>> + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
>>> +
>>> +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
>>> +# define MINSIGSTKSZ 2048
>>> +# define SIGSTKSZ 8192
>>> +#endif
>>> +
>>> +/* gregs[0] holds the program counter. */
>>> +
>>> +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
>>> +typedef unsigned long greg_t;
>>> +typedef unsigned long gregset_t[32];
>>> +
>>> +struct __riscv_f_ext_state {
>>> +    unsigned int f[32];
>>> +    unsigned int fcsr;
>>> +};
>>> +
>>> +struct __riscv_d_ext_state {
>>> +    unsigned long long f[32];
>>> +    unsigned int fcsr;
>>> +};
>>> +
>>> +struct __riscv_q_ext_state {
>>> +    unsigned long long f[64] __attribute__((aligned(16)));
>>> +    unsigned int fcsr;
>>> +    unsigned int reserved[3];
>>> +};
>>> +
>>> +union __riscv_fp_state {
>>> +    struct __riscv_f_ext_state f;
>>> +    struct __riscv_d_ext_state d;
>>> +    struct __riscv_q_ext_state q;
>>> +};
>>> +
>>> +typedef union __riscv_fp_state fpregset_t;
>>> +
>>> +typedef struct sigcontext {
>>> +    gregset_t gregs;
>>> +    fpregset_t fpregs;
>>> +} mcontext_t;
>>> +
>>> +#else
>>> +typedef struct {
>>> +    unsigned long gregs[32];
>>> +    unsigned long long fpregs[66];
>>> +} mcontext_t;
>>> +#endif
>> 
>> In the namespace-safe version of mcontext_t, the names gregs and
>> fpregs are not valid here. They would need to be __-prefixed or in
>> some other reserved namespace.
>> 
>>> +struct sigaltstack {
>>> +    void *ss_sp;
>>> +    int ss_flags;
>>> +    size_t ss_size;
>>> +};
>>> +
>>> +typedef struct __ucontext
>>> +{
>>> +    unsigned long uc_flags;
>>> +    struct __ucontext *uc_link;
>>> +    stack_t uc_stack;
>>> +    sigset_t uc_sigmask;
>>> +    char __unused[1024 / 8 - sizeof(sigset_t)];
>> 
>> This is an invalid array of size zero and should just be removed.
>> 
>>> +    mcontext_t uc_mcontext;
>>> +} ucontext_t;
>> 
>> ....
>> 
>>> diff --git a/arch/riscv32/crt_arch.h b/arch/riscv32/crt_arch.h
>>> new file mode 100644
>>> index 0000000..65187e1
>>> --- /dev/null
>>> +++ b/arch/riscv32/crt_arch.h
>>> @@ -0,0 +1,18 @@
>>> +__asm__(
>>> +".text\n"
>>> +".global " START "\n"
>>> +".type " START ",%function\n"
>>> +START ":\n"
>>> +".weak __global_pointer$\n"
>>> +".hidden __global_pointer$\n\t"
>>> +".option push\n"
>>> +".option norelax\n\t"
>>> +"lla gp, __global_pointer$\n"
>>> +".option pop\n\t"
>>> +"mv a0, sp\n"
>>> +".weak _DYNAMIC\n"
>>> +".hidden _DYNAMIC\n\t"
>>> +"lla a1, _DYNAMIC\n\t"
>>> +"andi sp, sp, -16\n\t"
>>> +"jal " START "_c"
>>> +);
>>> diff --git a/arch/riscv32/pthread_arch.h b/arch/riscv32/pthread_arch.h
>>> new file mode 100644
>>> index 0000000..feffaa4
>>> --- /dev/null
>>> +++ b/arch/riscv32/pthread_arch.h
>>> @@ -0,0 +1,12 @@
>>> +static inline struct pthread *__pthread_self()
>>> +{
>>> +    char *tp;
>>> +    __asm__ __volatile__("mv %0, tp" : "=r"(tp));
>>> +    return (void *)(tp - sizeof(struct pthread));
>>> +}
>>> +
>>> +#define TLS_ABOVE_TP
>>> +#define GAP_ABOVE_TP 0
>>> +#define TP_ADJ(p) ((char *)p + sizeof(struct pthread))
>>> +
>>> +#define MC_PC gregs[0]
>>> diff --git a/arch/riscv32/reloc.h b/arch/riscv32/reloc.h
>>> new file mode 100644
>>> index 0000000..d057bbe
>>> --- /dev/null
>>> +++ b/arch/riscv32/reloc.h
>>> @@ -0,0 +1,27 @@
>>> +#if defined __riscv_float_abi_soft
>>> +#define RISCV_FP_SUFFIX "-sf"
>>> +#elif defined __riscv_float_abi_single
>>> +#define RISCV_FP_SUFFIX "-sp"
>>> +#elif defined __riscv_float_abi_double
>>> +#define RISCV_FP_SUFFIX ""
>>> +#endif
>>> +
>>> +#define RISCV_LDSO_HELPER(x) "riscv" #x
>>> +#define RISCV_LDSO(x) RISCV_LDSO_HELPER(x)
>>> +
>>> +#define LDSO_ARCH RISCV_LDSO(__riscv_xlen) RISCV_FP_SUFFIX
>> 
>> Elsewhere it looks like little/big endian are both options, but I see
>> no endian variant here. If so this needs to be fixed.
>> 
>> Also what is __riscv_xlen? A predefined macro that expands to 32 or
>> 64? Since this file is just for 32-bit it should just be hard-coded
>> rather than assuming a macro would expand to the token 32 and not
>> (31+1) or some other expression equal to 32, I think.
>> 
>>> diff --git a/arch/riscv32/syscall_arch.h b/arch/riscv32/syscall_arch.h
>>> new file mode 100644
>>> index 0000000..bc60d1f
>>> --- /dev/null
>>> +++ b/arch/riscv32/syscall_arch.h
>>> @@ -0,0 +1,78 @@
>>> +#define __SYSCALL_LL_E(x) \
>>> +((union { long long ll; long l[2]; }){ .ll = x }).l[0], \
>>> +((union { long long ll; long l[2]; }){ .ll = x }).l[1]
>>> +#define __SYSCALL_LL_O(x) 0, __SYSCALL_LL_E((x))
>>> +
>>> +#define __asm_syscall(...) \
>>> +    __asm__ __volatile__ ("scall\n\t" \
>>> +    : "+r"(a0) : __VA_ARGS__ : "memory"); \
>>> +    return a0; \
>>> +
>>> +static inline long __syscall0(long n)
>>> +{
>>> +    register long a7 __asm__("a7") = n;
>>> +    register long a0 __asm__("a0");
>>> +    __asm_syscall("r"(a7))
>>> +}
>>> +
>>> +static inline long __syscall1(long n, long a)
>>> +{
>>> +    register long a7 __asm__("a7") = n;
>>> +    register long a0 __asm__("a0") = a;
>>> +    __asm_syscall("r"(a7), "0"(a0))
>>> +}
>>> +
>>> +static inline long __syscall2(long n, long a, long b)
>>> +{
>>> +    register long a7 __asm__("a7") = n;
>>> +    register long a0 __asm__("a0") = a;
>>> +    register long a1 __asm__("a1") = b;
>>> +    __asm_syscall("r"(a7), "0"(a0), "r"(a1))
>>> +}
>>> +
>>> +static inline long __syscall3(long n, long a, long b, long c)
>>> +{
>>> +    register long a7 __asm__("a7") = n;
>>> +    register long a0 __asm__("a0") = a;
>>> +    register long a1 __asm__("a1") = b;
>>> +    register long a2 __asm__("a2") = c;
>>> +    __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2))
>>> +}
>>> +
>>> +static inline long __syscall4(long n, long a, long b, long c, long d)
>>> +{
>>> +    register long a7 __asm__("a7") = n;
>>> +    register long a0 __asm__("a0") = a;
>>> +    register long a1 __asm__("a1") = b;
>>> +    register long a2 __asm__("a2") = c;
>>> +    register long a3 __asm__("a3") = d;
>>> +    __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3))
>>> +}
>>> +
>>> +static inline long __syscall5(long n, long a, long b, long c, long d, long e)
>>> +{
>>> +    register long a7 __asm__("a7") = n;
>>> +    register long a0 __asm__("a0") = a;
>>> +    register long a1 __asm__("a1") = b;
>>> +    register long a2 __asm__("a2") = c;
>>> +    register long a3 __asm__("a3") = d;
>>> +    register long a4 __asm__("a4") = e;
>>> +    __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4))
>>> +}
>>> +
>>> +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
>>> +{
>>> +    register long a7 __asm__("a7") = n;
>>> +    register long a0 __asm__("a0") = a;
>>> +    register long a1 __asm__("a1") = b;
>>> +    register long a2 __asm__("a2") = c;
>>> +    register long a3 __asm__("a3") = d;
>>> +    register long a4 __asm__("a4") = e;
>>> +    register long a5 __asm__("a5") = f;
>>> +    __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5))
>>> +}
>>> +
>>> +#define VDSO_USEFUL
>>> +/* We don't have a clock_gettime function.
>>> +#define VDSO_CGT_SYM "__vdso_clock_gettime"
>>> +#define VDSO_CGT_VER "LINUX_2.6" */
>> 
>> In that case VDSO_USEFUL might as well also be omitted for now.
>> 
>>> diff --git a/arch/riscv64/atomic_arch.h b/arch/riscv64/atomic_arch.h
>>> new file mode 100644
>>> index 0000000..018c7fd
>>> --- /dev/null
>>> +++ b/arch/riscv64/atomic_arch.h
>>> @@ -0,0 +1,66 @@
>>> +#define a_barrier a_barrier
>>> +static inline void a_barrier()
>>> +{
>>> +    __asm__ __volatile__ ("fence rw,rw" : : : "memory");
>>> +}
>>> +
>>> +#define a_ll a_ll
>>> +static inline int a_ll(volatile int *p)
>>> +{
>>> +    int v;
>>> +    __asm__ __volatile__ ("lr.w %0, %1" : "=&r"(v), "+A"(*p));
>>> +    return v;
>>> +}
>>> +
>>> +#define a_sc a_sc
>>> +static inline int a_sc(volatile int *p, int v)
>>> +{
>>> +    int r;
>>> +    __asm__ __volatile__ ("sc.w %0, %2, %1" : "=&r"(r), "+A"(*p) : "r"(v) : "memory");
>>> +return !r;
>>> +}
>>> +
>>> +#define a_cas a_cas
>>> +static inline int a_cas(volatile int *p, int t, int s)
>>> +{
>>> +    int old, tmp;
>>> +    __asm__("1:  lr.w    %0, %2      \n"
>>> +        "    bne     %0, %3, 1f  \n"
>>> +        "    sc.w    %1, %4, %2  \n"
>>> +        "    bnez    %1, 1b      \n"
>>> +        "1:                      \n"
>>> +        : "=&r"(old), "+r"(tmp), "+A"(*p)
>>> +        : "r"(t), "r"(s));
>>> +    return old;
>>> +}
>>> +
>>> +#define a_ll_p a_ll_p
>>> +static inline void *a_ll_p(volatile void *p)
>>> +{
>>> +    void *v;
>>> +    __asm__ __volatile__ ("lr.d %0, %1" : "=&r"(v), "+A"(*(long *)p));
>>> +    return v;
>>> +}
>>> +
>>> +#define a_sc_p a_sc_p
>>> +static inline int a_sc_p(volatile int *p, void *v)
>>> +{
>>> +    int r;
>>> +    __asm__ __volatile__ ("sc.d %0, %2, %1" : "=&r"(r), "+A"(*(long *)p) : "r"(v) : "memory");
>>> +    return !r;
>>> +}
>>> +
>>> +#define a_cas_p a_cas_p
>>> +static inline void *a_cas_p(volatile void *p, void *t, void *s)
>>> +{
>>> +    void *old;
>>> +    int tmp;
>>> +    __asm__("1:  lr.d    %0, %2      \n"
>>> +        "    bne     %0, %3, 1f  \n"
>>> +        "    sc.d    %1, %4, %2  \n"
>>> +        "    bnez    %1, 1b      \n"
>>> +        "1:                      \n"
>>> +        : "=&r"(old), "+r"(tmp), "+A"(*(long *)p)
>>> +        : "r"(t), "r"(s));
>>> +    return old;
>>> +}
>> 
>> Same comments about cas vs ll/sc, and lack of barrier, as 32-bit version.
>> 
>>> diff --git a/arch/riscv64/bits/signal.h b/arch/riscv64/bits/signal.h
>>> new file mode 100644
>>> index 0000000..8b992cc
>>> --- /dev/null
>>> +++ b/arch/riscv64/bits/signal.h
>>> @@ -0,0 +1,113 @@
>>> +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
>>> + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
>>> +
>>> +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
>>> +# define MINSIGSTKSZ 2048
>>> +# define SIGSTKSZ 8192
>>> +#endif
>>> +
>>> +/* gregs[0] holds the program counter. */
>>> +
>>> +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
>>> +typedef unsigned long greg_t;
>>> +typedef unsigned long gregset_t[32];
>>> +
>>> +struct __riscv_f_ext_state {
>>> +    unsigned int f[32];
>>> +    unsigned int fcsr;
>>> +};
>>> +
>>> +struct __riscv_d_ext_state {
>>> +    unsigned long long f[32];
>>> +    unsigned int fcsr;
>>> +};
>>> +
>>> +struct __riscv_q_ext_state {
>>> +    unsigned long long f[64] __attribute__((aligned(16)));
>>> +    unsigned int fcsr;
>>> +    unsigned int reserved[3];
>>> +};
>>> +
>>> +union __riscv_fp_state {
>>> +    struct __riscv_f_ext_state f;
>>> +    struct __riscv_d_ext_state d;
>>> +    struct __riscv_q_ext_state q;
>>> +};
>>> +
>>> +typedef union __riscv_fp_state fpregset_t;
>>> +
>>> +typedef struct sigcontext {
>>> +    gregset_t gregs;
>>> +    fpregset_t fpregs;
>>> +} mcontext_t;
>>> +
>>> +#else
>>> +typedef struct {
>>> +    unsigned long gregs[32];
>>> +    unsigned long long fpregs[66];
>>> +} mcontext_t;
>>> +#endif
>>> +
>>> +struct sigaltstack {
>>> +    void *ss_sp;
>>> +    int ss_flags;
>>> +    size_t ss_size;
>>> +};
>>> +
>>> +typedef struct __ucontext
>>> +{
>>> +    unsigned long uc_flags;
>>> +    struct __ucontext *uc_link;
>>> +    stack_t uc_stack;
>>> +    sigset_t uc_sigmask;
>>> +    char __unused[1024 / 8 - sizeof(sigset_t)];
>>> +    mcontext_t uc_mcontext;
>>> +} ucontext_t;
>> 
>> Same issues here as 32-bit.
>> 
>>> diff --git a/arch/riscv64/reloc.h b/arch/riscv64/reloc.h
>>> new file mode 100644
>>> index 0000000..8bd90dd
>>> --- /dev/null
>>> +++ b/arch/riscv64/reloc.h
>>> @@ -0,0 +1,27 @@
>>> +#if defined __riscv_float_abi_soft
>>> +#define RISCV_FP_SUFFIX "-sf"
>>> +#elif defined __riscv_float_abi_single
>>> +#define RISCV_FP_SUFFIX "-sp"
>>> +#elif defined __riscv_float_abi_double
>>> +#define RISCV_FP_SUFFIX ""
>>> +#endif
>>> +
>>> +#define RISCV_LDSO_HELPER(x) "riscv" #x
>>> +#define RISCV_LDSO(x) RISCV_LDSO_HELPER(x)
>>> +
>>> +#define LDSO_ARCH RISCV_LDSO(__riscv_xlen) RISCV_FP_SUFFIX
>> 
>> Same here.
>> 
>>> diff --git a/configure b/configure
>>> index 997e665..4d3d8b4 100755
>>> --- a/configure
>>> +++ b/configure
>>> @@ -322,6 +322,8 @@ microblaze*) ARCH=microblaze ;;
>>> or1k*) ARCH=or1k ;;
>>> powerpc64*) ARCH=powerpc64 ;;
>>> powerpc*) ARCH=powerpc ;;
>>> +riscv64*) ARCH=riscv64 ;;
>>> +riscv*) ARCH=riscv32 ;;
>>> sh[1-9bel-]*|sh|superh*) ARCH=sh ;;
>>> s390x*) ARCH=s390x ;;
>>> unknown) fail "$0: unable to detect target arch; try $0 --target=..." ;;
>>> @@ -640,6 +642,11 @@ trycppif __LITTLE_ENDIAN__ "$t" && SUBARCH=${SUBARCH}le
>>> trycppif _SOFT_FLOAT "$t" && fail "$0: error: soft-float not supported on powerpc64"
>>> fi
>>> 
>>> +if test "$ARCH" = "riscv" || test "$ARCH" = "riscv64" ; then
>>> +trycppif "RISCVEB || _RISCVEB || __RISCVEB || __RISCVEB__" "$t" && SUBARCH=${SUBARCH}eb
>> 
>> Predefined macros that violate the namespace (RISCVEB) shouldn't be
>> defined or observed.
>> 
>>> +trycppif __riscv_soft_float "$t" && SUBARCH=${SUBARCH}-sf
>>> +fi
>>> +
>>> if test "$ARCH" = "sh" ; then
>>> tryflag CFLAGS_AUTO -Wa,--isa=any
>>> trycppif __BIG_ENDIAN__ "$t" && SUBARCH=${SUBARCH}eb
>>> diff --git a/crt/riscv32/crti.s b/crt/riscv32/crti.s
>>> new file mode 100644
>>> index 0000000..6916bfd
>>> --- /dev/null
>>> +++ b/crt/riscv32/crti.s
>>> @@ -0,0 +1,11 @@
>>> +.section .init
>>> +.global _init
>>> +.type _init,%function
>>> +_init:
>>> +        ret
>>> +
>>> +.section .fini
>>> +.global _fini
>>> +.type _fini,%function
>>> +_fini:
>>> +        ret
>>> diff --git a/crt/riscv32/crtn.s b/crt/riscv32/crtn.s
>>> new file mode 100644
>>> index 0000000..e69de29
>> 
>> It looks like these are not used, right?
>> 
>>> diff --git a/include/elf.h b/include/elf.h
>>> index c229735..ec2e8fd 100644
>>> --- a/include/elf.h
>>> +++ b/include/elf.h
>>> @@ -3164,6 +3164,62 @@ enum
>>> #define R_BPF_NONE        0
>>> #define R_BPF_MAP_FD        1
>>> 
>>> +#define R_RISCV_NONE            0
>>> +#define R_RISCV_32              1
>>> +#define R_RISCV_64              2
>>> +#define R_RISCV_RELATIVE        3
>>> +#define R_RISCV_COPY            4
>>> +#define R_RISCV_JUMP_SLOT       5
>>> +#define R_RISCV_TLS_DTPMOD32    6
>>> +#define R_RISCV_TLS_DTPMOD64    7
>>> +#define R_RISCV_TLS_DTPREL32    8
>>> +#define R_RISCV_TLS_DTPREL64    9
>>> +#define R_RISCV_TLS_TPREL32     10
>>> +#define R_RISCV_TLS_TPREL64     11
>>> +
>>> +#define R_RISCV_BRANCH          16
>>> +#define R_RISCV_JAL             17
>>> +#define R_RISCV_CALL            18
>>> +#define R_RISCV_CALL_PLT        19
>>> +#define R_RISCV_GOT_HI20        20
>>> +#define R_RISCV_TLS_GOT_HI20    21
>>> +#define R_RISCV_TLS_GD_HI20     22
>>> +#define R_RISCV_PCREL_HI20      23
>>> +#define R_RISCV_PCREL_LO12_I    24
>>> +#define R_RISCV_PCREL_LO12_S    25
>>> +#define R_RISCV_HI20            26
>>> +#define R_RISCV_LO12_I          27
>>> +#define R_RISCV_LO12_S          28
>>> +#define R_RISCV_TPREL_HI20      29
>>> +#define R_RISCV_TPREL_LO12_I    30
>>> +#define R_RISCV_TPREL_LO12_S    31
>>> +#define R_RISCV_TPREL_ADD       32
>>> +#define R_RISCV_ADD8            33
>>> +#define R_RISCV_ADD16           34
>>> +#define R_RISCV_ADD32           35
>>> +#define R_RISCV_ADD64           36
>>> +#define R_RISCV_SUB8            37
>>> +#define R_RISCV_SUB16           38
>>> +#define R_RISCV_SUB32           39
>>> +#define R_RISCV_SUB64           40
>>> +#define R_RISCV_GNU_VTINHERIT   41
>>> +#define R_RISCV_GNU_VTENTRY     42
>>> +#define R_RISCV_ALIGN           43
>>> +#define R_RISCV_RVC_BRANCH      44
>>> +#define R_RISCV_RVC_JUMP        45
>>> +#define R_RISCV_RVC_LUI         46
>>> +#define R_RISCV_GPREL_I         47
>>> +#define R_RISCV_GPREL_S         48
>>> +#define R_RISCV_TPREL_I         49
>>> +#define R_RISCV_TPREL_S         50
>>> +#define R_RISCV_RELAX           51
>>> +#define R_RISCV_SUB6            52
>>> +#define R_RISCV_SET6            53
>>> +#define R_RISCV_SET8            54
>>> +#define R_RISCV_SET16           55
>>> +#define R_RISCV_SET32           56
>>> +#define R_RISCV_32_PCREL        57
>>> +
>>> #ifdef __cplusplus
>>> }
>>> #endif
>> 
>> This should be its own patch independent of the port; I can commit it
>> earlier.
>> 
>>> diff --git a/src/thread/riscv32/syscall_cp.s b/src/thread/riscv32/syscall_cp.s
>>> new file mode 100644
>>> index 0000000..71bf6d3
>>> --- /dev/null
>>> +++ b/src/thread/riscv32/syscall_cp.s
>>> @@ -0,0 +1,29 @@
>>> +.global __cp_begin
>>> +.hidden __cp_begin
>>> +.global __cp_end
>>> +.hidden __cp_end
>>> +.global __cp_cancel
>>> +.hidden __cp_cancel
>>> +.hidden __cancel
>>> +.global __syscall_cp_asm
>>> +.hidden __syscall_cp_asm
>>> +.type __syscall_cp_asm, %function
>>> +__syscall_cp_asm:
>>> +__cp_begin:
>>> +        lw t0, 0(a0)
>>> +        bnez t0, __cp_cancel
>>> +
>>> +        mv t0, a1
>>> +        mv a0, a2
>>> +        mv a1, a3
>>> +        mv a2, a4
>>> +        mv a3, a5
>>> +        mv a4, a6
>>> +        mv a5, a7
>>> +        lw a6, 0(sp)
>>> +        mv a7, t0
>>> +        scall
>>> +__cp_cancel:
>>> +        ret
>>> +__cp_end:
>>> +        j __cancel
>> 
>> The labels here are backwards. __cp_end must point immediately after
>> the syscall instruction, and __cp_end needs to jump to __cancel.
>> 
>>> diff --git a/src/thread/riscv64/syscall_cp.s b/src/thread/riscv64/syscall_cp.s
>>> new file mode 100644
>>> index 0000000..c745b32
>>> --- /dev/null
>>> +++ b/src/thread/riscv64/syscall_cp.s
>>> @@ -0,0 +1,29 @@
>>> +.global __cp_begin
>>> +.hidden __cp_begin
>>> +.global __cp_end
>>> +.hidden __cp_end
>>> +.global __cp_cancel
>>> +.hidden __cp_cancel
>>> +.hidden __cancel
>>> +.global __syscall_cp_asm
>>> +.hidden __syscall_cp_asm
>>> +.type __syscall_cp_asm, %function
>>> +__syscall_cp_asm:
>>> +__cp_begin:
>>> +        ld t0, 0(a0)
>>> +        bnez t0, __cp_cancel
>>> +
>>> +        mv t0, a1
>>> +        mv a0, a2
>>> +        mv a1, a3
>>> +        mv a2, a4
>>> +        mv a3, a5
>>> +        mv a4, a6
>>> +        mv a5, a7
>>> +        ld a6, 0(sp)
>>> +        mv a7, t0
>>> +        scall
>>> +__cp_cancel:
>>> +        ret
>>> +__cp_end:
>>> +        j __cancel
>>> -- 
>>> 2.10.0
>>> 
>> 
>> Likewise here.
>> 
>> Rich
Khem Raj Oct. 10, 2018, 1:14 a.m.
On Tue, Oct 9, 2018 at 2:36 PM Michael Clark <michaeljclark@mac.com> wrote:
>
> Hi,
>
> I have a status update. I haven’t made any changes to the musl port since last week but I did investigate and fix the stat issue in qemu-riscv32. I ran tests with riscv32 Linux kernel with glibc in QEMU full system emulation as Linux kernel is canonical for the ABI.
>
> riscv32 is indeed a unique port in linux-kernel land. It does not define __ARCH_WANT_STAT64 in arch/riscv/include/asm/unistd.h (unlike all other 32-bit ports which confused me a bit). It does not have fstat64 and its stat structure matches rv64. I’m kind of stubborn so I had to see the test pass/fail so I spent some time getting riscv32 linux to build. I should submit a couple of small patches for riscv-linux.
>
> I fixed riscv32 stat in riscv-qemu: https://github.com/riscv/riscv-qemu
>
> RISC-V QEMU had the 32-bit asm-generic which has a 32-bit stat, but no fstat64. We may have missed a chunk when we rebased the 2016 riscv-qemu baseline. The stat patch is in qemu-for-upstream branch in the riscv-qemu branch.
>
> We need to work on getting our QEMU changes upstream. We have problems with getting code into upstream QEMU as they have very strict code review policy on pull requests. Every commit must have “Reviewed-by:” with a “trusted reviewer”. It doesn’t seem to prevent changes coming from Linaro breaking the RISC-V port but it does prevent our fixes going in. My current focus is working on automated test cases for the fixes in the QEMU queue so we can change the discourse to does it pass an extensive set of tests. Currently the baseline for inclusion is does it compile and passes “make check”, have Reviewed-by and Signed-off-by tags and does it conform to the QEMU coding style (checkpatch.pl). The issue is we are making changes that typically require reading the Privileged ISA manual for verification and we don’t have high test case coverage for the Privileged ISA. The Base ISA has pretty good test coverage.
>
> I would be happy if someone volunteered to help with the RISC-V musl port...

Thanks Michael, its on my TODO list after ELCE, I have setup OE builds
already, but need to cherry-pick your patches and test a
core-image-minimal to start the process.

>
> Michael
>
> On 10/10/2018, at 7:05 AM, Rich Felker <dalias@libc.org> wrote:
>
> Ping.
>
> On Thu, Sep 27, 2018 at 10:46:33PM -0400, Rich Felker wrote:
>
> On Thu, Sep 27, 2018 at 10:24:04PM -0400, Rich Felker wrote:
>
> Pulled from here:
>
> https://github.com/riscv/riscv-musl/commit/6a4f4a9c774608add4b02f95322518bd2f5f51ee
>
>
> Attached for review.
>
>
> Review inline below:
>
>
> diff --git a/arch/riscv32/atomic_arch.h b/arch/riscv32/atomic_arch.h
>
> new file mode 100644
>
> index 0000000..93c89cc
>
> --- /dev/null
>
> +++ b/arch/riscv32/atomic_arch.h
>
> @@ -0,0 +1,35 @@
>
> +#define a_barrier a_barrier
>
> +static inline void a_barrier()
>
> +{
>
> +    __asm__ __volatile__ ("fence rw,rw" : : : "memory");
>
> +}
>
> +
>
> +#define a_ll a_ll
>
> +static inline int a_ll(volatile int *p)
>
> +{
>
> +    int v;
>
> +    __asm__ __volatile__ ("lr.w %0, (%1)" : "=&r"(v) : "r"(p));
>
> +    return v;
>
> +}
>
> +
>
> +#define a_sc a_sc
>
> +static inline int a_sc(volatile int *p, int v)
>
> +{
>
> +    int r;
>
> +    __asm__ __volatile__ ("sc.w %0, %2, (%1)" : "=&r"(r) : "r"(p), "r"(v) : "memory");
>
> +    return !r;
>
> +}
>
> +
>
> +#define a_cas a_cas
>
> +static inline int a_cas(volatile int *p, int t, int s)
>
> +{
>
> +    int old, tmp;
>
> +    __asm__("1:  lr.w    %0, %2      \n"
>
> +        "    bne     %0, %3, 1f  \n"
>
> +        "    sc.w    %1, %4, %2  \n"
>
> +        "    bnez    %1, 1b      \n"
>
> +        "1:                      \n"
>
> +        : "=&r"(old), "+r"(tmp), "+A"(*p)
>
> +        : "r"(t), "r"(s));
>
> +    return old;
>
> +}
>
>
> Why are both a_ll/a_sc and a_cas defined, and why is a_cas missing
>
> barriers? Normally if a_ll/a_sc/a_barrier are defined, the top-level
>
> atomic.h should be allowed to generate a_cas in terms of them.
>
>
> diff --git a/arch/riscv32/bits/signal.h b/arch/riscv32/bits/signal.h
>
> new file mode 100644
>
> index 0000000..8b992cc
>
> --- /dev/null
>
> +++ b/arch/riscv32/bits/signal.h
>
> @@ -0,0 +1,113 @@
>
> +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
>
> + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
>
> +
>
> +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
>
> +# define MINSIGSTKSZ 2048
>
> +# define SIGSTKSZ 8192
>
> +#endif
>
> +
>
> +/* gregs[0] holds the program counter. */
>
> +
>
> +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
>
> +typedef unsigned long greg_t;
>
> +typedef unsigned long gregset_t[32];
>
> +
>
> +struct __riscv_f_ext_state {
>
> +    unsigned int f[32];
>
> +    unsigned int fcsr;
>
> +};
>
> +
>
> +struct __riscv_d_ext_state {
>
> +    unsigned long long f[32];
>
> +    unsigned int fcsr;
>
> +};
>
> +
>
> +struct __riscv_q_ext_state {
>
> +    unsigned long long f[64] __attribute__((aligned(16)));
>
> +    unsigned int fcsr;
>
> +    unsigned int reserved[3];
>
> +};
>
> +
>
> +union __riscv_fp_state {
>
> +    struct __riscv_f_ext_state f;
>
> +    struct __riscv_d_ext_state d;
>
> +    struct __riscv_q_ext_state q;
>
> +};
>
> +
>
> +typedef union __riscv_fp_state fpregset_t;
>
> +
>
> +typedef struct sigcontext {
>
> +    gregset_t gregs;
>
> +    fpregset_t fpregs;
>
> +} mcontext_t;
>
> +
>
> +#else
>
> +typedef struct {
>
> +    unsigned long gregs[32];
>
> +    unsigned long long fpregs[66];
>
> +} mcontext_t;
>
> +#endif
>
>
> In the namespace-safe version of mcontext_t, the names gregs and
>
> fpregs are not valid here. They would need to be __-prefixed or in
>
> some other reserved namespace.
>
>
> +struct sigaltstack {
>
> +    void *ss_sp;
>
> +    int ss_flags;
>
> +    size_t ss_size;
>
> +};
>
> +
>
> +typedef struct __ucontext
>
> +{
>
> +    unsigned long uc_flags;
>
> +    struct __ucontext *uc_link;
>
> +    stack_t uc_stack;
>
> +    sigset_t uc_sigmask;
>
> +    char __unused[1024 / 8 - sizeof(sigset_t)];
>
>
> This is an invalid array of size zero and should just be removed.
>
>
> +    mcontext_t uc_mcontext;
>
> +} ucontext_t;
>
>
> ....
>
>
> diff --git a/arch/riscv32/crt_arch.h b/arch/riscv32/crt_arch.h
>
> new file mode 100644
>
> index 0000000..65187e1
>
> --- /dev/null
>
> +++ b/arch/riscv32/crt_arch.h
>
> @@ -0,0 +1,18 @@
>
> +__asm__(
>
> +".text\n"
>
> +".global " START "\n"
>
> +".type " START ",%function\n"
>
> +START ":\n"
>
> +".weak __global_pointer$\n"
>
> +".hidden __global_pointer$\n\t"
>
> +".option push\n"
>
> +".option norelax\n\t"
>
> +"lla gp, __global_pointer$\n"
>
> +".option pop\n\t"
>
> +"mv a0, sp\n"
>
> +".weak _DYNAMIC\n"
>
> +".hidden _DYNAMIC\n\t"
>
> +"lla a1, _DYNAMIC\n\t"
>
> +"andi sp, sp, -16\n\t"
>
> +"jal " START "_c"
>
> +);
>
> diff --git a/arch/riscv32/pthread_arch.h b/arch/riscv32/pthread_arch.h
>
> new file mode 100644
>
> index 0000000..feffaa4
>
> --- /dev/null
>
> +++ b/arch/riscv32/pthread_arch.h
>
> @@ -0,0 +1,12 @@
>
> +static inline struct pthread *__pthread_self()
>
> +{
>
> +    char *tp;
>
> +    __asm__ __volatile__("mv %0, tp" : "=r"(tp));
>
> +    return (void *)(tp - sizeof(struct pthread));
>
> +}
>
> +
>
> +#define TLS_ABOVE_TP
>
> +#define GAP_ABOVE_TP 0
>
> +#define TP_ADJ(p) ((char *)p + sizeof(struct pthread))
>
> +
>
> +#define MC_PC gregs[0]
>
> diff --git a/arch/riscv32/reloc.h b/arch/riscv32/reloc.h
>
> new file mode 100644
>
> index 0000000..d057bbe
>
> --- /dev/null
>
> +++ b/arch/riscv32/reloc.h
>
> @@ -0,0 +1,27 @@
>
> +#if defined __riscv_float_abi_soft
>
> +#define RISCV_FP_SUFFIX "-sf"
>
> +#elif defined __riscv_float_abi_single
>
> +#define RISCV_FP_SUFFIX "-sp"
>
> +#elif defined __riscv_float_abi_double
>
> +#define RISCV_FP_SUFFIX ""
>
> +#endif
>
> +
>
> +#define RISCV_LDSO_HELPER(x) "riscv" #x
>
> +#define RISCV_LDSO(x) RISCV_LDSO_HELPER(x)
>
> +
>
> +#define LDSO_ARCH RISCV_LDSO(__riscv_xlen) RISCV_FP_SUFFIX
>
>
> Elsewhere it looks like little/big endian are both options, but I see
>
> no endian variant here. If so this needs to be fixed.
>
>
> Also what is __riscv_xlen? A predefined macro that expands to 32 or
>
> 64? Since this file is just for 32-bit it should just be hard-coded
>
> rather than assuming a macro would expand to the token 32 and not
>
> (31+1) or some other expression equal to 32, I think.
>
>
> diff --git a/arch/riscv32/syscall_arch.h b/arch/riscv32/syscall_arch.h
>
> new file mode 100644
>
> index 0000000..bc60d1f
>
> --- /dev/null
>
> +++ b/arch/riscv32/syscall_arch.h
>
> @@ -0,0 +1,78 @@
>
> +#define __SYSCALL_LL_E(x) \
>
> +((union { long long ll; long l[2]; }){ .ll = x }).l[0], \
>
> +((union { long long ll; long l[2]; }){ .ll = x }).l[1]
>
> +#define __SYSCALL_LL_O(x) 0, __SYSCALL_LL_E((x))
>
> +
>
> +#define __asm_syscall(...) \
>
> +    __asm__ __volatile__ ("scall\n\t" \
>
> +    : "+r"(a0) : __VA_ARGS__ : "memory"); \
>
> +    return a0; \
>
> +
>
> +static inline long __syscall0(long n)
>
> +{
>
> +    register long a7 __asm__("a7") = n;
>
> +    register long a0 __asm__("a0");
>
> +    __asm_syscall("r"(a7))
>
> +}
>
> +
>
> +static inline long __syscall1(long n, long a)
>
> +{
>
> +    register long a7 __asm__("a7") = n;
>
> +    register long a0 __asm__("a0") = a;
>
> +    __asm_syscall("r"(a7), "0"(a0))
>
> +}
>
> +
>
> +static inline long __syscall2(long n, long a, long b)
>
> +{
>
> +    register long a7 __asm__("a7") = n;
>
> +    register long a0 __asm__("a0") = a;
>
> +    register long a1 __asm__("a1") = b;
>
> +    __asm_syscall("r"(a7), "0"(a0), "r"(a1))
>
> +}
>
> +
>
> +static inline long __syscall3(long n, long a, long b, long c)
>
> +{
>
> +    register long a7 __asm__("a7") = n;
>
> +    register long a0 __asm__("a0") = a;
>
> +    register long a1 __asm__("a1") = b;
>
> +    register long a2 __asm__("a2") = c;
>
> +    __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2))
>
> +}
>
> +
>
> +static inline long __syscall4(long n, long a, long b, long c, long d)
>
> +{
>
> +    register long a7 __asm__("a7") = n;
>
> +    register long a0 __asm__("a0") = a;
>
> +    register long a1 __asm__("a1") = b;
>
> +    register long a2 __asm__("a2") = c;
>
> +    register long a3 __asm__("a3") = d;
>
> +    __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3))
>
> +}
>
> +
>
> +static inline long __syscall5(long n, long a, long b, long c, long d, long e)
>
> +{
>
> +    register long a7 __asm__("a7") = n;
>
> +    register long a0 __asm__("a0") = a;
>
> +    register long a1 __asm__("a1") = b;
>
> +    register long a2 __asm__("a2") = c;
>
> +    register long a3 __asm__("a3") = d;
>
> +    register long a4 __asm__("a4") = e;
>
> +    __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4))
>
> +}
>
> +
>
> +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
>
> +{
>
> +    register long a7 __asm__("a7") = n;
>
> +    register long a0 __asm__("a0") = a;
>
> +    register long a1 __asm__("a1") = b;
>
> +    register long a2 __asm__("a2") = c;
>
> +    register long a3 __asm__("a3") = d;
>
> +    register long a4 __asm__("a4") = e;
>
> +    register long a5 __asm__("a5") = f;
>
> +    __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5))
>
> +}
>
> +
>
> +#define VDSO_USEFUL
>
> +/* We don't have a clock_gettime function.
>
> +#define VDSO_CGT_SYM "__vdso_clock_gettime"
>
> +#define VDSO_CGT_VER "LINUX_2.6" */
>
>
> In that case VDSO_USEFUL might as well also be omitted for now.
>
>
> diff --git a/arch/riscv64/atomic_arch.h b/arch/riscv64/atomic_arch.h
>
> new file mode 100644
>
> index 0000000..018c7fd
>
> --- /dev/null
>
> +++ b/arch/riscv64/atomic_arch.h
>
> @@ -0,0 +1,66 @@
>
> +#define a_barrier a_barrier
>
> +static inline void a_barrier()
>
> +{
>
> +    __asm__ __volatile__ ("fence rw,rw" : : : "memory");
>
> +}
>
> +
>
> +#define a_ll a_ll
>
> +static inline int a_ll(volatile int *p)
>
> +{
>
> +    int v;
>
> +    __asm__ __volatile__ ("lr.w %0, %1" : "=&r"(v), "+A"(*p));
>
> +    return v;
>
> +}
>
> +
>
> +#define a_sc a_sc
>
> +static inline int a_sc(volatile int *p, int v)
>
> +{
>
> +    int r;
>
> +    __asm__ __volatile__ ("sc.w %0, %2, %1" : "=&r"(r), "+A"(*p) : "r"(v) : "memory");
>
> +return !r;
>
> +}
>
> +
>
> +#define a_cas a_cas
>
> +static inline int a_cas(volatile int *p, int t, int s)
>
> +{
>
> +    int old, tmp;
>
> +    __asm__("1:  lr.w    %0, %2      \n"
>
> +        "    bne     %0, %3, 1f  \n"
>
> +        "    sc.w    %1, %4, %2  \n"
>
> +        "    bnez    %1, 1b      \n"
>
> +        "1:                      \n"
>
> +        : "=&r"(old), "+r"(tmp), "+A"(*p)
>
> +        : "r"(t), "r"(s));
>
> +    return old;
>
> +}
>
> +
>
> +#define a_ll_p a_ll_p
>
> +static inline void *a_ll_p(volatile void *p)
>
> +{
>
> +    void *v;
>
> +    __asm__ __volatile__ ("lr.d %0, %1" : "=&r"(v), "+A"(*(long *)p));
>
> +    return v;
>
> +}
>
> +
>
> +#define a_sc_p a_sc_p
>
> +static inline int a_sc_p(volatile int *p, void *v)
>
> +{
>
> +    int r;
>
> +    __asm__ __volatile__ ("sc.d %0, %2, %1" : "=&r"(r), "+A"(*(long *)p) : "r"(v) : "memory");
>
> +    return !r;
>
> +}
>
> +
>
> +#define a_cas_p a_cas_p
>
> +static inline void *a_cas_p(volatile void *p, void *t, void *s)
>
> +{
>
> +    void *old;
>
> +    int tmp;
>
> +    __asm__("1:  lr.d    %0, %2      \n"
>
> +        "    bne     %0, %3, 1f  \n"
>
> +        "    sc.d    %1, %4, %2  \n"
>
> +        "    bnez    %1, 1b      \n"
>
> +        "1:                      \n"
>
> +        : "=&r"(old), "+r"(tmp), "+A"(*(long *)p)
>
> +        : "r"(t), "r"(s));
>
> +    return old;
>
> +}
>
>
> Same comments about cas vs ll/sc, and lack of barrier, as 32-bit version.
>
>
> diff --git a/arch/riscv64/bits/signal.h b/arch/riscv64/bits/signal.h
>
> new file mode 100644
>
> index 0000000..8b992cc
>
> --- /dev/null
>
> +++ b/arch/riscv64/bits/signal.h
>
> @@ -0,0 +1,113 @@
>
> +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
>
> + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
>
> +
>
> +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
>
> +# define MINSIGSTKSZ 2048
>
> +# define SIGSTKSZ 8192
>
> +#endif
>
> +
>
> +/* gregs[0] holds the program counter. */
>
> +
>
> +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
>
> +typedef unsigned long greg_t;
>
> +typedef unsigned long gregset_t[32];
>
> +
>
> +struct __riscv_f_ext_state {
>
> +    unsigned int f[32];
>
> +    unsigned int fcsr;
>
> +};
>
> +
>
> +struct __riscv_d_ext_state {
>
> +    unsigned long long f[32];
>
> +    unsigned int fcsr;
>
> +};
>
> +
>
> +struct __riscv_q_ext_state {
>
> +    unsigned long long f[64] __attribute__((aligned(16)));
>
> +    unsigned int fcsr;
>
> +    unsigned int reserved[3];
>
> +};
>
> +
>
> +union __riscv_fp_state {
>
> +    struct __riscv_f_ext_state f;
>
> +    struct __riscv_d_ext_state d;
>
> +    struct __riscv_q_ext_state q;
>
> +};
>
> +
>
> +typedef union __riscv_fp_state fpregset_t;
>
> +
>
> +typedef struct sigcontext {
>
> +    gregset_t gregs;
>
> +    fpregset_t fpregs;
>
> +} mcontext_t;
>
> +
>
> +#else
>
> +typedef struct {
>
> +    unsigned long gregs[32];
>
> +    unsigned long long fpregs[66];
>
> +} mcontext_t;
>
> +#endif
>
> +
>
> +struct sigaltstack {
>
> +    void *ss_sp;
>
> +    int ss_flags;
>
> +    size_t ss_size;
>
> +};
>
> +
>
> +typedef struct __ucontext
>
> +{
>
> +    unsigned long uc_flags;
>
> +    struct __ucontext *uc_link;
>
> +    stack_t uc_stack;
>
> +    sigset_t uc_sigmask;
>
> +    char __unused[1024 / 8 - sizeof(sigset_t)];
>
> +    mcontext_t uc_mcontext;
>
> +} ucontext_t;
>
>
> Same issues here as 32-bit.
>
>
> diff --git a/arch/riscv64/reloc.h b/arch/riscv64/reloc.h
>
> new file mode 100644
>
> index 0000000..8bd90dd
>
> --- /dev/null
>
> +++ b/arch/riscv64/reloc.h
>
> @@ -0,0 +1,27 @@
>
> +#if defined __riscv_float_abi_soft
>
> +#define RISCV_FP_SUFFIX "-sf"
>
> +#elif defined __riscv_float_abi_single
>
> +#define RISCV_FP_SUFFIX "-sp"
>
> +#elif defined __riscv_float_abi_double
>
> +#define RISCV_FP_SUFFIX ""
>
> +#endif
>
> +
>
> +#define RISCV_LDSO_HELPER(x) "riscv" #x
>
> +#define RISCV_LDSO(x) RISCV_LDSO_HELPER(x)
>
> +
>
> +#define LDSO_ARCH RISCV_LDSO(__riscv_xlen) RISCV_FP_SUFFIX
>
>
> Same here.
>
>
> diff --git a/configure b/configure
>
> index 997e665..4d3d8b4 100755
>
> --- a/configure
>
> +++ b/configure
>
> @@ -322,6 +322,8 @@ microblaze*) ARCH=microblaze ;;
>
> or1k*) ARCH=or1k ;;
>
> powerpc64*) ARCH=powerpc64 ;;
>
> powerpc*) ARCH=powerpc ;;
>
> +riscv64*) ARCH=riscv64 ;;
>
> +riscv*) ARCH=riscv32 ;;
>
> sh[1-9bel-]*|sh|superh*) ARCH=sh ;;
>
> s390x*) ARCH=s390x ;;
>
> unknown) fail "$0: unable to detect target arch; try $0 --target=..." ;;
>
> @@ -640,6 +642,11 @@ trycppif __LITTLE_ENDIAN__ "$t" && SUBARCH=${SUBARCH}le
>
> trycppif _SOFT_FLOAT "$t" && fail "$0: error: soft-float not supported on powerpc64"
>
> fi
>
>
> +if test "$ARCH" = "riscv" || test "$ARCH" = "riscv64" ; then
>
> +trycppif "RISCVEB || _RISCVEB || __RISCVEB || __RISCVEB__" "$t" && SUBARCH=${SUBARCH}eb
>
>
> Predefined macros that violate the namespace (RISCVEB) shouldn't be
>
> defined or observed.
>
>
> +trycppif __riscv_soft_float "$t" && SUBARCH=${SUBARCH}-sf
>
> +fi
>
> +
>
> if test "$ARCH" = "sh" ; then
>
> tryflag CFLAGS_AUTO -Wa,--isa=any
>
> trycppif __BIG_ENDIAN__ "$t" && SUBARCH=${SUBARCH}eb
>
> diff --git a/crt/riscv32/crti.s b/crt/riscv32/crti.s
>
> new file mode 100644
>
> index 0000000..6916bfd
>
> --- /dev/null
>
> +++ b/crt/riscv32/crti.s
>
> @@ -0,0 +1,11 @@
>
> +.section .init
>
> +.global _init
>
> +.type _init,%function
>
> +_init:
>
> +        ret
>
> +
>
> +.section .fini
>
> +.global _fini
>
> +.type _fini,%function
>
> +_fini:
>
> +        ret
>
> diff --git a/crt/riscv32/crtn.s b/crt/riscv32/crtn.s
>
> new file mode 100644
>
> index 0000000..e69de29
>
>
> It looks like these are not used, right?
>
>
> diff --git a/include/elf.h b/include/elf.h
>
> index c229735..ec2e8fd 100644
>
> --- a/include/elf.h
>
> +++ b/include/elf.h
>
> @@ -3164,6 +3164,62 @@ enum
>
> #define R_BPF_NONE        0
>
> #define R_BPF_MAP_FD        1
>
>
> +#define R_RISCV_NONE            0
>
> +#define R_RISCV_32              1
>
> +#define R_RISCV_64              2
>
> +#define R_RISCV_RELATIVE        3
>
> +#define R_RISCV_COPY            4
>
> +#define R_RISCV_JUMP_SLOT       5
>
> +#define R_RISCV_TLS_DTPMOD32    6
>
> +#define R_RISCV_TLS_DTPMOD64    7
>
> +#define R_RISCV_TLS_DTPREL32    8
>
> +#define R_RISCV_TLS_DTPREL64    9
>
> +#define R_RISCV_TLS_TPREL32     10
>
> +#define R_RISCV_TLS_TPREL64     11
>
> +
>
> +#define R_RISCV_BRANCH          16
>
> +#define R_RISCV_JAL             17
>
> +#define R_RISCV_CALL            18
>
> +#define R_RISCV_CALL_PLT        19
>
> +#define R_RISCV_GOT_HI20        20
>
> +#define R_RISCV_TLS_GOT_HI20    21
>
> +#define R_RISCV_TLS_GD_HI20     22
>
> +#define R_RISCV_PCREL_HI20      23
>
> +#define R_RISCV_PCREL_LO12_I    24
>
> +#define R_RISCV_PCREL_LO12_S    25
>
> +#define R_RISCV_HI20            26
>
> +#define R_RISCV_LO12_I          27
>
> +#define R_RISCV_LO12_S          28
>
> +#define R_RISCV_TPREL_HI20      29
>
> +#define R_RISCV_TPREL_LO12_I    30
>
> +#define R_RISCV_TPREL_LO12_S    31
>
> +#define R_RISCV_TPREL_ADD       32
>
> +#define R_RISCV_ADD8            33
>
> +#define R_RISCV_ADD16           34
>
> +#define R_RISCV_ADD32           35
>
> +#define R_RISCV_ADD64           36
>
> +#define R_RISCV_SUB8            37
>
> +#define R_RISCV_SUB16           38
>
> +#define R_RISCV_SUB32           39
>
> +#define R_RISCV_SUB64           40
>
> +#define R_RISCV_GNU_VTINHERIT   41
>
> +#define R_RISCV_GNU_VTENTRY     42
>
> +#define R_RISCV_ALIGN           43
>
> +#define R_RISCV_RVC_BRANCH      44
>
> +#define R_RISCV_RVC_JUMP        45
>
> +#define R_RISCV_RVC_LUI         46
>
> +#define R_RISCV_GPREL_I         47
>
> +#define R_RISCV_GPREL_S         48
>
> +#define R_RISCV_TPREL_I         49
>
> +#define R_RISCV_TPREL_S         50
>
> +#define R_RISCV_RELAX           51
>
> +#define R_RISCV_SUB6            52
>
> +#define R_RISCV_SET6            53
>
> +#define R_RISCV_SET8            54
>
> +#define R_RISCV_SET16           55
>
> +#define R_RISCV_SET32           56
>
> +#define R_RISCV_32_PCREL        57
>
> +
>
> #ifdef __cplusplus
>
> }
>
> #endif
>
>
> This should be its own patch independent of the port; I can commit it
>
> earlier.
>
>
> diff --git a/src/thread/riscv32/syscall_cp.s b/src/thread/riscv32/syscall_cp.s
>
> new file mode 100644
>
> index 0000000..71bf6d3
>
> --- /dev/null
>
> +++ b/src/thread/riscv32/syscall_cp.s
>
> @@ -0,0 +1,29 @@
>
> +.global __cp_begin
>
> +.hidden __cp_begin
>
> +.global __cp_end
>
> +.hidden __cp_end
>
> +.global __cp_cancel
>
> +.hidden __cp_cancel
>
> +.hidden __cancel
>
> +.global __syscall_cp_asm
>
> +.hidden __syscall_cp_asm
>
> +.type __syscall_cp_asm, %function
>
> +__syscall_cp_asm:
>
> +__cp_begin:
>
> +        lw t0, 0(a0)
>
> +        bnez t0, __cp_cancel
>
> +
>
> +        mv t0, a1
>
> +        mv a0, a2
>
> +        mv a1, a3
>
> +        mv a2, a4
>
> +        mv a3, a5
>
> +        mv a4, a6
>
> +        mv a5, a7
>
> +        lw a6, 0(sp)
>
> +        mv a7, t0
>
> +        scall
>
> +__cp_cancel:
>
> +        ret
>
> +__cp_end:
>
> +        j __cancel
>
>
> The labels here are backwards. __cp_end must point immediately after
>
> the syscall instruction, and __cp_end needs to jump to __cancel.
>
>
> diff --git a/src/thread/riscv64/syscall_cp.s b/src/thread/riscv64/syscall_cp.s
>
> new file mode 100644
>
> index 0000000..c745b32
>
> --- /dev/null
>
> +++ b/src/thread/riscv64/syscall_cp.s
>
> @@ -0,0 +1,29 @@
>
> +.global __cp_begin
>
> +.hidden __cp_begin
>
> +.global __cp_end
>
> +.hidden __cp_end
>
> +.global __cp_cancel
>
> +.hidden __cp_cancel
>
> +.hidden __cancel
>
> +.global __syscall_cp_asm
>
> +.hidden __syscall_cp_asm
>
> +.type __syscall_cp_asm, %function
>
> +__syscall_cp_asm:
>
> +__cp_begin:
>
> +        ld t0, 0(a0)
>
> +        bnez t0, __cp_cancel
>
> +
>
> +        mv t0, a1
>
> +        mv a0, a2
>
> +        mv a1, a3
>
> +        mv a2, a4
>
> +        mv a3, a5
>
> +        mv a4, a6
>
> +        mv a5, a7
>
> +        ld a6, 0(sp)
>
> +        mv a7, t0
>
> +        scall
>
> +__cp_cancel:
>
> +        ret
>
> +__cp_end:
>
> +        j __cancel
>
> --
>
> 2.10.0
>
>
>
> Likewise here.
>
>
> Rich
Michael Clark Oct. 10, 2018, 3:41 a.m.
> On 10/10/2018, at 2:14 PM, Khem Raj <raj.khem@gmail.com> wrote:
> 
>> On Tue, Oct 9, 2018 at 2:36 PM Michael Clark <michaeljclark@mac.com> wrote:
>> 
>> Hi,
>> 
>> I have a status update. I haven’t made any changes to the musl port since last week but I did investigate and fix the stat issue in qemu-riscv32. I ran tests with riscv32 Linux kernel with glibc in QEMU full system emulation as Linux kernel is canonical for the ABI.
>> 
>> riscv32 is indeed a unique port in linux-kernel land. It does not define __ARCH_WANT_STAT64 in arch/riscv/include/asm/unistd.h (unlike all other 32-bit ports which confused me a bit). It does not have fstat64 and its stat structure matches rv64. I’m kind of stubborn so I had to see the test pass/fail so I spent some time getting riscv32 linux to build. I should submit a couple of small patches for riscv-linux.
>> 
>> I fixed riscv32 stat in riscv-qemu: https://github.com/riscv/riscv-qemu
>> 
>> RISC-V QEMU had the 32-bit asm-generic which has a 32-bit stat, but no fstat64. We may have missed a chunk when we rebased the 2016 riscv-qemu baseline. The stat patch is in qemu-for-upstream branch in the riscv-qemu branch.
>> 
>> We need to work on getting our QEMU changes upstream. We have problems with getting code into upstream QEMU as they have very strict code review policy on pull requests. Every commit must have “Reviewed-by:” with a “trusted reviewer”. It doesn’t seem to prevent changes coming from Linaro breaking the RISC-V port but it does prevent our fixes going in. My current focus is working on automated test cases for the fixes in the QEMU queue so we can change the discourse to does it pass an extensive set of tests. Currently the baseline for inclusion is does it compile and passes “make check”, have Reviewed-by and Signed-off-by tags and does it conform to the QEMU coding style (checkpatch.pl). The issue is we are making changes that typically require reading the Privileged ISA manual for verification and we don’t have high test case coverage for the Privileged ISA. The Base ISA has pretty good test coverage.
>> 
>> I would be happy if someone volunteered to help with the RISC-V musl port...
> 
> Thanks Michael, its on my TODO list after ELCE, I have setup OE builds
> already, but need to cherry-pick your patches and test a
> core-image-minimal to start the process.

Awesome! Thanks.

I’ve squashed everything to make it easy to cherry-pick (a habit for work-in-progress code). There was a bit of patch churn during some testing and alignment with glibc/Linux. I tend to squash patch churn like this; when moving between trees. Fortunately it is easy with musl’s layout because it is pretty much restricted to arch/riscv32 and arch/riscv64

Of course for changes this approach can make it harder for reviewers. I actually think GitHub adds some value here. I like to see the code as a whole, not as a context diff.

It can be split appropriately when the time comes. It does make one consider our view of history. Fortunately I think we are in the hands of good custodians...

Hopefully we don’t have to split it up into 100 different patches. Maybe we will. Who knows... I haven’t actually checked the whitespace is conforming or not.

>> Michael
>> 
>> On 10/10/2018, at 7:05 AM, Rich Felker <dalias@libc.org> wrote:
>> 
>> Ping.
>> 
>> On Thu, Sep 27, 2018 at 10:46:33PM -0400, Rich Felker wrote:
>> 
>> On Thu, Sep 27, 2018 at 10:24:04PM -0400, Rich Felker wrote:
>> 
>> Pulled from here:
>> 
>> https://github.com/riscv/riscv-musl/commit/6a4f4a9c774608add4b02f95322518bd2f5f51ee
>> 
>> 
>> Attached for review.
>> 
>> 
>> Review inline below:
>> 
>> 
>> diff --git a/arch/riscv32/atomic_arch.h b/arch/riscv32/atomic_arch.h
>> 
>> new file mode 100644
>> 
>> index 0000000..93c89cc
>> 
>> --- /dev/null
>> 
>> +++ b/arch/riscv32/atomic_arch.h
>> 
>> @@ -0,0 +1,35 @@
>> 
>> +#define a_barrier a_barrier
>> 
>> +static inline void a_barrier()
>> 
>> +{
>> 
>> +    __asm__ __volatile__ ("fence rw,rw" : : : "memory");
>> 
>> +}
>> 
>> +
>> 
>> +#define a_ll a_ll
>> 
>> +static inline int a_ll(volatile int *p)
>> 
>> +{
>> 
>> +    int v;
>> 
>> +    __asm__ __volatile__ ("lr.w %0, (%1)" : "=&r"(v) : "r"(p));
>> 
>> +    return v;
>> 
>> +}
>> 
>> +
>> 
>> +#define a_sc a_sc
>> 
>> +static inline int a_sc(volatile int *p, int v)
>> 
>> +{
>> 
>> +    int r;
>> 
>> +    __asm__ __volatile__ ("sc.w %0, %2, (%1)" : "=&r"(r) : "r"(p), "r"(v) : "memory");
>> 
>> +    return !r;
>> 
>> +}
>> 
>> +
>> 
>> +#define a_cas a_cas
>> 
>> +static inline int a_cas(volatile int *p, int t, int s)
>> 
>> +{
>> 
>> +    int old, tmp;
>> 
>> +    __asm__("1:  lr.w    %0, %2      \n"
>> 
>> +        "    bne     %0, %3, 1f  \n"
>> 
>> +        "    sc.w    %1, %4, %2  \n"
>> 
>> +        "    bnez    %1, 1b      \n"
>> 
>> +        "1:                      \n"
>> 
>> +        : "=&r"(old), "+r"(tmp), "+A"(*p)
>> 
>> +        : "r"(t), "r"(s));
>> 
>> +    return old;
>> 
>> +}
>> 
>> 
>> Why are both a_ll/a_sc and a_cas defined, and why is a_cas missing
>> 
>> barriers? Normally if a_ll/a_sc/a_barrier are defined, the top-level
>> 
>> atomic.h should be allowed to generate a_cas in terms of them.
>> 
>> 
>> diff --git a/arch/riscv32/bits/signal.h b/arch/riscv32/bits/signal.h
>> 
>> new file mode 100644
>> 
>> index 0000000..8b992cc
>> 
>> --- /dev/null
>> 
>> +++ b/arch/riscv32/bits/signal.h
>> 
>> @@ -0,0 +1,113 @@
>> 
>> +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
>> 
>> + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
>> 
>> +
>> 
>> +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
>> 
>> +# define MINSIGSTKSZ 2048
>> 
>> +# define SIGSTKSZ 8192
>> 
>> +#endif
>> 
>> +
>> 
>> +/* gregs[0] holds the program counter. */
>> 
>> +
>> 
>> +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
>> 
>> +typedef unsigned long greg_t;
>> 
>> +typedef unsigned long gregset_t[32];
>> 
>> +
>> 
>> +struct __riscv_f_ext_state {
>> 
>> +    unsigned int f[32];
>> 
>> +    unsigned int fcsr;
>> 
>> +};
>> 
>> +
>> 
>> +struct __riscv_d_ext_state {
>> 
>> +    unsigned long long f[32];
>> 
>> +    unsigned int fcsr;
>> 
>> +};
>> 
>> +
>> 
>> +struct __riscv_q_ext_state {
>> 
>> +    unsigned long long f[64] __attribute__((aligned(16)));
>> 
>> +    unsigned int fcsr;
>> 
>> +    unsigned int reserved[3];
>> 
>> +};
>> 
>> +
>> 
>> +union __riscv_fp_state {
>> 
>> +    struct __riscv_f_ext_state f;
>> 
>> +    struct __riscv_d_ext_state d;
>> 
>> +    struct __riscv_q_ext_state q;
>> 
>> +};
>> 
>> +
>> 
>> +typedef union __riscv_fp_state fpregset_t;
>> 
>> +
>> 
>> +typedef struct sigcontext {
>> 
>> +    gregset_t gregs;
>> 
>> +    fpregset_t fpregs;
>> 
>> +} mcontext_t;
>> 
>> +
>> 
>> +#else
>> 
>> +typedef struct {
>> 
>> +    unsigned long gregs[32];
>> 
>> +    unsigned long long fpregs[66];
>> 
>> +} mcontext_t;
>> 
>> +#endif
>> 
>> 
>> In the namespace-safe version of mcontext_t, the names gregs and
>> 
>> fpregs are not valid here. They would need to be __-prefixed or in
>> 
>> some other reserved namespace.
>> 
>> 
>> +struct sigaltstack {
>> 
>> +    void *ss_sp;
>> 
>> +    int ss_flags;
>> 
>> +    size_t ss_size;
>> 
>> +};
>> 
>> +
>> 
>> +typedef struct __ucontext
>> 
>> +{
>> 
>> +    unsigned long uc_flags;
>> 
>> +    struct __ucontext *uc_link;
>> 
>> +    stack_t uc_stack;
>> 
>> +    sigset_t uc_sigmask;
>> 
>> +    char __unused[1024 / 8 - sizeof(sigset_t)];
>> 
>> 
>> This is an invalid array of size zero and should just be removed.
>> 
>> 
>> +    mcontext_t uc_mcontext;
>> 
>> +} ucontext_t;
>> 
>> 
>> ....
>> 
>> 
>> diff --git a/arch/riscv32/crt_arch.h b/arch/riscv32/crt_arch.h
>> 
>> new file mode 100644
>> 
>> index 0000000..65187e1
>> 
>> --- /dev/null
>> 
>> +++ b/arch/riscv32/crt_arch.h
>> 
>> @@ -0,0 +1,18 @@
>> 
>> +__asm__(
>> 
>> +".text\n"
>> 
>> +".global " START "\n"
>> 
>> +".type " START ",%function\n"
>> 
>> +START ":\n"
>> 
>> +".weak __global_pointer$\n"
>> 
>> +".hidden __global_pointer$\n\t"
>> 
>> +".option push\n"
>> 
>> +".option norelax\n\t"
>> 
>> +"lla gp, __global_pointer$\n"
>> 
>> +".option pop\n\t"
>> 
>> +"mv a0, sp\n"
>> 
>> +".weak _DYNAMIC\n"
>> 
>> +".hidden _DYNAMIC\n\t"
>> 
>> +"lla a1, _DYNAMIC\n\t"
>> 
>> +"andi sp, sp, -16\n\t"
>> 
>> +"jal " START "_c"
>> 
>> +);
>> 
>> diff --git a/arch/riscv32/pthread_arch.h b/arch/riscv32/pthread_arch.h
>> 
>> new file mode 100644
>> 
>> index 0000000..feffaa4
>> 
>> --- /dev/null
>> 
>> +++ b/arch/riscv32/pthread_arch.h
>> 
>> @@ -0,0 +1,12 @@
>> 
>> +static inline struct pthread *__pthread_self()
>> 
>> +{
>> 
>> +    char *tp;
>> 
>> +    __asm__ __volatile__("mv %0, tp" : "=r"(tp));
>> 
>> +    return (void *)(tp - sizeof(struct pthread));
>> 
>> +}
>> 
>> +
>> 
>> +#define TLS_ABOVE_TP
>> 
>> +#define GAP_ABOVE_TP 0
>> 
>> +#define TP_ADJ(p) ((char *)p + sizeof(struct pthread))
>> 
>> +
>> 
>> +#define MC_PC gregs[0]
>> 
>> diff --git a/arch/riscv32/reloc.h b/arch/riscv32/reloc.h
>> 
>> new file mode 100644
>> 
>> index 0000000..d057bbe
>> 
>> --- /dev/null
>> 
>> +++ b/arch/riscv32/reloc.h
>> 
>> @@ -0,0 +1,27 @@
>> 
>> +#if defined __riscv_float_abi_soft
>> 
>> +#define RISCV_FP_SUFFIX "-sf"
>> 
>> +#elif defined __riscv_float_abi_single
>> 
>> +#define RISCV_FP_SUFFIX "-sp"
>> 
>> +#elif defined __riscv_float_abi_double
>> 
>> +#define RISCV_FP_SUFFIX ""
>> 
>> +#endif
>> 
>> +
>> 
>> +#define RISCV_LDSO_HELPER(x) "riscv" #x
>> 
>> +#define RISCV_LDSO(x) RISCV_LDSO_HELPER(x)
>> 
>> +
>> 
>> +#define LDSO_ARCH RISCV_LDSO(__riscv_xlen) RISCV_FP_SUFFIX
>> 
>> 
>> Elsewhere it looks like little/big endian are both options, but I see
>> 
>> no endian variant here. If so this needs to be fixed.
>> 
>> 
>> Also what is __riscv_xlen? A predefined macro that expands to 32 or
>> 
>> 64? Since this file is just for 32-bit it should just be hard-coded
>> 
>> rather than assuming a macro would expand to the token 32 and not
>> 
>> (31+1) or some other expression equal to 32, I think.
>> 
>> 
>> diff --git a/arch/riscv32/syscall_arch.h b/arch/riscv32/syscall_arch.h
>> 
>> new file mode 100644
>> 
>> index 0000000..bc60d1f
>> 
>> --- /dev/null
>> 
>> +++ b/arch/riscv32/syscall_arch.h
>> 
>> @@ -0,0 +1,78 @@
>> 
>> +#define __SYSCALL_LL_E(x) \
>> 
>> +((union { long long ll; long l[2]; }){ .ll = x }).l[0], \
>> 
>> +((union { long long ll; long l[2]; }){ .ll = x }).l[1]
>> 
>> +#define __SYSCALL_LL_O(x) 0, __SYSCALL_LL_E((x))
>> 
>> +
>> 
>> +#define __asm_syscall(...) \
>> 
>> +    __asm__ __volatile__ ("scall\n\t" \
>> 
>> +    : "+r"(a0) : __VA_ARGS__ : "memory"); \
>> 
>> +    return a0; \
>> 
>> +
>> 
>> +static inline long __syscall0(long n)
>> 
>> +{
>> 
>> +    register long a7 __asm__("a7") = n;
>> 
>> +    register long a0 __asm__("a0");
>> 
>> +    __asm_syscall("r"(a7))
>> 
>> +}
>> 
>> +
>> 
>> +static inline long __syscall1(long n, long a)
>> 
>> +{
>> 
>> +    register long a7 __asm__("a7") = n;
>> 
>> +    register long a0 __asm__("a0") = a;
>> 
>> +    __asm_syscall("r"(a7), "0"(a0))
>> 
>> +}
>> 
>> +
>> 
>> +static inline long __syscall2(long n, long a, long b)
>> 
>> +{
>> 
>> +    register long a7 __asm__("a7") = n;
>> 
>> +    register long a0 __asm__("a0") = a;
>> 
>> +    register long a1 __asm__("a1") = b;
>> 
>> +    __asm_syscall("r"(a7), "0"(a0), "r"(a1))
>> 
>> +}
>> 
>> +
>> 
>> +static inline long __syscall3(long n, long a, long b, long c)
>> 
>> +{
>> 
>> +    register long a7 __asm__("a7") = n;
>> 
>> +    register long a0 __asm__("a0") = a;
>> 
>> +    register long a1 __asm__("a1") = b;
>> 
>> +    register long a2 __asm__("a2") = c;
>> 
>> +    __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2))
>> 
>> +}
>> 
>> +
>> 
>> +static inline long __syscall4(long n, long a, long b, long c, long d)
>> 
>> +{
>> 
>> +    register long a7 __asm__("a7") = n;
>> 
>> +    register long a0 __asm__("a0") = a;
>> 
>> +    register long a1 __asm__("a1") = b;
>> 
>> +    register long a2 __asm__("a2") = c;
>> 
>> +    register long a3 __asm__("a3") = d;
>> 
>> +    __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3))
>> 
>> +}
>> 
>> +
>> 
>> +static inline long __syscall5(long n, long a, long b, long c, long d, long e)
>> 
>> +{
>> 
>> +    register long a7 __asm__("a7") = n;
>> 
>> +    register long a0 __asm__("a0") = a;
>> 
>> +    register long a1 __asm__("a1") = b;
>> 
>> +    register long a2 __asm__("a2") = c;
>> 
>> +    register long a3 __asm__("a3") = d;
>> 
>> +    register long a4 __asm__("a4") = e;
>> 
>> +    __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4))
>> 
>> +}
>> 
>> +
>> 
>> +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
>> 
>> +{
>> 
>> +    register long a7 __asm__("a7") = n;
>> 
>> +    register long a0 __asm__("a0") = a;
>> 
>> +    register long a1 __asm__("a1") = b;
>> 
>> +    register long a2 __asm__("a2") = c;
>> 
>> +    register long a3 __asm__("a3") = d;
>> 
>> +    register long a4 __asm__("a4") = e;
>> 
>> +    register long a5 __asm__("a5") = f;
>> 
>> +    __asm_syscall("r"(a7), "0"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5))
>> 
>> +}
>> 
>> +
>> 
>> +#define VDSO_USEFUL
>> 
>> +/* We don't have a clock_gettime function.
>> 
>> +#define VDSO_CGT_SYM "__vdso_clock_gettime"
>> 
>> +#define VDSO_CGT_VER "LINUX_2.6" */
>> 
>> 
>> In that case VDSO_USEFUL might as well also be omitted for now.
>> 
>> 
>> diff --git a/arch/riscv64/atomic_arch.h b/arch/riscv64/atomic_arch.h
>> 
>> new file mode 100644
>> 
>> index 0000000..018c7fd
>> 
>> --- /dev/null
>> 
>> +++ b/arch/riscv64/atomic_arch.h
>> 
>> @@ -0,0 +1,66 @@
>> 
>> +#define a_barrier a_barrier
>> 
>> +static inline void a_barrier()
>> 
>> +{
>> 
>> +    __asm__ __volatile__ ("fence rw,rw" : : : "memory");
>> 
>> +}
>> 
>> +
>> 
>> +#define a_ll a_ll
>> 
>> +static inline int a_ll(volatile int *p)
>> 
>> +{
>> 
>> +    int v;
>> 
>> +    __asm__ __volatile__ ("lr.w %0, %1" : "=&r"(v), "+A"(*p));
>> 
>> +    return v;
>> 
>> +}
>> 
>> +
>> 
>> +#define a_sc a_sc
>> 
>> +static inline int a_sc(volatile int *p, int v)
>> 
>> +{
>> 
>> +    int r;
>> 
>> +    __asm__ __volatile__ ("sc.w %0, %2, %1" : "=&r"(r), "+A"(*p) : "r"(v) : "memory");
>> 
>> +return !r;
>> 
>> +}
>> 
>> +
>> 
>> +#define a_cas a_cas
>> 
>> +static inline int a_cas(volatile int *p, int t, int s)
>> 
>> +{
>> 
>> +    int old, tmp;
>> 
>> +    __asm__("1:  lr.w    %0, %2      \n"
>> 
>> +        "    bne     %0, %3, 1f  \n"
>> 
>> +        "    sc.w    %1, %4, %2  \n"
>> 
>> +        "    bnez    %1, 1b      \n"
>> 
>> +        "1:                      \n"
>> 
>> +        : "=&r"(old), "+r"(tmp), "+A"(*p)
>> 
>> +        : "r"(t), "r"(s));
>> 
>> +    return old;
>> 
>> +}
>> 
>> +
>> 
>> +#define a_ll_p a_ll_p
>> 
>> +static inline void *a_ll_p(volatile void *p)
>> 
>> +{
>> 
>> +    void *v;
>> 
>> +    __asm__ __volatile__ ("lr.d %0, %1" : "=&r"(v), "+A"(*(long *)p));
>> 
>> +    return v;
>> 
>> +}
>> 
>> +
>> 
>> +#define a_sc_p a_sc_p
>> 
>> +static inline int a_sc_p(volatile int *p, void *v)
>> 
>> +{
>> 
>> +    int r;
>> 
>> +    __asm__ __volatile__ ("sc.d %0, %2, %1" : "=&r"(r), "+A"(*(long *)p) : "r"(v) : "memory");
>> 
>> +    return !r;
>> 
>> +}
>> 
>> +
>> 
>> +#define a_cas_p a_cas_p
>> 
>> +static inline void *a_cas_p(volatile void *p, void *t, void *s)
>> 
>> +{
>> 
>> +    void *old;
>> 
>> +    int tmp;
>> 
>> +    __asm__("1:  lr.d    %0, %2      \n"
>> 
>> +        "    bne     %0, %3, 1f  \n"
>> 
>> +        "    sc.d    %1, %4, %2  \n"
>> 
>> +        "    bnez    %1, 1b      \n"
>> 
>> +        "1:                      \n"
>> 
>> +        : "=&r"(old), "+r"(tmp), "+A"(*(long *)p)
>> 
>> +        : "r"(t), "r"(s));
>> 
>> +    return old;
>> 
>> +}
>> 
>> 
>> Same comments about cas vs ll/sc, and lack of barrier, as 32-bit version.
>> 
>> 
>> diff --git a/arch/riscv64/bits/signal.h b/arch/riscv64/bits/signal.h
>> 
>> new file mode 100644
>> 
>> index 0000000..8b992cc
>> 
>> --- /dev/null
>> 
>> +++ b/arch/riscv64/bits/signal.h
>> 
>> @@ -0,0 +1,113 @@
>> 
>> +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
>> 
>> + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
>> 
>> +
>> 
>> +#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
>> 
>> +# define MINSIGSTKSZ 2048
>> 
>> +# define SIGSTKSZ 8192
>> 
>> +#endif
>> 
>> +
>> 
>> +/* gregs[0] holds the program counter. */
>> 
>> +
>> 
>> +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
>> 
>> +typedef unsigned long greg_t;
>> 
>> +typedef unsigned long gregset_t[32];
>> 
>> +
>> 
>> +struct __riscv_f_ext_state {
>> 
>> +    unsigned int f[32];
>> 
>> +    unsigned int fcsr;
>> 
>> +};
>> 
>> +
>> 
>> +struct __riscv_d_ext_state {
>> 
>> +    unsigned long long f[32];
>> 
>> +    unsigned int fcsr;
>> 
>> +};
>> 
>> +
>> 
>> +struct __riscv_q_ext_state {
>> 
>> +    unsigned long long f[64] __attribute__((aligned(16)));
>> 
>> +    unsigned int fcsr;
>> 
>> +    unsigned int reserved[3];
>> 
>> +};
>> 
>> +
>> 
>> +union __riscv_fp_state {
>> 
>> +    struct __riscv_f_ext_state f;
>> 
>> +    struct __riscv_d_ext_state d;
>> 
>> +    struct __riscv_q_ext_state q;
>> 
>> +};
>> 
>> +
>> 
>> +typedef union __riscv_fp_state fpregset_t;
>> 
>> +
>> 
>> +typedef struct sigcontext {
>> 
>> +    gregset_t gregs;
>> 
>> +    fpregset_t fpregs;
>> 
>> +} mcontext_t;
>> 
>> +
>> 
>> +#else
>> 
>> +typedef struct {
>> 
>> +    unsigned long gregs[32];
>> 
>> +    unsigned long long fpregs[66];
>> 
>> +} mcontext_t;
>> 
>> +#endif
>> 
>> +
>> 
>> +struct sigaltstack {
>> 
>> +    void *ss_sp;
>> 
>> +    int ss_flags;
>> 
>> +    size_t ss_size;
>> 
>> +};
>> 
>> +
>> 
>> +typedef struct __ucontext
>> 
>> +{
>> 
>> +    unsigned long uc_flags;
>> 
>> +    struct __ucontext *uc_link;
>> 
>> +    stack_t uc_stack;
>> 
>> +    sigset_t uc_sigmask;
>> 
>> +    char __unused[1024 / 8 - sizeof(sigset_t)];
>> 
>> +    mcontext_t uc_mcontext;
>> 
>> +} ucontext_t;
>> 
>> 
>> Same issues here as 32-bit.
>> 
>> 
>> diff --git a/arch/riscv64/reloc.h b/arch/riscv64/reloc.h
>> 
>> new file mode 100644
>> 
>> index 0000000..8bd90dd
>> 
>> --- /dev/null
>> 
>> +++ b/arch/riscv64/reloc.h
>> 
>> @@ -0,0 +1,27 @@
>> 
>> +#if defined __riscv_float_abi_soft
>> 
>> +#define RISCV_FP_SUFFIX "-sf"
>> 
>> +#elif defined __riscv_float_abi_single
>> 
>> +#define RISCV_FP_SUFFIX "-sp"
>> 
>> +#elif defined __riscv_float_abi_double
>> 
>> +#define RISCV_FP_SUFFIX ""
>> 
>> +#endif
>> 
>> +
>> 
>> +#define RISCV_LDSO_HELPER(x) "riscv" #x
>> 
>> +#define RISCV_LDSO(x) RISCV_LDSO_HELPER(x)
>> 
>> +
>> 
>> +#define LDSO_ARCH RISCV_LDSO(__riscv_xlen) RISCV_FP_SUFFIX
>> 
>> 
>> Same here.
>> 
>> 
>> diff --git a/configure b/configure
>> 
>> index 997e665..4d3d8b4 100755
>> 
>> --- a/configure
>> 
>> +++ b/configure
>> 
>> @@ -322,6 +322,8 @@ microblaze*) ARCH=microblaze ;;
>> 
>> or1k*) ARCH=or1k ;;
>> 
>> powerpc64*) ARCH=powerpc64 ;;
>> 
>> powerpc*) ARCH=powerpc ;;
>> 
>> +riscv64*) ARCH=riscv64 ;;
>> 
>> +riscv*) ARCH=riscv32 ;;
>> 
>> sh[1-9bel-]*|sh|superh*) ARCH=sh ;;
>> 
>> s390x*) ARCH=s390x ;;
>> 
>> unknown) fail "$0: unable to detect target arch; try $0 --target=..." ;;
>> 
>> @@ -640,6 +642,11 @@ trycppif __LITTLE_ENDIAN__ "$t" && SUBARCH=${SUBARCH}le
>> 
>> trycppif _SOFT_FLOAT "$t" && fail "$0: error: soft-float not supported on powerpc64"
>> 
>> fi
>> 
>> 
>> +if test "$ARCH" = "riscv" || test "$ARCH" = "riscv64" ; then
>> 
>> +trycppif "RISCVEB || _RISCVEB || __RISCVEB || __RISCVEB__" "$t" && SUBARCH=${SUBARCH}eb
>> 
>> 
>> Predefined macros that violate the namespace (RISCVEB) shouldn't be
>> 
>> defined or observed.
>> 
>> 
>> +trycppif __riscv_soft_float "$t" && SUBARCH=${SUBARCH}-sf
>> 
>> +fi
>> 
>> +
>> 
>> if test "$ARCH" = "sh" ; then
>> 
>> tryflag CFLAGS_AUTO -Wa,--isa=any
>> 
>> trycppif __BIG_ENDIAN__ "$t" && SUBARCH=${SUBARCH}eb
>> 
>> diff --git a/crt/riscv32/crti.s b/crt/riscv32/crti.s
>> 
>> new file mode 100644
>> 
>> index 0000000..6916bfd
>> 
>> --- /dev/null
>> 
>> +++ b/crt/riscv32/crti.s
>> 
>> @@ -0,0 +1,11 @@
>> 
>> +.section .init
>> 
>> +.global _init
>> 
>> +.type _init,%function
>> 
>> +_init:
>> 
>> +        ret
>> 
>> +
>> 
>> +.section .fini
>> 
>> +.global _fini
>> 
>> +.type _fini,%function
>> 
>> +_fini:
>> 
>> +        ret
>> 
>> diff --git a/crt/riscv32/crtn.s b/crt/riscv32/crtn.s
>> 
>> new file mode 100644
>> 
>> index 0000000..e69de29
>> 
>> 
>> It looks like these are not used, right?
>> 
>> 
>> diff --git a/include/elf.h b/include/elf.h
>> 
>> index c229735..ec2e8fd 100644
>> 
>> --- a/include/elf.h
>> 
>> +++ b/include/elf.h
>> 
>> @@ -3164,6 +3164,62 @@ enum
>> 
>> #define R_BPF_NONE        0
>> 
>> #define R_BPF_MAP_FD        1
>> 
>> 
>> +#define R_RISCV_NONE            0
>> 
>> +#define R_RISCV_32              1
>> 
>> +#define R_RISCV_64              2
>> 
>> +#define R_RISCV_RELATIVE        3
>> 
>> +#define R_RISCV_COPY            4
>> 
>> +#define R_RISCV_JUMP_SLOT       5
>> 
>> +#define R_RISCV_TLS_DTPMOD32    6
>> 
>> +#define R_RISCV_TLS_DTPMOD64    7
>> 
>> +#define R_RISCV_TLS_DTPREL32    8
>> 
>> +#define R_RISCV_TLS_DTPREL64    9
>> 
>> +#define R_RISCV_TLS_TPREL32     10
>> 
>> +#define R_RISCV_TLS_TPREL64     11
>> 
>> +
>> 
>> +#define R_RISCV_BRANCH          16
>> 
>> +#define R_RISCV_JAL             17
>> 
>> +#define R_RISCV_CALL            18
>> 
>> +#define R_RISCV_CALL_PLT        19
>> 
>> +#define R_RISCV_GOT_HI20        20
>> 
>> +#define R_RISCV_TLS_GOT_HI20    21
>> 
>> +#define R_RISCV_TLS_GD_HI20     22
>> 
>> +#define R_RISCV_PCREL_HI20      23
>> 
>> +#define R_RISCV_PCREL_LO12_I    24
>> 
>> +#define R_RISCV_PCREL_LO12_S    25
>> 
>> +#define R_RISCV_HI20            26
>> 
>> +#define R_RISCV_LO12_I          27
>> 
>> +#define R_RISCV_LO12_S          28
>> 
>> +#define R_RISCV_TPREL_HI20      29
>> 
>> +#define R_RISCV_TPREL_LO12_I    30
>> 
>> +#define R_RISCV_TPREL_LO12_S    31
>> 
>> +#define R_RISCV_TPREL_ADD       32
>> 
>> +#define R_RISCV_ADD8            33
>> 
>> +#define R_RISCV_ADD16           34
>> 
>> +#define R_RISCV_ADD32           35
>> 
>> +#define R_RISCV_ADD64           36
>> 
>> +#define R_RISCV_SUB8            37
>> 
>> +#define R_RISCV_SUB16           38
>> 
>> +#define R_RISCV_SUB32           39
>> 
>> +#define R_RISCV_SUB64           40
>> 
>> +#define R_RISCV_GNU_VTINHERIT   41
>> 
>> +#define R_RISCV_GNU_VTENTRY     42
>> 
>> +#define R_RISCV_ALIGN           43
>> 
>> +#define R_RISCV_RVC_BRANCH      44
>> 
>> +#define R_RISCV_RVC_JUMP        45
>> 
>> +#define R_RISCV_RVC_LUI         46
>> 
>> +#define R_RISCV_GPREL_I         47
>> 
>> +#define R_RISCV_GPREL_S         48
>> 
>> +#define R_RISCV_TPREL_I         49
>> 
>> +#define R_RISCV_TPREL_S         50
>> 
>> +#define R_RISCV_RELAX           51
>> 
>> +#define R_RISCV_SUB6            52
>> 
>> +#define R_RISCV_SET6            53
>> 
>> +#define R_RISCV_SET8            54
>> 
>> +#define R_RISCV_SET16           55
>> 
>> +#define R_RISCV_SET32           56
>> 
>> +#define R_RISCV_32_PCREL        57
>> 
>> +
>> 
>> #ifdef __cplusplus
>> 
>> }
>> 
>> #endif
>> 
>> 
>> This should be its own patch independent of the port; I can commit it
>> 
>> earlier.
>> 
>> 
>> diff --git a/src/thread/riscv32/syscall_cp.s b/src/thread/riscv32/syscall_cp.s
>> 
>> new file mode 100644
>> 
>> index 0000000..71bf6d3
>> 
>> --- /dev/null
>> 
>> +++ b/src/thread/riscv32/syscall_cp.s
>> 
>> @@ -0,0 +1,29 @@
>> 
>> +.global __cp_begin
>> 
>> +.hidden __cp_begin
>> 
>> +.global __cp_end
>> 
>> +.hidden __cp_end
>> 
>> +.global __cp_cancel
>> 
>> +.hidden __cp_cancel
>> 
>> +.hidden __cancel
>> 
>> +.global __syscall_cp_asm
>> 
>> +.hidden __syscall_cp_asm
>> 
>> +.type __syscall_cp_asm, %function
>> 
>> +__syscall_cp_asm:
>> 
>> +__cp_begin:
>> 
>> +        lw t0, 0(a0)
>> 
>> +        bnez t0, __cp_cancel
>> 
>> +
>> 
>> +        mv t0, a1
>> 
>> +        mv a0, a2
>> 
>> +        mv a1, a3
>> 
>> +        mv a2, a4
>> 
>> +        mv a3, a5
>> 
>> +        mv a4, a6
>> 
>> +        mv a5, a7
>> 
>> +        lw a6, 0(sp)
>> 
>> +        mv a7, t0
>> 
>> +        scall
>> 
>> +__cp_cancel:
>> 
>> +        ret
>> 
>> +__cp_end:
>> 
>> +        j __cancel
>> 
>> 
>> The labels here are backwards. __cp_end must point immediately after
>> 
>> the syscall instruction, and __cp_end needs to jump to __cancel.
>> 
>> 
>> diff --git a/src/thread/riscv64/syscall_cp.s b/src/thread/riscv64/syscall_cp.s
>> 
>> new file mode 100644
>> 
>> index 0000000..c745b32
>> 
>> --- /dev/null
>> 
>> +++ b/src/thread/riscv64/syscall_cp.s
>> 
>> @@ -0,0 +1,29 @@
>> 
>> +.global __cp_begin
>> 
>> +.hidden __cp_begin
>> 
>> +.global __cp_end
>> 
>> +.hidden __cp_end
>> 
>> +.global __cp_cancel
>> 
>> +.hidden __cp_cancel
>> 
>> +.hidden __cancel
>> 
>> +.global __syscall_cp_asm
>> 
>> +.hidden __syscall_cp_asm
>> 
>> +.type __syscall_cp_asm, %function
>> 
>> +__syscall_cp_asm:
>> 
>> +__cp_begin:
>> 
>> +        ld t0, 0(a0)
>> 
>> +        bnez t0, __cp_cancel
>> 
>> +
>> 
>> +        mv t0, a1
>> 
>> +        mv a0, a2
>> 
>> +        mv a1, a3
>> 
>> +        mv a2, a4
>> 
>> +        mv a3, a5
>> 
>> +        mv a4, a6
>> 
>> +        mv a5, a7
>> 
>> +        ld a6, 0(sp)
>> 
>> +        mv a7, t0
>> 
>> +        scall
>> 
>> +__cp_cancel:
>> 
>> +        ret
>> 
>> +__cp_end:
>> 
>> +        j __cancel
>> 
>> --
>> 
>> 2.10.0
>> 
>> 
>> 
>> Likewise here.
>> 
>> 
>> Rich
Michael Forney Oct. 11, 2018, 7:34 a.m.
On 2018-09-27, Rich Felker <dalias@libc.org> wrote:
> Pulled from here:
> https://github.com/riscv/riscv-musl/commit/6a4f4a9c774608add4b02f95322518bd2f5f51ee
>
> Attached for review.

I noticed that some fcntl.h constants are incorrect (O_DIRECTORY,
O_NOFOLLOW, O_DIRECT, O_LARGEFILE, and O_TMPFILE). Linux doesn't seem
to have a riscv-specific fcntl.h, so I think they just come from
asm-generic.
Rich Felker Oct. 11, 2018, 3:49 p.m.
On Thu, Oct 11, 2018 at 12:34:40AM -0700, Michael Forney wrote:
> On 2018-09-27, Rich Felker <dalias@libc.org> wrote:
> > Pulled from here:
> > https://github.com/riscv/riscv-musl/commit/6a4f4a9c774608add4b02f95322518bd2f5f51ee
> >
> > Attached for review.
> 
> I noticed that some fcntl.h constants are incorrect (O_DIRECTORY,
> O_NOFOLLOW, O_DIRECT, O_LARGEFILE, and O_TMPFILE). Linux doesn't seem
> to have a riscv-specific fcntl.h, so I think they just come from
> asm-generic.

If that's the case the riscv32/riscv64 bits/fcntl.h files should just
be removed and the generic one will be used.

Rich