Commit c0368991 authored by Coleman Dietsch's avatar Coleman Dietsch Committed by Paolo Bonzini

KVM: x86/xen: Stop Xen timer before changing IRQ

Stop Xen timer (if it's running) prior to changing the IRQ vector and
potentially (re)starting the timer. Changing the IRQ vector while the
timer is still running can result in KVM injecting a garbage event, e.g.
vm_xen_inject_timer_irqs() could see a non-zero xen.timer_pending from
a previous timer but inject the new xen.timer_virq.

Fixes: 53639526 ("KVM: x86/xen: handle PV timers oneshot mode")
Cc: stable@vger.kernel.org
Link: https://syzkaller.appspot.com/bug?id=8234a9dfd3aafbf092cc5a7cd9842e3ebc45fc42
Reported-by: syzbot+e54f930ed78eb0f85281@syzkaller.appspotmail.com
Signed-off-by: default avatarColeman Dietsch <dietschc@csp.edu>
Reviewed-by: default avatarSean Christopherson <seanjc@google.com>
Acked-by: default avatarDavid Woodhouse <dwmw@amazon.co.uk>
Message-Id: <20220808190607.323899-3-dietschc@csp.edu>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent af735db3
...@@ -707,25 +707,24 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data) ...@@ -707,25 +707,24 @@ int kvm_xen_vcpu_set_attr(struct kvm_vcpu *vcpu, struct kvm_xen_vcpu_attr *data)
break; break;
case KVM_XEN_VCPU_ATTR_TYPE_TIMER: case KVM_XEN_VCPU_ATTR_TYPE_TIMER:
if (data->u.timer.port) { if (data->u.timer.port &&
if (data->u.timer.priority != KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL) { data->u.timer.priority != KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL) {
r = -EINVAL; r = -EINVAL;
break; break;
} }
vcpu->arch.xen.timer_virq = data->u.timer.port;
if (!vcpu->arch.xen.timer.function) if (!vcpu->arch.xen.timer.function)
kvm_xen_init_timer(vcpu); kvm_xen_init_timer(vcpu);
/* Restart the timer if it's set */ /* Stop the timer (if it's running) before changing the vector */
if (data->u.timer.expires_ns) kvm_xen_stop_timer(vcpu);
vcpu->arch.xen.timer_virq = data->u.timer.port;
/* Start the timer if the new value has a valid vector+expiry. */
if (data->u.timer.port && data->u.timer.expires_ns)
kvm_xen_start_timer(vcpu, data->u.timer.expires_ns, kvm_xen_start_timer(vcpu, data->u.timer.expires_ns,
data->u.timer.expires_ns - data->u.timer.expires_ns -
get_kvmclock_ns(vcpu->kvm)); get_kvmclock_ns(vcpu->kvm));
} else if (kvm_xen_timer_enabled(vcpu)) {
kvm_xen_stop_timer(vcpu);
vcpu->arch.xen.timer_virq = 0;
}
r = 0; r = 0;
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment