[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: NetBSD dom0 PVH: hardware interrupts stalls
On Mon, Nov 23, 2020 at 12:32:41PM +0100, Manuel Bouyer wrote: > On Mon, Nov 23, 2020 at 10:57:13AM +0100, Roger Pau Monné wrote: > > > [...] > > > OK. > > > I finally found where the EOI occurs (it's within a macro so s simple grep > > > didn't show it). > > > > > > When interrupts are not masked (e.g. via cli), the ioapic halder is > > > called. > > > From here, 2 paths can happen: > > > a) the software interrupt priority level (called spl in BSD world) allows > > > the > > > driver's handler to run. In this case it's called, then the interrupt > > > is unmasked at ioapic level, and EOI'd at lapic. > > > b) the software interrupt priority level doesn't allow this driver's > > > handler to > > > run. In this case, the interrupt is marked as pending in software, > > > explicitely masked at the iopic level and EOI'd at lapic. > > > Later, when the spl is lowered, the driver's interrupt handler is run, > > > then the interrupt is unmasked at ioapic level, and EOI'd at lapic > > > (this is the same path as a)). here we may EOI the lapic twice, and the > > > second time when there's no hardware interrupt pending any more. > > > > > > I suspect it's case b) which causes the problem with Xen. > > > > Case b) should be handled fine AFAICT. If there's no interrupt pending > > in the lapic ISR the EOI is just a noop. Iff there's somehow another > > vector pending in ISR you might actually be EOIing the wrong vector, > > and thus this would be a bug in NetBSD. I certainly don't know much of > > NetBSD interrupt model in order to know whether this second EOI is just > > not necessary or whether it could cause issues. > > > > Can you actually assert that disabling this second unneeded EOI does > > solve the problem? > > I tried this, and it didn't change anything ... > > I'm out of idea to try. Hm, yes, it's quite weird. Do you know whether a NetBSD kernel can be multibooted from pxelinux with Xen? I would like to see if I can reproduce this myself. I have the following patch also which will print a warning message when GSI 34 is injected from hardware or when Xen performs an EOI (either from a time out or when reacting to a guest one). I would expect at least the interrupt injection one to trigger together with the existing message. Thanks, Roger. ---8<--- diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c index 67d4a6237f..bbd141a3d9 100644 --- a/xen/arch/x86/hvm/vioapic.c +++ b/xen/arch/x86/hvm/vioapic.c @@ -43,7 +43,12 @@ /* HACK: Route IRQ0 only to VCPU0 to prevent time jumps. */ #define IRQ0_SPECIAL_ROUTING 1 -static void vioapic_deliver(struct hvm_vioapic *vioapic, unsigned int irq); +static void _vioapic_deliver(struct hvm_vioapic *vioapic, unsigned int irq); + +bool __read_mostly irqprint; +#define vioapic_deliver(vioapic, irq) ({\ + WARN_ON(irqprint && vioapic->base_gsi + irq == 34); \ + _vioapic_deliver(vioapic, irq); }) static struct hvm_vioapic *addr_vioapic(const struct domain *d, unsigned long addr) @@ -119,6 +124,16 @@ static uint32_t vioapic_read_indirect(const struct hvm_vioapic *vioapic) if ( redir_index >= vioapic->nr_pins ) { + switch ( vioapic->ioregsel ) + { + case 3: + irqprint = true; + break; + + case 0xf: + irqprint = false; + break; + } gdprintk(XENLOG_WARNING, "apic_mem_readl:undefined ioregsel %x\n", vioapic->ioregsel); break; @@ -391,7 +406,7 @@ static void ioapic_inj_irq( vlapic_set_irq(target, vector, trig_mode); } -static void vioapic_deliver(struct hvm_vioapic *vioapic, unsigned int pin) +static void _vioapic_deliver(struct hvm_vioapic *vioapic, unsigned int pin) { uint16_t dest = vioapic->redirtbl[pin].fields.dest_id; uint8_t dest_mode = vioapic->redirtbl[pin].fields.dest_mode; diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c index 8d1f9a9fc6..91fb99d271 100644 --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -1388,10 +1388,12 @@ static void set_eoi_ready(void *data) flush_ready_eoi(); } +extern bool irqprint; void pirq_guest_eoi(struct pirq *pirq) { struct irq_desc *desc; + WARN_ON(irqprint && pirq->pirq == 34); ASSERT(local_irq_is_enabled()); desc = pirq_spin_lock_irq_desc(pirq, NULL); if ( desc ) @@ -1837,6 +1839,8 @@ static void do_IRQ_guest(struct irq_desc *desc, unsigned int vector) unsigned int i; struct pending_eoi *peoi = this_cpu(pending_eoi); + WARN_ON(irqprint && desc->irq == 34); + if ( unlikely(!action->nr_guests) ) { /* An interrupt may slip through while freeing an ACKTYPE_EOI irq. */
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |