Commit Graph

28 Commits

Author SHA1 Message Date
jhb
23cec608a6 Minor fixes and tweaks to the x86 interrupt code:
- Split the intr_table_lock into an sx lock used for most things, and a
  spin lock to protect intrcnt_index.  Originally I had this as a spin lock
  so interrupt code could use it to lookup sources.  However, we don't
  actually do that because it would add a lot of overhead to interrupts,
  and if we ever do support removing interrupt sources, we can use other
  means to safely do so w/o locking in the interrupt handling code.
- Replace is_enabled (boolean) with is_handlers (a count of handlers) to
  determine if a source is enabled or not.  This allows us to notice when
  a source is no longer in use.  When that happens, we now invoke a new
  PIC method (pic_disable_intr()) to inform the PIC driver that the
  source is no longer in use.  The I/O APIC driver frees the APIC IDT
  vector when this happens.  The MSI driver no longer needs to have a
  hack to clear is_enabled during msi_alloc() and msix_alloc() as a result
  of this change as well.
- Add an apic_disable_vector() to reset an IDT vector back to Xrsvd to
  complement apic_enable_vector() and use it in the I/O APIC and MSI code
  when freeing an IDT vector.
- Add a new nexus hook: nexus_add_irq() to ask the nexus driver to add an
  IRQ to its irq_rman.  The MSI code uses this when it creates new
  interrupt sources to let the nexus know about newly valid IRQs.
  Previously the msi_alloc() and msix_alloc() passed some extra stuff
  back to the nexus methods which then added the IRQs.  This approach is
  a bit cleaner.
- Change the MSI sx lock to a mutex.  If we need to create new sources,
  drop the lock, create the required number of sources, then get the lock
  and try the allocation again.
2007-05-08 21:29:14 +00:00
kmacy
ee539b99dc Evidently FreeBSD has long relied on the compiler to treat structures
passed by value (trap frames) as if they were in fact being passed by
reference. For better or worse, this incorrect behaviour is no longer
present in gcc 4.1. In this patch I convert all trapframe arguments to
be explicitly pass by reference. I also remove vm86_initflags, pushing
the very little work that it actually does up into vm86_prepcall.

Reviewed by: kan
Tested by: kan
2006-12-17 05:07:01 +00:00
jhb
920b219fcf Change the x86 interrupt code to suspend/resume interrupt controllers
(PICs) rather than interrupt sources.  This allows interrupt controllers
with no interrupt pics (such as the 8259As when APIC is in use) to
participate in suspend/resume.
- Always register the 8259A PICs even if we don't use any of their pins.
- Explicitly reset the 8259As on resume on amd64 if 'device atpic' isn't
  included.
- Add a "dummy" PIC for the local APIC on the BSP to reset the local APIC
  on resume.  This gets suspend/resume working with APIC on UP systems.
  SMP still needs more work to bring the APs back to life.

The MFC after is tentative.

Tested by:	anholt (i386)
Submitted by:	Andrea Bittau <a.bittau at cs.ucl.ac.uk> (3)
MFC after:	1 week
2006-10-10 23:23:12 +00:00
jhb
3478c467ee Rework how we wire up interrupt sources to CPUs:
- Throw out all of the logical APIC ID stuff.  The Intel docs are somewhat
  ambiguous, but it seems that the "flat" cluster model we are currently
  using is only supported on Pentium and P6 family CPUs.  The other
  "hierarchy" cluster model that is supported on all Intel CPUs with
  local APICs is severely underdocumented.  For example, it's not clear
  if the OS needs to glean the topology of the APIC hierarchy from
  somewhere (neither ACPI nor MP Table include it) and setup the logical
  clusters based on the physical hierarchy or not.  Not only that, but on
  certain Intel chipsets, even though there were 4 CPUs in a logical
  cluster, all the interrupts were only sent to one CPU anyway.
- We now bind interrupts to individual CPUs using physical addressing via
  the local APIC IDs.  This code has also moved out of the ioapic PIC
  driver and into the common interrupt source code so that it can be
  shared with MSI interrupt sources since MSI is addressed to APICs the
  same way that I/O APIC pins are.
- Interrupt source classes grow a new method pic_assign_cpu() to bind an
  interrupt source to a specific local APIC ID.
- The SMP code now tells the interrupt code which CPUs are avaiable to
  handle interrupts in a simpler and more intuitive manner.  For one thing,
  it means we could now choose to not route interrupts to HT cores if we
  wanted to (this code is currently in place in fact, but under an #if 0
  for now).
- For now we simply do static round-robin of IRQs to CPUs when the first
  interrupt handler just as before, with the change that IRQs are now
  bound to individual CPUs rather than groups of up to 4 CPUs.
- Because the IRQ to CPU mapping has now been moved up a layer, it would
  be easier to manage this mapping from higher levels.  For example, we
  could allow drivers to specify a CPU affinity map for their interrupts,
  or we could allow a userland tool to bind IRQs to specific CPUs.

The MFC is tentative, but I want to see if this fixes problems some folks
had with UP APIC kernels on 6.0 on SMP machines (an SMP kernel would work
fine, but a UP APIC kernel (such as GENERIC in RELENG_6) would lose
interrupts).

MFC after:	1 week
2006-02-28 22:24:55 +00:00
jhb
a1d5c4c24e Whitespace: reduce diffs with amd64. 2005-12-08 18:33:48 +00:00
jhb
c77d4150b7 Change the i386 code to pass the interrupt vector as a separate argument
rather than embedding it in the intrframe as if_vec.  This reduces diffs
with amd64 somewhat.
- Remove cf_vec from clockframe (it wasn't used anyway) and stop pushing
  dummy vector arguments for ipi_bitmap_handler() and lapic_handle_timer()
  since clockframe == trapframe now.
- Fix ddb to handle stack traces across interrupt entry points that just
  have a trapframe on their stack and not a trapframe + vector.
- Change intr_execute_handlers() to take a trapframe rather than an
  intrframe pointer.
- Change lapic_handle_intr() and atpic_handle_intr() to take a vector and
  trapframe rather than an intrframe.
- GC struct intrframe now that nothing uses it anymore.
- GC CLOCK_TO_TRAPFRAME() and INTR_TO_TRAPFRAME().

Reviewed by:	bde
Requested by:	peter
2005-12-05 22:39:09 +00:00
jhb
bd6187382d Really slam the door on mixed mode now that we don't depend on it for a
working IRQ0 with APIC anymore.  Previously, it was possible to have
some other ATPIC IRQS "leak" through in a few edge cases.  For example, on
my x86 test machine, ACPI re-routes the SCI (IRQ 9) to intpin 13 on the
first I/O APIC.  This leaves a hole for IRQ 13 (since the APIC doesn't
provide a source for IRQ 13 in that case) with the result that the ATPIC
IRQ13 source was registered instead.  This changes the 8259A drivers to
only register their interrupt sources if none of the 16 ISA IRQs have an
interrupt source already installed.

MFC after:	1 week
2005-12-05 22:09:30 +00:00
jhb
e20e5c07ce Reorganize the interrupt handling code a bit to make a few things cleaner
and increase flexibility to allow various different approaches to be tried
in the future.
- Split struct ithd up into two pieces.  struct intr_event holds the list
  of interrupt handlers associated with interrupt sources.
  struct intr_thread contains the data relative to an interrupt thread.
  Currently we still provide a 1:1 relationship of events to threads
  with the exception that events only have an associated thread if there
  is at least one threaded interrupt handler attached to the event.  This
  means that on x86 we no longer have 4 bazillion interrupt threads with
  no handlers.  It also means that interrupt events with only INTR_FAST
  handlers no longer have an associated thread either.
- Renamed struct intrhand to struct intr_handler to follow the struct
  intr_foo naming convention.  This did require renaming the powerpc
  MD struct intr_handler to struct ppc_intr_handler.
- INTR_FAST no longer implies INTR_EXCL on all architectures except for
  powerpc.  This means that multiple INTR_FAST handlers can attach to the
  same interrupt and that INTR_FAST and non-INTR_FAST handlers can attach
  to the same interrupt.  Sharing INTR_FAST handlers may not always be
  desirable, but having sio(4) and uhci(4) fight over an IRQ isn't fun
  either.  Drivers can always still use INTR_EXCL to ask for an interrupt
  exclusively.  The way this sharing works is that when an interrupt
  comes in, all the INTR_FAST handlers are executed first, and if any
  threaded handlers exist, the interrupt thread is scheduled afterwards.
  This type of layout also makes it possible to investigate using interrupt
  filters ala OS X where the filter determines whether or not its companion
  threaded handler should run.
- Aside from the INTR_FAST changes above, the impact on MD interrupt code
  is mostly just 's/ithread/intr_event/'.
- A new MI ddb command 'show intrs' walks the list of interrupt events
  dumping their state.  It also has a '/v' verbose switch which dumps
  info about all of the handlers attached to each event.
- We currently don't destroy an interrupt thread when the last threaded
  handler is removed because it would suck for things like ppbus(8)'s
  braindead behavior.  The code is present, though, it is just under
  #if 0 for now.
- Move the code to actually execute the threaded handlers for an interrrupt
  event into a separate function so that ithread_loop() becomes more
  readable.  Previously this code was all in the middle of ithread_loop()
  and indented halfway across the screen.
- Made struct intr_thread private to kern_intr.c and replaced td_ithd
  with a thread private flag TDP_ITHREAD.
- In statclock, check curthread against idlethread directly rather than
  curthread's proc against idlethread's proc. (Not really related to intr
  changes)

Tested on:	alpha, amd64, i386, sparc64
Tested on:	arm, ia64 (older version of patch by cognet and marcel)
2005-10-25 19:48:48 +00:00
nyan
7d03ad1458 Change a directory layout for pc98.
- Move MD files into <arch>/<arch>.
  - Move bus dependent files into <arch>/<bus>.
Rename some files to more suitable names.

Repo-copied by:	peter
Discussed with:	imp
2005-05-10 12:02:18 +00:00
jhb
5a3bc2892e Tweak the ELCR support slightly. Explicitly probe the ELCR during boot
instead of burying that in the atpic(4) code as atpic(4) is not the only
user of elcr(4).  Change the elcr(4) code to export a global elcr_found
variable that other code can check to see if a valid ELCR was found.

MFC after:	1 month
2005-01-18 20:24:47 +00:00
scottl
fb7f90d7ec Optimize intr_execute_handlers() by combining the pic_disable_source() and
pic_eoi_source() into one call.  This halves the number of spinlock operations
and indirect function calls in the normal case of handling a normal (ithread)
interrupt.  Optimize the atpic and ioapic drivers to use inlines where
appropriate in supporting the intr_execute_handlers() change.

This knocks 900ns, or roughly 1350 cycles, off of the time spent servicing an
interrupt in the common case on my 1.5GHz P4 uniprocessor system.  SMP systems
likely won't see as much of a gain due to the ioapic being more efficient than
the atpic.  I'll investigate porting this to amd64 soon.

Reviewed by:	jhb
2004-08-02 15:31:10 +00:00
phk
d6f7d2bde6 Add some missing <sys/module.h> includes which are masked by the
one on death-row in <sys/kernel.h>
2004-05-30 17:57:46 +00:00
jhb
052c3f46af - Move some macros from icu.h into atpic.c as that is the only place they
are used.
- Reduce duplication of a couple of macros removing the duplicates from
  ich.h.
- Remove unused macros from icu.h as well as locore protection as this
  header is no longer included in assembly sources.
2004-05-11 20:23:24 +00:00
jhb
da67f4fe48 - Simplify the sizeof expression in the CTASSERT() for NUM_ISA_IRQS.
- Fixup grammar in a comment.

Submitted by:	bde (1)
2004-05-10 18:33:52 +00:00
nyan
e93748992b Fixed PC98 support.
- Disable an ELCR on PC98.
 - Correct IRQs.
2004-05-06 13:48:34 +00:00
jhb
415131cd6d - Add a new pic method pic_config_intr() to set the trigger mode and
polarity for a specified IRQ.  The intr_config_intr() function wraps
  this pic method hiding the IRQ to interrupt source lookup.
- Add a config_intr() method to the atpic(4) driver that reconfigures
  the interrupt using the ELCR if possible and returns an error otherwise.
- Add a config_intr() method to the apic(4) driver that just logs any
  requests that would change the existing programming under bootverbose.
  Currently, the only changes the apic(4) driver receives are due to bugs
  in the acpi(4) driver and its handling of link devices, hence the reason
  for such requests currently being ignored.
- Have the nexus(4) driver on i386 implement the bus_config_intr() function
  by calling intr_config_intr().
2004-05-04 21:02:56 +00:00
jhb
4bc7c8e398 - Add a member to the atpic interrupt source structures to indicate if the
IRQ is edge triggered or level triggered.  For ISA interrupts, we assume
  that edge triggered interrupts are always active high and that level
  triggered interrupts are always active low.
- Don't disable an edge triggered interrupt in the PIC.  This avoids
  outb instructions to the actual PIC for traditional ISA IRQs such as
  IRQ 1, 6, 14, and 15.  (Fast interrupts such as IRQs 0 and 8 don't mask
  their source, so this doesn't change anything for them.)
- For MCA systems we assume that all interrupts are level triggered and
  thus need masking.  Otherwise, we probe the ELCR.  If it exists we trust
  what it tells us regarding which interrupts are level triggered.  If it
  does not exist, we assume that IRQs 0, 1, 2, and 8 are edge triggered
  and that all other IRQs are level triggered and need masking.
- Instruct the ELCR mini-driver to restore its saved state during resume.
2004-05-04 20:12:52 +00:00
jhb
7ea4fab234 - Add an IMEN_MASK macro that returns the 8-bit bitmask of an atpic
interrupt source.
- Only do an outb() to the PIC to clear a bit in imen if the bit is set.
- Add a NUM_ISA_IRQS macro to replace uglier
  'sizeof(array) / sizeof(member)' expressions along with a CTASSERT() to
  ensure that the macro is correct.
2004-05-03 14:52:41 +00:00
obrien
6e5a424e76 Use BSD spelling vs. SysV. 2004-04-19 18:38:04 +00:00
njl
05a1f56fc9 Convert callers to the new bus_alloc_resource_any(9) API.
Submitted by:	Mark Santcroos <marks@ripe.net>
Reviewed by:	imp, dfr, bde
2004-03-17 17:50:55 +00:00
jhb
bd0c4d216c - Use i8259A register defines from shared sys/dev/ic/i8259.h rather than
from the i386-specific icu.h.
- Replace PC98 magic numbers with equivalent register define values along
  with comments about PC-98 "quirks".
2004-01-06 19:07:08 +00:00
jhb
e9c1e3387f Add a special check for a stray IRQ 7 or IRQ 15 to see if it is actually
a spurious interrupt from one of the 8259As.  If so, don't log it as a
stray IRQ, but just silently ignore it.

Approved by:	re (rwatson)
2003-11-19 15:40:23 +00:00
jhb
1e7f54677c - Add counts to the ATPIC interrupt sources and point the ATPIC interrupt
source count pointers at them so that intr_execute_handlers() won't
  choke when it tries to handle an unregisterd ATPIC interrupt source.
- Install the low-level ATPIC interrupt handlers when we first program the
  ATPIC in atpic_startup() rather than at SI_SUB_INTR.  This is only
  necessary to work around buggy code that enables interrupts too early
  in the boot process (namely, the vm86 code).

Approved by:	re (rwatson)
2003-11-19 15:38:56 +00:00
jhb
5d2ca74893 Always install IDT entries for ATPIC interrupt sources. The APIC no
longer uses these interrupt vectors for its ISA interrupt pins, so these
entries will not be overwritten.  If we get a spurious interrupt from the
ATPIC when using the APIC, it will be treated as a stray interrupt instead
of causing a panic.
2003-11-14 21:02:49 +00:00
jhb
398b81cbfe Replace magic numbers with macros for i8259A register constants. Still
need the ICW4 bits for PC98 though.
2003-11-14 19:13:06 +00:00
jhb
9428d57b9b - Move manipulation of td_intr_nesting_level out of assembly interrupt
vector stubs and into the C functions they call.
- Move disabling and EOIing of interrupt sources out of PIC driver entry
  points and into intr_execute_handlers().  Intr_execute_handlers() only
  disables a source for an interrupt if it is a stray interrupt or has
  threaded handlers.  Sources with fast handlers no longer disable (mask)
  the source while executing the handlers.
- Move the setting of clkintr_pending into intr_execute_handlers() and set
  the variable for any interrupt source with a vector of 0.  (Should only
  be true for IRQ 0.)  This fixes clkintr_pending in the NO_MIXED_MODE
  case.
- Implement lapic_eoi() and use it to implement ioapic_eoi_source().
- Rename atpic_sched_ithd() to atpic_handle_intr() since it is used to
  handle all atpic interrupts and not just threaded ones.

Inspired by:	peter's changes to amd64 in p4 (1)
Requested by:	bde (2)
2003-11-12 18:13:57 +00:00
nyan
9a0462c2a3 Fix to support pc98. 2003-11-04 13:13:04 +00:00
jhb
aac4b7181c Add the new atpic(4) driver for the 8259A master and slave PICs. By
default we provide 16 interrupt sources for IRQs 0 through 15.  However,
if the I/O APIC driver has already registered sources for any of those IRQs
then we will silently fail to register our own source for that IRQ.

Note that i386/isa/icu.h is now specific to the 8259A and no longer
contains any info relevant to APICs.  Also note that fast interrupts no
longer use a separate entry point.  Instead, both fast and threaded
interrupts share the same entry point which merely looks up the appropriate
source and passes control to intr_execute_handlers().
2003-11-03 21:34:45 +00:00