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/riscv/riscv/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) 2015-2016 Ruslan Bukin <br@bsdpad.com>
    3  * All rights reserved.
    4  *
    5  * Portions of this software were developed by SRI International and the
    6  * University of Cambridge Computer Laboratory under DARPA/AFRL contract
    7  * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
    8  *
    9  * Portions of this software were developed by the University of Cambridge
   10  * Computer Laboratory as part of the CTSRD Project, with support from the
   11  * UK Higher Education Innovation Fund (HEIF).
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  */
   34 
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD: releng/11.2/sys/riscv/riscv/intr_machdep.c 298636 2016-04-26 12:56:44Z br $");
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/bus.h>
   41 #include <sys/cpuset.h>
   42 #include <sys/interrupt.h>
   43 #include <sys/smp.h>
   44 
   45 #include <machine/clock.h>
   46 #include <machine/cpu.h>
   47 #include <machine/cpufunc.h>
   48 #include <machine/frame.h>
   49 #include <machine/intr.h>
   50 
   51 #ifdef SMP
   52 #include <machine/smp.h>
   53 #endif
   54 
   55 u_long intrcnt[NIRQS];
   56 size_t sintrcnt = sizeof(intrcnt);
   57 
   58 char intrnames[NIRQS * (MAXCOMLEN + 1) * 2];
   59 size_t sintrnames = sizeof(intrnames);
   60 
   61 static struct intr_event *intr_events[NIRQS];
   62 static riscv_intrcnt_t riscv_intr_counters[NIRQS];
   63 
   64 static int intrcnt_index;
   65 
   66 riscv_intrcnt_t
   67 riscv_intrcnt_create(const char* name)
   68 {
   69         riscv_intrcnt_t counter;
   70 
   71         counter = &intrcnt[intrcnt_index++];
   72         riscv_intrcnt_setname(counter, name);
   73 
   74         return (counter);
   75 }
   76 
   77 void
   78 riscv_intrcnt_setname(riscv_intrcnt_t counter, const char *name)
   79 {
   80         int i;
   81 
   82         i = (counter - intrcnt);
   83 
   84         KASSERT(counter != NULL, ("riscv_intrcnt_setname: NULL counter"));
   85 
   86         snprintf(intrnames + (MAXCOMLEN + 1) * i,
   87             MAXCOMLEN + 1, "%-*s", MAXCOMLEN, name);
   88 }
   89 
   90 static void
   91 riscv_mask_irq(void *source)
   92 {
   93         uintptr_t irq;
   94 
   95         irq = (uintptr_t)source;
   96 
   97         switch (irq) {
   98         case IRQ_TIMER:
   99                 csr_clear(sie, SIE_STIE);
  100                 break;
  101         case IRQ_SOFTWARE:
  102                 csr_clear(sie, SIE_SSIE);
  103                 break;
  104         case IRQ_UART:
  105                 machine_command(ECALL_IO_IRQ_MASK, 0);
  106                 break;
  107         default:
  108                 panic("Unknown irq %d\n", irq);
  109         }
  110 }
  111 
  112 static void
  113 riscv_unmask_irq(void *source)
  114 {
  115         uintptr_t irq;
  116 
  117         irq = (uintptr_t)source;
  118 
  119         switch (irq) {
  120         case IRQ_TIMER:
  121                 csr_set(sie, SIE_STIE);
  122                 break;
  123         case IRQ_SOFTWARE:
  124                 csr_set(sie, SIE_SSIE);
  125                 break;
  126         case IRQ_UART:
  127                 machine_command(ECALL_IO_IRQ_MASK, 1);
  128                 break;
  129         default:
  130                 panic("Unknown irq %d\n", irq);
  131         }
  132 }
  133 
  134 void
  135 riscv_init_interrupts(void)
  136 {
  137         char name[MAXCOMLEN + 1];
  138         int i;
  139 
  140         for (i = 0; i < NIRQS; i++) {
  141                 snprintf(name, MAXCOMLEN + 1, "int%d:", i);
  142                 riscv_intr_counters[i] = riscv_intrcnt_create(name);
  143         }
  144 }
  145 
  146 int
  147 riscv_setup_intr(const char *name, driver_filter_t *filt,
  148     void (*handler)(void*), void *arg, int irq, int flags, void **cookiep)
  149 {
  150         struct intr_event *event;
  151         int error;
  152 
  153         if (irq < 0 || irq >= NIRQS)
  154                 panic("%s: unknown intr %d", __func__, irq);
  155 
  156         event = intr_events[irq];
  157         if (event == NULL) {
  158                 error = intr_event_create(&event, (void *)(uintptr_t)irq, 0,
  159                     irq, riscv_mask_irq, riscv_unmask_irq,
  160                     NULL, NULL, "int%d", irq);
  161                 if (error)
  162                         return (error);
  163                 intr_events[irq] = event;
  164                 riscv_unmask_irq((void*)(uintptr_t)irq);
  165         }
  166 
  167         error = intr_event_add_handler(event, name, filt, handler, arg,
  168             intr_priority(flags), flags, cookiep);
  169         if (error) {
  170                 printf("Failed to setup intr: %d\n", irq);
  171                 return (error);
  172         }
  173 
  174         riscv_intrcnt_setname(riscv_intr_counters[irq],
  175                              event->ie_fullname);
  176 
  177         return (0);
  178 }
  179 
  180 int
  181 riscv_teardown_intr(void *ih)
  182 {
  183 
  184         /* TODO */
  185 
  186         return (0);
  187 }
  188 
  189 int
  190 riscv_config_intr(u_int irq, enum intr_trigger trig, enum intr_polarity pol)
  191 {
  192 
  193         /* There is no configuration for interrupts */
  194 
  195         return (0);
  196 }
  197 
  198 void
  199 riscv_cpu_intr(struct trapframe *frame)
  200 {
  201         struct intr_event *event;
  202         int active_irq;
  203 
  204         critical_enter();
  205 
  206         KASSERT(frame->tf_scause & EXCP_INTR,
  207                 ("riscv_cpu_intr: wrong frame passed"));
  208 
  209         active_irq = (frame->tf_scause & EXCP_MASK);
  210 
  211         switch (active_irq) {
  212         case IRQ_UART:
  213         case IRQ_SOFTWARE:
  214         case IRQ_TIMER:
  215                 event = intr_events[active_irq];
  216                 /* Update counters */
  217                 atomic_add_long(riscv_intr_counters[active_irq], 1);
  218                 PCPU_INC(cnt.v_intr);
  219                 break;
  220         case IRQ_HTIF:
  221                 /* HTIF interrupts are only handled in machine mode */
  222                 panic("%s: HTIF interrupt", __func__);
  223                 break;
  224         default:
  225                 event = NULL;
  226         }
  227 
  228         if (!event || TAILQ_EMPTY(&event->ie_handlers) ||
  229             (intr_event_handle(event, frame) != 0))
  230                 printf("stray interrupt %d\n", active_irq);
  231 
  232         critical_exit();
  233 }
  234 
  235 #ifdef SMP
  236 void
  237 riscv_setup_ipihandler(driver_filter_t *filt)
  238 {
  239 
  240         riscv_setup_intr("ipi", filt, NULL, NULL, IRQ_SOFTWARE,
  241             INTR_TYPE_MISC, NULL);
  242 }
  243 
  244 void
  245 riscv_unmask_ipi(void)
  246 {
  247 
  248         csr_set(sie, SIE_SSIE);
  249 }
  250 
  251 /* Sending IPI */
  252 static void
  253 ipi_send(struct pcpu *pc, int ipi)
  254 {
  255 
  256         CTR3(KTR_SMP, "%s: cpu=%d, ipi=%x", __func__, pc->pc_cpuid, ipi);
  257 
  258         atomic_set_32(&pc->pc_pending_ipis, ipi);
  259         machine_command(ECALL_SEND_IPI, pc->pc_reg);
  260 
  261         CTR1(KTR_SMP, "%s: sent", __func__);
  262 }
  263 
  264 void
  265 ipi_all_but_self(u_int ipi)
  266 {
  267         cpuset_t other_cpus;
  268 
  269         other_cpus = all_cpus;
  270         CPU_CLR(PCPU_GET(cpuid), &other_cpus);
  271 
  272         CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
  273         ipi_selected(other_cpus, ipi);
  274 }
  275 
  276 void
  277 ipi_cpu(int cpu, u_int ipi)
  278 {
  279         cpuset_t cpus;
  280 
  281         CPU_ZERO(&cpus);
  282         CPU_SET(cpu, &cpus);
  283 
  284         CTR3(KTR_SMP, "%s: cpu: %d, ipi: %x\n", __func__, cpu, ipi);
  285         ipi_send(cpuid_to_pcpu[cpu], ipi);
  286 }
  287 
  288 void
  289 ipi_selected(cpuset_t cpus, u_int ipi)
  290 {
  291         struct pcpu *pc;
  292 
  293         CTR1(KTR_SMP, "ipi_selected: ipi: %x", ipi);
  294 
  295         STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
  296                 if (CPU_ISSET(pc->pc_cpuid, &cpus)) {
  297                         CTR3(KTR_SMP, "%s: pc: %p, ipi: %x\n", __func__, pc,
  298                             ipi);
  299                         ipi_send(pc, ipi);
  300                 }
  301         }
  302 }
  303 
  304 #endif

Cache object: b77f6b7a43d3a11d613535ca58272fb6


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