#pypp 0 // Iris: micro-kernel for a capability-based operating system. // panic.ccp: Stop running and try to notify the user of the problem. // Copyright 2009 Bas Wijnen // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #define ARCH #include "kernel.hh" #ifdef USE_SERIAL void dbg_log_char (unsigned ch): while !(UART0_LSR & UARTLSR_TDRQ): UART0_TDR = ch #else void dbg_log_char (unsigned ch): if !dbg_cap.valid () || dbg_code.l: return kCapability::Context c c.data[0] = ch ++dbg_code.l dbg_cap->invoke (&c) --dbg_code.l #endif void dbg_log (char const *str): while *str: dbg_log_char (*str++) void dbg_log_num (unsigned num, unsigned digits): char const *encode = "0123456789abcdef" for unsigned i = 0; i < digits; ++i: dbg_log_char (encode[(num >> (4 * ((digits - 1) - i))) & 0xf]) return #if 1 || defined (NDEBUG) static void panic_message (unsigned n, const char *line, char const *name, char const *message): //unsigned addr //cp0_get (CP0_BAD_V_ADDR, addr) //unsigned de = addr >> 21 //unsigned te = (addr >> 12) & ((1 << 9) - 1) //dbg_log_num ((unsigned)old_current->address_space->arch.directory[de]->page[te]) //dbg_log (":") //dbg_log_num (old_current->address_space->arch.directory[de]->entrylo[te]) //dbg_log ("\n") //__asm__ volatile ("tlbp") //unsigned idx, hi //cp0_get (CP0_INDEX, idx) //dbg_log_num (idx) //dbg_log (":") //cp0_get (CP0_ENTRY_HI, hi) //dbg_log_num (hi) //dbg_log (":") //unsigned lo //cp0_get (CP0_ENTRY_LO0, lo) //dbg_log_num (lo) //dbg_log (":") //cp0_get (CP0_ENTRY_LO1, lo) //dbg_log_num (lo) //dbg_log ("\n") dbg_log ("Panic: caller = ") if old_current: dbg_log_num (old_current->id, 2) dbg_log (":") dbg_log_num ((unsigned)old_current) if old_current: dbg_log_char ('@') dbg_log_num (old_current->pc) dbg_log ("; ") dbg_log (name) dbg_log_char (':') dbg_log (line) dbg_log (": ") dbg_log (message) dbg_log_char ('/') dbg_log_num (n) dbg_log_char (';') dbg_log_num (dbg_code.h) dbg_log (" bad vaddr = ") unsigned a cp0_get (CP0_BAD_V_ADDR, a) dbg_log_num (a) dbg_log (" epc = ") cp0_get (CP0_EPC, a) dbg_log_num (a) dbg_log_char ('\n') void panic_impl (unsigned n, const char *line, char const *name, char const *message): // Stop all threads. while first_scheduled: first_scheduled->unrun () for kReceiver *r = first_alarm; r; r = r->next_alarm: if r->owner: r->owner->unrun () for unsigned i = 0; i < 32; ++i: if arch_interrupt_receiver[i] && arch_interrupt_receiver[i]->owner: arch_interrupt_receiver[i]->owner->unrun () #ifndef NDEBUG // If a log capability is registered, run its owner. panic_message (n, line, name, message) if dbg_cap.valid () && dbg_cap->target->owner: #ifndef USE_SERIAL dbg_cap->target->owner->run () #endif // Use the (now running) log thread to display the message. // If no log capability is registered, the machine just hangs. #ifdef USE_SERIAL arch_reboot () #endif #endif #ifndef NDEBUG void dbg_send (unsigned num, unsigned bits): dbg_log ("Warning: ") dbg_log_num (num) dbg_log_char ('/') dbg_log_num (bits) dbg_log_char ('\n') #endif #else void delay (unsigned ms): for unsigned t = 0; t < 8000 * ms; ++t: GPIO_GPDIR (0) = GPIO_GPDIR (0) void set_leds (bool a, bool b): gpio_as_output (GPIO_NUM_PORT, GPIO_NUM) gpio_as_output (GPIO_CAPS_PORT, GPIO_CAPS) if a: GPIO_GPDR (GPIO_NUM_PORT) &= ~(1 << GPIO_NUM) else: GPIO_GPDR (GPIO_NUM_PORT) |= 1 << GPIO_NUM if b: GPIO_GPDR (GPIO_CAPS_PORT) &= ~(1 << GPIO_CAPS) else: GPIO_GPDR (GPIO_CAPS_PORT) |= 1 << GPIO_CAPS void dbg_send (unsigned n, unsigned bits): for unsigned i = 0; i < bits; ++i: bool v = n & (1 << (bits - 1)) set_leds (v, !v) delay (350) set_leds (false, false) delay (150) n <<= 1 set_leds (true, true) delay (50) set_leds (false, false) delay (50) void panic_impl (unsigned n, const char *line, char const *name, char const *message): unsigned epc cp0_get (CP0_EPC, epc) dbg_send (epc, 32) while true: dbg_send (n, 32) #endif