X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Farch%2Fx86%2Ferrors.c;h=1e0278b6ab9f691211e0bf959c40828beffa7e30;hb=126cef9a37b4859e3d6555760a5bbaa308a715d6;hp=2c3582cdcf2d4e14b54a1adbd5f2a2637dbd85dc;hpb=f119d0e5b18b7286d04fc536a94e0f96e3c51714;p=tpg%2Facess2.git diff --git a/Kernel/arch/x86/errors.c b/Kernel/arch/x86/errors.c index 2c3582cd..1e0278b6 100644 --- a/Kernel/arch/x86/errors.c +++ b/Kernel/arch/x86/errors.c @@ -3,22 +3,64 @@ * arch/x86/errors.c * - CPU Error Handler */ -#include +#include +#include + +// === CONSTANTS === +#define MAX_BACKTRACE 8 //!< Maximum distance to trace the stack backwards // === IMPORTS === extern void MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs); -extern void Threads_Dump(); +extern void VM8086_GPF(tRegs *Regs); +extern void Threads_Dump(void); +extern void Threads_Fault(int Num); +extern int GetCPUNum(void); + +// === PROTOTYPES === +void __stack_chk_fail(void); +void ErrorHandler(tRegs *Regs); +void Error_Backtrace(Uint eip, Uint ebp); +void StartupPrint(char *Str); + +// === GLOBALS === +const char *csaERROR_NAMES[] = { + "Divide By Zero", "Debug", "NMI Exception", "INT3", + "INTO", "Out of Bounds", "Invalid Opcode", "Coprocessor not avaliable", + "Double Fault", "Coprocessor Segment Overrun", "Bad TSS", "Segment Not Present", + "Stack Fault Exception", "GPF", "#PF", "Reserved", + "Floating Point Exception", "Alignment Check Exception", "Machine Check Exception", "Reserved", + "Reserved", "Reserved", "Reserved", "Reserved", + "Reserved", "Reserved", "Reserved", "Reserved", + "Reserved", "Reserved", "Reserved", "Reserved" + }; // === CODE === +/** + * \brief Keeps GCC happy + */ +void __stack_chk_fail(void) +{ + Panic("FATAL ERROR: Stack Check Failed\n"); + for(;;); +} + /** * \fn void ErrorHandler(tRegs *Regs) * \brief General Error Handler + * \param Regs Register state at error */ void ErrorHandler(tRegs *Regs) { Uint cr; + + //if( Regs && !(Regs->int_num == 13 && Regs->eflags & 0x20000) ) + // __asm__ __volatile__ ("xchg %bx, %bx"); + //Log_Debug("X86", "Regs = %p", Regs); + //Log_Debug("X86", "Error %i at 0x%08x", Regs->int_num, Regs->eip); + __asm__ __volatile__ ("cli"); + // Page Fault if(Regs->int_num == 14) { __asm__ __volatile__ ("mov %%cr2, %0":"=r"(cr)); @@ -26,27 +68,166 @@ void ErrorHandler(tRegs *Regs) return ; } - Warning("CPU Error %i, Code: 0x%x", Regs->int_num, Regs->err_code); - Warning(" CS:EIP = 0x%04x:%08x", Regs->cs, Regs->eip); - Warning(" SS:ESP = 0x%04x:%08x", Regs->ss, Regs->esp); + // VM8086 GPF + if(Regs->int_num == 13 && Regs->eflags & 0x20000) + { + VM8086_GPF(Regs); + return ; + } + + // Check if it's a user mode fault + if( Regs->eip < KERNEL_BASE || (Regs->cs & 3) == 3 ) { + Log_Warning("Arch", "User Fault - %s, Code: 0x%x", + csaERROR_NAMES[Regs->int_num], Regs->err_code); + Log_Warning("Arch", "at CS:EIP %04x:%08x", + Regs->cs, Regs->eip); + switch( Regs->int_num ) + { + // Division by Zero + case 0: Threads_Fault(FAULT_DIV0); break; + // Invalid opcode + case 6: Threads_Fault(FAULT_OPCODE); break; + // GPF + case 13: Threads_Fault(FAULT_ACCESS); break; + // Floating Point Exception + case 16: Threads_Fault(FAULT_FLOAT); break; + + default: Threads_Fault(FAULT_MISC); break; + } + return ; + } + + Debug_KernelPanic(); + + LogF("CPU %i Error %i - %s, Code: 0x%x - At %08x", + GetCPUNum(), + Regs->int_num, csaERROR_NAMES[Regs->int_num], Regs->err_code, + Regs->eip); + + //Warning("CPU Error %i - %s, Code: 0x%x", + // Regs->int_num, csaERROR_NAMES[Regs->int_num], Regs->err_code); + //Warning(" CS:EIP = 0x%04x:%08x", Regs->cs, Regs->eip); + __ASM__ ("xchg %bx, %bx"); + if(Regs->cs == 0x08) + Warning(" SS:ESP = 0x0010:%08x", (Uint)Regs+sizeof(tRegs)); + else + Warning(" SS:ESP = 0x%04x:%08x", Regs->ss, Regs->esp); Warning(" EFLAGS = 0x%08x", Regs->eflags); - Warning(" EAX %08x EBX %08x", Regs->eax, Regs->ebx); - Warning(" ECX %08x EDX %08x", Regs->ecx, Regs->edx); - Warning(" ESP %08x EBP %08x", Regs->esp, Regs->ebp); - Warning(" ESI %08x EDI %08x", Regs->esi, Regs->edi); - Warning(" DS %04x ES %04x", Regs->ds, Regs->es); - Warning(" FS %04x GS %04x", Regs->fs, Regs->gs); + Warning(" EAX %08x ECX %08x EDX %08x EBX %08x", + Regs->eax, Regs->ecx, Regs->edx, Regs->ebx); + Warning(" ESP %08x EBP %08x ESI %08x EDI %08x", + Regs->esp, Regs->ebp, Regs->esi, Regs->edi); + Warning(" DS %04x ES %04x FS %04x GS %04x", + Regs->ds, Regs->es, Regs->fs, Regs->gs); // Control Registers __asm__ __volatile__ ("mov %%cr0, %0":"=r"(cr)); - Warning(" CR0: 0x%08x", cr); + Warning(" CR0 0x%08x", cr); __asm__ __volatile__ ("mov %%cr2, %0":"=r"(cr)); - Warning(" CR2: 0x%08x", cr); + Warning(" CR2 0x%08x", cr); __asm__ __volatile__ ("mov %%cr3, %0":"=r"(cr)); - Warning(" CR3: 0x%08x", cr); + Warning(" CR3 0x%08x", cr); + + switch( Regs->int_num ) + { + case 6: // #UD + Warning(" Offending bytes: %02x %02x %02x %02x", + *(Uint8*)Regs->eip+0, *(Uint8*)Regs->eip+1, + *(Uint8*)Regs->eip+2, *(Uint8*)Regs->eip+3); + break; + } + + // Print Stack Backtrace + Error_Backtrace(Regs->eip, Regs->ebp); // Dump running threads Threads_Dump(); for(;;) __asm__ __volatile__ ("hlt"); } +/** + * \fn void Error_Backtrace(Uint eip, Uint ebp) + * \brief Unrolls the stack to trace execution + * \param eip Current Instruction Pointer + * \param ebp Current Base Pointer (Stack Frame) + */ +void Error_Backtrace(Uint eip, Uint ebp) +{ + int i = 0; + Uint delta = 0; + char *str = NULL; + + //if(eip < 0xC0000000 && eip > 0x1000) + //{ + // LogF("Backtrace: User - 0x%x\n", eip); + // return; + //} + + if(eip > 0xE0000000) + { + LogF("Backtrace: Data Area - 0x%x\n", eip); + return; + } + + if(eip > 0xC8000000) + { + LogF("Backtrace: Kernel Module - 0x%x\n", eip); + return; + } + + //str = Debug_GetSymbol(eip, &delta); + if(str == NULL) + LogF("Backtrace: 0x%x", eip); + else + LogF("Backtrace: %s+0x%x", str, delta); + if(!MM_GetPhysAddr(ebp)) + { + LogF("\nBacktrace: Invalid EBP, stopping\n"); + return; + } + + + while( MM_GetPhysAddr(ebp) && i < MAX_BACKTRACE ) + { + //str = Debug_GetSymbol(*(Uint*)(ebp+4), &delta); + if(str == NULL) + LogF(" >> 0x%x", *(Uint*)(ebp+4)); + else + LogF(" >> %s+0x%x", str, delta); + ebp = *(Uint*)ebp; + i++; + } + LogF("\n"); +} + +/** + * \fn void StartupPrint(char *Str) + * \brief Str String to print + * \note WHY IS THIS HERE?!?! + */ +void StartupPrint(char *Str) +{ + Uint16 *buf = (void*)0xC00B8000; + int i = 0; + static int line = 0; + while(*Str) + { + buf[line*80 + i++] = *Str | 0x0700; + Str ++; + } + + // Clear the rest of the line + while(i < 80) + buf[line*80 + i++] = 0x0720; + + line ++; + if(line == 25) + { + line --; + memcpy(buf, &buf[80], 80*24*2); + memset(&buf[80*24], 0, 80*2); + } +} + +// === EXPORTS === +EXPORT(__stack_chk_fail);