mailing list of musl libc
 help / color / mirror / code / Atom feed
* [musl] riscv32 v2
@ 2020-09-04  5:48 Stefan O'Rear
  2020-09-07 10:47 ` Stefan O'Rear
                   ` (3 more replies)
  0 siblings, 4 replies; 21+ messages in thread
From: Stefan O'Rear @ 2020-09-04  5:48 UTC (permalink / raw)
  To: musl

[-- Attachment #1: Type: text/plain, Size: 3397 bytes --]

Changes since v1:

Fixed ptrace support by passing through high bits of WSTOPSIG.
WEXITSTATUS is still masked (required by POSIX); WTERMSIG is also
masked because bits 8-15 have nowhere to go.

Added SYS_futex as an alias of SYS_futex_time64.

Changed conditionals in patch 2.  __wait4 is significantly reorganized
and now uses a conditionally defined wrapper in src/internal/syscall.h.
Duplication reduced in statx-using patches.

Arnd Bergmann's comment about identical fcntl.h files has NOT been
addressed.

Rich Felker's suggestion (on IRC) to use a 0-instruction __get_tp was
NOT implemented after discovering that it generates dramatically worse
code on clang and cannot easily be conditionalized.  Bug reports to come.

Patches other than 2, 6, 7, 10 are unchanged.

Testing:

Smoke tested on riscv32, replacing the musl libc.so in an
OpenEmbedded-generated VM with a dynamically linked systemd and verified
boot.  Smoke testing on i386 and x86_64 by replacing libc.so in an
Alpine chroot and running build tools.

libc-test was run on all three architectures.  The errors on riscv32
are as follows:

FAIL src/api/main.exe [status 1]          
FAIL src/functional/fcntl-static.exe [status 1]                                                                                        
FAIL src/functional/fcntl.exe [status 1]                                                                                               
FAIL src/functional/ipc_msg-static.exe [status 1]
FAIL src/functional/ipc_msg.exe [status 1]                                                                                             
FAIL src/functional/ipc_sem-static.exe [status 1]                                                                                      
FAIL src/functional/ipc_sem.exe [status 1]
FAIL src/functional/ipc_shm-static.exe [status 1]               
FAIL src/functional/ipc_shm.exe [status 1]                     
FAIL src/functional/strptime-static.exe [status 1]         
FAIL src/functional/strptime.exe [status 1]                
FAIL src/math/fma.exe [status 1]                         
FAIL src/math/fmaf.exe [status 1]                 
FAIL src/math/powf.exe [status 1]                               
FAIL src/regression/malloc-brk-fail-static.exe [status 1]      
FAIL src/regression/malloc-brk-fail.exe [status 1]         
FAIL src/regression/pthread_atfork-errno-clobber-static.exe [status 1]
FAIL src/regression/pthread_atfork-errno-clobber.exe [status 1]

The fcntl and sysvipc errors do not correspond to any error in x86_64
and potentially require investigation, although they could be kernel
configuration issues.  x86_64 has a different but overlapping set of
math errors; qemu is known to not give bit-exact results for RISC-V
floating point.  The malloc, pthread, and src/api/main.exe failures
match failures on x86_64.

The test results are identical between master and my branch on x86_64.
On i386, I saw a utime.exe and utime-static.exe error but have not
managed to reproduce them.

I was not able to run LTP on musl on any of the three architectures
following the instructions in its README.

make autotools && ./configure && make all -j16
eventually results in:
confstr01.c:51:3: error: '_CS_XBS5_ILP32_OFF32_CFLAGS' undeclared here (not in a function)

A cloneable repository with the present version is:
git clone https://github.com/sorear/riscv-musl -b rv32_submit_v2

[-- Attachment #2: 0001-Remove-ARMSUBARCH-relic-from-configure.patch --]
[-- Type: application/octet-stream, Size: 721 bytes --]

From 020ccd0e2c77ded655bab68c2b3a0d3dc1151aab 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/14] Remove ARMSUBARCH relic from configure

---
 configure | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/configure b/configure
index 947adf41..49a7b403 100755
--- a/configure
+++ b/configure
@@ -725,11 +725,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.25.4


[-- Attachment #3: 0002-time64-Don-t-make-aliases-to-nonexistent-syscalls.patch --]
[-- Type: application/octet-stream, Size: 1920 bytes --]

From d3c237f0b0f7e5d1d2a53f5382e370ce3f0c493c 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/14] 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.25.4


[-- Attachment #4: 0003-time64-Only-getrlimit-setrlimit-if-they-exist.patch --]
[-- Type: application/octet-stream, Size: 1949 bytes --]

From f8cec3f6ff1e0a3737f1b55321e826f2208f940c 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/14] 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.25.4


[-- Attachment #5: 0004-time64-Only-gettimeofday-settimeofday-if-exist.patch --]
[-- Type: application/octet-stream, Size: 1328 bytes --]

From 9860fca6d45169b2c299f526243b12bff3f8180e 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/14] 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.25.4


[-- Attachment #6: 0005-Add-src-internal-statx.h.patch --]
[-- Type: application/octet-stream, Size: 2418 bytes --]

From daab92fbd69f7c8e3c0ff6faba142de827d007e6 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/14] 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.25.4


[-- Attachment #7: 0006-Only-call-fstatat-if-defined.patch --]
[-- Type: application/octet-stream, Size: 5779 bytes --]

From cd57a6b47783c5302f931e543b608cb3ba58387d 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/14] 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.25.4


[-- Attachment #8: 0007-Emulate-wait4-using-waitid.patch --]
[-- Type: application/octet-stream, Size: 5480 bytes --]

From 9ca6f23f7fcb6a387a394bc09a2aad1971b27857 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/14] 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.25.4


[-- Attachment #9: 0008-riscv-Fall-back-to-syscall-__riscv_flush_icache.patch --]
[-- Type: application/octet-stream, Size: 822 bytes --]

From 3e6bd3fd86883b448fc250d96cde9d37f9efa879 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/14] 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.25.4


[-- Attachment #10: 0009-riscv32-Target-and-subtarget-detection.patch --]
[-- Type: application/octet-stream, Size: 1090 bytes --]

From 8aabc20dade2b2c6019f46a528857bb434a38167 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/14] riscv32: Target and subtarget detection

---
 configure | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/configure b/configure
index 49a7b403..346080ce 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=..." ;;
@@ -694,7 +695,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.25.4


[-- Attachment #11: 0010-riscv32-add-arch-headers.patch --]
[-- Type: application/octet-stream, Size: 23648 bytes --]

From aae7aeed7378f10cba709b6643acbd46f0b36213 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/14] 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.25.4


[-- Attachment #12: 0011-riscv32-Add-fenv-and-math.patch --]
[-- Type: application/octet-stream, Size: 7215 bytes --]

From 338c60d72bcf9033fe87656cd8430371230ee166 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/14] 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.25.4


[-- Attachment #13: 0012-riscv32-Add-dlsym.patch --]
[-- Type: application/octet-stream, Size: 610 bytes --]

From 96cd92f116b06762e8770a3e06046fe4daae81e3 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/14] 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.25.4


[-- Attachment #14: 0013-riscv32-Add-jmp_buf-and-sigreturn.patch --]
[-- Type: application/octet-stream, Size: 3481 bytes --]

From 863f3d896d365aba0b294fb47e7b2a63512cf43a 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/14] 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.25.4


[-- Attachment #15: 0014-riscv32-Add-thread-support.patch --]
[-- Type: application/octet-stream, Size: 2837 bytes --]

From c3b508f979a6c94be607591d3ca11e838c4cf1e6 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/14] 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.25.4


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [musl] riscv32 v2
  2020-09-04  5:48 [musl] riscv32 v2 Stefan O'Rear
@ 2020-09-07 10:47 ` Stefan O'Rear
  2020-09-07 18:06   ` Rich Felker
  2020-09-07 11:27 ` Stefan O'Rear
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 21+ messages in thread
From: Stefan O'Rear @ 2020-09-07 10:47 UTC (permalink / raw)
  To: musl

[-- Attachment #1: Type: text/plain, Size: 2104 bytes --]

On Fri, Sep 4, 2020, at 1:48 AM, Stefan O'Rear wrote:
> FAIL src/api/main.exe [status 1]
> FAIL src/functional/fcntl-static.exe [status 1]
> FAIL src/functional/fcntl.exe [status 1]
> FAIL src/functional/ipc_msg-static.exe [status 1]
> FAIL src/functional/ipc_msg.exe [status 1]
> FAIL src/functional/ipc_sem-static.exe [status 1]
> FAIL src/functional/ipc_sem.exe [status 1]
> FAIL src/functional/ipc_shm-static.exe [status 1]
> FAIL src/functional/ipc_shm.exe [status 1]
> FAIL src/functional/strptime-static.exe [status 1]
> FAIL src/functional/strptime.exe [status 1]
> FAIL src/math/fma.exe [status 1]
> FAIL src/math/fmaf.exe [status 1]
> FAIL src/math/powf.exe [status 1]
> FAIL src/regression/malloc-brk-fail-static.exe [status 1]
> FAIL src/regression/malloc-brk-fail.exe [status 1]
> FAIL src/regression/pthread_atfork-errno-clobber-static.exe [status 1]
> FAIL src/regression/pthread_atfork-errno-clobber.exe [status 1]
> 
> The fcntl and sysvipc errors do not correspond to any error in x86_64
> and potentially require investigation, although they could be kernel
> configuration issues.  x86_64 has a different but overlapping set of
> math errors; qemu is known to not give bit-exact results for RISC-V
> floating point.  The malloc, pthread, and src/api/main.exe failures
> match failures on x86_64.

Attached patch reaches test failure parity between riscv32 and riscv64
and will be included in v3.

* 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.

-s

[-- Attachment #2: post-v2.diff --]
[-- Type: application/octet-stream, Size: 4293 bytes --]

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));
 }

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [musl] riscv32 v2
  2020-09-04  5:48 [musl] riscv32 v2 Stefan O'Rear
  2020-09-07 10:47 ` Stefan O'Rear
@ 2020-09-07 11:27 ` Stefan O'Rear
  2020-09-07 18:09   ` Rich Felker
  2020-09-08  1:54 ` Rich Felker
  2020-09-09 20:28 ` Rich Felker
  3 siblings, 1 reply; 21+ messages in thread
From: Stefan O'Rear @ 2020-09-07 11:27 UTC (permalink / raw)
  To: musl

On Fri, Sep 4, 2020, at 1:48 AM, Stefan O'Rear wrote:
> Rich Felker's suggestion (on IRC) to use a 0-instruction __get_tp was
> NOT implemented after discovering that it generates dramatically worse
> code on clang and cannot easily be conditionalized.  Bug reports to come.

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96952
https://bugs.llvm.org/show_bug.cgi?id=47447

-s

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [musl] riscv32 v2
  2020-09-07 10:47 ` Stefan O'Rear
@ 2020-09-07 18:06   ` Rich Felker
  2020-09-07 21:35     ` Arnd Bergmann
  0 siblings, 1 reply; 21+ messages in thread
From: Rich Felker @ 2020-09-07 18:06 UTC (permalink / raw)
  To: musl

On Mon, Sep 07, 2020 at 06:47:00AM -0400, Stefan O'Rear wrote:
> On Fri, Sep 4, 2020, at 1:48 AM, Stefan O'Rear wrote:
> > FAIL src/api/main.exe [status 1]
> > FAIL src/functional/fcntl-static.exe [status 1]
> > FAIL src/functional/fcntl.exe [status 1]
> > FAIL src/functional/ipc_msg-static.exe [status 1]
> > FAIL src/functional/ipc_msg.exe [status 1]
> > FAIL src/functional/ipc_sem-static.exe [status 1]
> > FAIL src/functional/ipc_sem.exe [status 1]
> > FAIL src/functional/ipc_shm-static.exe [status 1]
> > FAIL src/functional/ipc_shm.exe [status 1]
> > FAIL src/functional/strptime-static.exe [status 1]
> > FAIL src/functional/strptime.exe [status 1]
> > FAIL src/math/fma.exe [status 1]
> > FAIL src/math/fmaf.exe [status 1]
> > FAIL src/math/powf.exe [status 1]
> > FAIL src/regression/malloc-brk-fail-static.exe [status 1]
> > FAIL src/regression/malloc-brk-fail.exe [status 1]
> > FAIL src/regression/pthread_atfork-errno-clobber-static.exe [status 1]
> > FAIL src/regression/pthread_atfork-errno-clobber.exe [status 1]
> > 
> > The fcntl and sysvipc errors do not correspond to any error in x86_64
> > and potentially require investigation, although they could be kernel
> > configuration issues.  x86_64 has a different but overlapping set of
> > math errors; qemu is known to not give bit-exact results for RISC-V
> > floating point.  The malloc, pthread, and src/api/main.exe failures
> > match failures on x86_64.
> 
> Attached patch reaches test failure parity between riscv32 and riscv64
> and will be included in v3.
> 
> * 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.)

Ick. Indeed I think this is wrong/probably an oversight in glibc, and
the way you've done it sounds better.

> * Restore accidentally removed errno setting in waitpid, fixes a gdb
>   assertion failure.

OK. As an aside (I haven't gotten to sending review for this yet,
sorry) I think I'd prefer to name the function __sys_wait4 or similar
to make it more clear that it's analogous to __sys_open[23] etc. (a
function or macro emulating the syscall) and not a namespace-safe
version of wait4. (musl's having __wait be a futex wait makes this
even more confusing, btw)

Perhaps also leave the int cp argument to the function but make
separate __sys_wait4 and __sys_wait4_cp macros to call it via so that
there's not a mysterious boolean argument that doesn't correspond to
an actual syscall argument. (This would also be parallel with how
__sys_open[23] is done.)

> * Zero IPC_64 because the kernel only recognizes one set of IPC commands.

OK.

> * 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.

If the riscv32 IPC syscalls don't actually provide in-place time64 but
require translation, I think it's fairly appropriate as-is.

From the definitions in your patch, it looks like all the time fields
are fixed-word-order (little endian) and possibly not aligned, so it
seems like they can't be used in-place. Is this correct?

> * riscv32 _does_ provide both F_GETLK and F_GETLK32; make sure we use
>   the right one.

IIRC someone already suggested using the generic bits/fcntl.h, which
would have solved this. I also have unpushed changed that let 64-bit
archs share the generic bits/fcntl.h too, via #if on __LONG_MAX.

Rich

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [musl] riscv32 v2
  2020-09-07 11:27 ` Stefan O'Rear
@ 2020-09-07 18:09   ` Rich Felker
  0 siblings, 0 replies; 21+ messages in thread
From: Rich Felker @ 2020-09-07 18:09 UTC (permalink / raw)
  To: musl

On Mon, Sep 07, 2020 at 07:27:37AM -0400, Stefan O'Rear wrote:
> On Fri, Sep 4, 2020, at 1:48 AM, Stefan O'Rear wrote:
> > Rich Felker's suggestion (on IRC) to use a 0-instruction __get_tp was
> > NOT implemented after discovering that it generates dramatically worse
> > code on clang and cannot easily be conditionalized.  Bug reports to come.
> 
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96952
> https://bugs.llvm.org/show_bug.cgi?id=47447

Thanks! I think the GCC issue & response to it supports my preference
not to use GCC __builtin_*, but I would like to see them fix it. The
form with __asm__("" : ...) is semantically correct and has always
worked, but I don't see enough benefit over the current non-empty asm
to justify accepting the worse codegen from llvm getting it wrong.
Maybe we can change it at some point in the future after llvm is
fixed, but it's really no big deal.

Rich

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [musl] riscv32 v2
  2020-09-07 18:06   ` Rich Felker
@ 2020-09-07 21:35     ` Arnd Bergmann
  2020-09-07 21:45       ` Rich Felker
  0 siblings, 1 reply; 21+ messages in thread
From: Arnd Bergmann @ 2020-09-07 21:35 UTC (permalink / raw)
  To: musl

On Mon, Sep 7, 2020 at 8:06 PM Rich Felker <dalias@libc.org> wrote:
> On Mon, Sep 07, 2020 at 06:47:00AM -0400, Stefan O'Rear wrote:

> > * 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.
>
> If the riscv32 IPC syscalls don't actually provide in-place time64 but
> require translation, I think it's fairly appropriate as-is.
>
> From the definitions in your patch, it looks like all the time fields
> are fixed-word-order (little endian) and possibly not aligned, so it
> seems like they can't be used in-place. Is this correct?

Yes, rv32 uses the generic system call arguments, which are
unfortunately defined this way. In retrospect I wish I had
replaced the ipc syscalls with a sane version for time64, but at
the time time it seemed as easy way out to use the fields that
had been reserved for this purpose despite the broken
byte order and alignment.

       Arnd

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [musl] riscv32 v2
  2020-09-07 21:35     ` Arnd Bergmann
@ 2020-09-07 21:45       ` Rich Felker
  2020-09-07 21:58         ` Arnd Bergmann
  0 siblings, 1 reply; 21+ messages in thread
From: Rich Felker @ 2020-09-07 21:45 UTC (permalink / raw)
  To: musl

On Mon, Sep 07, 2020 at 11:35:45PM +0200, Arnd Bergmann wrote:
> On Mon, Sep 7, 2020 at 8:06 PM Rich Felker <dalias@libc.org> wrote:
> > On Mon, Sep 07, 2020 at 06:47:00AM -0400, Stefan O'Rear wrote:
> 
> > > * 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.
> >
> > If the riscv32 IPC syscalls don't actually provide in-place time64 but
> > require translation, I think it's fairly appropriate as-is.
> >
> > From the definitions in your patch, it looks like all the time fields
> > are fixed-word-order (little endian) and possibly not aligned, so it
> > seems like they can't be used in-place. Is this correct?
> 
> Yes, rv32 uses the generic system call arguments, which are
> unfortunately defined this way. In retrospect I wish I had
> replaced the ipc syscalls with a sane version for time64, but at
> the time time it seemed as easy way out to use the fields that
> had been reserved for this purpose despite the broken
> byte order and alignment.

Thanks for clarifying. BTW does passing IPC_64 produce an error on
rv32? If so, this is another advantage of keeping the IPC_TIME64 bit
-- it would catch programs bypassing libc and making the syscalls
directly.

Rich

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [musl] riscv32 v2
  2020-09-07 21:45       ` Rich Felker
@ 2020-09-07 21:58         ` Arnd Bergmann
  2020-09-07 22:11           ` Rich Felker
  0 siblings, 1 reply; 21+ messages in thread
From: Arnd Bergmann @ 2020-09-07 21:58 UTC (permalink / raw)
  To: musl

On Mon, Sep 7, 2020 at 11:46 PM Rich Felker <dalias@libc.org> wrote:
> On Mon, Sep 07, 2020 at 11:35:45PM +0200, Arnd Bergmann wrote:
> > On Mon, Sep 7, 2020 at 8:06 PM Rich Felker <dalias@libc.org> wrote:
> > > On Mon, Sep 07, 2020 at 06:47:00AM -0400, Stefan O'Rear wrote:
> >
> > > > * 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.
> > >
> > > If the riscv32 IPC syscalls don't actually provide in-place time64 but
> > > require translation, I think it's fairly appropriate as-is.
> > >
> > > From the definitions in your patch, it looks like all the time fields
> > > are fixed-word-order (little endian) and possibly not aligned, so it
> > > seems like they can't be used in-place. Is this correct?
> >
> > Yes, rv32 uses the generic system call arguments, which are
> > unfortunately defined this way. In retrospect I wish I had
> > replaced the ipc syscalls with a sane version for time64, but at
> > the time time it seemed as easy way out to use the fields that
> > had been reserved for this purpose despite the broken
> > byte order and alignment.
>
> Thanks for clarifying. BTW does passing IPC_64 produce an error on
> rv32? If so, this is another advantage of keeping the IPC_TIME64 bit
> -- it would catch programs bypassing libc and making the syscalls
> directly.

Yes, this is now the generic behavior for the split IPC syscalls
(as opposed to sys_ipc on older architectures). The only architectures
that parse the version in the split ipc syscalls are the ones that
already had these and were interpreting IPC_64 before linux-5.1:
alpha, arm32, microblaze, mips-n32, mips-n64, and xtensa.

There are additional architectures that require passing IPC_64
in sys_ipc() but reject it in the split syscalls: m68k, mips-o32,
powerpc, s390, sh, sparc, and x86.

        Arnd

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [musl] riscv32 v2
  2020-09-07 21:58         ` Arnd Bergmann
@ 2020-09-07 22:11           ` Rich Felker
  2020-09-07 22:30             ` Arnd Bergmann
  0 siblings, 1 reply; 21+ messages in thread
From: Rich Felker @ 2020-09-07 22:11 UTC (permalink / raw)
  To: musl

On Mon, Sep 07, 2020 at 11:58:20PM +0200, Arnd Bergmann wrote:
> On Mon, Sep 7, 2020 at 11:46 PM Rich Felker <dalias@libc.org> wrote:
> > On Mon, Sep 07, 2020 at 11:35:45PM +0200, Arnd Bergmann wrote:
> > > On Mon, Sep 7, 2020 at 8:06 PM Rich Felker <dalias@libc.org> wrote:
> > > > On Mon, Sep 07, 2020 at 06:47:00AM -0400, Stefan O'Rear wrote:
> > >
> > > > > * 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.
> > > >
> > > > If the riscv32 IPC syscalls don't actually provide in-place time64 but
> > > > require translation, I think it's fairly appropriate as-is.
> > > >
> > > > From the definitions in your patch, it looks like all the time fields
> > > > are fixed-word-order (little endian) and possibly not aligned, so it
> > > > seems like they can't be used in-place. Is this correct?
> > >
> > > Yes, rv32 uses the generic system call arguments, which are
> > > unfortunately defined this way. In retrospect I wish I had
> > > replaced the ipc syscalls with a sane version for time64, but at
> > > the time time it seemed as easy way out to use the fields that
> > > had been reserved for this purpose despite the broken
> > > byte order and alignment.
> >
> > Thanks for clarifying. BTW does passing IPC_64 produce an error on
> > rv32? If so, this is another advantage of keeping the IPC_TIME64 bit
> > -- it would catch programs bypassing libc and making the syscalls
> > directly.
> 
> Yes, this is now the generic behavior for the split IPC syscalls

Great!

> (as opposed to sys_ipc on older architectures). The only architectures
> that parse the version in the split ipc syscalls are the ones that
> already had these and were interpreting IPC_64 before linux-5.1:
> alpha, arm32, microblaze, mips-n32, mips-n64, and xtensa.
> 
> There are additional architectures that require passing IPC_64
> in sys_ipc() but reject it in the split syscalls: m68k, mips-o32,
> powerpc, s390, sh, sparc, and x86.

Uhg, good to know. I just re-checked, and at present we don't use the
new split syscalls unless SYS_ipc doesn't exist. musl's arch-specific
IPC_64 definition (0 or 0x100) serves as the value needed for SYS_ipc
if SYS_ipc is defined, and as the value needed for the split syscalls
if SYS_ipc is not defined. So if in the future we want to use the new
ones with fallback to SYS_ipc, we'd need the archs to define the
needed IPC_64 flag separately for each...

As an aside, I should probably cleanup the current definition
framework where IPC_64==0x100 is the default and archs that want 0
have to define it explicitly. It looks like, for the most part, IPC_64
is needed iff SYS_ipc is defined. Of the archs we support, arm
(32-bit) and mips{n32,64} seem to be the only ones that lack SYS_ipc
but need the IPC_64 bit set. Does this agree with your assessment?

Rich

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [musl] riscv32 v2
  2020-09-07 22:11           ` Rich Felker
@ 2020-09-07 22:30             ` Arnd Bergmann
  2020-09-08  1:02               ` Rich Felker
  0 siblings, 1 reply; 21+ messages in thread
From: Arnd Bergmann @ 2020-09-07 22:30 UTC (permalink / raw)
  To: musl

On Tue, Sep 8, 2020 at 12:12 AM Rich Felker <dalias@libc.org> wrote:
> As an aside, I should probably cleanup the current definition
> framework where IPC_64==0x100 is the default and archs that want 0
> have to define it explicitly. It looks like, for the most part, IPC_64
> is needed iff SYS_ipc is defined.

Right, there are no architectures that provide sys_ipc and want the
flag to be zero.

> Of the archs we support, arm
> (32-bit) and mips{n32,64} seem to be the only ones that lack SYS_ipc
> but need the IPC_64 bit set. Does this agree with your assessment?

I think microblaze is in the same group. Note that for odd reasons it
has always defined the __NR_ipc macro to 117 but hooked it up
to -ENOSYS instead of sys_ipc in the kernel. I'm never quite sure
whether we should treat that as a bug in the header file that we want
to fix, or whether we should keep such constants around in new
headers that were present in older ones.

      Arnd

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [musl] riscv32 v2
  2020-09-07 22:30             ` Arnd Bergmann
@ 2020-09-08  1:02               ` Rich Felker
  2020-09-08  7:00                 ` Arnd Bergmann
  0 siblings, 1 reply; 21+ messages in thread
From: Rich Felker @ 2020-09-08  1:02 UTC (permalink / raw)
  To: musl

On Tue, Sep 08, 2020 at 12:30:27AM +0200, Arnd Bergmann wrote:
> On Tue, Sep 8, 2020 at 12:12 AM Rich Felker <dalias@libc.org> wrote:
> > As an aside, I should probably cleanup the current definition
> > framework where IPC_64==0x100 is the default and archs that want 0
> > have to define it explicitly. It looks like, for the most part, IPC_64
> > is needed iff SYS_ipc is defined.
> 
> Right, there are no architectures that provide sys_ipc and want the
> flag to be zero.
> 
> > Of the archs we support, arm
> > (32-bit) and mips{n32,64} seem to be the only ones that lack SYS_ipc
> > but need the IPC_64 bit set. Does this agree with your assessment?
> 
> I think microblaze is in the same group. Note that for odd reasons it
> has always defined the __NR_ipc macro to 117 but hooked it up
> to -ENOSYS instead of sys_ipc in the kernel. I'm never quite sure
> whether we should treat that as a bug in the header file that we want
> to fix, or whether we should keep such constants around in new
> headers that were present in older ones.

Oh, really? In that case musl's almost surely broken on microblaze,
and yes it would be another exception.

Rich

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [musl] riscv32 v2
  2020-09-04  5:48 [musl] riscv32 v2 Stefan O'Rear
  2020-09-07 10:47 ` Stefan O'Rear
  2020-09-07 11:27 ` Stefan O'Rear
@ 2020-09-08  1:54 ` Rich Felker
  2020-09-09  6:07   ` Rich Felker
  2020-09-09 20:28 ` Rich Felker
  3 siblings, 1 reply; 21+ messages in thread
From: Rich Felker @ 2020-09-08  1:54 UTC (permalink / raw)
  To: musl

On Fri, Sep 04, 2020 at 01:48:19AM -0400, Stefan O'Rear wrote:
> From cd57a6b47783c5302f931e543b608cb3ba58387d 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/14] 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);
>  	}
>  

I was just looking at this file for another reason, and wondered why
we're not just calling the fstatat function here. There's no namespace
reason not to. According to the description of commit
c9ebff4736128186121424364c1c62224b02aee3, use of struct kstat here was
done "as a low-risk fix" right before release of 1.2.0, and I probably
had in mind changing it to fstatat later and just never got around to
it.

The same could be done for tempnam (POSIX) but not tmpnam (C) or
__map_file (used in plain C interfaces like setlocale and time
functions) without adding a namespace-safe alias for fstatat.

Of course this does pull in more code that's not needed, so maybe your
version of the change is best, and maybe this is what I had in mind
when I hesitated to make the bigger change back in February. I don't
like that knowledge of different syscall alternatives leaks all over
the place, but I also don't like increasing code size unnecessarily on
all archs...

Rich

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [musl] riscv32 v2
  2020-09-08  1:02               ` Rich Felker
@ 2020-09-08  7:00                 ` Arnd Bergmann
  0 siblings, 0 replies; 21+ messages in thread
From: Arnd Bergmann @ 2020-09-08  7:00 UTC (permalink / raw)
  To: musl

On Tue, Sep 8, 2020 at 3:03 AM Rich Felker <dalias@libc.org> wrote:
>
> On Tue, Sep 08, 2020 at 12:30:27AM +0200, Arnd Bergmann wrote:
> > On Tue, Sep 8, 2020 at 12:12 AM Rich Felker <dalias@libc.org> wrote:
> > > As an aside, I should probably cleanup the current definition
> > > framework where IPC_64==0x100 is the default and archs that want 0
> > > have to define it explicitly. It looks like, for the most part, IPC_64
> > > is needed iff SYS_ipc is defined.
> >
> > Right, there are no architectures that provide sys_ipc and want the
> > flag to be zero.
> >
> > > Of the archs we support, arm
> > > (32-bit) and mips{n32,64} seem to be the only ones that lack SYS_ipc
> > > but need the IPC_64 bit set. Does this agree with your assessment?
> >
> > I think microblaze is in the same group. Note that for odd reasons it
> > has always defined the __NR_ipc macro to 117 but hooked it up
> > to -ENOSYS instead of sys_ipc in the kernel. I'm never quite sure
> > whether we should treat that as a bug in the header file that we want
> > to fix, or whether we should keep such constants around in new
> > headers that were present in older ones.
>
> Oh, really? In that case musl's almost surely broken on microblaze,
> and yes it would be another exception.

There was (very briefly) a sys_ipc implementation on microblaze
in 2009 as the architecture got merged, but this was never part of
a released kernel as far as I can tell.

I'm not surprised that this was never caught though, as sysvipc
is not that common on the super-small softcore implementations
that microblaze tends to be used for.

On sparc32, sysvipc had been broken in a slightly different way
in the kernel for over 11 years without anyone complaining (it
was working in compat mode on 64-bit kernels though).

For future 64-bit microblaze, we will have to decide which ABI
to use, I'd probably go with the new variant (only split calls,
no IPC_64 flag).

        Arnd

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [musl] riscv32 v2
  2020-09-08  1:54 ` Rich Felker
@ 2020-09-09  6:07   ` Rich Felker
  0 siblings, 0 replies; 21+ messages in thread
From: Rich Felker @ 2020-09-09  6:07 UTC (permalink / raw)
  To: musl

On Mon, Sep 07, 2020 at 09:54:56PM -0400, Rich Felker wrote:
> On Fri, Sep 04, 2020 at 01:48:19AM -0400, Stefan O'Rear wrote:
> > From cd57a6b47783c5302f931e543b608cb3ba58387d 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/14] 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);
> >  	}
> >  
> 
> I was just looking at this file for another reason, and wondered why
> we're not just calling the fstatat function here. There's no namespace
> reason not to. According to the description of commit
> c9ebff4736128186121424364c1c62224b02aee3, use of struct kstat here was
> done "as a low-risk fix" right before release of 1.2.0, and I probably
> had in mind changing it to fstatat later and just never got around to
> it.
> 
> The same could be done for tempnam (POSIX) but not tmpnam (C) or
> __map_file (used in plain C interfaces like setlocale and time
> functions) without adding a namespace-safe alias for fstatat.
> 
> Of course this does pull in more code that's not needed, so maybe your
> version of the change is best, and maybe this is what I had in mind
> when I hesitated to make the bigger change back in February. I don't
> like that knowledge of different syscall alternatives leaks all over
> the place, but I also don't like increasing code size unnecessarily on
> all archs...

Not something that requires action, but possible streamlining I just
discovered: in places where lstat is being used to probe file
existence (tmpnam, etc.), SYS_readlink also works, yields smaller
code, and is #ifdef-free. You get the same ENOENT for nonexistence,
and success or EINVAL indicating existence as a symlink or
non-symlink, respectively.

Rich

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [musl] riscv32 v2
  2020-09-04  5:48 [musl] riscv32 v2 Stefan O'Rear
                   ` (2 preceding siblings ...)
  2020-09-08  1:54 ` Rich Felker
@ 2020-09-09 20:28 ` Rich Felker
  2020-09-09 21:28   ` Palmer Dabbelt
  3 siblings, 1 reply; 21+ messages in thread
From: Rich Felker @ 2020-09-09 20:28 UTC (permalink / raw)
  To: musl

On Fri, Sep 04, 2020 at 01:48:19AM -0400, Stefan O'Rear wrote:
> Changes since v1:
> 
> Fixed ptrace support by passing through high bits of WSTOPSIG.
> WEXITSTATUS is still masked (required by POSIX); WTERMSIG is also
> masked because bits 8-15 have nowhere to go.
> 
> Added SYS_futex as an alias of SYS_futex_time64.
> 
> Changed conditionals in patch 2.  __wait4 is significantly reorganized
> and now uses a conditionally defined wrapper in src/internal/syscall.h.
> Duplication reduced in statx-using patches.
> 
> Arnd Bergmann's comment about identical fcntl.h files has NOT been
> addressed.
> 
> Rich Felker's suggestion (on IRC) to use a 0-instruction __get_tp was
> NOT implemented after discovering that it generates dramatically worse
> code on clang and cannot easily be conditionalized.  Bug reports to come.
> 
> Patches other than 2, 6, 7, 10 are unchanged.
> 
> Testing:
> 
> Smoke tested on riscv32, replacing the musl libc.so in an
> OpenEmbedded-generated VM with a dynamically linked systemd and verified
> boot.  Smoke testing on i386 and x86_64 by replacing libc.so in an
> Alpine chroot and running build tools.
> 
> libc-test was run on all three architectures.  The errors on riscv32
> are as follows:
> 
> FAIL src/api/main.exe [status 1]          
> FAIL src/functional/fcntl-static.exe [status 1]                                                                                        
> FAIL src/functional/fcntl.exe [status 1]                                                                                               
> FAIL src/functional/ipc_msg-static.exe [status 1]
> FAIL src/functional/ipc_msg.exe [status 1]                                                                                             
> FAIL src/functional/ipc_sem-static.exe [status 1]                                                                                      
> FAIL src/functional/ipc_sem.exe [status 1]
> FAIL src/functional/ipc_shm-static.exe [status 1]               
> FAIL src/functional/ipc_shm.exe [status 1]                     
> FAIL src/functional/strptime-static.exe [status 1]         
> FAIL src/functional/strptime.exe [status 1]                
> FAIL src/math/fma.exe [status 1]                         
> FAIL src/math/fmaf.exe [status 1]                 
> FAIL src/math/powf.exe [status 1]                               
> FAIL src/regression/malloc-brk-fail-static.exe [status 1]      
> FAIL src/regression/malloc-brk-fail.exe [status 1]         
> FAIL src/regression/pthread_atfork-errno-clobber-static.exe [status 1]
> FAIL src/regression/pthread_atfork-errno-clobber.exe [status 1]
> 
> The fcntl and sysvipc errors do not correspond to any error in x86_64
> and potentially require investigation, although they could be kernel
> configuration issues.  x86_64 has a different but overlapping set of
> math errors; qemu is known to not give bit-exact results for RISC-V
> floating point.  The malloc, pthread, and src/api/main.exe failures
> match failures on x86_64.
> 
> The test results are identical between master and my branch on x86_64.
> On i386, I saw a utime.exe and utime-static.exe error but have not
> managed to reproduce them.
> 
> I was not able to run LTP on musl on any of the three architectures
> following the instructions in its README.
> 
> make autotools && ./configure && make all -j16
> eventually results in:
> confstr01.c:51:3: error: '_CS_XBS5_ILP32_OFF32_CFLAGS' undeclared here (not in a function)
> 
> A cloneable repository with the present version is:
> git clone https://github.com/sorear/riscv-musl -b rv32_submit_v2

> From 020ccd0e2c77ded655bab68c2b3a0d3dc1151aab 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/14] Remove ARMSUBARCH relic from configure

commit 0f814a4e57e80d2512934820b878211e9d71c93e removed its use.

> From d3c237f0b0f7e5d1d2a53f5382e370ce3f0c493c 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/14] 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.

commit 4bbd7baea7c8538b3fb8e30f7b022a1eee071450 was written with the
intent that future time64-only archs, including riscv32, not need to
explicitly define the unadorned syscall names; the logic in
internal/syscall.h would automatically define them as the
corresponding _time64 syscall numbers. however, subsequent commits
beginning with 5a105f19b5aae79dd302899e634b6b18b3dcd0d6 broke this
when they renamed legacy time32 syscalls externally and introduced
preprocessor logic in internal/syscall.h to define the unadorned names
in terms of the renamed _time32 ones.

flip the preprocessor logic for the latter to be dependent on the
_time32 names being defined. this has the added benefit of producing a
diagnostic for redefinition if a conflicting definition ever arises.

> From f8cec3f6ff1e0a3737f1b55321e826f2208f940c 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/14] 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
>  }

No action required, but this could be improved by moving to __syscall
with return __syscall_ret(ret) at the end outside the #endif. That's
an independent change we can make later.

> From 9860fca6d45169b2c299f526243b12bff3f8180e 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/14] time64: Only gettimeofday/settimeofday if exist
> 
> riscv64 and future architectures only provide the clock_ functions.

Commit message mentions settimeofday but it does not appear in the
diff. There's presently no fallback for settimeofday anywhere in musl,
and commit 2c2c3605d3b3ff32902c406d17ac44e7544be4e2 noted that it's
not needed (although perhaps it would be nice to have anyway?). In any
case, only action needed now is fixing the commit message.

> From daab92fbd69f7c8e3c0ff6faba142de827d007e6 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/14] 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.

This wording is confusing. Perhaps just "make struct statx available
for internal use outside fstatat.c."

> From 9ca6f23f7fcb6a387a394bc09a2aad1971b27857 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/14] 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
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

This is not the case. It's specified as an optional cancellation
point, not UB, but the only possible actions on cancellation are
incompatible with other requirements of POSIX and with consistency of
the program state. These essentially impose a requirement that it not
be a cancellation point, or at least that it can't act on
cancellation after the close finishes.

> 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.

With the above fixed, I don't object to keeping this kind of message,
but I'd rather focus on (or at least also have) an explanation of why
this is needed. Key points seem to be that Linux has dropped SYS_wait4
for new archs, but it's nontrivial to get the semantics needed for
functions that use waitpid in terms of waitid, and that the rusage
logic is only needed for wait4() not other functions that use
SYS_wait4, so a common place to do the conversion is required.

> ---
>  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)

As mentioned before, I'd like to rename this to __sys_wait4 and make
macros to call it as __sys_wait4 or __sys_wait4_cp (hiding the last
argument) via internal/syscall.h (matching __sys_open pattern).

If SYS_wait4 is defined, the macros in internal/syscall.h can then
directly expand to __syscall[_cp](SYS_wait4, ...). Then the source
files don't need their own #ifdef's.

> From 3e6bd3fd86883b448fc250d96cde9d37f9efa879 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/14] 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.

I would highlight in the commit title (first line) that this is fixing
an actual bug, the case where the vdso function isn't defined.
Something like:

    fix __riscv_flush_icache when vdso function is not available

    previously execution fell off the end of the function without
    performing any fallback or returning any value when the vdso
    function was not available.

> From 8aabc20dade2b2c6019f46a528857bb434a38167 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/14] riscv32: Target and subtarget detection

Having them split out has been ok for review, but I think this and the
remaining commits can be squashed for upstreaming. They don't
individually produce consistent states you could build or use.

> From aae7aeed7378f10cba709b6643acbd46f0b36213 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/14] riscv32: add arch headers

This is the only commit where you had significant informative message
content, and it should probably be kept but revised slightly to apply
too the whole port.

> 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.

This is just the psABI, not a libstdc++ issue. Almost all 32-bit archs
use int rather than long for wordsize types.

> 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.

"Should be" is confusing here and suggests it's not. Maybe explain it
as the jmp_buf using 64-bit slots so that it remains sufficiently
aligned for 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.

OK.

> 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

I think this file can be removed; after fixes it's identical to the
generic one.

> 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.25.4
> 

Is this correct? I see the comment is just copied from riscv64, but it
seems wrong there, and here too. Also, is the vdso function named
"clock_gettime" or "clock_gettime64" for riscv32? Or is there none at
all and this macro just wrong?

Rich

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [musl] riscv32 v2
  2020-09-09 20:28 ` Rich Felker
@ 2020-09-09 21:28   ` Palmer Dabbelt
  2020-09-09 21:36     ` Rich Felker
  0 siblings, 1 reply; 21+ messages in thread
From: Palmer Dabbelt @ 2020-09-09 21:28 UTC (permalink / raw)
  To: dalias; +Cc: musl

On Wed, 09 Sep 2020 13:28:27 PDT (-0700), dalias@libc.org wrote:
> On Fri, Sep 04, 2020 at 01:48:19AM -0400, Stefan O'Rear wrote:
>> Changes since v1:
>>
>> Fixed ptrace support by passing through high bits of WSTOPSIG.
>> WEXITSTATUS is still masked (required by POSIX); WTERMSIG is also
>> masked because bits 8-15 have nowhere to go.
>>
>> Added SYS_futex as an alias of SYS_futex_time64.
>>
>> Changed conditionals in patch 2.  __wait4 is significantly reorganized
>> and now uses a conditionally defined wrapper in src/internal/syscall.h.
>> Duplication reduced in statx-using patches.
>>
>> Arnd Bergmann's comment about identical fcntl.h files has NOT been
>> addressed.
>>
>> Rich Felker's suggestion (on IRC) to use a 0-instruction __get_tp was
>> NOT implemented after discovering that it generates dramatically worse
>> code on clang and cannot easily be conditionalized.  Bug reports to come.
>>
>> Patches other than 2, 6, 7, 10 are unchanged.
>>
>> Testing:
>>
>> Smoke tested on riscv32, replacing the musl libc.so in an
>> OpenEmbedded-generated VM with a dynamically linked systemd and verified
>> boot.  Smoke testing on i386 and x86_64 by replacing libc.so in an
>> Alpine chroot and running build tools.
>>
>> libc-test was run on all three architectures.  The errors on riscv32
>> are as follows:
>>
>> FAIL src/api/main.exe [status 1]
>> FAIL src/functional/fcntl-static.exe [status 1]
>> FAIL src/functional/fcntl.exe [status 1]
>> FAIL src/functional/ipc_msg-static.exe [status 1]
>> FAIL src/functional/ipc_msg.exe [status 1]
>> FAIL src/functional/ipc_sem-static.exe [status 1]
>> FAIL src/functional/ipc_sem.exe [status 1]
>> FAIL src/functional/ipc_shm-static.exe [status 1]
>> FAIL src/functional/ipc_shm.exe [status 1]
>> FAIL src/functional/strptime-static.exe [status 1]
>> FAIL src/functional/strptime.exe [status 1]
>> FAIL src/math/fma.exe [status 1]
>> FAIL src/math/fmaf.exe [status 1]
>> FAIL src/math/powf.exe [status 1]
>> FAIL src/regression/malloc-brk-fail-static.exe [status 1]
>> FAIL src/regression/malloc-brk-fail.exe [status 1]
>> FAIL src/regression/pthread_atfork-errno-clobber-static.exe [status 1]
>> FAIL src/regression/pthread_atfork-errno-clobber.exe [status 1]
>>
>> The fcntl and sysvipc errors do not correspond to any error in x86_64
>> and potentially require investigation, although they could be kernel
>> configuration issues.  x86_64 has a different but overlapping set of
>> math errors; qemu is known to not give bit-exact results for RISC-V
>> floating point.  The malloc, pthread, and src/api/main.exe failures
>> match failures on x86_64.
>>
>> The test results are identical between master and my branch on x86_64.
>> On i386, I saw a utime.exe and utime-static.exe error but have not
>> managed to reproduce them.
>>
>> I was not able to run LTP on musl on any of the three architectures
>> following the instructions in its README.
>>
>> make autotools && ./configure && make all -j16
>> eventually results in:
>> confstr01.c:51:3: error: '_CS_XBS5_ILP32_OFF32_CFLAGS' undeclared here (not in a function)
>>
>> A cloneable repository with the present version is:
>> git clone https://github.com/sorear/riscv-musl -b rv32_submit_v2
>
>> From 020ccd0e2c77ded655bab68c2b3a0d3dc1151aab 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/14] Remove ARMSUBARCH relic from configure
>
> commit 0f814a4e57e80d2512934820b878211e9d71c93e removed its use.
>
>> From d3c237f0b0f7e5d1d2a53f5382e370ce3f0c493c 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/14] 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.
>
> commit 4bbd7baea7c8538b3fb8e30f7b022a1eee071450 was written with the
> intent that future time64-only archs, including riscv32, not need to
> explicitly define the unadorned syscall names; the logic in
> internal/syscall.h would automatically define them as the
> corresponding _time64 syscall numbers. however, subsequent commits
> beginning with 5a105f19b5aae79dd302899e634b6b18b3dcd0d6 broke this
> when they renamed legacy time32 syscalls externally and introduced
> preprocessor logic in internal/syscall.h to define the unadorned names
> in terms of the renamed _time32 ones.
>
> flip the preprocessor logic for the latter to be dependent on the
> _time32 names being defined. this has the added benefit of producing a
> diagnostic for redefinition if a conflicting definition ever arises.
>
>> From f8cec3f6ff1e0a3737f1b55321e826f2208f940c 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/14] 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
>>  }
>
> No action required, but this could be improved by moving to __syscall
> with return __syscall_ret(ret) at the end outside the #endif. That's
> an independent change we can make later.
>
>> From 9860fca6d45169b2c299f526243b12bff3f8180e 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/14] time64: Only gettimeofday/settimeofday if exist
>>
>> riscv64 and future architectures only provide the clock_ functions.
>
> Commit message mentions settimeofday but it does not appear in the
> diff. There's presently no fallback for settimeofday anywhere in musl,
> and commit 2c2c3605d3b3ff32902c406d17ac44e7544be4e2 noted that it's
> not needed (although perhaps it would be nice to have anyway?). In any
> case, only action needed now is fixing the commit message.
>
>> From daab92fbd69f7c8e3c0ff6faba142de827d007e6 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/14] 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.
>
> This wording is confusing. Perhaps just "make struct statx available
> for internal use outside fstatat.c."
>
>> From 9ca6f23f7fcb6a387a394bc09a2aad1971b27857 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/14] 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
>   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> This is not the case. It's specified as an optional cancellation
> point, not UB, but the only possible actions on cancellation are
> incompatible with other requirements of POSIX and with consistency of
> the program state. These essentially impose a requirement that it not
> be a cancellation point, or at least that it can't act on
> cancellation after the close finishes.
>
>> 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.
>
> With the above fixed, I don't object to keeping this kind of message,
> but I'd rather focus on (or at least also have) an explanation of why
> this is needed. Key points seem to be that Linux has dropped SYS_wait4
> for new archs, but it's nontrivial to get the semantics needed for
> functions that use waitpid in terms of waitid, and that the rusage
> logic is only needed for wait4() not other functions that use
> SYS_wait4, so a common place to do the conversion is required.
>
>> ---
>>  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)
>
> As mentioned before, I'd like to rename this to __sys_wait4 and make
> macros to call it as __sys_wait4 or __sys_wait4_cp (hiding the last
> argument) via internal/syscall.h (matching __sys_open pattern).
>
> If SYS_wait4 is defined, the macros in internal/syscall.h can then
> directly expand to __syscall[_cp](SYS_wait4, ...). Then the source
> files don't need their own #ifdef's.
>
>> From 3e6bd3fd86883b448fc250d96cde9d37f9efa879 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/14] 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.
>
> I would highlight in the commit title (first line) that this is fixing
> an actual bug, the case where the vdso function isn't defined.
> Something like:
>
>     fix __riscv_flush_icache when vdso function is not available
>
>     previously execution fell off the end of the function without
>     performing any fallback or returning any value when the vdso
>     function was not available.
>
>> From 8aabc20dade2b2c6019f46a528857bb434a38167 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/14] riscv32: Target and subtarget detection
>
> Having them split out has been ok for review, but I think this and the
> remaining commits can be squashed for upstreaming. They don't
> individually produce consistent states you could build or use.
>
>> From aae7aeed7378f10cba709b6643acbd46f0b36213 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/14] riscv32: add arch headers
>
> This is the only commit where you had significant informative message
> content, and it should probably be kept but revised slightly to apply
> too the whole port.
>
>> 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.
>
> This is just the psABI, not a libstdc++ issue. Almost all 32-bit archs
> use int rather than long for wordsize types.
>
>> 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.
>
> "Should be" is confusing here and suggests it's not. Maybe explain it
> as the jmp_buf using 64-bit slots so that it remains sufficiently
> aligned for 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.
>
> OK.
>
>> 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
>
> I think this file can be removed; after fixes it's identical to the
> generic one.
>
>> 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.25.4
>>
>
> Is this correct? I see the comment is just copied from riscv64, but it
> seems wrong there, and here too. Also, is the vdso function named
> "clock_gettime" or "clock_gettime64" for riscv32? Or is there none at
> all and this macro just wrong?

Looks like we don't have __vdso_clock_gettime on rv32 but we do have one on
rv64.  glibc doesn't have the clock VDSO calls on rv32.

I'm not opposed to adding some sort of clock-related VDSO calls on rv32, but it
looks like doing so will require some thought.  Maybe it's best to wait on that
so we don't hold up the initial port?

>
> Rich

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [musl] riscv32 v2
  2020-09-09 21:28   ` Palmer Dabbelt
@ 2020-09-09 21:36     ` Rich Felker
  2020-09-09 23:08       ` Palmer Dabbelt
  0 siblings, 1 reply; 21+ messages in thread
From: Rich Felker @ 2020-09-09 21:36 UTC (permalink / raw)
  To: Palmer Dabbelt; +Cc: musl

On Wed, Sep 09, 2020 at 02:28:55PM -0700, Palmer Dabbelt wrote:
> On Wed, 09 Sep 2020 13:28:27 PDT (-0700), dalias@libc.org wrote:
> >On Fri, Sep 04, 2020 at 01:48:19AM -0400, Stefan O'Rear wrote:
> >>+#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.25.4
> >>
> >
> >Is this correct? I see the comment is just copied from riscv64, but it
> >seems wrong there, and here too. Also, is the vdso function named
> >"clock_gettime" or "clock_gettime64" for riscv32? Or is there none at
> >all and this macro just wrong?
> 
> Looks like we don't have __vdso_clock_gettime on rv32 but we do have one on
> rv64.  glibc doesn't have the clock VDSO calls on rv32.
> 
> I'm not opposed to adding some sort of clock-related VDSO calls on rv32, but it
> looks like doing so will require some thought.  Maybe it's best to wait on that
> so we don't hold up the initial port?

Possible addition of vdso clock_gettime isn't a blocker for moving
forward with the musl port, but syscall_arch.h should accurately
describe what's available and should not attempt to use vdso before
it's a public kernel interface (e.g. resolving the question of what
the function name will be). So I think it should be removed for now.
But VDSO_USEFUL must be kept if we want to support the vdso icache
flush function (is that actually supported on rv32 either? if not it
should be made conditional on rv64 in src/linux/cache.c.

Rich

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [musl] riscv32 v2
  2020-09-09 21:36     ` Rich Felker
@ 2020-09-09 23:08       ` Palmer Dabbelt
  2020-09-10  7:36         ` Arnd Bergmann
  0 siblings, 1 reply; 21+ messages in thread
From: Palmer Dabbelt @ 2020-09-09 23:08 UTC (permalink / raw)
  To: dalias, Arnd Bergmann; +Cc: musl

On Wed, 09 Sep 2020 14:36:44 PDT (-0700), dalias@libc.org wrote:
> On Wed, Sep 09, 2020 at 02:28:55PM -0700, Palmer Dabbelt wrote:
>> On Wed, 09 Sep 2020 13:28:27 PDT (-0700), dalias@libc.org wrote:
>> >On Fri, Sep 04, 2020 at 01:48:19AM -0400, Stefan O'Rear wrote:
>> >>+#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.25.4
>> >>
>> >
>> >Is this correct? I see the comment is just copied from riscv64, but it
>> >seems wrong there, and here too. Also, is the vdso function named
>> >"clock_gettime" or "clock_gettime64" for riscv32? Or is there none at
>> >all and this macro just wrong?
>>
>> Looks like we don't have __vdso_clock_gettime on rv32 but we do have one on
>> rv64.  glibc doesn't have the clock VDSO calls on rv32.
>>
>> I'm not opposed to adding some sort of clock-related VDSO calls on rv32, but it
>> looks like doing so will require some thought.  Maybe it's best to wait on that
>> so we don't hold up the initial port?
>
> Possible addition of vdso clock_gettime isn't a blocker for moving
> forward with the musl port, but syscall_arch.h should accurately
> describe what's available and should not attempt to use vdso before
> it's a public kernel interface (e.g. resolving the question of what
> the function name will be). So I think it should be removed for now.

Sorry if that was confusing, but I definitely agree.

I guess my point was that the lack of VDSO clock functions on rv32 was probably
an oversight, but one that shouldn't block the port.  We definitely can't just
make up a kernel interface, particularly as the reason we don't have these on
rv32 is because the generic versions of the functions we're using don't appear
to run on 32-bit targets.

That probably means there's some more subtle issue, though TBH I don't know
enough about the 64-bit-ification of time_t for it to just jump out at me.  I
don't want to derail the thread too much, but I tried the obvious thing

    diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
    index 33dde87218dd..1cf24a8f76c4 100644
    --- a/arch/riscv/Kconfig
    +++ b/arch/riscv/Kconfig
    @@ -65,7 +65,7 @@ config RISCV
     	select HAVE_EBPF_JIT if MMU
     	select HAVE_FUTEX_CMPXCHG if FUTEX
     	select HAVE_GCC_PLUGINS
    -	select HAVE_GENERIC_VDSO if MMU && 64BIT
    +	select HAVE_GENERIC_VDSO if MMU
     	select HAVE_PCI
     	select HAVE_PERF_EVENTS
     	select HAVE_PERF_REGS
    diff --git a/arch/riscv/kernel/vdso/Makefile b/arch/riscv/kernel/vdso/Makefile
    index 478e7338ddc1..10f7a07ce85a 100644
    --- a/arch/riscv/kernel/vdso/Makefile
    +++ b/arch/riscv/kernel/vdso/Makefile
    @@ -7,9 +7,7 @@ ARCH_REL_TYPE_ABS := R_RISCV_32|R_RISCV_64|R_RISCV_JUMP_SLOT
     include $(srctree)/lib/vdso/Makefile
     # Symbols present in the vdso
     vdso-syms  = rt_sigreturn
    -ifdef CONFIG_64BIT
     vdso-syms += vgettimeofday
    -endif
     vdso-syms += getcpu
     vdso-syms += flush_icache

and it doesn't build.  I've added Arnd, who might have a better idea of what's
going on.  Whatever happens, I think the best bet is to just drop the clock
functions (specifically __vdso_{clock_gettime,gettimeofday,clock_getres}) from
the rv32 port right now.

> But VDSO_USEFUL must be kept if we want to support the vdso icache
> flush function (is that actually supported on rv32 either? if not it
> should be made conditional on rv64 in src/linux/cache.c.

Yes, we have __vdso_flush_icache on rv32 and as far as I know it should work
fine (I guess QEMU isn't really going to find fence.i issues, but this
interface in particular is quite simple).  There's no way to build a working
system without some kernel-based fence.i mechanism, and IIRC we added the VDSO
entry at the same time as the syscall so it should always work itself out
(though we do have the syscall-based fallback in glibc)).  One of my working
directories reports

    $ riscv64-linux-gnu-objdump -d arch/riscv/kernel/vdso/vdso.so
    
    arch/riscv/kernel/vdso/vdso.so:     file format elf32-littleriscv
    
    
    Disassembly of section .text:
    
    00000800 <__vdso_rt_sigreturn@@LINUX_4.15>:
     800:	08b00893          	li	a7,139
     804:	00000073          	ecall
     808:	0000                	unimp
    	...
    
    0000080c <__vdso_getcpu@@LINUX_4.15>:
     80c:	0a800893          	li	a7,168
     810:	00000073          	ecall
     814:	8082                	ret
    	...
    
    00000818 <__vdso_flush_icache@@LINUX_4.15>:
     818:	10300893          	li	a7,259
     81c:	00000073          	ecall
     820:	8082                	ret

when built for rv32 (despite the rv64 objdump command).

>
> Rich

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [musl] riscv32 v2
  2020-09-09 23:08       ` Palmer Dabbelt
@ 2020-09-10  7:36         ` Arnd Bergmann
  2020-09-10 10:01           ` Vincenzo Frascino
  0 siblings, 1 reply; 21+ messages in thread
From: Arnd Bergmann @ 2020-09-10  7:36 UTC (permalink / raw)
  To: Palmer Dabbelt; +Cc: Rich Felker, musl, Vincenzo Frascino

On Thu, Sep 10, 2020 at 1:08 AM Palmer Dabbelt <palmerdabbelt@google.com> wrote:
> On Wed, 09 Sep 2020 14:36:44 PDT (-0700), dalias@libc.org wrote:
> > On Wed, Sep 09, 2020 at 02:28:55PM -0700, Palmer Dabbelt wrote:
> >> On Wed, 09 Sep 2020 13:28:27 PDT (-0700), dalias@libc.org wrote:
> > Possible addition of vdso clock_gettime isn't a blocker for moving
> > forward with the musl port, but syscall_arch.h should accurately
> > describe what's available and should not attempt to use vdso before
> > it's a public kernel interface (e.g. resolving the question of what
> > the function name will be). So I think it should be removed for now.
>
> Sorry if that was confusing, but I definitely agree.
>
> I guess my point was that the lack of VDSO clock functions on rv32 was probably
> an oversight, but one that shouldn't block the port.  We definitely can't just
> make up a kernel interface, particularly as the reason we don't have these on
> rv32 is because the generic versions of the functions we're using don't appear
> to run on 32-bit targets.
>
> That probably means there's some more subtle issue, though TBH I don't know
> enough about the 64-bit-ification of time_t for it to just jump out at me.  I
> don't want to derail the thread too much, but I tried the obvious thing

When the vdso for rv64 was added, there was no time64 support in the
vdso code in general, as this only came with the "generic vdso" infrastructure
that was added later on, with commit ad5d1122b82f ("riscv: use vDSO
common flow to reduce the latency of the time-related functions") in v5.8.

At that point it probably should have been added as well.

>     --- a/arch/riscv/kernel/vdso/Makefile
>     +++ b/arch/riscv/kernel/vdso/Makefile
>     @@ -7,9 +7,7 @@ ARCH_REL_TYPE_ABS := R_RISCV_32|R_RISCV_64|R_RISCV_JUMP_SLOT
>      include $(srctree)/lib/vdso/Makefile
>      # Symbols present in the vdso
>      vdso-syms  = rt_sigreturn
>     -ifdef CONFIG_64BIT
>      vdso-syms += vgettimeofday
>     -endif
>      vdso-syms += getcpu
>      vdso-syms += flush_icache
>
> and it doesn't build.  I've added Arnd, who might have a better idea of what's
> going on.  Whatever happens, I think the best bet is to just drop the clock
> functions (specifically __vdso_{clock_gettime,gettimeofday,clock_getres}) from
> the rv32 port right now.

For rv32 you need clock_gettime64, not clock_gettime, which in the Linux
ABI refers to the interface with the old timespec. There was some debate
over whether clock_getres_time64 and gettimeofday_time64 would make
sense to be added here, but I have so far leaned to the position that these
are not as performance critical and not worth the effort.

Vincenzo has argued that we might want to extend the generic vdso code
to include a number of additional syscall implementations, which would
then include gettimeofday_time64 and clock_getres_time64.

        Arnd

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [musl] riscv32 v2
  2020-09-10  7:36         ` Arnd Bergmann
@ 2020-09-10 10:01           ` Vincenzo Frascino
  2020-09-11  0:08             ` Palmer Dabbelt
  0 siblings, 1 reply; 21+ messages in thread
From: Vincenzo Frascino @ 2020-09-10 10:01 UTC (permalink / raw)
  To: Arnd Bergmann, Palmer Dabbelt; +Cc: Rich Felker, musl



On 9/10/20 8:36 AM, Arnd Bergmann wrote:
> On Thu, Sep 10, 2020 at 1:08 AM Palmer Dabbelt <palmerdabbelt@google.com> wrote:
>> On Wed, 09 Sep 2020 14:36:44 PDT (-0700), dalias@libc.org wrote:
>>> On Wed, Sep 09, 2020 at 02:28:55PM -0700, Palmer Dabbelt wrote:
>>>> On Wed, 09 Sep 2020 13:28:27 PDT (-0700), dalias@libc.org wrote:
>>> Possible addition of vdso clock_gettime isn't a blocker for moving
>>> forward with the musl port, but syscall_arch.h should accurately
>>> describe what's available and should not attempt to use vdso before
>>> it's a public kernel interface (e.g. resolving the question of what
>>> the function name will be). So I think it should be removed for now.
>>
>> Sorry if that was confusing, but I definitely agree.
>>
>> I guess my point was that the lack of VDSO clock functions on rv32 was probably
>> an oversight, but one that shouldn't block the port.  We definitely can't just
>> make up a kernel interface, particularly as the reason we don't have these on
>> rv32 is because the generic versions of the functions we're using don't appear
>> to run on 32-bit targets.
>>
>> That probably means there's some more subtle issue, though TBH I don't know
>> enough about the 64-bit-ification of time_t for it to just jump out at me.  I
>> don't want to derail the thread too much, but I tried the obvious thing
> 
> When the vdso for rv64 was added, there was no time64 support in the
> vdso code in general, as this only came with the "generic vdso" infrastructure
> that was added later on, with commit ad5d1122b82f ("riscv: use vDSO
> common flow to reduce the latency of the time-related functions") in v5.8.
> 
> At that point it probably should have been added as well.
> 
>>     --- a/arch/riscv/kernel/vdso/Makefile
>>     +++ b/arch/riscv/kernel/vdso/Makefile
>>     @@ -7,9 +7,7 @@ ARCH_REL_TYPE_ABS := R_RISCV_32|R_RISCV_64|R_RISCV_JUMP_SLOT
>>      include $(srctree)/lib/vdso/Makefile
>>      # Symbols present in the vdso
>>      vdso-syms  = rt_sigreturn
>>     -ifdef CONFIG_64BIT
>>      vdso-syms += vgettimeofday
>>     -endif
>>      vdso-syms += getcpu
>>      vdso-syms += flush_icache
>>
>> and it doesn't build.  I've added Arnd, who might have a better idea of what's
>> going on.  Whatever happens, I think the best bet is to just drop the clock
>> functions (specifically __vdso_{clock_gettime,gettimeofday,clock_getres}) from
>> the rv32 port right now.
> 
> For rv32 you need clock_gettime64, not clock_gettime, which in the Linux
> ABI refers to the interface with the old timespec. There was some debate
> over whether clock_getres_time64 and gettimeofday_time64 would make
> sense to be added here, but I have so far leaned to the position that these
> are not as performance critical and not worth the effort.
> 
> Vincenzo has argued that we might want to extend the generic vdso code
> to include a number of additional syscall implementations, which would
> then include gettimeofday_time64 and clock_getres_time64.
> 

I agree with Arnd, clock_getres_time64 and gettimeofday_time64 were not added in
the original port because not considered as performance critical as
clock_gettime64. We might reconsider if there is a strong use case for those.

>         Arnd
> 

-- 
Regards,
Vincenzo

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [musl] riscv32 v2
  2020-09-10 10:01           ` Vincenzo Frascino
@ 2020-09-11  0:08             ` Palmer Dabbelt
  0 siblings, 0 replies; 21+ messages in thread
From: Palmer Dabbelt @ 2020-09-11  0:08 UTC (permalink / raw)
  To: vincenzo.frascino; +Cc: Arnd Bergmann, dalias, musl

On Thu, 10 Sep 2020 03:01:31 PDT (-0700), vincenzo.frascino@arm.com wrote:
>
>
> On 9/10/20 8:36 AM, Arnd Bergmann wrote:
>> On Thu, Sep 10, 2020 at 1:08 AM Palmer Dabbelt <palmerdabbelt@google.com> wrote:
>>> On Wed, 09 Sep 2020 14:36:44 PDT (-0700), dalias@libc.org wrote:
>>>> On Wed, Sep 09, 2020 at 02:28:55PM -0700, Palmer Dabbelt wrote:
>>>>> On Wed, 09 Sep 2020 13:28:27 PDT (-0700), dalias@libc.org wrote:
>>>> Possible addition of vdso clock_gettime isn't a blocker for moving
>>>> forward with the musl port, but syscall_arch.h should accurately
>>>> describe what's available and should not attempt to use vdso before
>>>> it's a public kernel interface (e.g. resolving the question of what
>>>> the function name will be). So I think it should be removed for now.
>>>
>>> Sorry if that was confusing, but I definitely agree.
>>>
>>> I guess my point was that the lack of VDSO clock functions on rv32 was probably
>>> an oversight, but one that shouldn't block the port.  We definitely can't just
>>> make up a kernel interface, particularly as the reason we don't have these on
>>> rv32 is because the generic versions of the functions we're using don't appear
>>> to run on 32-bit targets.
>>>
>>> That probably means there's some more subtle issue, though TBH I don't know
>>> enough about the 64-bit-ification of time_t for it to just jump out at me.  I
>>> don't want to derail the thread too much, but I tried the obvious thing
>>
>> When the vdso for rv64 was added, there was no time64 support in the
>> vdso code in general, as this only came with the "generic vdso" infrastructure
>> that was added later on, with commit ad5d1122b82f ("riscv: use vDSO
>> common flow to reduce the latency of the time-related functions") in v5.8.
>>
>> At that point it probably should have been added as well.
>>
>>>     --- a/arch/riscv/kernel/vdso/Makefile
>>>     +++ b/arch/riscv/kernel/vdso/Makefile
>>>     @@ -7,9 +7,7 @@ ARCH_REL_TYPE_ABS := R_RISCV_32|R_RISCV_64|R_RISCV_JUMP_SLOT
>>>      include $(srctree)/lib/vdso/Makefile
>>>      # Symbols present in the vdso
>>>      vdso-syms  = rt_sigreturn
>>>     -ifdef CONFIG_64BIT
>>>      vdso-syms += vgettimeofday
>>>     -endif
>>>      vdso-syms += getcpu
>>>      vdso-syms += flush_icache
>>>
>>> and it doesn't build.  I've added Arnd, who might have a better idea of what's
>>> going on.  Whatever happens, I think the best bet is to just drop the clock
>>> functions (specifically __vdso_{clock_gettime,gettimeofday,clock_getres}) from
>>> the rv32 port right now.
>>
>> For rv32 you need clock_gettime64, not clock_gettime, which in the Linux
>> ABI refers to the interface with the old timespec. There was some debate
>> over whether clock_getres_time64 and gettimeofday_time64 would make
>> sense to be added here, but I have so far leaned to the position that these
>> are not as performance critical and not worth the effort.
>>
>> Vincenzo has argued that we might want to extend the generic vdso code
>> to include a number of additional syscall implementations, which would
>> then include gettimeofday_time64 and clock_getres_time64.
>>
>
> I agree with Arnd, clock_getres_time64 and gettimeofday_time64 were not added in
> the original port because not considered as performance critical as
> clock_gettime64. We might reconsider if there is a strong use case for those.

OK, seems reasonable to me.  I guess we can always add things later if they end
up being important, though I don't really have any feel for this sort of stuff
so I don't really have an opinion either way.

Thanks!

>
>>         Arnd
>>

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2020-09-11  0:28 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-04  5:48 [musl] riscv32 v2 Stefan O'Rear
2020-09-07 10:47 ` Stefan O'Rear
2020-09-07 18:06   ` Rich Felker
2020-09-07 21:35     ` Arnd Bergmann
2020-09-07 21:45       ` Rich Felker
2020-09-07 21:58         ` Arnd Bergmann
2020-09-07 22:11           ` Rich Felker
2020-09-07 22:30             ` Arnd Bergmann
2020-09-08  1:02               ` Rich Felker
2020-09-08  7:00                 ` Arnd Bergmann
2020-09-07 11:27 ` Stefan O'Rear
2020-09-07 18:09   ` Rich Felker
2020-09-08  1:54 ` Rich Felker
2020-09-09  6:07   ` Rich Felker
2020-09-09 20:28 ` Rich Felker
2020-09-09 21:28   ` Palmer Dabbelt
2020-09-09 21:36     ` Rich Felker
2020-09-09 23:08       ` Palmer Dabbelt
2020-09-10  7:36         ` Arnd Bergmann
2020-09-10 10:01           ` Vincenzo Frascino
2020-09-11  0:08             ` Palmer Dabbelt

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).