kernel - Fix serious issue w/ smp_invltlb(), plus other issues (2)
authorMatthew Dillon <dillon@apollo.backplane.com>
Thu, 28 Oct 2010 19:36:32 +0000 (12:36 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Thu, 28 Oct 2010 21:22:29 +0000 (14:22 -0700)
commitdd4ef322d7c93551990f53da73fb477e8db39ee8
treec37f6fe3d0e83ed5f06a8c5df3f90f8227758399
parent7402df27b5be0de4f74c3e2b8b5c8327434e8509
kernel - Fix serious issue w/ smp_invltlb(), plus other issues (2)

It looks like there are a number of additional cases where kernel threads
can wind up running with interrupts physically disabled, which can create
serious problems for smp_invltlb().

It is not entirely clear how these deadlocks occur since the IPI code does
a forced "STI" if it would otherwise loop, but there are several other
hard loops that do not:  lwkt_switch looping on a vm_token, spin locks,
and probably a few other places.

We want interrupts to be enabled in all cases where these sorts of loops
occur in order to be able to service Xinvltlb via smp_invltlb() as well
as to prevent the LAPIC interrupt queue from filling up and livelocking
something that it shouldn't.

* lwkt_preempt() must save, zero, and restore gd->gd_intr_nesting_level
  when issuing a preemption.  Otherwise it will improperly panic on
  an assertion if the preempting interrupt thread code tries to switch out.
  It is perfectly acceptable for the preempting thread to block (it just
  switches back to the thread that got preempted).

  Why the assertion was not occuring before I do not know but it is
  probably related to threads getting stuck in 'cli' mode.  The additional
  changes below appear to significantly increase the number of interrupt
  thread preemptions which succeed (lwkt.preempt_{hit,miss} counters).

* STI prior to running ithread_fast_handler() from all IDTVECs related
  to device interrupts.

* STI in Xcpustop, Xipiq, and Xtimer.  These functions can call more
  complex C code and doing so with interrupts disabled may prevent
  Xinvltlb (via smp_invltlb()) from being executed, deadlocking the
  system.

* Reorder a mfence().  Probably not needed but do it anyway.
sys/kern/lwkt_thread.c
sys/platform/pc32/apic/apic_vector.s
sys/platform/pc32/i386/mp_machdep.c
sys/platform/pc32/icu/icu_vector.s
sys/platform/pc64/apic/apic_vector.s
sys/platform/pc64/icu/icu_vector.s
sys/platform/pc64/x86_64/mp_machdep.c