aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAqua-sama <aqua@iserlohn-fortress.net>2021-02-28 14:53:13 +0200
committerAqua-sama <aqua@iserlohn-fortress.net>2021-02-28 14:53:13 +0200
commit09cf6b4ca8799990b9c01db04c5f4ffbef798773 (patch)
treed660da543cccbfad03d637b34815017d0e477e47
parentEnable interrupts (diff)
downloadkernel.cpp-09cf6b4ca8799990b9c01db04c5f4ffbef798773.tar.xz
Fix interrupts causing exception 0xd
-rw-r--r--.gitignore2
-rw-r--r--libk/stdlib/abort.cc11
-rw-r--r--src/cpu/exceptions.s51
-rw-r--r--src/cpu/interrupts.s50
-rw-r--r--src/gdt.cc9
-rw-r--r--src/gdt.h2
-rw-r--r--src/idt.cc89
-rw-r--r--src/idt.h46
-rw-r--r--src/irq/kirq.cc21
-rw-r--r--src/kernel.cc9
-rw-r--r--src/makefile15
11 files changed, 198 insertions, 107 deletions
diff --git a/.gitignore b/.gitignore
index 5ef19a0..5873c6f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,8 @@ build/
isodir/
drivers/hardware.h
+src/cpu/irq.h
+
.config.old
*.tar*
diff --git a/libk/stdlib/abort.cc b/libk/stdlib/abort.cc
index 56ca7ee..41bf991 100644
--- a/libk/stdlib/abort.cc
+++ b/libk/stdlib/abort.cc
@@ -8,8 +8,13 @@ void abort() {
*/
asm volatile("cli");
- while (true) {
- asm volatile("hlt");
- }
+ while (true) asm volatile("hlt");
__builtin_unreachable();
}
+
+extern "C" void print_exception(uint8_t irq) {
+ printk("exception ", uhex{irq}, '\n');
+ asm volatile("cli");
+ while (true) asm volatile("hlt");
+ __builtin_unreachable();
+};
diff --git a/src/cpu/exceptions.s b/src/cpu/exceptions.s
new file mode 100644
index 0000000..9736be1
--- /dev/null
+++ b/src/cpu/exceptions.s
@@ -0,0 +1,51 @@
+.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
new file mode 100644
index 0000000..17c39e9
--- /dev/null
+++ b/src/cpu/interrupts.s
@@ -0,0 +1,50 @@
+.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/gdt.cc b/src/gdt.cc
index 289462b..9c86888 100644
--- a/src/gdt.cc
+++ b/src/gdt.cc
@@ -1,12 +1,21 @@
#include "gdt.h"
+#include <stdlib.h>
using seg = GDT::SegmentDescriptor;
GDT::GDT()
: segments{seg::make<0>(0, {.present = false}), // null segment
+ seg::make<0>(0, {.present = false}), // unused segment ???
seg::make<0xffffffff>(0, {.r_w = true, .exe = true, .segment = true}), // code segment
seg::make<0xffffffff>(0, {.r_w = true, .segment = true})} // data segment
{
Pointer gdtr{.limit = sizeof(segments) - 1, .base = reinterpret_cast<uint32_t>(segments)};
asm volatile("lgdt %0" : : "p"(gdtr));
+
+ printk("GDT installed at ", uhex{gdtr.base}, '\n');
+}
+
+uint16_t GDT::codeDescriptor() const {
+ return static_cast<uint16_t>(reinterpret_cast<const uint32_t>(&segments[2]) -
+ reinterpret_cast<const uint32_t>(&segments));
}
diff --git a/src/gdt.h b/src/gdt.h
index a86a14f..bb7181b 100644
--- a/src/gdt.h
+++ b/src/gdt.h
@@ -30,6 +30,8 @@ public:
GDT();
~GDT() = default;
+ uint16_t codeDescriptor() const;
+
struct Pointer {
uint16_t limit;
uint32_t base;
diff --git a/src/idt.cc b/src/idt.cc
index e4c21b7..fefe53e 100644
--- a/src/idt.cc
+++ b/src/idt.cc
@@ -1,11 +1,10 @@
#include "idt.h"
#include <stdlib.h>
+#include "cpu/irq.h"
#include "ports.h"
static_assert(sizeof(IDT::Pointer) == 6);
-// size of IDT::Entry in protected mode is 64 bits
-// and in long mode is 128 bits
-static_assert(sizeof(IDT::Entry) == 8);
+static_assert(sizeof(IDT::Entry) == 8); // size of IDT::Entry in protected mode is 64 bits
/* reinitialize the PIC controllers, giving them specified vector offsets
rather than 8h and 70h, as configured by default */
@@ -22,60 +21,74 @@ static_assert(sizeof(IDT::Entry) == 8);
#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
#define ICW4_SFNM 0x10 /* Special fully nested (not) */
-template <uint8_t irq>
-__attribute__((interrupt)) void t_irq(interrupt_frame*) {
- static_assert(irq <= 15);
-
- com1_port_t com1;
- com1.write("0123456789abcdef"[irq]);
- com1.write('\n');
- com1.write('\r');
-
+extern "C" uint32_t handle_interrupt(uint8_t irq, uint32_t esp) {
+ printk("interrupt ", uhex{irq}, '\n');
pic1_t pic1;
pic1.write(0x20);
- if constexpr (irq > 7) {
+ if (irq > 7) {
pic2_t pic2;
pic2.write(0x20);
}
+ return esp;
};
-IDT::IDT() {
+IDT::IDT(const uint16_t selector) {
+ table[0x00] = Entry(&exception0x00, selector, Intr);
+ table[0x01] = Entry(&exception0x01, selector, Intr);
+ table[0x02] = Entry(&exception0x02, selector, Intr);
+ table[0x03] = Entry(&exception0x03, selector, Intr);
+ table[0x04] = Entry(&exception0x04, selector, Intr);
+ table[0x05] = Entry(&exception0x05, selector, Intr);
+ table[0x06] = Entry(&exception0x06, selector, Intr);
+ table[0x07] = Entry(&exception0x07, selector, Intr);
+ table[0x08] = Entry(&exception0x08, selector, Intr);
+ table[0x09] = Entry(&exception0x09, selector, Intr);
+ table[0x0a] = Entry(&exception0x0a, selector, Intr);
+ table[0x0b] = Entry(&exception0x0b, selector, Intr);
+ table[0x0c] = Entry(&exception0x0c, selector, Intr);
+ table[0x0d] = Entry(&exception0x0d, selector, Intr);
+ table[0x0e] = Entry(&exception0x0e, selector, Intr);
+ table[0x0f] = Entry(&exception0x0f, selector, Intr);
+ table[0x10] = Entry(&exception0x10, selector, Intr);
+ table[0x11] = Entry(&exception0x11, selector, Intr);
+ table[0x12] = Entry(&exception0x12, selector, Intr);
+ table[0x13] = Entry(&exception0x13, selector, Intr);
+
+ table[0x20] = Entry(&interrupt0x00, selector, Intr);
+ table[0x21] = Entry(&interrupt0x01, selector, Intr);
+ table[0x22] = Entry(&interrupt0x02, selector, Intr);
+ table[0x23] = Entry(&interrupt0x03, selector, Intr);
+ table[0x24] = Entry(&interrupt0x04, selector, Intr);
+ table[0x25] = Entry(&interrupt0x05, selector, Intr);
+ table[0x26] = Entry(&interrupt0x06, selector, Intr);
+ table[0x27] = Entry(&interrupt0x07, selector, Intr);
+
+ table[0x28] = Entry(&interrupt0x08, selector, Intr);
+ table[0x29] = Entry(&interrupt0x09, selector, Intr);
+ table[0x2a] = Entry(&interrupt0x0a, selector, Intr);
+ table[0x2b] = Entry(&interrupt0x0b, selector, Intr);
+ table[0x2c] = Entry(&interrupt0x0c, selector, Intr);
+ table[0x2d] = Entry(&interrupt0x0d, selector, Intr);
+ table[0x2e] = Entry(&interrupt0x0e, selector, Intr);
+ table[0x2f] = Entry(&interrupt0x0f, selector, Intr);
+
pic1_t pic1;
pic2_t pic2;
- // const auto mask1 = pic1.read(0x1);
- // const auto mask2 = pic2.read(0x1);
-
pic1.write(ICW1_INIT | ICW1_ICW4);
pic2.write(ICW1_INIT | ICW1_ICW4);
pic1.write(0x20, 0x1); // offset 0x20
pic2.write(0x28, 0x1); // offset 0x28
- pic1.write(4, 0x1); // tell master pic there is a slave pic
- pic2.write(2, 0x1); // tell slave pic its cascade identity
+ pic1.write(0x04, 0x1); // tell master pic there is a slave pic
+ pic2.write(0x02, 0x1); // tell slave pic its cascade identity
+
pic1.write(ICW4_8086, 0x1);
pic2.write(ICW4_8086, 0x1);
- // pic1.write(mask1);
- // pic2.write(mask2);
- pic1.write(0xfd, 0x1); // only enable irq1
+ // pic masks
+ pic1.write(0xfc, 0x1); // only enable irq1
pic2.write(0xff, 0x1);
- table[0x20] = Entry(reinterpret_cast<unsigned long>(t_irq<0x0>), 0x08, InterruptGate);
- table[0x21] = Entry(reinterpret_cast<unsigned long>(t_irq<0x1>), 0x08, InterruptGate);
- table[0x22] = Entry(reinterpret_cast<unsigned long>(t_irq<0x2>), 0x08, InterruptGate);
- table[0x23] = Entry(reinterpret_cast<unsigned long>(t_irq<0x3>), 0x08, InterruptGate);
- table[0x24] = Entry(reinterpret_cast<unsigned long>(t_irq<0x4>), 0x08, InterruptGate);
- table[0x25] = Entry(reinterpret_cast<unsigned long>(t_irq<0x5>), 0x08, InterruptGate);
- table[0x26] = Entry(reinterpret_cast<unsigned long>(t_irq<0x6>), 0x08, InterruptGate);
- table[0x27] = Entry(reinterpret_cast<unsigned long>(t_irq<0x7>), 0x08, InterruptGate);
- table[0x28] = Entry(reinterpret_cast<unsigned long>(t_irq<0x8>), 0x08, InterruptGate);
- table[0x29] = Entry(reinterpret_cast<unsigned long>(t_irq<0x9>), 0x08, InterruptGate);
- table[0x2a] = Entry(reinterpret_cast<unsigned long>(t_irq<0xa>), 0x08, InterruptGate);
- table[0x2b] = Entry(reinterpret_cast<unsigned long>(t_irq<0xb>), 0x08, InterruptGate);
- table[0x2c] = Entry(reinterpret_cast<unsigned long>(t_irq<0xc>), 0x08, InterruptGate);
- table[0x2d] = Entry(reinterpret_cast<unsigned long>(t_irq<0xd>), 0x08, InterruptGate);
- table[0x2e] = Entry(reinterpret_cast<unsigned long>(t_irq<0xe>), 0x08, InterruptGate);
-
Pointer ptr{.limit = sizeof(table), .base = reinterpret_cast<uint32_t>(table)};
asm volatile("lidt %0" : : "m"(ptr));
asm volatile("sti");
diff --git a/src/idt.h b/src/idt.h
index 628eb23..bc71f05 100644
--- a/src/idt.h
+++ b/src/idt.h
@@ -11,54 +11,32 @@ public:
enum InterruptType : uint8_t {
Null = 0,
- InterruptGate = 0b110, // hardware interrupts are disabled while the handler runs
- TrapGate = 0b111, // hardware interrupts remain active while the handler runs
- TaskGate = 0b101, // selector points to TSS rather than a code segment
+ Task = 0b10000101, // 32-bit task gate selector points to TSS rather than a code segment
+ Intr = 0b10001110, // 32-bit interrupt hardware interrupts are disabled while the handler runs
+ Trap = 0b10001111, // 32-bit trap gate hardware interrupts remain active while the handler runs
};
class Entry {
public:
- constexpr Entry(uint32_t offset = 0, uint16_t select = 0, InterruptType t = Null) {
- offset_0_15 = offset & 0xffff;
- offset_16_31 = (offset & 0xffff0000) >> 16;
+ constexpr Entry() = default;
+ Entry(void (*handler)(), uint16_t select, InterruptType t) {
+ offset_0_15 = reinterpret_cast<uint32_t>(handler) & 0xffff;
+ offset_16_31 = (reinterpret_cast<uint32_t>(handler) >> 16) & 0xffff;
selector = select;
type = t;
- if (offset != 0) {
- e = true;
- }
}
private:
- uint16_t offset_0_15; // 0-15 offset in the segment
- uint16_t selector; // 16-31 selector of the code segment
+ uint16_t offset_0_15 = 0; // 0-15 offset in the segment
+ uint16_t selector = 0; // 16-31 selector of the code segment
[[maybe_unused]] uint8_t null = 0; // 32-39 unused in protected mode
- InterruptType type : 3; // 40-42 type
- [[maybe_unused]] bool d : 1 = true; // 43 true: 32-bit, false: 16-bit segment
- [[maybe_unused]] uint8_t u : 1 = 0; // 44 unused
- [[maybe_unused]] uint8_t dpl : 2 = 0; // 45-46 descriptor privilege level
- [[maybe_unused]] bool e : 1 = false; // 47 enable
- uint16_t offset_16_31; // 48-63 offset high
+ InterruptType type = Null; // 40-43 type
+ uint16_t offset_16_31 = 0; // 48-63 offset high
} __attribute__((packed));
- IDT();
+ IDT(const uint16_t selector);
private:
Entry table[256];
};
-struct interrupt_frame {
- uword_t ip;
- uword_t cs;
- uword_t flags;
- uword_t sp;
- uword_t ss;
-};
-
-/* https://wiki.osdev.org/Interrupt_Service_Routines */
-template <uint8_t irq>
-__attribute__((interrupt)) void kirq(interrupt_frame* frame);
-
-template <>
-void kirq<0x0>(interrupt_frame* frame);
-template <>
-void kirq<0x1>(interrupt_frame* frame);
diff --git a/src/irq/kirq.cc b/src/irq/kirq.cc
deleted file mode 100644
index acd57d4..0000000
--- a/src/irq/kirq.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-#include <stdlib.h>
-#include "../idt.h"
-#include "ports.h"
-
-template <>
-void kirq<0x0>(interrupt_frame*) {
- printk("Interrupt 0x0\n");
-
- // send end of interrupt
- pic1_t pic1;
- pic1.write(0x20);
-}
-
-template <>
-void kirq<0x1>(interrupt_frame*) {
- printk("Interrupt 0x0\n");
-
- // send end of interrupt
- pic1_t pic1;
- pic1.write(0x20);
-}
diff --git a/src/kernel.cc b/src/kernel.cc
index 4337edb..6bfb021 100644
--- a/src/kernel.cc
+++ b/src/kernel.cc
@@ -45,15 +45,8 @@ void kernel_main([[maybe_unused]] uint32_t mb_magic, [[maybe_unused]] uint32_t m
// dump_multiboot(mb_magic, mb_addr);
// dump_gdt();
- // printk("GDT::SegmentDescriptor tests\n");
- auto x = GDT::SegmentDescriptor::make<0xffff>(0xdeadbeef, {});
- // printk("x.base(): ", uhex{x.base()}, '\n');
-
- // printk("Setting new GDT\n");
GDT gdt;
- // dump_gdt();
-
- IDT idt;
+ IDT idt{gdt.codeDescriptor()};
while (true) asm volatile("hlt");
}
diff --git a/src/makefile b/src/makefile
index ab08ee2..8b21640 100644
--- a/src/makefile
+++ b/src/makefile
@@ -1,4 +1,5 @@
-AS_OBJ += src/boot.o
+AS_OBJ += src/boot.o \
+ src/cpu/exceptions.o src/cpu/interrupts.o
CXX_OBJ += src/kernel.o \
src/kernel/dump_gdt.o \
@@ -6,5 +7,13 @@ CXX_OBJ += src/kernel.o \
src/memory.o \
src/gdt.o \
src/gdt/segmentdescriptor.o \
- src/idt.o \
- src/irq/kirq.o
+ src/idt.o
+
+src/cpu/irq.h: $(OBJ_DIR)/src/cpu/exceptions.o $(OBJ_DIR)/src/cpu/interrupts.o
+ @echo " GEN $@"
+ @echo '#pragma once' > $@
+ @echo 'extern "C" {' >> $@
+ @for x in $^; do nm $$x -g | sed -nr 's/[0-9a-f]{8} T (.+)/void \1();/p'; done >> $@
+ @echo '}' >> $@
+
+autogen := $(autogen) src/cpu/irq.h