diff options
author | Andrey Smetanin <asmetanin@virtuozzo.com> | 2015-12-28 10:27:21 -0500 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2016-01-08 13:04:41 -0500 |
commit | 0cdeabb1186fc3a6c7854f05cec7c99e32935ebc (patch) | |
tree | 9669ccea141691fe28419654a1aa745e18c361a2 | |
parent | f808495da56f28e94c6448125158f1175009fcfc (diff) |
kvm/x86: Reorg stimer_expiration() to better control timer restart
Split stimer_expiration() into two parts - timer expiration message
sending and timer restart/cleanup based on timer state(config).
This also fixes a bug where a one-shot timer message whose delivery
failed once would get lost for good.
Signed-off-by: Andrey Smetanin <asmetanin@virtuozzo.com>
Reviewed-by: Roman Kagan <rkagan@virtuozzo.com>
CC: Gleb Natapov <gleb@kernel.org>
CC: Paolo Bonzini <pbonzini@redhat.com>
CC: Roman Kagan <rkagan@virtuozzo.com>
CC: Denis V. Lunev <den@openvz.org>
CC: qemu-devel@nongnu.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | arch/x86/kvm/hyperv.c | 26 |
1 files changed, 14 insertions, 12 deletions
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 0dd7d1731c22..5f85c12b223c 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c | |||
@@ -554,30 +554,27 @@ static int synic_deliver_msg(struct kvm_vcpu_hv_synic *synic, u32 sint, | |||
554 | return r; | 554 | return r; |
555 | } | 555 | } |
556 | 556 | ||
557 | static void stimer_send_msg(struct kvm_vcpu_hv_stimer *stimer) | 557 | static int stimer_send_msg(struct kvm_vcpu_hv_stimer *stimer) |
558 | { | 558 | { |
559 | struct kvm_vcpu *vcpu = stimer_to_vcpu(stimer); | 559 | struct kvm_vcpu *vcpu = stimer_to_vcpu(stimer); |
560 | struct hv_message *msg = &stimer->msg; | 560 | struct hv_message *msg = &stimer->msg; |
561 | struct hv_timer_message_payload *payload = | 561 | struct hv_timer_message_payload *payload = |
562 | (struct hv_timer_message_payload *)&msg->u.payload; | 562 | (struct hv_timer_message_payload *)&msg->u.payload; |
563 | int r; | ||
564 | 563 | ||
565 | stimer->msg_pending = true; | ||
566 | payload->expiration_time = stimer->exp_time; | 564 | payload->expiration_time = stimer->exp_time; |
567 | payload->delivery_time = get_time_ref_counter(vcpu->kvm); | 565 | payload->delivery_time = get_time_ref_counter(vcpu->kvm); |
568 | r = synic_deliver_msg(vcpu_to_synic(vcpu), | 566 | return synic_deliver_msg(vcpu_to_synic(vcpu), |
569 | HV_STIMER_SINT(stimer->config), msg); | 567 | HV_STIMER_SINT(stimer->config), msg); |
570 | if (!r) | ||
571 | stimer->msg_pending = false; | ||
572 | } | 568 | } |
573 | 569 | ||
574 | static void stimer_expiration(struct kvm_vcpu_hv_stimer *stimer) | 570 | static void stimer_expiration(struct kvm_vcpu_hv_stimer *stimer) |
575 | { | 571 | { |
576 | stimer_send_msg(stimer); | 572 | stimer->msg_pending = true; |
577 | if (!(stimer->config & HV_STIMER_PERIODIC)) | 573 | if (!stimer_send_msg(stimer)) { |
578 | stimer->config &= ~HV_STIMER_ENABLE; | 574 | stimer->msg_pending = false; |
579 | else | 575 | if (!(stimer->config & HV_STIMER_PERIODIC)) |
580 | stimer_start(stimer); | 576 | stimer->config &= ~HV_STIMER_ENABLE; |
577 | } | ||
581 | } | 578 | } |
582 | 579 | ||
583 | void kvm_hv_process_stimers(struct kvm_vcpu *vcpu) | 580 | void kvm_hv_process_stimers(struct kvm_vcpu *vcpu) |
@@ -594,6 +591,11 @@ void kvm_hv_process_stimers(struct kvm_vcpu *vcpu) | |||
594 | time_now = get_time_ref_counter(vcpu->kvm); | 591 | time_now = get_time_ref_counter(vcpu->kvm); |
595 | if (time_now >= stimer->exp_time) | 592 | if (time_now >= stimer->exp_time) |
596 | stimer_expiration(stimer); | 593 | stimer_expiration(stimer); |
594 | |||
595 | if (stimer->config & HV_STIMER_ENABLE) | ||
596 | stimer_start(stimer); | ||
597 | else | ||
598 | stimer_cleanup(stimer); | ||
597 | } | 599 | } |
598 | } | 600 | } |
599 | } | 601 | } |