--- zzzz-none-000/linux-5.4.213/arch/arm/vfp/vfpmodule.c 2022-09-15 10:04:56.000000000 +0000 +++ miami-7690-761/linux-5.4.213/arch/arm/vfp/vfpmodule.c 2024-05-29 11:19:50.000000000 +0000 @@ -176,8 +176,11 @@ * case the thread migrates to a different CPU. The * restoring is done lazily. */ - if ((fpexc & FPEXC_EN) && vfp_current_hw_state[cpu]) + if ((fpexc & FPEXC_EN) && vfp_current_hw_state[cpu]) { + /* vfp_save_state oopses on VFP11 if EX bit set */ + fmxr(FPEXC, fpexc & ~FPEXC_EX); vfp_save_state(vfp_current_hw_state[cpu], fpexc); + } #endif /* @@ -454,6 +457,8 @@ /* if vfp is on, then save state for resumption */ if (fpexc & FPEXC_EN) { pr_debug("%s: saving vfp state\n", __func__); + /* vfp_save_state oopses on VFP11 if EX bit set */ + fmxr(FPEXC, fpexc & ~FPEXC_EX); vfp_save_state(&ti->vfpstate, fpexc); /* disable, just in case */ @@ -461,6 +466,8 @@ } else if (vfp_current_hw_state[ti->cpu]) { #ifndef CONFIG_SMP fmxr(FPEXC, fpexc | FPEXC_EN); + /* vfp_save_state oopses on VFP11 if EX bit set */ + fmxr(FPEXC, fpexc & ~FPEXC_EX); vfp_save_state(vfp_current_hw_state[ti->cpu], fpexc); fmxr(FPEXC, fpexc); #endif @@ -524,6 +531,8 @@ * Save the last VFP state on this CPU. */ fmxr(FPEXC, fpexc | FPEXC_EN); + /* vfp_save_state oopses on VFP11 if EX bit set */ + fmxr(FPEXC, (fpexc & ~FPEXC_EX) | FPEXC_EN); vfp_save_state(&thread->vfpstate, fpexc | FPEXC_EN); fmxr(FPEXC, fpexc); } @@ -732,11 +741,17 @@ * Save the userland NEON/VFP state. Under UP, * the owner could be a task other than 'current' */ - if (vfp_state_in_hw(cpu, thread)) + if (vfp_state_in_hw(cpu, thread)) { + /* vfp_save_state oopses on VFP11 if EX bit set */ + fmxr(FPEXC, fpexc & ~FPEXC_EX); vfp_save_state(&thread->vfpstate, fpexc); + } #ifndef CONFIG_SMP - else if (vfp_current_hw_state[cpu] != NULL) + else if (vfp_current_hw_state[cpu] != NULL) { + /* vfp_save_state oopses on VFP11 if EX bit set */ + fmxr(FPEXC, fpexc & ~FPEXC_EX); vfp_save_state(vfp_current_hw_state[cpu], fpexc); + } #endif vfp_current_hw_state[cpu] = NULL; }