Home | History | Annotate | Line # | Download | only in riscv
      1 /*	$NetBSD: interrupt.c,v 1.3 2024/11/19 08:28:01 skrll Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2022 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Simon Burge and Nick Hudson.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include "opt_multiprocessor.h"
     33 
     34 #include <sys/cdefs.h>
     35 
     36 __RCSID("$NetBSD: interrupt.c,v 1.3 2024/11/19 08:28:01 skrll Exp $");
     37 
     38 #include <sys/param.h>
     39 #include <sys/systm.h>
     40 
     41 #include <sys/bus.h>
     42 #include <sys/cpu.h>
     43 #include <sys/kernel.h>
     44 
     45 #include <machine/locore.h>
     46 #include <machine/machdep.h>
     47 #include <machine/sbi.h>
     48 
     49 #include <riscv/dev/plicvar.h>
     50 
     51 
     52 static void
     53 riscv_intr_default_handler(struct trapframe *frame, register_t epc,
     54     register_t status, register_t cause)
     55 {
     56 #if 1
     57 	panic("not supposed to get here");
     58 #else
     59 	struct cpu_info * const ci = curcpu();
     60 	const int code = CAUSE_CODE(cause);
     61 
     62 	KASSERT(CAUSE_INTERRUPT_P(cause));
     63 
     64 	ci->ci_intr_depth++;
     65 	switch (code) {
     66 	case IRQ_SUPERVISOR_SOFTWARE:
     67 #ifdef MULTIPROCESSOR
     68 		ipi_handler(tf);
     69 #else
     70 		panic("%s: SUPERVISOR SOFTWARE interrupt", __func__);
     71 #endif
     72 		break;
     73 	case IRQ_SUPERVISOR_TIMER: {
     74 		struct clockframe cf = {
     75 			.cf_epc = epc,
     76 			.cf_status = status,
     77 			.cf_intr_depth = ci->ci_intr_depth
     78 		};
     79 		timer_handler(&cf);
     80 		break;
     81 	    }
     82 	case IRQ_SUPERVISOR_EXTERNAL:
     83 		extintr_handler(tf);
     84 		break;
     85 	default:
     86 		panic("%s: unknown exception code %u", __func__, code);
     87 	}
     88 	ci->ci_intr_depth--;
     89 #endif
     90 }
     91 
     92 
     93 static void (*_riscv_intr_handler)(struct trapframe *, register_t,
     94     register_t, register_t) = riscv_intr_default_handler;
     95 
     96 
     97 void
     98 riscv_intr_set_handler(void (*intr_handler)(struct trapframe *, register_t,
     99     register_t, register_t))
    100 {
    101 	KASSERT(_riscv_intr_handler == riscv_intr_default_handler ||
    102 		_riscv_intr_handler == intr_handler);
    103 	_riscv_intr_handler = intr_handler;
    104 }
    105 
    106 
    107 void
    108 cpu_intr(struct trapframe *tf, register_t epc, register_t status,
    109     register_t cause)
    110 {
    111 	_riscv_intr_handler(tf, epc, status, cause);
    112 }
    113 
    114 
    115 void *
    116 intr_establish_xname(int irq, int ipl, int type, int (*func)(void *), void *arg,
    117     const char *xname)
    118 {
    119 	KASSERT(!cpu_intr_p());
    120 	KASSERT(!cpu_softintr_p());
    121 
    122 	return plic_intr_establish_xname(irq, ipl, type, func, arg, xname);
    123 }
    124 
    125 void *
    126 intr_establish(int irq, int ipl, int type, int (*func)(void *), void *arg)
    127 {
    128 	return intr_establish_xname(irq, ipl, type, func, arg, NULL);
    129 }
    130 
    131 void
    132 intr_disestablish(void *ih)
    133 {
    134 //	struct intrsource * const is = ih;
    135 
    136 	KASSERT(!cpu_intr_p());
    137 	KASSERT(!cpu_softintr_p());
    138 }
    139 
    140 
    141 #ifdef MULTIPROCESSOR
    142 __CTASSERT(NIPIS < 16);
    143 
    144 int
    145 riscv_ipi_intr(void *arg)
    146 {
    147 	struct cpu_info * const ci = curcpu();
    148 	membar_acquire();
    149 
    150 	csr_sip_clear(SIP_SSIP);	/* clean pending interrupt status */
    151 
    152 	unsigned long pending;
    153 	while ((pending = atomic_swap_ulong(&ci->ci_request_ipis, 0)) != 0) {
    154 		membar_acquire();
    155 		atomic_or_ulong(&ci->ci_active_ipis, pending);
    156 
    157 		ipi_process(ci, pending);
    158 
    159 		atomic_and_ulong(&ci->ci_active_ipis, pending);
    160 	}
    161 
    162 	return 1;
    163 }
    164 
    165 int
    166 cpu_send_ipi(struct cpu_info *ci, int req)
    167 {
    168 	KASSERT(req < NIPIS);
    169 	if (ci == NULL) {
    170 		CPU_INFO_ITERATOR cii;
    171 		for (CPU_INFO_FOREACH(cii, ci)) {
    172 			if (ci != curcpu()) {
    173 				cpu_send_ipi(ci, req);
    174 			}
    175 		}
    176 		return 0;
    177 	}
    178 	const uint32_t ipi_mask = __BIT(req);
    179 
    180 	membar_release();
    181 	atomic_or_ulong(&ci->ci_request_ipis, ipi_mask);
    182 
    183 	membar_release();
    184 	unsigned long hartmask = 0;
    185 	const cpuid_t hartid = ci->ci_cpuid;
    186 	KASSERT(hartid < sizeof(unsigned long) * NBBY);
    187 	hartmask |= __BIT(hartid);
    188 	struct sbiret sbiret = sbi_send_ipi(hartmask, 0);
    189 
    190 	KASSERT(sbiret.error == SBI_SUCCESS);
    191 
    192 	return 0;
    193 }
    194 #endif	/* MULTIPROCESSOR */
    195