xenomai.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3] [POC] test implementaion of rt-signals
@ 2023-05-09 13:13 Johannes Kirchmair
  2023-05-09 13:13 ` [PATCH 2/3] [POC] Add rt_signal test Johannes Kirchmair
                   ` (2 more replies)
  0 siblings, 3 replies; 30+ messages in thread
From: Johannes Kirchmair @ 2023-05-09 13:13 UTC (permalink / raw)
  To: xenomai; +Cc: johannes.kirchmair

We implement rt signals to handle exceptions in rt stage.

This is done using dovetail specific functions for setting up the signal
frame.

This can be used to handle fpe exceptions on the fly, like fixing
division by zero. An other use case are breakpoints, implemented using the
illegal opcode exception. The real time handling of the breakpoints would
be handy for conditional breakpoints or also for stopping watchdogs and
other tasks in time.

Signed-off-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     | 13 ++++
 kernel/cobalt/arch/x86/signal_ia32.c          | 75 +++++++++++++++++++
 kernel/cobalt/arch/x86/signal_ia64.c          | 26 +++++++
 kernel/cobalt/dovetail/kevents.c              |  5 ++
 kernel/cobalt/posix/process.c                 |  3 +-
 kernel/cobalt/posix/syscall.c                 | 28 +++++++
 kernel/cobalt/posix/syscall32.c               | 16 ++++
 kernel/cobalt/thread.c                        | 39 ++++++++++
 lib/cobalt/arch/x86/Makefile.am               |  2 +-
 lib/cobalt/arch/x86/sigreturn.c               | 32 ++++++++
 lib/cobalt/internal.h                         |  2 +
 lib/cobalt/signal.c                           | 13 ++++
 17 files changed, 266 insertions(+), 3 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

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 b79cb8429..33d468419 100644
--- a/include/cobalt/kernel/thread.h
+++ b/include/cobalt/kernel/thread.h
@@ -574,6 +574,8 @@ static inline void xnthread_propagate_schedparam(struct xnthread *curr)
 		__xnthread_propagate_schedparam(curr);
 }
 
+int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs);
+
 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 9646a0d97..6307fae7f 100644
--- a/include/cobalt/uapi/syscall.h
+++ b/include/cobalt/uapi/syscall.h
@@ -137,6 +137,12 @@
 #define sc_cobalt_recvmmsg64			114
 #define sc_cobalt_cond_wait_prologue64		115
 
+/*
+ * 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 93929b645..e725afbff 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 smi.o c1e.o
+xenomai-y := machine.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 745c32467..4d004680b 100644
--- a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
+++ b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
@@ -28,5 +28,18 @@
 #define xnarch_fault_bp_p(__nr)		((current->ptrace & PT_PTRACED) &&	\
 					 ((__nr) == X86_TRAP_DB || (__nr) == X86_TRAP_BP))
 #define xnarch_fault_notify(__nr)	(!xnarch_fault_bp_p(__nr))
+#define xnarch_fault_code(__regs)		((__regs)->orig_ax)
+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);
+
+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);
 
 #endif /* !_COBALT_X86_ASM_THREAD_H */
diff --git a/kernel/cobalt/arch/x86/signal_ia32.c b/kernel/cobalt/arch/x86/signal_ia32.c
new file mode 100644
index 000000000..e78c8c4d4
--- /dev/null
+++ b/kernel/cobalt/arch/x86/signal_ia32.c
@@ -0,0 +1,75 @@
+#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>
+
+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;
+}
+
+int xnarch_rt_sigreturn_ia32(struct pt_regs *regs)
+{
+	int ret;
+
+	ret = dovetail_restore_rt_signal_frame(regs);
+	if (ret < 0)
+		goto badframe;
+
+	return regs->ax;
+
+badframe:
+	xnthread_call_mayday(xnthread_current(), SIGKILL);
+	return -1;
+}
+
diff --git a/kernel/cobalt/arch/x86/signal_ia64.c b/kernel/cobalt/arch/x86/signal_ia64.c
new file mode 100644
index 000000000..a7044db40
--- /dev/null
+++ b/kernel/cobalt/arch/x86/signal_ia64.c
@@ -0,0 +1,26 @@
+// 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
+ */
+
+#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>
+
+int xnarch_rt_sigreturn_ia64(struct pt_regs *regs)
+{
+	return dovetail_restore_rt_signal_frame(regs);
+}
+
diff --git a/kernel/cobalt/dovetail/kevents.c b/kernel/cobalt/dovetail/kevents.c
index 4da4f51b7..61417717b 100644
--- a/kernel/cobalt/dovetail/kevents.c
+++ b/kernel/cobalt/dovetail/kevents.c
@@ -57,6 +57,9 @@ void handle_oob_trap_entry(unsigned int trapnr, struct pt_regs *regs)
 		xnsched_run();
 	}
 
+	if (xnthread_handle_rt_signals(trapnr, regs) == 0)
+		return;
+
 	/*
 	 * If we experienced a trap on behalf of a shadow thread
 	 * running in primary mode, move it to the Linux domain,
@@ -88,6 +91,8 @@ void handle_oob_trap_entry(unsigned int trapnr, struct pt_regs *regs)
 		xnstat_counter_inc(&thread->stat.pf);
 
 	xnthread_relax(xnarch_fault_notify(trapnr), SIGDEBUG_MIGRATE_FAULT);
+
+	return;
 }
 
 static inline int handle_setaffinity_event(struct dovetail_migration_data *d)
diff --git a/kernel/cobalt/posix/process.c b/kernel/cobalt/posix/process.c
index 1abc86f37..2069129cb 100644
--- a/kernel/cobalt/posix/process.c
+++ b/kernel/cobalt/posix/process.c
@@ -738,9 +738,10 @@ void cobalt_unregister_debugged_thread(struct xnthread *thread)
 		cobalt_resume_debugged_process(process);
 }
 
+#ifdef CONFIG_SMP
+
 int cobalt_handle_setaffinity_event(struct task_struct *task)
 {
-#ifdef CONFIG_SMP
 	struct xnthread *thread;
 	spl_t s;
 
diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c
index 46c4998e4..b4bd4c587 100644
--- a/kernel/cobalt/posix/syscall.c
+++ b/kernel/cobalt/posix/syscall.c
@@ -277,6 +277,34 @@ static COBALT_SYSCALL(serialdbg, current,
 	return 0;
 }
 
+static COBALT_SYSCALL(sigreturn, current, (void))
+{
+	struct pt_regs *regs = task_pt_regs(current);
+
+	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);
+}
+
+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 b65a0a760..f8b21bfb2 100644
--- a/kernel/cobalt/posix/syscall32.c
+++ b/kernel/cobalt/posix/syscall32.c
@@ -774,6 +774,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 old_timespec32 __user *u_ts,
diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
index 41804b24f..71f97c481 100644
--- a/kernel/cobalt/thread.c
+++ b/kernel/cobalt/thread.c
@@ -25,6 +25,7 @@
 #include <linux/signal.h>
 #include <linux/pid.h>
 #include <linux/sched.h>
+#include <asm/sighandling.h>
 #include <uapi/linux/sched/types.h>
 #include <cobalt/kernel/sched.h>
 #include <cobalt/kernel/timer.h>
@@ -43,6 +44,7 @@
 #include <pipeline/inband_work.h>
 #include <pipeline/sched.h>
 #include <trace/events/cobalt-core.h>
+#include "posix/process.h"
 #include "debug.h"
 
 static DECLARE_WAIT_QUEUE_HEAD(join_all);
@@ -2520,6 +2522,43 @@ int xnthread_killall(int grace, int mask)
 }
 EXPORT_SYMBOL_GPL(xnthread_killall);
 
+int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs)
+{
+	struct ksignal ksig;
+
+	unsigned int vector = trapnr;
+	unsigned int code = xnarch_fault_code(regs);
+	struct cobalt_ppd *sys_ppd;
+	int sig, ret = 0;
+	struct kernel_siginfo si;
+
+	code = xnarch_fault_code(regs);
+	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;
+
+	ksig.sig = sig;
+	memcpy(&ksig.info, &si, sizeof(si));
+	ksig.ka.sa.sa_flags = SA_SIGINFO | SA_RESTORER;
+	ksig.ka.sa.sa_restorer = sys_ppd->sigrestorer;
+	ksig.ka.sa.sa_handler = sys_ppd->sighand[sig];
+
+	ret = dovetail_setup_rt_signal_frame(&ksig, regs);
+	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..76292e145
--- /dev/null
+++ b/lib/cobalt/arch/x86/sigreturn.c
@@ -0,0 +1,32 @@
+#include <cobalt/uapi/syscall.h>
+#include "internal.h"
+
+extern void cobalt_sigreturn (void) asm ("__cobalt_sigreturn") __attribute__ ((visibility ("hidden")));
+
+#ifdef __x86_64__
+#define build_restorer(syscall_number)                                         \
+	asm(".text\n"                                                          \
+	    "    .align 16\n"                                                  \
+	    "__cobalt_sigreturn:\n"                                            \
+	    "    movq $ " #syscall_number ", %rax\n"                           \
+	    "    syscall")
+#endif
+
+#ifdef __i386__
+#define build_restorer(syscall_number)                                         \
+	asm(".text\n"                                                          \
+	    "    .align 16\n"                                                  \
+	    "__cobalt_sigreturn:\n"                                            \
+	    "    movl $ " #syscall_number ", %eax\n"                           \
+	    "    int  $0x80")
+#endif
+
+/*
+ * __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 acb3989f1..4782d154a 100644
--- a/lib/cobalt/internal.h
+++ b/lib/cobalt/internal.h
@@ -132,4 +132,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 40d315ebb..af174d570 100644
--- a/lib/cobalt/signal.c
+++ b/lib/cobalt/signal.c
@@ -126,3 +126,16 @@ 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] 30+ messages in thread

* [PATCH 2/3] [POC] Add rt_signal test
  2023-05-09 13:13 [PATCH 1/3] [POC] test implementaion of rt-signals Johannes Kirchmair
@ 2023-05-09 13:13 ` Johannes Kirchmair
  2023-05-09 13:13 ` [PATCH 3/3] [POC] add a tool to measure rt_signal latency Johannes Kirchmair
  2023-05-09 13:17 ` [PATCH 1/3] [POC] test implementaion of rt-signals Johannes Kirchmair
  2 siblings, 0 replies; 30+ messages in thread
From: Johannes Kirchmair @ 2023-05-09 13:13 UTC (permalink / raw)
  To: xenomai; +Cc: johannes.kirchmair

This commit adds simple rt signal test for SIGFPE, SIGILL and SIGSEGV.
---
 configure.ac                               |   1 +
 testsuite/Makefile.am                      |   1 +
 testsuite/rt-signal-tests/Makefile.am      |  31 +++
 testsuite/rt-signal-tests/rt_signal_test.c | 228 +++++++++++++++++++++
 4 files changed, 261 insertions(+)
 create mode 100644 testsuite/rt-signal-tests/Makefile.am
 create mode 100644 testsuite/rt-signal-tests/rt_signal_test.c

diff --git a/configure.ac b/configure.ac
index 3ce34048e..3325482fc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1007,6 +1007,7 @@ AC_CONFIG_FILES([ \
 	testsuite/switchtest/Makefile \
 	testsuite/gpiotest/Makefile \
 	testsuite/gpiobench/Makefile \
+	testsuite/rt-signal-tests/Makefile \
 	testsuite/spitest/Makefile \
 	testsuite/smokey/Makefile \
 	testsuite/smokey/arith/Makefile \
diff --git a/testsuite/Makefile.am b/testsuite/Makefile.am
index 4932f6d33..59f36967a 100644
--- a/testsuite/Makefile.am
+++ b/testsuite/Makefile.am
@@ -5,6 +5,7 @@ if XENO_COBALT
 SUBDIRS += 		\
 	clocktest	\
 	gpiotest	\
+	rt-signal-tests	\
 	spitest		\
 	switchtest	\
 	xeno-test
diff --git a/testsuite/rt-signal-tests/Makefile.am b/testsuite/rt-signal-tests/Makefile.am
new file mode 100644
index 000000000..084347631
--- /dev/null
+++ b/testsuite/rt-signal-tests/Makefile.am
@@ -0,0 +1,31 @@
+testdir = @XENO_TEST_DIR@
+
+CCLD = $(top_srcdir)/scripts/wrap-link.sh $(CC)
+
+test_PROGRAMS = rt_signal_test_fpe rt_signal_test_segfault rt_signal_test_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
+
+rt_signal_test_fpe_SOURCES = rt_signal_test.c
+rt_signal_test_fpe_CPPFLAGS = $(alchemycppflags) -DTEST_FPE=1
+rt_signal_test_fpe_LDADD = $(alchemyldadd)
+
+rt_signal_test_segfault_SOURCES = rt_signal_test.c
+rt_signal_test_segfault_CPPFLAGS = $(alchemycppflags) -DTEST_SEGFAULT=1
+rt_signal_test_segfault_LDADD = $(alchemyldadd)
+
+rt_signal_test_ill_SOURCES = rt_signal_test.c
+rt_signal_test_ill_CPPFLAGS = $(alchemycppflags)
+rt_signal_test_ill_LDADD = $(alchemyldadd)
+
diff --git a/testsuite/rt-signal-tests/rt_signal_test.c b/testsuite/rt-signal-tests/rt_signal_test.c
new file mode 100644
index 000000000..0d43ac8da
--- /dev/null
+++ b/testsuite/rt-signal-tests/rt_signal_test.c
@@ -0,0 +1,228 @@
+#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;
+
+// #define JMP_CLEANUP
+#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?)",
+};
+
+
+#ifndef JMP_CLEANUP
+static int get_step(void)
+{
+#ifdef TEST_SEGFAULT
+#if defined(__i386__) || defined(__x86_64__)
+	return 11;
+#else
+	return 4;
+#endif
+#elif defined(TEST_FPE)
+	return 2;
+#else
+#if defined(__i386__) || defined(__x86_64__)
+	return 2;
+#else
+	return 4;
+#endif
+#endif
+}
+
+static void do_cleanup(void *context)
+{
+	int step = 0;
+	struct ucontext *uc = context;
+
+	step = get_step();
+
+#if defined(__i386__)
+	uc->uc_mcontext.eip += step;
+#elif defined(__x86_64__)
+	uc->uc_mcontext.rip += step;
+#elif defined(__aarch64__)
+	uc->uc_mcontext.pc += step;
+#endif
+}
+#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
+	}
+}
+
+static void do_div_by_0(void)
+{
+#if defined(__i386__) || defined (__x86_64__)
+	__asm__("xorl %eax, %eax\n\t"
+		"movl %eax, %ecx\n\t"
+		"cltd\n\t"
+		"idivl %ecx");
+#endif
+	//TODO find a cortex-A way to trigger an FPE
+}
+
+static void do_ill(void)
+{
+#if defined(__i386__) || defined (__x86_64__)
+	__asm__("ud2");
+#else
+	__asm__("udf #0xdead");
+#endif
+}
+
+static void do_segfault(void)
+{
+	*((int *)0x73) = 0xdecafbad;
+}
+
+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
+	do_segfault();
+#elif defined(TEST_FPE)
+	do_div_by_0();
+#else
+	do_ill();
+#endif
+
+	if (0) { // so we don't geht defined but not used errors
+		do_segfault();
+		do_div_by_0();
+		do_ill();
+	}
+}
+
+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] 30+ messages in thread

* [PATCH 3/3] [POC] add a tool to measure rt_signal latency
  2023-05-09 13:13 [PATCH 1/3] [POC] test implementaion of rt-signals Johannes Kirchmair
  2023-05-09 13:13 ` [PATCH 2/3] [POC] Add rt_signal test Johannes Kirchmair
@ 2023-05-09 13:13 ` Johannes Kirchmair
  2023-05-09 13:17 ` [PATCH 1/3] [POC] test implementaion of rt-signals Johannes Kirchmair
  2 siblings, 0 replies; 30+ messages in thread
From: Johannes Kirchmair @ 2023-05-09 13:13 UTC (permalink / raw)
  To: xenomai; +Cc: johannes.kirchmair

Signed-off-by: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
---
 configure.ac                          |   1 +
 utils/Makefile.am                     |   2 +-
 utils/rt_signal_hist/Makefile.am      |  22 ++++
 utils/rt_signal_hist/error.h          |  14 +++
 utils/rt_signal_hist/histo.c          |  46 ++++++++
 utils/rt_signal_hist/histo.h          |  13 +++
 utils/rt_signal_hist/result.c         |  16 +++
 utils/rt_signal_hist/result.h         |  12 ++
 utils/rt_signal_hist/rt_signal_hist.c | 158 ++++++++++++++++++++++++++
 9 files changed, 283 insertions(+), 1 deletion(-)
 create mode 100644 utils/rt_signal_hist/Makefile.am
 create mode 100644 utils/rt_signal_hist/error.h
 create mode 100644 utils/rt_signal_hist/histo.c
 create mode 100644 utils/rt_signal_hist/histo.h
 create mode 100644 utils/rt_signal_hist/result.c
 create mode 100644 utils/rt_signal_hist/result.h
 create mode 100644 utils/rt_signal_hist/rt_signal_hist.c

diff --git a/configure.ac b/configure.ac
index 3325482fc..fe4a3b3e0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1054,6 +1054,7 @@ AC_CONFIG_FILES([ \
 	utils/slackspot/Makefile \
 	utils/corectl/Makefile \
 	utils/autotune/Makefile \
+	utils/rt_signal_hist/Makefile \
 	utils/net/rtnet \
 	utils/net/rtnet.conf \
 	utils/net/Makefile \
diff --git a/utils/Makefile.am b/utils/Makefile.am
index 4de6434a9..79c39ac90 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -1,5 +1,5 @@
 SUBDIRS = hdb
 if XENO_COBALT
-SUBDIRS += analogy autotune can net ps slackspot corectl
+SUBDIRS += analogy autotune can net ps slackspot corectl rt_signal_hist
 endif
 SUBDIRS += chkkconf
diff --git a/utils/rt_signal_hist/Makefile.am b/utils/rt_signal_hist/Makefile.am
new file mode 100644
index 000000000..810a63bba
--- /dev/null
+++ b/utils/rt_signal_hist/Makefile.am
@@ -0,0 +1,22 @@
+testdir = @XENO_TEST_DIR@
+
+CCLD = $(top_srcdir)/scripts/wrap-link.sh $(CC)
+
+test_PROGRAMS = rt_signal_hist
+
+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
+
+rt_signal_hist_SOURCES = rt_signal_hist.c histo.c result.c
+rt_signal_hist_CPPFLAGS = $(alchemycppflags)
+rt_signal_hist_LDADD = $(alchemyldadd)
diff --git a/utils/rt_signal_hist/error.h b/utils/rt_signal_hist/error.h
new file mode 100644
index 000000000..4aa50e70e
--- /dev/null
+++ b/utils/rt_signal_hist/error.h
@@ -0,0 +1,14 @@
+#ifndef ERROR_EXIT_H
+#define ERROR_EXIT_H
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static int error(char *reason, int ret)
+{
+	printf("%s: err= %d\n", reason, ret);
+	exit(1);
+}
+
+#endif
+
diff --git a/utils/rt_signal_hist/histo.c b/utils/rt_signal_hist/histo.c
new file mode 100644
index 000000000..36e51201b
--- /dev/null
+++ b/utils/rt_signal_hist/histo.c
@@ -0,0 +1,46 @@
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "histo.h"
+#include "error.h"
+
+void initHisto(struct histo **histo, unsigned long n)
+{
+	int i = 0;
+	*histo = malloc(sizeof(struct histo) + n * sizeof(unsigned long));
+	if (!histo)
+		return;
+
+	for (i = 0; i < n; ++i) {
+		(*histo)->data[i] = 0;
+	}
+	(*histo)->max_index = 0;
+	(*histo)->n = n;
+}
+
+void writeHisto(struct histo *histo)
+{
+	unsigned long i;
+	FILE *f = fopen("hist.txt", "w");
+	if (!f)
+		error("can't open \"hist.txt\n", errno);
+
+	for (i = 0; i <= histo->max_index; ++i) {
+		fprintf(f, "%lu %lu\n", i, histo->data[i]);
+	}
+
+	fclose(f);
+}
+
+void updateHisto(struct histo *histo, unsigned long curr)
+{
+	unsigned long index;
+
+	index = curr;
+	index = index >= histo->n ? histo->n - 1 : index;
+
+	histo->max_index = histo->max_index >= index ? histo->max_index : index;
+	histo->data[index]++;
+}
+
diff --git a/utils/rt_signal_hist/histo.h b/utils/rt_signal_hist/histo.h
new file mode 100644
index 000000000..63c92014a
--- /dev/null
+++ b/utils/rt_signal_hist/histo.h
@@ -0,0 +1,13 @@
+#ifndef HISTO_H
+#define HISTO_H
+
+struct histo {
+	unsigned long n;
+	unsigned long max_index;
+	unsigned long data[];
+};
+
+void initHisto(struct histo **histo, unsigned long n);
+void writeHisto(struct histo *histo);
+void updateHisto(struct histo *histo, unsigned long curr);
+#endif
diff --git a/utils/rt_signal_hist/result.c b/utils/rt_signal_hist/result.c
new file mode 100644
index 000000000..a863d7182
--- /dev/null
+++ b/utils/rt_signal_hist/result.c
@@ -0,0 +1,16 @@
+#include "result.h"
+
+void initResult(struct result *resu)
+{
+	resu->min = (unsigned long)-1l;
+	resu->max = 0ul;
+	resu->avr = 0ul;
+}
+
+void updateResult(struct result *resu, unsigned long curr, unsigned long ith_entry)
+{
+	resu->min = curr < resu->min ? curr: resu->min;
+	resu->max = curr > resu->max ? curr: resu->max;
+	resu->avr = (resu->avr *(ith_entry - 1) + curr) / ith_entry;
+}
+
diff --git a/utils/rt_signal_hist/result.h b/utils/rt_signal_hist/result.h
new file mode 100644
index 000000000..9895535ee
--- /dev/null
+++ b/utils/rt_signal_hist/result.h
@@ -0,0 +1,12 @@
+#ifndef RESULT_H
+#define RESULT_H
+
+struct result {
+	unsigned long min;
+	unsigned long max;
+	unsigned long avr;
+};
+
+void initResult(struct result *resu);
+void updateResult(struct result *resu, unsigned long curr, unsigned long ith_entry);
+#endif
diff --git a/utils/rt_signal_hist/rt_signal_hist.c b/utils/rt_signal_hist/rt_signal_hist.c
new file mode 100644
index 000000000..076084e9e
--- /dev/null
+++ b/utils/rt_signal_hist/rt_signal_hist.c
@@ -0,0 +1,158 @@
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdio.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <asm/ucontext.h>
+
+#include <alchemy/task.h>
+#include <cobalt/signal.h>
+#include <copperplate/clockobj.h>
+
+#include "histo.h"
+#include "result.h"
+#include "error.h"
+
+#define TEST_SIGNAL SIGILL
+#define USE_GETTIME 0
+#define USE_RT_SIGNALS 1
+
+static RT_TASK task;
+
+static void do_cleanup(void *context)
+{
+	struct ucontext *uc = context;
+
+#if defined(__i386__)
+	uc->uc_mcontext.eip += 2;
+#elif defined(__x86_64__)
+	uc->uc_mcontext.rip += 2;
+#else
+	uc->uc_mcontext.pc += 4;
+#endif
+}
+
+static void sighandler(int sig, siginfo_t *info, void *data)
+{
+	do_cleanup(data);
+}
+
+static void do_ill(void)
+{
+#if defined(__i386__) || defined (__x86_64__)
+	__asm__("ud2");
+#else
+	__asm__("udf #0xdead");
+#endif
+}
+
+static void registerSignal(void)
+{
+	int ret;
+
+	ret = cobalt_rt_signal(TEST_SIGNAL, sighandler);
+	if (ret)
+		error("cobalt_rt_signal", ret);
+}
+
+static void printPreRunInfo(void)
+{
+	if (USE_GETTIME) {
+		struct timespec time;
+		clock_getres(CLOCK_MONOTONIC_RAW, &time);
+		printf("res_sec = %ld res_nsec = %ld \n", time.tv_sec, time.tv_nsec);
+	} else {
+		printf("res_nsec = %lld\n", clockobj_tsc_to_ns(1));
+	}
+}
+
+static inline unsigned long ns_now(void)
+{
+	if (USE_GETTIME) {
+		struct timespec time;
+		clock_gettime(CLOCK_MONOTONIC_RAW, &time);
+		return time.tv_nsec;
+	} else {
+		ticks_t ticks;
+		ticks = clockobj_get_tsc();
+		return clockobj_tsc_to_ns(ticks);
+	}
+}
+
+static void task_func(void *cookie)
+{
+	struct histo *histo = (struct histo *)cookie;
+	struct result resu;
+
+	unsigned long start, stop, curr;
+	int i, j;
+
+	printPreRunInfo();
+
+	registerSignal();
+
+	initResult(&resu);
+
+	for (j = 0; j < 10000; ++j) {
+		for (i = 0; i < 1000; ++i) {
+
+			start = ns_now();
+			do_ill();
+			stop = ns_now();
+
+			if (stop <= start) { // dismiss on counter overrun
+				continue;
+			}
+
+			curr = stop - start;
+
+			updateResult(&resu, curr, i+1); // + 1 as we add with index i the (i+1)th entry
+
+			updateHisto(histo, curr);
+		}
+
+		printf("min = %lu max = %lu avr = %lu\n", resu.min, resu.max, resu.avr);
+		rt_task_sleep(1000000);
+	}
+}
+
+static const char *task_name = "signal_test_task";
+static const int prio = 80;
+
+int main(int argc, char **argv)
+{
+	int ret;
+	struct histo *histo;
+
+	struct sigaction sa;
+
+	memset(&sa, 0, sizeof(sa));
+	sa.sa_sigaction = sighandler;
+	sa.sa_flags = SA_SIGINFO | SA_NODEFER;
+	sigaction(TEST_SIGNAL, &sa, NULL);
+
+	initHisto(&histo, 100000000);
+	if (!histo)
+		error("could not init histo", -ENOMEM);
+
+	ret = rt_task_create(&task, task_name, 0, prio, T_JOINABLE);
+	if (ret)
+		error("rt_task_create", ret);
+
+	ret = rt_task_start(&task, task_func, histo);
+	if (ret)
+		error("cant start task", ret);
+
+	rt_task_join(&task);
+	rt_task_delete(&task);
+
+	writeHisto(histo);
+
+	return 0;
+}
+
-- 
2.25.1


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

* RE: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-05-09 13:13 [PATCH 1/3] [POC] test implementaion of rt-signals Johannes Kirchmair
  2023-05-09 13:13 ` [PATCH 2/3] [POC] Add rt_signal test Johannes Kirchmair
  2023-05-09 13:13 ` [PATCH 3/3] [POC] add a tool to measure rt_signal latency Johannes Kirchmair
@ 2023-05-09 13:17 ` Johannes Kirchmair
  2023-05-12 17:38   ` Jan Kiszka
  2023-08-09  9:50   ` Schaffner, Tobias
  2 siblings, 2 replies; 30+ messages in thread
From: Johannes Kirchmair @ 2023-05-09 13:17 UTC (permalink / raw)
  To: xenomai, Schaffner, Tobias, Jan Kiszka

Hello Jan and Tobias,

I just dropped the patches on the mailing list.
For the dovetail functions I took a rather naive approach, using most of the frame setup code provided by Linux.
I just tested it for 32bit and 64bit x86 Applications and it seems to work. 

I also added a tool rt_signal_hist that runs in a cycle and measures the time an exception handling takes.
It is afterwards put into an txt file that reassembles an histogram of the timings.

Unfortunately as a 32bit application the rt_signal_hist tool does not run to completion, printing the following:
" Xenomai/cobalt: sleeping while holding mutex
CPU time limit exceeded"

Maybe the naive approach is not so reliable ;-/
Hope I find the time the look into it. 

Sorry for not putting more effort into this so fare.

The next most important step in my opinion would be to define a clean interface into dovetail for the signal frame setup and restoring.
Actually that's the task I consider one of the harder and I am not so sure how to approach this.

Best regards
Johannes

> -----Original Message-----
> From: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
> Sent: Dienstag, 9. Mai 2023 15:14
> To: xenomai@lists.linux.dev
> Cc: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
> Subject: [PATCH 1/3] [POC] test implementaion of rt-signals
> 
> We implement rt signals to handle exceptions in rt stage.
> 
> This is done using dovetail specific functions for setting up the signal
> frame.
> 
> This can be used to handle fpe exceptions on the fly, like fixing
> division by zero. An other use case are breakpoints, implemented using the
> illegal opcode exception. The real time handling of the breakpoints would
> be handy for conditional breakpoints or also for stopping watchdogs and
> other tasks in time.
> 
> Signed-off-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     | 13 ++++
>  kernel/cobalt/arch/x86/signal_ia32.c          | 75 +++++++++++++++++++
>  kernel/cobalt/arch/x86/signal_ia64.c          | 26 +++++++
>  kernel/cobalt/dovetail/kevents.c              |  5 ++
>  kernel/cobalt/posix/process.c                 |  3 +-
>  kernel/cobalt/posix/syscall.c                 | 28 +++++++
>  kernel/cobalt/posix/syscall32.c               | 16 ++++
>  kernel/cobalt/thread.c                        | 39 ++++++++++
>  lib/cobalt/arch/x86/Makefile.am               |  2 +-
>  lib/cobalt/arch/x86/sigreturn.c               | 32 ++++++++
>  lib/cobalt/internal.h                         |  2 +
>  lib/cobalt/signal.c                           | 13 ++++
>  17 files changed, 266 insertions(+), 3 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
> 
> 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 b79cb8429..33d468419 100644
> --- a/include/cobalt/kernel/thread.h
> +++ b/include/cobalt/kernel/thread.h
> @@ -574,6 +574,8 @@ static inline void xnthread_propagate_schedparam(struct
> xnthread *curr)
>  		__xnthread_propagate_schedparam(curr);
>  }
> 
> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs);
> +
>  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 9646a0d97..6307fae7f 100644
> --- a/include/cobalt/uapi/syscall.h
> +++ b/include/cobalt/uapi/syscall.h
> @@ -137,6 +137,12 @@
>  #define sc_cobalt_recvmmsg64			114
>  #define sc_cobalt_cond_wait_prologue64		115
> 
> +/*
> + * 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 93929b645..e725afbff 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 smi.o c1e.o
> +xenomai-y := machine.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 745c32467..4d004680b 100644
> --- a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
> +++ b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
> @@ -28,5 +28,18 @@
>  #define xnarch_fault_bp_p(__nr)		((current->ptrace & PT_PTRACED)
> &&	\
>  					 ((__nr) == X86_TRAP_DB || (__nr) ==
> X86_TRAP_BP))
>  #define xnarch_fault_notify(__nr)	(!xnarch_fault_bp_p(__nr))
> +#define xnarch_fault_code(__regs)		((__regs)->orig_ax)
> +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);
> +
> +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);
> 
>  #endif /* !_COBALT_X86_ASM_THREAD_H */
> diff --git a/kernel/cobalt/arch/x86/signal_ia32.c
> b/kernel/cobalt/arch/x86/signal_ia32.c
> new file mode 100644
> index 000000000..e78c8c4d4
> --- /dev/null
> +++ b/kernel/cobalt/arch/x86/signal_ia32.c
> @@ -0,0 +1,75 @@
> +#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>
> +
> +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;
> +}
> +
> +int xnarch_rt_sigreturn_ia32(struct pt_regs *regs)
> +{
> +	int ret;
> +
> +	ret = dovetail_restore_rt_signal_frame(regs);
> +	if (ret < 0)
> +		goto badframe;
> +
> +	return regs->ax;
> +
> +badframe:
> +	xnthread_call_mayday(xnthread_current(), SIGKILL);
> +	return -1;
> +}
> +
> diff --git a/kernel/cobalt/arch/x86/signal_ia64.c
> b/kernel/cobalt/arch/x86/signal_ia64.c
> new file mode 100644
> index 000000000..a7044db40
> --- /dev/null
> +++ b/kernel/cobalt/arch/x86/signal_ia64.c
> @@ -0,0 +1,26 @@
> +// 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
> + */
> +
> +#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>
> +
> +int xnarch_rt_sigreturn_ia64(struct pt_regs *regs)
> +{
> +	return dovetail_restore_rt_signal_frame(regs);
> +}
> +
> diff --git a/kernel/cobalt/dovetail/kevents.c b/kernel/cobalt/dovetail/kevents.c
> index 4da4f51b7..61417717b 100644
> --- a/kernel/cobalt/dovetail/kevents.c
> +++ b/kernel/cobalt/dovetail/kevents.c
> @@ -57,6 +57,9 @@ void handle_oob_trap_entry(unsigned int trapnr, struct
> pt_regs *regs)
>  		xnsched_run();
>  	}
> 
> +	if (xnthread_handle_rt_signals(trapnr, regs) == 0)
> +		return;
> +
>  	/*
>  	 * If we experienced a trap on behalf of a shadow thread
>  	 * running in primary mode, move it to the Linux domain,
> @@ -88,6 +91,8 @@ void handle_oob_trap_entry(unsigned int trapnr, struct
> pt_regs *regs)
>  		xnstat_counter_inc(&thread->stat.pf);
> 
>  	xnthread_relax(xnarch_fault_notify(trapnr), SIGDEBUG_MIGRATE_FAULT);
> +
> +	return;
>  }
> 
>  static inline int handle_setaffinity_event(struct dovetail_migration_data *d)
> diff --git a/kernel/cobalt/posix/process.c b/kernel/cobalt/posix/process.c
> index 1abc86f37..2069129cb 100644
> --- a/kernel/cobalt/posix/process.c
> +++ b/kernel/cobalt/posix/process.c
> @@ -738,9 +738,10 @@ void cobalt_unregister_debugged_thread(struct
> xnthread *thread)
>  		cobalt_resume_debugged_process(process);
>  }
> 
> +#ifdef CONFIG_SMP
> +
>  int cobalt_handle_setaffinity_event(struct task_struct *task)
>  {
> -#ifdef CONFIG_SMP
>  	struct xnthread *thread;
>  	spl_t s;
> 
> diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c
> index 46c4998e4..b4bd4c587 100644
> --- a/kernel/cobalt/posix/syscall.c
> +++ b/kernel/cobalt/posix/syscall.c
> @@ -277,6 +277,34 @@ static COBALT_SYSCALL(serialdbg, current,
>  	return 0;
>  }
> 
> +static COBALT_SYSCALL(sigreturn, current, (void))
> +{
> +	struct pt_regs *regs = task_pt_regs(current);
> +
> +	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);
> +}
> +
> +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 b65a0a760..f8b21bfb2 100644
> --- a/kernel/cobalt/posix/syscall32.c
> +++ b/kernel/cobalt/posix/syscall32.c
> @@ -774,6 +774,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 old_timespec32 __user *u_ts,
> diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
> index 41804b24f..71f97c481 100644
> --- a/kernel/cobalt/thread.c
> +++ b/kernel/cobalt/thread.c
> @@ -25,6 +25,7 @@
>  #include <linux/signal.h>
>  #include <linux/pid.h>
>  #include <linux/sched.h>
> +#include <asm/sighandling.h>
>  #include <uapi/linux/sched/types.h>
>  #include <cobalt/kernel/sched.h>
>  #include <cobalt/kernel/timer.h>
> @@ -43,6 +44,7 @@
>  #include <pipeline/inband_work.h>
>  #include <pipeline/sched.h>
>  #include <trace/events/cobalt-core.h>
> +#include "posix/process.h"
>  #include "debug.h"
> 
>  static DECLARE_WAIT_QUEUE_HEAD(join_all);
> @@ -2520,6 +2522,43 @@ int xnthread_killall(int grace, int mask)
>  }
>  EXPORT_SYMBOL_GPL(xnthread_killall);
> 
> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs)
> +{
> +	struct ksignal ksig;
> +
> +	unsigned int vector = trapnr;
> +	unsigned int code = xnarch_fault_code(regs);
> +	struct cobalt_ppd *sys_ppd;
> +	int sig, ret = 0;
> +	struct kernel_siginfo si;
> +
> +	code = xnarch_fault_code(regs);
> +	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;
> +
> +	ksig.sig = sig;
> +	memcpy(&ksig.info, &si, sizeof(si));
> +	ksig.ka.sa.sa_flags = SA_SIGINFO | SA_RESTORER;
> +	ksig.ka.sa.sa_restorer = sys_ppd->sigrestorer;
> +	ksig.ka.sa.sa_handler = sys_ppd->sighand[sig];
> +
> +	ret = dovetail_setup_rt_signal_frame(&ksig, regs);
> +	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..76292e145
> --- /dev/null
> +++ b/lib/cobalt/arch/x86/sigreturn.c
> @@ -0,0 +1,32 @@
> +#include <cobalt/uapi/syscall.h>
> +#include "internal.h"
> +
> +extern void cobalt_sigreturn (void) asm ("__cobalt_sigreturn") __attribute__
> ((visibility ("hidden")));
> +
> +#ifdef __x86_64__
> +#define build_restorer(syscall_number)                                         \
> +	asm(".text\n"                                                          \
> +	    "    .align 16\n"                                                  \
> +	    "__cobalt_sigreturn:\n"                                            \
> +	    "    movq $ " #syscall_number ", %rax\n"                           \
> +	    "    syscall")
> +#endif
> +
> +#ifdef __i386__
> +#define build_restorer(syscall_number)                                         \
> +	asm(".text\n"                                                          \
> +	    "    .align 16\n"                                                  \
> +	    "__cobalt_sigreturn:\n"                                            \
> +	    "    movl $ " #syscall_number ", %eax\n"                           \
> +	    "    int  $0x80")
> +#endif
> +
> +/*
> + * __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 acb3989f1..4782d154a 100644
> --- a/lib/cobalt/internal.h
> +++ b/lib/cobalt/internal.h
> @@ -132,4 +132,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 40d315ebb..af174d570 100644
> --- a/lib/cobalt/signal.c
> +++ b/lib/cobalt/signal.c
> @@ -126,3 +126,16 @@ 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	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-05-09 13:17 ` [PATCH 1/3] [POC] test implementaion of rt-signals Johannes Kirchmair
@ 2023-05-12 17:38   ` Jan Kiszka
  2023-05-15  6:50     ` Johannes Kirchmair
  2023-08-09  9:50   ` Schaffner, Tobias
  1 sibling, 1 reply; 30+ messages in thread
From: Jan Kiszka @ 2023-05-12 17:38 UTC (permalink / raw)
  To: Johannes Kirchmair, xenomai, Schaffner, Tobias

On 09.05.23 15:17, Johannes Kirchmair wrote:
> Hello Jan and Tobias,
> 
> I just dropped the patches on the mailing list.
> For the dovetail functions I took a rather naive approach, using most of the frame setup code provided by Linux.
> I just tested it for 32bit and 64bit x86 Applications and it seems to work. 
> 
> I also added a tool rt_signal_hist that runs in a cycle and measures the time an exception handling takes.
> It is afterwards put into an txt file that reassembles an histogram of the timings.
> 
> Unfortunately as a 32bit application the rt_signal_hist tool does not run to completion, printing the following:
> " Xenomai/cobalt: sleeping while holding mutex
> CPU time limit exceeded"
> 
> Maybe the naive approach is not so reliable ;-/
> Hope I find the time the look into it. 
> 

I looked into the x86 signalframe helpers before and found some traces
of locking that make them incompatible - if I rember correctly. After
that, I dropped the idea of just removing the "static".

> Sorry for not putting more effort into this so fare.
> 
> The next most important step in my opinion would be to define a clean interface into dovetail for the signal frame setup and restoring.
> Actually that's the task I consider one of the harder and I am not so sure how to approach this.
> 

Exactly, and we need to involve Philippe now soon. Let me medidate over
some interface options as well. Will pick up if you don't find the time
soon.

Jan

> Best regards
> Johannes
> 
>> -----Original Message-----
>> From: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
>> Sent: Dienstag, 9. Mai 2023 15:14
>> To: xenomai@lists.linux.dev
>> Cc: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
>> Subject: [PATCH 1/3] [POC] test implementaion of rt-signals
>>
>> We implement rt signals to handle exceptions in rt stage.
>>
>> This is done using dovetail specific functions for setting up the signal
>> frame.
>>
>> This can be used to handle fpe exceptions on the fly, like fixing
>> division by zero. An other use case are breakpoints, implemented using the
>> illegal opcode exception. The real time handling of the breakpoints would
>> be handy for conditional breakpoints or also for stopping watchdogs and
>> other tasks in time.
>>
>> Signed-off-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     | 13 ++++
>>  kernel/cobalt/arch/x86/signal_ia32.c          | 75 +++++++++++++++++++
>>  kernel/cobalt/arch/x86/signal_ia64.c          | 26 +++++++
>>  kernel/cobalt/dovetail/kevents.c              |  5 ++
>>  kernel/cobalt/posix/process.c                 |  3 +-
>>  kernel/cobalt/posix/syscall.c                 | 28 +++++++
>>  kernel/cobalt/posix/syscall32.c               | 16 ++++
>>  kernel/cobalt/thread.c                        | 39 ++++++++++
>>  lib/cobalt/arch/x86/Makefile.am               |  2 +-
>>  lib/cobalt/arch/x86/sigreturn.c               | 32 ++++++++
>>  lib/cobalt/internal.h                         |  2 +
>>  lib/cobalt/signal.c                           | 13 ++++
>>  17 files changed, 266 insertions(+), 3 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
>>
>> 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 b79cb8429..33d468419 100644
>> --- a/include/cobalt/kernel/thread.h
>> +++ b/include/cobalt/kernel/thread.h
>> @@ -574,6 +574,8 @@ static inline void xnthread_propagate_schedparam(struct
>> xnthread *curr)
>>  		__xnthread_propagate_schedparam(curr);
>>  }
>>
>> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs);
>> +
>>  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 9646a0d97..6307fae7f 100644
>> --- a/include/cobalt/uapi/syscall.h
>> +++ b/include/cobalt/uapi/syscall.h
>> @@ -137,6 +137,12 @@
>>  #define sc_cobalt_recvmmsg64			114
>>  #define sc_cobalt_cond_wait_prologue64		115
>>
>> +/*
>> + * 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 93929b645..e725afbff 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 smi.o c1e.o
>> +xenomai-y := machine.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 745c32467..4d004680b 100644
>> --- a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
>> +++ b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
>> @@ -28,5 +28,18 @@
>>  #define xnarch_fault_bp_p(__nr)		((current->ptrace & PT_PTRACED)
>> &&	\
>>  					 ((__nr) == X86_TRAP_DB || (__nr) ==
>> X86_TRAP_BP))
>>  #define xnarch_fault_notify(__nr)	(!xnarch_fault_bp_p(__nr))
>> +#define xnarch_fault_code(__regs)		((__regs)->orig_ax)
>> +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);
>> +
>> +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);
>>
>>  #endif /* !_COBALT_X86_ASM_THREAD_H */
>> diff --git a/kernel/cobalt/arch/x86/signal_ia32.c
>> b/kernel/cobalt/arch/x86/signal_ia32.c
>> new file mode 100644
>> index 000000000..e78c8c4d4
>> --- /dev/null
>> +++ b/kernel/cobalt/arch/x86/signal_ia32.c
>> @@ -0,0 +1,75 @@
>> +#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>
>> +
>> +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;
>> +}
>> +
>> +int xnarch_rt_sigreturn_ia32(struct pt_regs *regs)
>> +{
>> +	int ret;
>> +
>> +	ret = dovetail_restore_rt_signal_frame(regs);
>> +	if (ret < 0)
>> +		goto badframe;
>> +
>> +	return regs->ax;
>> +
>> +badframe:
>> +	xnthread_call_mayday(xnthread_current(), SIGKILL);
>> +	return -1;
>> +}
>> +
>> diff --git a/kernel/cobalt/arch/x86/signal_ia64.c
>> b/kernel/cobalt/arch/x86/signal_ia64.c
>> new file mode 100644
>> index 000000000..a7044db40
>> --- /dev/null
>> +++ b/kernel/cobalt/arch/x86/signal_ia64.c
>> @@ -0,0 +1,26 @@
>> +// 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
>> + */
>> +
>> +#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>
>> +
>> +int xnarch_rt_sigreturn_ia64(struct pt_regs *regs)
>> +{
>> +	return dovetail_restore_rt_signal_frame(regs);
>> +}
>> +
>> diff --git a/kernel/cobalt/dovetail/kevents.c b/kernel/cobalt/dovetail/kevents.c
>> index 4da4f51b7..61417717b 100644
>> --- a/kernel/cobalt/dovetail/kevents.c
>> +++ b/kernel/cobalt/dovetail/kevents.c
>> @@ -57,6 +57,9 @@ void handle_oob_trap_entry(unsigned int trapnr, struct
>> pt_regs *regs)
>>  		xnsched_run();
>>  	}
>>
>> +	if (xnthread_handle_rt_signals(trapnr, regs) == 0)
>> +		return;
>> +
>>  	/*
>>  	 * If we experienced a trap on behalf of a shadow thread
>>  	 * running in primary mode, move it to the Linux domain,
>> @@ -88,6 +91,8 @@ void handle_oob_trap_entry(unsigned int trapnr, struct
>> pt_regs *regs)
>>  		xnstat_counter_inc(&thread->stat.pf);
>>
>>  	xnthread_relax(xnarch_fault_notify(trapnr), SIGDEBUG_MIGRATE_FAULT);
>> +
>> +	return;
>>  }
>>
>>  static inline int handle_setaffinity_event(struct dovetail_migration_data *d)
>> diff --git a/kernel/cobalt/posix/process.c b/kernel/cobalt/posix/process.c
>> index 1abc86f37..2069129cb 100644
>> --- a/kernel/cobalt/posix/process.c
>> +++ b/kernel/cobalt/posix/process.c
>> @@ -738,9 +738,10 @@ void cobalt_unregister_debugged_thread(struct
>> xnthread *thread)
>>  		cobalt_resume_debugged_process(process);
>>  }
>>
>> +#ifdef CONFIG_SMP
>> +
>>  int cobalt_handle_setaffinity_event(struct task_struct *task)
>>  {
>> -#ifdef CONFIG_SMP
>>  	struct xnthread *thread;
>>  	spl_t s;
>>
>> diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c
>> index 46c4998e4..b4bd4c587 100644
>> --- a/kernel/cobalt/posix/syscall.c
>> +++ b/kernel/cobalt/posix/syscall.c
>> @@ -277,6 +277,34 @@ static COBALT_SYSCALL(serialdbg, current,
>>  	return 0;
>>  }
>>
>> +static COBALT_SYSCALL(sigreturn, current, (void))
>> +{
>> +	struct pt_regs *regs = task_pt_regs(current);
>> +
>> +	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);
>> +}
>> +
>> +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 b65a0a760..f8b21bfb2 100644
>> --- a/kernel/cobalt/posix/syscall32.c
>> +++ b/kernel/cobalt/posix/syscall32.c
>> @@ -774,6 +774,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 old_timespec32 __user *u_ts,
>> diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
>> index 41804b24f..71f97c481 100644
>> --- a/kernel/cobalt/thread.c
>> +++ b/kernel/cobalt/thread.c
>> @@ -25,6 +25,7 @@
>>  #include <linux/signal.h>
>>  #include <linux/pid.h>
>>  #include <linux/sched.h>
>> +#include <asm/sighandling.h>
>>  #include <uapi/linux/sched/types.h>
>>  #include <cobalt/kernel/sched.h>
>>  #include <cobalt/kernel/timer.h>
>> @@ -43,6 +44,7 @@
>>  #include <pipeline/inband_work.h>
>>  #include <pipeline/sched.h>
>>  #include <trace/events/cobalt-core.h>
>> +#include "posix/process.h"
>>  #include "debug.h"
>>
>>  static DECLARE_WAIT_QUEUE_HEAD(join_all);
>> @@ -2520,6 +2522,43 @@ int xnthread_killall(int grace, int mask)
>>  }
>>  EXPORT_SYMBOL_GPL(xnthread_killall);
>>
>> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs)
>> +{
>> +	struct ksignal ksig;
>> +
>> +	unsigned int vector = trapnr;
>> +	unsigned int code = xnarch_fault_code(regs);
>> +	struct cobalt_ppd *sys_ppd;
>> +	int sig, ret = 0;
>> +	struct kernel_siginfo si;
>> +
>> +	code = xnarch_fault_code(regs);
>> +	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;
>> +
>> +	ksig.sig = sig;
>> +	memcpy(&ksig.info, &si, sizeof(si));
>> +	ksig.ka.sa.sa_flags = SA_SIGINFO | SA_RESTORER;
>> +	ksig.ka.sa.sa_restorer = sys_ppd->sigrestorer;
>> +	ksig.ka.sa.sa_handler = sys_ppd->sighand[sig];
>> +
>> +	ret = dovetail_setup_rt_signal_frame(&ksig, regs);
>> +	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..76292e145
>> --- /dev/null
>> +++ b/lib/cobalt/arch/x86/sigreturn.c
>> @@ -0,0 +1,32 @@
>> +#include <cobalt/uapi/syscall.h>
>> +#include "internal.h"
>> +
>> +extern void cobalt_sigreturn (void) asm ("__cobalt_sigreturn") __attribute__
>> ((visibility ("hidden")));
>> +
>> +#ifdef __x86_64__
>> +#define build_restorer(syscall_number)                                         \
>> +	asm(".text\n"                                                          \
>> +	    "    .align 16\n"                                                  \
>> +	    "__cobalt_sigreturn:\n"                                            \
>> +	    "    movq $ " #syscall_number ", %rax\n"                           \
>> +	    "    syscall")
>> +#endif
>> +
>> +#ifdef __i386__
>> +#define build_restorer(syscall_number)                                         \
>> +	asm(".text\n"                                                          \
>> +	    "    .align 16\n"                                                  \
>> +	    "__cobalt_sigreturn:\n"                                            \
>> +	    "    movl $ " #syscall_number ", %eax\n"                           \
>> +	    "    int  $0x80")
>> +#endif
>> +
>> +/*
>> + * __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 acb3989f1..4782d154a 100644
>> --- a/lib/cobalt/internal.h
>> +++ b/lib/cobalt/internal.h
>> @@ -132,4 +132,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 40d315ebb..af174d570 100644
>> --- a/lib/cobalt/signal.c
>> +++ b/lib/cobalt/signal.c
>> @@ -126,3 +126,16 @@ 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
> 

-- 
Siemens AG, Technology
Competence Center Embedded Linux


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

* RE: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-05-12 17:38   ` Jan Kiszka
@ 2023-05-15  6:50     ` Johannes Kirchmair
  2023-05-15 10:38       ` Jan Kiszka
  0 siblings, 1 reply; 30+ messages in thread
From: Johannes Kirchmair @ 2023-05-15  6:50 UTC (permalink / raw)
  To: Jan Kiszka, xenomai, Schaffner, Tobias

> -----Original Message-----
> From: Jan Kiszka <jan.kiszka@siemens.com>
> Sent: Freitag, 12. Mai 2023 19:39
> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
> xenomai@lists.linux.dev; Schaffner, Tobias <tobias.schaffner@siemens.com>
> Subject: Re: [PATCH 1/3] [POC] test implementaion of rt-signals
> 
> CAUTION: External E-Mail !
> 
> On 09.05.23 15:17, Johannes Kirchmair wrote:
> > Hello Jan and Tobias,
> >
> > I just dropped the patches on the mailing list.
> > For the dovetail functions I took a rather naive approach, using most of the
> frame setup code provided by Linux.
> > I just tested it for 32bit and 64bit x86 Applications and it seems to work.
> >
> > I also added a tool rt_signal_hist that runs in a cycle and measures the time an
> exception handling takes.
> > It is afterwards put into an txt file that reassembles an histogram of the timings.
> >
> > Unfortunately as a 32bit application the rt_signal_hist tool does not run to
> completion, printing the following:
> > " Xenomai/cobalt: sleeping while holding mutex
> > CPU time limit exceeded"
> >
> > Maybe the naive approach is not so reliable ;-/
> > Hope I find the time the look into it.
> >
> 
> I looked into the x86 signalframe helpers before and found some traces
> of locking that make them incompatible - if I rember correctly. After
> that, I dropped the idea of just removing the "static".
Do you remember where you saw the locking in the code, was it rather obvious or hidden?
When I had a look I did not see locking in the functions I used, so I thought dropping the "static" would be fine.

Would you still try to use some of the functions Linux provides?

> 
> > Sorry for not putting more effort into this so fare.
> >
> > The next most important step in my opinion would be to define a clean interface
> into dovetail for the signal frame setup and restoring.
> > Actually that's the task I consider one of the harder and I am not so sure how to
> approach this.
> >
> 
> Exactly, and we need to involve Philippe now soon. Let me medidate over
> some interface options as well. Will pick up if you don't find the time
> soon.
At the moment, I am not event sure, what the next task would be to continue with this feature.
As I am not sure how to define the interface for dovetail, I hesitate a little bit to change the code as it is right now.

What I could do is have a look why my hist-tool breaks in the 32bit user space case.

I also could try to provide an idea for the interface, but I am not so sure if it is of good use, as my knowledge of the Kernels internal workings is still rather limited.

Best regards Johannes

> 
> Jan
> 
> > Best regards
> > Johannes
> >
> >> -----Original Message-----
> >> From: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
> >> Sent: Dienstag, 9. Mai 2023 15:14
> >> To: xenomai@lists.linux.dev
> >> Cc: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
> >> Subject: [PATCH 1/3] [POC] test implementaion of rt-signals
> >>
> >> We implement rt signals to handle exceptions in rt stage.
> >>
> >> This is done using dovetail specific functions for setting up the signal
> >> frame.
> >>
> >> This can be used to handle fpe exceptions on the fly, like fixing
> >> division by zero. An other use case are breakpoints, implemented using the
> >> illegal opcode exception. The real time handling of the breakpoints would
> >> be handy for conditional breakpoints or also for stopping watchdogs and
> >> other tasks in time.
> >>
> >> Signed-off-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     | 13 ++++
> >>  kernel/cobalt/arch/x86/signal_ia32.c          | 75 +++++++++++++++++++
> >>  kernel/cobalt/arch/x86/signal_ia64.c          | 26 +++++++
> >>  kernel/cobalt/dovetail/kevents.c              |  5 ++
> >>  kernel/cobalt/posix/process.c                 |  3 +-
> >>  kernel/cobalt/posix/syscall.c                 | 28 +++++++
> >>  kernel/cobalt/posix/syscall32.c               | 16 ++++
> >>  kernel/cobalt/thread.c                        | 39 ++++++++++
> >>  lib/cobalt/arch/x86/Makefile.am               |  2 +-
> >>  lib/cobalt/arch/x86/sigreturn.c               | 32 ++++++++
> >>  lib/cobalt/internal.h                         |  2 +
> >>  lib/cobalt/signal.c                           | 13 ++++
> >>  17 files changed, 266 insertions(+), 3 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
> >>
> >> 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 b79cb8429..33d468419 100644
> >> --- a/include/cobalt/kernel/thread.h
> >> +++ b/include/cobalt/kernel/thread.h
> >> @@ -574,6 +574,8 @@ static inline void
> xnthread_propagate_schedparam(struct
> >> xnthread *curr)
> >>              __xnthread_propagate_schedparam(curr);
> >>  }
> >>
> >> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs);
> >> +
> >>  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 9646a0d97..6307fae7f 100644
> >> --- a/include/cobalt/uapi/syscall.h
> >> +++ b/include/cobalt/uapi/syscall.h
> >> @@ -137,6 +137,12 @@
> >>  #define sc_cobalt_recvmmsg64                        114
> >>  #define sc_cobalt_cond_wait_prologue64              115
> >>
> >> +/*
> >> + * 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 93929b645..e725afbff 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 smi.o c1e.o
> >> +xenomai-y := machine.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 745c32467..4d004680b 100644
> >> --- a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
> >> +++ b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
> >> @@ -28,5 +28,18 @@
> >>  #define xnarch_fault_bp_p(__nr)             ((current->ptrace & PT_PTRACED)
> >> &&   \
> >>                                       ((__nr) == X86_TRAP_DB || (__nr) ==
> >> X86_TRAP_BP))
> >>  #define xnarch_fault_notify(__nr)   (!xnarch_fault_bp_p(__nr))
> >> +#define xnarch_fault_code(__regs)           ((__regs)->orig_ax)
> >> +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);
> >> +
> >> +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);
> >>
> >>  #endif /* !_COBALT_X86_ASM_THREAD_H */
> >> diff --git a/kernel/cobalt/arch/x86/signal_ia32.c
> >> b/kernel/cobalt/arch/x86/signal_ia32.c
> >> new file mode 100644
> >> index 000000000..e78c8c4d4
> >> --- /dev/null
> >> +++ b/kernel/cobalt/arch/x86/signal_ia32.c
> >> @@ -0,0 +1,75 @@
> >> +#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>
> >> +
> >> +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;
> >> +}
> >> +
> >> +int xnarch_rt_sigreturn_ia32(struct pt_regs *regs)
> >> +{
> >> +    int ret;
> >> +
> >> +    ret = dovetail_restore_rt_signal_frame(regs);
> >> +    if (ret < 0)
> >> +            goto badframe;
> >> +
> >> +    return regs->ax;
> >> +
> >> +badframe:
> >> +    xnthread_call_mayday(xnthread_current(), SIGKILL);
> >> +    return -1;
> >> +}
> >> +
> >> diff --git a/kernel/cobalt/arch/x86/signal_ia64.c
> >> b/kernel/cobalt/arch/x86/signal_ia64.c
> >> new file mode 100644
> >> index 000000000..a7044db40
> >> --- /dev/null
> >> +++ b/kernel/cobalt/arch/x86/signal_ia64.c
> >> @@ -0,0 +1,26 @@
> >> +// 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
> >> + */
> >> +
> >> +#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>
> >> +
> >> +int xnarch_rt_sigreturn_ia64(struct pt_regs *regs)
> >> +{
> >> +    return dovetail_restore_rt_signal_frame(regs);
> >> +}
> >> +
> >> diff --git a/kernel/cobalt/dovetail/kevents.c b/kernel/cobalt/dovetail/kevents.c
> >> index 4da4f51b7..61417717b 100644
> >> --- a/kernel/cobalt/dovetail/kevents.c
> >> +++ b/kernel/cobalt/dovetail/kevents.c
> >> @@ -57,6 +57,9 @@ void handle_oob_trap_entry(unsigned int trapnr, struct
> >> pt_regs *regs)
> >>              xnsched_run();
> >>      }
> >>
> >> +    if (xnthread_handle_rt_signals(trapnr, regs) == 0)
> >> +            return;
> >> +
> >>      /*
> >>       * If we experienced a trap on behalf of a shadow thread
> >>       * running in primary mode, move it to the Linux domain,
> >> @@ -88,6 +91,8 @@ void handle_oob_trap_entry(unsigned int trapnr, struct
> >> pt_regs *regs)
> >>              xnstat_counter_inc(&thread->stat.pf);
> >>
> >>      xnthread_relax(xnarch_fault_notify(trapnr), SIGDEBUG_MIGRATE_FAULT);
> >> +
> >> +    return;
> >>  }
> >>
> >>  static inline int handle_setaffinity_event(struct dovetail_migration_data *d)
> >> diff --git a/kernel/cobalt/posix/process.c b/kernel/cobalt/posix/process.c
> >> index 1abc86f37..2069129cb 100644
> >> --- a/kernel/cobalt/posix/process.c
> >> +++ b/kernel/cobalt/posix/process.c
> >> @@ -738,9 +738,10 @@ void cobalt_unregister_debugged_thread(struct
> >> xnthread *thread)
> >>              cobalt_resume_debugged_process(process);
> >>  }
> >>
> >> +#ifdef CONFIG_SMP
> >> +
> >>  int cobalt_handle_setaffinity_event(struct task_struct *task)
> >>  {
> >> -#ifdef CONFIG_SMP
> >>      struct xnthread *thread;
> >>      spl_t s;
> >>
> >> diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c
> >> index 46c4998e4..b4bd4c587 100644
> >> --- a/kernel/cobalt/posix/syscall.c
> >> +++ b/kernel/cobalt/posix/syscall.c
> >> @@ -277,6 +277,34 @@ static COBALT_SYSCALL(serialdbg, current,
> >>      return 0;
> >>  }
> >>
> >> +static COBALT_SYSCALL(sigreturn, current, (void))
> >> +{
> >> +    struct pt_regs *regs = task_pt_regs(current);
> >> +
> >> +    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);
> >> +}
> >> +
> >> +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 b65a0a760..f8b21bfb2 100644
> >> --- a/kernel/cobalt/posix/syscall32.c
> >> +++ b/kernel/cobalt/posix/syscall32.c
> >> @@ -774,6 +774,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 old_timespec32 __user *u_ts,
> >> diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
> >> index 41804b24f..71f97c481 100644
> >> --- a/kernel/cobalt/thread.c
> >> +++ b/kernel/cobalt/thread.c
> >> @@ -25,6 +25,7 @@
> >>  #include <linux/signal.h>
> >>  #include <linux/pid.h>
> >>  #include <linux/sched.h>
> >> +#include <asm/sighandling.h>
> >>  #include <uapi/linux/sched/types.h>
> >>  #include <cobalt/kernel/sched.h>
> >>  #include <cobalt/kernel/timer.h>
> >> @@ -43,6 +44,7 @@
> >>  #include <pipeline/inband_work.h>
> >>  #include <pipeline/sched.h>
> >>  #include <trace/events/cobalt-core.h>
> >> +#include "posix/process.h"
> >>  #include "debug.h"
> >>
> >>  static DECLARE_WAIT_QUEUE_HEAD(join_all);
> >> @@ -2520,6 +2522,43 @@ int xnthread_killall(int grace, int mask)
> >>  }
> >>  EXPORT_SYMBOL_GPL(xnthread_killall);
> >>
> >> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs)
> >> +{
> >> +    struct ksignal ksig;
> >> +
> >> +    unsigned int vector = trapnr;
> >> +    unsigned int code = xnarch_fault_code(regs);
> >> +    struct cobalt_ppd *sys_ppd;
> >> +    int sig, ret = 0;
> >> +    struct kernel_siginfo si;
> >> +
> >> +    code = xnarch_fault_code(regs);
> >> +    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;
> >> +
> >> +    ksig.sig = sig;
> >> +    memcpy(&ksig.info, &si, sizeof(si));
> >> +    ksig.ka.sa.sa_flags = SA_SIGINFO | SA_RESTORER;
> >> +    ksig.ka.sa.sa_restorer = sys_ppd->sigrestorer;
> >> +    ksig.ka.sa.sa_handler = sys_ppd->sighand[sig];
> >> +
> >> +    ret = dovetail_setup_rt_signal_frame(&ksig, regs);
> >> +    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..76292e145
> >> --- /dev/null
> >> +++ b/lib/cobalt/arch/x86/sigreturn.c
> >> @@ -0,0 +1,32 @@
> >> +#include <cobalt/uapi/syscall.h>
> >> +#include "internal.h"
> >> +
> >> +extern void cobalt_sigreturn (void) asm ("__cobalt_sigreturn") __attribute__
> >> ((visibility ("hidden")));
> >> +
> >> +#ifdef __x86_64__
> >> +#define build_restorer(syscall_number)                                         \
> >> +    asm(".text\n"                                                          \
> >> +        "    .align 16\n"                                                  \
> >> +        "__cobalt_sigreturn:\n"                                            \
> >> +        "    movq $ " #syscall_number ", %rax\n"                           \
> >> +        "    syscall")
> >> +#endif
> >> +
> >> +#ifdef __i386__
> >> +#define build_restorer(syscall_number)                                         \
> >> +    asm(".text\n"                                                          \
> >> +        "    .align 16\n"                                                  \
> >> +        "__cobalt_sigreturn:\n"                                            \
> >> +        "    movl $ " #syscall_number ", %eax\n"                           \
> >> +        "    int  $0x80")
> >> +#endif
> >> +
> >> +/*
> >> + * __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 acb3989f1..4782d154a 100644
> >> --- a/lib/cobalt/internal.h
> >> +++ b/lib/cobalt/internal.h
> >> @@ -132,4 +132,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 40d315ebb..af174d570 100644
> >> --- a/lib/cobalt/signal.c
> >> +++ b/lib/cobalt/signal.c
> >> @@ -126,3 +126,16 @@ 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
> >
> 
> --
> Siemens AG, Technology
> Competence Center Embedded Linux


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

* Re: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-05-15  6:50     ` Johannes Kirchmair
@ 2023-05-15 10:38       ` Jan Kiszka
  2023-05-16  6:46         ` Johannes Kirchmair
  0 siblings, 1 reply; 30+ messages in thread
From: Jan Kiszka @ 2023-05-15 10:38 UTC (permalink / raw)
  To: Johannes Kirchmair, xenomai, Schaffner, Tobias

On 15.05.23 08:50, Johannes Kirchmair wrote:
>> -----Original Message-----
>> From: Jan Kiszka <jan.kiszka@siemens.com>
>> Sent: Freitag, 12. Mai 2023 19:39
>> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
>> xenomai@lists.linux.dev; Schaffner, Tobias <tobias.schaffner@siemens.com>
>> Subject: Re: [PATCH 1/3] [POC] test implementaion of rt-signals
>>
>> CAUTION: External E-Mail !
>>
>> On 09.05.23 15:17, Johannes Kirchmair wrote:
>>> Hello Jan and Tobias,
>>>
>>> I just dropped the patches on the mailing list.
>>> For the dovetail functions I took a rather naive approach, using most of the
>> frame setup code provided by Linux.
>>> I just tested it for 32bit and 64bit x86 Applications and it seems to work.
>>>
>>> I also added a tool rt_signal_hist that runs in a cycle and measures the time an
>> exception handling takes.
>>> It is afterwards put into an txt file that reassembles an histogram of the timings.
>>>
>>> Unfortunately as a 32bit application the rt_signal_hist tool does not run to
>> completion, printing the following:
>>> " Xenomai/cobalt: sleeping while holding mutex
>>> CPU time limit exceeded"
>>>
>>> Maybe the naive approach is not so reliable ;-/
>>> Hope I find the time the look into it.
>>>
>>
>> I looked into the x86 signalframe helpers before and found some traces
>> of locking that make them incompatible - if I rember correctly. After
>> that, I dropped the idea of just removing the "static".
> Do you remember where you saw the locking in the code, was it rather obvious or hidden?
> When I had a look I did not see locking in the functions I used, so I thought dropping the "static" would be fine.
> 
> Would you still try to use some of the functions Linux provides?
> 

I don't recall too many details, specficially not which kernel version I
looked at. Maybe part of my concerns was that I started from
setup_rt_frame (rseq_signal_deliver), rather than x64_setup_rt_frame & Co.

I was now digging into 6.3, and one area that is sensitive is the FPU
handling. We end up in fault_in_readable, and I'm not sure yet if that
is ok. The whole FPU save/restore needs a careful check, or more, if we
are not violating the assumptions of OOB.

But did you run your code with full lock debugging enabled already? Did
you stress faulting sigframe setups/restores? That would be needed as well.

>>
>>> Sorry for not putting more effort into this so fare.
>>>
>>> The next most important step in my opinion would be to define a clean interface
>> into dovetail for the signal frame setup and restoring.
>>> Actually that's the task I consider one of the harder and I am not so sure how to
>> approach this.
>>>
>>
>> Exactly, and we need to involve Philippe now soon. Let me medidate over
>> some interface options as well. Will pick up if you don't find the time
>> soon.
> At the moment, I am not event sure, what the next task would be to continue with this feature.
> As I am not sure how to define the interface for dovetail, I hesitate a little bit to change the code as it is right now.
> 
> What I could do is have a look why my hist-tool breaks in the 32bit user space case.
> 

Agree, this needs to be understood.

> I also could try to provide an idea for the interface, but I am not so sure if it is of good use, as my knowledge of the Kernels internal workings is still rather limited.

In general, requests from the co-kernel core to switch to a signal stack
(signal setup) or restore from it (sigreturn) sounds like a reasonable
abstraction to me for now.

Jan

-- 
Siemens AG, Technology
Competence Center Embedded Linux


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

* RE: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-05-15 10:38       ` Jan Kiszka
@ 2023-05-16  6:46         ` Johannes Kirchmair
  2023-05-16  6:52           ` Jan Kiszka
  0 siblings, 1 reply; 30+ messages in thread
From: Johannes Kirchmair @ 2023-05-16  6:46 UTC (permalink / raw)
  To: Jan Kiszka, xenomai, Schaffner, Tobias

Hello, 

> -----Original Message-----
> From: Jan Kiszka <jan.kiszka@siemens.com>
> Sent: Montag, 15. Mai 2023 12:38
> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
> xenomai@lists.linux.dev; Schaffner, Tobias <tobias.schaffner@siemens.com>
> Subject: Re: [PATCH 1/3] [POC] test implementaion of rt-signals
> 
> CAUTION: External E-Mail !
> 
> On 15.05.23 08:50, Johannes Kirchmair wrote:
> >> -----Original Message-----
> >> From: Jan Kiszka <jan.kiszka@siemens.com>
> >> Sent: Freitag, 12. Mai 2023 19:39
> >> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
> >> xenomai@lists.linux.dev; Schaffner, Tobias <tobias.schaffner@siemens.com>
> >> Subject: Re: [PATCH 1/3] [POC] test implementaion of rt-signals
> >>
> >> CAUTION: External E-Mail !
> >>
> >> On 09.05.23 15:17, Johannes Kirchmair wrote:
> >>> Hello Jan and Tobias,
> >>>
> >>> I just dropped the patches on the mailing list.
> >>> For the dovetail functions I took a rather naive approach, using most of the
> >> frame setup code provided by Linux.
> >>> I just tested it for 32bit and 64bit x86 Applications and it seems to work.
> >>>
> >>> I also added a tool rt_signal_hist that runs in a cycle and measures the time an
> >> exception handling takes.
> >>> It is afterwards put into an txt file that reassembles an histogram of the
> timings.
> >>>
> >>> Unfortunately as a 32bit application the rt_signal_hist tool does not run to
> >> completion, printing the following:
> >>> " Xenomai/cobalt: sleeping while holding mutex
> >>> CPU time limit exceeded"
> >>>
> >>> Maybe the naive approach is not so reliable ;-/
> >>> Hope I find the time the look into it.
> >>>
> >>
> >> I looked into the x86 signalframe helpers before and found some traces
> >> of locking that make them incompatible - if I rember correctly. After
> >> that, I dropped the idea of just removing the "static".
> > Do you remember where you saw the locking in the code, was it rather obvious
> or hidden?
> > When I had a look I did not see locking in the functions I used, so I thought
> dropping the "static" would be fine.
> >
> > Would you still try to use some of the functions Linux provides?
> >
> 
> I don't recall too many details, specficially not which kernel version I
> looked at. Maybe part of my concerns was that I started from
> setup_rt_frame (rseq_signal_deliver), rather than x64_setup_rt_frame & Co.
> 
> I was now digging into 6.3, and one area that is sensitive is the FPU
> handling. We end up in fault_in_readable, and I'm not sure yet if that
> is ok. The whole FPU save/restore needs a careful check, or more, if we
> are not violating the assumptions of OOB.
> 
> But did you run your code with full lock debugging enabled already? Did
> you stress faulting sigframe setups/restores? That would be needed as well.

Yes, thought about activating debugging in kernel, yesterday. Resulting in the following kernel output:
[   83.338288] ------------[ cut here ]------------
[   83.338292] WARNING: CPU: 3 PID: 268 at mm/memory.c:5640 __might_fault+0x28/0x30
[   83.338299] Modules linked in:
[   83.338301] CPU: 3 PID: 268 Comm: signal_test_tas Tainted: G        W          6.3.0+ #7
[   83.338304] Hardware name: Default string Default string/Default string, BIOS 5.19 04/28/2022
[   83.338305] IRQ stage: Xenomai
[   83.338306] RIP: 0010:__might_fault+0x28/0x30
[   83.338308] Code: 90 90 f3 0f 1e fa 0f 1f 44 00 00 55 65 8b 05 57 11 24 6a 48 89 e5 a9 00 00 00 02 75 06 5d c3 cc cc cc cc 9c 58 f6 c4 02 75 f3 <0f> 0b 5d c3 cc cc cc cc 90 90 90 90 90 90 90 90 90 90 90 90 90 90
[   83.338311] RSP: 0000:ffffafbc417d3cb8 EFLAGS: 00010046
[   83.338313] RAX: 0000000000000006 RBX: 00000000df53adbc RCX: ffffafbc417d3d68
[   83.338314] RDX: 00000000000002b4 RSI: 0000000000000060 RDI: ffffffff9782ead0
[   83.338315] RBP: ffffafbc417d3cb8 R08: ffffafbc417d3e48 R09: 0000000000000001
[   83.338316] R10: 0000000000000001 R11: 0000000000000000 R12: 00000000df53af40
[   83.338317] R13: ffffafbc417d3db8 R14: 0000000002000000 R15: 0000000000000000
[   83.338318] FS:  0000000000000000(0000) GS:ffff966e2e000000(0063) knlGS:00000000df53bb40
[   83.338320] CS:  0010 DS: 002b ES: 002b CR0: 0000000080050033
[   83.338321] CR2: 00000000f7ee7080 CR3: 0000000006550000 CR4: 0000000000350ee0
[   83.338323] Call Trace:
[   83.338325]  <TASK>
[   83.338328]  copy_fpstate_to_sigframe+0xaa/0x410
[   83.338335]  get_sigframe+0xdc/0x2e0
[   83.338339]  ia32_setup_rt_frame+0x67/0x2f0
[   83.338343]  dovetail_setup_rt_signal_frame+0x43/0x50
[   83.338346]  xnthread_handle_rt_signals+0xf2/0x130
[   83.338349]  ? handle_head_syscall+0x179/0x550
[   83.338352]  ? __pfx_CoBaLt_sigaction+0x10/0x10
[   83.338355]  ? handle_head_syscall+0x179/0x550
[   83.338357]  ? __pfx_CoBaLt_sigaction+0x10/0x10
[   83.338359]  handle_oob_trap_entry+0x1b6/0x3c0
[   83.338362]  ? syscall_enter_from_user_mode_work+0x31/0xb0
[   83.338366]  __oob_trap_notify+0x2f/0x40
[   83.338368]  exc_invalid_op+0xb7/0x110
[   83.338371]  asm_exc_invalid_op+0x1f/0x30
[   83.338374] RIP: 0023:0x5659868a
[   83.338376] Code: Unable to access opcode bytes at 0x56598660.
[   83.338377] RSP: 002b:00000000df53b1c0 EFLAGS: 00010246
[   83.338378] RAX: 00000000f453ff4d RBX: 000000005659b000 RCX: 0000000000000000
[   83.338379] RDX: 0000000000000012 RSI: 00000000f453ff4d RDI: 00000000f7ed3ac8
[   83.338380] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
[   83.338381] R10: 0000000000000000 R11: 0000000000000296 R12: 0000000000000000
[   83.338382] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
[   83.338386]  </TASK>
[   83.338387] irq event stamp: 0
[   83.338388] hardirqs last  enabled at (0): [<0000000000000000>] 0x0
[   83.338389] hardirqs last disabled at (0): [<ffffffff95cb68eb>] copy_process+0x7fb/0x21b0
[   83.338393] softirqs last  enabled at (0): [<ffffffff95cb68ef>] copy_process+0x7ff/0x21b0
[   83.338395] softirqs last disabled at (0): [<0000000000000000>] 0x0
[   83.338396] ---[ end trace 0000000000000000 ]---

Do you think, this is related to the message I get on execution.

Other question: By "stress faulting" you mean running tests while generating a lot of cpu load?

  Johannes
> 
> >>
> >>> Sorry for not putting more effort into this so fare.
> >>>
> >>> The next most important step in my opinion would be to define a clean
> interface
> >> into dovetail for the signal frame setup and restoring.
> >>> Actually that's the task I consider one of the harder and I am not so sure how
> to
> >> approach this.
> >>>
> >>
> >> Exactly, and we need to involve Philippe now soon. Let me medidate over
> >> some interface options as well. Will pick up if you don't find the time
> >> soon.
> > At the moment, I am not event sure, what the next task would be to continue
> with this feature.
> > As I am not sure how to define the interface for dovetail, I hesitate a little bit to
> change the code as it is right now.
> >
> > What I could do is have a look why my hist-tool breaks in the 32bit user space
> case.
> >
> 
> Agree, this needs to be understood.
> 
> > I also could try to provide an idea for the interface, but I am not so sure if it is of
> good use, as my knowledge of the Kernels internal workings is still rather limited.
> 
> In general, requests from the co-kernel core to switch to a signal stack
> (signal setup) or restore from it (sigreturn) sounds like a reasonable
> abstraction to me for now.
> 
> Jan
> 
> --
> Siemens AG, Technology
> Competence Center Embedded Linux


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

* Re: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-05-16  6:46         ` Johannes Kirchmair
@ 2023-05-16  6:52           ` Jan Kiszka
  0 siblings, 0 replies; 30+ messages in thread
From: Jan Kiszka @ 2023-05-16  6:52 UTC (permalink / raw)
  To: Johannes Kirchmair, xenomai, Schaffner, Tobias

On 16.05.23 08:46, Johannes Kirchmair wrote:
> Hello, 
> 
>> -----Original Message-----
>> From: Jan Kiszka <jan.kiszka@siemens.com>
>> Sent: Montag, 15. Mai 2023 12:38
>> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
>> xenomai@lists.linux.dev; Schaffner, Tobias <tobias.schaffner@siemens.com>
>> Subject: Re: [PATCH 1/3] [POC] test implementaion of rt-signals
>>
>> CAUTION: External E-Mail !
>>
>> On 15.05.23 08:50, Johannes Kirchmair wrote:
>>>> -----Original Message-----
>>>> From: Jan Kiszka <jan.kiszka@siemens.com>
>>>> Sent: Freitag, 12. Mai 2023 19:39
>>>> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
>>>> xenomai@lists.linux.dev; Schaffner, Tobias <tobias.schaffner@siemens.com>
>>>> Subject: Re: [PATCH 1/3] [POC] test implementaion of rt-signals
>>>>
>>>> CAUTION: External E-Mail !
>>>>
>>>> On 09.05.23 15:17, Johannes Kirchmair wrote:
>>>>> Hello Jan and Tobias,
>>>>>
>>>>> I just dropped the patches on the mailing list.
>>>>> For the dovetail functions I took a rather naive approach, using most of the
>>>> frame setup code provided by Linux.
>>>>> I just tested it for 32bit and 64bit x86 Applications and it seems to work.
>>>>>
>>>>> I also added a tool rt_signal_hist that runs in a cycle and measures the time an
>>>> exception handling takes.
>>>>> It is afterwards put into an txt file that reassembles an histogram of the
>> timings.
>>>>>
>>>>> Unfortunately as a 32bit application the rt_signal_hist tool does not run to
>>>> completion, printing the following:
>>>>> " Xenomai/cobalt: sleeping while holding mutex
>>>>> CPU time limit exceeded"
>>>>>
>>>>> Maybe the naive approach is not so reliable ;-/
>>>>> Hope I find the time the look into it.
>>>>>
>>>>
>>>> I looked into the x86 signalframe helpers before and found some traces
>>>> of locking that make them incompatible - if I rember correctly. After
>>>> that, I dropped the idea of just removing the "static".
>>> Do you remember where you saw the locking in the code, was it rather obvious
>> or hidden?
>>> When I had a look I did not see locking in the functions I used, so I thought
>> dropping the "static" would be fine.
>>>
>>> Would you still try to use some of the functions Linux provides?
>>>
>>
>> I don't recall too many details, specficially not which kernel version I
>> looked at. Maybe part of my concerns was that I started from
>> setup_rt_frame (rseq_signal_deliver), rather than x64_setup_rt_frame & Co.
>>
>> I was now digging into 6.3, and one area that is sensitive is the FPU
>> handling. We end up in fault_in_readable, and I'm not sure yet if that
>> is ok. The whole FPU save/restore needs a careful check, or more, if we
>> are not violating the assumptions of OOB.
>>
>> But did you run your code with full lock debugging enabled already? Did
>> you stress faulting sigframe setups/restores? That would be needed as well.
> 
> Yes, thought about activating debugging in kernel, yesterday. Resulting in the following kernel output:
> [   83.338288] ------------[ cut here ]------------
> [   83.338292] WARNING: CPU: 3 PID: 268 at mm/memory.c:5640 __might_fault+0x28/0x30
> [   83.338299] Modules linked in:
> [   83.338301] CPU: 3 PID: 268 Comm: signal_test_tas Tainted: G        W          6.3.0+ #7
> [   83.338304] Hardware name: Default string Default string/Default string, BIOS 5.19 04/28/2022
> [   83.338305] IRQ stage: Xenomai
> [   83.338306] RIP: 0010:__might_fault+0x28/0x30
> [   83.338308] Code: 90 90 f3 0f 1e fa 0f 1f 44 00 00 55 65 8b 05 57 11 24 6a 48 89 e5 a9 00 00 00 02 75 06 5d c3 cc cc cc cc 9c 58 f6 c4 02 75 f3 <0f> 0b 5d c3 cc cc cc cc 90 90 90 90 90 90 90 90 90 90 90 90 90 90
> [   83.338311] RSP: 0000:ffffafbc417d3cb8 EFLAGS: 00010046
> [   83.338313] RAX: 0000000000000006 RBX: 00000000df53adbc RCX: ffffafbc417d3d68
> [   83.338314] RDX: 00000000000002b4 RSI: 0000000000000060 RDI: ffffffff9782ead0
> [   83.338315] RBP: ffffafbc417d3cb8 R08: ffffafbc417d3e48 R09: 0000000000000001
> [   83.338316] R10: 0000000000000001 R11: 0000000000000000 R12: 00000000df53af40
> [   83.338317] R13: ffffafbc417d3db8 R14: 0000000002000000 R15: 0000000000000000
> [   83.338318] FS:  0000000000000000(0000) GS:ffff966e2e000000(0063) knlGS:00000000df53bb40
> [   83.338320] CS:  0010 DS: 002b ES: 002b CR0: 0000000080050033
> [   83.338321] CR2: 00000000f7ee7080 CR3: 0000000006550000 CR4: 0000000000350ee0
> [   83.338323] Call Trace:
> [   83.338325]  <TASK>
> [   83.338328]  copy_fpstate_to_sigframe+0xaa/0x410
> [   83.338335]  get_sigframe+0xdc/0x2e0
> [   83.338339]  ia32_setup_rt_frame+0x67/0x2f0
> [   83.338343]  dovetail_setup_rt_signal_frame+0x43/0x50
> [   83.338346]  xnthread_handle_rt_signals+0xf2/0x130
> [   83.338349]  ? handle_head_syscall+0x179/0x550
> [   83.338352]  ? __pfx_CoBaLt_sigaction+0x10/0x10
> [   83.338355]  ? handle_head_syscall+0x179/0x550
> [   83.338357]  ? __pfx_CoBaLt_sigaction+0x10/0x10
> [   83.338359]  handle_oob_trap_entry+0x1b6/0x3c0
> [   83.338362]  ? syscall_enter_from_user_mode_work+0x31/0xb0
> [   83.338366]  __oob_trap_notify+0x2f/0x40
> [   83.338368]  exc_invalid_op+0xb7/0x110
> [   83.338371]  asm_exc_invalid_op+0x1f/0x30
> [   83.338374] RIP: 0023:0x5659868a
> [   83.338376] Code: Unable to access opcode bytes at 0x56598660.
> [   83.338377] RSP: 002b:00000000df53b1c0 EFLAGS: 00010246
> [   83.338378] RAX: 00000000f453ff4d RBX: 000000005659b000 RCX: 0000000000000000
> [   83.338379] RDX: 0000000000000012 RSI: 00000000f453ff4d RDI: 00000000f7ed3ac8
> [   83.338380] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
> [   83.338381] R10: 0000000000000000 R11: 0000000000000296 R12: 0000000000000000
> [   83.338382] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
> [   83.338386]  </TASK>
> [   83.338387] irq event stamp: 0
> [   83.338388] hardirqs last  enabled at (0): [<0000000000000000>] 0x0
> [   83.338389] hardirqs last disabled at (0): [<ffffffff95cb68eb>] copy_process+0x7fb/0x21b0
> [   83.338393] softirqs last  enabled at (0): [<ffffffff95cb68ef>] copy_process+0x7ff/0x21b0
> [   83.338395] softirqs last disabled at (0): [<0000000000000000>] 0x0
> [   83.338396] ---[ end trace 0000000000000000 ]---
> 
> Do you think, this is related to the message I get on execution.

I don't think so unless we actually ran into a fault in your 32-bit case.

This one here is unhappy that a fault might be taken with hard IRQs off,
see __might_fault:

 #if defined(CONFIG_PROVE_LOCKING) || defined(CONFIG_DEBUG_ATOMIC_SLEEP)
 void __might_fault(const char *file, int line)
 {
+       /*
+        * When running over the oob stage (e.g. some co-kernel's own
+        * thread), we should only make sure to run with hw IRQs
+        * enabled before accessing the memory.
+        */
+       if (running_oob()) {
+               WARN_ON_ONCE(hard_irqs_disabled());
+               return;
+       }

> 
> Other question: By "stress faulting" you mean running tests while generating a lot of cpu load?

No, I meant constructing fault-causing sigframes or stacks so that we
actually take faults. Normally, the involved memory should all be
present and locked into the process.

Jan

-- 
Siemens AG, Technology
Competence Center Embedded Linux


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

* Re: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-05-09 13:17 ` [PATCH 1/3] [POC] test implementaion of rt-signals Johannes Kirchmair
  2023-05-12 17:38   ` Jan Kiszka
@ 2023-08-09  9:50   ` Schaffner, Tobias
  1 sibling, 0 replies; 30+ messages in thread
From: Schaffner, Tobias @ 2023-08-09  9:50 UTC (permalink / raw)
  To: johannes.kirchmair, xenomai, Kiszka, Jan

Hi Johannes,

On 09.05.23 15:17, Johannes Kirchmair wrote:
> Hello Jan and Tobias,
> 
> I just dropped the patches on the mailing list.
> For the dovetail functions I took a rather naive approach, using most of the frame setup code provided by Linux.
> I just tested it for 32bit and 64bit x86 Applications and it seems to work.
> 
> I also added a tool rt_signal_hist that runs in a cycle and measures the time an exception handling takes.
> It is afterwards put into an txt file that reassembles an histogram of the timings.
> 
> Unfortunately as a 32bit application the rt_signal_hist tool does not run to completion, printing the following:
> " Xenomai/cobalt: sleeping while holding mutex
> CPU time limit exceeded"

I finally had some time to look at it again.

There is a problem in the dovetail patch you send.

In dovetail_restore_32_rt_signal_frame the ax register is returned. This 
is a long unsigned int that is returned as an int. When it becomes 
negative every now and then, it is interpreted as an error.

The dovetail_restore_64_rt_signal_frame function has the same issue, but 
the return value is ignored for x64.

As you already noticed:
The xnarch_rt_sigreturn_ia32 reacts with a 
xnthread_call_mayday(xnthread_current(), SIGKILL);

SIGKILL may not be used in this context. It is interpreted as a 
sigdebug_reason which leads to the wrong SIGDEBUG_MUTEX_SLEEP signal and 
the corresponding "Xenomai/cobalt: sleeping while holding mutex" message.


All the best,
Tobias

> Maybe the naive approach is not so reliable ;-/
> Hope I find the time the look into it.
> 
> Sorry for not putting more effort into this so fare.
> 
> The next most important step in my opinion would be to define a clean interface into dovetail for the signal frame setup and restoring.
> Actually that's the task I consider one of the harder and I am not so sure how to approach this.
> 
> Best regards
> Johannes
> 
>> -----Original Message-----
>> From: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
>> Sent: Dienstag, 9. Mai 2023 15:14
>> To: xenomai@lists.linux.dev
>> Cc: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
>> Subject: [PATCH 1/3] [POC] test implementaion of rt-signals
>>
>> We implement rt signals to handle exceptions in rt stage.
>>
>> This is done using dovetail specific functions for setting up the signal
>> frame.
>>
>> This can be used to handle fpe exceptions on the fly, like fixing
>> division by zero. An other use case are breakpoints, implemented using the
>> illegal opcode exception. The real time handling of the breakpoints would
>> be handy for conditional breakpoints or also for stopping watchdogs and
>> other tasks in time.
>>
>> Signed-off-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     | 13 ++++
>>   kernel/cobalt/arch/x86/signal_ia32.c          | 75 +++++++++++++++++++
>>   kernel/cobalt/arch/x86/signal_ia64.c          | 26 +++++++
>>   kernel/cobalt/dovetail/kevents.c              |  5 ++
>>   kernel/cobalt/posix/process.c                 |  3 +-
>>   kernel/cobalt/posix/syscall.c                 | 28 +++++++
>>   kernel/cobalt/posix/syscall32.c               | 16 ++++
>>   kernel/cobalt/thread.c                        | 39 ++++++++++
>>   lib/cobalt/arch/x86/Makefile.am               |  2 +-
>>   lib/cobalt/arch/x86/sigreturn.c               | 32 ++++++++
>>   lib/cobalt/internal.h                         |  2 +
>>   lib/cobalt/signal.c                           | 13 ++++
>>   17 files changed, 266 insertions(+), 3 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
>>
>> 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 b79cb8429..33d468419 100644
>> --- a/include/cobalt/kernel/thread.h
>> +++ b/include/cobalt/kernel/thread.h
>> @@ -574,6 +574,8 @@ static inline void xnthread_propagate_schedparam(struct
>> xnthread *curr)
>>   		__xnthread_propagate_schedparam(curr);
>>   }
>>
>> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs);
>> +
>>   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 9646a0d97..6307fae7f 100644
>> --- a/include/cobalt/uapi/syscall.h
>> +++ b/include/cobalt/uapi/syscall.h
>> @@ -137,6 +137,12 @@
>>   #define sc_cobalt_recvmmsg64			114
>>   #define sc_cobalt_cond_wait_prologue64		115
>>
>> +/*
>> + * 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 93929b645..e725afbff 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 smi.o c1e.o
>> +xenomai-y := machine.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 745c32467..4d004680b 100644
>> --- a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
>> +++ b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
>> @@ -28,5 +28,18 @@
>>   #define xnarch_fault_bp_p(__nr)		((current->ptrace & PT_PTRACED)
>> &&	\
>>   					 ((__nr) == X86_TRAP_DB || (__nr) ==
>> X86_TRAP_BP))
>>   #define xnarch_fault_notify(__nr)	(!xnarch_fault_bp_p(__nr))
>> +#define xnarch_fault_code(__regs)		((__regs)->orig_ax)
>> +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);
>> +
>> +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);
>>
>>   #endif /* !_COBALT_X86_ASM_THREAD_H */
>> diff --git a/kernel/cobalt/arch/x86/signal_ia32.c
>> b/kernel/cobalt/arch/x86/signal_ia32.c
>> new file mode 100644
>> index 000000000..e78c8c4d4
>> --- /dev/null
>> +++ b/kernel/cobalt/arch/x86/signal_ia32.c
>> @@ -0,0 +1,75 @@
>> +#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>
>> +
>> +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;
>> +}
>> +
>> +int xnarch_rt_sigreturn_ia32(struct pt_regs *regs)
>> +{
>> +	int ret;
>> +
>> +	ret = dovetail_restore_rt_signal_frame(regs);
>> +	if (ret < 0)
>> +		goto badframe;
>> +
>> +	return regs->ax;
>> +
>> +badframe:
>> +	xnthread_call_mayday(xnthread_current(), SIGKILL);
>> +	return -1;
>> +}
>> +
>> diff --git a/kernel/cobalt/arch/x86/signal_ia64.c
>> b/kernel/cobalt/arch/x86/signal_ia64.c
>> new file mode 100644
>> index 000000000..a7044db40
>> --- /dev/null
>> +++ b/kernel/cobalt/arch/x86/signal_ia64.c
>> @@ -0,0 +1,26 @@
>> +// 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
>> + */
>> +
>> +#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>
>> +
>> +int xnarch_rt_sigreturn_ia64(struct pt_regs *regs)
>> +{
>> +	return dovetail_restore_rt_signal_frame(regs);
>> +}
>> +
>> diff --git a/kernel/cobalt/dovetail/kevents.c b/kernel/cobalt/dovetail/kevents.c
>> index 4da4f51b7..61417717b 100644
>> --- a/kernel/cobalt/dovetail/kevents.c
>> +++ b/kernel/cobalt/dovetail/kevents.c
>> @@ -57,6 +57,9 @@ void handle_oob_trap_entry(unsigned int trapnr, struct
>> pt_regs *regs)
>>   		xnsched_run();
>>   	}
>>
>> +	if (xnthread_handle_rt_signals(trapnr, regs) == 0)
>> +		return;
>> +
>>   	/*
>>   	 * If we experienced a trap on behalf of a shadow thread
>>   	 * running in primary mode, move it to the Linux domain,
>> @@ -88,6 +91,8 @@ void handle_oob_trap_entry(unsigned int trapnr, struct
>> pt_regs *regs)
>>   		xnstat_counter_inc(&thread->stat.pf);
>>
>>   	xnthread_relax(xnarch_fault_notify(trapnr), SIGDEBUG_MIGRATE_FAULT);
>> +
>> +	return;
>>   }
>>
>>   static inline int handle_setaffinity_event(struct dovetail_migration_data *d)
>> diff --git a/kernel/cobalt/posix/process.c b/kernel/cobalt/posix/process.c
>> index 1abc86f37..2069129cb 100644
>> --- a/kernel/cobalt/posix/process.c
>> +++ b/kernel/cobalt/posix/process.c
>> @@ -738,9 +738,10 @@ void cobalt_unregister_debugged_thread(struct
>> xnthread *thread)
>>   		cobalt_resume_debugged_process(process);
>>   }
>>
>> +#ifdef CONFIG_SMP
>> +
>>   int cobalt_handle_setaffinity_event(struct task_struct *task)
>>   {
>> -#ifdef CONFIG_SMP
>>   	struct xnthread *thread;
>>   	spl_t s;
>>
>> diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c
>> index 46c4998e4..b4bd4c587 100644
>> --- a/kernel/cobalt/posix/syscall.c
>> +++ b/kernel/cobalt/posix/syscall.c
>> @@ -277,6 +277,34 @@ static COBALT_SYSCALL(serialdbg, current,
>>   	return 0;
>>   }
>>
>> +static COBALT_SYSCALL(sigreturn, current, (void))
>> +{
>> +	struct pt_regs *regs = task_pt_regs(current);
>> +
>> +	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);
>> +}
>> +
>> +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 b65a0a760..f8b21bfb2 100644
>> --- a/kernel/cobalt/posix/syscall32.c
>> +++ b/kernel/cobalt/posix/syscall32.c
>> @@ -774,6 +774,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 old_timespec32 __user *u_ts,
>> diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
>> index 41804b24f..71f97c481 100644
>> --- a/kernel/cobalt/thread.c
>> +++ b/kernel/cobalt/thread.c
>> @@ -25,6 +25,7 @@
>>   #include <linux/signal.h>
>>   #include <linux/pid.h>
>>   #include <linux/sched.h>
>> +#include <asm/sighandling.h>
>>   #include <uapi/linux/sched/types.h>
>>   #include <cobalt/kernel/sched.h>
>>   #include <cobalt/kernel/timer.h>
>> @@ -43,6 +44,7 @@
>>   #include <pipeline/inband_work.h>
>>   #include <pipeline/sched.h>
>>   #include <trace/events/cobalt-core.h>
>> +#include "posix/process.h"
>>   #include "debug.h"
>>
>>   static DECLARE_WAIT_QUEUE_HEAD(join_all);
>> @@ -2520,6 +2522,43 @@ int xnthread_killall(int grace, int mask)
>>   }
>>   EXPORT_SYMBOL_GPL(xnthread_killall);
>>
>> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs)
>> +{
>> +	struct ksignal ksig;
>> +
>> +	unsigned int vector = trapnr;
>> +	unsigned int code = xnarch_fault_code(regs);
>> +	struct cobalt_ppd *sys_ppd;
>> +	int sig, ret = 0;
>> +	struct kernel_siginfo si;
>> +
>> +	code = xnarch_fault_code(regs);
>> +	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;
>> +
>> +	ksig.sig = sig;
>> +	memcpy(&ksig.info, &si, sizeof(si));
>> +	ksig.ka.sa.sa_flags = SA_SIGINFO | SA_RESTORER;
>> +	ksig.ka.sa.sa_restorer = sys_ppd->sigrestorer;
>> +	ksig.ka.sa.sa_handler = sys_ppd->sighand[sig];
>> +
>> +	ret = dovetail_setup_rt_signal_frame(&ksig, regs);
>> +	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..76292e145
>> --- /dev/null
>> +++ b/lib/cobalt/arch/x86/sigreturn.c
>> @@ -0,0 +1,32 @@
>> +#include <cobalt/uapi/syscall.h>
>> +#include "internal.h"
>> +
>> +extern void cobalt_sigreturn (void) asm ("__cobalt_sigreturn") __attribute__
>> ((visibility ("hidden")));
>> +
>> +#ifdef __x86_64__
>> +#define build_restorer(syscall_number)                                         \
>> +	asm(".text\n"                                                          \
>> +	    "    .align 16\n"                                                  \
>> +	    "__cobalt_sigreturn:\n"                                            \
>> +	    "    movq $ " #syscall_number ", %rax\n"                           \
>> +	    "    syscall")
>> +#endif
>> +
>> +#ifdef __i386__
>> +#define build_restorer(syscall_number)                                         \
>> +	asm(".text\n"                                                          \
>> +	    "    .align 16\n"                                                  \
>> +	    "__cobalt_sigreturn:\n"                                            \
>> +	    "    movl $ " #syscall_number ", %eax\n"                           \
>> +	    "    int  $0x80")
>> +#endif
>> +
>> +/*
>> + * __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 acb3989f1..4782d154a 100644
>> --- a/lib/cobalt/internal.h
>> +++ b/lib/cobalt/internal.h
>> @@ -132,4 +132,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 40d315ebb..af174d570 100644
>> --- a/lib/cobalt/signal.c
>> +++ b/lib/cobalt/signal.c
>> @@ -126,3 +126,16 @@ 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	[flat|nested] 30+ messages in thread

* Re: [PATCH 1/3] [POC] test implementaion of rt-signals
  2024-03-05 17:05   ` Jan Kiszka
@ 2024-03-05 17:14     ` Richard Weinberger
  0 siblings, 0 replies; 30+ messages in thread
From: Richard Weinberger @ 2024-03-05 17:14 UTC (permalink / raw)
  To: Jan Kiszka
  Cc: Richard Weinberger, xenomai, Florian Bezdeka, david oberhollenzer

----- Ursprüngliche Mail -----
> Von: "Jan Kiszka" <jan.kiszka@siemens.com>
> An: "Richard Weinberger" <richard.weinberger@gmail.com>, "xenomai" <xenomai@lists.linux.dev>
> CC: "Florian Bezdeka" <florian.bezdeka@siemens.com>, "david oberhollenzer" <david.oberhollenzer@sigma-star.at>
> Gesendet: Dienstag, 5. März 2024 18:05:08
> Betreff: Re: [PATCH 1/3] [POC] test implementaion of rt-signals

> On 05.03.24 16:54, Richard Weinberger wrote:
>> On Wed, Aug 16, 2023 at 12:19 PM Johannes Kirchmair
>> <johannes.kirchmair@sigmatek.at> wrote:
>>> diff --git a/kernel/cobalt/dovetail/kevents.c b/kernel/cobalt/dovetail/kevents.c
>>> index 4da4f51b7..61417717b 100644
>>> --- a/kernel/cobalt/dovetail/kevents.c
>>> +++ b/kernel/cobalt/dovetail/kevents.c
>>> @@ -57,6 +57,9 @@ void handle_oob_trap_entry(unsigned int trapnr, struct pt_regs
>>> *regs)
>>>                 xnsched_run();
>>>         }
>>>
>>> +       if (xnthread_handle_rt_signals(trapnr, regs) == 0)
>>> +               return;
>>> +
>> 
> 
> This is not the version I shared. But I assume the issue applies to that
> one as well, right?

Yes, I'm fighting currently on x86 and arm64. :-/

Thanks,
//richard

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

* Re: [PATCH 1/3] [POC] test implementaion of rt-signals
  2024-03-05 15:54 ` Richard Weinberger
@ 2024-03-05 17:05   ` Jan Kiszka
  2024-03-05 17:14     ` Richard Weinberger
  0 siblings, 1 reply; 30+ messages in thread
From: Jan Kiszka @ 2024-03-05 17:05 UTC (permalink / raw)
  To: Richard Weinberger, xenomai; +Cc: Bezdeka, Florian, David Oberhollenzer

On 05.03.24 16:54, Richard Weinberger wrote:
> On Wed, Aug 16, 2023 at 12:19 PM Johannes Kirchmair
> <johannes.kirchmair@sigmatek.at> wrote:
>> diff --git a/kernel/cobalt/dovetail/kevents.c b/kernel/cobalt/dovetail/kevents.c
>> index 4da4f51b7..61417717b 100644
>> --- a/kernel/cobalt/dovetail/kevents.c
>> +++ b/kernel/cobalt/dovetail/kevents.c
>> @@ -57,6 +57,9 @@ void handle_oob_trap_entry(unsigned int trapnr, struct pt_regs *regs)
>>                 xnsched_run();
>>         }
>>
>> +       if (xnthread_handle_rt_signals(trapnr, regs) == 0)
>> +               return;
>> +
> 

This is not the version I shared. But I assume the issue applies to that
one as well, right?

> While continuing Johannes' work I noticed a problem with this code.
> If we happen to trigger another exception while setting up the signal
> frame a domain
> switch could have happened and the subsequently call to
> xnthread_relax() will crash the kernel
> because it works only when we're in the primary domain.
> 
> e.g. if regs->sp points to a bogus memory location in userspace,
> xnthread_handle_rt_signals() will
> not only fail but also switch domains due to a page fault.
> We'll return here relaxed.
> 
> My current workaround is a check like:
> if (is_secondary_domain())
>     return;
> 

Yes, this makes sense.

Jan

-- 
Siemens AG, Technology
Linux Expert Center


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

* Re: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-08-16 10:18 Johannes Kirchmair
                   ` (2 preceding siblings ...)
  2023-09-01 13:51 ` Jan Kiszka
@ 2024-03-05 15:54 ` Richard Weinberger
  2024-03-05 17:05   ` Jan Kiszka
  3 siblings, 1 reply; 30+ messages in thread
From: Richard Weinberger @ 2024-03-05 15:54 UTC (permalink / raw)
  To: xenomai; +Cc: J. Kiszka, Bezdeka, Florian, David Oberhollenzer

On Wed, Aug 16, 2023 at 12:19 PM Johannes Kirchmair
<johannes.kirchmair@sigmatek.at> wrote:
> diff --git a/kernel/cobalt/dovetail/kevents.c b/kernel/cobalt/dovetail/kevents.c
> index 4da4f51b7..61417717b 100644
> --- a/kernel/cobalt/dovetail/kevents.c
> +++ b/kernel/cobalt/dovetail/kevents.c
> @@ -57,6 +57,9 @@ void handle_oob_trap_entry(unsigned int trapnr, struct pt_regs *regs)
>                 xnsched_run();
>         }
>
> +       if (xnthread_handle_rt_signals(trapnr, regs) == 0)
> +               return;
> +

While continuing Johannes' work I noticed a problem with this code.
If we happen to trigger another exception while setting up the signal
frame a domain
switch could have happened and the subsequently call to
xnthread_relax() will crash the kernel
because it works only when we're in the primary domain.

e.g. if regs->sp points to a bogus memory location in userspace,
xnthread_handle_rt_signals() will
not only fail but also switch domains due to a page fault.
We'll return here relaxed.

My current workaround is a check like:
if (is_secondary_domain())
    return;

>         /*
>          * If we experienced a trap on behalf of a shadow thread
>          * running in primary mode, move it to the Linux domain,
> @@ -88,6 +91,8 @@ void handle_oob_trap_entry(unsigned int trapnr, struct pt_regs *regs)
>                 xnstat_counter_inc(&thread->stat.pf);
>
>         xnthread_relax(xnarch_fault_notify(trapnr), SIGDEBUG_MIGRATE_FAULT);
> +
> +       return;
>  }



-- 
Thanks,
//richard

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

* Re: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-09-07 10:48   ` Johannes Kirchmair
@ 2023-09-11  8:41     ` Florian Bezdeka
  0 siblings, 0 replies; 30+ messages in thread
From: Florian Bezdeka @ 2023-09-11  8:41 UTC (permalink / raw)
  To: Johannes Kirchmair, xenomai; +Cc: Jan Kiszka

On Thu, 2023-09-07 at 10:48 +0000, Johannes Kirchmair wrote:
> Hey Florian,
> 
> > -----Original Message-----
> > From: Florian Bezdeka <florian.bezdeka@siemens.com>
> [...]
> > > +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;
> > > +}
> > > +
> > 
> > You did not touch the syscall32-table.h (x86 specific), so I would
> > expect that your compat support is broken right now. You should end up
> > in the "native" so x86_64 implementation. That brings me to the next
> > question:
> Checked this and you are right, we end up in the "native" implementation of the syscall.
> Will drop the compat syscall.

Fine.

> 
> > 
> > Can't we avoid a special compat case here? The pointers themselfs are
> > corrected by the syscall entry machinery but the memory pointed to is
> > not. So is the memory pointed to by handler and restorer different in
> > terms of memory layout/padding?
> We don’t access the memory pointed to from kernel space, so this should not be imported or am I missing something?

This is obsolete. We could drop the compat case.

> 
> > 
> > In addition you should update kernel/cobalt/trace/cobalt-posix.h to get
> > proper trace support.
> Changed the following define to look like this:
> #define __cobalt_syscall_name(__nr)					\
> 	__print_symbolic((__nr),					\
> 		....
> 		__cobalt_symbolic_syscall(pselect64),			\
> 		__cobalt_symbolic_syscall(sigreturn),			\
> 		__cobalt_symbolic_syscall(sigaction))
> 
> Is this sufficient or do I have to change something else?

Yes, that should be sufficient.

> 
> Best regards Johannes
> 
> 


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

* Re: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-09-08 10:50 Johannes Kirchmair
  2023-09-08 10:54 ` Johannes Kirchmair
@ 2023-09-09 11:35 ` Jan Kiszka
  1 sibling, 0 replies; 30+ messages in thread
From: Jan Kiszka @ 2023-09-09 11:35 UTC (permalink / raw)
  To: Johannes Kirchmair, xenomai

On 08.09.23 12:50, Johannes Kirchmair wrote:
> We implement rt signals to handle exceptions in rt stage.
> 
> This is done using dovetail specific functions for setting up the signal
> frame.
> 
> This can be used to handle fpe exceptions on the fly, like fixing
> division by zero. An other use case are breakpoints, implemented using the
> illegal opcode exception. The real time handling of the breakpoints would
> be handy for conditional breakpoints or also for stopping watchdogs and
> other tasks in time.
> 
> Signed-off-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                 |  2 +
>  kernel/cobalt/arch/x86/Makefile               |  2 +-
>  .../arch/x86/include/asm/xenomai/thread.h     |  3 ++
>  kernel/cobalt/arch/x86/signal.c               | 51 +++++++++++++++++++
>  kernel/cobalt/dovetail/kevents.c              |  3 ++
>  kernel/cobalt/posix/syscall.c                 | 32 ++++++++++++
>  kernel/cobalt/thread.c                        | 38 ++++++++++++++
>  kernel/cobalt/trace/cobalt-posix.h            |  4 +-
>  lib/cobalt/arch/x86/Makefile.am               |  2 +-
>  lib/cobalt/arch/x86/sigreturn.c               | 36 +++++++++++++
>  lib/cobalt/internal.h                         |  2 +
>  lib/cobalt/signal.c                           | 13 +++++
>  15 files changed, 192 insertions(+), 3 deletions(-)
>  create mode 100644 kernel/cobalt/arch/x86/signal.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 b79cb8429..33d468419 100644
> --- a/include/cobalt/kernel/thread.h
> +++ b/include/cobalt/kernel/thread.h
> @@ -574,6 +574,8 @@ static inline void xnthread_propagate_schedparam(struct xnthread *curr)
>  		__xnthread_propagate_schedparam(curr);
>  }
>  
> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs);
> +
>  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 3e65efaab..3913cc610 100644
> --- a/include/cobalt/uapi/syscall.h
> +++ b/include/cobalt/uapi/syscall.h
> @@ -141,6 +141,8 @@
>  #define sc_cobalt_timerfd_settime64		118
>  #define sc_cobalt_timerfd_gettime64		119
>  #define sc_cobalt_pselect64			120
> +#define sc_cobalt_sigreturn			121
> +#define sc_cobalt_sigaction			122
>  
>  #define __NR_COBALT_SYSCALLS			128 /* Power of 2 */
>  
> diff --git a/kernel/cobalt/arch/x86/Makefile b/kernel/cobalt/arch/x86/Makefile
> index 93929b645..e3d8eb476 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 smi.o c1e.o
> +xenomai-y := machine.o smi.o c1e.o signal.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 745c32467..70f3df2f1 100644
> --- a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
> +++ b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
> @@ -28,5 +28,8 @@
>  #define xnarch_fault_bp_p(__nr)		((current->ptrace & PT_PTRACED) &&	\
>  					 ((__nr) == X86_TRAP_DB || (__nr) == X86_TRAP_BP))
>  #define xnarch_fault_notify(__nr)	(!xnarch_fault_bp_p(__nr))
> +#define xnarch_fault_code(__regs)		((__regs)->orig_ax)
> +int xnarch_setup_trap_info(unsigned int vector, struct pt_regs *regs,
> +			   long errcode, int *sig, struct kernel_siginfo *info);
>  
>  #endif /* !_COBALT_X86_ASM_THREAD_H */
> diff --git a/kernel/cobalt/arch/x86/signal.c b/kernel/cobalt/arch/x86/signal.c
> new file mode 100644
> index 000000000..2e8fdc571
> --- /dev/null
> +++ b/kernel/cobalt/arch/x86/signal.c
> @@ -0,0 +1,51 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#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>
> +#include <asm/trapnr.h>
> +
> +int xnarch_setup_trap_info(unsigned int vector, struct pt_regs *regs,
> +			   long errcode, int *sig, struct kernel_siginfo *info)
> +{
> +	switch (vector) {
> +	case X86_TRAP_DE: /* 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 X86_TRAP_UD: /* 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 X86_TRAP_MF:
> +		*sig = SIGFPE;
> +
> +		info->si_signo = *sig;
> +		info->si_errno = 0;
> +		info->si_code = 0;
> +		info->si_addr = (void __user *)regs->ip;
> +		return 0;
> +        case X86_TRAP_PF:
> +                *sig = SIGSEGV;
> +                info->si_signo = *sig;
> +                info->si_errno = errcode;
> +                info->si_code = 0;
> +                info->si_addr = 0;
> +                return 0;

Indention got damaged.

> +	default:
> +		break;
> +	}
> +
> +	return -ENOSYS;
> +}
> +
> diff --git a/kernel/cobalt/dovetail/kevents.c b/kernel/cobalt/dovetail/kevents.c
> index 4da4f51b7..09eb12acb 100644
> --- a/kernel/cobalt/dovetail/kevents.c
> +++ b/kernel/cobalt/dovetail/kevents.c
> @@ -57,6 +57,9 @@ void handle_oob_trap_entry(unsigned int trapnr, struct pt_regs *regs)
>  		xnsched_run();
>  	}
>  
> +	if (xnthread_handle_rt_signals(trapnr, regs) == 0)
> +		return;
> +
>  	/*
>  	 * If we experienced a trap on behalf of a shadow thread
>  	 * running in primary mode, move it to the Linux domain,
> diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c
> index 46c4998e4..d570bd595 100644
> --- a/kernel/cobalt/posix/syscall.c
> +++ b/kernel/cobalt/posix/syscall.c
> @@ -277,6 +277,38 @@ static COBALT_SYSCALL(serialdbg, current,
>  	return 0;
>  }
>  
> +static COBALT_SYSCALL(sigreturn, current, (void))
> +{
> +	struct pt_regs *regs = task_pt_regs(current);
> +	int ret;
> +
> +	ret = dovetail_restore_rt_signal_frame(regs);
> +	if (ret < 0)
> +		goto badframe;
> +
> +	return __xn_reg_rval(regs);
> +
> +badframe:
> +	xnthread_signal(xnthread_current(), SIGSEGV, 0);
> +	return -1;
> +}
> +
> +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;

Checked if we can do better during binding or thread mapping but,
indeed, none of those calls provide a convenient channel to carry this
information.

But then let's avoid the "optimization" and simply always deliver this
from userspace (what you already do) and always assign here in kernel space.

> +
> +	return 0;
> +}
> +
>  static void stringify_feature_set(unsigned long fset, char *buf, int size)
>  {
>  	unsigned long feature;
> diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
> index 41804b24f..ae8fa5c88 100644
> --- a/kernel/cobalt/thread.c
> +++ b/kernel/cobalt/thread.c
> @@ -25,6 +25,7 @@
>  #include <linux/signal.h>
>  #include <linux/pid.h>
>  #include <linux/sched.h>
> +#include <asm/sighandling.h>
>  #include <uapi/linux/sched/types.h>
>  #include <cobalt/kernel/sched.h>
>  #include <cobalt/kernel/timer.h>
> @@ -43,6 +44,7 @@
>  #include <pipeline/inband_work.h>
>  #include <pipeline/sched.h>
>  #include <trace/events/cobalt-core.h>
> +#include "posix/process.h"
>  #include "debug.h"
>  
>  static DECLARE_WAIT_QUEUE_HEAD(join_all);
> @@ -2520,6 +2522,42 @@ int xnthread_killall(int grace, int mask)
>  }
>  EXPORT_SYMBOL_GPL(xnthread_killall);
>  
> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs)
> +{
> +	unsigned int code = xnarch_fault_code(regs);
> +	unsigned int vector = trapnr;
> +	struct cobalt_ppd *sys_ppd;
> +	struct kernel_siginfo si;
> +	struct ksignal ksig;
> +	int sig, ret = 0;
> +
> +	code = xnarch_fault_code(regs);

Duplicate assignment. But actually I see no value in asking the arch
first for this fault code, only to deliver it to an arch-specific call,
and only to it. Just let xnarch_setup_trap_info retrieve the fault code
itself.

> +	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;
> +
> +	ksig.sig = sig;
> +	memcpy(&ksig.info, &si, sizeof(si));
> +	ksig.ka.sa.sa_flags = SA_SIGINFO | SA_RESTORER;
> +	ksig.ka.sa.sa_restorer = sys_ppd->sigrestorer;
> +	ksig.ka.sa.sa_handler = sys_ppd->sighand[sig];
> +
> +	ret = dovetail_setup_rt_signal_frame(&ksig, regs);
> +	if (ret)
> +		return 1;
> +
> +	return 0;
> +}
> +
>  /* Xenomai's generic personality. */
>  struct xnthread_personality xenomai_personality = {
>  	.name = "core",
> diff --git a/kernel/cobalt/trace/cobalt-posix.h b/kernel/cobalt/trace/cobalt-posix.h
> index 47dc77e1c..8eda3bb27 100644
> --- a/kernel/cobalt/trace/cobalt-posix.h
> +++ b/kernel/cobalt/trace/cobalt-posix.h
> @@ -173,7 +173,9 @@
>  		__cobalt_symbolic_syscall(timer_gettime64),		\
>  		__cobalt_symbolic_syscall(timerfd_settime64),		\
>  		__cobalt_symbolic_syscall(timerfd_gettime64),		\
> -		__cobalt_symbolic_syscall(pselect64))
> +		__cobalt_symbolic_syscall(pselect64),			\
> +		__cobalt_symbolic_syscall(sigreturn),			\
> +		__cobalt_symbolic_syscall(sigaction))
>  
>  DECLARE_EVENT_CLASS(cobalt_syscall_entry,
>  	TP_PROTO(unsigned int nr),
> 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..df961469e
> --- /dev/null
> +++ b/lib/cobalt/arch/x86/sigreturn.c
> @@ -0,0 +1,36 @@
> +#include <cobalt/uapi/syscall.h>
> +#include "internal.h"
> +
> +extern void cobalt_sigreturn (void) asm ("__cobalt_sigreturn") __attribute__ ((visibility ("hidden")));
> +
> +#define TO_STR(x) #x
> +
> +#ifdef __x86_64__
> +#define build_restorer(syscall_bit, syscall)                                   \
> +	asm(".text\n"                                                          \
> +	    "    .align 16\n"                                                  \
> +	    "__cobalt_sigreturn:\n"                                            \
> +	    "    movq $ " TO_STR(syscall_bit) ", %rax\n"                       \
> +	    "    orq $ " TO_STR(syscall) ", %rax\n"                            \
> +	    "    syscall")
> +#endif
> +
> +#ifdef __i386__
> +#define build_restorer(syscall_bit, syscall)                                   \
> +	asm(".text\n"                                                          \
> +	    "    .align 16\n"                                                  \
> +	    "__cobalt_sigreturn:\n"                                            \
> +	    "    movl $ " TO_STR(syscall_bit) ", %eax\n"                       \
> +	    "    orl $ " TO_STR(syscall) ", %eax\n"                            \
> +	    "    int  $0x80")
> +#endif

I still need to play with those two in order to see if we can do it more
elegantly, ie. without assembly.

> +
> +/*
> + * __COBALT_SYSCALL_BIT | sc_cobalt_sigreturn
> + */
> +build_restorer(__COBALT_SYSCALL_BIT, sc_cobalt_sigreturn);
> +
> +void *cobalt_get_restorer(void)
> +{
> +	return &cobalt_sigreturn;
> +}

Not sure if we need that getter, definitely not as non-inline function
unless you make cobalt_sigreturn static.

> diff --git a/lib/cobalt/internal.h b/lib/cobalt/internal.h
> index acb3989f1..4782d154a 100644
> --- a/lib/cobalt/internal.h
> +++ b/lib/cobalt/internal.h
> @@ -132,4 +132,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 40d315ebb..af174d570 100644
> --- a/lib/cobalt/signal.c
> +++ b/lib/cobalt/signal.c
> @@ -126,3 +126,16 @@ 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;
> +}

Thanks,
Jan

-- 
Siemens AG, Technology
Linux Expert Center


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

* RE: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-09-08 10:50 Johannes Kirchmair
@ 2023-09-08 10:54 ` Johannes Kirchmair
  2023-09-09 11:35 ` Jan Kiszka
  1 sibling, 0 replies; 30+ messages in thread
From: Johannes Kirchmair @ 2023-09-08 10:54 UTC (permalink / raw)
  To: xenomai; +Cc: Jan Kiszka

Changed the following things:

- replace magic numbers with X86_TRAP_*
- removed uneeded changes that slipped in (return in void function and move of #ifdef CONFIG_SMP)
- removed DB and BP code
- if sigreturn fails send SIGSEGV and not MAYDAY .... will have to write a test for this
- added sigreturn and sigaction to sysentery sysexit tracing
- removed specific sigaction compat code
- removed xnarch_rt_sigreturn_ia32/ia64 functions and call dovetail_restore_rt_signal_frame in generic code 
- moved xnarch_setup_trap_info to signal.c to dont confuse people by having it in ia32 specific file


Freundliche Grüße
Johannes

> -----Original Message-----
> From: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
> Sent: Freitag, 8. September 2023 12:51
> To: xenomai@lists.linux.dev
> Cc: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>
> Subject: [PATCH 1/3] [POC] test implementaion of rt-signals
> 
> We implement rt signals to handle exceptions in rt stage.
> 
> This is done using dovetail specific functions for setting up the signal
> frame.
> 
> This can be used to handle fpe exceptions on the fly, like fixing
> division by zero. An other use case are breakpoints, implemented using the
> illegal opcode exception. The real time handling of the breakpoints would
> be handy for conditional breakpoints or also for stopping watchdogs and
> other tasks in time.
> 
> Signed-off-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                 |  2 +
>  kernel/cobalt/arch/x86/Makefile               |  2 +-
>  .../arch/x86/include/asm/xenomai/thread.h     |  3 ++
>  kernel/cobalt/arch/x86/signal.c               | 51 +++++++++++++++++++
>  kernel/cobalt/dovetail/kevents.c              |  3 ++
>  kernel/cobalt/posix/syscall.c                 | 32 ++++++++++++
>  kernel/cobalt/thread.c                        | 38 ++++++++++++++
>  kernel/cobalt/trace/cobalt-posix.h            |  4 +-
>  lib/cobalt/arch/x86/Makefile.am               |  2 +-
>  lib/cobalt/arch/x86/sigreturn.c               | 36 +++++++++++++
>  lib/cobalt/internal.h                         |  2 +
>  lib/cobalt/signal.c                           | 13 +++++
>  15 files changed, 192 insertions(+), 3 deletions(-)
>  create mode 100644 kernel/cobalt/arch/x86/signal.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 b79cb8429..33d468419 100644
> --- a/include/cobalt/kernel/thread.h
> +++ b/include/cobalt/kernel/thread.h
> @@ -574,6 +574,8 @@ static inline void xnthread_propagate_schedparam(struct
> xnthread *curr)
>  		__xnthread_propagate_schedparam(curr);
>  }
> 
> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs);
> +
>  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 3e65efaab..3913cc610 100644
> --- a/include/cobalt/uapi/syscall.h
> +++ b/include/cobalt/uapi/syscall.h
> @@ -141,6 +141,8 @@
>  #define sc_cobalt_timerfd_settime64		118
>  #define sc_cobalt_timerfd_gettime64		119
>  #define sc_cobalt_pselect64			120
> +#define sc_cobalt_sigreturn			121
> +#define sc_cobalt_sigaction			122
> 
>  #define __NR_COBALT_SYSCALLS			128 /* Power of 2 */
> 
> diff --git a/kernel/cobalt/arch/x86/Makefile b/kernel/cobalt/arch/x86/Makefile
> index 93929b645..e3d8eb476 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 smi.o c1e.o
> +xenomai-y := machine.o smi.o c1e.o signal.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 745c32467..70f3df2f1 100644
> --- a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
> +++ b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
> @@ -28,5 +28,8 @@
>  #define xnarch_fault_bp_p(__nr)		((current->ptrace & PT_PTRACED)
> &&	\
>  					 ((__nr) == X86_TRAP_DB || (__nr) ==
> X86_TRAP_BP))
>  #define xnarch_fault_notify(__nr)	(!xnarch_fault_bp_p(__nr))
> +#define xnarch_fault_code(__regs)		((__regs)->orig_ax)
> +int xnarch_setup_trap_info(unsigned int vector, struct pt_regs *regs,
> +			   long errcode, int *sig, struct kernel_siginfo *info);
> 
>  #endif /* !_COBALT_X86_ASM_THREAD_H */
> diff --git a/kernel/cobalt/arch/x86/signal.c b/kernel/cobalt/arch/x86/signal.c
> new file mode 100644
> index 000000000..2e8fdc571
> --- /dev/null
> +++ b/kernel/cobalt/arch/x86/signal.c
> @@ -0,0 +1,51 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#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>
> +#include <asm/trapnr.h>
> +
> +int xnarch_setup_trap_info(unsigned int vector, struct pt_regs *regs,
> +			   long errcode, int *sig, struct kernel_siginfo *info)
> +{
> +	switch (vector) {
> +	case X86_TRAP_DE: /* 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 X86_TRAP_UD: /* 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 X86_TRAP_MF:
> +		*sig = SIGFPE;
> +
> +		info->si_signo = *sig;
> +		info->si_errno = 0;
> +		info->si_code = 0;
> +		info->si_addr = (void __user *)regs->ip;
> +		return 0;
> +        case X86_TRAP_PF:
> +                *sig = SIGSEGV;
> +                info->si_signo = *sig;
> +                info->si_errno = errcode;
> +                info->si_code = 0;
> +                info->si_addr = 0;
> +                return 0;
> +	default:
> +		break;
> +	}
> +
> +	return -ENOSYS;
> +}
> +
> diff --git a/kernel/cobalt/dovetail/kevents.c b/kernel/cobalt/dovetail/kevents.c
> index 4da4f51b7..09eb12acb 100644
> --- a/kernel/cobalt/dovetail/kevents.c
> +++ b/kernel/cobalt/dovetail/kevents.c
> @@ -57,6 +57,9 @@ void handle_oob_trap_entry(unsigned int trapnr, struct
> pt_regs *regs)
>  		xnsched_run();
>  	}
> 
> +	if (xnthread_handle_rt_signals(trapnr, regs) == 0)
> +		return;
> +
>  	/*
>  	 * If we experienced a trap on behalf of a shadow thread
>  	 * running in primary mode, move it to the Linux domain,
> diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c
> index 46c4998e4..d570bd595 100644
> --- a/kernel/cobalt/posix/syscall.c
> +++ b/kernel/cobalt/posix/syscall.c
> @@ -277,6 +277,38 @@ static COBALT_SYSCALL(serialdbg, current,
>  	return 0;
>  }
> 
> +static COBALT_SYSCALL(sigreturn, current, (void))
> +{
> +	struct pt_regs *regs = task_pt_regs(current);
> +	int ret;
> +
> +	ret = dovetail_restore_rt_signal_frame(regs);
> +	if (ret < 0)
> +		goto badframe;
> +
> +	return __xn_reg_rval(regs);
> +
> +badframe:
> +	xnthread_signal(xnthread_current(), SIGSEGV, 0);
> +	return -1;
> +}
> +
> +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/thread.c b/kernel/cobalt/thread.c
> index 41804b24f..ae8fa5c88 100644
> --- a/kernel/cobalt/thread.c
> +++ b/kernel/cobalt/thread.c
> @@ -25,6 +25,7 @@
>  #include <linux/signal.h>
>  #include <linux/pid.h>
>  #include <linux/sched.h>
> +#include <asm/sighandling.h>
>  #include <uapi/linux/sched/types.h>
>  #include <cobalt/kernel/sched.h>
>  #include <cobalt/kernel/timer.h>
> @@ -43,6 +44,7 @@
>  #include <pipeline/inband_work.h>
>  #include <pipeline/sched.h>
>  #include <trace/events/cobalt-core.h>
> +#include "posix/process.h"
>  #include "debug.h"
> 
>  static DECLARE_WAIT_QUEUE_HEAD(join_all);
> @@ -2520,6 +2522,42 @@ int xnthread_killall(int grace, int mask)
>  }
>  EXPORT_SYMBOL_GPL(xnthread_killall);
> 
> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs)
> +{
> +	unsigned int code = xnarch_fault_code(regs);
> +	unsigned int vector = trapnr;
> +	struct cobalt_ppd *sys_ppd;
> +	struct kernel_siginfo si;
> +	struct ksignal ksig;
> +	int sig, ret = 0;
> +
> +	code = xnarch_fault_code(regs);
> +	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;
> +
> +	ksig.sig = sig;
> +	memcpy(&ksig.info, &si, sizeof(si));
> +	ksig.ka.sa.sa_flags = SA_SIGINFO | SA_RESTORER;
> +	ksig.ka.sa.sa_restorer = sys_ppd->sigrestorer;
> +	ksig.ka.sa.sa_handler = sys_ppd->sighand[sig];
> +
> +	ret = dovetail_setup_rt_signal_frame(&ksig, regs);
> +	if (ret)
> +		return 1;
> +
> +	return 0;
> +}
> +
>  /* Xenomai's generic personality. */
>  struct xnthread_personality xenomai_personality = {
>  	.name = "core",
> diff --git a/kernel/cobalt/trace/cobalt-posix.h b/kernel/cobalt/trace/cobalt-posix.h
> index 47dc77e1c..8eda3bb27 100644
> --- a/kernel/cobalt/trace/cobalt-posix.h
> +++ b/kernel/cobalt/trace/cobalt-posix.h
> @@ -173,7 +173,9 @@
>  		__cobalt_symbolic_syscall(timer_gettime64),		\
>  		__cobalt_symbolic_syscall(timerfd_settime64),		\
>  		__cobalt_symbolic_syscall(timerfd_gettime64),		\
> -		__cobalt_symbolic_syscall(pselect64))
> +		__cobalt_symbolic_syscall(pselect64),			\
> +		__cobalt_symbolic_syscall(sigreturn),			\
> +		__cobalt_symbolic_syscall(sigaction))
> 
>  DECLARE_EVENT_CLASS(cobalt_syscall_entry,
>  	TP_PROTO(unsigned int nr),
> 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..df961469e
> --- /dev/null
> +++ b/lib/cobalt/arch/x86/sigreturn.c
> @@ -0,0 +1,36 @@
> +#include <cobalt/uapi/syscall.h>
> +#include "internal.h"
> +
> +extern void cobalt_sigreturn (void) asm ("__cobalt_sigreturn") __attribute__
> ((visibility ("hidden")));
> +
> +#define TO_STR(x) #x
> +
> +#ifdef __x86_64__
> +#define build_restorer(syscall_bit, syscall)                                   \
> +	asm(".text\n"                                                          \
> +	    "    .align 16\n"                                                  \
> +	    "__cobalt_sigreturn:\n"                                            \
> +	    "    movq $ " TO_STR(syscall_bit) ", %rax\n"                       \
> +	    "    orq $ " TO_STR(syscall) ", %rax\n"                            \
> +	    "    syscall")
> +#endif
> +
> +#ifdef __i386__
> +#define build_restorer(syscall_bit, syscall)                                   \
> +	asm(".text\n"                                                          \
> +	    "    .align 16\n"                                                  \
> +	    "__cobalt_sigreturn:\n"                                            \
> +	    "    movl $ " TO_STR(syscall_bit) ", %eax\n"                       \
> +	    "    orl $ " TO_STR(syscall) ", %eax\n"                            \
> +	    "    int  $0x80")
> +#endif
> +
> +/*
> + * __COBALT_SYSCALL_BIT | sc_cobalt_sigreturn
> + */
> +build_restorer(__COBALT_SYSCALL_BIT, sc_cobalt_sigreturn);
> +
> +void *cobalt_get_restorer(void)
> +{
> +	return &cobalt_sigreturn;
> +}
> diff --git a/lib/cobalt/internal.h b/lib/cobalt/internal.h
> index acb3989f1..4782d154a 100644
> --- a/lib/cobalt/internal.h
> +++ b/lib/cobalt/internal.h
> @@ -132,4 +132,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 40d315ebb..af174d570 100644
> --- a/lib/cobalt/signal.c
> +++ b/lib/cobalt/signal.c
> @@ -126,3 +126,16 @@ 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	[flat|nested] 30+ messages in thread

* [PATCH 1/3] [POC] test implementaion of rt-signals
@ 2023-09-08 10:50 Johannes Kirchmair
  2023-09-08 10:54 ` Johannes Kirchmair
  2023-09-09 11:35 ` Jan Kiszka
  0 siblings, 2 replies; 30+ messages in thread
From: Johannes Kirchmair @ 2023-09-08 10:50 UTC (permalink / raw)
  To: xenomai; +Cc: Johannes Kirchmair

We implement rt signals to handle exceptions in rt stage.

This is done using dovetail specific functions for setting up the signal
frame.

This can be used to handle fpe exceptions on the fly, like fixing
division by zero. An other use case are breakpoints, implemented using the
illegal opcode exception. The real time handling of the breakpoints would
be handy for conditional breakpoints or also for stopping watchdogs and
other tasks in time.

Signed-off-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                 |  2 +
 kernel/cobalt/arch/x86/Makefile               |  2 +-
 .../arch/x86/include/asm/xenomai/thread.h     |  3 ++
 kernel/cobalt/arch/x86/signal.c               | 51 +++++++++++++++++++
 kernel/cobalt/dovetail/kevents.c              |  3 ++
 kernel/cobalt/posix/syscall.c                 | 32 ++++++++++++
 kernel/cobalt/thread.c                        | 38 ++++++++++++++
 kernel/cobalt/trace/cobalt-posix.h            |  4 +-
 lib/cobalt/arch/x86/Makefile.am               |  2 +-
 lib/cobalt/arch/x86/sigreturn.c               | 36 +++++++++++++
 lib/cobalt/internal.h                         |  2 +
 lib/cobalt/signal.c                           | 13 +++++
 15 files changed, 192 insertions(+), 3 deletions(-)
 create mode 100644 kernel/cobalt/arch/x86/signal.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 b79cb8429..33d468419 100644
--- a/include/cobalt/kernel/thread.h
+++ b/include/cobalt/kernel/thread.h
@@ -574,6 +574,8 @@ static inline void xnthread_propagate_schedparam(struct xnthread *curr)
 		__xnthread_propagate_schedparam(curr);
 }
 
+int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs);
+
 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 3e65efaab..3913cc610 100644
--- a/include/cobalt/uapi/syscall.h
+++ b/include/cobalt/uapi/syscall.h
@@ -141,6 +141,8 @@
 #define sc_cobalt_timerfd_settime64		118
 #define sc_cobalt_timerfd_gettime64		119
 #define sc_cobalt_pselect64			120
+#define sc_cobalt_sigreturn			121
+#define sc_cobalt_sigaction			122
 
 #define __NR_COBALT_SYSCALLS			128 /* Power of 2 */
 
diff --git a/kernel/cobalt/arch/x86/Makefile b/kernel/cobalt/arch/x86/Makefile
index 93929b645..e3d8eb476 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 smi.o c1e.o
+xenomai-y := machine.o smi.o c1e.o signal.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 745c32467..70f3df2f1 100644
--- a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
+++ b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
@@ -28,5 +28,8 @@
 #define xnarch_fault_bp_p(__nr)		((current->ptrace & PT_PTRACED) &&	\
 					 ((__nr) == X86_TRAP_DB || (__nr) == X86_TRAP_BP))
 #define xnarch_fault_notify(__nr)	(!xnarch_fault_bp_p(__nr))
+#define xnarch_fault_code(__regs)		((__regs)->orig_ax)
+int xnarch_setup_trap_info(unsigned int vector, struct pt_regs *regs,
+			   long errcode, int *sig, struct kernel_siginfo *info);
 
 #endif /* !_COBALT_X86_ASM_THREAD_H */
diff --git a/kernel/cobalt/arch/x86/signal.c b/kernel/cobalt/arch/x86/signal.c
new file mode 100644
index 000000000..2e8fdc571
--- /dev/null
+++ b/kernel/cobalt/arch/x86/signal.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#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>
+#include <asm/trapnr.h>
+
+int xnarch_setup_trap_info(unsigned int vector, struct pt_regs *regs,
+			   long errcode, int *sig, struct kernel_siginfo *info)
+{
+	switch (vector) {
+	case X86_TRAP_DE: /* 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 X86_TRAP_UD: /* 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 X86_TRAP_MF:
+		*sig = SIGFPE;
+
+		info->si_signo = *sig;
+		info->si_errno = 0;
+		info->si_code = 0;
+		info->si_addr = (void __user *)regs->ip;
+		return 0;
+        case X86_TRAP_PF:
+                *sig = SIGSEGV;
+                info->si_signo = *sig;
+                info->si_errno = errcode;
+                info->si_code = 0;
+                info->si_addr = 0;
+                return 0;
+	default:
+		break;
+	}
+
+	return -ENOSYS;
+}
+
diff --git a/kernel/cobalt/dovetail/kevents.c b/kernel/cobalt/dovetail/kevents.c
index 4da4f51b7..09eb12acb 100644
--- a/kernel/cobalt/dovetail/kevents.c
+++ b/kernel/cobalt/dovetail/kevents.c
@@ -57,6 +57,9 @@ void handle_oob_trap_entry(unsigned int trapnr, struct pt_regs *regs)
 		xnsched_run();
 	}
 
+	if (xnthread_handle_rt_signals(trapnr, regs) == 0)
+		return;
+
 	/*
 	 * If we experienced a trap on behalf of a shadow thread
 	 * running in primary mode, move it to the Linux domain,
diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c
index 46c4998e4..d570bd595 100644
--- a/kernel/cobalt/posix/syscall.c
+++ b/kernel/cobalt/posix/syscall.c
@@ -277,6 +277,38 @@ static COBALT_SYSCALL(serialdbg, current,
 	return 0;
 }
 
+static COBALT_SYSCALL(sigreturn, current, (void))
+{
+	struct pt_regs *regs = task_pt_regs(current);
+	int ret;
+
+	ret = dovetail_restore_rt_signal_frame(regs);
+	if (ret < 0)
+		goto badframe;
+
+	return __xn_reg_rval(regs);
+
+badframe:
+	xnthread_signal(xnthread_current(), SIGSEGV, 0);
+	return -1;
+}
+
+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/thread.c b/kernel/cobalt/thread.c
index 41804b24f..ae8fa5c88 100644
--- a/kernel/cobalt/thread.c
+++ b/kernel/cobalt/thread.c
@@ -25,6 +25,7 @@
 #include <linux/signal.h>
 #include <linux/pid.h>
 #include <linux/sched.h>
+#include <asm/sighandling.h>
 #include <uapi/linux/sched/types.h>
 #include <cobalt/kernel/sched.h>
 #include <cobalt/kernel/timer.h>
@@ -43,6 +44,7 @@
 #include <pipeline/inband_work.h>
 #include <pipeline/sched.h>
 #include <trace/events/cobalt-core.h>
+#include "posix/process.h"
 #include "debug.h"
 
 static DECLARE_WAIT_QUEUE_HEAD(join_all);
@@ -2520,6 +2522,42 @@ int xnthread_killall(int grace, int mask)
 }
 EXPORT_SYMBOL_GPL(xnthread_killall);
 
+int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs)
+{
+	unsigned int code = xnarch_fault_code(regs);
+	unsigned int vector = trapnr;
+	struct cobalt_ppd *sys_ppd;
+	struct kernel_siginfo si;
+	struct ksignal ksig;
+	int sig, ret = 0;
+
+	code = xnarch_fault_code(regs);
+	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;
+
+	ksig.sig = sig;
+	memcpy(&ksig.info, &si, sizeof(si));
+	ksig.ka.sa.sa_flags = SA_SIGINFO | SA_RESTORER;
+	ksig.ka.sa.sa_restorer = sys_ppd->sigrestorer;
+	ksig.ka.sa.sa_handler = sys_ppd->sighand[sig];
+
+	ret = dovetail_setup_rt_signal_frame(&ksig, regs);
+	if (ret)
+		return 1;
+
+	return 0;
+}
+
 /* Xenomai's generic personality. */
 struct xnthread_personality xenomai_personality = {
 	.name = "core",
diff --git a/kernel/cobalt/trace/cobalt-posix.h b/kernel/cobalt/trace/cobalt-posix.h
index 47dc77e1c..8eda3bb27 100644
--- a/kernel/cobalt/trace/cobalt-posix.h
+++ b/kernel/cobalt/trace/cobalt-posix.h
@@ -173,7 +173,9 @@
 		__cobalt_symbolic_syscall(timer_gettime64),		\
 		__cobalt_symbolic_syscall(timerfd_settime64),		\
 		__cobalt_symbolic_syscall(timerfd_gettime64),		\
-		__cobalt_symbolic_syscall(pselect64))
+		__cobalt_symbolic_syscall(pselect64),			\
+		__cobalt_symbolic_syscall(sigreturn),			\
+		__cobalt_symbolic_syscall(sigaction))
 
 DECLARE_EVENT_CLASS(cobalt_syscall_entry,
 	TP_PROTO(unsigned int nr),
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..df961469e
--- /dev/null
+++ b/lib/cobalt/arch/x86/sigreturn.c
@@ -0,0 +1,36 @@
+#include <cobalt/uapi/syscall.h>
+#include "internal.h"
+
+extern void cobalt_sigreturn (void) asm ("__cobalt_sigreturn") __attribute__ ((visibility ("hidden")));
+
+#define TO_STR(x) #x
+
+#ifdef __x86_64__
+#define build_restorer(syscall_bit, syscall)                                   \
+	asm(".text\n"                                                          \
+	    "    .align 16\n"                                                  \
+	    "__cobalt_sigreturn:\n"                                            \
+	    "    movq $ " TO_STR(syscall_bit) ", %rax\n"                       \
+	    "    orq $ " TO_STR(syscall) ", %rax\n"                            \
+	    "    syscall")
+#endif
+
+#ifdef __i386__
+#define build_restorer(syscall_bit, syscall)                                   \
+	asm(".text\n"                                                          \
+	    "    .align 16\n"                                                  \
+	    "__cobalt_sigreturn:\n"                                            \
+	    "    movl $ " TO_STR(syscall_bit) ", %eax\n"                       \
+	    "    orl $ " TO_STR(syscall) ", %eax\n"                            \
+	    "    int  $0x80")
+#endif
+
+/*
+ * __COBALT_SYSCALL_BIT | sc_cobalt_sigreturn
+ */
+build_restorer(__COBALT_SYSCALL_BIT, sc_cobalt_sigreturn);
+
+void *cobalt_get_restorer(void)
+{
+	return &cobalt_sigreturn;
+}
diff --git a/lib/cobalt/internal.h b/lib/cobalt/internal.h
index acb3989f1..4782d154a 100644
--- a/lib/cobalt/internal.h
+++ b/lib/cobalt/internal.h
@@ -132,4 +132,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 40d315ebb..af174d570 100644
--- a/lib/cobalt/signal.c
+++ b/lib/cobalt/signal.c
@@ -126,3 +126,16 @@ 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] 30+ messages in thread

* RE: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-09-07 13:39     ` Jan Kiszka
@ 2023-09-07 13:58       ` Johannes Kirchmair
  0 siblings, 0 replies; 30+ messages in thread
From: Johannes Kirchmair @ 2023-09-07 13:58 UTC (permalink / raw)
  To: Jan Kiszka, xenomai


> -----Original Message-----
> From: Jan Kiszka <jan.kiszka@siemens.com>
> Sent: Donnerstag, 7. September 2023 15:40
> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
> xenomai@lists.linux.dev
> Subject: Re: [PATCH 1/3] [POC] test implementaion of rt-signals
> 
> CAUTION: External E-Mail !
> 
> On 04.09.23 08:55, Johannes Kirchmair wrote:
> > Hi Jan,
> >
> >> -----Original Message-----
> >> From: Jan Kiszka <jan.kiszka@siemens.com>
> >> Sent: Freitag, 1. September 2023 14:00
> >> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
> >> xenomai@lists.linux.dev
> >> Subject: Re: [PATCH 1/3] [POC] test implementaion of rt-signals
> >>
> >> CAUTION: External E-Mail !
> >>
> >> On 16.08.23 12:18, Johannes Kirchmair wrote:
> >>> We implement rt signals to handle exceptions in rt stage.
> >>>
> >>> This is done using dovetail specific functions for setting up the signal
> >>> frame.
> >>>
> >>> This can be used to handle fpe exceptions on the fly, like fixing
> >>> division by zero. An other use case are breakpoints, implemented using the
> >>> illegal opcode exception. The real time handling of the breakpoints would
> >>> be handy for conditional breakpoints or also for stopping watchdogs and
> >>> other tasks in time.
> >>>
> >>> Signed-off-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/signal.h                  |  1 +
> >>>  include/cobalt/uapi/syscall.h                 |  6 ++
> >>>  kernel/cobalt/arch/x86/Makefile               |  2 +-
> >>>  .../arch/x86/include/asm/xenomai/thread.h     | 13 ++++
> >>>  kernel/cobalt/arch/x86/signal_ia32.c          | 75 +++++++++++++++++++
> >>>  kernel/cobalt/arch/x86/signal_ia64.c          | 37 +++++++++
> >>>  kernel/cobalt/dovetail/kevents.c              |  5 ++
> >>>  kernel/cobalt/posix/process.c                 |  3 +-
> >>>  kernel/cobalt/posix/syscall.c                 | 28 +++++++
> >>>  kernel/cobalt/posix/syscall32.c               | 16 ++++
> >>>  kernel/cobalt/thread.c                        | 39 ++++++++++
> >>>  lib/cobalt/arch/x86/Makefile.am               |  2 +-
> >>>  lib/cobalt/arch/x86/sigreturn.c               | 36 +++++++++
> >>>  lib/cobalt/internal.h                         |  2 +
> >>>  lib/cobalt/signal.c                           | 13 ++++
> >>>  18 files changed, 282 insertions(+), 3 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
> >>>
> >>> 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 b79cb8429..33d468419 100644
> >>> --- a/include/cobalt/kernel/thread.h
> >>> +++ b/include/cobalt/kernel/thread.h
> >>> @@ -574,6 +574,8 @@ static inline void
> >> xnthread_propagate_schedparam(struct xnthread *curr)
> >>>               __xnthread_propagate_schedparam(curr);
> >>>  }
> >>>
> >>> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs);
> >>> +
> >>>  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/signal.h b/include/cobalt/uapi/signal.h
> >>> index 8a7ea15a4..1afb6050a 100644
> >>> --- a/include/cobalt/uapi/signal.h
> >>> +++ b/include/cobalt/uapi/signal.h
> >>> @@ -68,6 +68,7 @@
> >>>  #define SIGDEBUG_RESCNT_IMBALANCE    7
> >>>  #define SIGDEBUG_LOCK_BREAK          8
> >>>  #define SIGDEBUG_MUTEX_SLEEP         9
> >>> +#define SIGDEBUG_SIGRESTOR           10
> >>>
> >>>  #define COBALT_DELAYMAX                      2147483647U
> >>>
> >>> diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
> >>> index 3e65efaab..f14bd8ffe 100644
> >>> --- a/include/cobalt/uapi/syscall.h
> >>> +++ b/include/cobalt/uapi/syscall.h
> >>> @@ -142,6 +142,12 @@
> >>>  #define sc_cobalt_timerfd_gettime64          119
> >>>  #define sc_cobalt_pselect64                  120
> >>>
> >>> +/*
> >>> + * Sigmatek specific syscalls
> >>> + */
> >>> +#define sc_cobalt_sigreturn                  121
> >>> +#define sc_cobalt_sigaction                  122
> >>> +
> >>>  #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 93929b645..e725afbff 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 smi.o c1e.o
> >>> +xenomai-y := machine.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 745c32467..4d004680b 100644
> >>> --- a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
> >>> +++ b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
> >>> @@ -28,5 +28,18 @@
> >>>  #define xnarch_fault_bp_p(__nr)              ((current->ptrace & PT_PTRACED)
> &&
> >> \
> >>>                                        ((__nr) == X86_TRAP_DB || (__nr) == X86_TRAP_BP))
> >>>  #define xnarch_fault_notify(__nr)    (!xnarch_fault_bp_p(__nr))
> >>> +#define xnarch_fault_code(__regs)            ((__regs)->orig_ax)
> >>> +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);
> >>> +
> >>> +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);
> >>>
> >>>  #endif /* !_COBALT_X86_ASM_THREAD_H */
> >>> diff --git a/kernel/cobalt/arch/x86/signal_ia32.c
> >> b/kernel/cobalt/arch/x86/signal_ia32.c
> >>> new file mode 100644
> >>> index 000000000..140016460
> >>> --- /dev/null
> >>> +++ b/kernel/cobalt/arch/x86/signal_ia32.c
> >>> @@ -0,0 +1,75 @@
> >>> +#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>
> >>> +
> >>> +int xnarch_setup_trap_info(unsigned int vector, struct pt_regs *regs,
> >>> +                        long errcode, int *sig, struct kernel_siginfo *info)
> >>
> >> Why is this function in file that suggests to handle only 32-bit? It's
> >> shared by both 32 and 64 bit.
> > Did not changed it yet?
> > Should I add an distinct signal.c file for the function?
> 
> Yes, that would be logical in this case.
Actually noticed that I do exactly the same in xnarch_rt_sigreturn_ia32
and xnarch_rt_sigreturn_ia64 so I moved this to generic code.
And moved the xnarch_setup_trap_info to signal.c

Will post new patches, where I fixed some of the complains in the previous mails, tomorrow.
> 
> >
> >>
> >>> +{
> >>> +     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;
> >>> +}
> >>> +
> >>> +int xnarch_rt_sigreturn_ia32(struct pt_regs *regs)
> >>> +{
> >>> +     int ret;
> >>> +
> >>> +     ret = dovetail_restore_rt_signal_frame(regs);
> >>> +     if (ret < 0)
> >>> +             goto badframe;
> >>> +
> >>> +     return regs->ax;
> >>> +
> >>> +badframe:
> >>> +     xnthread_call_mayday(xnthread_current(), SIGDEBUG_SIGRESTOR);
> >>> +     return -1;
> >>> +}
> >>> +
> >>> diff --git a/kernel/cobalt/arch/x86/signal_ia64.c
> >> b/kernel/cobalt/arch/x86/signal_ia64.c
> >>> new file mode 100644
> >>> index 000000000..3b8cd3330
> >>> --- /dev/null
> >>> +++ b/kernel/cobalt/arch/x86/signal_ia64.c
> >>> @@ -0,0 +1,37 @@
> >>> +// 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
> >>> + */
> >>> +
> >>> +#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>
> >>> +
> >>> +int xnarch_rt_sigreturn_ia64(struct pt_regs *regs)
> >>> +{
> >>> +     int ret;
> >>> +
> >>> +     ret = dovetail_restore_rt_signal_frame(regs);
> >>> +     if (ret < 0)
> >>> +             goto badframe;
> >>> +
> >>> +     return regs->ax;
> >>> +
> >>> +badframe:
> >>> +     xnthread_call_mayday(xnthread_current(), SIGDEBUG_SIGRESTOR);
> >>
> >> I'm not sure if this is the right way to react. Mayday will translate to
> >> SIGDEBUG, but we need a SIGSEGV.
> >>
> >>> +     return -1;
> >>> +
> >>> +}
> >>> +
> >>> diff --git a/kernel/cobalt/dovetail/kevents.c
> b/kernel/cobalt/dovetail/kevents.c
> >>> index 4da4f51b7..61417717b 100644
> >>> --- a/kernel/cobalt/dovetail/kevents.c
> >>> +++ b/kernel/cobalt/dovetail/kevents.c
> >>> @@ -57,6 +57,9 @@ void handle_oob_trap_entry(unsigned int trapnr, struct
> >> pt_regs *regs)
> >>>               xnsched_run();
> >>>       }
> >>>
> >>> +     if (xnthread_handle_rt_signals(trapnr, regs) == 0)
> >>> +             return;
> >>> +
> >>>       /*
> >>>        * If we experienced a trap on behalf of a shadow thread
> >>>        * running in primary mode, move it to the Linux domain,
> >>> @@ -88,6 +91,8 @@ void handle_oob_trap_entry(unsigned int trapnr, struct
> >> pt_regs *regs)
> >>>               xnstat_counter_inc(&thread->stat.pf);
> >>>
> >>>       xnthread_relax(xnarch_fault_notify(trapnr), SIGDEBUG_MIGRATE_FAULT);
> >>> +
> >>> +     return;
> >>
> >> Unrelated and unneeded change.
> >>
> >>>  }
> >>>
> >>>  static inline int handle_setaffinity_event(struct dovetail_migration_data *d)
> >>> diff --git a/kernel/cobalt/posix/process.c b/kernel/cobalt/posix/process.c
> >>> index 1abc86f37..2069129cb 100644
> >>> --- a/kernel/cobalt/posix/process.c
> >>> +++ b/kernel/cobalt/posix/process.c
> >>> @@ -738,9 +738,10 @@ void cobalt_unregister_debugged_thread(struct
> >> xnthread *thread)
> >>>               cobalt_resume_debugged_process(process);
> >>>  }
> >>>
> >>> +#ifdef CONFIG_SMP
> >>> +
> >>>  int cobalt_handle_setaffinity_event(struct task_struct *task)
> >>>  {
> >>> -#ifdef CONFIG_SMP
> >>
> >> Unrelated and bogus change.
> >>
> >>>       struct xnthread *thread;
> >>>       spl_t s;
> >>>
> >>> diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c
> >>> index 46c4998e4..b4bd4c587 100644
> >>> --- a/kernel/cobalt/posix/syscall.c
> >>> +++ b/kernel/cobalt/posix/syscall.c
> >>> @@ -277,6 +277,34 @@ static COBALT_SYSCALL(serialdbg, current,
> >>>       return 0;
> >>>  }
> >>>
> >>> +static COBALT_SYSCALL(sigreturn, current, (void))
> >>> +{
> >>> +     struct pt_regs *regs = task_pt_regs(current);
> >>> +
> >>> +     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);
> >>> +}
> >>> +
> >>> +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 780d276b1..7c858f904 100644
> >>> --- a/kernel/cobalt/posix/syscall32.c
> >>> +++ b/kernel/cobalt/posix/syscall32.c
> >>> @@ -705,6 +705,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 old_timespec32 __user *u_ts,
> >>> diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
> >>> index 41804b24f..71f97c481 100644
> >>> --- a/kernel/cobalt/thread.c
> >>> +++ b/kernel/cobalt/thread.c
> >>> @@ -25,6 +25,7 @@
> >>>  #include <linux/signal.h>
> >>>  #include <linux/pid.h>
> >>>  #include <linux/sched.h>
> >>> +#include <asm/sighandling.h>
> >>>  #include <uapi/linux/sched/types.h>
> >>>  #include <cobalt/kernel/sched.h>
> >>>  #include <cobalt/kernel/timer.h>
> >>> @@ -43,6 +44,7 @@
> >>>  #include <pipeline/inband_work.h>
> >>>  #include <pipeline/sched.h>
> >>>  #include <trace/events/cobalt-core.h>
> >>> +#include "posix/process.h"
> >>>  #include "debug.h"
> >>>
> >>>  static DECLARE_WAIT_QUEUE_HEAD(join_all);
> >>> @@ -2520,6 +2522,43 @@ int xnthread_killall(int grace, int mask)
> >>>  }
> >>>  EXPORT_SYMBOL_GPL(xnthread_killall);
> >>>
> >>> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs)
> >>> +{
> >>> +     struct ksignal ksig;
> >>> +
> >>> +     unsigned int vector = trapnr;
> >>> +     unsigned int code = xnarch_fault_code(regs);
> >>> +     struct cobalt_ppd *sys_ppd;
> >>> +     int sig, ret = 0;
> >>> +     struct kernel_siginfo si;
> >>> +
> >>> +     code = xnarch_fault_code(regs);
> >>> +     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;
> >>> +
> >>> +     ksig.sig = sig;
> >>> +     memcpy(&ksig.info, &si, sizeof(si));
> >>> +     ksig.ka.sa.sa_flags = SA_SIGINFO | SA_RESTORER;
> >>> +     ksig.ka.sa.sa_restorer = sys_ppd->sigrestorer;
> >>> +     ksig.ka.sa.sa_handler = sys_ppd->sighand[sig];
> >>> +
> >>> +     ret = dovetail_setup_rt_signal_frame(&ksig, regs);
> >>
> >> All this is called with interrupts off on x86, and that makes dovetail
> >> unhappy:
> >>
> >> [   17.051995] 9pnet: Limiting 'msize' to 512000 as this is the maximum
> supported
> >> by transport virtio
> >> [   37.268218] ------------[ cut here ]------------
> >> [   37.268223] WARNING: CPU: 2 PID: 1402 at ../mm/memory.c:5857
> >> __might_fault+0x95/0xa0
> >> [   37.268237] Modules linked in: 9p netfs rt_e1000 rt_e1000_new rtnet
> >> [   37.268252] CPU: 2 PID: 1402 Comm: rt-task Not tainted 6.5.0+ #40
> >> [   37.268259] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS
> rel-
> >> 1.16.0-0-gd239552c-rebuilt.opensuse.org 04/01/2014
> >> [   37.268262] IRQ stage: Xenomai
> >> [   37.268265] RIP: 0010:__might_fault+0x95/0xa0
> >> [   37.268271] Code: b8 a0 01 00 00 e8 cb bf e3 ff 48 8b bb e8 04 00 00 48 8b
> 5d
> >> f8 48 c7 c6 6b 29 2d 81 58 c9 48 81 c7 a0 01 00 00 e9 2b bc e3 ff <0f> 0b eb
> 86
> >> 0f 1f 80 00 00 00 00 90 90 90 90 90 90 90 90 90 90 90
> >> [   37.268277] RSP: 0000:ffffc900007f3cd0 EFLAGS: 00010046
> >> [   37.268283] RAX: 0000000000000006 RBX: 00007f5aa94016b8 RCX:
> >> ffffc900007f3d70
> >> [   37.268287] RDX: 00007f5aa9401cc4 RSI: 00000000000000a7 RDI:
> >> ffffffff82962a10
> >> [   37.268291] RBP: ffffc900007f3cd8 R08: 0000000000000444 R09:
> >> 0000000000000000
> >> [   37.268295] R10: 0000000000000000 R11: 0000000000000000 R12:
> >> 0000000000000000
> >> [   37.268298] R13: ffff888009e6e700 R14: 0000000000000000 R15:
> >> 00000000000299a0
> >> [   37.268302] FS:  00007f5aa9402700(0000) GS:ffff88803ed00000(0000)
> >> knlGS:0000000000000000
> >> [   37.268313] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> >> [   37.268317] CR2: 0000560ba8044008 CR3: 000000000981a004 CR4:
> >> 0000000000370ee0
> >> [   37.268321] DR0: 0000000000000000 DR1: 0000000000000000 DR2:
> >> 0000000000000000
> >> [   37.268324] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7:
> >> 0000000000000400
> >> [   37.268328] Call Trace:
> >> [   37.268332]  <TASK>
> >> [   37.268339]  ? __warn+0x81/0x180
> >> [   37.268350]  ? __might_fault+0x95/0xa0
> >> [   37.268363]  ? report_bug+0x10b/0x200
> >> [   37.268406]  ? handle_bug+0x50/0xc0
> >> [   37.268417]  ? exc_invalid_op+0xc7/0xe0
> >> [   37.268427]  ? asm_exc_invalid_op+0x16/0x20
> >> [   37.268467]  ? __might_fault+0x95/0xa0
> >> [   37.268485]  copy_fpstate_to_sigframe+0x74/0x430
> >> [   37.268496]  ? ___xnsched_run+0x223/0x590
> >> [   37.268515]  ? __pfx____xnsched_run+0x10/0x10
> >> [   37.268541]  get_sigframe+0xea/0x2b0
> >> [   37.268562]  x64_setup_rt_frame+0x68/0x2f0
> >> [   37.268583]  xnthread_handle_rt_signals+0xf8/0x130
> >> [   37.268633]  handle_oob_trap_entry+0xaa/0x3a0
> >> [   37.268640]  ? __pfx_CoBaLt_sigaction+0x10/0x10
> >> [   37.268666]  __oob_trap_notify+0x27/0x30
> >> [   37.268674]  do_error_trap+0x162/0x1d0
> >> [   37.268695]  exc_divide_error+0x35/0x50
> >> [   37.268707]  asm_exc_divide_error+0x16/0x20
> >> [   37.268713] RIP: 0033:0x400e68
> >>
> >> I'm currently scratching my head if we can safely enable hard interrupts
> >> here to resolve this (and the underlying latency source).
> > Not sure what is the right way. Have some problems understanding, what has to
> be protected for the setup to work correct.
> >
> 
> I have a working dovetail patch locally will share it later.
Nice.
> 
> >>
> >> We will also need pagefault_disable in our dovetail functions, already
> >> playing with that.
> > Could you explain to me, what pagefault_disable does and by we need it.
> 
> For us, it primarily signals to the might_sleep() check that we don't
> expect any waiting due to not yet mapped memory - accesses under that
> protection are supposed to succeed or fail immediately. The kernel
> writes: "If disabled, it will not take any locks and go straight to the
> fixup table."
Ok, thx for explaining.

Johannes

> 
> Jan
> 
> --
> Siemens AG, Technology
> Linux Expert Center


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

* Re: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-09-04  6:55   ` Johannes Kirchmair
@ 2023-09-07 13:39     ` Jan Kiszka
  2023-09-07 13:58       ` Johannes Kirchmair
  0 siblings, 1 reply; 30+ messages in thread
From: Jan Kiszka @ 2023-09-07 13:39 UTC (permalink / raw)
  To: Johannes Kirchmair, xenomai

On 04.09.23 08:55, Johannes Kirchmair wrote:
> Hi Jan,
> 
>> -----Original Message-----
>> From: Jan Kiszka <jan.kiszka@siemens.com>
>> Sent: Freitag, 1. September 2023 14:00
>> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
>> xenomai@lists.linux.dev
>> Subject: Re: [PATCH 1/3] [POC] test implementaion of rt-signals
>>
>> CAUTION: External E-Mail !
>>
>> On 16.08.23 12:18, Johannes Kirchmair wrote:
>>> We implement rt signals to handle exceptions in rt stage.
>>>
>>> This is done using dovetail specific functions for setting up the signal
>>> frame.
>>>
>>> This can be used to handle fpe exceptions on the fly, like fixing
>>> division by zero. An other use case are breakpoints, implemented using the
>>> illegal opcode exception. The real time handling of the breakpoints would
>>> be handy for conditional breakpoints or also for stopping watchdogs and
>>> other tasks in time.
>>>
>>> Signed-off-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/signal.h                  |  1 +
>>>  include/cobalt/uapi/syscall.h                 |  6 ++
>>>  kernel/cobalt/arch/x86/Makefile               |  2 +-
>>>  .../arch/x86/include/asm/xenomai/thread.h     | 13 ++++
>>>  kernel/cobalt/arch/x86/signal_ia32.c          | 75 +++++++++++++++++++
>>>  kernel/cobalt/arch/x86/signal_ia64.c          | 37 +++++++++
>>>  kernel/cobalt/dovetail/kevents.c              |  5 ++
>>>  kernel/cobalt/posix/process.c                 |  3 +-
>>>  kernel/cobalt/posix/syscall.c                 | 28 +++++++
>>>  kernel/cobalt/posix/syscall32.c               | 16 ++++
>>>  kernel/cobalt/thread.c                        | 39 ++++++++++
>>>  lib/cobalt/arch/x86/Makefile.am               |  2 +-
>>>  lib/cobalt/arch/x86/sigreturn.c               | 36 +++++++++
>>>  lib/cobalt/internal.h                         |  2 +
>>>  lib/cobalt/signal.c                           | 13 ++++
>>>  18 files changed, 282 insertions(+), 3 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
>>>
>>> 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 b79cb8429..33d468419 100644
>>> --- a/include/cobalt/kernel/thread.h
>>> +++ b/include/cobalt/kernel/thread.h
>>> @@ -574,6 +574,8 @@ static inline void
>> xnthread_propagate_schedparam(struct xnthread *curr)
>>>               __xnthread_propagate_schedparam(curr);
>>>  }
>>>
>>> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs);
>>> +
>>>  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/signal.h b/include/cobalt/uapi/signal.h
>>> index 8a7ea15a4..1afb6050a 100644
>>> --- a/include/cobalt/uapi/signal.h
>>> +++ b/include/cobalt/uapi/signal.h
>>> @@ -68,6 +68,7 @@
>>>  #define SIGDEBUG_RESCNT_IMBALANCE    7
>>>  #define SIGDEBUG_LOCK_BREAK          8
>>>  #define SIGDEBUG_MUTEX_SLEEP         9
>>> +#define SIGDEBUG_SIGRESTOR           10
>>>
>>>  #define COBALT_DELAYMAX                      2147483647U
>>>
>>> diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
>>> index 3e65efaab..f14bd8ffe 100644
>>> --- a/include/cobalt/uapi/syscall.h
>>> +++ b/include/cobalt/uapi/syscall.h
>>> @@ -142,6 +142,12 @@
>>>  #define sc_cobalt_timerfd_gettime64          119
>>>  #define sc_cobalt_pselect64                  120
>>>
>>> +/*
>>> + * Sigmatek specific syscalls
>>> + */
>>> +#define sc_cobalt_sigreturn                  121
>>> +#define sc_cobalt_sigaction                  122
>>> +
>>>  #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 93929b645..e725afbff 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 smi.o c1e.o
>>> +xenomai-y := machine.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 745c32467..4d004680b 100644
>>> --- a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
>>> +++ b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
>>> @@ -28,5 +28,18 @@
>>>  #define xnarch_fault_bp_p(__nr)              ((current->ptrace & PT_PTRACED) &&
>> \
>>>                                        ((__nr) == X86_TRAP_DB || (__nr) == X86_TRAP_BP))
>>>  #define xnarch_fault_notify(__nr)    (!xnarch_fault_bp_p(__nr))
>>> +#define xnarch_fault_code(__regs)            ((__regs)->orig_ax)
>>> +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);
>>> +
>>> +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);
>>>
>>>  #endif /* !_COBALT_X86_ASM_THREAD_H */
>>> diff --git a/kernel/cobalt/arch/x86/signal_ia32.c
>> b/kernel/cobalt/arch/x86/signal_ia32.c
>>> new file mode 100644
>>> index 000000000..140016460
>>> --- /dev/null
>>> +++ b/kernel/cobalt/arch/x86/signal_ia32.c
>>> @@ -0,0 +1,75 @@
>>> +#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>
>>> +
>>> +int xnarch_setup_trap_info(unsigned int vector, struct pt_regs *regs,
>>> +                        long errcode, int *sig, struct kernel_siginfo *info)
>>
>> Why is this function in file that suggests to handle only 32-bit? It's
>> shared by both 32 and 64 bit.
> Did not changed it yet?
> Should I add an distinct signal.c file for the function?

Yes, that would be logical in this case.

> 
>>
>>> +{
>>> +     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;
>>> +}
>>> +
>>> +int xnarch_rt_sigreturn_ia32(struct pt_regs *regs)
>>> +{
>>> +     int ret;
>>> +
>>> +     ret = dovetail_restore_rt_signal_frame(regs);
>>> +     if (ret < 0)
>>> +             goto badframe;
>>> +
>>> +     return regs->ax;
>>> +
>>> +badframe:
>>> +     xnthread_call_mayday(xnthread_current(), SIGDEBUG_SIGRESTOR);
>>> +     return -1;
>>> +}
>>> +
>>> diff --git a/kernel/cobalt/arch/x86/signal_ia64.c
>> b/kernel/cobalt/arch/x86/signal_ia64.c
>>> new file mode 100644
>>> index 000000000..3b8cd3330
>>> --- /dev/null
>>> +++ b/kernel/cobalt/arch/x86/signal_ia64.c
>>> @@ -0,0 +1,37 @@
>>> +// 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
>>> + */
>>> +
>>> +#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>
>>> +
>>> +int xnarch_rt_sigreturn_ia64(struct pt_regs *regs)
>>> +{
>>> +     int ret;
>>> +
>>> +     ret = dovetail_restore_rt_signal_frame(regs);
>>> +     if (ret < 0)
>>> +             goto badframe;
>>> +
>>> +     return regs->ax;
>>> +
>>> +badframe:
>>> +     xnthread_call_mayday(xnthread_current(), SIGDEBUG_SIGRESTOR);
>>
>> I'm not sure if this is the right way to react. Mayday will translate to
>> SIGDEBUG, but we need a SIGSEGV.
>>
>>> +     return -1;
>>> +
>>> +}
>>> +
>>> diff --git a/kernel/cobalt/dovetail/kevents.c b/kernel/cobalt/dovetail/kevents.c
>>> index 4da4f51b7..61417717b 100644
>>> --- a/kernel/cobalt/dovetail/kevents.c
>>> +++ b/kernel/cobalt/dovetail/kevents.c
>>> @@ -57,6 +57,9 @@ void handle_oob_trap_entry(unsigned int trapnr, struct
>> pt_regs *regs)
>>>               xnsched_run();
>>>       }
>>>
>>> +     if (xnthread_handle_rt_signals(trapnr, regs) == 0)
>>> +             return;
>>> +
>>>       /*
>>>        * If we experienced a trap on behalf of a shadow thread
>>>        * running in primary mode, move it to the Linux domain,
>>> @@ -88,6 +91,8 @@ void handle_oob_trap_entry(unsigned int trapnr, struct
>> pt_regs *regs)
>>>               xnstat_counter_inc(&thread->stat.pf);
>>>
>>>       xnthread_relax(xnarch_fault_notify(trapnr), SIGDEBUG_MIGRATE_FAULT);
>>> +
>>> +     return;
>>
>> Unrelated and unneeded change.
>>
>>>  }
>>>
>>>  static inline int handle_setaffinity_event(struct dovetail_migration_data *d)
>>> diff --git a/kernel/cobalt/posix/process.c b/kernel/cobalt/posix/process.c
>>> index 1abc86f37..2069129cb 100644
>>> --- a/kernel/cobalt/posix/process.c
>>> +++ b/kernel/cobalt/posix/process.c
>>> @@ -738,9 +738,10 @@ void cobalt_unregister_debugged_thread(struct
>> xnthread *thread)
>>>               cobalt_resume_debugged_process(process);
>>>  }
>>>
>>> +#ifdef CONFIG_SMP
>>> +
>>>  int cobalt_handle_setaffinity_event(struct task_struct *task)
>>>  {
>>> -#ifdef CONFIG_SMP
>>
>> Unrelated and bogus change.
>>
>>>       struct xnthread *thread;
>>>       spl_t s;
>>>
>>> diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c
>>> index 46c4998e4..b4bd4c587 100644
>>> --- a/kernel/cobalt/posix/syscall.c
>>> +++ b/kernel/cobalt/posix/syscall.c
>>> @@ -277,6 +277,34 @@ static COBALT_SYSCALL(serialdbg, current,
>>>       return 0;
>>>  }
>>>
>>> +static COBALT_SYSCALL(sigreturn, current, (void))
>>> +{
>>> +     struct pt_regs *regs = task_pt_regs(current);
>>> +
>>> +     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);
>>> +}
>>> +
>>> +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 780d276b1..7c858f904 100644
>>> --- a/kernel/cobalt/posix/syscall32.c
>>> +++ b/kernel/cobalt/posix/syscall32.c
>>> @@ -705,6 +705,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 old_timespec32 __user *u_ts,
>>> diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
>>> index 41804b24f..71f97c481 100644
>>> --- a/kernel/cobalt/thread.c
>>> +++ b/kernel/cobalt/thread.c
>>> @@ -25,6 +25,7 @@
>>>  #include <linux/signal.h>
>>>  #include <linux/pid.h>
>>>  #include <linux/sched.h>
>>> +#include <asm/sighandling.h>
>>>  #include <uapi/linux/sched/types.h>
>>>  #include <cobalt/kernel/sched.h>
>>>  #include <cobalt/kernel/timer.h>
>>> @@ -43,6 +44,7 @@
>>>  #include <pipeline/inband_work.h>
>>>  #include <pipeline/sched.h>
>>>  #include <trace/events/cobalt-core.h>
>>> +#include "posix/process.h"
>>>  #include "debug.h"
>>>
>>>  static DECLARE_WAIT_QUEUE_HEAD(join_all);
>>> @@ -2520,6 +2522,43 @@ int xnthread_killall(int grace, int mask)
>>>  }
>>>  EXPORT_SYMBOL_GPL(xnthread_killall);
>>>
>>> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs)
>>> +{
>>> +     struct ksignal ksig;
>>> +
>>> +     unsigned int vector = trapnr;
>>> +     unsigned int code = xnarch_fault_code(regs);
>>> +     struct cobalt_ppd *sys_ppd;
>>> +     int sig, ret = 0;
>>> +     struct kernel_siginfo si;
>>> +
>>> +     code = xnarch_fault_code(regs);
>>> +     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;
>>> +
>>> +     ksig.sig = sig;
>>> +     memcpy(&ksig.info, &si, sizeof(si));
>>> +     ksig.ka.sa.sa_flags = SA_SIGINFO | SA_RESTORER;
>>> +     ksig.ka.sa.sa_restorer = sys_ppd->sigrestorer;
>>> +     ksig.ka.sa.sa_handler = sys_ppd->sighand[sig];
>>> +
>>> +     ret = dovetail_setup_rt_signal_frame(&ksig, regs);
>>
>> All this is called with interrupts off on x86, and that makes dovetail
>> unhappy:
>>
>> [   17.051995] 9pnet: Limiting 'msize' to 512000 as this is the maximum supported
>> by transport virtio
>> [   37.268218] ------------[ cut here ]------------
>> [   37.268223] WARNING: CPU: 2 PID: 1402 at ../mm/memory.c:5857
>> __might_fault+0x95/0xa0
>> [   37.268237] Modules linked in: 9p netfs rt_e1000 rt_e1000_new rtnet
>> [   37.268252] CPU: 2 PID: 1402 Comm: rt-task Not tainted 6.5.0+ #40
>> [   37.268259] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-
>> 1.16.0-0-gd239552c-rebuilt.opensuse.org 04/01/2014
>> [   37.268262] IRQ stage: Xenomai
>> [   37.268265] RIP: 0010:__might_fault+0x95/0xa0
>> [   37.268271] Code: b8 a0 01 00 00 e8 cb bf e3 ff 48 8b bb e8 04 00 00 48 8b 5d
>> f8 48 c7 c6 6b 29 2d 81 58 c9 48 81 c7 a0 01 00 00 e9 2b bc e3 ff <0f> 0b eb 86
>> 0f 1f 80 00 00 00 00 90 90 90 90 90 90 90 90 90 90 90
>> [   37.268277] RSP: 0000:ffffc900007f3cd0 EFLAGS: 00010046
>> [   37.268283] RAX: 0000000000000006 RBX: 00007f5aa94016b8 RCX:
>> ffffc900007f3d70
>> [   37.268287] RDX: 00007f5aa9401cc4 RSI: 00000000000000a7 RDI:
>> ffffffff82962a10
>> [   37.268291] RBP: ffffc900007f3cd8 R08: 0000000000000444 R09:
>> 0000000000000000
>> [   37.268295] R10: 0000000000000000 R11: 0000000000000000 R12:
>> 0000000000000000
>> [   37.268298] R13: ffff888009e6e700 R14: 0000000000000000 R15:
>> 00000000000299a0
>> [   37.268302] FS:  00007f5aa9402700(0000) GS:ffff88803ed00000(0000)
>> knlGS:0000000000000000
>> [   37.268313] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
>> [   37.268317] CR2: 0000560ba8044008 CR3: 000000000981a004 CR4:
>> 0000000000370ee0
>> [   37.268321] DR0: 0000000000000000 DR1: 0000000000000000 DR2:
>> 0000000000000000
>> [   37.268324] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7:
>> 0000000000000400
>> [   37.268328] Call Trace:
>> [   37.268332]  <TASK>
>> [   37.268339]  ? __warn+0x81/0x180
>> [   37.268350]  ? __might_fault+0x95/0xa0
>> [   37.268363]  ? report_bug+0x10b/0x200
>> [   37.268406]  ? handle_bug+0x50/0xc0
>> [   37.268417]  ? exc_invalid_op+0xc7/0xe0
>> [   37.268427]  ? asm_exc_invalid_op+0x16/0x20
>> [   37.268467]  ? __might_fault+0x95/0xa0
>> [   37.268485]  copy_fpstate_to_sigframe+0x74/0x430
>> [   37.268496]  ? ___xnsched_run+0x223/0x590
>> [   37.268515]  ? __pfx____xnsched_run+0x10/0x10
>> [   37.268541]  get_sigframe+0xea/0x2b0
>> [   37.268562]  x64_setup_rt_frame+0x68/0x2f0
>> [   37.268583]  xnthread_handle_rt_signals+0xf8/0x130
>> [   37.268633]  handle_oob_trap_entry+0xaa/0x3a0
>> [   37.268640]  ? __pfx_CoBaLt_sigaction+0x10/0x10
>> [   37.268666]  __oob_trap_notify+0x27/0x30
>> [   37.268674]  do_error_trap+0x162/0x1d0
>> [   37.268695]  exc_divide_error+0x35/0x50
>> [   37.268707]  asm_exc_divide_error+0x16/0x20
>> [   37.268713] RIP: 0033:0x400e68
>>
>> I'm currently scratching my head if we can safely enable hard interrupts
>> here to resolve this (and the underlying latency source).
> Not sure what is the right way. Have some problems understanding, what has to be protected for the setup to work correct.
> 

I have a working dovetail patch locally will share it later.

>>
>> We will also need pagefault_disable in our dovetail functions, already
>> playing with that.
> Could you explain to me, what pagefault_disable does and by we need it.

For us, it primarily signals to the might_sleep() check that we don't
expect any waiting due to not yet mapped memory - accesses under that
protection are supposed to succeed or fail immediately. The kernel
writes: "If disabled, it will not take any locks and go straight to the
fixup table."

Jan

-- 
Siemens AG, Technology
Linux Expert Center


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

* RE: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-08-16 11:24 ` Florian Bezdeka
  2023-08-16 11:36   ` Jan Kiszka
@ 2023-09-07 10:48   ` Johannes Kirchmair
  2023-09-11  8:41     ` Florian Bezdeka
  1 sibling, 1 reply; 30+ messages in thread
From: Johannes Kirchmair @ 2023-09-07 10:48 UTC (permalink / raw)
  To: Florian Bezdeka, xenomai; +Cc: Jan Kiszka

Hey Florian,

> -----Original Message-----
> From: Florian Bezdeka <florian.bezdeka@siemens.com>
[...]
> > +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;
> > +}
> > +
> 
> You did not touch the syscall32-table.h (x86 specific), so I would
> expect that your compat support is broken right now. You should end up
> in the "native" so x86_64 implementation. That brings me to the next
> question:
Checked this and you are right, we end up in the "native" implementation of the syscall.
Will drop the compat syscall.

> 
> Can't we avoid a special compat case here? The pointers themselfs are
> corrected by the syscall entry machinery but the memory pointed to is
> not. So is the memory pointed to by handler and restorer different in
> terms of memory layout/padding?
We don’t access the memory pointed to from kernel space, so this should not be imported or am I missing something?

> 
> In addition you should update kernel/cobalt/trace/cobalt-posix.h to get
> proper trace support.
Changed the following define to look like this:
#define __cobalt_syscall_name(__nr)					\
	__print_symbolic((__nr),					\
		....
		__cobalt_symbolic_syscall(pselect64),			\
		__cobalt_symbolic_syscall(sigreturn),			\
		__cobalt_symbolic_syscall(sigaction))

Is this sufficient or do I have to change something else?

Best regards Johannes




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

* RE: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-09-01 14:11   ` Jan Kiszka
@ 2023-09-04  7:04     ` Johannes Kirchmair
  0 siblings, 0 replies; 30+ messages in thread
From: Johannes Kirchmair @ 2023-09-04  7:04 UTC (permalink / raw)
  To: Jan Kiszka, xenomai


> -----Original Message-----
> From: Jan Kiszka <jan.kiszka@siemens.com>
> Sent: Freitag, 1. September 2023 16:12
> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
> xenomai@lists.linux.dev
> Subject: Re: [PATCH 1/3] [POC] test implementaion of rt-signals
> 
> CAUTION: External E-Mail !
> 
> On 01.09.23 15:51, Jan Kiszka wrote:
> > On 16.08.23 12:18, Johannes Kirchmair wrote:
> >> +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);
> >
> > This looks suspicious: We modify DR7 unconditionally, even if we do not
> > handle the signal? Is that OK for the kernel code that takes over then
> > because it will simply do the same?
> >
> 
> I fact, I'm not sure if we can solve any real problem by permitting the
> application to catch breakpoint or single-step events over RT threads.
> 
> We do have the use case of hooking in with a high-prio RT handler prior
> to a debug stop of an RT process, and we have a downstream approach for
> that. But that is using a special monitor threat and cannot be
> re-modeled via synchronous signals this way.
> 
> For now, I would leave out DB and BP traps.
Removed it for now and added the code for SEGV from one of the previous mails.

Johannes

> 
> Jan
> 
> --
> Siemens AG, Technology
> Linux Expert Center


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

* RE: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-09-01 12:00 ` Jan Kiszka
  2023-09-01 13:38   ` Jan Kiszka
@ 2023-09-04  6:55   ` Johannes Kirchmair
  2023-09-07 13:39     ` Jan Kiszka
  1 sibling, 1 reply; 30+ messages in thread
From: Johannes Kirchmair @ 2023-09-04  6:55 UTC (permalink / raw)
  To: Jan Kiszka, xenomai

Hi Jan,

> -----Original Message-----
> From: Jan Kiszka <jan.kiszka@siemens.com>
> Sent: Freitag, 1. September 2023 14:00
> To: Johannes Kirchmair <johannes.kirchmair@sigmatek.at>;
> xenomai@lists.linux.dev
> Subject: Re: [PATCH 1/3] [POC] test implementaion of rt-signals
> 
> CAUTION: External E-Mail !
> 
> On 16.08.23 12:18, Johannes Kirchmair wrote:
> > We implement rt signals to handle exceptions in rt stage.
> >
> > This is done using dovetail specific functions for setting up the signal
> > frame.
> >
> > This can be used to handle fpe exceptions on the fly, like fixing
> > division by zero. An other use case are breakpoints, implemented using the
> > illegal opcode exception. The real time handling of the breakpoints would
> > be handy for conditional breakpoints or also for stopping watchdogs and
> > other tasks in time.
> >
> > Signed-off-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/signal.h                  |  1 +
> >  include/cobalt/uapi/syscall.h                 |  6 ++
> >  kernel/cobalt/arch/x86/Makefile               |  2 +-
> >  .../arch/x86/include/asm/xenomai/thread.h     | 13 ++++
> >  kernel/cobalt/arch/x86/signal_ia32.c          | 75 +++++++++++++++++++
> >  kernel/cobalt/arch/x86/signal_ia64.c          | 37 +++++++++
> >  kernel/cobalt/dovetail/kevents.c              |  5 ++
> >  kernel/cobalt/posix/process.c                 |  3 +-
> >  kernel/cobalt/posix/syscall.c                 | 28 +++++++
> >  kernel/cobalt/posix/syscall32.c               | 16 ++++
> >  kernel/cobalt/thread.c                        | 39 ++++++++++
> >  lib/cobalt/arch/x86/Makefile.am               |  2 +-
> >  lib/cobalt/arch/x86/sigreturn.c               | 36 +++++++++
> >  lib/cobalt/internal.h                         |  2 +
> >  lib/cobalt/signal.c                           | 13 ++++
> >  18 files changed, 282 insertions(+), 3 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
> >
> > 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 b79cb8429..33d468419 100644
> > --- a/include/cobalt/kernel/thread.h
> > +++ b/include/cobalt/kernel/thread.h
> > @@ -574,6 +574,8 @@ static inline void
> xnthread_propagate_schedparam(struct xnthread *curr)
> >               __xnthread_propagate_schedparam(curr);
> >  }
> >
> > +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs);
> > +
> >  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/signal.h b/include/cobalt/uapi/signal.h
> > index 8a7ea15a4..1afb6050a 100644
> > --- a/include/cobalt/uapi/signal.h
> > +++ b/include/cobalt/uapi/signal.h
> > @@ -68,6 +68,7 @@
> >  #define SIGDEBUG_RESCNT_IMBALANCE    7
> >  #define SIGDEBUG_LOCK_BREAK          8
> >  #define SIGDEBUG_MUTEX_SLEEP         9
> > +#define SIGDEBUG_SIGRESTOR           10
> >
> >  #define COBALT_DELAYMAX                      2147483647U
> >
> > diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
> > index 3e65efaab..f14bd8ffe 100644
> > --- a/include/cobalt/uapi/syscall.h
> > +++ b/include/cobalt/uapi/syscall.h
> > @@ -142,6 +142,12 @@
> >  #define sc_cobalt_timerfd_gettime64          119
> >  #define sc_cobalt_pselect64                  120
> >
> > +/*
> > + * Sigmatek specific syscalls
> > + */
> > +#define sc_cobalt_sigreturn                  121
> > +#define sc_cobalt_sigaction                  122
> > +
> >  #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 93929b645..e725afbff 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 smi.o c1e.o
> > +xenomai-y := machine.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 745c32467..4d004680b 100644
> > --- a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
> > +++ b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
> > @@ -28,5 +28,18 @@
> >  #define xnarch_fault_bp_p(__nr)              ((current->ptrace & PT_PTRACED) &&
> \
> >                                        ((__nr) == X86_TRAP_DB || (__nr) == X86_TRAP_BP))
> >  #define xnarch_fault_notify(__nr)    (!xnarch_fault_bp_p(__nr))
> > +#define xnarch_fault_code(__regs)            ((__regs)->orig_ax)
> > +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);
> > +
> > +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);
> >
> >  #endif /* !_COBALT_X86_ASM_THREAD_H */
> > diff --git a/kernel/cobalt/arch/x86/signal_ia32.c
> b/kernel/cobalt/arch/x86/signal_ia32.c
> > new file mode 100644
> > index 000000000..140016460
> > --- /dev/null
> > +++ b/kernel/cobalt/arch/x86/signal_ia32.c
> > @@ -0,0 +1,75 @@
> > +#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>
> > +
> > +int xnarch_setup_trap_info(unsigned int vector, struct pt_regs *regs,
> > +                        long errcode, int *sig, struct kernel_siginfo *info)
> 
> Why is this function in file that suggests to handle only 32-bit? It's
> shared by both 32 and 64 bit.
Did not changed it yet?
Should I add an distinct signal.c file for the function?

> 
> > +{
> > +     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;
> > +}
> > +
> > +int xnarch_rt_sigreturn_ia32(struct pt_regs *regs)
> > +{
> > +     int ret;
> > +
> > +     ret = dovetail_restore_rt_signal_frame(regs);
> > +     if (ret < 0)
> > +             goto badframe;
> > +
> > +     return regs->ax;
> > +
> > +badframe:
> > +     xnthread_call_mayday(xnthread_current(), SIGDEBUG_SIGRESTOR);
> > +     return -1;
> > +}
> > +
> > diff --git a/kernel/cobalt/arch/x86/signal_ia64.c
> b/kernel/cobalt/arch/x86/signal_ia64.c
> > new file mode 100644
> > index 000000000..3b8cd3330
> > --- /dev/null
> > +++ b/kernel/cobalt/arch/x86/signal_ia64.c
> > @@ -0,0 +1,37 @@
> > +// 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
> > + */
> > +
> > +#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>
> > +
> > +int xnarch_rt_sigreturn_ia64(struct pt_regs *regs)
> > +{
> > +     int ret;
> > +
> > +     ret = dovetail_restore_rt_signal_frame(regs);
> > +     if (ret < 0)
> > +             goto badframe;
> > +
> > +     return regs->ax;
> > +
> > +badframe:
> > +     xnthread_call_mayday(xnthread_current(), SIGDEBUG_SIGRESTOR);
> 
> I'm not sure if this is the right way to react. Mayday will translate to
> SIGDEBUG, but we need a SIGSEGV.
> 
> > +     return -1;
> > +
> > +}
> > +
> > diff --git a/kernel/cobalt/dovetail/kevents.c b/kernel/cobalt/dovetail/kevents.c
> > index 4da4f51b7..61417717b 100644
> > --- a/kernel/cobalt/dovetail/kevents.c
> > +++ b/kernel/cobalt/dovetail/kevents.c
> > @@ -57,6 +57,9 @@ void handle_oob_trap_entry(unsigned int trapnr, struct
> pt_regs *regs)
> >               xnsched_run();
> >       }
> >
> > +     if (xnthread_handle_rt_signals(trapnr, regs) == 0)
> > +             return;
> > +
> >       /*
> >        * If we experienced a trap on behalf of a shadow thread
> >        * running in primary mode, move it to the Linux domain,
> > @@ -88,6 +91,8 @@ void handle_oob_trap_entry(unsigned int trapnr, struct
> pt_regs *regs)
> >               xnstat_counter_inc(&thread->stat.pf);
> >
> >       xnthread_relax(xnarch_fault_notify(trapnr), SIGDEBUG_MIGRATE_FAULT);
> > +
> > +     return;
> 
> Unrelated and unneeded change.
> 
> >  }
> >
> >  static inline int handle_setaffinity_event(struct dovetail_migration_data *d)
> > diff --git a/kernel/cobalt/posix/process.c b/kernel/cobalt/posix/process.c
> > index 1abc86f37..2069129cb 100644
> > --- a/kernel/cobalt/posix/process.c
> > +++ b/kernel/cobalt/posix/process.c
> > @@ -738,9 +738,10 @@ void cobalt_unregister_debugged_thread(struct
> xnthread *thread)
> >               cobalt_resume_debugged_process(process);
> >  }
> >
> > +#ifdef CONFIG_SMP
> > +
> >  int cobalt_handle_setaffinity_event(struct task_struct *task)
> >  {
> > -#ifdef CONFIG_SMP
> 
> Unrelated and bogus change.
> 
> >       struct xnthread *thread;
> >       spl_t s;
> >
> > diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c
> > index 46c4998e4..b4bd4c587 100644
> > --- a/kernel/cobalt/posix/syscall.c
> > +++ b/kernel/cobalt/posix/syscall.c
> > @@ -277,6 +277,34 @@ static COBALT_SYSCALL(serialdbg, current,
> >       return 0;
> >  }
> >
> > +static COBALT_SYSCALL(sigreturn, current, (void))
> > +{
> > +     struct pt_regs *regs = task_pt_regs(current);
> > +
> > +     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);
> > +}
> > +
> > +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 780d276b1..7c858f904 100644
> > --- a/kernel/cobalt/posix/syscall32.c
> > +++ b/kernel/cobalt/posix/syscall32.c
> > @@ -705,6 +705,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 old_timespec32 __user *u_ts,
> > diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
> > index 41804b24f..71f97c481 100644
> > --- a/kernel/cobalt/thread.c
> > +++ b/kernel/cobalt/thread.c
> > @@ -25,6 +25,7 @@
> >  #include <linux/signal.h>
> >  #include <linux/pid.h>
> >  #include <linux/sched.h>
> > +#include <asm/sighandling.h>
> >  #include <uapi/linux/sched/types.h>
> >  #include <cobalt/kernel/sched.h>
> >  #include <cobalt/kernel/timer.h>
> > @@ -43,6 +44,7 @@
> >  #include <pipeline/inband_work.h>
> >  #include <pipeline/sched.h>
> >  #include <trace/events/cobalt-core.h>
> > +#include "posix/process.h"
> >  #include "debug.h"
> >
> >  static DECLARE_WAIT_QUEUE_HEAD(join_all);
> > @@ -2520,6 +2522,43 @@ int xnthread_killall(int grace, int mask)
> >  }
> >  EXPORT_SYMBOL_GPL(xnthread_killall);
> >
> > +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs)
> > +{
> > +     struct ksignal ksig;
> > +
> > +     unsigned int vector = trapnr;
> > +     unsigned int code = xnarch_fault_code(regs);
> > +     struct cobalt_ppd *sys_ppd;
> > +     int sig, ret = 0;
> > +     struct kernel_siginfo si;
> > +
> > +     code = xnarch_fault_code(regs);
> > +     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;
> > +
> > +     ksig.sig = sig;
> > +     memcpy(&ksig.info, &si, sizeof(si));
> > +     ksig.ka.sa.sa_flags = SA_SIGINFO | SA_RESTORER;
> > +     ksig.ka.sa.sa_restorer = sys_ppd->sigrestorer;
> > +     ksig.ka.sa.sa_handler = sys_ppd->sighand[sig];
> > +
> > +     ret = dovetail_setup_rt_signal_frame(&ksig, regs);
> 
> All this is called with interrupts off on x86, and that makes dovetail
> unhappy:
> 
> [   17.051995] 9pnet: Limiting 'msize' to 512000 as this is the maximum supported
> by transport virtio
> [   37.268218] ------------[ cut here ]------------
> [   37.268223] WARNING: CPU: 2 PID: 1402 at ../mm/memory.c:5857
> __might_fault+0x95/0xa0
> [   37.268237] Modules linked in: 9p netfs rt_e1000 rt_e1000_new rtnet
> [   37.268252] CPU: 2 PID: 1402 Comm: rt-task Not tainted 6.5.0+ #40
> [   37.268259] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-
> 1.16.0-0-gd239552c-rebuilt.opensuse.org 04/01/2014
> [   37.268262] IRQ stage: Xenomai
> [   37.268265] RIP: 0010:__might_fault+0x95/0xa0
> [   37.268271] Code: b8 a0 01 00 00 e8 cb bf e3 ff 48 8b bb e8 04 00 00 48 8b 5d
> f8 48 c7 c6 6b 29 2d 81 58 c9 48 81 c7 a0 01 00 00 e9 2b bc e3 ff <0f> 0b eb 86
> 0f 1f 80 00 00 00 00 90 90 90 90 90 90 90 90 90 90 90
> [   37.268277] RSP: 0000:ffffc900007f3cd0 EFLAGS: 00010046
> [   37.268283] RAX: 0000000000000006 RBX: 00007f5aa94016b8 RCX:
> ffffc900007f3d70
> [   37.268287] RDX: 00007f5aa9401cc4 RSI: 00000000000000a7 RDI:
> ffffffff82962a10
> [   37.268291] RBP: ffffc900007f3cd8 R08: 0000000000000444 R09:
> 0000000000000000
> [   37.268295] R10: 0000000000000000 R11: 0000000000000000 R12:
> 0000000000000000
> [   37.268298] R13: ffff888009e6e700 R14: 0000000000000000 R15:
> 00000000000299a0
> [   37.268302] FS:  00007f5aa9402700(0000) GS:ffff88803ed00000(0000)
> knlGS:0000000000000000
> [   37.268313] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [   37.268317] CR2: 0000560ba8044008 CR3: 000000000981a004 CR4:
> 0000000000370ee0
> [   37.268321] DR0: 0000000000000000 DR1: 0000000000000000 DR2:
> 0000000000000000
> [   37.268324] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7:
> 0000000000000400
> [   37.268328] Call Trace:
> [   37.268332]  <TASK>
> [   37.268339]  ? __warn+0x81/0x180
> [   37.268350]  ? __might_fault+0x95/0xa0
> [   37.268363]  ? report_bug+0x10b/0x200
> [   37.268406]  ? handle_bug+0x50/0xc0
> [   37.268417]  ? exc_invalid_op+0xc7/0xe0
> [   37.268427]  ? asm_exc_invalid_op+0x16/0x20
> [   37.268467]  ? __might_fault+0x95/0xa0
> [   37.268485]  copy_fpstate_to_sigframe+0x74/0x430
> [   37.268496]  ? ___xnsched_run+0x223/0x590
> [   37.268515]  ? __pfx____xnsched_run+0x10/0x10
> [   37.268541]  get_sigframe+0xea/0x2b0
> [   37.268562]  x64_setup_rt_frame+0x68/0x2f0
> [   37.268583]  xnthread_handle_rt_signals+0xf8/0x130
> [   37.268633]  handle_oob_trap_entry+0xaa/0x3a0
> [   37.268640]  ? __pfx_CoBaLt_sigaction+0x10/0x10
> [   37.268666]  __oob_trap_notify+0x27/0x30
> [   37.268674]  do_error_trap+0x162/0x1d0
> [   37.268695]  exc_divide_error+0x35/0x50
> [   37.268707]  asm_exc_divide_error+0x16/0x20
> [   37.268713] RIP: 0033:0x400e68
> 
> I'm currently scratching my head if we can safely enable hard interrupts
> here to resolve this (and the underlying latency source).
Not sure what is the right way. Have some problems understanding, what has to be protected for the setup to work correct.

> 
> We will also need pagefault_disable in our dovetail functions, already
> playing with that.
Could you explain to me, what pagefault_disable does and by we need it.

> 
> > +     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..df961469e
> > --- /dev/null
> > +++ b/lib/cobalt/arch/x86/sigreturn.c
> > @@ -0,0 +1,36 @@
> > +#include <cobalt/uapi/syscall.h>
> > +#include "internal.h"
> > +
> > +extern void cobalt_sigreturn (void) asm ("__cobalt_sigreturn") __attribute__
> ((visibility ("hidden")));
> > +
> > +#define TO_STR(x) #x
> > +
> > +#ifdef __x86_64__
> > +#define build_restorer(syscall_bit, syscall)                                   \
> > +     asm(".text\n"                                                          \
> > +         "    .align 16\n"                                                  \
> > +         "__cobalt_sigreturn:\n"                                            \
> > +         "    movq $ " TO_STR(syscall_bit) ", %rax\n"                       \
> > +         "    orq $ " TO_STR(syscall) ", %rax\n"                            \
> > +         "    syscall")
> > +#endif
> > +
> > +#ifdef __i386__
> > +#define build_restorer(syscall_bit, syscall)                                   \
> > +     asm(".text\n"                                                          \
> > +         "    .align 16\n"                                                  \
> > +         "__cobalt_sigreturn:\n"                                            \
> > +         "    movl $ " TO_STR(syscall_bit) ", %eax\n"                       \
> > +         "    orl $ " TO_STR(syscall) ", %eax\n"                            \
> > +         "    int  $0x80")
> > +#endif
> > +
> > +/*
> > + * __COBALT_SYSCALL_BIT | sc_cobalt_sigreturn
> > + */
> > +build_restorer(__COBALT_SYSCALL_BIT, sc_cobalt_sigreturn);
> > +
> > +void *cobalt_get_restorer(void)
> > +{
> > +     return &cobalt_sigreturn;
> > +}
> > diff --git a/lib/cobalt/internal.h b/lib/cobalt/internal.h
> > index acb3989f1..4782d154a 100644
> > --- a/lib/cobalt/internal.h
> > +++ b/lib/cobalt/internal.h
> > @@ -132,4 +132,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 40d315ebb..af174d570 100644
> > --- a/lib/cobalt/signal.c
> > +++ b/lib/cobalt/signal.c
> > @@ -126,3 +126,16 @@ 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;
> > +}
> 
> IOW: I started hacking as well, based on latest 6.5 and xenomai next.
> More to come.
That’s good, actually notice more and more, that my knowledge of the kernel is to limited to tackle this signal implementation.

Best regards 
Johannes
> 
> Jan
> 
> --
> Siemens AG, Technology
> Linux Expert Center


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

* Re: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-09-01 13:51 ` Jan Kiszka
@ 2023-09-01 14:11   ` Jan Kiszka
  2023-09-04  7:04     ` Johannes Kirchmair
  0 siblings, 1 reply; 30+ messages in thread
From: Jan Kiszka @ 2023-09-01 14:11 UTC (permalink / raw)
  To: Johannes Kirchmair, xenomai

On 01.09.23 15:51, Jan Kiszka wrote:
> On 16.08.23 12:18, Johannes Kirchmair wrote:
>> +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);
> 
> This looks suspicious: We modify DR7 unconditionally, even if we do not
> handle the signal? Is that OK for the kernel code that takes over then
> because it will simply do the same?
> 

I fact, I'm not sure if we can solve any real problem by permitting the
application to catch breakpoint or single-step events over RT threads.

We do have the use case of hooking in with a high-prio RT handler prior
to a debug stop of an RT process, and we have a downstream approach for
that. But that is using a special monitor threat and cannot be
re-modeled via synchronous signals this way.

For now, I would leave out DB and BP traps.

Jan

-- 
Siemens AG, Technology
Linux Expert Center


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

* Re: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-08-16 10:18 Johannes Kirchmair
  2023-08-16 11:24 ` Florian Bezdeka
  2023-09-01 12:00 ` Jan Kiszka
@ 2023-09-01 13:51 ` Jan Kiszka
  2023-09-01 14:11   ` Jan Kiszka
  2024-03-05 15:54 ` Richard Weinberger
  3 siblings, 1 reply; 30+ messages in thread
From: Jan Kiszka @ 2023-09-01 13:51 UTC (permalink / raw)
  To: Johannes Kirchmair, xenomai

On 16.08.23 12:18, Johannes Kirchmair wrote:
> +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);

This looks suspicious: We modify DR7 unconditionally, even if we do not
handle the signal? Is that OK for the kernel code that takes over then
because it will simply do the same?

Jan

> +		*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;
> +	}

-- 
Siemens AG, Technology
Linux Expert Center


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

* Re: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-09-01 12:00 ` Jan Kiszka
@ 2023-09-01 13:38   ` Jan Kiszka
  2023-09-04  6:55   ` Johannes Kirchmair
  1 sibling, 0 replies; 30+ messages in thread
From: Jan Kiszka @ 2023-09-01 13:38 UTC (permalink / raw)
  To: Johannes Kirchmair, xenomai

On 01.09.23 14:00, Jan Kiszka wrote:
> On 16.08.23 12:18, Johannes Kirchmair wrote:
>> We implement rt signals to handle exceptions in rt stage.
>>
>> This is done using dovetail specific functions for setting up the signal
>> frame.
>>
>> This can be used to handle fpe exceptions on the fly, like fixing
>> division by zero. An other use case are breakpoints, implemented using the
>> illegal opcode exception. The real time handling of the breakpoints would
>> be handy for conditional breakpoints or also for stopping watchdogs and
>> other tasks in time.
>>
>> Signed-off-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/signal.h                  |  1 +
>>  include/cobalt/uapi/syscall.h                 |  6 ++
>>  kernel/cobalt/arch/x86/Makefile               |  2 +-
>>  .../arch/x86/include/asm/xenomai/thread.h     | 13 ++++
>>  kernel/cobalt/arch/x86/signal_ia32.c          | 75 +++++++++++++++++++
>>  kernel/cobalt/arch/x86/signal_ia64.c          | 37 +++++++++
>>  kernel/cobalt/dovetail/kevents.c              |  5 ++
>>  kernel/cobalt/posix/process.c                 |  3 +-
>>  kernel/cobalt/posix/syscall.c                 | 28 +++++++
>>  kernel/cobalt/posix/syscall32.c               | 16 ++++
>>  kernel/cobalt/thread.c                        | 39 ++++++++++
>>  lib/cobalt/arch/x86/Makefile.am               |  2 +-
>>  lib/cobalt/arch/x86/sigreturn.c               | 36 +++++++++
>>  lib/cobalt/internal.h                         |  2 +
>>  lib/cobalt/signal.c                           | 13 ++++
>>  18 files changed, 282 insertions(+), 3 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
>>
>> 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 b79cb8429..33d468419 100644
>> --- a/include/cobalt/kernel/thread.h
>> +++ b/include/cobalt/kernel/thread.h
>> @@ -574,6 +574,8 @@ static inline void xnthread_propagate_schedparam(struct xnthread *curr)
>>  		__xnthread_propagate_schedparam(curr);
>>  }
>>  
>> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs);
>> +
>>  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/signal.h b/include/cobalt/uapi/signal.h
>> index 8a7ea15a4..1afb6050a 100644
>> --- a/include/cobalt/uapi/signal.h
>> +++ b/include/cobalt/uapi/signal.h
>> @@ -68,6 +68,7 @@
>>  #define SIGDEBUG_RESCNT_IMBALANCE	7
>>  #define SIGDEBUG_LOCK_BREAK		8
>>  #define SIGDEBUG_MUTEX_SLEEP		9
>> +#define SIGDEBUG_SIGRESTOR		10
>>  
>>  #define COBALT_DELAYMAX			2147483647U
>>  
>> diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
>> index 3e65efaab..f14bd8ffe 100644
>> --- a/include/cobalt/uapi/syscall.h
>> +++ b/include/cobalt/uapi/syscall.h
>> @@ -142,6 +142,12 @@
>>  #define sc_cobalt_timerfd_gettime64		119
>>  #define sc_cobalt_pselect64			120
>>  
>> +/*
>> + * Sigmatek specific syscalls
>> + */
>> +#define sc_cobalt_sigreturn			121
>> +#define sc_cobalt_sigaction			122
>> +
>>  #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 93929b645..e725afbff 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 smi.o c1e.o
>> +xenomai-y := machine.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 745c32467..4d004680b 100644
>> --- a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
>> +++ b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
>> @@ -28,5 +28,18 @@
>>  #define xnarch_fault_bp_p(__nr)		((current->ptrace & PT_PTRACED) &&	\
>>  					 ((__nr) == X86_TRAP_DB || (__nr) == X86_TRAP_BP))
>>  #define xnarch_fault_notify(__nr)	(!xnarch_fault_bp_p(__nr))
>> +#define xnarch_fault_code(__regs)		((__regs)->orig_ax)
>> +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);
>> +
>> +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);
>>  
>>  #endif /* !_COBALT_X86_ASM_THREAD_H */
>> diff --git a/kernel/cobalt/arch/x86/signal_ia32.c b/kernel/cobalt/arch/x86/signal_ia32.c
>> new file mode 100644
>> index 000000000..140016460
>> --- /dev/null
>> +++ b/kernel/cobalt/arch/x86/signal_ia32.c
>> @@ -0,0 +1,75 @@
>> +#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>
>> +
>> +int xnarch_setup_trap_info(unsigned int vector, struct pt_regs *regs,
>> +			   long errcode, int *sig, struct kernel_siginfo *info)
> 
> Why is this function in file that suggests to handle only 32-bit? It's 
> shared by both 32 and 64 bit.
> 
>> +{
>> +	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;

I've also added this:

	case 14:
		*sig = SIGSEGV;
		info->si_signo = *sig;
		info->si_errno = errcode;
		info->si_code = 0;
		info->si_addr = 0;
		return 0;

That fixes the related test case.

As you can see, we can neither provide an accurate fault address nor a
proper code because those information are lost along the dovetail
notification path or do not even exist by that time. The address could
probably be forwarded by extending dovetail, the code likely not.

Jan

-- 
Siemens AG, Technology
Linux Expert Center


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

* Re: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-08-16 10:18 Johannes Kirchmair
  2023-08-16 11:24 ` Florian Bezdeka
@ 2023-09-01 12:00 ` Jan Kiszka
  2023-09-01 13:38   ` Jan Kiszka
  2023-09-04  6:55   ` Johannes Kirchmair
  2023-09-01 13:51 ` Jan Kiszka
  2024-03-05 15:54 ` Richard Weinberger
  3 siblings, 2 replies; 30+ messages in thread
From: Jan Kiszka @ 2023-09-01 12:00 UTC (permalink / raw)
  To: Johannes Kirchmair, xenomai

On 16.08.23 12:18, Johannes Kirchmair wrote:
> We implement rt signals to handle exceptions in rt stage.
> 
> This is done using dovetail specific functions for setting up the signal
> frame.
> 
> This can be used to handle fpe exceptions on the fly, like fixing
> division by zero. An other use case are breakpoints, implemented using the
> illegal opcode exception. The real time handling of the breakpoints would
> be handy for conditional breakpoints or also for stopping watchdogs and
> other tasks in time.
> 
> Signed-off-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/signal.h                  |  1 +
>  include/cobalt/uapi/syscall.h                 |  6 ++
>  kernel/cobalt/arch/x86/Makefile               |  2 +-
>  .../arch/x86/include/asm/xenomai/thread.h     | 13 ++++
>  kernel/cobalt/arch/x86/signal_ia32.c          | 75 +++++++++++++++++++
>  kernel/cobalt/arch/x86/signal_ia64.c          | 37 +++++++++
>  kernel/cobalt/dovetail/kevents.c              |  5 ++
>  kernel/cobalt/posix/process.c                 |  3 +-
>  kernel/cobalt/posix/syscall.c                 | 28 +++++++
>  kernel/cobalt/posix/syscall32.c               | 16 ++++
>  kernel/cobalt/thread.c                        | 39 ++++++++++
>  lib/cobalt/arch/x86/Makefile.am               |  2 +-
>  lib/cobalt/arch/x86/sigreturn.c               | 36 +++++++++
>  lib/cobalt/internal.h                         |  2 +
>  lib/cobalt/signal.c                           | 13 ++++
>  18 files changed, 282 insertions(+), 3 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
> 
> 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 b79cb8429..33d468419 100644
> --- a/include/cobalt/kernel/thread.h
> +++ b/include/cobalt/kernel/thread.h
> @@ -574,6 +574,8 @@ static inline void xnthread_propagate_schedparam(struct xnthread *curr)
>  		__xnthread_propagate_schedparam(curr);
>  }
>  
> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs);
> +
>  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/signal.h b/include/cobalt/uapi/signal.h
> index 8a7ea15a4..1afb6050a 100644
> --- a/include/cobalt/uapi/signal.h
> +++ b/include/cobalt/uapi/signal.h
> @@ -68,6 +68,7 @@
>  #define SIGDEBUG_RESCNT_IMBALANCE	7
>  #define SIGDEBUG_LOCK_BREAK		8
>  #define SIGDEBUG_MUTEX_SLEEP		9
> +#define SIGDEBUG_SIGRESTOR		10
>  
>  #define COBALT_DELAYMAX			2147483647U
>  
> diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
> index 3e65efaab..f14bd8ffe 100644
> --- a/include/cobalt/uapi/syscall.h
> +++ b/include/cobalt/uapi/syscall.h
> @@ -142,6 +142,12 @@
>  #define sc_cobalt_timerfd_gettime64		119
>  #define sc_cobalt_pselect64			120
>  
> +/*
> + * Sigmatek specific syscalls
> + */
> +#define sc_cobalt_sigreturn			121
> +#define sc_cobalt_sigaction			122
> +
>  #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 93929b645..e725afbff 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 smi.o c1e.o
> +xenomai-y := machine.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 745c32467..4d004680b 100644
> --- a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
> +++ b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
> @@ -28,5 +28,18 @@
>  #define xnarch_fault_bp_p(__nr)		((current->ptrace & PT_PTRACED) &&	\
>  					 ((__nr) == X86_TRAP_DB || (__nr) == X86_TRAP_BP))
>  #define xnarch_fault_notify(__nr)	(!xnarch_fault_bp_p(__nr))
> +#define xnarch_fault_code(__regs)		((__regs)->orig_ax)
> +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);
> +
> +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);
>  
>  #endif /* !_COBALT_X86_ASM_THREAD_H */
> diff --git a/kernel/cobalt/arch/x86/signal_ia32.c b/kernel/cobalt/arch/x86/signal_ia32.c
> new file mode 100644
> index 000000000..140016460
> --- /dev/null
> +++ b/kernel/cobalt/arch/x86/signal_ia32.c
> @@ -0,0 +1,75 @@
> +#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>
> +
> +int xnarch_setup_trap_info(unsigned int vector, struct pt_regs *regs,
> +			   long errcode, int *sig, struct kernel_siginfo *info)

Why is this function in file that suggests to handle only 32-bit? It's 
shared by both 32 and 64 bit.

> +{
> +	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;
> +}
> +
> +int xnarch_rt_sigreturn_ia32(struct pt_regs *regs)
> +{
> +	int ret;
> +
> +	ret = dovetail_restore_rt_signal_frame(regs);
> +	if (ret < 0)
> +		goto badframe;
> +
> +	return regs->ax;
> +
> +badframe:
> +	xnthread_call_mayday(xnthread_current(), SIGDEBUG_SIGRESTOR);
> +	return -1;
> +}
> +
> diff --git a/kernel/cobalt/arch/x86/signal_ia64.c b/kernel/cobalt/arch/x86/signal_ia64.c
> new file mode 100644
> index 000000000..3b8cd3330
> --- /dev/null
> +++ b/kernel/cobalt/arch/x86/signal_ia64.c
> @@ -0,0 +1,37 @@
> +// 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
> + */
> +
> +#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>
> +
> +int xnarch_rt_sigreturn_ia64(struct pt_regs *regs)
> +{
> +	int ret;
> +
> +	ret = dovetail_restore_rt_signal_frame(regs);
> +	if (ret < 0)
> +		goto badframe;
> +
> +	return regs->ax;
> +
> +badframe:
> +	xnthread_call_mayday(xnthread_current(), SIGDEBUG_SIGRESTOR);

I'm not sure if this is the right way to react. Mayday will translate to 
SIGDEBUG, but we need a SIGSEGV.

> +	return -1;
> +
> +}
> +
> diff --git a/kernel/cobalt/dovetail/kevents.c b/kernel/cobalt/dovetail/kevents.c
> index 4da4f51b7..61417717b 100644
> --- a/kernel/cobalt/dovetail/kevents.c
> +++ b/kernel/cobalt/dovetail/kevents.c
> @@ -57,6 +57,9 @@ void handle_oob_trap_entry(unsigned int trapnr, struct pt_regs *regs)
>  		xnsched_run();
>  	}
>  
> +	if (xnthread_handle_rt_signals(trapnr, regs) == 0)
> +		return;
> +
>  	/*
>  	 * If we experienced a trap on behalf of a shadow thread
>  	 * running in primary mode, move it to the Linux domain,
> @@ -88,6 +91,8 @@ void handle_oob_trap_entry(unsigned int trapnr, struct pt_regs *regs)
>  		xnstat_counter_inc(&thread->stat.pf);
>  
>  	xnthread_relax(xnarch_fault_notify(trapnr), SIGDEBUG_MIGRATE_FAULT);
> +
> +	return;

Unrelated and unneeded change.

>  }
>  
>  static inline int handle_setaffinity_event(struct dovetail_migration_data *d)
> diff --git a/kernel/cobalt/posix/process.c b/kernel/cobalt/posix/process.c
> index 1abc86f37..2069129cb 100644
> --- a/kernel/cobalt/posix/process.c
> +++ b/kernel/cobalt/posix/process.c
> @@ -738,9 +738,10 @@ void cobalt_unregister_debugged_thread(struct xnthread *thread)
>  		cobalt_resume_debugged_process(process);
>  }
>  
> +#ifdef CONFIG_SMP
> +
>  int cobalt_handle_setaffinity_event(struct task_struct *task)
>  {
> -#ifdef CONFIG_SMP

Unrelated and bogus change.

>  	struct xnthread *thread;
>  	spl_t s;
>  
> diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c
> index 46c4998e4..b4bd4c587 100644
> --- a/kernel/cobalt/posix/syscall.c
> +++ b/kernel/cobalt/posix/syscall.c
> @@ -277,6 +277,34 @@ static COBALT_SYSCALL(serialdbg, current,
>  	return 0;
>  }
>  
> +static COBALT_SYSCALL(sigreturn, current, (void))
> +{
> +	struct pt_regs *regs = task_pt_regs(current);
> +
> +	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);
> +}
> +
> +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 780d276b1..7c858f904 100644
> --- a/kernel/cobalt/posix/syscall32.c
> +++ b/kernel/cobalt/posix/syscall32.c
> @@ -705,6 +705,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 old_timespec32 __user *u_ts,
> diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
> index 41804b24f..71f97c481 100644
> --- a/kernel/cobalt/thread.c
> +++ b/kernel/cobalt/thread.c
> @@ -25,6 +25,7 @@
>  #include <linux/signal.h>
>  #include <linux/pid.h>
>  #include <linux/sched.h>
> +#include <asm/sighandling.h>
>  #include <uapi/linux/sched/types.h>
>  #include <cobalt/kernel/sched.h>
>  #include <cobalt/kernel/timer.h>
> @@ -43,6 +44,7 @@
>  #include <pipeline/inband_work.h>
>  #include <pipeline/sched.h>
>  #include <trace/events/cobalt-core.h>
> +#include "posix/process.h"
>  #include "debug.h"
>  
>  static DECLARE_WAIT_QUEUE_HEAD(join_all);
> @@ -2520,6 +2522,43 @@ int xnthread_killall(int grace, int mask)
>  }
>  EXPORT_SYMBOL_GPL(xnthread_killall);
>  
> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs)
> +{
> +	struct ksignal ksig;
> +
> +	unsigned int vector = trapnr;
> +	unsigned int code = xnarch_fault_code(regs);
> +	struct cobalt_ppd *sys_ppd;
> +	int sig, ret = 0;
> +	struct kernel_siginfo si;
> +
> +	code = xnarch_fault_code(regs);
> +	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;
> +
> +	ksig.sig = sig;
> +	memcpy(&ksig.info, &si, sizeof(si));
> +	ksig.ka.sa.sa_flags = SA_SIGINFO | SA_RESTORER;
> +	ksig.ka.sa.sa_restorer = sys_ppd->sigrestorer;
> +	ksig.ka.sa.sa_handler = sys_ppd->sighand[sig];
> +
> +	ret = dovetail_setup_rt_signal_frame(&ksig, regs);

All this is called with interrupts off on x86, and that makes dovetail 
unhappy:

[   17.051995] 9pnet: Limiting 'msize' to 512000 as this is the maximum supported by transport virtio
[   37.268218] ------------[ cut here ]------------
[   37.268223] WARNING: CPU: 2 PID: 1402 at ../mm/memory.c:5857 __might_fault+0x95/0xa0
[   37.268237] Modules linked in: 9p netfs rt_e1000 rt_e1000_new rtnet
[   37.268252] CPU: 2 PID: 1402 Comm: rt-task Not tainted 6.5.0+ #40
[   37.268259] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.0-0-gd239552c-rebuilt.opensuse.org 04/01/2014
[   37.268262] IRQ stage: Xenomai
[   37.268265] RIP: 0010:__might_fault+0x95/0xa0
[   37.268271] Code: b8 a0 01 00 00 e8 cb bf e3 ff 48 8b bb e8 04 00 00 48 8b 5d f8 48 c7 c6 6b 29 2d 81 58 c9 48 81 c7 a0 01 00 00 e9 2b bc e3 ff <0f> 0b eb 86 0f 1f 80 00 00 00 00 90 90 90 90 90 90 90 90 90 90 90
[   37.268277] RSP: 0000:ffffc900007f3cd0 EFLAGS: 00010046
[   37.268283] RAX: 0000000000000006 RBX: 00007f5aa94016b8 RCX: ffffc900007f3d70
[   37.268287] RDX: 00007f5aa9401cc4 RSI: 00000000000000a7 RDI: ffffffff82962a10
[   37.268291] RBP: ffffc900007f3cd8 R08: 0000000000000444 R09: 0000000000000000
[   37.268295] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
[   37.268298] R13: ffff888009e6e700 R14: 0000000000000000 R15: 00000000000299a0
[   37.268302] FS:  00007f5aa9402700(0000) GS:ffff88803ed00000(0000) knlGS:0000000000000000
[   37.268313] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   37.268317] CR2: 0000560ba8044008 CR3: 000000000981a004 CR4: 0000000000370ee0
[   37.268321] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[   37.268324] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[   37.268328] Call Trace:
[   37.268332]  <TASK>
[   37.268339]  ? __warn+0x81/0x180
[   37.268350]  ? __might_fault+0x95/0xa0
[   37.268363]  ? report_bug+0x10b/0x200
[   37.268406]  ? handle_bug+0x50/0xc0
[   37.268417]  ? exc_invalid_op+0xc7/0xe0
[   37.268427]  ? asm_exc_invalid_op+0x16/0x20
[   37.268467]  ? __might_fault+0x95/0xa0
[   37.268485]  copy_fpstate_to_sigframe+0x74/0x430
[   37.268496]  ? ___xnsched_run+0x223/0x590
[   37.268515]  ? __pfx____xnsched_run+0x10/0x10
[   37.268541]  get_sigframe+0xea/0x2b0
[   37.268562]  x64_setup_rt_frame+0x68/0x2f0
[   37.268583]  xnthread_handle_rt_signals+0xf8/0x130
[   37.268633]  handle_oob_trap_entry+0xaa/0x3a0
[   37.268640]  ? __pfx_CoBaLt_sigaction+0x10/0x10
[   37.268666]  __oob_trap_notify+0x27/0x30
[   37.268674]  do_error_trap+0x162/0x1d0
[   37.268695]  exc_divide_error+0x35/0x50
[   37.268707]  asm_exc_divide_error+0x16/0x20
[   37.268713] RIP: 0033:0x400e68

I'm currently scratching my head if we can safely enable hard interrupts 
here to resolve this (and the underlying latency source).

We will also need pagefault_disable in our dovetail functions, already 
playing with that.

> +	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..df961469e
> --- /dev/null
> +++ b/lib/cobalt/arch/x86/sigreturn.c
> @@ -0,0 +1,36 @@
> +#include <cobalt/uapi/syscall.h>
> +#include "internal.h"
> +
> +extern void cobalt_sigreturn (void) asm ("__cobalt_sigreturn") __attribute__ ((visibility ("hidden")));
> +
> +#define TO_STR(x) #x
> +
> +#ifdef __x86_64__
> +#define build_restorer(syscall_bit, syscall)                                   \
> +	asm(".text\n"                                                          \
> +	    "    .align 16\n"                                                  \
> +	    "__cobalt_sigreturn:\n"                                            \
> +	    "    movq $ " TO_STR(syscall_bit) ", %rax\n"                       \
> +	    "    orq $ " TO_STR(syscall) ", %rax\n"                            \
> +	    "    syscall")
> +#endif
> +
> +#ifdef __i386__
> +#define build_restorer(syscall_bit, syscall)                                   \
> +	asm(".text\n"                                                          \
> +	    "    .align 16\n"                                                  \
> +	    "__cobalt_sigreturn:\n"                                            \
> +	    "    movl $ " TO_STR(syscall_bit) ", %eax\n"                       \
> +	    "    orl $ " TO_STR(syscall) ", %eax\n"                            \
> +	    "    int  $0x80")
> +#endif
> +
> +/*
> + * __COBALT_SYSCALL_BIT | sc_cobalt_sigreturn
> + */
> +build_restorer(__COBALT_SYSCALL_BIT, sc_cobalt_sigreturn);
> +
> +void *cobalt_get_restorer(void)
> +{
> +	return &cobalt_sigreturn;
> +}
> diff --git a/lib/cobalt/internal.h b/lib/cobalt/internal.h
> index acb3989f1..4782d154a 100644
> --- a/lib/cobalt/internal.h
> +++ b/lib/cobalt/internal.h
> @@ -132,4 +132,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 40d315ebb..af174d570 100644
> --- a/lib/cobalt/signal.c
> +++ b/lib/cobalt/signal.c
> @@ -126,3 +126,16 @@ 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;
> +}

IOW: I started hacking as well, based on latest 6.5 and xenomai next. 
More to come.

Jan

-- 
Siemens AG, Technology
Linux Expert Center


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

* RE: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-08-16 11:36   ` Jan Kiszka
@ 2023-08-16 11:59     ` Johannes Kirchmair
  0 siblings, 0 replies; 30+ messages in thread
From: Johannes Kirchmair @ 2023-08-16 11:59 UTC (permalink / raw)
  To: Jan Kiszka, Florian Bezdeka, xenomai

Hello,

> -----Original Message-----
> From: Jan Kiszka <jan.kiszka@siemens.com>
> Sent: Mittwoch, 16. August 2023 13:36
> To: Florian Bezdeka <florian.bezdeka@siemens.com>; Johannes Kirchmair
> <johannes.kirchmair@sigmatek.at>; xenomai@lists.linux.dev
> Subject: Re: [PATCH 1/3] [POC] test implementaion of rt-signals
> 
> CAUTION: External E-Mail !
> 
> On 16.08.23 13:24, Florian Bezdeka wrote:
> > On Wed, 2023-08-16 at 12:18 +0200, Johannes Kirchmair wrote:
> >> We implement rt signals to handle exceptions in rt stage.
> >>
> >> This is done using dovetail specific functions for setting up the signal
> >> frame.
> >>
> >> This can be used to handle fpe exceptions on the fly, like fixing
> >> division by zero. An other use case are breakpoints, implemented using the
> >> illegal opcode exception. The real time handling of the breakpoints would
> >> be handy for conditional breakpoints or also for stopping watchdogs and
> >> other tasks in time.
> >>
> >> Signed-off-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/signal.h                  |  1 +
> >>  include/cobalt/uapi/syscall.h                 |  6 ++
> >>  kernel/cobalt/arch/x86/Makefile               |  2 +-
> >>  .../arch/x86/include/asm/xenomai/thread.h     | 13 ++++
> >>  kernel/cobalt/arch/x86/signal_ia32.c          | 75 +++++++++++++++++++
> >>  kernel/cobalt/arch/x86/signal_ia64.c          | 37 +++++++++
> >>  kernel/cobalt/dovetail/kevents.c              |  5 ++
> >>  kernel/cobalt/posix/process.c                 |  3 +-
> >>  kernel/cobalt/posix/syscall.c                 | 28 +++++++
> >>  kernel/cobalt/posix/syscall32.c               | 16 ++++
> >>  kernel/cobalt/thread.c                        | 39 ++++++++++
> >>  lib/cobalt/arch/x86/Makefile.am               |  2 +-
> >>  lib/cobalt/arch/x86/sigreturn.c               | 36 +++++++++
> >>  lib/cobalt/internal.h                         |  2 +
> >>  lib/cobalt/signal.c                           | 13 ++++
> >>  18 files changed, 282 insertions(+), 3 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
> >>
> >> 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 b79cb8429..33d468419 100644
> >> --- a/include/cobalt/kernel/thread.h
> >> +++ b/include/cobalt/kernel/thread.h
> >> @@ -574,6 +574,8 @@ static inline void
> xnthread_propagate_schedparam(struct xnthread *curr)
> >>              __xnthread_propagate_schedparam(curr);
> >>  }
> >>
> >> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs);
> >> +
> >>  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/signal.h b/include/cobalt/uapi/signal.h
> >> index 8a7ea15a4..1afb6050a 100644
> >> --- a/include/cobalt/uapi/signal.h
> >> +++ b/include/cobalt/uapi/signal.h
> >> @@ -68,6 +68,7 @@
> >>  #define SIGDEBUG_RESCNT_IMBALANCE   7
> >>  #define SIGDEBUG_LOCK_BREAK         8
> >>  #define SIGDEBUG_MUTEX_SLEEP                9
> >> +#define SIGDEBUG_SIGRESTOR          10
> >>
> >>  #define COBALT_DELAYMAX                     2147483647U
> >>
> >> diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
> >> index 3e65efaab..f14bd8ffe 100644
> >> --- a/include/cobalt/uapi/syscall.h
> >> +++ b/include/cobalt/uapi/syscall.h
> >> @@ -142,6 +142,12 @@
> >>  #define sc_cobalt_timerfd_gettime64         119
> >>  #define sc_cobalt_pselect64                 120
> >>
> >> +/*
> >> + * Sigmatek specific syscalls
> >> + */
> >
> > The goal would be to become generic so no longer
> > "sigmatek specific" ;-)
> >
> >> +#define sc_cobalt_sigreturn                 121
> >> +#define sc_cobalt_sigaction                 122
> >> +
> >>  #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 93929b645..e725afbff 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 smi.o c1e.o
> >> +xenomai-y := machine.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 745c32467..4d004680b 100644
> >> --- a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
> >> +++ b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
> >> @@ -28,5 +28,18 @@
> >>  #define xnarch_fault_bp_p(__nr)             ((current->ptrace & PT_PTRACED)
> &&      \
> >>                                       ((__nr) == X86_TRAP_DB || (__nr) == X86_TRAP_BP))
> >>  #define xnarch_fault_notify(__nr)   (!xnarch_fault_bp_p(__nr))
> >> +#define xnarch_fault_code(__regs)           ((__regs)->orig_ax)
> >> +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);
> >> +
> >> +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);
> >>
> >>  #endif /* !_COBALT_X86_ASM_THREAD_H */
> >> diff --git a/kernel/cobalt/arch/x86/signal_ia32.c
> b/kernel/cobalt/arch/x86/signal_ia32.c
> >> new file mode 100644
> >> index 000000000..140016460
> >> --- /dev/null
> >> +++ b/kernel/cobalt/arch/x86/signal_ia32.c
> >> @@ -0,0 +1,75 @@
> >> +#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>
> >> +
> >> +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 */
> >
> > Can't we assign names to the possible values of vector? Can't we model
> > that as enum?
> >
> 
> arch/x86/include/asm/trapnr.h ;)
> 
> >> +            *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;
> >> +}
> >> +
> >> +int xnarch_rt_sigreturn_ia32(struct pt_regs *regs)
> >> +{
> >> +    int ret;
> >> +
> >> +    ret = dovetail_restore_rt_signal_frame(regs);
> >> +    if (ret < 0)
> >> +            goto badframe;
> >> +
> >> +    return regs->ax;
> >> +
> >> +badframe:
> >> +    xnthread_call_mayday(xnthread_current(), SIGDEBUG_SIGRESTOR);
> >> +    return -1;
> >> +}
> >> +
> >> diff --git a/kernel/cobalt/arch/x86/signal_ia64.c
> b/kernel/cobalt/arch/x86/signal_ia64.c
> >> new file mode 100644
> >> index 000000000..3b8cd3330
> >> --- /dev/null
> >> +++ b/kernel/cobalt/arch/x86/signal_ia64.c
> >> @@ -0,0 +1,37 @@
> >> +// 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
> >> + */
> >
> > I think the copyright information is just wrong.
> >
> 
> Agreed I don't spot significant kernel code below.
> 
> >> +
> >> +#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>
> >> +
> >> +int xnarch_rt_sigreturn_ia64(struct pt_regs *regs)
> >> +{
> >> +    int ret;
> >> +
> >> +    ret = dovetail_restore_rt_signal_frame(regs);
> >> +    if (ret < 0)
> >> +            goto badframe;
> >> +
> >> +    return regs->ax;
> >> +
> >> +badframe:
> >> +    xnthread_call_mayday(xnthread_current(), SIGDEBUG_SIGRESTOR);
> >> +    return -1;
> >> +
> >> +}
> >> +
> >> diff --git a/kernel/cobalt/dovetail/kevents.c b/kernel/cobalt/dovetail/kevents.c
> >> index 4da4f51b7..61417717b 100644
> >> --- a/kernel/cobalt/dovetail/kevents.c
> >> +++ b/kernel/cobalt/dovetail/kevents.c
> >> @@ -57,6 +57,9 @@ void handle_oob_trap_entry(unsigned int trapnr, struct
> pt_regs *regs)
> >>              xnsched_run();
> >>      }
> >>
> >> +    if (xnthread_handle_rt_signals(trapnr, regs) == 0)
> >> +            return;
> >> +
> >>      /*
> >>       * If we experienced a trap on behalf of a shadow thread
> >>       * running in primary mode, move it to the Linux domain,
> >> @@ -88,6 +91,8 @@ void handle_oob_trap_entry(unsigned int trapnr, struct
> pt_regs *regs)
> >>              xnstat_counter_inc(&thread->stat.pf);
> >>
> >>      xnthread_relax(xnarch_fault_notify(trapnr), SIGDEBUG_MIGRATE_FAULT);
> >> +
> >> +    return;
> >>  }
> >>
> >>  static inline int handle_setaffinity_event(struct dovetail_migration_data *d)
> >> diff --git a/kernel/cobalt/posix/process.c b/kernel/cobalt/posix/process.c
> >> index 1abc86f37..2069129cb 100644
> >> --- a/kernel/cobalt/posix/process.c
> >> +++ b/kernel/cobalt/posix/process.c
> >> @@ -738,9 +738,10 @@ void cobalt_unregister_debugged_thread(struct
> xnthread *thread)
> >>              cobalt_resume_debugged_process(process);
> >>  }
> >>
> >> +#ifdef CONFIG_SMP
> >> +
> >>  int cobalt_handle_setaffinity_event(struct task_struct *task)
> >>  {
> >> -#ifdef CONFIG_SMP
> >>      struct xnthread *thread;
> >>      spl_t s;
> >>
> >> diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c
> >> index 46c4998e4..b4bd4c587 100644
> >> --- a/kernel/cobalt/posix/syscall.c
> >> +++ b/kernel/cobalt/posix/syscall.c
> >> @@ -277,6 +277,34 @@ static COBALT_SYSCALL(serialdbg, current,
> >>      return 0;
> >>  }
> >>
> >> +static COBALT_SYSCALL(sigreturn, current, (void))
> >> +{
> >> +    struct pt_regs *regs = task_pt_regs(current);
> >> +
> >> +    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);
> >> +}
> >> +
> >> +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;
> >
> > No error if sys_ppd->sighand[sig] or sys_ppd->sigrestorer is
> > overwritten?
> > Or the other way around: Why can only the handler be overwritten?
> 
> I think the idea behind this user-provided handler is to replace the
> vdso approach of the kernel - which we can't use as-is because we have a
> different sigreturn syscall. So, the first call from userspace sets this
> handler for the whole process. But there might be better ways than this,
> maybe something done during cobalt binding?
How would I do this?
At what part of code would I have to look?

> 
> This syscall interface is not yet done in any case. It's missing the old
> handler parameter e.g.
> 
> >
> >> +
> >> +    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 780d276b1..7c858f904 100644
> >> --- a/kernel/cobalt/posix/syscall32.c
> >> +++ b/kernel/cobalt/posix/syscall32.c
> >> @@ -705,6 +705,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;
> >> +}
> >> +
> >
> > You did not touch the syscall32-table.h (x86 specific), so I would
> > expect that your compat support is broken right now. You should end up
> > in the "native" so x86_64 implementation. That brings me to the next
> > question:
> >
> > Can't we avoid a special compat case here? The pointers themselfs are
> > corrected by the syscall entry machinery but the memory pointed to is
> > not. So is the memory pointed to by handler and restorer different in
> > terms of memory layout/padding?
> 
> Yes, no new compats, please.
How would I fix this. Where should I look for an example? 
> 
> >
> > In addition you should update kernel/cobalt/trace/cobalt-posix.h to get
> > proper trace support.
> >
> >
> >>  COBALT_SYSCALL32emu(monitor_wait, nonrestartable,
> >>                  (struct cobalt_monitor_shadow __user *u_mon,
> >>                   int event, const struct old_timespec32 __user *u_ts,
> >> diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
> >> index 41804b24f..71f97c481 100644
> >> --- a/kernel/cobalt/thread.c
> >> +++ b/kernel/cobalt/thread.c
> >> @@ -25,6 +25,7 @@
> >>  #include <linux/signal.h>
> >>  #include <linux/pid.h>
> >>  #include <linux/sched.h>
> >> +#include <asm/sighandling.h>
> >>  #include <uapi/linux/sched/types.h>
> >>  #include <cobalt/kernel/sched.h>
> >>  #include <cobalt/kernel/timer.h>
> >> @@ -43,6 +44,7 @@
> >>  #include <pipeline/inband_work.h>
> >>  #include <pipeline/sched.h>
> >>  #include <trace/events/cobalt-core.h>
> >> +#include "posix/process.h"
> >>  #include "debug.h"
> >>
> >>  static DECLARE_WAIT_QUEUE_HEAD(join_all);
> >> @@ -2520,6 +2522,43 @@ int xnthread_killall(int grace, int mask)
> >>  }
> >>  EXPORT_SYMBOL_GPL(xnthread_killall);
> >>
> >> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs)
> >> +{
> >> +    struct ksignal ksig;
> >> +
> >> +    unsigned int vector = trapnr;
> >> +    unsigned int code = xnarch_fault_code(regs);
> >> +    struct cobalt_ppd *sys_ppd;
> >> +    int sig, ret = 0;
> >> +    struct kernel_siginfo si;
> >
> > Style: Reverse christmas tree.
> >
> >> +
> >> +    code = xnarch_fault_code(regs);
> >> +    ret = xnarch_setup_trap_info(vector, regs, code, &sig, &si);
> >> +    if (ret || sig == 0)
> >> +            return 1;
> >
> > Why not:
> >
> >       if (ret)
> >               return ret;
> >
> >       if (sig == 0)
> >               return -EINVAL;
> >
> >> +
> >> +    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;
> >> +
> >> +    ksig.sig = sig;
> >> +    memcpy(&ksig.info, &si, sizeof(si));
> >> +    ksig.ka.sa.sa_flags = SA_SIGINFO | SA_RESTORER;
> >> +    ksig.ka.sa.sa_restorer = sys_ppd->sigrestorer;
> >> +    ksig.ka.sa.sa_handler = sys_ppd->sighand[sig];
> >> +
> >> +    ret = dovetail_setup_rt_signal_frame(&ksig, regs);
> >> +    if (ret)
> >> +            return 1;
> >
> > Applies here and on more locations: Why returning 1 instead of
> > reporting the underlying issue (return ret;) ?
> >
> >> +
> >> +    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..df961469e
> >> --- /dev/null
> >> +++ b/lib/cobalt/arch/x86/sigreturn.c
> >> @@ -0,0 +1,36 @@
> >> +#include <cobalt/uapi/syscall.h>
> >> +#include "internal.h"
> >> +
> >> +extern void cobalt_sigreturn (void) asm ("__cobalt_sigreturn") __attribute__
> ((visibility ("hidden")));
> >> +
> >> +#define TO_STR(x) #x
> >> +
> >> +#ifdef __x86_64__
> >> +#define build_restorer(syscall_bit, syscall)                                   \
> >> +    asm(".text\n"                                                          \
> >> +        "    .align 16\n"                                                  \
> >> +        "__cobalt_sigreturn:\n"                                            \
> >> +        "    movq $ " TO_STR(syscall_bit) ", %rax\n"                       \
> >> +        "    orq $ " TO_STR(syscall) ", %rax\n"                            \
> >> +        "    syscall")
> >> +#endif
> >> +
> >> +#ifdef __i386__
> >> +#define build_restorer(syscall_bit, syscall)                                   \
> >> +    asm(".text\n"                                                          \
> >> +        "    .align 16\n"                                                  \
> >> +        "__cobalt_sigreturn:\n"                                            \
> >> +        "    movl $ " TO_STR(syscall_bit) ", %eax\n"                       \
> >> +        "    orl $ " TO_STR(syscall) ", %eax\n"                            \
> >> +        "    int  $0x80")
> >> +#endif
> >> +
> >> +/*
> >> + * __COBALT_SYSCALL_BIT | sc_cobalt_sigreturn
> >> + */
> >> +build_restorer(__COBALT_SYSCALL_BIT, sc_cobalt_sigreturn);
> >
> > This looks like a partial bypass to the XENOMAI_SYSCALL() machinery. In
> > case we wan't to change the implementation of that interface (targeting
> > prctl usage) we would have to touch the rt signal interface as well...
> 
> I wonder why this has to be written in assembly, in fact. Can't we
> implement a C trampoline that issues cobalt's sigreturn with normal
> means? That function would not take any parameters and will never
> return, thus should not need a special assembly entry IMHO. Plus, we
> would have it for all archs then.

A C function may change the stack pointer. In kernelspace the position of the signal frame on stack is deduced from the stack pointer. So changing it in the "return trampoline" would make restoring impossible. I am not sure if there is the possibility to have C code that ensures to leave the stack pointer unchanged.
If there is a way, we could switch to it. 

> 
> >
> >> +
> >> +void *cobalt_get_restorer(void)
> >> +{
> >> +    return &cobalt_sigreturn;
> >> +}
> >> diff --git a/lib/cobalt/internal.h b/lib/cobalt/internal.h
> >> index acb3989f1..4782d154a 100644
> >> --- a/lib/cobalt/internal.h
> >> +++ b/lib/cobalt/internal.h
> >> @@ -132,4 +132,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 40d315ebb..af174d570 100644
> >> --- a/lib/cobalt/signal.c
> >> +++ b/lib/cobalt/signal.c
> >> @@ -126,3 +126,16 @@ 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
> >>
> >
> 
Hope to address the other stuff, you pointed out soon. 

Johannes

> Jan
> 
> --
> Siemens AG, Technology
> Linux Expert Center


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

* Re: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-08-16 11:24 ` Florian Bezdeka
@ 2023-08-16 11:36   ` Jan Kiszka
  2023-08-16 11:59     ` Johannes Kirchmair
  2023-09-07 10:48   ` Johannes Kirchmair
  1 sibling, 1 reply; 30+ messages in thread
From: Jan Kiszka @ 2023-08-16 11:36 UTC (permalink / raw)
  To: Florian Bezdeka, Johannes Kirchmair, xenomai

On 16.08.23 13:24, Florian Bezdeka wrote:
> On Wed, 2023-08-16 at 12:18 +0200, Johannes Kirchmair wrote:
>> We implement rt signals to handle exceptions in rt stage.
>>
>> This is done using dovetail specific functions for setting up the signal
>> frame.
>>
>> This can be used to handle fpe exceptions on the fly, like fixing
>> division by zero. An other use case are breakpoints, implemented using the
>> illegal opcode exception. The real time handling of the breakpoints would
>> be handy for conditional breakpoints or also for stopping watchdogs and
>> other tasks in time.
>>
>> Signed-off-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/signal.h                  |  1 +
>>  include/cobalt/uapi/syscall.h                 |  6 ++
>>  kernel/cobalt/arch/x86/Makefile               |  2 +-
>>  .../arch/x86/include/asm/xenomai/thread.h     | 13 ++++
>>  kernel/cobalt/arch/x86/signal_ia32.c          | 75 +++++++++++++++++++
>>  kernel/cobalt/arch/x86/signal_ia64.c          | 37 +++++++++
>>  kernel/cobalt/dovetail/kevents.c              |  5 ++
>>  kernel/cobalt/posix/process.c                 |  3 +-
>>  kernel/cobalt/posix/syscall.c                 | 28 +++++++
>>  kernel/cobalt/posix/syscall32.c               | 16 ++++
>>  kernel/cobalt/thread.c                        | 39 ++++++++++
>>  lib/cobalt/arch/x86/Makefile.am               |  2 +-
>>  lib/cobalt/arch/x86/sigreturn.c               | 36 +++++++++
>>  lib/cobalt/internal.h                         |  2 +
>>  lib/cobalt/signal.c                           | 13 ++++
>>  18 files changed, 282 insertions(+), 3 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
>>
>> 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 b79cb8429..33d468419 100644
>> --- a/include/cobalt/kernel/thread.h
>> +++ b/include/cobalt/kernel/thread.h
>> @@ -574,6 +574,8 @@ static inline void xnthread_propagate_schedparam(struct xnthread *curr)
>>  		__xnthread_propagate_schedparam(curr);
>>  }
>>  
>> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs);
>> +
>>  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/signal.h b/include/cobalt/uapi/signal.h
>> index 8a7ea15a4..1afb6050a 100644
>> --- a/include/cobalt/uapi/signal.h
>> +++ b/include/cobalt/uapi/signal.h
>> @@ -68,6 +68,7 @@
>>  #define SIGDEBUG_RESCNT_IMBALANCE	7
>>  #define SIGDEBUG_LOCK_BREAK		8
>>  #define SIGDEBUG_MUTEX_SLEEP		9
>> +#define SIGDEBUG_SIGRESTOR		10
>>  
>>  #define COBALT_DELAYMAX			2147483647U
>>  
>> diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
>> index 3e65efaab..f14bd8ffe 100644
>> --- a/include/cobalt/uapi/syscall.h
>> +++ b/include/cobalt/uapi/syscall.h
>> @@ -142,6 +142,12 @@
>>  #define sc_cobalt_timerfd_gettime64		119
>>  #define sc_cobalt_pselect64			120
>>  
>> +/*
>> + * Sigmatek specific syscalls
>> + */
> 
> The goal would be to become generic so no longer 
> "sigmatek specific" ;-)
> 
>> +#define sc_cobalt_sigreturn			121
>> +#define sc_cobalt_sigaction			122
>> +
>>  #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 93929b645..e725afbff 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 smi.o c1e.o
>> +xenomai-y := machine.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 745c32467..4d004680b 100644
>> --- a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
>> +++ b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
>> @@ -28,5 +28,18 @@
>>  #define xnarch_fault_bp_p(__nr)		((current->ptrace & PT_PTRACED) &&	\
>>  					 ((__nr) == X86_TRAP_DB || (__nr) == X86_TRAP_BP))
>>  #define xnarch_fault_notify(__nr)	(!xnarch_fault_bp_p(__nr))
>> +#define xnarch_fault_code(__regs)		((__regs)->orig_ax)
>> +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);
>> +
>> +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);
>>  
>>  #endif /* !_COBALT_X86_ASM_THREAD_H */
>> diff --git a/kernel/cobalt/arch/x86/signal_ia32.c b/kernel/cobalt/arch/x86/signal_ia32.c
>> new file mode 100644
>> index 000000000..140016460
>> --- /dev/null
>> +++ b/kernel/cobalt/arch/x86/signal_ia32.c
>> @@ -0,0 +1,75 @@
>> +#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>
>> +
>> +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 */
> 
> Can't we assign names to the possible values of vector? Can't we model
> that as enum?
> 

arch/x86/include/asm/trapnr.h ;)

>> +		*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;
>> +}
>> +
>> +int xnarch_rt_sigreturn_ia32(struct pt_regs *regs)
>> +{
>> +	int ret;
>> +
>> +	ret = dovetail_restore_rt_signal_frame(regs);
>> +	if (ret < 0)
>> +		goto badframe;
>> +
>> +	return regs->ax;
>> +
>> +badframe:
>> +	xnthread_call_mayday(xnthread_current(), SIGDEBUG_SIGRESTOR);
>> +	return -1;
>> +}
>> +
>> diff --git a/kernel/cobalt/arch/x86/signal_ia64.c b/kernel/cobalt/arch/x86/signal_ia64.c
>> new file mode 100644
>> index 000000000..3b8cd3330
>> --- /dev/null
>> +++ b/kernel/cobalt/arch/x86/signal_ia64.c
>> @@ -0,0 +1,37 @@
>> +// 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
>> + */
> 
> I think the copyright information is just wrong.
> 

Agreed I don't spot significant kernel code below.

>> +
>> +#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>
>> +
>> +int xnarch_rt_sigreturn_ia64(struct pt_regs *regs)
>> +{
>> +	int ret;
>> +
>> +	ret = dovetail_restore_rt_signal_frame(regs);
>> +	if (ret < 0)
>> +		goto badframe;
>> +
>> +	return regs->ax;
>> +
>> +badframe:
>> +	xnthread_call_mayday(xnthread_current(), SIGDEBUG_SIGRESTOR);
>> +	return -1;
>> +
>> +}
>> +
>> diff --git a/kernel/cobalt/dovetail/kevents.c b/kernel/cobalt/dovetail/kevents.c
>> index 4da4f51b7..61417717b 100644
>> --- a/kernel/cobalt/dovetail/kevents.c
>> +++ b/kernel/cobalt/dovetail/kevents.c
>> @@ -57,6 +57,9 @@ void handle_oob_trap_entry(unsigned int trapnr, struct pt_regs *regs)
>>  		xnsched_run();
>>  	}
>>  
>> +	if (xnthread_handle_rt_signals(trapnr, regs) == 0)
>> +		return;
>> +
>>  	/*
>>  	 * If we experienced a trap on behalf of a shadow thread
>>  	 * running in primary mode, move it to the Linux domain,
>> @@ -88,6 +91,8 @@ void handle_oob_trap_entry(unsigned int trapnr, struct pt_regs *regs)
>>  		xnstat_counter_inc(&thread->stat.pf);
>>  
>>  	xnthread_relax(xnarch_fault_notify(trapnr), SIGDEBUG_MIGRATE_FAULT);
>> +
>> +	return;
>>  }
>>  
>>  static inline int handle_setaffinity_event(struct dovetail_migration_data *d)
>> diff --git a/kernel/cobalt/posix/process.c b/kernel/cobalt/posix/process.c
>> index 1abc86f37..2069129cb 100644
>> --- a/kernel/cobalt/posix/process.c
>> +++ b/kernel/cobalt/posix/process.c
>> @@ -738,9 +738,10 @@ void cobalt_unregister_debugged_thread(struct xnthread *thread)
>>  		cobalt_resume_debugged_process(process);
>>  }
>>  
>> +#ifdef CONFIG_SMP
>> +
>>  int cobalt_handle_setaffinity_event(struct task_struct *task)
>>  {
>> -#ifdef CONFIG_SMP
>>  	struct xnthread *thread;
>>  	spl_t s;
>>  
>> diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c
>> index 46c4998e4..b4bd4c587 100644
>> --- a/kernel/cobalt/posix/syscall.c
>> +++ b/kernel/cobalt/posix/syscall.c
>> @@ -277,6 +277,34 @@ static COBALT_SYSCALL(serialdbg, current,
>>  	return 0;
>>  }
>>  
>> +static COBALT_SYSCALL(sigreturn, current, (void))
>> +{
>> +	struct pt_regs *regs = task_pt_regs(current);
>> +
>> +	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);
>> +}
>> +
>> +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;
> 
> No error if sys_ppd->sighand[sig] or sys_ppd->sigrestorer is
> overwritten? 
> Or the other way around: Why can only the handler be overwritten?

I think the idea behind this user-provided handler is to replace the
vdso approach of the kernel - which we can't use as-is because we have a
different sigreturn syscall. So, the first call from userspace sets this
handler for the whole process. But there might be better ways than this,
maybe something done during cobalt binding?

This syscall interface is not yet done in any case. It's missing the old
handler parameter e.g.

> 
>> +
>> +	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 780d276b1..7c858f904 100644
>> --- a/kernel/cobalt/posix/syscall32.c
>> +++ b/kernel/cobalt/posix/syscall32.c
>> @@ -705,6 +705,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;
>> +}
>> +
> 
> You did not touch the syscall32-table.h (x86 specific), so I would
> expect that your compat support is broken right now. You should end up
> in the "native" so x86_64 implementation. That brings me to the next
> question:
> 
> Can't we avoid a special compat case here? The pointers themselfs are
> corrected by the syscall entry machinery but the memory pointed to is
> not. So is the memory pointed to by handler and restorer different in
> terms of memory layout/padding?

Yes, no new compats, please.

> 
> In addition you should update kernel/cobalt/trace/cobalt-posix.h to get
> proper trace support.
> 
> 
>>  COBALT_SYSCALL32emu(monitor_wait, nonrestartable,
>>  		    (struct cobalt_monitor_shadow __user *u_mon,
>>  		     int event, const struct old_timespec32 __user *u_ts,
>> diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
>> index 41804b24f..71f97c481 100644
>> --- a/kernel/cobalt/thread.c
>> +++ b/kernel/cobalt/thread.c
>> @@ -25,6 +25,7 @@
>>  #include <linux/signal.h>
>>  #include <linux/pid.h>
>>  #include <linux/sched.h>
>> +#include <asm/sighandling.h>
>>  #include <uapi/linux/sched/types.h>
>>  #include <cobalt/kernel/sched.h>
>>  #include <cobalt/kernel/timer.h>
>> @@ -43,6 +44,7 @@
>>  #include <pipeline/inband_work.h>
>>  #include <pipeline/sched.h>
>>  #include <trace/events/cobalt-core.h>
>> +#include "posix/process.h"
>>  #include "debug.h"
>>  
>>  static DECLARE_WAIT_QUEUE_HEAD(join_all);
>> @@ -2520,6 +2522,43 @@ int xnthread_killall(int grace, int mask)
>>  }
>>  EXPORT_SYMBOL_GPL(xnthread_killall);
>>  
>> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs)
>> +{
>> +	struct ksignal ksig;
>> +
>> +	unsigned int vector = trapnr;
>> +	unsigned int code = xnarch_fault_code(regs);
>> +	struct cobalt_ppd *sys_ppd;
>> +	int sig, ret = 0;
>> +	struct kernel_siginfo si;
> 
> Style: Reverse christmas tree.
> 
>> +
>> +	code = xnarch_fault_code(regs);
>> +	ret = xnarch_setup_trap_info(vector, regs, code, &sig, &si);
>> +	if (ret || sig == 0)
>> +		return 1;
> 
> Why not:
> 
> 	if (ret)
> 		return ret;
> 
> 	if (sig == 0)
> 		return -EINVAL;
> 
>> +
>> +	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;
>> +
>> +	ksig.sig = sig;
>> +	memcpy(&ksig.info, &si, sizeof(si));
>> +	ksig.ka.sa.sa_flags = SA_SIGINFO | SA_RESTORER;
>> +	ksig.ka.sa.sa_restorer = sys_ppd->sigrestorer;
>> +	ksig.ka.sa.sa_handler = sys_ppd->sighand[sig];
>> +
>> +	ret = dovetail_setup_rt_signal_frame(&ksig, regs);
>> +	if (ret)
>> +		return 1;
> 
> Applies here and on more locations: Why returning 1 instead of
> reporting the underlying issue (return ret;) ?
> 
>> +
>> +	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..df961469e
>> --- /dev/null
>> +++ b/lib/cobalt/arch/x86/sigreturn.c
>> @@ -0,0 +1,36 @@
>> +#include <cobalt/uapi/syscall.h>
>> +#include "internal.h"
>> +
>> +extern void cobalt_sigreturn (void) asm ("__cobalt_sigreturn") __attribute__ ((visibility ("hidden")));
>> +
>> +#define TO_STR(x) #x
>> +
>> +#ifdef __x86_64__
>> +#define build_restorer(syscall_bit, syscall)                                   \
>> +	asm(".text\n"                                                          \
>> +	    "    .align 16\n"                                                  \
>> +	    "__cobalt_sigreturn:\n"                                            \
>> +	    "    movq $ " TO_STR(syscall_bit) ", %rax\n"                       \
>> +	    "    orq $ " TO_STR(syscall) ", %rax\n"                            \
>> +	    "    syscall")
>> +#endif
>> +
>> +#ifdef __i386__
>> +#define build_restorer(syscall_bit, syscall)                                   \
>> +	asm(".text\n"                                                          \
>> +	    "    .align 16\n"                                                  \
>> +	    "__cobalt_sigreturn:\n"                                            \
>> +	    "    movl $ " TO_STR(syscall_bit) ", %eax\n"                       \
>> +	    "    orl $ " TO_STR(syscall) ", %eax\n"                            \
>> +	    "    int  $0x80")
>> +#endif
>> +
>> +/*
>> + * __COBALT_SYSCALL_BIT | sc_cobalt_sigreturn
>> + */
>> +build_restorer(__COBALT_SYSCALL_BIT, sc_cobalt_sigreturn);
> 
> This looks like a partial bypass to the XENOMAI_SYSCALL() machinery. In
> case we wan't to change the implementation of that interface (targeting
> prctl usage) we would have to touch the rt signal interface as well...

I wonder why this has to be written in assembly, in fact. Can't we
implement a C trampoline that issues cobalt's sigreturn with normal
means? That function would not take any parameters and will never
return, thus should not need a special assembly entry IMHO. Plus, we
would have it for all archs then.

> 
>> +
>> +void *cobalt_get_restorer(void)
>> +{
>> +	return &cobalt_sigreturn;
>> +}
>> diff --git a/lib/cobalt/internal.h b/lib/cobalt/internal.h
>> index acb3989f1..4782d154a 100644
>> --- a/lib/cobalt/internal.h
>> +++ b/lib/cobalt/internal.h
>> @@ -132,4 +132,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 40d315ebb..af174d570 100644
>> --- a/lib/cobalt/signal.c
>> +++ b/lib/cobalt/signal.c
>> @@ -126,3 +126,16 @@ 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
>>
> 

Jan

-- 
Siemens AG, Technology
Linux Expert Center


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

* Re: [PATCH 1/3] [POC] test implementaion of rt-signals
  2023-08-16 10:18 Johannes Kirchmair
@ 2023-08-16 11:24 ` Florian Bezdeka
  2023-08-16 11:36   ` Jan Kiszka
  2023-09-07 10:48   ` Johannes Kirchmair
  2023-09-01 12:00 ` Jan Kiszka
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 30+ messages in thread
From: Florian Bezdeka @ 2023-08-16 11:24 UTC (permalink / raw)
  To: Johannes Kirchmair, xenomai; +Cc: Jan Kiszka

On Wed, 2023-08-16 at 12:18 +0200, Johannes Kirchmair wrote:
> We implement rt signals to handle exceptions in rt stage.
> 
> This is done using dovetail specific functions for setting up the signal
> frame.
> 
> This can be used to handle fpe exceptions on the fly, like fixing
> division by zero. An other use case are breakpoints, implemented using the
> illegal opcode exception. The real time handling of the breakpoints would
> be handy for conditional breakpoints or also for stopping watchdogs and
> other tasks in time.
> 
> Signed-off-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/signal.h                  |  1 +
>  include/cobalt/uapi/syscall.h                 |  6 ++
>  kernel/cobalt/arch/x86/Makefile               |  2 +-
>  .../arch/x86/include/asm/xenomai/thread.h     | 13 ++++
>  kernel/cobalt/arch/x86/signal_ia32.c          | 75 +++++++++++++++++++
>  kernel/cobalt/arch/x86/signal_ia64.c          | 37 +++++++++
>  kernel/cobalt/dovetail/kevents.c              |  5 ++
>  kernel/cobalt/posix/process.c                 |  3 +-
>  kernel/cobalt/posix/syscall.c                 | 28 +++++++
>  kernel/cobalt/posix/syscall32.c               | 16 ++++
>  kernel/cobalt/thread.c                        | 39 ++++++++++
>  lib/cobalt/arch/x86/Makefile.am               |  2 +-
>  lib/cobalt/arch/x86/sigreturn.c               | 36 +++++++++
>  lib/cobalt/internal.h                         |  2 +
>  lib/cobalt/signal.c                           | 13 ++++
>  18 files changed, 282 insertions(+), 3 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
> 
> 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 b79cb8429..33d468419 100644
> --- a/include/cobalt/kernel/thread.h
> +++ b/include/cobalt/kernel/thread.h
> @@ -574,6 +574,8 @@ static inline void xnthread_propagate_schedparam(struct xnthread *curr)
>  		__xnthread_propagate_schedparam(curr);
>  }
>  
> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs);
> +
>  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/signal.h b/include/cobalt/uapi/signal.h
> index 8a7ea15a4..1afb6050a 100644
> --- a/include/cobalt/uapi/signal.h
> +++ b/include/cobalt/uapi/signal.h
> @@ -68,6 +68,7 @@
>  #define SIGDEBUG_RESCNT_IMBALANCE	7
>  #define SIGDEBUG_LOCK_BREAK		8
>  #define SIGDEBUG_MUTEX_SLEEP		9
> +#define SIGDEBUG_SIGRESTOR		10
>  
>  #define COBALT_DELAYMAX			2147483647U
>  
> diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
> index 3e65efaab..f14bd8ffe 100644
> --- a/include/cobalt/uapi/syscall.h
> +++ b/include/cobalt/uapi/syscall.h
> @@ -142,6 +142,12 @@
>  #define sc_cobalt_timerfd_gettime64		119
>  #define sc_cobalt_pselect64			120
>  
> +/*
> + * Sigmatek specific syscalls
> + */

The goal would be to become generic so no longer 
"sigmatek specific" ;-)

> +#define sc_cobalt_sigreturn			121
> +#define sc_cobalt_sigaction			122
> +
>  #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 93929b645..e725afbff 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 smi.o c1e.o
> +xenomai-y := machine.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 745c32467..4d004680b 100644
> --- a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
> +++ b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
> @@ -28,5 +28,18 @@
>  #define xnarch_fault_bp_p(__nr)		((current->ptrace & PT_PTRACED) &&	\
>  					 ((__nr) == X86_TRAP_DB || (__nr) == X86_TRAP_BP))
>  #define xnarch_fault_notify(__nr)	(!xnarch_fault_bp_p(__nr))
> +#define xnarch_fault_code(__regs)		((__regs)->orig_ax)
> +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);
> +
> +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);
>  
>  #endif /* !_COBALT_X86_ASM_THREAD_H */
> diff --git a/kernel/cobalt/arch/x86/signal_ia32.c b/kernel/cobalt/arch/x86/signal_ia32.c
> new file mode 100644
> index 000000000..140016460
> --- /dev/null
> +++ b/kernel/cobalt/arch/x86/signal_ia32.c
> @@ -0,0 +1,75 @@
> +#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>
> +
> +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 */

Can't we assign names to the possible values of vector? Can't we model
that as enum?

> +		*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;
> +}
> +
> +int xnarch_rt_sigreturn_ia32(struct pt_regs *regs)
> +{
> +	int ret;
> +
> +	ret = dovetail_restore_rt_signal_frame(regs);
> +	if (ret < 0)
> +		goto badframe;
> +
> +	return regs->ax;
> +
> +badframe:
> +	xnthread_call_mayday(xnthread_current(), SIGDEBUG_SIGRESTOR);
> +	return -1;
> +}
> +
> diff --git a/kernel/cobalt/arch/x86/signal_ia64.c b/kernel/cobalt/arch/x86/signal_ia64.c
> new file mode 100644
> index 000000000..3b8cd3330
> --- /dev/null
> +++ b/kernel/cobalt/arch/x86/signal_ia64.c
> @@ -0,0 +1,37 @@
> +// 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
> + */

I think the copyright information is just wrong.

> +
> +#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>
> +
> +int xnarch_rt_sigreturn_ia64(struct pt_regs *regs)
> +{
> +	int ret;
> +
> +	ret = dovetail_restore_rt_signal_frame(regs);
> +	if (ret < 0)
> +		goto badframe;
> +
> +	return regs->ax;
> +
> +badframe:
> +	xnthread_call_mayday(xnthread_current(), SIGDEBUG_SIGRESTOR);
> +	return -1;
> +
> +}
> +
> diff --git a/kernel/cobalt/dovetail/kevents.c b/kernel/cobalt/dovetail/kevents.c
> index 4da4f51b7..61417717b 100644
> --- a/kernel/cobalt/dovetail/kevents.c
> +++ b/kernel/cobalt/dovetail/kevents.c
> @@ -57,6 +57,9 @@ void handle_oob_trap_entry(unsigned int trapnr, struct pt_regs *regs)
>  		xnsched_run();
>  	}
>  
> +	if (xnthread_handle_rt_signals(trapnr, regs) == 0)
> +		return;
> +
>  	/*
>  	 * If we experienced a trap on behalf of a shadow thread
>  	 * running in primary mode, move it to the Linux domain,
> @@ -88,6 +91,8 @@ void handle_oob_trap_entry(unsigned int trapnr, struct pt_regs *regs)
>  		xnstat_counter_inc(&thread->stat.pf);
>  
>  	xnthread_relax(xnarch_fault_notify(trapnr), SIGDEBUG_MIGRATE_FAULT);
> +
> +	return;
>  }
>  
>  static inline int handle_setaffinity_event(struct dovetail_migration_data *d)
> diff --git a/kernel/cobalt/posix/process.c b/kernel/cobalt/posix/process.c
> index 1abc86f37..2069129cb 100644
> --- a/kernel/cobalt/posix/process.c
> +++ b/kernel/cobalt/posix/process.c
> @@ -738,9 +738,10 @@ void cobalt_unregister_debugged_thread(struct xnthread *thread)
>  		cobalt_resume_debugged_process(process);
>  }
>  
> +#ifdef CONFIG_SMP
> +
>  int cobalt_handle_setaffinity_event(struct task_struct *task)
>  {
> -#ifdef CONFIG_SMP
>  	struct xnthread *thread;
>  	spl_t s;
>  
> diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c
> index 46c4998e4..b4bd4c587 100644
> --- a/kernel/cobalt/posix/syscall.c
> +++ b/kernel/cobalt/posix/syscall.c
> @@ -277,6 +277,34 @@ static COBALT_SYSCALL(serialdbg, current,
>  	return 0;
>  }
>  
> +static COBALT_SYSCALL(sigreturn, current, (void))
> +{
> +	struct pt_regs *regs = task_pt_regs(current);
> +
> +	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);
> +}
> +
> +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;

No error if sys_ppd->sighand[sig] or sys_ppd->sigrestorer is
overwritten? 
Or the other way around: Why can only the handler be overwritten?

> +
> +	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 780d276b1..7c858f904 100644
> --- a/kernel/cobalt/posix/syscall32.c
> +++ b/kernel/cobalt/posix/syscall32.c
> @@ -705,6 +705,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;
> +}
> +

You did not touch the syscall32-table.h (x86 specific), so I would
expect that your compat support is broken right now. You should end up
in the "native" so x86_64 implementation. That brings me to the next
question:

Can't we avoid a special compat case here? The pointers themselfs are
corrected by the syscall entry machinery but the memory pointed to is
not. So is the memory pointed to by handler and restorer different in
terms of memory layout/padding?

In addition you should update kernel/cobalt/trace/cobalt-posix.h to get
proper trace support.


>  COBALT_SYSCALL32emu(monitor_wait, nonrestartable,
>  		    (struct cobalt_monitor_shadow __user *u_mon,
>  		     int event, const struct old_timespec32 __user *u_ts,
> diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
> index 41804b24f..71f97c481 100644
> --- a/kernel/cobalt/thread.c
> +++ b/kernel/cobalt/thread.c
> @@ -25,6 +25,7 @@
>  #include <linux/signal.h>
>  #include <linux/pid.h>
>  #include <linux/sched.h>
> +#include <asm/sighandling.h>
>  #include <uapi/linux/sched/types.h>
>  #include <cobalt/kernel/sched.h>
>  #include <cobalt/kernel/timer.h>
> @@ -43,6 +44,7 @@
>  #include <pipeline/inband_work.h>
>  #include <pipeline/sched.h>
>  #include <trace/events/cobalt-core.h>
> +#include "posix/process.h"
>  #include "debug.h"
>  
>  static DECLARE_WAIT_QUEUE_HEAD(join_all);
> @@ -2520,6 +2522,43 @@ int xnthread_killall(int grace, int mask)
>  }
>  EXPORT_SYMBOL_GPL(xnthread_killall);
>  
> +int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs)
> +{
> +	struct ksignal ksig;
> +
> +	unsigned int vector = trapnr;
> +	unsigned int code = xnarch_fault_code(regs);
> +	struct cobalt_ppd *sys_ppd;
> +	int sig, ret = 0;
> +	struct kernel_siginfo si;

Style: Reverse christmas tree.

> +
> +	code = xnarch_fault_code(regs);
> +	ret = xnarch_setup_trap_info(vector, regs, code, &sig, &si);
> +	if (ret || sig == 0)
> +		return 1;

Why not:

	if (ret)
		return ret;

	if (sig == 0)
		return -EINVAL;

> +
> +	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;
> +
> +	ksig.sig = sig;
> +	memcpy(&ksig.info, &si, sizeof(si));
> +	ksig.ka.sa.sa_flags = SA_SIGINFO | SA_RESTORER;
> +	ksig.ka.sa.sa_restorer = sys_ppd->sigrestorer;
> +	ksig.ka.sa.sa_handler = sys_ppd->sighand[sig];
> +
> +	ret = dovetail_setup_rt_signal_frame(&ksig, regs);
> +	if (ret)
> +		return 1;

Applies here and on more locations: Why returning 1 instead of
reporting the underlying issue (return ret;) ?

> +
> +	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..df961469e
> --- /dev/null
> +++ b/lib/cobalt/arch/x86/sigreturn.c
> @@ -0,0 +1,36 @@
> +#include <cobalt/uapi/syscall.h>
> +#include "internal.h"
> +
> +extern void cobalt_sigreturn (void) asm ("__cobalt_sigreturn") __attribute__ ((visibility ("hidden")));
> +
> +#define TO_STR(x) #x
> +
> +#ifdef __x86_64__
> +#define build_restorer(syscall_bit, syscall)                                   \
> +	asm(".text\n"                                                          \
> +	    "    .align 16\n"                                                  \
> +	    "__cobalt_sigreturn:\n"                                            \
> +	    "    movq $ " TO_STR(syscall_bit) ", %rax\n"                       \
> +	    "    orq $ " TO_STR(syscall) ", %rax\n"                            \
> +	    "    syscall")
> +#endif
> +
> +#ifdef __i386__
> +#define build_restorer(syscall_bit, syscall)                                   \
> +	asm(".text\n"                                                          \
> +	    "    .align 16\n"                                                  \
> +	    "__cobalt_sigreturn:\n"                                            \
> +	    "    movl $ " TO_STR(syscall_bit) ", %eax\n"                       \
> +	    "    orl $ " TO_STR(syscall) ", %eax\n"                            \
> +	    "    int  $0x80")
> +#endif
> +
> +/*
> + * __COBALT_SYSCALL_BIT | sc_cobalt_sigreturn
> + */
> +build_restorer(__COBALT_SYSCALL_BIT, sc_cobalt_sigreturn);

This looks like a partial bypass to the XENOMAI_SYSCALL() machinery. In
case we wan't to change the implementation of that interface (targeting
prctl usage) we would have to touch the rt signal interface as well...

> +
> +void *cobalt_get_restorer(void)
> +{
> +	return &cobalt_sigreturn;
> +}
> diff --git a/lib/cobalt/internal.h b/lib/cobalt/internal.h
> index acb3989f1..4782d154a 100644
> --- a/lib/cobalt/internal.h
> +++ b/lib/cobalt/internal.h
> @@ -132,4 +132,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 40d315ebb..af174d570 100644
> --- a/lib/cobalt/signal.c
> +++ b/lib/cobalt/signal.c
> @@ -126,3 +126,16 @@ 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	[flat|nested] 30+ messages in thread

* [PATCH 1/3] [POC] test implementaion of rt-signals
@ 2023-08-16 10:18 Johannes Kirchmair
  2023-08-16 11:24 ` Florian Bezdeka
                   ` (3 more replies)
  0 siblings, 4 replies; 30+ messages in thread
From: Johannes Kirchmair @ 2023-08-16 10:18 UTC (permalink / raw)
  To: xenomai; +Cc: Johannes Kirchmair

We implement rt signals to handle exceptions in rt stage.

This is done using dovetail specific functions for setting up the signal
frame.

This can be used to handle fpe exceptions on the fly, like fixing
division by zero. An other use case are breakpoints, implemented using the
illegal opcode exception. The real time handling of the breakpoints would
be handy for conditional breakpoints or also for stopping watchdogs and
other tasks in time.

Signed-off-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/signal.h                  |  1 +
 include/cobalt/uapi/syscall.h                 |  6 ++
 kernel/cobalt/arch/x86/Makefile               |  2 +-
 .../arch/x86/include/asm/xenomai/thread.h     | 13 ++++
 kernel/cobalt/arch/x86/signal_ia32.c          | 75 +++++++++++++++++++
 kernel/cobalt/arch/x86/signal_ia64.c          | 37 +++++++++
 kernel/cobalt/dovetail/kevents.c              |  5 ++
 kernel/cobalt/posix/process.c                 |  3 +-
 kernel/cobalt/posix/syscall.c                 | 28 +++++++
 kernel/cobalt/posix/syscall32.c               | 16 ++++
 kernel/cobalt/thread.c                        | 39 ++++++++++
 lib/cobalt/arch/x86/Makefile.am               |  2 +-
 lib/cobalt/arch/x86/sigreturn.c               | 36 +++++++++
 lib/cobalt/internal.h                         |  2 +
 lib/cobalt/signal.c                           | 13 ++++
 18 files changed, 282 insertions(+), 3 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

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 b79cb8429..33d468419 100644
--- a/include/cobalt/kernel/thread.h
+++ b/include/cobalt/kernel/thread.h
@@ -574,6 +574,8 @@ static inline void xnthread_propagate_schedparam(struct xnthread *curr)
 		__xnthread_propagate_schedparam(curr);
 }
 
+int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs);
+
 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/signal.h b/include/cobalt/uapi/signal.h
index 8a7ea15a4..1afb6050a 100644
--- a/include/cobalt/uapi/signal.h
+++ b/include/cobalt/uapi/signal.h
@@ -68,6 +68,7 @@
 #define SIGDEBUG_RESCNT_IMBALANCE	7
 #define SIGDEBUG_LOCK_BREAK		8
 #define SIGDEBUG_MUTEX_SLEEP		9
+#define SIGDEBUG_SIGRESTOR		10
 
 #define COBALT_DELAYMAX			2147483647U
 
diff --git a/include/cobalt/uapi/syscall.h b/include/cobalt/uapi/syscall.h
index 3e65efaab..f14bd8ffe 100644
--- a/include/cobalt/uapi/syscall.h
+++ b/include/cobalt/uapi/syscall.h
@@ -142,6 +142,12 @@
 #define sc_cobalt_timerfd_gettime64		119
 #define sc_cobalt_pselect64			120
 
+/*
+ * Sigmatek specific syscalls
+ */
+#define sc_cobalt_sigreturn			121
+#define sc_cobalt_sigaction			122
+
 #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 93929b645..e725afbff 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 smi.o c1e.o
+xenomai-y := machine.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 745c32467..4d004680b 100644
--- a/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
+++ b/kernel/cobalt/arch/x86/include/asm/xenomai/thread.h
@@ -28,5 +28,18 @@
 #define xnarch_fault_bp_p(__nr)		((current->ptrace & PT_PTRACED) &&	\
 					 ((__nr) == X86_TRAP_DB || (__nr) == X86_TRAP_BP))
 #define xnarch_fault_notify(__nr)	(!xnarch_fault_bp_p(__nr))
+#define xnarch_fault_code(__regs)		((__regs)->orig_ax)
+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);
+
+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);
 
 #endif /* !_COBALT_X86_ASM_THREAD_H */
diff --git a/kernel/cobalt/arch/x86/signal_ia32.c b/kernel/cobalt/arch/x86/signal_ia32.c
new file mode 100644
index 000000000..140016460
--- /dev/null
+++ b/kernel/cobalt/arch/x86/signal_ia32.c
@@ -0,0 +1,75 @@
+#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>
+
+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;
+}
+
+int xnarch_rt_sigreturn_ia32(struct pt_regs *regs)
+{
+	int ret;
+
+	ret = dovetail_restore_rt_signal_frame(regs);
+	if (ret < 0)
+		goto badframe;
+
+	return regs->ax;
+
+badframe:
+	xnthread_call_mayday(xnthread_current(), SIGDEBUG_SIGRESTOR);
+	return -1;
+}
+
diff --git a/kernel/cobalt/arch/x86/signal_ia64.c b/kernel/cobalt/arch/x86/signal_ia64.c
new file mode 100644
index 000000000..3b8cd3330
--- /dev/null
+++ b/kernel/cobalt/arch/x86/signal_ia64.c
@@ -0,0 +1,37 @@
+// 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
+ */
+
+#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>
+
+int xnarch_rt_sigreturn_ia64(struct pt_regs *regs)
+{
+	int ret;
+
+	ret = dovetail_restore_rt_signal_frame(regs);
+	if (ret < 0)
+		goto badframe;
+
+	return regs->ax;
+
+badframe:
+	xnthread_call_mayday(xnthread_current(), SIGDEBUG_SIGRESTOR);
+	return -1;
+
+}
+
diff --git a/kernel/cobalt/dovetail/kevents.c b/kernel/cobalt/dovetail/kevents.c
index 4da4f51b7..61417717b 100644
--- a/kernel/cobalt/dovetail/kevents.c
+++ b/kernel/cobalt/dovetail/kevents.c
@@ -57,6 +57,9 @@ void handle_oob_trap_entry(unsigned int trapnr, struct pt_regs *regs)
 		xnsched_run();
 	}
 
+	if (xnthread_handle_rt_signals(trapnr, regs) == 0)
+		return;
+
 	/*
 	 * If we experienced a trap on behalf of a shadow thread
 	 * running in primary mode, move it to the Linux domain,
@@ -88,6 +91,8 @@ void handle_oob_trap_entry(unsigned int trapnr, struct pt_regs *regs)
 		xnstat_counter_inc(&thread->stat.pf);
 
 	xnthread_relax(xnarch_fault_notify(trapnr), SIGDEBUG_MIGRATE_FAULT);
+
+	return;
 }
 
 static inline int handle_setaffinity_event(struct dovetail_migration_data *d)
diff --git a/kernel/cobalt/posix/process.c b/kernel/cobalt/posix/process.c
index 1abc86f37..2069129cb 100644
--- a/kernel/cobalt/posix/process.c
+++ b/kernel/cobalt/posix/process.c
@@ -738,9 +738,10 @@ void cobalt_unregister_debugged_thread(struct xnthread *thread)
 		cobalt_resume_debugged_process(process);
 }
 
+#ifdef CONFIG_SMP
+
 int cobalt_handle_setaffinity_event(struct task_struct *task)
 {
-#ifdef CONFIG_SMP
 	struct xnthread *thread;
 	spl_t s;
 
diff --git a/kernel/cobalt/posix/syscall.c b/kernel/cobalt/posix/syscall.c
index 46c4998e4..b4bd4c587 100644
--- a/kernel/cobalt/posix/syscall.c
+++ b/kernel/cobalt/posix/syscall.c
@@ -277,6 +277,34 @@ static COBALT_SYSCALL(serialdbg, current,
 	return 0;
 }
 
+static COBALT_SYSCALL(sigreturn, current, (void))
+{
+	struct pt_regs *regs = task_pt_regs(current);
+
+	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);
+}
+
+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 780d276b1..7c858f904 100644
--- a/kernel/cobalt/posix/syscall32.c
+++ b/kernel/cobalt/posix/syscall32.c
@@ -705,6 +705,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 old_timespec32 __user *u_ts,
diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
index 41804b24f..71f97c481 100644
--- a/kernel/cobalt/thread.c
+++ b/kernel/cobalt/thread.c
@@ -25,6 +25,7 @@
 #include <linux/signal.h>
 #include <linux/pid.h>
 #include <linux/sched.h>
+#include <asm/sighandling.h>
 #include <uapi/linux/sched/types.h>
 #include <cobalt/kernel/sched.h>
 #include <cobalt/kernel/timer.h>
@@ -43,6 +44,7 @@
 #include <pipeline/inband_work.h>
 #include <pipeline/sched.h>
 #include <trace/events/cobalt-core.h>
+#include "posix/process.h"
 #include "debug.h"
 
 static DECLARE_WAIT_QUEUE_HEAD(join_all);
@@ -2520,6 +2522,43 @@ int xnthread_killall(int grace, int mask)
 }
 EXPORT_SYMBOL_GPL(xnthread_killall);
 
+int xnthread_handle_rt_signals(unsigned int trapnr, struct pt_regs *regs)
+{
+	struct ksignal ksig;
+
+	unsigned int vector = trapnr;
+	unsigned int code = xnarch_fault_code(regs);
+	struct cobalt_ppd *sys_ppd;
+	int sig, ret = 0;
+	struct kernel_siginfo si;
+
+	code = xnarch_fault_code(regs);
+	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;
+
+	ksig.sig = sig;
+	memcpy(&ksig.info, &si, sizeof(si));
+	ksig.ka.sa.sa_flags = SA_SIGINFO | SA_RESTORER;
+	ksig.ka.sa.sa_restorer = sys_ppd->sigrestorer;
+	ksig.ka.sa.sa_handler = sys_ppd->sighand[sig];
+
+	ret = dovetail_setup_rt_signal_frame(&ksig, regs);
+	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..df961469e
--- /dev/null
+++ b/lib/cobalt/arch/x86/sigreturn.c
@@ -0,0 +1,36 @@
+#include <cobalt/uapi/syscall.h>
+#include "internal.h"
+
+extern void cobalt_sigreturn (void) asm ("__cobalt_sigreturn") __attribute__ ((visibility ("hidden")));
+
+#define TO_STR(x) #x
+
+#ifdef __x86_64__
+#define build_restorer(syscall_bit, syscall)                                   \
+	asm(".text\n"                                                          \
+	    "    .align 16\n"                                                  \
+	    "__cobalt_sigreturn:\n"                                            \
+	    "    movq $ " TO_STR(syscall_bit) ", %rax\n"                       \
+	    "    orq $ " TO_STR(syscall) ", %rax\n"                            \
+	    "    syscall")
+#endif
+
+#ifdef __i386__
+#define build_restorer(syscall_bit, syscall)                                   \
+	asm(".text\n"                                                          \
+	    "    .align 16\n"                                                  \
+	    "__cobalt_sigreturn:\n"                                            \
+	    "    movl $ " TO_STR(syscall_bit) ", %eax\n"                       \
+	    "    orl $ " TO_STR(syscall) ", %eax\n"                            \
+	    "    int  $0x80")
+#endif
+
+/*
+ * __COBALT_SYSCALL_BIT | sc_cobalt_sigreturn
+ */
+build_restorer(__COBALT_SYSCALL_BIT, sc_cobalt_sigreturn);
+
+void *cobalt_get_restorer(void)
+{
+	return &cobalt_sigreturn;
+}
diff --git a/lib/cobalt/internal.h b/lib/cobalt/internal.h
index acb3989f1..4782d154a 100644
--- a/lib/cobalt/internal.h
+++ b/lib/cobalt/internal.h
@@ -132,4 +132,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 40d315ebb..af174d570 100644
--- a/lib/cobalt/signal.c
+++ b/lib/cobalt/signal.c
@@ -126,3 +126,16 @@ 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] 30+ messages in thread

end of thread, other threads:[~2024-03-05 17:14 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-09 13:13 [PATCH 1/3] [POC] test implementaion of rt-signals Johannes Kirchmair
2023-05-09 13:13 ` [PATCH 2/3] [POC] Add rt_signal test Johannes Kirchmair
2023-05-09 13:13 ` [PATCH 3/3] [POC] add a tool to measure rt_signal latency Johannes Kirchmair
2023-05-09 13:17 ` [PATCH 1/3] [POC] test implementaion of rt-signals Johannes Kirchmair
2023-05-12 17:38   ` Jan Kiszka
2023-05-15  6:50     ` Johannes Kirchmair
2023-05-15 10:38       ` Jan Kiszka
2023-05-16  6:46         ` Johannes Kirchmair
2023-05-16  6:52           ` Jan Kiszka
2023-08-09  9:50   ` Schaffner, Tobias
2023-08-16 10:18 Johannes Kirchmair
2023-08-16 11:24 ` Florian Bezdeka
2023-08-16 11:36   ` Jan Kiszka
2023-08-16 11:59     ` Johannes Kirchmair
2023-09-07 10:48   ` Johannes Kirchmair
2023-09-11  8:41     ` Florian Bezdeka
2023-09-01 12:00 ` Jan Kiszka
2023-09-01 13:38   ` Jan Kiszka
2023-09-04  6:55   ` Johannes Kirchmair
2023-09-07 13:39     ` Jan Kiszka
2023-09-07 13:58       ` Johannes Kirchmair
2023-09-01 13:51 ` Jan Kiszka
2023-09-01 14:11   ` Jan Kiszka
2023-09-04  7:04     ` Johannes Kirchmair
2024-03-05 15:54 ` Richard Weinberger
2024-03-05 17:05   ` Jan Kiszka
2024-03-05 17:14     ` Richard Weinberger
2023-09-08 10:50 Johannes Kirchmair
2023-09-08 10:54 ` Johannes Kirchmair
2023-09-09 11:35 ` Jan Kiszka

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