Root/
| 1 | #pypp 0 |
| 2 | // Iris: micro-kernel for a capability-based operating system. |
| 3 | // panic.ccp: Stop running and try to notify the user of the problem. |
| 4 | // Copyright 2009 Bas Wijnen <wijnen@debian.org> |
| 5 | // |
| 6 | // This program is free software: you can redistribute it and/or modify |
| 7 | // it under the terms of the GNU General Public License as published by |
| 8 | // the Free Software Foundation, either version 3 of the License, or |
| 9 | // (at your option) any later version. |
| 10 | // |
| 11 | // This program is distributed in the hope that it will be useful, |
| 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | // GNU General Public License for more details. |
| 15 | // |
| 16 | // You should have received a copy of the GNU General Public License |
| 17 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 18 | |
| 19 | #define ARCH |
| 20 | #include "kernel.hh" |
| 21 | |
| 22 | #ifdef USE_SERIAL |
| 23 | void kdebug (unsigned ch): |
| 24 | while !(UART0_LSR & UARTLSR_TDRQ): |
| 25 | UART0_TDR = ch |
| 26 | #else |
| 27 | void kdebug (unsigned ch): |
| 28 | if !dbg_cap.valid () || dbg_code.l: |
| 29 | return |
| 30 | kCapability::Context c |
| 31 | c.data[0] = ch |
| 32 | ++dbg_code.l |
| 33 | dbg_cap->invoke (&c) |
| 34 | --dbg_code.l |
| 35 | #endif |
| 36 | |
| 37 | void kdebug (char const *str): |
| 38 | while *str: |
| 39 | kdebug (*str++) |
| 40 | |
| 41 | void kdebug_num (unsigned num, unsigned digits): |
| 42 | char const *encode = "0123456789abcdef" |
| 43 | for unsigned i = 0; i < digits; ++i: |
| 44 | kdebug (encode[(num >> (4 * ((digits - 1) - i))) & 0xf]) |
| 45 | return |
| 46 | |
| 47 | #if 1 || defined (NDEBUG) |
| 48 | static void print_addr (char const *t, unsigned addr, bool last = false): |
| 49 | kdebug (t) |
| 50 | kdebug_num (addr) |
| 51 | #if 0 |
| 52 | unsigned de = addr >> 21 |
| 53 | unsigned te = (addr >> 12) & ((1 << 9) - 1) |
| 54 | if de < 0x400 && old_current && old_current->address_space->arch.directory && old_current->address_space->arch.directory[de]: |
| 55 | kdebug ("; EntryLo = ") |
| 56 | kdebug_num (old_current->address_space->arch.directory[de]->entrylo[te]) |
| 57 | else: |
| 58 | kdebug ("; no directory or page table") |
| 59 | if old_current && de < 0x400: |
| 60 | cp0_set (CP0_ENTRY_HI, (addr & (PAGE_MASK << 1)) | old_current->address_space->arch.asid) |
| 61 | __asm__ volatile ("tlbp") |
| 62 | unsigned idx, hi |
| 63 | cp0_get (CP0_INDEX, idx) |
| 64 | kdebug ("; tlb index: ") |
| 65 | if idx & (1 << 31): |
| 66 | kdebug ("none\n") |
| 67 | else: |
| 68 | __asm__ volatile ("tlbr") |
| 69 | kdebug_num (idx, 2) |
| 70 | kdebug ("; EntryLo = ") |
| 71 | unsigned lo |
| 72 | cp0_get (CP0_ENTRY_LO0, lo) |
| 73 | kdebug_num (lo) |
| 74 | kdebug (":") |
| 75 | cp0_get (CP0_ENTRY_LO1, lo) |
| 76 | kdebug_num (lo) |
| 77 | kdebug ("\n") |
| 78 | else: |
| 79 | kdebug ('\n') |
| 80 | if addr >= 0x80000000 && addr < 0xc0000000: |
| 81 | for int i = -4; i < 4; ++i: |
| 82 | kdebug (" ") |
| 83 | kdebug_num (((unsigned *)addr)[i]) |
| 84 | kdebug ("\n") |
| 85 | #else |
| 86 | kdebug (last ? "\n" : "; ") |
| 87 | #endif |
| 88 | |
| 89 | static void panic_message (unsigned n, const char *line, char const *name, char const *message): |
| 90 | kdebug ("**********************************************************************\n") |
| 91 | unsigned vaddr, epc |
| 92 | cp0_get (CP0_BAD_V_ADDR, vaddr) |
| 93 | cp0_get (CP0_EPC, epc) |
| 94 | #if 1 |
| 95 | unsigned addr |
| 96 | print_addr ("BadVAddr: ", vaddr) |
| 97 | if old_current: |
| 98 | print_addr ("PC: ", old_current->pc) |
| 99 | print_addr ("epc: ", epc, true) |
| 100 | #endif |
| 101 | kdebug ("Panic: caller = ") |
| 102 | if old_current: |
| 103 | kdebug_num (old_current->id, 2) |
| 104 | kdebug (":") |
| 105 | kdebug_num ((unsigned)old_current) |
| 106 | if old_current: |
| 107 | kdebug ('@') |
| 108 | kdebug_num (old_current->pc) |
| 109 | kdebug ("\nregisters: sp=") |
| 110 | kdebug_num (old_current->sp) |
| 111 | kdebug (" at=") |
| 112 | kdebug_num (old_current->arch.at) |
| 113 | kdebug ("\nv=") |
| 114 | kdebug_num (old_current->arch.v[0]) |
| 115 | kdebug (" ") |
| 116 | kdebug_num (old_current->arch.v[1]) |
| 117 | kdebug ("\na=") |
| 118 | for unsigned i = 0; i < 4; ++i: |
| 119 | kdebug_num (old_current->arch.a[i]) |
| 120 | kdebug (" ") |
| 121 | kdebug ("\nt=") |
| 122 | for unsigned i = 0; i < 10; ++i: |
| 123 | kdebug_num (old_current->arch.t[i]) |
| 124 | kdebug (" ") |
| 125 | kdebug ("\ns=") |
| 126 | for unsigned i = 0; i < 8; ++i: |
| 127 | kdebug_num (old_current->arch.s[i]) |
| 128 | kdebug (" ") |
| 129 | kdebug ("\ngp=") |
| 130 | kdebug_num (old_current->arch.gp) |
| 131 | kdebug (" fp=") |
| 132 | kdebug_num (old_current->arch.fp) |
| 133 | kdebug (" ra=") |
| 134 | kdebug_num (old_current->arch.ra) |
| 135 | kdebug ("\nhi=") |
| 136 | kdebug_num (old_current->arch.hi) |
| 137 | kdebug (" lo=") |
| 138 | kdebug_num (old_current->arch.lo) |
| 139 | kdebug ('\n') |
| 140 | kdebug ("Directory: ") |
| 141 | kdebug_num ((unsigned)directory) |
| 142 | kdebug ("; ") |
| 143 | kdebug (name) |
| 144 | kdebug (':') |
| 145 | kdebug (line) |
| 146 | kdebug (": ") |
| 147 | kdebug (message) |
| 148 | kdebug ('/') |
| 149 | kdebug_num (n) |
| 150 | kdebug ("; debug: ") |
| 151 | kdebug_num (dbg_code.h) |
| 152 | kdebug (':') |
| 153 | kdebug_num (dbg_code.l) |
| 154 | kdebug ('\n') |
| 155 | kdebug ("debug buffer (most recently pushed at end):") |
| 156 | unsigned b = dbg_buffer_head |
| 157 | for unsigned i = 0; i < 8; ++i: |
| 158 | kdebug ('\n') |
| 159 | for unsigned j = 0; j < 4; ++j: |
| 160 | kdebug (' ') |
| 161 | kdebug_num (dbg_buffer[b]) |
| 162 | ++b |
| 163 | if b == 32: |
| 164 | b = 0 |
| 165 | kdebug ('\n') |
| 166 | if old_current: |
| 167 | kdebug ("Attempt to print *pc:\n") |
| 168 | unsigned page = old_current->pc & PAGE_MASK |
| 169 | unsigned start = old_current->pc & ~(4 * 4 - 1) |
| 170 | for int i = -4; i < 8; ++i: |
| 171 | kdebug_num (start + i * 4 * 4) |
| 172 | kdebug (" ==>") |
| 173 | for unsigned j = 0; j < 4; ++j: |
| 174 | kdebug (' ') |
| 175 | unsigned addr = start + (i * 4 + j) * 4 |
| 176 | if (addr & PAGE_MASK) == page: |
| 177 | kdebug_num (*(unsigned *)addr) |
| 178 | else: |
| 179 | kdebug ("--------") |
| 180 | kdebug ('\n') |
| 181 | |
| 182 | void panic_impl (unsigned n, const char *line, char const *name, char const *message): |
| 183 | // Stop all threads. |
| 184 | while first_scheduled: |
| 185 | first_scheduled->unrun () |
| 186 | for kReceiver *r = first_alarm; r; r = r->next_alarm: |
| 187 | if r->owner: |
| 188 | r->owner->unrun () |
| 189 | for unsigned i = 0; i < 32; ++i: |
| 190 | if arch_interrupt_receiver[i] && arch_interrupt_receiver[i]->owner: |
| 191 | arch_interrupt_receiver[i]->owner->unrun () |
| 192 | #ifndef NDEBUG |
| 193 | panic_message (n, line, name, message) |
| 194 | // If a log capability is registered, run its owner. |
| 195 | #ifndef USE_SERIAL |
| 196 | if dbg_cap.valid () && dbg_cap->target->owner: |
| 197 | dbg_cap->target->owner->run () |
| 198 | // Use the (now running) log thread to display the message. |
| 199 | // If no log capability is registered, the machine just hangs. |
| 200 | #else |
| 201 | arch_reboot () |
| 202 | #endif |
| 203 | #endif |
| 204 | #ifndef NDEBUG |
| 205 | void dbg_send (unsigned num, unsigned bits): |
| 206 | kdebug ("Warning: ") |
| 207 | kdebug_num (num) |
| 208 | kdebug ('/') |
| 209 | kdebug_num (bits) |
| 210 | kdebug ('\n') |
| 211 | #endif |
| 212 | #else |
| 213 | void delay (unsigned ms): |
| 214 | for unsigned t = 0; t < 8000 * ms; ++t: |
| 215 | GPIO_GPDIR (0) = GPIO_GPDIR (0) |
| 216 | |
| 217 | void set_leds (bool a, bool b): |
| 218 | gpio_as_output (GPIO_NUM_PORT, GPIO_NUM) |
| 219 | gpio_as_output (GPIO_CAPS_PORT, GPIO_CAPS) |
| 220 | if a: |
| 221 | GPIO_GPDR (GPIO_NUM_PORT) &= ~(1 << GPIO_NUM) |
| 222 | else: |
| 223 | GPIO_GPDR (GPIO_NUM_PORT) |= 1 << GPIO_NUM |
| 224 | if b: |
| 225 | GPIO_GPDR (GPIO_CAPS_PORT) &= ~(1 << GPIO_CAPS) |
| 226 | else: |
| 227 | GPIO_GPDR (GPIO_CAPS_PORT) |= 1 << GPIO_CAPS |
| 228 | |
| 229 | void dbg_send (unsigned n, unsigned bits): |
| 230 | for unsigned i = 0; i < bits; ++i: |
| 231 | bool v = n & (1 << (bits - 1)) |
| 232 | set_leds (v, !v) |
| 233 | delay (350) |
| 234 | set_leds (false, false) |
| 235 | delay (150) |
| 236 | n <<= 1 |
| 237 | set_leds (true, true) |
| 238 | delay (50) |
| 239 | set_leds (false, false) |
| 240 | delay (50) |
| 241 | void panic_impl (unsigned n, const char *line, char const *name, char const *message): |
| 242 | unsigned epc |
| 243 | cp0_get (CP0_EPC, epc) |
| 244 | dbg_send (epc, 32) |
| 245 | while true: |
| 246 | dbg_send (n, 32) |
| 247 | #endif |
| 248 |
Branches:
master
