The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/kern_intr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice unmodified, this list of conditions, and the following
   12  *    disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include "opt_ddb.h"
   33 #include "opt_kstack_usage_prof.h"
   34 
   35 #include <sys/param.h>
   36 #include <sys/bus.h>
   37 #include <sys/conf.h>
   38 #include <sys/cpuset.h>
   39 #include <sys/rtprio.h>
   40 #include <sys/systm.h>
   41 #include <sys/interrupt.h>
   42 #include <sys/kernel.h>
   43 #include <sys/kthread.h>
   44 #include <sys/ktr.h>
   45 #include <sys/limits.h>
   46 #include <sys/lock.h>
   47 #include <sys/malloc.h>
   48 #include <sys/mutex.h>
   49 #include <sys/priv.h>
   50 #include <sys/proc.h>
   51 #include <sys/random.h>
   52 #include <sys/resourcevar.h>
   53 #include <sys/sched.h>
   54 #include <sys/smp.h>
   55 #include <sys/sysctl.h>
   56 #include <sys/syslog.h>
   57 #include <sys/unistd.h>
   58 #include <sys/vmmeter.h>
   59 #include <machine/atomic.h>
   60 #include <machine/cpu.h>
   61 #include <machine/md_var.h>
   62 #include <machine/smp.h>
   63 #include <machine/stdarg.h>
   64 #ifdef DDB
   65 #include <ddb/ddb.h>
   66 #include <ddb/db_sym.h>
   67 #endif
   68 
   69 /*
   70  * Describe an interrupt thread.  There is one of these per interrupt event.
   71  */
   72 struct intr_thread {
   73         struct intr_event *it_event;
   74         struct thread *it_thread;       /* Kernel thread. */
   75         int     it_flags;               /* (j) IT_* flags. */
   76         int     it_need;                /* Needs service. */
   77 };
   78 
   79 /* Interrupt thread flags kept in it_flags */
   80 #define IT_DEAD         0x000001        /* Thread is waiting to exit. */
   81 #define IT_WAIT         0x000002        /* Thread is waiting for completion. */
   82 
   83 struct  intr_entropy {
   84         struct  thread *td;
   85         uintptr_t event;
   86 };
   87 
   88 struct  intr_event *clk_intr_event;
   89 struct  intr_event *tty_intr_event;
   90 void    *vm_ih;
   91 struct proc *intrproc;
   92 
   93 static MALLOC_DEFINE(M_ITHREAD, "ithread", "Interrupt Threads");
   94 
   95 static int intr_storm_threshold = 1000;
   96 SYSCTL_INT(_hw, OID_AUTO, intr_storm_threshold, CTLFLAG_RWTUN,
   97     &intr_storm_threshold, 0,
   98     "Number of consecutive interrupts before storm protection is enabled");
   99 static TAILQ_HEAD(, intr_event) event_list =
  100     TAILQ_HEAD_INITIALIZER(event_list);
  101 static struct mtx event_lock;
  102 MTX_SYSINIT(intr_event_list, &event_lock, "intr event list", MTX_DEF);
  103 
  104 static void     intr_event_update(struct intr_event *ie);
  105 static int      intr_event_schedule_thread(struct intr_event *ie);
  106 static struct intr_thread *ithread_create(const char *name);
  107 static void     ithread_destroy(struct intr_thread *ithread);
  108 static void     ithread_execute_handlers(struct proc *p, 
  109                     struct intr_event *ie);
  110 static void     ithread_loop(void *);
  111 static void     ithread_update(struct intr_thread *ithd);
  112 static void     start_softintr(void *);
  113 
  114 /* Map an interrupt type to an ithread priority. */
  115 u_char
  116 intr_priority(enum intr_type flags)
  117 {
  118         u_char pri;
  119 
  120         flags &= (INTR_TYPE_TTY | INTR_TYPE_BIO | INTR_TYPE_NET |
  121             INTR_TYPE_CAM | INTR_TYPE_MISC | INTR_TYPE_CLK | INTR_TYPE_AV);
  122         switch (flags) {
  123         case INTR_TYPE_TTY:
  124                 pri = PI_TTY;
  125                 break;
  126         case INTR_TYPE_BIO:
  127                 pri = PI_DISK;
  128                 break;
  129         case INTR_TYPE_NET:
  130                 pri = PI_NET;
  131                 break;
  132         case INTR_TYPE_CAM:
  133                 pri = PI_DISK;
  134                 break;
  135         case INTR_TYPE_AV:
  136                 pri = PI_AV;
  137                 break;
  138         case INTR_TYPE_CLK:
  139                 pri = PI_REALTIME;
  140                 break;
  141         case INTR_TYPE_MISC:
  142                 pri = PI_DULL;          /* don't care */
  143                 break;
  144         default:
  145                 /* We didn't specify an interrupt level. */
  146                 panic("intr_priority: no interrupt type in flags");
  147         }
  148 
  149         return pri;
  150 }
  151 
  152 /*
  153  * Update an ithread based on the associated intr_event.
  154  */
  155 static void
  156 ithread_update(struct intr_thread *ithd)
  157 {
  158         struct intr_event *ie;
  159         struct thread *td;
  160         u_char pri;
  161 
  162         ie = ithd->it_event;
  163         td = ithd->it_thread;
  164         mtx_assert(&ie->ie_lock, MA_OWNED);
  165 
  166         /* Determine the overall priority of this event. */
  167         if (CK_SLIST_EMPTY(&ie->ie_handlers))
  168                 pri = PRI_MAX_ITHD;
  169         else
  170                 pri = CK_SLIST_FIRST(&ie->ie_handlers)->ih_pri;
  171 
  172         /* Update name and priority. */
  173         strlcpy(td->td_name, ie->ie_fullname, sizeof(td->td_name));
  174 #ifdef KTR
  175         sched_clear_tdname(td);
  176 #endif
  177         thread_lock(td);
  178         sched_prio(td, pri);
  179         thread_unlock(td);
  180 }
  181 
  182 /*
  183  * Regenerate the full name of an interrupt event and update its priority.
  184  */
  185 static void
  186 intr_event_update(struct intr_event *ie)
  187 {
  188         struct intr_handler *ih;
  189         char *last;
  190         int missed, space;
  191 
  192         /* Start off with no entropy and just the name of the event. */
  193         mtx_assert(&ie->ie_lock, MA_OWNED);
  194         strlcpy(ie->ie_fullname, ie->ie_name, sizeof(ie->ie_fullname));
  195         ie->ie_flags &= ~IE_ENTROPY;
  196         missed = 0;
  197         space = 1;
  198 
  199         /* Run through all the handlers updating values. */
  200         CK_SLIST_FOREACH(ih, &ie->ie_handlers, ih_next) {
  201                 if (strlen(ie->ie_fullname) + strlen(ih->ih_name) + 1 <
  202                     sizeof(ie->ie_fullname)) {
  203                         strcat(ie->ie_fullname, " ");
  204                         strcat(ie->ie_fullname, ih->ih_name);
  205                         space = 0;
  206                 } else
  207                         missed++;
  208                 if (ih->ih_flags & IH_ENTROPY)
  209                         ie->ie_flags |= IE_ENTROPY;
  210         }
  211 
  212         /*
  213          * If there is only one handler and its name is too long, just copy in
  214          * as much of the end of the name (includes the unit number) as will
  215          * fit.  Otherwise, we have multiple handlers and not all of the names
  216          * will fit.  Add +'s to indicate missing names.  If we run out of room
  217          * and still have +'s to add, change the last character from a + to a *.
  218          */
  219         if (missed == 1 && space == 1) {
  220                 ih = CK_SLIST_FIRST(&ie->ie_handlers);
  221                 missed = strlen(ie->ie_fullname) + strlen(ih->ih_name) + 2 -
  222                     sizeof(ie->ie_fullname);
  223                 strcat(ie->ie_fullname, (missed == 0) ? " " : "-");
  224                 strcat(ie->ie_fullname, &ih->ih_name[missed]);
  225                 missed = 0;
  226         }
  227         last = &ie->ie_fullname[sizeof(ie->ie_fullname) - 2];
  228         while (missed-- > 0) {
  229                 if (strlen(ie->ie_fullname) + 1 == sizeof(ie->ie_fullname)) {
  230                         if (*last == '+') {
  231                                 *last = '*';
  232                                 break;
  233                         } else
  234                                 *last = '+';
  235                 } else if (space) {
  236                         strcat(ie->ie_fullname, " +");
  237                         space = 0;
  238                 } else
  239                         strcat(ie->ie_fullname, "+");
  240         }
  241 
  242         /*
  243          * If this event has an ithread, update it's priority and
  244          * name.
  245          */
  246         if (ie->ie_thread != NULL)
  247                 ithread_update(ie->ie_thread);
  248         CTR2(KTR_INTR, "%s: updated %s", __func__, ie->ie_fullname);
  249 }
  250 
  251 int
  252 intr_event_create(struct intr_event **event, void *source, int flags, int irq,
  253     void (*pre_ithread)(void *), void (*post_ithread)(void *),
  254     void (*post_filter)(void *), int (*assign_cpu)(void *, int),
  255     const char *fmt, ...)
  256 {
  257         struct intr_event *ie;
  258         va_list ap;
  259 
  260         /* The only valid flag during creation is IE_SOFT. */
  261         if ((flags & ~IE_SOFT) != 0)
  262                 return (EINVAL);
  263         ie = malloc(sizeof(struct intr_event), M_ITHREAD, M_WAITOK | M_ZERO);
  264         ie->ie_source = source;
  265         ie->ie_pre_ithread = pre_ithread;
  266         ie->ie_post_ithread = post_ithread;
  267         ie->ie_post_filter = post_filter;
  268         ie->ie_assign_cpu = assign_cpu;
  269         ie->ie_flags = flags;
  270         ie->ie_irq = irq;
  271         ie->ie_cpu = NOCPU;
  272         CK_SLIST_INIT(&ie->ie_handlers);
  273         mtx_init(&ie->ie_lock, "intr event", NULL, MTX_DEF);
  274 
  275         va_start(ap, fmt);
  276         vsnprintf(ie->ie_name, sizeof(ie->ie_name), fmt, ap);
  277         va_end(ap);
  278         strlcpy(ie->ie_fullname, ie->ie_name, sizeof(ie->ie_fullname));
  279         mtx_lock(&event_lock);
  280         TAILQ_INSERT_TAIL(&event_list, ie, ie_list);
  281         mtx_unlock(&event_lock);
  282         if (event != NULL)
  283                 *event = ie;
  284         CTR2(KTR_INTR, "%s: created %s", __func__, ie->ie_name);
  285         return (0);
  286 }
  287 
  288 /*
  289  * Bind an interrupt event to the specified CPU.  Note that not all
  290  * platforms support binding an interrupt to a CPU.  For those
  291  * platforms this request will fail.  Using a cpu id of NOCPU unbinds
  292  * the interrupt event.
  293  */
  294 static int
  295 _intr_event_bind(struct intr_event *ie, int cpu, bool bindirq, bool bindithread)
  296 {
  297         lwpid_t id;
  298         int error;
  299 
  300         /* Need a CPU to bind to. */
  301         if (cpu != NOCPU && CPU_ABSENT(cpu))
  302                 return (EINVAL);
  303 
  304         if (ie->ie_assign_cpu == NULL)
  305                 return (EOPNOTSUPP);
  306 
  307         error = priv_check(curthread, PRIV_SCHED_CPUSET_INTR);
  308         if (error)
  309                 return (error);
  310 
  311         /*
  312          * If we have any ithreads try to set their mask first to verify
  313          * permissions, etc.
  314          */
  315         if (bindithread) {
  316                 mtx_lock(&ie->ie_lock);
  317                 if (ie->ie_thread != NULL) {
  318                         id = ie->ie_thread->it_thread->td_tid;
  319                         mtx_unlock(&ie->ie_lock);
  320                         error = cpuset_setithread(id, cpu);
  321                         if (error)
  322                                 return (error);
  323                 } else
  324                         mtx_unlock(&ie->ie_lock);
  325         }
  326         if (bindirq)
  327                 error = ie->ie_assign_cpu(ie->ie_source, cpu);
  328         if (error) {
  329                 if (bindithread) {
  330                         mtx_lock(&ie->ie_lock);
  331                         if (ie->ie_thread != NULL) {
  332                                 cpu = ie->ie_cpu;
  333                                 id = ie->ie_thread->it_thread->td_tid;
  334                                 mtx_unlock(&ie->ie_lock);
  335                                 (void)cpuset_setithread(id, cpu);
  336                         } else
  337                                 mtx_unlock(&ie->ie_lock);
  338                 }
  339                 return (error);
  340         }
  341 
  342         if (bindirq) {
  343                 mtx_lock(&ie->ie_lock);
  344                 ie->ie_cpu = cpu;
  345                 mtx_unlock(&ie->ie_lock);
  346         }
  347 
  348         return (error);
  349 }
  350 
  351 /*
  352  * Bind an interrupt event to the specified CPU.  For supported platforms, any
  353  * associated ithreads as well as the primary interrupt context will be bound
  354  * to the specificed CPU.
  355  */
  356 int
  357 intr_event_bind(struct intr_event *ie, int cpu)
  358 {
  359 
  360         return (_intr_event_bind(ie, cpu, true, true));
  361 }
  362 
  363 /*
  364  * Bind an interrupt event to the specified CPU, but do not bind associated
  365  * ithreads.
  366  */
  367 int
  368 intr_event_bind_irqonly(struct intr_event *ie, int cpu)
  369 {
  370 
  371         return (_intr_event_bind(ie, cpu, true, false));
  372 }
  373 
  374 /*
  375  * Bind an interrupt event's ithread to the specified CPU.
  376  */
  377 int
  378 intr_event_bind_ithread(struct intr_event *ie, int cpu)
  379 {
  380 
  381         return (_intr_event_bind(ie, cpu, false, true));
  382 }
  383 
  384 static struct intr_event *
  385 intr_lookup(int irq)
  386 {
  387         struct intr_event *ie;
  388 
  389         mtx_lock(&event_lock);
  390         TAILQ_FOREACH(ie, &event_list, ie_list)
  391                 if (ie->ie_irq == irq &&
  392                     (ie->ie_flags & IE_SOFT) == 0 &&
  393                     CK_SLIST_FIRST(&ie->ie_handlers) != NULL)
  394                         break;
  395         mtx_unlock(&event_lock);
  396         return (ie);
  397 }
  398 
  399 int
  400 intr_setaffinity(int irq, int mode, void *m)
  401 {
  402         struct intr_event *ie;
  403         cpuset_t *mask;
  404         int cpu, n;
  405 
  406         mask = m;
  407         cpu = NOCPU;
  408         /*
  409          * If we're setting all cpus we can unbind.  Otherwise make sure
  410          * only one cpu is in the set.
  411          */
  412         if (CPU_CMP(cpuset_root, mask)) {
  413                 for (n = 0; n < CPU_SETSIZE; n++) {
  414                         if (!CPU_ISSET(n, mask))
  415                                 continue;
  416                         if (cpu != NOCPU)
  417                                 return (EINVAL);
  418                         cpu = n;
  419                 }
  420         }
  421         ie = intr_lookup(irq);
  422         if (ie == NULL)
  423                 return (ESRCH);
  424         switch (mode) {
  425         case CPU_WHICH_IRQ:
  426                 return (intr_event_bind(ie, cpu));
  427         case CPU_WHICH_INTRHANDLER:
  428                 return (intr_event_bind_irqonly(ie, cpu));
  429         case CPU_WHICH_ITHREAD:
  430                 return (intr_event_bind_ithread(ie, cpu));
  431         default:
  432                 return (EINVAL);
  433         }
  434 }
  435 
  436 int
  437 intr_getaffinity(int irq, int mode, void *m)
  438 {
  439         struct intr_event *ie;
  440         struct thread *td;
  441         struct proc *p;
  442         cpuset_t *mask;
  443         lwpid_t id;
  444         int error;
  445 
  446         mask = m;
  447         ie = intr_lookup(irq);
  448         if (ie == NULL)
  449                 return (ESRCH);
  450 
  451         error = 0;
  452         CPU_ZERO(mask);
  453         switch (mode) {
  454         case CPU_WHICH_IRQ:
  455         case CPU_WHICH_INTRHANDLER:
  456                 mtx_lock(&ie->ie_lock);
  457                 if (ie->ie_cpu == NOCPU)
  458                         CPU_COPY(cpuset_root, mask);
  459                 else
  460                         CPU_SET(ie->ie_cpu, mask);
  461                 mtx_unlock(&ie->ie_lock);
  462                 break;
  463         case CPU_WHICH_ITHREAD:
  464                 mtx_lock(&ie->ie_lock);
  465                 if (ie->ie_thread == NULL) {
  466                         mtx_unlock(&ie->ie_lock);
  467                         CPU_COPY(cpuset_root, mask);
  468                 } else {
  469                         id = ie->ie_thread->it_thread->td_tid;
  470                         mtx_unlock(&ie->ie_lock);
  471                         error = cpuset_which(CPU_WHICH_TID, id, &p, &td, NULL);
  472                         if (error != 0)
  473                                 return (error);
  474                         CPU_COPY(&td->td_cpuset->cs_mask, mask);
  475                         PROC_UNLOCK(p);
  476                 }
  477         default:
  478                 return (EINVAL);
  479         }
  480         return (0);
  481 }
  482 
  483 int
  484 intr_event_destroy(struct intr_event *ie)
  485 {
  486 
  487         mtx_lock(&event_lock);
  488         mtx_lock(&ie->ie_lock);
  489         if (!CK_SLIST_EMPTY(&ie->ie_handlers)) {
  490                 mtx_unlock(&ie->ie_lock);
  491                 mtx_unlock(&event_lock);
  492                 return (EBUSY);
  493         }
  494         TAILQ_REMOVE(&event_list, ie, ie_list);
  495 #ifndef notyet
  496         if (ie->ie_thread != NULL) {
  497                 ithread_destroy(ie->ie_thread);
  498                 ie->ie_thread = NULL;
  499         }
  500 #endif
  501         mtx_unlock(&ie->ie_lock);
  502         mtx_unlock(&event_lock);
  503         mtx_destroy(&ie->ie_lock);
  504         free(ie, M_ITHREAD);
  505         return (0);
  506 }
  507 
  508 static struct intr_thread *
  509 ithread_create(const char *name)
  510 {
  511         struct intr_thread *ithd;
  512         struct thread *td;
  513         int error;
  514 
  515         ithd = malloc(sizeof(struct intr_thread), M_ITHREAD, M_WAITOK | M_ZERO);
  516 
  517         error = kproc_kthread_add(ithread_loop, ithd, &intrproc,
  518                     &td, RFSTOPPED | RFHIGHPID,
  519                     0, "intr", "%s", name);
  520         if (error)
  521                 panic("kproc_create() failed with %d", error);
  522         thread_lock(td);
  523         sched_class(td, PRI_ITHD);
  524         TD_SET_IWAIT(td);
  525         thread_unlock(td);
  526         td->td_pflags |= TDP_ITHREAD;
  527         ithd->it_thread = td;
  528         CTR2(KTR_INTR, "%s: created %s", __func__, name);
  529         return (ithd);
  530 }
  531 
  532 static void
  533 ithread_destroy(struct intr_thread *ithread)
  534 {
  535         struct thread *td;
  536 
  537         CTR2(KTR_INTR, "%s: killing %s", __func__, ithread->it_event->ie_name);
  538         td = ithread->it_thread;
  539         thread_lock(td);
  540         ithread->it_flags |= IT_DEAD;
  541         if (TD_AWAITING_INTR(td)) {
  542                 TD_CLR_IWAIT(td);
  543                 sched_add(td, SRQ_INTR);
  544         }
  545         thread_unlock(td);
  546 }
  547 
  548 int
  549 intr_event_add_handler(struct intr_event *ie, const char *name,
  550     driver_filter_t filter, driver_intr_t handler, void *arg, u_char pri,
  551     enum intr_type flags, void **cookiep)
  552 {
  553         struct intr_handler *ih, *temp_ih;
  554         struct intr_handler **prevptr;
  555         struct intr_thread *it;
  556 
  557         if (ie == NULL || name == NULL || (handler == NULL && filter == NULL))
  558                 return (EINVAL);
  559 
  560         /* Allocate and populate an interrupt handler structure. */
  561         ih = malloc(sizeof(struct intr_handler), M_ITHREAD, M_WAITOK | M_ZERO);
  562         ih->ih_filter = filter;
  563         ih->ih_handler = handler;
  564         ih->ih_argument = arg;
  565         strlcpy(ih->ih_name, name, sizeof(ih->ih_name));
  566         ih->ih_event = ie;
  567         ih->ih_pri = pri;
  568         if (flags & INTR_EXCL)
  569                 ih->ih_flags = IH_EXCLUSIVE;
  570         if (flags & INTR_MPSAFE)
  571                 ih->ih_flags |= IH_MPSAFE;
  572         if (flags & INTR_ENTROPY)
  573                 ih->ih_flags |= IH_ENTROPY;
  574 
  575         /* We can only have one exclusive handler in a event. */
  576         mtx_lock(&ie->ie_lock);
  577         if (!CK_SLIST_EMPTY(&ie->ie_handlers)) {
  578                 if ((flags & INTR_EXCL) ||
  579                     (CK_SLIST_FIRST(&ie->ie_handlers)->ih_flags & IH_EXCLUSIVE)) {
  580                         mtx_unlock(&ie->ie_lock);
  581                         free(ih, M_ITHREAD);
  582                         return (EINVAL);
  583                 }
  584         }
  585 
  586         /* Create a thread if we need one. */
  587         while (ie->ie_thread == NULL && handler != NULL) {
  588                 if (ie->ie_flags & IE_ADDING_THREAD)
  589                         msleep(ie, &ie->ie_lock, 0, "ithread", 0);
  590                 else {
  591                         ie->ie_flags |= IE_ADDING_THREAD;
  592                         mtx_unlock(&ie->ie_lock);
  593                         it = ithread_create("intr: newborn");
  594                         mtx_lock(&ie->ie_lock);
  595                         ie->ie_flags &= ~IE_ADDING_THREAD;
  596                         ie->ie_thread = it;
  597                         it->it_event = ie;
  598                         ithread_update(it);
  599                         wakeup(ie);
  600                 }
  601         }
  602 
  603         /* Add the new handler to the event in priority order. */
  604         CK_SLIST_FOREACH_PREVPTR(temp_ih, prevptr, &ie->ie_handlers, ih_next) {
  605                 if (temp_ih->ih_pri > ih->ih_pri)
  606                         break;
  607         }
  608         CK_SLIST_INSERT_PREVPTR(prevptr, temp_ih, ih, ih_next);
  609 
  610         intr_event_update(ie);
  611 
  612         CTR3(KTR_INTR, "%s: added %s to %s", __func__, ih->ih_name,
  613             ie->ie_name);
  614         mtx_unlock(&ie->ie_lock);
  615 
  616         if (cookiep != NULL)
  617                 *cookiep = ih;
  618         return (0);
  619 }
  620 
  621 /*
  622  * Append a description preceded by a ':' to the name of the specified
  623  * interrupt handler.
  624  */
  625 int
  626 intr_event_describe_handler(struct intr_event *ie, void *cookie,
  627     const char *descr)
  628 {
  629         struct intr_handler *ih;
  630         size_t space;
  631         char *start;
  632 
  633         mtx_lock(&ie->ie_lock);
  634 #ifdef INVARIANTS
  635         CK_SLIST_FOREACH(ih, &ie->ie_handlers, ih_next) {
  636                 if (ih == cookie)
  637                         break;
  638         }
  639         if (ih == NULL) {
  640                 mtx_unlock(&ie->ie_lock);
  641                 panic("handler %p not found in interrupt event %p", cookie, ie);
  642         }
  643 #endif
  644         ih = cookie;
  645 
  646         /*
  647          * Look for an existing description by checking for an
  648          * existing ":".  This assumes device names do not include
  649          * colons.  If one is found, prepare to insert the new
  650          * description at that point.  If one is not found, find the
  651          * end of the name to use as the insertion point.
  652          */
  653         start = strchr(ih->ih_name, ':');
  654         if (start == NULL)
  655                 start = strchr(ih->ih_name, 0);
  656 
  657         /*
  658          * See if there is enough remaining room in the string for the
  659          * description + ":".  The "- 1" leaves room for the trailing
  660          * '\0'.  The "+ 1" accounts for the colon.
  661          */
  662         space = sizeof(ih->ih_name) - (start - ih->ih_name) - 1;
  663         if (strlen(descr) + 1 > space) {
  664                 mtx_unlock(&ie->ie_lock);
  665                 return (ENOSPC);
  666         }
  667 
  668         /* Append a colon followed by the description. */
  669         *start = ':';
  670         strcpy(start + 1, descr);
  671         intr_event_update(ie);
  672         mtx_unlock(&ie->ie_lock);
  673         return (0);
  674 }
  675 
  676 /*
  677  * Return the ie_source field from the intr_event an intr_handler is
  678  * associated with.
  679  */
  680 void *
  681 intr_handler_source(void *cookie)
  682 {
  683         struct intr_handler *ih;
  684         struct intr_event *ie;
  685 
  686         ih = (struct intr_handler *)cookie;
  687         if (ih == NULL)
  688                 return (NULL);
  689         ie = ih->ih_event;
  690         KASSERT(ie != NULL,
  691             ("interrupt handler \"%s\" has a NULL interrupt event",
  692             ih->ih_name));
  693         return (ie->ie_source);
  694 }
  695 
  696 /*
  697  * If intr_event_handle() is running in the ISR context at the time of the call,
  698  * then wait for it to complete.
  699  */
  700 static void
  701 intr_event_barrier(struct intr_event *ie)
  702 {
  703         int phase;
  704 
  705         mtx_assert(&ie->ie_lock, MA_OWNED);
  706         phase = ie->ie_phase;
  707 
  708         /*
  709          * Switch phase to direct future interrupts to the other active counter.
  710          * Make sure that any preceding stores are visible before the switch.
  711          */
  712         KASSERT(ie->ie_active[!phase] == 0, ("idle phase has activity"));
  713         atomic_store_rel_int(&ie->ie_phase, !phase);
  714 
  715         /*
  716          * This code cooperates with wait-free iteration of ie_handlers
  717          * in intr_event_handle.
  718          * Make sure that the removal and the phase update are not reordered
  719          * with the active count check.
  720          * Note that no combination of acquire and release fences can provide
  721          * that guarantee as Store->Load sequences can always be reordered.
  722          */
  723         atomic_thread_fence_seq_cst();
  724 
  725         /*
  726          * Now wait on the inactive phase.
  727          * The acquire fence is needed so that all post-barrier accesses
  728          * are after the check.
  729          */
  730         while (ie->ie_active[phase] > 0)
  731                 cpu_spinwait();
  732         atomic_thread_fence_acq();
  733 }
  734 
  735 static void
  736 intr_handler_barrier(struct intr_handler *handler)
  737 {
  738         struct intr_event *ie;
  739 
  740         ie = handler->ih_event;
  741         mtx_assert(&ie->ie_lock, MA_OWNED);
  742         KASSERT((handler->ih_flags & IH_DEAD) == 0,
  743             ("update for a removed handler"));
  744 
  745         if (ie->ie_thread == NULL) {
  746                 intr_event_barrier(ie);
  747                 return;
  748         }
  749         if ((handler->ih_flags & IH_CHANGED) == 0) {
  750                 handler->ih_flags |= IH_CHANGED;
  751                 intr_event_schedule_thread(ie);
  752         }
  753         while ((handler->ih_flags & IH_CHANGED) != 0)
  754                 msleep(handler, &ie->ie_lock, 0, "ih_barr", 0);
  755 }
  756 
  757 /*
  758  * Sleep until an ithread finishes executing an interrupt handler.
  759  *
  760  * XXX Doesn't currently handle interrupt filters or fast interrupt
  761  * handlers. This is intended for LinuxKPI drivers only.
  762  * Do not use in BSD code.
  763  */
  764 void
  765 _intr_drain(int irq)
  766 {
  767         struct intr_event *ie;
  768         struct intr_thread *ithd;
  769         struct thread *td;
  770 
  771         ie = intr_lookup(irq);
  772         if (ie == NULL)
  773                 return;
  774         if (ie->ie_thread == NULL)
  775                 return;
  776         ithd = ie->ie_thread;
  777         td = ithd->it_thread;
  778         /*
  779          * We set the flag and wait for it to be cleared to avoid
  780          * long delays with potentially busy interrupt handlers
  781          * were we to only sample TD_AWAITING_INTR() every tick.
  782          */
  783         thread_lock(td);
  784         if (!TD_AWAITING_INTR(td)) {
  785                 ithd->it_flags |= IT_WAIT;
  786                 while (ithd->it_flags & IT_WAIT) {
  787                         thread_unlock(td);
  788                         pause("idrain", 1);
  789                         thread_lock(td);
  790                 }
  791         }
  792         thread_unlock(td);
  793         return;
  794 }
  795 
  796 int
  797 intr_event_remove_handler(void *cookie)
  798 {
  799         struct intr_handler *handler = (struct intr_handler *)cookie;
  800         struct intr_event *ie;
  801         struct intr_handler *ih;
  802         struct intr_handler **prevptr;
  803 #ifdef notyet
  804         int dead;
  805 #endif
  806 
  807         if (handler == NULL)
  808                 return (EINVAL);
  809         ie = handler->ih_event;
  810         KASSERT(ie != NULL,
  811             ("interrupt handler \"%s\" has a NULL interrupt event",
  812             handler->ih_name));
  813 
  814         mtx_lock(&ie->ie_lock);
  815         CTR3(KTR_INTR, "%s: removing %s from %s", __func__, handler->ih_name,
  816             ie->ie_name);
  817         CK_SLIST_FOREACH_PREVPTR(ih, prevptr, &ie->ie_handlers, ih_next) {
  818                 if (ih == handler)
  819                         break;
  820         }
  821         if (ih == NULL) {
  822                 panic("interrupt handler \"%s\" not found in "
  823                     "interrupt event \"%s\"", handler->ih_name, ie->ie_name);
  824         }
  825 
  826         /*
  827          * If there is no ithread, then directly remove the handler.  Note that
  828          * intr_event_handle() iterates ie_handlers in a lock-less fashion, so
  829          * care needs to be taken to keep ie_handlers consistent and to free
  830          * the removed handler only when ie_handlers is quiescent.
  831          */
  832         if (ie->ie_thread == NULL) {
  833                 CK_SLIST_REMOVE_PREVPTR(prevptr, ih, ih_next);
  834                 intr_event_barrier(ie);
  835                 intr_event_update(ie);
  836                 mtx_unlock(&ie->ie_lock);
  837                 free(handler, M_ITHREAD);
  838                 return (0);
  839         }
  840 
  841         /*
  842          * Let the interrupt thread do the job.
  843          * The interrupt source is disabled when the interrupt thread is
  844          * running, so it does not have to worry about interaction with
  845          * intr_event_handle().
  846          */
  847         KASSERT((handler->ih_flags & IH_DEAD) == 0,
  848             ("duplicate handle remove"));
  849         handler->ih_flags |= IH_DEAD;
  850         intr_event_schedule_thread(ie);
  851         while (handler->ih_flags & IH_DEAD)
  852                 msleep(handler, &ie->ie_lock, 0, "iev_rmh", 0);
  853         intr_event_update(ie);
  854 
  855 #ifdef notyet
  856         /*
  857          * XXX: This could be bad in the case of ppbus(8).  Also, I think
  858          * this could lead to races of stale data when servicing an
  859          * interrupt.
  860          */
  861         dead = 1;
  862         CK_SLIST_FOREACH(ih, &ie->ie_handlers, ih_next) {
  863                 if (ih->ih_handler != NULL) {
  864                         dead = 0;
  865                         break;
  866                 }
  867         }
  868         if (dead) {
  869                 ithread_destroy(ie->ie_thread);
  870                 ie->ie_thread = NULL;
  871         }
  872 #endif
  873         mtx_unlock(&ie->ie_lock);
  874         free(handler, M_ITHREAD);
  875         return (0);
  876 }
  877 
  878 int
  879 intr_event_suspend_handler(void *cookie)
  880 {
  881         struct intr_handler *handler = (struct intr_handler *)cookie;
  882         struct intr_event *ie;
  883 
  884         if (handler == NULL)
  885                 return (EINVAL);
  886         ie = handler->ih_event;
  887         KASSERT(ie != NULL,
  888             ("interrupt handler \"%s\" has a NULL interrupt event",
  889             handler->ih_name));
  890         mtx_lock(&ie->ie_lock);
  891         handler->ih_flags |= IH_SUSP;
  892         intr_handler_barrier(handler);
  893         mtx_unlock(&ie->ie_lock);
  894         return (0);
  895 }
  896 
  897 int
  898 intr_event_resume_handler(void *cookie)
  899 {
  900         struct intr_handler *handler = (struct intr_handler *)cookie;
  901         struct intr_event *ie;
  902 
  903         if (handler == NULL)
  904                 return (EINVAL);
  905         ie = handler->ih_event;
  906         KASSERT(ie != NULL,
  907             ("interrupt handler \"%s\" has a NULL interrupt event",
  908             handler->ih_name));
  909 
  910         /*
  911          * intr_handler_barrier() acts not only as a barrier,
  912          * it also allows to check for any pending interrupts.
  913          */
  914         mtx_lock(&ie->ie_lock);
  915         handler->ih_flags &= ~IH_SUSP;
  916         intr_handler_barrier(handler);
  917         mtx_unlock(&ie->ie_lock);
  918         return (0);
  919 }
  920 
  921 static int
  922 intr_event_schedule_thread(struct intr_event *ie)
  923 {
  924         struct intr_entropy entropy;
  925         struct intr_thread *it;
  926         struct thread *td;
  927         struct thread *ctd;
  928 
  929         /*
  930          * If no ithread or no handlers, then we have a stray interrupt.
  931          */
  932         if (ie == NULL || CK_SLIST_EMPTY(&ie->ie_handlers) ||
  933             ie->ie_thread == NULL)
  934                 return (EINVAL);
  935 
  936         ctd = curthread;
  937         it = ie->ie_thread;
  938         td = it->it_thread;
  939 
  940         /*
  941          * If any of the handlers for this ithread claim to be good
  942          * sources of entropy, then gather some.
  943          */
  944         if (ie->ie_flags & IE_ENTROPY) {
  945                 entropy.event = (uintptr_t)ie;
  946                 entropy.td = ctd;
  947                 random_harvest_queue(&entropy, sizeof(entropy), RANDOM_INTERRUPT);
  948         }
  949 
  950         KASSERT(td->td_proc != NULL, ("ithread %s has no process", ie->ie_name));
  951 
  952         /*
  953          * Set it_need to tell the thread to keep running if it is already
  954          * running.  Then, lock the thread and see if we actually need to
  955          * put it on the runqueue.
  956          *
  957          * Use store_rel to arrange that the store to ih_need in
  958          * swi_sched() is before the store to it_need and prepare for
  959          * transfer of this order to loads in the ithread.
  960          */
  961         atomic_store_rel_int(&it->it_need, 1);
  962         thread_lock(td);
  963         if (TD_AWAITING_INTR(td)) {
  964                 CTR3(KTR_INTR, "%s: schedule pid %d (%s)", __func__, td->td_proc->p_pid,
  965                     td->td_name);
  966                 TD_CLR_IWAIT(td);
  967                 sched_add(td, SRQ_INTR);
  968         } else {
  969                 CTR5(KTR_INTR, "%s: pid %d (%s): it_need %d, state %d",
  970                     __func__, td->td_proc->p_pid, td->td_name, it->it_need, td->td_state);
  971         }
  972         thread_unlock(td);
  973 
  974         return (0);
  975 }
  976 
  977 /*
  978  * Allow interrupt event binding for software interrupt handlers -- a no-op,
  979  * since interrupts are generated in software rather than being directed by
  980  * a PIC.
  981  */
  982 static int
  983 swi_assign_cpu(void *arg, int cpu)
  984 {
  985 
  986         return (0);
  987 }
  988 
  989 /*
  990  * Add a software interrupt handler to a specified event.  If a given event
  991  * is not specified, then a new event is created.
  992  */
  993 int
  994 swi_add(struct intr_event **eventp, const char *name, driver_intr_t handler,
  995             void *arg, int pri, enum intr_type flags, void **cookiep)
  996 {
  997         struct intr_event *ie;
  998         int error = 0;
  999 
 1000         if (flags & INTR_ENTROPY)
 1001                 return (EINVAL);
 1002 
 1003         ie = (eventp != NULL) ? *eventp : NULL;
 1004 
 1005         if (ie != NULL) {
 1006                 if (!(ie->ie_flags & IE_SOFT))
 1007                         return (EINVAL);
 1008         } else {
 1009                 error = intr_event_create(&ie, NULL, IE_SOFT, 0,
 1010                     NULL, NULL, NULL, swi_assign_cpu, "swi%d:", pri);
 1011                 if (error)
 1012                         return (error);
 1013                 if (eventp != NULL)
 1014                         *eventp = ie;
 1015         }
 1016         if (handler != NULL) {
 1017                 error = intr_event_add_handler(ie, name, NULL, handler, arg,
 1018                     PI_SWI(pri), flags, cookiep);
 1019         }
 1020         return (error);
 1021 }
 1022 
 1023 /*
 1024  * Schedule a software interrupt thread.
 1025  */
 1026 void
 1027 swi_sched(void *cookie, int flags)
 1028 {
 1029         struct intr_handler *ih = (struct intr_handler *)cookie;
 1030         struct intr_event *ie = ih->ih_event;
 1031         struct intr_entropy entropy;
 1032         int error __unused;
 1033 
 1034         CTR3(KTR_INTR, "swi_sched: %s %s need=%d", ie->ie_name, ih->ih_name,
 1035             ih->ih_need);
 1036 
 1037         if ((flags & SWI_FROMNMI) == 0) {
 1038                 entropy.event = (uintptr_t)ih;
 1039                 entropy.td = curthread;
 1040                 random_harvest_queue(&entropy, sizeof(entropy), RANDOM_SWI);
 1041         }
 1042 
 1043         /*
 1044          * Set ih_need for this handler so that if the ithread is already
 1045          * running it will execute this handler on the next pass.  Otherwise,
 1046          * it will execute it the next time it runs.
 1047          */
 1048         ih->ih_need = 1;
 1049 
 1050         if (flags & SWI_DELAY)
 1051                 return;
 1052 
 1053         if (flags & SWI_FROMNMI) {
 1054 #if defined(SMP) && (defined(__i386__) || defined(__amd64__))
 1055                 KASSERT(ie == clk_intr_event,
 1056                     ("SWI_FROMNMI used not with clk_intr_event"));
 1057                 ipi_self_from_nmi(IPI_SWI);
 1058 #endif
 1059         } else {
 1060                 VM_CNT_INC(v_soft);
 1061                 error = intr_event_schedule_thread(ie);
 1062                 KASSERT(error == 0, ("stray software interrupt"));
 1063         }
 1064 }
 1065 
 1066 /*
 1067  * Remove a software interrupt handler.  Currently this code does not
 1068  * remove the associated interrupt event if it becomes empty.  Calling code
 1069  * may do so manually via intr_event_destroy(), but that's not really
 1070  * an optimal interface.
 1071  */
 1072 int
 1073 swi_remove(void *cookie)
 1074 {
 1075 
 1076         return (intr_event_remove_handler(cookie));
 1077 }
 1078 
 1079 static void
 1080 intr_event_execute_handlers(struct proc *p, struct intr_event *ie)
 1081 {
 1082         struct intr_handler *ih, *ihn, *ihp;
 1083 
 1084         ihp = NULL;
 1085         CK_SLIST_FOREACH_SAFE(ih, &ie->ie_handlers, ih_next, ihn) {
 1086                 /*
 1087                  * If this handler is marked for death, remove it from
 1088                  * the list of handlers and wake up the sleeper.
 1089                  */
 1090                 if (ih->ih_flags & IH_DEAD) {
 1091                         mtx_lock(&ie->ie_lock);
 1092                         if (ihp == NULL)
 1093                                 CK_SLIST_REMOVE_HEAD(&ie->ie_handlers, ih_next);
 1094                         else
 1095                                 CK_SLIST_REMOVE_AFTER(ihp, ih_next);
 1096                         ih->ih_flags &= ~IH_DEAD;
 1097                         wakeup(ih);
 1098                         mtx_unlock(&ie->ie_lock);
 1099                         continue;
 1100                 }
 1101 
 1102                 /*
 1103                  * Now that we know that the current element won't be removed
 1104                  * update the previous element.
 1105                  */
 1106                 ihp = ih;
 1107 
 1108                 if ((ih->ih_flags & IH_CHANGED) != 0) {
 1109                         mtx_lock(&ie->ie_lock);
 1110                         ih->ih_flags &= ~IH_CHANGED;
 1111                         wakeup(ih);
 1112                         mtx_unlock(&ie->ie_lock);
 1113                 }
 1114 
 1115                 /* Skip filter only handlers */
 1116                 if (ih->ih_handler == NULL)
 1117                         continue;
 1118 
 1119                 /* Skip suspended handlers */
 1120                 if ((ih->ih_flags & IH_SUSP) != 0)
 1121                         continue;
 1122 
 1123                 /*
 1124                  * For software interrupt threads, we only execute
 1125                  * handlers that have their need flag set.  Hardware
 1126                  * interrupt threads always invoke all of their handlers.
 1127                  *
 1128                  * ih_need can only be 0 or 1.  Failed cmpset below
 1129                  * means that there is no request to execute handlers,
 1130                  * so a retry of the cmpset is not needed.
 1131                  */
 1132                 if ((ie->ie_flags & IE_SOFT) != 0 &&
 1133                     atomic_cmpset_int(&ih->ih_need, 1, 0) == 0)
 1134                         continue;
 1135 
 1136                 /* Execute this handler. */
 1137                 CTR6(KTR_INTR, "%s: pid %d exec %p(%p) for %s flg=%x",
 1138                     __func__, p->p_pid, (void *)ih->ih_handler, 
 1139                     ih->ih_argument, ih->ih_name, ih->ih_flags);
 1140 
 1141                 if (!(ih->ih_flags & IH_MPSAFE))
 1142                         mtx_lock(&Giant);
 1143                 ih->ih_handler(ih->ih_argument);
 1144                 if (!(ih->ih_flags & IH_MPSAFE))
 1145                         mtx_unlock(&Giant);
 1146         }
 1147 }
 1148 
 1149 static void
 1150 ithread_execute_handlers(struct proc *p, struct intr_event *ie)
 1151 {
 1152 
 1153         /* Interrupt handlers should not sleep. */
 1154         if (!(ie->ie_flags & IE_SOFT))
 1155                 THREAD_NO_SLEEPING();
 1156         intr_event_execute_handlers(p, ie);
 1157         if (!(ie->ie_flags & IE_SOFT))
 1158                 THREAD_SLEEPING_OK();
 1159 
 1160         /*
 1161          * Interrupt storm handling:
 1162          *
 1163          * If this interrupt source is currently storming, then throttle
 1164          * it to only fire the handler once  per clock tick.
 1165          *
 1166          * If this interrupt source is not currently storming, but the
 1167          * number of back to back interrupts exceeds the storm threshold,
 1168          * then enter storming mode.
 1169          */
 1170         if (intr_storm_threshold != 0 && ie->ie_count >= intr_storm_threshold &&
 1171             !(ie->ie_flags & IE_SOFT)) {
 1172                 /* Report the message only once every second. */
 1173                 if (ppsratecheck(&ie->ie_warntm, &ie->ie_warncnt, 1)) {
 1174                         printf(
 1175         "interrupt storm detected on \"%s\"; throttling interrupt source\n",
 1176                             ie->ie_name);
 1177                 }
 1178                 pause("istorm", 1);
 1179         } else
 1180                 ie->ie_count++;
 1181 
 1182         /*
 1183          * Now that all the handlers have had a chance to run, reenable
 1184          * the interrupt source.
 1185          */
 1186         if (ie->ie_post_ithread != NULL)
 1187                 ie->ie_post_ithread(ie->ie_source);
 1188 }
 1189 
 1190 /*
 1191  * This is the main code for interrupt threads.
 1192  */
 1193 static void
 1194 ithread_loop(void *arg)
 1195 {
 1196         struct intr_thread *ithd;
 1197         struct intr_event *ie;
 1198         struct thread *td;
 1199         struct proc *p;
 1200         int wake;
 1201 
 1202         td = curthread;
 1203         p = td->td_proc;
 1204         ithd = (struct intr_thread *)arg;
 1205         KASSERT(ithd->it_thread == td,
 1206             ("%s: ithread and proc linkage out of sync", __func__));
 1207         ie = ithd->it_event;
 1208         ie->ie_count = 0;
 1209         wake = 0;
 1210 
 1211         /*
 1212          * As long as we have interrupts outstanding, go through the
 1213          * list of handlers, giving each one a go at it.
 1214          */
 1215         for (;;) {
 1216                 /*
 1217                  * If we are an orphaned thread, then just die.
 1218                  */
 1219                 if (ithd->it_flags & IT_DEAD) {
 1220                         CTR3(KTR_INTR, "%s: pid %d (%s) exiting", __func__,
 1221                             p->p_pid, td->td_name);
 1222                         free(ithd, M_ITHREAD);
 1223                         kthread_exit();
 1224                 }
 1225 
 1226                 /*
 1227                  * Service interrupts.  If another interrupt arrives while
 1228                  * we are running, it will set it_need to note that we
 1229                  * should make another pass.
 1230                  *
 1231                  * The load_acq part of the following cmpset ensures
 1232                  * that the load of ih_need in ithread_execute_handlers()
 1233                  * is ordered after the load of it_need here.
 1234                  */
 1235                 while (atomic_cmpset_acq_int(&ithd->it_need, 1, 0) != 0)
 1236                         ithread_execute_handlers(p, ie);
 1237                 WITNESS_WARN(WARN_PANIC, NULL, "suspending ithread");
 1238                 mtx_assert(&Giant, MA_NOTOWNED);
 1239 
 1240                 /*
 1241                  * Processed all our interrupts.  Now get the sched
 1242                  * lock.  This may take a while and it_need may get
 1243                  * set again, so we have to check it again.
 1244                  */
 1245                 thread_lock(td);
 1246                 if (atomic_load_acq_int(&ithd->it_need) == 0 &&
 1247                     (ithd->it_flags & (IT_DEAD | IT_WAIT)) == 0) {
 1248                         TD_SET_IWAIT(td);
 1249                         ie->ie_count = 0;
 1250                         mi_switch(SW_VOL | SWT_IWAIT, NULL);
 1251                 }
 1252                 if (ithd->it_flags & IT_WAIT) {
 1253                         wake = 1;
 1254                         ithd->it_flags &= ~IT_WAIT;
 1255                 }
 1256                 thread_unlock(td);
 1257                 if (wake) {
 1258                         wakeup(ithd);
 1259                         wake = 0;
 1260                 }
 1261         }
 1262 }
 1263 
 1264 /*
 1265  * Main interrupt handling body.
 1266  *
 1267  * Input:
 1268  * o ie:                        the event connected to this interrupt.
 1269  * o frame:                     some archs (i.e. i386) pass a frame to some.
 1270  *                              handlers as their main argument.
 1271  * Return value:
 1272  * o 0:                         everything ok.
 1273  * o EINVAL:                    stray interrupt.
 1274  */
 1275 int
 1276 intr_event_handle(struct intr_event *ie, struct trapframe *frame)
 1277 {
 1278         struct intr_handler *ih;
 1279         struct trapframe *oldframe;
 1280         struct thread *td;
 1281         int phase;
 1282         int ret;
 1283         bool filter, thread;
 1284 
 1285         td = curthread;
 1286 
 1287 #ifdef KSTACK_USAGE_PROF
 1288         intr_prof_stack_use(td, frame);
 1289 #endif
 1290 
 1291         /* An interrupt with no event or handlers is a stray interrupt. */
 1292         if (ie == NULL || CK_SLIST_EMPTY(&ie->ie_handlers))
 1293                 return (EINVAL);
 1294 
 1295         /*
 1296          * Execute fast interrupt handlers directly.
 1297          * To support clock handlers, if a handler registers
 1298          * with a NULL argument, then we pass it a pointer to
 1299          * a trapframe as its argument.
 1300          */
 1301         td->td_intr_nesting_level++;
 1302         filter = false;
 1303         thread = false;
 1304         ret = 0;
 1305         critical_enter();
 1306         oldframe = td->td_intr_frame;
 1307         td->td_intr_frame = frame;
 1308 
 1309         phase = ie->ie_phase;
 1310         atomic_add_int(&ie->ie_active[phase], 1);
 1311 
 1312         /*
 1313          * This fence is required to ensure that no later loads are
 1314          * re-ordered before the ie_active store.
 1315          */
 1316         atomic_thread_fence_seq_cst();
 1317 
 1318         CK_SLIST_FOREACH(ih, &ie->ie_handlers, ih_next) {
 1319                 if ((ih->ih_flags & IH_SUSP) != 0)
 1320                         continue;
 1321                 if ((ie->ie_flags & IE_SOFT) != 0 && ih->ih_need == 0)
 1322                         continue;
 1323                 if (ih->ih_filter == NULL) {
 1324                         thread = true;
 1325                         continue;
 1326                 }
 1327                 CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__,
 1328                     ih->ih_filter, ih->ih_argument == NULL ? frame :
 1329                     ih->ih_argument, ih->ih_name);
 1330                 if (ih->ih_argument == NULL)
 1331                         ret = ih->ih_filter(frame);
 1332                 else
 1333                         ret = ih->ih_filter(ih->ih_argument);
 1334                 KASSERT(ret == FILTER_STRAY ||
 1335                     ((ret & (FILTER_SCHEDULE_THREAD | FILTER_HANDLED)) != 0 &&
 1336                     (ret & ~(FILTER_SCHEDULE_THREAD | FILTER_HANDLED)) == 0),
 1337                     ("%s: incorrect return value %#x from %s", __func__, ret,
 1338                     ih->ih_name));
 1339                 filter = filter || ret == FILTER_HANDLED;
 1340 
 1341                 /*
 1342                  * Wrapper handler special handling:
 1343                  *
 1344                  * in some particular cases (like pccard and pccbb),
 1345                  * the _real_ device handler is wrapped in a couple of
 1346                  * functions - a filter wrapper and an ithread wrapper.
 1347                  * In this case (and just in this case), the filter wrapper
 1348                  * could ask the system to schedule the ithread and mask
 1349                  * the interrupt source if the wrapped handler is composed
 1350                  * of just an ithread handler.
 1351                  *
 1352                  * TODO: write a generic wrapper to avoid people rolling
 1353                  * their own.
 1354                  */
 1355                 if (!thread) {
 1356                         if (ret == FILTER_SCHEDULE_THREAD)
 1357                                 thread = true;
 1358                 }
 1359         }
 1360         atomic_add_rel_int(&ie->ie_active[phase], -1);
 1361 
 1362         td->td_intr_frame = oldframe;
 1363 
 1364         if (thread) {
 1365                 if (ie->ie_pre_ithread != NULL)
 1366                         ie->ie_pre_ithread(ie->ie_source);
 1367         } else {
 1368                 if (ie->ie_post_filter != NULL)
 1369                         ie->ie_post_filter(ie->ie_source);
 1370         }
 1371 
 1372         /* Schedule the ithread if needed. */
 1373         if (thread) {
 1374                 int error __unused;
 1375 
 1376                 error =  intr_event_schedule_thread(ie);
 1377                 KASSERT(error == 0, ("bad stray interrupt"));
 1378         }
 1379         critical_exit();
 1380         td->td_intr_nesting_level--;
 1381 #ifdef notyet
 1382         /* The interrupt is not aknowledged by any filter and has no ithread. */
 1383         if (!thread && !filter)
 1384                 return (EINVAL);
 1385 #endif
 1386         return (0);
 1387 }
 1388 
 1389 #ifdef DDB
 1390 /*
 1391  * Dump details about an interrupt handler
 1392  */
 1393 static void
 1394 db_dump_intrhand(struct intr_handler *ih)
 1395 {
 1396         int comma;
 1397 
 1398         db_printf("\t%-10s ", ih->ih_name);
 1399         switch (ih->ih_pri) {
 1400         case PI_REALTIME:
 1401                 db_printf("CLK ");
 1402                 break;
 1403         case PI_AV:
 1404                 db_printf("AV  ");
 1405                 break;
 1406         case PI_TTY:
 1407                 db_printf("TTY ");
 1408                 break;
 1409         case PI_NET:
 1410                 db_printf("NET ");
 1411                 break;
 1412         case PI_DISK:
 1413                 db_printf("DISK");
 1414                 break;
 1415         case PI_DULL:
 1416                 db_printf("DULL");
 1417                 break;
 1418         default:
 1419                 if (ih->ih_pri >= PI_SOFT)
 1420                         db_printf("SWI ");
 1421                 else
 1422                         db_printf("%4u", ih->ih_pri);
 1423                 break;
 1424         }
 1425         db_printf(" ");
 1426         if (ih->ih_filter != NULL) {
 1427                 db_printf("[F]");
 1428                 db_printsym((uintptr_t)ih->ih_filter, DB_STGY_PROC);
 1429         }
 1430         if (ih->ih_handler != NULL) {
 1431                 if (ih->ih_filter != NULL)
 1432                         db_printf(",");
 1433                 db_printf("[H]");
 1434                 db_printsym((uintptr_t)ih->ih_handler, DB_STGY_PROC);
 1435         }
 1436         db_printf("(%p)", ih->ih_argument);
 1437         if (ih->ih_need ||
 1438             (ih->ih_flags & (IH_EXCLUSIVE | IH_ENTROPY | IH_DEAD |
 1439             IH_MPSAFE)) != 0) {
 1440                 db_printf(" {");
 1441                 comma = 0;
 1442                 if (ih->ih_flags & IH_EXCLUSIVE) {
 1443                         if (comma)
 1444                                 db_printf(", ");
 1445                         db_printf("EXCL");
 1446                         comma = 1;
 1447                 }
 1448                 if (ih->ih_flags & IH_ENTROPY) {
 1449                         if (comma)
 1450                                 db_printf(", ");
 1451                         db_printf("ENTROPY");
 1452                         comma = 1;
 1453                 }
 1454                 if (ih->ih_flags & IH_DEAD) {
 1455                         if (comma)
 1456                                 db_printf(", ");
 1457                         db_printf("DEAD");
 1458                         comma = 1;
 1459                 }
 1460                 if (ih->ih_flags & IH_MPSAFE) {
 1461                         if (comma)
 1462                                 db_printf(", ");
 1463                         db_printf("MPSAFE");
 1464                         comma = 1;
 1465                 }
 1466                 if (ih->ih_need) {
 1467                         if (comma)
 1468                                 db_printf(", ");
 1469                         db_printf("NEED");
 1470                 }
 1471                 db_printf("}");
 1472         }
 1473         db_printf("\n");
 1474 }
 1475 
 1476 /*
 1477  * Dump details about a event.
 1478  */
 1479 void
 1480 db_dump_intr_event(struct intr_event *ie, int handlers)
 1481 {
 1482         struct intr_handler *ih;
 1483         struct intr_thread *it;
 1484         int comma;
 1485 
 1486         db_printf("%s ", ie->ie_fullname);
 1487         it = ie->ie_thread;
 1488         if (it != NULL)
 1489                 db_printf("(pid %d)", it->it_thread->td_proc->p_pid);
 1490         else
 1491                 db_printf("(no thread)");
 1492         if ((ie->ie_flags & (IE_SOFT | IE_ENTROPY | IE_ADDING_THREAD)) != 0 ||
 1493             (it != NULL && it->it_need)) {
 1494                 db_printf(" {");
 1495                 comma = 0;
 1496                 if (ie->ie_flags & IE_SOFT) {
 1497                         db_printf("SOFT");
 1498                         comma = 1;
 1499                 }
 1500                 if (ie->ie_flags & IE_ENTROPY) {
 1501                         if (comma)
 1502                                 db_printf(", ");
 1503                         db_printf("ENTROPY");
 1504                         comma = 1;
 1505                 }
 1506                 if (ie->ie_flags & IE_ADDING_THREAD) {
 1507                         if (comma)
 1508                                 db_printf(", ");
 1509                         db_printf("ADDING_THREAD");
 1510                         comma = 1;
 1511                 }
 1512                 if (it != NULL && it->it_need) {
 1513                         if (comma)
 1514                                 db_printf(", ");
 1515                         db_printf("NEED");
 1516                 }
 1517                 db_printf("}");
 1518         }
 1519         db_printf("\n");
 1520 
 1521         if (handlers)
 1522                 CK_SLIST_FOREACH(ih, &ie->ie_handlers, ih_next)
 1523                     db_dump_intrhand(ih);
 1524 }
 1525 
 1526 /*
 1527  * Dump data about interrupt handlers
 1528  */
 1529 DB_SHOW_COMMAND(intr, db_show_intr)
 1530 {
 1531         struct intr_event *ie;
 1532         int all, verbose;
 1533 
 1534         verbose = strchr(modif, 'v') != NULL;
 1535         all = strchr(modif, 'a') != NULL;
 1536         TAILQ_FOREACH(ie, &event_list, ie_list) {
 1537                 if (!all && CK_SLIST_EMPTY(&ie->ie_handlers))
 1538                         continue;
 1539                 db_dump_intr_event(ie, verbose);
 1540                 if (db_pager_quit)
 1541                         break;
 1542         }
 1543 }
 1544 #endif /* DDB */
 1545 
 1546 /*
 1547  * Start standard software interrupt threads
 1548  */
 1549 static void
 1550 start_softintr(void *dummy)
 1551 {
 1552 
 1553         if (swi_add(NULL, "vm", swi_vm, NULL, SWI_VM, INTR_MPSAFE, &vm_ih))
 1554                 panic("died while creating vm swi ithread");
 1555 }
 1556 SYSINIT(start_softintr, SI_SUB_SOFTINTR, SI_ORDER_FIRST, start_softintr,
 1557     NULL);
 1558 
 1559 /*
 1560  * Sysctls used by systat and others: hw.intrnames and hw.intrcnt.
 1561  * The data for this machine dependent, and the declarations are in machine
 1562  * dependent code.  The layout of intrnames and intrcnt however is machine
 1563  * independent.
 1564  *
 1565  * We do not know the length of intrcnt and intrnames at compile time, so
 1566  * calculate things at run time.
 1567  */
 1568 static int
 1569 sysctl_intrnames(SYSCTL_HANDLER_ARGS)
 1570 {
 1571         return (sysctl_handle_opaque(oidp, intrnames, sintrnames, req));
 1572 }
 1573 
 1574 SYSCTL_PROC(_hw, OID_AUTO, intrnames, CTLTYPE_OPAQUE | CTLFLAG_RD,
 1575     NULL, 0, sysctl_intrnames, "", "Interrupt Names");
 1576 
 1577 static int
 1578 sysctl_intrcnt(SYSCTL_HANDLER_ARGS)
 1579 {
 1580 #ifdef SCTL_MASK32
 1581         uint32_t *intrcnt32;
 1582         unsigned i;
 1583         int error;
 1584 
 1585         if (req->flags & SCTL_MASK32) {
 1586                 if (!req->oldptr)
 1587                         return (sysctl_handle_opaque(oidp, NULL, sintrcnt / 2, req));
 1588                 intrcnt32 = malloc(sintrcnt / 2, M_TEMP, M_NOWAIT);
 1589                 if (intrcnt32 == NULL)
 1590                         return (ENOMEM);
 1591                 for (i = 0; i < sintrcnt / sizeof (u_long); i++)
 1592                         intrcnt32[i] = intrcnt[i];
 1593                 error = sysctl_handle_opaque(oidp, intrcnt32, sintrcnt / 2, req);
 1594                 free(intrcnt32, M_TEMP);
 1595                 return (error);
 1596         }
 1597 #endif
 1598         return (sysctl_handle_opaque(oidp, intrcnt, sintrcnt, req));
 1599 }
 1600 
 1601 SYSCTL_PROC(_hw, OID_AUTO, intrcnt, CTLTYPE_OPAQUE | CTLFLAG_RD,
 1602     NULL, 0, sysctl_intrcnt, "", "Interrupt Counts");
 1603 
 1604 #ifdef DDB
 1605 /*
 1606  * DDB command to dump the interrupt statistics.
 1607  */
 1608 DB_SHOW_COMMAND(intrcnt, db_show_intrcnt)
 1609 {
 1610         u_long *i;
 1611         char *cp;
 1612         u_int j;
 1613 
 1614         cp = intrnames;
 1615         j = 0;
 1616         for (i = intrcnt; j < (sintrcnt / sizeof(u_long)) && !db_pager_quit;
 1617             i++, j++) {
 1618                 if (*cp == '\0')
 1619                         break;
 1620                 if (*i != 0)
 1621                         db_printf("%s\t%lu\n", cp, *i);
 1622                 cp += strlen(cp) + 1;
 1623         }
 1624 }
 1625 #endif

Cache object: 1be81c0e172786b32a81b216fef1c4b2


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.