• Xiaoming Gao's avatar
    x86/tsc: Prevent 32bit truncation in calc_hpet_ref() · d3878e16
    Xiaoming Gao authored
    The TSC calibration code uses HPET as reference. The conversion normalizes
    the delta of two HPET timestamps:
    
        hpetref = ((tshpet1 - tshpet2) * HPET_PERIOD) / 1e6
    
    and then divides the normalized delta of the corresponding TSC timestamps
    by the result to calulate the TSC frequency.
    
        tscfreq = ((tstsc1 - tstsc2 ) * 1e6) / hpetref
    
    This uses do_div() which takes an u32 as the divisor, which worked so far
    because the HPET frequency was low enough that 'hpetref' never exceeded
    32bit.
    
    On Skylake machines the HPET frequency increased so 'hpetref' can exceed
    32bit. do_div() truncates the divisor, which causes the calibration to
    fail.
    
    Use div64_u64() to avoid the problem.
    
    [ tglx: Fixes whitespace mangled patch and rewrote changelog ]
    Signed-off-by: default avatarXiaoming Gao <newtongao@tencent.com>
    Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    Cc: stable@vger.kernel.org
    Cc: peterz@infradead.org
    Cc: hpa@zytor.com
    Link: https://lkml.kernel.org/r/38894564-4fc9-b8ec-353f-de702839e44e@gmail.com
    d3878e16
tsc.c 37.1 KB