/*-
* 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);
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);
*/
}