• Paul Burton's avatar
    MIPS: Fix set_pte() for Netlogic XLR using cmpxchg64() · c7e2d71d
    Paul Burton authored
    Commit 46011e6e ("MIPS: Make set_pte() SMP safe.") introduced an
    open-coded version of cmpxchg() within set_pte(), that always operated
    on a value the size of an unsigned long. That is, it used ll/sc
    instructions when CONFIG_32BIT=y or lld/scd instructions when
    CONFIG_64BIT=y.
    
    This was broken for configurations in which pte_t is larger than an
    unsigned long (with the exception of XPA configurations which have a
    different implementation of set_pte()), because we no longer update the
    whole PTE. Indeed commit 46011e6e ("MIPS: Make set_pte() SMP safe.")
    notes:
    
    > The case of CONFIG_64BIT_PHYS_ADDR && CONFIG_CPU_MIPS32 is *not*
    > handled.
    
    In practice this affects Netlogic XLR/XLS systems including
    nlm_xlr_defconfig.
    
    Commit 82f4f66d ("MIPS: Remove open-coded cmpxchg() in set_pte()")
    then replaced this open-coded version of cmpxchg() with an actual call
    to cmpxchg(). Unfortunately the configurations mentioned above then fail
    to build because cmpxchg() can only operate on values 32 bits or smaller
    in size, resulting in:
    
      arch/mips/include/asm/cmpxchg.h:166:11: error:
        call to '__cmpxchg_called_with_bad_pointer' declared with
        attribute error: Bad argument size for cmpxchg
    
    One option that would fix the build failure & restore the previous
    behaviour would be to cast the pte pointer to a pointer to unsigned
    long, so that cmpxchg() would operate on just 32 bits of the PTE as it
    has been since commit 46011e6e ("MIPS: Make set_pte() SMP safe.").
    That feels like an ugly hack though, and the behaviour of set_pte() is
    likely a little broken.
    
    Instead we take advantage of the fact that the affected configurations
    already know at compile time that the CPU will support 64 bits (ie. have
    hardcoded cpu_has_64bits in cpu-feature-overrides.h) in order to allow
    cmpxchg64() to be used in these configurations. set_pte() then makes use
    of cmpxchg64() when necessary.
    Signed-off-by: default avatarPaul Burton <paul.burton@mips.com>
    Fixes: 46011e6e ("MIPS: Make set_pte() SMP safe.")
    Fixes: 82f4f66d ("MIPS: Remove open-coded cmpxchg() in set_pte()")
    c7e2d71d
cmpxchg.h 7.85 KB