lkml.org 
[lkml]   [2015]   [Jun]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[tip:x86/fpu] x86/fpu/xstate: Fix up bad get_xsave_addr() assumptions
    Commit-ID:  0c4109bec0a6cde471bef3a21cd6f8384a614469
    Gitweb: http://git.kernel.org/tip/0c4109bec0a6cde471bef3a21cd6f8384a614469
    Author: Dave Hansen <dave.hansen@linux.intel.com>
    AuthorDate: Sun, 7 Jun 2015 11:37:00 -0700
    Committer: Ingo Molnar <mingo@kernel.org>
    CommitDate: Tue, 9 Jun 2015 12:24:29 +0200

    x86/fpu/xstate: Fix up bad get_xsave_addr() assumptions

    get_xsave_addr() assumes that if an xsave bit is present in the
    hardware (pcntxt_mask) that it is present in a given xsave
    buffer. Due to an bug in the xsave code on all of the systems
    that have MPX (and thus all the users of this code), that has
    been a true assumption.

    But, the bug is getting fixed, so our assumption is not going
    to hold any more.

    It's quite possible (and normal) for an enabled state to be
    present on 'pcntxt_mask', but *not* in 'xstate_bv'. We need
    to consult 'xstate_bv'.

    Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
    Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
    Cc: Andrew Morton <akpm@linux-foundation.org>
    Cc: Dave Hansen <dave@sr71.net>
    Cc: H. Peter Anvin <hpa@zytor.com>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Link: http://lkml.kernel.org/r/20150607183700.1E739B34@viggo.jf.intel.com
    Signed-off-by: Ingo Molnar <mingo@kernel.org>
    ---
    arch/x86/kernel/fpu/xstate.c | 45 ++++++++++++++++++++++++++++++++++++--------
    1 file changed, 37 insertions(+), 8 deletions(-)

    diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
    index a580eb5..af3700e 100644
    --- a/arch/x86/kernel/fpu/xstate.c
    +++ b/arch/x86/kernel/fpu/xstate.c
    @@ -382,19 +382,48 @@ void fpu__resume_cpu(void)
    * This is the API that is called to get xstate address in either
    * standard format or compacted format of xsave area.
    *
    + * Note that if there is no data for the field in the xsave buffer
    + * this will return NULL.
    + *
    * Inputs:
    - * xsave: base address of the xsave area;
    - * xstate: state which is defined in xsave.h (e.g. XSTATE_FP, XSTATE_SSE,
    - * etc.)
    + * xstate: the thread's storage area for all FPU data
    + * xstate_feature: state which is defined in xsave.h (e.g.
    + * XSTATE_FP, XSTATE_SSE, etc...)
    * Output:
    - * address of the state in the xsave area.
    + * address of the state in the xsave area, or NULL if the
    + * field is not present in the xsave buffer.
    */
    -void *get_xsave_addr(struct xregs_state *xsave, int xstate)
    +void *get_xsave_addr(struct xregs_state *xsave, int xstate_feature)
    {
    - int feature = fls64(xstate) - 1;
    - if (!test_bit(feature, (unsigned long *)&xfeatures_mask))
    + int feature_nr = fls64(xstate_feature) - 1;
    + /*
    + * Do we even *have* xsave state?
    + */
    + if (!boot_cpu_has(X86_FEATURE_XSAVE))
    + return NULL;
    +
    + xsave = &current->thread.fpu.state.xsave;
    + /*
    + * We should not ever be requesting features that we
    + * have not enabled. Remember that pcntxt_mask is
    + * what we write to the XCR0 register.
    + */
    + WARN_ONCE(!(xfeatures_mask & xstate_feature),
    + "get of unsupported state");
    + /*
    + * This assumes the last 'xsave*' instruction to
    + * have requested that 'xstate_feature' be saved.
    + * If it did not, we might be seeing and old value
    + * of the field in the buffer.
    + *
    + * This can happen because the last 'xsave' did not
    + * request that this feature be saved (unlikely)
    + * or because the "init optimization" caused it
    + * to not be saved.
    + */
    + if (!(xsave->header.xfeatures & xstate_feature))
    return NULL;

    - return (void *)xsave + xstate_comp_offsets[feature];
    + return (void *)xsave + xstate_comp_offsets[feature_nr];
    }
    EXPORT_SYMBOL_GPL(get_xsave_addr);

    \
     
     \ /
      Last update: 2015-06-09 14:41    [W:4.182 / U:0.064 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site