1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-18 10:35:55 +00:00

Drop the icu_lock spinlock while pausing briefly after masking the

interrupt in the I/O APIC before moving it to a different CPU.  If the
interrupt had been triggered by the I/O APIC after locking icu_lock but
before we masked the pin in the I/O APIC, then this could cause the
interrupt to be pending on the "old" CPU and it would finally trigger
after we had moved the interrupt to the new CPU.  This could cause us to
panic as there was no interrupt source associated with the old IDT vector
on the old CPU.  Dropping the lock after the interrupt is masked but
before it is moved allows the interrupt to fire and be handled in this
case before it is moved.

Tested by:	Daniel Braniss  danny of cs huji ac il
MFC after:	1 week
This commit is contained in:
John Baldwin 2010-12-23 15:17:28 +00:00
parent 1c45127bd3
commit e1070bf509
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=216679

View File

@ -359,7 +359,9 @@ ioapic_assign_cpu(struct intsrc *isrc, u_int apic_id)
if (!intpin->io_masked && !intpin->io_edgetrigger) { if (!intpin->io_masked && !intpin->io_edgetrigger) {
ioapic_write(io->io_addr, IOAPIC_REDTBL_LO(intpin->io_intpin), ioapic_write(io->io_addr, IOAPIC_REDTBL_LO(intpin->io_intpin),
intpin->io_lowreg | IOART_INTMSET); intpin->io_lowreg | IOART_INTMSET);
mtx_unlock_spin(&icu_lock);
DELAY(100); DELAY(100);
mtx_lock_spin(&icu_lock);
} }
intpin->io_cpu = apic_id; intpin->io_cpu = apic_id;