22ad1a39afda8d45fc16a80196c79f7e3609bd89
[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         // Debug exception (used for single-stepping)
64         if(Regs->int_num == 1)
65         {
66                 static Uint32   lastEIP = 0;
67                 tThread *thread = Proc_GetCurThread();
68                 if( Regs->eip == lastEIP )
69                         return;
70                 Log("%p(%i %s) IP=%08x", thread, thread->TID, thread->ThreadName, Regs->eip);
71                 lastEIP = Regs->eip;
72                 return ;
73         }
74         
75         // Page Fault
76         if(Regs->int_num == 14)
77         {
78                 __asm__ __volatile__ ("mov %%cr2, %0":"=r"(cr));
79                 MM_PageFault( cr, Regs->err_code, Regs );
80                 return ;
81         }
82         
83         // VM8086 GPF
84         if(Regs->int_num == 13 && Regs->eflags & 0x20000)
85         {
86                 VM8086_GPF(Regs);
87                 return ;
88         }
89         
90         // Check if it's a user mode fault
91         if( Regs->eip < KERNEL_BASE || (Regs->cs & 3) == 3 ) {
92                 Log_Warning("Arch", "User Fault -  %s, Code: 0x%x",
93                         csaERROR_NAMES[Regs->int_num], Regs->err_code);
94                 Log_Warning("Arch", "at CS:EIP %04x:%08x",
95                         Regs->cs, Regs->eip);
96                 switch( Regs->int_num )
97                 {
98                 // Division by Zero
99                 case  0:        Threads_Fault(FAULT_DIV0);      break;
100                 // Invalid opcode
101                 case  6:        Threads_Fault(FAULT_OPCODE);    break;
102                 // GPF
103                 case 13:        Threads_Fault(FAULT_ACCESS);    break;
104                 // Floating Point Exception
105                 case 16:        Threads_Fault(FAULT_FLOAT);     break;
106                 
107                 default:        Threads_Fault(FAULT_MISC);      break;
108                 }
109                 return ;
110         }
111         
112         Debug_KernelPanic();
113         
114         LogF("CPU %i Error %i - %s, Code: 0x%x - At %08x",
115                 GetCPUNum(),
116                 Regs->int_num, csaERROR_NAMES[Regs->int_num], Regs->err_code,
117                 Regs->eip);
118         
119         //Warning("CPU Error %i - %s, Code: 0x%x",
120         //      Regs->int_num, csaERROR_NAMES[Regs->int_num], Regs->err_code);
121         //Warning(" CS:EIP = 0x%04x:%08x", Regs->cs, Regs->eip);
122         __ASM__ ("xchg %bx, %bx");
123         if(Regs->cs == 0x08)
124                 Warning(" SS:ESP = 0x0010:%08x", (Uint)Regs+sizeof(tRegs));
125         else
126                 Warning(" SS:ESP = 0x%04x:%08x", Regs->ss, Regs->esp);
127         Warning(" EFLAGS = 0x%08x", Regs->eflags);
128         Warning(" EAX %08x ECX %08x EDX %08x EBX %08x",
129                 Regs->eax, Regs->ecx, Regs->edx, Regs->ebx);
130         Warning(" ESP %08x EBP %08x ESI %08x EDI %08x",
131                 Regs->esp, Regs->ebp, Regs->esi, Regs->edi);
132         Warning(" DS %04x ES %04x FS %04x GS %04x",
133                 Regs->ds, Regs->es, Regs->fs, Regs->gs);
134         
135         // Control Registers
136         __asm__ __volatile__ ("mov %%cr0, %0":"=r"(cr));
137         Warning(" CR0 0x%08x", cr);
138         __asm__ __volatile__ ("mov %%cr2, %0":"=r"(cr));
139         Warning(" CR2 0x%08x", cr);
140         __asm__ __volatile__ ("mov %%cr3, %0":"=r"(cr));
141         Warning(" CR3 0x%08x", cr);
142         
143         switch( Regs->int_num )
144         {
145         case 6: // #UD
146                 Warning(" Offending bytes: %02x %02x %02x %02x",
147                         *(Uint8*)Regs->eip+0, *(Uint8*)Regs->eip+1,
148                         *(Uint8*)Regs->eip+2, *(Uint8*)Regs->eip+3);
149                 break;
150         }
151         
152         // Print Stack Backtrace
153         Error_Backtrace(Regs->eip, Regs->ebp);
154         
155         // Dump running threads
156         Threads_Dump();
157         
158         for(;;) __asm__ __volatile__ ("hlt");
159 }
160 /**
161  * \fn void Error_Backtrace(Uint eip, Uint ebp)
162  * \brief Unrolls the stack to trace execution
163  * \param eip   Current Instruction Pointer
164  * \param ebp   Current Base Pointer (Stack Frame)
165  */
166 void Error_Backtrace(Uint eip, Uint ebp)
167 {
168          int    i = 0;
169         Uint    delta = 0;
170         char    *str = NULL;
171         
172         //if(eip < 0xC0000000 && eip > 0x1000)
173         //{
174         //      LogF("Backtrace: User - 0x%x\n", eip);
175         //      return;
176         //}
177         
178         if(eip > 0xE0000000)
179         {
180                 LogF("Backtrace: Data Area - 0x%x\n", eip);
181                 return;
182         }
183         
184         if(eip > 0xC8000000)
185         {
186                 LogF("Backtrace: Kernel Module - 0x%x\n", eip);
187                 return;
188         }
189         
190         //str = Debug_GetSymbol(eip, &delta);
191         if(str == NULL)
192                 LogF("Backtrace: 0x%x", eip);
193         else
194                 LogF("Backtrace: %s+0x%x", str, delta);
195         if(!MM_GetPhysAddr(ebp))
196         {
197                 LogF("\nBacktrace: Invalid EBP, stopping\n");
198                 return;
199         }
200         
201         
202         while( MM_GetPhysAddr(ebp) && i < MAX_BACKTRACE )
203         {
204                 //str = Debug_GetSymbol(*(Uint*)(ebp+4), &delta);
205                 if(str == NULL)
206                         LogF(" >> 0x%x", *(Uint*)(ebp+4));
207                 else
208                         LogF(" >> %s+0x%x", str, delta);
209                 ebp = *(Uint*)ebp;
210                 i++;
211         }
212         LogF("\n");
213 }
214
215 /**
216  * \fn void StartupPrint(char *Str)
217  * \brief Str   String to print
218  * \note WHY IS THIS HERE?!?!
219  */
220 void StartupPrint(char *Str)
221 {
222         Uint16  *buf = (void*)0xC00B8000;
223          int    i = 0;
224         static int      line = 0;
225         while(*Str)
226         {
227                 buf[line*80 + i++] = *Str | 0x0700;
228                 Str ++;
229         }
230         
231         // Clear the rest of the line
232         while(i < 80)
233                 buf[line*80 + i++] = 0x0720;
234         
235         line ++;
236         if(line == 25)
237         {
238                 line --;
239                 memcpy(buf, &buf[80], 80*24*2);
240                 memset(&buf[80*24], 0, 80*2);
241         }
242 }
243
244 // === EXPORTS ===
245 EXPORT(__stack_chk_fail);

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