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-2017 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/12.0/sys/riscv/riscv/intr_machdep.c 335007 2018-06-12 17:45:15Z br $");
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/bus.h>
   41 #include <sys/kernel.h>
   42 #include <sys/module.h>
   43 #include <sys/cpuset.h>
   44 #include <sys/interrupt.h>
   45 #include <sys/smp.h>
   46 
   47 #include <machine/bus.h>
   48 #include <machine/clock.h>
   49 #include <machine/cpu.h>
   50 #include <machine/cpufunc.h>
   51 #include <machine/frame.h>
   52 #include <machine/intr.h>
   53 #include <machine/sbi.h>
   54 
   55 #include <dev/ofw/openfirm.h>
   56 #include <dev/ofw/ofw_bus.h>
   57 #include <dev/ofw/ofw_bus_subr.h>
   58 
   59 #ifdef SMP
   60 #include <machine/smp.h>
   61 #endif
   62 
   63 void intr_irq_handler(struct trapframe *tf);
   64 
   65 struct intc_irqsrc {
   66         struct intr_irqsrc      isrc;
   67         u_int                   irq;
   68 };
   69 
   70 struct intc_irqsrc isrcs[INTC_NIRQS];
   71 
   72 static void
   73 riscv_mask_irq(void *source)
   74 {
   75         uintptr_t irq;
   76 
   77         irq = (uintptr_t)source;
   78 
   79         switch (irq) {
   80         case IRQ_TIMER_SUPERVISOR:
   81                 csr_clear(sie, SIE_STIE);
   82                 break;
   83         case IRQ_SOFTWARE_USER:
   84                 csr_clear(sie, SIE_USIE);
   85                 break;
   86         case IRQ_SOFTWARE_SUPERVISOR:
   87                 csr_clear(sie, SIE_SSIE);
   88                 break;
   89         default:
   90                 panic("Unknown irq %d\n", irq);
   91         }
   92 }
   93 
   94 static void
   95 riscv_unmask_irq(void *source)
   96 {
   97         uintptr_t irq;
   98 
   99         irq = (uintptr_t)source;
  100 
  101         switch (irq) {
  102         case IRQ_TIMER_SUPERVISOR:
  103                 csr_set(sie, SIE_STIE);
  104                 break;
  105         case IRQ_SOFTWARE_USER:
  106                 csr_set(sie, SIE_USIE);
  107                 break;
  108         case IRQ_SOFTWARE_SUPERVISOR:
  109                 csr_set(sie, SIE_SSIE);
  110                 break;
  111         default:
  112                 panic("Unknown irq %d\n", irq);
  113         }
  114 }
  115 
  116 int
  117 riscv_setup_intr(const char *name, driver_filter_t *filt,
  118     void (*handler)(void*), void *arg, int irq, int flags, void **cookiep)
  119 {
  120         struct intr_irqsrc *isrc;
  121         int error;
  122 
  123         if (irq < 0 || irq >= INTC_NIRQS)
  124                 panic("%s: unknown intr %d", __func__, irq);
  125 
  126         isrc = &isrcs[irq].isrc;
  127         if (isrc->isrc_event == NULL) {
  128                 error = intr_event_create(&isrc->isrc_event, isrc, 0, irq,
  129                     riscv_mask_irq, riscv_unmask_irq, NULL, NULL, "int%d", irq);
  130                 if (error)
  131                         return (error);
  132                 riscv_unmask_irq((void*)(uintptr_t)irq);
  133         }
  134 
  135         error = intr_event_add_handler(isrc->isrc_event, name,
  136             filt, handler, arg, intr_priority(flags), flags, cookiep);
  137         if (error) {
  138                 printf("Failed to setup intr: %d\n", irq);
  139                 return (error);
  140         }
  141 
  142         return (0);
  143 }
  144 
  145 int
  146 riscv_teardown_intr(void *ih)
  147 {
  148 
  149         /* TODO */
  150 
  151         return (0);
  152 }
  153 
  154 void
  155 riscv_cpu_intr(struct trapframe *frame)
  156 {
  157         struct intr_irqsrc *isrc;
  158         int active_irq;
  159 
  160         critical_enter();
  161 
  162         KASSERT(frame->tf_scause & EXCP_INTR,
  163                 ("riscv_cpu_intr: wrong frame passed"));
  164 
  165         active_irq = (frame->tf_scause & EXCP_MASK);
  166 
  167         switch (active_irq) {
  168         case IRQ_SOFTWARE_USER:
  169         case IRQ_SOFTWARE_SUPERVISOR:
  170         case IRQ_TIMER_SUPERVISOR:
  171                 isrc = &isrcs[active_irq].isrc;
  172                 if (intr_isrc_dispatch(isrc, frame) != 0)
  173                         printf("stray interrupt %d\n", active_irq);
  174                 break;
  175         case IRQ_EXTERNAL_SUPERVISOR:
  176                 intr_irq_handler(frame);
  177                 break;
  178         default:
  179                 break;
  180         }
  181 
  182         critical_exit();
  183 }
  184 
  185 #ifdef SMP
  186 void
  187 riscv_setup_ipihandler(driver_filter_t *filt)
  188 {
  189 
  190         riscv_setup_intr("ipi", filt, NULL, NULL, IRQ_SOFTWARE_SUPERVISOR,
  191             INTR_TYPE_MISC, NULL);
  192 }
  193 
  194 void
  195 riscv_unmask_ipi(void)
  196 {
  197 
  198         csr_set(sie, SIE_SSIE);
  199 }
  200 
  201 /* Sending IPI */
  202 static void
  203 ipi_send(struct pcpu *pc, int ipi)
  204 {
  205         uintptr_t mask;
  206 
  207         CTR3(KTR_SMP, "%s: cpu=%d, ipi=%x", __func__, pc->pc_cpuid, ipi);
  208 
  209         atomic_set_32(&pc->pc_pending_ipis, ipi);
  210         mask = (1 << (pc->pc_cpuid));
  211 
  212         sbi_send_ipi(&mask);
  213 
  214         CTR1(KTR_SMP, "%s: sent", __func__);
  215 }
  216 
  217 void
  218 ipi_all_but_self(u_int ipi)
  219 {
  220         cpuset_t other_cpus;
  221 
  222         other_cpus = all_cpus;
  223         CPU_CLR(PCPU_GET(cpuid), &other_cpus);
  224 
  225         CTR2(KTR_SMP, "%s: ipi: %x", __func__, ipi);
  226         ipi_selected(other_cpus, ipi);
  227 }
  228 
  229 void
  230 ipi_cpu(int cpu, u_int ipi)
  231 {
  232         cpuset_t cpus;
  233 
  234         CPU_ZERO(&cpus);
  235         CPU_SET(cpu, &cpus);
  236 
  237         CTR3(KTR_SMP, "%s: cpu: %d, ipi: %x\n", __func__, cpu, ipi);
  238         ipi_send(cpuid_to_pcpu[cpu], ipi);
  239 }
  240 
  241 void
  242 ipi_selected(cpuset_t cpus, u_int ipi)
  243 {
  244         struct pcpu *pc;
  245         uintptr_t mask;
  246 
  247         CTR1(KTR_SMP, "ipi_selected: ipi: %x", ipi);
  248 
  249         mask = 0;
  250         STAILQ_FOREACH(pc, &cpuhead, pc_allcpu) {
  251                 if (CPU_ISSET(pc->pc_cpuid, &cpus)) {
  252                         CTR3(KTR_SMP, "%s: pc: %p, ipi: %x\n", __func__, pc,
  253                             ipi);
  254                         atomic_set_32(&pc->pc_pending_ipis, ipi);
  255                         mask |= (1 << (pc->pc_cpuid));
  256                 }
  257         }
  258         sbi_send_ipi(&mask);
  259 }
  260 #endif
  261 
  262 /* Interrupt machdep initialization routine. */
  263 static void
  264 intc_init(void *dummy __unused)
  265 {
  266         int error;
  267         int i;
  268 
  269         for (i = 0; i < INTC_NIRQS; i++) {
  270                 isrcs[i].irq = i;
  271                 error = intr_isrc_register(&isrcs[i].isrc, NULL,
  272                     0, "intc,%u", i);
  273                 if (error != 0)
  274                         printf("Can't register interrupt %d\n", i);
  275         }
  276 }
  277 
  278 SYSINIT(intc_init, SI_SUB_INTR, SI_ORDER_MIDDLE, intc_init, NULL);

Cache object: b4e8cfbe5eed903c8672f3b21396f830


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