diff options
author | Your Name <you@example.com> | 2020-06-23 19:31:26 +0200 |
---|---|---|
committer | Your Name <you@example.com> | 2020-06-23 19:31:26 +0200 |
commit | 86add5103e8b80a5ba614c1d4986b67ffb073953 (patch) | |
tree | 338e0af49c5093cef88485509fc4fce8010da79e | |
parent | Format: added kernel includes to pOS.h instead of kernel.cpp (diff) | |
download | pOS-86add5103e8b80a5ba614c1d4986b67ffb073953.tar.gz pOS-86add5103e8b80a5ba614c1d4986b67ffb073953.tar.bz2 pOS-86add5103e8b80a5ba614c1d4986b67ffb073953.zip |
Base: Added support for interrupts and exception handlers
-rw-r--r-- | src/bootloader/boot.s | 5 | ||||
-rw-r--r-- | src/bootloader/utils/gdt.s | 33 | ||||
-rw-r--r-- | src/bootloader/utils/irq.s | 157 | ||||
-rw-r--r-- | src/bootloader/utils/isrs.s | 282 | ||||
-rw-r--r-- | src/pOS/arch/x86/kernel/interrupts/asm/gdt.s | 15 | ||||
-rw-r--r-- | src/pOS/arch/x86/kernel/interrupts/asm/idt.s | 5 | ||||
-rw-r--r-- | src/pOS/arch/x86/kernel/interrupts/gdt.cpp | 56 | ||||
-rw-r--r-- | src/pOS/arch/x86/kernel/interrupts/idt.cpp | 35 | ||||
-rw-r--r-- | src/pOS/arch/x86/kernel/interrupts/irq.cpp | 86 | ||||
-rw-r--r-- | src/pOS/arch/x86/kernel/interrupts/isrs.cpp | 95 | ||||
-rw-r--r-- | src/pOS/arch/x86/kernel/interrupts/pic.cpp | 33 | ||||
-rw-r--r-- | src/pOS/include/kernel/interrupts/gdt.h | 37 | ||||
-rw-r--r-- | src/pOS/include/kernel/interrupts/idt.h | 37 | ||||
-rw-r--r-- | src/pOS/include/kernel/interrupts/irq.h | 36 | ||||
-rw-r--r-- | src/pOS/include/kernel/interrupts/isrs.h | 49 | ||||
-rw-r--r-- | src/pOS/include/kernel/interrupts/pic.h | 24 | ||||
-rw-r--r-- | src/pOS/include/kernel/registers.h | 48 | ||||
-rw-r--r-- | src/pOS/kernel/kernel.cpp | 17 |
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; } |