From: "Radim Krčmář" <rkrcmar@redhat.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org,
Yuki Shibuya <shibuya.yk@ncos.nec.co.jp>
Subject: Re: [PATCH 2/4] KVM: x86: refactor PIT state inject_lock
Date: Thu, 4 Feb 2016 14:13:06 +0100 [thread overview]
Message-ID: <20160204131306.GA16897@potion.brq.redhat.com> (raw)
In-Reply-To: <56B22E95.30504@redhat.com>
2016-02-03 17:45+0100, Paolo Bonzini:
> On 03/02/2016 17:23, Radim Krčmář wrote:
>> Following patches would be even uglier if inject_lock didn't go away.
>>
>> Patch changes the virtual wire comment to better describe our situation.
>>
>> Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
>> ---
>> diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
>> @@ -236,16 +236,13 @@ static void kvm_pit_ack_irq(struct kvm_irq_ack_notifier *kian)
>> {
>> struct kvm_kpit_state *ps = container_of(kian, struct kvm_kpit_state,
>> irq_ack_notifier);
>> - int value;
>>
>> - spin_lock(&ps->inject_lock);
(Our code doesn't need barrier between dereferencing the pointer and
reading its contents, and this bug is not possible happen on x86.)
>> + atomic_set(&ps->irq_ack, 1);
>
> smp_mb__before_atomic();
irq_ack has to be set before queueing pit_do_work, or could lose the
interrupt.
atomic_add_unless implies full barriers, so I think we're ok here.
>> if (atomic_add_unless(&ps->pending, -1, 0))
>> queue_kthread_work(&ps->pit->worker, &ps->pit->expired);
>> void __kvm_migrate_pit_timer(struct kvm_vcpu *vcpu)
>> @@ -323,6 +311,12 @@ static enum hrtimer_restart pit_timer_fn(struct hrtimer *data)
>> return HRTIMER_NORESTART;
>> }
>>
>> +static void kvm_pit_reset_reinject(struct kvm_pit *pit)
>> +{
>> + atomic_set(&pit->pit_state.pending, 0);
>
> smp_wmb()?
I don't think that we need to ensure the order of pending and irq_ack
because there isn't a dependency between these two. The reset is a slap
out of nowhere ... I think we'd need locks to make it behave correctly.
The worst that can happen is one virtual wire NMI injection when the
IOAPIC interrupt was in IRR and number of injections therefore won't
match. The race goes like this:
kvm_pit_ack_irq is running and we have pending > 0, so pit_do_work is
scheduled and executed. pit_do_work sets irq_ack from 1 to 0.
Then pit_timer_fn gets executed, increases pending and queues
pit_do_work. Before pit_do_work has a chance to run, we set pending=0
and irq_ack=1 in kvm_pit_reset_reinject. pit_do_work is executed, sets
irq_ack from 1 to 0, but injects only the NMI, because interrupt is
already in IRR. When the interrupt does EOI, we don't reinject it,
because pending==0.
Barriers can't solve this, locking would be pretty awkward and I think
that having one interrupt more or less is ok for the delay policy. :)
| + atomic_set(&pit->pit_state.irq_ack, 1);
Callers of kvm_pit_reset_reinject are providing barriers, so assignment
can't be reordered into inappropriate places, but it wouldn't hurt to
add barriers here.
> Looks safe otherwise. (Please also add a comment before the memory
> barriers to show the pairing).
Thanks, I'll comment what I can.
next prev parent reply other threads:[~2016-02-04 13:13 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-02-03 16:23 [PATCH 0/4] KVM: x86: change and fix PIT discard tick policy Radim Krčmář
2016-02-03 16:23 ` [PATCH 1/4] KVM: x86: fix interrupt dropping race in PIT Radim Krčmář
2016-02-04 13:35 ` Radim Krčmář
2016-02-03 16:23 ` [PATCH 2/4] KVM: x86: refactor PIT state inject_lock Radim Krčmář
2016-02-03 16:45 ` Paolo Bonzini
2016-02-04 13:13 ` Radim Krčmář [this message]
2016-02-03 16:23 ` [PATCH 3/4] KVM: x86: change PIT discard tick policy Radim Krčmář
2016-02-03 16:48 ` Paolo Bonzini
2016-02-03 16:23 ` [PATCH 4/4] KVM: x86: remove notifiers from PIT discard policy Radim Krčmář
2016-02-03 16:51 ` Paolo Bonzini
2016-02-04 13:15 ` Radim Krčmář
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20160204131306.GA16897@potion.brq.redhat.com \
--to=rkrcmar@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=shibuya.yk@ncos.nec.co.jp \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox