From 755fa1a701927c11be9c9caf7b3272fd5693a496 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Mon, 14 Apr 2025 13:33:54 -0500 Subject: [PATCH 1/2] linuxkm/x86_vector_register_glue.c: fix can_save_vector_registers_x86() to check wc_linuxkm_fpu_states before calling irq_fpu_usable(), needed for recursive call patterns. also, check TIF_NEED_FPU_LOAD only if it's defined. --- linuxkm/x86_vector_register_glue.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/linuxkm/x86_vector_register_glue.c b/linuxkm/x86_vector_register_glue.c index 818230b69..2f0618de5 100644 --- a/linuxkm/x86_vector_register_glue.c +++ b/linuxkm/x86_vector_register_glue.c @@ -400,12 +400,34 @@ static inline void wc_linuxkm_fpu_state_release( WARN_UNUSED_RESULT int can_save_vector_registers_x86(void) { + /* First, check if we're already saved, per wc_linuxkm_fpu_states. + * + * On kernel >= 6.15, irq_fpu_usable() dumps a backtrace to the kernel log + * if called while already saved, so it's crucial to preempt that call by + * checking wc_linuxkm_fpu_states. + */ + + struct wc_thread_fpu_count_ent *pstate = wc_linuxkm_fpu_state_assoc(0); + + if ((pstate != NULL) && (pstate->fpu_state != 0U)) { + if (unlikely((pstate->fpu_state & WC_FPU_COUNT_MASK) + == WC_FPU_COUNT_MASK)) + { + /* would overflow */ + return 0; + } else { + return 1; + } + } + if (irq_fpu_usable()) return 1; else if (in_nmi() || (hardirq_count() > 0) || (softirq_count() > 0)) return 0; +#ifdef TIF_NEED_FPU_LOAD else if (test_thread_flag(TIF_NEED_FPU_LOAD)) return 1; +#endif return 0; } @@ -441,7 +463,7 @@ WARN_UNUSED_RESULT int save_vector_registers_x86(void) } if (irq_fpu_usable() -#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 17, 0)) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(5, 17, 0)) && defined(TIF_NEED_FPU_LOAD) /* work around a kernel bug -- see linux commit 59f5ede3bc0f0. * what we really want here is this_cpu_read(in_kernel_fpu), but * in_kernel_fpu is an unexported static array. @@ -489,6 +511,7 @@ WARN_UNUSED_RESULT int save_vector_registers_x86(void) wc_linuxkm_fpu_state_release(pstate); #endif return BAD_STATE_E; +#ifdef TIF_NEED_FPU_LOAD } else if (!test_thread_flag(TIF_NEED_FPU_LOAD)) { static int warned_fpu_forbidden = 0; if (! warned_fpu_forbidden) @@ -498,6 +521,7 @@ WARN_UNUSED_RESULT int save_vector_registers_x86(void) wc_linuxkm_fpu_state_release(pstate); #endif return BAD_STATE_E; +#endif } else { /* assume already safely in_kernel_fpu from caller, but recursively * preempt_disable() to be extra-safe. From ecf9982a0f3496d18571258252e8dcd407530d5e Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Mon, 14 Apr 2025 13:49:14 -0500 Subject: [PATCH 2/2] .wolfssl_known_macro_extras: add TIF_NEED_FPU_LOAD. --- .wolfssl_known_macro_extras | 1 + 1 file changed, 1 insertion(+) diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index d32c167e6..9c87962f2 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -492,6 +492,7 @@ TCP_NODELAY TFM_ALREADY_SET TFM_SMALL_MONT_SET THREADED_SNIFFTEST +TIF_NEED_FPU_LOAD TIME_T_NOT_LONG TI_DUMMY_BUILD TLS13_RSA_PSS_SIGN_CB_NO_PREHASH