From 6de1a70574ff82f34b4dfe2c635a3c7861dbecf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Quei=C3=9Fner?= Date: Mon, 30 May 2016 19:48:07 +0200 Subject: [PATCH 1/3] First, primitive single threaded VM integration. --- prototypes/Makefile | 2 +- prototypes/base/Makefile | 18 +++--- prototypes/base/init.cpp | 103 +++++++++++++++++++++++++++++-- prototypes/base/lists/errors.lst | 3 +- prototypes/supervm/vm.c | 3 + prototypes/supervm/vm.h | 3 + 6 files changed, 117 insertions(+), 15 deletions(-) diff --git a/prototypes/Makefile b/prototypes/Makefile index e00f0ea..cc9b95b 100644 --- a/prototypes/Makefile +++ b/prototypes/Makefile @@ -5,4 +5,4 @@ all: $(PROJECTS) .PHONY: $(PROJECTS) $(PROJECTS): - make -C $@ + make -C $@ $(ARGS) diff --git a/prototypes/base/Makefile b/prototypes/base/Makefile index 88e8a29..d6de073 100644 --- a/prototypes/base/Makefile +++ b/prototypes/base/Makefile @@ -4,23 +4,27 @@ CC=gcc CXX=g++ LD=ld +LIBGCC = $(shell gcc -m32 -print-libgcc-file-name) +LIBSTD = ../stdlib/libstd.a +LIBVM = ../supervm/libvm.a + IDT_DISPATCH = _ZN3IDT8dispatchEP8CpuState -FLAGS = -mno-sse -DIDT_DISPATCH=$(IDT_DISPATCH) -ffreestanding -m32 -Werror -Wall -iquote include -iquote lists -I../stdlib/include -O3 -g +INCLUDE_DIRS = ../stdlib/include ../supervm/ + +FLAGS = -mno-sse -DIDT_DISPATCH=$(IDT_DISPATCH) -ffreestanding -m32 -Werror -Wall -iquote include -iquote lists $(addprefix -I, $(INCLUDE_DIRS)) -O3 -g ASFLAGS = $(FLAGS) CFLAGS = $(FLAGS) CXXFLAGS = $(FLAGS) -std=c++14 -fno-rtti -fno-exceptions -fno-leading-underscore -fno-use-cxa-atexit -nostdlib -fno-builtin SRCS = $(shell find -regextype egrep -regex '.*/.*\.(cpp|S|c)') OBJS = $(addsuffix .o, $(notdir $(basename $(SRCS)))) - -LIBGCC = $(shell gcc -m32 -print-libgcc-file-name) -LIBSTD = ../stdlib/libstd.a +LIBS = $(LIBGCC) $(LIBSTD) $(LIBVM) all: kernel-base.ker kernel-base.ker: $(OBJS) - $(LD) -melf_i386 -Tlinker.ld -o kernel-base.ker $(addprefix obj/, $^) $(LIBGCC) $(LIBSTD) + $(LD) -melf_i386 -Tlinker.ld -o kernel-base.ker $(addprefix obj/, $^) $(LIBS) %.o: %.cpp $(CXX) $(CXXFLAGS) -c -o obj/$@ $< @@ -46,8 +50,8 @@ kernel-base.ker: $(OBJS) # -initrd file use 'file' as initial ram disk # -dtb file use 'file' as device tree image - run: + echo `pwd` qemu-system-i386 \ -kernel kernel-base.ker \ -m 64 \ @@ -55,7 +59,7 @@ run: -no-reboot \ -no-shutdown \ -serial stdio \ - -initrd ../program0/program + -initrd `pwd`/../supervm-asm/testcode.bin insight: objdump -d kernel-base.ker | c++filt | less diff --git a/prototypes/base/init.cpp b/prototypes/base/init.cpp index fee486b..2a5a448 100644 --- a/prototypes/base/init.cpp +++ b/prototypes/base/init.cpp @@ -21,6 +21,10 @@ #include +namespace vm { +#include +} + using namespace multiboot; using namespace console_tools; @@ -35,6 +39,7 @@ driver::Keyboard keyboardDriver; VMMContext * kernelContext; +/* static const uint32_t entryPointAddress = 0x40000000; void run_program0(Module const & module) @@ -55,7 +60,7 @@ void run_program0(Module const & module) void* dest = (void*) ph->virt_addr; void* src = ((char*) header) + ph->offset; - /* Nur Program Header vom Typ LOAD laden */ + // Nur Program Header vom Typ LOAD laden if (ph->type != 1) { continue; } @@ -85,7 +90,7 @@ static void dump_elf(elf::Header *header) ProgramHeader *ph; int i; - /* Ist es ueberhaupt eine ELF-Datei? */ + // Ist es ueberhaupt eine ELF-Datei? if (header->magic != MAGIC) { BSOD::die(Error::InvalidELFImage, "Keine gueltige ELF-Magic!\n"); return; @@ -104,6 +109,12 @@ static void dump_elf(elf::Header *header) << "\n"; } } +*/ + +static void strcpy(char *dst, const char *src) +{ + while((*dst++ = *src++)); +} static void initializePMM(Structure const & data) { @@ -217,12 +228,92 @@ extern "C" void init(Structure const & data) if(data.modules.length > 0) { - Console::main << "ELF Modukle:\n"; - dump_elf(data.modules[0].start.data()); - run_program0(data.modules[0]); + // Console::main << "ELF Modukle:\n"; + // dump_elf(data.modules[0].start.data()); + // run_program0(data.modules[0]); + + vm::Module module = { + .code = reinterpret_cast(data.modules[0].start.data()), + .length = data.modules[0].size() / sizeof(vm::Instruction), + }; + + + Console::main << "Loaded instructions: " << module.length << "\n"; + + uint8_t page0[64]; + uint8_t page1[64]; + + strcpy((char*)page0, "Hallo Welt!\nDies ist die erste Ausgabe durch die VM."); + + uint8_t *pages[2]; + pages[0] = page0; + pages[1] = page1; + + + vm::VirtualMemoryMap mmap = { + .pageSize = 64, + .length = 2, + .pages = pages, + }; + + vm::Process process = { + .module = &module, + .tag = (void*)1, + .codePointer = 0, + .stackPointer = 0, + .basePointer = 0, + .flags = 0, + .stack = { 0 }, + .mmap = mmap, + }; + + auto *p = &process; + + while(vm::vm_step_process(p) && p->tag) { + //Console::main << "?"; + // dump_proc(p); + } + } while(true); } -static_assert(sizeof(void*) == 4, "Target platform is not 32 bit."); \ No newline at end of file +static_assert(sizeof(void*) == 4, "Target platform is not 32 bit."); + + + + +namespace vm +{ + extern "C" void vm_assert(int assertion, const char *msg) + { + if(assertion != 0) + return; + BSOD::die(Error::VMError, msg); + } + + extern "C" void vm_syscall(Process *p, CommandInfo *info) + { + switch(info->additional) + { + case 0: // EXIT + p->tag = NULL; + break; + case 1: + Console::main << (char)info->input0; + break; + case 2: + Console::main << info->input0; + break; + default: + Console::main << "[SYSCALL " << info->additional << "]"; + break; + } + } + + extern "C" void vm_hwio(Process *p, CommandInfo *info) + { + BSOD::die(Error::VMError, "hwio not implemented yet."); + } +} \ No newline at end of file diff --git a/prototypes/base/lists/errors.lst b/prototypes/base/lists/errors.lst index 7e248b4..661dc88 100644 --- a/prototypes/base/lists/errors.lst +++ b/prototypes/base/lists/errors.lst @@ -3,4 +3,5 @@ ERROR(1, OutOfMemory, The system has run out of memory.) ERROR(2, UnhandledException, An unhandled exception has occurred.) ERROR(3, UnhandledInterrupt, An unhandled interrupt has occurred.) ERROR(4, DriverAlreadyInstalled, A driver was already installed.) -ERROR(5, InvalidELFImage, The file beeing loaded is not a valid ELF file.) \ No newline at end of file +ERROR(5, InvalidELFImage, The file beeing loaded is not a valid ELF file.) +ERROR(6, VMError, The virtual machine has failed.) \ No newline at end of file diff --git a/prototypes/supervm/vm.c b/prototypes/supervm/vm.c index 92f8c30..49c945a 100644 --- a/prototypes/supervm/vm.c +++ b/prototypes/supervm/vm.c @@ -182,6 +182,9 @@ int vm_step_process(Process *process) case VM_OUTPUT_DISCARD: break; case VM_OUTPUT_PUSH: vm_push(process, info.output); break; case VM_OUTPUT_JUMP: process->codePointer = info.output; break; + case VM_OUTPUT_JUMPR: + process->codePointer += *((int32_t*)&info.output); + break; default: vm_assert(0, "Invalid instruction: invalid output."); } diff --git a/prototypes/supervm/vm.h b/prototypes/supervm/vm.h index c97fb1d..15b1544 100644 --- a/prototypes/supervm/vm.h +++ b/prototypes/supervm/vm.h @@ -5,6 +5,7 @@ #if defined(__cplusplus) extern "C" { +#define _Static_assert static_assert #endif #if !defined(VM_STACKSIZE) @@ -57,6 +58,7 @@ extern "C" { #define VM_OUTPUT_DISCARD 0 #define VM_OUTPUT_PUSH 1 #define VM_OUTPUT_JUMP 2 +#define VM_OUTPUT_JUMPR 3 #define VM_FLAG_Z (1<<0) #define VM_FLAG_N (1<<1) @@ -179,4 +181,5 @@ void vm_hwio(Process *process, CommandInfo *info); #if defined(__cplusplus) } +#undef _Static_assert #endif \ No newline at end of file From 2904c1c211c7584aa8b8d4649cd30fe90a584b84 Mon Sep 17 00:00:00 2001 From: Morten Delenk Date: Sun, 5 Jun 2016 12:51:33 +0000 Subject: [PATCH 2/3] Added storing and loading 16 and 32 bits of RAM --- prototypes/supervm/main.c | 2 +- prototypes/supervm/vm.c | 25 ++++++++++++++++++++++--- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/prototypes/supervm/main.c b/prototypes/supervm/main.c index c078047..de06cd7 100644 --- a/prototypes/supervm/main.c +++ b/prototypes/supervm/main.c @@ -175,4 +175,4 @@ int main(int argc, const char **argv) dump_memory(p); return 0; -} \ No newline at end of file +} diff --git a/prototypes/supervm/vm.c b/prototypes/supervm/vm.c index 92f8c30..920a106 100644 --- a/prototypes/supervm/vm.c +++ b/prototypes/supervm/vm.c @@ -9,12 +9,31 @@ static void cmd_copy(CommandInfo *info) static void cmd_load(Process *p, CommandInfo *info) { - info->output = vm_read_byte(p, info->input0); + info->output = 0; + switch(info->additional) { + case 2: + info->output|=(uint32_t)(vm_read_byte(p, info->input0+3))<<24; + info->output|=(uint32_t)(vm_read_byte(p, info->input0+2))<<16; + case 1: + info->output|=(uint32_t)(vm_read_byte(p, info->input0+1))<< 8; + case 0: + info->output|=(uint32_t)(vm_read_byte(p, info->input0+0))<< 0; + break; + } } static void cmd_store(Process *p, CommandInfo *info) { - vm_write_byte(p, info->input0, info->input1); + switch(info->additional) { + case 2: + vm_write_byte(p, info->input0+3, info->input1>>24); + vm_write_byte(p, info->input0+2, info->input1>>16); + case 1: + vm_write_byte(p, info->input0+1, info->input1>>8); + case 0: + vm_write_byte(p, info->input0, info->input1); + break; + } info->output = info->input1; } @@ -239,4 +258,4 @@ void vm_write_byte(Process *process, uint32_t address, uint8_t value) vm_assert(page < process->mmap.length, "Out of memory."); process->mmap.pages[page][index] = value; -} \ No newline at end of file +} From e4b29f2c3cb2de6c38be88702357f401bb3d58f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Quei=C3=9Fner?= Date: Tue, 14 Jun 2016 20:41:26 +0200 Subject: [PATCH 3/3] Adds relational jumps. --- documentation/supervm.md | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/documentation/supervm.md b/documentation/supervm.md index 3d12300..0d69098 100644 --- a/documentation/supervm.md +++ b/documentation/supervm.md @@ -213,6 +213,12 @@ The math command is a compound operator that contains all ALU operations. The ALU operation is selected by the `cmdinfo`. +If an ALU operation takes two operands, the right hand side is +defined by `input0`, the left hand side is defined by `input1`. +This allows a configuration such that the right hand side operand +is taken by the argument of the instruction instead of beeing popped +from the stack. + | cmdinfo | Operation | |---------|-----------------------------| | 0 | Addition | @@ -258,11 +264,12 @@ is set when the highest bit is set. ### Output Each instruction can emit an output value. The output can be used in the following ways: -| # | Output | Effect | -|---|---------|--------------------------------------------------------------| -| 0 | discard | The output value is discarded. | -| 1 | push | The output is pushed to the stack. | -| 2 | jump | The code pointer is set to the output, thus a jump is taken. | +| # | Output | Effect | +|---|---------|-----------------------------------------------------------------------------| +| 0 | discard | The output value is discarded. | +| 1 | push | The output is pushed to the stack. | +| 2 | jump | The code pointer is set to the output, thus a jump is taken. | +| 3 | jumpr | The code pointer is increased by the output, thus a relative jump is taken. | ### Argument The instruction argument can provide static input which can be used