Skip to content

Commit 448f1ec

Browse files
committed
linuxkm: in {save,restore}_vector_registers_x86(), check if vector register file has already been saved and invalidated, and if so, inhibit the kernel_fpu_{begin,end}() wrap and instead just use preempt_{disable,enable}() wraps.
1 parent 8a89303 commit 448f1ec

2 files changed

Lines changed: 46 additions & 11 deletions

File tree

linuxkm/linuxkm_memory.c

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
#endif
3131
#else
3232
static unsigned int *wolfcrypt_linuxkm_fpu_states = NULL;
33+
#define WC_FPU_COUNT_MASK 0x7fffffffU
34+
#define WC_FPU_SAVED_MASK 0x80000000U
3335
#endif
3436

3537
static WARN_UNUSED_RESULT inline int am_in_hard_interrupt_handler(void)
@@ -223,8 +225,10 @@
223225
*/
224226
((unsigned char *)wolfcrypt_linuxkm_fpu_states[processor_id])[PAGE_SIZE-1] = 1;
225227
#else /* !LINUXKM_SIMD_IRQ */
226-
if (wolfcrypt_linuxkm_fpu_states[processor_id] != 0) {
227-
if (wolfcrypt_linuxkm_fpu_states[processor_id] == ~0U) {
228+
if (wolfcrypt_linuxkm_fpu_states[processor_id] != 0U) {
229+
if ((wolfcrypt_linuxkm_fpu_states[processor_id] & WC_FPU_COUNT_MASK)
230+
== WC_FPU_COUNT_MASK)
231+
{
228232
preempt_enable();
229233
pr_err("save_vector_registers_x86 recursion register overflow for "
230234
"cpu id %d.\n", processor_id);
@@ -234,11 +238,28 @@
234238
return 0;
235239
}
236240
}
237-
kernel_fpu_begin();
238-
preempt_enable(); /* kernel_fpu_begin() does its own
239-
* preempt_disable(). decrement ours.
240-
*/
241-
wolfcrypt_linuxkm_fpu_states[processor_id] = 1;
241+
242+
/* if kernel_fpu_begin() won't actually save the reg file (because
243+
* it was already saved and invalidated, or because we're in a
244+
* kernel thread), don't call kernel_fpu_begin() here, nor call
245+
* kernel_fpu_end() in cleanup. this avoids pointless overhead. in
246+
* kernels >=5.17.12 (from changes to irq_fpu_usable() in linux
247+
* commit 59f5ede3bc0f, backported somewhere >5.17.5), this also
248+
* fixes register corruption.
249+
*/
250+
if ((current->flags & PF_KTHREAD) ||
251+
test_thread_flag(TIF_NEED_FPU_LOAD))
252+
{
253+
wolfcrypt_linuxkm_fpu_states[processor_id] =
254+
WC_FPU_SAVED_MASK + 1U; /* set msb 1 to inhibit kernel_fpu_end() at cleanup. */
255+
/* keep preempt_disable()d from above. */
256+
} else {
257+
kernel_fpu_begin();
258+
preempt_enable(); /* kernel_fpu_begin() does its own
259+
* preempt_disable(). decrement ours.
260+
*/
261+
wolfcrypt_linuxkm_fpu_states[processor_id] = 1U; /* set msb 0 to trigger kernel_fpu_end() at cleanup. */
262+
}
242263
#endif /* !LINUXKM_SIMD_IRQ */
243264

244265
return 0;
@@ -287,19 +308,29 @@
287308
kernel_fpu_end();
288309
}
289310
#else /* !LINUXKM_SIMD_IRQ */
290-
if (wolfcrypt_linuxkm_fpu_states[processor_id] == 0)
311+
if ((wolfcrypt_linuxkm_fpu_states[processor_id] & WC_FPU_COUNT_MASK) == 0U)
291312
{
292313
pr_err("restore_vector_registers_x86 called for cpu id %d "
293314
"without saved context.\n", processor_id);
294315
return;
295316
}
296317

297-
if (--wolfcrypt_linuxkm_fpu_states[processor_id] > 0) {
298-
preempt_enable(); /* preempt_disable count will still be nonzero after this decrement. */
318+
if ((--wolfcrypt_linuxkm_fpu_states[processor_id] & WC_FPU_COUNT_MASK) > 0U) {
319+
preempt_enable(); /* preempt_disable count may still be nonzero
320+
* after this decrement, but any remaining
321+
* count(s) aren't ours.
322+
*/
299323
return;
300324
}
301325

302-
kernel_fpu_end();
326+
if (wolfcrypt_linuxkm_fpu_states[processor_id] == 0U) {
327+
kernel_fpu_end();
328+
} else {
329+
preempt_enable(); /* preempt_disable count will still be nonzero
330+
* after this decrement.
331+
*/
332+
wolfcrypt_linuxkm_fpu_states[processor_id] = 0U;
333+
}
303334
#endif /* !LINUXKM_SIMD_IRQ */
304335

305336
return;

wolfcrypt/src/memory.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
#include <config.h>
2525
#endif
2626

27+
#ifdef WOLFSSL_LINUXKM
28+
#define WOLFSSL_NEED_LINUX_CURRENT
29+
#endif
30+
2731
#include <wolfssl/wolfcrypt/settings.h>
2832

2933
/* check old macros @wc_fips */

0 commit comments

Comments
 (0)