diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile | 14 | ||||
-rw-r--r-- | lib/arch.h | 2 | ||||
-rw-r--r-- | lib/arch/arm64/api.h | 6 | ||||
-rw-r--r-- | lib/arch/arm64/init_stack.cc | 37 | ||||
-rw-r--r-- | lib/arch/arm64/thread_create.s | 20 | ||||
-rw-r--r-- | lib/arch/arm64/yield.s | 42 |
6 files changed, 116 insertions, 5 deletions
diff --git a/lib/Makefile b/lib/Makefile index 78b051e..c880346 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,12 +1,16 @@ # Copyright (c) 2020 Johannes Stoelp -AS := gcc +ARCH ?= x86_64 + +ifeq ($(ARCH),arm64) +PREFIX := aarch64-linux-gnu- +endif + +AS := $(PREFIX)gcc ASFLAGS := -g -O0 -CXX := g++ +CXX := $(PREFIX)g++ CXXFLAGS := -g -O0 -Wall -Wextra -I. -AR := ar - -ARCH := x86_64 +AR := $(PREFIX)ar libmatcha.a: thread.o executor.o \ thread.h executor.h \ @@ -8,6 +8,8 @@ static_assert(false, "Matcha Threads only supported on Linux!"); #if defined(__x86_64__) || defined(__amd64__) # include "arch/x86_64/api.h" +#elif defined(__aarch64__) +# include "arch/arm64/api.h" #else static_assert(false, "Matcha Threads only supported on x86_64!"); #endif diff --git a/lib/arch/arm64/api.h b/lib/arch/arm64/api.h new file mode 100644 index 0000000..b2babc9 --- /dev/null +++ b/lib/arch/arm64/api.h @@ -0,0 +1,6 @@ +/* Copyright (c) 2020 Johannes Stoelp */ + +#pragma once + +extern "C" void yield(const void* new_stack, void* const* old_stack); +void* init_stack(void* stack_ptr, void (*entry)(void*), void* ctx); diff --git a/lib/arch/arm64/init_stack.cc b/lib/arch/arm64/init_stack.cc new file mode 100644 index 0000000..b28d957 --- /dev/null +++ b/lib/arch/arm64/init_stack.cc @@ -0,0 +1,37 @@ +#include <cassert> +#include <cstdint> // uintN_t + +extern "C" void thread_create(); + +void* init_stack(void* stack_ptr, void (*entry)(void*), void* ctx) { + static_assert(sizeof(uint64_t) == sizeof(std::uintptr_t), "Pointer must be 64bit!"); + + // Setup initial stack frame which will be popped when yielding + // first time into the thread. + // Basic idea is to yield into Thread::entry() function which will + // then call the user function. + + uint64_t* stack = static_cast<uint64_t*>(stack_ptr); + // Arguments for `thread_create`. + *(--stack) = reinterpret_cast<uint64_t>(ctx); + *(--stack) = reinterpret_cast<uint64_t>(entry); + + // Yield epilogue. + *(--stack) = reinterpret_cast<uint64_t>(thread_create); // x30 (LR) + *(--stack) = static_cast<uint64_t>(0); // x29 (FP) + + // Callee saved registers. + *(--stack) = static_cast<uint64_t>(0); // x28 + *(--stack) = static_cast<uint64_t>(0); // x27 + *(--stack) = static_cast<uint64_t>(0); // x26 + *(--stack) = static_cast<uint64_t>(0); // x25 + *(--stack) = static_cast<uint64_t>(0); // x24 + *(--stack) = static_cast<uint64_t>(0); // x23 + *(--stack) = static_cast<uint64_t>(0); // x22 + *(--stack) = static_cast<uint64_t>(0); // x21 + *(--stack) = static_cast<uint64_t>(0); // x20 + *(--stack) = static_cast<uint64_t>(0); // x19 + + assert((reinterpret_cast<std::uintptr_t>(stack) & 0xf) == 0); // 16byte aligned + return static_cast<void*>(stack); +} diff --git a/lib/arch/arm64/thread_create.s b/lib/arch/arm64/thread_create.s new file mode 100644 index 0000000..dc6fae2 --- /dev/null +++ b/lib/arch/arm64/thread_create.s @@ -0,0 +1,20 @@ +# Copyright (c) 2020 Johannes Stoelp + + .arch armv8-a + .section .text, "ax", @progbits + + # extern "C" void thread_create(); + .global thread_create + .type thread_create, @function +thread_create: + .cfi_startproc + ldr x0, [sp, 0x8] + ldr x1, [sp] + + blr x1 + + # FIXME: no return from thread after user fn finished. +1: + b 1b + .cfi_endproc + .size thread_create, .-thread_create diff --git a/lib/arch/arm64/yield.s b/lib/arch/arm64/yield.s new file mode 100644 index 0000000..63a4051 --- /dev/null +++ b/lib/arch/arm64/yield.s @@ -0,0 +1,42 @@ +# Copyright (c) 2020 Johannes Stoelp + + .arch armv8-a + .section .text, "ax", @progbits + + # extern "C" void yield(const void* new_stack, void* const* old_stack); + # ^^^^^^^^^ ^^^^^^^^^ + # rdi rsi + .global yield + .type yield, @function +yield: + .cfi_startproc + // prologue + stp x29, x30, [sp, -16]! + mov x29, sp + + // push callee saved registers + stp x27, x28, [sp, -16]! + stp x25, x26, [sp, -16]! + stp x23, x24, [sp, -16]! + stp x21, x22, [sp, -16]! + stp x19, x20, [sp, -16]! + + // arg0: x0 holds new stack + // arg1: x1 holds addr to location current stack must be saved + mov x2, sp + str x2, [x1] // save current stack ptr + mov sp, x0 // switch to new stack ptr + + // pop callee saved registers + ldp x19, x20, [sp], 16 + ldp x21, x22, [sp], 16 + ldp x23, x24, [sp], 16 + ldp x25, x26, [sp], 16 + ldp x27, x28, [sp], 16 + + // epilogue + ldp x29, x30, [sp], 16 + + ret + .cfi_endproc + .size yield, .-yield |