All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH Dovetail] arm64: fpsimd: dovetail: Allow preemption of in-band fpsimd kernel sections
@ 2025-02-19 14:17 Florian Bezdeka
  2025-02-20 11:36 ` Jan Kiszka
  2025-03-02 15:07 ` Philippe Gerum
  0 siblings, 2 replies; 5+ messages in thread
From: Florian Bezdeka @ 2025-02-19 14:17 UTC (permalink / raw)
  To: xenomai; +Cc: Florian Bezdeka, powertree, Jan Kiszka, Philippe Gerum

Preemption of in-band in-kernel fpsimd sections was not allowed /
properly implemented in Dovetail up to now.

That piled up again as some crypto code was optimized for arm64 in
Linux 6.14. A possible call stack that makes clear that the FPU was
corrupted follows. The inband stage was using crypto/FPU code inside
the kernel and got interrupted by OOB.

	[  331.703695]  task_fpsimd_load+0xd0/0x214 (P)
	[  331.703713]  fpsimd_restore_current_state+0x9c/0xb8
	[  331.703732]  fpsimd_restore_current_oob+0x1c/0x2c
	[  331.703751]  dovetail_context_switch+0x90/0x180
	[  331.703769]  pipeline_switch_to+0x10/0x1c
	[  331.703792]  ___xnsched_run+0x1bc/0x29c
	[  331.703811]  run_oob_call+0x98/0x17c
	[  331.703830]  handle_irq_pipelined_finish+0x1e0/0x1ec
	[  331.703848]  handle_irq_pipelined+0x58/0x6c
	[  331.703865]  call_on_irq_stack+0x24/0x4c
	[  331.703884]  do_interrupt_handler+0x150/0x178
	[  331.703902]  el1_interrupt+0x44/0x11c
	[  331.703921]  el1h_64_irq_handler+0x18/0x24
	[  331.703941]  el1h_64_irq+0x6c/0x70                <- oob
	[  331.703957]  crc32c_le_arm64_4way+0x4c/0xc0 (P)   <- inband
	[  331.703978]  ext4_block_bitmap_csum_set+0x38/0x60
	[  331.704002]  ext4_mb_mark_context+0x1b0/0x398
	[  331.704025]  ext4_mb_mark_diskspace_used+0xd8/0x1f8

To fix that we have to hook into the task switch as we do on x86 and
invoke the FPU (re)store logic.

Cc: powertree <powertree@163.com>
Cc: Jan Kiszka <jan.kiszka@siemens.com>
Cc: Philippe Gerum <rpm@xenomai.org>

Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
---
 arch/arm64/include/asm/dovetail.h    | 10 +++++++--
 arch/arm64/include/asm/fpsimd.h      |  7 +++++-
 arch/arm64/include/asm/thread_info.h |  1 +
 arch/arm64/kernel/fpsimd.c           | 33 ++++++++++++++++++++++++++++
 4 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/include/asm/dovetail.h b/arch/arm64/include/asm/dovetail.h
index dc46f131e3eb..8cd359710353 100644
--- a/arch/arm64/include/asm/dovetail.h
+++ b/arch/arm64/include/asm/dovetail.h
@@ -26,11 +26,17 @@ static inline void arch_dovetail_exec_prepare(void)
 { }
 
 static inline void arch_dovetail_switch_prepare(bool leave_inband)
-{ }
+{
+	if (leave_inband)
+		fpsimd_suspend_inband();
+}
 
 static inline void arch_dovetail_switch_finish(bool enter_inband)
 {
-	fpsimd_restore_current_oob();
+	if (enter_inband)
+		fpsimd_resume_inband();
+	else
+		fpsimd_restore_current_oob();
 }
 
 /*
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index 8e12d5be076e..1ba7b75b2277 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -79,10 +79,15 @@ extern void fpsimd_flush_thread(void);
 extern void fpsimd_signal_preserve_current_state(void);
 extern void fpsimd_preserve_current_state(void);
 extern void fpsimd_restore_current_state(void);
-extern void fpsimd_restore_current_oob(void);
 extern void fpsimd_update_current_state(struct user_fpsimd_state const *state);
 extern void fpsimd_kvm_prepare(void);
 
+#ifdef CONFIG_DOVETAIL
+extern void fpsimd_restore_current_oob(void);
+extern void fpsimd_suspend_inband(void);
+extern void fpsimd_resume_inband(void);
+#endif
+
 struct cpu_fp_state {
 	struct user_fpsimd_state *st;
 	void *sve_state;
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index 3028a8f294c2..8ee08fd30d8c 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -76,6 +76,7 @@ void arch_setup_new_exec(void);
 #define TIF_SECCOMP		11	/* syscall secure computing */
 #define TIF_SYSCALL_EMU		12	/* syscall emulation active */
 #define TIF_MAYDAY		13	/* Emergency trap pending */
+#define TIF_KERNEL_FP_PREEMPTED	14	/* Dovetail: kernel mode FPSIMD section preempted by OOB */
 #define TIF_MEMDIE		18	/* is terminating due to OOM killer */
 #define TIF_FREEZE		19
 #define TIF_RESTORE_SIGMASK	20
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 96f2f60b4caa..032234593d6e 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -2240,6 +2240,39 @@ void cpu_enable_fpsimd(const struct arm64_cpu_capabilities *__always_unused p)
 	isb();
 }
 
+#ifdef CONFIG_DOVETAIL
+
+/*
+ * Holds the in-kernel fpu state when preempted by a task running on the
+ * out-of-band stage.
+ */
+static DEFINE_PER_CPU(struct user_fpsimd_state, in_kernel_fpstate);
+
+void fpsimd_suspend_inband(void)
+{
+	struct user_fpsimd_state *kfpu = this_cpu_ptr(&in_kernel_fpstate);
+
+	/*
+	 * If TIF_KERNEL_FPSTATE is set, we are dealing with the preemption of an
+	 * inband kernel context currently using the fpu by a thread which resumes
+	 * on the oob stage.
+	 */
+	if (test_thread_flag(TIF_KERNEL_FPSTATE)) {
+		fpsimd_save_state(kfpu);
+		set_thread_flag(TIF_KERNEL_FP_PREEMPTED);
+	}
+}
+
+void fpsimd_resume_inband(void)
+{
+	struct user_fpsimd_state *kfpu = this_cpu_ptr(&in_kernel_fpstate);
+
+	if (test_and_clear_thread_flag(TIF_KERNEL_FP_PREEMPTED))
+		fpsimd_load_state(kfpu);
+}
+
+#endif
+
 /*
  * FP/SIMD support code initialisation.
  */
-- 
2.39.5


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

end of thread, other threads:[~2025-03-13 10:12 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-19 14:17 [PATCH Dovetail] arm64: fpsimd: dovetail: Allow preemption of in-band fpsimd kernel sections Florian Bezdeka
2025-02-20 11:36 ` Jan Kiszka
2025-03-13  8:55   ` Florian Bezdeka
2025-03-13 10:12     ` Jan Kiszka
2025-03-02 15:07 ` Philippe Gerum

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