- Implement first part of SMP support.
[planlOS.git] / system / kernel / ke / interrupts.c
blobd4b87f2ac22c8af7bb3ac56e751f9afd0eff953b
1 /*
2 Copyright (C) 2008 Mathias Gottschlag
4 Permission is hereby granted, free of charge, to any person obtaining a copy of
5 this software and associated documentation files (the "Software"), to deal in the
6 Software without restriction, including without limitation the rights to use,
7 copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
8 Software, and to permit persons to whom the Software is furnished to do so,
9 subject to the following conditions:
11 The above copyright notice and this permission notice shall be included in all
12 copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
15 INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16 PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
17 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
18 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 #include "ke/interrupts.h"
23 #include "ke/debug.h"
24 #include "ke/ports.h"
25 #include "ke/gdt.h"
27 #include <string.h>
29 static IDTEntry idt[256];
31 static void keSetIDTEntry(int intno, void (*handler)(void), int dpl)
33 IDTEntry entry;
34 entry.zero = 0;
35 entry.offset_low = (uint32_t)handler & 0x0000FFFF;
36 entry.offset_high = (uint32_t)handler >> 16;
37 entry.selector = 0x8;
38 entry.type = 0x8e + ((dpl & 0x3) << 5);
39 idt[intno] = entry;
42 void keInitPIC(void)
44 memset(idt, 0, sizeof(IDTEntry) * 256);
46 // Remap PIC
47 outb(0x20, 0x11);
48 outb(0xa0, 0x11);
49 outb(0x21, 0x20);
50 outb(0xa1, 0x28);
51 outb(0x21, 0x04);
52 outb(0xa1, 0x02);
53 outb(0x21, 0x01);
54 outb(0xa1, 0x01);
55 outb(0x21, 0xff);
56 outb(0xa1, 0xff);
58 // Fill IDT
59 keSetIDTEntry(0x00, keInt00, 0);
60 keSetIDTEntry(0x01, keInt01, 0);
61 keSetIDTEntry(0x02, keInt02, 0);
62 keSetIDTEntry(0x03, keInt03, 0);
63 keSetIDTEntry(0x04, keInt04, 0);
64 keSetIDTEntry(0x05, keInt05, 0);
65 keSetIDTEntry(0x06, keInt06, 0);
66 keSetIDTEntry(0x07, keInt07, 0);
67 keSetIDTEntry(0x08, keInt08, 0);
68 keSetIDTEntry(0x09, keInt09, 0);
69 keSetIDTEntry(0x0a, keInt0a, 0);
70 keSetIDTEntry(0x0b, keInt0b, 0);
71 keSetIDTEntry(0x0c, keInt0c, 0);
72 keSetIDTEntry(0x0d, keInt0d, 0);
73 keSetIDTEntry(0x0e, keInt0e, 0);
74 keSetIDTEntry(0x0f, keInt0f, 0);
75 keSetIDTEntry(0x10, keInt10, 0);
76 keSetIDTEntry(0x11, keInt11, 0);
77 keSetIDTEntry(0x12, keInt12, 0);
78 keSetIDTEntry(0x13, keInt13, 0);
79 keSetIDTEntry(0x14, keInt14, 0);
80 keSetIDTEntry(0x15, keInt15, 0);
81 keSetIDTEntry(0x16, keInt16, 0);
82 keSetIDTEntry(0x17, keInt17, 0);
83 keSetIDTEntry(0x18, keInt18, 0);
84 keSetIDTEntry(0x19, keInt19, 0);
85 keSetIDTEntry(0x1a, keInt1a, 0);
86 keSetIDTEntry(0x1b, keInt1b, 0);
87 keSetIDTEntry(0x1c, keInt1c, 0);
88 keSetIDTEntry(0x1d, keInt1d, 0);
89 keSetIDTEntry(0x1e, keInt1e, 0);
90 keSetIDTEntry(0x1f, keInt1f, 0);
92 keSetIDTEntry(0x20, keInt20, 0);
93 keSetIDTEntry(0x21, keInt21, 0);
94 keSetIDTEntry(0x22, keInt22, 0);
95 keSetIDTEntry(0x23, keInt23, 0);
96 keSetIDTEntry(0x24, keInt24, 0);
97 keSetIDTEntry(0x25, keInt25, 0);
98 keSetIDTEntry(0x26, keInt26, 0);
99 keSetIDTEntry(0x27, keInt27, 0);
100 keSetIDTEntry(0x28, keInt28, 0);
101 keSetIDTEntry(0x29, keInt29, 0);
102 keSetIDTEntry(0x2a, keInt2a, 0);
103 keSetIDTEntry(0x2b, keInt2b, 0);
104 keSetIDTEntry(0x2c, keInt2c, 0);
105 keSetIDTEntry(0x2d, keInt2d, 0);
106 keSetIDTEntry(0x2e, keInt2e, 0);
107 keSetIDTEntry(0x2f, keInt2f, 0);
109 keSetIDTEntry(0x30, keInt30, 3);
111 // Enable IDT
112 IDTDescriptor desc;
113 desc.size = 256 * sizeof(IDTEntry) - 1;
114 desc.base = (uint32_t)idt - 0xC0000000;
116 asm("lidt %0"::"m"(desc));
119 void keInitPIC2(void)
121 // Enable IDT
122 IDTDescriptor desc;
123 desc.size = 256 * sizeof(IDTEntry) - 1;
124 desc.base = (uint32_t)idt;
126 asm("lidt %0"::"m"(desc));
129 //extern Thread *current_thread;
131 //static volatile int exception_handler_started = 0;
133 void keExceptionHandler(IntStackFrame *isf)
135 /*if (isf->cs == 0x8)
137 // TODO: Don't kill kernel on non-critical exceptions
138 // Print register info
139 if (isf->intno == 14) {
140 uint32_t cr2;
141 asm("mov %%cr2, %0":"=r"(cr2));
142 kePrint("\nPanic:\nPage fault at %x, error code: %x\n\n", cr2, isf->error);
143 /*if (current_thread && current_thread->thread.task)
145 kePrint("Task: %d, thread: %d\n\n", current_thread->thread.task->id, current_thread->thread.id);
147 } else {
148 kePrint("\n\nPanic:\nException %d, error code: %x\n\n", isf->intno, isf->error);
150 kePrint("eax: %x\tebx: %x\tecx: %x\tedx: %x\n", isf->eax, isf->ebx, isf->ecx, isf->edx);
151 kePrint("ds: %x\tes: %x\tfs: %x\tgs: %x\n", isf->ds, isf->es, isf->fs, isf->gs);
152 kePrint("ss: %x\tesp: %x\tcs: %x\teip: %x\n", isf->ss, isf->esp, isf->cs, isf->eip);
153 kePrint("eflags: %x\n", isf->eflags);
154 asm("cli");
155 asm("hlt");
156 while(1);
158 else
160 // Print register info
161 if (isf->intno == 14) {
162 uint32_t cr2;
163 asm("mov %%cr2, %0":"=r"(cr2));
164 if (current_thread && (cr2 < current_thread->userstack + 0x400000) && (cr2 > current_thread->userstack))
166 // Just grow stack
167 uint32_t *page_dir = (uint32_t*)halFindContinuousPages(kernel_directory, 1, 0xE0000000, 0xFFFFFFFF);
168 halMapPage(kernel_directory, (uint32_t)page_dir, ((X86Task*)current_thread->thread.task)->pagedir, 0x3);
169 uintptr_t userstack_phys = halAllocPhysPage();
170 halMapPage(page_dir, cr2 & ~0xFFF, userstack_phys, 0x7);
171 halMapPage(kernel_directory, (uint32_t)page_dir, 0, 0x0);
172 return;
174 kePrint("\nProcess killed:\nPage fault at %x, error code: %x\n\n", cr2, isf->error);
175 if (current_thread && current_thread->thread.task)
177 kePrint("Task: %d, thread: %d\n\n", current_thread->thread.task->id, current_thread->thread.id);
179 } else {
180 kePrint("\n\nProcess killed:\nException %d, error code: %x\n\n", isf->intno, isf->error);
182 kePrint("eax: %x\tebx: %x\tecx: %x\tedx: %x\n", isf->eax, isf->ebx, isf->ecx, isf->edx);
183 kePrint("ds: %x\tes: %x\tfs: %x\tgs: %x\n", isf->ds, isf->es, isf->fs, isf->gs);
184 kePrint("ss: %x\tesp: %x\tcs: %x\teip: %x\n", isf->ss, isf->esp, isf->cs, isf->eip);
185 kePrint("eflags: %x\n", isf->eflags);
186 // Kill task
187 Task *task = current_thread->thread.task;
188 while (task->threadcount > 0)
190 Thread *thread0 = task->threads[0];
191 sysRemoveThread(thread0);
192 halDestroyThread(thread0);
194 halDestroyTask(task);
195 }*/
198 /*inline void keSyscall(void)
200 IntStackFrame *isf = (IntStackFrame*)current_thread->kernelstack;
201 sysSyscall(&current_thread->thread, isf->eax, &isf->ebx, &isf->ecx, &isf->edx, &isf->esi, &isf->edi);
204 void (*irq_handler[16])(void);
206 void *keIntHandler(IntStackFrame *isf)
208 /*if (current_thread)
210 current_thread->kernelstack = (uintptr_t)isf;
212 if (isf->intno < 0x20) {
213 // Exception
214 keExceptionHandler(isf);
215 } else if (isf->intno >= 0x30) {
216 if (isf->intno == 0x30) {
217 if (isf->cs != 0x8) {
218 //halSyscall();
219 //keSyscall(&current_thread->thread, isf->eax, &isf->ebx, &isf->ecx, &isf->edx, &isf->esi, &isf->edi);
220 } else {
221 //halSyscall();
224 } else {
225 // Call handler
227 if (irq_handler[isf->intno - 0x20]) {
228 irq_handler[isf->intno - 0x20]();
230 /*if (irq_handler_user[isf->intno - 0x20].entry && irq_handler_user[isf->intno - 0x20].thread)
232 keThreadCallFunction(irq_handler_user[isf->intno - 0x20].thread, irq_handler_user[isf->intno - 0x20].entry, 1, isf->intno - 0x20);
233 keScheduleThread(irq_handler_user[isf->intno - 0x20].thread);
235 else */if (!irq_handler[isf->intno - 0x20])
237 kePrint("Interrupt (%d) without handler!\n", isf->intno - 0x20);
240 // Send EOI
241 if (isf->intno >= 0x28) {
242 outb(0xA0, 0x20);
244 outb(0x20, 0x20);
246 //if (!current_thread) return isf;
247 //tss.esp0 = current_thread->kernelstack + 19 * 4;
248 //return (void*)current_thread->kernelstack;
251 void keRegisterIRQ(uint32_t irqno, void (*handler)(void))
253 irq_handler[irqno] = handler;
254 if (handler)
256 if (irqno < 8)
258 outb(0x21, inb(0x21) & ~(0x1 << irqno));
260 else
262 outb(0xa1, inb(0xa1) & ~(0x1 << (irqno - 8)));
265 else
267 if (irqno < 8)
269 outb(0x21, inb(0x21) | (0x1 << irqno));
271 else
273 outb(0xa1, inb(0xa1) | (0x1 << irqno));