aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAqua-sama <aqua@iserlohn-fortress.net>2021-02-16 22:22:38 +0200
committerAqua-sama <aqua@iserlohn-fortress.net>2021-02-16 22:22:38 +0200
commita00456084240e11e29fc5eaf9c34227491eaf1dc (patch)
treed1987768f9f99616883e865b09d720a221427160
parentAdd grub build instructions (diff)
downloadkernel.cpp-a00456084240e11e29fc5eaf9c34227491eaf1dc.tar.xz
Add IDT
-rw-r--r--.gitignore2
-rw-r--r--drivers/ports.h4
-rw-r--r--libk/types.h9
-rw-r--r--src/idt.cc51
-rw-r--r--src/idt.h61
-rw-r--r--src/irq/kirq.cc21
-rw-r--r--src/kernel.cc5
-rw-r--r--src/makefile4
8 files changed, 155 insertions, 2 deletions
diff --git a/.gitignore b/.gitignore
index 94e1555..bd048b4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,5 @@ glitch.elf
glitch.iso
build/
isodir/
+
+*.tar*
diff --git a/drivers/ports.h b/drivers/ports.h
index 8671f19..98cac72 100644
--- a/drivers/ports.h
+++ b/drivers/ports.h
@@ -53,3 +53,7 @@ typedef Port<0x3f8, uint8_t> com1_port_t;
typedef Port<0x2f8, uint8_t> com2_port_t;
typedef Port<0x3e8, uint8_t> com3_port_t;
typedef Port<0x2e8, uint8_t> com4_port_t;
+
+/* 8259 PIC */
+typedef Port<0x20, uint8_t> pic1_t;
+typedef Port<0xA0, uint8_t> pic2_t;
diff --git a/libk/types.h b/libk/types.h
index 599f852..08d42b9 100644
--- a/libk/types.h
+++ b/libk/types.h
@@ -13,6 +13,15 @@ typedef short int16_t;
typedef int int32_t;
typedef long long int int64_t;
+/* in x86:
+ * byte: 1 byte, 8 bits
+ * word: 2 bytes, 16 bits
+ * dword: 4 bytes, 32 bits
+ * qword: 8 bytes, 64 bits
+ * */
+typedef uint16_t uword_t;
+typedef int16_t word_t;
+
// Type Traits
template <class T, T v>
diff --git a/src/idt.cc b/src/idt.cc
new file mode 100644
index 0000000..fe4c159
--- /dev/null
+++ b/src/idt.cc
@@ -0,0 +1,51 @@
+#include "idt.h"
+#include <stdlib.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);
+
+/* reinitialize the PIC controllers, giving them specified vector offsets
+ rather than 8h and 70h, as configured by default */
+
+#define ICW1_ICW4 0x01 /* ICW4 (not) needed */
+#define ICW1_SINGLE 0x02 /* Single (cascade) mode */
+#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */
+#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */
+#define ICW1_INIT 0x10 /* Initialization - required! */
+
+#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */
+#define ICW4_AUTO 0x02 /* Auto (normal) EOI */
+#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */
+#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */
+#define ICW4_SFNM 0x10 /* Special fully nested (not) */
+
+IDT::IDT() {
+ 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(ICW4_8086, 0x1);
+ pic2.write(ICW4_8086, 0x1);
+
+ pic1.write(mask1);
+ pic2.write(mask2);
+
+ table[32] = Entry((unsigned long)kirq<0x0>, 0x08, InterruptGate);
+ table[33] = Entry((unsigned long)kirq<0x1>, 0x08, InterruptGate);
+
+ Pointer ptr{.limit = sizeof(table), .base = (uint32_t)table};
+ asm volatile("lidt %0" : : "m"(ptr));
+
+ printk("IDT installed at ", (uint32_t)table, '\n');
+}
diff --git a/src/idt.h b/src/idt.h
new file mode 100644
index 0000000..3aa5a1e
--- /dev/null
+++ b/src/idt.h
@@ -0,0 +1,61 @@
+#pragma once
+
+#include <types.h>
+
+class IDT {
+public:
+ struct Pointer {
+ uint16_t limit;
+ uint32_t base;
+ } __attribute__((packed));
+
+ 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
+ };
+
+ class Entry {
+ public:
+ Entry(uint32_t offset = 0, uint16_t select = 0, InterruptType t = Null) {
+ offset_0_15 = offset & 0xffff;
+ offset_16_31 = (offset & 0xffff0000) >> 16;
+ selector = select;
+ type = t;
+ }
+
+ private:
+ uint16_t offset_0_15; // 0-15 offset in the segment
+ uint16_t selector; // 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
+ uint8_t dpl : 2 = 0; // 45-46 descriptor privilege level
+ [[maybe_unused]] bool e : 1 = true; // 47 enable
+ uint16_t offset_16_31; // 48-63 offset high
+ } __attribute__((packed));
+
+ IDT();
+
+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
new file mode 100644
index 0000000..acd57d4
--- /dev/null
+++ b/src/irq/kirq.cc
@@ -0,0 +1,21 @@
+#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 1139e3b..7aaaa37 100644
--- a/src/kernel.cc
+++ b/src/kernel.cc
@@ -12,6 +12,7 @@
#include <types.h>
#include "cga.h"
#include "gdt.h"
+#include "idt.h"
#include "serial.h"
extern "C" {
@@ -38,6 +39,8 @@ void kernel_main([[maybe_unused]] uint32_t mb_magic, [[maybe_unused]] uint32_t m
GDT gdt;
dump_gdt();
- abort();
+ IDT idt;
+
+ // abort();
}
} // extern "C"
diff --git a/src/makefile b/src/makefile
index 8214d03..ab08ee2 100644
--- a/src/makefile
+++ b/src/makefile
@@ -5,4 +5,6 @@ CXX_OBJ += src/kernel.o \
src/kernel/dump_multiboot.o \
src/memory.o \
src/gdt.o \
- src/gdt/segmentdescriptor.o
+ src/gdt/segmentdescriptor.o \
+ src/idt.o \
+ src/irq/kirq.o