Date: Wed, 16 Nov 2005 12:48:19 +0200 From: Nikos Ntarmos <ntarmos@ceid.upatras.gr> To: freebsd-hackers@freebsd.org Subject: Bogus ioapic entry Message-ID: <20051116104819.GA10128@diogenis.ceid.upatras.gr>
next in thread | raw e-mail | index | archive | help
--gatW/ieO32f1wygP Content-Type: multipart/mixed; boundary="LZvS9be/3tNcYl/X" Content-Disposition: inline --LZvS9be/3tNcYl/X Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi all. I spent a couple of hours last night trying to get ACPI to function correctly on my new Acer Aspire 1692WLMi. I found out that with apic enabled, the system hangs when returning from S3, while with apic disabled it suffers from interrupt storms on irq9 and the screen is not reinitialized on return from S3 (with hw.acpi.reset_video set to both "0" and "1"). While trying to hunt this thing down, I noticed that the GENERIC kernel of 6.0-STABLE (and probably of other branches as well) incorrectly discovers two ioapic devices: ioapic1: Changing APIC ID to 2 ioapic0 <Version 2.0> irqs 0-23 on motherboard ioapic1 <Version 15.15> irqs 24-23 on motherboard There is something obviously wrong with ioapic1. The cause seems to be the handling of value and numintr in ioapic_create(...). value is a uint32_t, while numintr is a u_int, both of which are 32-bits long (per <sys/types.h> and <machine/_types.h> at least on my i386). The code in ioapic_create(...), after the call to ioapic_read(apic, IOAPIC_VER), uses the latter's return value to compute the number of interrupts assigned to the current ioapic. This return value is checked against 0xffffff (that's 24 1-bits) to detect an error and bail out. This code chunk is also in -current (so perhaps I'm missing something here...) The (buggy?) BIOS implementation of my laptop returns a value of 0xffffffff (32 1-bits) in ioapic_read(...). This, however, doesn't trigger the current if-clause, so the code proceeds and creates ioapic1 with -1(!) assigned IRQs (due to the and-and-shift-plus-one formula of computing numintr). The attached diff fixes this situation and seems more correct to me than the current code, given that io_numintr is 8 bits and u_int is 32 bits per <cannot-remember> C standard. The problems with resuming from S3 still haunt me though. I guess I should have a look at acpi@ later today... Cheers. \n\n --LZvS9be/3tNcYl/X Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="io_apic.c.diff" Content-Transfer-Encoding: quoted-printable --- io_apic.c.orig Fri Aug 5 22:08:25 2005 +++ io_apic.c Wed Nov 16 12:26:47 2005 @@ -478,14 +478,21 @@ value =3D ioapic_read(apic, IOAPIC_VER); mtx_unlock_spin(&icu_lock); =20 - /* If it's version register doesn't seem to work, punt. */ - if (value =3D=3D 0xffffff) { + /* Determine the number of vectors and set the APIC ID. */ + numintr =3D ((value & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1; + + /* numintr is a uint32_t but io_numintr is only 8 bits long. On my + * Acer Aspire 1692WLMi, two ioapic's are discovered. However, the + * second one is bogus, since ioapic_read(apic, IOAPIC_VER) returns + * 0xffffffff, which doesn't trigger the old if-clause (value =3D=3D + * 0xffffff). Keeping around an ioapic with -1 assigned IRQs doesn't + * make much sense, so: + */ + if ((numintr & 0x000000ff) =3D=3D 0) { pmap_unmapdev((vm_offset_t)apic, IOAPIC_MEM_REGION); return (NULL); } =20 - /* Determine the number of vectors and set the APIC ID. */ - numintr =3D ((value & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1; io =3D malloc(sizeof(struct ioapic) + numintr * sizeof(struct ioapic_intsrc), M_IOAPIC, M_WAITOK); io->io_pic =3D ioapic_template; --LZvS9be/3tNcYl/X-- --gatW/ieO32f1wygP Content-Type: application/pgp-signature; name="signature.asc" Content-Description: Digital signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.1 (GNU/Linux) Comment: Nikos Ntarmos <ntarmos@ceid.upatras.gr> iD8DBQFDew5zm6J1ac+VFgoRAihHAKCGEl+nzwUPqEJsg8menyuoE4RPZwCgkGjZ U/2bmem5pLsLug6YKVKmpYU= =KfKL -----END PGP SIGNATURE----- --gatW/ieO32f1wygP--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20051116104819.GA10128>