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/ddb/db_mp.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  * Mach Operating System
    3  * Copyright (c) 1993,1992 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon 
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        db_mp.c,v $
   29  * Revision 2.3  93/01/19  09:00:53  danner
   30  *      More info in debugging printouts.
   31  *      [92/12/26            af]
   32  * 
   33  * Revision 2.2  93/01/14  17:25:20  danner
   34  *      Made more machine-independent, as alpha and mips keep
   35  *      register states on stack.  Spots.
   36  *      [92/12/16  12:44:42  af]
   37  * 
   38  *      Pulled code from OSF/Grenoble and restructured.
   39  *      [92/10/24            dbg]
   40  * 
   41  */
   42 #include <cpus.h>
   43 
   44 #if     NCPUS > 1
   45 
   46 #include <mach/boolean.h>
   47 #include <mach/machine.h>
   48 
   49 #include <kern/cpu_number.h>
   50 #include <kern/lock.h>
   51 
   52 #include <machine/db_machdep.h>
   53 
   54 #include <ddb/db_command.h>
   55 #include <ddb/db_run.h>
   56 
   57 /*
   58  * Routines to interlock access to the kernel debugger on
   59  * multiprocessors.
   60  */
   61 
   62 decl_simple_lock_data(,db_lock)         /* lock to enter debugger */
   63 volatile int    db_cpu = -1;            /* CPU currently in debugger */
   64                                         /* -1 if none */
   65 int     db_active[NCPUS] = { 0 };       /* count recursive entries
   66                                            into debugger */
   67 int     db_slave[NCPUS] = { 0 };        /* nonzero if cpu interrupted
   68                                            by another cpu in debugger */
   69 
   70 int     db_enter_debug = 0;
   71 
   72 void    remote_db();            /* forward */
   73 void    lock_db();
   74 void    unlock_db();
   75 
   76 
   77 /*
   78  * Called when entering kernel debugger.
   79  * Takes db lock. If we were called remotely (slave state) we just
   80  * wait for db_cpu to be equal to cpu_number(). Otherwise enter debugger
   81  * if not active on another cpu
   82  */
   83 
   84 boolean_t
   85 db_enter()
   86 {
   87         int     mycpu = cpu_number();
   88 
   89         /*
   90          * Count recursive entries to debugger.
   91          */
   92         db_active[mycpu]++;
   93 
   94         /*
   95          * Wait for other CPUS to leave debugger.
   96          */
   97         lock_db();
   98 
   99         if (db_enter_debug)
  100             db_printf(
  101                 "db_enter: cpu %d[%d], master %d, db_cpu %d, run mode %d\n",
  102                 mycpu, db_slave[mycpu], master_cpu, db_cpu, db_run_mode);
  103 
  104         /*
  105          * If no CPU in debugger, and I am not being stopped,
  106          * enter the debugger.
  107          */
  108         if (db_cpu == -1 && !db_slave[mycpu]) {
  109             remote_db();        /* stop other cpus */
  110             db_cpu = mycpu;
  111             return TRUE;
  112         }
  113         /*
  114          * If I am already in the debugger (recursive entry
  115          * or returning from single step), enter debugger.
  116          */
  117         else if (db_cpu == mycpu)
  118             return TRUE;
  119         /*
  120          * Otherwise, cannot enter debugger.
  121          */
  122         else
  123             return FALSE;
  124 }
  125 
  126 /*
  127  * Leave debugger.
  128  */
  129 void
  130 db_leave()
  131 {
  132         int     mycpu = cpu_number();
  133 
  134         /*
  135          * If continuing, give up debugger
  136          */
  137         if (db_run_mode == STEP_CONTINUE)
  138             db_cpu = -1;
  139 
  140         /*
  141          * If I am a slave, drop my slave count.
  142          */
  143         if (db_slave[mycpu])
  144             db_slave[mycpu]--;
  145         if (db_enter_debug)
  146             db_printf("db_leave: cpu %d[%d], db_cpu %d, run_mode %d\n",
  147                       mycpu, db_slave[mycpu], db_cpu, db_run_mode);
  148         /*
  149          * Unlock debugger.
  150          */
  151         unlock_db();
  152 
  153         /*
  154          * Drop recursive entry count.
  155          */
  156         db_active[mycpu]--;
  157 }
  158 
  159 
  160 /*
  161  * invoke kernel debugger on slave processors 
  162  */
  163 
  164 void
  165 remote_db() {
  166         int     my_cpu = cpu_number();
  167         register int    i;
  168 
  169         for (i = 0; i < NCPUS; i++) {
  170             if (i != my_cpu &&
  171                 machine_slot[i].is_cpu &&
  172                 machine_slot[i].running)
  173             {
  174                 cpu_interrupt_to_db(i);
  175             }
  176         }
  177 }
  178 
  179 /*
  180  * Save and restore DB global registers.
  181  *
  182  * DB_SAVE_CTXT must be at the start of a block, and
  183  * DB_RESTORE_CTXT must be in the same block.
  184  */
  185 
  186 #ifdef  __STDC__
  187 #define DB_SAVE(type, name) extern type name; type name##_save = name
  188 #define DB_RESTORE(name) name = name##_save
  189 #else   /* __STDC__ */
  190 #define DB_SAVE(type, name) extern type name; type name/**/_save = name
  191 #define DB_RESTORE(name) name = name/**/_save
  192 #endif  /* __STDC__ */
  193 
  194 #define DB_SAVE_CTXT() \
  195         DB_SAVE(int, db_run_mode); \
  196         DB_SAVE(boolean_t, db_sstep_print); \
  197         DB_SAVE(int, db_loop_count); \
  198         DB_SAVE(int, db_call_depth); \
  199         DB_SAVE(int, db_inst_count); \
  200         DB_SAVE(int, db_last_inst_count); \
  201         DB_SAVE(int, db_load_count); \
  202         DB_SAVE(int, db_store_count); \
  203         DB_SAVE(boolean_t, db_cmd_loop_done); \
  204         DB_SAVE(jmp_buf_t *, db_recover); \
  205         DB_SAVE(db_addr_t, db_dot); \
  206         DB_SAVE(db_addr_t, db_last_addr); \
  207         DB_SAVE(db_addr_t, db_prev); \
  208         DB_SAVE(db_addr_t, db_next); \
  209         SAVE_DDB_REGS
  210 
  211 #define DB_RESTORE_CTXT() \
  212         DB_RESTORE(db_run_mode); \
  213         DB_RESTORE(db_sstep_print); \
  214         DB_RESTORE(db_loop_count); \
  215         DB_RESTORE(db_call_depth); \
  216         DB_RESTORE(db_inst_count); \
  217         DB_RESTORE(db_last_inst_count); \
  218         DB_RESTORE(db_load_count); \
  219         DB_RESTORE(db_store_count); \
  220         DB_RESTORE(db_cmd_loop_done); \
  221         DB_RESTORE(db_recover); \
  222         DB_RESTORE(db_dot); \
  223         DB_RESTORE(db_last_addr); \
  224         DB_RESTORE(db_prev); \
  225         DB_RESTORE(db_next); \
  226         RESTORE_DDB_REGS
  227 
  228 /*
  229  * switch to another cpu
  230  */
  231 void
  232 db_on(cpu)
  233         int     cpu;
  234 {
  235         /*
  236          * Save ddb global variables
  237          */
  238         DB_SAVE_CTXT();
  239 
  240         /*
  241          * Don`t do if bad CPU number.
  242          * CPU must also be spinning in db_entry.
  243          */
  244         if (cpu < 0 || cpu >= NCPUS || !db_active[cpu])
  245             return;
  246 
  247         /*
  248          * Give debugger to that CPU
  249          */
  250         db_cpu = cpu;
  251         unlock_db();
  252 
  253         /*
  254          * Wait for it to come back again
  255          */
  256         lock_db();
  257 
  258         /*
  259          * Restore ddb globals
  260          */
  261         DB_RESTORE_CTXT();
  262 
  263         if (db_cpu == -1) /* someone continued */
  264             db_continue_cmd(0, 0, 0, "");
  265 }
  266 
  267 /*
  268  * Called by interprocessor interrupt when one CPU is
  269  * in kernel debugger and wants to stop other CPUs
  270  */
  271 void
  272 remote_db_enter()
  273 {
  274         db_slave[cpu_number()]++;
  275         kdb_kintr();
  276 }
  277 
  278 /*
  279  * Acquire kernel debugger.
  280  * Conditional code for forwarding characters from slave to console
  281  * if console on master only.
  282  */
  283 
  284 /*
  285  * As long as db_cpu is not -1 or cpu_number(), we know that debugger
  286  * is active on another cpu.
  287  */
  288 void
  289 lock_db()
  290 {
  291         int     my_cpu = cpu_number();
  292 
  293         for (;;) {
  294 #if     CONSOLE_ON_MASTER
  295             if (my_cpu == master_cpu) {
  296                 db_console();
  297             }
  298 #endif
  299             if (db_cpu != -1 && db_cpu != my_cpu)
  300                 continue;
  301 
  302 #if     CONSOLE_ON_MASTER
  303             if (my_cpu == master_cpu) {
  304                 if (!simple_lock_try(&db_lock))
  305                     continue;
  306             }
  307             else {
  308                 simple_lock(&db_lock);
  309             }
  310 #else
  311             simple_lock(&db_lock);
  312 #endif
  313             if (db_cpu == -1 || db_cpu == my_cpu)
  314                 break;
  315             simple_unlock(&db_lock);
  316         }
  317 }
  318 
  319 void
  320 unlock_db()
  321 {
  322         simple_unlock(&db_lock);
  323 }
  324 
  325 #ifdef sketch
  326 void
  327 db_console()
  328 {
  329                         if (i_bit(CBUS_PUT_CHAR, my_word)) {
  330                                 volatile u_char c = cbus_ochar;
  331                                 i_bit_clear(CBUS_PUT_CHAR, my_word);
  332                                 cnputc(c);
  333                         } else if (i_bit(CBUS_GET_CHAR, my_word)) {
  334                                 if (cbus_wait_char)
  335                                         cbus_ichar = cngetc();
  336                                 else
  337                                         cbus_ichar = cnmaygetc();
  338                                 i_bit_clear(CBUS_GET_CHAR, my_word);
  339 #ifndef notdef
  340                         } else if (!cnmaygetc()) {
  341 #else   /* notdef */
  342                         } else if (com_is_char() && !com_getc(TRUE)) {
  343 #endif  /* notdef */
  344                                 simple_unlock(&db_lock);
  345                                 db_cpu = my_cpu;
  346                         }
  347 }
  348 #endif  /* sketch */
  349 
  350 #endif  /* NCPUS > 1 */

Cache object: d209528c4a54a210e6543818d599a44e


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