The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/subr_kdb.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2004 The FreeBSD Project
    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  *
    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 AUTHORS ``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 AUTHORS 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 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD: releng/9.0/sys/kern/subr_kdb.c 225797 2011-09-27 14:00:32Z attilio $");
   29 
   30 #include "opt_kdb.h"
   31 #include "opt_stack.h"
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/kdb.h>
   36 #include <sys/kernel.h>
   37 #include <sys/malloc.h>
   38 #include <sys/pcpu.h>
   39 #include <sys/proc.h>
   40 #include <sys/sbuf.h>
   41 #include <sys/smp.h>
   42 #include <sys/stack.h>
   43 #include <sys/sysctl.h>
   44 
   45 #include <machine/kdb.h>
   46 #include <machine/pcb.h>
   47 
   48 #ifdef SMP
   49 #include <machine/smp.h>
   50 #endif
   51 
   52 int kdb_active = 0;
   53 static void *kdb_jmpbufp = NULL;
   54 struct kdb_dbbe *kdb_dbbe = NULL;
   55 static struct pcb kdb_pcb;
   56 struct pcb *kdb_thrctx = NULL;
   57 struct thread *kdb_thread = NULL;
   58 struct trapframe *kdb_frame = NULL;
   59 
   60 #ifdef BREAK_TO_DEBUGGER
   61 #define KDB_BREAK_TO_DEBUGGER   1
   62 #else
   63 #define KDB_BREAK_TO_DEBUGGER   0
   64 #endif
   65 
   66 #ifdef ALT_BREAK_TO_DEBUGGER
   67 #define KDB_ALT_BREAK_TO_DEBUGGER       1
   68 #else
   69 #define KDB_ALT_BREAK_TO_DEBUGGER       0
   70 #endif
   71 
   72 static int      kdb_break_to_debugger = KDB_BREAK_TO_DEBUGGER;
   73 static int      kdb_alt_break_to_debugger = KDB_ALT_BREAK_TO_DEBUGGER;
   74 
   75 KDB_BACKEND(null, NULL, NULL, NULL);
   76 SET_DECLARE(kdb_dbbe_set, struct kdb_dbbe);
   77 
   78 static int kdb_sysctl_available(SYSCTL_HANDLER_ARGS);
   79 static int kdb_sysctl_current(SYSCTL_HANDLER_ARGS);
   80 static int kdb_sysctl_enter(SYSCTL_HANDLER_ARGS);
   81 static int kdb_sysctl_panic(SYSCTL_HANDLER_ARGS);
   82 static int kdb_sysctl_trap(SYSCTL_HANDLER_ARGS);
   83 static int kdb_sysctl_trap_code(SYSCTL_HANDLER_ARGS);
   84 
   85 SYSCTL_NODE(_debug, OID_AUTO, kdb, CTLFLAG_RW, NULL, "KDB nodes");
   86 
   87 SYSCTL_PROC(_debug_kdb, OID_AUTO, available, CTLTYPE_STRING | CTLFLAG_RD, NULL,
   88     0, kdb_sysctl_available, "A", "list of available KDB backends");
   89 
   90 SYSCTL_PROC(_debug_kdb, OID_AUTO, current, CTLTYPE_STRING | CTLFLAG_RW, NULL,
   91     0, kdb_sysctl_current, "A", "currently selected KDB backend");
   92 
   93 SYSCTL_PROC(_debug_kdb, OID_AUTO, enter, CTLTYPE_INT | CTLFLAG_RW, NULL, 0,
   94     kdb_sysctl_enter, "I", "set to enter the debugger");
   95 
   96 SYSCTL_PROC(_debug_kdb, OID_AUTO, panic, CTLTYPE_INT | CTLFLAG_RW, NULL, 0,
   97     kdb_sysctl_panic, "I", "set to panic the kernel");
   98 
   99 SYSCTL_PROC(_debug_kdb, OID_AUTO, trap, CTLTYPE_INT | CTLFLAG_RW, NULL, 0,
  100     kdb_sysctl_trap, "I", "set to cause a page fault via data access");
  101 
  102 SYSCTL_PROC(_debug_kdb, OID_AUTO, trap_code, CTLTYPE_INT | CTLFLAG_RW, NULL, 0,
  103     kdb_sysctl_trap_code, "I", "set to cause a page fault via code access");
  104 
  105 SYSCTL_INT(_debug_kdb, OID_AUTO, break_to_debugger, CTLTYPE_INT | CTLFLAG_RW |
  106     CTLFLAG_TUN, &kdb_break_to_debugger, 0, "Enable break to debugger");
  107 TUNABLE_INT("debug.kdb.break_to_debugger", &kdb_break_to_debugger);
  108 
  109 SYSCTL_INT(_debug_kdb, OID_AUTO, alt_break_to_debugger, CTLTYPE_INT |
  110     CTLFLAG_RW | CTLFLAG_TUN, &kdb_alt_break_to_debugger, 0,
  111     "Enable alternative break to debugger");
  112 TUNABLE_INT("debug.kdb.alt_break_to_debugger", &kdb_alt_break_to_debugger);
  113 
  114 /*
  115  * Flag to indicate to debuggers why the debugger was entered.
  116  */
  117 const char * volatile kdb_why = KDB_WHY_UNSET;
  118 
  119 static int
  120 kdb_sysctl_available(SYSCTL_HANDLER_ARGS)
  121 {
  122         struct kdb_dbbe **iter;
  123         struct sbuf sbuf;
  124         int error;
  125 
  126         sbuf_new_for_sysctl(&sbuf, NULL, 64, req);
  127         SET_FOREACH(iter, kdb_dbbe_set) {
  128                 if ((*iter)->dbbe_active == 0)
  129                         sbuf_printf(&sbuf, "%s ", (*iter)->dbbe_name);
  130         }
  131         error = sbuf_finish(&sbuf);
  132         sbuf_delete(&sbuf);
  133         return (error);
  134 }
  135 
  136 static int
  137 kdb_sysctl_current(SYSCTL_HANDLER_ARGS)
  138 {
  139         char buf[16];
  140         int error;
  141 
  142         if (kdb_dbbe != NULL)
  143                 strlcpy(buf, kdb_dbbe->dbbe_name, sizeof(buf));
  144         else
  145                 *buf = '\0';
  146         error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
  147         if (error != 0 || req->newptr == NULL)
  148                 return (error);
  149         if (kdb_active)
  150                 return (EBUSY);
  151         return (kdb_dbbe_select(buf));
  152 }
  153 
  154 static int
  155 kdb_sysctl_enter(SYSCTL_HANDLER_ARGS)
  156 {
  157         int error, i;
  158 
  159         error = sysctl_wire_old_buffer(req, sizeof(int));
  160         if (error == 0) {
  161                 i = 0;
  162                 error = sysctl_handle_int(oidp, &i, 0, req);
  163         }
  164         if (error != 0 || req->newptr == NULL)
  165                 return (error);
  166         if (kdb_active)
  167                 return (EBUSY);
  168         kdb_enter(KDB_WHY_SYSCTL, "sysctl debug.kdb.enter");
  169         return (0);
  170 }
  171 
  172 static int
  173 kdb_sysctl_panic(SYSCTL_HANDLER_ARGS)
  174 {
  175         int error, i;
  176 
  177         error = sysctl_wire_old_buffer(req, sizeof(int));
  178         if (error == 0) {
  179                 i = 0;
  180                 error = sysctl_handle_int(oidp, &i, 0, req);
  181         }
  182         if (error != 0 || req->newptr == NULL)
  183                 return (error);
  184         panic("kdb_sysctl_panic");
  185         return (0);
  186 }
  187 
  188 static int
  189 kdb_sysctl_trap(SYSCTL_HANDLER_ARGS)
  190 {
  191         int error, i;
  192         int *addr = (int *)0x10;
  193 
  194         error = sysctl_wire_old_buffer(req, sizeof(int));
  195         if (error == 0) {
  196                 i = 0;
  197                 error = sysctl_handle_int(oidp, &i, 0, req);
  198         }
  199         if (error != 0 || req->newptr == NULL)
  200                 return (error);
  201         return (*addr);
  202 }
  203 
  204 static int
  205 kdb_sysctl_trap_code(SYSCTL_HANDLER_ARGS)
  206 {
  207         int error, i;
  208         void (*fp)(u_int, u_int, u_int) = (void *)0xdeadc0de;
  209 
  210         error = sysctl_wire_old_buffer(req, sizeof(int));
  211         if (error == 0) {
  212                 i = 0;
  213                 error = sysctl_handle_int(oidp, &i, 0, req);
  214         }
  215         if (error != 0 || req->newptr == NULL)
  216                 return (error);
  217         (*fp)(0x11111111, 0x22222222, 0x33333333);
  218         return (0);
  219 }
  220 
  221 void
  222 kdb_panic(const char *msg)
  223 {
  224 #ifdef SMP
  225         cpuset_t other_cpus;
  226 
  227         other_cpus = all_cpus;
  228         CPU_CLR(PCPU_GET(cpuid), &other_cpus);
  229         stop_cpus_hard(other_cpus);
  230 #endif
  231         printf("KDB: panic\n");
  232         panic("%s", msg);
  233 }
  234 
  235 void
  236 kdb_reboot(void)
  237 {
  238 
  239         printf("KDB: reboot requested\n");
  240         shutdown_nice(0);
  241 }
  242 
  243 /*
  244  * Solaris implements a new BREAK which is initiated by a character sequence
  245  * CR ~ ^b which is similar to a familiar pattern used on Sun servers by the
  246  * Remote Console.
  247  *
  248  * Note that this function may be called from almost anywhere, with interrupts
  249  * disabled and with unknown locks held, so it must not access data other than
  250  * its arguments.  Its up to the caller to ensure that the state variable is
  251  * consistent.
  252  */
  253 
  254 #define KEY_CR          13      /* CR '\r' */
  255 #define KEY_TILDE       126     /* ~ */
  256 #define KEY_CRTLB       2       /* ^B */
  257 #define KEY_CRTLP       16      /* ^P */
  258 #define KEY_CRTLR       18      /* ^R */
  259 
  260 /* States of th KDB "alternate break sequence" detecting state machine. */
  261 enum {
  262         KDB_ALT_BREAK_SEEN_NONE,
  263         KDB_ALT_BREAK_SEEN_CR,
  264         KDB_ALT_BREAK_SEEN_CR_TILDE,
  265 };
  266 
  267 int
  268 kdb_break(void)
  269 {
  270 
  271         if (!kdb_break_to_debugger)
  272                 return (0);
  273         kdb_enter(KDB_WHY_BREAK, "Break to debugger");
  274         return (KDB_REQ_DEBUGGER);
  275 }
  276 
  277 static int
  278 kdb_alt_break_state(int key, int *state)
  279 {
  280         int brk;
  281 
  282         /* All states transition to KDB_ALT_BREAK_SEEN_CR on a CR. */
  283         if (key == KEY_CR) {
  284                 *state = KDB_ALT_BREAK_SEEN_CR;
  285                 return (0);
  286         }
  287 
  288         brk = 0;
  289         switch (*state) {
  290         case KDB_ALT_BREAK_SEEN_CR:
  291                 *state = KDB_ALT_BREAK_SEEN_NONE;
  292                 if (key == KEY_TILDE)
  293                         *state = KDB_ALT_BREAK_SEEN_CR_TILDE;
  294                 break;
  295         case KDB_ALT_BREAK_SEEN_CR_TILDE:
  296                 *state = KDB_ALT_BREAK_SEEN_NONE;
  297                 if (key == KEY_CRTLB)
  298                         brk = KDB_REQ_DEBUGGER;
  299                 else if (key == KEY_CRTLP)
  300                         brk = KDB_REQ_PANIC;
  301                 else if (key == KEY_CRTLR)
  302                         brk = KDB_REQ_REBOOT;
  303                 break;
  304         case KDB_ALT_BREAK_SEEN_NONE:
  305         default:
  306                 *state = KDB_ALT_BREAK_SEEN_NONE;
  307                 break;
  308         }
  309         return (brk);
  310 }
  311 
  312 static int
  313 kdb_alt_break_internal(int key, int *state, int force_gdb)
  314 {
  315         int brk;
  316 
  317         if (!kdb_alt_break_to_debugger)
  318                 return (0);
  319         brk = kdb_alt_break_state(key, state);
  320         switch (brk) {
  321         case KDB_REQ_DEBUGGER:
  322                 if (force_gdb)
  323                         kdb_dbbe_select("gdb");
  324                 kdb_enter(KDB_WHY_BREAK, "Break to debugger");
  325                 break;
  326 
  327         case KDB_REQ_PANIC:
  328                 if (force_gdb)
  329                         kdb_dbbe_select("gdb");
  330                 kdb_panic("Panic sequence on console");
  331                 break;
  332 
  333         case KDB_REQ_REBOOT:
  334                 kdb_reboot();
  335                 break;
  336         }
  337         return (0);
  338 }
  339 
  340 int
  341 kdb_alt_break(int key, int *state)
  342 {
  343 
  344         return (kdb_alt_break_internal(key, state, 0));
  345 }
  346 
  347 /*
  348  * This variation on kdb_alt_break() is used only by dcons, which has its own
  349  * configuration flag to force GDB use regardless of the global KDB
  350  * configuration.
  351  */
  352 int
  353 kdb_alt_break_gdb(int key, int *state)
  354 {
  355 
  356         return (kdb_alt_break_internal(key, state, 1));
  357 }
  358 
  359 /*
  360  * Print a backtrace of the calling thread. The backtrace is generated by
  361  * the selected debugger, provided it supports backtraces. If no debugger
  362  * is selected or the current debugger does not support backtraces, this
  363  * function silently returns.
  364  */
  365 
  366 void
  367 kdb_backtrace(void)
  368 {
  369 
  370         if (kdb_dbbe != NULL && kdb_dbbe->dbbe_trace != NULL) {
  371                 printf("KDB: stack backtrace:\n");
  372                 kdb_dbbe->dbbe_trace();
  373         }
  374 #ifdef STACK
  375         else {
  376                 struct stack st;
  377 
  378                 printf("KDB: stack backtrace:\n");
  379                 stack_save(&st);
  380                 stack_print_ddb(&st);
  381         }
  382 #endif
  383 }
  384 
  385 /*
  386  * Set/change the current backend.
  387  */
  388 
  389 int
  390 kdb_dbbe_select(const char *name)
  391 {
  392         struct kdb_dbbe *be, **iter;
  393 
  394         SET_FOREACH(iter, kdb_dbbe_set) {
  395                 be = *iter;
  396                 if (be->dbbe_active == 0 && strcmp(be->dbbe_name, name) == 0) {
  397                         kdb_dbbe = be;
  398                         return (0);
  399                 }
  400         }
  401         return (EINVAL);
  402 }
  403 
  404 /*
  405  * Enter the currently selected debugger. If a message has been provided,
  406  * it is printed first. If the debugger does not support the enter method,
  407  * it is entered by using breakpoint(), which enters the debugger through
  408  * kdb_trap().  The 'why' argument will contain a more mechanically usable
  409  * string than 'msg', and is relied upon by DDB scripting to identify the
  410  * reason for entering the debugger so that the right script can be run.
  411  */
  412 void
  413 kdb_enter(const char *why, const char *msg)
  414 {
  415 
  416         if (kdb_dbbe != NULL && kdb_active == 0) {
  417                 if (msg != NULL)
  418                         printf("KDB: enter: %s\n", msg);
  419                 kdb_why = why;
  420                 breakpoint();
  421                 kdb_why = KDB_WHY_UNSET;
  422         }
  423 }
  424 
  425 /*
  426  * Initialize the kernel debugger interface.
  427  */
  428 
  429 void
  430 kdb_init(void)
  431 {
  432         struct kdb_dbbe *be, **iter;
  433         int cur_pri, pri;
  434 
  435         kdb_active = 0;
  436         kdb_dbbe = NULL;
  437         cur_pri = -1;
  438         SET_FOREACH(iter, kdb_dbbe_set) {
  439                 be = *iter;
  440                 pri = (be->dbbe_init != NULL) ? be->dbbe_init() : -1;
  441                 be->dbbe_active = (pri >= 0) ? 0 : -1;
  442                 if (pri > cur_pri) {
  443                         cur_pri = pri;
  444                         kdb_dbbe = be;
  445                 }
  446         }
  447         if (kdb_dbbe != NULL) {
  448                 printf("KDB: debugger backends:");
  449                 SET_FOREACH(iter, kdb_dbbe_set) {
  450                         be = *iter;
  451                         if (be->dbbe_active == 0)
  452                                 printf(" %s", be->dbbe_name);
  453                 }
  454                 printf("\n");
  455                 printf("KDB: current backend: %s\n",
  456                     kdb_dbbe->dbbe_name);
  457         }
  458 }
  459 
  460 /*
  461  * Handle contexts.
  462  */
  463 
  464 void *
  465 kdb_jmpbuf(jmp_buf new)
  466 {
  467         void *old;
  468 
  469         old = kdb_jmpbufp;
  470         kdb_jmpbufp = new;
  471         return (old);
  472 }
  473 
  474 void
  475 kdb_reenter(void)
  476 {
  477 
  478         if (!kdb_active || kdb_jmpbufp == NULL)
  479                 return;
  480 
  481         longjmp(kdb_jmpbufp, 1);
  482         /* NOTREACHED */
  483 }
  484 
  485 /*
  486  * Thread related support functions.
  487  */
  488 
  489 struct pcb *
  490 kdb_thr_ctx(struct thread *thr)
  491 {  
  492 #if defined(SMP) && defined(KDB_STOPPEDPCB)
  493         struct pcpu *pc;
  494 #endif
  495  
  496         if (thr == curthread) 
  497                 return (&kdb_pcb);
  498 
  499 #if defined(SMP) && defined(KDB_STOPPEDPCB)
  500         STAILQ_FOREACH(pc, &cpuhead, pc_allcpu)  {
  501                 if (pc->pc_curthread == thr &&
  502                     CPU_ISSET(pc->pc_cpuid, &stopped_cpus))
  503                         return (KDB_STOPPEDPCB(pc));
  504         }
  505 #endif
  506         return (thr->td_pcb);
  507 }
  508 
  509 struct thread *
  510 kdb_thr_first(void)
  511 {
  512         struct proc *p;
  513         struct thread *thr;
  514 
  515         p = LIST_FIRST(&allproc);
  516         while (p != NULL) {
  517                 if (p->p_flag & P_INMEM) {
  518                         thr = FIRST_THREAD_IN_PROC(p);
  519                         if (thr != NULL)
  520                                 return (thr);
  521                 }
  522                 p = LIST_NEXT(p, p_list);
  523         }
  524         return (NULL);
  525 }
  526 
  527 struct thread *
  528 kdb_thr_from_pid(pid_t pid)
  529 {
  530         struct proc *p;
  531 
  532         p = LIST_FIRST(&allproc);
  533         while (p != NULL) {
  534                 if (p->p_flag & P_INMEM && p->p_pid == pid)
  535                         return (FIRST_THREAD_IN_PROC(p));
  536                 p = LIST_NEXT(p, p_list);
  537         }
  538         return (NULL);
  539 }
  540 
  541 struct thread *
  542 kdb_thr_lookup(lwpid_t tid)
  543 {
  544         struct thread *thr;
  545 
  546         thr = kdb_thr_first();
  547         while (thr != NULL && thr->td_tid != tid)
  548                 thr = kdb_thr_next(thr);
  549         return (thr);
  550 }
  551 
  552 struct thread *
  553 kdb_thr_next(struct thread *thr)
  554 {
  555         struct proc *p;
  556 
  557         p = thr->td_proc;
  558         thr = TAILQ_NEXT(thr, td_plist);
  559         do {
  560                 if (thr != NULL)
  561                         return (thr);
  562                 p = LIST_NEXT(p, p_list);
  563                 if (p != NULL && (p->p_flag & P_INMEM))
  564                         thr = FIRST_THREAD_IN_PROC(p);
  565         } while (p != NULL);
  566         return (NULL);
  567 }
  568 
  569 int
  570 kdb_thr_select(struct thread *thr)
  571 {
  572         if (thr == NULL)
  573                 return (EINVAL);
  574         kdb_thread = thr;
  575         kdb_thrctx = kdb_thr_ctx(thr);
  576         return (0);
  577 }
  578 
  579 /*
  580  * Enter the debugger due to a trap.
  581  */
  582 
  583 int
  584 kdb_trap(int type, int code, struct trapframe *tf)
  585 {
  586 #ifdef SMP
  587         cpuset_t other_cpus;
  588 #endif
  589         struct kdb_dbbe *be;
  590         register_t intr;
  591         int handled;
  592 
  593         be = kdb_dbbe;
  594         if (be == NULL || be->dbbe_trap == NULL)
  595                 return (0);
  596 
  597         /* We reenter the debugger through kdb_reenter(). */
  598         if (kdb_active)
  599                 return (0);
  600 
  601         intr = intr_disable();
  602 
  603 #ifdef SMP
  604         other_cpus = all_cpus;
  605         CPU_CLR(PCPU_GET(cpuid), &other_cpus);
  606         stop_cpus_hard(other_cpus);
  607 #endif
  608 
  609         kdb_active++;
  610 
  611         kdb_frame = tf;
  612 
  613         /* Let MD code do its thing first... */
  614         kdb_cpu_trap(type, code);
  615 
  616         makectx(tf, &kdb_pcb);
  617         kdb_thr_select(curthread);
  618 
  619         for (;;) {
  620                 handled = be->dbbe_trap(type, code);
  621                 if (be == kdb_dbbe)
  622                         break;
  623                 be = kdb_dbbe;
  624                 if (be == NULL || be->dbbe_trap == NULL)
  625                         break;
  626                 printf("Switching to %s back-end\n", be->dbbe_name);
  627         }
  628 
  629         kdb_active--;
  630 
  631 #ifdef SMP
  632         restart_cpus(stopped_cpus);
  633 #endif
  634 
  635         intr_restore(intr);
  636 
  637         return (handled);
  638 }

Cache object: bf7010dc3abfbaa9bfa7b1e975740aab


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.