diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/boot.S (renamed from src/boot.s) | 1 | ||||
-rw-r--r-- | src/cpu/exceptions.s | 51 | ||||
-rw-r--r-- | src/cpu/interrupts.s | 50 | ||||
-rw-r--r-- | src/cpu/registers.h | 26 | ||||
-rw-r--r-- | src/idt.cc | 30 | ||||
-rw-r--r-- | src/idt/stubs.S | 82 | ||||
-rw-r--r-- | src/makefile | 4 |
7 files changed, 132 insertions, 112 deletions
@@ -46,6 +46,7 @@ stack_top: .global _start .type _start, @function _start: + mov $stack_bottom, %ebp mov $stack_top, %esp # point the stack pointer to the stack /* diff --git a/src/cpu/exceptions.s b/src/cpu/exceptions.s deleted file mode 100644 index 9736be1..0000000 --- a/src/cpu/exceptions.s +++ /dev/null @@ -1,51 +0,0 @@ -.section .text -.extern print_exception - -.macro exception num -.global exception\num -exception\num: - movb $\num, (exc) - jmp exception_common -.endm - -exception 0x00 -exception 0x01 -exception 0x02 -exception 0x03 -exception 0x04 -exception 0x05 -exception 0x06 -exception 0x07 -exception 0x08 -exception 0x09 -exception 0x0a -exception 0x0b -exception 0x0c -exception 0x0d -exception 0x0e -exception 0x0f -exception 0x10 -exception 0x11 -exception 0x12 -exception 0x13 - -exception_common: - pusha - pushl %ds - pushl %es - pushl %fs - pushl %gs - - push (exc) - call print_exception - - popl %gs - popl %fs - popl %es - popl %ds - popa - iret - -.data - exc: .byte 0 - diff --git a/src/cpu/interrupts.s b/src/cpu/interrupts.s deleted file mode 100644 index 17c39e9..0000000 --- a/src/cpu/interrupts.s +++ /dev/null @@ -1,50 +0,0 @@ -.section .text -.extern handle_interrupt - -.macro interrupt num -.global interrupt\num -interrupt\num: - movb $\num, (irq) - jmp interrupt_common -.endm - -interrupt 0x00 # system timer -interrupt 0x01 # keyboard controller -interrupt 0x02 # slave pic -interrupt 0x03 # serial port 2 and 4 -interrupt 0x04 # serial port 1 and 3 -interrupt 0x05 # parallel port 2 and 3, sound card -interrupt 0x06 # floppy controller -interrupt 0x07 # parallel port 1 - -interrupt 0x08 # real-time clock -interrupt 0x09 # acpi -interrupt 0x0a # -interrupt 0x0b # -interrupt 0x0c # mouse on ps/2 -interrupt 0x0d # fpu -interrupt 0x0e # primary ATA -interrupt 0x0f # secondary ATA - -interrupt_common: - pusha - pushl %ds - pushl %es - pushl %fs - pushl %gs - - pushl %esp - push (irq) - call handle_interrupt - mov %eax, %esp - - popl %gs - popl %fs - popl %es - popl %ds - popa - iret - -.data - irq: .byte 0 - diff --git a/src/cpu/registers.h b/src/cpu/registers.h new file mode 100644 index 0000000..edb6b7b --- /dev/null +++ b/src/cpu/registers.h @@ -0,0 +1,26 @@ +#pragma once + +#include <types.h> + +namespace x86 { + +struct cpu_state { + /* pusha */ + uint32_t edi, esi; // destination index, source index + uint32_t ebp, esp; // base pointer, stack pointer + uint32_t ebx, edx, ecx, eax; // general registers + + uint32_t irq; + uint32_t error; + + /* stack frame, pushed by cpu */ + uint32_t eip; + uint32_t cs; + uint32_t eflags; + uint32_t __esp; + uint32_t ss; +} __attribute__((packed)); + +} // namespace x86 + +typedef x86::cpu_state cpu_state_t; @@ -1,22 +1,24 @@ #include "idt.h" #include <stdlib.h> #include "cpu/irq.h" +#include "cpu/registers.h" #include "ports.h" static_assert(sizeof(IDT::Pointer) == 6); +constexpr uint8_t irq_base = 0x20; static InterruptHandler* handlers[256] = {nullptr}; bool IDT::install(uint8_t irq, InterruptHandler* h) { - if (h != nullptr && handlers[irq] == nullptr) { - handlers[irq] = h; + if (h != nullptr && handlers[irq + irq_base] == nullptr) { + handlers[irq + irq_base] = h; return true; } return false; } bool IDT::uninstall(uint8_t irq, InterruptHandler* h) { - if (handlers[irq] == h) { - handlers[irq] = nullptr; + if (handlers[irq + irq_base] == h) { + handlers[irq + irq_base] = nullptr; return true; } return false; @@ -37,18 +39,28 @@ bool IDT::uninstall(uint8_t irq, InterruptHandler* h) { #define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */ #define ICW4_SFNM 0x10 /* Special fully nested (not) */ -extern "C" uint32_t handle_interrupt(uint8_t irq, uint32_t esp) { - if (handlers[irq] != nullptr) { - handlers[irq]->trigger(); +extern "C" void print_exception(cpu_state_t* r) { + printk("exception ", uhex{r->irq}, " error ", uhex{r->error}, '\n'); + asm volatile("cli"); + while (true) asm volatile("hlt"); + __builtin_unreachable(); +}; + +extern "C" uint32_t handle_interrupt(cpu_state_t* r) { + if (r->irq < irq_base) print_exception(r); + + if (handlers[r->irq] != nullptr) { + handlers[r->irq]->trigger(); } pic1_t pic1; pic1.write(0x20); - if (irq > 7) { + if (r->irq > 7 + irq_base) { pic2_t pic2; pic2.write(0x20); } - return esp; + + return reinterpret_cast<uint32_t>(r); }; IDT::IDT(const uint16_t selector) { diff --git a/src/idt/stubs.S b/src/idt/stubs.S new file mode 100644 index 0000000..97f1797 --- /dev/null +++ b/src/idt/stubs.S @@ -0,0 +1,82 @@ +.set IRQ_BASE, 0x20 + +.section .text +.extern handle_interrupt + +.macro interrupt num +.global interrupt\num +interrupt\num: + push $0 + push $\num + IRQ_BASE + jmp interrupt_common +.endm + +.macro exception num +.global exception\num +exception\num: + push $0 + push $\num + jmp interrupt_common +.endm + +.macro exception_ec num +.global exception\num +exception\num: + push $\num + jmp interrupt_common +.endm + +/* exceptions */ +exception 0x00 +exception 0x01 +exception 0x02 +exception 0x03 +exception 0x04 +exception 0x05 +exception 0x06 +exception 0x07 +exception_ec 0x08 +exception 0x09 +exception_ec 0x0a +exception_ec 0x0b +exception_ec 0x0c +exception_ec 0x0d +exception_ec 0x0e +exception 0x0f +exception 0x10 +exception_ec 0x11 +exception 0x12 +exception 0x13 + +/* interrupts - master pic */ +interrupt 0x00 # system timer +interrupt 0x01 # keyboard controller +interrupt 0x02 # slave pic +interrupt 0x03 # serial port 2 and 4 +interrupt 0x04 # serial port 1 and 3 +interrupt 0x05 # parallel port 2 and 3, sound card +interrupt 0x06 # floppy controller +interrupt 0x07 # parallel port 1 +/* interrupts - slave pic */ +interrupt 0x08 # real-time clock +interrupt 0x09 # acpi +interrupt 0x0a # +interrupt 0x0b # +interrupt 0x0c # mouse on ps/2 +interrupt 0x0d # fpu +interrupt 0x0e # primary ATA +interrupt 0x0f # secondary ATA + +interrupt_common: + pusha + + push %esp + call handle_interrupt + mov %eax, %esp + + popa + /* remove error code and irq from stack */ + add $8, %esp + + iret + diff --git a/src/makefile b/src/makefile index 8db63d6..64853fe 100644 --- a/src/makefile +++ b/src/makefile @@ -1,5 +1,5 @@ AS_OBJ += src/boot.o \ - src/cpu/exceptions.o src/cpu/interrupts.o + src/idt/stubs.o CXX_OBJ += src/kernel.o \ src/kernel/dump_gdt.o \ @@ -10,7 +10,7 @@ CXX_OBJ += src/kernel.o \ src/idt.o \ src/idt/interruptgate.o src/idt/interrupthandler.o -src/cpu/irq.h: $(OBJ_DIR)/src/cpu/exceptions.o $(OBJ_DIR)/src/cpu/interrupts.o +src/cpu/irq.h: $(OBJ_DIR)/src/idt/stubs.o @echo " GEN $@" @echo '#pragma once' > $@ @echo 'extern "C" {' >> $@ |