Fixes to x86 error and interrupt handling
[tpg/acess2.git] / Kernel / arch / x86 / errors.c
1 /*
2  * Acess2 - x86 Architecture
3  * arch/x86/errors.c
4  * - CPU Error Handler
5  */
6 #include <acess.h>
7 #include <proc.h>
8
9 // === CONSTANTS ===
10 #define MAX_BACKTRACE   8       //!< Maximum distance to trace the stack backwards
11
12 // === IMPORTS ===
13 extern void     MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs);
14 extern void     VM8086_GPF(tRegs *Regs);
15 extern void Threads_Dump();
16
17 // === PROTOTYPES ===
18 void    Error_Backtrace(Uint eip, Uint ebp);
19
20 // === GLOBALS ===
21 const char *csaERROR_NAMES[] = {
22         "Divide By Zero", "Debug", "NMI Exception", "INT3",
23         "INTO", "Out of Bounds", "Invalid Opcode", "Coprocessor not avaliable",
24         "Double Fault", "Coprocessor Segment Overrun", "Bad TSS", "Segment Not Present",
25         "Stack Fault Exception", "GPF", "#PF", "Reserved",
26         "Floating Point Exception", "Alignment Check Exception", "Machine Check Exception",     "Reserved",
27         "Reserved", "Reserved", "Reserved", "Reserved",
28         "Reserved", "Reserved", "Reserved", "Reserved",
29         "Reserved", "Reserved", "Reserved", "Reserved"
30         };
31
32 // === CODE ===
33 void __stack_chk_fail()
34 {
35         Panic("FATAL ERROR: Stack Check Failed\n");
36         for(;;);
37 }
38
39 /**
40  * \fn void ErrorHandler(tRegs *Regs)
41  * \brief General Error Handler
42  */
43 void ErrorHandler(tRegs *Regs)
44 {
45         Uint    cr;
46         
47         //if( Regs && !(Regs->int_num == 13 && Regs->eflags & 0x20000) )
48         //      __asm__ __volatile__ ("xchg %bx, %bx");
49         //Log_Debug("X86", "Regs = %p", Regs);
50         //Log_Debug("X86", "Error %i at 0x%08x", Regs->int_num, Regs->eip);
51         
52         __asm__ __volatile__ ("cli");
53         
54         // Page Fault
55         if(Regs->int_num == 14)
56         {
57                 __asm__ __volatile__ ("mov %%cr2, %0":"=r"(cr));
58                 MM_PageFault( cr, Regs->err_code, Regs );
59                 return ;
60         }
61         
62         // VM8086 GPF
63         if(Regs->int_num == 13 && Regs->eflags & 0x20000)
64         {
65                 VM8086_GPF(Regs);
66                 return ;
67         }
68         
69         Warning("CPU Error %i - %s, Code: 0x%x",
70                 Regs->int_num, csaERROR_NAMES[Regs->int_num], Regs->err_code);
71         Warning(" CS:EIP = 0x%04x:%08x", Regs->cs, Regs->eip);
72         if(Regs->cs == 0x08)
73                 Warning(" SS:ESP = 0x0010:%08x", 0x10, (Uint)Regs+sizeof(tRegs));
74         else
75                 Warning(" SS:ESP = 0x%04x:%08x", Regs->ss, Regs->esp);
76         Warning(" EFLAGS = 0x%08x", Regs->eflags);
77         Warning(" EAX %08x ECX %08x EDX %08x EBX %08x",
78                 Regs->eax, Regs->ecx, Regs->edx, Regs->ebx);
79         Warning(" ESP %08x EBP %08x ESI %08x EDI %08x",
80                 Regs->esp, Regs->ebp, Regs->esi, Regs->edi);
81         Warning(" DS %04x ES %04x FS %04x GS %04x",
82                 Regs->ds, Regs->es, Regs->fs, Regs->gs);
83         
84         // Control Registers
85         __asm__ __volatile__ ("mov %%cr0, %0":"=r"(cr));
86         Warning(" CR0 0x%08x", cr);
87         __asm__ __volatile__ ("mov %%cr2, %0":"=r"(cr));
88         Warning(" CR2 0x%08x", cr);
89         __asm__ __volatile__ ("mov %%cr3, %0":"=r"(cr));
90         Warning(" CR3 0x%08x", cr);
91         
92         switch( Regs->int_num )
93         {
94         case 6: // #UD
95                 Warning(" Offending bytes: %02x %02x %02x %02x",
96                         *(Uint8*)Regs->eip+0, *(Uint8*)Regs->eip+1,
97                         *(Uint8*)Regs->eip+2, *(Uint8*)Regs->eip+3);
98                 break;
99         }
100         
101         // Print Stack Backtrace
102         Error_Backtrace(Regs->eip, Regs->ebp);
103         
104         // Dump running threads
105         Threads_Dump();
106         
107         for(;;) __asm__ __volatile__ ("hlt");
108 }
109 /**
110  * \fn void Error_Backtrace(Uint eip, Uint ebp)
111  * \brief Unrolls the stack to trace execution
112  */
113 void Error_Backtrace(Uint eip, Uint ebp)
114 {
115          int    i = 0;
116         Uint    delta = 0;
117         char    *str = NULL;
118         
119         //if(eip < 0xC0000000 && eip > 0x1000)
120         //{
121         //      LogF("Backtrace: User - 0x%x\n", eip);
122         //      return;
123         //}
124         
125         if(eip > 0xE0000000)
126         {
127                 LogF("Backtrace: Data Area - 0x%x\n", eip);
128                 return;
129         }
130         
131         if(eip > 0xC8000000)
132         {
133                 LogF("Backtrace: Kernel Module - 0x%x\n", eip);
134                 return;
135         }
136         
137         //str = Debug_GetSymbol(eip, &delta);
138         if(str == NULL)
139                 LogF("Backtrace: 0x%x", eip);
140         else
141                 LogF("Backtrace: %s+0x%x", str, delta);
142         if(!MM_GetPhysAddr(ebp))
143         {
144                 LogF("\nBacktrace: Invalid EBP, stopping\n");
145                 return;
146         }
147         
148         
149         while( MM_GetPhysAddr(ebp) && i < MAX_BACKTRACE )
150         {
151                 //str = Debug_GetSymbol(*(Uint*)(ebp+4), &delta);
152                 if(str == NULL)
153                         LogF(" >> 0x%x", *(Uint*)(ebp+4));
154                 else
155                         LogF(" >> %s+0x%x", str, delta);
156                 ebp = *(Uint*)ebp;
157                 i++;
158         }
159         LogF("\n");
160 }
161
162 /**
163  * \fn void StartupPrint(char *Str)
164  */
165 void StartupPrint(char *Str)
166 {
167         Uint16  *buf = (void*)0xC00B8000;
168          int    i = 0;
169         static int      line = 0;
170         while(*Str)
171         {
172                 buf[line*80 + i++] = *Str | 0x0700;
173                 Str ++;
174         }
175         
176         while(i < 80)   buf[line*80 + i++] = 0x0720;
177         
178         line ++;
179         if(line == 25)
180         {
181                 line --;
182                 memcpy(buf, &buf[80], 80*24*2);
183                 memset(&buf[80*24], 0, 80*2);
184         }
185 }
186
187 // === EXPORTS ===
188 EXPORT(__stack_chk_fail);

UCC git Repository :: git.ucc.asn.au