1 /* $OpenBSD: intr.h,v 1.8 2024/10/16 02:32:27 jsg Exp $ */ 2 3 /* 4 * Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) 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 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 19 * 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 #ifndef _MACHINE_INTR_H_ 30 #define _MACHINE_INTR_H_ 31 32 /* 33 * The interrupt level ipl is a logical level; per-platform interrupt 34 * code will turn it into the appropriate hardware interrupt masks 35 * values. 36 * 37 * Interrupt sources on the CPU are kept enabled regardless of the 38 * current ipl value; individual hardware sources interrupting while 39 * logically masked are masked on the fly, remembered as pending, and 40 * unmasked at the first splx() opportunity. 41 */ 42 #ifdef _KERNEL 43 44 /* Interrupt priority `levels'; not mutually exclusive. */ 45 #define IPL_NONE 0 /* nothing */ 46 #define IPL_SOFT 1 /* soft interrupts */ 47 #define IPL_SOFTCLOCK 2 /* soft clock interrupts */ 48 #define IPL_SOFTNET 3 /* soft network interrupts */ 49 #define IPL_SOFTTTY 4 /* soft terminal interrupts */ 50 #define IPL_BIO 5 /* block I/O */ 51 #define IPL_NET 6 /* network */ 52 #define IPL_TTY 7 /* terminal */ 53 #define IPL_VM 8 /* memory allocation */ 54 #define IPL_AUDIO 9 /* audio */ 55 #define IPL_CLOCK 10 /* clock */ 56 #define IPL_SCHED IPL_CLOCK 57 #define IPL_STATCLOCK IPL_CLOCK 58 #define IPL_HIGH 11 /* everything */ 59 #define IPL_IPI 12 /* interprocessor interrupt */ 60 #define NIPL 13 /* number of levels */ 61 62 #define IPL_MPFLOOR IPL_TTY 63 /* Interrupt priority 'flags'. */ 64 #define IPL_IRQMASK 0xf /* priority only */ 65 #define IPL_FLAGMASK 0xf00 /* flags only*/ 66 #define IPL_MPSAFE 0x100 /* 'mpsafe' interrupt, no kernel lock */ 67 68 /* Interrupt sharing types. */ 69 #define IST_NONE 0 /* none */ 70 #define IST_PULSE 1 /* pulsed */ 71 #define IST_EDGE 2 /* edge-triggered */ 72 #define IST_LEVEL 3 /* level-triggered */ 73 74 #define IST_LEVEL_LOW IST_LEVEL 75 #define IST_LEVEL_HIGH 4 76 #define IST_EDGE_FALLING IST_EDGE 77 #define IST_EDGE_RISING 5 78 #define IST_EDGE_BOTH 6 79 80 /* RISCV interrupt mcause, from freebsd */ 81 #define RISCV_NIRQ 1024 82 83 #ifndef NIRQ 84 #define NIRQ RISCV_NIRQ 85 #endif 86 87 enum { 88 IRQ_SOFTWARE_USER, 89 IRQ_SOFTWARE_SUPERVISOR, 90 IRQ_SOFTWARE_HYPERVISOR, 91 IRQ_SOFTWARE_MACHINE, 92 IRQ_TIMER_USER, 93 IRQ_TIMER_SUPERVISOR, 94 IRQ_TIMER_HYPERVISOR, 95 IRQ_TIMER_MACHINE, 96 IRQ_EXTERNAL_USER, 97 IRQ_EXTERNAL_SUPERVISOR, 98 IRQ_EXTERNAL_HYPERVISOR, 99 IRQ_EXTERNAL_MACHINE, 100 INTC_NIRQS 101 }; 102 103 #ifndef _LOCORE 104 #include <sys/queue.h> 105 106 int splraise(int); 107 int spllower(int); 108 void splx(int); 109 110 void riscv_cpu_intr(void *); 111 void riscv_do_pending_intr(int); 112 void riscv_set_intr_func(int (*raise)(int), int (*lower)(int), 113 void (*x)(int), void (*setipl)(int)); 114 void riscv_set_intr_handler(void (*intr_handle)(void *)); 115 116 struct machine_intr_handle { 117 struct interrupt_controller *ih_ic; 118 void *ih_ih; 119 }; 120 121 struct riscv_intr_func { 122 int (*raise)(int); 123 int (*lower)(int); 124 void (*x)(int); 125 void (*setipl)(int); 126 }; 127 128 extern struct riscv_intr_func riscv_intr_func; 129 130 #define splraise(cpl) (riscv_intr_func.raise(cpl)) 131 #define _splraise(cpl) (riscv_intr_func.raise(cpl)) 132 #define spllower(cpl) (riscv_intr_func.lower(cpl)) 133 #define splx(cpl) (riscv_intr_func.x(cpl)) 134 135 #define splsoft() splraise(IPL_SOFT) 136 #define splsoftclock() splraise(IPL_SOFTCLOCK) 137 #define splsoftnet() splraise(IPL_SOFTNET) 138 #define splsofttty() splraise(IPL_SOFTTTY) 139 #define splbio() splraise(IPL_BIO) 140 #define splnet() splraise(IPL_NET) 141 #define spltty() splraise(IPL_TTY) 142 #define splvm() splraise(IPL_VM) 143 #define splaudio() splraise(IPL_AUDIO) 144 #define splclock() splraise(IPL_CLOCK) 145 #define splsched() splraise(IPL_SCHED) 146 #define splstatclock() splraise(IPL_STATCLOCK) 147 #define splhigh() splraise(IPL_HIGH) 148 149 #define spl0() spllower(IPL_NONE) 150 151 void intr_barrier(void *); 152 153 void riscv_init_smask(void); /* XXX */ 154 extern uint32_t riscv_smask[NIPL]; 155 156 #include <machine/softintr.h> 157 158 void riscv_clock_register(void (*)(void), void (*)(u_int), void (*)(int), 159 void (*)(void)); 160 161 /* 162 **** interrupt controller structure and routines **** 163 */ 164 struct cpu_info; 165 struct interrupt_controller { 166 int ic_node; 167 void *ic_cookie; 168 void *(*ic_establish)(void *, int *, int, struct cpu_info *, 169 int (*)(void *), void *, char *); 170 void *(*ic_establish_msi)(void *, uint64_t *, uint64_t *, int, 171 struct cpu_info *, int (*)(void *), void *, char *); 172 void (*ic_disestablish)(void *); 173 void (*ic_enable)(void *); 174 void (*ic_disable)(void *); 175 void (*ic_route)(void *, int, struct cpu_info *); 176 void (*ic_cpu_enable)(void); 177 void (*ic_barrier)(void *); 178 179 LIST_ENTRY(interrupt_controller) ic_list; 180 uint32_t ic_phandle; 181 uint32_t ic_cells; 182 }; 183 184 void riscv_intr_init_fdt(void); 185 void riscv_intr_register_fdt(struct interrupt_controller *); 186 void *riscv_intr_establish_fdt(int, int, int (*)(void *), 187 void *, char *); 188 void *riscv_intr_establish_fdt_idx(int, int, int, int (*)(void *), 189 void *, char *); 190 void *riscv_intr_establish_fdt_idx_cpu(int, int, int, struct cpu_info *, 191 int (*)(void *), void *, char *); 192 void *riscv_intr_establish_fdt_imap_cpu(int, int *, int, int, 193 struct cpu_info *, int (*)(void *), void *, char *); 194 void *riscv_intr_establish_fdt_msi(int, uint64_t *, uint64_t *, int, 195 int (*)(void *), void *, char *); 196 void *riscv_intr_establish_fdt_msi_cpu(int, uint64_t *, uint64_t *, int, 197 struct cpu_info *, int (*)(void *), void *, char *); 198 void riscv_intr_disestablish_fdt(void *); 199 void riscv_intr_enable(void *); 200 void riscv_intr_disable(void *); 201 void riscv_intr_route(void *, int, struct cpu_info *); 202 void riscv_intr_cpu_enable(void); 203 204 #define IPI_NOP 0 205 #define IPI_DDB (1 << 0) 206 207 void intr_send_ipi(struct cpu_info *, int); 208 209 #ifdef DIAGNOSTIC 210 /* 211 * Although this function is implemented in MI code, it must be in this MD 212 * header because we don't want this header to include MI includes. 213 */ 214 void splassert_fail(int, int, const char *); 215 extern int splassert_ctl; 216 void riscv_splassert_check(int, const char *); 217 #define splassert(__wantipl) do { \ 218 if (splassert_ctl > 0) { \ 219 riscv_splassert_check(__wantipl, __func__); \ 220 } \ 221 } while (0) 222 #define splsoftassert(wantipl) splassert(wantipl) 223 #else 224 #define splassert(wantipl) do { /* nothing */ } while (0) 225 #define splsoftassert(wantipl) do { /* nothing */ } while (0) 226 #endif 227 228 #endif /* ! _LOCORE */ 229 230 #endif /* _KERNEL */ 231 232 #endif /* _MACHINE_INTR_H_ */ 233 234