Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 30 Nov 2012 19:30:03 +0200
From:      Andriy Gapon <avg@FreeBSD.org>
To:        Andreas Longwitz <longwitz@incore.de>, John Baldwin <jhb@FreeBSD.org>
Cc:        freebsd-stable@FreeBSD.org
Subject:   Re: page fault on verbose boot
Message-ID:  <50B8ED1B.8080009@FreeBSD.org>
In-Reply-To: <50B8DD1C.4010308@incore.de>
References:  <50ABE8BC.1010904@incore.de> <50B8CD59.1050308@FreeBSD.org> <50B8DD1C.4010308@incore.de>

next in thread | previous in thread | raw e-mail | index | archive | help
on 30/11/2012 18:21 Andreas Longwitz said the following:
> ioapic1: routing intpin 15 (PCI IRQ 31) to lapic 0 vector 54
> kernel trap 12 with interrupts disabled
[snip]
> db> bt
> Tracing pid 0 tid 100000 td 0xc0a35350
> intr_execute_handlers(0,c1020cb4,3,c1020cf8,c08e4625,...) at
> intr_execute_handlers+0x15
> lapic_handle_intr(36,c1020cb4) at lapic_handle_intr+0x4c
> Xapic_isr1() at Xapic_isr1+0x35
> --- interrupt, eip = 0xc08ee8fb, esp = 0xc1020cf4, ebp = 0xc1020cf8 ---
> spinlock_exit(c09a1e2e,0,36,3,c1020d38,...) at spinlock_exit+0x2b
> ioapic_assign_cpu(c4d1565c,0,0,0,c08f3d29,...) at ioapic_assign_cpu+0x2b0
> intr_shuffle_irqs(0,101ec00,101ec00,101e000,1025000,...) at
> intr_shuffle_irqs+0xba
> mi_startup() at mi_startup+0xac
> begin() at begin+0x2c

Thank you for all the additional information, which proved to be very useful.
Something struck me now that I didn't realize before: your BSP has APIC ID of 3
while the other CPU has ID of zero.  So, lapic3 is the BSP's lapic and lapic0 is
the other one.
Hence, it looks like IRQ31 (a signal on pin 15 of ioapic1) was delivered to a new
vector of 54 (as opposed to vector 48) but to the old LAPIC/CPU 3 (as opposed to
newly configured lapic0).
So it looks like that the interrupt was handled at IO-APIC in the middle of pin
reconfiguration.

Looking at the code in ioapic_program_intpin() this seems to be possible indeed:

/* Write the values to the APIC. */
intpin->io_lowreg = low;
ioapic_write(io->io_addr, IOAPIC_REDTBL_LO(intpin->io_intpin), low);

The line above reprograms vector number AND _unmasks_ the pin (which was
specifically masked before reprogramming in ioapic_assign_cpu).
The lines below reprogram the destination LAPIC/CPU:

value = ioapic_read(io->io_addr, IOAPIC_REDTBL_HI(intpin->io_intpin));
value &= ~IOART_DEST;
value |= high;
ioapic_write(io->io_addr, IOAPIC_REDTBL_HI(intpin->io_intpin), value);

So a pending interrupt would be happily delivered to a wrong destination (new
vector + old lapic).

I am not sure if just swapping these two blocks of lines would fix the issue, but
I hope that it would.  Could you please try that?

John, what do you think (if you've got a spare minute)?

Thank you very much.

P.S. I am also quite unsure if it's a good idea for apic_idt_to_irq() to return
zero for a non-configured vector.  Perhaps, there should be an assert or some such
(at least in the context of lapic_handle_intr) ...

-- 
Andriy Gapon



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?50B8ED1B.8080009>