Cleanup in elf.c with .bss section clean; adm command mounts cdrom instead of floppy...
[ZeXOS.git] / kernel / arch / i386 / isrs.c
blob92ec5b2b427db5f17b3faed4419008faa42637e8
1 /*
2 * ZeX/OS
3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include <system.h>
22 #include <arch/io.h>
23 #include <string.h>
25 /* These are function prototypes for all of the exception
26 * handlers: The first 32 entries in the IDT are reserved
27 * by Intel, and are designed to service exceptions! */
28 extern void isr0 ();
29 extern void isr1 ();
30 extern void isr2 ();
31 extern void isr3 ();
32 extern void isr4 ();
33 extern void isr5 ();
34 extern void isr6 ();
35 extern void isr7 ();
36 extern void isr8 ();
37 extern void isr9 ();
38 extern void isr10 ();
39 extern void isr11 ();
40 extern void isr12 ();
41 extern void isr13 ();
42 extern void isr14 ();
43 extern void isr15 ();
44 extern void isr16 ();
45 extern void isr17 ();
46 extern void isr18 ();
47 extern void isr19 ();
48 extern void isr20 ();
49 extern void isr21 ();
50 extern void isr22 ();
51 extern void isr23 ();
52 extern void isr24 ();
53 extern void isr25 ();
54 extern void isr26 ();
55 extern void isr27 ();
56 extern void isr28 ();
57 extern void isr29 ();
58 extern void isr30 ();
59 extern void isr31 ();
62 /* This is a very repetitive function... it's not hard, it's
63 * just annoying. As you can see, we set the first 32 entries
64 * in the IDT to the first 32 ISRs. We can't use a for loop
65 * for this, because there is no way to get the function names
66 * that correspond to that given entry. We set the access
67 * flags to 0x8E. This means that the entry is present, is
68 * running in ring 0 (kernel level), and has the lower 5 bits
69 * set to the required '14', which is represented by 'E' in
70 * hex. */
71 unsigned int isrs_install ()
73 idt_set_gate (0, (unsigned) isr0, 0x08, 0x8E);
74 idt_set_gate (1, (unsigned) isr1, 0x08, 0x8E);
75 idt_set_gate (2, (unsigned) isr2, 0x08, 0x8E);
76 idt_set_gate (3, (unsigned) isr3, 0x08, 0x8E);
77 idt_set_gate (4, (unsigned) isr4, 0x08, 0x8E);
78 idt_set_gate (5, (unsigned) isr5, 0x08, 0x8E);
79 idt_set_gate (6, (unsigned) isr6, 0x08, 0x8E);
80 idt_set_gate (7, (unsigned) isr7, 0x08, 0x8E);
82 idt_set_gate (8, (unsigned) isr8, 0x08, 0x8E);
83 idt_set_gate (9, (unsigned) isr9, 0x08, 0x8E);
84 idt_set_gate (10, (unsigned) isr10, 0x08, 0x8E);
85 idt_set_gate (11, (unsigned) isr11, 0x08, 0x8E);
86 idt_set_gate (12, (unsigned) isr12, 0x08, 0x8E);
87 idt_set_gate (13, (unsigned) isr13, 0x08, 0x8E);
88 idt_set_gate (14, (unsigned) isr14, 0x08, 0x8E);
89 idt_set_gate (15, (unsigned) isr15, 0x08, 0x8E);
91 idt_set_gate (16, (unsigned) isr16, 0x08, 0x8E);
92 idt_set_gate (17, (unsigned) isr17, 0x08, 0x8E);
93 idt_set_gate (18, (unsigned) isr18, 0x08, 0x8E);
94 idt_set_gate (19, (unsigned) isr19, 0x08, 0x8E);
95 idt_set_gate (20, (unsigned) isr20, 0x08, 0x8E);
96 idt_set_gate (21, (unsigned) isr21, 0x08, 0x8E);
97 idt_set_gate (22, (unsigned) isr22, 0x08, 0x8E);
98 idt_set_gate (23, (unsigned) isr23, 0x08, 0x8E);
100 idt_set_gate (24, (unsigned) isr24, 0x08, 0x8E);
101 idt_set_gate (25, (unsigned) isr25, 0x08, 0x8E);
102 idt_set_gate (26, (unsigned) isr26, 0x08, 0x8E);
103 idt_set_gate (27, (unsigned) isr27, 0x08, 0x8E);
104 idt_set_gate (28, (unsigned) isr28, 0x08, 0x8E);
105 idt_set_gate (29, (unsigned) isr29, 0x08, 0x8E);
106 idt_set_gate (30, (unsigned) isr30, 0x08, 0x8E);
107 idt_set_gate (31, (unsigned) isr31, 0x08, 0x8E);
109 return 1;
112 /* This is a simple string array. It contains the message that
113 * corresponds to each and every exception. We get the correct
114 * message by accessing like:
115 * exception_message[interrupt_number] */
116 char *exception_messages[] =
118 "Division By Zero",
119 "Debug",
120 "Non Maskable Interrupt",
121 "Breakpoint",
122 "Into Detected Overflow",
123 "Out of Bounds",
124 "Invalid Opcode",
125 "No Coprocessor",
127 "Double Fault",
128 "Coprocessor Segment Overrun",
129 "Bad TSS",
130 "Segment Not Present",
131 "Stack Fault",
132 "General Protection Fault",
133 "Page Fault",
134 "Unknown Interrupt",
136 "Coprocessor Fault",
137 "Alignment Check",
138 "Machine Check",
139 "Reserved",
140 "Reserved",
141 "Reserved",
142 "Reserved",
143 "Reserved",
145 "Reserved",
146 "Reserved",
147 "Reserved",
148 "Reserved",
149 "Reserved",
150 "Reserved",
151 "Reserved",
152 "Reserved"
155 /* All of our Exception handling Interrupt Service Routines will
156 * point to this function. This will tell us what exception has
157 * happened! Right now, we simply halt the system by hitting an
158 * endless loop. All ISRs disable interrupts while they are being
159 * serviced as a 'locking' mechanism to prevent an IRQ from
160 * happening and messing up kernel data structures */
161 void fault_handler (struct regs *r)
163 if (r->int_no < 32) {
164 int ret = 0;
166 /* page fault */
167 if (r->int_no == 14)
168 ret = page_fault (r);
170 /* is it page fault of user space (process) or kernel space ? */
171 if (ret)
172 return;
174 /* display kernel panic message */
175 video_color (4, 0);
176 kprintf ((unsigned char *) "Kernel panic -> ");
178 video_color (15, 0);
179 kprintf ((unsigned char *) exception_messages[r->int_no]);
180 kprintf ((unsigned char *) " Exception. System Halted!\n");
182 int_disable ();
184 while (1)
185 asm ("hlt;");
189 /*****************************************************************************
190 *****************************************************************************/
191 int fault (uregs_t *regs)
193 static const char *msg[] = {
194 "divide error", "debug exception", "NMI", "INT3",
195 "INTO", "BOUND exception", "invalid opcode", "no coprocessor",
196 "double fault", "coprocessor segment overrun",
197 "bad TSS", "segment not present",
198 "stack fault", "GPF", "page fault", "??",
199 "coprocessor error", "alignment check", "??", "??",
200 "??", "??", "??", "??",
201 "??", "??", "??", "??",
202 "??", "??", "??", "??",
203 "IRQ0", "IRQ1", "IRQ2", "IRQ3",
204 "IRQ4", "IRQ5", "IRQ6", "IRQ7",
205 "IRQ8", "IRQ9", "IRQ10", "IRQ11",
206 "IRQ12", "IRQ13", "IRQ14", "IRQ15",
207 "syscall"
210 int i;
212 /* "reflect" hardware interrupts (IRQs) to V86 mode */
213 if(regs->which_int >= 0x20 && regs->which_int < 0x30) {
214 /* for timer interrupt, blink character in upper left corner of screen */
215 //if(regs->which_int == 0x20)
216 // blink();
218 /* IRQs 0-7 -> pmode exception numbers 20h-27h -> real-mode vectors 8-15 */
219 if (regs->which_int < 0x28)
220 i = (regs->which_int - 0x20) + 8;
221 /* IRQs 8-15 -> pmode exception numbers 28h-2Fh -> real-mode vectors 70h-77h */
222 else
223 i = (regs->which_int - 0x28) + 0x70;
225 v86_int (regs, i);
227 return 0;
229 /* stack fault from V86 mode with SP=0xFFFF means we're done */
230 else if (regs->which_int == 0x0C) {
231 if ((regs->eflags & 0x20000uL) && regs->user_esp == 0xFFFF)
232 return 1;
234 /* GPF from V86 mode: emulate instructions */
235 else if (regs->which_int == 0x0D) {
236 if (regs->eflags & 0x20000uL) {
237 i = v86_emulate (regs);
239 /* error */
240 if (i < 0) {
241 kprintf ("virtual mode x86 error !\n");
242 while (1);
245 /* pop from empty stack: end V86 session */
246 else if(i > 0)
247 return 1;
248 return 0;
252 /* for anything else, display exception number, exception name, and CPU mode */
253 kprintf("*** Exception #%u ", regs->which_int);
255 if (regs->which_int <= sizeof(msg) / sizeof(char *))
256 kprintf ("(%s) ", msg[regs->which_int]);
258 if (regs->eflags & 0x20000uL)
259 kprintf ("in V86");
260 else if (regs->cs & 0x03)
261 kprintf ("in user");
262 else
263 kprintf ("in kernel");
265 kprintf (" mode ***\n");
267 /* not reached */
268 return -1;