* [PATCH 0/3] Reset PIT reinjection logic on irq unmask
@ 2009-01-04 16:14 Avi Kivity
2009-01-04 16:14 ` [PATCH 1/3] KVM: Add CONFIG_HAVE_KVM_IRQCHIP Avi Kivity
` (2 more replies)
0 siblings, 3 replies; 13+ messages in thread
From: Avi Kivity @ 2009-01-04 16:14 UTC (permalink / raw)
To: Sheng Yang, Marcelo Tosatti; +Cc: kvm
Currently, when a guest has the pit running but masked, it will accumulate
pending irq injection requests but will never ack them (as the interrupts
are masked). When the interrupt is finally unmasked, the reinject logic
ignores pending interrupts since it sees unacked pending irqs.
Add a notifier on irq unmasking, and use that in the PIT to clear the
reinject logic.
Currently only ioapic mask notifications are implemented.
This could be used to disable the hrtimer if the guest masks the PIT and
uses some other timer.
Please review.
Avi Kivity (3):
KVM: Add CONFIG_HAVE_KVM_IRQCHIP
KVM: Interrupt mask notifiers for ioapic
KVM: Reset PIT irq injection logic when the PIT IRQ is unmasked
arch/ia64/kvm/Kconfig | 4 ++++
arch/powerpc/kvm/Kconfig | 3 +++
arch/s390/kvm/Kconfig | 3 +++
arch/x86/kvm/Kconfig | 4 ++++
arch/x86/kvm/i8254.c | 15 +++++++++++++++
arch/x86/kvm/i8254.h | 1 +
include/linux/kvm_host.h | 17 +++++++++++++++++
virt/kvm/ioapic.c | 7 ++++++-
virt/kvm/irq_comm.c | 24 ++++++++++++++++++++++++
virt/kvm/kvm_main.c | 3 +++
10 files changed, 80 insertions(+), 1 deletions(-)
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH 1/3] KVM: Add CONFIG_HAVE_KVM_IRQCHIP 2009-01-04 16:14 [PATCH 0/3] Reset PIT reinjection logic on irq unmask Avi Kivity @ 2009-01-04 16:14 ` Avi Kivity 2009-01-04 16:14 ` [PATCH 2/3] KVM: Interrupt mask notifiers for ioapic Avi Kivity 2009-01-04 16:14 ` [PATCH 3/3] KVM: Reset PIT irq injection logic when the PIT IRQ is unmasked Avi Kivity 2 siblings, 0 replies; 13+ messages in thread From: Avi Kivity @ 2009-01-04 16:14 UTC (permalink / raw) To: Sheng Yang, Marcelo Tosatti; +Cc: kvm Two KVM archs support irqchips and two don't. Add a Kconfig item to make selecting between the two models easier. Signed-off-by: Avi Kivity <avi@redhat.com> --- arch/ia64/kvm/Kconfig | 4 ++++ arch/powerpc/kvm/Kconfig | 3 +++ arch/s390/kvm/Kconfig | 3 +++ arch/x86/kvm/Kconfig | 4 ++++ 4 files changed, 14 insertions(+), 0 deletions(-) diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig index f833a0b..0a2d6b8 100644 --- a/arch/ia64/kvm/Kconfig +++ b/arch/ia64/kvm/Kconfig @@ -4,6 +4,10 @@ config HAVE_KVM bool +config HAVE_KVM_IRQCHIP + bool + default y + menuconfig VIRTUALIZATION bool "Virtualization" depends on HAVE_KVM || IA64 diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig index 1465705..5a152a5 100644 --- a/arch/powerpc/kvm/Kconfig +++ b/arch/powerpc/kvm/Kconfig @@ -2,6 +2,9 @@ # KVM configuration # +config HAVE_KVM_IRQCHIP + bool + menuconfig VIRTUALIZATION bool "Virtualization" ---help--- diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig index e051cad..3e260b7 100644 --- a/arch/s390/kvm/Kconfig +++ b/arch/s390/kvm/Kconfig @@ -4,6 +4,9 @@ config HAVE_KVM bool +config HAVE_KVM_IRQCHIP + bool + menuconfig VIRTUALIZATION bool "Virtualization" default y diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig index b81125f..0a303c3 100644 --- a/arch/x86/kvm/Kconfig +++ b/arch/x86/kvm/Kconfig @@ -4,6 +4,10 @@ config HAVE_KVM bool +config HAVE_KVM_IRQCHIP + bool + default y + menuconfig VIRTUALIZATION bool "Virtualization" depends on HAVE_KVM || X86 -- 1.6.0.6 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 2/3] KVM: Interrupt mask notifiers for ioapic 2009-01-04 16:14 [PATCH 0/3] Reset PIT reinjection logic on irq unmask Avi Kivity 2009-01-04 16:14 ` [PATCH 1/3] KVM: Add CONFIG_HAVE_KVM_IRQCHIP Avi Kivity @ 2009-01-04 16:14 ` Avi Kivity 2009-01-05 7:06 ` Sheng Yang 2009-01-05 18:29 ` Marcelo Tosatti 2009-01-04 16:14 ` [PATCH 3/3] KVM: Reset PIT irq injection logic when the PIT IRQ is unmasked Avi Kivity 2 siblings, 2 replies; 13+ messages in thread From: Avi Kivity @ 2009-01-04 16:14 UTC (permalink / raw) To: Sheng Yang, Marcelo Tosatti; +Cc: kvm Allow clients to request notifications when the guest masks or unmasks a particular irq line. This complements irq ack notifications, as the guest will not ack an irq line that is masked. Currently implemented for the ioapic only. Signed-off-by: Avi Kivity <avi@redhat.com> --- include/linux/kvm_host.h | 17 +++++++++++++++++ virt/kvm/ioapic.c | 7 ++++++- virt/kvm/irq_comm.c | 24 ++++++++++++++++++++++++ virt/kvm/kvm_main.c | 3 +++ 4 files changed, 50 insertions(+), 1 deletions(-) diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 545a133..43385fa 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -127,6 +127,10 @@ struct kvm { struct kvm_coalesced_mmio_ring *coalesced_mmio_ring; #endif +#ifdef CONFIG_HAVE_KVM_IRQCHIP + struct hlist_head mask_notifier_list; +#endif + #ifdef KVM_ARCH_WANT_MMU_NOTIFIER struct mmu_notifier mmu_notifier; unsigned long mmu_notifier_seq; @@ -320,6 +324,19 @@ struct kvm_assigned_dev_kernel { struct pci_dev *dev; struct kvm *kvm; }; + +struct kvm_irq_mask_notifier { + void (*func)(struct kvm_irq_mask_notifier *kimn, int masked); + int irq; + struct hlist_node link; +}; + +void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq, + struct kvm_irq_mask_notifier *kimn); +void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq, + struct kvm_irq_mask_notifier *kimn); +void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, int mask); + void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level); void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi); void kvm_register_irq_ack_notifier(struct kvm *kvm, diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index 23b81cf..15b9ddd 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c @@ -100,7 +100,7 @@ static void ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx) static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) { - unsigned index; + unsigned index, mask_before, mask_after; switch (ioapic->ioregsel) { case IOAPIC_REG_VERSION: @@ -120,6 +120,7 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) ioapic_debug("change redir index %x val %x\n", index, val); if (index >= IOAPIC_NUM_PINS) return; + mask_before = ioapic->redirtbl[index].fields.mask; if (ioapic->ioregsel & 1) { ioapic->redirtbl[index].bits &= 0xffffffff; ioapic->redirtbl[index].bits |= (u64) val << 32; @@ -128,6 +129,9 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) ioapic->redirtbl[index].bits |= (u32) val; ioapic->redirtbl[index].fields.remote_irr = 0; } + mask_after = ioapic->redirtbl[index].fields.mask; + if (mask_before != mask_after) + kvm_fire_mask_notifiers(ioapic->kvm, index, mask_after); if (ioapic->irr & (1 << index)) ioapic_service(ioapic, index); break; @@ -426,3 +430,4 @@ int kvm_ioapic_init(struct kvm *kvm) kvm_io_bus_register_dev(&kvm->mmio_bus, &ioapic->dev); return 0; } + diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index aa5d1e5..2cbde68 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c @@ -99,3 +99,27 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id) clear_bit(irq_source_id, &kvm->arch.irq_states[i]); clear_bit(irq_source_id, &kvm->arch.irq_sources_bitmap); } + +void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq, + struct kvm_irq_mask_notifier *kimn) +{ + kimn->irq = irq; + hlist_add_head(&kimn->link, &kvm->mask_notifier_list); +} + +void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq, + struct kvm_irq_mask_notifier *kimn) +{ + hlist_del(&kimn->link); +} + +void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, int mask) +{ + struct kvm_irq_mask_notifier *kimn; + struct hlist_node *n; + + hlist_for_each_entry(kimn, n, &kvm->mask_notifier_list, link) + if (kimn->irq == irq) + kimn->func(kimn, mask); +} + diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 5703557..dcd58d6 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -806,6 +806,9 @@ static struct kvm *kvm_create_vm(void) if (IS_ERR(kvm)) goto out; +#ifdef CONFIG_HAVE_KVM_IRQCHIP + INIT_HLIST_HEAD(&kvm->mask_notifier_list); +#endif #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET page = alloc_page(GFP_KERNEL | __GFP_ZERO); -- 1.6.0.6 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] KVM: Interrupt mask notifiers for ioapic 2009-01-04 16:14 ` [PATCH 2/3] KVM: Interrupt mask notifiers for ioapic Avi Kivity @ 2009-01-05 7:06 ` Sheng Yang 2009-01-05 13:24 ` Avi Kivity 2009-01-05 18:29 ` Marcelo Tosatti 1 sibling, 1 reply; 13+ messages in thread From: Sheng Yang @ 2009-01-05 7:06 UTC (permalink / raw) To: Avi Kivity; +Cc: Marcelo Tosatti, kvm On Monday 05 January 2009 00:14:44 Avi Kivity wrote: > Allow clients to request notifications when the guest masks or unmasks a > particular irq line. This complements irq ack notifications, as the guest > will not ack an irq line that is masked. > > Currently implemented for the ioapic only. Hi Avi Need a lock for this list? Seems kvm_fire_mask_notifiers() implicit holding kvm->lock, but register/unregister didn't. And I think we need some comments for the necessary of lock. -- regards Yang, Sheng > > Signed-off-by: Avi Kivity <avi@redhat.com> > --- > include/linux/kvm_host.h | 17 +++++++++++++++++ > virt/kvm/ioapic.c | 7 ++++++- > virt/kvm/irq_comm.c | 24 ++++++++++++++++++++++++ > virt/kvm/kvm_main.c | 3 +++ > 4 files changed, 50 insertions(+), 1 deletions(-) > > diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h > index 545a133..43385fa 100644 > --- a/include/linux/kvm_host.h > +++ b/include/linux/kvm_host.h > @@ -127,6 +127,10 @@ struct kvm { > struct kvm_coalesced_mmio_ring *coalesced_mmio_ring; > #endif > > +#ifdef CONFIG_HAVE_KVM_IRQCHIP > + struct hlist_head mask_notifier_list; > +#endif > + > #ifdef KVM_ARCH_WANT_MMU_NOTIFIER > struct mmu_notifier mmu_notifier; > unsigned long mmu_notifier_seq; > @@ -320,6 +324,19 @@ struct kvm_assigned_dev_kernel { > struct pci_dev *dev; > struct kvm *kvm; > }; > + > +struct kvm_irq_mask_notifier { > + void (*func)(struct kvm_irq_mask_notifier *kimn, int masked); > + int irq; > + struct hlist_node link; > +}; > + > +void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq, > + struct kvm_irq_mask_notifier *kimn); > +void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq, > + struct kvm_irq_mask_notifier *kimn); > +void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, int mask); > + > void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level); > void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi); > void kvm_register_irq_ack_notifier(struct kvm *kvm, > diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c > index 23b81cf..15b9ddd 100644 > --- a/virt/kvm/ioapic.c > +++ b/virt/kvm/ioapic.c > @@ -100,7 +100,7 @@ static void ioapic_service(struct kvm_ioapic *ioapic, > unsigned int idx) > > static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) > { > - unsigned index; > + unsigned index, mask_before, mask_after; > > switch (ioapic->ioregsel) { > case IOAPIC_REG_VERSION: > @@ -120,6 +120,7 @@ static void ioapic_write_indirect(struct kvm_ioapic > *ioapic, u32 val) ioapic_debug("change redir index %x val %x\n", index, > val); > if (index >= IOAPIC_NUM_PINS) > return; > + mask_before = ioapic->redirtbl[index].fields.mask; > if (ioapic->ioregsel & 1) { > ioapic->redirtbl[index].bits &= 0xffffffff; > ioapic->redirtbl[index].bits |= (u64) val << 32; > @@ -128,6 +129,9 @@ static void ioapic_write_indirect(struct kvm_ioapic > *ioapic, u32 val) ioapic->redirtbl[index].bits |= (u32) val; > ioapic->redirtbl[index].fields.remote_irr = 0; > } > + mask_after = ioapic->redirtbl[index].fields.mask; > + if (mask_before != mask_after) > + kvm_fire_mask_notifiers(ioapic->kvm, index, mask_after); > if (ioapic->irr & (1 << index)) > ioapic_service(ioapic, index); > break; > @@ -426,3 +430,4 @@ int kvm_ioapic_init(struct kvm *kvm) > kvm_io_bus_register_dev(&kvm->mmio_bus, &ioapic->dev); > return 0; > } > + > diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c > index aa5d1e5..2cbde68 100644 > --- a/virt/kvm/irq_comm.c > +++ b/virt/kvm/irq_comm.c > @@ -99,3 +99,27 @@ void kvm_free_irq_source_id(struct kvm *kvm, int > irq_source_id) clear_bit(irq_source_id, &kvm->arch.irq_states[i]); > clear_bit(irq_source_id, &kvm->arch.irq_sources_bitmap); > } > + > +void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq, > + struct kvm_irq_mask_notifier *kimn) > +{ > + kimn->irq = irq; > + hlist_add_head(&kimn->link, &kvm->mask_notifier_list); > +} > + > +void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq, > + struct kvm_irq_mask_notifier *kimn) > +{ > + hlist_del(&kimn->link); > +} > + > +void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, int mask) > +{ > + struct kvm_irq_mask_notifier *kimn; > + struct hlist_node *n; > + > + hlist_for_each_entry(kimn, n, &kvm->mask_notifier_list, link) > + if (kimn->irq == irq) > + kimn->func(kimn, mask); > +} > + > diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c > index 5703557..dcd58d6 100644 > --- a/virt/kvm/kvm_main.c > +++ b/virt/kvm/kvm_main.c > @@ -806,6 +806,9 @@ static struct kvm *kvm_create_vm(void) > > if (IS_ERR(kvm)) > goto out; > +#ifdef CONFIG_HAVE_KVM_IRQCHIP > + INIT_HLIST_HEAD(&kvm->mask_notifier_list); > +#endif > > #ifdef KVM_COALESCED_MMIO_PAGE_OFFSET > page = alloc_page(GFP_KERNEL | __GFP_ZERO); ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] KVM: Interrupt mask notifiers for ioapic 2009-01-05 7:06 ` Sheng Yang @ 2009-01-05 13:24 ` Avi Kivity 0 siblings, 0 replies; 13+ messages in thread From: Avi Kivity @ 2009-01-05 13:24 UTC (permalink / raw) To: Sheng Yang; +Cc: Marcelo Tosatti, kvm Sheng Yang wrote: > On Monday 05 January 2009 00:14:44 Avi Kivity wrote: > >> Allow clients to request notifications when the guest masks or unmasks a >> particular irq line. This complements irq ack notifications, as the guest >> will not ack an irq line that is masked. >> >> Currently implemented for the ioapic only. >> > > Hi Avi > > Need a lock for this list? Seems kvm_fire_mask_notifiers() implicit holding > kvm->lock, but register/unregister didn't. And I think we need some comments > for the necessary of lock. > Good catch. Everything in struct kvm is protected by kvm->lock (except vcpus and the mmu... need a locking document). I added locking around PIT creation so now registration is also protected (it also fixes a potential leak if two threads try to create a PIT simultaneously). -- error compiling committee.c: too many arguments to function ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] KVM: Interrupt mask notifiers for ioapic 2009-01-04 16:14 ` [PATCH 2/3] KVM: Interrupt mask notifiers for ioapic Avi Kivity 2009-01-05 7:06 ` Sheng Yang @ 2009-01-05 18:29 ` Marcelo Tosatti 2009-01-05 20:57 ` Avi Kivity 1 sibling, 1 reply; 13+ messages in thread From: Marcelo Tosatti @ 2009-01-05 18:29 UTC (permalink / raw) To: Avi Kivity; +Cc: Sheng Yang, kvm On Sun, Jan 04, 2009 at 06:14:44PM +0200, Avi Kivity wrote: > Allow clients to request notifications when the guest masks or unmasks a > particular irq line. This complements irq ack notifications, as the guest > will not ack an irq line that is masked. > > Currently implemented for the ioapic only. > > Signed-off-by: Avi Kivity <avi@redhat.com> > --- > include/linux/kvm_host.h | 17 +++++++++++++++++ > virt/kvm/ioapic.c | 7 ++++++- > virt/kvm/irq_comm.c | 24 ++++++++++++++++++++++++ > virt/kvm/kvm_main.c | 3 +++ > 4 files changed, 50 insertions(+), 1 deletions(-) > > diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h > index 545a133..43385fa 100644 > --- a/include/linux/kvm_host.h > +++ b/include/linux/kvm_host.h > @@ -127,6 +127,10 @@ struct kvm { > struct kvm_coalesced_mmio_ring *coalesced_mmio_ring; > #endif > > +#ifdef CONFIG_HAVE_KVM_IRQCHIP > + struct hlist_head mask_notifier_list; > +#endif > + > #ifdef KVM_ARCH_WANT_MMU_NOTIFIER > struct mmu_notifier mmu_notifier; > unsigned long mmu_notifier_seq; > @@ -320,6 +324,19 @@ struct kvm_assigned_dev_kernel { > struct pci_dev *dev; > struct kvm *kvm; > }; > + > +struct kvm_irq_mask_notifier { > + void (*func)(struct kvm_irq_mask_notifier *kimn, int masked); bool masked? > + int irq; > + struct hlist_node link; > +}; > + > +void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq, > + struct kvm_irq_mask_notifier *kimn); > +void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq, > + struct kvm_irq_mask_notifier *kimn); > +void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, int mask); > + > void kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level); > void kvm_notify_acked_irq(struct kvm *kvm, unsigned gsi); > void kvm_register_irq_ack_notifier(struct kvm *kvm, > diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c > index 23b81cf..15b9ddd 100644 > --- a/virt/kvm/ioapic.c > +++ b/virt/kvm/ioapic.c > @@ -100,7 +100,7 @@ static void ioapic_service(struct kvm_ioapic *ioapic, unsigned int idx) > > static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) > { > - unsigned index; > + unsigned index, mask_before, mask_after; > > switch (ioapic->ioregsel) { > case IOAPIC_REG_VERSION: > @@ -120,6 +120,7 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) > ioapic_debug("change redir index %x val %x\n", index, val); > if (index >= IOAPIC_NUM_PINS) > return; > + mask_before = ioapic->redirtbl[index].fields.mask; > if (ioapic->ioregsel & 1) { > ioapic->redirtbl[index].bits &= 0xffffffff; > ioapic->redirtbl[index].bits |= (u64) val << 32; > @@ -128,6 +129,9 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) > ioapic->redirtbl[index].bits |= (u32) val; > ioapic->redirtbl[index].fields.remote_irr = 0; > } > + mask_after = ioapic->redirtbl[index].fields.mask; > + if (mask_before != mask_after) > + kvm_fire_mask_notifiers(ioapic->kvm, index, mask_after); This can generate "spurious acks", for example: - inject irq - guest masks, mask notifier cleans internal state to "acked". - guest writes EOI But I suppose thats fine, since PIT (for example) is getting spurious acks even without mask notifiers and so has to handle them. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/3] KVM: Interrupt mask notifiers for ioapic 2009-01-05 18:29 ` Marcelo Tosatti @ 2009-01-05 20:57 ` Avi Kivity 0 siblings, 0 replies; 13+ messages in thread From: Avi Kivity @ 2009-01-05 20:57 UTC (permalink / raw) To: Marcelo Tosatti; +Cc: Sheng Yang, kvm Marcelo Tosatti wrote: > On Sun, Jan 04, 2009 at 06:14:44PM +0200, Avi Kivity wrote: > >> Allow clients to request notifications when the guest masks or unmasks a >> particular irq line. This complements irq ack notifications, as the guest >> will not ack an irq line that is masked. >> >> Currently implemented for the ioapic only. >> + >> +struct kvm_irq_mask_notifier { >> + void (*func)(struct kvm_irq_mask_notifier *kimn, int masked); >> > > bool masked? > > Hey, I'm the bool fanatic! >> @@ -128,6 +129,9 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) >> ioapic->redirtbl[index].bits |= (u32) val; >> ioapic->redirtbl[index].fields.remote_irr = 0; >> } >> + mask_after = ioapic->redirtbl[index].fields.mask; >> + if (mask_before != mask_after) >> + kvm_fire_mask_notifiers(ioapic->kvm, index, mask_after); >> > > This can generate "spurious acks", for example: > > - inject irq > - guest masks, mask notifier cleans internal state to "acked". > - guest writes EOI > > But I suppose thats fine, since PIT (for example) is getting spurious > acks even without mask notifiers and so has to handle them. > If the mask happened for a long time then the guest would expect not to receive those interrupts. If it happened due to scheduling then we need to reinject them. I suppose we could measure descheduled time and correct appropriately. There previously existed logic that limited the pending count to some value (10?) so there wouldn't be a stream of interrupts injected into the guest endlessly. I expect in most cases, masking of the timer interrupt would not happen for short periods. You'd use eflags.if or apic.tpr to mask for short periods. -- I have a truly marvellous patch that fixes the bug which this signature is too narrow to contain. ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 3/3] KVM: Reset PIT irq injection logic when the PIT IRQ is unmasked 2009-01-04 16:14 [PATCH 0/3] Reset PIT reinjection logic on irq unmask Avi Kivity 2009-01-04 16:14 ` [PATCH 1/3] KVM: Add CONFIG_HAVE_KVM_IRQCHIP Avi Kivity 2009-01-04 16:14 ` [PATCH 2/3] KVM: Interrupt mask notifiers for ioapic Avi Kivity @ 2009-01-04 16:14 ` Avi Kivity 2009-01-05 18:31 ` Marcelo Tosatti 2 siblings, 1 reply; 13+ messages in thread From: Avi Kivity @ 2009-01-04 16:14 UTC (permalink / raw) To: Sheng Yang, Marcelo Tosatti; +Cc: kvm While the PIT is masked the guest cannot ack the irq, so the reinject logic will never allow the interrupt to be injected. Fix by resetting the reinjection counters on unmask. Unbreaks Xen. Signed-off-by: Avi Kivity <avi@redhat.com> --- arch/x86/kvm/i8254.c | 15 +++++++++++++++ arch/x86/kvm/i8254.h | 1 + 2 files changed, 16 insertions(+), 0 deletions(-) diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c index 528daad..d78d430 100644 --- a/arch/x86/kvm/i8254.c +++ b/arch/x86/kvm/i8254.c @@ -539,6 +539,16 @@ void kvm_pit_reset(struct kvm_pit *pit) pit->pit_state.irq_ack = 1; } +static void pit_mask_notifer(struct kvm_irq_mask_notifier *kimn, int mask) +{ + struct kvm_pit *pit = container_of(kimn, struct kvm_pit, mask_notifier); + + if (!mask) { + atomic_set(&pit->pit_state.pit_timer.pending, 0); + pit->pit_state.irq_ack = 1; + } +} + struct kvm_pit *kvm_create_pit(struct kvm *kvm) { struct kvm_pit *pit; @@ -588,6 +598,9 @@ struct kvm_pit *kvm_create_pit(struct kvm *kvm) kvm_pit_reset(pit); + pit->mask_notifier.func = pit_mask_notifer; + kvm_register_irq_mask_notifier(kvm, 0, &pit->mask_notifier); + return pit; } @@ -596,6 +609,8 @@ void kvm_free_pit(struct kvm *kvm) struct hrtimer *timer; if (kvm->arch.vpit) { + kvm_unregister_irq_mask_notifier(kvm, 0, + &kvm->arch.vpit->mask_notifier); mutex_lock(&kvm->arch.vpit->pit_state.lock); timer = &kvm->arch.vpit->pit_state.pit_timer.timer; hrtimer_cancel(timer); diff --git a/arch/x86/kvm/i8254.h b/arch/x86/kvm/i8254.h index 76959c4..6acbe4b 100644 --- a/arch/x86/kvm/i8254.h +++ b/arch/x86/kvm/i8254.h @@ -46,6 +46,7 @@ struct kvm_pit { struct kvm *kvm; struct kvm_kpit_state pit_state; int irq_source_id; + struct kvm_irq_mask_notifier mask_notifier; }; #define KVM_PIT_BASE_ADDRESS 0x40 -- 1.6.0.6 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 3/3] KVM: Reset PIT irq injection logic when the PIT IRQ is unmasked 2009-01-04 16:14 ` [PATCH 3/3] KVM: Reset PIT irq injection logic when the PIT IRQ is unmasked Avi Kivity @ 2009-01-05 18:31 ` Marcelo Tosatti 2009-01-05 20:59 ` Avi Kivity 0 siblings, 1 reply; 13+ messages in thread From: Marcelo Tosatti @ 2009-01-05 18:31 UTC (permalink / raw) To: Avi Kivity; +Cc: Sheng Yang, kvm On Sun, Jan 04, 2009 at 06:14:45PM +0200, Avi Kivity wrote: > While the PIT is masked the guest cannot ack the irq, so the reinject logic > will never allow the interrupt to be injected. > > Fix by resetting the reinjection counters on unmask. > > Unbreaks Xen. > > Signed-off-by: Avi Kivity <avi@redhat.com> > --- > arch/x86/kvm/i8254.c | 15 +++++++++++++++ > arch/x86/kvm/i8254.h | 1 + > 2 files changed, 16 insertions(+), 0 deletions(-) > > diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c > index 528daad..d78d430 100644 > --- a/arch/x86/kvm/i8254.c > +++ b/arch/x86/kvm/i8254.c > @@ -539,6 +539,16 @@ void kvm_pit_reset(struct kvm_pit *pit) > pit->pit_state.irq_ack = 1; > } > > +static void pit_mask_notifer(struct kvm_irq_mask_notifier *kimn, int mask) > +{ > + struct kvm_pit *pit = container_of(kimn, struct kvm_pit, mask_notifier); > + > + if (!mask) { > + atomic_set(&pit->pit_state.pit_timer.pending, 0); > + pit->pit_state.irq_ack = 1; > + } > +} I'm not sure about zeroing the counter here. The guest can mask the interrupt during normal operation, and in such cases you want the pending count to be retained (and reinjected later). I suppose setting irq_ack to one is enough. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 3/3] KVM: Reset PIT irq injection logic when the PIT IRQ is unmasked 2009-01-05 18:31 ` Marcelo Tosatti @ 2009-01-05 20:59 ` Avi Kivity 2009-01-05 21:58 ` Marcelo Tosatti 0 siblings, 1 reply; 13+ messages in thread From: Avi Kivity @ 2009-01-05 20:59 UTC (permalink / raw) To: Marcelo Tosatti; +Cc: Sheng Yang, kvm Marcelo Tosatti wrote: > On Sun, Jan 04, 2009 at 06:14:45PM +0200, Avi Kivity wrote: > >> While the PIT is masked the guest cannot ack the irq, so the reinject logic >> will never allow the interrupt to be injected. >> >> Fix by resetting the reinjection counters on unmask. >> >> Unbreaks Xen. >> >> diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c >> index 528daad..d78d430 100644 >> --- a/arch/x86/kvm/i8254.c >> +++ b/arch/x86/kvm/i8254.c >> @@ -539,6 +539,16 @@ void kvm_pit_reset(struct kvm_pit *pit) >> pit->pit_state.irq_ack = 1; >> } >> >> +static void pit_mask_notifer(struct kvm_irq_mask_notifier *kimn, int mask) >> +{ >> + struct kvm_pit *pit = container_of(kimn, struct kvm_pit, mask_notifier); >> + >> + if (!mask) { >> + atomic_set(&pit->pit_state.pit_timer.pending, 0); >> + pit->pit_state.irq_ack = 1; >> + } >> +} >> > > I'm not sure about zeroing the counter here. The guest can mask the > interrupt during normal operation, and in such cases you want the > pending count to be retained (and reinjected later). > > I suppose setting irq_ack to one is enough. > I'm worried about: - boot guest using local apic timer - reset - boot with pit timer - a zillion interrupts So at the very least, we need a limiter. -- I have a truly marvellous patch that fixes the bug which this signature is too narrow to contain. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 3/3] KVM: Reset PIT irq injection logic when the PIT IRQ is unmasked 2009-01-05 20:59 ` Avi Kivity @ 2009-01-05 21:58 ` Marcelo Tosatti 2009-01-06 8:25 ` Avi Kivity 0 siblings, 1 reply; 13+ messages in thread From: Marcelo Tosatti @ 2009-01-05 21:58 UTC (permalink / raw) To: Avi Kivity; +Cc: Sheng Yang, kvm On Mon, Jan 05, 2009 at 10:59:01PM +0200, Avi Kivity wrote: > Marcelo Tosatti wrote: >> On Sun, Jan 04, 2009 at 06:14:45PM +0200, Avi Kivity wrote: >> >>> While the PIT is masked the guest cannot ack the irq, so the reinject logic >>> will never allow the interrupt to be injected. >>> >>> Fix by resetting the reinjection counters on unmask. >>> >>> Unbreaks Xen. >>> >>> diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c >>> index 528daad..d78d430 100644 >>> --- a/arch/x86/kvm/i8254.c >>> +++ b/arch/x86/kvm/i8254.c >>> @@ -539,6 +539,16 @@ void kvm_pit_reset(struct kvm_pit *pit) >>> pit->pit_state.irq_ack = 1; >>> } >>> +static void pit_mask_notifer(struct kvm_irq_mask_notifier *kimn, >>> int mask) >>> +{ >>> + struct kvm_pit *pit = container_of(kimn, struct kvm_pit, mask_notifier); >>> + >>> + if (!mask) { >>> + atomic_set(&pit->pit_state.pit_timer.pending, 0); >>> + pit->pit_state.irq_ack = 1; >>> + } >>> +} >>> >> >> I'm not sure about zeroing the counter here. The guest can mask the >> interrupt during normal operation, and in such cases you want the >> pending count to be retained (and reinjected later). >> >> I suppose setting irq_ack to one is enough. >> > > I'm worried about: > > - boot guest using local apic timer > - reset > - boot with pit timer > - a zillion interrupts > > So at the very least, we need a limiter. Or have a new notifier on kvm_pic_reset, instead of simply acking one pending irq? That seems the appropriate place to zero the counter. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 3/3] KVM: Reset PIT irq injection logic when the PIT IRQ is unmasked 2009-01-05 21:58 ` Marcelo Tosatti @ 2009-01-06 8:25 ` Avi Kivity 2009-01-06 9:35 ` Dor Laor 0 siblings, 1 reply; 13+ messages in thread From: Avi Kivity @ 2009-01-06 8:25 UTC (permalink / raw) To: Marcelo Tosatti; +Cc: Sheng Yang, kvm Marcelo Tosatti wrote: >> >> I'm worried about: >> >> - boot guest using local apic timer >> - reset >> - boot with pit timer >> - a zillion interrupts >> >> So at the very least, we need a limiter. >> > > Or have a new notifier on kvm_pic_reset, instead of simply acking one > pending irq? That seems the appropriate place to zero the counter. > Clearing the counter on reset is good, but it doesn't solve the underlying problem, which is that there are two separate cases that appear to the host as the same thing: - guest masks irqs, does a lot of work, unmasks irqs - host deschedules guest, does a lot of work, reschedules guest Right now we assume any missed interrupts are due to host load. In the reboot case, that's clearly wrong, but that is only an example. Maybe we can use preempt notifiers to detect whether the timer tick happened while the guest was scheduled or not. -- I have a truly marvellous patch that fixes the bug which this signature is too narrow to contain. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 3/3] KVM: Reset PIT irq injection logic when the PIT IRQ is unmasked 2009-01-06 8:25 ` Avi Kivity @ 2009-01-06 9:35 ` Dor Laor 0 siblings, 0 replies; 13+ messages in thread From: Dor Laor @ 2009-01-06 9:35 UTC (permalink / raw) To: Avi Kivity; +Cc: Marcelo Tosatti, Sheng Yang, kvm Avi Kivity wrote: > Marcelo Tosatti wrote: >>> >>> I'm worried about: >>> >>> - boot guest using local apic timer >>> - reset >>> - boot with pit timer >>> - a zillion interrupts >>> >>> So at the very least, we need a limiter. >>> >> >> Or have a new notifier on kvm_pic_reset, instead of simply acking one >> pending irq? That seems the appropriate place to zero the counter. >> > > Clearing the counter on reset is good, but it doesn't solve the > underlying problem, which is that there are two separate cases that > appear to the host as the same thing: > > - guest masks irqs, does a lot of work, unmasks irqs > - host deschedules guest, does a lot of work, reschedules guest > > Right now we assume any missed interrupts are due to host load. In > the reboot case, that's clearly wrong, but that is only an example. > Maybe we can use preempt notifiers to detect whether the timer tick > happened while the guest was scheduled or not. > It might get too complex. It can be done inside the vcpu_run function too: An irq needs reinjection if the irq window was not open from the timer tick till the next timer tick minus the deschedule time. You also need to know on the right vcpu that the pit irq it routed to. Since scenarios like guests masking their pit and do a lot of work are rare and a bad guest behaviour anyway, I don't think we should special case them. So the pit reset hook is enough. ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2009-01-06 9:34 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-01-04 16:14 [PATCH 0/3] Reset PIT reinjection logic on irq unmask Avi Kivity 2009-01-04 16:14 ` [PATCH 1/3] KVM: Add CONFIG_HAVE_KVM_IRQCHIP Avi Kivity 2009-01-04 16:14 ` [PATCH 2/3] KVM: Interrupt mask notifiers for ioapic Avi Kivity 2009-01-05 7:06 ` Sheng Yang 2009-01-05 13:24 ` Avi Kivity 2009-01-05 18:29 ` Marcelo Tosatti 2009-01-05 20:57 ` Avi Kivity 2009-01-04 16:14 ` [PATCH 3/3] KVM: Reset PIT irq injection logic when the PIT IRQ is unmasked Avi Kivity 2009-01-05 18:31 ` Marcelo Tosatti 2009-01-05 20:59 ` Avi Kivity 2009-01-05 21:58 ` Marcelo Tosatti 2009-01-06 8:25 ` Avi Kivity 2009-01-06 9:35 ` Dor Laor
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).