From: Peter Xu <peterx@redhat.com>
To: Ladi Prosek <lprosek@redhat.com>
Cc: kvm@vger.kernel.org, rkrcmar@redhat.com
Subject: Re: [PATCH] KVM: x86: implement IOAPIC_REG_EOI for directed EOI support
Date: Wed, 12 Apr 2017 14:40:29 +0800 [thread overview]
Message-ID: <20170412064029.GD16464@pxdev.xzpeter.org> (raw)
In-Reply-To: <20170411141115.4314-1-lprosek@redhat.com>
On Tue, Apr 11, 2017 at 04:11:15PM +0200, Ladi Prosek wrote:
> If the guest takes advantage of the directed EOI feature by setting
> APIC_SPIV_DIRECTED_EOI, it is expected to signal EOI by writing to
> the EOI register of the respective IOAPIC.
>
> From Intel's x2APIC Specification:
> "following the EOI to the local x2APIC unit for a level triggered
> interrupt, perform a directed EOI to the IOxAPIC generating the
> interrupt by writing to its EOI register."
>
> Commit fc61b800f950 ("KVM: Add Directed EOI support to APIC emulation")
> inhibited EOI on LAPIC EOI register write but didn't add the IOAPIC
> part. IOAPIC_REG_EOI writes were handled only on IA64 and the code
> was later removed with the rest of IA64 support.
>
> The bug has gone undetected for a long time because Linux writes to
> IOAPIC_REG_EOI only if the IOAPIC version is >=0x20. Windows doesn't
> seem to perform such a check.
Hi, Ladi,
Not sure I'm understanding it correctly... I see "direct EOI" is a
feature for IOAPIC version 0x20, while "suppress EOI-broadcast" is
another feature for APIC. They are not the same feature, so it may not
be required to have them all together. IIUC current x86 kvm is just
the case - it supports EOI broadcast suppression on APIC, but it does
not support direct EOI on kernel IOAPIC.
I think the problem is why the guest setup APIC_SPIV_DIRECTED_EOI even
if IOAPIC does not support direct EOI (the guest can know it by
probing IOAPIC version). Please correct if I'm wrong.
>
> This commit re-adds IOAPIC_REG_EOI and implements it in terms of
> __kvm_ioapic_update_eoi.
>
> Fixes: fc61b800f950 ("KVM: Add Directed EOI support to APIC emulation")
> Signed-off-by: Ladi Prosek <lprosek@redhat.com>
> ---
> arch/x86/kvm/ioapic.c | 46 ++++++++++++++++++++++++++++------------------
> arch/x86/kvm/ioapic.h | 1 +
> 2 files changed, 29 insertions(+), 18 deletions(-)
>
> diff --git a/arch/x86/kvm/ioapic.c b/arch/x86/kvm/ioapic.c
> index 289270a..8df1c6c 100644
> --- a/arch/x86/kvm/ioapic.c
> +++ b/arch/x86/kvm/ioapic.c
> @@ -415,14 +415,15 @@ static void kvm_ioapic_eoi_inject_work(struct work_struct *work)
> #define IOAPIC_SUCCESSIVE_IRQ_MAX_COUNT 10000
>
> static void __kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu,
> - struct kvm_ioapic *ioapic, int vector, int trigger_mode)
> + struct kvm_ioapic *ioapic, int vector, int trigger_mode,
> + bool directed)
> {
> struct dest_map *dest_map = &ioapic->rtc_status.dest_map;
> struct kvm_lapic *apic = vcpu->arch.apic;
> int i;
>
> /* RTC special handling */
> - if (test_bit(vcpu->vcpu_id, dest_map->map) &&
> + if (!directed && test_bit(vcpu->vcpu_id, dest_map->map) &&
> vector == dest_map->vectors[vcpu->vcpu_id])
> rtc_irq_eoi(ioapic, vcpu);
>
> @@ -432,21 +433,23 @@ static void __kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu,
> if (ent->fields.vector != vector)
> continue;
>
> - /*
> - * We are dropping lock while calling ack notifiers because ack
> - * notifier callbacks for assigned devices call into IOAPIC
> - * recursively. Since remote_irr is cleared only after call
> - * to notifiers if the same vector will be delivered while lock
> - * is dropped it will be put into irr and will be delivered
> - * after ack notifier returns.
> - */
> - spin_unlock(&ioapic->lock);
> - kvm_notify_acked_irq(ioapic->kvm, KVM_IRQCHIP_IOAPIC, i);
> - spin_lock(&ioapic->lock);
> -
> - if (trigger_mode != IOAPIC_LEVEL_TRIG ||
> - kvm_lapic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI)
> - continue;
> + if (!directed) {
Could I ask why we need to skip this if the EOI is sent via direct EOI
register of IOAPIC?
Thanks,
> + /*
> + * We are dropping lock while calling ack notifiers because ack
> + * notifier callbacks for assigned devices call into IOAPIC
> + * recursively. Since remote_irr is cleared only after call
> + * to notifiers if the same vector will be delivered while lock
> + * is dropped it will be put into irr and will be delivered
> + * after ack notifier returns.
> + */
> + spin_unlock(&ioapic->lock);
> + kvm_notify_acked_irq(ioapic->kvm, KVM_IRQCHIP_IOAPIC, i);
> + spin_lock(&ioapic->lock);
> +
> + if (trigger_mode != IOAPIC_LEVEL_TRIG ||
> + kvm_lapic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI)
> + continue;
> + }
>
> ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG);
> ent->fields.remote_irr = 0;
> @@ -478,7 +481,7 @@ void kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu, int vector, int trigger_mode)
> struct kvm_ioapic *ioapic = vcpu->kvm->arch.vioapic;
>
> spin_lock(&ioapic->lock);
> - __kvm_ioapic_update_eoi(vcpu, ioapic, vector, trigger_mode);
> + __kvm_ioapic_update_eoi(vcpu, ioapic, vector, trigger_mode, false);
> spin_unlock(&ioapic->lock);
> }
>
> @@ -540,6 +543,7 @@ static int ioapic_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
> gpa_t addr, int len, const void *val)
> {
> struct kvm_ioapic *ioapic = to_ioapic(this);
> + struct kvm_lapic *apic = vcpu->arch.apic;
> u32 data;
> if (!ioapic_in_range(ioapic, addr))
> return -EOPNOTSUPP;
> @@ -575,6 +579,12 @@ static int ioapic_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
> ioapic_write_indirect(ioapic, data);
> break;
>
> + case IOAPIC_REG_EOI:
> + if (kvm_lapic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI)
> + __kvm_ioapic_update_eoi(vcpu, ioapic, data,
> + IOAPIC_LEVEL_TRIG, true);
> + break;
> +
> default:
> break;
> }
> diff --git a/arch/x86/kvm/ioapic.h b/arch/x86/kvm/ioapic.h
> index 1cc6e54..251b61b 100644
> --- a/arch/x86/kvm/ioapic.h
> +++ b/arch/x86/kvm/ioapic.h
> @@ -20,6 +20,7 @@ struct kvm_vcpu;
> /* Direct registers. */
> #define IOAPIC_REG_SELECT 0x00
> #define IOAPIC_REG_WINDOW 0x10
> +#define IOAPIC_REG_EOI 0x40
>
> /* Indirect registers. */
> #define IOAPIC_REG_APIC_ID 0x00 /* x86 IOAPIC only */
> --
> 2.9.3
>
--
Peter Xu
next prev parent reply other threads:[~2017-04-12 6:40 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-04-11 14:11 [PATCH] KVM: x86: implement IOAPIC_REG_EOI for directed EOI support Ladi Prosek
2017-04-12 6:40 ` Peter Xu [this message]
2017-04-12 7:36 ` Ladi Prosek
2017-04-12 9:06 ` Peter Xu
2017-04-12 9:37 ` Ladi Prosek
2017-04-12 10:28 ` Ladi Prosek
2017-04-12 11:57 ` Peter Xu
2017-04-12 12:20 ` Ladi Prosek
2017-04-13 8:32 ` Peter Xu
2017-04-13 14:09 ` Radim Krcmar
2017-04-13 15:11 ` Ladi Prosek
2017-04-14 5:28 ` Paolo Bonzini
2017-04-12 20:52 ` Radim Krcmar
2017-04-13 6:36 ` Ladi Prosek
2017-04-13 14:15 ` Radim Krcmar
2017-04-14 5:27 ` 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=20170412064029.GD16464@pxdev.xzpeter.org \
--to=peterx@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=lprosek@redhat.com \
--cc=rkrcmar@redhat.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox