Working on MP build (now can run, just crashes due to CPUs treading on each other...
[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(void);
16 extern void     Threads_Fault(int Num);
17 extern int      GetCPUNum(void);
18
19 // === PROTOTYPES ===
20 void    __stack_chk_fail(void);
21 void    ErrorHandler(tRegs *Regs);
22 void    Error_Backtrace(Uint eip, Uint ebp);
23 void    StartupPrint(char *Str);
24
25 // === GLOBALS ===
26 const char *csaERROR_NAMES[] = {
27         "Divide By Zero", "Debug", "NMI Exception", "INT3",
28         "INTO", "Out of Bounds", "Invalid Opcode", "Coprocessor not avaliable",
29         "Double Fault", "Coprocessor Segment Overrun", "Bad TSS", "Segment Not Present",
30         "Stack Fault Exception", "GPF", "#PF", "Reserved",
31         "Floating Point Exception", "Alignment Check Exception", "Machine Check Exception",     "Reserved",
32         "Reserved", "Reserved", "Reserved", "Reserved",
33         "Reserved", "Reserved", "Reserved", "Reserved",
34         "Reserved", "Reserved", "Reserved", "Reserved"
35         };
36
37 // === CODE ===
38 /**
39  * \brief Keeps GCC happy
40  */
41 void __stack_chk_fail(void)
42 {
43         Panic("FATAL ERROR: Stack Check Failed\n");
44         for(;;);
45 }
46
47 /**
48  * \fn void ErrorHandler(tRegs *Regs)
49  * \brief General Error Handler
50  * \param Regs  Register state at error
51  */
52 void ErrorHandler(tRegs *Regs)
53 {
54         Uint    cr;
55         
56         //if( Regs && !(Regs->int_num == 13 && Regs->eflags & 0x20000) )
57         //      __asm__ __volatile__ ("xchg %bx, %bx");
58         //Log_Debug("X86", "Regs = %p", Regs);
59         //Log_Debug("X86", "Error %i at 0x%08x", Regs->int_num, Regs->eip);
60         
61         __asm__ __volatile__ ("cli");
62         
63         // Page Fault
64         if(Regs->int_num == 14)
65         {
66                 __asm__ __volatile__ ("mov %%cr2, %0":"=r"(cr));
67                 MM_PageFault( cr, Regs->err_code, Regs );
68                 return ;
69         }
70         
71         // VM8086 GPF
72         if(Regs->int_num == 13 && Regs->eflags & 0x20000)
73         {
74                 VM8086_GPF(Regs);
75                 return ;
76         }
77         
78         // Check if it's a user mode fault
79         if( Regs->eip < KERNEL_BASE || (Regs->cs & 3) == 3 ) {
80                 Log_Warning("Arch", "User Fault -  %s, Code: 0x%x",
81                         csaERROR_NAMES[Regs->int_num], Regs->err_code);
82                 Log_Warning("Arch", "at CS:EIP %04x:%08x",
83                         Regs->cs, Regs->eip);
84                 switch( Regs->int_num )
85                 {
86                 // Division by Zero
87                 case  0:        Threads_Fault(FAULT_DIV0);      break;
88                 // Invalid opcode
89                 case  6:        Threads_Fault(FAULT_OPCODE);    break;
90                 // GPF
91                 case 13:        Threads_Fault(FAULT_ACCESS);    break;
92                 // Floating Point Exception
93                 case 16:        Threads_Fault(FAULT_FLOAT);     break;
94                 
95                 default:        Threads_Fault(FAULT_MISC);      break;
96                 }
97                 return ;
98         }
99         
100         Debug_KernelPanic();
101         
102         LogF("CPU %i Error %i - %s, Code: 0x%x - At %08x",
103                 GetCPUNum(),
104                 Regs->int_num, csaERROR_NAMES[Regs->int_num], Regs->err_code,
105                 Regs->eip);
106         
107         //Warning("CPU Error %i - %s, Code: 0x%x",
108         //      Regs->int_num, csaERROR_NAMES[Regs->int_num], Regs->err_code);
109         //Warning(" CS:EIP = 0x%04x:%08x", Regs->cs, Regs->eip);
110         __ASM__ ("xchg %bx, %bx");
111         if(Regs->cs == 0x08)
112                 Warning(" SS:ESP = 0x0010:%08x", (Uint)Regs+sizeof(tRegs));
113         else
114                 Warning(" SS:ESP = 0x%04x:%08x", Regs->ss, Regs->esp);
115         Warning(" EFLAGS = 0x%08x", Regs->eflags);
116         Warning(" EAX %08x ECX %08x EDX %08x EBX %08x",
117                 Regs->eax, Regs->ecx, Regs->edx, Regs->ebx);
118         Warning(" ESP %08x EBP %08x ESI %08x EDI %08x",
119                 Regs->esp, Regs->ebp, Regs->esi, Regs->edi);
120         Warning(" DS %04x ES %04x FS %04x GS %04x",
121                 Regs->ds, Regs->es, Regs->fs, Regs->gs);
122         
123         // Control Registers
124         __asm__ __volatile__ ("mov %%cr0, %0":"=r"(cr));
125         Warning(" CR0 0x%08x", cr);
126         __asm__ __volatile__ ("mov %%cr2, %0":"=r"(cr));
127         Warning(" CR2 0x%08x", cr);
128         __asm__ __volatile__ ("mov %%cr3, %0":"=r"(cr));
129         Warning(" CR3 0x%08x", cr);
130         
131         switch( Regs->int_num )
132         {
133         case 6: // #UD
134                 Warning(" Offending bytes: %02x %02x %02x %02x",
135                         *(Uint8*)Regs->eip+0, *(Uint8*)Regs->eip+1,
136                         *(Uint8*)Regs->eip+2, *(Uint8*)Regs->eip+3);
137                 break;
138         }
139         
140         // Print Stack Backtrace
141         Error_Backtrace(Regs->eip, Regs->ebp);
142         
143         // Dump running threads
144         Threads_Dump();
145         
146         for(;;) __asm__ __volatile__ ("hlt");
147 }
148 /**
149  * \fn void Error_Backtrace(Uint eip, Uint ebp)
150  * \brief Unrolls the stack to trace execution
151  * \param eip   Current Instruction Pointer
152  * \param ebp   Current Base Pointer (Stack Frame)
153  */
154 void Error_Backtrace(Uint eip, Uint ebp)
155 {
156          int    i = 0;
157         Uint    delta = 0;
158         char    *str = NULL;
159         
160         //if(eip < 0xC0000000 && eip > 0x1000)
161         //{
162         //      LogF("Backtrace: User - 0x%x\n", eip);
163         //      return;
164         //}
165         
166         if(eip > 0xE0000000)
167         {
168                 LogF("Backtrace: Data Area - 0x%x\n", eip);
169                 return;
170         }
171         
172         if(eip > 0xC8000000)
173         {
174                 LogF("Backtrace: Kernel Module - 0x%x\n", eip);
175                 return;
176         }
177         
178         //str = Debug_GetSymbol(eip, &delta);
179         if(str == NULL)
180                 LogF("Backtrace: 0x%x", eip);
181         else
182                 LogF("Backtrace: %s+0x%x", str, delta);
183         if(!MM_GetPhysAddr(ebp))
184         {
185                 LogF("\nBacktrace: Invalid EBP, stopping\n");
186                 return;
187         }
188         
189         
190         while( MM_GetPhysAddr(ebp) && i < MAX_BACKTRACE )
191         {
192                 //str = Debug_GetSymbol(*(Uint*)(ebp+4), &delta);
193                 if(str == NULL)
194                         LogF(" >> 0x%x", *(Uint*)(ebp+4));
195                 else
196                         LogF(" >> %s+0x%x", str, delta);
197                 ebp = *(Uint*)ebp;
198                 i++;
199         }
200         LogF("\n");
201 }
202
203 /**
204  * \fn void StartupPrint(char *Str)
205  * \brief Str   String to print
206  * \note WHY IS THIS HERE?!?!
207  */
208 void StartupPrint(char *Str)
209 {
210         Uint16  *buf = (void*)0xC00B8000;
211          int    i = 0;
212         static int      line = 0;
213         while(*Str)
214         {
215                 buf[line*80 + i++] = *Str | 0x0700;
216                 Str ++;
217         }
218         
219         // Clear the rest of the line
220         while(i < 80)
221                 buf[line*80 + i++] = 0x0720;
222         
223         line ++;
224         if(line == 25)
225         {
226                 line --;
227                 memcpy(buf, &buf[80], 80*24*2);
228                 memset(&buf[80*24], 0, 80*2);
229         }
230 }
231
232 // === EXPORTS ===
233 EXPORT(__stack_chk_fail);

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