Fork me on GitHub

root/kernel/traps.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. do_divide_error
  2. do_debug
  3. do_nmi_interrupt
  4. do_breakpoint
  5. do_overflow
  6. do_bound
  7. do_invalid_opcode
  8. do_no_math_coprocessor
  9. do_double_fault
  10. do_coprocessor_segment_overrun
  11. do_invalid_tss
  12. do_segment_not_present
  13. do_stack_segment_fault
  14. do_general_protection
  15. do_reserved
  16. do_floating_point_error
  17. do_alignment_check
  18. do_machine_check
  19. do_simd_fault
  20. trap_handler
  21. elf_lookup_symbol
  22. dump_registers

   1 /*
   2  * fiwix/kernel/traps.c
   3  *
   4  * Copyright 2018, Jordi Sanfeliu. All rights reserved.
   5  * Distributed under the terms of the Fiwix License.
   6  */
   7 
   8 #include <fiwix/asm.h>
   9 #include <fiwix/kernel.h>
  10 #include <fiwix/traps.h>
  11 #include <fiwix/cpu.h>
  12 #include <fiwix/mm.h>
  13 #include <fiwix/process.h>
  14 #include <fiwix/signal.h>
  15 #include <fiwix/stdio.h>
  16 #include <fiwix/string.h>
  17 #include <fiwix/sched.h>
  18 
  19 /*
  20  * PS/2 System Control Port B
  21  * ---------------------------------------
  22  * bit 7 -> system board RAM parity check
  23  * bit 6 -> channel check
  24  * bit 5 -> timer 2 (speaker time) output
  25  * bit 4 -> refresh request (toggle)
  26  * bit 3 -> channel check status
  27  * bit 2 -> parity check status
  28  * bit 1 -> speaker data status
  29  * bit 0 -> timer 2 gate to speaker status
  30  */
  31 #define PS2_SYSCTRL_B   0x61    /* PS/2 system control port B (read) */
  32 
  33 struct traps traps_table[NR_EXCEPTIONS] = {
  34         { "Divide Error", do_divide_error, 0 },
  35         { "Debug", do_debug, 0 },
  36         { "NMI Interrupt", do_nmi_interrupt, 0 },
  37         { "Breakpoint", do_breakpoint, 0 },
  38         { "Overflow" , do_overflow, 0 },
  39         { "BOUND Range Exceeded", do_bound, 0 },
  40         { "Invalid Opcode", do_invalid_opcode, 0 },
  41         { "Device Not Available (No Math Coprocessor)", do_no_math_coprocessor, 0 },
  42         { "Double Fault", do_double_fault, 1 },
  43         { "Coprocessor Segment Overrun", do_coprocessor_segment_overrun, 0 },
  44         { "Invalid TSS", do_invalid_tss, 1 },
  45         { "Segment Not Present", do_segment_not_present, 1 },
  46         { "Stack-Segment Fault", do_stack_segment_fault, 1 },
  47         { "General Protection", do_general_protection, 1 },
  48         { "Page Fault", do_page_fault, 1 },
  49         { "Intel reserved", do_reserved, 0 },
  50         { "x87 FPU Floating-Point Error", do_floating_point_error, 0 },
  51         { "Alignment Check", do_alignment_check, 1 },
  52         { "Machine Check", do_machine_check, 0 },
  53         { "SIMD Floating-Point Exception", do_simd_fault, 0 },
  54         { "Intel reserved", do_reserved, 0 },
  55         { "Intel reserved", do_reserved, 0 },
  56         { "Intel reserved", do_reserved, 0 },
  57         { "Intel reserved", do_reserved, 0 },
  58         { "Intel reserved", do_reserved, 0 },
  59         { "Intel reserved", do_reserved, 0 },
  60         { "Intel reserved", do_reserved, 0 },
  61         { "Intel reserved", do_reserved, 0 },
  62         { "Intel reserved", do_reserved, 0 },
  63         { "Intel reserved", do_reserved, 0 },
  64         { "Intel reserved", do_reserved, 0 },
  65         { "Intel reserved", do_reserved, 0 }
  66 };
  67 
  68 void do_divide_error(unsigned int trap, struct sigcontext *sc)
  69 {
  70         if(dump_registers(trap, sc)) {
  71                 PANIC("");
  72         }
  73         send_sig(current, SIGFPE);
  74         return;
  75 }
  76 
  77 void do_debug(unsigned int trap, struct sigcontext *sc)
  78 {
  79         if(dump_registers(trap, sc)) {
  80                 PANIC("");
  81         }
  82         send_sig(current, SIGTRAP);
  83         return;
  84 }
  85 
  86 void do_nmi_interrupt(unsigned int trap, struct sigcontext *sc)
  87 {
  88         unsigned char error;
  89 
  90         error = inport_b(PS2_SYSCTRL_B);
  91 
  92         printk("NMI received: ", error);
  93         switch(error) {
  94                 case 0x80:
  95                         printk("parity check occurred. Defective RAM chips?\n");
  96                         break;
  97                 default:
  98                         printk("unknown error 0x%x\n", error);
  99                         break;
 100         }
 101 
 102         if(dump_registers(trap, sc)) {
 103                 PANIC("");
 104         }
 105         send_sig(current, SIGSEGV);
 106         return;
 107 }
 108 
 109 void do_breakpoint(unsigned int trap, struct sigcontext *sc)
 110 {
 111         if(dump_registers(trap, sc)) {
 112                 PANIC("");
 113         }
 114         send_sig(current, SIGTRAP);
 115         return;
 116 }
 117 
 118 void do_overflow(unsigned int trap, struct sigcontext *sc)
 119 {
 120         if(dump_registers(trap, sc)) {
 121                 PANIC("");
 122         }
 123         send_sig(current, SIGSEGV);
 124         return;
 125 }
 126 
 127 void do_bound(unsigned int trap, struct sigcontext *sc)
 128 {
 129         if(dump_registers(trap, sc)) {
 130                 PANIC("");
 131         }
 132         send_sig(current, SIGSEGV);
 133         return;
 134 }
 135 
 136 void do_invalid_opcode(unsigned int trap, struct sigcontext *sc)
 137 {
 138         if(dump_registers(trap, sc)) {
 139                 PANIC("");
 140         }
 141         send_sig(current, SIGILL);
 142         return;
 143 }
 144 
 145 void do_no_math_coprocessor(unsigned int trap, struct sigcontext *sc)
 146 {
 147         /* floating-point emulation would go here */
 148 
 149         if(dump_registers(trap, sc)) {
 150                 PANIC("No coprocessor/emulation found.\n");
 151         }
 152         send_sig(current, SIGILL);
 153         return;
 154 }
 155 
 156 void do_double_fault(unsigned int trap, struct sigcontext *sc)
 157 {
 158         if(dump_registers(trap, sc)) {
 159                 PANIC("");
 160         }
 161         send_sig(current, SIGSEGV);
 162         return;
 163 }
 164 
 165 void do_coprocessor_segment_overrun(unsigned int trap, struct sigcontext *sc)
 166 {
 167         if(dump_registers(trap, sc)) {
 168                 PANIC("");
 169         }
 170         send_sig(current, SIGFPE);
 171         return;
 172 }
 173 
 174 void do_invalid_tss(unsigned int trap, struct sigcontext *sc)
 175 {
 176         if(dump_registers(trap, sc)) {
 177                 PANIC("");
 178         }
 179         send_sig(current, SIGSEGV);
 180         return;
 181 }
 182 
 183 void do_segment_not_present(unsigned int trap, struct sigcontext *sc)
 184 {
 185         if(dump_registers(trap, sc)) {
 186                 PANIC("");
 187         }
 188         send_sig(current, SIGBUS);
 189         return;
 190 }
 191 
 192 void do_stack_segment_fault(unsigned int trap, struct sigcontext *sc)
 193 {
 194         if(dump_registers(trap, sc)) {
 195                 PANIC("");
 196         }
 197         send_sig(current, SIGBUS);
 198         return;
 199 }
 200 
 201 void do_general_protection(unsigned int trap, struct sigcontext *sc)
 202 {
 203         if(dump_registers(trap, sc)) {
 204                 PANIC("");
 205         }
 206         send_sig(current, SIGSEGV);
 207         return;
 208 }
 209 
 210 /* do_page_fault() resides in mm/fault.c */
 211 
 212 void do_reserved(unsigned int trap, struct sigcontext *sc)
 213 {
 214         if(dump_registers(trap, sc)) {
 215                 PANIC("");
 216         }
 217         send_sig(current, SIGSEGV);
 218         return;
 219 }
 220 
 221 void do_floating_point_error(unsigned int trap, struct sigcontext *sc)
 222 {
 223         if(dump_registers(trap, sc)) {
 224                 PANIC("");
 225         }
 226         send_sig(current, SIGFPE);
 227         return;
 228 }
 229 
 230 void do_alignment_check(unsigned int trap, struct sigcontext *sc)
 231 {
 232         if(dump_registers(trap, sc)) {
 233                 PANIC("");
 234         }
 235         send_sig(current, SIGSEGV);
 236         return;
 237 }
 238 
 239 void do_machine_check(unsigned int trap, struct sigcontext *sc)
 240 {
 241         if(dump_registers(trap, sc)) {
 242                 PANIC("");
 243         }
 244         send_sig(current, SIGSEGV);
 245         return;
 246 }
 247 
 248 void do_simd_fault(unsigned int trap, struct sigcontext *sc)
 249 {
 250         if(dump_registers(trap, sc)) {
 251                 PANIC("");
 252         }
 253         send_sig(current, SIGSEGV);
 254         return;
 255 }
 256 
 257 void trap_handler(unsigned int trap, struct sigcontext sc)
 258 {
 259         traps_table[trap].handler(trap, &sc);
 260 
 261         /* avoids confusion with -RESTART return value */
 262         sc.err = -sc.err;
 263 }
 264 
 265 static const char * elf_lookup_symbol(unsigned int addr)
 266 {
 267         Elf32_Sym *sym;
 268         unsigned int n;
 269 
 270         sym = (Elf32_Sym *)symtab->sh_addr;
 271         for(n = 0; n < symtab->sh_size / sizeof(Elf32_Sym); n++, sym++) {
 272                 if(ELF32_ST_TYPE(sym->st_info) != STT_FUNC) {
 273                         continue;
 274                 }
 275                 if(addr >= sym->st_value && addr < (sym->st_value + sym->st_size)) {
 276                         return (const char *)strtab->sh_addr + sym->st_name;
 277                 }
 278         }
 279         return NULL;
 280 }
 281 
 282 int dump_registers(unsigned int trap, struct sigcontext *sc)
 283 {
 284         unsigned int cr2, addr, n;
 285         unsigned int *sp;
 286         const char *str;
 287 
 288         printk("\n");
 289         if(trap == 14) {        /* Page Fault */
 290                 GET_CR2(cr2);
 291                 printk("%s at 0x%08x (%s) with error code 0x%08x (0b%b)\n", traps_table[trap].name, cr2, sc->err & PFAULT_W ? "writing" : "reading", sc->err, sc->err);
 292         } else {
 293                 printk("EXCEPTION: %s", traps_table[trap].name);
 294                 if(traps_table[trap].errcode) {
 295                         printk(": error code 0x%08x (0b%b)", sc->err, sc->err);
 296                 }
 297                 printk("\n");
 298         }
 299 
 300         printk("Process '%s' with pid %d", current->argv0, current->pid);
 301         if(sc->cs == KERNEL_CS) {
 302                 printk(" in '%s()'.", elf_lookup_symbol(sc->eip));
 303         }
 304         printk("\n");
 305 
 306         printk(" cs: 0x%08x\teip: 0x%08x\tefl: 0x%08x\t ss: 0x%08x\tesp: 0x%08x\n", sc->cs, sc->eip, sc->eflags, sc->oldss, sc->oldesp);
 307         printk("eax: 0x%08x\tebx: 0x%08x\tecx: 0x%08x\tedx: 0x%08x\n", sc->eax, sc->ebx, sc->ecx, sc->edx);
 308         printk("esi: 0x%08x\tedi: 0x%08x\tesp: 0x%08x\tebp: 0x%08x\n", sc->esi, sc->edi, sc->esp, sc->ebp);
 309         printk(" ds: 0x%08x\t es: 0x%08x\t fs: 0x%08x\t gs: 0x%08x\n", sc->ds, sc->es, sc->fs, sc->gs);
 310 
 311         if(sc->cs == KERNEL_CS) {
 312                 printk("Stack:\n");
 313                 GET_ESP(sp);
 314                 sp = (unsigned int *)sp;
 315                 for(n = 1; n <= 32; n++) {
 316                         printk(" %08x", *sp);
 317                         sp++;
 318                         if(!(n % 8)) {
 319                                 printk("\n");
 320                         }
 321                 }
 322                 printk("Backtrace:\n");
 323                 GET_ESP(sp);
 324                 sp = (unsigned int *)sp;
 325                 for(n = 0; n < 128; n++) {
 326                         addr = *sp;
 327                         str = elf_lookup_symbol(addr);
 328                         if(str) {
 329                                 printk("<0x%08x> %s()\n", addr, str);
 330                         }
 331                         sp++;
 332                 }
 333         }
 334 
 335         /* panics if the exception has been in kernel mode */
 336         if(current->flags & PF_KPROC || sc->cs == KERNEL_CS) {
 337                 return 1;
 338         }
 339 
 340         return 0;
 341 }

/* [previous][next][first][last][top][bottom][index][help] */