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/ppc/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 #include <cpus.h>
   30 #include <platforms.h>
   31 #include <time_stamp.h>
   32 #include <mach_mp_debug.h>
   33 #include <mach_ldebug.h>
   34 #include <db_machine_commands.h>
   35 
   36 #include <kern/spl.h>
   37 #include <kern/cpu_number.h>
   38 #include <kern/kern_types.h>
   39 #include <kern/misc_protos.h>
   40 #include <vm/pmap.h>
   41 
   42 #include <ppc/mem.h>
   43 #include <ppc/thread.h>
   44 #include <ppc/db_machdep.h>
   45 #include <ppc/trap.h>
   46 #include <ppc/setjmp.h>
   47 #include <ppc/pmap.h>
   48 #include <ppc/misc_protos.h>
   49 #include <ppc/exception.h>
   50 #include <ppc/db_machdep.h>
   51 #include <ppc/mappings.h>
   52 #include <ppc/Firmware.h>
   53 
   54 #include <mach/vm_param.h>
   55 #include <mach/machine/vm_types.h>
   56 #include <vm/vm_map.h>
   57 #include <kern/thread.h>
   58 #include <kern/task.h>
   59 #include <kern/debug.h>
   60 
   61 #include <ddb/db_command.h>
   62 #include <ddb/db_task_thread.h>
   63 #include <ddb/db_run.h>
   64 #include <ddb/db_trap.h>
   65 #include <ddb/db_output.h>
   66 #include <ddb/db_access.h>
   67 #include <ddb/db_sym.h>
   68 #include <ddb/db_break.h>
   69 #include <ddb/db_watch.h>
   70 
   71 struct   savearea *ppc_last_saved_statep;
   72 struct   savearea ppc_nested_saved_state;
   73 unsigned ppc_last_kdb_sp;
   74 
   75 extern int debugger_active[NCPUS];              /* Debugger active on CPU */
   76 extern int debugger_cpu;                                /* Current cpu running debugger */
   77 
   78 int             db_all_set_up = 0;
   79 
   80 
   81 #if !MACH_KDP
   82 void kdp_register_send_receive(void);
   83 #endif
   84 
   85 /*
   86  *      Enter KDB through a keyboard trap.
   87  *      We show the registers as of the keyboard interrupt
   88  *      instead of those at its call to KDB.
   89  */
   90 struct int_regs {
   91         /* XXX more registers ? */
   92         struct ppc_interrupt_state *is;
   93 };
   94 
   95 extern char *   trap_type[];
   96 extern int      TRAP_TYPES;
   97 
   98 /*
   99  * Code used to synchronize kdb among all cpus, one active at a time, switch
  100  * from on to another using kdb_on! #cpu or cpu #cpu
  101  */
  102 
  103 decl_simple_lock_data(, kdb_lock)       /* kdb lock                     */
  104 
  105 #define db_simple_lock_init(l, e)       hw_lock_init(&((l)->interlock))
  106 #define db_simple_lock_try(l)           hw_lock_try(&((l)->interlock))
  107 #define db_simple_unlock(l)             hw_lock_unlock(&((l)->interlock))
  108 
  109 extern volatile unsigned int    cpus_holding_bkpts;     /* counter for number of cpus holding
  110                                                    breakpoints (ie: cpus that did not
  111                                                    insert back breakpoints) */
  112 extern boolean_t        db_breakpoints_inserted;
  113 
  114 /* Forward */
  115 
  116 extern void     kdbprinttrap(
  117                         int                     type,
  118                         int                     code,
  119                         int                     *pc,
  120                         int                     sp);
  121 extern void     db_write_bytes_user_space(
  122                         vm_offset_t             addr,
  123                         int                     size,
  124                         char                    *data,
  125                         task_t                  task);
  126 extern int      db_search_null(
  127                         task_t                  task,
  128                         unsigned                *svaddr,
  129                         unsigned                evaddr,
  130                         unsigned                *skaddr,
  131                         int                     flag);
  132 extern int      kdb_enter(int);
  133 extern void     kdb_leave(void);
  134 extern void     lock_kdb(void);
  135 extern void     unlock_kdb(void);
  136 
  137 #if DB_MACHINE_COMMANDS
  138 struct db_command       ppc_db_commands[] = {
  139         { "lt",         db_low_trace,   CS_MORE|CS_SET_DOT,     0 },
  140         { (char *)0,    0,              0,                      0 }
  141 };
  142 #endif /* DB_MACHINE_COMMANDS */
  143 
  144 #if !MACH_KDP
  145 void kdp_register_send_receive(void) {}
  146 #endif
  147 
  148 extern jmp_buf_t *db_recover;
  149 spl_t   saved_ipl[NCPUS];       /* just to know what IPL was before trap */
  150 struct savearea *saved_state[NCPUS];
  151 
  152 /*
  153  *  kdb_trap - field a TRACE or BPT trap
  154  */
  155 void
  156 kdb_trap(
  157         int                     type,
  158         struct savearea *regs)
  159 {
  160         boolean_t       trap_from_user;
  161         int                     previous_console_device;
  162         int                     code=0;
  163 
  164         previous_console_device=switch_to_serial_console();
  165 
  166         switch (type) {
  167             case T_TRACE:       /* single_step */
  168             case T_PROGRAM:     /* breakpoint */
  169 #if 0
  170             case T_WATCHPOINT:  /* watchpoint */
  171 #endif
  172             case -1:    /* keyboard interrupt */
  173                 break;
  174 
  175             default:
  176                 if (db_recover) {
  177                     ppc_nested_saved_state = *regs;
  178                     db_printf("Caught ");
  179                     if (type > TRAP_TYPES)
  180                         db_printf("type %d", type);
  181                     else
  182                         db_printf("%s", trap_type[type]);
  183                     db_printf(" trap, pc = %x\n",
  184                               regs->save_srr0);
  185                     db_error("");
  186                     /*NOTREACHED*/
  187                 }
  188                 kdbprinttrap(type, code, (int *)&regs->save_srr0, regs->save_r1);
  189         }
  190 
  191         saved_state[cpu_number()] = regs;
  192 
  193         ppc_last_saved_statep = regs;
  194         ppc_last_kdb_sp = (unsigned) &type;
  195 
  196         if (!IS_USER_TRAP(regs)) {
  197                 bzero((char *)&ddb_regs, sizeof (ddb_regs));
  198                 ddb_regs = *regs;
  199                 trap_from_user = FALSE; 
  200 
  201         }
  202         else {
  203                 ddb_regs = *regs;
  204                 trap_from_user = TRUE;
  205         }
  206 
  207         db_task_trap(type, code, trap_from_user);
  208 
  209         *regs = ddb_regs;
  210 
  211         if ((type == T_PROGRAM) &&
  212             (db_get_task_value(regs->save_srr0,
  213                                BKPT_SIZE,
  214                                FALSE,
  215                                db_target_space(current_act(),
  216                                                trap_from_user))
  217                               == BKPT_INST))
  218             regs->save_srr0 += BKPT_SIZE;
  219 
  220 kdb_exit:
  221         saved_state[cpu_number()] = 0;
  222         switch_to_old_console(previous_console_device);
  223 
  224 }
  225 
  226 
  227 /*
  228  * Print trap reason.
  229  */
  230 
  231 void
  232 kdbprinttrap(
  233         int     type,
  234         int     code,
  235         int     *pc,
  236         int     sp)
  237 {
  238         printf("kernel: ");
  239         if (type > TRAP_TYPES)
  240             db_printf("type %d", type);
  241         else
  242             db_printf("%s", trap_type[type]);
  243         db_printf(" trap, code=%x pc@%x = %x sp=%x\n",
  244                   code, pc, *(int *)pc, sp);
  245         db_run_mode = STEP_CONTINUE;
  246 }
  247 
  248 /*
  249  *
  250  */
  251 addr64_t db_vtophys(
  252         pmap_t pmap,
  253         vm_offset_t va)
  254 {
  255         ppnum_t pp;
  256         addr64_t pa;
  257 
  258         pp = pmap_find_phys(pmap, (addr64_t)va);
  259 
  260         if (pp == 0) return(0);                                 /* Couldn't find it */
  261         
  262         pa = ((addr64_t)pp << 12) | (addr64_t)(va & 0xFFF);     /* Get physical address */
  263 
  264         return(pa);
  265 }
  266 
  267 /*
  268  * Read bytes from task address space for debugger.
  269  */
  270 void
  271 db_read_bytes(
  272         vm_offset_t     addr,
  273         int             size,
  274         char            *data,
  275         task_t          task)
  276 {
  277         int             n,max;
  278         addr64_t        phys_dst;
  279         addr64_t        phys_src;
  280         pmap_t  pmap;
  281         
  282         while (size > 0) {
  283                 if (task != NULL)
  284                         pmap = task->map->pmap;
  285                 else
  286                         pmap = kernel_pmap;
  287 
  288                 phys_src = db_vtophys(pmap, (vm_offset_t)addr);  
  289                 if (phys_src == 0) {
  290                         db_printf("\nno memory is assigned to src address %08x\n",
  291                                   addr);
  292                         db_error(0);
  293                         /* NOTREACHED */
  294                 }
  295 
  296                 phys_dst = db_vtophys(kernel_pmap, (vm_offset_t)data); 
  297                 if (phys_dst == 0) {
  298                         db_printf("\nno memory is assigned to dst address %08x\n",
  299                                   data);
  300                         db_error(0);
  301                         /* NOTREACHED */
  302                 }
  303                 
  304                 /* don't over-run any page boundaries - check src range */
  305                 max = round_page_64(phys_src + 1) - phys_src;
  306                 if (max > size)
  307                         max = size;
  308                 /* Check destination won't run over boundary either */
  309                 n = round_page_64(phys_dst + 1) - phys_dst;
  310                 
  311                 if (n < max) max = n;
  312                 size -= max;
  313                 addr += max;
  314                 phys_copy(phys_src, phys_dst, max);
  315 
  316                 /* resync I+D caches */
  317                 sync_cache64(phys_dst, max);
  318 
  319                 phys_src += max;
  320                 phys_dst += max;
  321         }
  322 }
  323 
  324 /*
  325  * Write bytes to task address space for debugger.
  326  */
  327 void
  328 db_write_bytes(
  329         vm_offset_t     addr,
  330         int             size,
  331         char            *data,
  332         task_t          task)
  333 {
  334         int             n,max;
  335         addr64_t        phys_dst;
  336         addr64_t        phys_src;
  337         pmap_t  pmap;
  338         
  339         while (size > 0) {
  340 
  341                 phys_src = db_vtophys(kernel_pmap, (vm_offset_t)data); 
  342                 if (phys_src == 0) {
  343                         db_printf("\nno memory is assigned to src address %08x\n",
  344                                   data);
  345                         db_error(0);
  346                         /* NOTREACHED */
  347                 }
  348                 
  349                 /* space stays as kernel space unless in another task */
  350                 if (task == NULL) pmap = kernel_pmap;
  351                 else pmap = task->map->pmap;
  352 
  353                 phys_dst = db_vtophys(pmap, (vm_offset_t)addr);  
  354                 if (phys_dst == 0) {
  355                         db_printf("\nno memory is assigned to dst address %08x\n",
  356                                   addr);
  357                         db_error(0);
  358                         /* NOTREACHED */
  359                 }
  360 
  361                 /* don't over-run any page boundaries - check src range */
  362                 max = round_page_64(phys_src + 1) - phys_src;
  363                 if (max > size)
  364                         max = size;
  365                 /* Check destination won't run over boundary either */
  366                 n = round_page_64(phys_dst + 1) - phys_dst;
  367                 if (n < max)
  368                         max = n;
  369                 size -= max;
  370                 addr += max;
  371                 phys_copy(phys_src, phys_dst, max);
  372 
  373                 /* resync I+D caches */
  374                 sync_cache64(phys_dst, max);
  375 
  376                 phys_src += max;
  377                 phys_dst += max;
  378         }
  379 }
  380         
  381 boolean_t
  382 db_check_access(
  383         vm_offset_t     addr,
  384         int             size,
  385         task_t          task)
  386 {
  387         register int    n;
  388         unsigned int    kern_addr;
  389 
  390         if (task == kernel_task || task == TASK_NULL) {
  391             if (kernel_task == TASK_NULL)  return(TRUE);
  392             task = kernel_task;
  393         } else if (task == TASK_NULL) {
  394             if (current_act() == THR_ACT_NULL) return(FALSE);
  395             task = current_act()->task;
  396         }
  397 
  398         while (size > 0) {
  399                 if(!pmap_find_phys(task->map->pmap, (addr64_t)addr)) return (FALSE);    /* Fail if page not mapped */
  400             n = trunc_page_32(addr+PPC_PGBYTES) - addr;
  401             if (n > size)
  402                 n = size;
  403             size -= n;
  404             addr += n;
  405         }
  406         return(TRUE);
  407 }
  408 
  409 boolean_t
  410 db_phys_eq(
  411         task_t          task1,
  412         vm_offset_t     addr1,
  413         task_t          task2,
  414         vm_offset_t     addr2)
  415 {
  416         addr64_t        physa, physb;
  417 
  418         if ((addr1 & (PPC_PGBYTES-1)) != (addr2 & (PPC_PGBYTES-1)))     /* Is byte displacement the same? */
  419                 return FALSE;
  420 
  421         if (task1 == TASK_NULL) {                                               /* See if there is a task active */
  422                 if (current_act() == THR_ACT_NULL)                      /* See if there is a current task */
  423                         return FALSE;
  424                 task1 = current_act()->task;                            /* If so, use that one */
  425         }
  426         
  427         if(!(physa = db_vtophys(task1->map->pmap, (vm_offset_t)trunc_page_32(addr1)))) return FALSE;    /* Get real address of the first */
  428         if(!(physb = db_vtophys(task2->map->pmap, (vm_offset_t)trunc_page_32(addr2)))) return FALSE;    /* Get real address of the second */
  429         
  430         return (physa == physb);                                                /* Check if they are equal, then return... */
  431 }
  432 
  433 #define DB_USER_STACK_ADDR              (0xc0000000)
  434 #define DB_NAME_SEARCH_LIMIT            (DB_USER_STACK_ADDR-(PPC_PGBYTES*3))
  435 
  436 boolean_t       db_phys_cmp(
  437                                 vm_offset_t a1, 
  438                                 vm_offset_t a2, 
  439                                 vm_size_t s1) {
  440 
  441         db_printf("db_phys_cmp: not implemented\n");
  442         return 0;
  443 }
  444 
  445 
  446 int
  447 db_search_null(
  448         task_t          task,
  449         unsigned        *svaddr,
  450         unsigned        evaddr,
  451         unsigned        *skaddr,
  452         int             flag)
  453 {
  454         register unsigned vaddr;
  455         register unsigned *kaddr;
  456 
  457         db_printf("db_search_null: not implemented\n");
  458 
  459         return(-1);
  460 }
  461 
  462 unsigned char *getProcName(struct proc *proc);
  463 
  464 void
  465 db_task_name(
  466         task_t          task)
  467 {
  468         register unsigned char *p;
  469         register int n;
  470         unsigned int vaddr, kaddr;
  471         unsigned char tname[33];
  472         int i;
  473 
  474         p = 0;
  475         tname[0] = 0;
  476         
  477         if(task->bsd_info) p = getProcName((struct proc *)(task->bsd_info));    /* Point to task name */
  478         
  479         if(p) {
  480                 for(i = 0; i < 32; i++) {                       /* Move no more than 32 bytes */
  481                         tname[i] = p[i];
  482                         if(p[i] == 0) break;
  483                 }
  484                 tname[i] = 0;
  485                 db_printf("%s", tname);
  486         }
  487         else db_printf("no name");
  488 }
  489 
  490 void
  491 db_machdep_init(void) {
  492 #define KDB_READY       0x1
  493         extern int     kdb_flag;  
  494 
  495         kdb_flag |= KDB_READY;
  496 }
  497 
  498 
  499 #ifdef  __STDC__
  500 #define KDB_SAVE(type, name) extern type name; type name##_save = name
  501 #define KDB_RESTORE(name) name = name##_save
  502 #else   /* __STDC__ */
  503 #define KDB_SAVE(type, name) extern type name; type name/**/_save = name
  504 #define KDB_RESTORE(name) name = name/**/_save
  505 #endif  /* __STDC__ */
  506 
  507 #define KDB_SAVE_CTXT() \
  508         KDB_SAVE(int, db_run_mode); \
  509         KDB_SAVE(boolean_t, db_sstep_print); \
  510         KDB_SAVE(int, db_loop_count); \
  511         KDB_SAVE(int, db_call_depth); \
  512         KDB_SAVE(int, db_inst_count); \
  513         KDB_SAVE(int, db_last_inst_count); \
  514         KDB_SAVE(int, db_load_count); \
  515         KDB_SAVE(int, db_store_count); \
  516         KDB_SAVE(boolean_t, db_cmd_loop_done); \
  517         KDB_SAVE(jmp_buf_t *, db_recover); \
  518         KDB_SAVE(db_addr_t, db_dot); \
  519         KDB_SAVE(db_addr_t, db_last_addr); \
  520         KDB_SAVE(db_addr_t, db_prev); \
  521         KDB_SAVE(db_addr_t, db_next); \
  522         KDB_SAVE(db_regs_t, ddb_regs); 
  523 
  524 #define KDB_RESTORE_CTXT() \
  525         KDB_RESTORE(db_run_mode); \
  526         KDB_RESTORE(db_sstep_print); \
  527         KDB_RESTORE(db_loop_count); \
  528         KDB_RESTORE(db_call_depth); \
  529         KDB_RESTORE(db_inst_count); \
  530         KDB_RESTORE(db_last_inst_count); \
  531         KDB_RESTORE(db_load_count); \
  532         KDB_RESTORE(db_store_count); \
  533         KDB_RESTORE(db_cmd_loop_done); \
  534         KDB_RESTORE(db_recover); \
  535         KDB_RESTORE(db_dot); \
  536         KDB_RESTORE(db_last_addr); \
  537         KDB_RESTORE(db_prev); \
  538         KDB_RESTORE(db_next); \
  539         KDB_RESTORE(ddb_regs); 
  540 
  541 /*
  542  * switch to another cpu
  543  */
  544 void
  545 kdb_on(
  546         int             cpu)
  547 {
  548         KDB_SAVE_CTXT();
  549         if (cpu < 0 || cpu >= NCPUS || !debugger_active[cpu])
  550                 return;
  551         db_set_breakpoints();
  552         db_set_watchpoints();
  553         debugger_cpu = cpu;
  554         unlock_debugger();
  555         lock_debugger();
  556         db_clear_breakpoints();
  557         db_clear_watchpoints();
  558         KDB_RESTORE_CTXT();
  559         if (debugger_cpu == -1)  {/* someone continued */
  560                 debugger_cpu = cpu_number();
  561                 db_continue_cmd(0, 0, 0, "");
  562         }
  563 }
  564 
  565 /*
  566  * system reboot
  567  */
  568 void db_reboot(
  569         db_expr_t       addr,
  570         boolean_t       have_addr,
  571         db_expr_t       count,
  572         char            *modif)
  573 {
  574         boolean_t       reboot = TRUE;
  575         char            *cp, c;
  576         
  577         cp = modif;
  578         while ((c = *cp++) != 0) {
  579                 if (c == 'r')   /* reboot */
  580                         reboot = TRUE;
  581                 if (c == 'h')   /* halt */
  582                         reboot = FALSE;
  583         }
  584         halt_all_cpus(reboot);
  585 }
  586 
  587 /*
  588  * Switch to gdb
  589  */
  590 void
  591 db_to_gdb(
  592         void)
  593 {
  594         extern unsigned int switch_debugger;
  595 
  596         switch_debugger=1;
  597 }

Cache object: 7754822a9447ec1057cd8ab9359507a7


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