• James Hogan's avatar
    MIPS: KVM: Fix timer IRQ race when writing CP0_Compare · b45bacd2
    James Hogan authored
    Writing CP0_Compare clears the timer interrupt pending bit
    (CP0_Cause.TI), but this wasn't being done atomically. If a timer
    interrupt raced with the write of the guest CP0_Compare, the timer
    interrupt could end up being pending even though the new CP0_Compare is
    nowhere near CP0_Count.
    
    We were already updating the hrtimer expiry with
    kvm_mips_update_hrtimer(), which used both kvm_mips_freeze_hrtimer() and
    kvm_mips_resume_hrtimer(). Close the race window by expanding out
    kvm_mips_update_hrtimer(), and clearing CP0_Cause.TI and setting
    CP0_Compare between the freeze and resume. Since the pending timer
    interrupt should not be cleared when CP0_Compare is written via the KVM
    user API, an ack argument is added to distinguish the source of the
    write.
    
    Fixes: e30492bb ("MIPS: KVM: Rewrite count/compare timer emulation")
    Signed-off-by: default avatarJames Hogan <james.hogan@imgtec.com>
    Cc: Paolo Bonzini <pbonzini@redhat.com>
    Cc: "Radim KrčmáÅ" <rkrcmar@redhat.com>
    Cc: Ralf Baechle <ralf@linux-mips.org>
    Cc: linux-mips@linux-mips.org
    Cc: kvm@vger.kernel.org
    Cc: <stable@vger.kernel.org> # 3.16.x-
    Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
    b45bacd2
emulate.c 68.6 KB