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/mips/mips/intr_machdep.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) 2006 Oleksandr Tymoshenko
    5  * Copyright (c) 2002-2004 Juli Mallett <jmallett@FreeBSD.org>
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions, and the following disclaimer,
   13  *    without modification, immediately at the beginning of the file.
   14  * 2. The name of the author may not be used to endorse or promote products
   15  *    derived from this software without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD$");
   33 
   34 #include "opt_hwpmc_hooks.h"
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/bus.h>
   39 #include <sys/interrupt.h>
   40 #include <sys/pmc.h>
   41 #include <sys/pmckern.h>
   42 
   43 #include <machine/clock.h>
   44 #include <machine/cpu.h>
   45 #include <machine/cpufunc.h>
   46 #include <machine/cpuinfo.h>
   47 #include <machine/cpuregs.h>
   48 #include <machine/frame.h>
   49 #include <machine/intr_machdep.h>
   50 #include <machine/md_var.h>
   51 #include <machine/trap.h>
   52 
   53 static struct intr_event *hardintr_events[NHARD_IRQS];
   54 static struct intr_event *softintr_events[NSOFT_IRQS];
   55 static mips_intrcnt_t mips_intr_counters[NSOFT_IRQS + NHARD_IRQS];
   56 
   57 static int intrcnt_index;
   58 
   59 static cpu_intr_mask_t          hardintr_mask_func;
   60 static cpu_intr_unmask_t        hardintr_unmask_func;
   61 
   62 mips_intrcnt_t
   63 mips_intrcnt_create(const char* name)
   64 {
   65         mips_intrcnt_t counter = &intrcnt[intrcnt_index++];
   66 
   67         mips_intrcnt_setname(counter, name);
   68         return counter;
   69 }
   70 
   71 void
   72 mips_intrcnt_setname(mips_intrcnt_t counter, const char *name)
   73 {
   74         int idx = counter - intrcnt;
   75 
   76         KASSERT(counter != NULL, ("mips_intrcnt_setname: NULL counter"));
   77 
   78         snprintf(intrnames + (MAXCOMLEN + 1) * idx,
   79             MAXCOMLEN + 1, "%-*s", MAXCOMLEN, name);
   80 }
   81 
   82 static void
   83 mips_mask_hard_irq(void *source)
   84 {
   85         uintptr_t irq = (uintptr_t)source;
   86 
   87         mips_wr_status(mips_rd_status() & ~(((1 << irq) << 8) << 2));
   88 }
   89 
   90 static void
   91 mips_unmask_hard_irq(void *source)
   92 {
   93         uintptr_t irq = (uintptr_t)source;
   94 
   95         mips_wr_status(mips_rd_status() | (((1 << irq) << 8) << 2));
   96 }
   97 
   98 static void
   99 mips_mask_soft_irq(void *source)
  100 {
  101         uintptr_t irq = (uintptr_t)source;
  102 
  103         mips_wr_status(mips_rd_status() & ~((1 << irq) << 8));
  104 }
  105 
  106 static void
  107 mips_unmask_soft_irq(void *source)
  108 {
  109         uintptr_t irq = (uintptr_t)source;
  110 
  111         mips_wr_status(mips_rd_status() | ((1 << irq) << 8));
  112 }
  113 
  114 /*
  115  * Perform initialization of interrupts prior to setting 
  116  * handlings
  117  */
  118 void
  119 cpu_init_interrupts()
  120 {
  121         int i;
  122         char name[MAXCOMLEN + 1];
  123 
  124         /*
  125          * Initialize all available vectors so spare IRQ
  126          * would show up in systat output 
  127          */
  128         for (i = 0; i < NSOFT_IRQS; i++) {
  129                 snprintf(name, MAXCOMLEN + 1, "sint%d:", i);
  130                 mips_intr_counters[i] = mips_intrcnt_create(name);
  131         }
  132 
  133         for (i = 0; i < NHARD_IRQS; i++) {
  134                 snprintf(name, MAXCOMLEN + 1, "int%d:", i);
  135                 mips_intr_counters[NSOFT_IRQS + i] = mips_intrcnt_create(name);
  136         }
  137 }
  138 
  139 void
  140 cpu_set_hardintr_mask_func(cpu_intr_mask_t func)
  141 {
  142 
  143         hardintr_mask_func = func;
  144 }
  145 
  146 void
  147 cpu_set_hardintr_unmask_func(cpu_intr_unmask_t func)
  148 {
  149 
  150         hardintr_unmask_func = func;
  151 }
  152 
  153 void
  154 cpu_establish_hardintr(const char *name, driver_filter_t *filt,
  155     void (*handler)(void*), void *arg, int irq, int flags, void **cookiep)
  156 {
  157         struct intr_event *event;
  158         int error;
  159 
  160         /*
  161          * We have 6 levels, but thats 0 - 5 (not including 6)
  162          */
  163         if (irq < 0 || irq >= NHARD_IRQS)
  164                 panic("%s called for unknown hard intr %d", __func__, irq);
  165 
  166         if (hardintr_mask_func == NULL)
  167                 hardintr_mask_func = mips_mask_hard_irq;
  168 
  169         if (hardintr_unmask_func == NULL)
  170                 hardintr_unmask_func = mips_unmask_hard_irq;
  171 
  172         event = hardintr_events[irq];
  173         if (event == NULL) {
  174                 error = intr_event_create(&event, (void *)(uintptr_t)irq, 0,
  175                     irq, hardintr_mask_func, hardintr_unmask_func,
  176                     NULL, NULL, "int%d", irq);
  177                 if (error)
  178                         return;
  179                 hardintr_events[irq] = event;
  180                 mips_unmask_hard_irq((void*)(uintptr_t)irq);
  181         }
  182 
  183         intr_event_add_handler(event, name, filt, handler, arg,
  184             intr_priority(flags), flags, cookiep);
  185 
  186         mips_intrcnt_setname(mips_intr_counters[NSOFT_IRQS + irq],
  187                              event->ie_fullname);
  188 }
  189 
  190 void
  191 cpu_establish_softintr(const char *name, driver_filter_t *filt,
  192     void (*handler)(void*), void *arg, int irq, int flags,
  193     void **cookiep)
  194 {
  195         struct intr_event *event;
  196         int error;
  197 
  198 #if 0
  199         printf("Establish SOFT IRQ %d: filt %p handler %p arg %p\n",
  200             irq, filt, handler, arg);
  201 #endif
  202         if (irq < 0 || irq > NSOFT_IRQS)
  203                 panic("%s called for unknown hard intr %d", __func__, irq);
  204 
  205         event = softintr_events[irq];
  206         if (event == NULL) {
  207                 error = intr_event_create(&event, (void *)(uintptr_t)irq, 0,
  208                     irq, mips_mask_soft_irq, mips_unmask_soft_irq,
  209                     NULL, NULL, "sint%d:", irq);
  210                 if (error)
  211                         return;
  212                 softintr_events[irq] = event;
  213                 mips_unmask_soft_irq((void*)(uintptr_t)irq);
  214         }
  215 
  216         intr_event_add_handler(event, name, filt, handler, arg,
  217             intr_priority(flags), flags, cookiep);
  218 
  219         mips_intrcnt_setname(mips_intr_counters[irq], event->ie_fullname);
  220 }
  221 
  222 void
  223 cpu_intr(struct trapframe *tf)
  224 {
  225         struct intr_event *event;
  226         register_t cause, status;
  227         int hard, i, intr;
  228 
  229         critical_enter();
  230 
  231         cause = mips_rd_cause();
  232         status = mips_rd_status();
  233         intr = (cause & MIPS_INT_MASK) >> 8;
  234         /*
  235          * Do not handle masked interrupts. They were masked by 
  236          * pre_ithread function (mips_mask_XXX_intr) and will be 
  237          * unmasked once ithread is through with handler
  238          */
  239         intr &= (status & MIPS_INT_MASK) >> 8;
  240         while ((i = fls(intr)) != 0) {
  241                 intr &= ~(1 << (i - 1));
  242                 switch (i) {
  243                 case 1: case 2:
  244                         /* Software interrupt. */
  245                         i--; /* Get a 0-offset interrupt. */
  246                         hard = 0;
  247                         event = softintr_events[i];
  248                         mips_intrcnt_inc(mips_intr_counters[i]);
  249                         break;
  250                 default:
  251                         /* Hardware interrupt. */
  252                         i -= 2; /* Trim software interrupt bits. */
  253                         i--; /* Get a 0-offset interrupt. */
  254                         hard = 1;
  255                         event = hardintr_events[i];
  256                         mips_intrcnt_inc(mips_intr_counters[NSOFT_IRQS + i]);
  257                         break;
  258                 }
  259 
  260                 if (!event || CK_SLIST_EMPTY(&event->ie_handlers)) {
  261                         printf("stray %s interrupt %d\n",
  262                             hard ? "hard" : "soft", i);
  263                         continue;
  264                 }
  265 
  266                 if (intr_event_handle(event, tf) != 0) {
  267                         printf("stray %s interrupt %d\n", 
  268                             hard ? "hard" : "soft", i);
  269                 }
  270         }
  271 
  272         KASSERT(i == 0, ("all interrupts handled"));
  273 
  274         critical_exit();
  275 
  276 #ifdef HWPMC_HOOKS
  277         if (pmc_hook && (PCPU_GET(curthread)->td_pflags & TDP_CALLCHAIN))
  278                 pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, tf);
  279 #endif
  280 }

Cache object: 4ff82cb24c69b25902505fc5a916f40b


[ 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.