[PATCH v3 5/5] testsuite/switchtest: Add support for Dovetail >= 6.19

Florian Bezdeka <[email protected]>
Newsgroups dev.linux.lists.xenomai
Message-ID <[email protected]>
The background for this reworking is a recent change to Linux in 6.19:

commit 4fa617cc6851 ("arm64/fpsimd: Allocate kernel mode FP/SIMD
		     buffers on the stack")

expects all (non-preemtable) users to provide a buffer that is used
in case the calling task is scheduled out. NULL is only allowed when
preemption is disabled.

preempt_disable() has no impact on OOB tasks, so when an OOB task
is scheduled out the fpsimd code tries to save the FPU regs to NULL,
which (obviously) triggered a fault.

To be able to provide a struct user_fpsimd_state located on the
stack  the signature of fp_linux_begin() on all architectures has
been updated.

There is a new arch dependent struct now: cobalt_arch_fp_state.
Arm64 will wrap the FPU state (struct user_fpsimd_state) there,
all remaining archs will implement an empty (and unused) type.

Signed-off-by: Florian Bezdeka <[email protected]>
---
 kernel/cobalt/arch/arm/include/asm/xenomai/fptest.h   |  6 ++++--
 kernel/cobalt/arch/arm64/include/asm/xenomai/fptest.h | 16 +++++++++++-----
 kernel/cobalt/arch/x86/include/asm/xenomai/fptest.h   |  9 ++++++---
 kernel/cobalt/include/asm-generic/xenomai/wrappers.h  |  7 +++++++
 kernel/drivers/testing/switchtest.c                   | 18 +++++++++++++-----
 5 files changed, 41 insertions(+), 15 deletions(-)

diff --git a/kernel/cobalt/arch/arm/include/asm/xenomai/fptest.h b/kernel/cobalt/arch/arm/include/asm/xenomai/fptest.h
index fc177fcb53bd259011a4a65f889c236f7c8e115e..3b80fa8461d44e3cf224dcba3d0bd7255d302732 100644
--- a/kernel/cobalt/arch/arm/include/asm/xenomai/fptest.h
+++ b/kernel/cobalt/arch/arm/include/asm/xenomai/fptest.h
@@ -30,12 +30,14 @@
 
 #include <asm/xenomai/uapi/fptest.h>
 
-static inline int fp_linux_begin(void)
+struct cobalt_arch_fp_state {};
+
+static inline int fp_linux_begin(struct cobalt_arch_fp_state *state)
 {
 	return -ENOSYS;
 }
 
-static inline void fp_linux_end(void)
+static inline void fp_linux_end(struct cobalt_arch_fp_state *state)
 {
 }
 
diff --git a/kernel/cobalt/arch/arm64/include/asm/xenomai/fptest.h b/kernel/cobalt/arch/arm64/include/asm/xenomai/fptest.h
index 520cd38519db66ad25baecedd183d56f92895539..e1ff046e1c9a99990cc93bcb7f3aa600186bfb36 100644
--- a/kernel/cobalt/arch/arm64/include/asm/xenomai/fptest.h
+++ b/kernel/cobalt/arch/arm64/include/asm/xenomai/fptest.h
@@ -7,22 +7,28 @@
 #ifndef _COBALT_ARM64_FPTEST_H
 #define _COBALT_ARM64_FPTEST_H
 
-#include <asm/xenomai/uapi/fptest.h>
 #include <asm/hwcap.h>
 #include <asm/neon.h>
 
+#include <asm/xenomai/uapi/fptest.h>
+#include <asm-generic/xenomai/wrappers.h>
+
 #define have_fp (ELF_HWCAP & HWCAP_FP)
 
-static inline int fp_linux_begin(void)
+struct cobalt_arch_fp_state {
+	struct user_fpsimd_state state;
+};
+
+static inline int fp_linux_begin(struct cobalt_arch_fp_state *state)
 {
-	kernel_neon_begin();
+	kernel_neon_begin(&state->state);
 
 	return 0;
 }
 
-static inline void fp_linux_end(void)
+static inline void fp_linux_end(struct cobalt_arch_fp_state *state)
 {
-	kernel_neon_end();
+	kernel_neon_end(&state->state);
 }
 
 static inline int fp_detect(void)
diff --git a/kernel/cobalt/arch/x86/include/asm/xenomai/fptest.h b/kernel/cobalt/arch/x86/include/asm/xenomai/fptest.h
index 55818f853c2407eef40f3d1d9a1336bfa7605512..de6a931077fc7ff6aca6f8a27423e31d64bace0d 100644
--- a/kernel/cobalt/arch/x86/include/asm/xenomai/fptest.h
+++ b/kernel/cobalt/arch/x86/include/asm/xenomai/fptest.h
@@ -19,12 +19,15 @@
 #ifndef _COBALT_X86_ASM_FPTEST_H
 #define _COBALT_X86_ASM_FPTEST_H
 
-#include <linux/errno.h>
+#include <asm/fpu/api.h>
+
 #include <asm/processor.h>
 #include <asm/xenomai/wrappers.h>
 #include <asm/xenomai/uapi/fptest.h>
 
-static inline int fp_linux_begin(void)
+struct cobalt_arch_fp_state {};
+
+static inline int fp_linux_begin(struct cobalt_arch_fp_state *state)
 {
 	kernel_fpu_begin();
 	/*
@@ -38,7 +41,7 @@ static inline int fp_linux_begin(void)
 	return true;
 }
 
-static inline void fp_linux_end(void)
+static inline void fp_linux_end(struct cobalt_arch_fp_state *state)
 {
 	kernel_fpu_end();
 }
diff --git a/kernel/cobalt/include/asm-generic/xenomai/wrappers.h b/kernel/cobalt/include/asm-generic/xenomai/wrappers.h
index baf54dcfe7bb5071a1abea48bd87f471eb938297..27e641fa7f9178229e0616e4de64b0e267910915 100644
--- a/kernel/cobalt/include/asm-generic/xenomai/wrappers.h
+++ b/kernel/cobalt/include/asm-generic/xenomai/wrappers.h
@@ -84,4 +84,11 @@
 	})
 #endif
 
+#ifdef CONFIG_ARM64
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6,19,0)
+#define kernel_neon_begin(fpu_preempt_buffer)	kernel_neon_begin()
+#define kernel_neon_end(fpu_preempt_buffer)	kernel_neon_end()
+#endif
+#endif
+
 #endif /* _COBALT_ASM_GENERIC_WRAPPERS_H */
diff --git a/kernel/drivers/testing/switchtest.c b/kernel/drivers/testing/switchtest.c
index f8f6c892076bba729d5d4b536288574df431e344..bb9c3dcae36f412562b78713bb10260d764dfd40 100644
--- a/kernel/drivers/testing/switchtest.c
+++ b/kernel/drivers/testing/switchtest.c
@@ -15,16 +15,23 @@
  * along with Xenomai; if not, write to the Free Software Foundation,
  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
+
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/semaphore.h>
+
+/*
+ * Needs to be the first non-Linux include, wrappers.h for older kernels
+ * involved on arm64 and further Linux headers included at the top of fptest.h
+ */
+#include <asm/xenomai/fptest.h>
+
 #include <cobalt/kernel/sched.h>
 #include <cobalt/kernel/synch.h>
 #include <cobalt/kernel/thread.h>
 #include <cobalt/kernel/trace.h>
 #include <rtdm/testing.h>
 #include <rtdm/driver.h>
-#include <asm/xenomai/fptest.h>
 
 MODULE_DESCRIPTION("Cobalt context switch test helper");
 MODULE_AUTHOR("Gilles Chanteperdrix <[email protected]>");
@@ -236,6 +243,7 @@ static int rtswitch_to_nrt(struct rtswitch_context *ctx,
 			   unsigned int from_idx,
 			   unsigned int to_idx)
 {
+	struct cobalt_arch_fp_state state;
 	struct rtswitch_task *from, *to;
 	unsigned int expected, fp_val;
 	int fp_check;
@@ -276,7 +284,7 @@ static int rtswitch_to_nrt(struct rtswitch_context *ctx,
 
 		case RTSWITCH_RT:
 
-			if (!fp_check || fp_linux_begin() < 0) {
+			if (!fp_check || fp_linux_begin(&state) < 0) {
 				fp_check = 0;
 				goto signal_nofp;
 			}
@@ -287,7 +295,7 @@ static int rtswitch_to_nrt(struct rtswitch_context *ctx,
 			fp_regs_set(fp_features, expected);
 			rtdm_event_signal(&to->rt_synch);
 			fp_val = fp_regs_check(fp_features, expected, report);
-			fp_linux_end();
+			fp_linux_end(&state);
 
 			if(down_interruptible(&from->nrt_synch))
 				return -EINTR;
@@ -308,11 +316,11 @@ static int rtswitch_to_nrt(struct rtswitch_context *ctx,
 				(ctx->switches_count % 4000000) * 1000;
 			barrier();
 
-			fp_linux_begin();
+			fp_linux_begin(&state);
 			fp_regs_set(fp_features, expected);
 			rtdm_event_signal(&to->rt_synch);
 			fp_val = fp_regs_check(fp_features, expected, report);
-			fp_linux_end();
+			fp_linux_end(&state);
 
 			if (down_interruptible(&from->nrt_synch))
 				return -EINTR;

-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.