1 1.76 mrg /* $NetBSD: kern_softint.c,v 1.76 2024/03/01 04:32:38 mrg Exp $ */ 2 1.2 ad 3 1.2 ad /*- 4 1.58 ad * Copyright (c) 2007, 2008, 2019, 2020 The NetBSD Foundation, Inc. 5 1.2 ad * All rights reserved. 6 1.2 ad * 7 1.2 ad * This code is derived from software contributed to The NetBSD Foundation 8 1.2 ad * by Andrew Doran. 9 1.2 ad * 10 1.2 ad * Redistribution and use in source and binary forms, with or without 11 1.2 ad * modification, are permitted provided that the following conditions 12 1.2 ad * are met: 13 1.2 ad * 1. Redistributions of source code must retain the above copyright 14 1.2 ad * notice, this list of conditions and the following disclaimer. 15 1.2 ad * 2. Redistributions in binary form must reproduce the above copyright 16 1.2 ad * notice, this list of conditions and the following disclaimer in the 17 1.2 ad * documentation and/or other materials provided with the distribution. 18 1.2 ad * 19 1.2 ad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.2 ad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.2 ad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.2 ad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.2 ad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.2 ad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.2 ad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.2 ad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.2 ad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.2 ad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.2 ad * POSSIBILITY OF SUCH DAMAGE. 30 1.2 ad */ 31 1.2 ad 32 1.2 ad /* 33 1.5 ad * Generic software interrupt framework. 34 1.5 ad * 35 1.5 ad * Overview 36 1.5 ad * 37 1.5 ad * The soft interrupt framework provides a mechanism to schedule a 38 1.5 ad * low priority callback that runs with thread context. It allows 39 1.5 ad * for dynamic registration of software interrupts, and for fair 40 1.5 ad * queueing and prioritization of those interrupts. The callbacks 41 1.5 ad * can be scheduled to run from nearly any point in the kernel: by 42 1.5 ad * code running with thread context, by code running from a 43 1.5 ad * hardware interrupt handler, and at any interrupt priority 44 1.5 ad * level. 45 1.5 ad * 46 1.5 ad * Priority levels 47 1.5 ad * 48 1.5 ad * Since soft interrupt dispatch can be tied to the underlying 49 1.5 ad * architecture's interrupt dispatch code, it can be limited 50 1.5 ad * both by the capabilities of the hardware and the capabilities 51 1.5 ad * of the interrupt dispatch code itself. The number of priority 52 1.5 ad * levels is restricted to four. In order of priority (lowest to 53 1.5 ad * highest) the levels are: clock, bio, net, serial. 54 1.5 ad * 55 1.5 ad * The names are symbolic and in isolation do not have any direct 56 1.5 ad * connection with a particular kind of device activity: they are 57 1.5 ad * only meant as a guide. 58 1.5 ad * 59 1.5 ad * The four priority levels map directly to scheduler priority 60 1.5 ad * levels, and where the architecture implements 'fast' software 61 1.5 ad * interrupts, they also map onto interrupt priorities. The 62 1.5 ad * interrupt priorities are intended to be hidden from machine 63 1.5 ad * independent code, which should use thread-safe mechanisms to 64 1.5 ad * synchronize with software interrupts (for example: mutexes). 65 1.5 ad * 66 1.5 ad * Capabilities 67 1.5 ad * 68 1.5 ad * Software interrupts run with limited machine context. In 69 1.5 ad * particular, they do not posess any address space context. They 70 1.5 ad * should not try to operate on user space addresses, or to use 71 1.5 ad * virtual memory facilities other than those noted as interrupt 72 1.5 ad * safe. 73 1.5 ad * 74 1.5 ad * Unlike hardware interrupts, software interrupts do have thread 75 1.5 ad * context. They may block on synchronization objects, sleep, and 76 1.5 ad * resume execution at a later time. 77 1.5 ad * 78 1.5 ad * Since software interrupts are a limited resource and run with 79 1.5 ad * higher priority than most other LWPs in the system, all 80 1.5 ad * block-and-resume activity by a software interrupt must be kept 81 1.67 msaitoh * short to allow further processing at that level to continue. By 82 1.5 ad * extension, code running with process context must take care to 83 1.5 ad * ensure that any lock that may be taken from a software interrupt 84 1.5 ad * can not be held for more than a short period of time. 85 1.5 ad * 86 1.5 ad * The kernel does not allow software interrupts to use facilities 87 1.5 ad * or perform actions that may block for a significant amount of 88 1.5 ad * time. This means that it's not valid for a software interrupt 89 1.10 ad * to sleep on condition variables or wait for resources to become 90 1.10 ad * available (for example, memory). 91 1.5 ad * 92 1.5 ad * Per-CPU operation 93 1.5 ad * 94 1.5 ad * If a soft interrupt is triggered on a CPU, it can only be 95 1.5 ad * dispatched on the same CPU. Each LWP dedicated to handling a 96 1.5 ad * soft interrupt is bound to its home CPU, so if the LWP blocks 97 1.5 ad * and needs to run again, it can only run there. Nearly all data 98 1.5 ad * structures used to manage software interrupts are per-CPU. 99 1.5 ad * 100 1.5 ad * The per-CPU requirement is intended to reduce "ping-pong" of 101 1.5 ad * cache lines between CPUs: lines occupied by data structures 102 1.5 ad * used to manage the soft interrupts, and lines occupied by data 103 1.5 ad * items being passed down to the soft interrupt. As a positive 104 1.5 ad * side effect, this also means that the soft interrupt dispatch 105 1.5 ad * code does not need to to use spinlocks to synchronize. 106 1.5 ad * 107 1.5 ad * Generic implementation 108 1.5 ad * 109 1.5 ad * A generic, low performance implementation is provided that 110 1.5 ad * works across all architectures, with no machine-dependent 111 1.5 ad * modifications needed. This implementation uses the scheduler, 112 1.5 ad * and so has a number of restrictions: 113 1.5 ad * 114 1.5 ad * 1) The software interrupts are not currently preemptive, so 115 1.65 skrll * must wait for the currently executing LWP to yield the CPU. 116 1.5 ad * This can introduce latency. 117 1.5 ad * 118 1.5 ad * 2) An expensive context switch is required for a software 119 1.5 ad * interrupt to be handled. 120 1.5 ad * 121 1.5 ad * 'Fast' software interrupts 122 1.5 ad * 123 1.5 ad * If an architectures defines __HAVE_FAST_SOFTINTS, it implements 124 1.5 ad * the fast mechanism. Threads running either in the kernel or in 125 1.5 ad * userspace will be interrupted, but will not be preempted. When 126 1.5 ad * the soft interrupt completes execution, the interrupted LWP 127 1.5 ad * is resumed. Interrupt dispatch code must provide the minimum 128 1.5 ad * level of context necessary for the soft interrupt to block and 129 1.5 ad * be resumed at a later time. The machine-dependent dispatch 130 1.5 ad * path looks something like the following: 131 1.5 ad * 132 1.5 ad * softintr() 133 1.5 ad * { 134 1.5 ad * go to IPL_HIGH if necessary for switch; 135 1.5 ad * save any necessary registers in a format that can be 136 1.5 ad * restored by cpu_switchto if the softint blocks; 137 1.5 ad * arrange for cpu_switchto() to restore into the 138 1.5 ad * trampoline function; 139 1.5 ad * identify LWP to handle this interrupt; 140 1.5 ad * switch to the LWP's stack; 141 1.5 ad * switch register stacks, if necessary; 142 1.5 ad * assign new value of curlwp; 143 1.5 ad * call MI softint_dispatch, passing old curlwp and IPL 144 1.5 ad * to execute interrupt at; 145 1.5 ad * switch back to old stack; 146 1.5 ad * switch back to old register stack, if necessary; 147 1.5 ad * restore curlwp; 148 1.5 ad * return to interrupted LWP; 149 1.5 ad * } 150 1.5 ad * 151 1.5 ad * If the soft interrupt blocks, a trampoline function is returned 152 1.5 ad * to in the context of the interrupted LWP, as arranged for by 153 1.5 ad * softint(): 154 1.5 ad * 155 1.5 ad * softint_ret() 156 1.5 ad * { 157 1.5 ad * unlock soft interrupt LWP; 158 1.5 ad * resume interrupt processing, likely returning to 159 1.5 ad * interrupted LWP or dispatching another, different 160 1.5 ad * interrupt; 161 1.5 ad * } 162 1.5 ad * 163 1.5 ad * Once the soft interrupt has fired (and even if it has blocked), 164 1.5 ad * no further soft interrupts at that level will be triggered by 165 1.65 skrll * MI code until the soft interrupt handler has ceased execution. 166 1.5 ad * If a soft interrupt handler blocks and is resumed, it resumes 167 1.5 ad * execution as a normal LWP (kthread) and gains VM context. Only 168 1.5 ad * when it has completed and is ready to fire again will it 169 1.5 ad * interrupt other threads. 170 1.2 ad */ 171 1.2 ad 172 1.2 ad #include <sys/cdefs.h> 173 1.76 mrg __KERNEL_RCSID(0, "$NetBSD: kern_softint.c,v 1.76 2024/03/01 04:32:38 mrg Exp $"); 174 1.2 ad 175 1.2 ad #include <sys/param.h> 176 1.5 ad #include <sys/proc.h> 177 1.2 ad #include <sys/intr.h> 178 1.41 rmind #include <sys/ipi.h> 179 1.61 ad #include <sys/lock.h> 180 1.5 ad #include <sys/mutex.h> 181 1.45 msaitoh #include <sys/kernel.h> 182 1.5 ad #include <sys/kthread.h> 183 1.5 ad #include <sys/evcnt.h> 184 1.5 ad #include <sys/cpu.h> 185 1.24 ad #include <sys/xcall.h> 186 1.71 thorpej #include <sys/psref.h> 187 1.72 riastrad #include <sys/sdt.h> 188 1.5 ad 189 1.5 ad #include <uvm/uvm_extern.h> 190 1.5 ad 191 1.5 ad /* This could overlap with signal info in struct lwp. */ 192 1.5 ad typedef struct softint { 193 1.5 ad SIMPLEQ_HEAD(, softhand) si_q; 194 1.5 ad struct lwp *si_lwp; 195 1.5 ad struct cpu_info *si_cpu; 196 1.5 ad uintptr_t si_machdep; 197 1.5 ad struct evcnt si_evcnt; 198 1.5 ad struct evcnt si_evcnt_block; 199 1.63 ad volatile int si_active; 200 1.66 ad int si_ipl; 201 1.5 ad char si_name[8]; 202 1.5 ad char si_name_block[8+6]; 203 1.5 ad } softint_t; 204 1.5 ad 205 1.5 ad typedef struct softhand { 206 1.5 ad SIMPLEQ_ENTRY(softhand) sh_q; 207 1.5 ad void (*sh_func)(void *); 208 1.5 ad void *sh_arg; 209 1.5 ad softint_t *sh_isr; 210 1.28 bouyer u_int sh_flags; 211 1.41 rmind u_int sh_ipi_id; 212 1.5 ad } softhand_t; 213 1.5 ad 214 1.5 ad typedef struct softcpu { 215 1.5 ad struct cpu_info *sc_cpu; 216 1.5 ad softint_t sc_int[SOFTINT_COUNT]; 217 1.5 ad softhand_t sc_hand[1]; 218 1.5 ad } softcpu_t; 219 1.5 ad 220 1.5 ad static void softint_thread(void *); 221 1.5 ad 222 1.44 msaitoh u_int softint_bytes = 32768; 223 1.5 ad u_int softint_timing; 224 1.5 ad static u_int softint_max; 225 1.5 ad static kmutex_t softint_lock; 226 1.2 ad 227 1.72 riastrad SDT_PROBE_DEFINE4(sdt, kernel, softint, establish, 228 1.72 riastrad "void *"/*sih*/, 229 1.72 riastrad "void (*)(void *)"/*func*/, 230 1.72 riastrad "void *"/*arg*/, 231 1.72 riastrad "unsigned"/*flags*/); 232 1.72 riastrad 233 1.72 riastrad SDT_PROBE_DEFINE1(sdt, kernel, softint, disestablish, 234 1.72 riastrad "void *"/*sih*/); 235 1.72 riastrad 236 1.72 riastrad SDT_PROBE_DEFINE2(sdt, kernel, softint, schedule, 237 1.72 riastrad "void *"/*sih*/, 238 1.72 riastrad "struct cpu_info *"/*ci*/); 239 1.72 riastrad 240 1.72 riastrad SDT_PROBE_DEFINE4(sdt, kernel, softint, entry, 241 1.72 riastrad "void *"/*sih*/, 242 1.72 riastrad "void (*)(void *)"/*func*/, 243 1.72 riastrad "void *"/*arg*/, 244 1.72 riastrad "unsigned"/*flags*/); 245 1.72 riastrad 246 1.72 riastrad SDT_PROBE_DEFINE4(sdt, kernel, softint, return, 247 1.72 riastrad "void *"/*sih*/, 248 1.72 riastrad "void (*)(void *)"/*func*/, 249 1.72 riastrad "void *"/*arg*/, 250 1.72 riastrad "unsigned"/*flags*/); 251 1.72 riastrad 252 1.5 ad /* 253 1.5 ad * softint_init_isr: 254 1.5 ad * 255 1.5 ad * Initialize a single interrupt level for a single CPU. 256 1.5 ad */ 257 1.5 ad static void 258 1.66 ad softint_init_isr(softcpu_t *sc, const char *desc, pri_t pri, u_int level, 259 1.66 ad int ipl) 260 1.5 ad { 261 1.5 ad struct cpu_info *ci; 262 1.5 ad softint_t *si; 263 1.5 ad int error; 264 1.5 ad 265 1.5 ad si = &sc->sc_int[level]; 266 1.5 ad ci = sc->sc_cpu; 267 1.5 ad si->si_cpu = ci; 268 1.5 ad 269 1.5 ad SIMPLEQ_INIT(&si->si_q); 270 1.5 ad 271 1.5 ad error = kthread_create(pri, KTHREAD_MPSAFE | KTHREAD_INTR | 272 1.5 ad KTHREAD_IDLE, ci, softint_thread, si, &si->si_lwp, 273 1.12 martin "soft%s/%u", desc, ci->ci_index); 274 1.5 ad if (error != 0) 275 1.5 ad panic("softint_init_isr: error %d", error); 276 1.5 ad 277 1.12 martin snprintf(si->si_name, sizeof(si->si_name), "%s/%u", desc, 278 1.12 martin ci->ci_index); 279 1.20 ad evcnt_attach_dynamic(&si->si_evcnt, EVCNT_TYPE_MISC, NULL, 280 1.5 ad "softint", si->si_name); 281 1.12 martin snprintf(si->si_name_block, sizeof(si->si_name_block), "%s block/%u", 282 1.12 martin desc, ci->ci_index); 283 1.20 ad evcnt_attach_dynamic(&si->si_evcnt_block, EVCNT_TYPE_MISC, NULL, 284 1.5 ad "softint", si->si_name_block); 285 1.3 ad 286 1.66 ad si->si_ipl = ipl; 287 1.5 ad si->si_lwp->l_private = si; 288 1.5 ad softint_init_md(si->si_lwp, level, &si->si_machdep); 289 1.5 ad } 290 1.37 uebayasi 291 1.2 ad /* 292 1.2 ad * softint_init: 293 1.2 ad * 294 1.2 ad * Initialize per-CPU data structures. Called from mi_cpu_attach(). 295 1.2 ad */ 296 1.2 ad void 297 1.2 ad softint_init(struct cpu_info *ci) 298 1.2 ad { 299 1.5 ad static struct cpu_info *first; 300 1.5 ad softcpu_t *sc, *scfirst; 301 1.5 ad softhand_t *sh, *shmax; 302 1.5 ad 303 1.5 ad if (first == NULL) { 304 1.5 ad /* Boot CPU. */ 305 1.5 ad first = ci; 306 1.5 ad mutex_init(&softint_lock, MUTEX_DEFAULT, IPL_NONE); 307 1.5 ad softint_bytes = round_page(softint_bytes); 308 1.5 ad softint_max = (softint_bytes - sizeof(softcpu_t)) / 309 1.5 ad sizeof(softhand_t); 310 1.5 ad } 311 1.2 ad 312 1.37 uebayasi /* Use uvm_km(9) for persistent, page-aligned allocation. */ 313 1.37 uebayasi sc = (softcpu_t *)uvm_km_alloc(kernel_map, softint_bytes, 0, 314 1.37 uebayasi UVM_KMF_WIRED | UVM_KMF_ZERO); 315 1.5 ad if (sc == NULL) 316 1.5 ad panic("softint_init_cpu: cannot allocate memory"); 317 1.5 ad 318 1.5 ad ci->ci_data.cpu_softcpu = sc; 319 1.5 ad ci->ci_data.cpu_softints = 0; 320 1.5 ad sc->sc_cpu = ci; 321 1.5 ad 322 1.66 ad softint_init_isr(sc, "net", PRI_SOFTNET, SOFTINT_NET, 323 1.66 ad IPL_SOFTNET); 324 1.66 ad softint_init_isr(sc, "bio", PRI_SOFTBIO, SOFTINT_BIO, 325 1.66 ad IPL_SOFTBIO); 326 1.66 ad softint_init_isr(sc, "clk", PRI_SOFTCLOCK, SOFTINT_CLOCK, 327 1.66 ad IPL_SOFTCLOCK); 328 1.66 ad softint_init_isr(sc, "ser", PRI_SOFTSERIAL, SOFTINT_SERIAL, 329 1.66 ad IPL_SOFTSERIAL); 330 1.5 ad 331 1.5 ad if (first != ci) { 332 1.5 ad mutex_enter(&softint_lock); 333 1.5 ad scfirst = first->ci_data.cpu_softcpu; 334 1.5 ad sh = sc->sc_hand; 335 1.5 ad memcpy(sh, scfirst->sc_hand, sizeof(*sh) * softint_max); 336 1.5 ad /* Update pointers for this CPU. */ 337 1.5 ad for (shmax = sh + softint_max; sh < shmax; sh++) { 338 1.5 ad if (sh->sh_func == NULL) 339 1.5 ad continue; 340 1.5 ad sh->sh_isr = 341 1.5 ad &sc->sc_int[sh->sh_flags & SOFTINT_LVLMASK]; 342 1.5 ad } 343 1.5 ad mutex_exit(&softint_lock); 344 1.5 ad } 345 1.2 ad } 346 1.2 ad 347 1.2 ad /* 348 1.2 ad * softint_establish: 349 1.2 ad * 350 1.2 ad * Register a software interrupt handler. 351 1.2 ad */ 352 1.2 ad void * 353 1.2 ad softint_establish(u_int flags, void (*func)(void *), void *arg) 354 1.2 ad { 355 1.5 ad CPU_INFO_ITERATOR cii; 356 1.5 ad struct cpu_info *ci; 357 1.5 ad softcpu_t *sc; 358 1.5 ad softhand_t *sh; 359 1.5 ad u_int level, index; 360 1.41 rmind u_int ipi_id = 0; 361 1.41 rmind void *sih; 362 1.2 ad 363 1.2 ad level = (flags & SOFTINT_LVLMASK); 364 1.2 ad KASSERT(level < SOFTINT_COUNT); 365 1.24 ad KASSERT((flags & SOFTINT_IMPMASK) == 0); 366 1.2 ad 367 1.5 ad mutex_enter(&softint_lock); 368 1.5 ad 369 1.5 ad /* Find a free slot. */ 370 1.5 ad sc = curcpu()->ci_data.cpu_softcpu; 371 1.32 matt for (index = 1; index < softint_max; index++) { 372 1.5 ad if (sc->sc_hand[index].sh_func == NULL) 373 1.5 ad break; 374 1.32 matt } 375 1.5 ad if (index == softint_max) { 376 1.5 ad mutex_exit(&softint_lock); 377 1.5 ad printf("WARNING: softint_establish: table full, " 378 1.5 ad "increase softint_bytes\n"); 379 1.5 ad return NULL; 380 1.5 ad } 381 1.41 rmind sih = (void *)((uint8_t *)&sc->sc_hand[index] - (uint8_t *)sc); 382 1.41 rmind 383 1.41 rmind if (flags & SOFTINT_RCPU) { 384 1.41 rmind if ((ipi_id = ipi_register(softint_schedule, sih)) == 0) { 385 1.41 rmind mutex_exit(&softint_lock); 386 1.41 rmind return NULL; 387 1.41 rmind } 388 1.41 rmind } 389 1.5 ad 390 1.5 ad /* Set up the handler on each CPU. */ 391 1.8 ad if (ncpu < 2) { 392 1.7 ad /* XXX hack for machines with no CPU_INFO_FOREACH() early on */ 393 1.7 ad sc = curcpu()->ci_data.cpu_softcpu; 394 1.7 ad sh = &sc->sc_hand[index]; 395 1.7 ad sh->sh_isr = &sc->sc_int[level]; 396 1.7 ad sh->sh_func = func; 397 1.7 ad sh->sh_arg = arg; 398 1.7 ad sh->sh_flags = flags; 399 1.41 rmind sh->sh_ipi_id = ipi_id; 400 1.7 ad } else for (CPU_INFO_FOREACH(cii, ci)) { 401 1.5 ad sc = ci->ci_data.cpu_softcpu; 402 1.5 ad sh = &sc->sc_hand[index]; 403 1.5 ad sh->sh_isr = &sc->sc_int[level]; 404 1.5 ad sh->sh_func = func; 405 1.5 ad sh->sh_arg = arg; 406 1.5 ad sh->sh_flags = flags; 407 1.41 rmind sh->sh_ipi_id = ipi_id; 408 1.2 ad } 409 1.5 ad mutex_exit(&softint_lock); 410 1.5 ad 411 1.72 riastrad SDT_PROBE4(sdt, kernel, softint, establish, sih, func, arg, flags); 412 1.72 riastrad 413 1.41 rmind return sih; 414 1.2 ad } 415 1.2 ad 416 1.2 ad /* 417 1.2 ad * softint_disestablish: 418 1.2 ad * 419 1.24 ad * Unregister a software interrupt handler. The soft interrupt could 420 1.24 ad * still be active at this point, but the caller commits not to try 421 1.24 ad * and trigger it again once this call is made. The caller must not 422 1.24 ad * hold any locks that could be taken from soft interrupt context, 423 1.24 ad * because we will wait for the softint to complete if it's still 424 1.24 ad * running. 425 1.2 ad */ 426 1.2 ad void 427 1.2 ad softint_disestablish(void *arg) 428 1.2 ad { 429 1.5 ad CPU_INFO_ITERATOR cii; 430 1.5 ad struct cpu_info *ci; 431 1.5 ad softcpu_t *sc; 432 1.5 ad softhand_t *sh; 433 1.5 ad uintptr_t offset; 434 1.5 ad 435 1.5 ad offset = (uintptr_t)arg; 436 1.73 riastrad KASSERT(offset != 0); 437 1.73 riastrad KASSERTMSG(offset < softint_bytes, "%"PRIuPTR" %u", 438 1.40 matt offset, softint_bytes); 439 1.5 ad 440 1.24 ad /* 441 1.66 ad * Unregister IPI handler if there is any. Note: there is no need 442 1.66 ad * to disable preemption here - ID is stable. 443 1.41 rmind */ 444 1.41 rmind sc = curcpu()->ci_data.cpu_softcpu; 445 1.41 rmind sh = (softhand_t *)((uint8_t *)sc + offset); 446 1.41 rmind if (sh->sh_ipi_id) { 447 1.41 rmind ipi_unregister(sh->sh_ipi_id); 448 1.41 rmind } 449 1.41 rmind 450 1.41 rmind /* 451 1.66 ad * Run a dummy softint at the same level on all CPUs and wait for 452 1.66 ad * completion, to make sure this softint is no longer running 453 1.66 ad * anywhere. 454 1.24 ad */ 455 1.66 ad xc_barrier(XC_HIGHPRI_IPL(sh->sh_isr->si_ipl)); 456 1.5 ad 457 1.72 riastrad /* 458 1.72 riastrad * Notify dtrace probe when the old softint can't be running 459 1.72 riastrad * any more, but before it can be recycled for a new softint. 460 1.72 riastrad */ 461 1.72 riastrad SDT_PROBE1(sdt, kernel, softint, disestablish, arg); 462 1.72 riastrad 463 1.5 ad /* Clear the handler on each CPU. */ 464 1.24 ad mutex_enter(&softint_lock); 465 1.5 ad for (CPU_INFO_FOREACH(cii, ci)) { 466 1.5 ad sc = ci->ci_data.cpu_softcpu; 467 1.5 ad sh = (softhand_t *)((uint8_t *)sc + offset); 468 1.5 ad KASSERT(sh->sh_func != NULL); 469 1.5 ad sh->sh_func = NULL; 470 1.5 ad } 471 1.5 ad mutex_exit(&softint_lock); 472 1.2 ad } 473 1.2 ad 474 1.2 ad /* 475 1.2 ad * softint_schedule: 476 1.2 ad * 477 1.2 ad * Trigger a software interrupt. Must be called from a hardware 478 1.2 ad * interrupt handler, or with preemption disabled (since we are 479 1.2 ad * using the value of curcpu()). 480 1.2 ad */ 481 1.2 ad void 482 1.2 ad softint_schedule(void *arg) 483 1.2 ad { 484 1.5 ad softhand_t *sh; 485 1.5 ad softint_t *si; 486 1.5 ad uintptr_t offset; 487 1.5 ad int s; 488 1.5 ad 489 1.72 riastrad SDT_PROBE2(sdt, kernel, softint, schedule, arg, /*ci*/NULL); 490 1.72 riastrad 491 1.64 ad /* 492 1.64 ad * If this assert fires, rather than disabling preemption explicitly 493 1.64 ad * to make it stop, consider that you are probably using a softint 494 1.64 ad * when you don't need to. 495 1.65 skrll */ 496 1.17 ad KASSERT(kpreempt_disabled()); 497 1.17 ad 498 1.5 ad /* Find the handler record for this CPU. */ 499 1.5 ad offset = (uintptr_t)arg; 500 1.73 riastrad KASSERT(offset != 0); 501 1.73 riastrad KASSERTMSG(offset < softint_bytes, "%"PRIuPTR" %u", 502 1.40 matt offset, softint_bytes); 503 1.5 ad sh = (softhand_t *)((uint8_t *)curcpu()->ci_data.cpu_softcpu + offset); 504 1.5 ad 505 1.5 ad /* If it's already pending there's nothing to do. */ 506 1.32 matt if ((sh->sh_flags & SOFTINT_PENDING) != 0) { 507 1.5 ad return; 508 1.32 matt } 509 1.5 ad 510 1.5 ad /* 511 1.5 ad * Enqueue the handler into the LWP's pending list. 512 1.5 ad * If the LWP is completely idle, then make it run. 513 1.5 ad */ 514 1.5 ad s = splhigh(); 515 1.24 ad if ((sh->sh_flags & SOFTINT_PENDING) == 0) { 516 1.5 ad si = sh->sh_isr; 517 1.24 ad sh->sh_flags |= SOFTINT_PENDING; 518 1.5 ad SIMPLEQ_INSERT_TAIL(&si->si_q, sh, sh_q); 519 1.5 ad if (si->si_active == 0) { 520 1.5 ad si->si_active = 1; 521 1.5 ad softint_trigger(si->si_machdep); 522 1.5 ad } 523 1.5 ad } 524 1.5 ad splx(s); 525 1.5 ad } 526 1.5 ad 527 1.5 ad /* 528 1.41 rmind * softint_schedule_cpu: 529 1.41 rmind * 530 1.41 rmind * Trigger a software interrupt on a target CPU. This invokes 531 1.41 rmind * softint_schedule() for the local CPU or send an IPI to invoke 532 1.41 rmind * this routine on the remote CPU. Preemption must be disabled. 533 1.41 rmind */ 534 1.41 rmind void 535 1.41 rmind softint_schedule_cpu(void *arg, struct cpu_info *ci) 536 1.41 rmind { 537 1.41 rmind KASSERT(kpreempt_disabled()); 538 1.41 rmind 539 1.41 rmind if (curcpu() != ci) { 540 1.41 rmind const softcpu_t *sc = ci->ci_data.cpu_softcpu; 541 1.41 rmind const uintptr_t offset = (uintptr_t)arg; 542 1.41 rmind const softhand_t *sh; 543 1.41 rmind 544 1.72 riastrad SDT_PROBE2(sdt, kernel, softint, schedule, arg, ci); 545 1.41 rmind sh = (const softhand_t *)((const uint8_t *)sc + offset); 546 1.41 rmind KASSERT((sh->sh_flags & SOFTINT_RCPU) != 0); 547 1.41 rmind ipi_trigger(sh->sh_ipi_id, ci); 548 1.41 rmind return; 549 1.41 rmind } 550 1.41 rmind 551 1.41 rmind /* Just a local CPU. */ 552 1.41 rmind softint_schedule(arg); 553 1.41 rmind } 554 1.41 rmind 555 1.41 rmind /* 556 1.5 ad * softint_execute: 557 1.5 ad * 558 1.5 ad * Invoke handlers for the specified soft interrupt. 559 1.5 ad * Must be entered at splhigh. Will drop the priority 560 1.5 ad * to the level specified, but returns back at splhigh. 561 1.5 ad */ 562 1.5 ad static inline void 563 1.66 ad softint_execute(lwp_t *l, int s) 564 1.5 ad { 565 1.66 ad softint_t *si = l->l_private; 566 1.5 ad softhand_t *sh; 567 1.5 ad 568 1.5 ad KASSERT(si->si_lwp == curlwp); 569 1.5 ad KASSERT(si->si_cpu == curcpu()); 570 1.5 ad KASSERT(si->si_lwp->l_wchan == NULL); 571 1.5 ad KASSERT(si->si_active); 572 1.76 mrg KASSERTMSG(l->l_nopreempt == 0, "lwp %p nopreempt %d", 573 1.76 mrg l, l->l_nopreempt); 574 1.5 ad 575 1.5 ad /* 576 1.5 ad * Note: due to priority inheritance we may have interrupted a 577 1.5 ad * higher priority LWP. Since the soft interrupt must be quick 578 1.5 ad * and is non-preemptable, we don't bother yielding. 579 1.5 ad */ 580 1.5 ad 581 1.5 ad while (!SIMPLEQ_EMPTY(&si->si_q)) { 582 1.5 ad /* 583 1.5 ad * Pick the longest waiting handler to run. We block 584 1.5 ad * interrupts but do not lock in order to do this, as 585 1.5 ad * we are protecting against the local CPU only. 586 1.5 ad */ 587 1.5 ad sh = SIMPLEQ_FIRST(&si->si_q); 588 1.5 ad SIMPLEQ_REMOVE_HEAD(&si->si_q, sh_q); 589 1.24 ad KASSERT((sh->sh_flags & SOFTINT_PENDING) != 0); 590 1.66 ad sh->sh_flags ^= SOFTINT_PENDING; 591 1.5 ad splx(s); 592 1.5 ad 593 1.5 ad /* Run the handler. */ 594 1.72 riastrad SDT_PROBE4(sdt, kernel, softint, entry, 595 1.72 riastrad ((const char *)sh - 596 1.72 riastrad (const char *)curcpu()->ci_data.cpu_softcpu), 597 1.72 riastrad sh->sh_func, sh->sh_arg, sh->sh_flags); 598 1.58 ad if (__predict_true((sh->sh_flags & SOFTINT_MPSAFE) != 0)) { 599 1.58 ad (*sh->sh_func)(sh->sh_arg); 600 1.58 ad } else { 601 1.5 ad KERNEL_LOCK(1, l); 602 1.58 ad (*sh->sh_func)(sh->sh_arg); 603 1.58 ad KERNEL_UNLOCK_ONE(l); 604 1.5 ad } 605 1.72 riastrad SDT_PROBE4(sdt, kernel, softint, return, 606 1.72 riastrad ((const char *)sh - 607 1.72 riastrad (const char *)curcpu()->ci_data.cpu_softcpu), 608 1.72 riastrad sh->sh_func, sh->sh_arg, sh->sh_flags); 609 1.65 skrll 610 1.34 rmind /* Diagnostic: check that spin-locks have not leaked. */ 611 1.34 rmind KASSERTMSG(curcpu()->ci_mtx_count == 0, 612 1.38 jym "%s: ci_mtx_count (%d) != 0, sh_func %p\n", 613 1.38 jym __func__, curcpu()->ci_mtx_count, sh->sh_func); 614 1.46 ozaki /* Diagnostic: check that psrefs have not leaked. */ 615 1.46 ozaki KASSERTMSG(l->l_psrefs == 0, "%s: l_psrefs=%d, sh_func=%p\n", 616 1.46 ozaki __func__, l->l_psrefs, sh->sh_func); 617 1.70 riastrad /* Diagnostic: check that biglocks have not leaked. */ 618 1.70 riastrad KASSERTMSG(l->l_blcnt == 0, 619 1.70 riastrad "%s: sh_func=%p leaked %d biglocks", 620 1.70 riastrad __func__, sh->sh_func, curlwp->l_blcnt); 621 1.76 mrg /* Diagnostic: check that LWP nopreempt remains zero. */ 622 1.76 mrg KASSERTMSG(l->l_nopreempt == 0, 623 1.76 mrg "%s: lwp %p nopreempt %d func %p", 624 1.76 mrg __func__, l, l->l_nopreempt, sh->sh_func); 625 1.41 rmind 626 1.5 ad (void)splhigh(); 627 1.5 ad } 628 1.2 ad 629 1.47 ozaki PSREF_DEBUG_BARRIER(); 630 1.47 ozaki 631 1.56 ad CPU_COUNT(CPU_COUNT_NSOFT, 1); 632 1.5 ad 633 1.13 ad KASSERT(si->si_cpu == curcpu()); 634 1.13 ad KASSERT(si->si_lwp->l_wchan == NULL); 635 1.13 ad KASSERT(si->si_active); 636 1.5 ad si->si_evcnt.ev_count++; 637 1.5 ad si->si_active = 0; 638 1.2 ad } 639 1.2 ad 640 1.2 ad /* 641 1.2 ad * softint_block: 642 1.2 ad * 643 1.2 ad * Update statistics when the soft interrupt blocks. 644 1.2 ad */ 645 1.2 ad void 646 1.2 ad softint_block(lwp_t *l) 647 1.2 ad { 648 1.5 ad softint_t *si = l->l_private; 649 1.5 ad 650 1.5 ad KASSERT((l->l_pflag & LP_INTR) != 0); 651 1.5 ad si->si_evcnt_block.ev_count++; 652 1.5 ad } 653 1.5 ad 654 1.5 ad #ifndef __HAVE_FAST_SOFTINTS 655 1.5 ad 656 1.19 ad #ifdef __HAVE_PREEMPTION 657 1.19 ad #error __HAVE_PREEMPTION requires __HAVE_FAST_SOFTINTS 658 1.17 ad #endif 659 1.17 ad 660 1.5 ad /* 661 1.5 ad * softint_init_md: 662 1.5 ad * 663 1.5 ad * Slow path: perform machine-dependent initialization. 664 1.5 ad */ 665 1.5 ad void 666 1.5 ad softint_init_md(lwp_t *l, u_int level, uintptr_t *machdep) 667 1.5 ad { 668 1.50 ad struct proc *p; 669 1.5 ad softint_t *si; 670 1.5 ad 671 1.5 ad *machdep = (1 << level); 672 1.5 ad si = l->l_private; 673 1.50 ad p = l->l_proc; 674 1.5 ad 675 1.50 ad mutex_enter(p->p_lock); 676 1.5 ad lwp_lock(l); 677 1.5 ad /* Cheat and make the KASSERT in softint_thread() happy. */ 678 1.5 ad si->si_active = 1; 679 1.50 ad setrunnable(l); 680 1.50 ad /* LWP now unlocked */ 681 1.50 ad mutex_exit(p->p_lock); 682 1.5 ad } 683 1.5 ad 684 1.5 ad /* 685 1.5 ad * softint_trigger: 686 1.5 ad * 687 1.5 ad * Slow path: cause a soft interrupt handler to begin executing. 688 1.5 ad * Called at IPL_HIGH. 689 1.5 ad */ 690 1.5 ad void 691 1.5 ad softint_trigger(uintptr_t machdep) 692 1.5 ad { 693 1.5 ad struct cpu_info *ci; 694 1.5 ad lwp_t *l; 695 1.2 ad 696 1.51 ad ci = curcpu(); 697 1.5 ad ci->ci_data.cpu_softints |= machdep; 698 1.52 ad l = ci->ci_onproc; 699 1.63 ad 700 1.63 ad /* 701 1.63 ad * Arrange for mi_switch() to be called. If called from interrupt 702 1.63 ad * mode, we don't know if curlwp is executing in kernel or user, so 703 1.63 ad * post an AST and have it take a trip through userret(). If not in 704 1.63 ad * interrupt mode, curlwp is running in kernel and will notice the 705 1.63 ad * resched soon enough; avoid the AST. 706 1.63 ad */ 707 1.5 ad if (l == ci->ci_data.cpu_idlelwp) { 708 1.54 ad atomic_or_uint(&ci->ci_want_resched, 709 1.54 ad RESCHED_IDLE | RESCHED_UPREEMPT); 710 1.5 ad } else { 711 1.63 ad atomic_or_uint(&ci->ci_want_resched, RESCHED_UPREEMPT); 712 1.63 ad if (cpu_intr_p()) { 713 1.63 ad cpu_signotify(l); 714 1.63 ad } 715 1.5 ad } 716 1.5 ad } 717 1.5 ad 718 1.5 ad /* 719 1.5 ad * softint_thread: 720 1.5 ad * 721 1.5 ad * Slow path: MI software interrupt dispatch. 722 1.5 ad */ 723 1.5 ad void 724 1.5 ad softint_thread(void *cookie) 725 1.5 ad { 726 1.5 ad softint_t *si; 727 1.5 ad lwp_t *l; 728 1.5 ad int s; 729 1.5 ad 730 1.5 ad l = curlwp; 731 1.5 ad si = l->l_private; 732 1.5 ad 733 1.5 ad for (;;) { 734 1.64 ad /* Clear pending status and run it. */ 735 1.5 ad s = splhigh(); 736 1.5 ad l->l_cpu->ci_data.cpu_softints &= ~si->si_machdep; 737 1.66 ad softint_execute(l, s); 738 1.5 ad splx(s); 739 1.5 ad 740 1.64 ad /* Interrupts allowed to run again before switching. */ 741 1.5 ad lwp_lock(l); 742 1.5 ad l->l_stat = LSIDL; 743 1.55 ad spc_lock(l->l_cpu); 744 1.5 ad mi_switch(l); 745 1.5 ad } 746 1.2 ad } 747 1.4 ad 748 1.4 ad /* 749 1.4 ad * softint_picklwp: 750 1.4 ad * 751 1.4 ad * Slow path: called from mi_switch() to pick the highest priority 752 1.4 ad * soft interrupt LWP that needs to run. 753 1.4 ad */ 754 1.4 ad lwp_t * 755 1.4 ad softint_picklwp(void) 756 1.4 ad { 757 1.5 ad struct cpu_info *ci; 758 1.5 ad u_int mask; 759 1.5 ad softint_t *si; 760 1.5 ad lwp_t *l; 761 1.5 ad 762 1.5 ad ci = curcpu(); 763 1.5 ad si = ((softcpu_t *)ci->ci_data.cpu_softcpu)->sc_int; 764 1.5 ad mask = ci->ci_data.cpu_softints; 765 1.5 ad 766 1.5 ad if ((mask & (1 << SOFTINT_SERIAL)) != 0) { 767 1.5 ad l = si[SOFTINT_SERIAL].si_lwp; 768 1.5 ad } else if ((mask & (1 << SOFTINT_NET)) != 0) { 769 1.5 ad l = si[SOFTINT_NET].si_lwp; 770 1.5 ad } else if ((mask & (1 << SOFTINT_BIO)) != 0) { 771 1.5 ad l = si[SOFTINT_BIO].si_lwp; 772 1.5 ad } else if ((mask & (1 << SOFTINT_CLOCK)) != 0) { 773 1.5 ad l = si[SOFTINT_CLOCK].si_lwp; 774 1.5 ad } else { 775 1.5 ad panic("softint_picklwp"); 776 1.5 ad } 777 1.4 ad 778 1.5 ad return l; 779 1.4 ad } 780 1.4 ad 781 1.5 ad #else /* !__HAVE_FAST_SOFTINTS */ 782 1.5 ad 783 1.5 ad /* 784 1.5 ad * softint_thread: 785 1.5 ad * 786 1.5 ad * Fast path: the LWP is switched to without restoring any state, 787 1.5 ad * so we should not arrive here - there is a direct handoff between 788 1.5 ad * the interrupt stub and softint_dispatch(). 789 1.5 ad */ 790 1.5 ad void 791 1.5 ad softint_thread(void *cookie) 792 1.5 ad { 793 1.5 ad 794 1.5 ad panic("softint_thread"); 795 1.5 ad } 796 1.5 ad 797 1.5 ad /* 798 1.5 ad * softint_dispatch: 799 1.5 ad * 800 1.5 ad * Fast path: entry point from machine-dependent code. 801 1.5 ad */ 802 1.5 ad void 803 1.5 ad softint_dispatch(lwp_t *pinned, int s) 804 1.5 ad { 805 1.9 yamt struct bintime now; 806 1.5 ad u_int timing; 807 1.5 ad lwp_t *l; 808 1.5 ad 809 1.59 ad #ifdef DIAGNOSTIC 810 1.60 ad if ((pinned->l_pflag & LP_RUNNING) == 0 || curlwp->l_stat != LSIDL) { 811 1.59 ad struct lwp *onproc = curcpu()->ci_onproc; 812 1.59 ad int s2 = splhigh(); 813 1.59 ad printf("curcpu=%d, spl=%d curspl=%d\n" 814 1.59 ad "onproc=%p => l_stat=%d l_flag=%08x l_cpu=%d\n" 815 1.59 ad "curlwp=%p => l_stat=%d l_flag=%08x l_cpu=%d\n" 816 1.59 ad "pinned=%p => l_stat=%d l_flag=%08x l_cpu=%d\n", 817 1.59 ad cpu_index(curcpu()), s, s2, onproc, onproc->l_stat, 818 1.59 ad onproc->l_flag, cpu_index(onproc->l_cpu), curlwp, 819 1.59 ad curlwp->l_stat, curlwp->l_flag, 820 1.59 ad cpu_index(curlwp->l_cpu), pinned, pinned->l_stat, 821 1.59 ad pinned->l_flag, cpu_index(pinned->l_cpu)); 822 1.59 ad splx(s2); 823 1.59 ad panic("softint screwup"); 824 1.59 ad } 825 1.59 ad #endif 826 1.59 ad 827 1.5 ad /* 828 1.5 ad * Note the interrupted LWP, and mark the current LWP as running 829 1.5 ad * before proceeding. Although this must as a rule be done with 830 1.5 ad * the LWP locked, at this point no external agents will want to 831 1.5 ad * modify the interrupt LWP's state. 832 1.5 ad */ 833 1.57 ad timing = softint_timing; 834 1.66 ad l = curlwp; 835 1.5 ad l->l_switchto = pinned; 836 1.5 ad l->l_stat = LSONPROC; 837 1.5 ad 838 1.5 ad /* 839 1.5 ad * Dispatch the interrupt. If softints are being timed, charge 840 1.5 ad * for it. 841 1.5 ad */ 842 1.49 ad if (timing) { 843 1.11 yamt binuptime(&l->l_stime); 844 1.49 ad membar_producer(); /* for calcru */ 845 1.57 ad l->l_pflag |= LP_TIMEINTR; 846 1.49 ad } 847 1.60 ad l->l_pflag |= LP_RUNNING; 848 1.66 ad softint_execute(l, s); 849 1.5 ad if (timing) { 850 1.11 yamt binuptime(&now); 851 1.5 ad updatertime(l, &now); 852 1.22 ad l->l_pflag &= ~LP_TIMEINTR; 853 1.5 ad } 854 1.5 ad 855 1.5 ad /* 856 1.5 ad * If we blocked while handling the interrupt, the pinned LWP is 857 1.66 ad * gone and we are now running as a kthread, so find another LWP to 858 1.66 ad * run. softint_dispatch() won't be reentered until the priority is 859 1.66 ad * finally dropped to IPL_NONE on entry to the next LWP on this CPU. 860 1.5 ad */ 861 1.5 ad l->l_stat = LSIDL; 862 1.5 ad if (l->l_switchto == NULL) { 863 1.57 ad lwp_lock(l); 864 1.57 ad spc_lock(l->l_cpu); 865 1.57 ad mi_switch(l); 866 1.5 ad /* NOTREACHED */ 867 1.5 ad } 868 1.5 ad l->l_switchto = NULL; 869 1.60 ad l->l_pflag &= ~LP_RUNNING; 870 1.5 ad } 871 1.5 ad 872 1.5 ad #endif /* !__HAVE_FAST_SOFTINTS */ 873