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

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