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

Cache object: fbec0b310a048481174edad2a2ab7af5


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