diff options
author | johannst <johannes.stoelp@gmail.com> | 2021-02-26 23:19:03 +0100 |
---|---|---|
committer | johannst <johannes.stoelp@gmail.com> | 2021-02-26 23:19:03 +0100 |
commit | 0d881bc974b74dff75c00a3cab5d535cbb2ace46 (patch) | |
tree | 35c5892c135d5623879b106e93df4cc235669a8d | |
parent | 5fbee6be76c8751c282b45c54b8179ae525e00c1 (diff) | |
download | matcha-threads-0d881bc974b74dff75c00a3cab5d535cbb2ace46.tar.gz matcha-threads-0d881bc974b74dff75c00a3cab5d535cbb2ace46.zip |
added implementation for armv7a
-rw-r--r-- | .github/workflows/check.yml | 2 | ||||
-rw-r--r-- | Makefile | 14 | ||||
-rw-r--r-- | docker/Dockerfile | 4 | ||||
-rw-r--r-- | lib/Makefile | 2 | ||||
-rw-r--r-- | lib/arch.h | 2 | ||||
-rw-r--r-- | lib/arch/arm/README.md | 9 | ||||
-rw-r--r-- | lib/arch/arm/api.h | 6 | ||||
-rw-r--r-- | lib/arch/arm/init_stack.cc | 35 | ||||
-rw-r--r-- | lib/arch/arm/thread_create.s | 20 | ||||
-rw-r--r-- | lib/arch/arm/yield.s | 32 |
10 files changed, 124 insertions, 2 deletions
diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 1d7dfa4..e8278d7 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -15,7 +15,7 @@ jobs: docker/build.sh matcha-box - name: Run examples run: | - for arch in x86_64 arm64; do + for arch in x86_64 arm64 arm; do echo -e "\e[1;32m==> check ARCH=$arch\e0m" docker run \ --rm \ @@ -4,6 +4,8 @@ ARCH ?= x86_64 ifeq ($(ARCH),arm64) PREFIX := aarch64-linux-gnu- +else ifeq ($(ARCH),arm) +PREFIX := arm-linux-gnueabi- endif CXX := $(PREFIX)g++ @@ -28,6 +30,11 @@ ifeq ($(ARCH),arm64) -L /usr/aarch64-linux-gnu \ -E LD_LIBRARY_PATH=/usr/aarch64-linux-gnu/lib \ $< +else ifeq ($(ARCH),arm) + qemu-arm \ + -L /usr/arm-linux-gnueabi \ + -E LD_LIBRARY_PATH=/usr/arm-linux-gnueabi/lib \ + $< else $< endif @@ -40,6 +47,13 @@ ifeq ($(ARCH),arm64) -g 1234 \ $< & gdb-multiarch -ex 'target remote :1234' -ex 'b main' -ex 'c' $< +else ifeq ($(ARCH),arm) + qemu-arm \ + -L /usr/arm-linux-gnueabi \ + -E LD_LIBRARY_PATH=/usr/arm-linux-gnueabi/lib \ + -g 1234 \ + $< & + gdb-multiarch -ex 'target remote :1234' -ex 'b main' -ex 'c' $< else which cgdb && cgdb --ex 'start' $< \ || gdb --ex 'start' $< diff --git a/docker/Dockerfile b/docker/Dockerfile index 7a41480..703ee7a 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -11,11 +11,13 @@ RUN apt update \ g++ \ gcc-aarch64-linux-gnu \ g++-aarch64-linux-gnu \ + gcc-arm-linux-gnueabi \ + g++-arm-linux-gnueabi \ gdb-multiarch \ qemu-user \ && rm -rf /var/lib/apt/lists/* \ && apt-get clean \ # Remove expensive qemu emulators which are currently not used. - && rm -f $(find /usr/bin -name 'qemu-*' | grep -v 'qemu-aarch64$') + && rm -f $(find /usr/bin -name 'qemu-*' | grep -v 'qemu-aarch64$\|qemu-arm$') WORKDIR /develop diff --git a/lib/Makefile b/lib/Makefile index 24fe7bd..c85d450 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -4,6 +4,8 @@ ARCH ?= x86_64 ifeq ($(ARCH),arm64) PREFIX := aarch64-linux-gnu- +else ifeq ($(ARCH),arm) +PREFIX := arm-linux-gnueabi- endif AS := $(PREFIX)gcc @@ -10,6 +10,8 @@ static_assert(false, "Matcha Threads only supported on Linux!"); # include "arch/x86_64/api.h" #elif defined(__aarch64__) # include "arch/arm64/api.h" +#elif defined(__arm__) +# include "arch/arm/api.h" #else static_assert(false, "Unsupported architecture!"); #endif diff --git a/lib/arch/arm/README.md b/lib/arch/arm/README.md new file mode 100644 index 0000000..8631c93 --- /dev/null +++ b/lib/arch/arm/README.md @@ -0,0 +1,9 @@ +# Procedure Call Standard ARM64 + +- Integer/pointer arguments via `r0`-`r3` +- Integer/pointer return values via `r0` +- Callee saved registers `r4`-`r11`, `sp`, `lr`, `fp` + +## Reference +- [johannst armv7 notes](https://johannst.github.io/notes/arch/armv7.html) + diff --git a/lib/arch/arm/api.h b/lib/arch/arm/api.h new file mode 100644 index 0000000..c7a688d --- /dev/null +++ b/lib/arch/arm/api.h @@ -0,0 +1,6 @@ +/* Copyright (c) 2021 Johannes Stoelp */ + +#pragma once + +extern "C" void yield(const void* new_stack, void** old_stack); +void* init_stack(void* stack_ptr, void (*entry)(void*), const void* ctx); diff --git a/lib/arch/arm/init_stack.cc b/lib/arch/arm/init_stack.cc new file mode 100644 index 0000000..422be64 --- /dev/null +++ b/lib/arch/arm/init_stack.cc @@ -0,0 +1,35 @@ +#include <cassert> +#include <cstdint> // uintN_t + +extern "C" void thread_create(); + +void* init_stack(void* stack_ptr, void (*entry)(void*), const void* ctx) { + static_assert(sizeof(uint32_t) == sizeof(std::uintptr_t), "Pointer must be 32bit!"); + + // 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. + + uint32_t* stack = static_cast<uint32_t*>(stack_ptr); + // Arguments for `thread_create`. + *(--stack) = reinterpret_cast<uint32_t>(ctx); + *(--stack) = reinterpret_cast<uint32_t>(entry); + + // Yield epilogue. + *(--stack) = reinterpret_cast<uint32_t>(thread_create); // r15 (PC) + *(--stack) = static_cast<uint32_t>(0); // r11 (FP) + + // Callee saved registers. + *(--stack) = static_cast<uint32_t>(0); // r11 + *(--stack) = static_cast<uint32_t>(0); // r10 + *(--stack) = static_cast<uint32_t>(0); // r9 + *(--stack) = static_cast<uint32_t>(0); // r8 + *(--stack) = static_cast<uint32_t>(0); // r7 + *(--stack) = static_cast<uint32_t>(0); // r6 + *(--stack) = static_cast<uint32_t>(0); // r5 + *(--stack) = static_cast<uint32_t>(0); // r4 + + assert((reinterpret_cast<std::uintptr_t>(stack) & 0x7) == 0); // 8byte aligned + return static_cast<void*>(stack); +} diff --git a/lib/arch/arm/thread_create.s b/lib/arch/arm/thread_create.s new file mode 100644 index 0000000..7231c3e --- /dev/null +++ b/lib/arch/arm/thread_create.s @@ -0,0 +1,20 @@ +# Copyright (c) 2021 Johannes Stoelp + + .arch armv7-a + .section .text, "ax", %progbits + + # extern "C" void thread_create(); + .global thread_create + .type thread_create, %function +thread_create: + .cfi_startproc + ldr r0, [sp, #0x4] + ldr r1, [sp] + + blx r1 + + # FIXME: no return from thread after user fn finished. +1: + b 1b + .cfi_endproc + .size thread_create, .-thread_create diff --git a/lib/arch/arm/yield.s b/lib/arch/arm/yield.s new file mode 100644 index 0000000..de9d604 --- /dev/null +++ b/lib/arch/arm/yield.s @@ -0,0 +1,32 @@ +# Copyright (c) 2021 Johannes Stoelp + + .arch armv7-a + .section .text, "ax", %progbits + + # extern "C" void yield(const void* new_stack, void** old_stack); + # ^^^^^^^^^ ^^^^^^^^^ + # x0 x1 + .global yield + .type yield, %function +yield: + .cfi_startproc + // prologue + push {fp, lr} + mov fp, sp + + // push callee saved registers + push {r4-r11} + + // arg0: r0 holds new stack + // arg1: r1 holds addr to location current stack must be saved + mov r2, sp + str r2, [r1] // save current stack ptr + mov sp, r0 // switch to new stack ptr + + // pop callee saved registers + pop {r4-r11} + + // epilogue + pop {fp, pc} + .cfi_endproc + .size yield, .-yield |