lkml.org 
[lkml]   [2015]   [Aug]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Subject[PATCH 11/11] x86, fpu: check CPU-provided sizes against struct declarations
    From
    Date

    From: Dave Hansen <dave.hansen@linux.intel.com>

    We now have C structures defined for each of the XSAVE state
    components that we support. This patch adds checks during our
    verification pass to ensure that the CPU-provided data
    enumerated in CPUID leaves matches our C structures.

    If not, we warn and dump all the XSAVE CPUID leaves.

    Note: this *actually* found an inconsistency with the MPX
    'bndcsr' state. The hardware pads it out differently from
    our C structures. This patch caught it and warned.

    Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
    Cc: Ingo Molnar <mingo@redhat.com>
    Cc: x86@kernel.org
    Cc: Borislav Petkov <bp@alien8.de>
    Cc: Fenghua Yu <fenghua.yu@intel.com>
    Cc: Tim Chen <tim.c.chen@linux.intel.com>
    Cc: linux-kernel@vger.kernel.org
    ---

    b/arch/x86/kernel/fpu/xstate.c | 53 +++++++++++++++++++++++++++++++++++++++++
    1 file changed, 53 insertions(+)

    diff -puN arch/x86/kernel/fpu/xstate.c~x86-fpu-check-against-struct-declarations arch/x86/kernel/fpu/xstate.c
    --- a/arch/x86/kernel/fpu/xstate.c~x86-fpu-check-against-struct-declarations 2015-08-27 10:08:05.023791536 -0700
    +++ b/arch/x86/kernel/fpu/xstate.c 2015-08-27 10:08:05.027791718 -0700
    @@ -409,6 +409,49 @@ static void __xstate_dump_leaves(void)
    } \
    } while (0)

    +#define XCHECK_SZ(sz, nr, nr_macro, __struct) do { \
    + if ((nr == nr_macro) && \
    + WARN_ONCE(sz != sizeof(__struct), \
    + "%s: struct is %ld bytes, cpu state %d bytes\n", \
    + __stringify(nr_macro), sizeof(__struct), sz)) { \
    + __xstate_dump_leaves(); \
    + } \
    +} while (0)
    +
    +/*
    + * We have a C struct for each 'xstate'. We need to ensure
    + * that our software representation matches what the CPU
    + * tells us about the state's size.
    + */
    +static void check_xstate_against_struct(int nr)
    +{
    + /*
    + * Ask the CPU for the size of the state.
    + */
    + int sz = xfeature_size(nr);
    + /*
    + * Match each CPU state with the corresponding software
    + * structure.
    + */
    + XCHECK_SZ(sz, nr, XFEATURE_NR_YMM, struct ymmh_struct);
    + XCHECK_SZ(sz, nr, XFEATURE_NR_BNDREGS, struct mpx_bndreg_state);
    + XCHECK_SZ(sz, nr, XFEATURE_NR_BNDCSR, struct mpx_bndcsr_state);
    + XCHECK_SZ(sz, nr, XFEATURE_NR_OPMASK, struct avx_512_opmask_state);
    + XCHECK_SZ(sz, nr, XFEATURE_NR_ZMM_Hi256, struct avx_512_zmm_uppers_state);
    + XCHECK_SZ(sz, nr, XFEATURE_NR_Hi16_ZMM, struct avx_512_hi16_state);
    +
    + /*
    + * Make *SURE* to add any feature numbers in below if
    + * there are "holes" in the xsave state component
    + * numbers.
    + */
    + if ((nr < XFEATURE_NR_YMM) ||
    + (nr >= XFEATURES_NR_MAX)) {
    + WARN_ONCE(1, "no structure for xstate: %d\n", nr);
    + XSTATE_WARN_ON(1);
    + }
    +}
    +
    /*
    * This essentially double-checks what the cpu told us about
    * how large the XSAVE buffer needs to be. We are recalculating
    @@ -422,6 +465,8 @@ static void do_extra_xstate_size_checks(
    for (i = FIRST_EXTENDED_XFEATURE_NR; i < XFEATURES_NR_MAX; i++) {
    if (!xfeature_nr_enabled(i))
    continue;
    +
    + check_xstate_against_struct(i);
    /*
    * Supervisor state components can be managed only by
    * XSAVES, which is compacted-format only.
    @@ -447,6 +492,14 @@ static void do_extra_xstate_size_checks(
    paranoid_xstate_size += xfeature_size(i);
    }
    XSTATE_WARN_ON(paranoid_xstate_size != xstate_size);
    + /*
    + * Basically, make sure that XSTATE_RESERVE has forced
    + * xregs_state to be large enough. This is not fatal
    + * because we reserve a *lot* of extra room in the init
    + * task struct, but we should at least know we got it
    + * wrong.
    + */
    + XSTATE_WARN_ON(xstate_size > sizeof(struct xregs_state));
    }

    /*
    _

    \
     
     \ /
      Last update: 2015-08-27 19:41    [W:5.015 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site