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

Cache object: ed843407359dfa1dd3a01c05d1f8c801


[ 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.