LCOV - code coverage report
Current view: top level - arch/x86/kernel/fpu - core.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 65 141 46.1 %
Date: 2021-04-22 12:43:58 Functions: 10 17 58.8 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-only
       2             : /*
       3             :  *  Copyright (C) 1994 Linus Torvalds
       4             :  *
       5             :  *  Pentium III FXSR, SSE support
       6             :  *  General FPU state handling cleanups
       7             :  *      Gareth Hughes <gareth@valinux.com>, May 2000
       8             :  */
       9             : #include <asm/fpu/internal.h>
      10             : #include <asm/fpu/regset.h>
      11             : #include <asm/fpu/signal.h>
      12             : #include <asm/fpu/types.h>
      13             : #include <asm/traps.h>
      14             : #include <asm/irq_regs.h>
      15             : 
      16             : #include <linux/hardirq.h>
      17             : #include <linux/pkeys.h>
      18             : 
      19             : #define CREATE_TRACE_POINTS
      20             : #include <asm/trace/fpu.h>
      21             : 
      22             : /*
      23             :  * Represents the initial FPU state. It's mostly (but not completely) zeroes,
      24             :  * depending on the FPU hardware format:
      25             :  */
      26             : union fpregs_state init_fpstate __read_mostly;
      27             : 
      28             : /*
      29             :  * Track whether the kernel is using the FPU state
      30             :  * currently.
      31             :  *
      32             :  * This flag is used:
      33             :  *
      34             :  *   - by IRQ context code to potentially use the FPU
      35             :  *     if it's unused.
      36             :  *
      37             :  *   - to debug kernel_fpu_begin()/end() correctness
      38             :  */
      39             : static DEFINE_PER_CPU(bool, in_kernel_fpu);
      40             : 
      41             : /*
      42             :  * Track which context is using the FPU on the CPU:
      43             :  */
      44             : DEFINE_PER_CPU(struct fpu *, fpu_fpregs_owner_ctx);
      45             : 
      46           0 : static bool kernel_fpu_disabled(void)
      47             : {
      48           0 :         return this_cpu_read(in_kernel_fpu);
      49             : }
      50             : 
      51           0 : static bool interrupted_kernel_fpu_idle(void)
      52             : {
      53           0 :         return !kernel_fpu_disabled();
      54             : }
      55             : 
      56             : /*
      57             :  * Were we in user mode (or vm86 mode) when we were
      58             :  * interrupted?
      59             :  *
      60             :  * Doing kernel_fpu_begin/end() is ok if we are running
      61             :  * in an interrupt context from user mode - we'll just
      62             :  * save the FPU state as required.
      63             :  */
      64           0 : static bool interrupted_user_mode(void)
      65             : {
      66           0 :         struct pt_regs *regs = get_irq_regs();
      67           0 :         return regs && user_mode(regs);
      68             : }
      69             : 
      70             : /*
      71             :  * Can we use the FPU in kernel mode with the
      72             :  * whole "kernel_fpu_begin/end()" sequence?
      73             :  *
      74             :  * It's always ok in process context (ie "not interrupt")
      75             :  * but it is sometimes ok even from an irq.
      76             :  */
      77           0 : bool irq_fpu_usable(void)
      78             : {
      79           0 :         return !in_interrupt() ||
      80           0 :                 interrupted_user_mode() ||
      81           0 :                 interrupted_kernel_fpu_idle();
      82             : }
      83             : EXPORT_SYMBOL(irq_fpu_usable);
      84             : 
      85             : /*
      86             :  * These must be called with preempt disabled. Returns
      87             :  * 'true' if the FPU state is still intact and we can
      88             :  * keep registers active.
      89             :  *
      90             :  * The legacy FNSAVE instruction cleared all FPU state
      91             :  * unconditionally, so registers are essentially destroyed.
      92             :  * Modern FPU state can be kept in registers, if there are
      93             :  * no pending FP exceptions.
      94             :  */
      95       17149 : int copy_fpregs_to_fpstate(struct fpu *fpu)
      96             : {
      97       34300 :         if (likely(use_xsave())) {
      98       17151 :                 copy_xregs_to_kernel(&fpu->state.xsave);
      99             : 
     100             :                 /*
     101             :                  * AVX512 state is tracked here because its use is
     102             :                  * known to slow the max clock speed of the core.
     103             :                  */
     104       17150 :                 if (fpu->state.xsave.header.xfeatures & XFEATURE_MASK_AVX512)
     105           0 :                         fpu->avx512_timestamp = jiffies;
     106       17150 :                 return 1;
     107             :         }
     108             : 
     109           0 :         if (likely(use_fxsr())) {
     110           0 :                 copy_fxregs_to_kernel(fpu);
     111           0 :                 return 1;
     112             :         }
     113             : 
     114             :         /*
     115             :          * Legacy FPU register saving, FNSAVE always clears FPU registers,
     116             :          * so we have to mark them inactive:
     117             :          */
     118             :         asm volatile("fnsave %[fp]; fwait" : [fp] "=m" (fpu->state.fsave));
     119             : 
     120             :         return 0;
     121             : }
     122             : EXPORT_SYMBOL(copy_fpregs_to_fpstate);
     123             : 
     124           0 : void kernel_fpu_begin_mask(unsigned int kfpu_mask)
     125             : {
     126           0 :         preempt_disable();
     127             : 
     128           0 :         WARN_ON_FPU(!irq_fpu_usable());
     129           0 :         WARN_ON_FPU(this_cpu_read(in_kernel_fpu));
     130             : 
     131           0 :         this_cpu_write(in_kernel_fpu, true);
     132             : 
     133           0 :         if (!(current->flags & PF_KTHREAD) &&
     134           0 :             !test_thread_flag(TIF_NEED_FPU_LOAD)) {
     135           0 :                 set_thread_flag(TIF_NEED_FPU_LOAD);
     136             :                 /*
     137             :                  * Ignore return value -- we don't care if reg state
     138             :                  * is clobbered.
     139             :                  */
     140           0 :                 copy_fpregs_to_fpstate(&current->thread.fpu);
     141             :         }
     142           0 :         __cpu_invalidate_fpregs_state();
     143             : 
     144             :         /* Put sane initial values into the control registers. */
     145           0 :         if (likely(kfpu_mask & KFPU_MXCSR) && boot_cpu_has(X86_FEATURE_XMM))
     146           0 :                 ldmxcsr(MXCSR_DEFAULT);
     147             : 
     148           0 :         if (unlikely(kfpu_mask & KFPU_387) && boot_cpu_has(X86_FEATURE_FPU))
     149           0 :                 asm volatile ("fninit");
     150           0 : }
     151             : EXPORT_SYMBOL_GPL(kernel_fpu_begin_mask);
     152             : 
     153           0 : void kernel_fpu_end(void)
     154             : {
     155           0 :         WARN_ON_FPU(!this_cpu_read(in_kernel_fpu));
     156             : 
     157           0 :         this_cpu_write(in_kernel_fpu, false);
     158           0 :         preempt_enable();
     159           0 : }
     160             : EXPORT_SYMBOL_GPL(kernel_fpu_end);
     161             : 
     162             : /*
     163             :  * Save the FPU state (mark it for reload if necessary):
     164             :  *
     165             :  * This only ever gets called for the current task.
     166             :  */
     167           0 : void fpu__save(struct fpu *fpu)
     168             : {
     169           0 :         WARN_ON_FPU(fpu != &current->thread.fpu);
     170             : 
     171           0 :         fpregs_lock();
     172           0 :         trace_x86_fpu_before_save(fpu);
     173             : 
     174           0 :         if (!test_thread_flag(TIF_NEED_FPU_LOAD)) {
     175           0 :                 if (!copy_fpregs_to_fpstate(fpu)) {
     176           0 :                         copy_kernel_to_fpregs(&fpu->state);
     177             :                 }
     178             :         }
     179             : 
     180           0 :         trace_x86_fpu_after_save(fpu);
     181           0 :         fpregs_unlock();
     182           0 : }
     183             : 
     184             : /*
     185             :  * Legacy x87 fpstate state init:
     186             :  */
     187             : static inline void fpstate_init_fstate(struct fregs_state *fp)
     188             : {
     189             :         fp->cwd = 0xffff037fu;
     190             :         fp->swd = 0xffff0000u;
     191             :         fp->twd = 0xffffffffu;
     192             :         fp->fos = 0xffff0000u;
     193             : }
     194             : 
     195           1 : void fpstate_init(union fpregs_state *state)
     196             : {
     197           1 :         if (!static_cpu_has(X86_FEATURE_FPU)) {
     198             :                 fpstate_init_soft(&state->soft);
     199             :                 return;
     200             :         }
     201             : 
     202           1 :         memset(state, 0, fpu_kernel_xstate_size);
     203             : 
     204           1 :         if (static_cpu_has(X86_FEATURE_XSAVES))
     205           0 :                 fpstate_init_xstate(&state->xsave);
     206           1 :         if (static_cpu_has(X86_FEATURE_FXSR))
     207           1 :                 fpstate_init_fxstate(&state->fxsave);
     208             :         else
     209             :                 fpstate_init_fstate(&state->fsave);
     210             : }
     211             : EXPORT_SYMBOL_GPL(fpstate_init);
     212             : 
     213        2622 : int fpu__copy(struct task_struct *dst, struct task_struct *src)
     214             : {
     215        2622 :         struct fpu *dst_fpu = &dst->thread.fpu;
     216        2622 :         struct fpu *src_fpu = &src->thread.fpu;
     217             : 
     218        2622 :         dst_fpu->last_cpu = -1;
     219             : 
     220        2622 :         if (!static_cpu_has(X86_FEATURE_FPU))
     221             :                 return 0;
     222             : 
     223        2622 :         WARN_ON_FPU(src_fpu != &current->thread.fpu);
     224             : 
     225             :         /*
     226             :          * Don't let 'init optimized' areas of the XSAVE area
     227             :          * leak into the child task:
     228             :          */
     229        2622 :         memset(&dst_fpu->state.xsave, 0, fpu_kernel_xstate_size);
     230             : 
     231             :         /*
     232             :          * If the FPU registers are not current just memcpy() the state.
     233             :          * Otherwise save current FPU registers directly into the child's FPU
     234             :          * context, without any memory-to-memory copying.
     235             :          *
     236             :          * ( The function 'fails' in the FNSAVE case, which destroys
     237             :          *   register contents so we have to load them back. )
     238             :          */
     239        2622 :         fpregs_lock();
     240        2622 :         if (test_thread_flag(TIF_NEED_FPU_LOAD))
     241          51 :                 memcpy(&dst_fpu->state, &src_fpu->state, fpu_kernel_xstate_size);
     242             : 
     243        2571 :         else if (!copy_fpregs_to_fpstate(dst_fpu))
     244           0 :                 copy_kernel_to_fpregs(&dst_fpu->state);
     245             : 
     246        2622 :         fpregs_unlock();
     247             : 
     248        2622 :         set_tsk_thread_flag(dst, TIF_NEED_FPU_LOAD);
     249             : 
     250        2622 :         trace_x86_fpu_copy_src(src_fpu);
     251        2622 :         trace_x86_fpu_copy_dst(dst_fpu);
     252             : 
     253        2622 :         return 0;
     254             : }
     255             : 
     256             : /*
     257             :  * Activate the current task's in-memory FPU context,
     258             :  * if it has not been used before:
     259             :  */
     260             : static void fpu__initialize(struct fpu *fpu)
     261             : {
     262             :         WARN_ON_FPU(fpu != &current->thread.fpu);
     263             : 
     264             :         set_thread_flag(TIF_NEED_FPU_LOAD);
     265             :         fpstate_init(&fpu->state);
     266             :         trace_x86_fpu_init_state(fpu);
     267             : }
     268             : 
     269             : /*
     270             :  * This function must be called before we read a task's fpstate.
     271             :  *
     272             :  * There's two cases where this gets called:
     273             :  *
     274             :  * - for the current task (when coredumping), in which case we have
     275             :  *   to save the latest FPU registers into the fpstate,
     276             :  *
     277             :  * - or it's called for stopped tasks (ptrace), in which case the
     278             :  *   registers were already saved by the context-switch code when
     279             :  *   the task scheduled out.
     280             :  *
     281             :  * If the task has used the FPU before then save it.
     282             :  */
     283           0 : void fpu__prepare_read(struct fpu *fpu)
     284             : {
     285           0 :         if (fpu == &current->thread.fpu)
     286           0 :                 fpu__save(fpu);
     287           0 : }
     288             : 
     289             : /*
     290             :  * This function must be called before we write a task's fpstate.
     291             :  *
     292             :  * Invalidate any cached FPU registers.
     293             :  *
     294             :  * After this function call, after registers in the fpstate are
     295             :  * modified and the child task has woken up, the child task will
     296             :  * restore the modified FPU state from the modified context. If we
     297             :  * didn't clear its cached status here then the cached in-registers
     298             :  * state pending on its former CPU could be restored, corrupting
     299             :  * the modifications.
     300             :  */
     301           0 : void fpu__prepare_write(struct fpu *fpu)
     302             : {
     303             :         /*
     304             :          * Only stopped child tasks can be used to modify the FPU
     305             :          * state in the fpstate buffer:
     306             :          */
     307           0 :         WARN_ON_FPU(fpu == &current->thread.fpu);
     308             : 
     309             :         /* Invalidate any cached state: */
     310           0 :         __fpu_invalidate_fpregs_state(fpu);
     311           0 : }
     312             : 
     313             : /*
     314             :  * Drops current FPU state: deactivates the fpregs and
     315             :  * the fpstate. NOTE: it still leaves previous contents
     316             :  * in the fpregs in the eager-FPU case.
     317             :  *
     318             :  * This function can be used in cases where we know that
     319             :  * a state-restore is coming: either an explicit one,
     320             :  * or a reschedule.
     321             :  */
     322        2545 : void fpu__drop(struct fpu *fpu)
     323             : {
     324        2545 :         preempt_disable();
     325             : 
     326        2545 :         if (fpu == &current->thread.fpu) {
     327             :                 /* Ignore delayed exceptions from user space */
     328        2545 :                 asm volatile("1: fwait\n"
     329             :                              "2:\n"
     330             :                              _ASM_EXTABLE(1b, 2b));
     331        2545 :                 fpregs_deactivate(fpu);
     332             :         }
     333             : 
     334        2545 :         trace_x86_fpu_dropped(fpu);
     335             : 
     336        2545 :         preempt_enable();
     337        2545 : }
     338             : 
     339             : /*
     340             :  * Clear FPU registers by setting them up from the init fpstate.
     341             :  * Caller must do fpregs_[un]lock() around it.
     342             :  */
     343        3561 : static inline void copy_init_fpstate_to_fpregs(u64 features_mask)
     344             : {
     345        3561 :         if (use_xsave())
     346        3561 :                 copy_kernel_to_xregs(&init_fpstate.xsave, features_mask);
     347           0 :         else if (static_cpu_has(X86_FEATURE_FXSR))
     348           0 :                 copy_kernel_to_fxregs(&init_fpstate.fxsave);
     349             :         else
     350             :                 copy_kernel_to_fregs(&init_fpstate.fsave);
     351             : 
     352        3561 :         if (boot_cpu_has(X86_FEATURE_OSPKE))
     353             :                 copy_init_pkru_to_fpregs();
     354        3561 : }
     355             : 
     356             : /*
     357             :  * Clear the FPU state back to init state.
     358             :  *
     359             :  * Called by sys_execve(), by the signal handler code and by various
     360             :  * error paths.
     361             :  */
     362        3561 : static void fpu__clear(struct fpu *fpu, bool user_only)
     363             : {
     364        3561 :         WARN_ON_FPU(fpu != &current->thread.fpu);
     365             : 
     366        3561 :         if (!static_cpu_has(X86_FEATURE_FPU)) {
     367             :                 fpu__drop(fpu);
     368             :                 fpu__initialize(fpu);
     369             :                 return;
     370             :         }
     371             : 
     372        3561 :         fpregs_lock();
     373             : 
     374        3561 :         if (user_only) {
     375        1304 :                 if (!fpregs_state_valid(fpu, smp_processor_id()) &&
     376             :                     xfeatures_mask_supervisor())
     377           0 :                         copy_kernel_to_xregs(&fpu->state.xsave,
     378             :                                              xfeatures_mask_supervisor());
     379        1304 :                 copy_init_fpstate_to_fpregs(xfeatures_mask_user());
     380             :         } else {
     381        2257 :                 copy_init_fpstate_to_fpregs(xfeatures_mask_all);
     382             :         }
     383             : 
     384        3561 :         fpregs_mark_activate();
     385        3561 :         fpregs_unlock();
     386             : }
     387             : 
     388        1304 : void fpu__clear_user_states(struct fpu *fpu)
     389             : {
     390        1304 :         fpu__clear(fpu, true);
     391        1304 : }
     392             : 
     393        2257 : void fpu__clear_all(struct fpu *fpu)
     394             : {
     395        2257 :         fpu__clear(fpu, false);
     396        2257 : }
     397             : 
     398             : /*
     399             :  * Load FPU context before returning to userspace.
     400             :  */
     401       12719 : void switch_fpu_return(void)
     402             : {
     403       12719 :         if (!static_cpu_has(X86_FEATURE_FPU))
     404             :                 return;
     405             : 
     406       12719 :         __fpregs_load_activate();
     407             : }
     408             : EXPORT_SYMBOL_GPL(switch_fpu_return);
     409             : 
     410             : #ifdef CONFIG_X86_DEBUG_FPU
     411             : /*
     412             :  * If current FPU state according to its tracking (loaded FPU context on this
     413             :  * CPU) is not valid then we must have TIF_NEED_FPU_LOAD set so the context is
     414             :  * loaded on return to userland.
     415             :  */
     416             : void fpregs_assert_state_consistent(void)
     417             : {
     418             :         struct fpu *fpu = &current->thread.fpu;
     419             : 
     420             :         if (test_thread_flag(TIF_NEED_FPU_LOAD))
     421             :                 return;
     422             : 
     423             :         WARN_ON_FPU(!fpregs_state_valid(fpu, smp_processor_id()));
     424             : }
     425             : EXPORT_SYMBOL_GPL(fpregs_assert_state_consistent);
     426             : #endif
     427             : 
     428        4865 : void fpregs_mark_activate(void)
     429             : {
     430        4865 :         struct fpu *fpu = &current->thread.fpu;
     431             : 
     432        4865 :         fpregs_activate(fpu);
     433        4865 :         fpu->last_cpu = smp_processor_id();
     434        4865 :         clear_thread_flag(TIF_NEED_FPU_LOAD);
     435        4865 : }
     436             : EXPORT_SYMBOL_GPL(fpregs_mark_activate);
     437             : 
     438             : /*
     439             :  * x87 math exception handling:
     440             :  */
     441             : 
     442           0 : int fpu__exception_code(struct fpu *fpu, int trap_nr)
     443             : {
     444           0 :         int err;
     445             : 
     446           0 :         if (trap_nr == X86_TRAP_MF) {
     447           0 :                 unsigned short cwd, swd;
     448             :                 /*
     449             :                  * (~cwd & swd) will mask out exceptions that are not set to unmasked
     450             :                  * status.  0x3f is the exception bits in these regs, 0x200 is the
     451             :                  * C1 reg you need in case of a stack fault, 0x040 is the stack
     452             :                  * fault bit.  We should only be taking one exception at a time,
     453             :                  * so if this combination doesn't produce any single exception,
     454             :                  * then we have a bad program that isn't synchronizing its FPU usage
     455             :                  * and it will suffer the consequences since we won't be able to
     456             :                  * fully reproduce the context of the exception.
     457             :                  */
     458           0 :                 if (boot_cpu_has(X86_FEATURE_FXSR)) {
     459           0 :                         cwd = fpu->state.fxsave.cwd;
     460           0 :                         swd = fpu->state.fxsave.swd;
     461             :                 } else {
     462             :                         cwd = (unsigned short)fpu->state.fsave.cwd;
     463             :                         swd = (unsigned short)fpu->state.fsave.swd;
     464             :                 }
     465             : 
     466           0 :                 err = swd & ~cwd;
     467             :         } else {
     468             :                 /*
     469             :                  * The SIMD FPU exceptions are handled a little differently, as there
     470             :                  * is only a single status/control register.  Thus, to determine which
     471             :                  * unmasked exception was caught we must mask the exception mask bits
     472             :                  * at 0x1f80, and then use these to mask the exception bits at 0x3f.
     473             :                  */
     474           0 :                 unsigned short mxcsr = MXCSR_DEFAULT;
     475             : 
     476           0 :                 if (boot_cpu_has(X86_FEATURE_XMM))
     477           0 :                         mxcsr = fpu->state.fxsave.mxcsr;
     478             : 
     479           0 :                 err = ~(mxcsr >> 7) & mxcsr;
     480             :         }
     481             : 
     482           0 :         if (err & 0x001) {  /* Invalid op */
     483             :                 /*
     484             :                  * swd & 0x240 == 0x040: Stack Underflow
     485             :                  * swd & 0x240 == 0x240: Stack Overflow
     486             :                  * User must clear the SF bit (0x40) if set
     487             :                  */
     488             :                 return FPE_FLTINV;
     489           0 :         } else if (err & 0x004) { /* Divide by Zero */
     490             :                 return FPE_FLTDIV;
     491           0 :         } else if (err & 0x008) { /* Overflow */
     492             :                 return FPE_FLTOVF;
     493           0 :         } else if (err & 0x012) { /* Denormal, Underflow */
     494             :                 return FPE_FLTUND;
     495           0 :         } else if (err & 0x020) { /* Precision */
     496           0 :                 return FPE_FLTRES;
     497             :         }
     498             : 
     499             :         /*
     500             :          * If we're using IRQ 13, or supposedly even some trap
     501             :          * X86_TRAP_MF implementations, it's possible
     502             :          * we get a spurious trap, which is not an error.
     503             :          */
     504             :         return 0;
     505             : }

Generated by: LCOV version 1.14