1 /* $OpenBSD: intr.h,v 1.6 2021/06/29 21:27:52 kettenis 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/device.h> 105 #include <sys/queue.h> 106 107 #include <machine/frame.h> 108 109 int splraise(int); 110 int spllower(int); 111 void splx(int); 112 113 void riscv_cpu_intr(void *); 114 void riscv_do_pending_intr(int); 115 void riscv_set_intr_func(int (*raise)(int), int (*lower)(int), 116 void (*x)(int), void (*setipl)(int)); 117 void riscv_set_intr_handler(void (*intr_handle)(void *)); 118 119 struct machine_intr_handle { 120 struct interrupt_controller *ih_ic; 121 void *ih_ih; 122 }; 123 124 struct riscv_intr_func { 125 int (*raise)(int); 126 int (*lower)(int); 127 void (*x)(int); 128 void (*setipl)(int); 129 }; 130 131 extern struct riscv_intr_func riscv_intr_func; 132 133 #define splraise(cpl) (riscv_intr_func.raise(cpl)) 134 #define _splraise(cpl) (riscv_intr_func.raise(cpl)) 135 #define spllower(cpl) (riscv_intr_func.lower(cpl)) 136 #define splx(cpl) (riscv_intr_func.x(cpl)) 137 138 #define splsoft() splraise(IPL_SOFT) 139 #define splsoftclock() splraise(IPL_SOFTCLOCK) 140 #define splsoftnet() splraise(IPL_SOFTNET) 141 #define splsofttty() splraise(IPL_SOFTTTY) 142 #define splbio() splraise(IPL_BIO) 143 #define splnet() splraise(IPL_NET) 144 #define spltty() splraise(IPL_TTY) 145 #define splvm() splraise(IPL_VM) 146 #define splaudio() splraise(IPL_AUDIO) 147 #define splclock() splraise(IPL_CLOCK) 148 #define splsched() splraise(IPL_SCHED) 149 #define splstatclock() splraise(IPL_STATCLOCK) 150 #define splhigh() splraise(IPL_HIGH) 151 152 #define spl0() spllower(IPL_NONE) 153 154 #include <machine/riscvreg.h> 155 156 void intr_barrier(void *); 157 158 void riscv_init_smask(void); /* XXX */ 159 extern uint32_t riscv_smask[NIPL]; 160 161 #include <machine/softintr.h> 162 163 void riscv_clock_register(void (*)(void), void (*)(u_int), void (*)(int), 164 void (*)(void)); 165 166 /* 167 **** interrupt controller structure and routines **** 168 */ 169 struct cpu_info; 170 struct interrupt_controller { 171 int ic_node; 172 void *ic_cookie; 173 void *(*ic_establish)(void *, int *, int, struct cpu_info *, 174 int (*)(void *), void *, char *); 175 void *(*ic_establish_msi)(void *, uint64_t *, uint64_t *, int, 176 struct cpu_info *, int (*)(void *), void *, char *); 177 void (*ic_disestablish)(void *); 178 void (*ic_enable)(void *); 179 void (*ic_disable)(void *); 180 void (*ic_route)(void *, int, struct cpu_info *); 181 void (*ic_cpu_enable)(void); 182 void (*ic_barrier)(void *); 183 184 LIST_ENTRY(interrupt_controller) ic_list; 185 uint32_t ic_phandle; 186 uint32_t ic_cells; 187 }; 188 189 void riscv_intr_init_fdt(void); 190 void riscv_intr_register_fdt(struct interrupt_controller *); 191 void *riscv_intr_establish_fdt(int, int, int (*)(void *), 192 void *, char *); 193 void *riscv_intr_establish_fdt_idx(int, int, int, int (*)(void *), 194 void *, char *); 195 void *riscv_intr_establish_fdt_idx_cpu(int, int, int, struct cpu_info *, 196 int (*)(void *), void *, char *); 197 void *riscv_intr_establish_fdt_imap_cpu(int, int *, int, int, 198 struct cpu_info *, int (*)(void *), void *, char *); 199 void *riscv_intr_establish_fdt_msi(int, uint64_t *, uint64_t *, int, 200 int (*)(void *), void *, char *); 201 void *riscv_intr_establish_fdt_msi_cpu(int, uint64_t *, uint64_t *, int, 202 struct cpu_info *, int (*)(void *), void *, char *); 203 void riscv_intr_disestablish_fdt(void *); 204 void riscv_intr_enable(void *); 205 void riscv_intr_disable(void *); 206 void riscv_intr_route(void *, int, struct cpu_info *); 207 void riscv_intr_cpu_enable(void); 208 209 #define IPI_NOP 0 210 #define IPI_DDB (1 << 0) 211 212 void intr_send_ipi(struct cpu_info *, int); 213 214 #ifdef DIAGNOSTIC 215 /* 216 * Although this function is implemented in MI code, it must be in this MD 217 * header because we don't want this header to include MI includes. 218 */ 219 void splassert_fail(int, int, const char *); 220 extern int splassert_ctl; 221 void riscv_splassert_check(int, const char *); 222 #define splassert(__wantipl) do { \ 223 if (splassert_ctl > 0) { \ 224 riscv_splassert_check(__wantipl, __func__); \ 225 } \ 226 } while (0) 227 #define splsoftassert(wantipl) splassert(wantipl) 228 #else 229 #define splassert(wantipl) do { /* nothing */ } while (0) 230 #define splsoftassert(wantipl) do { /* nothing */ } while (0) 231 #endif 232 233 #endif /* ! _LOCORE */ 234 235 #endif /* _KERNEL */ 236 237 #endif /* _MACHINE_INTR_H_ */ 238 239