#include <mach_kdb.h>
#include <mach_kdp.h>
#include <debug.h>
#include <mach/mach_types.h>
#include <mach/mach_traps.h>
#include <mach/thread_status.h>
#include <kern/processor.h>
#include <kern/thread.h>
#include <kern/exception.h>
#include <kern/syscall_sw.h>
#include <kern/cpu_data.h>
#include <kern/debug.h>
#include <vm/vm_fault.h>
#include <vm/vm_kern.h>
#include <ppc/misc_protos.h>
#include <ppc/trap.h>
#include <ppc/exception.h>
#include <ppc/proc_reg.h>
#include <ppc/pmap.h>
#include <ppc/mem.h>
#include <ppc/mappings.h>
#include <ppc/Firmware.h>
#include <ppc/low_trace.h>
#include <ppc/Diagnostics.h>
#include <ppc/hw_perfmon.h>
#include <ppc/fpu_protos.h>
#include <sys/kdebug.h>
volatile perfCallback perfTrapHook;
volatile perfCallback perfASTHook;
#if CONFIG_DTRACE
extern kern_return_t dtrace_user_probe(ppc_saved_state_t *sv);
perfCallback tempDTraceTrapHook = NULL;
extern boolean_t dtrace_tally_fault(user_addr_t);
#endif
#if MACH_KDB
#include <ddb/db_watch.h>
#include <ddb/db_run.h>
#include <ddb/db_break.h>
#include <ddb/db_trap.h>
boolean_t let_ddb_vm_fault = FALSE;
boolean_t debug_all_traps_with_kdb = FALSE;
extern struct db_watchpoint *db_watchpoint_list;
extern boolean_t db_watchpoints_inserted;
extern boolean_t db_breakpoints_inserted;
#endif
extern task_t bsd_init_task;
extern char init_task_failure_data[];
extern int not_in_kdp;
#define PROT_EXEC (VM_PROT_EXECUTE)
#define PROT_RO (VM_PROT_READ)
#define PROT_RW (VM_PROT_READ|VM_PROT_WRITE)
#define UPDATE_PPC_EXCEPTION_STATE { \
thread_t _thread = current_thread(); \
_thread->machine.pcb->save_dar = (uint64_t)dar; \
_thread->machine.pcb->save_dsisr = dsisr; \
_thread->machine.pcb->save_exception = trapno / T_VECTOR_SIZE; \
}
void unresolved_kernel_trap(int trapno,
struct savearea *ssp,
unsigned int dsisr,
addr64_t dar,
const char *message);
static void handleMck(struct savearea *ssp);
#ifdef MACH_BSD
extern void get_procrustime(time_value_t *);
extern void bsd_uprofil(time_value_t *, user_addr_t);
#endif
struct savearea *trap(int trapno,
struct savearea *ssp,
unsigned int dsisr,
addr64_t dar)
{
int exception;
mach_exception_code_t code = 0;
mach_exception_subcode_t subcode = 0;
vm_map_t map;
vm_map_offset_t offset;
thread_t thread = current_thread();
boolean_t intr;
ast_t *myast;
int ret;
#ifdef MACH_BSD
time_value_t tv;
#endif
myast = ast_pending();
perfCallback fn = perfASTHook;
if(fn) {
if(*myast & AST_CHUD_ALL) {
fn(trapno, ssp, dsisr, (unsigned int)dar);
}
} else {
*myast &= ~AST_CHUD_ALL;
}
fn = perfTrapHook;
if(fn) {
if(fn(trapno, ssp, dsisr, (unsigned int)dar) == KERN_SUCCESS) return ssp;
}
#if CONFIG_DTRACE
if(tempDTraceTrapHook) {
if(tempDTraceTrapHook(trapno, ssp, dsisr, (unsigned int)dar) == KERN_SUCCESS) return ssp;
}
#endif
#if 0
{
extern void fctx_text(void);
fctx_test();
}
#endif
exception = 0;
intr = (ssp->save_srr1 & MASK(MSR_EE)) != 0;
if (!USER_MODE(ssp->save_srr1)) {
switch (trapno) {
case T_PREEMPT:
ast_taken(AST_PREEMPTION, FALSE);
break;
case T_PERF_MON:
perfmon_handle_pmi(ssp);
break;
case T_RESET:
if (!Call_Debugger(trapno, ssp))
unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
break;
case T_DECREMENTER:
case T_IN_VAIN:
case T_SYSTEM_MANAGEMENT:
case T_ALTIVEC_ASSIST:
case T_INTERRUPT:
case T_FP_UNAVAILABLE:
case T_IO_ERROR:
case T_RESERVED:
default:
unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
break;
case T_MACHINE_CHECK:
handleMck(ssp);
break;
case T_ALIGNMENT:
if(ssp->save_hdr.save_misc3) {
unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
break;
}
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:
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:
case T_INSTRUCTION_BKPT:
if (!Call_Debugger(trapno, ssp))
unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
break;
case T_PROGRAM:
if (ssp->save_srr1 & MASK(SRR1_PRG_TRAP)) {
if (!Call_Debugger(trapno, ssp))
unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
} else {
unresolved_kernel_trap(trapno, ssp,
dsisr, dar, NULL);
}
break;
case T_DATA_ACCESS:
#if MACH_KDB
mp_disable_preemption();
if (debug_mode
&& getPerProc()->debugger_active
&& !let_ddb_vm_fault) {
kdb_trap(trapno, ssp);
}
mp_enable_preemption();
#endif
if (debug_mode
&& getPerProc()->debugger_active
&& !not_in_kdp) {
kdp_dump_trap(trapno, ssp);
}
if(ssp->save_dsisr & dsiInvMode) {
panic("trap: disallowed access to cache inhibited memory - %016llX\n", dar);
}
if(intr) ml_set_interrupts_enabled(TRUE);
if(((dar >> 28) < 0xE) | ((dar >> 28) > 0xF)) {
offset = (vm_map_offset_t)dar;
map = kernel_map;
if((0 == (offset & -PAGE_SIZE)) &&
((thread->machine.specFlags) & ignoreZeroFault)) {
ssp->save_srr0 += 4;
break;
}
#if CONFIG_DTRACE
if (thread->options & TH_OPT_DTRACE) {
if (dtrace_tally_fault(dar)) {
ssp->save_srr0 += 4;
break;
} else {
unresolved_kernel_trap(trapno, ssp, dsisr, dar, "Unexpected page fault under dtrace_probe");
}
}
#endif
code = vm_fault(map, vm_map_trunc_page(offset),
dsisr & MASK(DSISR_WRITE) ? PROT_RW : PROT_RO,
FALSE, THREAD_UNINT, NULL, vm_map_trunc_page(0));
if (code != KERN_SUCCESS) {
unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
} else {
ssp->save_hdr.save_flags |= SAVredrive;
ssp->save_dsisr = (ssp->save_dsisr &
~((MASK(DSISR_NOEX) | MASK(DSISR_PROT)))) | MASK(DSISR_HASH);
}
break;
}
#if CONFIG_DTRACE
if (thread->options & TH_OPT_DTRACE) {
if (dtrace_tally_fault(dar)) {
if (thread->recover) {
ssp->save_srr0 = thread->recover;
thread->recover = (vm_offset_t)NULL;
} else {
unresolved_kernel_trap(trapno, ssp, dsisr, dar, "copyin/out has no recovery point");
}
break;
} else {
unresolved_kernel_trap(trapno, ssp, dsisr, dar, "Unexpected UMW page fault under dtrace_probe");
}
}
#endif
map = thread->map;
offset = (vm_map_offset_t)(thread->machine.umwRelo + dar);
code = vm_fault(map, vm_map_trunc_page(offset),
dsisr & MASK(DSISR_WRITE) ? PROT_RW : PROT_RO,
FALSE, THREAD_UNINT, NULL, vm_map_trunc_page(0));
if (code != KERN_SUCCESS) {
if (thread->recover) {
ssp->save_srr0 = thread->recover;
thread->recover = (vm_offset_t)NULL;
} else {
unresolved_kernel_trap(trapno, ssp, dsisr, dar, "copyin/out has no recovery point");
}
}
else {
ssp->save_hdr.save_flags |= SAVredrive;
ssp->save_dsisr = (ssp->save_dsisr &
~((MASK(DSISR_NOEX) | MASK(DSISR_PROT)))) | MASK(DSISR_HASH);
}
break;
case T_INSTRUCTION_ACCESS:
#if MACH_KDB
if (debug_mode
&& getPerProc()->debugger_active
&& !let_ddb_vm_fault) {
kdb_trap(trapno, ssp);
}
#endif
if(intr) ml_set_interrupts_enabled(TRUE);
map = kernel_map;
code = vm_fault(map, vm_map_trunc_page(ssp->save_srr0),
(PROT_EXEC | PROT_RO), FALSE, THREAD_UNINT, NULL, vm_map_trunc_page(0));
if (code != KERN_SUCCESS) {
unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
} else {
ssp->save_hdr.save_flags |= SAVredrive;
ssp->save_srr1 = (ssp->save_srr1 &
~((unsigned long long)(MASK(DSISR_NOEX) | MASK(DSISR_PROT)))) | MASK(DSISR_HASH);
}
break;
case T_SYSTEM_CALL:
unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
break;
case T_AST:
unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
break;
}
} else {
if (trapno != T_AST)
ml_set_interrupts_enabled(TRUE);
#ifdef MACH_BSD
{
get_procrustime(&tv);
}
#endif
switch (trapno) {
case T_PREEMPT:
unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
break;
case T_PERF_MON:
perfmon_handle_pmi(ssp);
break;
case T_DECREMENTER:
case T_IN_VAIN:
case T_INTERRUPT:
case T_FP_UNAVAILABLE:
case T_SYSTEM_MANAGEMENT:
case T_RESERVED:
case T_IO_ERROR:
default:
ml_set_interrupts_enabled(FALSE);
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;
case T_MACHINE_CHECK:
handleMck(ssp);
break;
case T_RESET:
ml_set_interrupts_enabled(FALSE);
if (!Call_Debugger(trapno, ssp))
panic("Unexpected Reset exception: srr0 = %016llx, srr1 = %016llx\n",
ssp->save_srr0, ssp->save_srr1);
break;
case T_ALIGNMENT:
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);
if(ssp->save_hdr.save_misc3) {
exception = EXC_BAD_ACCESS;
code = EXC_PPC_UNALIGNED;
subcode = dar;
}
break;
case T_EMULATE:
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_INSTRUCTION_BKPT:
exception = EXC_BREAKPOINT;
code = EXC_PPC_TRACE;
subcode = ssp->save_srr0;
break;
case T_PROGRAM:
if (ssp->save_srr1 & MASK(SRR1_PRG_FE)) {
fpu_save(thread->machine.curctx);
UPDATE_PPC_EXCEPTION_STATE;
exception = EXC_ARITHMETIC;
code = EXC_ARITHMETIC;
mp_disable_preemption();
subcode = ssp->save_fpscr;
mp_enable_preemption();
}
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->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->save_srr0;
} else if (ssp->save_srr1 & MASK(SRR1_PRG_TRAP)) {
unsigned int inst;
if (copyin(ssp->save_srr0, (char *) &inst, 4 )) panic("copyin failed\n");
if(dgWork.dgFlags & enaDiagTrap) {
if((inst & 0xFFFFFFF0) == 0x0FFFFFF0) {
if(diagTrap(ssp, inst & 0xF)) {
ssp->save_srr0 += 4ULL;
exception = 0;
break;
}
}
}
#if CONFIG_DTRACE
if(inst == 0x0FFFDDDD) {
ret = dtrace_user_probe((ppc_saved_state_t *)ssp);
if(ret == KERN_SUCCESS) {
exception = 0;
break;
}
}
#endif
UPDATE_PPC_EXCEPTION_STATE;
if (inst == 0x7FE00008) {
exception = EXC_BREAKPOINT;
code = EXC_PPC_BREAKPOINT;
} else {
exception = EXC_SOFTWARE;
code = EXC_PPC_TRAP;
}
subcode = ssp->save_srr0;
}
break;
#if CONFIG_DTRACE
case T_DTRACE_RET:
ret = dtrace_user_probe((ppc_saved_state_t *)ssp);
if(ret == KERN_SUCCESS) {
exception = 0;
break;
}
break;
#endif
case T_ALTIVEC_ASSIST:
UPDATE_PPC_EXCEPTION_STATE;
exception = EXC_ARITHMETIC;
code = EXC_PPC_ALTIVECASSIST;
subcode = ssp->save_srr0;
break;
case T_DATA_ACCESS:
map = thread->map;
if(ssp->save_dsisr & dsiInvMode) {
UPDATE_PPC_EXCEPTION_STATE;
exception = EXC_BAD_ACCESS;
subcode = dar;
break;
}
code = vm_fault(map, vm_map_trunc_page(dar),
dsisr & MASK(DSISR_WRITE) ? PROT_RW : PROT_RO,
FALSE, THREAD_ABORTSAFE, NULL, vm_map_trunc_page(0));
if ((code != KERN_SUCCESS) && (code != KERN_ABORTED)) {
UPDATE_PPC_EXCEPTION_STATE;
exception = EXC_BAD_ACCESS;
subcode = dar;
} else {
ssp->save_hdr.save_flags |= SAVredrive;
ssp->save_dsisr = (ssp->save_dsisr &
~((MASK(DSISR_NOEX) | MASK(DSISR_PROT)))) | MASK(DSISR_HASH);
}
break;
case T_INSTRUCTION_ACCESS:
map = thread->map;
code = vm_fault(map, vm_map_trunc_page(ssp->save_srr0),
(PROT_EXEC | PROT_RO), FALSE, THREAD_ABORTSAFE, NULL, vm_map_trunc_page(0));
if ((code != KERN_SUCCESS) && (code != KERN_ABORTED)) {
UPDATE_PPC_EXCEPTION_STATE;
exception = EXC_BAD_ACCESS;
subcode = ssp->save_srr0;
} else {
ssp->save_hdr.save_flags |= SAVredrive;
ssp->save_srr1 = (ssp->save_srr1 &
~((unsigned long long)(MASK(DSISR_NOEX) | MASK(DSISR_PROT)))) | MASK(DSISR_HASH);
}
break;
case T_AST:
break;
}
#ifdef MACH_BSD
{
bsd_uprofil(&tv, ssp->save_srr0);
}
#endif
}
if (exception) {
#if 0
if(bsd_init_task == current_task()) {
char *buf;
int i;
buf = init_task_failure_data;
buf += sprintf(buf, "Exception Code = 0x%x, Subcode = 0x%x\n", code, subcode);
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->save_r0+i));
}
buf += sprintf(buf, "\n\n");
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");
buf += sprintf(buf, "Application level back trace:\n");
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(ssp->save_r1,(char*)stack_buf,
3 * sizeof(int))) {
buf += sprintf(buf, "0x%08X : 0x%08X\n"
,addr,stack_buf[2]);
addr = (char*)stack_buf[0];
} else {
break;
}
}
}
buf[0] = '\0';
}
#endif
doexception(exception, code, subcode);
}
ml_set_interrupts_enabled(FALSE);
if (USER_MODE(ssp->save_srr1)) {
myast = ast_pending();
while (*myast & AST_ALL) {
ast_taken(AST_ALL, intr);
ml_set_interrupts_enabled(FALSE);
myast = ast_pending();
}
}
return ssp;
}
extern int syscall_trace(int, struct savearea *);
extern int pmdebug;
int syscall_trace(int retval, struct savearea *ssp)
{
int i, argc;
int kdarg[3];
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;
}
extern int syscall_trace_end(int, struct savearea *);
int syscall_trace_end(int retval, struct savearea *ssp)
{
KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_SC,(-((unsigned int)ssp->save_r0))) | DBG_FUNC_END,
retval, 0, 0, 0, 0);
return retval;
}
int syscall_error(
int exception,
mach_exception_code_t code,
mach_exception_subcode_t subcode,
struct savearea *ssp)
{
register thread_t thread;
thread = current_thread();
if (thread == 0)
panic("syscall error in boot phase");
if (!USER_MODE(ssp->save_srr1))
panic("system call called from kernel");
doexception(exception, code, subcode);
return 0;
}
void
doexception(
int exc,
mach_exception_code_t code,
mach_exception_subcode_t sub)
{
mach_exception_data_type_t codes[EXCEPTION_CODE_MAX];
codes[0] = code;
codes[1] = sub;
exception_triage(exc, codes, 2);
}
const char *trap_type[] = {
"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 savearea *ssp,
__unused unsigned int dsisr,
addr64_t dar,
const char *message)
{
const char *trap_name;
ml_set_interrupts_enabled(FALSE);
lastTrace = LLTraceSet(0);
#if 0
{
struct per_proc_info *pp;
kprintf(" srr0: %016llX\n", ssp->save_srr0);
kprintf(" srr1: %016llX\n", ssp->save_srr1);
kprintf(" dar: %016llX\n", ssp->save_dar);
kprintf(" xcp: %08X\n", ssp->save_exception);
kprintf(" ins0: %08X\n", ssp->save_instr[0]);
kprintf(" ins1: %08X\n", ssp->save_instr[1]);
kprintf(" ins2: %08X\n", ssp->save_instr[2]);
kprintf(" ins3: %08X\n", ssp->save_instr[3]);
kprintf(" ins4: %08X\n", ssp->save_instr[4]);
kprintf(" ins5: %08X\n", ssp->save_instr[5]);
kprintf(" ins6: %08X\n", ssp->save_instr[6]);
kprintf(" ins7: %08X\n", ssp->save_instr[7]);
pp = getPerProc();
kprintf("ijsave: %016llX\n", pp->ijsave);
}
#endif
if( logPanicDataToScreen )
disable_debug_output = FALSE;
debug_mode++;
if ((unsigned)trapno <= T_MAX)
trap_name = trap_type[trapno / T_VECTOR_SIZE];
else
trap_name = "???? unrecognized exception";
if (message == NULL)
message = trap_name;
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);
panic_caller = (0xFFFF0000 | (trapno / T_VECTOR_SIZE) );
if (panicDebugging)
commit_paniclog();
draw_panic_dialog();
if( panicDebugging )
(void)Call_Debugger(trapno, ssp);
panic_plain("%s", message);
}
const char *corr[2] = {"uncorrected", "corrected "};
void handleMck(struct savearea *ssp) {
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);
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;
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_t thread = current_thread();
register struct savearea *regs = USER_REGS(thread);
if (kdebug_enable && ((unsigned int)regs->save_r0 & 0x80000000)) {
KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_SC,(-(regs->save_r0))) | DBG_FUNC_END,
ret, 0, 0, 0, 0);
}
regs->save_r3 = ret;
thread_exception_return();
}
#if MACH_KDB
void
thread_kdb_return(void)
{
register thread_t thread = current_thread();
register struct savearea *regs = USER_REGS(thread);
Call_Debugger(thread->machine.pcb->save_exception, regs);
thread_exception_return();
}
#endif