Allow 'options SMP' *WITHOUT* 'options APIC_IO'. That is, an ability to produce an SMP-capable kernel that uses the PIC/ICU instead of the IO APICs for interrupt routing. SMP boxes with broken BIOSes (namely my Shuttle XPC SN95G5) could very well have serious interrupt routing problems when operating in IO APIC mode. One solution is to not use the IO APICs. That is, to run only the Local APICs for the SMP management. * Don't conditionalize NIDT. Just set it to 256 * Make the ICU interrupt code MP SAFE. This primarily means using the imen_spinlock to protect accesses to icu_imen. * When running SMP without APIC_IO, set the LAPIC TPR to prevent unintentional interrupts. Leave LINT0 enabled (normally with APIC_IO LINT0 is disabled when the IO APICs are activated). LINT0 is the virtual wire between the 8259 and LAPIC 0. * Get rid of NRSVIDT. Just use IDT_OFFSET instead. * Clean up all the APIC_IO tests which should have been SMP tests, and all the SMP tests which should have been APIC_IO tests. Explicitly #ifdef out all code related to the IO APICs when APIC_IO is not set.
ICU/APIC cleanup part 9/many. Get rid of machine/smptests.h, remove or implement the related #defines. Distinguish between boot-time vector initialization and interrupt setup and teardown in MACHINTR ABI. Get rid of the ISR test for APIC-generated interrupts and all related support code. Just generate the EOI and pray. Document more of the IO APIC redirection register(s). Intel sure screwed up the LAPIC and IO APIC royally. There is no simple way to poll the actual signal level on a pin, no simple way to manually EOI interrupts or EOI them in the order we desire, no simple way to poll the LAPIC for the vector that will be EOI'd when we send the EOI. We can't mask the interrupt on the IO APIC without triggering stupid legacy code on some machines. We can't even program the IO APIC linearly, it uses a stupid register/data sequence that makes it impossible for access on an SMP system without serialization. It's a goddamn mess, and it is all Intel's fault.
ICU/APIC cleanup part 7/many. Get rid of most of the dependancies on ICU_LEN, NSWI, and NHWI, by creating a generous system standard maximum for hardware and software interrupts in the MI sys/interrupt.h. The interrupt architecture can then further limit available hardware and software interrupts. For example, i386 uses 32 bit masks and so is limited to 32 hardware interrupts and 32 software interrupts. The name ICU_OFFSET is confusing, rename it to IDT_OFFSET, which is what it really is. Note that this separation is possible due to recent work on the MI interrupt layer. Separate the software interrupt mask from the hardware interrupt mask in the i386 code. Get rid of rndcontrol's 16 irq limit by creating a new ioctl to iterate through interrupt numbers.
ICU/APIC cleanup part 5/many. Start migrating the ICU and APIC interrupt interfaces to a new machine level interrupt ABI. This ABI will eventually be tied into the BUS architecture. Move INTRDIS/INTREN to the new API: machintr_intrdis(irq) and machintr_intren(irq). Get rid of ithread_unmask(). Have the interrupt thread code call machintr_intrdis(irq) directly.
MP Implementation 1/2: Get the APIC code working again, sweetly integrate the MP lock into the LWKT scheduler, replace the old simplelock code with tokens or spin locks as appropriate. In particular, the vnode interlock (and most other interlocks) are now tokens. Also clean up a few curproc/cred sequences that are no longer needed. The APs are left in degenerate state with non IPI interrupts disabled as additional LWKT work must be done before we can really make use of them, and FAST interrupts are not managed by the MP lock yet. The main thing for this stage was to get the system working with an APIC again. buildworld tested on UP and 2xCPU/MP (Dell 2550)