1 /* 2 * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice unmodified, this list of conditions, and the following 10 * 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 OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 * 28 */ 29 30 31 #include <sys/param.h> 32 #include <sys/bus.h> 33 #include <sys/rtprio.h> 34 #include <sys/systm.h> 35 #include <sys/ipl.h> 36 #include <sys/interrupt.h> 37 #include <sys/kernel.h> 38 #include <sys/kthread.h> 39 #include <sys/ktr.h> 40 #include <sys/lock.h> 41 #include <sys/malloc.h> 42 #include <sys/mutex.h> 43 #include <sys/proc.h> 44 #include <sys/random.h> 45 #include <sys/resourcevar.h> 46 #include <sys/unistd.h> 47 #include <sys/vmmeter.h> 48 #include <machine/atomic.h> 49 #include <machine/cpu.h> 50 #include <machine/md_var.h> 51 #include <machine/stdarg.h> 52 53 #include <net/netisr.h> /* prototype for legacy_setsoftnet */ 54 55 struct int_entropy { 56 struct proc *proc; 57 int vector; 58 }; 59 60 void *net_ih; 61 void *vm_ih; 62 void *softclock_ih; 63 struct ithd *clk_ithd; 64 struct ithd *tty_ithd; 65 66 static struct mtx ithread_list_lock; 67 68 static MALLOC_DEFINE(M_ITHREAD, "ithread", "Interrupt Threads"); 69 70 static void ithread_update(struct ithd *); 71 static void ithread_loop(void *); 72 static void ithread_init(void *); 73 static void start_softintr(void *); 74 static void swi_net(void *); 75 76 u_char 77 ithread_priority(enum intr_type flags) 78 { 79 u_char pri; 80 81 flags &= (INTR_TYPE_TTY | INTR_TYPE_BIO | INTR_TYPE_NET | 82 INTR_TYPE_CAM | INTR_TYPE_MISC | INTR_TYPE_CLK); 83 switch (flags) { 84 case INTR_TYPE_TTY: 85 pri = PI_TTYLOW; 86 break; 87 case INTR_TYPE_BIO: 88 /* 89 * XXX We need to refine this. BSD/OS distinguishes 90 * between tape and disk priorities. 91 */ 92 pri = PI_DISK; 93 break; 94 case INTR_TYPE_NET: 95 pri = PI_NET; 96 break; 97 case INTR_TYPE_CAM: 98 pri = PI_DISK; /* XXX or PI_CAM? */ 99 break; 100 case INTR_TYPE_CLK: 101 pri = PI_REALTIME; 102 break; 103 case INTR_TYPE_MISC: 104 pri = PI_DULL; /* don't care */ 105 break; 106 default: 107 /* We didn't specify an interrupt level. */ 108 panic("ithread_priority: no interrupt type in flags"); 109 } 110 111 return pri; 112 } 113 114 /* 115 * Regenerate the name (p_comm) and priority for a threaded interrupt thread. 116 */ 117 static void 118 ithread_update(struct ithd *ithd) 119 { 120 struct intrhand *ih; 121 struct proc *p; 122 int entropy; 123 124 p = ithd->it_proc; 125 if (p == NULL) 126 return; 127 128 strncpy(p->p_comm, ithd->it_name, sizeof(ithd->it_name)); 129 ih = TAILQ_FIRST(&ithd->it_handlers); 130 if (ih == NULL) { 131 p->p_pri.pri_level = PRI_MAX_ITHD; 132 ithd->it_flags &= ~IT_ENTROPY; 133 return; 134 } 135 136 entropy = 0; 137 p->p_pri.pri_level = ih->ih_pri; 138 p->p_pri.pri_native = ih->ih_pri; 139 TAILQ_FOREACH(ih, &ithd->it_handlers, ih_next) { 140 if (strlen(p->p_comm) + strlen(ih->ih_name) + 1 < 141 sizeof(p->p_comm)) { 142 strcat(p->p_comm, " "); 143 strcat(p->p_comm, ih->ih_name); 144 } else if (strlen(p->p_comm) + 1 == sizeof(p->p_comm)) { 145 if (p->p_comm[sizeof(p->p_comm) - 2] == '+') 146 p->p_comm[sizeof(p->p_comm) - 2] = '*'; 147 else 148 p->p_comm[sizeof(p->p_comm) - 2] = '+'; 149 } else 150 strcat(p->p_comm, "+"); 151 if (ih->ih_flags & IH_ENTROPY) 152 entropy++; 153 } 154 155 if (entropy) 156 ithd->it_flags |= IT_ENTROPY; 157 else 158 ithd->it_flags &= ~IT_ENTROPY; 159 160 CTR1(KTR_INTR, __func__ ": updated %s\n", p->p_comm); 161 } 162 163 int 164 ithread_create(struct ithd **ithread, int vector, int flags, 165 void (*disable)(int), void (*enable)(int), const char *fmt, ...) 166 { 167 struct ithd *ithd; 168 struct proc *p; 169 int error; 170 va_list ap; 171 172 /* The only valid flag during creation is IT_SOFT. */ 173 if ((flags & ~IT_SOFT) != 0) 174 return (EINVAL); 175 176 ithd = malloc(sizeof(struct ithd), M_ITHREAD, M_WAITOK | M_ZERO); 177 ithd->it_vector = vector; 178 ithd->it_disable = disable; 179 ithd->it_enable = enable; 180 ithd->it_flags = flags; 181 TAILQ_INIT(&ithd->it_handlers); 182 183 va_start(ap, fmt); 184 vsnprintf(ithd->it_name, sizeof(ithd->it_name), fmt, ap); 185 va_end(ap); 186 187 error = kthread_create(ithread_loop, ithd, &p, RFSTOPPED | RFHIGHPID, 188 "%s", ithd->it_name); 189 if (error) { 190 free(ithd, M_ITHREAD); 191 return (error); 192 } 193 p->p_pri.pri_class = PRI_ITHD; 194 p->p_pri.pri_level = PRI_MAX_ITHD; 195 p->p_stat = SWAIT; 196 ithd->it_proc = p; 197 p->p_ithd = ithd; 198 if (ithread != NULL) 199 *ithread = ithd; 200 201 CTR1(KTR_INTR, __func__ ": created %s", ithd->it_name); 202 return (0); 203 } 204 205 int 206 ithread_destroy(struct ithd *ithread) 207 { 208 209 if (ithread == NULL || !TAILQ_EMPTY(&ithread->it_handlers)) 210 return (EINVAL); 211 212 mtx_lock_spin(&sched_lock); 213 ithread->it_flags |= IT_DEAD; 214 if (ithread->it_proc->p_stat == SWAIT) { 215 ithread->it_proc->p_stat = SRUN; 216 setrunqueue(ithread->it_proc); 217 } 218 mtx_unlock_spin(&sched_lock); 219 CTR1(KTR_INTR, __func__ ": killing %s", ithread->it_name); 220 return (0); 221 } 222 223 int 224 ithread_add_handler(struct ithd* ithread, const char *name, 225 driver_intr_t handler, void *arg, u_char pri, enum intr_type flags, 226 void **cookiep) 227 { 228 struct intrhand *ih, *temp_ih; 229 230 if (ithread == NULL || name == NULL || handler == NULL) 231 return (EINVAL); 232 if ((flags & INTR_FAST) !=0) 233 flags |= INTR_EXCL; 234 235 ih = malloc(sizeof(struct intrhand), M_ITHREAD, M_WAITOK | M_ZERO); 236 ih->ih_handler = handler; 237 ih->ih_argument = arg; 238 ih->ih_name = name; 239 ih->ih_ithread = ithread; 240 ih->ih_pri = pri; 241 if (flags & INTR_FAST) 242 ih->ih_flags = IH_FAST | IH_EXCLUSIVE; 243 else if (flags & INTR_EXCL) 244 ih->ih_flags = IH_EXCLUSIVE; 245 if (flags & INTR_MPSAFE) 246 ih->ih_flags |= IH_MPSAFE; 247 if (flags & INTR_ENTROPY) 248 ih->ih_flags |= IH_ENTROPY; 249 250 mtx_lock_spin(&ithread_list_lock); 251 if ((flags & INTR_EXCL) !=0 && !TAILQ_EMPTY(&ithread->it_handlers)) 252 goto fail; 253 if (!TAILQ_EMPTY(&ithread->it_handlers) && 254 (TAILQ_FIRST(&ithread->it_handlers)->ih_flags & IH_EXCLUSIVE) != 0) 255 goto fail; 256 257 TAILQ_FOREACH(temp_ih, &ithread->it_handlers, ih_next) 258 if (temp_ih->ih_pri > ih->ih_pri) 259 break; 260 if (temp_ih == NULL) 261 TAILQ_INSERT_TAIL(&ithread->it_handlers, ih, ih_next); 262 else 263 TAILQ_INSERT_BEFORE(temp_ih, ih, ih_next); 264 ithread_update(ithread); 265 mtx_unlock_spin(&ithread_list_lock); 266 267 if (cookiep != NULL) 268 *cookiep = ih; 269 CTR2(KTR_INTR, __func__ ": added %s to %s", ih->ih_name, 270 ithread->it_name); 271 return (0); 272 273 fail: 274 mtx_unlock_spin(&ithread_list_lock); 275 free(ih, M_ITHREAD); 276 return (EINVAL); 277 } 278 279 int 280 ithread_remove_handler(void *cookie) 281 { 282 struct intrhand *handler = (struct intrhand *)cookie; 283 struct ithd *ithread; 284 #ifdef INVARIANTS 285 struct intrhand *ih; 286 #endif 287 288 if (handler == NULL) 289 return (EINVAL); 290 ithread = handler->ih_ithread; 291 KASSERT(ithread != NULL, 292 ("interrupt handler \"%s\" has a NULL interrupt thread", 293 handler->ih_name)); 294 CTR2(KTR_INTR, __func__ ": removing %s from %s", handler->ih_name, 295 ithread->it_name); 296 mtx_lock_spin(&ithread_list_lock); 297 #ifdef INVARIANTS 298 TAILQ_FOREACH(ih, &ithread->it_handlers, ih_next) 299 if (ih == handler) 300 goto ok; 301 mtx_unlock_spin(&ithread_list_lock); 302 panic("interrupt handler \"%s\" not found in interrupt thread \"%s\"", 303 ih->ih_name, ithread->it_name); 304 ok: 305 #endif 306 /* 307 * If the interrupt thread is already running, then just mark this 308 * handler as being dead and let the ithread do the actual removal. 309 */ 310 mtx_lock_spin(&sched_lock); 311 if (ithread->it_proc->p_stat != SWAIT) { 312 handler->ih_flags |= IH_DEAD; 313 314 /* 315 * Ensure that the thread will process the handler list 316 * again and remove this handler if it has already passed 317 * it on the list. 318 */ 319 ithread->it_need = 1; 320 } else { 321 TAILQ_REMOVE(&ithread->it_handlers, handler, ih_next); 322 ithread_update(ithread); 323 } 324 mtx_unlock_spin(&sched_lock); 325 mtx_unlock_spin(&ithread_list_lock); 326 327 if ((handler->ih_flags & IH_DEAD) == 0) 328 free(handler, M_ITHREAD); 329 return (0); 330 } 331 332 int 333 ithread_schedule(struct ithd *ithread, int do_switch) 334 { 335 struct int_entropy entropy; 336 struct proc *p; 337 critical_t savecrit; 338 339 /* 340 * If no ithread or no handlers, then we have a stray interrupt. 341 */ 342 if ((ithread == NULL) || TAILQ_EMPTY(&ithread->it_handlers)) 343 return (EINVAL); 344 345 /* 346 * If any of the handlers for this ithread claim to be good 347 * sources of entropy, then gather some. 348 */ 349 if (harvest.interrupt && ithread->it_flags & IT_ENTROPY) { 350 entropy.vector = ithread->it_vector; 351 entropy.proc = CURPROC; 352 random_harvest(&entropy, sizeof(entropy), 2, 0, 353 RANDOM_INTERRUPT); 354 } 355 356 p = ithread->it_proc; 357 KASSERT(p != NULL, ("ithread %s has no process", ithread->it_name)); 358 CTR3(KTR_INTR, __func__ ": pid %d: (%s) need = %d", p->p_pid, p->p_comm, 359 ithread->it_need); 360 361 /* 362 * Set it_need to tell the thread to keep running if it is already 363 * running. Then, grab sched_lock and see if we actually need to 364 * put this thread on the runqueue. If so and the do_switch flag is 365 * true, then switch to the ithread immediately. Otherwise, use 366 * need_resched() to guarantee that this ithread will run before any 367 * userland processes. 368 */ 369 ithread->it_need = 1; 370 mtx_lock_spin(&sched_lock); 371 if (p->p_stat == SWAIT) { 372 CTR1(KTR_INTR, __func__ ": setrunqueue %d", p->p_pid); 373 p->p_stat = SRUN; 374 setrunqueue(p); 375 if (do_switch && curproc->p_stat == SRUN) { 376 savecrit = sched_lock.mtx_savecrit; 377 mtx_intr_enable(&sched_lock); 378 if (curproc != PCPU_GET(idleproc)) 379 setrunqueue(curproc); 380 curproc->p_stats->p_ru.ru_nvcsw++; 381 mi_switch(); 382 sched_lock.mtx_savecrit = savecrit; 383 } else 384 need_resched(curproc); 385 } else { 386 CTR3(KTR_INTR, __func__ ": pid %d: it_need %d, state %d", 387 p->p_pid, ithread->it_need, p->p_stat); 388 } 389 mtx_unlock_spin(&sched_lock); 390 391 return (0); 392 } 393 394 int 395 swi_add(struct ithd **ithdp, const char *name, driver_intr_t handler, 396 void *arg, int pri, enum intr_type flags, void **cookiep) 397 { 398 struct ithd *ithd; 399 int error; 400 401 if (flags & (INTR_FAST | INTR_ENTROPY)) 402 return (EINVAL); 403 404 ithd = (ithdp != NULL) ? *ithdp : NULL; 405 406 if (ithd != NULL) { 407 if ((ithd->it_flags & IT_SOFT) == 0) 408 return(EINVAL); 409 } else { 410 error = ithread_create(&ithd, pri, IT_SOFT, NULL, NULL, 411 "swi%d:", pri); 412 if (error) 413 return (error); 414 415 if (ithdp != NULL) 416 *ithdp = ithd; 417 } 418 return (ithread_add_handler(ithd, name, handler, arg, 419 (pri * RQ_PPQ) + PI_SOFT, flags, cookiep)); 420 } 421 422 423 /* 424 * Schedule a heavyweight software interrupt process. 425 */ 426 void 427 swi_sched(void *cookie, int flags) 428 { 429 struct intrhand *ih = (struct intrhand *)cookie; 430 struct ithd *it = ih->ih_ithread; 431 int error; 432 433 atomic_add_int(&cnt.v_intr, 1); /* one more global interrupt */ 434 435 CTR3(KTR_INTR, "swi_sched pid %d(%s) need=%d", 436 it->it_proc->p_pid, it->it_proc->p_comm, it->it_need); 437 438 /* 439 * Set ih_need for this handler so that if the ithread is already 440 * running it will execute this handler on the next pass. Otherwise, 441 * it will execute it the next time it runs. 442 */ 443 atomic_store_rel_int(&ih->ih_need, 1); 444 if (!(flags & SWI_DELAY)) { 445 error = ithread_schedule(it, !cold && flags & SWI_SWITCH); 446 KASSERT(error == 0, ("stray software interrupt")); 447 } 448 } 449 450 /* 451 * This is the main code for interrupt threads. 452 */ 453 void 454 ithread_loop(void *arg) 455 { 456 struct ithd *ithd; /* our thread context */ 457 struct intrhand *ih; /* and our interrupt handler chain */ 458 struct proc *p; 459 460 p = curproc; 461 ithd = (struct ithd *)arg; /* point to myself */ 462 KASSERT(ithd->it_proc == p && p->p_ithd == ithd, 463 (__func__ ": ithread and proc linkage out of sync")); 464 465 /* 466 * As long as we have interrupts outstanding, go through the 467 * list of handlers, giving each one a go at it. 468 */ 469 for (;;) { 470 /* 471 * If we are an orphaned thread, then just die. 472 */ 473 if (ithd->it_flags & IT_DEAD) { 474 CTR2(KTR_INTR, __func__ ": pid %d: (%s) exiting", 475 p->p_pid, p->p_comm); 476 p->p_ithd = NULL; 477 mtx_lock(&Giant); 478 free(ithd, M_ITHREAD); 479 kthread_exit(0); 480 } 481 482 CTR3(KTR_INTR, __func__ ": pid %d: (%s) need=%d", 483 p->p_pid, p->p_comm, ithd->it_need); 484 while (ithd->it_need) { 485 /* 486 * Service interrupts. If another interrupt 487 * arrives while we are running, they will set 488 * it_need to denote that we should make 489 * another pass. 490 */ 491 atomic_store_rel_int(&ithd->it_need, 0); 492 restart: 493 TAILQ_FOREACH(ih, &ithd->it_handlers, ih_next) { 494 if (ithd->it_flags & IT_SOFT && !ih->ih_need) 495 continue; 496 atomic_store_rel_int(&ih->ih_need, 0); 497 CTR5(KTR_INTR, 498 __func__ ": pid %d ih=%p: %p(%p) flg=%x", 499 p->p_pid, (void *)ih, 500 (void *)ih->ih_handler, ih->ih_argument, 501 ih->ih_flags); 502 503 if ((ih->ih_flags & IH_MPSAFE) == 0) 504 mtx_lock(&Giant); 505 if ((ih->ih_flags & IH_DEAD) != 0) { 506 mtx_lock_spin(&ithread_list_lock); 507 TAILQ_REMOVE(&ithd->it_handlers, ih, 508 ih_next); 509 ithread_update(ithd); 510 mtx_unlock_spin(&ithread_list_lock); 511 if (!mtx_owned(&Giant)) 512 mtx_lock(&Giant); 513 free(ih, M_ITHREAD); 514 mtx_unlock(&Giant); 515 goto restart; 516 } 517 ih->ih_handler(ih->ih_argument); 518 if ((ih->ih_flags & IH_MPSAFE) == 0) 519 mtx_unlock(&Giant); 520 } 521 } 522 523 /* 524 * Processed all our interrupts. Now get the sched 525 * lock. This may take a while and it_need may get 526 * set again, so we have to check it again. 527 */ 528 mtx_assert(&Giant, MA_NOTOWNED); 529 mtx_lock_spin(&sched_lock); 530 if (!ithd->it_need) { 531 /* 532 * Should we call this earlier in the loop above? 533 */ 534 if (ithd->it_enable != NULL) 535 ithd->it_enable(ithd->it_vector); 536 p->p_stat = SWAIT; /* we're idle */ 537 CTR1(KTR_INTR, __func__ ": pid %d: done", p->p_pid); 538 mi_switch(); 539 CTR1(KTR_INTR, __func__ ": pid %d: resumed", p->p_pid); 540 } 541 mtx_unlock_spin(&sched_lock); 542 } 543 } 544 545 /* 546 * Initialize mutex used to protect ithread handler lists. 547 */ 548 static void 549 ithread_init(void *dummy) 550 { 551 552 mtx_init(&ithread_list_lock, "ithread list lock", MTX_SPIN); 553 } 554 SYSINIT(ithread_init, SI_SUB_INTR, SI_ORDER_FIRST, ithread_init, NULL); 555 556 /* 557 * Start standard software interrupt threads 558 */ 559 static void 560 start_softintr(void *dummy) 561 { 562 563 if (swi_add(NULL, "net", swi_net, NULL, SWI_NET, 0, &net_ih) || 564 swi_add(&clk_ithd, "clock", softclock, NULL, SWI_CLOCK, 565 INTR_MPSAFE, &softclock_ih) || 566 swi_add(NULL, "vm", swi_vm, NULL, SWI_VM, 0, &vm_ih)) 567 panic("died while creating standard software ithreads"); 568 569 PROC_LOCK(clk_ithd->it_proc); 570 clk_ithd->it_proc->p_flag |= P_NOLOAD; 571 PROC_UNLOCK(clk_ithd->it_proc); 572 } 573 SYSINIT(start_softintr, SI_SUB_SOFTINTR, SI_ORDER_FIRST, start_softintr, NULL) 574 575 void 576 legacy_setsoftnet(void) 577 { 578 swi_sched(net_ih, SWI_NOSWITCH); 579 } 580 581 /* 582 * XXX: This should really be in the network code somewhere and installed 583 * via a SI_SUB_SOFINTR, SI_ORDER_MIDDLE sysinit. 584 */ 585 void (*netisrs[32]) __P((void)); 586 u_int netisr; 587 588 int 589 register_netisr(num, handler) 590 int num; 591 netisr_t *handler; 592 { 593 594 if (num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs)) ) { 595 printf("register_netisr: bad isr number: %d\n", num); 596 return (EINVAL); 597 } 598 netisrs[num] = handler; 599 return (0); 600 } 601 602 int 603 unregister_netisr(num) 604 int num; 605 { 606 607 if (num < 0 || num >= (sizeof(netisrs)/sizeof(*netisrs)) ) { 608 printf("unregister_netisr: bad isr number: %d\n", num); 609 return (EINVAL); 610 } 611 netisrs[num] = NULL; 612 return (0); 613 } 614 615 static void 616 swi_net(void *dummy) 617 { 618 u_int bits; 619 int i; 620 621 bits = atomic_readandclear_int(&netisr); 622 while ((i = ffs(bits)) != 0) { 623 i--; 624 if (netisrs[i] != NULL) 625 netisrs[i](); 626 else 627 printf("swi_net: unregistered isr number: %d.\n", i); 628 bits &= ~(1 << i); 629 } 630 } 631