• M
    MIPS: Avoid handcoded DIVU in `__div64_32' altogether · 8d5778e2
    Maciej W. Rozycki 提交于
    stable inclusion
    from stable-5.10.38
    commit 462049cfb342c4f5e8344452a205207fc5575f1b
    bugzilla: 51875
    CVE: NA
    
    --------------------------------
    
    commit 25ab14cb upstream.
    
    Remove the inline asm with a DIVU instruction from `__div64_32' and use
    plain C code for the intended DIVMOD calculation instead.  GCC is smart
    enough to know that both the quotient and the remainder are calculated
    with single DIVU, so with ISAs up to R5 the same instruction is actually
    produced with overall similar code.
    
    For R6 compiled code will work, but separate DIVU and MODU instructions
    will be produced, which are also interlocked, so scalar implementations
    will likely not perform as well as older ISAs with their asynchronous MD
    unit.  Likely still faster then the generic algorithm though.
    
    This removes a compilation error for R6 however where the original DIVU
    instruction is not supported anymore and the MDU accumulator registers
    have been removed and consequently GCC complains as to a constraint it
    cannot find a register for:
    
    In file included from ./include/linux/math.h:5,
                     from ./include/linux/kernel.h:13,
                     from mm/page-writeback.c:15:
    ./include/linux/math64.h: In function 'div_u64_rem':
    ./arch/mips/include/asm/div64.h:76:17: error: inconsistent operand constraints in an 'asm'
       76 |                 __asm__("divu   $0, %z1, %z2"                           \
          |                 ^~~~~~~
    ./include/asm-generic/div64.h:245:25: note: in expansion of macro '__div64_32'
      245 |                 __rem = __div64_32(&(n), __base);       \
          |                         ^~~~~~~~~~
    ./include/linux/math64.h:91:22: note: in expansion of macro 'do_div'
       91 |         *remainder = do_div(dividend, divisor);
          |                      ^~~~~~
    
    This has passed correctness verification with test_div64 and reduced the
    module's average execution time down to 1.0404s from 1.0445s with R3400
    @40MHz.  The module's MIPS I machine code has also shrunk by 12 bytes or
    3 instructions.
    Signed-off-by: NMaciej W. Rozycki <macro@orcam.me.uk>
    Signed-off-by: NThomas Bogendoerfer <tsbogend@alpha.franken.de>
    Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    Signed-off-by: NChen Jun <chenjun102@huawei.com>
    Acked-by: NWeilong Chen <chenweilong@huawei.com>
    Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
    8d5778e2
div64.h 2.2 KB