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/model_dep.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  * @APPLE_FREE_COPYRIGHT@
   30  */
   31 /*
   32  *  (c) Copyright 1988 HEWLETT-PACKARD COMPANY
   33  *
   34  *  To anyone who acknowledges that this file is provided "AS IS"
   35  *  without any express or implied warranty:
   36  *      permission to use, copy, modify, and distribute this file
   37  *  for any purpose is hereby granted without fee, provided that
   38  *  the above copyright notice and this notice appears in all
   39  *  copies, and that the name of Hewlett-Packard Company not be
   40  *  used in advertising or publicity pertaining to distribution
   41  *  of the software without specific, written prior permission.
   42  *  Hewlett-Packard Company makes no representations about the
   43  *  suitability of this software for any purpose.
   44  */
   45 /*
   46  * Copyright (c) 1990,1991,1992,1994 The University of Utah and
   47  * the Computer Systems Laboratory (CSL).  All rights reserved.
   48  *
   49  * THE UNIVERSITY OF UTAH AND CSL PROVIDE THIS SOFTWARE IN ITS "AS IS"
   50  * CONDITION, AND DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES
   51  * WHATSOEVER RESULTING FROM ITS USE.
   52  *
   53  * CSL requests users of this software to return to csl-dist@cs.utah.edu any
   54  * improvements that they make and grant CSL redistribution rights.
   55  *
   56  *      Utah $Hdr: model_dep.c 1.34 94/12/14$
   57  */
   58 
   59 #include <debug.h>
   60 #include <mach_kdb.h>
   61 #include <mach_kdp.h>
   62 #include <db_machine_commands.h>
   63 #include <cpus.h>
   64 
   65 #include <kern/thread.h>
   66 #include <machine/pmap.h>
   67 #include <machine/mach_param.h>
   68 #include <device/device_types.h>
   69 
   70 #include <mach/vm_param.h>
   71 #include <mach/clock_types.h>
   72 #include <mach/machine.h>
   73 #include <mach/kmod.h>
   74 #include <ppc/boot.h>
   75 
   76 #include <kern/misc_protos.h>
   77 #include <kern/startup.h>
   78 #include <ppc/misc_protos.h>
   79 #include <ppc/proc_reg.h>
   80 #include <ppc/thread.h>
   81 #include <ppc/asm.h>
   82 #include <ppc/mem.h>
   83 #include <ppc/Firmware.h>
   84 #include <ppc/low_trace.h>
   85 #include <ppc/mappings.h>
   86 #include <ppc/FirmwareCalls.h>
   87 #include <ppc/setjmp.h>
   88 #include <ppc/exception.h>
   89 #include <ppc/hw_perfmon.h>
   90 
   91 #include <kern/clock.h>
   92 #include <kern/debug.h>
   93 #include <machine/trap.h>
   94 #include <kern/spl.h>
   95 #include <pexpert/pexpert.h>
   96 #include <ppc/mp.h>
   97 
   98 #include <IOKit/IOPlatformExpert.h>
   99 
  100 #include <mach/vm_prot.h>
  101 #include <vm/pmap.h>
  102 #include <mach/time_value.h>
  103 #include <machine/machparam.h>  /* for btop */
  104 
  105 #if     MACH_KDB
  106 #include <ddb/db_aout.h>
  107 #include <ddb/db_output.h>
  108 #include <ddb/db_command.h>
  109 #include <machine/db_machdep.h>
  110 
  111 extern struct db_command ppc_db_commands[];
  112 #endif  /* MACH_KDB */
  113 
  114 char kernel_args_buf[256] = "/mach_kernel";
  115 char boot_args_buf[256] = "/mach_servers/bootstrap";
  116 char env_buf[256];
  117 
  118 #define TRAP_DEBUGGER   __asm__ volatile("tw 4,r3,r3");
  119 #define TRAP_DEBUGGER_INST      0x7c831808
  120 #define TRAP_DIRECT     __asm__ volatile("tw 4,r4,r4");
  121 #define TRAP_DIRECT_INST        0x7c842008
  122 #define TRAP_INST_SIZE  4
  123 #define BREAK_TO_KDP0 0x7fe00008
  124 #define BREAK_TO_KDP1 0x7c800008
  125 #define BREAK_TO_KDB0 0x7c810808
  126 
  127 /*
  128  * Code used to synchronize debuggers among all cpus, one active at a time, switch
  129  * from on to another using kdb_on! #cpu or cpu #cpu
  130  */
  131 
  132 hw_lock_data_t debugger_lock;   /* debugger lock */
  133 hw_lock_data_t pbtlock;         /* backtrace print lock */
  134 
  135 int                     debugger_cpu = -1;                      /* current cpu running debugger */
  136 int                     debugger_debug = 0;                     /* Debug debugger */
  137 int                     debugger_is_slave[NCPUS];       /* Show that we were entered via sigp */
  138 int                     debugger_active[NCPUS];         /* Debugger active on CPU */
  139 int                     debugger_pending[NCPUS];        /* Debugger entry pending on CPU (this is a HACK) */
  140 int                     debugger_holdoff[NCPUS];        /* Holdoff debugger entry on this CPU (this is a HACK) */
  141 int             db_run_mode;                            /* Debugger run mode */
  142 unsigned int debugger_sync = 0;                 /* Cross processor debugger entry sync */
  143 extern          unsigned int NMIss;                     /* NMI debounce switch */
  144 
  145 extern volatile int panicwait;
  146 volatile unsigned int pbtcnt = 0;
  147 volatile unsigned int pbtcpu = -1;
  148 
  149 unsigned int lastTrace;                                 /* Value of low-level exception trace controls */
  150 
  151 volatile unsigned int   cpus_holding_bkpts;     /* counter for number of cpus holding
  152                                                                                            breakpoints (ie: cpus that did not
  153                                                                                            insert back breakpoints) */
  154 void unlock_debugger(void);
  155 void lock_debugger(void);
  156 void dump_backtrace(unsigned int stackptr, unsigned int fence);
  157 void dump_savearea(savearea *sv, unsigned int fence);
  158 
  159 int packAsc (unsigned char *inbuf, unsigned int length);
  160 
  161 #if !MACH_KDB
  162 boolean_t       db_breakpoints_inserted = TRUE;
  163 jmp_buf_t *db_recover = 0;
  164 #endif
  165 
  166 #if     MACH_KDB
  167 #include <ddb/db_run.h>
  168 int     kdb_flag=0;
  169 extern boolean_t db_breakpoints_inserted;
  170 extern jmp_buf_t *db_recover;
  171 #define KDB_READY       0x1
  172 #endif
  173 
  174 #if     MACH_KDP
  175 extern int      kdp_flag;
  176 #define KDP_READY       0x1
  177 #endif
  178 
  179 boolean_t db_im_stepping = 0xFFFFFFFF;  /* Remember if we were stepping */
  180 
  181 
  182 char *failNames[] = {   
  183 
  184         "Debugging trap",                       /* failDebug */
  185         "Corrupt stack",                        /* failStack */
  186         "Corrupt mapping tables",       /* failMapping */
  187         "Corrupt context",                      /* failContext */
  188         "No saveareas",                         /* failNoSavearea */
  189         "Savearea corruption",          /* failSaveareaCorr */
  190         "Invalid live context",         /* failBadLiveContext */
  191         "Unaligned stack",                      /* failUnalignedStk */
  192         "Unknown failure code"          /* Unknown failure code - must always be last */
  193 };
  194 
  195 char *invxcption = "Unknown code";
  196 
  197 extern const char version[];
  198 extern char *trap_type[];
  199 
  200 #if !MACH_KDB
  201 void kdb_trap(int type, struct savearea *regs);
  202 void kdb_trap(int type, struct savearea *regs) {
  203         return;
  204 }
  205 #endif
  206 
  207 #if !MACH_KDP
  208 void kdp_trap(int type, struct savearea *regs);
  209 void kdp_trap(int type, struct savearea *regs) {
  210         return;
  211 }
  212 #endif
  213 
  214 void
  215 machine_startup(boot_args *args)
  216 {
  217         int     boot_arg;
  218 
  219         if (PE_parse_boot_arg("cpus", &wncpu)) {
  220                 if (!((wncpu > 0) && (wncpu < NCPUS)))
  221                         wncpu = NCPUS;
  222         } else 
  223                 wncpu = NCPUS;
  224 
  225         if( PE_get_hotkey( kPEControlKey ))
  226             halt_in_debugger = halt_in_debugger ? 0 : 1;
  227 
  228         if (PE_parse_boot_arg("debug", &boot_arg)) {
  229                 if (boot_arg & DB_HALT) halt_in_debugger=1;
  230                 if (boot_arg & DB_PRT) disableDebugOuput=FALSE; 
  231                 if (boot_arg & DB_SLOG) systemLogDiags=TRUE; 
  232                 if (boot_arg & DB_NMI) panicDebugging=TRUE; 
  233                 if (boot_arg & DB_LOG_PI_SCRN) logPanicDataToScreen=TRUE; 
  234         }
  235 
  236         hw_lock_init(&debugger_lock);                           /* initialize debugger lock */
  237         hw_lock_init(&pbtlock);                                         /* initialize print backtrace lock */
  238 
  239 #if     MACH_KDB
  240         /*
  241          * Initialize KDB
  242          */
  243 #if     DB_MACHINE_COMMANDS
  244         db_machine_commands_install(ppc_db_commands);
  245 #endif  /* DB_MACHINE_COMMANDS */
  246         ddb_init();
  247 
  248         if (boot_arg & DB_KDB)
  249                 current_debugger = KDB_CUR_DB;
  250 
  251         /*
  252          * Cause a breakpoint trap to the debugger before proceeding
  253          * any further if the proper option bit was specified in
  254          * the boot flags.
  255          */
  256         if (halt_in_debugger && (current_debugger == KDB_CUR_DB)) {
  257                 Debugger("inline call to debugger(machine_startup)");
  258                 halt_in_debugger = 0;
  259                 active_debugger =1;
  260         }
  261 #endif /* MACH_KDB */
  262         if (PE_parse_boot_arg("preempt", &boot_arg)) {
  263                 extern int default_preemption_rate;
  264 
  265                 default_preemption_rate = boot_arg;
  266         }
  267         if (PE_parse_boot_arg("unsafe", &boot_arg)) {
  268                 extern int max_unsafe_quanta;
  269 
  270                 max_unsafe_quanta = boot_arg;
  271         }
  272         if (PE_parse_boot_arg("poll", &boot_arg)) {
  273                 extern int max_poll_quanta;
  274 
  275                 max_poll_quanta = boot_arg;
  276         }
  277         if (PE_parse_boot_arg("yield", &boot_arg)) {
  278                 extern int sched_poll_yield_shift;
  279 
  280                 sched_poll_yield_shift = boot_arg;
  281         }
  282         if (PE_parse_boot_arg("refunn", &boot_arg)) {
  283                 extern int refunnel_hint_enabled;
  284 
  285                 refunnel_hint_enabled = boot_arg;
  286         }
  287 
  288         machine_conf();
  289 
  290         ml_thrm_init();                                                 /* Start thermal monitoring on this processor */
  291 
  292         /*
  293          * Start the system.
  294          */
  295         setup_main();
  296 
  297         /* Should never return */
  298 }
  299 
  300 char *
  301 machine_boot_info(
  302         char *buf, 
  303         vm_size_t size)
  304 {
  305         return(PE_boot_args());
  306 }
  307 
  308 void
  309 machine_conf(void)
  310 {
  311         machine_info.max_cpus = NCPUS;
  312         machine_info.avail_cpus = 1;
  313         machine_info.memory_size = mem_size;    /* Note that this will be 2 GB for >= 2 GB machines */
  314 }
  315 
  316 void
  317 machine_init(void)
  318 {
  319         clock_config();
  320         perfmon_init();
  321 }
  322 
  323 void slave_machine_init(void)
  324 {
  325         (void) ml_set_interrupts_enabled(FALSE);        /* Make sure we are disabled */
  326         clock_init();                           /* Init the clock */
  327         cpu_machine_init();                     /* Initialize the processor */
  328 }                               
  329 
  330 void
  331 halt_all_cpus(boolean_t reboot)
  332 {
  333         if(reboot)
  334         {
  335                 printf("MACH Reboot\n");
  336                 PEHaltRestart(kPERestartCPU);
  337         }
  338         else
  339         {
  340                 printf("CPU halted\n");
  341                 PEHaltRestart(kPEHaltCPU);
  342         } 
  343         while(1);
  344 }
  345 
  346 void
  347 halt_cpu(void)
  348 {
  349         halt_all_cpus(FALSE);
  350 }
  351 
  352 #if     MACH_ASSERT
  353 /*
  354  * Machine-dependent routine to fill in an array with up to callstack_max
  355  * levels of return pc information.
  356  */
  357 void machine_callstack(
  358         natural_t       *buf,
  359         vm_size_t       callstack_max)
  360 {
  361 }
  362 #endif  /* MACH_ASSERT */
  363 
  364 
  365 void
  366 print_backtrace(struct savearea *ssp)
  367 {
  368         unsigned int stackptr, *raddr, *rstack, trans, fence;
  369         int i, frames_cnt, skip_top_frames, frames_max;
  370         unsigned int store[8];                  /* Buffer for real storage reads */
  371         vm_offset_t backtrace_entries[32];
  372         thread_act_t *act;
  373         savearea *sv, *svssp;
  374         int cpu;
  375         savearea *psv;
  376 
  377 /*
  378  *      We need this lock to make sure we don't hang up when we double panic on an MP.
  379  */
  380 
  381         cpu  = cpu_number();                                    /* Just who are we anyways? */
  382         if(pbtcpu != cpu) {                                             /* Allow recursion */
  383                 hw_atomic_add((uint32_t *)&pbtcnt, 1); /* Remember we are trying */
  384                 while(!hw_lock_try(&pbtlock));          /* Spin here until we can get in. If we never do, well, we're crashing anyhow... */     
  385                 pbtcpu = cpu;                                           /* Mark it as us */     
  386         }       
  387 
  388         svssp = (savearea *)ssp;                                /* Make this easier */
  389         sv = 0;
  390         if(current_thread()) sv = (savearea *)current_act()->mact.pcb;  /* Find most current savearea if system has started */
  391 
  392         fence = 0xFFFFFFFF;                                             /* Show we go all the way */
  393         if(sv) fence = (unsigned int)sv->save_r1;       /* Stop at previous exception point */
  394         
  395         if(!svssp) {                                                    /* Should we start from stack? */
  396                 kdb_printf("Latest stack backtrace for cpu %d:\n", cpu_number());
  397                 __asm__ volatile("mr %0,r1" : "=r" (stackptr)); /* Get current stack */
  398                 dump_backtrace(stackptr, fence);        /* Dump the backtrace */
  399                 if(!sv) {                                                       /* Leave if no saveareas */
  400                         kdb_printf("\nKernel version:\n%s\n",version);  /* Print kernel version */
  401                         hw_lock_unlock(&pbtlock);               /* Allow another back trace to happen */
  402                         return; 
  403                 }
  404         }
  405         else {                                                                  /* Were we passed an exception? */
  406                 fence = 0xFFFFFFFF;                                     /* Show we go all the way */
  407                 if(svssp->save_hdr.save_prev) {
  408                         if((svssp->save_hdr.save_prev <= vm_last_addr) && ((unsigned int)pmap_find_phys(kernel_pmap, (addr64_t)svssp->save_hdr.save_prev))) {   /* Valid address? */    
  409                                 psv = (savearea *)((unsigned int)svssp->save_hdr.save_prev);    /* Get the 64-bit back chain converted to a regualr pointer */
  410                                 fence = (unsigned int)psv->save_r1;     /* Stop at previous exception point */
  411                         }
  412                 }
  413         
  414                 kdb_printf("Latest crash info for cpu %d:\n", cpu_number());
  415                 kdb_printf("   Exception state (sv=0x%08X)\n", sv);
  416                 dump_savearea(svssp, fence);            /* Dump this savearea */        
  417         }
  418 
  419         if(!sv) {                                                               /* Leave if no saveareas */
  420                 kdb_printf("\nKernel version:\n%s\n",version);  /* Print kernel version */
  421                 hw_lock_unlock(&pbtlock);                       /* Allow another back trace to happen */
  422                 return; 
  423         }
  424         
  425         kdb_printf("Proceeding back via exception chain:\n");
  426 
  427         while(sv) {                                                             /* Do them all... */
  428                 if(!(((addr64_t)((uintptr_t)sv) <= vm_last_addr) && 
  429                         (unsigned int)pmap_find_phys(kernel_pmap, (addr64_t)((uintptr_t)sv)))) {        /* Valid address? */    
  430                         kdb_printf("   Exception state (sv=0x%08X) Not mapped or invalid. stopping...\n", sv);
  431                         break;
  432                 }
  433                 
  434                 kdb_printf("   Exception state (sv=0x%08X)\n", sv);
  435                 if(sv == svssp) {                                       /* Did we dump it already? */
  436                         kdb_printf("      previously dumped as \"Latest\" state. skipping...\n");
  437                 }
  438                 else {
  439                         fence = 0xFFFFFFFF;                             /* Show we go all the way */
  440                         if(sv->save_hdr.save_prev) {
  441                                 if((sv->save_hdr.save_prev <= vm_last_addr) && ((unsigned int)pmap_find_phys(kernel_pmap, (addr64_t)sv->save_hdr.save_prev))) { /* Valid address? */    
  442                                         psv = (savearea *)((unsigned int)sv->save_hdr.save_prev);       /* Get the 64-bit back chain converted to a regualr pointer */
  443                                         fence = (unsigned int)psv->save_r1;     /* Stop at previous exception point */
  444                                 }
  445                         }
  446                         dump_savearea(sv, fence);               /* Dump this savearea */        
  447                 }       
  448                 
  449                 sv = CAST_DOWN(savearea *, sv->save_hdr.save_prev);     /* Back chain */ 
  450         }
  451         
  452         kdb_printf("\nKernel version:\n%s\n",version);  /* Print kernel version */
  453 
  454         pbtcpu = -1;                                                    /* Mark as unowned */
  455         hw_lock_unlock(&pbtlock);                               /* Allow another back trace to happen */
  456         hw_atomic_sub((uint32_t *) &pbtcnt, 1);  /* Show we are done */
  457 
  458         while(pbtcnt);                                                  /* Wait for completion */
  459 
  460         return;
  461 }
  462 
  463 void dump_savearea(savearea *sv, unsigned int fence) {
  464 
  465         char *xcode;
  466         
  467         if(sv->save_exception > T_MAX) xcode = invxcption;      /* Too big for table */
  468         else xcode = trap_type[sv->save_exception / 4];         /* Point to the type */
  469         
  470         kdb_printf("      PC=0x%08X; MSR=0x%08X; DAR=0x%08X; DSISR=0x%08X; LR=0x%08X; R1=0x%08X; XCP=0x%08X (%s)\n",
  471                 (unsigned int)sv->save_srr0, (unsigned int)sv->save_srr1, (unsigned int)sv->save_dar, sv->save_dsisr,
  472                 (unsigned int)sv->save_lr, (unsigned int)sv->save_r1, sv->save_exception, xcode);
  473         
  474         if(!(sv->save_srr1 & MASK(MSR_PR))) {           /* Are we in the kernel? */
  475                 dump_backtrace((unsigned int)sv->save_r1, fence);       /* Dump the stack back trace from  here if not user state */
  476         }
  477         
  478         return;
  479 }
  480 
  481 
  482 
  483 #define DUMPFRAMES 32
  484 #define LRindex 2
  485 
  486 void dump_backtrace(unsigned int stackptr, unsigned int fence) {
  487 
  488         unsigned int bframes[DUMPFRAMES];
  489         unsigned int  sframe[8], raddr, dumbo;
  490         int i;
  491         
  492         kdb_printf("      Backtrace:\n");
  493         for(i = 0; i < DUMPFRAMES; i++) {                       /* Dump up to max frames */
  494         
  495                 if(!stackptr || (stackptr == fence)) break;             /* Hit stop point or end... */
  496                 
  497                 if(stackptr & 0x0000000F) {                             /* Is stack pointer valid? */
  498                         kdb_printf("\n         backtrace terminated - unaligned frame address: 0x%08X\n", stackptr);    /* No, tell 'em */
  499                         break;
  500                 }
  501 
  502                 raddr = (unsigned int)pmap_find_phys(kernel_pmap, (addr64_t)stackptr);  /* Get physical frame address */
  503                 if(!raddr || (stackptr > vm_last_addr)) {               /* Is it mapped? */
  504                         kdb_printf("\n         backtrace terminated - frame not mapped or invalid: 0x%08X\n", stackptr);        /* No, tell 'em */
  505                         break;
  506                 }
  507         
  508                 if(!mapping_phys_lookup(raddr, &dumbo)) {       /* Is it within physical RAM? */
  509                         kdb_printf("\n         backtrace terminated - frame outside of RAM: v=0x%08X, p=%08X\n", stackptr, raddr);      /* No, tell 'em */
  510                         break;
  511                 }
  512         
  513                 ReadReal((addr64_t)((raddr << 12) | (stackptr & 4095)), &sframe[0]);    /* Fetch the stack frame */
  514 
  515                 bframes[i] = sframe[LRindex];                           /* Save the link register */
  516                 
  517                 if(!i) kdb_printf("         ");                         /* Indent first time */
  518                 else if(!(i & 7)) kdb_printf("\n         ");    /* Skip to new line every 8 */
  519                 kdb_printf("0x%08X ", bframes[i]);                      /* Dump the link register */
  520                 
  521                 stackptr = sframe[0];                                           /* Chain back */
  522         }
  523         kdb_printf("\n");
  524         if(i >= DUMPFRAMES) kdb_printf("      backtrace continues...\n");       /* Say we terminated early */
  525         if(i) kmod_dump((vm_offset_t *)&bframes[0], i); /* Show what kmods are in trace */
  526         
  527 }
  528         
  529 
  530 
  531 void 
  532 Debugger(const char     *message) {
  533 
  534         int i;
  535         unsigned int store[8];
  536         unsigned long pi_size = 0;
  537         spl_t spl;
  538         
  539         spl = splhigh();                                                                /* No interruptions from here on */
  540         
  541 /*
  542  *      backtrace for Debugger() call  from panic() if no current debugger
  543  *      backtrace and return for double panic() call
  544  */
  545         if ((panicstr != (char *)0) && 
  546           (((nestedpanic != 0) && (current_debugger == 1)) || (active_debugger == 0))) {
  547                 print_backtrace(NULL);
  548                 if (nestedpanic != 0)  {
  549                         splx(spl);
  550                         return;                                                                 /* Yeah, don't enter again... */
  551                 }
  552         }
  553         
  554         if (debug_mode && debugger_active[cpu_number()]) {      /* Are we already on debugger on this processor? */
  555                 splx(spl);
  556                 return;                                                                         /* Yeah, don't do it again... */
  557         }
  558 
  559 
  560 /*
  561  * The above stuff catches the double panic case so we shouldn't have to worry about that here.
  562  */
  563         if ( panicstr != (char *)0 )
  564         {
  565                 /* diable kernel preemptions */
  566                 disable_preemption();
  567         
  568                 /* everything should be printed now so copy to NVRAM
  569                 */
  570                 if( debug_buf_size > 0)
  571 
  572                   {
  573                     /* Do not compress the panic log unless kernel debugging 
  574                      * is disabled - the panic log isn't synced to NVRAM if 
  575                      * debugging is enabled, and the panic log is valuable 
  576                      * whilst debugging
  577                      */
  578                     if (!panicDebugging)
  579                       {
  580                         unsigned int bufpos;
  581                         
  582                         /* Now call the compressor */
  583                         bufpos = packAsc (debug_buf, (unsigned int) (debug_buf_ptr - debug_buf) );
  584                         /* If compression was successful, use the compressed length                */
  585                         if (bufpos)
  586                           {
  587                             debug_buf_ptr = debug_buf + bufpos;
  588                           }
  589                       }
  590                     /* Truncate if the buffer is larger than a certain magic 
  591                      * size - this really ought to be some appropriate fraction
  592                      * of the NVRAM image buffer, and is best done in the 
  593                      * savePanicInfo() or PESavePanicInfo() calls 
  594                      */
  595                     pi_size = debug_buf_ptr - debug_buf;
  596                     pi_size = PESavePanicInfo( debug_buf, ((pi_size > 2040) ? 2040 : pi_size));
  597                   }
  598                         
  599                 if( !panicDebugging && (pi_size != 0) ) {
  600                         int     my_cpu, debugger_cpu;
  601                         int     tcpu;
  602 
  603                         my_cpu = cpu_number();
  604                         debugger_cpu = my_cpu;
  605 
  606                         hw_atomic_add(&debug_mode, 1);
  607                         debugger_active[my_cpu]++;
  608                         lock_debugger();
  609 
  610                         for(tcpu = 0; tcpu < NCPUS; tcpu++) {
  611                                 if(tcpu == my_cpu) continue;
  612                                 hw_atomic_add(&debugger_sync, 1);
  613                                 (void)cpu_signal(tcpu, SIGPdebug, 0 ,0);
  614                         }
  615                         (void)hw_cpu_sync(&debugger_sync, LockTimeOut);
  616                         debugger_sync = 0;
  617                 }
  618 
  619                 draw_panic_dialog();
  620                 
  621                 if( !panicDebugging && (pi_size != 0))
  622                                         PEHaltRestart( kPEHangCPU );
  623 
  624                 enable_preemption();
  625         }
  626 
  627 
  628         if ((current_debugger != NO_CUR_DB)) {                  /* If there is a debugger configured, enter it */
  629                 printf("Debugger(%s)\n", message);
  630                 TRAP_DEBUGGER;
  631                 splx(spl);
  632                 return;                                                                         /* Done debugging for a while */
  633         }
  634 
  635         printf("\nNo debugger configured - dumping debug information\n");
  636         printf("MSR=%08X\n",mfmsr());
  637         print_backtrace(NULL);
  638         splx(spl);
  639         return;
  640 }
  641 
  642 /*
  643  *              Here's where we attempt to get some diagnostic information dumped out
  644  *              when the system is really confused.  We will try to get into the 
  645  *              debugger as well.
  646  *
  647  *              We are here with interrupts disabled and on the debug stack.  The savearea
  648  *              that was passed in is NOT chained to the activation.
  649  *
  650  *              save_r3 contains the failure reason code.
  651  */
  652 
  653 void SysChoked(int type, savearea *sv) {                        /* The system is bad dead */
  654 
  655         unsigned int failcode;
  656         
  657         mp_disable_preemption();
  658         disableDebugOuput = FALSE;
  659         debug_mode = TRUE;
  660 
  661         failcode = (unsigned int)sv->save_r3;                   /* Get the failure code */
  662         if(failcode > failUnknown) failcode = failUnknown;      /* Set unknown code code */
  663         
  664         kprintf("System Failure: cpu=%d; code=%08X (%s)\n", cpu_number(), (unsigned int)sv->save_r3, failNames[failcode]);
  665         kdb_printf("System Failure: cpu=%d; code=%08X (%s)\n", cpu_number(), (unsigned int)sv->save_r3, failNames[failcode]);
  666 
  667         print_backtrace(sv);                                                    /* Attempt to print backtrace */
  668         Call_DebuggerC(type, sv);                                               /* Attempt to get into debugger */
  669 
  670         if ((current_debugger != NO_CUR_DB)) Call_DebuggerC(type, sv);  /* Attempt to get into debugger */
  671 
  672 }
  673 
  674 
  675 
  676 /*
  677  *      When we get here, interruptions are disabled and we are on the debugger stack
  678  *      Never, ever, ever, ever enable interruptions from here on
  679  */
  680 
  681 int Call_DebuggerC(
  682         int     type,
  683         struct savearea *saved_state)
  684 {
  685         int                             directcall, wait;
  686         addr64_t                instr_ptr;
  687         ppnum_t                 instr_pp;
  688         unsigned int    instr;
  689         int                     my_cpu, tcpu;
  690 
  691         my_cpu = cpu_number();                                                          /* Get our CPU */
  692 
  693 #if     MACH_KDB
  694         if((debugger_cpu == my_cpu) &&                                          /* Do we already own debugger? */
  695           debugger_active[my_cpu] &&                                            /* and are we really active? */
  696           db_recover &&                                                                         /* and have we set up recovery? */
  697           (current_debugger == KDB_CUR_DB)) {                           /* and are we in KDB (only it handles recovery) */
  698                 kdb_trap(type, saved_state);                                    /* Then reenter it... */
  699         }
  700 #endif
  701         
  702         hw_atomic_add(&debug_mode, 1);                                          /* Indicate we are in debugger */
  703         debugger_active[my_cpu]++;                                                      /* Show active on our CPU */
  704         lock_debugger();                                                                        /* Insure that only one CPU is in debugger */
  705 
  706         if(db_im_stepping == my_cpu) {                                          /* Are we just back from a step? */
  707                 enable_preemption_no_check();                                   /* Enable preemption now */
  708                 db_im_stepping = 0xFFFFFFFF;                                    /* Nobody stepping right now */
  709         }
  710 
  711         if (debugger_debug) {
  712 #if 0
  713                 kprintf("Call_DebuggerC(%d): %08X %08X, debact = %d\n", my_cpu, type, saved_state, debug_mode); /* (TEST/DEBUG) */
  714 #endif
  715                 printf("Call_Debugger: enter - cpu %d, is_slave %d, debugger_cpu %d, pc %08X\n",
  716                    my_cpu, debugger_is_slave[my_cpu], debugger_cpu, saved_state->save_srr0);
  717         }
  718         
  719         instr_pp = (vm_offset_t)pmap_find_phys(kernel_pmap, (addr64_t)(saved_state->save_srr0));
  720 
  721         if (instr_pp) {
  722                 instr_ptr = (addr64_t)(((addr64_t)instr_pp << 12) | (saved_state->save_srr0 & 0xFFF));  /* Make physical address */
  723                 instr = ml_phys_read_64(instr_ptr);                             /* Get the trap that caused entry */
  724         } 
  725         else instr = 0;
  726 
  727 #if 0
  728         if (debugger_debug) kprintf("Call_DebuggerC(%d): instr_pp = %08X, instr_ptr = %016llX, instr = %08X\n", my_cpu, instr_pp, instr_ptr, instr);    /* (TEST/DEBUG) */
  729 #endif
  730 
  731         if (db_breakpoints_inserted) cpus_holding_bkpts++;      /* Bump up the holding count */
  732         if (debugger_cpu == -1 && !debugger_is_slave[my_cpu]) {
  733 #if 0
  734                 if (debugger_debug) kprintf("Call_DebuggerC(%d): lasttrace = %08X\n", my_cpu, lastTrace);       /* (TEST/DEBUG) */
  735 #endif
  736                 debugger_cpu = my_cpu;                                                  /* Show that we are debugger */
  737                 lastTrace = LLTraceSet(0);                                              /* Disable low-level tracing */
  738 
  739                 for(tcpu = 0; tcpu < NCPUS; tcpu++) {                   /* Stop all the other guys */
  740                         if(tcpu == my_cpu) continue;                            /* Don't diddle ourselves */
  741                         hw_atomic_add(&debugger_sync, 1);                       /* Count signal sent */
  742                         (void)cpu_signal(tcpu, SIGPdebug, 0 ,0);        /* Tell 'em to enter debugger */
  743                 }
  744                 (void)hw_cpu_sync(&debugger_sync, LockTimeOut); /* Wait for the other processors to enter debug */
  745                 debugger_sync = 0;                                                              /* We're done with it */
  746         } 
  747         else if (debugger_cpu != my_cpu)  goto debugger_exit;   /* We are not debugger, don't continue... */
  748         
  749 
  750         if (instr == TRAP_DIRECT_INST) {
  751                 disableDebugOuput = FALSE;
  752                 print_backtrace(saved_state);
  753         }
  754 
  755         switch_debugger = 0;                                                            /* Make sure switch request is off */
  756         directcall = 1;                                                                         /* Assume direct call */
  757 
  758         if (saved_state->save_srr1 & MASK(SRR1_PRG_TRAP)) {     /* Trap instruction? */
  759                 
  760                 directcall = 0;                                                                 /* We had a trap not a direct call */
  761 
  762                 switch (instr) {                                                                /* Select trap type */
  763 
  764 #if     MACH_KDP
  765                         case BREAK_TO_KDP0:                                                     /* Breakpoint into KDP? */
  766                         case BREAK_TO_KDP1:                                                     /* Breakpoint into KDP? */
  767                                 current_debugger = KDP_CUR_DB;                  /* Yes, set KDP */
  768                                 kdp_trap(type, saved_state);                    /* Enter it */
  769                                 break;
  770 #endif
  771         
  772 #if     MACH_KDB
  773                         case BREAK_TO_KDB0:                                             /* Breakpoint to KDB (the "good" debugger)? */
  774                                 current_debugger = KDB_CUR_DB;                  /* Yes, set it */
  775                                 kdb_trap(type, saved_state);                    /* Enter it */
  776                                 break;
  777 #endif
  778                                 
  779                         case TRAP_DEBUGGER_INST:                                        /* Should we enter the current debugger? */
  780                         case TRAP_DIRECT_INST:                                          /* Should we enter the current debugger? */
  781                                 if (current_debugger == KDP_CUR_DB)     /* Is current KDP? */
  782                                         kdp_trap(type, saved_state);            /* Yes, enter it */
  783                                 else if (current_debugger == KDB_CUR_DB)        /* Is this KDB? */
  784                                         kdb_trap(type, saved_state);            /* Yes, go ahead and enter */
  785                                 else goto debugger_error;                               /* No debugger active */
  786                                 break;
  787                                 
  788                         default:                                                                        /* Unknown/bogus trap type */
  789                                 goto debugger_error;
  790                 }
  791         }
  792 
  793         while(1) {                                                                                      /* We are here to handle debugger switches */
  794                 
  795                 if(!directcall) {                                                               /* Was this a direct call? */
  796                         if(!switch_debugger) break;                                     /* No, then leave if no switch requested... */
  797 
  798 /*
  799  *                      Note: we can only switch to a debugger we have.  Ignore bogus switch requests.
  800  */
  801 #if 0
  802                         if (debugger_debug) kprintf("Call_DebuggerC(%d): switching debuggers\n", my_cpu);       /* (TEST/DEBUG) */
  803 #endif
  804 #if MACH_KDB
  805                         if(current_debugger == KDP_CUR_DB) current_debugger = KDB_CUR_DB; /* Switch to KDB */
  806 #if MACH_KDP
  807                         else 
  808 #endif
  809 #endif
  810 #if MACH_KDP
  811                         if(current_debugger == KDB_CUR_DB) current_debugger = KDP_CUR_DB;               /* Switch to KDP */
  812 #endif
  813                 }
  814                 
  815                 switch_debugger = 0;                                                    /* Clear request */
  816                 directcall = 0;                                                                 /* Clear first-time direct call indication */
  817 
  818                 switch (current_debugger) {                                             /* Enter correct debugger */
  819                 
  820                         case KDP_CUR_DB:                                                        /* Enter KDP */
  821                                 kdp_trap(type, saved_state);
  822                                 break;
  823                                 
  824                         case KDB_CUR_DB:                                                        /* Enter KDB */
  825                                 kdb_trap(type, saved_state);
  826                                 break;
  827                                 
  828                         default:                                                                        /* No debugger installed */
  829                                 goto debugger_error;
  830                                 break;
  831                 }
  832         }
  833 
  834 debugger_exit:
  835 #if 0
  836         if (debugger_debug) kprintf("Call_DebuggerC(%d): exit - inst = %08X, cpu=%d(%d), run=%d\n", my_cpu, 
  837                 instr, my_cpu, debugger_cpu, db_run_mode);      /* (TEST/DEBUG) */
  838 #endif
  839         if ((instr == TRAP_DEBUGGER_INST) ||                            /* Did we trap to enter debugger? */
  840                 (instr == TRAP_DIRECT_INST)) saved_state->save_srr0 += TRAP_INST_SIZE;  /* Yes, point past trap */
  841 
  842         if(debugger_cpu == my_cpu) LLTraceSet(lastTrace);       /* Enable tracing on the way out if we are debugger */
  843 
  844         wait = FALSE;                                                                           /* Assume we are not going to wait */
  845         if (db_run_mode == STEP_CONTINUE) {                                     /* Are we going to run? */
  846                 wait = TRUE;                                                                    /* Yeah, remember to wait for breakpoints to clear */
  847                 debugger_cpu = -1;                                                              /* Release other processor's debuggers */
  848                 debugger_pending[0] = 0;                                                /* Release request (this is a HACK) */
  849                 debugger_pending[1] = 0;                                                /* Release request (this is a HACK) */
  850                 NMIss = 0;                                                                              /* Let NMI bounce */
  851         }
  852         
  853         if(db_run_mode == STEP_ONCE) {                                          /* Are we about to step? */
  854                 disable_preemption();                                                   /* Disable preemption for the step */
  855                 db_im_stepping = my_cpu;                                                /* Remember that I am about to step */
  856         }
  857 
  858         if (db_breakpoints_inserted) cpus_holding_bkpts--;      /* If any breakpoints, back off count */
  859         if (debugger_is_slave[my_cpu]) debugger_is_slave[my_cpu]--;     /* If we were a slove, uncount us */
  860         if (debugger_debug)
  861                 printf("Call_Debugger: exit - cpu %d, debugger_cpu %d, run_mode %d holds %d\n",
  862                           my_cpu, debugger_cpu, db_run_mode,
  863                           cpus_holding_bkpts);
  864 
  865         unlock_debugger();                                                                      /* Release the lock */
  866         debugger_active[my_cpu]--;                                                      /* Say we aren't active anymore */
  867 
  868         if (wait) while(cpus_holding_bkpts);                            /* Wait for breakpoints to clear */
  869 
  870         hw_atomic_sub(&debug_mode, 1);                                          /* Set out of debug now */
  871 
  872         return(1);                                                                                      /* Exit debugger normally */
  873 
  874 debugger_error:
  875         if(db_run_mode != STEP_ONCE) enable_preemption_no_check();      /* Enable preemption, but don't preempt here */
  876         hw_atomic_sub(&debug_mode, 1);                                          /* Set out of debug now */
  877         return(0);                                                                                      /* Return in shame... */
  878 
  879 }
  880 
  881 void lock_debugger(void) {
  882         int             my_cpu;
  883         register int    i;
  884 
  885         my_cpu = cpu_number();                                                          /* Get our CPU number */
  886 
  887         while(1) {                                                                                      /* Check until we get it */
  888 
  889                 if (debugger_cpu != -1 && debugger_cpu != my_cpu) continue;     /* Someone, not us, is debugger... */
  890                 if (hw_lock_try(&debugger_lock)) {                              /* Get the debug lock */                        
  891                         if (debugger_cpu == -1 || debugger_cpu == my_cpu) break;        /* Is it us? */
  892                         hw_lock_unlock(&debugger_lock);                         /* Not us, release lock */
  893                 }
  894         } 
  895 }
  896 
  897 void unlock_debugger(void) {
  898 
  899         hw_lock_unlock(&debugger_lock);
  900 
  901 }
  902 
  903 struct pasc {
  904   unsigned a: 7;
  905   unsigned b: 7;
  906   unsigned c: 7;
  907   unsigned d: 7;
  908   unsigned e: 7;
  909   unsigned f: 7;
  910   unsigned g: 7;
  911   unsigned h: 7;
  912 }  __attribute__((packed));
  913 
  914 typedef struct pasc pasc_t;
  915 
  916 int packAsc (unsigned char *inbuf, unsigned int length)
  917 {
  918   unsigned int i, j = 0;
  919   pasc_t pack;
  920 
  921   for (i = 0; i < length; i+=8)
  922     {
  923       pack.a = inbuf[i];
  924       pack.b = inbuf[i+1];
  925       pack.c = inbuf[i+2];
  926       pack.d = inbuf[i+3];
  927       pack.e = inbuf[i+4];
  928       pack.f = inbuf[i+5];
  929       pack.g = inbuf[i+6];
  930       pack.h = inbuf[i+7];
  931       bcopy ((char *) &pack, inbuf + j, 7);
  932       j += 7;
  933     }
  934   if (0 != (i - length))
  935     inbuf[j - (i - length)] &= 0xFF << (8-(i - length));
  936   return j-(((i-length) == 7) ? 6 : (i - length));
  937 }

Cache object: f1331cd4189bbaff9723492ba8289c08


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