All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/4] Adressing y2038 test failures on ARM and BBB
@ 2021-05-07 18:19 Florian Bezdeka
  2021-05-07 18:19 ` [PATCH v5 1/4] cobalt/sem: y2038: Fixing the sem_timedwait syscall for 32 bit systems Florian Bezdeka
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Florian Bezdeka @ 2021-05-07 18:19 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 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           |  22 +++
 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                   |  29 ++++
 lib/cobalt/semaphore.c                 |   5 +
 testsuite/smokey/Makefile.am           |   6 +-
 testsuite/smokey/y2038/Makefile.am     |  10 ++
 testsuite/smokey/y2038/syscall-tests.c | 177 +++++++++++++++++++++++++
 13 files changed, 317 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] 5+ messages in thread

* [PATCH v5 1/4] cobalt/sem: y2038: Fixing the sem_timedwait syscall for 32 bit systems
  2021-05-07 18:19 [PATCH v5 0/4] Adressing y2038 test failures on ARM and BBB Florian Bezdeka
@ 2021-05-07 18:19 ` Florian Bezdeka
  2021-05-07 18:19 ` [PATCH v5 2/4] y2038: Adding sem_timedwait64 Florian Bezdeka
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Florian Bezdeka @ 2021-05-07 18:19 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] 5+ messages in thread

* [PATCH v5 2/4] y2038: Adding sem_timedwait64
  2021-05-07 18:19 [PATCH v5 0/4] Adressing y2038 test failures on ARM and BBB Florian Bezdeka
  2021-05-07 18:19 ` [PATCH v5 1/4] cobalt/sem: y2038: Fixing the sem_timedwait syscall for 32 bit systems Florian Bezdeka
@ 2021-05-07 18:19 ` Florian Bezdeka
  2021-05-07 18:19 ` [PATCH v5 3/4] y2038: Add tests for the sc_cobalt_sem_timedwait64 syscall Florian Bezdeka
  2021-05-07 18:19 ` [PATCH v5 4/4] y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait64 Florian Bezdeka
  3 siblings, 0 replies; 5+ messages in thread
From: Florian Bezdeka @ 2021-05-07 18:19 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    | 22 ++++++++++++++++++++++
 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            | 29 +++++++++++++++++++++++++++++
 8 files changed, 91 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..19e8f2c56
--- /dev/null
+++ b/include/cobalt/kernel/time.h
@@ -0,0 +1,22 @@
+/*
+ * 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..0b5e26d9e 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..a3fd8a740
--- /dev/null
+++ b/kernel/cobalt/time.c
@@ -0,0 +1,29 @@
+/*
+ * 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] 5+ messages in thread

* [PATCH v5 3/4] y2038: Add tests for the sc_cobalt_sem_timedwait64 syscall
  2021-05-07 18:19 [PATCH v5 0/4] Adressing y2038 test failures on ARM and BBB Florian Bezdeka
  2021-05-07 18:19 ` [PATCH v5 1/4] cobalt/sem: y2038: Fixing the sem_timedwait syscall for 32 bit systems Florian Bezdeka
  2021-05-07 18:19 ` [PATCH v5 2/4] y2038: Adding sem_timedwait64 Florian Bezdeka
@ 2021-05-07 18:19 ` Florian Bezdeka
  2021-05-07 18:19 ` [PATCH v5 4/4] y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait64 Florian Bezdeka
  3 siblings, 0 replies; 5+ messages in thread
From: Florian Bezdeka @ 2021-05-07 18:19 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 | 177 +++++++++++++++++++++++++
 4 files changed, 192 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..4824fcdc1
--- /dev/null
+++ b/testsuite/smokey/y2038/syscall-tests.c
@@ -0,0 +1,177 @@
+/*
+ * 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 adress 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] 5+ messages in thread

* [PATCH v5 4/4] y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait64
  2021-05-07 18:19 [PATCH v5 0/4] Adressing y2038 test failures on ARM and BBB Florian Bezdeka
                   ` (2 preceding siblings ...)
  2021-05-07 18:19 ` [PATCH v5 3/4] y2038: Add tests for the sc_cobalt_sem_timedwait64 syscall Florian Bezdeka
@ 2021-05-07 18:19 ` Florian Bezdeka
  3 siblings, 0 replies; 5+ messages in thread
From: Florian Bezdeka @ 2021-05-07 18:19 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] 5+ messages in thread

end of thread, other threads:[~2021-05-07 18:19 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-07 18:19 [PATCH v5 0/4] Adressing y2038 test failures on ARM and BBB Florian Bezdeka
2021-05-07 18:19 ` [PATCH v5 1/4] cobalt/sem: y2038: Fixing the sem_timedwait syscall for 32 bit systems Florian Bezdeka
2021-05-07 18:19 ` [PATCH v5 2/4] y2038: Adding sem_timedwait64 Florian Bezdeka
2021-05-07 18:19 ` [PATCH v5 3/4] y2038: Add tests for the sc_cobalt_sem_timedwait64 syscall Florian Bezdeka
2021-05-07 18:19 ` [PATCH v5 4/4] y2038: lib/cobalt: Add support of sc_cobalt_sem_timedwait64 Florian Bezdeka

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.