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

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