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/>.
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! */
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
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);
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
[] =
120 "Non Maskable Interrupt",
122 "Into Detected Overflow",
128 "Coprocessor Segment Overrun",
130 "Segment Not Present",
132 "General Protection Fault",
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) {
168 ret
= page_fault (r
);
170 /* is it page fault of user space (process) or kernel space ? */
174 /* display kernel panic message */
176 kprintf ((unsigned char *) "Kernel panic -> ");
179 kprintf ((unsigned char *) exception_messages
[r
->int_no
]);
180 kprintf ((unsigned char *) " Exception. System Halted!\n");
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",
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)
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 */
223 i
= (regs
->which_int
- 0x28) + 0x70;
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)
234 /* GPF from V86 mode: emulate instructions */
235 else if (regs
->which_int
== 0x0D) {
236 if (regs
->eflags
& 0x20000uL
) {
237 i
= v86_emulate (regs
);
241 kprintf ("virtual mode x86 error !\n");
245 /* pop from empty stack: end V86 session */
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
)
260 else if (regs
->cs
& 0x03)
263 kprintf ("in kernel");
265 kprintf (" mode ***\n");