#include <mach_assert.h>
#include <mach_kdb.h>
#include <mach_kgdb.h>
#include <mach_kdp.h>
#include <kern/cpu_number.h>
#include <kern/lock.h>
#include <kern/spl.h>
#include <kern/thread.h>
#include <kern/assert.h>
#include <kern/sched_prim.h>
#include <kern/misc_protos.h>
#include <vm/vm_kern.h>
#include <vm/pmap.h>
#include <stdarg.h>
#ifdef __ppc__
#include <ppc/Firmware.h>
#include <ppc/low_trace.h>
#endif
unsigned int halt_in_debugger = 0;
unsigned int switch_debugger = 0;
unsigned int current_debugger = 0;
unsigned int active_debugger = 0;
unsigned int debug_mode=0;
unsigned int disableDebugOuput = TRUE;
unsigned int systemLogDiags = FALSE;
unsigned int logPanicDataToScreen = FALSE;
unsigned int panicDebugging = FALSE;
int mach_assert = 1;
const char *panicstr = (char *) 0;
decl_simple_lock_data(,panic_lock)
int paniccpu;
volatile int panicwait;
volatile unsigned int nestedpanic= 0;
unsigned int panic_is_inited = 0;
unsigned int return_on_panic = 0;
unsigned long panic_caller;
char *debug_buf;
ppnum_t debug_buf_page;
char *debug_buf_ptr;
unsigned int debug_buf_size = 0;
void
Assert(
const char *file,
int line,
const char *expression)
{
if (!mach_assert) {
return;
}
panic("{%d} Assertion failed: file \"%s\", line %d: %s\n",
cpu_number(), file, line, expression);
}
#define PANIC_LOCK() \
MACRO_BEGIN \
if (panic_is_inited) \
simple_lock(&panic_lock); \
MACRO_END
#define PANIC_UNLOCK() \
MACRO_BEGIN \
if (panic_is_inited) \
simple_unlock(&panic_lock); \
MACRO_END
void
panic_init(void)
{
simple_lock_init(&panic_lock, 0);
panic_is_inited = 1;
panic_caller = 0;
}
void
panic(const char *str, ...)
{
va_list listp;
spl_t s;
thread_t thread;
wait_queue_t wq;
s = splhigh();
disable_preemption();
#ifdef __ppc__
lastTrace = LLTraceSet(0);
#endif
thread = current_thread();
wq = thread->wait_queue;
thread->wait_queue = 0;
if( logPanicDataToScreen )
disableDebugOuput = FALSE;
debug_mode = TRUE;
if ( ! panic_caller )
panic_caller = (unsigned long) __builtin_return_address(0);
restart:
PANIC_LOCK();
if (panicstr) {
if (cpu_number() != paniccpu) {
PANIC_UNLOCK();
while (panicwait)
continue;
goto restart;
} else {
nestedpanic +=1;
PANIC_UNLOCK();
Debugger("double panic");
printf("double panic: We are hanging here...\n");
while(1);
}
}
panicstr = str;
paniccpu = cpu_number();
panicwait = 1;
PANIC_UNLOCK();
kdb_printf("panic(cpu %d caller 0x%08X): ", (unsigned) paniccpu, panic_caller);
va_start(listp, str);
_doprnt(str, &listp, consdebug_putc, 0);
va_end(listp);
kdb_printf("\n");
panicwait = 0;
Debugger("panic");
PANIC_LOCK();
panicstr = (char *)0;
PANIC_UNLOCK();
thread->wait_queue = wq;
if (return_on_panic) {
enable_preemption();
splx(s);
return;
}
kdb_printf("panic: We are hanging here...\n");
while(1);
}
void
log(int level, char *fmt, ...)
{
va_list listp;
#ifdef lint
level++;
#endif
#ifdef MACH_BSD
disable_preemption();
va_start(listp, fmt);
_doprnt(fmt, &listp, conslog_putc, 0);
va_end(listp);
enable_preemption();
#endif
}
void
debug_log_init(void)
{
if (debug_buf_size != 0)
return;
if (kmem_alloc(kernel_map, (vm_offset_t *) &debug_buf, PAGE_SIZE) != KERN_SUCCESS)
panic("cannot allocate debug_buf \n");
debug_buf_ptr = debug_buf;
debug_buf_size = PAGE_SIZE;
debug_buf_page = pmap_find_phys(kernel_pmap, (addr64_t)(uintptr_t)debug_buf_ptr);
}
void
debug_putc(char c)
{
if ((debug_buf_size != 0) && ((debug_buf_ptr-debug_buf) < debug_buf_size)) {
*debug_buf_ptr=c;
debug_buf_ptr++;
}
}