lkml.org 
[lkml]   [2019]   [Aug]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 3/3] linux/bits.h: Add compile time sanity check of GENMASK inputs
    Date
    GENMASK() and GENMASK_ULL() are supposed to be called with the high bit
    as the first argument and the low bit as the second argument. Mixing
    them will return a mask with zero bits set.

    Recent commits show getting this wrong is not uncommon, see e.g.
    commit aa4c0c9091b0 ("net: stmmac: Fix misuses of GENMASK macro") and
    commit 9bdd7bb3a844 ("clocksource/drivers/npcm: Fix misuse of GENMASK
    macro").

    To prevent such mistakes from appearing again, add compile time sanity
    checking to the arguments of GENMASK() and GENMASK_ULL(). If both
    arguments are known at compile time, and the low bit is higher than the
    high bit, break the build to detect the mistake immediately.

    Since GENMASK() is used in declarations, BUILD_BUG_ON_ZERO() must be
    used instead of BUILD_BUG_ON().

    __builtin_constant_p does not evaluate is argument, it only checks if it
    is a constant or not at compile time, and __builtin_choose_expr does not
    evaluate the expression that is not chosen. Therefore, GENMASK(x++, 0)
    does only evaluate x++ once.

    Commit 95b980d62d52 ("linux/bits.h: make BIT(), GENMASK(), and friends
    available in assembly") made the macros in linux/bits.h available in
    assembly. Since BUILD_BUG_OR_ZERO() is not asm compatible, disable the
    checks if the file is included in an asm file.

    Signed-off-by: Rikard Falkeborn <rikard.falkeborn@gmail.com>
    ---
    Changes in v3:
    - Changed back to shorter macro argument names
    - Remove casts and use 0 instead of UL(0) in GENMASK_INPUT_CHECK(),
    since all results in GENMASK_INPUT_CHECK() are now ints. Update
    commit message to reflect that.

    Changes in v2:
    - Add comment about why inputs are not checked when used in asm file
    - Use UL(0) instead of 0
    - Extract mask creation in a separate macro to improve readability
    - Use high and low instead of h and l (part of this was extracted to a
    separate patch)
    - Updated commit message

    Joe Perches sent a series to fix the existing misuses of GENMASK() that
    needs to be merged before this to avoid build failures. Currently, 5 of
    the patches are not in Linus tree, and 2 are not in linux-next. There is
    also a patch pending by Nathan Chancellor that also needs to be merged
    before this patch is merged to avoid build failures.

    include/linux/bits.h | 21 +++++++++++++++++++--
    1 file changed, 19 insertions(+), 2 deletions(-)

    diff --git a/include/linux/bits.h b/include/linux/bits.h
    index 669d69441a62..4ba0fb609239 100644
    --- a/include/linux/bits.h
    +++ b/include/linux/bits.h
    @@ -18,12 +18,29 @@
    * position @h. For example
    * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000.
    */
    -#define GENMASK(h, l) \
    +#ifndef __ASSEMBLY__
    +#include <linux/build_bug.h>
    +#define GENMASK_INPUT_CHECK(h, l) \
    + (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
    + __builtin_constant_p((l) > (h)), (l) > (h), 0)))
    +#else
    +/*
    + * BUILD_BUG_ON_ZERO is not available in h files included from asm files,
    + * disable the input check if that is the case.
    + */
    +#define GENMASK_INPUT_CHECK(h, l) 0
    +#endif
    +
    +#define __GENMASK(h, l) \
    (((~UL(0)) - (UL(1) << (l)) + 1) & \
    (~UL(0) >> (BITS_PER_LONG - 1 - (h))))
    +#define GENMASK(h, l) \
    + (GENMASK_INPUT_CHECK(h, l) + __GENMASK(h, l))

    -#define GENMASK_ULL(h, l) \
    +#define __GENMASK_ULL(h, l) \
    (((~ULL(0)) - (ULL(1) << (l)) + 1) & \
    (~ULL(0) >> (BITS_PER_LONG_LONG - 1 - (h))))
    +#define GENMASK_ULL(h, l) \
    + (GENMASK_INPUT_CHECK(h, l) + __GENMASK_ULL(h, l))

    #endif /* __LINUX_BITS_H */
    --
    2.22.0
    \
     
     \ /
      Last update: 2019-08-11 20:51    [W:4.183 / U:0.172 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site