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/i386/i386/db_interface.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) 1991,1990 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
   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 the
   24  * rights to redistribute these changes.
   25  *
   26  * $FreeBSD$
   27  */
   28 
   29 /*
   30  * Interface to new debugger.
   31  */
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/reboot.h>
   35 #include <sys/cons.h>
   36 
   37 #include <machine/cpu.h>
   38 #ifdef SMP
   39 #include <machine/smp.h>
   40 #include <machine/smptests.h>   /** CPUSTOP_ON_DDBBREAK */
   41 #endif
   42 
   43 #include <vm/vm.h>
   44 #include <vm/pmap.h>
   45 
   46 #include <ddb/ddb.h>
   47 
   48 #include <setjmp.h>
   49 
   50 static jmp_buf *db_nofault = 0;
   51 extern jmp_buf  db_jmpbuf;
   52 
   53 extern void     gdb_handle_exception __P((db_regs_t *, int, int));
   54 
   55 int     db_active;
   56 db_regs_t ddb_regs;
   57 
   58 static jmp_buf  db_global_jmpbuf;
   59 static int      db_global_jmpbuf_valid;
   60 
   61 #ifdef __GNUC__
   62 #define rss() ({u_short ss; __asm __volatile("mov %%ss,%0" : "=r" (ss)); ss;})
   63 #endif
   64 
   65 /*
   66  *  kdb_trap - field a TRACE or BPT trap
   67  */
   68 int
   69 kdb_trap(type, code, regs)
   70         int     type, code;
   71         register struct i386_saved_state *regs;
   72 {
   73         volatile int ddb_mode = !(boothowto & RB_GDB);
   74 
   75         /*
   76          * XXX try to do nothing if the console is in graphics mode.
   77          * Handle trace traps (and hardware breakpoints...) by ignoring
   78          * them except for forgetting about them.  Return 0 for other
   79          * traps to say that we haven't done anything.  The trap handler
   80          * will usually panic.  We should handle breakpoint traps for
   81          * our breakpoints by disarming our breakpoints and fixing up
   82          * %eip.
   83          */
   84         if (cons_unavail && ddb_mode) {
   85             if (type == T_TRCTRAP) {
   86                 regs->tf_eflags &= ~PSL_T;
   87                 return (1);
   88             }
   89             return (0);
   90         }
   91 
   92         switch (type) {
   93             case T_BPTFLT:      /* breakpoint */
   94             case T_TRCTRAP:     /* debug exception */
   95                 break;
   96 
   97             default:
   98                 /*
   99                  * XXX this is almost useless now.  In most cases,
  100                  * trap_fatal() has already printed a much more verbose
  101                  * message.  However, it is dangerous to print things in
  102                  * trap_fatal() - printf() might be reentered and trap.
  103                  * The debugger should be given control first.
  104                  */
  105                 if (ddb_mode)
  106                     db_printf("kernel: type %d trap, code=%x\n", type, code);
  107 
  108                 if (db_nofault) {
  109                     jmp_buf *no_fault = db_nofault;
  110                     db_nofault = 0;
  111                     longjmp(*no_fault, 1);
  112                 }
  113         }
  114 
  115         /*
  116          * This handles unexpected traps in ddb commands, including calls to
  117          * non-ddb functions.  db_nofault only applies to memory accesses by
  118          * internal ddb commands.
  119          */
  120         if (db_global_jmpbuf_valid)
  121             longjmp(db_global_jmpbuf, 1);
  122 
  123         /*
  124          * XXX We really should switch to a local stack here.
  125          */
  126         ddb_regs = *regs;
  127 
  128         /*
  129          * If in kernel mode, esp and ss are not saved, so dummy them up.
  130          */
  131         if (ISPL(regs->tf_cs) == 0) {
  132             ddb_regs.tf_esp = (int)&regs->tf_esp;
  133             ddb_regs.tf_ss = rss();
  134         }
  135 
  136 #ifdef SMP
  137 #ifdef CPUSTOP_ON_DDBBREAK
  138 
  139 #if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
  140         db_printf("\nCPU%d stopping CPUs: 0x%08x\n", cpuid, other_cpus);
  141 #endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
  142 
  143         /* We stop all CPUs except ourselves (obviously) */
  144         stop_cpus(other_cpus);
  145 
  146 #if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
  147         db_printf(" stopped\n");
  148 #endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
  149 
  150 #endif /* CPUSTOP_ON_DDBBREAK */
  151 #endif /* SMP */
  152 
  153         (void) setjmp(db_global_jmpbuf);
  154         db_global_jmpbuf_valid = TRUE;
  155         db_active++;
  156         if (ddb_mode) {
  157             cndbctl(TRUE);
  158             db_trap(type, code);
  159             cndbctl(FALSE);
  160         } else
  161             gdb_handle_exception(&ddb_regs, type, code);
  162         db_active--;
  163         db_global_jmpbuf_valid = FALSE;
  164 
  165 #ifdef SMP
  166 #ifdef CPUSTOP_ON_DDBBREAK
  167 
  168 #if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
  169         db_printf("\nCPU%d restarting CPUs: 0x%08x\n", cpuid, stopped_cpus);
  170 #endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
  171 
  172         /* Restart all the CPUs we previously stopped */
  173         if (stopped_cpus != other_cpus && smp_started != 0) {
  174                 db_printf("whoa, other_cpus: 0x%08x, stopped_cpus: 0x%08x\n",
  175                           other_cpus, stopped_cpus);
  176                 panic("stop_cpus() failed");
  177         }
  178         restart_cpus(stopped_cpus);
  179 
  180 #if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
  181         db_printf(" restarted\n");
  182 #endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
  183 
  184 #endif /* CPUSTOP_ON_DDBBREAK */
  185 #endif /* SMP */
  186 
  187         regs->tf_eip    = ddb_regs.tf_eip;
  188         regs->tf_eflags = ddb_regs.tf_eflags;
  189         regs->tf_eax    = ddb_regs.tf_eax;
  190         regs->tf_ecx    = ddb_regs.tf_ecx;
  191         regs->tf_edx    = ddb_regs.tf_edx;
  192         regs->tf_ebx    = ddb_regs.tf_ebx;
  193 
  194         /*
  195          * If in user mode, the saved ESP and SS were valid, restore them.
  196          */
  197         if (ISPL(regs->tf_cs)) {
  198             regs->tf_esp = ddb_regs.tf_esp;
  199             regs->tf_ss  = ddb_regs.tf_ss & 0xffff;
  200         }
  201 
  202         regs->tf_ebp    = ddb_regs.tf_ebp;
  203         regs->tf_esi    = ddb_regs.tf_esi;
  204         regs->tf_edi    = ddb_regs.tf_edi;
  205         regs->tf_es     = ddb_regs.tf_es & 0xffff;
  206         regs->tf_fs     = ddb_regs.tf_fs & 0xffff;
  207         regs->tf_cs     = ddb_regs.tf_cs & 0xffff;
  208         regs->tf_ds     = ddb_regs.tf_ds & 0xffff;
  209         return (1);
  210 }
  211 
  212 /*
  213  * Read bytes from kernel address space for debugger.
  214  */
  215 void
  216 db_read_bytes(addr, size, data)
  217         vm_offset_t     addr;
  218         register size_t size;
  219         register char   *data;
  220 {
  221         register char   *src;
  222 
  223         db_nofault = &db_jmpbuf;
  224 
  225         src = (char *)addr;
  226         while (size-- > 0)
  227             *data++ = *src++;
  228 
  229         db_nofault = 0;
  230 }
  231 
  232 /*
  233  * Write bytes to kernel address space for debugger.
  234  */
  235 void
  236 db_write_bytes(addr, size, data)
  237         vm_offset_t     addr;
  238         register size_t size;
  239         register char   *data;
  240 {
  241         register char   *dst;
  242 
  243         unsigned        *ptep0 = NULL;
  244         unsigned        oldmap0 = 0;
  245         vm_offset_t     addr1;
  246         unsigned        *ptep1 = NULL;
  247         unsigned        oldmap1 = 0;
  248 
  249         db_nofault = &db_jmpbuf;
  250 
  251         if (addr > trunc_page((vm_offset_t)btext) - size &&
  252             addr < round_page((vm_offset_t)etext)) {
  253 
  254             ptep0 = pmap_pte(kernel_pmap, addr);
  255             oldmap0 = *ptep0;
  256             *ptep0 |= PG_RW;
  257 
  258             /* Map another page if the data crosses a page boundary. */
  259             if ((*ptep0 & PG_PS) == 0) {
  260                 addr1 = trunc_page(addr + size - 1);
  261                 if (trunc_page(addr) != addr1) {
  262                     ptep1 = pmap_pte(kernel_pmap, addr1);
  263                     oldmap1 = *ptep1;
  264                     *ptep1 |= PG_RW;
  265                 }
  266             } else {
  267                 addr1 = trunc_4mpage(addr + size - 1);
  268                 if (trunc_4mpage(addr) != addr1) {
  269                     ptep1 = pmap_pte(kernel_pmap, addr1);
  270                     oldmap1 = *ptep1;
  271                     *ptep1 |= PG_RW;
  272                 }
  273             }
  274 
  275             invltlb();
  276         }
  277 
  278         dst = (char *)addr;
  279 
  280         while (size-- > 0)
  281             *dst++ = *data++;
  282 
  283         db_nofault = 0;
  284 
  285         if (ptep0) {
  286             *ptep0 = oldmap0;
  287 
  288             if (ptep1)
  289                 *ptep1 = oldmap1;
  290 
  291             invltlb();
  292         }
  293 }
  294 
  295 /*
  296  * XXX
  297  * Move this to machdep.c and allow it to be called if any debugger is
  298  * installed.
  299  */
  300 void
  301 Debugger(msg)
  302         const char *msg;
  303 {
  304         static volatile u_char in_Debugger;
  305 
  306         /*
  307          * XXX
  308          * Do nothing if the console is in graphics mode.  This is
  309          * OK if the call is for the debugger hotkey but not if the call
  310          * is a weak form of panicing.
  311          */
  312         if (cons_unavail && !(boothowto & RB_GDB))
  313             return;
  314 
  315         if (!in_Debugger) {
  316             in_Debugger = 1;
  317             db_printf("Debugger(\"%s\")\n", msg);
  318             breakpoint();
  319             in_Debugger = 0;
  320         }
  321 }

Cache object: 485fe96a567f045971c7ffe4cabff742


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