···172172 unsigned long fault_code; /* ESR_EL1 value */173173 struct debug_info debug; /* debugging */174174175175- struct user_fpsimd_state kernel_fpsimd_state;175175+ /*176176+ * Set [cleared] by kernel_neon_begin() [kernel_neon_end()] to the177177+ * address of a caller provided buffer that will be used to preserve a178178+ * task's kernel mode FPSIMD state while it is scheduled out.179179+ */180180+ struct user_fpsimd_state *kernel_fpsimd_state;176181 unsigned int kernel_fpsimd_cpu;177182#ifdef CONFIG_ARM64_PTR_AUTH178183 struct ptrauth_keys_user keys_user;
···14891489 * Elide the load if this CPU holds the most recent kernel mode14901490 * FPSIMD context of the current task.14911491 */14921492- if (last->st == &task->thread.kernel_fpsimd_state &&14921492+ if (last->st == task->thread.kernel_fpsimd_state &&14931493 task->thread.kernel_fpsimd_cpu == smp_processor_id())14941494 return;1495149514961496- fpsimd_load_state(&task->thread.kernel_fpsimd_state);14961496+ fpsimd_load_state(task->thread.kernel_fpsimd_state);14971497}1498149814991499static void fpsimd_save_kernel_state(struct task_struct *task)15001500{15011501 struct cpu_fp_state cpu_fp_state = {15021502- .st = &task->thread.kernel_fpsimd_state,15021502+ .st = task->thread.kernel_fpsimd_state,15031503 .to_save = FP_STATE_FPSIMD,15041504 };1505150515061506- fpsimd_save_state(&task->thread.kernel_fpsimd_state);15061506+ BUG_ON(!cpu_fp_state.st);15071507+15081508+ fpsimd_save_state(task->thread.kernel_fpsimd_state);15071509 fpsimd_bind_state_to_cpu(&cpu_fp_state);1508151015091511 task->thread.kernel_fpsimd_cpu = smp_processor_id();···17761774void fpsimd_flush_task_state(struct task_struct *t)17771775{17781776 t->thread.fpsimd_cpu = NR_CPUS;17771777+ t->thread.kernel_fpsimd_state = NULL;17791778 /*17801779 * If we don't support fpsimd, bail out after we have17811780 * reset the fpsimd_cpu for this task and clear the···18361833 *18371834 * The caller may freely use the FPSIMD registers until kernel_neon_end() is18381835 * called.18361836+ *18371837+ * Unless called from non-preemptible task context, @state must point to a18381838+ * caller provided buffer that will be used to preserve the task's kernel mode18391839+ * FPSIMD context when it is scheduled out, or if it is interrupted by kernel18401840+ * mode FPSIMD occurring in softirq context. May be %NULL otherwise.18391841 */18401840-void kernel_neon_begin(void)18421842+void kernel_neon_begin(struct user_fpsimd_state *state)18411843{18421844 if (WARN_ON(!system_supports_fpsimd()))18431845 return;18461846+18471847+ WARN_ON((preemptible() || in_serving_softirq()) && !state);1844184818451849 BUG_ON(!may_use_simd());18461850···18561846 /* Save unsaved fpsimd state, if any: */18571847 if (test_thread_flag(TIF_KERNEL_FPSTATE)) {18581848 BUG_ON(IS_ENABLED(CONFIG_PREEMPT_RT) || !in_serving_softirq());18591859- fpsimd_save_kernel_state(current);18491849+ fpsimd_save_state(state);18601850 } else {18611851 fpsimd_save_user_state();18621852···18771867 * mode in task context. So in this case, setting the flag here18781868 * is always appropriate.18791869 */18801880- if (IS_ENABLED(CONFIG_PREEMPT_RT) || !in_serving_softirq())18701870+ if (IS_ENABLED(CONFIG_PREEMPT_RT) || !in_serving_softirq()) {18711871+ /*18721872+ * Record the caller provided buffer as the kernel mode18731873+ * FP/SIMD buffer for this task, so that the state can18741874+ * be preserved and restored on a context switch.18751875+ */18761876+ WARN_ON(current->thread.kernel_fpsimd_state != NULL);18771877+ current->thread.kernel_fpsimd_state = state;18811878 set_thread_flag(TIF_KERNEL_FPSTATE);18791879+ }18821880 }1883188118841882 /* Invalidate any task state remaining in the fpsimd regs: */···19041886 *19051887 * The caller must not use the FPSIMD registers after this function is called,19061888 * unless kernel_neon_begin() is called again in the meantime.18891889+ *18901890+ * The value of @state must match the value passed to the preceding call to18911891+ * kernel_neon_begin().19071892 */19081908-void kernel_neon_end(void)18931893+void kernel_neon_end(struct user_fpsimd_state *state)19091894{19101895 if (!system_supports_fpsimd())18961896+ return;18971897+18981898+ if (!test_thread_flag(TIF_KERNEL_FPSTATE))19111899 return;1912190019131901 /*···19211897 * the task context kernel mode FPSIMD state. This can only happen when19221898 * running in softirq context on non-PREEMPT_RT.19231899 */19241924- if (!IS_ENABLED(CONFIG_PREEMPT_RT) && in_serving_softirq() &&19251925- test_thread_flag(TIF_KERNEL_FPSTATE))19261926- fpsimd_load_kernel_state(current);19271927- else19001900+ if (!IS_ENABLED(CONFIG_PREEMPT_RT) && in_serving_softirq()) {19011901+ fpsimd_load_state(state);19021902+ } else {19281903 clear_thread_flag(TIF_KERNEL_FPSTATE);19041904+ WARN_ON(current->thread.kernel_fpsimd_state != state);19051905+ current->thread.kernel_fpsimd_state = NULL;19061906+ }19291907}19301908EXPORT_SYMBOL_GPL(kernel_neon_end);19311909···19631937 WARN_ON(preemptible());1964193819651939 if (may_use_simd()) {19661966- kernel_neon_begin();19401940+ kernel_neon_begin(&efi_fpsimd_state);19671941 } else {19681942 /*19691943 * If !efi_sve_state, SVE can't be in use yet and doesn't need···20121986 return;2013198720141988 if (!efi_fpsimd_state_used) {20152015- kernel_neon_end();19891989+ kernel_neon_end(&efi_fpsimd_state);20161990 } else {20171991 if (system_supports_sve() && efi_sve_state_used) {20181992 bool ffr = true;