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

Cache object: 394c5755254ea4d0708c8c299523484d


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