xenomai.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] prove of concept
@ 2022-07-07 13:59 Johannes Kirchmair
  2022-07-07 13:59 ` [PATCH 1/3] rtsignals: part one, core code plus x86 Johannes Kirchmair
                   ` (4 more replies)
  0 siblings, 5 replies; 20+ messages in thread
From: Johannes Kirchmair @ 2022-07-07 13:59 UTC (permalink / raw)
  To: xenomai

This is a prove of concept implementation of exception handling in Xenomai real
time.

It implements an interface similar to the posix signals but with a much smaller
feature set.

For now, this feature can be used for handling floating point exception (fpe)
and illegal opcode exception in user space without losing real time.

The fpe exception handling can be used for fixing division by zero errors in
user space code without dropping out of the real time domain.

The illegal opcode exceptions can be used for implementing breakpoints. This
can be done by replacing the breakpoints original instruction by an illegal
opcode. At the time a task tries to execute the instruction an illegal opcode
exception will be triggered. The thread can be  suspended in the signal handler
in user space. There are two main advantages of having it done in real time.

The first is if a task does some time critical IO or has to meet some watchdog
constrains, the signal handler can be used to bring the IO into a sane state
before the task is stopped. Same for the watchdog, it can be stopped before it
sends the whole process into an error state.

The second advantage is for processes that have several real time tasks. For
example consider a process with rt tasks task1 and task2, where task1 is of a
higher priority than task2. If task1 triggers an exception and is relaxed to
the Linux domain, task2 of a lesser priority would take over and could block
the handling of the maybe more imported work/exception handling in task1.

Disclaimer:
This implementation is far from being ready to merge. It is mainly intended to
be a starting point for discussions about rather we (the community) want some
kind of exception handling interface in Xenomai and what a maintainable
interface for this could look like.



David Oberhollenzer (1):
  rtsignals: Add rt_signal test

Johannes Kirchmair (1):
  rtsignals: add i64 signal handling

Richard Weinberger (1):
  rtsignals: part one, core code plus x86

 configure.ac                                  |   1 +
 include/cobalt/kernel/ppd.h                   |   3 +
 include/cobalt/kernel/thread.h                |   2 +
 include/cobalt/signal.h                       |   2 +
 include/cobalt/uapi/syscall.h                 |   6 +
 kernel/cobalt/arch/x86/Makefile               |   2 +-
 .../arch/x86/include/asm/xenomai/thread.h     |  15 +
 kernel/cobalt/arch/x86/signal_ia32.c          | 293 ++++++++++++++++++
 kernel/cobalt/arch/x86/signal_ia64.c          | 283 +++++++++++++++++
 kernel/cobalt/posix/process.c                 |  10 +-
 kernel/cobalt/posix/syscall.c                 |  28 ++
 kernel/cobalt/posix/syscall32.c               |  16 +
 kernel/cobalt/thread.c                        |  40 ++-
 lib/cobalt/arch/x86/Makefile.am               |   2 +-
 lib/cobalt/arch/x86/sigreturn.c               |  22 ++
 lib/cobalt/internal.h                         |   2 +
 lib/cobalt/signal.c                           |  14 +
 testsuite/Makefile.am                         |   6 +-
 testsuite/rtsignal-tests/Makefile.am          |  30 ++
 testsuite/rtsignal-tests/test_rt_signal.c     | 185 +++++++++++
 20 files changed, 955 insertions(+), 7 deletions(-)
 create mode 100644 kernel/cobalt/arch/x86/signal_ia32.c
 create mode 100644 kernel/cobalt/arch/x86/signal_ia64.c
 create mode 100644 lib/cobalt/arch/x86/sigreturn.c
 create mode 100644 testsuite/rtsignal-tests/Makefile.am
 create mode 100644 testsuite/rtsignal-tests/test_rt_signal.c

-- 
2.25.1


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

* [PATCH 1/3] rtsignals: part one, core code plus x86
  2022-07-07 13:59 [PATCH 0/3] prove of concept Johannes Kirchmair
@ 2022-07-07 13:59 ` Johannes Kirchmair
  2022-07-07 15:23   ` Jan Kiszka
  2022-07-07 13:59 ` [PATCH 2/3] rtsignals: add i64 signal handling Johannes Kirchmair
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 20+ messages in thread
From: Johannes Kirchmair @ 2022-07-07 13:59 UTC (permalink / raw)
  To: xenomai

From: Richard Weinberger <richard@nod.at>

Adds code for implementing signals that are handled in the real time
domain. This is done for 32bit process under an 64bit kernel.
It works in a similar way to signals in the Linux kernel.

Edited-by: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
---
 include/cobalt/kernel/ppd.h                   |   3 +
 include/cobalt/kernel/thread.h                |   2 +
 include/cobalt/signal.h                       |   2 +
 include/cobalt/uapi/syscall.h                 |   6 +
 kernel/cobalt/arch/x86/Makefile               |   2 +-
 .../arch/x86/include/asm/xenomai/thread.h     |   9 +
 kernel/cobalt/arch/x86/signal_ia32.c          | 293 ++++++++++++++++++
 kernel/cobalt/posix/process.c                 |  10 +-
 kernel/cobalt/posix/syscall.c                 |  25 ++
 kernel/cobalt/posix/syscall32.c               |  16 +
 kernel/cobalt/thread.c                        |  34 +-
 lib/cobalt/arch/x86/Makefile.am               |   2 +-
 lib/cobalt/arch/x86/sigreturn.c               |  22 ++
 lib/cobalt/internal.h                         |   2 +
 lib/cobalt/signal.c                           |  14 +
 15 files changed, 437 insertions(+), 5 deletions(-)
 create mode 100644 kernel/cobalt/arch/x86/signal_ia32.c
 create mode 100644 lib/cobalt/arch/x86/sigreturn.c

diff --git a/include/cobalt/kernel/ppd.h b/include/cobalt/kernel/ppd.h
index f0079fe6e..fb2f682da 100644
--- a/include/cobalt/kernel/ppd.h
+++ b/include/cobalt/kernel/ppd.h
@@ -22,6 +22,7 @@
 #include <linux/types.h>
 #include <linux/atomic.h>
 #include <linux/rbtree.h>
+#include <linux/signal.h>
 #include <cobalt/kernel/heap.h>
 
 struct cobalt_umm {
@@ -32,6 +33,8 @@ struct cobalt_umm {
 
 struct cobalt_ppd {
 	struct cobalt_umm umm;
+	void __user *sighand[_NSIG];
+	void __user *sigrestorer;
 	atomic_t refcnt;
 	char *exe_path;
 	struct rb_root fds;
diff --git a/include/cobalt/kernel/thread.h b/include/cobalt/kernel/thread.h
index 03adb2529..6afed4f58 100644
--- a/include/cobalt/kernel/thread.h
+++ b/include/cobalt/kernel/thread.h
@@ -563,6 +563,8 @@ static inline void xnthread_propagate_schedparam(struct xnthread *curr)
 		__xnthread_propagate_schedparam(curr);
 }
 
+int xnthread_handle_rt_signals(struct ipipe_trap_data *d);
+
 extern struct xnthread_personality xenomai_personality;
 
 /** @} */
diff --git a/include/cobalt/signal.h b/include/cobalt/signal.h
index 62694f93a..3d6540aff 100644
--- a/include/cobalt/signal.h
+++ b/include/cobalt/signal.h
@@ -54,6 +54,8 @@ COBALT_DECL(int, kill(pid_t pid, int sig));
 COBALT_DECL(int, sigqueue(pid_t pid, int sig,
 			  const union sigval value));
 
+int cobalt_rt_signal(int sig, void (*handler)(int, siginfo_t *, void *));
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
index aa3c308d0..64a502f2a 100644
--- a/include/cobalt/uapi/syscall.h
+++ b/include/cobalt/uapi/syscall.h
@@ -123,6 +123,12 @@
 #define sc_cobalt_clock_adjtime			100
 #define sc_cobalt_thread_setschedprio		101
 
+/*
+ * Sigmatek specific syscalls
+ */
+#define sc_cobalt_sigreturn			120
+#define sc_cobalt_sigaction			121
+
 #define __NR_COBALT_SYSCALLS			128 /* Power of 2 */
 
 #endif /* !_COBALT_UAPI_SYSCALL_H */
diff --git a/kernel/cobalt/arch/x86/Makefile b/kernel/cobalt/arch/x86/Makefile
index 1ef407c35..6bbf15651 100644
--- a/kernel/cobalt/arch/x86/Makefile
+++ b/kernel/cobalt/arch/x86/Makefile
@@ -1,5 +1,5 @@
 
 obj-$(CONFIG_XENOMAI) += xenomai.o
-xenomai-y := machine.o thread.o smi.o c1e.o
+xenomai-y := machine.o thread.o smi.o c1e.o signal_ia32.o
 
 ccflags-y := -I$(srctree)/arch/x86/xenomai/include -I$(srctree)/include/xenomai
diff --git a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
index 10cd6ecd5..be93926a7 100644
--- a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
+++ b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
@@ -77,6 +77,15 @@ void xnarch_init_shadow_tcb(struct xnthread *thread);
 
 void xnarch_switch_to(struct xnthread *out, struct xnthread *in);
 
+int xnarch_setup_trap_info(unsigned int vector, struct pt_regs *regs,
+			   long errcode, int *sig, struct kernel_siginfo *info);
+
+int xnarch_setup_rt_frame_ia32(int sig, void *handler,
+			       struct kernel_siginfo *si, struct pt_regs *regs,
+			       void __user *restorer);
+
+int xnarch_rt_sigreturn_ia32(struct pt_regs *regs);
+
 static inline void xnarch_enter_root(struct xnthread *root) { }
 
 static inline int xnarch_escalate(void)
diff --git a/kernel/cobalt/arch/x86/signal_ia32.c b/kernel/cobalt/arch/x86/signal_ia32.c
new file mode 100644
index 000000000..17a95faf5
--- /dev/null
+++ b/kernel/cobalt/arch/x86/signal_ia32.c
@@ -0,0 +1,293 @@
+#include <linux/signal.h>
+#include <linux/uaccess.h>
+#include <cobalt/kernel/thread.h>
+
+#include <asm/sigframe.h>
+#include <asm/sighandling.h>
+#include <asm/fpu/signal.h>
+
+#define loadsegment_gs(v) load_gs_index(v)
+#define loadsegment_fs(v) loadsegment(fs, v)
+#define loadsegment_ds(v) loadsegment(ds, v)
+#define loadsegment_es(v) loadsegment(es, v)
+
+#define get_user_seg(seg)                                                      \
+	({                                                                     \
+		unsigned int v;                                                \
+		savesegment(seg, v);                                           \
+		v;                                                             \
+	})
+#define set_user_seg(seg, v) loadsegment_##seg(v)
+
+#define COPY(x)                                                                \
+	{                                                                      \
+		get_user_ex(regs->x, &sc->x);                                  \
+	}
+
+#define GET_SEG(seg)                                                           \
+	({                                                                     \
+		unsigned short tmp;                                            \
+		get_user_ex(tmp, &sc->seg);                                    \
+		tmp;                                                           \
+	})
+
+#define RELOAD_SEG(seg)                                                        \
+	{                                                                      \
+		unsigned int pre = GET_SEG(seg);                               \
+		unsigned int cur = get_user_seg(seg);                          \
+		pre |= 3;                                                      \
+		if (pre != cur)                                                \
+			set_user_seg(seg, pre);                                \
+	}
+
+#define COPY_SEG_CPL3(seg)                                                     \
+	do {                                                                   \
+		regs->seg = GET_SEG(seg) | 3;                                  \
+	} while (0)
+
+int xnarch_setup_trap_info(unsigned int vector, struct pt_regs *regs,
+			   long errcode, int *sig, struct kernel_siginfo *info)
+{
+	switch (vector) {
+	case 0: /* divide_error */
+		*sig = SIGFPE;
+		info->si_signo = *sig;
+		info->si_errno = 0;
+		info->si_code = FPE_INTDIV;
+		info->si_addr = (void __user *)regs->ip;
+		return 0;
+	case 1: /* trap_error */ {
+		unsigned long condition;
+		get_debugreg(condition, 6);
+		set_debugreg(0, 7);
+		*sig = SIGTRAP;
+		info->si_signo = *sig;
+		info->si_errno = errcode;
+		info->si_code = get_si_code(condition);
+		info->si_addr = (void __user *)regs->ip;
+		return 0;
+	}
+	case 3: /* trap_error */
+		*sig = SIGTRAP;
+		info->si_signo = *sig;
+		info->si_errno = errcode;
+		info->si_code = SI_KERNEL;
+		info->si_addr = (void __user *)regs->ip;
+		return 0;
+	case 6: /* invalid_op */
+		*sig = SIGILL;
+		info->si_signo = *sig;
+		info->si_errno = 0;
+		info->si_code = ILL_ILLOPN;
+		info->si_addr = (void __user *)regs->ip;
+		return 0;
+	case 16: { /* coprocessor_error */
+		*sig = SIGFPE;
+
+		info->si_signo = *sig;
+		info->si_errno = 0;
+		info->si_code = 0;
+		info->si_addr = (void __user *)regs->ip;
+		return 0;
+	}
+	default:
+		break;
+	}
+
+	return -ENOSYS;
+}
+
+static void *xnarch_get_sigframe_ia32(struct pt_regs *regs, size_t frame_size,
+				      void __user **fpstate)
+{
+	unsigned long sp = regs->sp;
+	unsigned long buf_fx = 0;
+	unsigned long math_size = 0;
+
+	sp = fpu__alloc_mathframe(sp, 1, &buf_fx, &math_size);
+	*fpstate = (void __user *)sp;
+
+	if (copy_fpstate_to_sigframe(*fpstate, (void __user *)buf_fx,
+				     math_size) < 0)
+		return (void __user *)-1L;
+
+	sp -= frame_size;
+	sp = ((sp + 4) & -16ul) - 4;
+
+	return (void __user *)sp;
+}
+
+static const struct {
+	u8 movl;
+	u32 val;
+	u16 int80;
+	u8 pad;
+} __attribute__((packed)) ia32_sigret_code = {
+	0xb8,
+	__NR_ia32_rt_sigreturn,
+	0x80cd,
+	0,
+};
+
+static int ia32_setup_sigcontext(struct sigcontext_32 __user *sc,
+				 void __user *fpstate, struct pt_regs *regs,
+				 unsigned int mask)
+{
+	int err = 0;
+
+	put_user_try
+	{
+		put_user_ex(get_user_seg(gs), (unsigned int __user *)&sc->gs);
+		put_user_ex(get_user_seg(fs), (unsigned int __user *)&sc->fs);
+		put_user_ex(get_user_seg(ds), (unsigned int __user *)&sc->ds);
+		put_user_ex(get_user_seg(es), (unsigned int __user *)&sc->es);
+
+		put_user_ex(regs->di, &sc->di);
+		put_user_ex(regs->si, &sc->si);
+		put_user_ex(regs->bp, &sc->bp);
+		put_user_ex(regs->sp, &sc->sp);
+		put_user_ex(regs->bx, &sc->bx);
+		put_user_ex(regs->dx, &sc->dx);
+		put_user_ex(regs->cx, &sc->cx);
+		put_user_ex(regs->ax, &sc->ax);
+		put_user_ex(current->thread.trap_nr, &sc->trapno);
+		put_user_ex(current->thread.error_code, &sc->err);
+		put_user_ex(regs->ip, &sc->ip);
+		put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
+		put_user_ex(regs->flags, &sc->flags);
+		put_user_ex(regs->sp, &sc->sp_at_signal);
+		put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
+
+		put_user_ex(ptr_to_compat(fpstate), &sc->fpstate);
+
+		/* non-iBCS2 extensions.. */
+		put_user_ex(mask, &sc->oldmask);
+		put_user_ex(current->thread.cr2, &sc->cr2);
+	}
+	put_user_catch(err);
+
+	return err;
+}
+
+static int xnarch_restore_sigcontext_ia32(struct pt_regs *regs,
+					  struct sigcontext_32 __user *sc)
+{
+	int tmpflags, err = 0;
+	void __user *buf;
+	u32 tmp;
+
+	get_user_try
+	{
+		/*
+		 * Reload fs and gs if they have changed in the signal
+		 * handler.  This does not handle long fs/gs base changes in
+		 * the handler, but does not clobber them at least in the
+		 * normal case.
+		 */
+		RELOAD_SEG(gs);
+		RELOAD_SEG(fs);
+		RELOAD_SEG(ds);
+		RELOAD_SEG(es);
+
+		COPY(di);
+		COPY(si);
+		COPY(bp);
+		COPY(sp);
+		COPY(bx);
+		COPY(dx);
+		COPY(cx);
+		COPY(ip);
+		COPY(ax);
+		/* Don't touch extended registers */
+
+		COPY_SEG_CPL3(cs);
+		COPY_SEG_CPL3(ss);
+
+		get_user_ex(tmpflags, &sc->flags);
+		regs->flags =
+			(regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
+		/* disable syscall checks */
+		regs->orig_ax = -1;
+
+		get_user_ex(tmp, &sc->fpstate);
+		buf = compat_ptr(tmp);
+	}
+	get_user_catch(err);
+
+	err |= fpu__restore_sig(buf, 1);
+
+	return err;
+}
+
+int xnarch_rt_sigreturn_ia32(struct pt_regs *regs)
+{
+	struct rt_sigframe_ia32 __user *frame =
+		(struct rt_sigframe_ia32 __user *)(regs->sp - 4);
+
+	if (!access_ok(frame, sizeof(*frame)))
+		goto badframe;
+
+	if (xnarch_restore_sigcontext_ia32(regs, &frame->uc.uc_mcontext))
+		goto badframe;
+
+	return 0;
+
+badframe:
+	xnthread_call_mayday(xnthread_current(), SIGKILL);
+	return -1;
+}
+
+int xnarch_setup_rt_frame_ia32(int sig, void *handler,
+			       struct kernel_siginfo *si, struct pt_regs *regs,
+			       void __user *restorer)
+{
+	struct rt_sigframe_ia32 __user *frame;
+	void __user *fpstate = NULL;
+	compat_sigset_t set;
+	int err = 0;
+
+	frame = xnarch_get_sigframe_ia32(regs, sizeof(*frame), &fpstate);
+	if (!access_ok(frame, sizeof(*frame)))
+		return -EFAULT;
+
+	put_user_try
+	{
+		put_user_ex(sig, &frame->sig);
+		put_user_ex(ptr_to_compat(&frame->info), &frame->pinfo);
+		put_user_ex(ptr_to_compat(&frame->uc), &frame->puc);
+
+		if (boot_cpu_has(X86_FEATURE_XSAVE))
+			put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
+		else
+			put_user_ex(0, &frame->uc.uc_flags);
+
+		put_user_ex(0, &frame->uc.uc_link);
+		put_user_ex(ptr_to_compat(restorer), &frame->pretcode);
+		put_user_ex(*((u64 *)&ia32_sigret_code),
+			    (u64 __user *)frame->retcode);
+	}
+	put_user_catch(err);
+
+	err |= __copy_siginfo_to_user32(&frame->info, si, false);
+	err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate, regs,
+				     set.sig[0]);
+	err |= __copy_to_user(&frame->uc.uc_sigmask, &set, sizeof(set));
+
+	if (err)
+		return -EFAULT;
+
+	regs->sp = (unsigned long)frame;
+	regs->ip = (unsigned long)handler;
+
+	regs->ax = sig;
+	regs->dx = (unsigned long)&frame->info;
+	regs->cx = (unsigned long)&frame->uc;
+
+	loadsegment(ds, __USER32_DS);
+	loadsegment(es, __USER32_DS);
+
+	regs->cs = __USER32_CS;
+	regs->ss = __USER32_DS;
+
+	return 0;
+}
diff --git a/kernel/cobalt/posix/process.c b/kernel/cobalt/posix/process.c
index f762fef2e..ef6fa8e38 100644
--- a/kernel/cobalt/posix/process.c
+++ b/kernel/cobalt/posix/process.c
@@ -860,13 +860,21 @@ static inline int handle_exception(struct ipipe_trap_data *d)
 		       xnarch_fault_pc(d),
 		       xnthread_host_pid(thread));
 		xntrace_panic_dump();
-	} else if (xnarch_fault_notify(d)) /* Don't report debug traps */
+	}
+#if 1
+	else {
+		if (xnthread_handle_rt_signals(d) == 0)
+			return KEVENT_STOP;
+	}
+#else
+	else if (xnarch_fault_notify(d)) /* Don't report debug traps */
 		printk(XENO_WARNING
 		       "switching %s to secondary mode after exception #%u from "
 		       "user-space at 0x%lx (pid %d)\n", thread->name,
 		       xnarch_fault_trap(d),
 		       xnarch_fault_pc(d),
 		       xnthread_host_pid(thread));
+#endif
 #endif
 
 	if (xnarch_fault_pf_p(d))
diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c
index a9c979903..b63923017 100644
--- a/kernel/cobalt/posix/syscall.c
+++ b/kernel/cobalt/posix/syscall.c
@@ -270,6 +270,31 @@ static COBALT_SYSCALL(serialdbg, current,
 	return 0;
 }
 
+static COBALT_SYSCALL(sigreturn, current, (void))
+{
+	struct pt_regs *regs = task_pt_regs(current);
+
+	xnarch_rt_sigreturn_ia32(regs);
+
+	return __xn_reg_rval(regs);
+}
+
+static COBALT_SYSCALL(sigaction, current,
+		      (int sig, void __user *handler, void __user *restorer))
+{
+	struct cobalt_ppd *sys_ppd = cobalt_ppd_get(0);
+
+	if (sig < 0 || sig >= _NSIG)
+		return -EINVAL;
+
+	sys_ppd->sighand[sig] = handler;
+
+	if (!sys_ppd->sigrestorer)
+		sys_ppd->sigrestorer = restorer;
+
+	return 0;
+}
+
 static void stringify_feature_set(unsigned long fset, char *buf, int size)
 {
 	unsigned long feature;
diff --git a/kernel/cobalt/posix/syscall32.c b/kernel/cobalt/posix/syscall32.c
index fd4e789b2..bd38dda15 100644
--- a/kernel/cobalt/posix/syscall32.c
+++ b/kernel/cobalt/posix/syscall32.c
@@ -658,6 +658,22 @@ COBALT_SYSCALL32emu(sigqueue, conforming,
 	return ret ?: __cobalt_sigqueue(pid, sig, &val);
 }
 
+COBALT_SYSCALL32emu(sigaction, current,
+		    (int sig, void __user *handler, void __user *restorer))
+{
+	struct cobalt_ppd *sys_ppd = cobalt_ppd_get(0);
+
+	if (sig < 0 || sig >= _NSIG)
+		return -EINVAL;
+
+	sys_ppd->sighand[sig] = handler;
+
+	if (!sys_ppd->sigrestorer)
+		sys_ppd->sigrestorer = restorer;
+
+	return 0;
+}
+
 COBALT_SYSCALL32emu(monitor_wait, nonrestartable,
 		    (struct cobalt_monitor_shadow __user *u_mon,
 		     int event, const struct compat_timespec __user *u_ts,
diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
index e286bf48a..34066e614 100644
--- a/kernel/cobalt/thread.c
+++ b/kernel/cobalt/thread.c
@@ -39,6 +39,7 @@
 #include <cobalt/kernel/lock.h>
 #include <cobalt/kernel/thread.h>
 #include <trace/events/cobalt-core.h>
+#include "posix/process.h"
 #include "debug.h"
 
 static DECLARE_WAIT_QUEUE_HEAD(join_all);
@@ -2077,7 +2078,7 @@ void xnthread_relax(int notify, int reason)
 	struct task_struct *p = current;
 	int suspension = XNRELAX;
 	int cpu __maybe_unused;
-	kernel_siginfo_t si;
+	struct kernel_siginfo si;
 
 	primary_mode_only();
 
@@ -2210,7 +2211,7 @@ static void lostage_task_signal(struct ipipe_work_header *work)
 	struct lostage_signal *rq;
 	struct xnthread *thread;
 	struct task_struct *p;
-	kernel_siginfo_t si;
+	struct kernel_siginfo si;
 	int signo;
 
 	rq = container_of(work, struct lostage_signal, work);
@@ -2663,6 +2664,35 @@ int xnthread_killall(int grace, int mask)
 }
 EXPORT_SYMBOL_GPL(xnthread_killall);
 
+int xnthread_handle_rt_signals(struct ipipe_trap_data *d)
+{
+	unsigned int vector = xnarch_fault_trap(d);
+	unsigned int code = xnarch_fault_code(d);
+	struct pt_regs *regs = d->regs;
+	struct cobalt_ppd *sys_ppd;
+	int sig, ret;
+	struct kernel_siginfo si;
+
+	ret = xnarch_setup_trap_info(vector, regs, code, &sig, &si);
+	if (ret || sig == 0)
+		return 1;
+
+	sys_ppd = cobalt_ppd_get(0);
+	if (sig >= _NSIG || sys_ppd->sighand[sig] == NULL ||
+	    sys_ppd->sighand[sig] == SIG_DFL)
+		return 1;
+
+	if (sys_ppd->sigrestorer == NULL)
+		return 1;
+
+	ret = xnarch_setup_rt_frame_ia32(sig, sys_ppd->sighand[sig], &si, regs,
+					 sys_ppd->sigrestorer);
+	if (ret)
+		return 1;
+
+	return 0;
+}
+
 /* Xenomai's generic personality. */
 struct xnthread_personality xenomai_personality = {
 	.name = "core",
diff --git a/lib/cobalt/arch/x86/Makefile.am b/lib/cobalt/arch/x86/Makefile.am
index a5095be3d..14f5eff97 100644
--- a/lib/cobalt/arch/x86/Makefile.am
+++ b/lib/cobalt/arch/x86/Makefile.am
@@ -2,7 +2,7 @@ noinst_LTLIBRARIES = libarch.la
 
 libarch_la_LDFLAGS = @XENO_LIB_LDFLAGS@
 
-libarch_la_SOURCES = features.c
+libarch_la_SOURCES = features.c sigreturn.c
 
 libarch_la_CPPFLAGS =			\
 	@XENO_COBALT_CFLAGS@ 		\
diff --git a/lib/cobalt/arch/x86/sigreturn.c b/lib/cobalt/arch/x86/sigreturn.c
new file mode 100644
index 000000000..6a3ecf07d
--- /dev/null
+++ b/lib/cobalt/arch/x86/sigreturn.c
@@ -0,0 +1,22 @@
+#include <cobalt/uapi/syscall.h>
+#include "internal.h"
+
+extern void cobalt_sigreturn(void) asm("__cobalt_sigreturn")
+	__attribute__((visibility("hidden")));
+
+#define build_restorer(syscall_number)                                         \
+	asm(".text\n"                                                          \
+	    "    .align 16\n"                                                  \
+	    "__cobalt_sigreturn:\n"                                            \
+	    "    movl $ " #syscall_number ", %eax\n"                           \
+	    "    int  $0x80")
+
+/*
+ * __COBALT_SYSCALL_BIT | sc_cobalt_sigreturn
+ */
+build_restorer(0x10000078);
+
+void *cobalt_get_restorer(void)
+{
+	return &cobalt_sigreturn;
+}
diff --git a/lib/cobalt/internal.h b/lib/cobalt/internal.h
index 4d81b70c2..74a20e6f1 100644
--- a/lib/cobalt/internal.h
+++ b/lib/cobalt/internal.h
@@ -126,4 +126,6 @@ static inline bool cobalt_features_available(unsigned int feat_mask)
 	return (cobalt_features & feat_mask) == feat_mask;
 }
 
+extern void *cobalt_get_restorer(void);
+
 #endif /* _LIB_COBALT_INTERNAL_H */
diff --git a/lib/cobalt/signal.c b/lib/cobalt/signal.c
index 7e033019a..de7f7bbb0 100644
--- a/lib/cobalt/signal.c
+++ b/lib/cobalt/signal.c
@@ -122,3 +122,17 @@ COBALT_IMPL(int, sigqueue, (pid_t pid, int sig, const union sigval value))
 
 	return 0;
 }
+
+int cobalt_rt_signal(int sig, void (*handler)(int, siginfo_t *, void *))
+{
+	int ret;
+
+	ret = XENOMAI_SYSCALL3(sc_cobalt_sigaction, sig, handler,
+			       cobalt_get_restorer());
+	if (ret) {
+		errno = -ret;
+		return -1;
+	}
+
+	return 0;
+}
-- 
2.25.1


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

* [PATCH 2/3] rtsignals: add i64 signal handling
  2022-07-07 13:59 [PATCH 0/3] prove of concept Johannes Kirchmair
  2022-07-07 13:59 ` [PATCH 1/3] rtsignals: part one, core code plus x86 Johannes Kirchmair
@ 2022-07-07 13:59 ` Johannes Kirchmair
  2022-07-07 13:59 ` [PATCH 3/3] rtsignals: Add rt_signal test Johannes Kirchmair
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 20+ messages in thread
From: Johannes Kirchmair @ 2022-07-07 13:59 UTC (permalink / raw)
  To: xenomai

Adds code for implementing signals that are handled in the real time
domain. This is done for 64bit processes.

It works in a similar way to signals in the Linux kernel.
---
 kernel/cobalt/arch/x86/Makefile               |   2 +-
 .../arch/x86/include/asm/xenomai/thread.h     |   6 +
 kernel/cobalt/arch/x86/signal_ia64.c          | 283 ++++++++++++++++++
 kernel/cobalt/posix/syscall.c                 |   5 +-
 kernel/cobalt/thread.c                        |  10 +-
 5 files changed, 302 insertions(+), 4 deletions(-)
 create mode 100644 kernel/cobalt/arch/x86/signal_ia64.c

diff --git a/kernel/cobalt/arch/x86/Makefile b/kernel/cobalt/arch/x86/Makefile
index 6bbf15651..bf58998cc 100644
--- a/kernel/cobalt/arch/x86/Makefile
+++ b/kernel/cobalt/arch/x86/Makefile
@@ -1,5 +1,5 @@
 
 obj-$(CONFIG_XENOMAI) += xenomai.o
-xenomai-y := machine.o thread.o smi.o c1e.o signal_ia32.o
+xenomai-y := machine.o thread.o smi.o c1e.o signal_ia32.o signal_ia64.o
 
 ccflags-y := -I$(srctree)/arch/x86/xenomai/include -I$(srctree)/include/xenomai
diff --git a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
index be93926a7..2505021c6 100644
--- a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
+++ b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
@@ -86,6 +86,12 @@ int xnarch_setup_rt_frame_ia32(int sig, void *handler,
 
 int xnarch_rt_sigreturn_ia32(struct pt_regs *regs);
 
+int xnarch_setup_rt_frame_ia64(int sig, void *handler,
+			       struct kernel_siginfo *si, struct pt_regs *regs,
+			       void __user *restorer);
+
+int xnarch_rt_sigreturn_ia64(struct pt_regs *regs);
+
 static inline void xnarch_enter_root(struct xnthread *root) { }
 
 static inline int xnarch_escalate(void)
diff --git a/kernel/cobalt/arch/x86/signal_ia64.c b/kernel/cobalt/arch/x86/signal_ia64.c
new file mode 100644
index 000000000..fd986e966
--- /dev/null
+++ b/kernel/cobalt/arch/x86/signal_ia64.c
@@ -0,0 +1,283 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *  Copyright (C) 2000, 2001, 2002 Andi Kleen SuSE Labs
+ *
+ *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
+ *  2000-06-20  Pentium III FXSR, SSE support by Gareth Hughes
+ *  2000-2002   x86-64 support by Andi Kleen
+ *
+ *  2022        changes for use in xenomai by Johannes Kirchmair
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/signal.h>
+#include <linux/uaccess.h>
+#include <cobalt/kernel/thread.h>
+
+#include <asm/sigframe.h>
+#include <asm/sighandling.h>
+#include <asm/fpu/signal.h>
+
+/*
+ * If regs->ss will cause an IRET fault, change it.  Otherwise leave it
+ * alone.  Using this generally makes no sense unless
+ * user_64bit_mode(regs) would return true.
+ */
+static void force_valid_ss(struct pt_regs *regs)
+{
+	u32 ar;
+
+	asm volatile ("lar %[old_ss], %[ar]\n\t"
+		      "jz 1f\n\t"		/* If invalid: */
+		      "xorl %[ar], %[ar]\n\t"	/* set ar = 0 */
+		      "1:"
+		      : [ar] "=r" (ar)
+		      : [old_ss] "rm" ((u16)regs->ss));
+
+	/*
+	 * For a valid 64-bit user context, we need DPL 3, type
+	 * read-write data or read-write exp-down data, and S and P
+	 * set.  We can't use VERW because VERW doesn't check the
+	 * P bit.
+	 */
+	ar &= AR_DPL_MASK | AR_S | AR_P | AR_TYPE_MASK;
+	if (ar != (AR_DPL3 | AR_S | AR_P | AR_TYPE_RWDATA) &&
+	    ar != (AR_DPL3 | AR_S | AR_P | AR_TYPE_RWDATA_EXPDOWN))
+		regs->ss = __USER_DS;
+}
+#define CONTEXT_COPY_SIZE offsetof(struct sigcontext, reserved1)
+
+static bool restore_sigcontext_ia64(struct pt_regs *regs,
+				    struct sigcontext __user *usc,
+				    unsigned long uc_flags)
+{
+	struct sigcontext sc;
+
+	if (copy_from_user(&sc, usc, CONTEXT_COPY_SIZE))
+		return false;
+
+	regs->bx = sc.bx;
+	regs->cx = sc.cx;
+	regs->dx = sc.dx;
+	regs->si = sc.si;
+	regs->di = sc.di;
+	regs->bp = sc.bp;
+	regs->ax = sc.ax;
+	regs->sp = sc.sp;
+	regs->ip = sc.ip;
+
+	regs->r8 = sc.r8;
+	regs->r9 = sc.r9;
+	regs->r10 = sc.r10;
+	regs->r11 = sc.r11;
+	regs->r12 = sc.r12;
+	regs->r13 = sc.r13;
+	regs->r14 = sc.r14;
+	regs->r15 = sc.r15;
+
+	/* Get CS/SS and force CPL3 */
+	regs->cs = sc.cs | 0x03;
+	regs->ss = sc.ss | 0x03;
+
+	regs->flags = (regs->flags & ~FIX_EFLAGS) | (sc.flags & FIX_EFLAGS);
+	/* disable syscall checks */
+	regs->orig_ax = -1;
+
+	/*
+	 * Fix up SS if needed for the benefit of old DOSEMU and
+	 * CRIU.
+	 */
+	force_valid_ss(regs);
+
+	return fpu__restore_sig((void __user *)sc.fpstate, 0);
+}
+
+static __always_inline int
+__unsafe_setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
+			  struct pt_regs *regs)
+{
+	unsafe_put_user(regs->di, &sc->di, Efault);
+	unsafe_put_user(regs->si, &sc->si, Efault);
+	unsafe_put_user(regs->bp, &sc->bp, Efault);
+	unsafe_put_user(regs->sp, &sc->sp, Efault);
+	unsafe_put_user(regs->bx, &sc->bx, Efault);
+	unsafe_put_user(regs->dx, &sc->dx, Efault);
+	unsafe_put_user(regs->cx, &sc->cx, Efault);
+	unsafe_put_user(regs->ax, &sc->ax, Efault);
+	unsafe_put_user(regs->r8, &sc->r8, Efault);
+	unsafe_put_user(regs->r9, &sc->r9, Efault);
+	unsafe_put_user(regs->r10, &sc->r10, Efault);
+	unsafe_put_user(regs->r11, &sc->r11, Efault);
+	unsafe_put_user(regs->r12, &sc->r12, Efault);
+	unsafe_put_user(regs->r13, &sc->r13, Efault);
+	unsafe_put_user(regs->r14, &sc->r14, Efault);
+	unsafe_put_user(regs->r15, &sc->r15, Efault);
+
+	unsafe_put_user(current->thread.trap_nr, &sc->trapno, Efault);
+	unsafe_put_user(current->thread.error_code, &sc->err, Efault);
+	unsafe_put_user(regs->ip, &sc->ip, Efault);
+	unsafe_put_user(regs->flags, &sc->flags, Efault);
+	unsafe_put_user(regs->cs, &sc->cs, Efault);
+	unsafe_put_user(0, &sc->gs, Efault);
+	unsafe_put_user(0, &sc->fs, Efault);
+	unsafe_put_user(regs->ss, &sc->ss, Efault);
+
+	unsafe_put_user(fpstate, (unsigned long __user *)&sc->fpstate, Efault);
+
+	/* non-iBCS2 extensions.. */
+	unsafe_put_user(current->thread.cr2, &sc->cr2, Efault);
+	return 0;
+Efault:
+	return -EFAULT;
+}
+
+#define unsafe_put_sigcontext(sc, fp, regs, label)                             \
+	do {                                                                   \
+		if (__unsafe_setup_sigcontext(sc, fp, regs))                   \
+			goto label;                                            \
+	} while (0);
+
+/*
+ * Set up a signal frame.
+ */
+
+/* x86 ABI requires 16-byte alignment */
+#define FRAME_ALIGNMENT 16UL
+
+/*
+ * Determine which stack to use..
+ */
+static unsigned long align_sigframe(unsigned long sp)
+{
+	sp = round_down(sp, FRAME_ALIGNMENT) - 8;
+	return sp;
+}
+
+static void __user *get_sigframe_ia64(struct pt_regs *regs, size_t frame_size,
+				      void __user **fpstate)
+{
+	/* Default to using normal stack */
+	unsigned long math_size = 0;
+	unsigned long sp = regs->sp;
+	unsigned long buf_fx = 0;
+
+	/* redzone */
+	if (IS_ENABLED(CONFIG_X86_64)) //TODO kirjoh ?
+		sp -= 128;
+
+	sp = fpu__alloc_mathframe(sp, 0, &buf_fx, &math_size);
+	*fpstate = (void __user *)sp;
+
+	sp = align_sigframe(sp - frame_size);
+
+	/* save i387 and extended state */
+	if (copy_fpstate_to_sigframe(*fpstate, (void __user *)buf_fx,
+				     math_size) < 0)
+		return (void __user *)-1L;
+
+	return (void __user *)sp;
+}
+
+static unsigned long frame_uc_flags_ia64(struct pt_regs *regs)
+{
+	unsigned long flags;
+
+	if (boot_cpu_has(X86_FEATURE_XSAVE))
+		flags = UC_FP_XSTATE | UC_SIGCONTEXT_SS;
+	else
+		flags = UC_SIGCONTEXT_SS;
+
+	return flags;
+}
+
+int xnarch_setup_rt_frame_ia64(int sig, void *handler,
+			       struct kernel_siginfo *si, struct pt_regs *regs,
+			       void __user *restorer)
+{
+	struct rt_sigframe __user *frame;
+	void __user *fp = NULL;
+	unsigned long uc_flags;
+
+	frame = get_sigframe_ia64(regs, sizeof(struct rt_sigframe), &fp);
+	uc_flags = frame_uc_flags_ia64(regs);
+
+	if (!user_access_begin(frame, sizeof(*frame)))
+		return -EFAULT;
+
+	/* Create the ucontext.  */
+	unsafe_put_user(uc_flags, &frame->uc.uc_flags, Efault);
+	unsafe_put_user(0, &frame->uc.uc_link, Efault);
+
+	/* Set up to return from userspace.  If provided, use a stub
+	   already in userspace.  */
+	unsafe_put_user(restorer, &frame->pretcode, Efault);
+	unsafe_put_sigcontext(&frame->uc.uc_mcontext, fp, regs, Efault);
+	user_access_end();
+
+	if (copy_siginfo_to_user(&frame->info, si))
+		return -EFAULT;
+
+	/* Set up registers for signal handler */
+	regs->di = sig;
+	/* In case the signal handler was declared without prototypes */
+	regs->ax = 0;
+
+	/* This also works for non SA_SIGINFO handlers because they expect the
+	   next argument after the signal number on the stack. */
+	regs->si = (unsigned long)&frame->info;
+	regs->dx = (unsigned long)&frame->uc;
+	regs->ip = (unsigned long)handler;
+
+	regs->sp = (unsigned long)frame;
+
+	/*
+	 * Set up the CS and SS registers to run signal handlers in
+	 * 64-bit mode, even if the handler happens to be interrupting
+	 * 32-bit or 16-bit code.
+	 *
+	 * SS is subtle.  In 64-bit mode, we don't need any particular
+	 * SS descriptor, but we do need SS to be valid.  It's possible
+	 * that the old SS is entirely bogus -- this can happen if the
+	 * signal we're trying to deliver is #GP or #SS caused by a bad
+	 * SS value.  We also have a compatibility issue here: DOSEMU
+	 * relies on the contents of the SS register indicating the
+	 * SS value at the time of the signal, even though that code in
+	 * DOSEMU predates sigreturn's ability to restore SS.  (DOSEMU
+	 * avoids relying on sigreturn to restore SS; instead it uses
+	 * a trampoline.)  So we do our best: if the old SS was valid,
+	 * we keep it.  Otherwise we replace it.
+	 */
+	regs->cs = __USER_CS;
+
+	if (unlikely(regs->ss != __USER_DS))
+		force_valid_ss(regs);
+
+	return 0;
+
+Efault:
+	user_access_end();
+
+	return -EFAULT;
+}
+
+int xnarch_rt_sigreturn_ia64(struct pt_regs *regs)
+{
+	struct rt_sigframe __user *frame;
+	unsigned long uc_flags;
+
+	frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long));
+	if (!access_ok(frame, sizeof(*frame)))
+		goto badframe;
+	if (__get_user(uc_flags, &frame->uc.uc_flags))
+		goto badframe;
+	if (!restore_sigcontext_ia64(regs, &frame->uc.uc_mcontext, uc_flags))
+		goto badframe;
+
+	return regs->ax;
+
+badframe:
+	// signal_fault(regs, frame, "rt_sigreturn"); //TODO kirjoh kill prozess
+	return 0;
+}
diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c
index b63923017..ad54380fa 100644
--- a/kernel/cobalt/posix/syscall.c
+++ b/kernel/cobalt/posix/syscall.c
@@ -274,7 +274,10 @@ static COBALT_SYSCALL(sigreturn, current, (void))
 {
 	struct pt_regs *regs = task_pt_regs(current);
 
-	xnarch_rt_sigreturn_ia32(regs);
+	if (regs->cs == __USER_CS)
+		xnarch_rt_sigreturn_ia64(regs);
+	if (regs->cs == __USER32_CS)
+		xnarch_rt_sigreturn_ia32(regs);
 
 	return __xn_reg_rval(regs);
 }
diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
index 34066e614..68473ac8f 100644
--- a/kernel/cobalt/thread.c
+++ b/kernel/cobalt/thread.c
@@ -2685,8 +2685,14 @@ int xnthread_handle_rt_signals(struct ipipe_trap_data *d)
 	if (sys_ppd->sigrestorer == NULL)
 		return 1;
 
-	ret = xnarch_setup_rt_frame_ia32(sig, sys_ppd->sighand[sig], &si, regs,
-					 sys_ppd->sigrestorer);
+	if (regs->cs == __USER_CS)
+		ret = xnarch_setup_rt_frame_ia64(sig, sys_ppd->sighand[sig],
+						 &si, regs,
+						 sys_ppd->sigrestorer);
+	if (regs->cs == __USER32_CS)
+		ret = xnarch_setup_rt_frame_ia32(sig, sys_ppd->sighand[sig],
+						 &si, regs,
+						 sys_ppd->sigrestorer);
 	if (ret)
 		return 1;
 
-- 
2.25.1


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

* [PATCH 3/3] rtsignals: Add rt_signal test
  2022-07-07 13:59 [PATCH 0/3] prove of concept Johannes Kirchmair
  2022-07-07 13:59 ` [PATCH 1/3] rtsignals: part one, core code plus x86 Johannes Kirchmair
  2022-07-07 13:59 ` [PATCH 2/3] rtsignals: add i64 signal handling Johannes Kirchmair
@ 2022-07-07 13:59 ` Johannes Kirchmair
  2022-07-07 15:19 ` [PATCH 0/3] prove of concept Jan Kiszka
  2022-07-08 17:42 ` Philippe Gerum
  4 siblings, 0 replies; 20+ messages in thread
From: Johannes Kirchmair @ 2022-07-07 13:59 UTC (permalink / raw)
  To: xenomai

From: David Oberhollenzer <david.oberhollenzer@sigma-star.at>

This commit adds an overhauled version of the rt signal test
for SIGFPE, SIGILL and SIGSEGV.

Edited-by: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
---
 configure.ac                              |   1 +
 testsuite/Makefile.am                     |   6 +-
 testsuite/rtsignal-tests/Makefile.am      |  30 ++++
 testsuite/rtsignal-tests/test_rt_signal.c | 185 ++++++++++++++++++++++
 4 files changed, 220 insertions(+), 2 deletions(-)
 create mode 100644 testsuite/rtsignal-tests/Makefile.am
 create mode 100644 testsuite/rtsignal-tests/test_rt_signal.c

diff --git a/configure.ac b/configure.ac
index 61789af13..db92ddcc6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -959,6 +959,7 @@ AC_CONFIG_FILES([ \
 	testsuite/switchtest/Makefile \
 	testsuite/gpiotest/Makefile \
 	testsuite/gpiobench/Makefile \
+	testsuite/rtsignal-tests/Makefile \
 	testsuite/spitest/Makefile \
 	testsuite/smokey/Makefile \
 	testsuite/smokey/arith/Makefile \
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
index 4932f6d33..87738dc78 100644
--- a/testsuite/Makefile.am
+++ b/testsuite/Makefile.am
@@ -5,6 +5,7 @@ if XENO_COBALT
 SUBDIRS += 		\
 	clocktest	\
 	gpiotest	\
+	rtsignal-tests	\
 	spitest		\
 	switchtest	\
 	xeno-test
@@ -13,9 +14,10 @@ endif
 DIST_SUBDIRS =		\
 	clocktest	\
 	gpiotest	\
-	gpiobench   \
+	gpiobench	\
 	latency		\
 	smokey		\
 	spitest		\
 	switchtest	\
-	xeno-test
+	xeno-test	\
+	rtsignal-tests
diff --git a/testsuite/rtsignal-tests/Makefile.am b/testsuite/rtsignal-tests/Makefile.am
new file mode 100644
index 000000000..25c1093c9
--- /dev/null
+++ b/testsuite/rtsignal-tests/Makefile.am
@@ -0,0 +1,30 @@
+testdir = @XENO_TEST_DIR@
+
+CCLD = $(top_srcdir)/scripts/wrap-link.sh $(CC)
+
+test_PROGRAMS = test_rt_signal_fpe test_rt_signal_segfault test_rt_signal_ill
+
+alchemycppflags =              			 \
+	$(XENO_USER_CFLAGS)    			 \
+	-I$(top_srcdir)/include
+
+alchemyldadd =					\
+	@XENO_AUTOINIT_LDFLAGS@			\
+	$(XENO_POSIX_WRAPPERS)			\
+	../../lib/alchemy/libalchemy.la		\
+	../../lib/copperplate/libcopperplate.la	\
+	@XENO_CORE_LDADD@			\
+	@XENO_USER_LDADD@			\
+	-lrt -lpthread -lm
+
+test_rt_signal_fpe_SOURCES = test_rt_signal.c
+test_rt_signal_fpe_CPPFLAGS = $(alchemycppflags) -DTEST_FPE=1
+test_rt_signal_fpe_LDADD = $(alchemyldadd)
+
+test_rt_signal_segfault_SOURCES = test_rt_signal.c
+test_rt_signal_segfault_CPPFLAGS = $(alchemycppflags) -DTEST_SEGFAULT=1
+test_rt_signal_segfault_LDADD = $(alchemyldadd)
+
+test_rt_signal_ill_SOURCES = test_rt_signal.c
+test_rt_signal_ill_CPPFLAGS = $(alchemycppflags)
+test_rt_signal_ill_LDADD = $(alchemyldadd)
diff --git a/testsuite/rtsignal-tests/test_rt_signal.c b/testsuite/rtsignal-tests/test_rt_signal.c
new file mode 100644
index 000000000..63ba5c30f
--- /dev/null
+++ b/testsuite/rtsignal-tests/test_rt_signal.c
@@ -0,0 +1,185 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <copperplate/traceobj.h>
+#include <alchemy/task.h>
+#include <assert.h>
+#include <setjmp.h>
+#include <asm/ucontext.h>
+
+#ifdef TEST_SEGFAULT
+#define TEST_SIGNAL SIGSEGV
+#elif defined(TEST_FPE)
+#define TEST_SIGNAL SIGFPE
+#else
+#define TEST_SIGNAL SIGILL
+#endif
+
+#define BIT_FAULT_HANDLER_ENTERD     1
+#define BIT_FAULT_HANDLER_FINISHED   2
+#define BIT_FAULT_HANDLER_WRONG_TASK 4
+#define BIT_FAULT_HANDLER_WRONG_SIG  8
+#define BIT_DOMAIN_SWITCH            16
+
+static RT_TASK t1;
+static sig_atomic_t status = 0;
+static sig_atomic_t cause = 0;
+
+#ifdef JMP_CLEANUP
+static jmp_buf jmpenv;
+#endif
+
+static int status_ok(void)
+{
+	return status ==
+	       (BIT_FAULT_HANDLER_ENTERD | BIT_FAULT_HANDLER_FINISHED);
+}
+
+static const char *sigdebug_msg[] = {
+	[SIGDEBUG_UNDEFINED] = "latency: received SIGXCPU for unknown reason",
+	[SIGDEBUG_MIGRATE_SIGNAL] = "received signal",
+	[SIGDEBUG_MIGRATE_SYSCALL] = "invoked syscall",
+	[SIGDEBUG_MIGRATE_FAULT] = "triggered fault",
+	[SIGDEBUG_MIGRATE_PRIOINV] = "affected by priority inversion",
+	[SIGDEBUG_NOMLOCK] = "Xenomai: process memory not locked "
+			     "(missing mlockall?)",
+	[SIGDEBUG_WATCHDOG] = "Xenomai: watchdog triggered "
+			      "(period too short?)",
+};
+
+static void do_cleanup(void *context)
+{
+	int step = 0;
+	struct ucontext *uc = context;
+
+#ifdef TEST_SEGFAULT
+	step = 11;
+#elif defined(TEST_FPE)
+	step = 2;
+#else
+	step = 2;
+#endif
+
+#ifdef __i386__
+	uc->uc_mcontext.eip += step;
+#else
+	uc->uc_mcontext.rip += step;
+#endif
+}
+
+static void signal_handler(int sig, siginfo_t *info, void *context)
+{
+	RT_TASK *self;
+	(void)context;
+
+	if (sig == SIGDEBUG) {
+		cause = sigdebug_reason(info);
+
+		if (cause > SIGDEBUG_WATCHDOG)
+			cause = SIGDEBUG_UNDEFINED;
+
+		/* XXX: caused by rt_task_delete() */
+		if (!(status & BIT_FAULT_HANDLER_ENTERD) &&
+		    cause == SIGDEBUG_MIGRATE_SYSCALL) {
+			return;
+		}
+
+		status |= BIT_DOMAIN_SWITCH;
+	} else {
+		status |= BIT_FAULT_HANDLER_ENTERD;
+		if (sig != TEST_SIGNAL) {
+			status |= BIT_FAULT_HANDLER_WRONG_SIG;
+			return;
+		}
+
+		self = rt_task_self();
+
+		if (self == NULL || !rt_task_same(self, &t1)) {
+			status |= BIT_FAULT_HANDLER_WRONG_TASK;
+		} else {
+			status |= BIT_FAULT_HANDLER_FINISHED;
+		}
+
+#ifdef JMP_CLEANUP
+		longjmp(jmpenv, 1);
+#else
+		do_cleanup(context);
+#endif
+	}
+}
+
+extern void do_div_by_0(void);
+
+static void task_proc(void *arg)
+{
+	int ret;
+	(void)arg;
+
+	ret = cobalt_rt_signal(TEST_SIGNAL, signal_handler);
+	assert(ret == 0);
+	(void)ret;
+
+#ifdef JMP_CLEANUP
+	if (setjmp(jmpenv) != 0)
+		return;
+#endif
+
+#ifdef TEST_SEGFAULT
+	*((int *)0x73) = 0xDECAFBAD;
+#elif defined(TEST_FPE)
+	// TODO: different instruction sequence for ARM
+	__asm__("xorl %eax, %eax\n\t"
+		"movl %eax, %ecx\n\t"
+		"cltd\n\t"
+		"idivl %ecx");
+#else
+	// TODO: different instruction for ARM
+	__asm__("ud2");
+#endif
+}
+
+static int test_sucessfull(void)
+{
+	if (status_ok()) {
+		fputs("Test passed\n", stderr);
+		return 1;
+	}
+
+	if (!(status & BIT_FAULT_HANDLER_ENTERD))
+		fputs("Test failed: signal handler not invoked!\n", stderr);
+	if ((status & BIT_FAULT_HANDLER_WRONG_TASK))
+		fputs("Test failed: Signal handler in wrong task!\n", stderr);
+	if ((status & BIT_FAULT_HANDLER_WRONG_SIG))
+		fputs("Test failed: Signal handler of wrong signal!\n", stderr);
+	if ((status & BIT_DOMAIN_SWITCH)) {
+		fputs("Test failed: domain switch happened!\n", stderr);
+		fprintf(stderr, "Caused by: %s\n", sigdebug_msg[cause]);
+	}
+
+	return 0;
+}
+
+int main(void)
+{
+	struct sigaction sa;
+	int ret;
+
+	memset(&sa, 0, sizeof(sa));
+	sa.sa_sigaction = signal_handler;
+	sa.sa_flags = SA_SIGINFO | SA_NODEFER;
+	sigaction(TEST_SIGNAL, &sa, NULL);
+	sigaction(SIGDEBUG, &sa, NULL);
+
+	ret = rt_task_create(&t1, "rt-task", 0, 20, T_JOINABLE | T_WARNSW);
+	assert(ret == 0);
+
+	ret = rt_task_start(&t1, task_proc, NULL);
+	assert(ret == 0);
+
+	ret = rt_task_join(&t1);
+	assert(ret == 0);
+	(void)ret; // so the compiler does not complain about not checking ret
+
+	return test_sucessfull() ? EXIT_SUCCESS : EXIT_FAILURE;
+}
-- 
2.25.1


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

* Re: [PATCH 0/3] prove of concept
  2022-07-07 13:59 [PATCH 0/3] prove of concept Johannes Kirchmair
                   ` (2 preceding siblings ...)
  2022-07-07 13:59 ` [PATCH 3/3] rtsignals: Add rt_signal test Johannes Kirchmair
@ 2022-07-07 15:19 ` Jan Kiszka
  2022-07-08  7:24   ` Johannes Kirchmair
  2022-07-08 17:42 ` Philippe Gerum
  4 siblings, 1 reply; 20+ messages in thread
From: Jan Kiszka @ 2022-07-07 15:19 UTC (permalink / raw)
  To: Johannes Kirchmair, xenomai

On 07.07.22 15:59, Johannes Kirchmair wrote:
> This is a prove of concept implementation of exception handling in Xenomai real
> time.
> 
> It implements an interface similar to the posix signals but with a much smaller
> feature set.
> 
> For now, this feature can be used for handling floating point exception (fpe)
> and illegal opcode exception in user space without losing real time.
> 
> The fpe exception handling can be used for fixing division by zero errors in
> user space code without dropping out of the real time domain.
> 
> The illegal opcode exceptions can be used for implementing breakpoints. This
> can be done by replacing the breakpoints original instruction by an illegal
> opcode. At the time a task tries to execute the instruction an illegal opcode
> exception will be triggered. The thread can be  suspended in the signal handler
> in user space. There are two main advantages of having it done in real time.
> 
> The first is if a task does some time critical IO or has to meet some watchdog
> constrains, the signal handler can be used to bring the IO into a sane state
> before the task is stopped. Same for the watchdog, it can be stopped before it
> sends the whole process into an error state.
> 
> The second advantage is for processes that have several real time tasks. For
> example consider a process with rt tasks task1 and task2, where task1 is of a
> higher priority than task2. If task1 triggers an exception and is relaxed to
> the Linux domain, task2 of a lesser priority would take over and could block
> the handling of the maybe more imported work/exception handling in task1.
> 
> Disclaimer:
> This implementation is far from being ready to merge. It is mainly intended to
> be a starting point for discussions about rather we (the community) want some
> kind of exception handling interface in Xenomai and what a maintainable
> interface for this could look like.
> 

Thanks for publishing this, will be very helpful to start the discussion!

I think you forgot to mention that it depends on I-pipe for now because
of "return KEVENT_STOP" from handle_exception. And I still owe you the
dovetail patch we have for 5.10 and that I just started to port to
5.19-rebase today. Will share soon.

Jan

-- 
Siemens AG, Technology
Competence Center Embedded Linux

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

* Re: [PATCH 1/3] rtsignals: part one, core code plus x86
  2022-07-07 13:59 ` [PATCH 1/3] rtsignals: part one, core code plus x86 Johannes Kirchmair
@ 2022-07-07 15:23   ` Jan Kiszka
  2022-07-08  7:30     ` Johannes Kirchmair
  0 siblings, 1 reply; 20+ messages in thread
From: Jan Kiszka @ 2022-07-07 15:23 UTC (permalink / raw)
  To: Johannes Kirchmair, xenomai

On 07.07.22 15:59, Johannes Kirchmair wrote:
> From: Richard Weinberger <richard@nod.at>
> 
> Adds code for implementing signals that are handled in the real time
> domain. This is done for 32bit process under an 64bit kernel.
> It works in a similar way to signals in the Linux kernel.
> 
> Edited-by: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>

...

> +static int ia32_setup_sigcontext(struct sigcontext_32 __user *sc,
> +				 void __user *fpstate, struct pt_regs *regs,
> +				 unsigned int mask)
> +{
> +	int err = 0;
> +
> +	put_user_try
> +	{
> +		put_user_ex(get_user_seg(gs), (unsigned int __user *)&sc->gs);
> +		put_user_ex(get_user_seg(fs), (unsigned int __user *)&sc->fs);
> +		put_user_ex(get_user_seg(ds), (unsigned int __user *)&sc->ds);
> +		put_user_ex(get_user_seg(es), (unsigned int __user *)&sc->es);
> +
> +		put_user_ex(regs->di, &sc->di);
> +		put_user_ex(regs->si, &sc->si);
> +		put_user_ex(regs->bp, &sc->bp);
> +		put_user_ex(regs->sp, &sc->sp);
> +		put_user_ex(regs->bx, &sc->bx);
> +		put_user_ex(regs->dx, &sc->dx);
> +		put_user_ex(regs->cx, &sc->cx);
> +		put_user_ex(regs->ax, &sc->ax);
> +		put_user_ex(current->thread.trap_nr, &sc->trapno);
> +		put_user_ex(current->thread.error_code, &sc->err);
> +		put_user_ex(regs->ip, &sc->ip);
> +		put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
> +		put_user_ex(regs->flags, &sc->flags);
> +		put_user_ex(regs->sp, &sc->sp_at_signal);
> +		put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
> +
> +		put_user_ex(ptr_to_compat(fpstate), &sc->fpstate);
> +
> +		/* non-iBCS2 extensions.. */
> +		put_user_ex(mask, &sc->oldmask);
> +		put_user_ex(current->thread.cr2, &sc->cr2);
> +	}
> +	put_user_catch(err);

Am I missing something - or did you miss to add the magic for this
get/put_user_try/catch?

Jan

-- 
Siemens AG, Technology
Competence Center Embedded Linux

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

* RE: [PATCH 0/3] prove of concept
  2022-07-07 15:19 ` [PATCH 0/3] prove of concept Jan Kiszka
@ 2022-07-08  7:24   ` Johannes Kirchmair
  0 siblings, 0 replies; 20+ messages in thread
From: Johannes Kirchmair @ 2022-07-08  7:24 UTC (permalink / raw)
  To: Jan Kiszka, xenomai

Hey Jan,

> -----Original Message-----
> From: Jan Kiszka <jan.kiszka@siemens.com>
> Sent: Donnerstag, 7. Juli 2022 17:19
> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
> xenomai@lists.linux.dev
> Subject: Re: [PATCH 0/3] prove of concept
> 
> On 07.07.22 15:59, Johannes Kirchmair wrote:
> > This is a prove of concept implementation of exception handling in Xenomai
> real
> > time.
> >
> > It implements an interface similar to the posix signals but with a much smaller
> > feature set.
> >
> > For now, this feature can be used for handling floating point exception (fpe)
> > and illegal opcode exception in user space without losing real time.
> >
> > The fpe exception handling can be used for fixing division by zero errors in
> > user space code without dropping out of the real time domain.
> >
> > The illegal opcode exceptions can be used for implementing breakpoints. This
> > can be done by replacing the breakpoints original instruction by an illegal
> > opcode. At the time a task tries to execute the instruction an illegal opcode
> > exception will be triggered. The thread can be  suspended in the signal handler
> > in user space. There are two main advantages of having it done in real time.
> >
> > The first is if a task does some time critical IO or has to meet some watchdog
> > constrains, the signal handler can be used to bring the IO into a sane state
> > before the task is stopped. Same for the watchdog, it can be stopped before it
> > sends the whole process into an error state.
> >
> > The second advantage is for processes that have several real time tasks. For
> > example consider a process with rt tasks task1 and task2, where task1 is of a
> > higher priority than task2. If task1 triggers an exception and is relaxed to
> > the Linux domain, task2 of a lesser priority would take over and could block
> > the handling of the maybe more imported work/exception handling in task1.
> >
> > Disclaimer:
> > This implementation is far from being ready to merge. It is mainly intended to
> > be a starting point for discussions about rather we (the community) want some
> > kind of exception handling interface in Xenomai and what a maintainable
> > interface for this could look like.
> >
> 
> Thanks for publishing this, will be very helpful to start the discussion!
> 
> I think you forgot to mention that it depends on I-pipe for now because
> of "return KEVENT_STOP" from handle_exception. And I still owe you the
> dovetail patch we have for 5.10 and that I just started to port to
> 5.19-rebase today. Will share soon.
See that you published it just now, will have a quick look later.

Yes forgot to add the information about the version. Have branched from stable/3.1.x and tested it with the 5.4 kernel.

Best regard
Johannes


> 
> Jan
> 
> --
> Siemens AG, Technology
> Competence Center Embedded Linux

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

* RE: [PATCH 1/3] rtsignals: part one, core code plus x86
  2022-07-07 15:23   ` Jan Kiszka
@ 2022-07-08  7:30     ` Johannes Kirchmair
  2023-01-20  9:04       ` Jan Kiszka
  0 siblings, 1 reply; 20+ messages in thread
From: Johannes Kirchmair @ 2022-07-08  7:30 UTC (permalink / raw)
  To: Jan Kiszka, xenomai

Hey Jan,

> -----Original Message-----
> From: Jan Kiszka <jan.kiszka@siemens.com>
> Sent: Donnerstag, 7. Juli 2022 17:24
> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
> xenomai@lists.linux.dev
> Subject: Re: [PATCH 1/3] rtsignals: part one, core code plus x86
> 
> On 07.07.22 15:59, Johannes Kirchmair wrote:
> > From: Richard Weinberger <richard@nod.at>
> >
> > Adds code for implementing signals that are handled in the real time
> > domain. This is done for 32bit process under an 64bit kernel.
> > It works in a similar way to signals in the Linux kernel.
> >
> > Edited-by: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
> 
> ...
> 
> > +static int ia32_setup_sigcontext(struct sigcontext_32 __user *sc,
> > +				 void __user *fpstate, struct pt_regs *regs,
> > +				 unsigned int mask)
> > +{
> > +	int err = 0;
> > +
> > +	put_user_try
> > +	{
> > +		put_user_ex(get_user_seg(gs), (unsigned int __user *)&sc->gs);
> > +		put_user_ex(get_user_seg(fs), (unsigned int __user *)&sc->fs);
> > +		put_user_ex(get_user_seg(ds), (unsigned int __user *)&sc->ds);
> > +		put_user_ex(get_user_seg(es), (unsigned int __user *)&sc->es);
> > +
> > +		put_user_ex(regs->di, &sc->di);
> > +		put_user_ex(regs->si, &sc->si);
> > +		put_user_ex(regs->bp, &sc->bp);
> > +		put_user_ex(regs->sp, &sc->sp);
> > +		put_user_ex(regs->bx, &sc->bx);
> > +		put_user_ex(regs->dx, &sc->dx);
> > +		put_user_ex(regs->cx, &sc->cx);
> > +		put_user_ex(regs->ax, &sc->ax);
> > +		put_user_ex(current->thread.trap_nr, &sc->trapno);
> > +		put_user_ex(current->thread.error_code, &sc->err);
> > +		put_user_ex(regs->ip, &sc->ip);
> > +		put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
> > +		put_user_ex(regs->flags, &sc->flags);
> > +		put_user_ex(regs->sp, &sc->sp_at_signal);
> > +		put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
> > +
> > +		put_user_ex(ptr_to_compat(fpstate), &sc->fpstate);
> > +
> > +		/* non-iBCS2 extensions.. */
> > +		put_user_ex(mask, &sc->oldmask);
> > +		put_user_ex(current->thread.cr2, &sc->cr2);
> > +	}
> > +	put_user_catch(err);
> 
> Am I missing something - or did you miss to add the magic for this
> get/put_user_try/catch?
Tried to figure it out this morning, but don’t understand it fully jet. Actually don’t quite get, how the errors of put_user_ex are propagated into the err variable. Probably in this case put_user_try, put_user_catch is only for disabling SMAP. But I will have a deeper look at it in the beginning of August after my vacation.

Best regards Johannes 

> 
> Jan
> 
> --
> Siemens AG, Technology
> Competence Center Embedded Linux

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

* Re: [PATCH 0/3] prove of concept
  2022-07-07 13:59 [PATCH 0/3] prove of concept Johannes Kirchmair
                   ` (3 preceding siblings ...)
  2022-07-07 15:19 ` [PATCH 0/3] prove of concept Jan Kiszka
@ 2022-07-08 17:42 ` Philippe Gerum
  2022-07-11  6:12   ` Jan Kiszka
  2022-08-23  6:32   ` Johannes Kirchmair
  4 siblings, 2 replies; 20+ messages in thread
From: Philippe Gerum @ 2022-07-08 17:42 UTC (permalink / raw)
  To: Johannes Kirchmair; +Cc: xenomai


Johannes Kirchmair <johannes.kirchmair@sigmatek.at> writes:

> This is a prove of concept implementation of exception handling in Xenomai real
> time.
>
> It implements an interface similar to the posix signals but with a much smaller
> feature set.
>
> For now, this feature can be used for handling floating point exception (fpe)
> and illegal opcode exception in user space without losing real time.
>
> The fpe exception handling can be used for fixing division by zero errors in
> user space code without dropping out of the real time domain.
>
> The illegal opcode exceptions can be used for implementing breakpoints. This
> can be done by replacing the breakpoints original instruction by an illegal
> opcode. At the time a task tries to execute the instruction an illegal opcode
> exception will be triggered. The thread can be  suspended in the signal handler
> in user space. There are two main advantages of having it done in real time.
>
> The first is if a task does some time critical IO or has to meet some watchdog
> constrains, the signal handler can be used to bring the IO into a sane state
> before the task is stopped. Same for the watchdog, it can be stopped before it
> sends the whole process into an error state.
>
> The second advantage is for processes that have several real time tasks. For
> example consider a process with rt tasks task1 and task2, where task1 is of a
> higher priority than task2. If task1 triggers an exception and is relaxed to
> the Linux domain, task2 of a lesser priority would take over and could block
> the handling of the maybe more imported work/exception handling in task1.
>
> Disclaimer:
> This implementation is far from being ready to merge. It is mainly intended to
> be a starting point for discussions about rather we (the community) want some
> kind of exception handling interface in Xenomai and what a maintainable
> interface for this could look like.
>

Thanks for taking a close look to this. Since the proposal is about
handling CPU traps in user-space, I have a couple of observations
regarding the kernel side of things, and some questions regarding the
intended use cases application-wise.

With respect to x86, the traps roughly fall into these categories:
   
- #NM, #XF, #XM, #MF, #DB, #PF, #AC and #BP may need some kernel fixup
  to be applied when taken from non-privileged mode, we cannot just
  return from the oob handler and be done with it in every possible
  case.

- #DF, #MC, #SS and #TS do not involve user-space activity, so let's
  ignore these, along with any trap involved in virtualization
  management, there is no point in routing them to a user-space handler
  anyway.

- #GP, #DE, #OF, #BR and #UD either do not need further kernel fixup, or
  at least such fixup can be done transparently on the oob stage with no
  impact on the worst-case latency. Routing them to a rt signal handler
  in user-space could be done.

The first set looks problematic though:
  
* duplicating the original fixup code in the real-time core
  (e.g. Cobalt, EVL) would be a bad idea (obsolescence, portability
  issues, prone to hidden regressions). We have been there with the
  I-pipe and FPU management offloaded to Cobalt already. This is the
  reason why Dovetail provides built-in scheduling and FPU management in
  oob mode, offloading such tasks to the real-time core can only end up
  in some interstellar mess.

* however, reusing the existing kernel fixup code may require to
  re-enter the regular inband execution context. In most cases, the
  portion of that code which handles user-originated traps cannot
  support out-of-band traversal (e.g. takes regular spinlocks we
  certainly do not want to convert to hard locks). Dovetail already
  tries hard not to notify the core about any fault which can be fixed
  up without switching in-band first, IOW: we leave oob mode only when
  we really have to, not systematically upon trap.

Because of this, generalizing the ability for the core to bypass the
kernel fixups for any kind of trap does not look right.

This does not impede us from looking for a way to catch the events from
the 3rd set which could be handled safely from user-space in oob mode
though. You mentioned so far the following use cases:

- unchecked maths: #DE handling

- I/O stall detection: watchdog disabling, hw cleanup then
  self-suspension on #UD (used as a way to force a breakpoint)

What a handler would do looks obvious with respect to receiving a
forced #UD, the user code may even be allowed to resume normally
from the suspension point at some point later.

However, it is unclear to me what a handler might do upon other traps,
such as #DE, #GP, #OF and so on: the faulty thread could not be allowed
to resume execution from the code location which caused the exception,
as I don't see how the original issue could be fixed reliably from the
rt signal handler.

I see two options for this handler:

- it does a siglongjmp() to some recovery point in the call stack:
  fairly ugly and basically unreliable for any state machine above
  trivial.

- it notifies some health monitoring agent to take over, in order to run
  some recovery steps, then self-suspends the current thread. We would
  not need POSIX signal semantics to implement this.

In other words, is a generic async signal API the best - and required -
way to address the issue(s) at hand?

-- 
Philippe.

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

* Re: [PATCH 0/3] prove of concept
  2022-07-08 17:42 ` Philippe Gerum
@ 2022-07-11  6:12   ` Jan Kiszka
  2022-08-23  6:32   ` Johannes Kirchmair
  1 sibling, 0 replies; 20+ messages in thread
From: Jan Kiszka @ 2022-07-11  6:12 UTC (permalink / raw)
  To: Philippe Gerum, Johannes Kirchmair; +Cc: xenomai

On 08.07.22 19:42, Philippe Gerum wrote:
> 
> Johannes Kirchmair <johannes.kirchmair@sigmatek.at> writes:
> 
>> This is a prove of concept implementation of exception handling in Xenomai real
>> time.
>>
>> It implements an interface similar to the posix signals but with a much smaller
>> feature set.
>>
>> For now, this feature can be used for handling floating point exception (fpe)
>> and illegal opcode exception in user space without losing real time.
>>
>> The fpe exception handling can be used for fixing division by zero errors in
>> user space code without dropping out of the real time domain.
>>
>> The illegal opcode exceptions can be used for implementing breakpoints. This
>> can be done by replacing the breakpoints original instruction by an illegal
>> opcode. At the time a task tries to execute the instruction an illegal opcode
>> exception will be triggered. The thread can be  suspended in the signal handler
>> in user space. There are two main advantages of having it done in real time.
>>
>> The first is if a task does some time critical IO or has to meet some watchdog
>> constrains, the signal handler can be used to bring the IO into a sane state
>> before the task is stopped. Same for the watchdog, it can be stopped before it
>> sends the whole process into an error state.
>>
>> The second advantage is for processes that have several real time tasks. For
>> example consider a process with rt tasks task1 and task2, where task1 is of a
>> higher priority than task2. If task1 triggers an exception and is relaxed to
>> the Linux domain, task2 of a lesser priority would take over and could block
>> the handling of the maybe more imported work/exception handling in task1.
>>
>> Disclaimer:
>> This implementation is far from being ready to merge. It is mainly intended to
>> be a starting point for discussions about rather we (the community) want some
>> kind of exception handling interface in Xenomai and what a maintainable
>> interface for this could look like.
>>
> 
> Thanks for taking a close look to this. Since the proposal is about
> handling CPU traps in user-space, I have a couple of observations
> regarding the kernel side of things, and some questions regarding the
> intended use cases application-wise.
> 
> With respect to x86, the traps roughly fall into these categories:
>    
> - #NM, #XF, #XM, #MF, #DB, #PF, #AC and #BP may need some kernel fixup
>   to be applied when taken from non-privileged mode, we cannot just
>   return from the oob handler and be done with it in every possible
>   case.
> 
> - #DF, #MC, #SS and #TS do not involve user-space activity, so let's
>   ignore these, along with any trap involved in virtualization
>   management, there is no point in routing them to a user-space handler
>   anyway.
> 
> - #GP, #DE, #OF, #BR and #UD either do not need further kernel fixup, or
>   at least such fixup can be done transparently on the oob stage with no
>   impact on the worst-case latency. Routing them to a rt signal handler
>   in user-space could be done.
> 
> The first set looks problematic though:
>   
> * duplicating the original fixup code in the real-time core
>   (e.g. Cobalt, EVL) would be a bad idea (obsolescence, portability
>   issues, prone to hidden regressions). We have been there with the
>   I-pipe and FPU management offloaded to Cobalt already. This is the
>   reason why Dovetail provides built-in scheduling and FPU management in
>   oob mode, offloading such tasks to the real-time core can only end up
>   in some interstellar mess.
> 
> * however, reusing the existing kernel fixup code may require to
>   re-enter the regular inband execution context. In most cases, the
>   portion of that code which handles user-originated traps cannot
>   support out-of-band traversal (e.g. takes regular spinlocks we
>   certainly do not want to convert to hard locks). Dovetail already
>   tries hard not to notify the core about any fault which can be fixed
>   up without switching in-band first, IOW: we leave oob mode only when
>   we really have to, not systematically upon trap.
> 
> Because of this, generalizing the ability for the core to bypass the
> kernel fixups for any kind of trap does not look right.
> 
> This does not impede us from looking for a way to catch the events from
> the 3rd set which could be handled safely from user-space in oob mode
> though. You mentioned so far the following use cases:
> 
> - unchecked maths: #DE handling
> 
> - I/O stall detection: watchdog disabling, hw cleanup then
>   self-suspension on #UD (used as a way to force a breakpoint)
> 
> What a handler would do looks obvious with respect to receiving a
> forced #UD, the user code may even be allowed to resume normally
> from the suspension point at some point later.
> 
> However, it is unclear to me what a handler might do upon other traps,
> such as #DE, #GP, #OF and so on: the faulty thread could not be allowed
> to resume execution from the code location which caused the exception,
> as I don't see how the original issue could be fixed reliably from the
> rt signal handler.
> 
> I see two options for this handler:
> 
> - it does a siglongjmp() to some recovery point in the call stack:
>   fairly ugly and basically unreliable for any state machine above
>   trivial.
> 
> - it notifies some health monitoring agent to take over, in order to run
>   some recovery steps, then self-suspends the current thread. We would
>   not need POSIX signal semantics to implement this.
> 
> In other words, is a generic async signal API the best - and required -
> way to address the issue(s) at hand?
> 

We have two kinds of reaction scenarios on our side:

 - fix up a by kind of siglongjmp (restart thread with a good state)
 - inform higher prio threads immediate about the problem of this
   thread, rather then doing that only after lower prio threads were run
   (analogous to pre/post debug handlers)

Regarding an asynchronous signal API in general: We are also considering
if timer signal handlers could allow to resolve certain scheduling /
schedule overflow scenarios. That would make another reason to consider
introducing RT signal frames. But that's not settled yet and has lower
prio than the exception topic.

Jan

-- 
Siemens AG, Technology
Competence Center Embedded Linux

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

* RE: [PATCH 0/3] prove of concept
  2022-07-08 17:42 ` Philippe Gerum
  2022-07-11  6:12   ` Jan Kiszka
@ 2022-08-23  6:32   ` Johannes Kirchmair
  1 sibling, 0 replies; 20+ messages in thread
From: Johannes Kirchmair @ 2022-08-23  6:32 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: xenomai

Hello Philippe,

I am sorry for the very late response.
After my vacation some other topics not directly linked to Xenomai hit me.

> -----Original Message-----
> From: Philippe Gerum <rpm@xenomai.org>
> Sent: Freitag, 8. Juli 2022 19:43
> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
> Cc: xenomai@lists.linux.dev
> Subject: Re: [PATCH 0/3] prove of concept
> 
> 
> Johannes Kirchmair <johannes.kirchmair@sigmatek.at> writes:
> 
> > This is a prove of concept implementation of exception handling in Xenomai
> real
> > time.
> >
> > It implements an interface similar to the posix signals but with a much smaller
> > feature set.
> >
> > For now, this feature can be used for handling floating point exception (fpe)
> > and illegal opcode exception in user space without losing real time.
> >
> > The fpe exception handling can be used for fixing division by zero errors in
> > user space code without dropping out of the real time domain.
> >
> > The illegal opcode exceptions can be used for implementing breakpoints. This
> > can be done by replacing the breakpoints original instruction by an illegal
> > opcode. At the time a task tries to execute the instruction an illegal opcode
> > exception will be triggered. The thread can be  suspended in the signal handler
> > in user space. There are two main advantages of having it done in real time.
> >
> > The first is if a task does some time critical IO or has to meet some watchdog
> > constrains, the signal handler can be used to bring the IO into a sane state
> > before the task is stopped. Same for the watchdog, it can be stopped before it
> > sends the whole process into an error state.
> >
> > The second advantage is for processes that have several real time tasks. For
> > example consider a process with rt tasks task1 and task2, where task1 is of a
> > higher priority than task2. If task1 triggers an exception and is relaxed to
> > the Linux domain, task2 of a lesser priority would take over and could block
> > the handling of the maybe more imported work/exception handling in task1.
> >
> > Disclaimer:
> > This implementation is far from being ready to merge. It is mainly intended to
> > be a starting point for discussions about rather we (the community) want some
> > kind of exception handling interface in Xenomai and what a maintainable
> > interface for this could look like.
> >
> 
> Thanks for taking a close look to this. Since the proposal is about
> handling CPU traps in user-space, I have a couple of observations
> regarding the kernel side of things, and some questions regarding the
> intended use cases application-wise.
> 
> With respect to x86, the traps roughly fall into these categories:
> 
> - #NM, #XF, #XM, #MF, #DB, #PF, #AC and #BP may need some kernel fixup
>   to be applied when taken from non-privileged mode, we cannot just
>   return from the oob handler and be done with it in every possible
>   case.
> 
> - #DF, #MC, #SS and #TS do not involve user-space activity, so let's
>   ignore these, along with any trap involved in virtualization
>   management, there is no point in routing them to a user-space handler
>   anyway.
> 
> - #GP, #DE, #OF, #BR and #UD either do not need further kernel fixup, or
>   at least such fixup can be done transparently on the oob stage with no
>   impact on the worst-case latency. Routing them to a rt signal handler
>   in user-space could be done.
> 
> The first set looks problematic though:
> 
> * duplicating the original fixup code in the real-time core
>   (e.g. Cobalt, EVL) would be a bad idea (obsolescence, portability
>   issues, prone to hidden regressions). We have been there with the
>   I-pipe and FPU management offloaded to Cobalt already. This is the
>   reason why Dovetail provides built-in scheduling and FPU management in
>   oob mode, offloading such tasks to the real-time core can only end up
>   in some interstellar mess.
> 
> * however, reusing the existing kernel fixup code may require to
>   re-enter the regular inband execution context. In most cases, the
>   portion of that code which handles user-originated traps cannot
>   support out-of-band traversal (e.g. takes regular spinlocks we
>   certainly do not want to convert to hard locks). Dovetail already
>   tries hard not to notify the core about any fault which can be fixed
>   up without switching in-band first, IOW: we leave oob mode only when
>   we really have to, not systematically upon trap.
> 
> Because of this, generalizing the ability for the core to bypass the
> kernel fixups for any kind of trap does not look right.
> 
> This does not impede us from looking for a way to catch the events from
> the 3rd set which could be handled safely from user-space in oob mode
> though. You mentioned so far the following use cases:


Thank you for you detailed write-up of the different groups of exceptions and their handling in the kernel.
Actually I so far did not entertain the fact that the kernel does some complex fixups for some exceptions. 
And I agree on the point that we probably should not handle those in oob-code.

My main concern was with #UD and #DE as we have use cases for just those. At least at this moment.

> - unchecked maths: #DE handling
> 
> - I/O stall detection: watchdog disabling, hw cleanup then
>   self-suspension on #UD (used as a way to force a breakpoint)
> 
> What a handler would do looks obvious with respect to receiving a
> forced #UD, the user code may even be allowed to resume normally
> from the suspension point at some point later.
> 
> However, it is unclear to me what a handler might do upon other traps,
> such as #DE, #GP, #OF and so on: the faulty thread could not be allowed
> to resume execution from the code location which caused the exception,
> as I don't see how the original issue could be fixed reliably from the
> rt signal handler.
> 
> I see two options for this handler:
> 
> - it does a siglongjmp() to some recovery point in the call stack:
>   fairly ugly and basically unreliable for any state machine above
>   trivial.
> 
> - it notifies some health monitoring agent to take over, in order to run
>   some recovery steps, then self-suspends the current thread. We would
>   not need POSIX signal semantics to implement this.
>

To add some context, we do automatization hardware and have a runtime engine that allows our customers to run their own applications on our hardware. They are able to run some stuff in real time tasks and also the runtime engine use real time tasks for interacting with hardware that needs a certain timing for the interaction with it.

If we don't have a way to fix the problems that caused the exception we do the following. 
We tell the runtime engine to stop the application running. Than in fact use siglongjmp to go to a certain point, where we most of the time do some cleanup for the task and  then terminate it.

> In other words, is a generic async signal API the best - and required -
> way to address the issue(s) at hand?

I prefer  a solution with a signal like approach because it runs the exception handling in the same task context so we don't have to think that much about tasks priorities. As the task that triggers an exception has a certain priority we should probably handle the error in the same priority. If we run the fixup in a monitoring task it will probably have a higher priority than the task having the issue. This could lead to indirect blocking of high priority tasks by a low priority task.

Anyways, I did not find a lot of time to think of an alternative approach for the problem at hand because the solution with signals
where already in use before I started at the my company.
I will think about if signals are the only way and talk to some of the senior developers here, to get a better understanding.
  
But for sure thank you for your input and concerns regarding the topic.

Best regards
Johannes


> 
> --
> Philippe.

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

* Re: [PATCH 1/3] rtsignals: part one, core code plus x86
  2022-07-08  7:30     ` Johannes Kirchmair
@ 2023-01-20  9:04       ` Jan Kiszka
  2023-01-20 11:01         ` Johannes Kirchmair
  0 siblings, 1 reply; 20+ messages in thread
From: Jan Kiszka @ 2023-01-20  9:04 UTC (permalink / raw)
  To: Johannes Kirchmair, xenomai

On 08.07.22 09:30, Johannes Kirchmair wrote:
> Hey Jan,
> 
>> -----Original Message-----
>> From: Jan Kiszka <jan.kiszka@siemens.com>
>> Sent: Donnerstag, 7. Juli 2022 17:24
>> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
>> xenomai@lists.linux.dev
>> Subject: Re: [PATCH 1/3] rtsignals: part one, core code plus x86
>>
>> On 07.07.22 15:59, Johannes Kirchmair wrote:
>>> From: Richard Weinberger <richard@nod.at>
>>>
>>> Adds code for implementing signals that are handled in the real time
>>> domain. This is done for 32bit process under an 64bit kernel.
>>> It works in a similar way to signals in the Linux kernel.
>>>
>>> Edited-by: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
>>
>> ...
>>
>>> +static int ia32_setup_sigcontext(struct sigcontext_32 __user *sc,
>>> +				 void __user *fpstate, struct pt_regs *regs,
>>> +				 unsigned int mask)
>>> +{
>>> +	int err = 0;
>>> +
>>> +	put_user_try
>>> +	{
>>> +		put_user_ex(get_user_seg(gs), (unsigned int __user *)&sc->gs);
>>> +		put_user_ex(get_user_seg(fs), (unsigned int __user *)&sc->fs);
>>> +		put_user_ex(get_user_seg(ds), (unsigned int __user *)&sc->ds);
>>> +		put_user_ex(get_user_seg(es), (unsigned int __user *)&sc->es);
>>> +
>>> +		put_user_ex(regs->di, &sc->di);
>>> +		put_user_ex(regs->si, &sc->si);
>>> +		put_user_ex(regs->bp, &sc->bp);
>>> +		put_user_ex(regs->sp, &sc->sp);
>>> +		put_user_ex(regs->bx, &sc->bx);
>>> +		put_user_ex(regs->dx, &sc->dx);
>>> +		put_user_ex(regs->cx, &sc->cx);
>>> +		put_user_ex(regs->ax, &sc->ax);
>>> +		put_user_ex(current->thread.trap_nr, &sc->trapno);
>>> +		put_user_ex(current->thread.error_code, &sc->err);
>>> +		put_user_ex(regs->ip, &sc->ip);
>>> +		put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
>>> +		put_user_ex(regs->flags, &sc->flags);
>>> +		put_user_ex(regs->sp, &sc->sp_at_signal);
>>> +		put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
>>> +
>>> +		put_user_ex(ptr_to_compat(fpstate), &sc->fpstate);
>>> +
>>> +		/* non-iBCS2 extensions.. */
>>> +		put_user_ex(mask, &sc->oldmask);
>>> +		put_user_ex(current->thread.cr2, &sc->cr2);
>>> +	}
>>> +	put_user_catch(err);
>>
>> Am I missing something - or did you miss to add the magic for this
>> get/put_user_try/catch?
> Tried to figure it out this morning, but don’t understand it fully jet. Actually don’t quite get, how the errors of put_user_ex are propagated into the err variable. Probably in this case put_user_try, put_user_catch is only for disabling SMAP. But I will have a deeper look at it in the beginning of August after my vacation.
> 

Was there a follow-up on this? I'm planning to revive this finally,
figuring out if there are pitfalls in going the sigaction/sigreturn path
for Xenomai.

BTW, I do not understand why you made the restorer function a direct
parameter of the sigaction syscall. It comes from the sigaction
structure. And your implementation cannot provide oact when we want to
add sigaction as library call as well.

Jan

-- 
Siemens AG, Technology
Competence Center Embedded Linux


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

* RE: [PATCH 1/3] rtsignals: part one, core code plus x86
  2023-01-20  9:04       ` Jan Kiszka
@ 2023-01-20 11:01         ` Johannes Kirchmair
  2023-01-20 11:41           ` Jan Kiszka
  0 siblings, 1 reply; 20+ messages in thread
From: Johannes Kirchmair @ 2023-01-20 11:01 UTC (permalink / raw)
  To: Jan Kiszka, xenomai

Hey Jan,

Sorry for not responding for so long.
Got dragged away from this unfortunatly. 


> -----Original Message-----
> From: Jan Kiszka <jan.kiszka@siemens.com>
> Sent: Freitag, 20. Jänner 2023 10:05
> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
> xenomai@lists.linux.dev
> Subject: Re: [PATCH 1/3] rtsignals: part one, core code plus x86
> 
> CAUTION: External E-Mail !
> 
> On 08.07.22 09:30, Johannes Kirchmair wrote:
> > Hey Jan,
> >
> >> -----Original Message-----
> >> From: Jan Kiszka <jan.kiszka@siemens.com>
> >> Sent: Donnerstag, 7. Juli 2022 17:24
> >> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
> >> xenomai@lists.linux.dev
> >> Subject: Re: [PATCH 1/3] rtsignals: part one, core code plus x86
> >>
> >> On 07.07.22 15:59, Johannes Kirchmair wrote:
> >>> From: Richard Weinberger <richard@nod.at>
> >>>
> >>> Adds code for implementing signals that are handled in the real time
> >>> domain. This is done for 32bit process under an 64bit kernel.
> >>> It works in a similar way to signals in the Linux kernel.
> >>>
> >>> Edited-by: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
> >>
> >> ...
> >>
> >>> +static int ia32_setup_sigcontext(struct sigcontext_32 __user *sc,
> >>> +                            void __user *fpstate, struct pt_regs *regs,
> >>> +                            unsigned int mask)
> >>> +{
> >>> +   int err = 0;
> >>> +
> >>> +   put_user_try
> >>> +   {
> >>> +           put_user_ex(get_user_seg(gs), (unsigned int __user *)&sc->gs);
> >>> +           put_user_ex(get_user_seg(fs), (unsigned int __user *)&sc->fs);
> >>> +           put_user_ex(get_user_seg(ds), (unsigned int __user *)&sc->ds);
> >>> +           put_user_ex(get_user_seg(es), (unsigned int __user *)&sc->es);
> >>> +
> >>> +           put_user_ex(regs->di, &sc->di);
> >>> +           put_user_ex(regs->si, &sc->si);
> >>> +           put_user_ex(regs->bp, &sc->bp);
> >>> +           put_user_ex(regs->sp, &sc->sp);
> >>> +           put_user_ex(regs->bx, &sc->bx);
> >>> +           put_user_ex(regs->dx, &sc->dx);
> >>> +           put_user_ex(regs->cx, &sc->cx);
> >>> +           put_user_ex(regs->ax, &sc->ax);
> >>> +           put_user_ex(current->thread.trap_nr, &sc->trapno);
> >>> +           put_user_ex(current->thread.error_code, &sc->err);
> >>> +           put_user_ex(regs->ip, &sc->ip);
> >>> +           put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
> >>> +           put_user_ex(regs->flags, &sc->flags);
> >>> +           put_user_ex(regs->sp, &sc->sp_at_signal);
> >>> +           put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
> >>> +
> >>> +           put_user_ex(ptr_to_compat(fpstate), &sc->fpstate);
> >>> +
> >>> +           /* non-iBCS2 extensions.. */
> >>> +           put_user_ex(mask, &sc->oldmask);
> >>> +           put_user_ex(current->thread.cr2, &sc->cr2);
> >>> +   }
> >>> +   put_user_catch(err);
> >>
> >> Am I missing something - or did you miss to add the magic for this
> >> get/put_user_try/catch?
> > Tried to figure it out this morning, but don’t understand it fully jet. Actually
> don’t quite get, how the errors of put_user_ex are propagated into the err
> variable. Probably in this case put_user_try, put_user_catch is only for disabling
> SMAP. But I will have a deeper look at it in the beginning of August after my
> vacation.
> >
> 
> Was there a follow-up on this? I'm planning to revive this finally,
> figuring out if there are pitfalls in going the sigaction/sigreturn path
> for Xenomai.
For the question of the try/catch 
We don’t have really a catch clause here, as we check access to the sigframe beforehand and we only use the put_user_try to disable SMAP to be able to copy to the user stack.

> 
> BTW, I do not understand why you made the restorer function a direct
> parameter of the sigaction syscall. It comes from the sigaction
> structure. And your implementation cannot provide oact when we want to
> add sigaction as library call as well.
Oact? 

Actually I am not quite sure, but I guess the reason was to have a rather simple distinct syscall to Linux sigaction syscall. 
We do not even pass a sigaction structure to the cobalt core, but just a handler and the restorer.

There are some things I thought about, but did not find the time to investigate:

- I copied and modified some of the signal code from Linux and removed everything I did not need for my purpose.
  Maybe it would be possible to use the Linux functions without modifying. (Primarily the sigframe setup and restore code) 
  I think it would be cleaner to not have too much copied code.

- I always wondered what would happen if we have a domain switch in a signal handler.
  I still have not a deep enough knowledge of Xenomai. If we switch from Xenomai to Linux domain. 
  The restorer code would make an cobald syscall ending up in the cobald restorer, but not quite sure about it.

- Thought about, if we could use the sighandler stored in Linuxes task struct.
  So we could handle signals in Xenomai domain, that were registered form Linux domain. 
  But not sure if possible. 

I am not quite sure, at what time I will have time to work on this again. Will have to talk to my supervisor. 

But would be happy if we would find a clean way of integrating this into Xenomai.

Best regards
Johannes



> 
> Jan
> 
> --
> Siemens AG, Technology
> Competence Center Embedded Linux


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

* Re: [PATCH 1/3] rtsignals: part one, core code plus x86
  2023-01-20 11:01         ` Johannes Kirchmair
@ 2023-01-20 11:41           ` Jan Kiszka
  2023-04-19  9:18             ` Johannes Kirchmair
  0 siblings, 1 reply; 20+ messages in thread
From: Jan Kiszka @ 2023-01-20 11:41 UTC (permalink / raw)
  To: Johannes Kirchmair, xenomai

On 20.01.23 12:01, Johannes Kirchmair wrote:
> Hey Jan,
> 
> Sorry for not responding for so long.
> Got dragged away from this unfortunatly. 
> 
> 
>> -----Original Message-----
>> From: Jan Kiszka <jan.kiszka@siemens.com>
>> Sent: Freitag, 20. Jänner 2023 10:05
>> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
>> xenomai@lists.linux.dev
>> Subject: Re: [PATCH 1/3] rtsignals: part one, core code plus x86
>>
>> CAUTION: External E-Mail !
>>
>> On 08.07.22 09:30, Johannes Kirchmair wrote:
>>> Hey Jan,
>>>
>>>> -----Original Message-----
>>>> From: Jan Kiszka <jan.kiszka@siemens.com>
>>>> Sent: Donnerstag, 7. Juli 2022 17:24
>>>> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
>>>> xenomai@lists.linux.dev
>>>> Subject: Re: [PATCH 1/3] rtsignals: part one, core code plus x86
>>>>
>>>> On 07.07.22 15:59, Johannes Kirchmair wrote:
>>>>> From: Richard Weinberger <richard@nod.at>
>>>>>
>>>>> Adds code for implementing signals that are handled in the real time
>>>>> domain. This is done for 32bit process under an 64bit kernel.
>>>>> It works in a similar way to signals in the Linux kernel.
>>>>>
>>>>> Edited-by: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
>>>>
>>>> ...
>>>>
>>>>> +static int ia32_setup_sigcontext(struct sigcontext_32 __user *sc,
>>>>> +                            void __user *fpstate, struct pt_regs *regs,
>>>>> +                            unsigned int mask)
>>>>> +{
>>>>> +   int err = 0;
>>>>> +
>>>>> +   put_user_try
>>>>> +   {
>>>>> +           put_user_ex(get_user_seg(gs), (unsigned int __user *)&sc->gs);
>>>>> +           put_user_ex(get_user_seg(fs), (unsigned int __user *)&sc->fs);
>>>>> +           put_user_ex(get_user_seg(ds), (unsigned int __user *)&sc->ds);
>>>>> +           put_user_ex(get_user_seg(es), (unsigned int __user *)&sc->es);
>>>>> +
>>>>> +           put_user_ex(regs->di, &sc->di);
>>>>> +           put_user_ex(regs->si, &sc->si);
>>>>> +           put_user_ex(regs->bp, &sc->bp);
>>>>> +           put_user_ex(regs->sp, &sc->sp);
>>>>> +           put_user_ex(regs->bx, &sc->bx);
>>>>> +           put_user_ex(regs->dx, &sc->dx);
>>>>> +           put_user_ex(regs->cx, &sc->cx);
>>>>> +           put_user_ex(regs->ax, &sc->ax);
>>>>> +           put_user_ex(current->thread.trap_nr, &sc->trapno);
>>>>> +           put_user_ex(current->thread.error_code, &sc->err);
>>>>> +           put_user_ex(regs->ip, &sc->ip);
>>>>> +           put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
>>>>> +           put_user_ex(regs->flags, &sc->flags);
>>>>> +           put_user_ex(regs->sp, &sc->sp_at_signal);
>>>>> +           put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
>>>>> +
>>>>> +           put_user_ex(ptr_to_compat(fpstate), &sc->fpstate);
>>>>> +
>>>>> +           /* non-iBCS2 extensions.. */
>>>>> +           put_user_ex(mask, &sc->oldmask);
>>>>> +           put_user_ex(current->thread.cr2, &sc->cr2);
>>>>> +   }
>>>>> +   put_user_catch(err);
>>>>
>>>> Am I missing something - or did you miss to add the magic for this
>>>> get/put_user_try/catch?
>>> Tried to figure it out this morning, but don’t understand it fully jet. Actually
>> don’t quite get, how the errors of put_user_ex are propagated into the err
>> variable. Probably in this case put_user_try, put_user_catch is only for disabling
>> SMAP. But I will have a deeper look at it in the beginning of August after my
>> vacation.
>>>
>>
>> Was there a follow-up on this? I'm planning to revive this finally,
>> figuring out if there are pitfalls in going the sigaction/sigreturn path
>> for Xenomai.
> For the question of the try/catch 
> We don’t have really a catch clause here, as we check access to the sigframe beforehand and we only use the put_user_try to disable SMAP to be able to copy to the user stack.
> 
>>
>> BTW, I do not understand why you made the restorer function a direct
>> parameter of the sigaction syscall. It comes from the sigaction
>> structure. And your implementation cannot provide oact when we want to
>> add sigaction as library call as well.
> Oact? 

Previous (old) action handler, see man sigaction.

> 
> Actually I am not quite sure, but I guess the reason was to have a rather simple distinct syscall to Linux sigaction syscall. 
> We do not even pass a sigaction structure to the cobalt core, but just a handler and the restorer.

Enough for signal(), not for sigaction(). But it would be a valid
question if we really want/have to support all features of sigaction.

> 
> There are some things I thought about, but did not find the time to investigate:
> 
> - I copied and modified some of the signal code from Linux and removed everything I did not need for my purpose.
>   Maybe it would be possible to use the Linux functions without modifying. (Primarily the sigframe setup and restore code) 
>   I think it would be cleaner to not have too much copied code.

Ack, to-be-checked.

> 
> - I always wondered what would happen if we have a domain switch in a signal handler.
>   I still have not a deep enough knowledge of Xenomai. If we switch from Xenomai to Linux domain. 
>   The restorer code would make an cobald syscall ending up in the cobald restorer, but not quite sure about it.

I don't think this should cause troubles. Cobalt's sigreturn would
simply enforce a switch-back to RT (if that is needed, didn't check) and
would restore userspace state from the saved state on the thread's stack.

What should be considered as well is an async signal handling in the
middle of the RT handler - whether already migrated or only migrated
upon that. As all userspace-related state is on the userspace stack,
nesting should work, but it all becomes quickly rather complicated.

> 
> - Thought about, if we could use the sighandler stored in Linuxes task struct.
>   So we could handle signals in Xenomai domain, that were registered form Linux domain. 
>   But not sure if possible. 

Also worth the check, though it comes with the risk of making the core
too much depend upon the Linux structures.

> 
> I am not quite sure, at what time I will have time to work on this again. Will have to talk to my supervisor. 
> 
> But would be happy if we would find a clean way of integrating this into Xenomai.

Yes, specifically as we now have the underlying Dovetail support. I
tested it with out current out-of-tree pattern, and it works as expected.

Jan

-- 
Siemens AG, Technology
Competence Center Embedded Linux


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

* RE: [PATCH 1/3] rtsignals: part one, core code plus x86
  2023-01-20 11:41           ` Jan Kiszka
@ 2023-04-19  9:18             ` Johannes Kirchmair
  2023-04-19 12:39               ` Jan Kiszka
  2023-04-20  8:12               ` [PATCH 1/3] rtsignals: part one, core code plus x86 Schaffner, Tobias
  0 siblings, 2 replies; 20+ messages in thread
From: Johannes Kirchmair @ 2023-04-19  9:18 UTC (permalink / raw)
  To: Jan Kiszka; +Cc: xenomai

Hey Jan, 

Richard told me that there was the topic of rt-signals in the community call today. 
He said that you asked if there are newer version of the rt-signal patches finally.

After the last call I attended, I did some work moving the signal frame setup and restoring into the dovetail part. As you said that this is the way if we want to use some of the Linux functions.

Unfortunately I had to stop working on it due to another topping popping up. 

I just look into the stuff I changed and it seems like it should work the way it is now.
But I will have to test it again (because I don’t remember, if it really worked after my changes).

After that I could provide patches for Dovetail and Xenomai. With this we could start discussing if I use to much of Linux code for real time. I am not really sure what is viable to do in oob stage and what is not. So I will depend on the experience of you and other experts.
And we should also speak about the interfaces and the functionality we really want to provide for rt task.

Sorry for the rather slow process of this features development.

FYI: I will be at EOSS in June and would be glad if we could meet up there.

Best regards
Johannes

> -----Original Message-----
> From: Jan Kiszka <jan.kiszka@siemens.com>
> Sent: Freitag, 20. Jänner 2023 12:42
> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
> xenomai@lists.linux.dev
> Subject: Re: [PATCH 1/3] rtsignals: part one, core code plus x86
> 
> CAUTION: External E-Mail !
> 
> On 20.01.23 12:01, Johannes Kirchmair wrote:
> > Hey Jan,
> >
> > Sorry for not responding for so long.
> > Got dragged away from this unfortunatly.
> >
> >
> >> -----Original Message-----
> >> From: Jan Kiszka <jan.kiszka@siemens.com>
> >> Sent: Freitag, 20. Jänner 2023 10:05
> >> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
> >> xenomai@lists.linux.dev
> >> Subject: Re: [PATCH 1/3] rtsignals: part one, core code plus x86
> >>
> >> CAUTION: External E-Mail !
> >>
> >> On 08.07.22 09:30, Johannes Kirchmair wrote:
> >>> Hey Jan,
> >>>
> >>>> -----Original Message-----
> >>>> From: Jan Kiszka <jan.kiszka@siemens.com>
> >>>> Sent: Donnerstag, 7. Juli 2022 17:24
> >>>> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
> >>>> xenomai@lists.linux.dev
> >>>> Subject: Re: [PATCH 1/3] rtsignals: part one, core code plus x86
> >>>>
> >>>> On 07.07.22 15:59, Johannes Kirchmair wrote:
> >>>>> From: Richard Weinberger <richard@nod.at>
> >>>>>
> >>>>> Adds code for implementing signals that are handled in the real time
> >>>>> domain. This is done for 32bit process under an 64bit kernel.
> >>>>> It works in a similar way to signals in the Linux kernel.
> >>>>>
> >>>>> Edited-by: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
> >>>>
> >>>> ...
> >>>>
> >>>>> +static int ia32_setup_sigcontext(struct sigcontext_32 __user *sc,
> >>>>> +                            void __user *fpstate, struct pt_regs *regs,
> >>>>> +                            unsigned int mask)
> >>>>> +{
> >>>>> +   int err = 0;
> >>>>> +
> >>>>> +   put_user_try
> >>>>> +   {
> >>>>> +           put_user_ex(get_user_seg(gs), (unsigned int __user *)&sc->gs);
> >>>>> +           put_user_ex(get_user_seg(fs), (unsigned int __user *)&sc->fs);
> >>>>> +           put_user_ex(get_user_seg(ds), (unsigned int __user *)&sc->ds);
> >>>>> +           put_user_ex(get_user_seg(es), (unsigned int __user *)&sc->es);
> >>>>> +
> >>>>> +           put_user_ex(regs->di, &sc->di);
> >>>>> +           put_user_ex(regs->si, &sc->si);
> >>>>> +           put_user_ex(regs->bp, &sc->bp);
> >>>>> +           put_user_ex(regs->sp, &sc->sp);
> >>>>> +           put_user_ex(regs->bx, &sc->bx);
> >>>>> +           put_user_ex(regs->dx, &sc->dx);
> >>>>> +           put_user_ex(regs->cx, &sc->cx);
> >>>>> +           put_user_ex(regs->ax, &sc->ax);
> >>>>> +           put_user_ex(current->thread.trap_nr, &sc->trapno);
> >>>>> +           put_user_ex(current->thread.error_code, &sc->err);
> >>>>> +           put_user_ex(regs->ip, &sc->ip);
> >>>>> +           put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
> >>>>> +           put_user_ex(regs->flags, &sc->flags);
> >>>>> +           put_user_ex(regs->sp, &sc->sp_at_signal);
> >>>>> +           put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
> >>>>> +
> >>>>> +           put_user_ex(ptr_to_compat(fpstate), &sc->fpstate);
> >>>>> +
> >>>>> +           /* non-iBCS2 extensions.. */
> >>>>> +           put_user_ex(mask, &sc->oldmask);
> >>>>> +           put_user_ex(current->thread.cr2, &sc->cr2);
> >>>>> +   }
> >>>>> +   put_user_catch(err);
> >>>>
> >>>> Am I missing something - or did you miss to add the magic for this
> >>>> get/put_user_try/catch?
> >>> Tried to figure it out this morning, but don’t understand it fully jet. Actually
> >> don’t quite get, how the errors of put_user_ex are propagated into the err
> >> variable. Probably in this case put_user_try, put_user_catch is only for
> disabling
> >> SMAP. But I will have a deeper look at it in the beginning of August after my
> >> vacation.
> >>>
> >>
> >> Was there a follow-up on this? I'm planning to revive this finally,
> >> figuring out if there are pitfalls in going the sigaction/sigreturn path
> >> for Xenomai.
> > For the question of the try/catch
> > We don’t have really a catch clause here, as we check access to the sigframe
> beforehand and we only use the put_user_try to disable SMAP to be able to
> copy to the user stack.
> >
> >>
> >> BTW, I do not understand why you made the restorer function a direct
> >> parameter of the sigaction syscall. It comes from the sigaction
> >> structure. And your implementation cannot provide oact when we want to
> >> add sigaction as library call as well.
> > Oact?
> 
> Previous (old) action handler, see man sigaction.
> 
> >
> > Actually I am not quite sure, but I guess the reason was to have a rather simple
> distinct syscall to Linux sigaction syscall.
> > We do not even pass a sigaction structure to the cobalt core, but just a handler
> and the restorer.
> 
> Enough for signal(), not for sigaction(). But it would be a valid
> question if we really want/have to support all features of sigaction.
> 
> >
> > There are some things I thought about, but did not find the time to investigate:
> >
> > - I copied and modified some of the signal code from Linux and removed
> everything I did not need for my purpose.
> >   Maybe it would be possible to use the Linux functions without modifying.
> (Primarily the sigframe setup and restore code)
> >   I think it would be cleaner to not have too much copied code.
> 
> Ack, to-be-checked.
> 
> >
> > - I always wondered what would happen if we have a domain switch in a signal
> handler.
> >   I still have not a deep enough knowledge of Xenomai. If we switch from
> Xenomai to Linux domain.
> >   The restorer code would make an cobald syscall ending up in the cobald
> restorer, but not quite sure about it.
> 
> I don't think this should cause troubles. Cobalt's sigreturn would
> simply enforce a switch-back to RT (if that is needed, didn't check) and
> would restore userspace state from the saved state on the thread's stack.
> 
> What should be considered as well is an async signal handling in the
> middle of the RT handler - whether already migrated or only migrated
> upon that. As all userspace-related state is on the userspace stack,
> nesting should work, but it all becomes quickly rather complicated.
> 
> >
> > - Thought about, if we could use the sighandler stored in Linuxes task struct.
> >   So we could handle signals in Xenomai domain, that were registered form
> Linux domain.
> >   But not sure if possible.
> 
> Also worth the check, though it comes with the risk of making the core
> too much depend upon the Linux structures.
> 
> >
> > I am not quite sure, at what time I will have time to work on this again. Will have
> to talk to my supervisor.
> >
> > But would be happy if we would find a clean way of integrating this into
> Xenomai.
> 
> Yes, specifically as we now have the underlying Dovetail support. I
> tested it with out current out-of-tree pattern, and it works as expected.
> 
> Jan
> 
> --
> Siemens AG, Technology
> Competence Center Embedded Linux


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

* Re: [PATCH 1/3] rtsignals: part one, core code plus x86
  2023-04-19  9:18             ` Johannes Kirchmair
@ 2023-04-19 12:39               ` Jan Kiszka
  2023-04-20  8:03                 ` [PATCH] testsuite: Add exception handling tests to smokey T. Schaffner
  2023-04-20  8:12               ` [PATCH 1/3] rtsignals: part one, core code plus x86 Schaffner, Tobias
  1 sibling, 1 reply; 20+ messages in thread
From: Jan Kiszka @ 2023-04-19 12:39 UTC (permalink / raw)
  To: Johannes Kirchmair; +Cc: xenomai, Schaffner, Tobias (T CED SES-DE)

On 19.04.23 11:18, Johannes Kirchmair wrote:
> Hey Jan, 
> 
> Richard told me that there was the topic of rt-signals in the community call today. 
> He said that you asked if there are newer version of the rt-signal patches finally.
> 
> After the last call I attended, I did some work moving the signal frame setup and restoring into the dovetail part. As you said that this is the way if we want to use some of the Linux functions.
> 
> Unfortunately I had to stop working on it due to another topping popping up. 
> 
> I just look into the stuff I changed and it seems like it should work the way it is now.
> But I will have to test it again (because I don’t remember, if it really worked after my changes).
> 
> After that I could provide patches for Dovetail and Xenomai. With this we could start discussing if I use to much of Linux code for real time. I am not really sure what is viable to do in oob stage and what is not. So I will depend on the experience of you and other experts.

Right, we definitely need everyone on the table to for that, including
Philippe.

> And we should also speak about the interfaces and the functionality we really want to provide for rt task.

Agreed. That's one reason Tobias wrote a smokey test case which he will
share with us soon.

> 
> Sorry for the rather slow process of this features development.

No problem, I know this situation very well.

> 
> FYI: I will be at EOSS in June and would be glad if we could meet up there.

Great, then we are at least 3: Maybe also follow-up on
https://lore.kernel.org/xenomai/CAFLxGvwrKVG8aBhrv5-VwfiQeCcgfGswXDnC=3FawvQMd58c6w@mail.gmail.com/T/#t

Jan

-- 
Siemens AG, Technology
Competence Center Embedded Linux


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

* [PATCH] testsuite: Add exception handling tests to smokey
  2023-04-19 12:39               ` Jan Kiszka
@ 2023-04-20  8:03                 ` T. Schaffner
  0 siblings, 0 replies; 20+ messages in thread
From: T. Schaffner @ 2023-04-20  8:03 UTC (permalink / raw)
  To: xenomai; +Cc: jan.kiszka, johannes.kirchmair, richard, Tobias Schaffner

From: Tobias Schaffner <tobias.schaffner@siemens.com>

Add a testsuite that ensures that different exceptions lead to the
designated signal described in the signal posix standard [1].

Introduces tests for floating point exceptions, illegal opcode
exceptions and segmentation faults.

If setup correctly the generated signals should not lead to a migration
but should be handled by the configured handler.

Further test if signals raised while already in the signal handler are
handled correctly with and without SA_NODEFER set.

Add an additional Makefile.standalone Makefile that allows to build
without the Xenomai kernel for reference. If build without Xenomai all
tests should pass.

[1] https://pubs.opengroup.org/onlinepubs/009695399/

Signed-off-by: Tobias Schaffner <tobias.schaffner@siemens.com>
---
 configure.ac                                  |   1 +
 testsuite/smokey/Makefile.am                  |   2 +
 testsuite/smokey/signal-tests/Makefile.am     |  15 ++
 .../smokey/signal-tests/Makefile.standalone   |  16 ++
 testsuite/smokey/signal-tests/main.c          |  51 ++++
 testsuite/smokey/signal-tests/signal_test.c   | 243 ++++++++++++++++++
 testsuite/smokey/signal-tests/signal_test.h   |  93 +++++++
 .../signal-tests/signal_test_exceptions.c     |  84 ++++++
 .../signal-tests/signal_test_exceptions.h     |  51 ++++
 .../smokey/signal-tests/signal_test_thread.c  |  61 +++++
 .../smokey/signal-tests/signal_test_thread.h  |  37 +++
 .../smokey/signal-tests/signal_test_utils.c   |  80 ++++++
 .../smokey/signal-tests/signal_test_utils.h   |  44 ++++
 13 files changed, 778 insertions(+)
 create mode 100644 testsuite/smokey/signal-tests/Makefile.am
 create mode 100644 testsuite/smokey/signal-tests/Makefile.standalone
 create mode 100644 testsuite/smokey/signal-tests/main.c
 create mode 100644 testsuite/smokey/signal-tests/signal_test.c
 create mode 100644 testsuite/smokey/signal-tests/signal_test.h
 create mode 100644 testsuite/smokey/signal-tests/signal_test_exceptions.c
 create mode 100644 testsuite/smokey/signal-tests/signal_test_exceptions.h
 create mode 100644 testsuite/smokey/signal-tests/signal_test_thread.c
 create mode 100644 testsuite/smokey/signal-tests/signal_test_thread.h
 create mode 100644 testsuite/smokey/signal-tests/signal_test_utils.c
 create mode 100644 testsuite/smokey/signal-tests/signal_test_utils.h

diff --git a/configure.ac b/configure.ac
index db92ddcc6..0e0bd0f44 100644
--- a/configure.ac
+++ b/configure.ac
@@ -978,6 +978,7 @@ AC_CONFIG_FILES([ \
 	testsuite/smokey/iddp/Makefile \
 	testsuite/smokey/bufp/Makefile \
 	testsuite/smokey/sigdebug/Makefile \
+	testsuite/smokey/signal-tests/Makefile \
 	testsuite/smokey/timerfd/Makefile \
 	testsuite/smokey/tsc/Makefile \
 	testsuite/smokey/leaks/Makefile \
diff --git a/testsuite/smokey/Makefile.am b/testsuite/smokey/Makefile.am
index 02613c7dc..877b16702 100644
--- a/testsuite/smokey/Makefile.am
+++ b/testsuite/smokey/Makefile.am
@@ -35,6 +35,7 @@ COBALT_SUBDIRS = 	\
 	sched-tp 	\
 	setsched	\
 	sigdebug	\
+	signal-tests    \
 	timerfd		\
 	tsc		\
 	vdso-access 	\
@@ -73,6 +74,7 @@ DIST_SUBDIRS = 		\
 	sched-tp 	\
 	setsched	\
 	sigdebug	\
+	signal-tests    \
 	timerfd		\
 	tsc		\
 	vdso-access 	\
diff --git a/testsuite/smokey/signal-tests/Makefile.am b/testsuite/smokey/signal-tests/Makefile.am
new file mode 100644
index 000000000..728a90744
--- /dev/null
+++ b/testsuite/smokey/signal-tests/Makefile.am
@@ -0,0 +1,15 @@
+noinst_LIBRARIES = libsignal-tests.a
+
+libsignal_tests_a_SOURCES = main.c \
+                       signal_test.c \
+                       signal_test.h \
+                       signal_test_exceptions.c \
+                       signal_test_exceptions.h \
+                       signal_test_thread.c \
+                       signal_test_thread.h \
+                       signal_test_utils.c \
+                       signal_test_utils.h
+
+libsignal_tests_a_CPPFLAGS = @XENO_USER_CFLAGS@ -I$(top_srcdir)/include -DXENOMAI
+
+CCLD = $(top_srcdir)/scripts/wrap-link.sh $(CC)
diff --git a/testsuite/smokey/signal-tests/Makefile.standalone b/testsuite/smokey/signal-tests/Makefile.standalone
new file mode 100644
index 000000000..15f7c79f3
--- /dev/null
+++ b/testsuite/smokey/signal-tests/Makefile.standalone
@@ -0,0 +1,16 @@
+# Use this Makefile to build without XENOMAI
+
+CC      = gcc
+CFLAGS  = -g -pthread
+RM      = rm -f
+
+default: all
+
+all: clean signal_test
+
+signal_test: *.c
+	$(CC) $(CFLAGS) -o signal_test *.c
+
+clean veryclean:
+	$(RM) signal_test
+
diff --git a/testsuite/smokey/signal-tests/main.c b/testsuite/smokey/signal-tests/main.c
new file mode 100644
index 000000000..cf3bbb39a
--- /dev/null
+++ b/testsuite/smokey/signal-tests/main.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Siemens AG 2023
+ *
+ * Authors:
+ *  Tobias Schaffner <tobias.schaffner@siemens.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "signal_test_utils.h"
+#include "signal_test.h"
+
+#ifdef XENOMAI
+
+#include <smokey/smokey.h>
+
+smokey_test_plugin(signal_tests, SMOKEY_NOARGS,
+		   "Test for signals on exceptions.");
+
+static int run_signal_tests(struct smokey_test *t, int argc, char *const argv[])
+#else
+int main(void)
+#endif
+{
+	TEST(test_exceptions_fpe());
+	TEST(test_exceptions_invalid_opcode());
+	TEST(test_exceptions_segfault());
+
+	TEST(test_exceptions_nesting_fpe());
+	TEST(test_exceptions_nesting_invalid_opcode());
+	TEST(test_exceptions_nesting_segfault());
+
+	TEST(test_exceptions_queuing_fpe());
+	TEST(test_exceptions_queuing_invalid_opcode());
+	TEST(test_exceptions_queuing_segfault());
+
+	return signal_test_testsuite_exit();
+}
diff --git a/testsuite/smokey/signal-tests/signal_test.c b/testsuite/smokey/signal-tests/signal_test.c
new file mode 100644
index 000000000..eaefce485
--- /dev/null
+++ b/testsuite/smokey/signal-tests/signal_test.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) Siemens AG 2023
+ *
+ * Authors:
+ *  Tobias Schaffner <tobias.schaffner@siemens.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <pthread.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "signal_test.h"
+#include "signal_test_exceptions.h"
+#include "signal_test_thread.h"
+#include "signal_test_utils.h"
+
+static int depth, handler_calls = 0;
+static bool wrong_thread, wrong_signal, migration, nested, do_reraise = false;
+static void (*exception_raise_func)(void);
+
+static void test_signal_handler(int sig, siginfo_t *info, void *context)
+{
+	if (thread_id != pthread_self())
+		wrong_thread = true;
+
+#ifdef XENOMAI
+	if (sig == SIGDEBUG) {
+		migration = true;
+		return;
+	}
+#endif
+
+	if (sig != signal_test_exceptions_get_expected_signal()) {
+		wrong_signal = true;
+		return;
+	}
+
+	handler_calls++;
+
+	if (do_reraise) {
+		if (depth++)
+			nested = true;
+
+		if (handler_calls < 3) {
+			(*exception_raise_func)();
+		}
+
+		depth--;
+	}
+
+	signal_test_exceptions_recover(context);
+}
+
+static int run_exception_test(int sa_flags, int signal, bool reraise,
+			      int expected_handler_calls)
+{
+	struct sigaction sigact = { 0 };
+	sigact.sa_sigaction = test_signal_handler;
+	sigact.sa_flags = sa_flags;
+
+	depth = 0;
+	do_reraise = reraise;
+	handler_calls = 0;
+	migration = false;
+	nested = false;
+	wrong_thread = false;
+	wrong_signal = false;
+
+#ifdef XENOMAI
+	ASSERT(sigaction(SIGDEBUG, &sigact, NULL), 0);
+	ASSERT(cobalt_rt_signal(signal, test_signal_handler), 0);
+#else
+	ASSERT(sigaction(signal, &sigact, NULL), 0);
+#endif
+
+	ASSERT(signal_test_thread_start((void *)exception_raise_func), 0);
+	ASSERT(pthread_join(thread_id, NULL), 0);
+
+	ASSERT(!reraise || nested, true);
+	ASSERT(depth, 0);
+	ASSERT(handler_calls, expected_handler_calls);
+	ASSERT(migration, false);
+	ASSERT(wrong_signal, false);
+	ASSERT(wrong_thread, false);
+
+	return 0;
+}
+
+static void reset_signals(void)
+{
+	struct sigaction sigAct;
+	sigAct.sa_handler = SIG_DFL;
+	sigaction(SIGSEGV, &sigAct, NULL);
+	sigaction(SIGFPE, &sigAct, NULL);
+	sigaction(SIGILL, &sigAct, NULL);
+#ifdef XENOMAI
+	sigaction(SIGDEBUG, &sigAct, NULL);
+	cobalt_rt_signal(SIGSEGV, (void (*)(int, siginfo_t *, void *))SIG_DFL);
+	cobalt_rt_signal(SIGFPE, (void (*)(int, siginfo_t *, void *))SIG_DFL);
+	cobalt_rt_signal(SIGILL, (void (*)(int, siginfo_t *, void *))SIG_DFL);
+#endif
+}
+
+static void setup(void)
+{
+	reset_signals();
+}
+
+static void teardown(void)
+{
+	reset_signals();
+}
+
+static int fork_exception_test(int *status, int sa_flags, int signal,
+			       bool reraise, int expected_handler_calls)
+{
+	setup();
+
+	pid_t child_pid = fork();
+
+	if (child_pid < 0) {
+		fprintf(stderr, "fork failed in %s:%d", __FILE__, __LINE__);
+		return 1;
+	} else if (child_pid == 0) {
+		exit(run_exception_test(sa_flags, signal, reraise,
+					expected_handler_calls));
+	} else {
+		waitpid(child_pid, status, 0);
+	}
+
+	teardown();
+
+	return 0;
+}
+
+static int test_exceptions(void (*exception)(void), int signal)
+{
+	int status;
+	exception_raise_func = exception;
+
+	fork_exception_test(&status, SA_SIGINFO, signal, false, 1);
+
+	ASSERT(WIFSIGNALED(status), false);
+	ASSERT(WIFEXITED(status), true);
+	return WEXITSTATUS(status);
+}
+
+int test_exceptions_segfault()
+{
+	return test_exceptions(&signal_test_exceptions_raise_segfault, SIGSEGV);
+}
+
+int test_exceptions_fpe()
+{
+	return test_exceptions(&signal_test_exceptions_raise_fpe, SIGFPE);
+}
+
+int test_exceptions_invalid_opcode()
+{
+	return test_exceptions(&signal_test_exceptions_raise_invalid_opcode,
+			       SIGILL);
+}
+
+static int test_exceptions_queuing(void (*exception)(void), int signal)
+{
+	int status;
+	exception_raise_func = exception;
+
+	fork_exception_test(&status, SA_SIGINFO, signal, true, 3);
+
+	ASSERT(WIFSIGNALED(status), true);
+	ASSERT(WTERMSIG(status), signal);
+
+	return 0;
+}
+
+int test_exceptions_queuing_segfault()
+{
+	return test_exceptions_queuing(&signal_test_exceptions_raise_segfault,
+				       SIGSEGV);
+}
+
+int test_exceptions_queuing_fpe()
+{
+	return test_exceptions_queuing(&signal_test_exceptions_raise_fpe,
+				       SIGFPE);
+}
+
+int test_exceptions_queuing_invalid_opcode()
+{
+	return test_exceptions_queuing(
+		&signal_test_exceptions_raise_invalid_opcode, SIGILL);
+}
+
+static int test_exceptions_nesting(void (*exception)(void), int signal)
+{
+	int status;
+	exception_raise_func = exception;
+
+	fork_exception_test(&status, SA_SIGINFO | SA_NODEFER, signal, true, 3);
+
+	ASSERT(WIFSIGNALED(status), false);
+	ASSERT(WIFEXITED(status), true);
+	return WEXITSTATUS(status);
+}
+
+int test_exceptions_nesting_segfault()
+{
+	return test_exceptions_nesting(&signal_test_exceptions_raise_segfault,
+				       SIGSEGV);
+}
+
+int test_exceptions_nesting_fpe()
+{
+	return test_exceptions_nesting(&signal_test_exceptions_raise_fpe,
+				       SIGFPE);
+}
+
+int test_exceptions_nesting_invalid_opcode()
+{
+	return test_exceptions_nesting(
+		&signal_test_exceptions_raise_invalid_opcode, SIGILL);
+}
+
diff --git a/testsuite/smokey/signal-tests/signal_test.h b/testsuite/smokey/signal-tests/signal_test.h
new file mode 100644
index 000000000..51e945ed2
--- /dev/null
+++ b/testsuite/smokey/signal-tests/signal_test.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) Siemens AG 2023
+ *
+ * Authors:
+ *  Tobias Schaffner <tobias.schaffner@siemens.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @brief Test if a segfault leads to a SIGSEGV signal.
+ * 
+ * @return int 0 if the test was successfull
+ */
+int test_exceptions_segfault(void);
+
+/**
+ * @brief Test if a floating point exception leads to a SIGFPE signal.
+ * 
+ * @return int 0 if the test was successfull
+ */
+int test_exceptions_fpe(void);
+
+/**
+ * @brief Test if an invalid opcode exceptions leads to a SIGILL signal.
+ * 
+ * @return int 0 if the test was successfull
+ */
+int test_exceptions_invalid_opcode(void);
+
+/**
+ * @brief Raise a second segfault while in the signal handler. Test if the
+ * second exception leads to process termination even if a signal handler is
+ * set.
+ * 
+ * @return int 0 if the test was successfull
+ */
+int test_exceptions_queuing_segfault(void);
+
+/**
+ * @brief Raise a second fpe exception while in the signal handler. Test if the
+ * second exception leads to process termination even if a signal handler is
+ * set.
+ * 
+ * @return int 0 if the test was successfull
+ */
+int test_exceptions_queuing_fpe(void);
+
+/**
+ * @brief Raise a second invalid opcode exception while in the signal handler.
+ * Test if the second exception leads to process termination even if a signal
+ * handler is set.
+ * 
+ * @return int 0 if the test was successfull
+ */
+int test_exceptions_queuing_invalid_opcode(void);
+
+/**
+ * @brief Test that that a second sefault raised while in the signal handler
+ * will be processed nested if SA_NODEFER is set.
+ * 
+ * @return int 0 if the test was successfull
+ */
+int test_exceptions_nesting_segfault(void);
+
+/**
+ * @brief Test that that a second fpe raised while in the signal handler will
+ * be processed nested if SA_NODEFER is set.
+ * 
+ * @return int 0 if the test was successfull
+ */
+int test_exceptions_nesting_fpe(void);
+
+/**
+ * @brief Test that that a second invalid opcode exception raised while in the
+ * signal handler will be processed nested if SA_NODEFER is set.
+ * 
+ * @return int 0 if the test was successfull
+ */
+int test_exceptions_nesting_invalid_opcode(void);
diff --git a/testsuite/smokey/signal-tests/signal_test_exceptions.c b/testsuite/smokey/signal-tests/signal_test_exceptions.c
new file mode 100644
index 000000000..fa74dfb46
--- /dev/null
+++ b/testsuite/smokey/signal-tests/signal_test_exceptions.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) Siemens AG 2023
+ *
+ * Authors:
+ *  Tobias Schaffner <tobias.schaffner@siemens.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <signal.h>
+
+#include "signal_test_exceptions.h"
+#include "signal_test_utils.h"
+
+static int expected_signal;
+static long unsigned int return_address;
+
+int signal_test_exceptions_get_expected_signal(void)
+{
+	return expected_signal;
+}
+
+void signal_test_exceptions_recover(struct ucontext *context)
+{
+	context->uc_mcontext.rip = return_address;
+}
+
+void signal_test_exceptions_raise_segfault(void)
+{
+	expected_signal = SIGSEGV;
+
+	__asm__("leaq .label%=(%%rip),%%r15;" // Store unique label address in r15
+		"movq %%r15,%0;"
+
+		"movl $0xDECAFBAD, 0x0;" // Raise SEGFAULT
+
+		".label%=:;" // Unique Label
+
+		: "=g"(return_address)::"memory", "r15");
+}
+
+void signal_test_exceptions_raise_fpe(void)
+{
+	expected_signal = SIGFPE;
+
+	__asm__("leaq .label%=(%%rip),%%r15;" // Store unique label address in r15
+		"movq %%r15,%0;"
+
+		"xorl %%eax, %%eax;" // Start raise FPE
+		"movl %%eax, %%ecx;"
+		"cltd;"
+		"idivl %%ecx;" // End raise FPE
+
+		".label%=:;" // Unique Label
+
+		: "=g"(return_address)::"memory", "eax", "ecx", "r15");
+}
+
+void signal_test_exceptions_raise_invalid_opcode(void)
+{
+	expected_signal = SIGILL;
+
+	__asm__("leaq .label%=(%%rip),%%r15;" // Store unique label address in r15
+		"movq %%r15,%0;"
+
+		"ud2;" // Raise invalid opcode
+
+		".label%=:;" // Unique Label
+
+		: "=g"(return_address)::"memory", "r15");
+}
diff --git a/testsuite/smokey/signal-tests/signal_test_exceptions.h b/testsuite/smokey/signal-tests/signal_test_exceptions.h
new file mode 100644
index 000000000..62652f1ea
--- /dev/null
+++ b/testsuite/smokey/signal-tests/signal_test_exceptions.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Siemens AG 2023
+ *
+ * Authors:
+ *  Tobias Schaffner <tobias.schaffner@siemens.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SIGNAL_TEST_EXCEPTIONS_H
+#define SIGNAL_TEST_EXCEPTIONS_H
+
+#include <asm/ucontext.h>
+
+/**
+ * @brief Raise a segfault.
+ */
+void signal_test_exceptions_raise_segfault(void);
+
+/**
+ * @brief Raise a floating point exception.
+ */
+void signal_test_exceptions_raise_fpe(void);
+
+/**
+ * @brief Raise an invalid opcode exception.
+ */
+void signal_test_exceptions_raise_invalid_opcode(void);
+
+/**
+ * @brief Recover from a exception by jumping to a label
+ * after the exception.
+ */
+void signal_test_exceptions_recover(struct ucontext *);
+
+int signal_test_exceptions_get_expected_signal(void);
+
+#endif
diff --git a/testsuite/smokey/signal-tests/signal_test_thread.c b/testsuite/smokey/signal-tests/signal_test_thread.c
new file mode 100644
index 000000000..95a0963e7
--- /dev/null
+++ b/testsuite/smokey/signal-tests/signal_test_thread.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) Siemens AG 2023
+ *
+ * Authors:
+ *  Tobias Schaffner <tobias.schaffner@siemens.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "signal_test_thread.h"
+#include "signal_test_utils.h"
+
+pthread_t thread_id;
+
+static pthread_attr_t attr;
+static struct sched_param sp;
+
+static void (*signal_test_thread_function)(void);
+
+static void signal_test_thread_run(void)
+{
+	thread_id = pthread_self();
+
+#ifdef XENOMAI
+	pthread_setmode_np(0, PTHREAD_WARNSW, NULL);
+#endif
+
+	(*signal_test_thread_function)();
+}
+
+int signal_test_thread_start(void *thread_function)
+{
+	signal_test_thread_function = thread_function;
+
+	ASSERT(pthread_attr_init(&attr), 0);
+
+#ifdef XENOMAI
+	sp.sched_priority = 1;
+	ASSERT(pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED), 0);
+	ASSERT(pthread_attr_setschedpolicy(&attr, SCHED_FIFO), 0);
+	ASSERT(pthread_attr_setschedparam(&attr, &sp), 0);
+#endif
+
+	ASSERT(pthread_create(&thread_id, &attr, (void *)signal_test_thread_run,
+			      NULL),
+	       0);
+	return 0;
+}
diff --git a/testsuite/smokey/signal-tests/signal_test_thread.h b/testsuite/smokey/signal-tests/signal_test_thread.h
new file mode 100644
index 000000000..5c42d2659
--- /dev/null
+++ b/testsuite/smokey/signal-tests/signal_test_thread.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) Siemens AG 2023
+ *
+ * Authors:
+ *  Tobias Schaffner <tobias.schaffner@siemens.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SIGNAL_TEST_THREAD_H
+#define SIGNAL_TEST_THREAD_H
+
+#include <pthread.h>
+
+extern pthread_t thread_id;
+
+/**
+ * @brief Start a thread that runs the given function.
+ * 
+ * @return int 0 if the test was successfull and 1 on failure.
+ */
+int signal_test_thread_start(void *);
+
+#endif
diff --git a/testsuite/smokey/signal-tests/signal_test_utils.c b/testsuite/smokey/signal-tests/signal_test_utils.c
new file mode 100644
index 000000000..117d32e8a
--- /dev/null
+++ b/testsuite/smokey/signal-tests/signal_test_utils.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) Siemens AG 2023
+ *
+ * Authors:
+ *  Tobias Schaffner <tobias.schaffner@siemens.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "signal_test_utils.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef XENOMAI
+#include <smokey/smokey.h>
+#else
+static int smokey_verbose_mode = 2;
+#endif
+
+static int testsuite_result = 0;
+
+int signal_test_assert(char *file, int line, int under_test, int expected)
+{
+	if (under_test == expected)
+		return 0;
+
+	fprintf(stderr,
+		"\n\x1B[31mAssertion error in %s:%d: expected \"%d\" but was \"%d\".\x1B[0m",
+		file, line, expected, under_test);
+
+	return 1;
+}
+
+void signal_test_entry(char *function_name)
+{
+	if (smokey_verbose_mode > 1) {
+		fprintf(stdout, "Test %s... ", function_name);
+		fflush(stdout);
+	}
+}
+
+void signal_test_exit(char *function_name, int error_code)
+{
+	if (error_code) {
+		fprintf(stderr,
+			"\n\x1B[31mTest %s failed with error: %d\x1B[0m\n",
+			function_name, error_code);
+		testsuite_result = 1;
+	} else {
+		if (smokey_verbose_mode > 1)
+			fprintf(stdout, "OK\n");
+	}
+}
+
+int signal_test_testsuite_exit(void)
+{
+	if (testsuite_result) {
+		fprintf(stdout,
+			"\nsignal_tests failed with error: %d\n",
+			testsuite_result);
+	} else {
+		fprintf(stdout, "signal_tests OK\n");
+	}
+
+	return testsuite_result;
+}
diff --git a/testsuite/smokey/signal-tests/signal_test_utils.h b/testsuite/smokey/signal-tests/signal_test_utils.h
new file mode 100644
index 000000000..ceaa21c35
--- /dev/null
+++ b/testsuite/smokey/signal-tests/signal_test_utils.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) Siemens AG 2023
+ *
+ * Authors:
+ *  Tobias Schaffner <tobias.schaffner@siemens.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef SIGNAL_TEST_UTILS_H
+#define SIGNAL_TEST_UTILS_H
+
+#define NAME(name) #name
+
+#define ASSERT(under_test, expected)                                           \
+	if (signal_test_assert(__FILE__, __LINE__, under_test, expected))      \
+		return 1;
+
+#define TEST(func)                                                             \
+	do {                                                                   \
+		signal_test_entry(NAME(func));                                 \
+		signal_test_exit(NAME(func), func);                            \
+	} while (0)
+
+int signal_test_assert(char *, int, int, int);
+void signal_test_entry(char *);
+void signal_test_exit(char *, int);
+
+int signal_test_testsuite_exit(void);
+
+#endif
-- 
2.34.1


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

* Re: [PATCH 1/3] rtsignals: part one, core code plus x86
  2023-04-19  9:18             ` Johannes Kirchmair
  2023-04-19 12:39               ` Jan Kiszka
@ 2023-04-20  8:12               ` Schaffner, Tobias
  2023-04-21 15:17                 ` Johannes Kirchmair
  1 sibling, 1 reply; 20+ messages in thread
From: Schaffner, Tobias @ 2023-04-20  8:12 UTC (permalink / raw)
  To: Johannes Kirchmair, Kiszka, Jan; +Cc: xenomai

On 19.04.23 11:18, Johannes Kirchmair wrote:
> Hey Jan,
> 
> Richard told me that there was the topic of rt-signals in the community call today.
> He said that you asked if there are newer version of the rt-signal patches finally.
> 
> After the last call I attended, I did some work moving the signal frame setup and restoring into the dovetail part. As you said that this is the way if we want to use some of the Linux functions.
> 
> Unfortunately I had to stop working on it due to another topping popping up.
> 
> I just look into the stuff I changed and it seems like it should work the way it is now.
> But I will have to test it again (because I don’t remember, if it really worked after my changes).

Hi Johannes,

i just posted a smokey test to this thread that addresses some 
additional corner cases.

Feel free to use it to test your changes.
I will extend the tests to test arm64 soon.

Feel free to report if you have ideas for additional test cases.

> After that I could provide patches for Dovetail and Xenomai. With this we could start discussing if I use to much of Linux code for real time. I am not really sure what is viable to do in oob stage and what is not. So I will depend on the experience of you and other experts.
> And we should also speak about the interfaces and the functionality we really want to provide for rt task.
> 
> Sorry for the rather slow process of this features development.
> 
> FYI: I will be at EOSS in June and would be glad if we could meet up there.

I will most probably also be there. Looking forward to it.

All the best,
Tobias

> Best regards
> Johannes
> 
>> -----Original Message-----
>> From: Jan Kiszka <jan.kiszka@siemens.com>
>> Sent: Freitag, 20. Jänner 2023 12:42
>> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
>> xenomai@lists.linux.dev
>> Subject: Re: [PATCH 1/3] rtsignals: part one, core code plus x86
>>
>> CAUTION: External E-Mail !
>>
>> On 20.01.23 12:01, Johannes Kirchmair wrote:
>>> Hey Jan,
>>>
>>> Sorry for not responding for so long.
>>> Got dragged away from this unfortunatly.
>>>
>>>
>>>> -----Original Message-----
>>>> From: Jan Kiszka <jan.kiszka@siemens.com>
>>>> Sent: Freitag, 20. Jänner 2023 10:05
>>>> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
>>>> xenomai@lists.linux.dev
>>>> Subject: Re: [PATCH 1/3] rtsignals: part one, core code plus x86
>>>>
>>>> CAUTION: External E-Mail !
>>>>
>>>> On 08.07.22 09:30, Johannes Kirchmair wrote:
>>>>> Hey Jan,
>>>>>
>>>>>> -----Original Message-----
>>>>>> From: Jan Kiszka <jan.kiszka@siemens.com>
>>>>>> Sent: Donnerstag, 7. Juli 2022 17:24
>>>>>> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
>>>>>> xenomai@lists.linux.dev
>>>>>> Subject: Re: [PATCH 1/3] rtsignals: part one, core code plus x86
>>>>>>
>>>>>> On 07.07.22 15:59, Johannes Kirchmair wrote:
>>>>>>> From: Richard Weinberger <richard@nod.at>
>>>>>>>
>>>>>>> Adds code for implementing signals that are handled in the real time
>>>>>>> domain. This is done for 32bit process under an 64bit kernel.
>>>>>>> It works in a similar way to signals in the Linux kernel.
>>>>>>>
>>>>>>> Edited-by: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
>>>>>>
>>>>>> ...
>>>>>>
>>>>>>> +static int ia32_setup_sigcontext(struct sigcontext_32 __user *sc,
>>>>>>> +                            void __user *fpstate, struct pt_regs *regs,
>>>>>>> +                            unsigned int mask)
>>>>>>> +{
>>>>>>> +   int err = 0;
>>>>>>> +
>>>>>>> +   put_user_try
>>>>>>> +   {
>>>>>>> +           put_user_ex(get_user_seg(gs), (unsigned int __user *)&sc->gs);
>>>>>>> +           put_user_ex(get_user_seg(fs), (unsigned int __user *)&sc->fs);
>>>>>>> +           put_user_ex(get_user_seg(ds), (unsigned int __user *)&sc->ds);
>>>>>>> +           put_user_ex(get_user_seg(es), (unsigned int __user *)&sc->es);
>>>>>>> +
>>>>>>> +           put_user_ex(regs->di, &sc->di);
>>>>>>> +           put_user_ex(regs->si, &sc->si);
>>>>>>> +           put_user_ex(regs->bp, &sc->bp);
>>>>>>> +           put_user_ex(regs->sp, &sc->sp);
>>>>>>> +           put_user_ex(regs->bx, &sc->bx);
>>>>>>> +           put_user_ex(regs->dx, &sc->dx);
>>>>>>> +           put_user_ex(regs->cx, &sc->cx);
>>>>>>> +           put_user_ex(regs->ax, &sc->ax);
>>>>>>> +           put_user_ex(current->thread.trap_nr, &sc->trapno);
>>>>>>> +           put_user_ex(current->thread.error_code, &sc->err);
>>>>>>> +           put_user_ex(regs->ip, &sc->ip);
>>>>>>> +           put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
>>>>>>> +           put_user_ex(regs->flags, &sc->flags);
>>>>>>> +           put_user_ex(regs->sp, &sc->sp_at_signal);
>>>>>>> +           put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
>>>>>>> +
>>>>>>> +           put_user_ex(ptr_to_compat(fpstate), &sc->fpstate);
>>>>>>> +
>>>>>>> +           /* non-iBCS2 extensions.. */
>>>>>>> +           put_user_ex(mask, &sc->oldmask);
>>>>>>> +           put_user_ex(current->thread.cr2, &sc->cr2);
>>>>>>> +   }
>>>>>>> +   put_user_catch(err);
>>>>>>
>>>>>> Am I missing something - or did you miss to add the magic for this
>>>>>> get/put_user_try/catch?
>>>>> Tried to figure it out this morning, but don’t understand it fully jet. Actually
>>>> don’t quite get, how the errors of put_user_ex are propagated into the err
>>>> variable. Probably in this case put_user_try, put_user_catch is only for
>> disabling
>>>> SMAP. But I will have a deeper look at it in the beginning of August after my
>>>> vacation.
>>>>>
>>>>
>>>> Was there a follow-up on this? I'm planning to revive this finally,
>>>> figuring out if there are pitfalls in going the sigaction/sigreturn path
>>>> for Xenomai.
>>> For the question of the try/catch
>>> We don’t have really a catch clause here, as we check access to the sigframe
>> beforehand and we only use the put_user_try to disable SMAP to be able to
>> copy to the user stack.
>>>
>>>>
>>>> BTW, I do not understand why you made the restorer function a direct
>>>> parameter of the sigaction syscall. It comes from the sigaction
>>>> structure. And your implementation cannot provide oact when we want to
>>>> add sigaction as library call as well.
>>> Oact?
>>
>> Previous (old) action handler, see man sigaction.
>>
>>>
>>> Actually I am not quite sure, but I guess the reason was to have a rather simple
>> distinct syscall to Linux sigaction syscall.
>>> We do not even pass a sigaction structure to the cobalt core, but just a handler
>> and the restorer.
>>
>> Enough for signal(), not for sigaction(). But it would be a valid
>> question if we really want/have to support all features of sigaction.
>>
>>>
>>> There are some things I thought about, but did not find the time to investigate:
>>>
>>> - I copied and modified some of the signal code from Linux and removed
>> everything I did not need for my purpose.
>>>    Maybe it would be possible to use the Linux functions without modifying.
>> (Primarily the sigframe setup and restore code)
>>>    I think it would be cleaner to not have too much copied code.
>>
>> Ack, to-be-checked.
>>
>>>
>>> - I always wondered what would happen if we have a domain switch in a signal
>> handler.
>>>    I still have not a deep enough knowledge of Xenomai. If we switch from
>> Xenomai to Linux domain.
>>>    The restorer code would make an cobald syscall ending up in the cobald
>> restorer, but not quite sure about it.
>>
>> I don't think this should cause troubles. Cobalt's sigreturn would
>> simply enforce a switch-back to RT (if that is needed, didn't check) and
>> would restore userspace state from the saved state on the thread's stack.
>>
>> What should be considered as well is an async signal handling in the
>> middle of the RT handler - whether already migrated or only migrated
>> upon that. As all userspace-related state is on the userspace stack,
>> nesting should work, but it all becomes quickly rather complicated.
>>
>>>
>>> - Thought about, if we could use the sighandler stored in Linuxes task struct.
>>>    So we could handle signals in Xenomai domain, that were registered form
>> Linux domain.
>>>    But not sure if possible.
>>
>> Also worth the check, though it comes with the risk of making the core
>> too much depend upon the Linux structures.
>>
>>>
>>> I am not quite sure, at what time I will have time to work on this again. Will have
>> to talk to my supervisor.
>>>
>>> But would be happy if we would find a clean way of integrating this into
>> Xenomai.
>>
>> Yes, specifically as we now have the underlying Dovetail support. I
>> tested it with out current out-of-tree pattern, and it works as expected.
>>
>> Jan
>>
>> --
>> Siemens AG, Technology
>> Competence Center Embedded Linux
> 

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

* RE: [PATCH 1/3] rtsignals: part one, core code plus x86
  2023-04-20  8:12               ` [PATCH 1/3] rtsignals: part one, core code plus x86 Schaffner, Tobias
@ 2023-04-21 15:17                 ` Johannes Kirchmair
  2023-05-04 13:06                   ` Schaffner, Tobias
  0 siblings, 1 reply; 20+ messages in thread
From: Johannes Kirchmair @ 2023-04-21 15:17 UTC (permalink / raw)
  To: Schaffner, Tobias; +Cc: xenomai

Hey Tobias,

> -----Original Message-----
> From: Schaffner, Tobias <tobias.schaffner@siemens.com>
> Sent: Donnerstag, 20. April 2023 10:13
> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>; Kiszka, Jan
> <jan.kiszka@siemens.com>
> Cc: xenomai@lists.linux.dev
> Subject: Re: [PATCH 1/3] rtsignals: part one, core code plus x86
> 
> CAUTION: External E-Mail !
> 
> On 19.04.23 11:18, Johannes Kirchmair wrote:
> > Hey Jan,
> >
> > Richard told me that there was the topic of rt-signals in the community call
> today.
> > He said that you asked if there are newer version of the rt-signal patches finally.
> >
> > After the last call I attended, I did some work moving the signal frame setup
> and restoring into the dovetail part. As you said that this is the way if we want to
> use some of the Linux functions.
> >
> > Unfortunately I had to stop working on it due to another topping popping up.
> >
> > I just look into the stuff I changed and it seems like it should work the way it is
> now.
> > But I will have to test it again (because I don’t remember, if it really worked
> after my changes).
> 
> Hi Johannes,
> 
> i just posted a smokey test to this thread that addresses some
> additional corner cases.
> 
> Feel free to use it to test your changes.
> I will extend the tests to test arm64 soon.
> 
> Feel free to report if you have ideas for additional test cases.
Hope I find the time to have a look at this next week.
And thanks that you provide testcases for this stuff.

> 
> > After that I could provide patches for Dovetail and Xenomai. With this we could
> start discussing if I use to much of Linux code for real time. I am not really sure
> what is viable to do in oob stage and what is not. So I will depend on the
> experience of you and other experts.
> > And we should also speak about the interfaces and the functionality we really
> want to provide for rt task.
> >
> > Sorry for the rather slow process of this features development.
> >
> > FYI: I will be at EOSS in June and would be glad if we could meet up there.
> 
> I will most probably also be there. Looking forward to it.
Nice.


Best regards 
Johannes

> 
> All the best,
> Tobias
> 
> > Best regards
> > Johannes
> >
> >> -----Original Message-----
> >> From: Jan Kiszka <jan.kiszka@siemens.com>
> >> Sent: Freitag, 20. Jänner 2023 12:42
> >> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
> >> xenomai@lists.linux.dev
> >> Subject: Re: [PATCH 1/3] rtsignals: part one, core code plus x86
> >>
> >> CAUTION: External E-Mail !
> >>
> >> On 20.01.23 12:01, Johannes Kirchmair wrote:
> >>> Hey Jan,
> >>>
> >>> Sorry for not responding for so long.
> >>> Got dragged away from this unfortunatly.
> >>>
> >>>
> >>>> -----Original Message-----
> >>>> From: Jan Kiszka <jan.kiszka@siemens.com>
> >>>> Sent: Freitag, 20. Jänner 2023 10:05
> >>>> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
> >>>> xenomai@lists.linux.dev
> >>>> Subject: Re: [PATCH 1/3] rtsignals: part one, core code plus x86
> >>>>
> >>>> CAUTION: External E-Mail !
> >>>>
> >>>> On 08.07.22 09:30, Johannes Kirchmair wrote:
> >>>>> Hey Jan,
> >>>>>
> >>>>>> -----Original Message-----
> >>>>>> From: Jan Kiszka <jan.kiszka@siemens.com>
> >>>>>> Sent: Donnerstag, 7. Juli 2022 17:24
> >>>>>> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
> >>>>>> xenomai@lists.linux.dev
> >>>>>> Subject: Re: [PATCH 1/3] rtsignals: part one, core code plus x86
> >>>>>>
> >>>>>> On 07.07.22 15:59, Johannes Kirchmair wrote:
> >>>>>>> From: Richard Weinberger <richard@nod.at>
> >>>>>>>
> >>>>>>> Adds code for implementing signals that are handled in the real time
> >>>>>>> domain. This is done for 32bit process under an 64bit kernel.
> >>>>>>> It works in a similar way to signals in the Linux kernel.
> >>>>>>>
> >>>>>>> Edited-by: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
> >>>>>>
> >>>>>> ...
> >>>>>>
> >>>>>>> +static int ia32_setup_sigcontext(struct sigcontext_32 __user *sc,
> >>>>>>> +                            void __user *fpstate, struct pt_regs *regs,
> >>>>>>> +                            unsigned int mask)
> >>>>>>> +{
> >>>>>>> +   int err = 0;
> >>>>>>> +
> >>>>>>> +   put_user_try
> >>>>>>> +   {
> >>>>>>> +           put_user_ex(get_user_seg(gs), (unsigned int __user *)&sc-
> >gs);
> >>>>>>> +           put_user_ex(get_user_seg(fs), (unsigned int __user *)&sc->fs);
> >>>>>>> +           put_user_ex(get_user_seg(ds), (unsigned int __user *)&sc-
> >ds);
> >>>>>>> +           put_user_ex(get_user_seg(es), (unsigned int __user *)&sc-
> >es);
> >>>>>>> +
> >>>>>>> +           put_user_ex(regs->di, &sc->di);
> >>>>>>> +           put_user_ex(regs->si, &sc->si);
> >>>>>>> +           put_user_ex(regs->bp, &sc->bp);
> >>>>>>> +           put_user_ex(regs->sp, &sc->sp);
> >>>>>>> +           put_user_ex(regs->bx, &sc->bx);
> >>>>>>> +           put_user_ex(regs->dx, &sc->dx);
> >>>>>>> +           put_user_ex(regs->cx, &sc->cx);
> >>>>>>> +           put_user_ex(regs->ax, &sc->ax);
> >>>>>>> +           put_user_ex(current->thread.trap_nr, &sc->trapno);
> >>>>>>> +           put_user_ex(current->thread.error_code, &sc->err);
> >>>>>>> +           put_user_ex(regs->ip, &sc->ip);
> >>>>>>> +           put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
> >>>>>>> +           put_user_ex(regs->flags, &sc->flags);
> >>>>>>> +           put_user_ex(regs->sp, &sc->sp_at_signal);
> >>>>>>> +           put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
> >>>>>>> +
> >>>>>>> +           put_user_ex(ptr_to_compat(fpstate), &sc->fpstate);
> >>>>>>> +
> >>>>>>> +           /* non-iBCS2 extensions.. */
> >>>>>>> +           put_user_ex(mask, &sc->oldmask);
> >>>>>>> +           put_user_ex(current->thread.cr2, &sc->cr2);
> >>>>>>> +   }
> >>>>>>> +   put_user_catch(err);
> >>>>>>
> >>>>>> Am I missing something - or did you miss to add the magic for this
> >>>>>> get/put_user_try/catch?
> >>>>> Tried to figure it out this morning, but don’t understand it fully jet. Actually
> >>>> don’t quite get, how the errors of put_user_ex are propagated into the err
> >>>> variable. Probably in this case put_user_try, put_user_catch is only for
> >> disabling
> >>>> SMAP. But I will have a deeper look at it in the beginning of August after my
> >>>> vacation.
> >>>>>
> >>>>
> >>>> Was there a follow-up on this? I'm planning to revive this finally,
> >>>> figuring out if there are pitfalls in going the sigaction/sigreturn path
> >>>> for Xenomai.
> >>> For the question of the try/catch
> >>> We don’t have really a catch clause here, as we check access to the sigframe
> >> beforehand and we only use the put_user_try to disable SMAP to be able to
> >> copy to the user stack.
> >>>
> >>>>
> >>>> BTW, I do not understand why you made the restorer function a direct
> >>>> parameter of the sigaction syscall. It comes from the sigaction
> >>>> structure. And your implementation cannot provide oact when we want to
> >>>> add sigaction as library call as well.
> >>> Oact?
> >>
> >> Previous (old) action handler, see man sigaction.
> >>
> >>>
> >>> Actually I am not quite sure, but I guess the reason was to have a rather
> simple
> >> distinct syscall to Linux sigaction syscall.
> >>> We do not even pass a sigaction structure to the cobalt core, but just a
> handler
> >> and the restorer.
> >>
> >> Enough for signal(), not for sigaction(). But it would be a valid
> >> question if we really want/have to support all features of sigaction.
> >>
> >>>
> >>> There are some things I thought about, but did not find the time to
> investigate:
> >>>
> >>> - I copied and modified some of the signal code from Linux and removed
> >> everything I did not need for my purpose.
> >>>    Maybe it would be possible to use the Linux functions without modifying.
> >> (Primarily the sigframe setup and restore code)
> >>>    I think it would be cleaner to not have too much copied code.
> >>
> >> Ack, to-be-checked.
> >>
> >>>
> >>> - I always wondered what would happen if we have a domain switch in a
> signal
> >> handler.
> >>>    I still have not a deep enough knowledge of Xenomai. If we switch from
> >> Xenomai to Linux domain.
> >>>    The restorer code would make an cobald syscall ending up in the cobald
> >> restorer, but not quite sure about it.
> >>
> >> I don't think this should cause troubles. Cobalt's sigreturn would
> >> simply enforce a switch-back to RT (if that is needed, didn't check) and
> >> would restore userspace state from the saved state on the thread's stack.
> >>
> >> What should be considered as well is an async signal handling in the
> >> middle of the RT handler - whether already migrated or only migrated
> >> upon that. As all userspace-related state is on the userspace stack,
> >> nesting should work, but it all becomes quickly rather complicated.
> >>
> >>>
> >>> - Thought about, if we could use the sighandler stored in Linuxes task struct.
> >>>    So we could handle signals in Xenomai domain, that were registered form
> >> Linux domain.
> >>>    But not sure if possible.
> >>
> >> Also worth the check, though it comes with the risk of making the core
> >> too much depend upon the Linux structures.
> >>
> >>>
> >>> I am not quite sure, at what time I will have time to work on this again. Will
> have
> >> to talk to my supervisor.
> >>>
> >>> But would be happy if we would find a clean way of integrating this into
> >> Xenomai.
> >>
> >> Yes, specifically as we now have the underlying Dovetail support. I
> >> tested it with out current out-of-tree pattern, and it works as expected.
> >>
> >> Jan
> >>
> >> --
> >> Siemens AG, Technology
> >> Competence Center Embedded Linux
> >

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

* Re: [PATCH 1/3] rtsignals: part one, core code plus x86
  2023-04-21 15:17                 ` Johannes Kirchmair
@ 2023-05-04 13:06                   ` Schaffner, Tobias
  0 siblings, 0 replies; 20+ messages in thread
From: Schaffner, Tobias @ 2023-05-04 13:06 UTC (permalink / raw)
  To: Johannes Kirchmair; +Cc: xenomai

On 21.04.23 17:17, Johannes Kirchmair wrote:
> Hey Tobias,
> 
>> -----Original Message-----
>> From: Schaffner, Tobias <tobias.schaffner@siemens.com>
>> Sent: Donnerstag, 20. April 2023 10:13
>> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>; Kiszka, Jan
>> <jan.kiszka@siemens.com>
>> Cc: xenomai@lists.linux.dev
>> Subject: Re: [PATCH 1/3] rtsignals: part one, core code plus x86
>>
>> CAUTION: External E-Mail !
>>
>> On 19.04.23 11:18, Johannes Kirchmair wrote:
>>> Hey Jan,
>>>
>>> Richard told me that there was the topic of rt-signals in the community call
>> today.
>>> He said that you asked if there are newer version of the rt-signal patches finally.
>>>
>>> After the last call I attended, I did some work moving the signal frame setup
>> and restoring into the dovetail part. As you said that this is the way if we want to
>> use some of the Linux functions.
>>>
>>> Unfortunately I had to stop working on it due to another topping popping up.
>>>
>>> I just look into the stuff I changed and it seems like it should work the way it is
>> now.
>>> But I will have to test it again (because I don’t remember, if it really worked
>> after my changes).
>>
>> Hi Johannes,
>>
>> i just posted a smokey test to this thread that addresses some
>> additional corner cases.
>>
>> Feel free to use it to test your changes.
>> I will extend the tests to test arm64 soon.
>>
>> Feel free to report if you have ideas for additional test cases.
> Hope I find the time to have a look at this next week.
> And thanks that you provide testcases for this stuff.

No worries. Feel free to just drop the patches, if you don't find the 
time to test them. Would be happy to help.

Best Tobias

>>
>>> After that I could provide patches for Dovetail and Xenomai. With this we could
>> start discussing if I use to much of Linux code for real time. I am not really sure
>> what is viable to do in oob stage and what is not. So I will depend on the
>> experience of you and other experts.
>>> And we should also speak about the interfaces and the functionality we really
>> want to provide for rt task.
>>>
>>> Sorry for the rather slow process of this features development.
>>>
>>> FYI: I will be at EOSS in June and would be glad if we could meet up there.
>>
>> I will most probably also be there. Looking forward to it.
> Nice.
> 
> 
> Best regards
> Johannes
> 
>>
>> All the best,
>> Tobias
>>
>>> Best regards
>>> Johannes
>>>
>>>> -----Original Message-----
>>>> From: Jan Kiszka <jan.kiszka@siemens.com>
>>>> Sent: Freitag, 20. Jänner 2023 12:42
>>>> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
>>>> xenomai@lists.linux.dev
>>>> Subject: Re: [PATCH 1/3] rtsignals: part one, core code plus x86
>>>>
>>>> CAUTION: External E-Mail !
>>>>
>>>> On 20.01.23 12:01, Johannes Kirchmair wrote:
>>>>> Hey Jan,
>>>>>
>>>>> Sorry for not responding for so long.
>>>>> Got dragged away from this unfortunatly.
>>>>>
>>>>>
>>>>>> -----Original Message-----
>>>>>> From: Jan Kiszka <jan.kiszka@siemens.com>
>>>>>> Sent: Freitag, 20. Jänner 2023 10:05
>>>>>> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
>>>>>> xenomai@lists.linux.dev
>>>>>> Subject: Re: [PATCH 1/3] rtsignals: part one, core code plus x86
>>>>>>
>>>>>> CAUTION: External E-Mail !
>>>>>>
>>>>>> On 08.07.22 09:30, Johannes Kirchmair wrote:
>>>>>>> Hey Jan,
>>>>>>>
>>>>>>>> -----Original Message-----
>>>>>>>> From: Jan Kiszka <jan.kiszka@siemens.com>
>>>>>>>> Sent: Donnerstag, 7. Juli 2022 17:24
>>>>>>>> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
>>>>>>>> xenomai@lists.linux.dev
>>>>>>>> Subject: Re: [PATCH 1/3] rtsignals: part one, core code plus x86
>>>>>>>>
>>>>>>>> On 07.07.22 15:59, Johannes Kirchmair wrote:
>>>>>>>>> From: Richard Weinberger <richard@nod.at>
>>>>>>>>>
>>>>>>>>> Adds code for implementing signals that are handled in the real time
>>>>>>>>> domain. This is done for 32bit process under an 64bit kernel.
>>>>>>>>> It works in a similar way to signals in the Linux kernel.
>>>>>>>>>
>>>>>>>>> Edited-by: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
>>>>>>>>
>>>>>>>> ...
>>>>>>>>
>>>>>>>>> +static int ia32_setup_sigcontext(struct sigcontext_32 __user *sc,
>>>>>>>>> +                            void __user *fpstate, struct pt_regs *regs,
>>>>>>>>> +                            unsigned int mask)
>>>>>>>>> +{
>>>>>>>>> +   int err = 0;
>>>>>>>>> +
>>>>>>>>> +   put_user_try
>>>>>>>>> +   {
>>>>>>>>> +           put_user_ex(get_user_seg(gs), (unsigned int __user *)&sc-
>>> gs);
>>>>>>>>> +           put_user_ex(get_user_seg(fs), (unsigned int __user *)&sc->fs);
>>>>>>>>> +           put_user_ex(get_user_seg(ds), (unsigned int __user *)&sc-
>>> ds);
>>>>>>>>> +           put_user_ex(get_user_seg(es), (unsigned int __user *)&sc-
>>> es);
>>>>>>>>> +
>>>>>>>>> +           put_user_ex(regs->di, &sc->di);
>>>>>>>>> +           put_user_ex(regs->si, &sc->si);
>>>>>>>>> +           put_user_ex(regs->bp, &sc->bp);
>>>>>>>>> +           put_user_ex(regs->sp, &sc->sp);
>>>>>>>>> +           put_user_ex(regs->bx, &sc->bx);
>>>>>>>>> +           put_user_ex(regs->dx, &sc->dx);
>>>>>>>>> +           put_user_ex(regs->cx, &sc->cx);
>>>>>>>>> +           put_user_ex(regs->ax, &sc->ax);
>>>>>>>>> +           put_user_ex(current->thread.trap_nr, &sc->trapno);
>>>>>>>>> +           put_user_ex(current->thread.error_code, &sc->err);
>>>>>>>>> +           put_user_ex(regs->ip, &sc->ip);
>>>>>>>>> +           put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
>>>>>>>>> +           put_user_ex(regs->flags, &sc->flags);
>>>>>>>>> +           put_user_ex(regs->sp, &sc->sp_at_signal);
>>>>>>>>> +           put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
>>>>>>>>> +
>>>>>>>>> +           put_user_ex(ptr_to_compat(fpstate), &sc->fpstate);
>>>>>>>>> +
>>>>>>>>> +           /* non-iBCS2 extensions.. */
>>>>>>>>> +           put_user_ex(mask, &sc->oldmask);
>>>>>>>>> +           put_user_ex(current->thread.cr2, &sc->cr2);
>>>>>>>>> +   }
>>>>>>>>> +   put_user_catch(err);
>>>>>>>>
>>>>>>>> Am I missing something - or did you miss to add the magic for this
>>>>>>>> get/put_user_try/catch?
>>>>>>> Tried to figure it out this morning, but don’t understand it fully jet. Actually
>>>>>> don’t quite get, how the errors of put_user_ex are propagated into the err
>>>>>> variable. Probably in this case put_user_try, put_user_catch is only for
>>>> disabling
>>>>>> SMAP. But I will have a deeper look at it in the beginning of August after my
>>>>>> vacation.
>>>>>>>
>>>>>>
>>>>>> Was there a follow-up on this? I'm planning to revive this finally,
>>>>>> figuring out if there are pitfalls in going the sigaction/sigreturn path
>>>>>> for Xenomai.
>>>>> For the question of the try/catch
>>>>> We don’t have really a catch clause here, as we check access to the sigframe
>>>> beforehand and we only use the put_user_try to disable SMAP to be able to
>>>> copy to the user stack.
>>>>>
>>>>>>
>>>>>> BTW, I do not understand why you made the restorer function a direct
>>>>>> parameter of the sigaction syscall. It comes from the sigaction
>>>>>> structure. And your implementation cannot provide oact when we want to
>>>>>> add sigaction as library call as well.
>>>>> Oact?
>>>>
>>>> Previous (old) action handler, see man sigaction.
>>>>
>>>>>
>>>>> Actually I am not quite sure, but I guess the reason was to have a rather
>> simple
>>>> distinct syscall to Linux sigaction syscall.
>>>>> We do not even pass a sigaction structure to the cobalt core, but just a
>> handler
>>>> and the restorer.
>>>>
>>>> Enough for signal(), not for sigaction(). But it would be a valid
>>>> question if we really want/have to support all features of sigaction.
>>>>
>>>>>
>>>>> There are some things I thought about, but did not find the time to
>> investigate:
>>>>>
>>>>> - I copied and modified some of the signal code from Linux and removed
>>>> everything I did not need for my purpose.
>>>>>     Maybe it would be possible to use the Linux functions without modifying.
>>>> (Primarily the sigframe setup and restore code)
>>>>>     I think it would be cleaner to not have too much copied code.
>>>>
>>>> Ack, to-be-checked.
>>>>
>>>>>
>>>>> - I always wondered what would happen if we have a domain switch in a
>> signal
>>>> handler.
>>>>>     I still have not a deep enough knowledge of Xenomai. If we switch from
>>>> Xenomai to Linux domain.
>>>>>     The restorer code would make an cobald syscall ending up in the cobald
>>>> restorer, but not quite sure about it.
>>>>
>>>> I don't think this should cause troubles. Cobalt's sigreturn would
>>>> simply enforce a switch-back to RT (if that is needed, didn't check) and
>>>> would restore userspace state from the saved state on the thread's stack.
>>>>
>>>> What should be considered as well is an async signal handling in the
>>>> middle of the RT handler - whether already migrated or only migrated
>>>> upon that. As all userspace-related state is on the userspace stack,
>>>> nesting should work, but it all becomes quickly rather complicated.
>>>>
>>>>>
>>>>> - Thought about, if we could use the sighandler stored in Linuxes task struct.
>>>>>     So we could handle signals in Xenomai domain, that were registered form
>>>> Linux domain.
>>>>>     But not sure if possible.
>>>>
>>>> Also worth the check, though it comes with the risk of making the core
>>>> too much depend upon the Linux structures.
>>>>
>>>>>
>>>>> I am not quite sure, at what time I will have time to work on this again. Will
>> have
>>>> to talk to my supervisor.
>>>>>
>>>>> But would be happy if we would find a clean way of integrating this into
>>>> Xenomai.
>>>>
>>>> Yes, specifically as we now have the underlying Dovetail support. I
>>>> tested it with out current out-of-tree pattern, and it works as expected.
>>>>
>>>> Jan
>>>>
>>>> --
>>>> Siemens AG, Technology
>>>> Competence Center Embedded Linux
>>>

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

end of thread, other threads:[~2023-05-04 13:06 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-07 13:59 [PATCH 0/3] prove of concept Johannes Kirchmair
2022-07-07 13:59 ` [PATCH 1/3] rtsignals: part one, core code plus x86 Johannes Kirchmair
2022-07-07 15:23   ` Jan Kiszka
2022-07-08  7:30     ` Johannes Kirchmair
2023-01-20  9:04       ` Jan Kiszka
2023-01-20 11:01         ` Johannes Kirchmair
2023-01-20 11:41           ` Jan Kiszka
2023-04-19  9:18             ` Johannes Kirchmair
2023-04-19 12:39               ` Jan Kiszka
2023-04-20  8:03                 ` [PATCH] testsuite: Add exception handling tests to smokey T. Schaffner
2023-04-20  8:12               ` [PATCH 1/3] rtsignals: part one, core code plus x86 Schaffner, Tobias
2023-04-21 15:17                 ` Johannes Kirchmair
2023-05-04 13:06                   ` Schaffner, Tobias
2022-07-07 13:59 ` [PATCH 2/3] rtsignals: add i64 signal handling Johannes Kirchmair
2022-07-07 13:59 ` [PATCH 3/3] rtsignals: Add rt_signal test Johannes Kirchmair
2022-07-07 15:19 ` [PATCH 0/3] prove of concept Jan Kiszka
2022-07-08  7:24   ` Johannes Kirchmair
2022-07-08 17:42 ` Philippe Gerum
2022-07-11  6:12   ` Jan Kiszka
2022-08-23  6:32   ` Johannes Kirchmair

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