]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/ppc/trap.c
xnu-517.7.21.tar.gz
[apple/xnu.git] / osfmk / ppc / trap.c
index 3b0fbddb8c5ef27b39186b5801c879639fb7a362..e87a876e9e625008f548fd20d8a764f784f7425f 100644 (file)
 #include <ppc/proc_reg.h>      /* for SR_xxx definitions */
 #include <ppc/pmap.h>
 #include <ppc/mem.h>
-#include <ppc/fpu_protos.h>
+#include <ppc/mappings.h>
+#include <ppc/Firmware.h>
+#include <ppc/low_trace.h>
+#include <ppc/Diagnostics.h>
+#include <ppc/hw_perfmon.h>
 
 #include <sys/kdebug.h>
 
+perfTrap perfTrapHook = 0;                                                     /* Pointer to performance trap hook routine */
+
 #if    MACH_KDB
 #include <ddb/db_watch.h>
 #include <ddb/db_run.h>
@@ -62,87 +68,93 @@ extern boolean_t db_breakpoints_inserted;
 #endif /* MACH_KDB */
 
 extern int debugger_active[NCPUS];
-extern vm_address_t bsd_init_task;
+extern task_t bsd_init_task;
 extern char init_task_failure_data[];
+extern int not_in_kdp;
 
-/*
- * XXX don't pass VM_PROT_EXECUTE to vm_fault(), execute permission is implied
- * in either R or RW (note: the pmap module knows this).  This is done for the
- * benefit of programs that execute out of their data space (ala lisp).
- * If we didn't do this in that scenerio, the ITLB miss code would call us
- * and we would call vm_fault() with RX permission.  However, the space was
- * probably vm_allocate()ed with just RW and vm_fault would fail.  The "right"
- * solution to me is to have the un*x server always allocate data with RWX for
- * compatibility with existing binaries.
- */
-
-#define        PROT_EXEC       (VM_PROT_READ)
+#define        PROT_EXEC       (VM_PROT_EXECUTE)
 #define PROT_RO                (VM_PROT_READ)
 #define PROT_RW                (VM_PROT_READ|VM_PROT_WRITE)
 
 /* A useful macro to update the ppc_exception_state in the PCB
  * before calling doexception
  */
-#define UPDATE_PPC_EXCEPTION_STATE {                                         \
-       thread_act_t thr_act = current_act();                                 \
-       struct ppc_exception_state *es = &thr_act->mact.pcb->es;              \
-       es->dar = dar;                                                        \
-       es->dsisr = dsisr;                                                    \
-       es->exception = trapno / T_VECTOR_SIZE; /* back to powerpc */ \
+#define UPDATE_PPC_EXCEPTION_STATE {                                                   \
+       thread_act_t thr_act = current_act();                                           \
+       thr_act->mact.pcb->save_dar = (uint64_t)dar;                            \
+       thr_act->mact.pcb->save_dsisr = dsisr;                                          \
+       thr_act->mact.pcb->save_exception = trapno / T_VECTOR_SIZE;     /* back to powerpc */ \
 }
 
 static void unresolved_kernel_trap(int trapno,
-                                  struct ppc_saved_state *ssp,
+                                  struct savearea *ssp,
                                   unsigned int dsisr,
-                                  unsigned int dar,
+                                  addr64_t dar,
                                   char *message);
 
-struct ppc_saved_state *trap(int trapno,
-                            struct ppc_saved_state *ssp,
+static void handleMck(struct savearea *ssp);           /* Common machine check handler */
+
+
+struct savearea *trap(int trapno,
+                            struct savearea *ssp,
                             unsigned int dsisr,
-                            unsigned int dar)
+                            addr64_t dar)
 {
-       int exception=0;
+       int exception;
        int code;
        int subcode;
        vm_map_t map;
-        unsigned int sp;
-       unsigned int space,space2;
+    unsigned int sp;
+       unsigned int space, space2;
        unsigned int offset;
-       thread_act_t thr_act = current_act();
+       thread_act_t thr_act;
        boolean_t intr;
+       
 #ifdef MACH_BSD
        time_value_t tv;
 #endif /* MACH_BSD */
 
+       if(perfTrapHook) {                                                      /* Is there a hook? */
+               if(perfTrapHook(trapno, ssp, dsisr, (unsigned int)dar) == KERN_SUCCESS) return ssp;     /* If it succeeds, we are done... */
+       }
+
+#if 0
+       {
+               extern void fctx_text(void);
+               fctx_test();
+       }
+#endif
+
+       thr_act = current_act();                                        /* Get current activation */
+       exception = 0;                                                          /* Clear exception for now */
+
 /*
  *     Remember that we are disabled for interruptions when we come in here.  Because
  *     of latency concerns, we need to enable interruptions in the interrupted process
  *     was enabled itself as soon as we can.
  */
 
-       intr = (ssp->srr1 & MASK(MSR_EE)) != 0;         /* Remember if we were enabled */
+       intr = (ssp->save_srr1 & MASK(MSR_EE)) != 0;    /* Remember if we were enabled */
 
        /* Handle kernel traps first */
 
-       if (!USER_MODE(ssp->srr1)) {
+       if (!USER_MODE(ssp->save_srr1)) {
                /*
                 * Trap came from kernel
                 */
                switch (trapno) {
 
                case T_PREEMPT:                 /* Handle a preempt trap */
-                       ast_taken(FALSE, AST_URGENT, FALSE);
+                       ast_taken(AST_PREEMPTION, FALSE);
                        break;  
 
+               case T_PERF_MON:
+                       perfmon_handle_pmi(ssp);
+                       break;
+
                case T_RESET:                                   /* Reset interruption */
-#if 0
-                       kprintf("*** Reset exception ignored; srr0 = %08X, srr1 = %08X\n",
-                               ssp->srr0, ssp->srr1);
-#else
-                       panic("Unexpected Reset exception; srr0 = %08X, srr1 = %08X\n",
-                               ssp->srr0, ssp->srr1);
-#endif
+                       if (!Call_Debugger(trapno, ssp))
+                               unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
                        break;                                          /* We just ignore these */
                
                /*
@@ -155,7 +167,6 @@ struct ppc_saved_state *trap(int trapno,
                 */
                case T_DECREMENTER:
                case T_IN_VAIN:                 /* Shouldn't ever see this, lowmem_vectors eats it */
-               case T_MACHINE_CHECK:
                case T_SYSTEM_MANAGEMENT:
                case T_ALTIVEC_ASSIST:
                case T_INTERRUPT:
@@ -165,6 +176,46 @@ struct ppc_saved_state *trap(int trapno,
                default:
                        unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
                        break;
+
+
+/*
+ *                     Here we handle a machine check in the kernel
+ */
+
+               case T_MACHINE_CHECK:
+                       handleMck(ssp);                                         /* Common to both user and kernel */
+                       break;
+
+
+               case T_ALIGNMENT:
+/*
+*                      If enaNotifyEMb is set, we get here, and
+*                      we have actually already emulated the unaligned access.
+*                      All that we want to do here is to ignore the interrupt. This is to allow logging or
+*                      tracing of unaligned accesses.  
+*/
+                       
+                       KERNEL_DEBUG_CONSTANT(
+                               MACHDBG_CODE(DBG_MACH_EXCP_ALNG, 0) | DBG_FUNC_NONE,
+                               (int)ssp->save_srr0 - 4, (int)dar, (int)dsisr, (int)ssp->save_lr, 0);
+                       break;
+
+               case T_EMULATE:
+/*
+*                      If enaNotifyEMb is set we get here, and
+*                      we have actually already emulated the instruction.
+*                      All that we want to do here is to ignore the interrupt. This is to allow logging or
+*                      tracing of emulated instructions.  
+*/
+
+                       KERNEL_DEBUG_CONSTANT(
+                               MACHDBG_CODE(DBG_MACH_EXCP_EMUL, 0) | DBG_FUNC_NONE,
+                               (int)ssp->save_srr0 - 4, (int)((savearea_comm *)ssp)->save_misc2, (int)dsisr, (int)ssp->save_lr, 0);
+                       break;
+
+
+
+
                        
                case T_TRACE:
                case T_RUNMODE_TRACE:
@@ -174,7 +225,7 @@ struct ppc_saved_state *trap(int trapno,
                        break;
 
                case T_PROGRAM:
-                       if (ssp->srr1 & MASK(SRR1_PRG_TRAP)) {
+                       if (ssp->save_srr1 & MASK(SRR1_PRG_TRAP)) {
                                if (!Call_Debugger(trapno, ssp))
                                        unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
                        } else {
@@ -183,14 +234,7 @@ struct ppc_saved_state *trap(int trapno,
                        }
                        break;
 
-               case T_ALIGNMENT:
-                       if (alignment(dsisr, dar, ssp)) {
-                               unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
-                       }
-                       break;
-
                case T_DATA_ACCESS:
-
 #if    MACH_KDB
                        mp_disable_preemption();
                        if (debug_mode
@@ -203,37 +247,49 @@ struct ppc_saved_state *trap(int trapno,
                        }
                        mp_enable_preemption();
 #endif /* MACH_KDB */
+                       /* can we take this during normal panic dump operation? */
+                       if (debug_mode
+                           && debugger_active[cpu_number()]
+                           && !not_in_kdp) {
+                               /* 
+                                * Access fault while in kernel core dump.
+                                */
+                               kdp_dump_trap(trapno, ssp); 
+                       }
 
-                       if(intr) ml_set_interrupts_enabled(TRUE);       /* Enable if we were */
 
-                       /* simple case : not SR_COPYIN segment, from kernel */
-                       if ((dar >> 28) != SR_COPYIN_NUM) {
-                               map = kernel_map;
+                       if(ssp->save_dsisr & dsiInvMode) {                      /* Did someone try to reserve cache inhibited? */
+                               panic("trap: disallowed access to cache inhibited memory - %016llX\n", dar);
+                       }
 
-                               offset = dar;
+                       if(intr) ml_set_interrupts_enabled(TRUE);       /* Enable if we were */
+                       
+                       if(((dar >> 28) < 0xE) | ((dar >> 28) > 0xF))  {        /* Is this a copy in/out? */
+                       
+                               offset = (unsigned int)dar;                             /* Set the failing address */
+                               map = kernel_map;                                               /* No, this is a normal kernel access */
                                
-
 /*
  *     Note: Some ROM device drivers will access page 0 when they start.  The IOKit will 
  *     set a flag to tell us to ignore any access fault on page 0.  After the driver is
  *     opened, it will clear the flag.
  */
-                               if((0 == (dar & -PAGE_SIZE)) &&         /* Check for access of page 0 and */
-                                 ((thr_act->mact.specFlags) & ignoreZeroFault)) {
-                                                                       /* special case of ignoring page zero faults */
-                                       ssp->srr0 += 4;                 /* Point to next instruction */
+                               if((0 == (offset & -PAGE_SIZE)) &&              /* Check for access of page 0 and */
+                                 ((thr_act->mact.specFlags) & ignoreZeroFault)) {      /* special case of ignoring page zero faults */
+                                       ssp->save_srr0 += 4;                            /* Point to next instruction */
                                        break;
                                }
 
-                               code = vm_fault(map, trunc_page(offset),
+                               code = vm_fault(map, trunc_page_32(offset),
                                                dsisr & MASK(DSISR_WRITE) ? PROT_RW : PROT_RO,
-                                               FALSE, THREAD_UNINT);
+                                               FALSE, THREAD_UNINT, NULL, 0);
 
                                if (code != KERN_SUCCESS) {
                                        unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
                                } else { 
-                                       ((savearea *)ssp)->save_flags |= SAVredrive;    /* Tell low-level to re-try fault */
-                                       ((savearea *)ssp)->save_dsisr |= MASK(DSISR_HASH);      /* Make sure this is marked as a miss */
+                                       ssp->save_hdr.save_flags |= SAVredrive; /* Tell low-level to re-try fault */
+                                       ssp->save_dsisr = (ssp->save_dsisr & 
+                                               ~((MASK(DSISR_NOEX) | MASK(DSISR_PROT)))) | MASK(DSISR_HASH);   /* Make sure this is marked as a miss */
                                }
                                break;
                        }
@@ -241,15 +297,12 @@ struct ppc_saved_state *trap(int trapno,
                        /* If we get here, the fault was due to a copyin/out */
 
                        map = thr_act->map;
+                       
+                       offset = (unsigned int)(thr_act->mact.cioRelo + dar);   /* Compute the user space address */
 
-                       /* Mask out SR_COPYIN and mask in original segment */
-
-                       offset = (dar & 0x0fffffff) |
-                               ((mfsrin(dar)<<8) & 0xF0000000);
-
-                       code = vm_fault(map, trunc_page(offset),
+                       code = vm_fault(map, trunc_page_32(offset),
                                        dsisr & MASK(DSISR_WRITE) ? PROT_RW : PROT_RO,
-                                       FALSE, THREAD_ABORTSAFE);
+                                       FALSE, THREAD_UNINT, NULL, 0);
 
                        /* If we failed, there should be a recovery
                         * spot to rfi to.
@@ -259,7 +312,7 @@ struct ppc_saved_state *trap(int trapno,
                                if (thr_act->thread->recover) {
                                
                                        act_lock_thread(thr_act);
-                                       ssp->srr0 = thr_act->thread->recover;
+                                       ssp->save_srr0 = thr_act->thread->recover;
                                        thr_act->thread->recover =
                                                        (vm_offset_t)NULL;
                                        act_unlock_thread(thr_act);
@@ -268,8 +321,9 @@ struct ppc_saved_state *trap(int trapno,
                                }
                        }
                        else { 
-                               ((savearea *)ssp)->save_flags |= SAVredrive;    /* Tell low-level to re-try fault */
-                               ((savearea *)ssp)->save_dsisr |= MASK(DSISR_HASH);      /* Make sure this is marked as a miss */
+                               ssp->save_hdr.save_flags |= SAVredrive; /* Tell low-level to re-try fault */
+                               ssp->save_dsisr = (ssp->save_dsisr & 
+                                       ~((MASK(DSISR_NOEX) | MASK(DSISR_PROT)))) | MASK(DSISR_HASH);   /* Make sure this is marked as a miss */
                        }
                        
                        break;
@@ -295,14 +349,15 @@ struct ppc_saved_state *trap(int trapno,
 
                        map = kernel_map;
                        
-                       code = vm_fault(map, trunc_page(ssp->srr0),
-                                       PROT_EXEC, FALSE, THREAD_UNINT);
+                       code = vm_fault(map, trunc_page_64(ssp->save_srr0),
+                                       PROT_EXEC, FALSE, THREAD_UNINT, NULL, 0);
 
                        if (code != KERN_SUCCESS) {
                                unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
                        } else { 
-                               ((savearea *)ssp)->save_flags |= SAVredrive;    /* Tell low-level to re-try fault */
-                               ssp->srr1 |= MASK(DSISR_HASH);                                  /* Make sure this is marked as a miss */
+                               ssp->save_hdr.save_flags |= SAVredrive; /* Tell low-level to re-try fault */
+                               ssp->save_srr1 = (ssp->save_srr1 & 
+                                       ~((unsigned long long)(MASK(DSISR_NOEX) | MASK(DSISR_PROT)))) | MASK(DSISR_HASH);               /* Make sure this is marked as a miss */
                        }
                        break;
 
@@ -342,6 +397,10 @@ struct ppc_saved_state *trap(int trapno,
                        unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
                        break;  
 
+               case T_PERF_MON:
+                       perfmon_handle_pmi(ssp);
+                       break;
+
                        /*
                         * These trap types should never be seen by trap()
                         * Some are interrupts that should be seen by
@@ -350,7 +409,6 @@ struct ppc_saved_state *trap(int trapno,
                         */
                case T_DECREMENTER:
                case T_IN_VAIN:                                                         /* Shouldn't ever see this, lowmem_vectors eats it */
-               case T_MACHINE_CHECK:
                case T_INTERRUPT:
                case T_FP_UNAVAILABLE:
                case T_SYSTEM_MANAGEMENT:
@@ -361,26 +419,50 @@ struct ppc_saved_state *trap(int trapno,
 
                        ml_set_interrupts_enabled(FALSE);                                       /* Turn off interruptions */
 
-                       panic("Unexpected user state trap(cpu %d): %08X DSISR=0x%08X DAR=0x%08X PC=0x%08X, MSR=0x%08X\n",
-                              cpu_number(), trapno, dsisr, dar, ssp->srr0, ssp->srr1);
+                       panic("Unexpected user state trap(cpu %d): 0x%08X DSISR=0x%08X DAR=0x%016llX PC=0x%016llX, MSR=0x%016llX\n",
+                              cpu_number(), trapno, dsisr, dar, ssp->save_srr0, ssp->save_srr1);
+                       break;
+
+
+/*
+ *                     Here we handle a machine check in user state
+ */
+
+               case T_MACHINE_CHECK:
+                       handleMck(ssp);                                         /* Common to both user and kernel */
                        break;
 
                case T_RESET:
-#if 0
-                       kprintf("*** Reset exception ignored; srr0 = %08X, srr1 = %08X\n",
-                               ssp->srr0, ssp->srr1);
-#else
-                       panic("Unexpected Reset exception: srr0 = %08X, srr1 = %08X\n",
-                               ssp->srr0, ssp->srr1);
-#endif
+                       ml_set_interrupts_enabled(FALSE);                                       /* Turn off interruptions */
+                       if (!Call_Debugger(trapno, ssp))
+                               panic("Unexpected Reset exception: srr0 = %016llx, srr1 = %016llx\n",
+                                       ssp->save_srr0, ssp->save_srr1);
                        break;                                          /* We just ignore these */
 
                case T_ALIGNMENT:
-                       if (alignment(dsisr, dar, ssp)) {
-                               code = EXC_PPC_UNALIGNED;
-                               exception = EXC_BAD_ACCESS;
-                               subcode = dar;
-                       }
+/*
+*                      If enaNotifyEMb is set, we get here, and
+*                      we have actually already emulated the unaligned access.
+*                      All that we want to do here is to ignore the interrupt. This is to allow logging or
+*                      tracing of unaligned accesses.  
+*/
+                       
+                       KERNEL_DEBUG_CONSTANT(
+                               MACHDBG_CODE(DBG_MACH_EXCP_ALNG, 0) | DBG_FUNC_NONE,
+                               (int)ssp->save_srr0 - 4, (int)dar, (int)dsisr, (int)ssp->save_lr, 0);
+                       break;
+
+               case T_EMULATE:
+/*
+*                      If enaNotifyEMb is set we get here, and
+*                      we have actually already emulated the instruction.
+*                      All that we want to do here is to ignore the interrupt. This is to allow logging or
+*                      tracing of emulated instructions.  
+*/
+
+                       KERNEL_DEBUG_CONSTANT(
+                               MACHDBG_CODE(DBG_MACH_EXCP_EMUL, 0) | DBG_FUNC_NONE,
+                               (int)ssp->save_srr0 - 4, (int)((savearea_comm *)ssp)->save_misc2, (int)dsisr, (int)ssp->save_lr, 0);
                        break;
 
                case T_TRACE:                   /* Real PPC chips */
@@ -390,42 +472,54 @@ struct ppc_saved_state *trap(int trapno,
                  }
                  /* fall through */
 
-               case T_INSTRUCTION_BKPT:        /* 603  PPC chips */
-               case T_RUNMODE_TRACE:           /* 601  PPC chips */
+               case T_INSTRUCTION_BKPT:
                        exception = EXC_BREAKPOINT;
                        code = EXC_PPC_TRACE;
-                       subcode = ssp->srr0;
+                       subcode = (unsigned int)ssp->save_srr0;
                        break;
 
                case T_PROGRAM:
-                       if (ssp->srr1 & MASK(SRR1_PRG_FE)) {
-                               fpu_save();
+                       if (ssp->save_srr1 & MASK(SRR1_PRG_FE)) {
+                               fpu_save(thr_act->mact.curctx);
                                UPDATE_PPC_EXCEPTION_STATE;
                                exception = EXC_ARITHMETIC;
                                code = EXC_ARITHMETIC;
                        
                                mp_disable_preemption();
-                               subcode = current_act()->mact.FPU_pcb->fs.fpscr;
+                               subcode = ssp->save_fpscr;
                                mp_enable_preemption();
                        }       
-                       else if (ssp->srr1 & MASK(SRR1_PRG_ILL_INS)) {
+                       else if (ssp->save_srr1 & MASK(SRR1_PRG_ILL_INS)) {
                                
                                UPDATE_PPC_EXCEPTION_STATE
                                exception = EXC_BAD_INSTRUCTION;
                                code = EXC_PPC_UNIPL_INST;
-                               subcode = ssp->srr0;
-                       } else if (ssp->srr1 & MASK(SRR1_PRG_PRV_INS)) {
+                               subcode = (unsigned int)ssp->save_srr0;
+                       } else if ((unsigned int)ssp->save_srr1 & MASK(SRR1_PRG_PRV_INS)) {
 
                                UPDATE_PPC_EXCEPTION_STATE;
                                exception = EXC_BAD_INSTRUCTION;
                                code = EXC_PPC_PRIVINST;
-                               subcode = ssp->srr0;
-                       } else if (ssp->srr1 & MASK(SRR1_PRG_TRAP)) {
+                               subcode = (unsigned int)ssp->save_srr0;
+                       } else if (ssp->save_srr1 & MASK(SRR1_PRG_TRAP)) {
                                unsigned int inst;
-
-                               if (copyin((char *) ssp->srr0, (char *) &inst, 4 ))
-                                       panic("copyin failed\n");
+                               char *iaddr;
+                               
+                               iaddr = CAST_DOWN(char *, ssp->save_srr0);              /* Trim from long long and make a char pointer */ 
+                               if (copyin(iaddr, (char *) &inst, 4 )) panic("copyin failed\n");
+                               
+                               if(dgWork.dgFlags & enaDiagTrap) {      /* Is the diagnostic trap enabled? */
+                                       if((inst & 0xFFFFFFF0) == 0x0FFFFFF0) { /* Is this a TWI 31,R31,0xFFFx? */
+                                               if(diagTrap(ssp, inst & 0xF)) { /* Call the trap code */
+                                                       ssp->save_srr0 += 4ULL; /* If we eat the trap, bump pc */
+                                                       exception = 0;                  /* Clear exception */
+                                                       break;                                  /* All done here */
+                                               }
+                                       }
+                               }
+                               
                                UPDATE_PPC_EXCEPTION_STATE;
+                               
                                if (inst == 0x7FE00008) {
                                        exception = EXC_BREAKPOINT;
                                        code = EXC_PPC_BREAKPOINT;
@@ -433,7 +527,7 @@ struct ppc_saved_state *trap(int trapno,
                                        exception = EXC_SOFTWARE;
                                        code = EXC_PPC_TRAP;
                                }
-                               subcode = ssp->srr0;
+                               subcode = (unsigned int)ssp->save_srr0;
                        }
                        break;
                        
@@ -441,23 +535,31 @@ struct ppc_saved_state *trap(int trapno,
                        UPDATE_PPC_EXCEPTION_STATE;
                        exception = EXC_ARITHMETIC;
                        code = EXC_PPC_ALTIVECASSIST;
-                       subcode = ssp->srr0;
+                       subcode = (unsigned int)ssp->save_srr0;
                        break;
 
                case T_DATA_ACCESS:
                        map = thr_act->map;
+
+                       if(ssp->save_dsisr & dsiInvMode) {                      /* Did someone try to reserve cache inhibited? */
+                               UPDATE_PPC_EXCEPTION_STATE;                             /* Don't even bother VM with this one */
+                               exception = EXC_BAD_ACCESS;
+                               subcode = (unsigned int)dar;
+                               break;
+                       }
                        
-                       code = vm_fault(map, trunc_page(dar),
+                       code = vm_fault(map, trunc_page_64(dar),
                                 dsisr & MASK(DSISR_WRITE) ? PROT_RW : PROT_RO,
-                                FALSE, THREAD_ABORTSAFE);
+                                FALSE, THREAD_ABORTSAFE, NULL, 0);
 
                        if ((code != KERN_SUCCESS) && (code != KERN_ABORTED)) {
                                UPDATE_PPC_EXCEPTION_STATE;
                                exception = EXC_BAD_ACCESS;
-                               subcode = dar;
+                               subcode = (unsigned int)dar;
                        } else { 
-                               ((savearea *)ssp)->save_flags |= SAVredrive;    /* Tell low-level to re-try fault */
-                               ((savearea *)ssp)->save_dsisr |= MASK(DSISR_HASH);      /* Make sure this is marked as a miss */
+                               ssp->save_hdr.save_flags |= SAVredrive; /* Tell low-level to re-try fault */
+                               ssp->save_dsisr = (ssp->save_dsisr & 
+                                       ~((MASK(DSISR_NOEX) | MASK(DSISR_PROT)))) | MASK(DSISR_HASH);   /* Make sure this is marked as a miss */
                        }
                        break;
                        
@@ -467,22 +569,23 @@ struct ppc_saved_state *trap(int trapno,
                         */
                        map = thr_act->map;
                        
-                       code = vm_fault(map, trunc_page(ssp->srr0),
-                                       PROT_EXEC, FALSE, THREAD_ABORTSAFE);
+                       code = vm_fault(map, trunc_page_64(ssp->save_srr0),
+                                       PROT_EXEC, FALSE, THREAD_ABORTSAFE, NULL, 0);
 
                        if ((code != KERN_SUCCESS) && (code != KERN_ABORTED)) {
                                UPDATE_PPC_EXCEPTION_STATE;
                                exception = EXC_BAD_ACCESS;
-                               subcode = ssp->srr0;
+                               subcode = (unsigned int)ssp->save_srr0;
                        } else { 
-                               ((savearea *)ssp)->save_flags |= SAVredrive;    /* Tell low-level to re-try fault */
-                               ssp->srr1 |= MASK(DSISR_HASH);                                  /* Make sure this is marked as a miss */
+                               ssp->save_hdr.save_flags |= SAVredrive; /* Tell low-level to re-try fault */
+                               ssp->save_srr1 = (ssp->save_srr1 & 
+                                       ~((unsigned long long)(MASK(DSISR_NOEX) | MASK(DSISR_PROT)))) | MASK(DSISR_HASH);               /* Make sure this is marked as a miss */
                        }
                        break;
 
                case T_AST:
                        ml_set_interrupts_enabled(FALSE);
-                       ast_taken(FALSE, AST_ALL, intr);
+                       ast_taken(AST_ALL, intr);
                        break;
                        
                }
@@ -490,7 +593,7 @@ struct ppc_saved_state *trap(int trapno,
                {
                void bsd_uprofil(time_value_t *, unsigned int);
 
-               bsd_uprofil(&tv, ssp->srr0);
+               bsd_uprofil(&tv, ssp->save_srr0);
                }
 #endif /* MACH_BSD */
        }
@@ -498,6 +601,7 @@ struct ppc_saved_state *trap(int trapno,
        if (exception) {
                /* if this is the init task, save the exception information */
                /* this probably is a fatal exception */
+#if 0
                if(bsd_init_task == current_task()) {
                        char *buf;
                        int i;
@@ -506,38 +610,38 @@ struct ppc_saved_state *trap(int trapno,
 
 
                        buf += sprintf(buf, "Exception Code = 0x%x, Subcode = 0x%x\n", code, subcode);
-                       buf += sprintf(buf, "DSISR = 0x%08x, DAR = 0x%08x\n"
+                       buf += sprintf(buf, "DSISR = 0x%08x, DAR = 0x%016llx\n"
                                                                , dsisr, dar);
 
                        for (i=0; i<32; i++) {
                                if ((i % 8) == 0) {
                                        buf += sprintf(buf, "\n%4d :",i);
                                }
-                               buf += sprintf(buf, " %08x",*(&ssp->r0+i));
+                               buf += sprintf(buf, " %08x",*(&ssp->save_r0+i));
                        }
 
                        buf += sprintf(buf, "\n\n");
-                       buf += sprintf(buf, "cr        = 0x%08x\t\t",ssp->cr);
-                       buf += sprintf(buf, "xer       = 0x%08x\n",ssp->xer);
-                       buf += sprintf(buf, "lr        = 0x%08x\t\t",ssp->lr);
-                       buf += sprintf(buf, "ctr       = 0x%08x\n",ssp->ctr); 
-                       buf += sprintf(buf, "srr0(iar) = 0x%08x\t\t",ssp->srr0);
-                       buf += sprintf(buf, "srr1(msr) = 0x%08B\n",ssp->srr1,
+                       buf += sprintf(buf, "cr        = 0x%08X\t\t",ssp->save_cr);
+                       buf += sprintf(buf, "xer       = 0x%08X\n",ssp->save_xer);
+                       buf += sprintf(buf, "lr        = 0x%016llX\t\t",ssp->save_lr);
+                       buf += sprintf(buf, "ctr       = 0x%016llX\n",ssp->save_ctr); 
+                       buf += sprintf(buf, "srr0(iar) = 0x%016llX\t\t",ssp->save_srr0);
+                       buf += sprintf(buf, "srr1(msr) = 0x%016llX\n",ssp->save_srr1,
                           "\x10\x11""EE\x12PR\x13""FP\x14ME\x15""FE0\x16SE\x18"
                           "FE1\x19""AL\x1a""EP\x1bIT\x1c""DT");
                        buf += sprintf(buf, "\n\n");
 
                        /* generate some stack trace */
                        buf += sprintf(buf, "Application level back trace:\n");
-                       if (ssp->srr1 & MASK(MSR_PR)) { 
-                          char *addr = (char*)ssp->r1;
+                       if (ssp->save_srr1 & MASK(MSR_PR)) { 
+                          char *addr = (char*)ssp->save_r1;
                           unsigned int stack_buf[3];
                           for (i = 0; i < 8; i++) {
                                if (addr == (char*)NULL)
                                                break;
                                if (!copyin(addr,(char*)stack_buf, 
                                                        3 * sizeof(int))) {
-                                               buf += sprintf(buf, "0x%08x : 0x%08x\n"
+                                               buf += sprintf(buf, "0x%08X : 0x%08X\n"
                                                ,addr,stack_buf[2]);
                                                addr = (char*)stack_buf[0];
                                } else {
@@ -547,15 +651,16 @@ struct ppc_saved_state *trap(int trapno,
                        }
                        buf[0] = '\0';
                }
+#endif
                doexception(exception, code, subcode);
        }
        /* AST delivery
         * Check to see if we need an AST, if so take care of it here
         */
        ml_set_interrupts_enabled(FALSE);
-       if (USER_MODE(ssp->srr1))
+       if (USER_MODE(ssp->save_srr1))
                while (ast_needed(cpu_number())) {
-                       ast_taken(FALSE, AST_ALL, intr);
+                       ast_taken(AST_ALL, intr);
                        ml_set_interrupts_enabled(FALSE);
                }
 
@@ -566,30 +671,31 @@ struct ppc_saved_state *trap(int trapno,
  * It must preserve r3.
  */
 
-extern int syscall_trace(int, struct ppc_saved_state *);
+extern int syscall_trace(int, struct savearea *);
 
 
 extern int pmdebug;
 
-int syscall_trace(int retval, struct ppc_saved_state *ssp)
+int syscall_trace(int retval, struct savearea *ssp)
 {
        int i, argc;
-
        int kdarg[3];
-       /* Always prepare to trace mach system calls */
-       if (kdebug_enable && (ssp->r0 & 0x80000000)) {
-         /* Mach trap */
-         kdarg[0]=0;
-         kdarg[1]=0;
-         kdarg[2]=0;
-         argc = mach_trap_table[-(ssp->r0)].mach_trap_arg_count;
-         if (argc > 3)
-           argc = 3;
-         for (i=0; i < argc; i++)
-           kdarg[i] = (int)*(&ssp->r3 + i);
-         KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_SC, (-(ssp->r0))) | DBG_FUNC_START,
-                      kdarg[0], kdarg[1], kdarg[2], 0, 0);
-       }           
+/* Always prepare to trace mach system calls */
+
+       kdarg[0]=0;
+       kdarg[1]=0;
+       kdarg[2]=0;
+       
+       argc = mach_trap_table[-((unsigned int)ssp->save_r0)].mach_trap_arg_count;
+       
+       if (argc > 3)
+               argc = 3;
+       
+       for (i=0; i < argc; i++)
+               kdarg[i] = (int)*(&ssp->save_r3 + i);
+       
+       KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_SC, (-(ssp->save_r0))) | DBG_FUNC_START,
+               kdarg[0], kdarg[1], kdarg[2], 0, 0);
 
        return retval;
 }
@@ -598,15 +704,12 @@ int syscall_trace(int retval, struct ppc_saved_state *ssp)
  * It must preserve r3.
  */
 
-extern int syscall_trace_end(int, struct ppc_saved_state *);
+extern int syscall_trace_end(int, struct savearea *);
 
-int syscall_trace_end(int retval, struct ppc_saved_state *ssp)
+int syscall_trace_end(int retval, struct savearea *ssp)
 {
-       if (kdebug_enable && (ssp->r0 & 0x80000000)) {
-         /* Mach trap */
-         KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_SC,(-(ssp->r0))) | DBG_FUNC_END,
-                      retval, 0, 0, 0, 0);
-       }           
+       KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_SC,(-((unsigned int)ssp->save_r0))) | DBG_FUNC_END,
+               retval, 0, 0, 0, 0);
        return retval;
 }
 
@@ -618,7 +721,7 @@ int syscall_error(
        int exception,
        int code,
        int subcode,
-       struct ppc_saved_state *ssp)
+       struct savearea *ssp)
 {
        register thread_t thread;
 
@@ -627,7 +730,7 @@ int syscall_error(
        if (thread == 0)
            panic("syscall error in boot phase");
 
-       if (!USER_MODE(ssp->srr1))
+       if (!USER_MODE(ssp->save_srr1))
                panic("system call called from kernel");
 
        doexception(exception, code, subcode);
@@ -650,56 +753,64 @@ doexception(
 }
 
 char *trap_type[] = {
-       "0x000   Interrupt in vain",
-       "0x100   System reset",
-       "0x200   Machine check",
-       "0x300   Data access",
-       "0x400   Instruction access",
-       "0x500   External interrupt",
-       "0x600   Alignment",
-       "0x700   Program",
-       "0x800   Floating point",
-       "0x900   Decrementer",
-       "0xA00   I/O controller interface",
-       "0xB00   INVALID EXCEPTION",
-       "0xC00   System call exception",
-       "0xD00   Trace",
-       "0xE00   FP assist",
-       "0xF20   VMX",
-       "0xF00   INVALID EXCEPTION",
-       "0x1000  Instruction PTE miss",
-       "0x1100  Data load PTE miss",
-       "0x1200  Data store PTE miss",
-       "0x1300  Instruction Breakpoint",
-       "0x1400  System Management",
-       "0x1500  INVALID EXCEPTION",
-       "0x1600  Altivec Assist",
-       "0x1700  INVALID EXCEPTION",
-       "0x1800  INVALID EXCEPTION",
-       "0x1900  INVALID EXCEPTION",
-       "0x1A00  INVALID EXCEPTION",
-       "0x1B00  INVALID EXCEPTION",
-       "0x1C00  INVALID EXCEPTION",
-       "0x1D00  INVALID EXCEPTION",
-       "0x1E00  INVALID EXCEPTION",
-       "0x1F00  INVALID EXCEPTION",
-       "0x2000  Run Mode/Trace"
+       "Unknown",
+       "0x100 - System reset",
+       "0x200 - Machine check",
+       "0x300 - Data access",
+       "0x400 - Inst access",
+       "0x500 - Ext int",
+       "0x600 - Alignment",
+       "0x700 - Program",
+       "0x800 - Floating point",
+       "0x900 - Decrementer",
+       "0xA00 - n/a",
+       "0xB00 - n/a",
+       "0xC00 - System call",
+       "0xD00 - Trace",
+       "0xE00 - FP assist",
+       "0xF00 - Perf mon",
+       "0xF20 - VMX",
+       "INVALID EXCEPTION",
+       "INVALID EXCEPTION",
+       "INVALID EXCEPTION",
+       "0x1300 - Inst bkpnt",
+       "0x1400 - Sys mgmt",
+       "0x1600 - Altivec Assist",
+       "0x1700 - Thermal",
+       "INVALID EXCEPTION",
+       "INVALID EXCEPTION",
+       "INVALID EXCEPTION",
+       "INVALID EXCEPTION",
+       "INVALID EXCEPTION",
+       "INVALID EXCEPTION",
+       "INVALID EXCEPTION",
+       "INVALID EXCEPTION",
+       "Emulate",
+       "0x2000 - Run Mode/Trace",
+       "Signal Processor",
+       "Preemption",
+       "Context Switch",
+       "Shutdown",
+       "System Failure"
 };
 int TRAP_TYPES = sizeof (trap_type) / sizeof (trap_type[0]);
 
 void unresolved_kernel_trap(int trapno,
-                           struct ppc_saved_state *ssp,
+                           struct savearea *ssp,
                            unsigned int dsisr,
-                           unsigned int dar,
+                           addr64_t dar,
                            char *message)
 {
        char *trap_name;
-       extern void print_backtrace(struct ppc_saved_state *);
+       extern void print_backtrace(struct savearea *);
        extern unsigned int debug_mode, disableDebugOuput;
 
        ml_set_interrupts_enabled(FALSE);                                       /* Turn off interruptions */
+       lastTrace = LLTraceSet(0);                                                      /* Disable low-level tracing */
 
-       disableDebugOuput = FALSE;
+       if( logPanicDataToScreen )
+               disableDebugOuput = FALSE;
+       
        debug_mode++;
        if ((unsigned)trapno <= T_MAX)
                trap_name = trap_type[trapno / T_VECTOR_SIZE];
@@ -708,29 +819,55 @@ void unresolved_kernel_trap(int trapno,
        if (message == NULL)
                message = trap_name;
 
-       printf("\n\nUnresolved kernel trap(cpu %d): %s DSISR=0x%08x DAR=0x%08x PC=0x%08x, MSR=0x%08X\n"
-              "generating stack backtrace prior to panic:\n\n",
-              cpu_number(), trap_name, dsisr, dar, ssp->srr0, ssp->srr1);
+       kdb_printf("\n\nUnresolved kernel trap(cpu %d): %s DAR=0x%016llX PC=0x%016llX\n",
+              cpu_number(), trap_name, dar, ssp->save_srr0);
 
        print_backtrace(ssp);
 
-       (void *)Call_Debugger(trapno, ssp);
+       draw_panic_dialog();
+               
+       if( panicDebugging )
+               (void *)Call_Debugger(trapno, ssp);
        panic(message);
 }
 
+char *corr[2] = {"uncorrected", "corrected  "};
+
+void handleMck(struct savearea *ssp) {                                 /* Common machine check handler */
+
+       int cpu;
+       
+       cpu = cpu_number();
+
+       printf("Machine check (%d) - %s - pc = %016llX, msr = %016llX, dsisr = %08X, dar = %016llX\n",
+               cpu, corr[ssp->save_hdr.save_misc3], ssp->save_srr0, ssp->save_srr1, ssp->save_dsisr, ssp->save_dar);           /* Tell us about it */
+       printf("Machine check (%d) -   AsyncSrc = %016llX, CoreFIR = %016llx\n", cpu, ssp->save_xdat0, ssp->save_xdat1);
+       printf("Machine check (%d) -      L2FIR = %016llX,  BusFir = %016llx\n", cpu, ssp->save_xdat2, ssp->save_xdat3);
+       
+       if(ssp->save_hdr.save_misc3) return;                            /* Leave the the machine check was recovered */
+
+       panic("Uncorrectable machine check: pc = %016llX, msr = %016llX, dsisr = %08X, dar = %016llX\n"
+             "  AsyncSrc = %016llX, CoreFIR = %016llx\n"
+             "     L2FIR = %016llX,  BusFir = %016llx\n",
+                 ssp->save_srr0, ssp->save_srr1, ssp->save_dsisr, ssp->save_dar, 
+                 ssp->save_xdat0, ssp->save_xdat1, ssp->save_xdat2, ssp->save_xdat3);
+       
+       return;
+}
+
 void
 thread_syscall_return(
         kern_return_t ret)
 {
         register thread_act_t   thr_act = current_act();
-        register struct ppc_saved_state *regs = USER_REGS(thr_act);
+        register struct savearea *regs = USER_REGS(thr_act);
 
-       if (kdebug_enable && (regs->r0 & 0x80000000)) {
+       if (kdebug_enable && ((unsigned int)regs->save_r0 & 0x80000000)) {
          /* Mach trap */
-         KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_SC,(-(regs->r0))) | DBG_FUNC_END,
+         KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_SC,(-(regs->save_r0))) | DBG_FUNC_END,
                       ret, 0, 0, 0, 0);
        }           
-        regs->r3 = ret;
+        regs->save_r3 = ret;
 
         thread_exception_return();
         /*NOTREACHED*/
@@ -743,9 +880,9 @@ thread_kdb_return(void)
 {
        register thread_act_t   thr_act = current_act();
        register thread_t       cur_thr = current_thread();
-       register struct ppc_saved_state *regs = USER_REGS(thr_act);
+       register struct savearea *regs = USER_REGS(thr_act);
 
-       Call_Debugger(thr_act->mact.pcb->es.exception, regs);
+       Call_Debugger(thr_act->mact.pcb->save_exception, regs);
 #if            MACH_LDEBUG
        assert(cur_thr->mutex_count == 0); 
 #endif         /* MACH_LDEBUG */