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

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