kern_return_t bsd_exception( exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt) { task_t task; struct exception_action *excp; lck_mtx_t *mutex; thread_t self = current_thread(); kern_return_t kr; /* * Maybe the task level will handle it. */ task = current_task(); mutex = &task->lock; excp = &task->exc_actions[exception]; kr = exception_deliver(self, exception, code, codeCnt, excp, mutex); if (kr == KERN_SUCCESS || kr == MACH_RCV_PORT_DIED) return(KERN_SUCCESS); return(KERN_FAILURE); }
/* * Trap handler * Invoke the exception handler if it is needed. */ void trap_handler(struct cpu_regs *regs) { uint32_t trap_no = regs->trap_no; #ifdef CONFIG_MMU switch (trap_no) { case TRAP_DATA_TLB_MISS: case TRAP_INST_TLB_MISS: handle_tlb_miss(regs); return; }; #endif #ifdef DEBUG printf("============================\n"); printf("Trap %x: %s\n", trap_no, trap_name[trap_no]); printf("============================\n"); trap_dump(regs); for (;;) ; #endif if ((regs->srr1 & MSR_PR) != MSR_PR) panic("Kernel exception"); exception_mark(exception_map[trap_no]); exception_deliver(); }
/* * Handle interface for special performance monitoring * This is a special case of the host exception handler */ kern_return_t sys_perf_notify(thread_t thread, int pid) { host_priv_t hostp; struct exception_action *excp; ipc_port_t xport; wait_interrupt_t wsave; kern_return_t ret; hostp = host_priv_self(); /* Get the host privileged ports */ mach_exception_data_type_t code[EXCEPTION_CODE_MAX]; code[0] = 0xFF000001; /* Set terminate code */ code[1] = pid; /* Pass out the pid */ struct task *task = thread->task; excp = &hostp->exc_actions[EXC_RPC_ALERT]; xport = excp->port; /* Make sure we're not catching our own exception */ if (!IP_VALID(xport) || !ip_active(xport) || task->itk_space == xport->data.receiver) { return(KERN_FAILURE); } wsave = thread_interrupt_level(THREAD_UNINT); ret = exception_deliver( thread, EXC_RPC_ALERT, code, 2, excp, &hostp->lock); (void)thread_interrupt_level(wsave); return(ret); }
/* * Routine: exception * Purpose: * The current thread caught an exception. * We make an up-call to the thread's exception server. * Conditions: * Nothing locked and no resources held. * Called from an exception context, so * thread_exception_return and thread_kdb_return * are possible. * Returns: * Doesn't return. */ void exception_triage( exception_type_t exception, mach_exception_data_t code, mach_msg_type_number_t codeCnt) { thread_t thread; task_t task; host_priv_t host_priv; struct exception_action *excp; lck_mtx_t *mutex; kern_return_t kr; assert(exception != EXC_RPC_ALERT); if (exception == KERN_SUCCESS) panic("exception"); /* * Try to raise the exception at the activation level. */ thread = current_thread(); mutex = &thread->mutex; excp = &thread->exc_actions[exception]; kr = exception_deliver(thread, exception, code, codeCnt, excp, mutex); if (kr == KERN_SUCCESS || kr == MACH_RCV_PORT_DIED) goto out; /* * Maybe the task level will handle it. */ task = current_task(); mutex = &task->lock; excp = &task->exc_actions[exception]; kr = exception_deliver(thread, exception, code, codeCnt, excp, mutex); if (kr == KERN_SUCCESS || kr == MACH_RCV_PORT_DIED) goto out; /* * How about at the host level? */ host_priv = host_priv_self(); mutex = &host_priv->lock; excp = &host_priv->exc_actions[exception]; kr = exception_deliver(thread, exception, code, codeCnt, excp, mutex); if (kr == KERN_SUCCESS || kr == MACH_RCV_PORT_DIED) goto out; /* * Nobody handled it, terminate the task. */ #if MACH_KDB if (debug_user_with_kdb) { /* * Debug the exception with kdb. * If kdb handles the exception, * then thread_kdb_return won't return. */ db_printf("No exception server, calling kdb...\n"); thread_kdb_return(); } #endif /* MACH_KDB */ (void) task_terminate(task); out: if (exception != EXC_CRASH) thread_exception_return(); return; }