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

Cache object: 2b10ad731fa9d574ad1a740d3fa2f54b


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