diff --git a/Makefile b/Makefile index 857a7e7..50bd6f2 100644 --- a/Makefile +++ b/Makefile @@ -96,7 +96,8 @@ obj/cpp-test.o: src/cpp-test.cpp include/console.h include/ker/string.hpp \ # src/vm.cpp obj/vm.o: src/vm.cpp include/kstdlib.h include/varargs.h include/config.h \ - include/malloc.h include/timer.h include/dynamic.h include/console.h + include/malloc.h include/timer.h include/dynamic.h include/console.h \ + include/interrupts.h include/cpustate.h $(CXX) $(FLAGS) $(CXXFLAGS) -o $@ -c src/vm.cpp # asm/dynamic.S diff --git a/include/ker/vector.hpp b/include/ker/vector.hpp index 5a14fac..fc2b675 100644 --- a/include/ker/vector.hpp +++ b/include/ker/vector.hpp @@ -2,6 +2,7 @@ #include #include +#include #if defined(CIRCUIT_OS) #include "kstdlib.h" @@ -56,6 +57,15 @@ namespace ker other.mReserved = 0; } + Vector(const std::initializer_list &init) : + Vector() + { + this->reserve(init.size()); + for(auto & value : init) { + this->append(value); + } + } + Vector & operator = (const Vector &other) { this->resize(other.mLength); diff --git a/scripts/main.spark b/scripts/main.spark index 75d6c59..882e203 100644 --- a/scripts/main.spark +++ b/scripts/main.spark @@ -26,4 +26,16 @@ _loop: jmp _loop _end: +; Our OS should not end. + jmp _end + ret + +irq: + pusht "Hello IRQ: " + load -1 + pusht ", " + load -2 + pusht "\n" + calln print 5 + ret diff --git a/src/interrupts.c b/src/interrupts.c index af77753..d60ee3f 100644 --- a/src/interrupts.c +++ b/src/interrupts.c @@ -80,11 +80,12 @@ void intr_routine(CpuState *state) if(state->intr < interruptNameCount) name = interruptNames[state->intr]; InterruptHandler handler = handlers[state->intr]; + if(handler != nullptr) { + handler(state); + } if(state->intr < 0x20) { - if(handler != nullptr) { - handler(state); - } else { + if(handler == nullptr) { kprintf("\n\x12\x04 Exception [%d] %s!\x12\0x07 \n", state->intr, name); kprintf( "EIP: %x" @@ -98,9 +99,7 @@ void intr_routine(CpuState *state) } if (state->intr >= 0x20 && state->intr <= 0x2f) { - if(handler != nullptr) { - handler(state); - } else { + if(handler == nullptr) { kprintf("[Unhandled IRQ: %d]", state->intr); } @@ -114,9 +113,7 @@ void intr_routine(CpuState *state) } else { - if(handler != nullptr) { - handler(state); - } else { + if(handler == nullptr) { kprintf("\n\x12\x04Interrupt [%d] %s occurred!\x12\0x7\n", state->intr, name); while(1) { diff --git a/src/vm.cpp b/src/vm.cpp index b9cb137..eadcdb7 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -7,6 +7,8 @@ #include #include +#include + extern "C" { extern const char mainscript_start; extern const char mainscript_end; @@ -56,59 +58,90 @@ struct dtortest { ~dtortest() { free(mem); } }; -extern "C" void vm_start() -{ -/* +struct { + const char *ptr; + uint32_t size; +} mainAssembly { + &mainscript_start, + (uint32_t)&mainscript_size +}; + +struct IrqList { + static const size_t length = 64; + volatile uint32_t read; + volatile uint32_t write; + CpuState items[IrqList::length]; +} irqFiFo { + 0, 0, {} +}; + +extern "C" void vm_handle_interrupt(CpuState *state) +{ + irqFiFo.items[irqFiFo.write] = *state; + irqFiFo.write += 1; + if(irqFiFo.write >= irqFiFo.length) { + // TODO: Don't die + die("irqList overflow."); + } } -void code() +extern "C" void vm_start() { -//*/ + intr_set_handler(0x20, vm_handle_interrupt); + intr_set_handler(0x21, vm_handle_interrupt); - struct { - const char *ptr; - uint32_t size; - } mainAssembly { - &mainscript_start, - (uint32_t)&mainscript_size - }; + VirtualMachine machine; + machine.import("print") = printArguments; - VirtualMachine vm; - vm.import("print") = printArguments; - - Assembly *assembly = vm.load(mainAssembly.ptr, mainAssembly.size); + Assembly *assembly = machine.load(mainAssembly.ptr, mainAssembly.size); if(assembly == nullptr) { kprintf("failed to load assembly :(\n"); return; } - /* - kprintf("Assembly:\n"); - kprintf(" Name: %s\n", assembly->name().str()); - kprintf(" Author: %s\n", assembly->author().str()); - kprintf(" Description: %s\n", assembly->description().str()); - //*/ - /* - kprintf("Type list:\n"); - for(const auto &type : vm.types()) { - kprintf("%s: %x\n", type.first.str(), vm.type(type.first)); - } - //*/ - - Process *process = vm.createProcess(assembly); - if(process == nullptr) { + Process *irqService = machine.createProcess(assembly, true); + if(irqService == nullptr) { kprintf("Failed to create process.\n"); return; } + uint32_t irqRoutine = irqService->assembly()->exports()["irq"]; - while(vm.step()) + while(machine.step()) { - // kprintf("."); + // check for IRQ requests + do + { + // atomic checking for existing IRQ item + irq_disable(); + bool hasItem = (irqFiFo.read < irqFiFo.write); + irq_enable(); + + if(hasItem == false) { + break; // we don't have anything to read + } + + CpuState *cpu = &irqFiFo.items[irqFiFo.read]; + + auto *thread = irqService->createThread(irqRoutine); + thread->start({ VMValue::Int32(cpu->intr), VMValue::Int32(cpu->eip) }); + + irqFiFo.read += 1; + + irq_disable(); + // When fifo is emptied, reset list pointers + if(irqFiFo.read == irqFiFo.write) { + irqFiFo.read = 0; + irqFiFo.write = 0; + } + irq_enable(); + } while(true); } - process->release(); + irqService->release(); + irqService = nullptr; + assembly->release(); kprintf("\n"); diff --git a/trainOS.pro b/trainOS.pro index 3c6db5a..6c5cebc 100644 --- a/trainOS.pro +++ b/trainOS.pro @@ -54,10 +54,12 @@ DISTFILES += \ README.md \ scripts/main.spark +INCLUDEPATH += include +DEPENDPATH += include + INCLUDEPATH += $$quote("/home/felix/projects/Electronics/Electronics/Conductance") DEPENDPATH += $$quote("/home/felix/projects/Electronics/Electronics/Conductance") -QMAKE_INCDIR = QMAKE_CFLAGS = -m32 -Dnullptr=0 -std=c11 -Wall -fno-stack-protector -ffreestanding