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

Cache object: d50c41e5218bf82754277566a3f079e7


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