All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v6 0/4] Adressing y2038 test failures on ARM and BBB
@ 2021-05-07 21:51 Florian Bezdeka
  2021-05-07 21:51 ` [PATCH v6 1/4] cobalt/sem: y2038: Fixing the sem_timedwait syscall for 32 bit systems Florian Bezdeka
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Florian Bezdeka @ 2021-05-07 21:51 UTC (permalink / raw)
  To: xenomai

The CI pipeline discovered an invalid instruction on some ARM boards,
especially the BBB (beaglebone black). Applying this patch series should
fix the current test failure on "next" branch.

As already discussed: There might be another problem in the ARM syscall
prologue/epilogue but it still makes sense to use the same macro for
calling the syscalls as libcobalt does.

I'm still asking myself why libcobalt has special macros for calling the
syscalls instead of using plain syscall() from *libc. Any input?

The difference to v5:
 - Resend, forget to CC Philippe 
 - Fixed SPDX license header (newer version of checkpatch seems to care)
 - Fixed a typo in one of the test descriptions

The difference to v4:
 - Fixed the error handling / error reporting bugs introduced by v4
   errno => ret migration gone wrong
 - Took care of some review comments from Jan

The main difference to v3:
 - Migration from syscall() (libc) to XENOAMAI_SYSCALLx()


Florian Bezdeka (4):
  cobalt/sem: y2038: Fixing the sem_timedwait syscall for 32 bit systems
  y2038: Adding sem_timedwait64
  y2038: Add tests for the sc_cobalt_sem_timedwait64 syscall
  y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait64

 configure.ac                           |   1 +
 include/cobalt/kernel/time.h           |  20 +++
 include/cobalt/uapi/syscall.h          |   1 +
 kernel/cobalt/Makefile                 |   1 +
 kernel/cobalt/posix/sem.c              |  60 ++++++---
 kernel/cobalt/posix/sem.h              |  13 +-
 kernel/cobalt/posix/syscall32.c        |  17 ++-
 kernel/cobalt/posix/syscall32.h        |   6 +-
 kernel/cobalt/time.c                   |  27 ++++
 lib/cobalt/semaphore.c                 |   5 +
 testsuite/smokey/Makefile.am           |   6 +-
 testsuite/smokey/y2038/Makefile.am     |  10 ++
 testsuite/smokey/y2038/syscall-tests.c | 178 +++++++++++++++++++++++++
 13 files changed, 314 insertions(+), 31 deletions(-)
 create mode 100644 include/cobalt/kernel/time.h
 create mode 100644 kernel/cobalt/time.c
 create mode 100644 testsuite/smokey/y2038/Makefile.am
 create mode 100644 testsuite/smokey/y2038/syscall-tests.c

-- 
2.31.1



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

* [PATCH v6 1/4] cobalt/sem: y2038: Fixing the sem_timedwait syscall for 32 bit systems
  2021-05-07 21:51 [PATCH v6 0/4] Adressing y2038 test failures on ARM and BBB Florian Bezdeka
@ 2021-05-07 21:51 ` Florian Bezdeka
  2021-05-07 21:51 ` [PATCH v6 2/4] y2038: Adding sem_timedwait64 Florian Bezdeka
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Florian Bezdeka @ 2021-05-07 21:51 UTC (permalink / raw)
  To: xenomai

On systems using 32 bit for time_t the sem_timedwait syscall was broken
because the function used for copying the timeout value from userspace
to kernel (=sem_fetch_timeout()) was always copying
sizeof(struct timespec64).

A 32 bit application (or more specific an application with 4 byte
time_t) would only provide sizeof(struct old_timespec32).

Notable changes:
  - The copy operation from userspace to kernel is now already done in
    the syscall handler. So it is always done and might fail. Reporting
    a failure is delayed until the timeout is being validated.

  - Validation: Switched to timespec64_valid() instead of our own
    check.

Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
---
 kernel/cobalt/posix/sem.c       | 40 +++++++++++++++------------------
 kernel/cobalt/posix/sem.h       |  6 ++---
 kernel/cobalt/posix/syscall32.c | 10 +++++++--
 kernel/cobalt/posix/syscall32.h |  2 +-
 4 files changed, 29 insertions(+), 29 deletions(-)

diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
index 467a9b7dd..827a4751a 100644
--- a/kernel/cobalt/posix/sem.c
+++ b/kernel/cobalt/posix/sem.c
@@ -267,20 +267,11 @@ out:
 	return ret;
 }
 
-static inline int sem_fetch_timeout(struct timespec64 *ts,
-				    const void __user *u_ts)
-{
-	return u_ts == NULL ? -EFAULT :
-		cobalt_copy_from_user(ts, u_ts, sizeof(*ts));
-}
-
 int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
-			   const void __user *u_ts,
-			   int (*fetch_timeout)(struct timespec64 *ts,
-						const void __user *u_ts))
+			   const struct timespec64 *ts)
 {
-	struct timespec64 ts = { .tv_sec = 0, .tv_nsec = 0 };
-	int pull_ts = 1, ret, info;
+	int ret, info;
+	bool validate_ts = true;
 	struct cobalt_sem *sem;
 	xnhandle_t handle;
 	xntmode_t tmode;
@@ -304,24 +295,23 @@ int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
 		 * it's actually more complex, to keep some
 		 * applications ported to Linux happy.
 		 */
-		if (pull_ts) {
+		if (validate_ts) {
 			atomic_inc(&sem->state->value);
-			xnlock_put_irqrestore(&nklock, s);
-			ret = fetch_timeout(&ts, u_ts);
-			xnlock_get_irqsave(&nklock, s);
-			if (ret)
+			if (!ts) {
+				ret = -EFAULT;
 				break;
-			if (ts.tv_nsec >= ONE_BILLION) {
+			}
+			if (!timespec64_valid(ts)) {
 				ret = -EINVAL;
 				break;
 			}
-			pull_ts = 0;
+			validate_ts = false;
 			continue;
 		}
 
 		ret = 0;
 		tmode = sem->flags & SEM_RAWCLOCK ? XN_ABSOLUTE : XN_REALTIME;
-		info = xnsynch_sleep_on(&sem->synchbase, ts2ns(&ts) + 1, tmode);
+		info = xnsynch_sleep_on(&sem->synchbase, ts2ns(ts) + 1, tmode);
 		if (info & XNRMID)
 			ret = -EINVAL;
 		else if (info & (XNBREAK|XNTIMEO)) {
@@ -434,9 +424,15 @@ COBALT_SYSCALL(sem_wait, primary,
 
 COBALT_SYSCALL(sem_timedwait, primary,
 	       (struct cobalt_sem_shadow __user *u_sem,
-		struct __user_old_timespec __user *u_ts))
+		const struct __user_old_timespec __user *u_ts))
 {
-	return __cobalt_sem_timedwait(u_sem, u_ts, sem_fetch_timeout);
+	int ret = 1;
+	struct timespec64 ts64;
+
+	if (u_ts)
+		ret = cobalt_get_u_timespec(&ts64, u_ts);
+
+	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
 }
 
 COBALT_SYSCALL(sem_trywait, primary,
diff --git a/kernel/cobalt/posix/sem.h b/kernel/cobalt/posix/sem.h
index d17299495..658e11f7a 100644
--- a/kernel/cobalt/posix/sem.h
+++ b/kernel/cobalt/posix/sem.h
@@ -64,9 +64,7 @@ __cobalt_sem_open(struct cobalt_sem_shadow __user *usm,
 		  int oflags, mode_t mode, unsigned int value);
 
 int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
-			   const void __user *u_ts,
-			   int (*fetch_timeout)(struct timespec64 *ts,
-						const void __user *u_ts));
+			   const struct timespec64 *ts);
 
 int __cobalt_sem_destroy(xnhandle_t handle);
 
@@ -91,7 +89,7 @@ COBALT_SYSCALL_DECL(sem_wait,
 
 COBALT_SYSCALL_DECL(sem_timedwait,
 		    (struct cobalt_sem_shadow __user *u_sem,
-		     struct __user_old_timespec __user *u_ts));
+		     const struct __user_old_timespec __user *u_ts));
 
 COBALT_SYSCALL_DECL(sem_trywait,
 		    (struct cobalt_sem_shadow __user *u_sem));
diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c
index 57aa7251a..edac7ea4a 100644
--- a/kernel/cobalt/posix/syscall32.c
+++ b/kernel/cobalt/posix/syscall32.c
@@ -124,9 +124,15 @@ COBALT_SYSCALL32emu(sem_open, lostage,
 
 COBALT_SYSCALL32emu(sem_timedwait, primary,
 		    (struct cobalt_sem_shadow __user *u_sem,
-		     struct old_timespec32 __user *u_ts))
+		     const struct old_timespec32 __user *u_ts))
 {
-	return __cobalt_sem_timedwait(u_sem, u_ts, sys32_fetch_timeout);
+	int ret = 1;
+	struct timespec64 ts64;
+
+	if (u_ts)
+		ret = sys32_fetch_timeout(&ts64, u_ts);
+
+	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
 }
 
 COBALT_SYSCALL32emu(clock_getres, current,
diff --git a/kernel/cobalt/posix/syscall32.h b/kernel/cobalt/posix/syscall32.h
index 66cd2a5d2..d72fd2022 100644
--- a/kernel/cobalt/posix/syscall32.h
+++ b/kernel/cobalt/posix/syscall32.h
@@ -229,6 +229,6 @@ COBALT_SYSCALL32emu_DECL(sem_open,
 
 COBALT_SYSCALL32emu_DECL(sem_timedwait,
 			 (struct cobalt_sem_shadow __user *u_sem,
-			  struct old_timespec32 __user *u_ts));
+			  const struct old_timespec32 __user *u_ts));
 
 #endif /* !_COBALT_POSIX_SYSCALL32_H */
-- 
2.31.1



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

* [PATCH v6 2/4] y2038: Adding sem_timedwait64
  2021-05-07 21:51 [PATCH v6 0/4] Adressing y2038 test failures on ARM and BBB Florian Bezdeka
  2021-05-07 21:51 ` [PATCH v6 1/4] cobalt/sem: y2038: Fixing the sem_timedwait syscall for 32 bit systems Florian Bezdeka
@ 2021-05-07 21:51 ` Florian Bezdeka
  2021-05-07 21:51 ` [PATCH v6 3/4] y2038: Add tests for the sc_cobalt_sem_timedwait64 syscall Florian Bezdeka
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Florian Bezdeka @ 2021-05-07 21:51 UTC (permalink / raw)
  To: xenomai

Implementation is heavily inspired by the sem_timedwait syscall,
but expecting time64 based timespec / timeout.

We need two new syscall handlers:
  - The native one (COBALT_SYSCALL()) to get 32 bit kernels time64
    aware. This handler is added for 64 bit kernels as well, but not
    used. As we don't have separate syscall tables for this both
    worlds we have to add it.

 - The compat handler (COBALT_SYSCALL32emu()) for x32 or x86
   applications running on an x86_64 kernel. Otherwise the redirection
   to the compat / emulation syscalls is broken.

Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
---
 include/cobalt/kernel/time.h    | 20 ++++++++++++++++++++
 include/cobalt/uapi/syscall.h   |  1 +
 kernel/cobalt/Makefile          |  1 +
 kernel/cobalt/posix/sem.c       | 20 ++++++++++++++++++++
 kernel/cobalt/posix/sem.h       |  7 +++++++
 kernel/cobalt/posix/syscall32.c |  7 +++++++
 kernel/cobalt/posix/syscall32.h |  4 ++++
 kernel/cobalt/time.c            | 27 +++++++++++++++++++++++++++
 8 files changed, 87 insertions(+)
 create mode 100644 include/cobalt/kernel/time.h
 create mode 100644 kernel/cobalt/time.c

diff --git a/include/cobalt/kernel/time.h b/include/cobalt/kernel/time.h
new file mode 100644
index 000000000..9c6fc3ca2
--- /dev/null
+++ b/include/cobalt/kernel/time.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _COBALT_KERNEL_TIME_H
+#define _COBALT_KERNEL_TIME_H
+
+#include <linux/time.h>
+#include <linux/time64.h>
+
+/**
+ * Read struct __kernel_timespec from userspace and convert to
+ * struct timespec64
+ *
+ * @param ts The destination, will be filled
+ * @param uts The source, provided by an application
+ * @return 0 on success, -EFAULT otherwise
+ */
+int cobalt_get_timespec64(struct timespec64 *ts,
+			  const struct __kernel_timespec __user *uts);
+
+#endif //_COBALT_KERNEL_TIME_H
diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
index aa3c308d0..8895d2bff 100644
--- a/include/cobalt/uapi/syscall.h
+++ b/include/cobalt/uapi/syscall.h
@@ -122,6 +122,7 @@
 #define sc_cobalt_sendmmsg			99
 #define sc_cobalt_clock_adjtime			100
 #define sc_cobalt_thread_setschedprio		101
+#define sc_cobalt_sem_timedwait64		102
 
 #define __NR_COBALT_SYSCALLS			128 /* Power of 2 */
 
diff --git a/kernel/cobalt/Makefile b/kernel/cobalt/Makefile
index 129005d8f..6cd2d5994 100644
--- a/kernel/cobalt/Makefile
+++ b/kernel/cobalt/Makefile
@@ -13,6 +13,7 @@ xenomai-y :=	arith.o 	\
 		select.o	\
 		synch.o		\
 		thread.o	\
+		time.o		\
 		timer.o		\
 		tree.o
 
diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
index 827a4751a..72b20c78d 100644
--- a/kernel/cobalt/posix/sem.c
+++ b/kernel/cobalt/posix/sem.c
@@ -19,6 +19,7 @@
 
 #include <stddef.h>
 #include <linux/err.h>
+#include <cobalt/kernel/time.h>
 #include "internal.h"
 #include "thread.h"
 #include "clock.h"
@@ -326,6 +327,18 @@ int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
 	return ret;
 }
 
+int __cobalt_sem_timedwait64(struct cobalt_sem_shadow __user *u_sem,
+			     const struct __kernel_timespec __user *u_ts)
+{
+	int ret = 1;
+	struct timespec64 ts64;
+
+	if (u_ts)
+		ret = cobalt_get_timespec64(&ts64, u_ts);
+
+	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
+}
+
 static int sem_post(xnhandle_t handle)
 {
 	struct cobalt_sem *sem;
@@ -435,6 +448,13 @@ COBALT_SYSCALL(sem_timedwait, primary,
 	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
 }
 
+COBALT_SYSCALL(sem_timedwait64, primary,
+	       (struct cobalt_sem_shadow __user *u_sem,
+		const struct __kernel_timespec __user *u_ts))
+{
+	return __cobalt_sem_timedwait64(u_sem, u_ts);
+}
+
 COBALT_SYSCALL(sem_trywait, primary,
 	       (struct cobalt_sem_shadow __user *u_sem))
 {
diff --git a/kernel/cobalt/posix/sem.h b/kernel/cobalt/posix/sem.h
index 658e11f7a..d7dbb9098 100644
--- a/kernel/cobalt/posix/sem.h
+++ b/kernel/cobalt/posix/sem.h
@@ -66,6 +66,9 @@ __cobalt_sem_open(struct cobalt_sem_shadow __user *usm,
 int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
 			   const struct timespec64 *ts);
 
+int __cobalt_sem_timedwait64(struct cobalt_sem_shadow __user *u_sem,
+			     const struct __kernel_timespec __user *u_ts);
+
 int __cobalt_sem_destroy(xnhandle_t handle);
 
 void cobalt_nsem_reclaim(struct cobalt_process *process);
@@ -91,6 +94,10 @@ COBALT_SYSCALL_DECL(sem_timedwait,
 		    (struct cobalt_sem_shadow __user *u_sem,
 		     const struct __user_old_timespec __user *u_ts));
 
+COBALT_SYSCALL_DECL(sem_timedwait64,
+		    (struct cobalt_sem_shadow __user *u_sem,
+		     const struct __kernel_timespec __user *u_ts));
+
 COBALT_SYSCALL_DECL(sem_trywait,
 		    (struct cobalt_sem_shadow __user *u_sem));
 
diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c
index edac7ea4a..a5dc6e48f 100644
--- a/kernel/cobalt/posix/syscall32.c
+++ b/kernel/cobalt/posix/syscall32.c
@@ -135,6 +135,13 @@ COBALT_SYSCALL32emu(sem_timedwait, primary,
 	return __cobalt_sem_timedwait(u_sem, ret ? NULL : &ts64);
 }
 
+COBALT_SYSCALL32emu(sem_timedwait64, primary,
+		    (struct cobalt_sem_shadow __user *u_sem,
+		     const struct __kernel_timespec __user *u_ts))
+{
+	return __cobalt_sem_timedwait64(u_sem, u_ts);
+}
+
 COBALT_SYSCALL32emu(clock_getres, current,
 		    (clockid_t clock_id,
 		     struct old_timespec32 __user *u_ts))
diff --git a/kernel/cobalt/posix/syscall32.h b/kernel/cobalt/posix/syscall32.h
index d72fd2022..bb62875ad 100644
--- a/kernel/cobalt/posix/syscall32.h
+++ b/kernel/cobalt/posix/syscall32.h
@@ -231,4 +231,8 @@ COBALT_SYSCALL32emu_DECL(sem_timedwait,
 			 (struct cobalt_sem_shadow __user *u_sem,
 			  const struct old_timespec32 __user *u_ts));
 
+COBALT_SYSCALL32emu_DECL(sem_timedwait64,
+			 (struct cobalt_sem_shadow __user *u_sem,
+			  const struct __kernel_timespec __user *u_ts));
+
 #endif /* !_COBALT_POSIX_SYSCALL32_H */
diff --git a/kernel/cobalt/time.c b/kernel/cobalt/time.c
new file mode 100644
index 000000000..c66e07478
--- /dev/null
+++ b/kernel/cobalt/time.c
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <asm-generic/xenomai/syscall.h>
+#include <cobalt/kernel/time.h>
+#include <linux/compat.h>
+
+int cobalt_get_timespec64(struct timespec64 *ts,
+			  const struct __kernel_timespec __user *uts)
+{
+	struct __kernel_timespec kts;
+	int ret;
+
+	ret = cobalt_copy_from_user(&kts, uts, sizeof(kts));
+	if (ret)
+		return -EFAULT;
+
+	ts->tv_sec = kts.tv_sec;
+
+	/* Zero out the padding in compat mode */
+	if (in_compat_syscall())
+		kts.tv_nsec &= 0xFFFFFFFFUL;
+
+	/* In 32-bit mode, this drops the padding */
+	ts->tv_nsec = kts.tv_nsec;
+
+	return 0;
+}
-- 
2.31.1



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

* [PATCH v6 3/4] y2038: Add tests for the sc_cobalt_sem_timedwait64 syscall
  2021-05-07 21:51 [PATCH v6 0/4] Adressing y2038 test failures on ARM and BBB Florian Bezdeka
  2021-05-07 21:51 ` [PATCH v6 1/4] cobalt/sem: y2038: Fixing the sem_timedwait syscall for 32 bit systems Florian Bezdeka
  2021-05-07 21:51 ` [PATCH v6 2/4] y2038: Adding sem_timedwait64 Florian Bezdeka
@ 2021-05-07 21:51 ` Florian Bezdeka
  2021-05-07 21:51 ` [PATCH v6 4/4] y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait64 Florian Bezdeka
  2021-05-10  6:51 ` [PATCH v6 0/4] Adressing y2038 test failures on ARM and BBB Jan Kiszka
  4 siblings, 0 replies; 7+ messages in thread
From: Florian Bezdeka @ 2021-05-07 21:51 UTC (permalink / raw)
  To: xenomai

Introducing a new smokey plugin that can be extended for all kind of
y2038 tests. For now we are testing the new sc_cobalt_sem_timedwait64
syscall without using any libc wrappers provided by libcobalt.

Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
---
 configure.ac                           |   1 +
 testsuite/smokey/Makefile.am           |   6 +-
 testsuite/smokey/y2038/Makefile.am     |  10 ++
 testsuite/smokey/y2038/syscall-tests.c | 178 +++++++++++++++++++++++++
 4 files changed, 193 insertions(+), 2 deletions(-)
 create mode 100644 testsuite/smokey/y2038/Makefile.am
 create mode 100644 testsuite/smokey/y2038/syscall-tests.c

diff --git a/configure.ac b/configure.ac
index abe538dbd..bd5fd5ba9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -990,6 +990,7 @@ AC_CONFIG_FILES([ \
 	testsuite/smokey/net_common/Makefile \
 	testsuite/smokey/cpu-affinity/Makefile \
 	testsuite/smokey/gdb/Makefile \
+	testsuite/smokey/y2038/Makefile \
 	testsuite/clocktest/Makefile \
 	testsuite/xeno-test/Makefile \
 	utils/Makefile \
diff --git a/testsuite/smokey/Makefile.am b/testsuite/smokey/Makefile.am
index 02613c7dc..56c873026 100644
--- a/testsuite/smokey/Makefile.am
+++ b/testsuite/smokey/Makefile.am
@@ -38,7 +38,8 @@ COBALT_SUBDIRS = 	\
 	timerfd		\
 	tsc		\
 	vdso-access 	\
-	xddp
+	xddp		\
+	y2038
 
 MERCURY_SUBDIRS =	\
 	memory-heapmem	\
@@ -76,7 +77,8 @@ DIST_SUBDIRS = 		\
 	timerfd		\
 	tsc		\
 	vdso-access 	\
-	xddp
+	xddp		\
+	y2038
 
 if XENO_COBALT
 if CONFIG_XENO_LIBS_DLOPEN
diff --git a/testsuite/smokey/y2038/Makefile.am b/testsuite/smokey/y2038/Makefile.am
new file mode 100644
index 000000000..8dd4c9734
--- /dev/null
+++ b/testsuite/smokey/y2038/Makefile.am
@@ -0,0 +1,10 @@
+
+noinst_LIBRARIES = liby2038.a
+
+liby2038_a_SOURCES = syscall-tests.c
+
+liby2038_a_CPPFLAGS = 	\
+	@XENO_COBALT_CFLAGS@	\
+	-I$(top_srcdir)		\
+	-I$(top_srcdir)/include \
+	-I$(top_srcdir)/lib/cobalt/arch/@XENO_TARGET_ARCH@/include
diff --git a/testsuite/smokey/y2038/syscall-tests.c b/testsuite/smokey/y2038/syscall-tests.c
new file mode 100644
index 000000000..716be4f2a
--- /dev/null
+++ b/testsuite/smokey/y2038/syscall-tests.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * y2038 tests
+ *
+ * Copyright (c) Siemens AG 2021
+ *
+ * Authors:
+ *  Florian Bezdeka <florian.bezdeka@siemens.com>
+ *
+ * Released under the terms of GPLv2.
+ */
+#include <asm/xenomai/syscall.h>
+#include <cobalt/uapi/syscall.h>
+#include <smokey/smokey.h>
+#include <semaphore.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <errno.h>
+
+smokey_test_plugin(y2038, SMOKEY_NOARGS, "Validate correct y2038 support");
+
+/*
+ * libc independent data type representing a time64_t based struct timespec
+ */
+struct xn_timespec64 {
+	int64_t tv_sec;
+	int64_t tv_nsec;
+};
+
+#define NSEC_PER_SEC 1000000000
+
+static void ts_normalise(struct xn_timespec64 *ts)
+{
+	while (ts->tv_nsec >= NSEC_PER_SEC) {
+		ts->tv_nsec += 1;
+		ts->tv_nsec -= NSEC_PER_SEC;
+	}
+
+	while (ts->tv_nsec <= -NSEC_PER_SEC) {
+		ts->tv_sec -= 1;
+		ts->tv_nsec += NSEC_PER_SEC;
+	}
+
+	if (ts->tv_nsec < 0) {
+		/*
+		 * Negative nanoseconds isn't valid according to POSIX.
+		 * Decrement tv_sec and roll tv_nsec over.
+		 */
+		ts->tv_sec -= 1;
+		ts->tv_nsec = (NSEC_PER_SEC + ts->tv_nsec);
+	}
+}
+
+static inline void ts_add_ns(struct xn_timespec64 *ts, int ns)
+{
+	ts->tv_nsec += ns;
+	ts_normalise(ts);
+}
+
+/**
+ * Compare two struct timespec instances
+ *
+ * @param a
+ * @param b
+ * @return True if a < b, false otherwise
+ */
+static inline bool ts_less(const struct xn_timespec64 *a,
+			   const struct xn_timespec64 *b)
+{
+	if (a->tv_sec < b->tv_sec)
+		return true;
+
+	if (a->tv_sec > b->tv_sec)
+		return false;
+
+	/* a->tv_sec == b->tv_sec */
+
+	if (a->tv_nsec < b->tv_nsec)
+		return true;
+
+	return false;
+}
+
+static int test_sc_cobalt_sem_timedwait64(void)
+{
+	int ret;
+	sem_t sem;
+	int sc_nr = sc_cobalt_sem_timedwait64;
+	struct xn_timespec64 ts64, ts_wu;
+	struct timespec ts_nat;
+
+	sem_init(&sem, 0, 0);
+
+	/* Make sure we don't crash because of NULL pointers */
+	ret = XENOMAI_SYSCALL2(sc_nr, NULL, NULL);
+	if (ret == -ENOSYS) {
+		smokey_note("sem_timedwait64: skipped. (no kernel support)");
+		return 0; // Not implemented, nothing to test, success
+	}
+	if (!smokey_assert(ret == -EINVAL))
+		return ret ? ret : -EINVAL;
+
+	/* Timeout is never read by the kernel, so NULL should be OK */
+	sem_post(&sem);
+	ret = XENOMAI_SYSCALL2(sc_nr, &sem, NULL);
+	if (!smokey_assert(!ret))
+		return ret ? ret : -EINVAL;
+
+	/*
+	 * The semaphore is already exhausted, so calling again will validate
+	 * the provided timeout now. Providing NULL has to deliver EFAULT
+	 */
+	ret = XENOMAI_SYSCALL2(sc_nr, &sem, NULL);
+	if (!smokey_assert(ret == -EFAULT))
+		return ret ? ret : -EINVAL;
+
+	/*
+	 * The semaphore is already exhausted, so calling again will validate
+	 * the provided timeout now. Providing an invalid address has to deliver
+	 * EFAULT
+	 */
+	ret = XENOMAI_SYSCALL2(sc_nr, &sem, (void *)0xdeadbeefUL);
+	if (!smokey_assert(ret == -EFAULT))
+		return ret ? ret : -EINVAL;
+
+	/*
+	 * The semaphore is still exhausted, calling again will validate the
+	 * timeout, providing an invalid timeout has to deliver EINVAL
+	 */
+	ts64.tv_sec = -1;
+	ret = XENOMAI_SYSCALL2(sc_nr, &sem, &ts64);
+	if (!smokey_assert(ret == -EINVAL))
+		return ret ? ret : -EINVAL;
+
+	/*
+	 * Providing a valid timeout, waiting for it to time out and check
+	 * that we didn't come back to early.
+	 */
+	ret = clock_gettime(CLOCK_MONOTONIC, &ts_nat);
+	if (ret)
+		return -errno;
+
+	ts64.tv_sec = ts_nat.tv_sec;
+	ts64.tv_nsec = ts_nat.tv_nsec;
+	ts_add_ns(&ts64, 500000);
+
+	ret = XENOMAI_SYSCALL2(sc_nr, &sem, &ts64);
+	if (!smokey_assert(ret == -ETIMEDOUT))
+		return ret;
+
+	ret = clock_gettime(CLOCK_MONOTONIC, &ts_nat);
+	if (ret)
+		return -errno;
+
+	ts_wu.tv_sec = ts_nat.tv_sec;
+	ts_wu.tv_nsec = ts_nat.tv_nsec;
+
+	if (ts_less(&ts_wu, &ts64))
+		smokey_warning("sem_timedwait64 returned to early!\n"
+			       "Expected wakeup at: %lld sec %lld nsec\n"
+			       "Back at           : %lld sec %lld nsec\n",
+			       ts64.tv_sec, ts64.tv_nsec, ts_wu.tv_sec,
+			       ts_wu.tv_nsec);
+
+	return 0;
+}
+
+static int run_y2038(struct smokey_test *t, int argc, char *const argv[])
+{
+	int ret;
+
+	ret = test_sc_cobalt_sem_timedwait64();
+	if (ret)
+		return ret;
+
+	return 0;
+}
-- 
2.31.1



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

* [PATCH v6 4/4] y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait64
  2021-05-07 21:51 [PATCH v6 0/4] Adressing y2038 test failures on ARM and BBB Florian Bezdeka
                   ` (2 preceding siblings ...)
  2021-05-07 21:51 ` [PATCH v6 3/4] y2038: Add tests for the sc_cobalt_sem_timedwait64 syscall Florian Bezdeka
@ 2021-05-07 21:51 ` Florian Bezdeka
  2021-05-10  6:51 ` [PATCH v6 0/4] Adressing y2038 test failures on ARM and BBB Jan Kiszka
  4 siblings, 0 replies; 7+ messages in thread
From: Florian Bezdeka @ 2021-05-07 21:51 UTC (permalink / raw)
  To: xenomai

In case libcobalt is build with -D_TIME_BITS=64
sc_cobalt_sem_timedwait64 will be used instead of
sc_cobalt_sem_timedwait.

Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
---
 lib/cobalt/semaphore.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/lib/cobalt/semaphore.c b/lib/cobalt/semaphore.c
index 45705d48f..bff005440 100644
--- a/lib/cobalt/semaphore.c
+++ b/lib/cobalt/semaphore.c
@@ -373,7 +373,12 @@ COBALT_IMPL(int, sem_timedwait, (sem_t *sem, const struct timespec *abs_timeout)
 
 	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
 
+#ifdef __USE_TIME_BITS64
+	ret = XENOMAI_SYSCALL2(sc_cobalt_sem_timedwait64, _sem,
+			       abs_timeout);
+#else
 	ret = XENOMAI_SYSCALL2(sc_cobalt_sem_timedwait, _sem, abs_timeout);
+#endif
 
 	pthread_setcanceltype(oldtype, NULL);
 
-- 
2.31.1



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

* Re: [PATCH v6 0/4] Adressing y2038 test failures on ARM and BBB
  2021-05-07 21:51 [PATCH v6 0/4] Adressing y2038 test failures on ARM and BBB Florian Bezdeka
                   ` (3 preceding siblings ...)
  2021-05-07 21:51 ` [PATCH v6 4/4] y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait64 Florian Bezdeka
@ 2021-05-10  6:51 ` Jan Kiszka
  2021-05-15 16:12   ` Philippe Gerum
  4 siblings, 1 reply; 7+ messages in thread
From: Jan Kiszka @ 2021-05-10  6:51 UTC (permalink / raw)
  To: Florian Bezdeka, xenomai

On 07.05.21 23:51, Florian Bezdeka wrote:
> The CI pipeline discovered an invalid instruction on some ARM boards,
> especially the BBB (beaglebone black). Applying this patch series should
> fix the current test failure on "next" branch.
> 
> As already discussed: There might be another problem in the ARM syscall
> prologue/epilogue but it still makes sense to use the same macro for
> calling the syscalls as libcobalt does.
> 
> I'm still asking myself why libcobalt has special macros for calling the
> syscalls instead of using plain syscall() from *libc. Any input?
> 
> The difference to v5:
>  - Resend, forget to CC Philippe 
>  - Fixed SPDX license header (newer version of checkpatch seems to care)
>  - Fixed a typo in one of the test descriptions
> 
> The difference to v4:
>  - Fixed the error handling / error reporting bugs introduced by v4
>    errno => ret migration gone wrong
>  - Took care of some review comments from Jan
> 
> The main difference to v3:
>  - Migration from syscall() (libc) to XENOAMAI_SYSCALLx()
> 
> 
> Florian Bezdeka (4):
>   cobalt/sem: y2038: Fixing the sem_timedwait syscall for 32 bit systems
>   y2038: Adding sem_timedwait64
>   y2038: Add tests for the sc_cobalt_sem_timedwait64 syscall
>   y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait64
> 
>  configure.ac                           |   1 +
>  include/cobalt/kernel/time.h           |  20 +++
>  include/cobalt/uapi/syscall.h          |   1 +
>  kernel/cobalt/Makefile                 |   1 +
>  kernel/cobalt/posix/sem.c              |  60 ++++++---
>  kernel/cobalt/posix/sem.h              |  13 +-
>  kernel/cobalt/posix/syscall32.c        |  17 ++-
>  kernel/cobalt/posix/syscall32.h        |   6 +-
>  kernel/cobalt/time.c                   |  27 ++++
>  lib/cobalt/semaphore.c                 |   5 +
>  testsuite/smokey/Makefile.am           |   6 +-
>  testsuite/smokey/y2038/Makefile.am     |  10 ++
>  testsuite/smokey/y2038/syscall-tests.c | 178 +++++++++++++++++++++++++
>  13 files changed, 314 insertions(+), 31 deletions(-)
>  create mode 100644 include/cobalt/kernel/time.h
>  create mode 100644 kernel/cobalt/time.c
>  create mode 100644 testsuite/smokey/y2038/Makefile.am
>  create mode 100644 testsuite/smokey/y2038/syscall-tests.c
> 

With these four plus the first 5 of [1], testing passed - thanks, merged.

Jan

[1] https://xenomai.org/pipermail/xenomai/2021-May/045094.html

-- 
Siemens AG, T RDA IOT
Corporate Competence Center Embedded Linux


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

* Re: [PATCH v6 0/4] Adressing y2038 test failures on ARM and BBB
  2021-05-10  6:51 ` [PATCH v6 0/4] Adressing y2038 test failures on ARM and BBB Jan Kiszka
@ 2021-05-15 16:12   ` Philippe Gerum
  0 siblings, 0 replies; 7+ messages in thread
From: Philippe Gerum @ 2021-05-15 16:12 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: Florian Bezdeka, xenomai, chensong_2000


Jan Kiszka <jan.kiszka@siemens.com> writes:

> On 07.05.21 23:51, Florian Bezdeka wrote:
>> The CI pipeline discovered an invalid instruction on some ARM boards,
>> especially the BBB (beaglebone black). Applying this patch series should
>> fix the current test failure on "next" branch.
>> 
>> As already discussed: There might be another problem in the ARM syscall
>> prologue/epilogue but it still makes sense to use the same macro for
>> calling the syscalls as libcobalt does.
>> 
>> I'm still asking myself why libcobalt has special macros for calling the
>> syscalls instead of using plain syscall() from *libc. Any input?
>> 
>> The difference to v5:
>>  - Resend, forget to CC Philippe 
>>  - Fixed SPDX license header (newer version of checkpatch seems to care)
>>  - Fixed a typo in one of the test descriptions
>> 
>> The difference to v4:
>>  - Fixed the error handling / error reporting bugs introduced by v4
>>    errno => ret migration gone wrong
>>  - Took care of some review comments from Jan
>> 
>> The main difference to v3:
>>  - Migration from syscall() (libc) to XENOAMAI_SYSCALLx()
>> 
>> 
>> Florian Bezdeka (4):
>>   cobalt/sem: y2038: Fixing the sem_timedwait syscall for 32 bit systems
>>   y2038: Adding sem_timedwait64
>>   y2038: Add tests for the sc_cobalt_sem_timedwait64 syscall
>>   y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait64
>> 
>>  configure.ac                           |   1 +
>>  include/cobalt/kernel/time.h           |  20 +++
>>  include/cobalt/uapi/syscall.h          |   1 +
>>  kernel/cobalt/Makefile                 |   1 +
>>  kernel/cobalt/posix/sem.c              |  60 ++++++---
>>  kernel/cobalt/posix/sem.h              |  13 +-
>>  kernel/cobalt/posix/syscall32.c        |  17 ++-
>>  kernel/cobalt/posix/syscall32.h        |   6 +-
>>  kernel/cobalt/time.c                   |  27 ++++
>>  lib/cobalt/semaphore.c                 |   5 +
>>  testsuite/smokey/Makefile.am           |   6 +-
>>  testsuite/smokey/y2038/Makefile.am     |  10 ++
>>  testsuite/smokey/y2038/syscall-tests.c | 178 +++++++++++++++++++++++++
>>  13 files changed, 314 insertions(+), 31 deletions(-)
>>  create mode 100644 include/cobalt/kernel/time.h
>>  create mode 100644 kernel/cobalt/time.c
>>  create mode 100644 testsuite/smokey/y2038/Makefile.am
>>  create mode 100644 testsuite/smokey/y2038/syscall-tests.c
>> 
>
> With these four plus the first 5 of [1], testing passed - thanks, merged.
>
> Jan
>
> [1] https://xenomai.org/pipermail/xenomai/2021-May/045094.html

There is a kernel splat when CONFIG_DEBUG_DOVETAIL is enabled here, as a
result of running smokey--run=y2038 specifically, no other test triggers
this. Observed on x86 and ARM indifferently. Dovetail complains about
the (virtual) interrupt state being broken, meaning irqs_disabled() on
return from a pipelined syscall handled by Cobalt, while still running
in-band:

[  527.286726] WARNING: CPU: 1 PID: 230 at kernel/dovetail.c:224 pipeline_syscall+0x88/0xd0
[  527.294854] Modules linked in:
[  527.297948] CPU: 1 PID: 230 Comm: smokey Not tainted 5.10.32+ #63
[  527.304068] Hardware name: TQ-Group TQMxE39M/Type2 - Board Product Name, BIOS 5.12.09.16.05 07/26/2017
[  527.313393] IRQ stage: Linux
[  527.316290] RIP: 0010:pipeline_syscall+0x88/0xd0
[  527.320923] Code: 00 e8 ec f5 04 00 8b 43 08 a8 04 74 26 48 8b 03 a9 00 00 00 04 75 2e 5b 5d b8 01 00 00 00 41 5c c3 e8 fc ad 7c 00 85 c0 74 14 <0f> 0b b8 ff ff ff ff eb ae e8 ea ad 7c 00 85 c0 74 02 0f 0b b8 ff
[  527.339702] RSP: 0018:ffffc9000007ff10 EFLAGS: 00010202
[  527.344945] RAX: 0000000000000001 RBX: ffff888101a03a80 RCX: 00000000ffffffff
[  527.352091] RDX: 0000000000000000 RSI: 0000000000000286 RDI: 0000000000000001
[  527.359235] RBP: ffffc9000007ff58 R08: 0000000000000286 R09: ffffffff82309340
[  527.366380] R10: 0000000000000001 R11: 0000000000000000 R12: 0000000010000066
[  527.373525] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
[  527.380669] FS:  00007f8154aed740(0000) GS:ffff88817bc80000(0000) knlGS:0000000000000000
[  527.388761] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  527.394517] CR2: 0000000000000008 CR3: 0000000101af2000 CR4: 00000000003506e0
[  527.401663] Call Trace:
[  527.404138]  syscall_enter_from_user_mode+0x25/0x80
[  527.409037]  do_syscall_64+0xf/0x90
[  527.412540]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[  527.417608] RIP: 0033:0x41c753
[  527.420681] Code: 83 f9 ff ff 0f 1f 00 41 54 31 f6 31 d2 55 bd 66 00 00 10 53 48 83 ec 40 48 8d 7c 24 20 e8 45 8e fe ff 31 f6 31 ff 89 e8 0f 05 <83> f8 da 0f 84 dc 00 00 00 48 89 c3 83 f8 ea 75 4c 48 8d 7c 24 20
[  527.439466] RSP: 002b:00007fff2ddb06c0 EFLAGS: 00000246 ORIG_RAX: 0000000010000066
[  527.447051] RAX: ffffffffffffffea RBX: 00000000004284c0 RCX: 000000000041c753
[  527.454200] RDX: 0000000000001000 RSI: 0000000000000000 RDI: 0000000000000000
[  527.461351] RBP: 0000000010000066 R08: 00007fff2ddb0694 R09: 0000000000000000
[  527.468498] R10: ffffffffffffffcc R11: 0000000000000246 R12: 00000000023dca20
[  527.475653] R13: 00007f8154aed740 R14: 0000000000000000 R15: 0000000000000000
[  527.482800] ---[ end trace 1c9b99d832e6d115 ]---
syscall-tests.c:160, sem_timedwait64 returned to early!
Expected wakeup at: 526 sec 163325942 nsec
Back at           : 526 sec 162839069 nsec

[   17.206475] ------------[ cut here ]------------
[   17.211138] WARNING: CPU: 3 PID: 229 at kernel/dovetail.c:224 pipeline_syscall+0x88/0xd0
[   17.219269] Modules linked in:
[   17.222349] CPU: 3 PID: 229 Comm: smokey Not tainted 5.10.32+ #64
[   17.228483] Hardware name: TQ-Group TQMxE39M/Type2 - Board Product Name, BIOS 5.12.09.16.05 07/26/2017
[   17.237817] IRQ stage: Linux
[   17.240729] RIP: 0010:pipeline_syscall+0x88/0xd0
[   17.245367] Code: 00 e8 ec f5 04 00 8b 43 08 a8 04 74 26 48 8b 03 a9 00 00 00 04 75 2e 5b 5d b8 01 00 00 00 41 5c c3 e8 fc ad 7c 00 85 c0 74 14 <0f> 0b b8 ff ff ff ff eb ae e8 ea ad 7c 00 85 c0 74 02 0f 0b b8 ff
[   17.264180] RSP: 0018:ffffc90000253f10 EFLAGS: 00010202
[   17.269432] RAX: 0000000000000001 RBX: ffff888101b78000 RCX: 00000000fffffffd
[   17.276594] RDX: 0000000000000000 RSI: 0000000000000286 RDI: 0000000000000003
[   17.283748] RBP: ffffc90000253f58 R08: 0000000000000286 R09: ffffffff82309340
[   17.290903] R10: 0000000000000003 R11: 0000000000000000 R12: 0000000010000066
[   17.298056] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
[   17.305213] FS:  00007f4d06618740(0000) GS:ffff88817bd80000(0000) knlGS:0000000000000000
[   17.313323] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   17.319087] CR2: 0000000000000008 CR3: 0000000101c14000 CR4: 00000000003506e0
[   17.326241] Call Trace:
[   17.328719]  syscall_enter_from_user_mode+0x25/0x80
[   17.333620]  do_syscall_64+0xf/0x90
[   17.337132]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[   17.342204] RIP: 0033:0x41c753
[   17.345284] Code: 83 f9 ff ff 0f 1f 00 41 54 31 f6 31 d2 55 bd 66 00 00 10 53 48 83 ec 40 48 8d 7c 24 20 e8 45 8e fe ff 31 f6 31 ff 89 e8 0f 05 <83> f8 da 0f 84 dc 00 00 00 48 89 c3 83 f8 ea 75 4c 48 8d 7c 24 20
[   17.364116] RSP: 002b:00007fff618cb770 EFLAGS: 00000246 ORIG_RAX: 0000000010000066
[   17.371713] RAX: ffffffffffffffea RBX: 00000000004284c0 RCX: 000000000041c753
[   17.378868] RDX: 0000000000001000 RSI: 0000000000000000 RDI: 0000000000000000
[   17.386026] RBP: 0000000010000066 R08: 00007fff618cb744 R09: 0000000000000000
[   17.393176] R10: ffffffffffffffcc R11: 0000000000000246 R12: 00000000010d3a20
[   17.400335] R13: 00007f4d06618740 R14: 0000000000000000 R15: 0000000000000000
[   17.407493] ---[ end trace 8da7e02b222f4015 ]---
syscall-tests.c:160, sem_timedwait64 returned to early!
Expected wakeup at: 16 sec 86652042 nsec
Back at           : 16 sec 86165276 nsec

Running from
https://lab.xenomai.org/xenomai-rpm.git/log/?h=for-upstream/dovetail,
which has just been rebased over -next. I did not look at the issue
closely yet.

-- 
Philippe.


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

end of thread, other threads:[~2021-05-15 16:12 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-07 21:51 [PATCH v6 0/4] Adressing y2038 test failures on ARM and BBB Florian Bezdeka
2021-05-07 21:51 ` [PATCH v6 1/4] cobalt/sem: y2038: Fixing the sem_timedwait syscall for 32 bit systems Florian Bezdeka
2021-05-07 21:51 ` [PATCH v6 2/4] y2038: Adding sem_timedwait64 Florian Bezdeka
2021-05-07 21:51 ` [PATCH v6 3/4] y2038: Add tests for the sc_cobalt_sem_timedwait64 syscall Florian Bezdeka
2021-05-07 21:51 ` [PATCH v6 4/4] y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait64 Florian Bezdeka
2021-05-10  6:51 ` [PATCH v6 0/4] Adressing y2038 test failures on ARM and BBB Jan Kiszka
2021-05-15 16:12   ` Philippe Gerum

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.