/*- * Copyright (c) 2002-2018 The UbixOS Project. * All rights reserved. * * This was developed by Christopher W. Olsen for the UbixOS Project. * * Redistribution and use in source and binary forms, with or without modification, are permitted * provided that the following conditions are met: * * 1) Redistributions of source code must retain the above copyright notice, this list of * conditions, the following disclaimer and the list of authors. * 2) Redistributions in binary form must reproduce the above copyright notice, this list of * conditions, the following disclaimer and the list of authors in the documentation and/or * other materials provided with the distribution. * 3) Neither the name of the UbixOS Project nor the names of its contributors may be used to * endorse or promote products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <i386/signal.h> #include <sys/trap.h> #include <sys/gdt.h> #include <ubixos/sched.h> #include <lib/kprintf.h> #include <vmm/vmm.h> int kmain(uint32_t); #define KERNEL_STACK 0x2000 static void trap_end_task(char *string, struct trapframe *regs, long error_code); #define TRAP_CODE(trap_nr, signr, str, trap_name, tsk) void do_##trap_name(struct trapframe *regs, long error_code) { \ trap_end_task(str, regs, error_code); \ } TRAP_CODE(0, SIGFPE, "divide error", divide_error, _current) TRAP_CODE(3, SIGTRAP, "int3", int3, _current) TRAP_CODE(4, SIGSEGV, "overflow", overflow, _current) TRAP_CODE(5, SIGSEGV, "bounds", bounds, _current) TRAP_CODE(6, SIGILL, "invalid operand", invalid_op, _current) TRAP_CODE(7, SIGSEGV, "device not available", device_not_available, _current) TRAP_CODE(8, SIGSEGV, "double fault", double_fault, _current) //TRAP_CODE( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun, last_task_used_math) TRAP_CODE(10, SIGSEGV, "invalid TSS", invalid_TSS, _current) TRAP_CODE(11, SIGBUS, "segment not present", segment_not_present, _current) TRAP_CODE(12, SIGBUS, "stack segment", stack_segment, _current) TRAP_CODE(15, SIGSEGV, "reserved", reserved, _current) TRAP_CODE(17, SIGSEGV, "alignment check", alignment_check, _current) static void trap_end_task(char *string, struct trapframe *regs, long error_code) { kprintf("S"); } #define FIRST_TSS_ENTRY 6 #define VM_MASK 0x00020000 #define store_TR(n) \ __asm__("str %%ax\n\t" \ "subl %2,%%eax\n\t" \ "shrl $4,%%eax" \ :"=a" (n) \ :"0" (0),"i" (FIRST_TSS_ENTRY<<3)) #define get_seg_long(seg,addr) ({ \ register unsigned long __res; \ __asm__("push %%fs;mov %%ax,%%fs;movl %%fs:%2,%%eax;pop %%fs" \ :"=a" (__res):"0" (seg),"m" (*(addr))); \ __res;}) #define get_seg_byte(seg,addr) ({ \ register char __res; \ __asm__("push %%fs;mov %%ax,%%fs;movb %%fs:%2,%%al;pop %%fs" \ :"=a" (__res):"0" (seg),"m" (*(addr))); \ __res;}) void die_if_kernel(char *str, struct trapframe *regs, long err) { int i; unsigned long esp; unsigned short ss; unsigned long *stack, addr, module_start, module_end; char *_etext = 0x300a0; esp = (unsigned long) ®s->tf_esp; ss = 0x10; //KERNEL_DS //if ((regs->tf_eflags & VM_MASK) || (3 & regs->tf_cs) == 3) // return; if ((regs->tf_cs & 3) == 3) { esp = regs->tf_esp; ss = regs->tf_ss; kprintf("USER TASK!"); } else { ss = 0x10; } kprintf("%s: %04lx(%i:%i)[0x%X]\n", str, err & 0xffff, regs->tf_trapno, regs->tf_err, regs->tf_ss); kprintf("CPU: %d\n", 0); kprintf("EIP: %04x:[<%08lx>]\nEFLAGS: %08lx\n", 0xffff & regs->tf_cs, regs->tf_eip, regs->tf_eflags); kprintf("eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n", regs->tf_eax, regs->tf_ebx, regs->tf_ecx, regs->tf_edx); kprintf("esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n", regs->tf_esi, regs->tf_edi, regs->tf_ebp, esp); kprintf("cs: 0x%X ds: 0x%X es: 0x%X fs: 0x%X gs: 0x%X ss: 0x%X\n", regs->tf_cs, regs->tf_ds, regs->tf_es, regs->tf_fs, regs->tf_gs, ss); store_TR(i); kprintf("Process %s (pid: %i, process nr: %d, stackpage=%08lx)\nStack:", _current->name, _current->id, 0xffff & i, KERNEL_STACK); stack = (unsigned long *) esp; for (i = 0; i < 16; i++) { if (i && ((i % 8) == 0)) kprintf("\n "); kprintf("%08lx ", get_seg_long(ss, stack++)); } #ifdef _IGNORE kprintf("\nCall Trace: "); stack = (unsigned long *)esp; i = 1; #define VMALLOC_OFFSET (8*1024*1024) #define MODULE_RANGE (8*1024*1024) module_start = ((numPages + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1)); module_end = module_start + MODULE_RANGE; //while (((long) stack & 4095) != 0) { while (i < 12) { addr = get_seg_long(ss, stack++); /* * If the address is either in the text segment of the * kernel, or in the region which contains vmalloc'ed * memory, it *may* be the address of a calling * routine; if so, print it so that someone tracing * down the cause of the crash will be able to figure * out the call path that was taken. */ if (((addr >= (unsigned long) &kmain) && (addr <= (unsigned long) &_etext)) || ((addr >= module_start) && (addr <= module_end))) { if (i && ((i % 8) == 0)) kprintf("\n "); kprintf("[<%08lx>] ", addr); i++; } } for (i = 0; i < 20; i++) kprintf("%02x ", 0xff & get_seg_byte(regs->tf_cs, (i+(char *)regs->tf_eip))); kprintf("\n"); #endif } void trap(struct trapframe *frame) { u_int trap_code; u_int cr2 = 0; struct thread *td = &_current->td; trap_code = frame->tf_trapno; if ((frame->tf_eflags & PSL_I) == 0) { if (SEL_GET_PL(frame->tf_cs) == SEL_PL_USER || (frame->tf_eflags & PSL_VM)) { die_if_kernel("TEST", frame, 0x100); // kpanic( "INT OFF! USER" ); } else { die_if_kernel("TEST", frame, 0x100); // kpanic( "INT OFF! KERN[0x%X]", trap_code ); } } cr2 = rcr2(); kprintf("trap_code: %i(0x%X), EIP: 0x%X, CR2: 0x%X\n", frame->tf_trapno, frame->tf_trapno, frame->tf_eip, cr2); //kpanic("trap_code: %i(0x%X), EIP: 0x%X, CR2: 0x%X\n", frame->tf_trapno, frame->tf_trapno, frame->tf_eip, cr2); die_if_kernel("trapCode", frame, frame->tf_trapno); endTask(_current->id); sched_yield(); /* switch (trap_code) { case 0xC: cr2 = rcr2(); kprintf("trap_code: %i(0x%X), EIP: 0x%X, CR2: 0x%X\n", frame->tf_trapno, frame->tf_trapno, frame->tf_eip, cr2); asm("sti"); // Turn Back On Ints! vmm_pageFault(frame, cr2); kprintf("Called page Fault\n"); default: break; } kprintf("GOTTA RETURN!\n"); while(1); */ }