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 19:36:32 +0000 (12:36 -0700)
commit2d910aaf6e46b623aae5ea8623eacfcd23f6e9dc
treea685c9edff1f2b22141d67f5f505cd96327dfb78
parent783fd4c335fb5ba076ae16ebd59a17c72fece785
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