Browse Source

musl: add rv32 support

Patches are under discussion in musl ml, this provides a way to test it
further on Yocto

Signed-off-by: Khem Raj <raj.khem@gmail.com>
Cc: Stefan O'Rear <sorear@fastmail.com>
Khem Raj 3 years ago
parent
commit
21abe9ccf7

+ 28 - 0
recipes-core/musl/musl/0001-Remove-ARMSUBARCH-relic-from-configure.patch

@@ -0,0 +1,28 @@
+From a1139168d22122b014ea8e5102f326426a2c15ba Mon Sep 17 00:00:00 2001
+From: Stefan O'Rear <sorear@fastmail.com>
+Date: Thu, 3 Sep 2020 03:17:45 -0400
+Subject: [PATCH 01/15] Remove ARMSUBARCH relic from configure
+
+---
+ configure | 5 -----
+ 1 file changed, 5 deletions(-)
+
+diff --git a/configure b/configure
+index 9abbbd66..acbfa8f2 100755
+--- a/configure
++++ b/configure
+@@ -727,11 +727,6 @@ fi
+ test "$SUBARCH" \
+ && printf "configured for %s variant: %s\n" "$ARCH" "$ARCH$SUBARCH"
+ 
+-case "$ARCH$SUBARCH" in
+-arm) ASMSUBARCH=el ;;
+-*) ASMSUBARCH=$SUBARCH ;;
+-esac
+-
+ #
+ # Some archs (powerpc) have different possible long double formats
+ # that the compiler can be configured for. The logic for whether this
+-- 
+2.28.0
+

+ 72 - 0
recipes-core/musl/musl/0002-time64-Don-t-make-aliases-to-nonexistent-syscalls.patch

@@ -0,0 +1,72 @@
+From 03d068679c7eff4fadc83fada190671f8f62fa19 Mon Sep 17 00:00:00 2001
+From: Stefan O'Rear <sorear@fastmail.com>
+Date: Thu, 3 Sep 2020 03:27:03 -0400
+Subject: [PATCH 02/15] time64: Don't make aliases to nonexistent syscalls
+
+riscv32 and future architectures lack the _time32 variants entirely, so
+don't try to use their numbers.
+---
+ src/internal/syscall.h | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/src/internal/syscall.h b/src/internal/syscall.h
+index d5f294d4..4f41e1dc 100644
+--- a/src/internal/syscall.h
++++ b/src/internal/syscall.h
+@@ -201,43 +201,43 @@ static inline long __alt_socketcall(int sys, int sock, int cp, long a, long b, l
+ #define SYS_sendfile SYS_sendfile64
+ #endif
+ 
+-#ifndef SYS_timer_settime
++#ifdef SYS_timer_settime32
+ #define SYS_timer_settime SYS_timer_settime32
+ #endif
+ 
+-#ifndef SYS_timer_gettime
++#ifdef SYS_timer_gettime32
+ #define SYS_timer_gettime SYS_timer_gettime32
+ #endif
+ 
+-#ifndef SYS_timerfd_settime
++#ifdef SYS_timerfd_settime32
+ #define SYS_timerfd_settime SYS_timerfd_settime32
+ #endif
+ 
+-#ifndef SYS_timerfd_gettime
++#ifdef SYS_timerfd_gettime32
+ #define SYS_timerfd_gettime SYS_timerfd_gettime32
+ #endif
+ 
+-#ifndef SYS_clock_settime
++#ifdef SYS_clock_settime32
+ #define SYS_clock_settime SYS_clock_settime32
+ #endif
+ 
+-#ifndef SYS_clock_gettime
++#ifdef SYS_clock_gettime32
+ #define SYS_clock_gettime SYS_clock_gettime32
+ #endif
+ 
+-#ifndef SYS_clock_getres
++#ifdef SYS_clock_getres_time32
+ #define SYS_clock_getres SYS_clock_getres_time32
+ #endif
+ 
+-#ifndef SYS_clock_nanosleep
++#ifdef SYS_clock_nanosleep_time32
+ #define SYS_clock_nanosleep SYS_clock_nanosleep_time32
+ #endif
+ 
+-#ifndef SYS_gettimeofday
++#ifdef SYS_gettimeofday_time32
+ #define SYS_gettimeofday SYS_gettimeofday_time32
+ #endif
+ 
+-#ifndef SYS_settimeofday
++#ifdef SYS_settimeofday_time32
+ #define SYS_settimeofday SYS_settimeofday_time32
+ #endif
+ 
+-- 
+2.28.0
+

+ 71 - 0
recipes-core/musl/musl/0003-time64-Only-getrlimit-setrlimit-if-they-exist.patch

@@ -0,0 +1,71 @@
+From b8b6f6ce49bac68e1e953dafde8421f8e33d656b Mon Sep 17 00:00:00 2001
+From: Stefan O'Rear <sorear@fastmail.com>
+Date: Thu, 3 Sep 2020 03:31:05 -0400
+Subject: [PATCH 03/15] time64: Only getrlimit/setrlimit if they exist
+
+riscv32 and future architectures only provide prlimit64.
+---
+ src/misc/getrlimit.c | 6 +++++-
+ src/misc/setrlimit.c | 6 +++++-
+ 2 files changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/src/misc/getrlimit.c b/src/misc/getrlimit.c
+index 2ab2f0f4..bf676307 100644
+--- a/src/misc/getrlimit.c
++++ b/src/misc/getrlimit.c
+@@ -6,12 +6,13 @@
+ 
+ int getrlimit(int resource, struct rlimit *rlim)
+ {
+-	unsigned long k_rlim[2];
+ 	int ret = syscall(SYS_prlimit64, 0, resource, 0, rlim);
+ 	if (!ret) {
+ 		FIX(rlim->rlim_cur);
+ 		FIX(rlim->rlim_max);
+ 	}
++#ifdef SYS_getrlimit
++	unsigned long k_rlim[2];
+ 	if (!ret || errno != ENOSYS)
+ 		return ret;
+ 	if (syscall(SYS_getrlimit, resource, k_rlim) < 0)
+@@ -21,6 +22,9 @@ int getrlimit(int resource, struct rlimit *rlim)
+ 	FIX(rlim->rlim_cur);
+ 	FIX(rlim->rlim_max);
+ 	return 0;
++#else
++	return ret;
++#endif
+ }
+ 
+ weak_alias(getrlimit, getrlimit64);
+diff --git a/src/misc/setrlimit.c b/src/misc/setrlimit.c
+index 7a66ab29..62eba5f3 100644
+--- a/src/misc/setrlimit.c
++++ b/src/misc/setrlimit.c
+@@ -8,7 +8,6 @@
+ 
+ static int __setrlimit(int resource, const struct rlimit *rlim)
+ {
+-	unsigned long k_rlim[2];
+ 	struct rlimit tmp;
+ 	if (SYSCALL_RLIM_INFINITY != RLIM_INFINITY) {
+ 		tmp = *rlim;
+@@ -17,10 +16,15 @@ static int __setrlimit(int resource, const struct rlimit *rlim)
+ 		rlim = &tmp;
+ 	}
+ 	int ret = __syscall(SYS_prlimit64, 0, resource, rlim, 0);
++#ifdef SYS_setrlimit
++	unsigned long k_rlim[2];
+ 	if (ret != -ENOSYS) return ret;
+ 	k_rlim[0] = MIN(rlim->rlim_cur, MIN(-1UL, SYSCALL_RLIM_INFINITY));
+ 	k_rlim[1] = MIN(rlim->rlim_max, MIN(-1UL, SYSCALL_RLIM_INFINITY));
+ 	return __syscall(SYS_setrlimit, resource, k_rlim);
++#else
++	return ret;
++#endif
+ }
+ 
+ struct ctx {
+-- 
+2.28.0
+

+ 46 - 0
recipes-core/musl/musl/0004-time64-Only-gettimeofday-settimeofday-if-exist.patch

@@ -0,0 +1,46 @@
+From bfab18e41795a322f9b05e7f85e909ac8e591baf Mon Sep 17 00:00:00 2001
+From: Stefan O'Rear <sorear@fastmail.com>
+Date: Thu, 3 Sep 2020 03:33:10 -0400
+Subject: [PATCH 04/15] time64: Only gettimeofday/settimeofday if exist
+
+riscv64 and future architectures only provide the clock_ functions.
+---
+ src/time/clock_gettime.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/src/time/clock_gettime.c b/src/time/clock_gettime.c
+index 3e1d0975..c7e66a51 100644
+--- a/src/time/clock_gettime.c
++++ b/src/time/clock_gettime.c
+@@ -80,10 +80,12 @@ int __clock_gettime(clockid_t clk, struct timespec *ts)
+ 		return __syscall_ret(r);
+ 	long ts32[2];
+ 	r = __syscall(SYS_clock_gettime, clk, ts32);
++#ifdef SYS_gettimeofday
+ 	if (r==-ENOSYS && clk==CLOCK_REALTIME) {
+ 		r = __syscall(SYS_gettimeofday, ts32, 0);
+ 		ts32[1] *= 1000;
+ 	}
++#endif
+ 	if (!r) {
+ 		ts->tv_sec = ts32[0];
+ 		ts->tv_nsec = ts32[1];
+@@ -92,6 +94,7 @@ int __clock_gettime(clockid_t clk, struct timespec *ts)
+ 	return __syscall_ret(r);
+ #else
+ 	r = __syscall(SYS_clock_gettime, clk, ts);
++#ifdef SYS_gettimeofday
+ 	if (r == -ENOSYS) {
+ 		if (clk == CLOCK_REALTIME) {
+ 			__syscall(SYS_gettimeofday, ts, 0);
+@@ -100,6 +103,7 @@ int __clock_gettime(clockid_t clk, struct timespec *ts)
+ 		}
+ 		r = -EINVAL;
+ 	}
++#endif
+ 	return __syscall_ret(r);
+ #endif
+ }
+-- 
+2.28.0
+

+ 94 - 0
recipes-core/musl/musl/0005-Add-src-internal-statx.h.patch

@@ -0,0 +1,94 @@
+From 8269f8eb73a17a882260dd60c30429f1eb0a27d8 Mon Sep 17 00:00:00 2001
+From: Stefan O'Rear <sorear@fastmail.com>
+Date: Thu, 3 Sep 2020 03:45:08 -0400
+Subject: [PATCH 05/15] Add src/internal/statx.h
+
+We need to make internal syscalls to SYS_statx when SYS_fstatat is not
+available without changing the musl API.
+---
+ src/internal/statx.h | 28 ++++++++++++++++++++++++++++
+ src/stat/fstatat.c   | 28 ++--------------------------
+ 2 files changed, 30 insertions(+), 26 deletions(-)
+ create mode 100644 src/internal/statx.h
+
+diff --git a/src/internal/statx.h b/src/internal/statx.h
+new file mode 100644
+index 00000000..46b16f62
+--- /dev/null
++++ b/src/internal/statx.h
+@@ -0,0 +1,28 @@
++struct statx {
++	uint32_t stx_mask;
++	uint32_t stx_blksize;
++	uint64_t stx_attributes;
++	uint32_t stx_nlink;
++	uint32_t stx_uid;
++	uint32_t stx_gid;
++	uint16_t stx_mode;
++	uint16_t pad1;
++	uint64_t stx_ino;
++	uint64_t stx_size;
++	uint64_t stx_blocks;
++	uint64_t stx_attributes_mask;
++	struct {
++		int64_t tv_sec;
++		uint32_t tv_nsec;
++		int32_t pad;
++	} stx_atime, stx_btime, stx_ctime, stx_mtime;
++	uint32_t stx_rdev_major;
++	uint32_t stx_rdev_minor;
++	uint32_t stx_dev_major;
++	uint32_t stx_dev_minor;
++	uint64_t spare[14];
++};
++
++#define STATX_TYPE         0x001U
++#define STATX_SIZE         0x200U
++#define STATX_BASIC_STATS  0x7ffU
+diff --git a/src/stat/fstatat.c b/src/stat/fstatat.c
+index de165b5c..230a83fc 100644
+--- a/src/stat/fstatat.c
++++ b/src/stat/fstatat.c
+@@ -7,37 +7,13 @@
+ #include <sys/sysmacros.h>
+ #include "syscall.h"
+ #include "kstat.h"
+-
+-struct statx {
+-	uint32_t stx_mask;
+-	uint32_t stx_blksize;
+-	uint64_t stx_attributes;
+-	uint32_t stx_nlink;
+-	uint32_t stx_uid;
+-	uint32_t stx_gid;
+-	uint16_t stx_mode;
+-	uint16_t pad1;
+-	uint64_t stx_ino;
+-	uint64_t stx_size;
+-	uint64_t stx_blocks;
+-	uint64_t stx_attributes_mask;
+-	struct {
+-		int64_t tv_sec;
+-		uint32_t tv_nsec;
+-		int32_t pad;
+-	} stx_atime, stx_btime, stx_ctime, stx_mtime;
+-	uint32_t stx_rdev_major;
+-	uint32_t stx_rdev_minor;
+-	uint32_t stx_dev_major;
+-	uint32_t stx_dev_minor;
+-	uint64_t spare[14];
+-};
++#include "statx.h"
+ 
+ static int fstatat_statx(int fd, const char *restrict path, struct stat *restrict st, int flag)
+ {
+ 	struct statx stx;
+ 
+-	int ret = __syscall(SYS_statx, fd, path, flag, 0x7ff, &stx);
++	int ret = __syscall(SYS_statx, fd, path, flag, STATX_BASIC_STATS, &stx);
+ 	if (ret) return ret;
+ 
+ 	*st = (struct stat){
+-- 
+2.28.0
+

+ 209 - 0
recipes-core/musl/musl/0006-Only-call-fstatat-if-defined.patch

@@ -0,0 +1,209 @@
+From 018b1b207e771304ea6bd6346c87d1f4115a172f Mon Sep 17 00:00:00 2001
+From: Stefan O'Rear <sorear@fastmail.com>
+Date: Thu, 3 Sep 2020 03:59:59 -0400
+Subject: [PATCH 06/15] Only call fstatat if defined
+
+riscv32 and future architectures lack it.
+---
+ src/stat/fchmodat.c   | 23 ++++++++++++++++++++---
+ src/stat/fstatat.c    |  6 ++++++
+ src/stdio/tempnam.c   |  9 +++++++--
+ src/stdio/tmpnam.c    |  9 +++++++--
+ src/time/__map_file.c | 19 +++++++++++++++----
+ 5 files changed, 55 insertions(+), 11 deletions(-)
+
+diff --git a/src/stat/fchmodat.c b/src/stat/fchmodat.c
+index 4ee00b0a..857e84e5 100644
+--- a/src/stat/fchmodat.c
++++ b/src/stat/fchmodat.c
+@@ -1,8 +1,10 @@
+ #include <sys/stat.h>
+ #include <fcntl.h>
+ #include <errno.h>
++#include <stdint.h>
+ #include "syscall.h"
+ #include "kstat.h"
++#include "statx.h"
+ 
+ int fchmodat(int fd, const char *path, mode_t mode, int flag)
+ {
+@@ -11,13 +13,22 @@ int fchmodat(int fd, const char *path, mode_t mode, int flag)
+ 	if (flag != AT_SYMLINK_NOFOLLOW)
+ 		return __syscall_ret(-EINVAL);
+ 
+-	struct kstat st;
+ 	int ret, fd2;
+ 	char proc[15+3*sizeof(int)];
+ 
++#ifdef SYS_fstatat
++	struct kstat st;
+ 	if ((ret = __syscall(SYS_fstatat, fd, path, &st, flag)))
+ 		return __syscall_ret(ret);
+-	if (S_ISLNK(st.st_mode))
++	mode_t get_mode = st.st_mode;
++#else
++	struct statx st;
++	if ((ret = __syscall(SYS_statx, fd, path, flag, STATX_TYPE, &st)))
++		return __syscall_ret(ret);
++	mode_t get_mode = st.stx_mode;
++#endif
++
++	if (S_ISLNK(get_mode))
+ 		return __syscall_ret(-EOPNOTSUPP);
+ 
+ 	if ((fd2 = __syscall(SYS_openat, fd, path, O_RDONLY|O_PATH|O_NOFOLLOW|O_NOCTTY|O_CLOEXEC)) < 0) {
+@@ -27,9 +38,15 @@ int fchmodat(int fd, const char *path, mode_t mode, int flag)
+ 	}
+ 
+ 	__procfdname(proc, fd2);
++#ifdef SYS_fstatat
+ 	ret = __syscall(SYS_fstatat, AT_FDCWD, proc, &st, 0);
++	get_mode = st.st_mode;
++#else
++	ret = __syscall(SYS_statx, AT_FDCWD, proc, 0, STATX_TYPE, &st);
++	get_mode = st.stx_mode;
++#endif
+ 	if (!ret) {
+-		if (S_ISLNK(st.st_mode)) ret = -EOPNOTSUPP;
++		if (S_ISLNK(get_mode)) ret = -EOPNOTSUPP;
+ 		else ret = __syscall(SYS_fchmodat, AT_FDCWD, proc, mode);
+ 	}
+ 
+diff --git a/src/stat/fstatat.c b/src/stat/fstatat.c
+index 230a83fc..0486f21a 100644
+--- a/src/stat/fstatat.c
++++ b/src/stat/fstatat.c
+@@ -45,6 +45,7 @@ static int fstatat_statx(int fd, const char *restrict path, struct stat *restric
+ 	return 0;
+ }
+ 
++#ifdef SYS_fstatat
+ static int fstatat_kstat(int fd, const char *restrict path, struct stat *restrict st, int flag)
+ {
+ 	int ret;
+@@ -106,15 +107,20 @@ static int fstatat_kstat(int fd, const char *restrict path, struct stat *restric
+ 
+ 	return 0;
+ }
++#endif
+ 
+ int fstatat(int fd, const char *restrict path, struct stat *restrict st, int flag)
+ {
+ 	int ret;
++#ifdef SYS_fstatat
+ 	if (sizeof((struct kstat){0}.st_atime_sec) < sizeof(time_t)) {
+ 		ret = fstatat_statx(fd, path, st, flag);
+ 		if (ret!=-ENOSYS) return __syscall_ret(ret);
+ 	}
+ 	ret = fstatat_kstat(fd, path, st, flag);
++#else
++	ret = fstatat_statx(fd, path, st, flag);
++#endif
+ 	return __syscall_ret(ret);
+ }
+ 
+diff --git a/src/stdio/tempnam.c b/src/stdio/tempnam.c
+index 565df6b6..9469923b 100644
+--- a/src/stdio/tempnam.c
++++ b/src/stdio/tempnam.c
+@@ -5,8 +5,10 @@
+ #include <limits.h>
+ #include <string.h>
+ #include <stdlib.h>
++#include <stdint.h>
+ #include "syscall.h"
+ #include "kstat.h"
++#include "statx.h"
+ 
+ #define MAXTRIES 100
+ 
+@@ -37,11 +39,14 @@ char *tempnam(const char *dir, const char *pfx)
+ 
+ 	for (try=0; try<MAXTRIES; try++) {
+ 		__randname(s+l-6);
+-#ifdef SYS_lstat
++#if defined(SYS_lstat)
+ 		r = __syscall(SYS_lstat, s, &(struct kstat){0});
+-#else
++#elif defined(SYS_fstatat)
+ 		r = __syscall(SYS_fstatat, AT_FDCWD, s,
+ 			&(struct kstat){0}, AT_SYMLINK_NOFOLLOW);
++#else
++		r = __syscall(SYS_statx, AT_FDCWD, s, AT_SYMLINK_NOFOLLOW, 0,
++			&(struct statx){0});
+ #endif
+ 		if (r == -ENOENT) return strdup(s);
+ 	}
+diff --git a/src/stdio/tmpnam.c b/src/stdio/tmpnam.c
+index d667a836..9576241b 100644
+--- a/src/stdio/tmpnam.c
++++ b/src/stdio/tmpnam.c
+@@ -4,8 +4,10 @@
+ #include <sys/stat.h>
+ #include <string.h>
+ #include <stdlib.h>
++#include <stdint.h>
+ #include "syscall.h"
+ #include "kstat.h"
++#include "statx.h"
+ 
+ #define MAXTRIES 100
+ 
+@@ -17,11 +19,14 @@ char *tmpnam(char *buf)
+ 	int r;
+ 	for (try=0; try<MAXTRIES; try++) {
+ 		__randname(s+12);
+-#ifdef SYS_lstat
++#if defined(SYS_lstat)
+ 		r = __syscall(SYS_lstat, s, &(struct kstat){0});
+-#else
++#elif defined(SYS_fstatat)
+ 		r = __syscall(SYS_fstatat, AT_FDCWD, s,
+ 			&(struct kstat){0}, AT_SYMLINK_NOFOLLOW);
++#else
++		r = __syscall(SYS_statx, AT_FDCWD, s, AT_SYMLINK_NOFOLLOW, 0,
++			&(struct statx){0});
+ #endif
+ 		if (r == -ENOENT) return strcpy(buf ? buf : internal, s);
+ 	}
+diff --git a/src/time/__map_file.c b/src/time/__map_file.c
+index d3cefa82..542c8ce4 100644
+--- a/src/time/__map_file.c
++++ b/src/time/__map_file.c
+@@ -1,18 +1,29 @@
++#define _BSD_SOURCE
+ #include <sys/mman.h>
+ #include <fcntl.h>
+ #include <sys/stat.h>
++#include <stdint.h>
+ #include "syscall.h"
+ #include "kstat.h"
++#include "statx.h"
+ 
+ const char unsigned *__map_file(const char *pathname, size_t *size)
+ {
+-	struct kstat st;
+ 	const unsigned char *map = MAP_FAILED;
+ 	int fd = sys_open(pathname, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
+ 	if (fd < 0) return 0;
+-	if (!syscall(SYS_fstat, fd, &st)) {
+-		map = __mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
+-		*size = st.st_size;
++#ifdef SYS_fstat
++	struct kstat st;
++	int r = syscall(SYS_fstat, fd, &st);
++	size_t fsize = st.st_size;
++#else
++	struct statx st;
++	int r = syscall(SYS_statx, fd, "", AT_EMPTY_PATH, STATX_SIZE, &st);
++	size_t fsize = st.stx_size;
++#endif
++	if (!r) {
++		map = __mmap(0, fsize, PROT_READ, MAP_SHARED, fd, 0);
++		*size = fsize;
+ 	}
+ 	__syscall(SYS_close, fd);
+ 	return map == MAP_FAILED ? 0 : map;
+-- 
+2.28.0
+

+ 183 - 0
recipes-core/musl/musl/0007-Emulate-wait4-using-waitid.patch

@@ -0,0 +1,183 @@
+From 121eae5570d791c8c704905f4df2575654faba0b Mon Sep 17 00:00:00 2001
+From: Stefan O'Rear <sorear@fastmail.com>
+Date: Thu, 3 Sep 2020 05:20:45 -0400
+Subject: [PATCH 07/15] Emulate wait4 using waitid
+
+riscv32 and future architectures lack wait4.
+
+waitpid is required by POSIX to be a cancellation point.  pclose is
+specified as undefined if a cancellation occurs, so it would be
+permitted for it to call a cancellable wait function; however, as a
+quality of implementation matter, pclose must close the pipe fd before
+it can wait (consider popen("yes","r")) and if the wait could be
+interrupted the pipe FILE would be left in an intermediate state that
+portable software cannot recover from, so the only useful behavior is
+for pclose to NOT be a cancellation point.  We therefore support both at
+a small cost in code size.
+
+wait4 is historically not a cancellation point in musl; we retain that
+since we need the non-cancellable version of __wait4 anyway.
+---
+ src/internal/__wait4.c | 55 ++++++++++++++++++++++++++++++++++++++++++
+ src/internal/syscall.h | 12 +++++++++
+ src/linux/wait4.c      |  2 +-
+ src/process/waitpid.c  |  2 +-
+ src/stdio/pclose.c     |  2 +-
+ src/unistd/faccessat.c |  6 ++++-
+ 6 files changed, 75 insertions(+), 4 deletions(-)
+ create mode 100644 src/internal/__wait4.c
+
+diff --git a/src/internal/__wait4.c b/src/internal/__wait4.c
+new file mode 100644
+index 00000000..04d7dc64
+--- /dev/null
++++ b/src/internal/__wait4.c
+@@ -0,0 +1,55 @@
++#include <sys/wait.h>
++#include "syscall.h"
++
++#ifndef SYS_wait4
++hidden pid_t __wait4(pid_t pid, int *status, int options, void *kru, int cp)
++{
++	idtype_t t;
++	int r;
++	siginfo_t info;
++
++	info.si_pid = 0;
++	if (pid < -1) {
++		t = P_PGID;
++		pid = -pid;
++	} else if (pid == -1) {
++		t = P_ALL;
++	} else if (pid == 0) {
++		t = P_PGID;
++	} else {
++		t = P_PID;
++	}
++
++	if (cp) r = __syscall_cp(SYS_waitid, t, pid, &info, options|WEXITED, kru);
++	else r = __syscall(SYS_waitid, t, pid, &info, options|WEXITED, kru);
++
++	if (r<0) return r;
++
++	if (info.si_pid && status) {
++		int sw=0;
++		switch (info.si_code) {
++		case CLD_CONTINUED:
++			sw = 0xffff;
++			break;
++		case CLD_DUMPED:
++			sw = info.si_status&0x7f | 0x80;
++			break;
++		case CLD_EXITED:
++			sw = (info.si_status&0xff) << 8;
++			break;
++		case CLD_KILLED:
++			sw = info.si_status&0x7f;
++			break;
++		case CLD_STOPPED:
++		case CLD_TRAPPED:
++			/* see ptrace(2); the high bits of si_status can contain */
++			/* PTRACE_EVENT_ values which must be preserved */
++			sw = (info.si_status << 8) + 0x7f;
++			break;
++		}
++		*status = sw;
++	}
++
++	return info.si_pid;
++}
++#endif
+diff --git a/src/internal/syscall.h b/src/internal/syscall.h
+index 4f41e1dc..27642938 100644
+--- a/src/internal/syscall.h
++++ b/src/internal/syscall.h
+@@ -5,6 +5,8 @@
+ #include <errno.h>
+ #include <sys/syscall.h>
+ #include "syscall_arch.h"
++#define __NEED_pid_t
++#include <bits/alltypes.h>
+ 
+ #ifndef SYSCALL_RLIM_INFINITY
+ #define SYSCALL_RLIM_INFINITY (~0ULL)
+@@ -395,4 +397,14 @@ hidden void __procfdname(char __buf[static 15+3*sizeof(int)], unsigned);
+ 
+ hidden void *__vdsosym(const char *, const char *);
+ 
++#ifdef SYS_wait4
++static inline pid_t __wait4(pid_t pid, int *status, int options, void *kru, int cp)
++{
++	if (cp) return __syscall_cp(SYS_wait4, pid, status, options, kru);
++	else return __syscall(SYS_wait4, pid, status, options, kru);
++}
++#else
++hidden pid_t __wait4(pid_t pid, int *status, int options, void *kru, int cp);
++#endif
++
+ #endif
+diff --git a/src/linux/wait4.c b/src/linux/wait4.c
+index 83650e34..32652dc2 100644
+--- a/src/linux/wait4.c
++++ b/src/linux/wait4.c
+@@ -26,7 +26,7 @@ pid_t wait4(pid_t pid, int *status, int options, struct rusage *ru)
+ 	}
+ #endif
+ 	char *dest = ru ? (char *)&ru->ru_maxrss - 4*sizeof(long) : 0;
+-	r = __syscall(SYS_wait4, pid, status, options, dest);
++	r = __wait4(pid, status, options, dest, 0);
+ 	if (r>0 && ru && sizeof(time_t) > sizeof(long)) {
+ 		long kru[4];
+ 		memcpy(kru, dest, 4*sizeof(long));
+diff --git a/src/process/waitpid.c b/src/process/waitpid.c
+index 1b65bf05..e5ff27ca 100644
+--- a/src/process/waitpid.c
++++ b/src/process/waitpid.c
+@@ -3,5 +3,5 @@
+ 
+ pid_t waitpid(pid_t pid, int *status, int options)
+ {
+-	return syscall_cp(SYS_wait4, pid, status, options, 0);
++	return __wait4(pid, status, options, 0, 1);
+ }
+diff --git a/src/stdio/pclose.c b/src/stdio/pclose.c
+index 080a4262..b60d8f2c 100644
+--- a/src/stdio/pclose.c
++++ b/src/stdio/pclose.c
+@@ -7,7 +7,7 @@ int pclose(FILE *f)
+ 	int status, r;
+ 	pid_t pid = f->pipe_pid;
+ 	fclose(f);
+-	while ((r=__syscall(SYS_wait4, pid, &status, 0, 0)) == -EINTR);
++	while ((r=__wait4(pid, &status, 0, 0, 0)) == -EINTR);
+ 	if (r<0) return __syscall_ret(r);
+ 	return status;
+ }
+diff --git a/src/unistd/faccessat.c b/src/unistd/faccessat.c
+index 76bbd4c7..8bf34995 100644
+--- a/src/unistd/faccessat.c
++++ b/src/unistd/faccessat.c
+@@ -34,7 +34,6 @@ int faccessat(int fd, const char *filename, int amode, int flag)
+ 	char stack[1024];
+ 	sigset_t set;
+ 	pid_t pid;
+-	int status;
+ 	int ret, p[2];
+ 
+ 	if (pipe2(p, O_CLOEXEC)) return __syscall_ret(-EBUSY);
+@@ -48,7 +47,12 @@ int faccessat(int fd, const char *filename, int amode, int flag)
+ 	if (pid<0 || __syscall(SYS_read, p[0], &ret, sizeof ret) != sizeof(ret))
+ 		ret = -EBUSY;
+ 	__syscall(SYS_close, p[0]);
++#ifdef SYS_wait4
++	int status;
+ 	__syscall(SYS_wait4, pid, &status, __WCLONE, 0);
++#else
++	__syscall(SYS_waitid, P_PID, pid, &(siginfo_t){0}, __WCLONE|WEXITED, 0);
++#endif
+ 
+ 	__restore_sigs(&set);
+ 
+-- 
+2.28.0
+

+ 26 - 0
recipes-core/musl/musl/0008-riscv-Fall-back-to-syscall-__riscv_flush_icache.patch

@@ -0,0 +1,26 @@
+From ce443fcf9332f9bda0eeed4cf50174bae3732417 Mon Sep 17 00:00:00 2001
+From: Stefan O'Rear <sorear@fastmail.com>
+Date: Thu, 3 Sep 2020 05:23:40 -0400
+Subject: [PATCH 08/15] riscv: Fall back to syscall __riscv_flush_icache
+
+Matches glibc behavior and fixes a case where we could fall off the
+function without returning a value.
+---
+ src/linux/cache.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/linux/cache.c b/src/linux/cache.c
+index 0eb051c2..9cacac2b 100644
+--- a/src/linux/cache.c
++++ b/src/linux/cache.c
+@@ -45,6 +45,7 @@ int __riscv_flush_icache(void *start, void *end, unsigned long int flags)
+ 		if (!r) return r;
+ 		if (r != -ENOSYS) return __syscall_ret(r);
+ 	}
++	return syscall(SYS_riscv_flush_icache, start, end, flags);
+ }
+ weak_alias(__riscv_flush_icache, riscv_flush_icache);
+ #endif
+-- 
+2.28.0
+

+ 33 - 0
recipes-core/musl/musl/0009-riscv32-Target-and-subtarget-detection.patch

@@ -0,0 +1,33 @@
+From 0922e3b87460a5601fb957f3c06fcd18db9f71d2 Mon Sep 17 00:00:00 2001
+From: Stefan O'Rear <sorear@fastmail.com>
+Date: Thu, 3 Sep 2020 05:26:50 -0400
+Subject: [PATCH 09/15] riscv32: Target and subtarget detection
+
+---
+ configure | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/configure b/configure
+index acbfa8f2..2e217c7e 100755
+--- a/configure
++++ b/configure
+@@ -336,6 +336,7 @@ or1k*) ARCH=or1k ;;
+ powerpc64*|ppc64*) ARCH=powerpc64 ;;
+ powerpc*|ppc*) ARCH=powerpc ;;
+ riscv64*) ARCH=riscv64 ;;
++riscv32*) ARCH=riscv32 ;;
+ sh[1-9bel-]*|sh|superh*) ARCH=sh ;;
+ s390x*) ARCH=s390x ;;
+ unknown) fail "$0: unable to detect target arch; try $0 --target=..." ;;
+@@ -696,7 +697,7 @@ trycppif __LITTLE_ENDIAN__ "$t" && SUBARCH=${SUBARCH}le
+ trycppif _SOFT_FLOAT "$t" && fail "$0: error: soft-float not supported on powerpc64"
+ fi
+ 
+-if test "$ARCH" = "riscv64" ; then
++if test "$ARCH" = "riscv64" -o "$ARCH" = "riscv32" ; then
+ trycppif __riscv_float_abi_soft "$t" && SUBARCH=${SUBARCH}-sf
+ trycppif __riscv_float_abi_single "$t" && SUBARCH=${SUBARCH}-sp
+ fi
+-- 
+2.28.0
+

+ 849 - 0
recipes-core/musl/musl/0010-riscv32-add-arch-headers.patch

@@ -0,0 +1,849 @@
+From 8c8c8ca3517984d04d6463690418716702fe1bdb Mon Sep 17 00:00:00 2001
+From: Stefan O'Rear <sorear@fastmail.com>
+Date: Thu, 3 Sep 2020 05:40:29 -0400
+Subject: [PATCH 10/15] riscv32: add arch headers
+
+These are mostly copied from riscv64.  _Addr and _Reg had to become int
+to avoid errors in libstdc++ when size_t and std::size_t mismatch.
+There is no kernel stat struct; the userspace stat matches glibc in the
+sizes and offsets of all fields (including glibc's __dev_t __pad1).  The
+jump buffer is 12 words larger to account for 12 saved double-precision
+floats; additionally it should be 64-bit aligned to save doubles.
+
+The syscall list was significantly revised by deleting all time32 and
+pre-statx syscalls, and renaming several syscalls that have different
+names depending on __BITS_PER_LONG, notably mmap2 and _llseek.
+
+futex was added as an alias to futex_time64 since it is widely used by
+software which does not pass time arguments.
+---
+ arch/riscv32/atomic_arch.h      |  21 +++
+ arch/riscv32/bits/alltypes.h.in |  18 ++
+ arch/riscv32/bits/fcntl.h       |  38 +++++
+ arch/riscv32/bits/fenv.h        |  17 ++
+ arch/riscv32/bits/float.h       |  16 ++
+ arch/riscv32/bits/posix.h       |   2 +
+ arch/riscv32/bits/setjmp.h      |   1 +
+ arch/riscv32/bits/signal.h      | 118 +++++++++++++
+ arch/riscv32/bits/stat.h        |  18 ++
+ arch/riscv32/bits/stdint.h      |  20 +++
+ arch/riscv32/bits/syscall.h.in  | 286 ++++++++++++++++++++++++++++++++
+ arch/riscv32/bits/user.h        |   5 +
+ arch/riscv32/crt_arch.h         |  19 +++
+ arch/riscv32/kstat.h            |   0
+ arch/riscv32/pthread_arch.h     |  13 ++
+ arch/riscv32/reloc.h            |  22 +++
+ arch/riscv32/syscall_arch.h     |  78 +++++++++
+ 17 files changed, 692 insertions(+)
+ create mode 100644 arch/riscv32/atomic_arch.h
+ create mode 100644 arch/riscv32/bits/alltypes.h.in
+ 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/posix.h
+ create mode 100644 arch/riscv32/bits/setjmp.h
+ create mode 100644 arch/riscv32/bits/signal.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/kstat.h
+ create mode 100644 arch/riscv32/pthread_arch.h
+ create mode 100644 arch/riscv32/reloc.h
+ create mode 100644 arch/riscv32/syscall_arch.h
+
+diff --git a/arch/riscv32/atomic_arch.h b/arch/riscv32/atomic_arch.h
+new file mode 100644
+index 00000000..4d418f63
+--- /dev/null
++++ b/arch/riscv32/atomic_arch.h
+@@ -0,0 +1,21 @@
++#define a_barrier a_barrier
++static inline void a_barrier()
++{
++	__asm__ __volatile__ ("fence rw,rw" : : : "memory");
++}
++
++#define a_cas a_cas
++static inline int a_cas(volatile int *p, int t, int s)
++{
++	int old, tmp;
++	__asm__ __volatile__ (
++		"\n1:	lr.w.aqrl %0, (%2)\n"
++		"	bne %0, %3, 1f\n"
++		"	sc.w.aqrl %1, %4, (%2)\n"
++		"	bnez %1, 1b\n"
++		"1:"
++		: "=&r"(old), "=&r"(tmp)
++		: "r"(p), "r"((long)t), "r"((long)s)
++		: "memory");
++	return old;
++}
+diff --git a/arch/riscv32/bits/alltypes.h.in b/arch/riscv32/bits/alltypes.h.in
+new file mode 100644
+index 00000000..e2b6129e
+--- /dev/null
++++ b/arch/riscv32/bits/alltypes.h.in
+@@ -0,0 +1,18 @@
++#define _Addr int
++#define _Int64 long long
++#define _Reg int
++
++#define __BYTE_ORDER 1234
++#define __LONG_MAX 0x7fffffffL
++
++#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;
+diff --git a/arch/riscv32/bits/fcntl.h b/arch/riscv32/bits/fcntl.h
+new file mode 100644
+index 00000000..ecb4d18f
+--- /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 0200000
++#define O_NOFOLLOW  0400000
++#define O_CLOEXEC  02000000
++
++#define O_ASYNC      020000
++#define O_DIRECT     040000
++#define O_LARGEFILE 0100000
++#define O_NOATIME  01000000
++#define O_PATH    010000000
++#define O_TMPFILE 020200000
++#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 00000000..806ec40f
+--- /dev/null
++++ b/arch/riscv32/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/riscv32/bits/float.h b/arch/riscv32/bits/float.h
+new file mode 100644
+index 00000000..719c7908
+--- /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/posix.h b/arch/riscv32/bits/posix.h
+new file mode 100644
+index 00000000..8897d37d
+--- /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/setjmp.h b/arch/riscv32/bits/setjmp.h
+new file mode 100644
+index 00000000..51e96276
+--- /dev/null
++++ b/arch/riscv32/bits/setjmp.h
+@@ -0,0 +1 @@
++typedef unsigned long long __jmp_buf[19];
+diff --git a/arch/riscv32/bits/signal.h b/arch/riscv32/bits/signal.h
+new file mode 100644
+index 00000000..b006334f
+--- /dev/null
++++ b/arch/riscv32/bits/signal.h
+@@ -0,0 +1,118 @@
++#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
++
++typedef unsigned long __riscv_mc_gp_state[32];
++
++struct __riscv_mc_f_ext_state {
++	unsigned int __f[32];
++	unsigned int __fcsr;
++};
++
++struct __riscv_mc_d_ext_state {
++	unsigned long long __f[32];
++	unsigned int __fcsr;
++};
++
++struct __riscv_mc_q_ext_state {
++	unsigned long long __f[64] __attribute__((aligned(16)));
++	unsigned int __fcsr;
++	unsigned int __reserved[3];
++};
++
++union __riscv_mc_fp_state {
++	struct __riscv_mc_f_ext_state __f;
++	struct __riscv_mc_d_ext_state __d;
++	struct __riscv_mc_q_ext_state __q;
++};
++
++typedef struct mcontext_t {
++	__riscv_mc_gp_state __gregs;
++	union __riscv_mc_fp_state __fpregs;
++} mcontext_t;
++
++#if defined(_GNU_SOURCE)
++#define REG_PC 0
++#define REG_RA 1
++#define REG_SP 2
++#define REG_TP 4
++#define REG_S0 8
++#define REG_A0 10
++#endif
++
++#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
++typedef unsigned long greg_t;
++typedef unsigned long gregset_t[32];
++typedef union __riscv_mc_fp_state fpregset_t;
++struct sigcontext {
++	gregset_t gregs;
++	fpregset_t fpregs;
++};
++#endif
++
++struct sigaltstack {
++	void *ss_sp;
++	int ss_flags;
++	size_t ss_size;
++};
++
++typedef struct ucontext_t
++{
++	unsigned long uc_flags;
++	struct ucontext_t *uc_link;
++	stack_t uc_stack;
++	sigset_t uc_sigmask;
++	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/stat.h b/arch/riscv32/bits/stat.h
+new file mode 100644
+index 00000000..f6d9e864
+--- /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 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 00000000..d1b27121
+--- /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 00000000..852d2aaa
+--- /dev/null
++++ b/arch/riscv32/bits/syscall.h.in
+@@ -0,0 +1,286 @@
++#define __NR_io_setup 0
++#define __NR_io_destroy 1
++#define __NR_io_submit 2
++#define __NR_io_cancel 3
++#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_fcntl64 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_umount2 39
++#define __NR_mount 40
++#define __NR_pivot_root 41
++#define __NR_nfsservctl 42
++#define __NR_statfs64 43
++#define __NR_fstatfs64 44
++#define __NR_truncate64 45
++#define __NR_ftruncate64 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__llseek 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_sendfile64 71
++#define __NR_signalfd4 74
++#define __NR_vmsplice 75
++#define __NR_splice 76
++#define __NR_tee 77
++#define __NR_readlinkat 78
++#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_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_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_getoverrun 109
++#define __NR_timer_delete 111
++#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_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_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_getrusage 165
++#define __NR_umask 166
++#define __NR_prctl 167
++#define __NR_getcpu 168
++#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_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_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_mmap2 222
++#define __NR_fadvise64_64 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_arch_specific_syscall 244
++#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_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_statx 291
++#define __NR_rseq 293
++#define __NR_kexec_file_load 294
++#define __NR_clock_gettime64		403
++#define __NR_clock_settime64		404
++#define __NR_clock_adjtime64		405
++#define __NR_clock_getres_time64	406
++#define __NR_clock_nanosleep_time64	407
++#define __NR_timer_gettime64		408
++#define __NR_timer_settime64		409
++#define __NR_timerfd_gettime64		410
++#define __NR_timerfd_settime64		411
++#define __NR_utimensat_time64		412
++#define __NR_pselect6_time64		413
++#define __NR_ppoll_time64		414
++#define __NR_io_pgetevents_time64	416
++#define __NR_recvmmsg_time64		417
++#define __NR_mq_timedsend_time64	418
++#define __NR_mq_timedreceive_time64	419
++#define __NR_semtimedop_time64		420
++#define __NR_rt_sigtimedwait_time64	421
++#define __NR_futex_time64		422
++#define __NR_sched_rr_get_interval_time64 423
++#define __NR_pidfd_send_signal 424
++#define __NR_io_uring_setup 425
++#define __NR_io_uring_enter 426
++#define __NR_io_uring_register 427
++#define __NR_open_tree		428
++#define __NR_move_mount		429
++#define __NR_fsopen		430
++#define __NR_fsconfig		431
++#define __NR_fsmount		432
++#define __NR_fspick		433
++#define __NR_pidfd_open		434
++
++#define __NR_futex __NR_futex_time64
++
++#define __NR_sysriscv __NR_arch_specific_syscall
++#define __NR_riscv_flush_icache (__NR_sysriscv + 15)
+diff --git a/arch/riscv32/bits/user.h b/arch/riscv32/bits/user.h
+new file mode 100644
+index 00000000..2da743ea
+--- /dev/null
++++ b/arch/riscv32/bits/user.h
+@@ -0,0 +1,5 @@
++#include <signal.h>
++
++#define ELF_NGREG 32
++typedef unsigned long elf_greg_t, elf_gregset_t[ELF_NGREG];
++typedef union __riscv_mc_fp_state elf_fpregset_t;
+diff --git a/arch/riscv32/crt_arch.h b/arch/riscv32/crt_arch.h
+new file mode 100644
+index 00000000..6b93fcfd
+--- /dev/null
++++ b/arch/riscv32/crt_arch.h
+@@ -0,0 +1,19 @@
++__asm__(
++".section .sdata,\"aw\"\n"
++".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"
++"tail " START "_c"
++);
+diff --git a/arch/riscv32/kstat.h b/arch/riscv32/kstat.h
+new file mode 100644
+index 00000000..e69de29b
+diff --git a/arch/riscv32/pthread_arch.h b/arch/riscv32/pthread_arch.h
+new file mode 100644
+index 00000000..a20d7fba
+--- /dev/null
++++ b/arch/riscv32/pthread_arch.h
+@@ -0,0 +1,13 @@
++static inline uintptr_t __get_tp()
++{
++	uintptr_t tp;
++	__asm__ __volatile__("mv %0, tp" : "=r"(tp));
++	return tp;
++}
++
++#define TLS_ABOVE_TP
++#define GAP_ABOVE_TP 0
++
++#define DTP_OFFSET 0x800
++
++#define MC_PC __gregs[0]
+diff --git a/arch/riscv32/reloc.h b/arch/riscv32/reloc.h
+new file mode 100644
+index 00000000..59d15f17
+--- /dev/null
++++ b/arch/riscv32/reloc.h
+@@ -0,0 +1,22 @@
++#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 LDSO_ARCH "riscv32" RISCV_FP_SUFFIX
++
++#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 00000000..9e916c76
+--- /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) __SYSCALL_LL_E((x))
++
++#define __asm_syscall(...) \
++	__asm__ __volatile__ ("ecall\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" */
+-- 
+2.28.0
+

+ 363 - 0
recipes-core/musl/musl/0011-riscv32-Add-fenv-and-math.patch

@@ -0,0 +1,363 @@
+From 12a435f0616337afa55a61b5fbcb8d0c8b2acbea Mon Sep 17 00:00:00 2001
+From: Stefan O'Rear <sorear@fastmail.com>
+Date: Thu, 3 Sep 2020 05:45:44 -0400
+Subject: [PATCH 11/15] riscv32: Add fenv and math
+
+These are identical to riscv64.
+---
+ src/fenv/riscv32/fenv-sf.c   |  3 ++
+ src/fenv/riscv32/fenv.S      | 56 ++++++++++++++++++++++++++++++++++++
+ src/math/riscv32/copysign.c  | 15 ++++++++++
+ src/math/riscv32/copysignf.c | 15 ++++++++++
+ src/math/riscv32/fabs.c      | 15 ++++++++++
+ src/math/riscv32/fabsf.c     | 15 ++++++++++
+ src/math/riscv32/fma.c       | 15 ++++++++++
+ src/math/riscv32/fmaf.c      | 15 ++++++++++
+ src/math/riscv32/fmax.c      | 15 ++++++++++
+ src/math/riscv32/fmaxf.c     | 15 ++++++++++
+ src/math/riscv32/fmin.c      | 15 ++++++++++
+ src/math/riscv32/fminf.c     | 15 ++++++++++
+ src/math/riscv32/sqrt.c      | 15 ++++++++++
+ src/math/riscv32/sqrtf.c     | 15 ++++++++++
+ 14 files changed, 239 insertions(+)
+ create mode 100644 src/fenv/riscv32/fenv-sf.c
+ create mode 100644 src/fenv/riscv32/fenv.S
+ create mode 100644 src/math/riscv32/copysign.c
+ create mode 100644 src/math/riscv32/copysignf.c
+ create mode 100644 src/math/riscv32/fabs.c
+ create mode 100644 src/math/riscv32/fabsf.c
+ create mode 100644 src/math/riscv32/fma.c
+ create mode 100644 src/math/riscv32/fmaf.c
+ create mode 100644 src/math/riscv32/fmax.c
+ create mode 100644 src/math/riscv32/fmaxf.c
+ create mode 100644 src/math/riscv32/fmin.c
+ create mode 100644 src/math/riscv32/fminf.c
+ create mode 100644 src/math/riscv32/sqrt.c
+ create mode 100644 src/math/riscv32/sqrtf.c
+
+diff --git a/src/fenv/riscv32/fenv-sf.c b/src/fenv/riscv32/fenv-sf.c
+new file mode 100644
+index 00000000..ecd3cb5c
+--- /dev/null
++++ b/src/fenv/riscv32/fenv-sf.c
+@@ -0,0 +1,3 @@
++#ifndef __riscv_flen
++#include "../fenv.c"
++#endif
+diff --git a/src/fenv/riscv32/fenv.S b/src/fenv/riscv32/fenv.S
+new file mode 100644
+index 00000000..0ea78bf9
+--- /dev/null
++++ b/src/fenv/riscv32/fenv.S
+@@ -0,0 +1,56 @@
++#ifdef __riscv_flen
++
++.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:
++	li t2, -1
++	li t1, 0
++	beq a0, t2, 1f
++	lw t1, 0(a0)
++1:	fscsr t1
++	li a0, 0
++	ret
++
++#endif
+diff --git a/src/math/riscv32/copysign.c b/src/math/riscv32/copysign.c
+new file mode 100644
+index 00000000..c7854178
+--- /dev/null
++++ b/src/math/riscv32/copysign.c
+@@ -0,0 +1,15 @@
++#include <math.h>
++
++#if __riscv_flen >= 64
++
++double copysign(double x, double y)
++{
++	__asm__ ("fsgnj.d %0, %1, %2" : "=f"(x) : "f"(x), "f"(y));
++	return x;
++}
++
++#else
++
++#include "../copysign.c"
++
++#endif
+diff --git a/src/math/riscv32/copysignf.c b/src/math/riscv32/copysignf.c
+new file mode 100644
+index 00000000..a125611a
+--- /dev/null
++++ b/src/math/riscv32/copysignf.c
+@@ -0,0 +1,15 @@
++#include <math.h>
++
++#if __riscv_flen >= 32
++
++float copysignf(float x, float y)
++{
++	__asm__ ("fsgnj.s %0, %1, %2" : "=f"(x) : "f"(x), "f"(y));
++	return x;
++}
++
++#else
++
++#include "../copysignf.c"
++
++#endif
+diff --git a/src/math/riscv32/fabs.c b/src/math/riscv32/fabs.c
+new file mode 100644
+index 00000000..5290b6f0
+--- /dev/null
++++ b/src/math/riscv32/fabs.c
+@@ -0,0 +1,15 @@
++#include <math.h>
++
++#if __riscv_flen >= 64
++
++double fabs(double x)
++{
++	__asm__ ("fabs.d %0, %1" : "=f"(x) : "f"(x));
++	return x;
++}
++
++#else
++
++#include "../fabs.c"
++
++#endif
+diff --git a/src/math/riscv32/fabsf.c b/src/math/riscv32/fabsf.c
+new file mode 100644
+index 00000000..f5032e35
+--- /dev/null
++++ b/src/math/riscv32/fabsf.c
+@@ -0,0 +1,15 @@
++#include <math.h>
++
++#if __riscv_flen >= 32
++
++float fabsf(float x)
++{
++	__asm__ ("fabs.s %0, %1" : "=f"(x) : "f"(x));
++	return x;
++}
++
++#else
++
++#include "../fabsf.c"
++
++#endif
+diff --git a/src/math/riscv32/fma.c b/src/math/riscv32/fma.c
+new file mode 100644
+index 00000000..99b05713
+--- /dev/null
++++ b/src/math/riscv32/fma.c
+@@ -0,0 +1,15 @@
++#include <math.h>
++
++#if __riscv_flen >= 64
++
++double fma(double x, double y, double z)
++{
++	__asm__ ("fmadd.d %0, %1, %2, %3" : "=f"(x) : "f"(x), "f"(y), "f"(z));
++	return x;
++}
++
++#else
++
++#include "../fma.c"
++
++#endif
+diff --git a/src/math/riscv32/fmaf.c b/src/math/riscv32/fmaf.c
+new file mode 100644
+index 00000000..f9dc47ed
+--- /dev/null
++++ b/src/math/riscv32/fmaf.c
+@@ -0,0 +1,15 @@
++#include <math.h>
++
++#if __riscv_flen >= 32
++
++float fmaf(float x, float y, float z)
++{
++	__asm__ ("fmadd.s %0, %1, %2, %3" : "=f"(x) : "f"(x), "f"(y), "f"(z));
++	return x;
++}
++
++#else
++
++#include "../fmaf.c"
++
++#endif
+diff --git a/src/math/riscv32/fmax.c b/src/math/riscv32/fmax.c
+new file mode 100644
+index 00000000..023709cd
+--- /dev/null
++++ b/src/math/riscv32/fmax.c
+@@ -0,0 +1,15 @@
++#include <math.h>
++
++#if __riscv_flen >= 64
++
++double fmax(double x, double y)
++{
++	__asm__ ("fmax.d %0, %1, %2" : "=f"(x) : "f"(x), "f"(y));
++	return x;
++}
++
++#else
++
++#include "../fmax.c"
++
++#endif
+diff --git a/src/math/riscv32/fmaxf.c b/src/math/riscv32/fmaxf.c
+new file mode 100644
+index 00000000..863d2bd1
+--- /dev/null
++++ b/src/math/riscv32/fmaxf.c
+@@ -0,0 +1,15 @@
++#include <math.h>
++
++#if __riscv_flen >= 32
++
++float fmaxf(float x, float y)
++{
++	__asm__ ("fmax.s %0, %1, %2" : "=f"(x) : "f"(x), "f"(y));
++	return x;
++}
++
++#else
++
++#include "../fmaxf.c"
++
++#endif
+diff --git a/src/math/riscv32/fmin.c b/src/math/riscv32/fmin.c
+new file mode 100644
+index 00000000..a4e3b067
+--- /dev/null
++++ b/src/math/riscv32/fmin.c
+@@ -0,0 +1,15 @@
++#include <math.h>
++
++#if __riscv_flen >= 64
++
++double fmin(double x, double y)
++{
++	__asm__ ("fmin.d %0, %1, %2" : "=f"(x) : "f"(x), "f"(y));
++	return x;
++}
++
++#else
++
++#include "../fmin.c"
++
++#endif
+diff --git a/src/math/riscv32/fminf.c b/src/math/riscv32/fminf.c
+new file mode 100644
+index 00000000..32156e80
+--- /dev/null
++++ b/src/math/riscv32/fminf.c
+@@ -0,0 +1,15 @@
++#include <math.h>
++
++#if __riscv_flen >= 32
++
++float fminf(float x, float y)
++{
++	__asm__ ("fmin.s %0, %1, %2" : "=f"(x) : "f"(x), "f"(y));
++	return x;
++}
++
++#else
++
++#include "../fminf.c"
++
++#endif
+diff --git a/src/math/riscv32/sqrt.c b/src/math/riscv32/sqrt.c
+new file mode 100644
+index 00000000..867a504c
+--- /dev/null
++++ b/src/math/riscv32/sqrt.c
+@@ -0,0 +1,15 @@
++#include <math.h>
++
++#if __riscv_flen >= 64
++
++double sqrt(double x)
++{
++	__asm__ ("fsqrt.d %0, %1" : "=f"(x) : "f"(x));
++	return x;
++}
++
++#else
++
++#include "../sqrt.c"
++
++#endif
+diff --git a/src/math/riscv32/sqrtf.c b/src/math/riscv32/sqrtf.c
+new file mode 100644
+index 00000000..610c2cf8
+--- /dev/null
++++ b/src/math/riscv32/sqrtf.c
+@@ -0,0 +1,15 @@
++#include <math.h>
++
++#if __riscv_flen >= 32
++
++float sqrtf(float x)
++{
++	__asm__ ("fsqrt.s %0, %1" : "=f"(x) : "f"(x));
++	return x;
++}
++
++#else
++
++#include "../sqrtf.c"
++
++#endif
+-- 
+2.28.0
+

+ 26 - 0
recipes-core/musl/musl/0012-riscv32-Add-dlsym.patch

@@ -0,0 +1,26 @@
+From 31fe4a4dc4435c7eb2d29902de20a1a78b17a418 Mon Sep 17 00:00:00 2001
+From: Stefan O'Rear <sorear@fastmail.com>
+Date: Thu, 3 Sep 2020 05:46:33 -0400
+Subject: [PATCH 12/15] riscv32: Add dlsym
+
+Identical to riscv64.
+---
+ src/ldso/riscv32/dlsym.s | 6 ++++++
+ 1 file changed, 6 insertions(+)
+ create mode 100644 src/ldso/riscv32/dlsym.s
+
+diff --git a/src/ldso/riscv32/dlsym.s b/src/ldso/riscv32/dlsym.s
+new file mode 100644
+index 00000000..2bafd72d
+--- /dev/null
++++ b/src/ldso/riscv32/dlsym.s
+@@ -0,0 +1,6 @@
++.global dlsym
++.hidden __dlsym
++.type dlsym, %function
++dlsym:
++	mv a2, ra
++	tail __dlsym
+-- 
+2.28.0
+

+ 158 - 0
recipes-core/musl/musl/0013-riscv32-Add-jmp_buf-and-sigreturn.patch

@@ -0,0 +1,158 @@
+From 314a0b81fc9bb69ac53f9bc1b367e08c772a2d23 Mon Sep 17 00:00:00 2001
+From: Stefan O'Rear <sorear@fastmail.com>
+Date: Thu, 3 Sep 2020 05:54:44 -0400
+Subject: [PATCH 13/15] riscv32: Add jmp_buf and sigreturn
+
+Largely copied from riscv64 but required recalculation of offsets.
+---
+ src/setjmp/riscv32/longjmp.S   | 42 ++++++++++++++++++++++++++++++++++
+ src/setjmp/riscv32/setjmp.S    | 41 +++++++++++++++++++++++++++++++++
+ src/signal/riscv32/restore.s   |  8 +++++++
+ src/signal/riscv32/sigsetjmp.s | 23 +++++++++++++++++++
+ 4 files changed, 114 insertions(+)
+ create mode 100644 src/setjmp/riscv32/longjmp.S
+ create mode 100644 src/setjmp/riscv32/setjmp.S
+ create mode 100644 src/signal/riscv32/restore.s
+ create mode 100644 src/signal/riscv32/sigsetjmp.s
+
+diff --git a/src/setjmp/riscv32/longjmp.S b/src/setjmp/riscv32/longjmp.S
+new file mode 100644
+index 00000000..f9cb3318
+--- /dev/null
++++ b/src/setjmp/riscv32/longjmp.S
+@@ -0,0 +1,42 @@
++.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_float_abi_soft
++	fld fs0,  56(a0)
++	fld fs1,  64(a0)
++	fld fs2,  72(a0)
++	fld fs3,  80(a0)
++	fld fs4,  88(a0)
++	fld fs5,  96(a0)
++	fld fs6,  104(a0)
++	fld fs7,  112(a0)
++	fld fs8,  120(a0)
++	fld fs9,  128(a0)
++	fld fs10, 136(a0)
++	fld fs11, 144(a0)
++#endif
++
++	seqz a0, a1
++	add a0, a0, a1
++	ret
+diff --git a/src/setjmp/riscv32/setjmp.S b/src/setjmp/riscv32/setjmp.S
+new file mode 100644
+index 00000000..8a75cf55
+--- /dev/null
++++ b/src/setjmp/riscv32/setjmp.S
+@@ -0,0 +1,41 @@
++.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_float_abi_soft
++	fsd fs0,  56(a0)
++	fsd fs1,  64(a0)
++	fsd fs2,  72(a0)
++	fsd fs3,  80(a0)
++	fsd fs4,  88(a0)
++	fsd fs5,  96(a0)
++	fsd fs6,  104(a0)
++	fsd fs7,  112(a0)
++	fsd fs8,  120(a0)
++	fsd fs9,  128(a0)
++	fsd fs10, 136(a0)
++	fsd fs11, 144(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 00000000..40012c75
+--- /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
++	ecall
+diff --git a/src/signal/riscv32/sigsetjmp.s b/src/signal/riscv32/sigsetjmp.s
+new file mode 100644
+index 00000000..c1caeab1
+--- /dev/null
++++ b/src/signal/riscv32/sigsetjmp.s
+@@ -0,0 +1,23 @@
++.global sigsetjmp
++.global __sigsetjmp
++.type sigsetjmp, %function
++.type __sigsetjmp, %function
++sigsetjmp:
++__sigsetjmp:
++	bnez a1, 1f
++	tail setjmp
++1:
++
++	sw ra, 152(a0)
++	sw s0, 164(a0)
++	mv s0, a0
++
++	call setjmp
++
++	mv a1, a0
++	mv a0, s0
++	lw s0, 164(a0)
++	lw ra, 152(a0)
++
++.hidden __sigsetjmp_tail
++	tail __sigsetjmp_tail
+-- 
+2.28.0
+

+ 120 - 0
recipes-core/musl/musl/0014-riscv32-Add-thread-support.patch

@@ -0,0 +1,120 @@
+From 3a1861e54d4e891229a3ff94d00ba4da7030d81c Mon Sep 17 00:00:00 2001
+From: Stefan O'Rear <sorear@fastmail.com>
+Date: Thu, 3 Sep 2020 05:56:46 -0400
+Subject: [PATCH 14/15] riscv32: Add thread support
+
+Identical to riscv64 except for stack offsets in clone.
+---
+ 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 ++++++++++++++++++++++
+ 4 files changed, 76 insertions(+)
+ 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
+
+diff --git a/src/thread/riscv32/__set_thread_area.s b/src/thread/riscv32/__set_thread_area.s
+new file mode 100644
+index 00000000..828154d2
+--- /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 00000000..2849119c
+--- /dev/null
++++ b/src/thread/riscv32/__unmapself.s
+@@ -0,0 +1,7 @@
++.global __unmapself
++.type __unmapself, %function
++__unmapself:
++	li a7, 215 # SYS_munmap
++	ecall
++	li a7, 93  # SYS_exit
++	ecall
+diff --git a/src/thread/riscv32/clone.s b/src/thread/riscv32/clone.s
+new file mode 100644
+index 00000000..3102239d
+--- /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
++	ecall
++
++	beqz a0, 1f
++	# Parent
++	ret
++
++	# Child
++1:      lw a1, 0(sp)
++	lw a0, 4(sp)
++	jalr a1
++
++	# Exit
++	li a7, 93 # SYS_exit
++	ecall
+diff --git a/src/thread/riscv32/syscall_cp.s b/src/thread/riscv32/syscall_cp.s
+new file mode 100644
+index 00000000..079d1ba0
+--- /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
++	ecall
++__cp_end:
++	ret
++__cp_cancel:
++	tail __cancel
+-- 
+2.28.0
+

+ 201 - 0
recipes-core/musl/musl/0015-Change-definitions-of-F_GETLK-F_SETLK-F_SETLKW.patch

@@ -0,0 +1,201 @@
+From b833e050dc341733fbf26a8f8074d90cd1eb587b Mon Sep 17 00:00:00 2001
+From: Stefan O'Rear <sorear@fastmail.com>
+Date: Wed, 9 Sep 2020 11:57:54 -0700
+Subject: [PATCH 15/15] Change definitions of F_GETLK, F_SETLK, F_SETLKW
+
+* gdb HEAD wants ELF_NFPREG, so I set it in bits/user.h to the value
+  gdb needs.  (glibc does #define ELF_NFPREG NFPREG and expects gdb
+  to define NFPREG. I don't get this.)
+
+* Restore accidentally removed errno setting in waitpid, fixes a gdb
+  assertion failure.
+
+* Zero IPC_64 because the kernel only recognizes one set of IPC commands.
+
+* Copy the IPC_TIME64 bits from arch/arm/bits to trigger the musl code
+  for fixing time64 IPC_STAT results.  I'm not super happy with this,
+  maybe there should be a new mechanism in musl for fixing IPC_STAT for
+  unconditionally-time64 architectures.
+
+* riscv32 _does_ provide both F_GETLK and F_GETLK32; make sure we use
+  the right one.
+
+Signed-off-by: Stefan O'Rear <sorear@fastmail.com>
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ arch/riscv32/bits/fcntl.h   |  7 ++++---
+ arch/riscv32/bits/ipcstat.h |  1 +
+ arch/riscv32/bits/msg.h     | 18 ++++++++++++++++++
+ arch/riscv32/bits/sem.h     | 18 ++++++++++++++++++
+ arch/riscv32/bits/shm.h     | 31 +++++++++++++++++++++++++++++++
+ arch/riscv32/bits/user.h    |  1 +
+ arch/riscv32/syscall_arch.h |  2 ++
+ arch/riscv64/bits/user.h    |  1 +
+ src/process/waitpid.c       |  2 +-
+ 9 files changed, 77 insertions(+), 4 deletions(-)
+ create mode 100644 arch/riscv32/bits/ipcstat.h
+ create mode 100644 arch/riscv32/bits/msg.h
+ create mode 100644 arch/riscv32/bits/sem.h
+ create mode 100644 arch/riscv32/bits/shm.h
+
+diff --git a/arch/riscv32/bits/fcntl.h b/arch/riscv32/bits/fcntl.h
+index ecb4d18f..66f84fac 100644
+--- a/arch/riscv32/bits/fcntl.h
++++ b/arch/riscv32/bits/fcntl.h
+@@ -24,14 +24,15 @@
+ #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_GETLK  12
++#define F_SETLK  13
++#define F_SETLKW 14
++
+ #define F_SETOWN_EX 15
+ #define F_GETOWN_EX 16
+ 
+diff --git a/arch/riscv32/bits/ipcstat.h b/arch/riscv32/bits/ipcstat.h
+new file mode 100644
+index 00000000..4f4fcb0c
+--- /dev/null
++++ b/arch/riscv32/bits/ipcstat.h
+@@ -0,0 +1 @@
++#define IPC_STAT 0x102
+diff --git a/arch/riscv32/bits/msg.h b/arch/riscv32/bits/msg.h
+new file mode 100644
+index 00000000..7bbbb2bf
+--- /dev/null
++++ b/arch/riscv32/bits/msg.h
+@@ -0,0 +1,18 @@
++struct msqid_ds {
++	struct ipc_perm msg_perm;
++	unsigned long __msg_stime_lo;
++	unsigned long __msg_stime_hi;
++	unsigned long __msg_rtime_lo;
++	unsigned long __msg_rtime_hi;
++	unsigned long __msg_ctime_lo;
++	unsigned long __msg_ctime_hi;
++	unsigned long msg_cbytes;
++	msgqnum_t msg_qnum;
++	msglen_t msg_qbytes;
++	pid_t msg_lspid;
++	pid_t msg_lrpid;
++	unsigned long __unused[2];
++	time_t msg_stime;
++	time_t msg_rtime;
++	time_t msg_ctime;
++};
+diff --git a/arch/riscv32/bits/sem.h b/arch/riscv32/bits/sem.h
+new file mode 100644
+index 00000000..544e3d2a
+--- /dev/null
++++ b/arch/riscv32/bits/sem.h
+@@ -0,0 +1,18 @@
++struct semid_ds {
++	struct ipc_perm sem_perm;
++	unsigned long __sem_otime_lo;
++	unsigned long __sem_otime_hi;
++	unsigned long __sem_ctime_lo;
++	unsigned long __sem_ctime_hi;
++#if __BYTE_ORDER == __LITTLE_ENDIAN
++	unsigned short sem_nsems;
++	char __sem_nsems_pad[sizeof(long)-sizeof(short)];
++#else
++	char __sem_nsems_pad[sizeof(long)-sizeof(short)];
++	unsigned short sem_nsems;
++#endif
++	long __unused3;
++	long __unused4;
++	time_t sem_otime;
++	time_t sem_ctime;
++};
+diff --git a/arch/riscv32/bits/shm.h b/arch/riscv32/bits/shm.h
+new file mode 100644
+index 00000000..725fb469
+--- /dev/null
++++ b/arch/riscv32/bits/shm.h
+@@ -0,0 +1,31 @@
++#define SHMLBA 4096
++
++struct shmid_ds {
++	struct ipc_perm shm_perm;
++	size_t shm_segsz;
++	unsigned long __shm_atime_lo;
++	unsigned long __shm_atime_hi;
++	unsigned long __shm_dtime_lo;
++	unsigned long __shm_dtime_hi;
++	unsigned long __shm_ctime_lo;
++	unsigned long __shm_ctime_hi;
++	pid_t shm_cpid;
++	pid_t shm_lpid;
++	unsigned long shm_nattch;
++	unsigned long __pad1;
++	unsigned long __pad2;
++	unsigned long __pad3;
++	time_t shm_atime;
++	time_t shm_dtime;
++	time_t shm_ctime;
++};
++
++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/user.h b/arch/riscv32/bits/user.h
+index 2da743ea..0d37de0b 100644
+--- a/arch/riscv32/bits/user.h
++++ b/arch/riscv32/bits/user.h
+@@ -1,5 +1,6 @@
+ #include <signal.h>
+ 
+ #define ELF_NGREG 32
++#define ELF_NFPREG 33
+ typedef unsigned long elf_greg_t, elf_gregset_t[ELF_NGREG];
+ typedef union __riscv_mc_fp_state elf_fpregset_t;
+diff --git a/arch/riscv32/syscall_arch.h b/arch/riscv32/syscall_arch.h
+index 9e916c76..c507f15f 100644
+--- a/arch/riscv32/syscall_arch.h
++++ b/arch/riscv32/syscall_arch.h
+@@ -76,3 +76,5 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
+ /* We don't have a clock_gettime function.
+ #define VDSO_CGT_SYM "__vdso_clock_gettime"
+ #define VDSO_CGT_VER "LINUX_2.6" */
++
++#define IPC_64 0
+diff --git a/arch/riscv64/bits/user.h b/arch/riscv64/bits/user.h
+index 2da743ea..0d37de0b 100644
+--- a/arch/riscv64/bits/user.h
++++ b/arch/riscv64/bits/user.h
+@@ -1,5 +1,6 @@
+ #include <signal.h>
+ 
+ #define ELF_NGREG 32
++#define ELF_NFPREG 33
+ typedef unsigned long elf_greg_t, elf_gregset_t[ELF_NGREG];
+ typedef union __riscv_mc_fp_state elf_fpregset_t;
+diff --git a/src/process/waitpid.c b/src/process/waitpid.c
+index e5ff27ca..9de4073f 100644
+--- a/src/process/waitpid.c
++++ b/src/process/waitpid.c
+@@ -3,5 +3,5 @@
+ 
+ pid_t waitpid(pid_t pid, int *status, int options)
+ {
+-	return __wait4(pid, status, options, 0, 1);
++	return __syscall_ret(__wait4(pid, status, options, 0, 1));
+ }
+-- 
+2.28.0
+

+ 19 - 0
recipes-core/musl/musl_%.bbappend

@@ -0,0 +1,19 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI_append_riscv32 = "\
+    file://0001-Remove-ARMSUBARCH-relic-from-configure.patch \
+    file://0002-time64-Don-t-make-aliases-to-nonexistent-syscalls.patch \
+    file://0003-time64-Only-getrlimit-setrlimit-if-they-exist.patch \
+    file://0004-time64-Only-gettimeofday-settimeofday-if-exist.patch \
+    file://0005-Add-src-internal-statx.h.patch \
+    file://0006-Only-call-fstatat-if-defined.patch \
+    file://0007-Emulate-wait4-using-waitid.patch \
+    file://0008-riscv-Fall-back-to-syscall-__riscv_flush_icache.patch \
+    file://0009-riscv32-Target-and-subtarget-detection.patch \
+    file://0010-riscv32-add-arch-headers.patch \
+    file://0011-riscv32-Add-fenv-and-math.patch \
+    file://0012-riscv32-Add-dlsym.patch \
+    file://0013-riscv32-Add-jmp_buf-and-sigreturn.patch \
+    file://0014-riscv32-Add-thread-support.patch \
+    file://0015-Change-definitions-of-F_GETLK-F_SETLK-F_SETLKW.patch \
+"