source: rtems-libbsd/freebsd/sys/kern/kern_intr.c @ 32fd702

55-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 32fd702 was 32fd702, checked in by Sebastian Huber <sebastian.huber@…>, on 06/23/16 at 12:06:21

Update due to RTEMS printer API changes

  • Property mode set to 100644
File size: 50.2 KB
Line 
1#include <machine/rtems-bsd-kernel-space.h>
2
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 <rtems/bsd/local/opt_ddb.h>
33
34#include <rtems/bsd/sys/param.h>
35#include <sys/bus.h>
36#include <sys/conf.h>
37#include <rtems/bsd/sys/cpuset.h>
38#include <sys/rtprio.h>
39#include <sys/systm.h>
40#include <sys/interrupt.h>
41#include <sys/kernel.h>
42#include <sys/kthread.h>
43#include <sys/ktr.h>
44#include <sys/limits.h>
45#include <rtems/bsd/sys/lock.h>
46#include <sys/malloc.h>
47#include <sys/mutex.h>
48#include <sys/priv.h>
49#include <sys/proc.h>
50#include <sys/random.h>
51#include <sys/resourcevar.h>
52#include <sys/sched.h>
53#include <sys/smp.h>
54#include <sys/sysctl.h>
55#include <sys/syslog.h>
56#include <rtems/bsd/sys/unistd.h>
57#include <sys/vmmeter.h>
58#include <machine/atomic.h>
59#include <machine/cpu.h>
60#ifndef __rtems__
61#include <machine/md_var.h>
62#else /* __rtems__ */
63  #ifdef INTR_FILTER
64    #error INTR_FILTER is currently not suppported with RTEMS
65  #endif
66  #include <machine/rtems-bsd-thread.h>
67  #define RTEMSBSD_SWI_WAKEUP_EVENT RTEMS_EVENT_31
68#endif /* __rtems__ */
69#include <machine/stdarg.h>
70#ifdef DDB
71#include <ddb/ddb.h>
72#include <ddb/db_sym.h>
73#endif
74
75/*
76 * Describe an interrupt thread.  There is one of these per interrupt event.
77 */
78struct intr_thread {
79        struct intr_event *it_event;
80        struct thread *it_thread;       /* Kernel thread. */
81        int     it_flags;               /* (j) IT_* flags. */
82        int     it_need;                /* Needs service. */
83};
84
85/* Interrupt thread flags kept in it_flags */
86#define IT_DEAD         0x000001        /* Thread is waiting to exit. */
87#define IT_WAIT         0x000002        /* Thread is waiting for completion. */
88
89struct  intr_entropy {
90        struct  thread *td;
91        uintptr_t event;
92};
93
94struct  intr_event *clk_intr_event;
95#ifndef __rtems__
96struct  intr_event *tty_intr_event;
97void    *vm_ih;
98#endif /* __rtems__ */
99struct proc *intrproc;
100
101static MALLOC_DEFINE(M_ITHREAD, "ithread", "Interrupt Threads");
102
103static int intr_storm_threshold = 1000;
104#ifndef __rtems__
105TUNABLE_INT("hw.intr_storm_threshold", &intr_storm_threshold);
106SYSCTL_INT(_hw, OID_AUTO, intr_storm_threshold, CTLFLAG_RW,
107    &intr_storm_threshold, 0,
108    "Number of consecutive interrupts before storm protection is enabled");
109#endif /* __rtems__ */
110static TAILQ_HEAD(, intr_event) event_list =
111    TAILQ_HEAD_INITIALIZER(event_list);
112static struct mtx event_lock;
113MTX_SYSINIT(intr_event_list, &event_lock, "intr event list", MTX_DEF);
114
115static void     intr_event_update(struct intr_event *ie);
116#ifdef INTR_FILTER
117static int      intr_event_schedule_thread(struct intr_event *ie,
118                    struct intr_thread *ithd);
119static int      intr_filter_loop(struct intr_event *ie,
120                    struct trapframe *frame, struct intr_thread **ithd);
121static struct intr_thread *ithread_create(const char *name,
122                              struct intr_handler *ih);
123#else
124static int      intr_event_schedule_thread(struct intr_event *ie);
125static struct intr_thread *ithread_create(const char *name);
126#endif
127#ifndef __rtems__
128static void     ithread_destroy(struct intr_thread *ithread);
129#endif /* __rtems__ */
130static void     ithread_execute_handlers(struct proc *p,
131                    struct intr_event *ie);
132#ifdef INTR_FILTER
133static void     priv_ithread_execute_handler(struct proc *p,
134                    struct intr_handler *ih);
135#endif
136static void     ithread_loop(void *);
137static void     ithread_update(struct intr_thread *ithd);
138#ifndef __rtems__
139static void     start_softintr(void *);
140
141/* Map an interrupt type to an ithread priority. */
142u_char
143intr_priority(enum intr_type flags)
144{
145        u_char pri;
146
147        flags &= (INTR_TYPE_TTY | INTR_TYPE_BIO | INTR_TYPE_NET |
148            INTR_TYPE_CAM | INTR_TYPE_MISC | INTR_TYPE_CLK | INTR_TYPE_AV);
149        switch (flags) {
150        case INTR_TYPE_TTY:
151                pri = PI_TTY;
152                break;
153        case INTR_TYPE_BIO:
154                pri = PI_DISK;
155                break;
156        case INTR_TYPE_NET:
157                pri = PI_NET;
158                break;
159        case INTR_TYPE_CAM:
160                pri = PI_DISK;
161                break;
162        case INTR_TYPE_AV:
163                pri = PI_AV;
164                break;
165        case INTR_TYPE_CLK:
166                pri = PI_REALTIME;
167                break;
168        case INTR_TYPE_MISC:
169                pri = PI_DULL;          /* don't care */
170                break;
171        default:
172                /* We didn't specify an interrupt level. */
173                panic("intr_priority: no interrupt type in flags");
174        }
175
176        return pri;
177}
178
179#endif /* __rtems__ */
180/*
181 * Update an ithread based on the associated intr_event.
182 */
183static void
184ithread_update(struct intr_thread *ithd)
185{
186        struct intr_event *ie;
187        struct thread *td;
188        u_char pri;
189
190        ie = ithd->it_event;
191        td = ithd->it_thread;
192
193        /* Determine the overall priority of this event. */
194        if (TAILQ_EMPTY(&ie->ie_handlers))
195                pri = PRI_MAX_ITHD;
196        else
197                pri = TAILQ_FIRST(&ie->ie_handlers)->ih_pri;
198
199        /* Update name and priority. */
200        strlcpy(td->td_name, ie->ie_fullname, sizeof(td->td_name));
201#ifdef KTR
202        sched_clear_tdname(td);
203#endif
204        thread_lock(td);
205#ifndef __rtems__
206        sched_prio(td, pri);
207#else /* __rtems__ */
208#warning TODO: set thread priority
209#endif /* __rtems__ */
210        thread_unlock(td);
211}
212
213/*
214 * Regenerate the full name of an interrupt event and update its priority.
215 */
216static void
217intr_event_update(struct intr_event *ie)
218{
219        struct intr_handler *ih;
220        char *last;
221        int missed, space;
222
223        /* Start off with no entropy and just the name of the event. */
224        mtx_assert(&ie->ie_lock, MA_OWNED);
225        strlcpy(ie->ie_fullname, ie->ie_name, sizeof(ie->ie_fullname));
226        ie->ie_flags &= ~IE_ENTROPY;
227        missed = 0;
228        space = 1;
229
230        /* Run through all the handlers updating values. */
231        TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
232                if (strlen(ie->ie_fullname) + strlen(ih->ih_name) + 1 <
233                    sizeof(ie->ie_fullname)) {
234                        strcat(ie->ie_fullname, " ");
235                        strcat(ie->ie_fullname, ih->ih_name);
236                        space = 0;
237                } else
238                        missed++;
239                if (ih->ih_flags & IH_ENTROPY)
240                        ie->ie_flags |= IE_ENTROPY;
241        }
242
243        /*
244         * If the handler names were too long, add +'s to indicate missing
245         * names. If we run out of room and still have +'s to add, change
246         * the last character from a + to a *.
247         */
248        last = &ie->ie_fullname[sizeof(ie->ie_fullname) - 2];
249        while (missed-- > 0) {
250                if (strlen(ie->ie_fullname) + 1 == sizeof(ie->ie_fullname)) {
251                        if (*last == '+') {
252                                *last = '*';
253                                break;
254                        } else
255                                *last = '+';
256                } else if (space) {
257                        strcat(ie->ie_fullname, " +");
258                        space = 0;
259                } else
260                        strcat(ie->ie_fullname, "+");
261        }
262
263        /*
264         * If this event has an ithread, update it's priority and
265         * name.
266         */
267        if (ie->ie_thread != NULL)
268                ithread_update(ie->ie_thread);
269        CTR2(KTR_INTR, "%s: updated %s", __func__, ie->ie_fullname);
270}
271
272int
273intr_event_create(struct intr_event **event, void *source, int flags, int irq,
274    void (*pre_ithread)(void *), void (*post_ithread)(void *),
275    void (*post_filter)(void *), int (*assign_cpu)(void *, u_char),
276    const char *fmt, ...)
277{
278        struct intr_event *ie;
279        va_list ap;
280
281        /* The only valid flag during creation is IE_SOFT. */
282        if ((flags & ~IE_SOFT) != 0)
283                return (EINVAL);
284        ie = malloc(sizeof(struct intr_event), M_ITHREAD, M_WAITOK | M_ZERO);
285        ie->ie_source = source;
286        ie->ie_pre_ithread = pre_ithread;
287        ie->ie_post_ithread = post_ithread;
288        ie->ie_post_filter = post_filter;
289        ie->ie_assign_cpu = assign_cpu;
290        ie->ie_flags = flags;
291        ie->ie_irq = irq;
292        ie->ie_cpu = NOCPU;
293        TAILQ_INIT(&ie->ie_handlers);
294        mtx_init(&ie->ie_lock, "intr event", NULL, MTX_DEF);
295
296        va_start(ap, fmt);
297        vsnprintf(ie->ie_name, sizeof(ie->ie_name), fmt, ap);
298        va_end(ap);
299        strlcpy(ie->ie_fullname, ie->ie_name, sizeof(ie->ie_fullname));
300        mtx_lock(&event_lock);
301        TAILQ_INSERT_TAIL(&event_list, ie, ie_list);
302        mtx_unlock(&event_lock);
303        if (event != NULL)
304                *event = ie;
305        CTR2(KTR_INTR, "%s: created %s", __func__, ie->ie_name);
306        return (0);
307}
308
309#ifndef __rtems__
310/*
311 * Bind an interrupt event to the specified CPU.  Note that not all
312 * platforms support binding an interrupt to a CPU.  For those
313 * platforms this request will fail.  For supported platforms, any
314 * associated ithreads as well as the primary interrupt context will
315 * be bound to the specificed CPU.  Using a cpu id of NOCPU unbinds
316 * the interrupt event.
317 */
318int
319intr_event_bind(struct intr_event *ie, u_char cpu)
320{
321        cpuset_t mask;
322        lwpid_t id;
323        int error;
324
325        /* Need a CPU to bind to. */
326        if (cpu != NOCPU && CPU_ABSENT(cpu))
327                return (EINVAL);
328
329        if (ie->ie_assign_cpu == NULL)
330                return (EOPNOTSUPP);
331
332        error = priv_check(curthread, PRIV_SCHED_CPUSET_INTR);
333        if (error)
334                return (error);
335
336        /*
337         * If we have any ithreads try to set their mask first to verify
338         * permissions, etc.
339         */
340        mtx_lock(&ie->ie_lock);
341        if (ie->ie_thread != NULL) {
342                CPU_ZERO(&mask);
343                if (cpu == NOCPU)
344                        CPU_COPY(cpuset_root, &mask);
345                else
346                        CPU_SET(cpu, &mask);
347                id = ie->ie_thread->it_thread->td_tid;
348                mtx_unlock(&ie->ie_lock);
349                error = cpuset_setthread(id, &mask);
350                if (error)
351                        return (error);
352        } else
353                mtx_unlock(&ie->ie_lock);
354        error = ie->ie_assign_cpu(ie->ie_source, cpu);
355        if (error) {
356                mtx_lock(&ie->ie_lock);
357                if (ie->ie_thread != NULL) {
358                        CPU_ZERO(&mask);
359                        if (ie->ie_cpu == NOCPU)
360                                CPU_COPY(cpuset_root, &mask);
361                        else
362                                CPU_SET(cpu, &mask);
363                        id = ie->ie_thread->it_thread->td_tid;
364                        mtx_unlock(&ie->ie_lock);
365                        (void)cpuset_setthread(id, &mask);
366                } else
367                        mtx_unlock(&ie->ie_lock);
368                return (error);
369        }
370
371        mtx_lock(&ie->ie_lock);
372        ie->ie_cpu = cpu;
373        mtx_unlock(&ie->ie_lock);
374
375        return (error);
376}
377
378static struct intr_event *
379intr_lookup(int irq)
380{
381        struct intr_event *ie;
382
383        mtx_lock(&event_lock);
384        TAILQ_FOREACH(ie, &event_list, ie_list)
385                if (ie->ie_irq == irq &&
386                    (ie->ie_flags & IE_SOFT) == 0 &&
387                    TAILQ_FIRST(&ie->ie_handlers) != NULL)
388                        break;
389        mtx_unlock(&event_lock);
390        return (ie);
391}
392
393int
394intr_setaffinity(int irq, void *m)
395{
396        struct intr_event *ie;
397        cpuset_t *mask;
398        u_char cpu;
399        int n;
400
401        mask = m;
402        cpu = NOCPU;
403        /*
404         * If we're setting all cpus we can unbind.  Otherwise make sure
405         * only one cpu is in the set.
406         */
407        if (CPU_CMP(cpuset_root, mask)) {
408                for (n = 0; n < CPU_SETSIZE; n++) {
409                        if (!CPU_ISSET(n, mask))
410                                continue;
411                        if (cpu != NOCPU)
412                                return (EINVAL);
413                        cpu = (u_char)n;
414                }
415        }
416        ie = intr_lookup(irq);
417        if (ie == NULL)
418                return (ESRCH);
419        return (intr_event_bind(ie, cpu));
420}
421
422int
423intr_getaffinity(int irq, void *m)
424{
425        struct intr_event *ie;
426        cpuset_t *mask;
427
428        mask = m;
429        ie = intr_lookup(irq);
430        if (ie == NULL)
431                return (ESRCH);
432        CPU_ZERO(mask);
433        mtx_lock(&ie->ie_lock);
434        if (ie->ie_cpu == NOCPU)
435                CPU_COPY(cpuset_root, mask);
436        else
437                CPU_SET(ie->ie_cpu, mask);
438        mtx_unlock(&ie->ie_lock);
439        return (0);
440}
441
442int
443intr_event_destroy(struct intr_event *ie)
444{
445
446        mtx_lock(&event_lock);
447        mtx_lock(&ie->ie_lock);
448        if (!TAILQ_EMPTY(&ie->ie_handlers)) {
449                mtx_unlock(&ie->ie_lock);
450                mtx_unlock(&event_lock);
451                return (EBUSY);
452        }
453        TAILQ_REMOVE(&event_list, ie, ie_list);
454#ifndef notyet
455        if (ie->ie_thread != NULL) {
456                ithread_destroy(ie->ie_thread);
457                ie->ie_thread = NULL;
458        }
459#endif
460        mtx_unlock(&ie->ie_lock);
461        mtx_unlock(&event_lock);
462        mtx_destroy(&ie->ie_lock);
463        free(ie, M_ITHREAD);
464        return (0);
465}
466
467#endif /* __rtems__ */
468#ifndef INTR_FILTER
469static struct intr_thread *
470ithread_create(const char *name)
471{
472        struct intr_thread *ithd;
473        struct thread *td;
474        int error;
475
476        ithd = malloc(sizeof(struct intr_thread), M_ITHREAD, M_WAITOK | M_ZERO);
477
478        error = kproc_kthread_add(ithread_loop, ithd, &intrproc,
479                    &td, RFSTOPPED | RFHIGHPID,
480                    0, "intr", "%s", name);
481        if (error)
482                panic("kproc_create() failed with %d", error);
483        thread_lock(td);
484#ifndef __rtems__
485        sched_class(td, PRI_ITHD);
486        TD_SET_IWAIT(td);
487#endif /* __rtems__ */
488        thread_unlock(td);
489#ifndef __rtems__
490        td->td_pflags |= TDP_ITHREAD;
491#endif /* __rtems__ */
492        ithd->it_thread = td;
493        CTR2(KTR_INTR, "%s: created %s", __func__, name);
494        return (ithd);
495}
496#else
497#ifndef __rtems__
498static struct intr_thread *
499ithread_create(const char *name, struct intr_handler *ih)
500{
501        struct intr_thread *ithd;
502        struct thread *td;
503        int error;
504
505        ithd = malloc(sizeof(struct intr_thread), M_ITHREAD, M_WAITOK | M_ZERO);
506
507        error = kproc_kthread_add(ithread_loop, ih, &intrproc,
508                    &td, RFSTOPPED | RFHIGHPID,
509                    0, "intr", "%s", name);
510        if (error)
511                panic("kproc_create() failed with %d", error);
512        thread_lock(td);
513        sched_class(td, PRI_ITHD);
514        TD_SET_IWAIT(td);
515        thread_unlock(td);
516        td->td_pflags |= TDP_ITHREAD;
517        ithd->it_thread = td;
518        CTR2(KTR_INTR, "%s: created %s", __func__, name);
519        return (ithd);
520}
521#endif /* __rtems__ */
522#endif
523#ifndef __rtems__
524
525static void
526ithread_destroy(struct intr_thread *ithread)
527{
528        struct thread *td;
529
530        CTR2(KTR_INTR, "%s: killing %s", __func__, ithread->it_event->ie_name);
531        td = ithread->it_thread;
532        thread_lock(td);
533        ithread->it_flags |= IT_DEAD;
534        if (TD_AWAITING_INTR(td)) {
535                TD_CLR_IWAIT(td);
536                sched_add(td, SRQ_INTR);
537        }
538        thread_unlock(td);
539}
540
541#endif /* __rtems__ */
542#ifndef INTR_FILTER
543int
544intr_event_add_handler(struct intr_event *ie, const char *name,
545    driver_filter_t filter, driver_intr_t handler, void *arg, u_char pri,
546    enum intr_type flags, void **cookiep)
547{
548        struct intr_handler *ih, *temp_ih;
549        struct intr_thread *it;
550
551        if (ie == NULL || name == NULL || (handler == NULL && filter == NULL))
552                return (EINVAL);
553
554        /* Allocate and populate an interrupt handler structure. */
555        ih = malloc(sizeof(struct intr_handler), M_ITHREAD, M_WAITOK | M_ZERO);
556        ih->ih_filter = filter;
557        ih->ih_handler = handler;
558        ih->ih_argument = arg;
559        strlcpy(ih->ih_name, name, sizeof(ih->ih_name));
560        ih->ih_event = ie;
561        ih->ih_pri = pri;
562        if (flags & INTR_EXCL)
563                ih->ih_flags = IH_EXCLUSIVE;
564        if (flags & INTR_MPSAFE)
565                ih->ih_flags |= IH_MPSAFE;
566        if (flags & INTR_ENTROPY)
567                ih->ih_flags |= IH_ENTROPY;
568
569        /* We can only have one exclusive handler in a event. */
570        mtx_lock(&ie->ie_lock);
571        if (!TAILQ_EMPTY(&ie->ie_handlers)) {
572                if ((flags & INTR_EXCL) ||
573                    (TAILQ_FIRST(&ie->ie_handlers)->ih_flags & IH_EXCLUSIVE)) {
574                        mtx_unlock(&ie->ie_lock);
575                        free(ih, M_ITHREAD);
576                        return (EINVAL);
577                }
578        }
579
580        /* Create a thread if we need one. */
581        while (ie->ie_thread == NULL && handler != NULL) {
582                if (ie->ie_flags & IE_ADDING_THREAD)
583                        msleep(ie, &ie->ie_lock, 0, "ithread", 0);
584                else {
585                        ie->ie_flags |= IE_ADDING_THREAD;
586                        mtx_unlock(&ie->ie_lock);
587                        it = ithread_create("intr: newborn");
588                        mtx_lock(&ie->ie_lock);
589                        ie->ie_flags &= ~IE_ADDING_THREAD;
590                        ie->ie_thread = it;
591                        it->it_event = ie;
592                        ithread_update(it);
593                        wakeup(ie);
594                }
595        }
596
597        /* Add the new handler to the event in priority order. */
598        TAILQ_FOREACH(temp_ih, &ie->ie_handlers, ih_next) {
599                if (temp_ih->ih_pri > ih->ih_pri)
600                        break;
601        }
602        if (temp_ih == NULL)
603                TAILQ_INSERT_TAIL(&ie->ie_handlers, ih, ih_next);
604        else
605                TAILQ_INSERT_BEFORE(temp_ih, ih, ih_next);
606        intr_event_update(ie);
607
608        CTR3(KTR_INTR, "%s: added %s to %s", __func__, ih->ih_name,
609            ie->ie_name);
610        mtx_unlock(&ie->ie_lock);
611
612        if (cookiep != NULL)
613                *cookiep = ih;
614        return (0);
615}
616#else
617#ifndef __rtems__
618int
619intr_event_add_handler(struct intr_event *ie, const char *name,
620    driver_filter_t filter, driver_intr_t handler, void *arg, u_char pri,
621    enum intr_type flags, void **cookiep)
622{
623        struct intr_handler *ih, *temp_ih;
624        struct intr_thread *it;
625
626        if (ie == NULL || name == NULL || (handler == NULL && filter == NULL))
627                return (EINVAL);
628
629        /* Allocate and populate an interrupt handler structure. */
630        ih = malloc(sizeof(struct intr_handler), M_ITHREAD, M_WAITOK | M_ZERO);
631        ih->ih_filter = filter;
632        ih->ih_handler = handler;
633        ih->ih_argument = arg;
634        strlcpy(ih->ih_name, name, sizeof(ih->ih_name));
635        ih->ih_event = ie;
636        ih->ih_pri = pri;
637        if (flags & INTR_EXCL)
638                ih->ih_flags = IH_EXCLUSIVE;
639        if (flags & INTR_MPSAFE)
640                ih->ih_flags |= IH_MPSAFE;
641        if (flags & INTR_ENTROPY)
642                ih->ih_flags |= IH_ENTROPY;
643
644        /* We can only have one exclusive handler in a event. */
645        mtx_lock(&ie->ie_lock);
646        if (!TAILQ_EMPTY(&ie->ie_handlers)) {
647                if ((flags & INTR_EXCL) ||
648                    (TAILQ_FIRST(&ie->ie_handlers)->ih_flags & IH_EXCLUSIVE)) {
649                        mtx_unlock(&ie->ie_lock);
650                        free(ih, M_ITHREAD);
651                        return (EINVAL);
652                }
653        }
654
655        /* For filtered handlers, create a private ithread to run on. */
656        if (filter != NULL && handler != NULL) {
657                mtx_unlock(&ie->ie_lock);
658                it = ithread_create("intr: newborn", ih);
659                mtx_lock(&ie->ie_lock);
660                it->it_event = ie;
661                ih->ih_thread = it;
662                ithread_update(it); // XXX - do we really need this?!?!?
663        } else { /* Create the global per-event thread if we need one. */
664                while (ie->ie_thread == NULL && handler != NULL) {
665                        if (ie->ie_flags & IE_ADDING_THREAD)
666                                msleep(ie, &ie->ie_lock, 0, "ithread", 0);
667                        else {
668                                ie->ie_flags |= IE_ADDING_THREAD;
669                                mtx_unlock(&ie->ie_lock);
670                                it = ithread_create("intr: newborn", ih);
671                                mtx_lock(&ie->ie_lock);
672                                ie->ie_flags &= ~IE_ADDING_THREAD;
673                                ie->ie_thread = it;
674                                it->it_event = ie;
675                                ithread_update(it);
676                                wakeup(ie);
677                        }
678                }
679        }
680
681        /* Add the new handler to the event in priority order. */
682        TAILQ_FOREACH(temp_ih, &ie->ie_handlers, ih_next) {
683                if (temp_ih->ih_pri > ih->ih_pri)
684                        break;
685        }
686        if (temp_ih == NULL)
687                TAILQ_INSERT_TAIL(&ie->ie_handlers, ih, ih_next);
688        else
689                TAILQ_INSERT_BEFORE(temp_ih, ih, ih_next);
690        intr_event_update(ie);
691
692        CTR3(KTR_INTR, "%s: added %s to %s", __func__, ih->ih_name,
693            ie->ie_name);
694        mtx_unlock(&ie->ie_lock);
695
696        if (cookiep != NULL)
697                *cookiep = ih;
698        return (0);
699}
700#endif /* __rtems__ */
701#endif
702
703#ifndef __rtems__
704/*
705 * Append a description preceded by a ':' to the name of the specified
706 * interrupt handler.
707 */
708int
709intr_event_describe_handler(struct intr_event *ie, void *cookie,
710    const char *descr)
711{
712        struct intr_handler *ih;
713        size_t space;
714        char *start;
715
716        mtx_lock(&ie->ie_lock);
717#ifdef INVARIANTS
718        TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
719                if (ih == cookie)
720                        break;
721        }
722        if (ih == NULL) {
723                mtx_unlock(&ie->ie_lock);
724                panic("handler %p not found in interrupt event %p", cookie, ie);
725        }
726#endif
727        ih = cookie;
728
729        /*
730         * Look for an existing description by checking for an
731         * existing ":".  This assumes device names do not include
732         * colons.  If one is found, prepare to insert the new
733         * description at that point.  If one is not found, find the
734         * end of the name to use as the insertion point.
735         */
736        start = index(ih->ih_name, ':');
737        if (start == NULL)
738                start = index(ih->ih_name, 0);
739
740        /*
741         * See if there is enough remaining room in the string for the
742         * description + ":".  The "- 1" leaves room for the trailing
743         * '\0'.  The "+ 1" accounts for the colon.
744         */
745        space = sizeof(ih->ih_name) - (start - ih->ih_name) - 1;
746        if (strlen(descr) + 1 > space) {
747                mtx_unlock(&ie->ie_lock);
748                return (ENOSPC);
749        }
750
751        /* Append a colon followed by the description. */
752        *start = ':';
753        strcpy(start + 1, descr);
754        intr_event_update(ie);
755        mtx_unlock(&ie->ie_lock);
756        return (0);
757}
758
759/*
760 * Return the ie_source field from the intr_event an intr_handler is
761 * associated with.
762 */
763void *
764intr_handler_source(void *cookie)
765{
766        struct intr_handler *ih;
767        struct intr_event *ie;
768
769        ih = (struct intr_handler *)cookie;
770        if (ih == NULL)
771                return (NULL);
772        ie = ih->ih_event;
773        KASSERT(ie != NULL,
774            ("interrupt handler \"%s\" has a NULL interrupt event",
775            ih->ih_name));
776        return (ie->ie_source);
777}
778
779/*
780 * Sleep until an ithread finishes executing an interrupt handler.
781 *
782 * XXX Doesn't currently handle interrupt filters or fast interrupt
783 * handlers.  This is intended for compatibility with linux drivers
784 * only.  Do not use in BSD code.
785 */
786void
787_intr_drain(int irq)
788{
789        struct intr_event *ie;
790        struct intr_thread *ithd;
791        struct thread *td;
792
793        ie = intr_lookup(irq);
794        if (ie == NULL)
795                return;
796        if (ie->ie_thread == NULL)
797                return;
798        ithd = ie->ie_thread;
799        td = ithd->it_thread;
800        /*
801         * We set the flag and wait for it to be cleared to avoid
802         * long delays with potentially busy interrupt handlers
803         * were we to only sample TD_AWAITING_INTR() every tick.
804         */
805        thread_lock(td);
806        if (!TD_AWAITING_INTR(td)) {
807                ithd->it_flags |= IT_WAIT;
808                while (ithd->it_flags & IT_WAIT) {
809                        thread_unlock(td);
810                        pause("idrain", 1);
811                        thread_lock(td);
812                }
813        }
814        thread_unlock(td);
815        return;
816}
817#endif /* __rtems__ */
818
819
820#ifndef INTR_FILTER
821#ifndef __rtems__
822int
823intr_event_remove_handler(void *cookie)
824{
825        struct intr_handler *handler = (struct intr_handler *)cookie;
826        struct intr_event *ie;
827#ifdef INVARIANTS
828        struct intr_handler *ih;
829#endif
830#ifdef notyet
831        int dead;
832#endif
833
834        if (handler == NULL)
835                return (EINVAL);
836        ie = handler->ih_event;
837        KASSERT(ie != NULL,
838            ("interrupt handler \"%s\" has a NULL interrupt event",
839            handler->ih_name));
840        mtx_lock(&ie->ie_lock);
841        CTR3(KTR_INTR, "%s: removing %s from %s", __func__, handler->ih_name,
842            ie->ie_name);
843#ifdef INVARIANTS
844        TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next)
845                if (ih == handler)
846                        goto ok;
847        mtx_unlock(&ie->ie_lock);
848        panic("interrupt handler \"%s\" not found in interrupt event \"%s\"",
849            ih->ih_name, ie->ie_name);
850ok:
851#endif
852        /*
853         * If there is no ithread, then just remove the handler and return.
854         * XXX: Note that an INTR_FAST handler might be running on another
855         * CPU!
856         */
857        if (ie->ie_thread == NULL) {
858                TAILQ_REMOVE(&ie->ie_handlers, handler, ih_next);
859                mtx_unlock(&ie->ie_lock);
860                free(handler, M_ITHREAD);
861                return (0);
862        }
863
864        /*
865         * If the interrupt thread is already running, then just mark this
866         * handler as being dead and let the ithread do the actual removal.
867         *
868         * During a cold boot while cold is set, msleep() does not sleep,
869         * so we have to remove the handler here rather than letting the
870         * thread do it.
871         */
872        thread_lock(ie->ie_thread->it_thread);
873        if (!TD_AWAITING_INTR(ie->ie_thread->it_thread) && !cold) {
874                handler->ih_flags |= IH_DEAD;
875
876                /*
877                 * Ensure that the thread will process the handler list
878                 * again and remove this handler if it has already passed
879                 * it on the list.
880                 */
881                atomic_store_rel_int(&ie->ie_thread->it_need, 1);
882        } else
883                TAILQ_REMOVE(&ie->ie_handlers, handler, ih_next);
884        thread_unlock(ie->ie_thread->it_thread);
885        while (handler->ih_flags & IH_DEAD)
886                msleep(handler, &ie->ie_lock, 0, "iev_rmh", 0);
887        intr_event_update(ie);
888#ifdef notyet
889        /*
890         * XXX: This could be bad in the case of ppbus(8).  Also, I think
891         * this could lead to races of stale data when servicing an
892         * interrupt.
893         */
894        dead = 1;
895        TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
896                if (!(ih->ih_flags & IH_FAST)) {
897                        dead = 0;
898                        break;
899                }
900        }
901        if (dead) {
902                ithread_destroy(ie->ie_thread);
903                ie->ie_thread = NULL;
904        }
905#endif
906        mtx_unlock(&ie->ie_lock);
907        free(handler, M_ITHREAD);
908        return (0);
909}
910
911#endif /* __rtems__ */
912static int
913intr_event_schedule_thread(struct intr_event *ie)
914{
915        struct intr_entropy entropy;
916        struct intr_thread *it;
917        struct thread *td;
918        struct thread *ctd;
919#ifndef __rtems__
920        struct proc *p;
921#endif /* __rtems__ */
922
923        /*
924         * If no ithread or no handlers, then we have a stray interrupt.
925         */
926        if (ie == NULL || TAILQ_EMPTY(&ie->ie_handlers) ||
927            ie->ie_thread == NULL)
928                return (EINVAL);
929
930        ctd = curthread;
931        it = ie->ie_thread;
932        td = it->it_thread;
933#ifndef __rtems__
934        p = td->td_proc;
935#endif /* __rtems__ */
936
937        /*
938         * If any of the handlers for this ithread claim to be good
939         * sources of entropy, then gather some.
940         */
941        if (harvest.interrupt && ie->ie_flags & IE_ENTROPY) {
942                CTR3(KTR_INTR, "%s: pid %d (%s) gathering entropy", __func__,
943                    p->p_pid, td->td_name);
944                entropy.event = (uintptr_t)ie;
945                entropy.td = ctd;
946                random_harvest(&entropy, sizeof(entropy), 2, 0,
947                    RANDOM_INTERRUPT);
948        }
949
950#ifndef __rtems__
951        KASSERT(p != NULL, ("ithread %s has no process", ie->ie_name));
952#endif /* __rtems__ */
953
954        /*
955         * Set it_need to tell the thread to keep running if it is already
956         * running.  Then, lock the thread and see if we actually need to
957         * put it on the runqueue.
958         */
959        atomic_store_rel_int(&it->it_need, 1);
960        thread_lock(td);
961#ifndef __rtems__
962        if (TD_AWAITING_INTR(td)) {
963                CTR3(KTR_INTR, "%s: schedule pid %d (%s)", __func__, p->p_pid,
964                    td->td_name);
965                TD_CLR_IWAIT(td);
966                sched_add(td, SRQ_INTR);
967        } else {
968                CTR5(KTR_INTR, "%s: pid %d (%s): it_need %d, state %d",
969                    __func__, p->p_pid, td->td_name, it->it_need, td->td_state);
970        }
971#else /* __rtems__ */
972        /* Send event to wake the thread up.
973         * TODO: eventually replace event by a better mechanism
974         */
975        rtems_status_code sc = rtems_event_send(rtems_bsd_get_task_id(td), RTEMSBSD_SWI_WAKEUP_EVENT);
976        BSD_ASSERT(sc == RTEMS_SUCCESSFUL);
977#endif /* __rtems__ */
978        thread_unlock(td);
979
980        return (0);
981}
982#else
983#ifndef __rtems__
984int
985intr_event_remove_handler(void *cookie)
986{
987        struct intr_handler *handler = (struct intr_handler *)cookie;
988        struct intr_event *ie;
989        struct intr_thread *it;
990#ifdef INVARIANTS
991        struct intr_handler *ih;
992#endif
993#ifdef notyet
994        int dead;
995#endif
996
997        if (handler == NULL)
998                return (EINVAL);
999        ie = handler->ih_event;
1000        KASSERT(ie != NULL,
1001            ("interrupt handler \"%s\" has a NULL interrupt event",
1002            handler->ih_name));
1003        mtx_lock(&ie->ie_lock);
1004        CTR3(KTR_INTR, "%s: removing %s from %s", __func__, handler->ih_name,
1005            ie->ie_name);
1006#ifdef INVARIANTS
1007        TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next)
1008                if (ih == handler)
1009                        goto ok;
1010        mtx_unlock(&ie->ie_lock);
1011        panic("interrupt handler \"%s\" not found in interrupt event \"%s\"",
1012            ih->ih_name, ie->ie_name);
1013ok:
1014#endif
1015        /*
1016         * If there are no ithreads (per event and per handler), then
1017         * just remove the handler and return. 
1018         * XXX: Note that an INTR_FAST handler might be running on another CPU!
1019         */
1020        if (ie->ie_thread == NULL && handler->ih_thread == NULL) {
1021                TAILQ_REMOVE(&ie->ie_handlers, handler, ih_next);
1022                mtx_unlock(&ie->ie_lock);
1023                free(handler, M_ITHREAD);
1024                return (0);
1025        }
1026
1027        /* Private or global ithread? */
1028        it = (handler->ih_thread) ? handler->ih_thread : ie->ie_thread;
1029        /*
1030         * If the interrupt thread is already running, then just mark this
1031         * handler as being dead and let the ithread do the actual removal.
1032         *
1033         * During a cold boot while cold is set, msleep() does not sleep,
1034         * so we have to remove the handler here rather than letting the
1035         * thread do it.
1036         */
1037        thread_lock(it->it_thread);
1038        if (!TD_AWAITING_INTR(it->it_thread) && !cold) {
1039                handler->ih_flags |= IH_DEAD;
1040
1041                /*
1042                 * Ensure that the thread will process the handler list
1043                 * again and remove this handler if it has already passed
1044                 * it on the list.
1045                 */
1046                atomic_store_rel_int(&it->it_need, 1);
1047        } else
1048                TAILQ_REMOVE(&ie->ie_handlers, handler, ih_next);
1049        thread_unlock(it->it_thread);
1050        while (handler->ih_flags & IH_DEAD)
1051                msleep(handler, &ie->ie_lock, 0, "iev_rmh", 0);
1052        /*
1053         * At this point, the handler has been disconnected from the event,
1054         * so we can kill the private ithread if any.
1055         */
1056        if (handler->ih_thread) {
1057                ithread_destroy(handler->ih_thread);
1058                handler->ih_thread = NULL;
1059        }
1060        intr_event_update(ie);
1061#ifdef notyet
1062        /*
1063         * XXX: This could be bad in the case of ppbus(8).  Also, I think
1064         * this could lead to races of stale data when servicing an
1065         * interrupt.
1066         */
1067        dead = 1;
1068        TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
1069                if (handler != NULL) {
1070                        dead = 0;
1071                        break;
1072                }
1073        }
1074        if (dead) {
1075                ithread_destroy(ie->ie_thread);
1076                ie->ie_thread = NULL;
1077        }
1078#endif
1079        mtx_unlock(&ie->ie_lock);
1080        free(handler, M_ITHREAD);
1081        return (0);
1082}
1083
1084static int
1085intr_event_schedule_thread(struct intr_event *ie, struct intr_thread *it)
1086{
1087        struct intr_entropy entropy;
1088        struct thread *td;
1089        struct thread *ctd;
1090#ifndef __rtems__
1091        struct proc *p;
1092#endif /* __rtems__ */
1093
1094        /*
1095         * If no ithread or no handlers, then we have a stray interrupt.
1096         */
1097        if (ie == NULL || TAILQ_EMPTY(&ie->ie_handlers) || it == NULL)
1098                return (EINVAL);
1099
1100        ctd = curthread;
1101        td = it->it_thread;
1102#ifndef __rtems__
1103        p = td->td_proc;
1104#endif /* __rtems__ */
1105
1106        /*
1107         * If any of the handlers for this ithread claim to be good
1108         * sources of entropy, then gather some.
1109         */
1110        if (harvest.interrupt && ie->ie_flags & IE_ENTROPY) {
1111                CTR3(KTR_INTR, "%s: pid %d (%s) gathering entropy", __func__,
1112                    p->p_pid, td->td_name);
1113                entropy.event = (uintptr_t)ie;
1114                entropy.td = ctd;
1115                random_harvest(&entropy, sizeof(entropy), 2, 0,
1116                    RANDOM_INTERRUPT);
1117        }
1118
1119        KASSERT(p != NULL, ("ithread %s has no process", ie->ie_name));
1120
1121        /*
1122         * Set it_need to tell the thread to keep running if it is already
1123         * running.  Then, lock the thread and see if we actually need to
1124         * put it on the runqueue.
1125         */
1126        atomic_store_rel_int(&it->it_need, 1);
1127        thread_lock(td);
1128        if (TD_AWAITING_INTR(td)) {
1129                CTR3(KTR_INTR, "%s: schedule pid %d (%s)", __func__, p->p_pid,
1130                    td->td_name);
1131                TD_CLR_IWAIT(td);
1132                sched_add(td, SRQ_INTR);
1133        } else {
1134                CTR5(KTR_INTR, "%s: pid %d (%s): it_need %d, state %d",
1135                    __func__, p->p_pid, td->td_name, it->it_need, td->td_state);
1136        }
1137        thread_unlock(td);
1138
1139        return (0);
1140}
1141#endif /* __rtems__ */
1142#endif
1143
1144/*
1145 * Allow interrupt event binding for software interrupt handlers -- a no-op,
1146 * since interrupts are generated in software rather than being directed by
1147 * a PIC.
1148 */
1149static int
1150swi_assign_cpu(void *arg, u_char cpu)
1151{
1152
1153        return (0);
1154}
1155
1156/*
1157 * Add a software interrupt handler to a specified event.  If a given event
1158 * is not specified, then a new event is created.
1159 */
1160int
1161swi_add(struct intr_event **eventp, const char *name, driver_intr_t handler,
1162            void *arg, int pri, enum intr_type flags, void **cookiep)
1163{
1164        struct thread *td;
1165        struct intr_event *ie;
1166        int error;
1167
1168        if (flags & INTR_ENTROPY)
1169                return (EINVAL);
1170
1171        ie = (eventp != NULL) ? *eventp : NULL;
1172
1173        if (ie != NULL) {
1174                if (!(ie->ie_flags & IE_SOFT))
1175                        return (EINVAL);
1176        } else {
1177                error = intr_event_create(&ie, NULL, IE_SOFT, 0,
1178                    NULL, NULL, NULL, swi_assign_cpu, "swi%d:", pri);
1179                if (error)
1180                        return (error);
1181                if (eventp != NULL)
1182                        *eventp = ie;
1183        }
1184        error = intr_event_add_handler(ie, name, NULL, handler, arg,
1185            PI_SWI(pri), flags, cookiep);
1186        if (error)
1187                return (error);
1188#ifndef __rtems__
1189        if (pri == SWI_CLOCK) {
1190                td = ie->ie_thread->it_thread;
1191                thread_lock(td);
1192                td->td_flags |= TDF_NOLOAD;
1193                thread_unlock(td);
1194        }
1195#else /* __rtems__ */
1196        // Do _not_ ignore the thread in the load avarage
1197#endif /* __rtems__ */
1198        return (0);
1199}
1200
1201/*
1202 * Schedule a software interrupt thread.
1203 */
1204void
1205swi_sched(void *cookie, int flags)
1206{
1207        struct intr_handler *ih = (struct intr_handler *)cookie;
1208        struct intr_event *ie = ih->ih_event;
1209        struct intr_entropy entropy;
1210        int error;
1211
1212        CTR3(KTR_INTR, "swi_sched: %s %s need=%d", ie->ie_name, ih->ih_name,
1213            ih->ih_need);
1214
1215        if (harvest.swi) {
1216                CTR2(KTR_INTR, "swi_sched: pid %d (%s) gathering entropy",
1217                    curproc->p_pid, curthread->td_name);
1218                entropy.event = (uintptr_t)ih;
1219                entropy.td = curthread;
1220                random_harvest(&entropy, sizeof(entropy), 1, 0,
1221                    RANDOM_INTERRUPT);
1222        }
1223
1224        /*
1225         * Set ih_need for this handler so that if the ithread is already
1226         * running it will execute this handler on the next pass.  Otherwise,
1227         * it will execute it the next time it runs.
1228         */
1229        atomic_store_rel_int(&ih->ih_need, 1);
1230
1231        if (!(flags & SWI_DELAY)) {
1232#ifndef __rtems__
1233                PCPU_INC(cnt.v_soft);
1234#endif /* __rtems__ */
1235#ifdef INTR_FILTER
1236                error = intr_event_schedule_thread(ie, ie->ie_thread);
1237#else
1238                error = intr_event_schedule_thread(ie);
1239#endif
1240                KASSERT(error == 0, ("stray software interrupt"));
1241        }
1242}
1243
1244#ifndef __rtems__
1245/*
1246 * Remove a software interrupt handler.  Currently this code does not
1247 * remove the associated interrupt event if it becomes empty.  Calling code
1248 * may do so manually via intr_event_destroy(), but that's not really
1249 * an optimal interface.
1250 */
1251int
1252swi_remove(void *cookie)
1253{
1254
1255        return (intr_event_remove_handler(cookie));
1256}
1257
1258#ifdef INTR_FILTER
1259static void
1260priv_ithread_execute_handler(struct proc *p, struct intr_handler *ih)
1261{
1262        struct intr_event *ie;
1263
1264        ie = ih->ih_event;
1265        /*
1266         * If this handler is marked for death, remove it from
1267         * the list of handlers and wake up the sleeper.
1268         */
1269        if (ih->ih_flags & IH_DEAD) {
1270                mtx_lock(&ie->ie_lock);
1271                TAILQ_REMOVE(&ie->ie_handlers, ih, ih_next);
1272                ih->ih_flags &= ~IH_DEAD;
1273                wakeup(ih);
1274                mtx_unlock(&ie->ie_lock);
1275                return;
1276        }
1277       
1278        /* Execute this handler. */
1279        CTR6(KTR_INTR, "%s: pid %d exec %p(%p) for %s flg=%x",
1280             __func__, p->p_pid, (void *)ih->ih_handler, ih->ih_argument,
1281             ih->ih_name, ih->ih_flags);
1282       
1283        if (!(ih->ih_flags & IH_MPSAFE))
1284                mtx_lock(&Giant);
1285        ih->ih_handler(ih->ih_argument);
1286        if (!(ih->ih_flags & IH_MPSAFE))
1287                mtx_unlock(&Giant);
1288}
1289#endif
1290
1291#endif /* __rtems__ */
1292/*
1293 * This is a public function for use by drivers that mux interrupt
1294 * handlers for child devices from their interrupt handler.
1295 */
1296void
1297intr_event_execute_handlers(struct proc *p, struct intr_event *ie)
1298{
1299        struct intr_handler *ih, *ihn;
1300
1301        TAILQ_FOREACH_SAFE(ih, &ie->ie_handlers, ih_next, ihn) {
1302                /*
1303                 * If this handler is marked for death, remove it from
1304                 * the list of handlers and wake up the sleeper.
1305                 */
1306                if (ih->ih_flags & IH_DEAD) {
1307                        mtx_lock(&ie->ie_lock);
1308                        TAILQ_REMOVE(&ie->ie_handlers, ih, ih_next);
1309                        ih->ih_flags &= ~IH_DEAD;
1310                        wakeup(ih);
1311                        mtx_unlock(&ie->ie_lock);
1312                        continue;
1313                }
1314
1315                /* Skip filter only handlers */
1316                if (ih->ih_handler == NULL)
1317                        continue;
1318
1319                /*
1320                 * For software interrupt threads, we only execute
1321                 * handlers that have their need flag set.  Hardware
1322                 * interrupt threads always invoke all of their handlers.
1323                 */
1324                if (ie->ie_flags & IE_SOFT) {
1325                        if (atomic_load_acq_int(&ih->ih_need) == 0)
1326                                continue;
1327                        else
1328                                atomic_store_rel_int(&ih->ih_need, 0);
1329                }
1330
1331                /* Execute this handler. */
1332                CTR6(KTR_INTR, "%s: pid %d exec %p(%p) for %s flg=%x",
1333                    __func__, p->p_pid, (void *)ih->ih_handler,
1334                    ih->ih_argument, ih->ih_name, ih->ih_flags);
1335
1336                if (!(ih->ih_flags & IH_MPSAFE))
1337                        mtx_lock(&Giant);
1338                ih->ih_handler(ih->ih_argument);
1339                if (!(ih->ih_flags & IH_MPSAFE))
1340                        mtx_unlock(&Giant);
1341        }
1342}
1343
1344static void
1345ithread_execute_handlers(struct proc *p, struct intr_event *ie)
1346{
1347
1348#ifndef __rtems__
1349        /* Interrupt handlers should not sleep. */
1350        if (!(ie->ie_flags & IE_SOFT))
1351                THREAD_NO_SLEEPING();
1352        intr_event_execute_handlers(p, ie);
1353        if (!(ie->ie_flags & IE_SOFT))
1354                THREAD_SLEEPING_OK();
1355#else /* __rtems__ */
1356        /* We only have soft-threads, so the two queries are not necessary. */
1357        intr_event_execute_handlers(p, ie);
1358#endif /* __rtems__ */
1359
1360        /*
1361         * Interrupt storm handling:
1362         *
1363         * If this interrupt source is currently storming, then throttle
1364         * it to only fire the handler once  per clock tick.
1365         *
1366         * If this interrupt source is not currently storming, but the
1367         * number of back to back interrupts exceeds the storm threshold,
1368         * then enter storming mode.
1369         */
1370        if (intr_storm_threshold != 0 && ie->ie_count >= intr_storm_threshold &&
1371            !(ie->ie_flags & IE_SOFT)) {
1372#ifndef __rtems__
1373                /* Report the message only once every second. */
1374                if (ppsratecheck(&ie->ie_warntm, &ie->ie_warncnt, 1)) {
1375                        printf(
1376        "interrupt storm detected on \"%s\"; throttling interrupt source\n",
1377                            ie->ie_name);
1378                }
1379#endif /* __rtems__ */
1380                pause("istorm", 1);
1381        } else
1382                ie->ie_count++;
1383
1384        /*
1385         * Now that all the handlers have had a chance to run, reenable
1386         * the interrupt source.
1387         */
1388        if (ie->ie_post_ithread != NULL)
1389                ie->ie_post_ithread(ie->ie_source);
1390}
1391
1392#ifndef INTR_FILTER
1393/*
1394 * This is the main code for interrupt threads.
1395 */
1396static void
1397ithread_loop(void *arg)
1398{
1399        struct intr_thread *ithd;
1400        struct intr_event *ie;
1401        struct thread *td;
1402        struct proc *p;
1403        int wake;
1404
1405        td = curthread;
1406#ifndef __rtems__
1407        p = td->td_proc;
1408#else /* __rtems__ */
1409        p = NULL;
1410#endif /* __rtems__ */
1411        ithd = (struct intr_thread *)arg;
1412        KASSERT(ithd->it_thread == td,
1413            ("%s: ithread and proc linkage out of sync", __func__));
1414        ie = ithd->it_event;
1415        ie->ie_count = 0;
1416        wake = 0;
1417
1418        /*
1419         * As long as we have interrupts outstanding, go through the
1420         * list of handlers, giving each one a go at it.
1421         */
1422        for (;;) {
1423                /*
1424                 * If we are an orphaned thread, then just die.
1425                 */
1426                if (ithd->it_flags & IT_DEAD) {
1427                        CTR3(KTR_INTR, "%s: pid %d (%s) exiting", __func__,
1428                            p->p_pid, td->td_name);
1429                        free(ithd, M_ITHREAD);
1430                        kthread_exit();
1431                }
1432
1433                /*
1434                 * Service interrupts.  If another interrupt arrives while
1435                 * we are running, it will set it_need to note that we
1436                 * should make another pass.
1437                 */
1438                while (atomic_load_acq_int(&ithd->it_need) != 0) {
1439                        /*
1440                         * This might need a full read and write barrier
1441                         * to make sure that this write posts before any
1442                         * of the memory or device accesses in the
1443                         * handlers.
1444                         */
1445                        atomic_store_rel_int(&ithd->it_need, 0);
1446                        ithread_execute_handlers(p, ie);
1447                }
1448                WITNESS_WARN(WARN_PANIC, NULL, "suspending ithread");
1449                mtx_assert(&Giant, MA_NOTOWNED);
1450
1451                /*
1452                 * Processed all our interrupts.  Now get the sched
1453                 * lock.  This may take a while and it_need may get
1454                 * set again, so we have to check it again.
1455                 */
1456                thread_lock(td);
1457                if ((atomic_load_acq_int(&ithd->it_need) == 0) &&
1458                    !(ithd->it_flags & (IT_DEAD | IT_WAIT))) {
1459#ifndef __rtems__
1460                        TD_SET_IWAIT(td);
1461                        ie->ie_count = 0;
1462                        mi_switch(SW_VOL | SWT_IWAIT, NULL);
1463#else /* __rtems__ */
1464                        /* wait for wakeup event
1465                         * TODO: eventually replace event by a better mechanism
1466                         */
1467                        rtems_event_set event_out;
1468                        rtems_status_code sc = rtems_event_receive(
1469                                RTEMSBSD_SWI_WAKEUP_EVENT,
1470                                RTEMS_WAIT | RTEMS_EVENT_ALL,
1471                                RTEMS_NO_TIMEOUT,
1472                                &event_out);
1473                        BSD_ASSERT(sc == RTEMS_SUCCESSFUL);
1474#endif /* __rtems__ */
1475                }
1476                if (ithd->it_flags & IT_WAIT) {
1477                        wake = 1;
1478                        ithd->it_flags &= ~IT_WAIT;
1479                }
1480                thread_unlock(td);
1481                if (wake) {
1482                        wakeup(ithd);
1483                        wake = 0;
1484                }
1485        }
1486}
1487#ifndef __rtems__
1488
1489/*
1490 * Main interrupt handling body.
1491 *
1492 * Input:
1493 * o ie:                        the event connected to this interrupt.
1494 * o frame:                     some archs (i.e. i386) pass a frame to some.
1495 *                              handlers as their main argument.
1496 * Return value:
1497 * o 0:                         everything ok.
1498 * o EINVAL:                    stray interrupt.
1499 */
1500int
1501intr_event_handle(struct intr_event *ie, struct trapframe *frame)
1502{
1503        struct intr_handler *ih;
1504        struct trapframe *oldframe;
1505        struct thread *td;
1506        int error, ret, thread;
1507
1508        td = curthread;
1509
1510        /* An interrupt with no event or handlers is a stray interrupt. */
1511        if (ie == NULL || TAILQ_EMPTY(&ie->ie_handlers))
1512                return (EINVAL);
1513
1514        /*
1515         * Execute fast interrupt handlers directly.
1516         * To support clock handlers, if a handler registers
1517         * with a NULL argument, then we pass it a pointer to
1518         * a trapframe as its argument.
1519         */
1520        td->td_intr_nesting_level++;
1521        thread = 0;
1522        ret = 0;
1523        critical_enter();
1524        oldframe = td->td_intr_frame;
1525        td->td_intr_frame = frame;
1526        TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
1527                if (ih->ih_filter == NULL) {
1528                        thread = 1;
1529                        continue;
1530                }
1531                CTR4(KTR_INTR, "%s: exec %p(%p) for %s", __func__,
1532                    ih->ih_filter, ih->ih_argument == NULL ? frame :
1533                    ih->ih_argument, ih->ih_name);
1534                if (ih->ih_argument == NULL)
1535                        ret = ih->ih_filter(frame);
1536                else
1537                        ret = ih->ih_filter(ih->ih_argument);
1538                KASSERT(ret == FILTER_STRAY ||
1539                    ((ret & (FILTER_SCHEDULE_THREAD | FILTER_HANDLED)) != 0 &&
1540                    (ret & ~(FILTER_SCHEDULE_THREAD | FILTER_HANDLED)) == 0),
1541                    ("%s: incorrect return value %#x from %s", __func__, ret,
1542                    ih->ih_name));
1543
1544                /*
1545                 * Wrapper handler special handling:
1546                 *
1547                 * in some particular cases (like pccard and pccbb),
1548                 * the _real_ device handler is wrapped in a couple of
1549                 * functions - a filter wrapper and an ithread wrapper.
1550                 * In this case (and just in this case), the filter wrapper
1551                 * could ask the system to schedule the ithread and mask
1552                 * the interrupt source if the wrapped handler is composed
1553                 * of just an ithread handler.
1554                 *
1555                 * TODO: write a generic wrapper to avoid people rolling
1556                 * their own
1557                 */
1558                if (!thread) {
1559                        if (ret == FILTER_SCHEDULE_THREAD)
1560                                thread = 1;
1561                }
1562        }
1563        td->td_intr_frame = oldframe;
1564
1565        if (thread) {
1566                if (ie->ie_pre_ithread != NULL)
1567                        ie->ie_pre_ithread(ie->ie_source);
1568        } else {
1569                if (ie->ie_post_filter != NULL)
1570                        ie->ie_post_filter(ie->ie_source);
1571        }
1572       
1573        /* Schedule the ithread if needed. */
1574        if (thread) {
1575                error = intr_event_schedule_thread(ie);
1576#ifndef XEN             
1577                KASSERT(error == 0, ("bad stray interrupt"));
1578#else
1579                if (error != 0)
1580                        log(LOG_WARNING, "bad stray interrupt");
1581#endif         
1582        }
1583        critical_exit();
1584        td->td_intr_nesting_level--;
1585        return (0);
1586}
1587#endif /* __rtems__ */
1588#else
1589#ifndef __rtems__
1590/*
1591 * This is the main code for interrupt threads.
1592 */
1593static void
1594ithread_loop(void *arg)
1595{
1596        struct intr_thread *ithd;
1597        struct intr_handler *ih;
1598        struct intr_event *ie;
1599        struct thread *td;
1600        struct proc *p;
1601        int priv;
1602        int wake;
1603
1604        td = curthread;
1605        p = td->td_proc;
1606        ih = (struct intr_handler *)arg;
1607        priv = (ih->ih_thread != NULL) ? 1 : 0;
1608        ithd = (priv) ? ih->ih_thread : ih->ih_event->ie_thread;
1609        KASSERT(ithd->it_thread == td,
1610            ("%s: ithread and proc linkage out of sync", __func__));
1611        ie = ithd->it_event;
1612        ie->ie_count = 0;
1613        wake = 0;
1614
1615        /*
1616         * As long as we have interrupts outstanding, go through the
1617         * list of handlers, giving each one a go at it.
1618         */
1619        for (;;) {
1620                /*
1621                 * If we are an orphaned thread, then just die.
1622                 */
1623                if (ithd->it_flags & IT_DEAD) {
1624                        CTR3(KTR_INTR, "%s: pid %d (%s) exiting", __func__,
1625                            p->p_pid, td->td_name);
1626                        free(ithd, M_ITHREAD);
1627                        kthread_exit();
1628                }
1629
1630                /*
1631                 * Service interrupts.  If another interrupt arrives while
1632                 * we are running, it will set it_need to note that we
1633                 * should make another pass.
1634                 */
1635                while (atomic_load_acq_int(&ithd->it_need) != 0) {
1636                        /*
1637                         * This might need a full read and write barrier
1638                         * to make sure that this write posts before any
1639                         * of the memory or device accesses in the
1640                         * handlers.
1641                         */
1642                        atomic_store_rel_int(&ithd->it_need, 0);
1643                        if (priv)
1644                                priv_ithread_execute_handler(p, ih);
1645                        else
1646                                ithread_execute_handlers(p, ie);
1647                }
1648                WITNESS_WARN(WARN_PANIC, NULL, "suspending ithread");
1649                mtx_assert(&Giant, MA_NOTOWNED);
1650
1651                /*
1652                 * Processed all our interrupts.  Now get the sched
1653                 * lock.  This may take a while and it_need may get
1654                 * set again, so we have to check it again.
1655                 */
1656                thread_lock(td);
1657                if ((atomic_load_acq_int(&ithd->it_need) == 0) &&
1658                    !(ithd->it_flags & (IT_DEAD | IT_WAIT))) {
1659                        TD_SET_IWAIT(td);
1660                        ie->ie_count = 0;
1661                        mi_switch(SW_VOL | SWT_IWAIT, NULL);
1662                }
1663                if (ithd->it_flags & IT_WAIT) {
1664                        wake = 1;
1665                        ithd->it_flags &= ~IT_WAIT;
1666                }
1667                thread_unlock(td);
1668                if (wake) {
1669                        wakeup(ithd);
1670                        wake = 0;
1671                }
1672        }
1673}
1674
1675/*
1676 * Main loop for interrupt filter.
1677 *
1678 * Some architectures (i386, amd64 and arm) require the optional frame
1679 * parameter, and use it as the main argument for fast handler execution
1680 * when ih_argument == NULL.
1681 *
1682 * Return value:
1683 * o FILTER_STRAY:              No filter recognized the event, and no
1684 *                              filter-less handler is registered on this
1685 *                              line.
1686 * o FILTER_HANDLED:            A filter claimed the event and served it.
1687 * o FILTER_SCHEDULE_THREAD:    No filter claimed the event, but there's at
1688 *                              least one filter-less handler on this line.
1689 * o FILTER_HANDLED |
1690 *   FILTER_SCHEDULE_THREAD:    A filter claimed the event, and asked for
1691 *                              scheduling the per-handler ithread.
1692 *
1693 * In case an ithread has to be scheduled, in *ithd there will be a
1694 * pointer to a struct intr_thread containing the thread to be
1695 * scheduled.
1696 */
1697
1698static int
1699intr_filter_loop(struct intr_event *ie, struct trapframe *frame,
1700                 struct intr_thread **ithd)
1701{
1702        struct intr_handler *ih;
1703        void *arg;
1704        int ret, thread_only;
1705
1706        ret = 0;
1707        thread_only = 0;
1708        TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next) {
1709                /*
1710                 * Execute fast interrupt handlers directly.
1711                 * To support clock handlers, if a handler registers
1712                 * with a NULL argument, then we pass it a pointer to
1713                 * a trapframe as its argument.
1714                 */
1715                arg = ((ih->ih_argument == NULL) ? frame : ih->ih_argument);
1716               
1717                CTR5(KTR_INTR, "%s: exec %p/%p(%p) for %s", __func__,
1718                     ih->ih_filter, ih->ih_handler, arg, ih->ih_name);
1719
1720                if (ih->ih_filter != NULL)
1721                        ret = ih->ih_filter(arg);
1722                else {
1723                        thread_only = 1;
1724                        continue;
1725                }
1726                KASSERT(ret == FILTER_STRAY ||
1727                    ((ret & (FILTER_SCHEDULE_THREAD | FILTER_HANDLED)) != 0 &&
1728                    (ret & ~(FILTER_SCHEDULE_THREAD | FILTER_HANDLED)) == 0),
1729                    ("%s: incorrect return value %#x from %s", __func__, ret,
1730                    ih->ih_name));
1731                if (ret & FILTER_STRAY)
1732                        continue;
1733                else {
1734                        *ithd = ih->ih_thread;
1735                        return (ret);
1736                }
1737        }
1738
1739        /*
1740         * No filters handled the interrupt and we have at least
1741         * one handler without a filter.  In this case, we schedule
1742         * all of the filter-less handlers to run in the ithread.
1743         */     
1744        if (thread_only) {
1745                *ithd = ie->ie_thread;
1746                return (FILTER_SCHEDULE_THREAD);
1747        }
1748        return (FILTER_STRAY);
1749}
1750
1751/*
1752 * Main interrupt handling body.
1753 *
1754 * Input:
1755 * o ie:                        the event connected to this interrupt.
1756 * o frame:                     some archs (i.e. i386) pass a frame to some.
1757 *                              handlers as their main argument.
1758 * Return value:
1759 * o 0:                         everything ok.
1760 * o EINVAL:                    stray interrupt.
1761 */
1762int
1763intr_event_handle(struct intr_event *ie, struct trapframe *frame)
1764{
1765        struct intr_thread *ithd;
1766        struct trapframe *oldframe;
1767        struct thread *td;
1768        int thread;
1769
1770        ithd = NULL;
1771        td = curthread;
1772
1773        if (ie == NULL || TAILQ_EMPTY(&ie->ie_handlers))
1774                return (EINVAL);
1775
1776        td->td_intr_nesting_level++;
1777        thread = 0;
1778        critical_enter();
1779        oldframe = td->td_intr_frame;
1780        td->td_intr_frame = frame;
1781        thread = intr_filter_loop(ie, frame, &ithd);   
1782        if (thread & FILTER_HANDLED) {
1783                if (ie->ie_post_filter != NULL)
1784                        ie->ie_post_filter(ie->ie_source);
1785        } else {
1786                if (ie->ie_pre_ithread != NULL)
1787                        ie->ie_pre_ithread(ie->ie_source);
1788        }
1789        td->td_intr_frame = oldframe;
1790        critical_exit();
1791       
1792        /* Interrupt storm logic */
1793        if (thread & FILTER_STRAY) {
1794                ie->ie_count++;
1795                if (ie->ie_count < intr_storm_threshold)
1796                        printf("Interrupt stray detection not present\n");
1797        }
1798
1799        /* Schedule an ithread if needed. */
1800        if (thread & FILTER_SCHEDULE_THREAD) {
1801                if (intr_event_schedule_thread(ie, ithd) != 0)
1802                        panic("%s: impossible stray interrupt", __func__);
1803        }
1804        td->td_intr_nesting_level--;
1805        return (0);
1806}
1807#endif /* __rtems__ */
1808#endif
1809#ifndef __rtems__
1810
1811#ifdef DDB
1812/*
1813 * Dump details about an interrupt handler
1814 */
1815static void
1816db_dump_intrhand(struct intr_handler *ih)
1817{
1818        int comma;
1819
1820        db_printf("\t%-10s ", ih->ih_name);
1821        switch (ih->ih_pri) {
1822        case PI_REALTIME:
1823                db_printf("CLK ");
1824                break;
1825        case PI_AV:
1826                db_printf("AV  ");
1827                break;
1828        case PI_TTY:
1829                db_printf("TTY ");
1830                break;
1831        case PI_NET:
1832                db_printf("NET ");
1833                break;
1834        case PI_DISK:
1835                db_printf("DISK");
1836                break;
1837        case PI_DULL:
1838                db_printf("DULL");
1839                break;
1840        default:
1841                if (ih->ih_pri >= PI_SOFT)
1842                        db_printf("SWI ");
1843                else
1844                        db_printf("%4u", ih->ih_pri);
1845                break;
1846        }
1847        db_printf(" ");
1848        if (ih->ih_filter != NULL) {
1849                db_printf("[F]");
1850                db_printsym((uintptr_t)ih->ih_filter, DB_STGY_PROC);
1851        }
1852        if (ih->ih_handler != NULL) {
1853                if (ih->ih_filter != NULL)
1854                        db_printf(",");
1855                db_printf("[H]");
1856                db_printsym((uintptr_t)ih->ih_handler, DB_STGY_PROC);
1857        }
1858        db_printf("(%p)", ih->ih_argument);
1859        if (ih->ih_need ||
1860            (ih->ih_flags & (IH_EXCLUSIVE | IH_ENTROPY | IH_DEAD |
1861            IH_MPSAFE)) != 0) {
1862                db_printf(" {");
1863                comma = 0;
1864                if (ih->ih_flags & IH_EXCLUSIVE) {
1865                        if (comma)
1866                                db_printf(", ");
1867                        db_printf("EXCL");
1868                        comma = 1;
1869                }
1870                if (ih->ih_flags & IH_ENTROPY) {
1871                        if (comma)
1872                                db_printf(", ");
1873                        db_printf("ENTROPY");
1874                        comma = 1;
1875                }
1876                if (ih->ih_flags & IH_DEAD) {
1877                        if (comma)
1878                                db_printf(", ");
1879                        db_printf("DEAD");
1880                        comma = 1;
1881                }
1882                if (ih->ih_flags & IH_MPSAFE) {
1883                        if (comma)
1884                                db_printf(", ");
1885                        db_printf("MPSAFE");
1886                        comma = 1;
1887                }
1888                if (ih->ih_need) {
1889                        if (comma)
1890                                db_printf(", ");
1891                        db_printf("NEED");
1892                }
1893                db_printf("}");
1894        }
1895        db_printf("\n");
1896}
1897
1898/*
1899 * Dump details about a event.
1900 */
1901void
1902db_dump_intr_event(struct intr_event *ie, int handlers)
1903{
1904        struct intr_handler *ih;
1905        struct intr_thread *it;
1906        int comma;
1907
1908        db_printf("%s ", ie->ie_fullname);
1909        it = ie->ie_thread;
1910        if (it != NULL)
1911                db_printf("(pid %d)", it->it_thread->td_proc->p_pid);
1912        else
1913                db_printf("(no thread)");
1914        if ((ie->ie_flags & (IE_SOFT | IE_ENTROPY | IE_ADDING_THREAD)) != 0 ||
1915            (it != NULL && it->it_need)) {
1916                db_printf(" {");
1917                comma = 0;
1918                if (ie->ie_flags & IE_SOFT) {
1919                        db_printf("SOFT");
1920                        comma = 1;
1921                }
1922                if (ie->ie_flags & IE_ENTROPY) {
1923                        if (comma)
1924                                db_printf(", ");
1925                        db_printf("ENTROPY");
1926                        comma = 1;
1927                }
1928                if (ie->ie_flags & IE_ADDING_THREAD) {
1929                        if (comma)
1930                                db_printf(", ");
1931                        db_printf("ADDING_THREAD");
1932                        comma = 1;
1933                }
1934                if (it != NULL && it->it_need) {
1935                        if (comma)
1936                                db_printf(", ");
1937                        db_printf("NEED");
1938                }
1939                db_printf("}");
1940        }
1941        db_printf("\n");
1942
1943        if (handlers)
1944                TAILQ_FOREACH(ih, &ie->ie_handlers, ih_next)
1945                    db_dump_intrhand(ih);
1946}
1947
1948/*
1949 * Dump data about interrupt handlers
1950 */
1951DB_SHOW_COMMAND(intr, db_show_intr)
1952{
1953        struct intr_event *ie;
1954        int all, verbose;
1955
1956        verbose = index(modif, 'v') != NULL;
1957        all = index(modif, 'a') != NULL;
1958        TAILQ_FOREACH(ie, &event_list, ie_list) {
1959                if (!all && TAILQ_EMPTY(&ie->ie_handlers))
1960                        continue;
1961                db_dump_intr_event(ie, verbose);
1962                if (db_pager_quit)
1963                        break;
1964        }
1965}
1966#endif /* DDB */
1967
1968/*
1969 * Start standard software interrupt threads
1970 */
1971static void
1972start_softintr(void *dummy)
1973{
1974
1975        if (swi_add(NULL, "vm", swi_vm, NULL, SWI_VM, INTR_MPSAFE, &vm_ih))
1976                panic("died while creating vm swi ithread");
1977}
1978SYSINIT(start_softintr, SI_SUB_SOFTINTR, SI_ORDER_FIRST, start_softintr,
1979    NULL);
1980
1981/*
1982 * Sysctls used by systat and others: hw.intrnames and hw.intrcnt.
1983 * The data for this machine dependent, and the declarations are in machine
1984 * dependent code.  The layout of intrnames and intrcnt however is machine
1985 * independent.
1986 *
1987 * We do not know the length of intrcnt and intrnames at compile time, so
1988 * calculate things at run time.
1989 */
1990static int
1991sysctl_intrnames(SYSCTL_HANDLER_ARGS)
1992{
1993        return (sysctl_handle_opaque(oidp, intrnames, sintrnames, req));
1994}
1995
1996SYSCTL_PROC(_hw, OID_AUTO, intrnames, CTLTYPE_OPAQUE | CTLFLAG_RD,
1997    NULL, 0, sysctl_intrnames, "", "Interrupt Names");
1998
1999static int
2000sysctl_intrcnt(SYSCTL_HANDLER_ARGS)
2001{
2002        return (sysctl_handle_opaque(oidp, intrcnt, sintrcnt, req));
2003}
2004
2005SYSCTL_PROC(_hw, OID_AUTO, intrcnt, CTLTYPE_OPAQUE | CTLFLAG_RD,
2006    NULL, 0, sysctl_intrcnt, "", "Interrupt Counts");
2007
2008#ifdef DDB
2009/*
2010 * DDB command to dump the interrupt statistics.
2011 */
2012DB_SHOW_COMMAND(intrcnt, db_show_intrcnt)
2013{
2014        u_long *i;
2015        char *cp;
2016        u_int j;
2017
2018        cp = intrnames;
2019        j = 0;
2020        for (i = intrcnt; j < (sintrcnt / sizeof(u_long)) && !db_pager_quit;
2021            i++, j++) {
2022                if (*cp == '\0')
2023                        break;
2024                if (*i != 0)
2025                        db_printf("%s\t%lu\n", cp, *i);
2026                cp += strlen(cp) + 1;
2027        }
2028}
2029#endif
2030#endif /* __rtems__ */
Note: See TracBrowser for help on using the repository browser.