aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2005-04-14 05:55:34 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2005-04-14 05:55:34 +0000
commitc9ed75c153dac4dac249176cd33b43f2a0fed034 (patch)
tree8dfa5650ba976ae02db9b701b8c63ed6d016ff70
parent20984f2f04e9589f0dfb1e116e80eae090cae40f (diff)
downloadsrc-c9ed75c153dac4dac249176cd33b43f2a0fed034.tar.gz
src-c9ed75c153dac4dac249176cd33b43f2a0fed034.zip
If an I/O APIC returns 0xffffffff for its version register after we map it,
assume it is bogus and return NULL instead of trying to parse it as an APIC. Inspired by: linux bug reports via njl
Notes
Notes: svn path=/head/; revision=145054
-rw-r--r--sys/i386/i386/io_apic.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/sys/i386/i386/io_apic.c b/sys/i386/i386/io_apic.c
index a403eebc68a9..b6c9446a7439 100644
--- a/sys/i386/i386/io_apic.c
+++ b/sys/i386/i386/io_apic.c
@@ -502,11 +502,20 @@ ioapic_create(uintptr_t addr, int32_t apic_id, int intbase)
u_int numintr, i;
uint32_t value;
+ /* Map the register window so we can access the device. */
apic = (ioapic_t *)pmap_mapdev(addr, IOAPIC_MEM_REGION);
mtx_lock_spin(&icu_lock);
- numintr = ((ioapic_read(apic, IOAPIC_VER) & IOART_VER_MAXREDIR) >>
- MAXREDIRSHIFT) + 1;
+ value = ioapic_read(apic, IOAPIC_VER);
mtx_unlock_spin(&icu_lock);
+
+ /* If it's version register doesn't seem to work, punt. */
+ if (value == 0xffffff) {
+ pmap_unmapdev(apic, IOAPIC_MEM_REGION);
+ return (NULL);
+ }
+
+ /* Determine the number of vectors and set the APIC ID. */
+ numintr = ((value & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1;
io = malloc(sizeof(struct ioapic) +
numintr * sizeof(struct ioapic_intsrc), M_IOAPIC, M_WAITOK);
io->io_pic = ioapic_template;