From 13ab5aef4da9ded93d7c93442911554e86ea9714 Mon Sep 17 00:00:00 2001 From: Aqua-sama Date: Fri, 5 Mar 2021 16:09:03 +0200 Subject: add broken Scheduler --- drivers/keyboard.cc | 4 +++- drivers/keyboard.h | 2 +- libk/types.h | 4 ++++ src/idt.cc | 11 ++++++----- src/idt.h | 3 ++- src/idt/interrupthandler.cc | 3 ++- src/idt/stubs.S | 20 +++++++++++++++++--- src/kernel.cc | 2 ++ src/makefile | 3 ++- src/scheduler.cc | 46 +++++++++++++++++++++++++++++++++++++++++++++ src/scheduler.h | 17 +++++++++++++++++ 11 files changed, 102 insertions(+), 13 deletions(-) create mode 100644 src/scheduler.cc create mode 100644 src/scheduler.h 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 #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(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(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 +#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 + +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(stack + 4096 - sizeof(cpu_state_t)); + cpu_state->eip = reinterpret_cast(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(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 +#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; +}; -- cgit v1.2.1