• James Hogan's avatar
    MIPS: KVM: Fix timer race modifying guest CP0_Cause · c73c99b0
    James Hogan authored
    The hrtimer callback for guest timer timeouts sets the guest's
    CP0_Cause.TI bit to indicate to the guest that a timer interrupt is
    pending, however there is no mutual exclusion implemented to prevent
    this occurring while the guest's CP0_Cause register is being
    read-modify-written elsewhere.
    
    When this occurs the setting of the CP0_Cause.TI bit is undone and the
    guest misses the timer interrupt and doesn't reprogram the CP0_Compare
    register for the next timeout. Currently another timer interrupt will be
    triggered again in another 10ms anyway due to the way timers are
    emulated, but after the MIPS timer emulation is fixed this would result
    in Linux guest time standing still and the guest scheduler not being
    invoked until the guest CP0_Count has looped around again, which at
    100MHz takes just under 43 seconds.
    
    Currently this is the only asynchronous modification of guest registers,
    therefore it is fixed by adjusting the implementations of the
    kvm_set_c0_guest_cause(), kvm_clear_c0_guest_cause(), and
    kvm_change_c0_guest_cause() macros which are used for modifying the
    guest CP0_Cause register to use ll/sc to ensure atomic modification.
    This should work in both UP and SMP cases without requiring interrupts
    to be disabled.
    Signed-off-by: default avatarJames Hogan <james.hogan@imgtec.com>
    Cc: Paolo Bonzini <pbonzini@redhat.com>
    Cc: Gleb Natapov <gleb@kernel.org>
    Cc: kvm@vger.kernel.org
    Cc: Ralf Baechle <ralf@linux-mips.org>
    Cc: linux-mips@linux-mips.org
    Cc: Sanjay Lal <sanjayl@kymasys.com>
    Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
    c73c99b0
kvm_host.h 24.5 KB