• Suzuki K Poulose's avatar
    arm64: nofpsmid: Handle TIF_FOREIGN_FPSTATE flag cleanly · 52f73c38
    Suzuki K Poulose authored
    We detect the absence of FP/SIMD after an incapable CPU is brought up,
    and by then we have kernel threads running already with TIF_FOREIGN_FPSTATE set
    which could be set for early userspace applications (e.g, modprobe triggered
    from initramfs) and init. This could cause the applications to loop forever in
    do_nofity_resume() as we never clear the TIF flag, once we now know that
    we don't support FP.
    
    Fix this by making sure that we clear the TIF_FOREIGN_FPSTATE flag
    for tasks which may have them set, as we would have done in the normal
    case, but avoiding touching the hardware state (since we don't support any).
    
    Also to make sure we handle the cases seemlessly we categorise the
    helper functions to two :
     1) Helpers for common core code, which calls into take appropriate
        actions without knowing the current FPSIMD state of the CPU/task.
    
        e.g fpsimd_restore_current_state(), fpsimd_flush_task_state(),
            fpsimd_save_and_flush_cpu_state().
    
        We bail out early for these functions, taking any appropriate actions
        (e.g, clearing the TIF flag) where necessary to hide the handling
        from core code.
    
     2) Helpers used when the presence of FP/SIMD is apparent.
        i.e, save/restore the FP/SIMD register state, modify the CPU/task
        FP/SIMD state.
        e.g,
    
        fpsimd_save(), task_fpsimd_load() - save/restore task FP/SIMD registers
    
        fpsimd_bind_task_to_cpu()  \
                                    - Update the "state" metadata for CPU/task.
        fpsimd_bind_state_to_cpu() /
    
        fpsimd_update_current_state() - Update the fp/simd state for the current
                                        task from memory.
    
        These must not be called in the absence of FP/SIMD. Put in a WARNING
        to make sure they are not invoked in the absence of FP/SIMD.
    
    KVM also uses the TIF_FOREIGN_FPSTATE flag to manage the FP/SIMD state
    on the CPU. However, without FP/SIMD support we trap all accesses and
    inject undefined instruction. Thus we should never "load" guest state.
    Add a sanity check to make sure this is valid.
    
    Fixes: 82e0191a ("arm64: Support systems without FP/ASIMD")
    Cc: Will Deacon <will@kernel.org>
    Cc: Mark Rutland <mark.rutland@arm.com>
    Reviewed-by: default avatarArd Biesheuvel <ardb@kernel.org>
    Reviewed-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
    Acked-by: default avatarMarc Zyngier <maz@kernel.org>
    Signed-off-by: default avatarSuzuki K Poulose <suzuki.poulose@arm.com>
    Signed-off-by: default avatarWill Deacon <will@kernel.org>
    52f73c38
fpsimd.c 38.5 KB