From: Paolo Bonzini <pbonzini@redhat.com>
To: David Woodhouse <dwmw2@infradead.org>,
Sean Christopherson <seanjc@google.com>
Cc: kvm <kvm@vger.kernel.org>, "Sironi, Filippo" <sironi@amazon.de>,
"Raslan, KarimAllah" <karahmed@amazon.de>,
Matt Gingell <gingell@google.com>,
Steve Rutherford <srutherford@google.com>,
liran@amazon.com
Subject: Re: [PATCH] kvm/x86: Fix simultaneous ExtINT and lapic interrupt handling with APICv
Date: Thu, 26 Nov 2020 19:00:20 +0100 [thread overview]
Message-ID: <e71a7296-810a-cb73-8d34-cd96391750eb@redhat.com> (raw)
In-Reply-To: <6a8897917188a3a23710199f8da3f5f33670b80f.camel@infradead.org>
On 26/11/20 13:05, David Woodhouse wrote:
> |It looks like this was introduced in commit 782d422bcaee, when
> dm_request_for_irq_injection() started returning true based purely on
> the fact that userspace had requested the interrupt window, without heed
> to kvm_cpu_has_interrupt() also being true. |
That patch had no semantic change, because
dm_request_for_irq_injection() was split in two and the problematic bit
was only split to kvm_vcpu_ready_for_interrupt_injection().
Even pre-patch there was a
if (kvm_cpu_has_interrupt(vcpu))
return false;
in dm_request_for_irq_injection() which your patch would have changed to
if (lapic_in_kernel(vcpu) && kvm_cpu_has_extint(vcpu))
return false;
Your patch certainly works, but _what_ does
!(lapic_in_kernel(vcpu) && kvm_cpu_has_extint(vcpu)) &&
kvm_cpu_accept_dm_intr(vcpu)
mean in terms of the vcpu's state? I have no idea, in fact at this
point I barely have an idea of what
kvm_vcpu_ready_for_interrupt_injection does. Let's figure it out.
First act
~~~~~~~~~
First of all let's take a step back from your patch. Let's just look at
kvm_cpu_has_interrupt(vcpu) and trivially remove the APIC case from
kvm_cpu_has_interrupt:
+static bool xxx(struct kvm_vcpu *vcpu)
+{
+ WARN_ON(pic_in_kernel(vcpu->kvm));
+ if (!lapic_in_kernel(vcpu))
+ return vcpu->arch.interrupt.injected;
+ else
+ return kvm_cpu_has_extint(vcpu);
+}
return kvm_arch_interrupt_allowed(vcpu) &&
- !kvm_cpu_has_interrupt(vcpu) &&
!kvm_event_needs_reinjection(vcpu) &&
+ !xxx(vcpu) &&
kvm_cpu_accept_dm_intr(vcpu);
Again, no idea does "xxx" do, much less its combination with
kvm_cpu_accept_dm_intr. We need to dive further down.
Second act
~~~~~~~~~~
kvm_cpu_accept_dm_intr can be rewritten like this:
if (!lapic_in_kernel(vcpu))
return true;
else
return kvm_apic_accept_pic_intr(vcpu));
Therefore, we can commonize the "if"s in our xxx function with those
from kvm_cpu_accept_dm_intr. Remembering that the first act used the
negation of xxx, the patch now takes this shape
+static int yyy(struct kvm_vcpu *vcpu)
+{
+ WARN_ON(pic_in_kernel(vcpu->kvm));
+ if (!lapic_in_kernel(vcpu))
+ return !vcpu->arch.interrupt.injected;
+ else
+ return (!kvm_cpu_has_extint(vcpu) &&
+ kvm_apic_accept_pic_intr(vcpu));
+}
return kvm_arch_interrupt_allowed(vcpu) &&
- !kvm_cpu_has_interrupt(vcpu) &&
!kvm_event_needs_reinjection(vcpu) &&
- kvm_cpu_accept_dm_intr(vcpu);
+ yyy(vcpu);
This doesn't seem like progress, but we're not done...
Third act
~~~~~~~~~
Let's look at the arms of yyy's "if" statement one by one.
If !lapic_in_kernel, the return statement will always be true because
the function is called under !kvm_event_needs_reinjection(vcpu). So
we're already at
static int yyy(struct kvm_vcpu *vcpu)
{
WARN_ON(pic_in_kernel(vcpu->kvm));
if (!lapic_in_kernel(vcpu))
return true;
return (!kvm_cpu_has_extint(vcpu) &&
kvm_apic_accept_pic_intr(vcpu));
}
As to the "else" branch, irqchip_split is true so
kvm_cpu_has_extint(vcpu) is "kvm_apic_accept_pic_intr(v) &&
pending_userspace_extint(v)". More simplifications ahead!
!(A && B) && A
=> (!A || !B) && A
=> A && !B
that is:
static int yyy(struct kvm_vcpu *vcpu)
{
WARN_ON(pic_in_kernel(vcpu->kvm));
if (!lapic_in_kernel(vcpu))
return true;
return (kvm_apic_accept_pic_intr(vcpu) &&
!pending_userspace_extint(vcpu));
}
which makes sense: focusing on ExtINT and ignoring event reinjection
(which is handled by the caller), the vCPU is ready for interrupt
injection if:
- there is no LAPIC (so ExtINT injection is in the hands of userspace), or
- PIC interrupts are being accepted, and userspace's last ExtINT isn't
still pending.
Thus, the final patch is:
static int kvm_vcpu_ready_for_interrupt_injection(struct kvm_vcpu *vcpu)
{
+ WARN_ON(pic_in_kernel(vcpu->kvm));
+
return kvm_arch_interrupt_allowed(vcpu) &&
- !kvm_cpu_has_interrupt(vcpu) &&
!kvm_event_needs_reinjection(vcpu) &&
- kvm_cpu_accept_dm_intr(vcpu);
+ (!lapic_in_kernel(vcpu)
+ || (kvm_apic_accept_pic_intr(vcpu)
+ && !pending_userspace_extint(v));
}
I'm wondering if this one fails as well...
Paolo
next prev parent reply other threads:[~2020-11-26 18:00 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-11-12 13:03 [RFC] Further hack request_interrupt_window handling to work around kvm_cpu_has_interrupt() nesting breakage David Woodhouse
2020-11-25 15:10 ` [RFC PATCH] Fix split-irqchip vs interrupt injection window request David Woodhouse
2020-11-25 21:19 ` Sean Christopherson
2020-11-26 11:10 ` David Woodhouse
2020-11-26 12:05 ` [PATCH] kvm/x86: Fix simultaneous ExtINT and lapic interrupt handling with APICv David Woodhouse
2020-11-26 18:00 ` Paolo Bonzini [this message]
2020-11-26 19:07 ` David Woodhouse
2020-11-26 17:29 ` [RFC PATCH] Fix split-irqchip vs interrupt injection window request David Woodhouse
2020-11-26 17:59 ` Paolo Bonzini
2020-11-26 21:48 ` David Woodhouse
2020-11-27 4:37 ` Paolo Bonzini
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=e71a7296-810a-cb73-8d34-cd96391750eb@redhat.com \
--to=pbonzini@redhat.com \
--cc=dwmw2@infradead.org \
--cc=gingell@google.com \
--cc=karahmed@amazon.de \
--cc=kvm@vger.kernel.org \
--cc=liran@amazon.com \
--cc=seanjc@google.com \
--cc=sironi@amazon.de \
--cc=srutherford@google.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.