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/osfmk/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  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /*
   26  * @OSF_COPYRIGHT@
   27  */
   28 /* 
   29  * Mach Operating System
   30  * Copyright (c) 1991,1990 Carnegie Mellon University
   31  * All Rights Reserved.
   32  * 
   33  * Permission to use, copy, modify and distribute this software and its
   34  * documentation is hereby granted, provided that both the copyright
   35  * notice and this permission notice appear in all copies of the
   36  * software, derivative works or modified versions, and any portions
   37  * thereof, and that both notices appear in supporting documentation.
   38  * 
   39  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   40  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   41  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   42  * 
   43  * Carnegie Mellon requests users of this software to return to
   44  * 
   45  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   46  *  School of Computer Science
   47  *  Carnegie Mellon University
   48  *  Pittsburgh PA 15213-3890
   49  * 
   50  * any improvements or extensions that they make and grant Carnegie Mellon
   51  * the rights to redistribute these changes.
   52  */
   53 /*
   54  */
   55 
   56 /*
   57  * Interface to new debugger.
   58  */
   59 #include <cpus.h>
   60 #include <platforms.h>
   61 #include <time_stamp.h>
   62 #include <mach_mp_debug.h>
   63 #include <mach_ldebug.h>
   64 #include <kern/spl.h>
   65 #include <kern/cpu_number.h>
   66 #include <kern/kern_types.h>
   67 #include <kern/misc_protos.h>
   68 #include <vm/pmap.h>
   69 
   70 #include <i386/thread.h>
   71 #include <i386/db_machdep.h>
   72 #include <i386/seg.h>
   73 #include <i386/trap.h>
   74 #include <i386/setjmp.h>
   75 #include <i386/pmap.h>
   76 #include <i386/misc_protos.h>
   77 
   78 #include <mach/vm_param.h>
   79 #include <vm/vm_map.h>
   80 #include <kern/thread.h>
   81 #include <kern/task.h>
   82 
   83 #include <ddb/db_command.h>
   84 #include <ddb/db_task_thread.h>
   85 #include <ddb/db_run.h>
   86 #include <ddb/db_trap.h>
   87 #include <ddb/db_output.h>
   88 #include <ddb/db_access.h>
   89 #include <ddb/db_sym.h>
   90 #include <ddb/db_break.h>
   91 #include <ddb/db_watch.h>
   92 
   93 int      db_active = 0;
   94 int      db_pass_thru[NCPUS];
   95 struct   i386_saved_state *i386_last_saved_statep;
   96 struct   i386_saved_state i386_nested_saved_state;
   97 unsigned i386_last_kdb_sp;
   98 
   99 vm_offset_t db_stacks[NCPUS];
  100 
  101 extern  thread_act_t db_default_act;
  102 
  103 #if     MACH_MP_DEBUG
  104 extern int masked_state_cnt[];
  105 #endif  /* MACH_MP_DEBUG */
  106 
  107 /*
  108  *      Enter KDB through a keyboard trap.
  109  *      We show the registers as of the keyboard interrupt
  110  *      instead of those at its call to KDB.
  111  */
  112 struct int_regs {
  113         int     gs;
  114         int     fs;
  115         int     edi;
  116         int     esi;
  117         int     ebp;
  118         int     ebx;
  119         struct i386_interrupt_state *is;
  120 };
  121 
  122 extern char *   trap_type[];
  123 extern int      TRAP_TYPES;
  124 
  125 /* Forward */
  126 
  127 extern void     kdbprinttrap(
  128                         int                     type,
  129                         int                     code,
  130                         int                     *pc,
  131                         int                     sp);
  132 extern void     kdb_kentry(
  133                         struct int_regs         *int_regs);
  134 extern int      db_user_to_kernel_address(
  135                         task_t                  task,
  136                         vm_offset_t             addr,
  137                         unsigned                *kaddr,
  138                         int                     flag);
  139 extern void     db_write_bytes_user_space(
  140                         vm_offset_t             addr,
  141                         int                     size,
  142                         char                    *data,
  143                         task_t                  task);
  144 extern int      db_search_null(
  145                         task_t                  task,
  146                         unsigned                *svaddr,
  147                         unsigned                evaddr,
  148                         unsigned                *skaddr,
  149                         int                     flag);
  150 extern int      kdb_enter(int);
  151 extern void     kdb_leave(void);
  152 extern void     lock_kdb(void);
  153 extern void     unlock_kdb(void);
  154 
  155 /*
  156  *  kdb_trap - field a TRACE or BPT trap
  157  */
  158 
  159 
  160 extern jmp_buf_t *db_recover;
  161 spl_t   saved_ipl[NCPUS];       /* just to know what IPL was before trap */
  162 struct i386_saved_state *saved_state[NCPUS];
  163 
  164 /*
  165  * Translate the state saved in a task state segment into an
  166  * exception frame.  Since we "know" we always want the state
  167  * in a ktss, we hard-wire that in, rather than indexing the gdt
  168  * with tss_sel to derive a pointer to the desired tss.
  169  */
  170 void
  171 db_tss_to_frame(
  172         int tss_sel,
  173         struct i386_saved_state *regs)
  174 {
  175         extern struct i386_tss ktss;
  176         int mycpu = cpu_number();
  177         struct i386_tss *tss;
  178 
  179 #if     NCPUS == 1
  180         tss = &ktss;    /* XXX */
  181 #else   /* NCPUS > 1 */
  182         tss = mp_ktss[mycpu];   /* XXX */
  183 #endif  /* NCPUS > 1 */
  184 
  185         /*
  186          * ddb will overwrite whatever's in esp, so put esp0 elsewhere, too.
  187          */
  188         regs->esp = tss->esp0;
  189         regs->efl = tss->eflags;
  190         regs->eip = tss->eip;
  191         regs->trapno = tss->ss0;        /* XXX */
  192         regs->err = tss->esp0;  /* XXX */
  193         regs->eax = tss->eax;
  194         regs->ecx = tss->ecx;
  195         regs->edx = tss->edx;
  196         regs->ebx = tss->ebx;
  197         regs->uesp = tss->esp;
  198         regs->ebp = tss->ebp;
  199         regs->esi = tss->esi;
  200         regs->edi = tss->edi;
  201         regs->es = tss->es;
  202         regs->ss = tss->ss;
  203         regs->cs = tss->cs;
  204         regs->ds = tss->ds;
  205         regs->fs = tss->fs;
  206         regs->gs = tss->gs;
  207 }
  208 
  209 /*
  210  * Compose a call to the debugger from the saved state in regs.  (No
  211  * reason not to do this in C.)
  212  */
  213 boolean_t
  214 db_trap_from_asm(
  215         struct i386_saved_state *regs)
  216 {
  217         int     code;
  218         int     type;
  219 
  220         type = regs->trapno;
  221         code = regs->err;
  222         return (kdb_trap(type, code, regs));
  223 }
  224 
  225 int
  226 kdb_trap(
  227         int                     type,
  228         int                     code,
  229         struct i386_saved_state *regs)
  230 {
  231         extern char             etext;
  232         boolean_t               trap_from_user;
  233         spl_t                   s = splhigh();
  234 
  235         switch (type) {
  236             case T_DEBUG:       /* single_step */
  237             {
  238                 extern int dr_addr[];
  239                 int addr;
  240                 int status = dr6();
  241 
  242                 if (status & 0xf) {     /* hmm hdw break */
  243                         addr =  status & 0x8 ? dr_addr[3] :
  244                                 status & 0x4 ? dr_addr[2] :
  245                                 status & 0x2 ? dr_addr[1] :
  246                                                dr_addr[0];
  247                         regs->efl |= EFL_RF;
  248                         db_single_step_cmd(addr, 0, 1, "p");
  249                 }
  250             }
  251             case T_INT3:        /* breakpoint */
  252             case T_WATCHPOINT:  /* watchpoint */
  253             case -1:    /* keyboard interrupt */
  254                 break;
  255 
  256             default:
  257                 if (db_recover) {
  258                     i386_nested_saved_state = *regs;
  259                     db_printf("Caught ");
  260                     if (type < 0 || type > TRAP_TYPES)
  261                         db_printf("type %d", type);
  262                     else
  263                         db_printf("%s", trap_type[type]);
  264                     db_printf(" trap, code = %x, pc = %x\n",
  265                               code, regs->eip);
  266                         splx(s);
  267                     db_error("");
  268                     /*NOTREACHED*/
  269                 }
  270                 kdbprinttrap(type, code, (int *)&regs->eip, regs->uesp);
  271         }
  272 
  273 #if     NCPUS > 1
  274         disable_preemption();
  275 #endif  /* NCPUS > 1 */
  276 
  277         saved_ipl[cpu_number()] = s;
  278         saved_state[cpu_number()] = regs;
  279 
  280         i386_last_saved_statep = regs;
  281         i386_last_kdb_sp = (unsigned) &type;
  282 
  283 #if     NCPUS > 1
  284         if (!kdb_enter(regs->eip))
  285                 goto kdb_exit;
  286 #endif  /* NCPUS > 1 */
  287 
  288         /*  Should switch to kdb's own stack here. */
  289 
  290         if (!IS_USER_TRAP(regs, &etext)) {
  291                 bzero((char *)&ddb_regs, sizeof (ddb_regs));
  292                 *(struct i386_saved_state_from_kernel *)&ddb_regs =
  293                         *(struct i386_saved_state_from_kernel *)regs;
  294                 trap_from_user = FALSE;
  295         }
  296         else {
  297                 ddb_regs = *regs;
  298                 trap_from_user = TRUE;
  299         }
  300         if (!trap_from_user) {
  301             /*
  302              * Kernel mode - esp and ss not saved
  303              */
  304             ddb_regs.uesp = (int)&regs->uesp;   /* kernel stack pointer */
  305             ddb_regs.ss   = KERNEL_DS;
  306         }
  307 
  308         db_active++;
  309         db_task_trap(type, code, trap_from_user);
  310         db_active--;
  311 
  312         regs->eip    = ddb_regs.eip;
  313         regs->efl    = ddb_regs.efl;
  314         regs->eax    = ddb_regs.eax;
  315         regs->ecx    = ddb_regs.ecx;
  316         regs->edx    = ddb_regs.edx;
  317         regs->ebx    = ddb_regs.ebx;
  318         if (trap_from_user) {
  319             /*
  320              * user mode - saved esp and ss valid
  321              */
  322             regs->uesp = ddb_regs.uesp;         /* user stack pointer */
  323             regs->ss   = ddb_regs.ss & 0xffff;  /* user stack segment */
  324         }
  325         regs->ebp    = ddb_regs.ebp;
  326         regs->esi    = ddb_regs.esi;
  327         regs->edi    = ddb_regs.edi;
  328         regs->es     = ddb_regs.es & 0xffff;
  329         regs->cs     = ddb_regs.cs & 0xffff;
  330         regs->ds     = ddb_regs.ds & 0xffff;
  331         regs->fs     = ddb_regs.fs & 0xffff;
  332         regs->gs     = ddb_regs.gs & 0xffff;
  333 
  334         if ((type == T_INT3) &&
  335             (db_get_task_value(regs->eip,
  336                                BKPT_SIZE,
  337                                FALSE,
  338                                db_target_space(current_act(),
  339                                                trap_from_user))
  340                               == BKPT_INST))
  341             regs->eip += BKPT_SIZE;
  342 
  343 #if     NCPUS > 1
  344 kdb_exit:
  345         kdb_leave();
  346 #endif  /* NCPUS > 1 */
  347 
  348         saved_state[cpu_number()] = 0;
  349 
  350 #if     MACH_MP_DEBUG
  351         masked_state_cnt[cpu_number()] = 0;
  352 #endif  /* MACH_MP_DEBUG */
  353 
  354 #if     NCPUS > 1
  355         enable_preemption();
  356 #endif  /* NCPUS > 1 */
  357 
  358         splx(s);
  359 
  360         /* Allow continue to upper layers of exception handling if
  361          * trap was not a debugging trap.
  362          */
  363 
  364         if (trap_from_user && type != T_DEBUG && type != T_INT3 
  365                 && type != T_WATCHPOINT)
  366                 return 0;
  367         else
  368                 return (1);
  369 }
  370 
  371 /*
  372  *      Enter KDB through a keyboard trap.
  373  *      We show the registers as of the keyboard interrupt
  374  *      instead of those at its call to KDB.
  375  */
  376 
  377 spl_t kdb_oldspl;
  378 
  379 void
  380 kdb_kentry(
  381         struct int_regs *int_regs)
  382 {
  383         extern char etext;
  384         boolean_t trap_from_user;
  385         struct i386_interrupt_state *is = int_regs->is;
  386         struct i386_saved_state regs;
  387         spl_t s;
  388 
  389         s = splhigh();
  390         kdb_oldspl = s;
  391 
  392         if (IS_USER_TRAP(is, &etext))
  393         {
  394             regs.uesp = ((int *)(is+1))[0];
  395             regs.ss   = ((int *)(is+1))[1];
  396         }
  397         else {
  398             regs.ss  = KERNEL_DS;
  399             regs.uesp= (int)(is+1);
  400         }
  401         regs.efl = is->efl;
  402         regs.cs  = is->cs;
  403         regs.eip = is->eip;
  404         regs.eax = is->eax;
  405         regs.ecx = is->ecx;
  406         regs.edx = is->edx;
  407         regs.ebx = int_regs->ebx;
  408         regs.ebp = int_regs->ebp;
  409         regs.esi = int_regs->esi;
  410         regs.edi = int_regs->edi;
  411         regs.ds  = is->ds;
  412         regs.es  = is->es;
  413         regs.fs  = int_regs->fs;
  414         regs.gs  = int_regs->gs;
  415 
  416 #if     NCPUS > 1
  417         disable_preemption();
  418 #endif  /* NCPUS > 1 */
  419 
  420         saved_state[cpu_number()] = &regs;
  421 
  422 #if     NCPUS > 1
  423         if (!kdb_enter(regs.eip))
  424                 goto kdb_exit;
  425 #endif  /* NCPUS > 1 */
  426 
  427         bcopy((char *)&regs, (char *)&ddb_regs, sizeof (ddb_regs));
  428         trap_from_user = IS_USER_TRAP(&ddb_regs, &etext);
  429 
  430         db_active++;
  431         db_task_trap(-1, 0, trap_from_user);
  432         db_active--;
  433 
  434         if (trap_from_user) {
  435             ((int *)(is+1))[0] = ddb_regs.uesp;
  436             ((int *)(is+1))[1] = ddb_regs.ss & 0xffff;
  437         }
  438         is->efl = ddb_regs.efl;
  439         is->cs  = ddb_regs.cs & 0xffff;
  440         is->eip = ddb_regs.eip;
  441         is->eax = ddb_regs.eax;
  442         is->ecx = ddb_regs.ecx;
  443         is->edx = ddb_regs.edx;
  444         int_regs->ebx = ddb_regs.ebx;
  445         int_regs->ebp = ddb_regs.ebp;
  446         int_regs->esi = ddb_regs.esi;
  447         int_regs->edi = ddb_regs.edi;
  448         is->ds  = ddb_regs.ds & 0xffff;
  449         is->es  = ddb_regs.es & 0xffff;
  450         int_regs->fs = ddb_regs.fs & 0xffff;
  451         int_regs->gs = ddb_regs.gs & 0xffff;
  452 
  453 #if     NCPUS > 1
  454 kdb_exit:
  455         kdb_leave();
  456 #endif  /* NCPUS > 1 */
  457         saved_state[cpu_number()] = 0;
  458 
  459 #if     NCPUS > 1
  460         enable_preemption();
  461 #endif  /* NCPUS > 1 */
  462 
  463         splx(s);
  464 }
  465 
  466 /*
  467  * Print trap reason.
  468  */
  469 
  470 void
  471 kdbprinttrap(
  472         int     type,
  473         int     code,
  474         int     *pc,
  475         int     sp)
  476 {
  477         printf("kernel: ");
  478         if (type < 0 || type > TRAP_TYPES)
  479             db_printf("type %d", type);
  480         else
  481             db_printf("%s", trap_type[type]);
  482         db_printf(" trap, code=%x eip@%x = %x esp=%x\n",
  483                   code, pc, *(int *)pc, sp);
  484         db_run_mode = STEP_CONTINUE;
  485 }
  486 
  487 int
  488 db_user_to_kernel_address(
  489         task_t          task,
  490         vm_offset_t     addr,
  491         unsigned        *kaddr,
  492         int             flag)
  493 {
  494         register pt_entry_t *ptp;
  495         
  496         ptp = pmap_pte(task->map->pmap, addr);
  497         if (ptp == PT_ENTRY_NULL || (*ptp & INTEL_PTE_VALID) == 0) {
  498             if (flag) {
  499                 db_printf("\nno memory is assigned to address %08x\n", addr);
  500                 db_error(0);
  501                 /* NOTREACHED */
  502             }
  503             return(-1);
  504         }
  505         *kaddr = (unsigned)ptetokv(*ptp) + (addr & (INTEL_PGBYTES-1));
  506         return(0);
  507 }
  508         
  509 /*
  510  * Read bytes from kernel address space for debugger.
  511  */
  512 
  513 void
  514 db_read_bytes(
  515         vm_offset_t     addr,
  516         int             size,
  517         char            *data,
  518         task_t          task)
  519 {
  520         register char   *src;
  521         register int    n;
  522         unsigned        kern_addr;
  523 
  524         src = (char *)addr;
  525         if (task == kernel_task || task == TASK_NULL) {
  526             while (--size >= 0) {
  527                 if (addr++ > VM_MAX_KERNEL_ADDRESS) {
  528                     db_printf("\nbad address %x\n", addr);
  529                     db_error(0);
  530                     /* NOTREACHED */
  531                 }
  532                 *data++ = *src++;
  533             }
  534             return;
  535         }
  536         while (size > 0) {
  537             if (db_user_to_kernel_address(task, addr, &kern_addr, 1) < 0)
  538                 return;
  539             src = (char *)kern_addr;
  540             n = intel_trunc_page(addr+INTEL_PGBYTES) - addr;
  541             if (n > size)
  542                 n = size;
  543             size -= n;
  544             addr += n;
  545             while (--n >= 0)
  546                 *data++ = *src++;
  547         }
  548 }
  549 
  550 /*
  551  * Write bytes to kernel address space for debugger.
  552  */
  553 
  554 void
  555 db_write_bytes(
  556         vm_offset_t     addr,
  557         int             size,
  558         char            *data,
  559         task_t          task)
  560 {
  561         register char   *dst;
  562 
  563         register pt_entry_t *ptep0 = 0;
  564         pt_entry_t      oldmap0 = 0;
  565         vm_offset_t     addr1;
  566         register pt_entry_t *ptep1 = 0;
  567         pt_entry_t      oldmap1 = 0;
  568         extern char     etext;
  569 
  570         if (task && task != kernel_task) {
  571             db_write_bytes_user_space(addr, size, data, task);
  572             return;
  573         }
  574 
  575             
  576         if (addr >= VM_MIN_KERNEL_LOADED_ADDRESS) {
  577                 db_write_bytes_user_space(addr, size, data, kernel_task);
  578                 return;
  579         }
  580 
  581         if (addr >= VM_MIN_KERNEL_ADDRESS &&
  582             addr <= (vm_offset_t)&etext)
  583         {
  584             ptep0 = pmap_pte(kernel_pmap, addr);
  585             oldmap0 = *ptep0;
  586             *ptep0 |= INTEL_PTE_WRITE;
  587 
  588             addr1 = i386_trunc_page(addr + size - 1);
  589             if (i386_trunc_page(addr) != addr1) {
  590                 /* data crosses a page boundary */
  591 
  592                 ptep1 = pmap_pte(kernel_pmap, addr1);
  593                 oldmap1 = *ptep1;
  594                 *ptep1 |= INTEL_PTE_WRITE;
  595             }
  596             flush_tlb();
  597         } 
  598 
  599         dst = (char *)addr;
  600 
  601         while (--size >= 0) {
  602             if (addr++ > VM_MAX_KERNEL_ADDRESS) {
  603                 db_printf("\nbad address %x\n", addr);
  604                 db_error(0);
  605                 /* NOTREACHED */
  606             }
  607             *dst++ = *data++;
  608         }
  609 
  610         if (ptep0) {
  611             *ptep0 = oldmap0;
  612             if (ptep1) {
  613                 *ptep1 = oldmap1;
  614             }
  615             flush_tlb();
  616         }
  617 }
  618         
  619 void
  620 db_write_bytes_user_space(
  621         vm_offset_t     addr,
  622         int             size,
  623         char            *data,
  624         task_t          task)
  625 {
  626         register char   *dst;
  627         register int    n;
  628         unsigned        kern_addr;
  629 
  630         while (size > 0) {
  631             if (db_user_to_kernel_address(task, addr, &kern_addr, 1) < 0)
  632                 return;
  633             dst = (char *)kern_addr;
  634             n = intel_trunc_page(addr+INTEL_PGBYTES) - addr;
  635             if (n > size)
  636                 n = size;
  637             size -= n;
  638             addr += n;
  639             while (--n >= 0)
  640                 *dst++ = *data++;
  641         }
  642 }
  643 
  644 boolean_t
  645 db_check_access(
  646         vm_offset_t     addr,
  647         int             size,
  648         task_t          task)
  649 {
  650         register        n;
  651         unsigned        kern_addr;
  652 
  653         if (task == kernel_task || task == TASK_NULL) {
  654             if (kernel_task == TASK_NULL)
  655                 return(TRUE);
  656             task = kernel_task;
  657         } else if (task == TASK_NULL) {
  658             if (current_act() == THR_ACT_NULL)
  659                 return(FALSE);
  660             task = current_act()->task;
  661         }
  662         while (size > 0) {
  663             if (db_user_to_kernel_address(task, addr, &kern_addr, 0) < 0)
  664                 return(FALSE);
  665             n = intel_trunc_page(addr+INTEL_PGBYTES) - addr;
  666             if (n > size)
  667                 n = size;
  668             size -= n;
  669             addr += n;
  670         }
  671         return(TRUE);
  672 }
  673 
  674 boolean_t
  675 db_phys_eq(
  676         task_t          task1,
  677         vm_offset_t     addr1,
  678         task_t          task2,
  679         vm_offset_t     addr2)
  680 {
  681         unsigned        kern_addr1, kern_addr2;
  682 
  683         if ((addr1 & (INTEL_PGBYTES-1)) != (addr2 & (INTEL_PGBYTES-1)))
  684             return(FALSE);
  685         if (task1 == TASK_NULL) {
  686             if (current_act() == THR_ACT_NULL)
  687                 return(FALSE);
  688             task1 = current_act()->task;
  689         }
  690         if (db_user_to_kernel_address(task1, addr1, &kern_addr1, 0) < 0 ||
  691                 db_user_to_kernel_address(task2, addr2, &kern_addr2, 0) < 0)
  692             return(FALSE);
  693         return(kern_addr1 == kern_addr2);
  694 }
  695 
  696 #define DB_USER_STACK_ADDR              (VM_MIN_KERNEL_ADDRESS)
  697 #define DB_NAME_SEARCH_LIMIT            (DB_USER_STACK_ADDR-(INTEL_PGBYTES*3))
  698 
  699 int
  700 db_search_null(
  701         task_t          task,
  702         unsigned        *svaddr,
  703         unsigned        evaddr,
  704         unsigned        *skaddr,
  705         int             flag)
  706 {
  707         register unsigned vaddr;
  708         register unsigned *kaddr;
  709 
  710         kaddr = (unsigned *)*skaddr;
  711         for (vaddr = *svaddr; vaddr > evaddr; vaddr -= sizeof(unsigned)) {
  712             if (vaddr % INTEL_PGBYTES == 0) {
  713                 vaddr -= sizeof(unsigned);
  714                 if (db_user_to_kernel_address(task, vaddr, skaddr, 0) < 0)
  715                     return(-1);
  716                 kaddr = (unsigned *)*skaddr;
  717             } else {
  718                 vaddr -= sizeof(unsigned);
  719                 kaddr--;
  720             }
  721             if ((*kaddr == 0) ^ (flag  == 0)) {
  722                 *svaddr = vaddr;
  723                 *skaddr = (unsigned)kaddr;
  724                 return(0);
  725             }
  726         }
  727         return(-1);
  728 }
  729 
  730 void
  731 db_task_name(
  732         task_t          task)
  733 {
  734         register char *p;
  735         register n;
  736         unsigned vaddr, kaddr;
  737 
  738         vaddr = DB_USER_STACK_ADDR;
  739         kaddr = 0;
  740 
  741         /*
  742          * skip nulls at the end
  743          */
  744         if (db_search_null(task, &vaddr, DB_NAME_SEARCH_LIMIT, &kaddr, 0) < 0) {
  745             db_printf(DB_NULL_TASK_NAME);
  746             return;
  747         }
  748         /*
  749          * search start of args
  750          */
  751         if (db_search_null(task, &vaddr, DB_NAME_SEARCH_LIMIT, &kaddr, 1) < 0) {
  752             db_printf(DB_NULL_TASK_NAME);
  753             return;
  754         }
  755 
  756         n = DB_TASK_NAME_LEN-1;
  757         p = (char *)kaddr + sizeof(unsigned);
  758         for (vaddr += sizeof(int); vaddr < DB_USER_STACK_ADDR && n > 0; 
  759                                                         vaddr++, p++, n--) {
  760             if (vaddr % INTEL_PGBYTES == 0) {
  761                 (void)db_user_to_kernel_address(task, vaddr, &kaddr, 0);
  762                 p = (char*)kaddr;
  763             }
  764             db_printf("%c", (*p < ' ' || *p > '~')? ' ': *p);
  765         }
  766         while (n-- >= 0)        /* compare with >= 0 for one more space */
  767             db_printf(" ");
  768 }
  769 
  770 #if NCPUS == 1
  771 
  772 void
  773 db_machdep_init(void)
  774 {
  775         db_stacks[0] = (vm_offset_t)(db_stack_store +
  776                 INTSTACK_SIZE - sizeof (natural_t));
  777         dbtss.esp0 = (int)(db_task_stack_store +
  778                 INTSTACK_SIZE - sizeof (natural_t));
  779         dbtss.esp = dbtss.esp0;
  780         dbtss.eip = (int)&db_task_start;
  781 }
  782 
  783 #else /* NCPUS > 1 */
  784 
  785 /*
  786  * Code used to synchronize kdb among all cpus, one active at a time, switch
  787  * from on to another using kdb_on! #cpu or cpu #cpu
  788  */
  789 
  790 decl_simple_lock_data(, kdb_lock)       /* kdb lock                     */
  791 
  792 #define db_simple_lock_init(l, e)       hw_lock_init(&((l)->interlock))
  793 #define db_simple_lock_try(l)           hw_lock_try(&((l)->interlock))
  794 #define db_simple_unlock(l)             hw_lock_unlock(&((l)->interlock))
  795 
  796 int                     kdb_cpu = -1;   /* current cpu running kdb      */
  797 int                     kdb_debug = 0;
  798 int                     kdb_is_slave[NCPUS];
  799 int                     kdb_active[NCPUS];
  800 volatile unsigned int   cpus_holding_bkpts;     /* counter for number of cpus holding
  801                                                    breakpoints (ie: cpus that did not
  802                                                    insert back breakpoints) */
  803 extern boolean_t        db_breakpoints_inserted;
  804 
  805 void
  806 db_machdep_init(void)
  807 {
  808         int c;
  809 
  810         db_simple_lock_init(&kdb_lock, ETAP_MISC_KDB);
  811         for (c = 0; c < NCPUS; ++c) {
  812                 db_stacks[c] = (vm_offset_t) (db_stack_store +
  813                         (INTSTACK_SIZE * (c + 1)) - sizeof (natural_t));
  814                 if (c == master_cpu) {
  815                         dbtss.esp0 = (int)(db_task_stack_store +
  816                                 (INTSTACK_SIZE * (c + 1)) - sizeof (natural_t));
  817                         dbtss.esp = dbtss.esp0;
  818                         dbtss.eip = (int)&db_task_start;
  819                         /*
  820                          * The TSS for the debugging task on each slave CPU
  821                          * is set up in mp_desc_init().
  822                          */
  823                 }
  824         }
  825 }
  826 
  827 /*
  828  * Called when entering kdb:
  829  * Takes kdb lock. If if we were called remotely (slave state) we just
  830  * wait for kdb_cpu to be equal to cpu_number(). Otherwise enter kdb if
  831  * not active on another cpu.
  832  * If db_pass_thru[cpu_number()] > 0, then kdb can't stop now.
  833  */
  834 
  835 int
  836 kdb_enter(int pc)
  837 {
  838         int my_cpu;
  839         int retval;
  840 
  841 #if     NCPUS > 1
  842         disable_preemption();
  843 #endif  /* NCPUS > 1 */
  844 
  845         my_cpu = cpu_number();
  846 
  847         if (db_pass_thru[my_cpu]) {
  848                 retval = 0;
  849                 goto kdb_exit;
  850         }
  851 
  852         kdb_active[my_cpu]++;
  853         lock_kdb();
  854 
  855         if (kdb_debug)
  856                 db_printf("kdb_enter: cpu %d, is_slave %d, kdb_cpu %d, run mode %d pc %x (%x) holds %d\n",
  857                           my_cpu, kdb_is_slave[my_cpu], kdb_cpu,
  858                           db_run_mode, pc, *(int *)pc, cpus_holding_bkpts);
  859         if (db_breakpoints_inserted)
  860                 cpus_holding_bkpts++;
  861         if (kdb_cpu == -1 && !kdb_is_slave[my_cpu]) {
  862                 kdb_cpu = my_cpu;
  863                 remote_kdb();   /* stop other cpus */
  864                 retval = 1;
  865         } else if (kdb_cpu == my_cpu) 
  866                 retval = 1;
  867         else
  868                 retval = 0;
  869 
  870 kdb_exit:
  871 #if     NCPUS > 1
  872         enable_preemption();
  873 #endif  /* NCPUS > 1 */
  874 
  875         return (retval);
  876 }
  877 
  878 void
  879 kdb_leave(void)
  880 {
  881         int my_cpu;
  882         boolean_t       wait = FALSE;
  883 
  884 #if     NCPUS > 1
  885         disable_preemption();
  886 #endif  /* NCPUS > 1 */
  887 
  888         my_cpu = cpu_number();
  889 
  890         if (db_run_mode == STEP_CONTINUE) {
  891                 wait = TRUE;
  892                 kdb_cpu = -1;
  893         }
  894         if (db_breakpoints_inserted)
  895                 cpus_holding_bkpts--;
  896         if (kdb_is_slave[my_cpu])
  897                 kdb_is_slave[my_cpu]--;
  898         if (kdb_debug)
  899                 db_printf("kdb_leave: cpu %d, kdb_cpu %d, run_mode %d pc %x (%x) holds %d\n",
  900                           my_cpu, kdb_cpu, db_run_mode,
  901                           ddb_regs.eip, *(int *)ddb_regs.eip,
  902                           cpus_holding_bkpts);
  903         clear_kdb_intr();
  904         unlock_kdb();
  905         kdb_active[my_cpu]--;
  906 
  907 #if     NCPUS > 1
  908         enable_preemption();
  909 #endif  /* NCPUS > 1 */
  910 
  911         if (wait) {
  912                 while(cpus_holding_bkpts);
  913         }
  914 }
  915 
  916 void
  917 lock_kdb(void)
  918 {
  919         int             my_cpu;
  920         register        i;
  921         extern void     kdb_console(void);
  922 
  923 #if     NCPUS > 1
  924         disable_preemption();
  925 #endif  /* NCPUS > 1 */
  926 
  927         my_cpu = cpu_number();
  928 
  929         for(;;) {
  930                 kdb_console();
  931                 if (kdb_cpu != -1 && kdb_cpu != my_cpu) {
  932                         continue;
  933                 }
  934                 if (db_simple_lock_try(&kdb_lock)) {
  935                         if (kdb_cpu == -1 || kdb_cpu == my_cpu)
  936                                 break;
  937                         db_simple_unlock(&kdb_lock);
  938                 }
  939         } 
  940 
  941 #if     NCPUS > 1
  942         enable_preemption();
  943 #endif  /* NCPUS > 1 */
  944 }
  945 
  946 #if     TIME_STAMP
  947 extern unsigned old_time_stamp;
  948 #endif  /* TIME_STAMP */
  949 
  950 void
  951 unlock_kdb(void)
  952 {
  953         db_simple_unlock(&kdb_lock);
  954 #if     TIME_STAMP
  955         old_time_stamp = 0;
  956 #endif  /* TIME_STAMP */
  957 }
  958 
  959 
  960 #ifdef  __STDC__
  961 #define KDB_SAVE(type, name) extern type name; type name##_save = name
  962 #define KDB_RESTORE(name) name = name##_save
  963 #else   /* __STDC__ */
  964 #define KDB_SAVE(type, name) extern type name; type name/**/_save = name
  965 #define KDB_RESTORE(name) name = name/**/_save
  966 #endif  /* __STDC__ */
  967 
  968 #define KDB_SAVE_CTXT() \
  969         KDB_SAVE(int, db_run_mode); \
  970         KDB_SAVE(boolean_t, db_sstep_print); \
  971         KDB_SAVE(int, db_loop_count); \
  972         KDB_SAVE(int, db_call_depth); \
  973         KDB_SAVE(int, db_inst_count); \
  974         KDB_SAVE(int, db_last_inst_count); \
  975         KDB_SAVE(int, db_load_count); \
  976         KDB_SAVE(int, db_store_count); \
  977         KDB_SAVE(boolean_t, db_cmd_loop_done); \
  978         KDB_SAVE(jmp_buf_t *, db_recover); \
  979         KDB_SAVE(db_addr_t, db_dot); \
  980         KDB_SAVE(db_addr_t, db_last_addr); \
  981         KDB_SAVE(db_addr_t, db_prev); \
  982         KDB_SAVE(db_addr_t, db_next); \
  983         KDB_SAVE(db_regs_t, ddb_regs); 
  984 
  985 #define KDB_RESTORE_CTXT() \
  986         KDB_RESTORE(db_run_mode); \
  987         KDB_RESTORE(db_sstep_print); \
  988         KDB_RESTORE(db_loop_count); \
  989         KDB_RESTORE(db_call_depth); \
  990         KDB_RESTORE(db_inst_count); \
  991         KDB_RESTORE(db_last_inst_count); \
  992         KDB_RESTORE(db_load_count); \
  993         KDB_RESTORE(db_store_count); \
  994         KDB_RESTORE(db_cmd_loop_done); \
  995         KDB_RESTORE(db_recover); \
  996         KDB_RESTORE(db_dot); \
  997         KDB_RESTORE(db_last_addr); \
  998         KDB_RESTORE(db_prev); \
  999         KDB_RESTORE(db_next); \
 1000         KDB_RESTORE(ddb_regs); 
 1001 
 1002 /*
 1003  * switch to another cpu
 1004  */
 1005 
 1006 void
 1007 kdb_on(
 1008         int             cpu)
 1009 {
 1010         KDB_SAVE_CTXT();
 1011         if (cpu < 0 || cpu >= NCPUS || !kdb_active[cpu])
 1012                 return;
 1013         db_set_breakpoints();
 1014         db_set_watchpoints();
 1015         kdb_cpu = cpu;
 1016         unlock_kdb();
 1017         lock_kdb();
 1018         db_clear_breakpoints();
 1019         db_clear_watchpoints();
 1020         KDB_RESTORE_CTXT();
 1021         if (kdb_cpu == -1)  {/* someone continued */
 1022                 kdb_cpu = cpu_number();
 1023                 db_continue_cmd(0, 0, 0, "");
 1024         }
 1025 }
 1026 
 1027 #endif  /* NCPUS > 1 */
 1028 
 1029 void db_reboot(
 1030         db_expr_t       addr,
 1031         boolean_t       have_addr,
 1032         db_expr_t       count,
 1033         char            *modif)
 1034 {
 1035         boolean_t       reboot = TRUE;
 1036         char            *cp, c;
 1037         
 1038         cp = modif;
 1039         while ((c = *cp++) != 0) {
 1040                 if (c == 'r')   /* reboot */
 1041                         reboot = TRUE;
 1042                 if (c == 'h')   /* halt */
 1043                         reboot = FALSE;
 1044         }
 1045         halt_all_cpus(reboot);
 1046 }

Cache object: 19bdad6322d174ee2d40d1e1dae80300


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