aboutsummaryrefslogtreecommitdiff
path: root/share/man/man9/intr_event.9
diff options
context:
space:
mode:
Diffstat (limited to 'share/man/man9/intr_event.9')
-rw-r--r--share/man/man9/intr_event.9481
1 files changed, 481 insertions, 0 deletions
diff --git a/share/man/man9/intr_event.9 b/share/man/man9/intr_event.9
new file mode 100644
index 000000000000..ba8faf877e6a
--- /dev/null
+++ b/share/man/man9/intr_event.9
@@ -0,0 +1,481 @@
+.\" Copyright (c) 2001 John H. Baldwin <jhb@FreeBSD.org>
+.\" Copyright (c) 2006 Tom Rhodes <trhodes@FreeBSD.org>
+.\" Copyright (c) 2021 Mitchell Horne <mhorne@FreeBSD.org>
+.\" Copyright (c) 2022 The FreeBSD Foundation
+.\"
+.\" Portions of this documentation were written by Mitchell Horne
+.\" under sponsorship from the FreeBSD Foundation.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd January 24, 2025
+.Dt INTR_EVENT 9
+.Os
+.Sh NAME
+.Nm intr_event_add_handler ,
+.Nm intr_event_create ,
+.Nm intr_event_destroy ,
+.Nm intr_event_handle ,
+.Nm intr_event_remove_handler ,
+.Nm intr_priority
+.Nd "kernel interrupt handler and thread API"
+.Sh SYNOPSIS
+.In sys/param.h
+.In sys/bus.h
+.In sys/interrupt.h
+.Ft int
+.Fo intr_event_add_handler
+.Fa "struct intr_event *ie"
+.Fa "const char *name"
+.Fa "driver_filter_t filter"
+.Fa "driver_intr_t handler"
+.Fa "void *arg"
+.Fa "u_char pri"
+.Fa "enum intr_type flags"
+.Fa "void **cookiep"
+.Fc
+.Ft int
+.Fo intr_event_create
+.Fa "struct intr_event **event"
+.Fa "void *source"
+.Fa "int flags"
+.Fa "int irq"
+.Fa "void (*pre_ithread)(void *)"
+.Fa "void (*post_ithread)(void *)"
+.Fa "void (*post_filter)(void *)"
+.Fa "int (*assign_cpu)(void *, int)"
+.Fa "const char *fmt"
+.Fa "..."
+.Fc
+.Ft int
+.Fn intr_event_destroy "struct intr_event *ie"
+.Ft int
+.Fn intr_event_handle "struct intr_event *ie" "struct trapframe *frame"
+.Ft int
+.Fn intr_event_remove_handler "void *cookie"
+.Ft u_char
+.Fn intr_priority "enum intr_type flags"
+.Sh DESCRIPTION
+The interrupt event API provides methods to manage the registration and
+execution of interrupt handlers and their associated thread contexts.
+.Pp
+Each interrupt event in the system corresponds to a single hardware or software
+interrupt source.
+Each interrupt event maintains a list of interrupt handlers, sorted by
+priority, which will be invoked when handling the event.
+An interrupt event will typically, but not always, have an associated
+.Xr kthread 9 ,
+known as the interrupt thread.
+Finally, each event contains optional callback functions which will be
+invoked before and after the handler functions themselves.
+.Pp
+An interrupt handler contains two distinct handler functions:
+the
+.Em filter
+and the thread
+.Em handler .
+The
+.Em filter
+function is run from interrupt context and is intended to perform quick
+handling such as acknowledging or masking a hardware interrupt,
+and queueing work for the ensuing thread
+.Em handler .
+Both functions are optional; each interrupt handler may choose to register a
+filter, a thread handler, or both.
+Each interrupt handler also consists of a name,
+a set of flags,
+and an opaque argument which will be passed to both the
+.Em filter
+and
+.Em handler
+functions.
+.Ss Handler Constraints
+The
+.Em filter
+function is executed inside a
+.Xr critical 9
+section.
+Therefore, filters may not yield the CPU for any reason, and may only use spin
+locks to access shared data.
+Allocating memory within a filter is not permitted.
+.Pp
+The
+.Em handler
+function executes from the context of the associated interrupt kernel thread.
+Sleeping is not permitted, but the interrupt thread may be preempted by higher
+priority threads.
+Thus, threaded handler functions may obtain non-sleepable locks, as described
+in
+.Xr locking 9 .
+Any memory or zone allocations in an interrupt thread must specify the
+.Dv M_NOWAIT
+flag, and any allocation errors must be handled.
+.Pp
+The exception to these constraints is software interrupt threads, which are
+allowed to sleep but should be allocated and scheduled using the
+.Xr swi 9
+interface.
+.Ss Function Descriptions
+The
+.Fn intr_event_create
+function creates a new interrupt event.
+The
+.Fa event
+argument points to a
+.Vt struct intr_event
+pointer that will reference the newly created event upon success.
+The
+.Fa source
+argument is an opaque pointer which will be passed to the
+.Fa pre_ithread ,
+.Fa post_ithread ,
+and
+.Fa post_filter
+callbacks.
+The
+.Fa flags
+argument is a mask of properties of this thread.
+The only valid flag currently for
+.Fn intr_event_create
+is
+.Dv IE_SOFT
+to specify that this interrupt thread is a software interrupt.
+The
+.Fa enable
+and
+.Fa disable
+arguments specify optional functions used to enable and disable this
+interrupt thread's interrupt source.
+The
+.Fa irq
+argument is the unique interrupt vector number corresponding to the event.
+The
+.Fa pre_ithread ,
+.Fa post_ithread ,
+and
+.Fa post_filter
+arguments are callback functions that are invoked at different
+points while handling an interrupt.
+This is described in more detail in the
+.Sx Handler Callbacks
+section, below.
+They may be
+.Va NULL
+to specify no callback.
+The
+.Fa assign_cpu
+argument points to a callback function that will be invoked when binding
+an interrupt to a particular CPU.
+It may be
+.Va NULL
+if binding is unsupported.
+The
+remaining arguments form a
+.Xr printf 9
+argument list that is used to build the base name of the new interrupt thread.
+The full name of an interrupt thread is formed by concatenating the base
+name of the interrupt thread with the names of all of its interrupt handlers.
+.Pp
+The
+.Fn intr_event_destroy
+function destroys a previously created interrupt event by releasing its
+resources.
+.\" The following is not true (yet):
+.\"and arranging for the backing kernel thread to terminate.
+An interrupt event can only be destroyed if it has no handlers remaining.
+.Pp
+The
+.Fn intr_event_add_handler
+function adds a new handler to an existing interrupt event specified by
+.Fa ie .
+The
+.Fa name
+argument specifies a name for this handler.
+The
+.Fa filter
+argument provide the filter function to execute.
+The
+.Fa handler
+argument provides the handler function to be executed from the
+event's interrupt thread.
+The
+.Fa arg
+argument will be passed to the
+.Fa filter
+and
+.Fa handler
+functions when they are invoked.
+The
+.Fa pri
+argument specifies the priority of this handler,
+corresponding to the values defined in
+.In sys/priority.h .
+It determines the order this handler is called relative to the other handlers
+for this event, as well as the scheduling priority of the backing kernel
+thread.
+.Fa flags
+argument can be used to specify properties of this handler as defined in
+.In sys/bus.h .
+If
+.Fa cookiep
+is not
+.Dv NULL ,
+then it will be assigned a cookie that can be used later to remove this
+handler.
+.Pp
+The
+.Fn intr_event_handle
+function is the main entry point into the interrupt handling code.
+It must be called from an interrupt context.
+The function will execute all filter handlers associated with the interrupt
+event
+.Fa ie ,
+and schedule the associated interrupt thread to run, if applicable.
+The
+.Fa frame
+argument is used to pass a pointer to the
+.Vt struct trapframe
+containing the machine state at the time of the interrupt.
+The main body of this function runs within a
+.Xr critical 9
+section.
+.Pp
+The
+.Fn intr_event_remove_handler
+function removes an interrupt handler from the interrupt event specified by
+.Fa ie .
+The
+.Fa cookie
+argument, obtained from
+.Fn intr_event_add_handler ,
+identifies the handler to remove.
+.Pp
+The
+.Fn intr_priority
+function translates the
+.Dv INTR_TYPE_*
+interrupt flags into interrupt thread scheduling priorities.
+.Pp
+The interrupt flags not related to the type of a particular interrupt
+.Pq Dv INTR_TYPE_*
+can be used to specify additional properties of both hardware and software
+interrupt handlers.
+The
+.Dv INTR_EXCL
+flag specifies that this handler cannot share an interrupt thread with
+another handler.
+The
+.Dv INTR_MPSAFE
+flag specifies that this handler is MP safe in that it does not need the
+Giant mutex to be held while it is executed.
+The
+.Dv INTR_ENTROPY
+flag specifies that the interrupt source this handler is tied to is a good
+source of entropy, and thus that entropy should be gathered when an interrupt
+from the handler's source triggers.
+Presently, the
+.Dv INTR_ENTROPY
+flag is not valid for software interrupt handlers.
+The
+.Dv INTR_SLEEPABLE
+flag specifies that the interrupt ithread may sleep.
+Presently, the
+.Dv INTR_SLEEPABLE
+flag requires the
+.Dv INTR_EXCL
+flag to be set.
+.Ss Handler Callbacks
+Each
+.Vt struct intr_event
+is assigned three optional callback functions when it is created:
+.Fa pre_ithread ,
+.Fa post_ithread ,
+and
+.Fa post_filter .
+These callbacks are intended to be defined by the interrupt controller driver,
+to allow for actions such as masking and unmasking hardware interrupt signals.
+.Pp
+When an interrupt is triggered, all filters are run to determine if any
+threaded interrupt handlers should be scheduled for execution by the associated
+interrupt thread. If no threaded handlers are scheduled, the
+.Fa post_filter
+callback is invoked which should acknowledge the interrupt and permit it to
+trigger in the future.
+If any threaded handlers are scheduled, the
+.Fa pre_ithread
+callback is invoked instead.
+This handler should acknowledge the interrupt, but it should also ensure that
+the interrupt will not fire continuously until after the threaded handlers have
+executed.
+Typically this callback masks level-triggered interrupts in an interrupt
+controller while leaving edge-triggered interrupts alone.
+Once all threaded handlers have executed,
+the
+.Fa post_ithread
+callback is invoked from the interrupt thread to enable future interrupts.
+Typically this callback unmasks level-triggered interrupts in an interrupt
+controller.
+.Sh RETURN VALUES
+The
+.Fn intr_event_add_handler ,
+.Fn intr_event_create ,
+.Fn intr_event_destroy ,
+.Fn intr_event_handle ,
+and
+.Fn intr_event_remove_handler
+functions return zero on success and non-zero on failure.
+The
+.Fn intr_priority
+function returns a process priority corresponding to the passed in interrupt
+flags.
+.Sh EXAMPLES
+The
+.Xr swi_add 9
+function demonstrates the use of
+.Fn intr_event_create
+and
+.Fn intr_event_add_handler .
+.Bd -literal -offset indent
+int
+swi_add(struct intr_event **eventp, const char *name, driver_intr_t handler,
+ void *arg, int pri, enum intr_type flags, void **cookiep)
+{
+ struct intr_event *ie;
+ int error = 0;
+
+ if (flags & INTR_ENTROPY)
+ return (EINVAL);
+
+ ie = (eventp != NULL) ? *eventp : NULL;
+
+ if (ie != NULL) {
+ if (!(ie->ie_flags & IE_SOFT))
+ return (EINVAL);
+ } else {
+ error = intr_event_create(&ie, NULL, IE_SOFT, 0,
+ NULL, NULL, NULL, swi_assign_cpu, "swi%d:", pri);
+ if (error)
+ return (error);
+ if (eventp != NULL)
+ *eventp = ie;
+ }
+ if (handler != NULL) {
+ error = intr_event_add_handler(ie, name, NULL, handler, arg,
+ PI_SWI(pri), flags, cookiep);
+ }
+ return (error);
+}
+.Ed
+.Sh ERRORS
+The
+.Fn intr_event_add_handler
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa ie
+or
+.Fa name
+arguments are
+.Dv NULL .
+.It Bq Er EINVAL
+The
+.Fa handler
+and
+.Fa filter
+arguments are both
+.Dv NULL .
+.It Bq Er EINVAL
+The
+.Dv IH_EXCLUSIVE
+flag is specified and the interrupt thread
+.Fa ie
+already has at least one handler, or the interrupt thread
+.Fa ie
+already has an exclusive handler.
+.El
+.Pp
+The
+.Fn intr_event_create
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+A flag other than
+.Dv IE_SOFT
+was specified in the
+.Fa flags
+parameter.
+.El
+.Pp
+The
+.Fn intr_event_destroy
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa ie
+argument is
+.Dv NULL .
+.It Bq Er EBUSY
+The interrupt event pointed to by
+.Fa ie
+has at least one handler which has not been removed with
+.Fn intr_event_remove_handler .
+.El
+.Pp
+The
+.Fn intr_event_handle
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa ie
+argument is
+.Dv NULL .
+.It Bq Er EINVAL
+There are no interrupt handlers assigned to
+.Fa ie .
+.It Bq Er EINVAL
+The interrupt was not acknowledged by any filter and has no associated thread
+handler.
+.El
+.Pp
+The
+.Fn intr_event_remove_handler
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa cookie
+argument is
+.Dv NULL .
+.El
+.Sh SEE ALSO
+.Xr critical 9 ,
+.Xr kthread 9 ,
+.Xr locking 9 ,
+.Xr malloc 9 ,
+.Xr swi 9 ,
+.Xr uma 9
+.Sh HISTORY
+Interrupt threads and their corresponding API first appeared in
+.Fx 5.0 .