aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAqua-sama <aqua@iserlohn-fortress.net>2021-03-05 16:09:03 +0200
committerAqua-sama <aqua@iserlohn-fortress.net>2021-03-05 16:09:03 +0200
commit13ab5aef4da9ded93d7c93442911554e86ea9714 (patch)
treee9efd37e3c65f3e0be9293f64f0f03e0ad2f4336
parentAdd makefile notes (diff)
downloadkernel.cpp-13ab5aef4da9ded93d7c93442911554e86ea9714.tar.xz
add broken Scheduler
-rw-r--r--drivers/keyboard.cc4
-rw-r--r--drivers/keyboard.h2
-rw-r--r--libk/types.h4
-rw-r--r--src/idt.cc11
-rw-r--r--src/idt.h3
-rw-r--r--src/idt/interrupthandler.cc3
-rw-r--r--src/idt/stubs.S20
-rw-r--r--src/kernel.cc2
-rw-r--r--src/makefile3
-rw-r--r--src/scheduler.cc46
-rw-r--r--src/scheduler.h17
11 files changed, 102 insertions, 13 deletions
diff --git a/drivers/keyboard.cc b/drivers/keyboard.cc
index 09fd4e9..2fae83c 100644
--- a/drivers/keyboard.cc
+++ b/drivers/keyboard.cc
@@ -25,7 +25,7 @@ Keyboard::Keyboard() : InterruptHandler(0x01) {
dataport.write(dat_enable_scanning);
}
-void Keyboard::trigger() {
+cpu_state_t* Keyboard::trigger(cpu_state_t* cpu) {
const auto key = dataport.read();
if (key < 0x80) {
@@ -157,4 +157,6 @@ void Keyboard::trigger() {
break;
}
}
+
+ return cpu;
}
diff --git a/drivers/keyboard.h b/drivers/keyboard.h
index cac0cb0..b7b67c1 100644
--- a/drivers/keyboard.h
+++ b/drivers/keyboard.h
@@ -8,7 +8,7 @@ class Keyboard : public InterruptHandler {
public:
Keyboard();
- void trigger() override;
+ cpu_state_t* trigger(cpu_state_t*) override;
private:
/* 8042 PS/2 Controller Ports */
diff --git a/libk/types.h b/libk/types.h
index 08d42b9..4c50a35 100644
--- a/libk/types.h
+++ b/libk/types.h
@@ -4,7 +4,11 @@ typedef unsigned short size_t;
typedef int ssize_t;
typedef unsigned char uint8_t;
+
typedef unsigned short uint16_t;
+constexpr uint16_t uint16_t_min = 0;
+constexpr uint16_t uint16_t_max = 0xffff;
+
typedef unsigned int uint32_t;
typedef unsigned long long int uint64_t;
diff --git a/src/idt.cc b/src/idt.cc
index 363afcd..5be738a 100644
--- a/src/idt.cc
+++ b/src/idt.cc
@@ -1,7 +1,6 @@
#include "idt.h"
#include <stdlib.h>
#include "cpu/irq.h"
-#include "cpu/registers.h"
#include "ports.h"
static_assert(sizeof(IDT::Pointer) == 6);
@@ -39,23 +38,25 @@ 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" void print_exception(cpu_state_t* r) {
+extern "C" uint32_t handle_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();
+
+ return reinterpret_cast<uint32_t>(r);
};
extern "C" uint32_t handle_interrupt(cpu_state_t* r) {
- if (r->irq < irq_base) print_exception(r);
+ if (r->irq < irq_base) return reinterpret_cast<uint32_t>(r);
if (handlers[r->irq] != nullptr) {
- handlers[r->irq]->trigger();
+ r = handlers[r->irq]->trigger(r);
}
pic1_t pic1;
pic1.write(0x20);
- if (r->irq > 7 + irq_base) {
+ if (r->irq > irq_base + 7) {
pic2_t pic2;
pic2.write(0x20);
}
diff --git a/src/idt.h b/src/idt.h
index 3a9848f..ce5209c 100644
--- a/src/idt.h
+++ b/src/idt.h
@@ -1,6 +1,7 @@
#pragma once
#include <types.h>
+#include "cpu/registers.h"
class InterruptHandler {
private:
@@ -11,7 +12,7 @@ protected:
~InterruptHandler();
public:
- virtual void trigger();
+ virtual cpu_state_t* trigger(cpu_state_t*);
};
class IDT {
diff --git a/src/idt/interrupthandler.cc b/src/idt/interrupthandler.cc
index 7af830b..7524f19 100644
--- a/src/idt/interrupthandler.cc
+++ b/src/idt/interrupthandler.cc
@@ -9,6 +9,7 @@ InterruptHandler::~InterruptHandler() {
IDT::uninstall(m_irq, this);
}
-void InterruptHandler::trigger() {
+cpu_state_t* InterruptHandler::trigger(cpu_state_t* cpu) {
printk("Unhandled interrupt ", uhex{m_irq}, '\n');
+ return cpu;
}
diff --git a/src/idt/stubs.S b/src/idt/stubs.S
index 97f1797..4f1440d 100644
--- a/src/idt/stubs.S
+++ b/src/idt/stubs.S
@@ -2,6 +2,7 @@
.section .text
.extern handle_interrupt
+.extern handle_exception
.macro interrupt num
.global interrupt\num
@@ -16,14 +17,14 @@ interrupt\num:
exception\num:
push $0
push $\num
- jmp interrupt_common
+ jmp exception_common
.endm
.macro exception_ec num
.global exception\num
exception\num:
push $\num
- jmp interrupt_common
+ jmp exception_common
.endm
/* exceptions */
@@ -67,12 +68,25 @@ interrupt 0x0d # fpu
interrupt 0x0e # primary ATA
interrupt 0x0f # secondary ATA
+exception_common:
+ pusha
+
+ push %esp
+ call handle_exception
+ mov %eax, %esp
+
+ popa
+ /* remove error code and irq from stack */
+ add $8, %esp
+
+ iret
+
interrupt_common:
pusha
push %esp
call handle_interrupt
- mov %eax, %esp
+ add $4, %esp
popa
/* remove error code and irq from stack */
diff --git a/src/kernel.cc b/src/kernel.cc
index ff8e6bd..85d4124 100644
--- a/src/kernel.cc
+++ b/src/kernel.cc
@@ -13,6 +13,7 @@
#include "cga.h"
#include "gdt.h"
#include "idt.h"
+#include "scheduler.h"
#include "serial.h"
#include "keyboard.h"
@@ -50,6 +51,7 @@ void kernel_main([[maybe_unused]] uint32_t mb_magic, [[maybe_unused]] uint32_t m
GDT gdt;
IDT idt{gdt.codeDescriptor()};
+ Scheduler s{gdt.codeDescriptor()};
Keyboard kb;
idt.enable();
diff --git a/src/makefile b/src/makefile
index 64853fe..d4b2ac8 100644
--- a/src/makefile
+++ b/src/makefile
@@ -8,7 +8,8 @@ CXX_OBJ += src/kernel.o \
src/gdt.o \
src/gdt/segmentdescriptor.o \
src/idt.o \
- src/idt/interruptgate.o src/idt/interrupthandler.o
+ src/idt/interruptgate.o src/idt/interrupthandler.o \
+ src/scheduler.o
src/cpu/irq.h: $(OBJ_DIR)/src/idt/stubs.o
@echo " GEN $@"
diff --git a/src/scheduler.cc b/src/scheduler.cc
new file mode 100644
index 0000000..1557e28
--- /dev/null
+++ b/src/scheduler.cc
@@ -0,0 +1,46 @@
+#include "scheduler.h"
+#include <stdlib.h>
+
+void task_a(void) {
+ while (true) printk("A");
+}
+
+void task_b(void) {
+ while (true) printk("B");
+}
+
+static uint8_t stack_a[4096] = {0};
+static uint8_t stack_b[4096] = {0};
+constexpr uint16_t max_tasks = 2;
+static cpu_state_t* tasks[max_tasks];
+
+Scheduler::Scheduler(uint16_t cs) : InterruptHandler(0x00) {
+ add_task(stack_a, cs, &task_a);
+ add_task(stack_b, cs, task_b);
+}
+
+bool Scheduler::add_task(uint8_t* stack, uint16_t cs, void (*entry)()) {
+ if (last_task_id == uint16_t_max) return false;
+
+ uint16_t id = last_task_id++;
+ ++num_tasks;
+
+ cpu_state_t* cpu_state = reinterpret_cast<cpu_state_t*>(stack + 4096 - sizeof(cpu_state_t));
+ cpu_state->eip = reinterpret_cast<uint32_t>(entry);
+ cpu_state->cs = cs;
+ cpu_state->eflags = 0x202;
+
+ tasks[id] = cpu_state;
+ printk("adding task: cs ", uhex{cpu_state->cs}, " stack ", uhex{reinterpret_cast<uint32_t>(tasks[id])}, " entry ",
+ uhex{cpu_state->eip}, '\n');
+ return true;
+}
+
+cpu_state_t* Scheduler::trigger(cpu_state_t* cpu) {
+ tasks[current_task] = cpu;
+
+ if (++current_task >= num_tasks) current_task %= num_tasks;
+
+ // printk("swapped to task ", current_task, '\n');
+ return tasks[current_task];
+}
diff --git a/src/scheduler.h b/src/scheduler.h
new file mode 100644
index 0000000..9e5e9f2
--- /dev/null
+++ b/src/scheduler.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include <types.h>
+#include "idt.h"
+
+class Scheduler : public InterruptHandler {
+public:
+ Scheduler(uint16_t cs);
+
+ bool add_task(uint8_t* stack, uint16_t cs, void (*entry)());
+ [[nodiscard]] cpu_state_t* trigger(cpu_state_t*) override;
+
+private:
+ uint16_t current_task = 0;
+ uint16_t last_task_id = 0;
+ uint16_t num_tasks = 0;
+};