about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYour Name <you@example.com>2020-06-23 19:31:26 +0200
committerYour Name <you@example.com>2020-06-23 19:31:26 +0200
commit86add5103e8b80a5ba614c1d4986b67ffb073953 (patch)
tree338e0af49c5093cef88485509fc4fce8010da79e
parentFormat: added kernel includes to pOS.h instead of kernel.cpp (diff)
downloadpOS-86add5103e8b80a5ba614c1d4986b67ffb073953.tar.gz
pOS-86add5103e8b80a5ba614c1d4986b67ffb073953.tar.bz2
pOS-86add5103e8b80a5ba614c1d4986b67ffb073953.zip
Base: Added support for interrupts and exception handlers
-rw-r--r--src/bootloader/boot.s5
-rw-r--r--src/bootloader/utils/gdt.s33
-rw-r--r--src/bootloader/utils/irq.s157
-rw-r--r--src/bootloader/utils/isrs.s282
-rw-r--r--src/pOS/arch/x86/kernel/interrupts/asm/gdt.s15
-rw-r--r--src/pOS/arch/x86/kernel/interrupts/asm/idt.s5
-rw-r--r--src/pOS/arch/x86/kernel/interrupts/gdt.cpp56
-rw-r--r--src/pOS/arch/x86/kernel/interrupts/idt.cpp35
-rw-r--r--src/pOS/arch/x86/kernel/interrupts/irq.cpp86
-rw-r--r--src/pOS/arch/x86/kernel/interrupts/isrs.cpp95
-rw-r--r--src/pOS/arch/x86/kernel/interrupts/pic.cpp33
-rw-r--r--src/pOS/include/kernel/interrupts/gdt.h37
-rw-r--r--src/pOS/include/kernel/interrupts/idt.h37
-rw-r--r--src/pOS/include/kernel/interrupts/irq.h36
-rw-r--r--src/pOS/include/kernel/interrupts/isrs.h49
-rw-r--r--src/pOS/include/kernel/interrupts/pic.h24
-rw-r--r--src/pOS/include/kernel/registers.h48
-rw-r--r--src/pOS/kernel/kernel.cpp17
18 files changed, 1042 insertions, 8 deletions
diff --git a/src/bootloader/boot.s b/src/bootloader/boot.s
index 0bb10d5..4b0de1f 100644
--- a/src/bootloader/boot.s
+++ b/src/bootloader/boot.s
@@ -30,4 +30,7 @@ _start:
 	cli
 .inf:	hlt
 	jmp .inf
-.end:	
+.end:
+
+%include "utils/isrs.s"
+%include "utils/irq.s"
diff --git a/src/bootloader/utils/gdt.s b/src/bootloader/utils/gdt.s
new file mode 100644
index 0000000..58883fd
--- /dev/null
+++ b/src/bootloader/utils/gdt.s
@@ -0,0 +1,33 @@
+gdt_start:
+  gdt_null:
+  dq 0
+
+  gdt_code:
+  dw 0FFFFh
+  dw 0
+
+  db 0
+  db 10011010b
+  db 11001111b
+  db 0
+
+  gdt_data:
+  dw 0FFFFh
+  dw 0
+
+  db 0
+  db 10010010b
+  db 11001111b
+  db 0
+
+  gdt_end:
+
+  gdt:
+   dw gdt_end - gdt_start - 1
+   dd gdt_start
+
+load_GDT:
+    cli
+    lgdt [gdt]
+    sti
+    ret
diff --git a/src/bootloader/utils/irq.s b/src/bootloader/utils/irq.s
new file mode 100644
index 0000000..c485613
--- /dev/null
+++ b/src/bootloader/utils/irq.s
@@ -0,0 +1,157 @@
+global irq0
+global irq1
+global irq2
+global irq3
+global irq4
+global irq5
+global irq6
+global irq7
+global irq8
+global irq9
+global irq10
+global irq11
+global irq12
+global irq13
+global irq14
+global irq15
+
+; 32: IRQ0
+irq0:
+    cli
+    push byte 0
+    push byte 32
+    jmp irq_common_stub
+
+; 33: IRQ1
+irq1:
+    cli
+    push byte 0
+    push byte 33
+    jmp irq_common_stub
+
+; 34: IRQ2
+irq2:
+    cli
+    push byte 0
+    push byte 34
+    jmp irq_common_stub
+
+; 35: IRQ3
+irq3:
+    cli
+    push byte 0
+    push byte 35
+    jmp irq_common_stub
+
+; 36: IRQ4
+irq4:
+    cli
+    push byte 0
+    push byte 36
+    jmp irq_common_stub
+
+; 37: IRQ5
+irq5:
+    cli
+    push byte 0
+    push byte 37
+    jmp irq_common_stub
+
+; 38: IRQ6
+irq6:
+    cli
+    push byte 0
+    push byte 38
+    jmp irq_common_stub
+
+; 39: IRQ7
+irq7:
+    cli
+    push byte 0
+    push byte 39
+    jmp irq_common_stub
+
+; 40: IRQ8
+irq8:
+    cli
+    push byte 0
+    push byte 40
+    jmp irq_common_stub
+
+; 41: IRQ9
+irq9:
+    cli
+    push byte 0
+    push byte 41
+    jmp irq_common_stub
+
+; 42: IRQ10
+irq10:
+    cli
+    push byte 0
+    push byte 42
+    jmp irq_common_stub
+
+; 43: IRQ11
+irq11:
+    cli
+    push byte 0
+    push byte 43
+    jmp irq_common_stub
+
+; 44: IRQ12
+irq12:
+    cli
+    push byte 0
+    push byte 44
+    jmp irq_common_stub
+
+; 45: IRQ13
+irq13:
+    cli
+    push byte 0
+    push byte 45
+    jmp irq_common_stub
+
+; 46: IRQ14
+irq14:
+    cli
+    push byte 0
+    push byte 46
+    jmp irq_common_stub
+
+; 47: IRQ15
+irq15:
+    cli
+    push byte 0
+    push byte 47
+    jmp irq_common_stub
+
+extern irq_handler
+
+irq_common_stub:
+    pusha
+    push ds
+    push es
+    push fs
+    push gs
+
+    mov ax, 0x10
+    mov ds, ax
+    mov es, ax
+    mov fs, ax
+    mov gs, ax
+    mov eax, esp
+
+    push eax
+    mov eax, irq_handler
+    call eax
+    pop eax
+
+    pop gs
+    pop fs
+    pop es
+    pop ds
+    popa
+    add esp, 8
+    iret
diff --git a/src/bootloader/utils/isrs.s b/src/bootloader/utils/isrs.s
new file mode 100644
index 0000000..4c2176a
--- /dev/null
+++ b/src/bootloader/utils/isrs.s
@@ -0,0 +1,282 @@
+global isr0
+global isr1
+global isr2
+global isr3
+global isr4
+global isr5
+global isr6
+global isr7
+global isr8
+global isr9
+global isr10
+global isr11
+global isr12
+global isr13
+global isr14
+global isr15
+global isr16
+global isr17
+global isr18
+global isr19
+global isr20
+global isr21
+global isr22
+global isr23
+global isr24
+global isr25
+global isr26
+global isr27
+global isr28
+global isr29
+global isr30
+global isr31
+
+;  0: Divide By Zero Exception
+isr0:
+    cli
+    push byte 0
+    push byte 0
+    jmp isr_common_stub
+
+;  1: Debug Exception
+isr1:
+    cli
+    push byte 0
+    push byte 1
+    jmp isr_common_stub
+
+;  2: Non Maskable Interrupt Exception
+isr2:
+    cli
+    push byte 0
+    push byte 2
+    jmp isr_common_stub
+
+;  3: Int 3 Exception
+isr3:
+    cli
+    push byte 0
+    push byte 3
+    jmp isr_common_stub
+
+;  4: INTO Exception
+isr4:
+    cli
+    push byte 0
+    push byte 4
+    jmp isr_common_stub
+
+;  5: Out of Bounds Exception
+isr5:
+    cli
+    push byte 0
+    push byte 5
+    jmp isr_common_stub
+
+;  6: Invalid Opcode Exception
+isr6:
+    cli
+    push byte 0
+    push byte 6
+    jmp isr_common_stub
+
+;  7: Coprocessor Not Available Exception
+isr7:
+    cli
+    push byte 0
+    push byte 7
+    jmp isr_common_stub
+
+;  8: Double Fault Exception (With Error Code!)
+isr8:
+    cli
+    push byte 8
+    jmp isr_common_stub
+
+;  9: Coprocessor Segment Overrun Exception
+isr9:
+    cli
+    push byte 0
+    push byte 9
+    jmp isr_common_stub
+
+; 10: Bad TSS Exception (With Error Code!)
+isr10:
+    cli
+    push byte 10
+    jmp isr_common_stub
+
+; 11: Segment Not Present Exception (With Error Code!)
+isr11:
+    cli
+    push byte 11
+    jmp isr_common_stub
+
+; 12: Stack Fault Exception (With Error Code!)
+isr12:
+    cli
+    push byte 12
+    jmp isr_common_stub
+
+; 13: General Protection Fault Exception (With Error Code!)
+isr13:
+    cli
+    push byte 13
+    jmp isr_common_stub
+
+; 14: Page Fault Exception (With Error Code!)
+isr14:
+    cli
+    push byte 14
+    jmp isr_common_stub
+
+; 15: Reserved Exception
+isr15:
+    cli
+    push byte 0
+    push byte 15
+    jmp isr_common_stub
+
+; 16: Floating Point Exception
+isr16:
+    cli
+    push byte 0
+    push byte 16
+    jmp isr_common_stub
+
+; 17: Alignment Check Exception
+isr17:
+    cli
+    push byte 0
+    push byte 17
+    jmp isr_common_stub
+
+; 18: Machine Check Exception
+isr18:
+    cli
+    push byte 0
+    push byte 18
+    jmp isr_common_stub
+
+; 19: Reserved
+isr19:
+    cli
+    push byte 0
+    push byte 19
+    jmp isr_common_stub
+
+; 20: Reserved
+isr20:
+    cli
+    push byte 0
+    push byte 20
+    jmp isr_common_stub
+
+; 21: Reserved
+isr21:
+    cli
+    push byte 0
+    push byte 21
+    jmp isr_common_stub
+
+; 22: Reserved
+isr22:
+    cli
+    push byte 0
+    push byte 22
+    jmp isr_common_stub
+
+; 23: Reserved
+isr23:
+    cli
+    push byte 0
+    push byte 23
+    jmp isr_common_stub
+
+; 24: Reserved
+isr24:
+    cli
+    push byte 0
+    push byte 24
+    jmp isr_common_stub
+
+; 25: Reserved
+isr25:
+    cli
+    push byte 0
+    push byte 25
+    jmp isr_common_stub
+
+; 26: Reserved
+isr26:
+    cli
+    push byte 0
+    push byte 26
+    jmp isr_common_stub
+
+; 27: Reserved
+isr27:
+    cli
+    push byte 0
+    push byte 27
+    jmp isr_common_stub
+
+; 28: Reserved
+isr28:
+    cli
+    push byte 0
+    push byte 28
+    jmp isr_common_stub
+
+; 29: Reserved
+isr29:
+    cli
+    push byte 0
+    push byte 29
+    jmp isr_common_stub
+
+; 30: Reserved
+isr30:
+    cli
+    push byte 0
+    push byte 30
+    jmp isr_common_stub
+
+; 31: Reserved
+isr31:
+    cli
+    push byte 0
+    push byte 31
+    jmp isr_common_stub
+
+
+; We call a C function in here. We need to let the assembler know
+; that '_fault_handler' exists in another file
+extern fault_handler
+
+; This is our common ISR stub. It saves the processor state, sets
+; up for kernel mode segments, calls the C-level fault handler,
+; and finally restores the stack frame.
+isr_common_stub:
+    pusha
+    push ds
+    push es
+    push fs
+    push gs
+    mov ax, 0x10
+    mov ds, ax
+    mov es, ax
+    mov fs, ax
+    mov gs, ax
+    mov eax, esp
+    push eax
+    mov eax, fault_handler
+    call eax
+    pop eax
+    pop gs
+    pop fs
+    pop es
+    pop ds
+    popa
+    add esp, 8
+    iret
diff --git a/src/pOS/arch/x86/kernel/interrupts/asm/gdt.s b/src/pOS/arch/x86/kernel/interrupts/asm/gdt.s
new file mode 100644
index 0000000..9480ef1
--- /dev/null
+++ b/src/pOS/arch/x86/kernel/interrupts/asm/gdt.s
@@ -0,0 +1,15 @@
+[GLOBAL gdt_flush]
+
+gdt_flush:
+   mov eax, [esp+4]  ; Get the pointer to the GDT, passed as a parameter.
+   lgdt [eax]        ; Load the new GDT pointer
+
+   mov ax, 0x10      ; 0x10 is the offset in the GDT to our data segment
+   mov ds, ax        ; Load all data segment selectors
+   mov es, ax
+   mov fs, ax
+   mov gs, ax
+   mov ss, ax
+   jmp 0x08:.flush   ; 0x08 is the offset to our code segment
+.flush:
+   ret
diff --git a/src/pOS/arch/x86/kernel/interrupts/asm/idt.s b/src/pOS/arch/x86/kernel/interrupts/asm/idt.s
new file mode 100644
index 0000000..f6bd58e
--- /dev/null
+++ b/src/pOS/arch/x86/kernel/interrupts/asm/idt.s
@@ -0,0 +1,5 @@
+[GLOBAL idt_flush]
+idt_flush:
+    mov eax, [esp + 4]
+    lidt [eax]
+    ret
diff --git a/src/pOS/arch/x86/kernel/interrupts/gdt.cpp b/src/pOS/arch/x86/kernel/interrupts/gdt.cpp
new file mode 100644
index 0000000..0774421
--- /dev/null
+++ b/src/pOS/arch/x86/kernel/interrupts/gdt.cpp
@@ -0,0 +1,56 @@
+#include <kernel/interrupts/gdt.h>
+
+gdt_entry_t GDT::gdt_entries[GDT_NUM_DESCRIPTORS];
+gdt_ptr_t gdt_ptr;
+
+int GDT::init(void) {
+    memset(gdt_entries, 0, sizeof(gdt_entries));
+
+    gdt_ptr.limit = sizeof(gdt_entries) - 1;
+    gdt_ptr.base = (uint32_t)gdt_entries;
+
+    // NULL Segment
+    set_entry(0, 0, 0, 0, 0);
+    /* Kernel code, access(9A = 1 00 1 1 0 1 0)
+        1   present
+        00  ring 0
+        1   always 1
+        1   code segment
+        0   can be executed by ring lower or equal to DPL,
+        1   code segment is readable
+        0   access bit, always 0, cpu set this to 1 when accessing this sector*/
+
+    set_entry(1, 0, 0xFFFFFFFF, 0x9A, 0xCF);
+    /* Kernel data, access(92 = 1 00 1 0 0 1 0)
+        Only differ at the fifth bit(counting from least insignificant bit), 0 means it's a data segment.*/
+
+    set_entry(2, 0, 0xFFFFFFFF, 0x92, 0xCF);
+    // User code and data segments, only differ in ring number(ring 3)
+    set_entry(3, 0, 0xFFFFFFFF, 0xFA, 0xCF);
+    set_entry(4, 0, 0xFFFFFFFF, 0xF2, 0xCF);
+
+    gdt_flush((uint32_t)(&gdt_ptr));
+
+    return 0;
+}
+
+int GDT::set_entry(int index, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) {
+    gdt_entry_t& entry = gdt_entries[index];
+
+    // Low 16 bits, middle 8 bits and high 8 bits of base
+    entry.base_low = base & 0xFFFF;
+    entry.base_middle = (base >> 16) & 0xFF;
+    entry.base_high = (base >> 24 & 0xFF);
+
+    /*  16 bits and high 4 bits of limit, since the high 4 bits of limits is between granularity and access, and we don't have 4 bit variable,
+    low 4 bits of granularity actually represents high 4 bits of limits. It's weird, I know.*/
+    entry.limit_low = limit & 0xFFFF;
+    entry.granularity = (limit >> 16) & 0x0F;
+
+    entry.access = access;
+
+    // Only need the high 4 bits of gran
+    entry.granularity = entry.granularity | (gran & 0xF0);
+
+    return 0;
+}
diff --git a/src/pOS/arch/x86/kernel/interrupts/idt.cpp b/src/pOS/arch/x86/kernel/interrupts/idt.cpp
new file mode 100644
index 0000000..b44d570
--- /dev/null
+++ b/src/pOS/arch/x86/kernel/interrupts/idt.cpp
@@ -0,0 +1,35 @@
+#include <kernel/interrupts/idt.h>
+
+idt_entry_t IDT::idt_entries[NUM_IDT_ENTRIES];
+idt_ptr_t idt_ptr;
+
+int IDT::init(void) {
+    memset(idt_entries, 0, sizeof(idt_entries));
+
+    idt_ptr.base = (uint32_t)idt_entries;
+    idt_ptr.limit = sizeof(idt_entries) - 1;
+
+    PIC::init();
+
+    IRQ::install();
+
+    idt_flush((uint32_t)&(idt_ptr));
+    asm volatile("sti");
+
+    return 0;
+}
+
+int IDT::set_entry(int index, uint32_t base, uint16_t sel, uint8_t flags) {
+    idt_entry_t& entry = idt_entries[index];
+
+    entry.base_lo = base & 0xFFFF;
+    entry.base_hi = (base >> 16) & 0xFFFF;
+
+    entry.always0 = 0;
+
+    entry.sel = sel;
+
+    entry.flags = flags | 0x60;
+
+    return 0;
+}
diff --git a/src/pOS/arch/x86/kernel/interrupts/irq.cpp b/src/pOS/arch/x86/kernel/interrupts/irq.cpp
new file mode 100644
index 0000000..70a577d
--- /dev/null
+++ b/src/pOS/arch/x86/kernel/interrupts/irq.cpp
@@ -0,0 +1,86 @@
+#include <kernel/interrupts/irq.h>
+
+static void* irq_routines[16] =
+{
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+int IRQ::install_handler(int irq, void (*handler)(struct regs *r))
+{
+    irq_routines[irq] = reinterpret_cast<void *&>(handler);
+
+    return 0;
+}
+
+int IRQ::uninstall_handler(int irq)
+{
+    irq_routines[irq] = 0;
+
+    return 0;
+}
+
+/* Remaps the IRQs so they are usable */
+int IRQ::remap(void)
+{
+    System::outb(0x20, 0x11);
+    System::outb(0xA0, 0x11);
+    System::outb(0x21, 0x20);
+    System::outb(0xA1, 0x28);
+    System::outb(0x21, 0x04);
+    System::outb(0xA1, 0x02);
+    System::outb(0x21, 0x01);
+    System::outb(0xA1, 0x01);
+    System::outb(0x21, 0x0);
+    System::outb(0xA1, 0x0);
+
+    return 0;
+}
+
+int IRQ::install(void)
+{
+
+    remap();
+
+    /* Do with macro */
+    IDT::set_entry(32, (unsigned)irq0, 0x08, 0x8E);
+    IDT::set_entry(33, (unsigned)irq1, 0x08, 0x8E);
+    IDT::set_entry(34, (unsigned)irq2, 0x08, 0x8E);
+    IDT::set_entry(35, (unsigned)irq3, 0x08, 0x8E);
+    IDT::set_entry(36, (unsigned)irq4, 0x08, 0x8E);
+    IDT::set_entry(37, (unsigned)irq5, 0x08, 0x8E);
+    IDT::set_entry(38, (unsigned)irq6, 0x08, 0x8E);
+    IDT::set_entry(39, (unsigned)irq7, 0x08, 0x8E);
+
+    IDT::set_entry(40, (unsigned)irq8, 0x08, 0x8E);
+    IDT::set_entry(41, (unsigned)irq9, 0x08, 0x8E);
+    IDT::set_entry(42, (unsigned)irq10, 0x08, 0x8E);
+    IDT::set_entry(43, (unsigned)irq11, 0x08, 0x8E);
+    IDT::set_entry(44, (unsigned)irq12, 0x08, 0x8E);
+    IDT::set_entry(45, (unsigned)irq13, 0x08, 0x8E);
+    IDT::set_entry(46, (unsigned)irq14, 0x08, 0x8E);
+    IDT::set_entry(47, (unsigned)irq15, 0x08, 0x8E);
+
+    return 0;
+}
+
+extern "C" void irq_handler(struct regs *r)
+{
+    void (*handler)(struct regs *r);
+
+    handler = reinterpret_cast<void (*)(struct regs *r)>(irq_routines[r->int_no - 32]);
+    if (handler)
+    {
+        handler(r);
+    }
+
+    /* If the IDT entry that was invoked was greater than 40
+    *  (meaning IRQ8 - 15), then we need to send an EOI to
+    *  the slave controller */
+    if (r->int_no >= 40)
+    {
+        System::outb(0xA0, 0x20);
+    }
+
+    /* EOI to the master interrupt controller */
+    System::outb(0x20, 0x20);
+}
diff --git a/src/pOS/arch/x86/kernel/interrupts/isrs.cpp b/src/pOS/arch/x86/kernel/interrupts/isrs.cpp
new file mode 100644
index 0000000..22935c9
--- /dev/null
+++ b/src/pOS/arch/x86/kernel/interrupts/isrs.cpp
@@ -0,0 +1,95 @@
+#include <kernel/interrupts/isrs.h>
+
+void ISRS::install(void)
+{
+    /* Do with macro */
+    IDT::set_entry(0, (unsigned)isr0, 0x08, 0x8E);
+    IDT::set_entry(1, (unsigned)isr1, 0x08, 0x8E);
+    IDT::set_entry(2, (unsigned)isr2, 0x08, 0x8E);
+    IDT::set_entry(3, (unsigned)isr3, 0x08, 0x8E);
+    IDT::set_entry(4, (unsigned)isr4, 0x08, 0x8E);
+    IDT::set_entry(5, (unsigned)isr5, 0x08, 0x8E);
+    IDT::set_entry(6, (unsigned)isr6, 0x08, 0x8E);
+    IDT::set_entry(7, (unsigned)isr7, 0x08, 0x8E);
+
+    IDT::set_entry(8, (unsigned)isr8, 0x08, 0x8E);
+    IDT::set_entry(9, (unsigned)isr9, 0x08, 0x8E);
+    IDT::set_entry(10, (unsigned)isr10, 0x08, 0x8E);
+    IDT::set_entry(11, (unsigned)isr11, 0x08, 0x8E);
+    IDT::set_entry(12, (unsigned)isr12, 0x08, 0x8E);
+    IDT::set_entry(13, (unsigned)isr13, 0x08, 0x8E);
+    IDT::set_entry(14, (unsigned)isr14, 0x08, 0x8E);
+    IDT::set_entry(15, (unsigned)isr15, 0x08, 0x8E);
+
+    IDT::set_entry(16, (unsigned)isr16, 0x08, 0x8E);
+    IDT::set_entry(17, (unsigned)isr17, 0x08, 0x8E);
+    IDT::set_entry(18, (unsigned)isr18, 0x08, 0x8E);
+    IDT::set_entry(19, (unsigned)isr19, 0x08, 0x8E);
+    IDT::set_entry(20, (unsigned)isr20, 0x08, 0x8E);
+    IDT::set_entry(21, (unsigned)isr21, 0x08, 0x8E);
+    IDT::set_entry(22, (unsigned)isr22, 0x08, 0x8E);
+    IDT::set_entry(23, (unsigned)isr23, 0x08, 0x8E);
+
+    IDT::set_entry(24, (unsigned)isr24, 0x08, 0x8E);
+    IDT::set_entry(25, (unsigned)isr25, 0x08, 0x8E);
+    IDT::set_entry(26, (unsigned)isr26, 0x08, 0x8E);
+    IDT::set_entry(27, (unsigned)isr27, 0x08, 0x8E);
+    IDT::set_entry(28, (unsigned)isr28, 0x08, 0x8E);
+    IDT::set_entry(29, (unsigned)isr29, 0x08, 0x8E);
+    IDT::set_entry(30, (unsigned)isr30, 0x08, 0x8E);
+    IDT::set_entry(31, (unsigned)isr31, 0x08, 0x8E);
+}
+
+/* This is a simple string array. It contains the message that
+*  corresponds to each and every exception. We get the correct
+*  message by accessing like:
+*  exception_message[interrupt_number] */
+const char *exception_messages[32] =
+{
+    "Division By Zero",
+    "Debug",
+    "Non Maskable Interrupt",
+    "Breakpoint",
+    "Into Detected Overflow",
+    "Out of Bounds",
+    "Invalid Opcode",
+    "No Coprocessor",
+
+    "Double Fault",
+    "Coprocessor Segment Overrun",
+    "Bad TSS",
+    "Segment Not Present",
+    "Stack Fault",
+    "General Protection Fault",
+    "Page Fault",
+    "Unknown Interrupt",
+
+    "Coprocessor Fault",
+    "Alignment Check",
+    "Machine Check",
+    "Reserved",
+    "Reserved",
+    "Reserved",
+    "Reserved",
+    "Reserved",
+
+    "Reserved",
+    "Reserved",
+    "Reserved",
+    "Reserved",
+    "Reserved",
+    "Reserved",
+    "Reserved",
+    "Reserved"
+};
+
+extern "C" void fault_handler(struct regs *r)
+{
+    if (r->int_no < 32)
+    {
+        REG::print_regs(r);
+        printf("%s", exception_messages[r->int_no]);
+        printf(" Exception. System Halted!\n");
+        System::idle_loop();
+    }
+}
diff --git a/src/pOS/arch/x86/kernel/interrupts/pic.cpp b/src/pOS/arch/x86/kernel/interrupts/pic.cpp
new file mode 100644
index 0000000..c540176
--- /dev/null
+++ b/src/pOS/arch/x86/kernel/interrupts/pic.cpp
@@ -0,0 +1,33 @@
+#include <kernel/interrupts/pic.h>
+
+int PIC::init(void) {
+    /* ICW1 */
+    System::outb(PIC1_COMMAND, ICW1);
+    System::outb(PIC2_COMMAND, ICW1);
+
+    /* ICW2, irq 0 to 7 is mapped to 0x20 to 0x27, irq 8 to F is mapped to 28 to 2F */
+    System::outb(PIC1_DATA, 0x20);
+    System::outb(PIC2_DATA, 0x28);
+
+    /* ICW3, connect master pic with slave pic */
+    System::outb(PIC1_DATA, 0x4);
+    System::outb(PIC2_DATA, 0x2);
+
+    /* ICW4, set x86 mode */
+    System::outb(PIC1_DATA, 1);
+    System::outb(PIC2_DATA, 1);
+
+    /* Clear the mask register */
+    System::outb(PIC1_DATA, 0);
+    System::outb(PIC2_DATA, 0);
+
+    return 0;
+}
+
+int PIC::irq_ack(uint8_t irq) {
+    if(irq >= 0x28)
+        System::outb(PIC2, PIC_EOI);
+    System::outb(PIC1, PIC_EOI);
+
+    return 0;
+}
diff --git a/src/pOS/include/kernel/interrupts/gdt.h b/src/pOS/include/kernel/interrupts/gdt.h
new file mode 100644
index 0000000..74a6e88
--- /dev/null
+++ b/src/pOS/include/kernel/interrupts/gdt.h
@@ -0,0 +1,37 @@
+#ifndef _GDT_H_
+#define _GDT_H_
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#define GDT_NUM_DESCRIPTORS 8
+
+typedef struct gdt_entry
+{
+    uint16_t limit_low;
+    uint16_t base_low;
+    uint8_t  base_middle;
+    uint8_t  access;
+    uint8_t  granularity;
+    uint8_t  base_high;
+} __attribute__((packed)) gdt_entry_t;
+
+typedef struct gdt_ptr
+{
+    uint16_t limit;
+    uint32_t base;
+} __attribute__((packed)) gdt_ptr_t;
+
+/* ASM func */
+extern "C" void gdt_flush(uint32_t gdt_ptr);
+
+class GDT
+{
+public:
+    static int init(void);
+    static int set_entry(int index, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran);
+private:
+    static gdt_entry_t gdt_entries[GDT_NUM_DESCRIPTORS];
+};
+
+#endif
diff --git a/src/pOS/include/kernel/interrupts/idt.h b/src/pOS/include/kernel/interrupts/idt.h
new file mode 100644
index 0000000..bca1006
--- /dev/null
+++ b/src/pOS/include/kernel/interrupts/idt.h
@@ -0,0 +1,37 @@
+#ifndef _IDT_H_
+#define _IDT_H_
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <kernel/interrupts/pic.h>
+#include <kernel/interrupts/irq.h>
+
+#define NUM_IDT_ENTRIES 256
+
+typedef struct idt_entry {
+    uint16_t base_lo;
+    uint16_t sel;
+    uint8_t always0;
+    uint8_t flags;
+    uint16_t base_hi;
+} __attribute__((packed)) idt_entry_t;
+
+typedef struct idt_ptr {
+    uint16_t limit;
+    uint32_t base;
+} __attribute__((packed)) idt_ptr_t;
+
+
+/* ASM func */
+extern "C" void idt_flush(uint32_t ptr);
+
+class IDT
+{
+public:
+    static int init(void);
+    static int set_entry(int index, uint32_t base, uint16_t sel, uint8_t ring);
+private:
+    static idt_entry_t idt_entries[NUM_IDT_ENTRIES];
+};
+
+#endif
diff --git a/src/pOS/include/kernel/interrupts/irq.h b/src/pOS/include/kernel/interrupts/irq.h
new file mode 100644
index 0000000..32db130
--- /dev/null
+++ b/src/pOS/include/kernel/interrupts/irq.h
@@ -0,0 +1,36 @@
+#ifndef _IRQ_H_
+#define _IRQ_H_
+
+#include <kernel/system.h>
+#include <kernel/registers.h>
+#include <kernel/interrupts/idt.h>
+
+/* Interrupt requests */
+extern "C" void irq0(void);
+extern "C" void irq1(void);
+extern "C" void irq2(void);
+extern "C" void irq3(void);
+extern "C" void irq4(void);
+extern "C" void irq5(void);
+extern "C" void irq6(void);
+extern "C" void irq7(void);
+extern "C" void irq8(void);
+extern "C" void irq9(void);
+extern "C" void irq10(void);
+extern "C" void irq11(void);
+extern "C" void irq12(void);
+extern "C" void irq13(void);
+extern "C" void irq14(void);
+extern "C" void irq15(void);
+
+class IRQ
+{
+public:
+    static int install_handler(int irq, void (*handler)(struct regs *r));
+    static int uninstall_handler(int irq);
+    static int install(void);
+private:
+    static int remap(void);
+};
+
+#endif
diff --git a/src/pOS/include/kernel/interrupts/isrs.h b/src/pOS/include/kernel/interrupts/isrs.h
new file mode 100644
index 0000000..c9cc9dd
--- /dev/null
+++ b/src/pOS/include/kernel/interrupts/isrs.h
@@ -0,0 +1,49 @@
+#ifndef _ISRS_H_
+#define _ISRS_H_
+
+#include <stdio.h>
+#include <kernel/system.h>
+#include <kernel/registers.h>
+#include <kernel/interrupts/idt.h>
+
+/* Exception handlers */
+extern "C" void isr0(void);
+extern "C" void isr1(void);
+extern "C" void isr2(void);
+extern "C" void isr3(void);
+extern "C" void isr4(void);
+extern "C" void isr5(void);
+extern "C" void isr6(void);
+extern "C" void isr7(void);
+extern "C" void isr8(void);
+extern "C" void isr9(void);
+extern "C" void isr10(void);
+extern "C" void isr11(void);
+extern "C" void isr12(void);
+extern "C" void isr13(void);
+extern "C" void isr14(void);
+extern "C" void isr15(void);
+extern "C" void isr16(void);
+extern "C" void isr17(void);
+extern "C" void isr18(void);
+extern "C" void isr19(void);
+extern "C" void isr20(void);
+extern "C" void isr21(void);
+extern "C" void isr22(void);
+extern "C" void isr23(void);
+extern "C" void isr24(void);
+extern "C" void isr25(void);
+extern "C" void isr26(void);
+extern "C" void isr27(void);
+extern "C" void isr28(void);
+extern "C" void isr29(void);
+extern "C" void isr30(void);
+extern "C" void isr31(void);
+
+class ISRS
+{
+public:
+    static void install(void);
+};
+
+#endif
diff --git a/src/pOS/include/kernel/interrupts/pic.h b/src/pOS/include/kernel/interrupts/pic.h
new file mode 100644
index 0000000..6284c00
--- /dev/null
+++ b/src/pOS/include/kernel/interrupts/pic.h
@@ -0,0 +1,24 @@
+#ifndef _PIC_H_
+#define _sPIC_H_
+
+#include <stdint.h>
+#include <kernel/system.h>
+
+#define PIC1            0x20
+#define PIC2            0xA0
+#define PIC1_COMMAND    PIC1
+#define PIC1_DATA       (PIC1+1)
+#define PIC2_COMMAND    PIC2
+#define PIC2_DATA       (PIC2+1)
+#define PIC_EOI         0x20
+
+#define ICW1            0x11
+#define ICW4            0x01
+
+class PIC
+{
+public:
+    static int init(void);
+    static int irq_ack(uint8_t irq);
+};
+#endif
diff --git a/src/pOS/include/kernel/registers.h b/src/pOS/include/kernel/registers.h
new file mode 100644
index 0000000..6ba96e1
--- /dev/null
+++ b/src/pOS/include/kernel/registers.h
@@ -0,0 +1,48 @@
+#ifndef _REG_H_
+#define _REG_H_
+
+#include <stdio.h>
+
+struct regs
+{
+    unsigned int gs, fs, es, ds;
+    unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax;
+    unsigned int int_no, err_code;
+    unsigned int eip, cs, eflags, useresp, ss;
+};
+
+
+
+class REG
+{
+public:
+    static void print_regs(regs * r)
+    {
+        Debug::set_serial_debug(true);
+
+        printf("gs: %i\n", r->gs);
+        printf("fs: %i\n", r->fs);
+        printf("es: %i\n", r->es);
+        printf("ds: %i\n\n", r->ds);
+
+        printf("edi: %i\n", r->edi);
+        printf("esi: %i\n", r->esi);
+        printf("ebp: %i\n", r->ebp);
+        printf("esp: %i\n", r->esp);
+        printf("ebx: %i\n", r->ebx);
+        printf("edx: %i\n", r->edx);
+        printf("ecx: %i\n", r->ecx);
+        printf("eax: %i\n\n", r->eax);
+
+        printf("int_no: %i\n", r->int_no);
+        printf("err_code: %i\n\n", r->err_code);
+
+        printf("eip: %i\n", r->eip);
+        printf("cs: %i\n", r->cs);
+        printf("eflags: %i\n", r->eflags);
+        printf("useresp: %i\n", r->useresp);
+        printf("ss: %i\n", r->ss);
+    }
+};
+
+#endif
diff --git a/src/pOS/kernel/kernel.cpp b/src/pOS/kernel/kernel.cpp
index fd0340c..c63bab0 100644
--- a/src/pOS/kernel/kernel.cpp
+++ b/src/pOS/kernel/kernel.cpp
@@ -1,19 +1,22 @@
-#include <stdio.h>
 #include <kernel/pOS.h>
-#include <kernel/time.h>
-#include <kernel/debug.h>
-#include <kernel/drivers.h>
-#include <math.h>
-#include <assert.h>
 
 extern "C" int kmain(void)
 {
     #ifdef DEBUG
     Debug::set_serial_debug(true);
     #endif
+
+    GDT::init();
+    IDT::init();
+    ISRS::install();
+
     TTY::tty_initialize();
     Drivers::load_drivers();
 
+    /*asm volatile("mov %eax, 0x100  \t\n"
+         "mov %ecx, 0x000            \t\n"
+         "div %ecx                       ");*/
+
     printf("Welcome to pOS v%s\n", VERSION);
     dbgprintf("Hi host %d!\n", pow(3, 2));
 
@@ -23,5 +26,5 @@ extern "C" int kmain(void)
 
     ASSERT(false);
 
-	return 1;
+    return 1;
 }