Skip to content

Commit

Permalink
[fiber] Add support for ARM64 targets
Browse files Browse the repository at this point in the history
  • Loading branch information
salkinium committed Jan 18, 2024
1 parent 95ef729 commit ce10452
Show file tree
Hide file tree
Showing 3 changed files with 217 additions and 2 deletions.
127 changes: 127 additions & 0 deletions src/modm/processing/fiber/context_arm64.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* Copyright (c) 2020, Erik Henriksson
* Copyright (c) 2021, 2023, Niklas Hauser
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#include "context.h"
#include <modm/architecture/detect.hpp>

/* Stack layout (growing downwards):
*
* Permanent Storage:
* Fiber Function
* Fiber Function Argument
*
* Temporary Prepare:
* Entry Function
*
* Register file:
* LR
* FP
* x28
* x27
* x26
* x25
* x24
* x23
* x22
* x21
* x20
* x19
* d15
* d14
* d13
* d12
* d11
* d10
* d9
* d8
*/

namespace
{

constexpr size_t StackWordsReset = 1;
constexpr size_t StackWordsStorage = 2;
constexpr size_t StackWordsRegisters = 20;
constexpr size_t StackWordsAll = StackWordsStorage + StackWordsRegisters;
constexpr size_t StackSizeWord = sizeof(uintptr_t);
constexpr uintptr_t StackWatermark = 0xc0ffee'f00d'facade;

}

extern "C" void modm_context_entry();

void
modm_context_init(modm_context_t *ctx,
uintptr_t *bottom, uintptr_t *top,
uintptr_t fn, uintptr_t fn_arg)
{
ctx->bottom = bottom;
ctx->top = top;

ctx->sp = top;
*--ctx->sp = fn;
*--ctx->sp = fn_arg;
}

void
modm_context_reset(modm_context_t *ctx)
{
*ctx->bottom = StackWatermark;

ctx->sp = ctx->top - StackWordsStorage;
*--ctx->sp = (uintptr_t) modm_context_entry;
ctx->sp -= StackWordsRegisters - StackWordsReset;
}

void
modm_context_watermark(modm_context_t *ctx)
{
// clear the register file on the stack
for (auto *word = ctx->top - StackWordsAll;
word < ctx->top - StackWordsStorage - StackWordsReset; word++)
*word = 0;

// then color the whole stack *below* the register file
for (auto *word = ctx->bottom; word < ctx->top - StackWordsAll; word++)
*word = StackWatermark;
}

size_t
modm_context_stack_usage(const modm_context_t *ctx)
{
for (auto *word = ctx->bottom; word < ctx->top; word++)
if (StackWatermark != *word)
return (ctx->top - word) * StackSizeWord;
return 0;
}

bool
modm_context_stack_overflow(const modm_context_t *ctx)
{
return *ctx->bottom != StackWatermark;
}

static modm_context_t main_context;

void
modm_context_start(modm_context_t *to)
{
modm_context_jump(&main_context, to);
}

void
modm_context_end()
{
modm_context_t dummy;
modm_context_jump(&dummy, &main_context);
__builtin_unreachable();
}
83 changes: 83 additions & 0 deletions src/modm/processing/fiber/context_arm64_asm.S.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright (c) 2023, Niklas Hauser
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
; ----------------------------------------------------------------------------

.text
.globl _modm_context_entry
.balign 16
_modm_context_entry:

ldr x0, [sp] ; Load closure data pointer
ldr x1, [sp, #8] ; Jump to closure function
br x1


/*
The assembly code below is adapted from the Boost Context library to work
for Windows, Linux and macOS.
See https://github.com/boostorg/context/tree/develop/src/asm
- Windows: jump_arm64_aapcs_pe_armasm.asm
- Linux: jump_arm64_aapcs_elf_gas.S
- macOS: jump_arm64_aapcs_macho_gas.S

Copyright Oliver Kowalke 2009.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
*/

.text
.globl _modm_context_jump
.balign 16
_modm_context_jump:

; move stack pointer down
sub sp, sp, #0xa0

; save d8 - d15
stp d8, d9, [sp, #0x00]
stp d10, d11, [sp, #0x10]
stp d12, d13, [sp, #0x20]
stp d14, d15, [sp, #0x30]

; save x19-x30
stp x19, x20, [sp, #0x40]
stp x21, x22, [sp, #0x50]
stp x23, x24, [sp, #0x60]
stp x25, x26, [sp, #0x70]
stp x27, x28, [sp, #0x80]
stp fp, lr, [sp, #0x90]

; Store the SP in from->sp
mov x19, sp
str x19, [x0]

; Restore SP from to->sp
ldr x19, [x1]
mov sp, x19

; load d8 - d15
ldp d8, d9, [sp, #0x00]
ldp d10, d11, [sp, #0x10]
ldp d12, d13, [sp, #0x20]
ldp d14, d15, [sp, #0x30]

; load x19-x30
ldp x19, x20, [sp, #0x40]
ldp x21, x22, [sp, #0x50]
ldp x23, x24, [sp, #0x60]
ldp x25, x26, [sp, #0x70]
ldp x27, x28, [sp, #0x80]
ldp fp, lr, [sp, #0x90]

; restore stack from GP + FPU
add sp, sp, #0xa0

ret
9 changes: 7 additions & 2 deletions src/modm/processing/fiber/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ def prepare(module, options):
module.add_query(
EnvironmentQuery(name="__enabled", factory=is_enabled))

# No ARM64 support yet!
return "arm64" not in options[":target"].get_driver("core")["type"]
return True


def build(env):
Expand Down Expand Up @@ -64,6 +63,12 @@ def build(env):
env.substitutions["default_stack_size"] = 2**20 # 1MB
env.template("context_x86_64.cpp.in")

elif "arm64" in core:
env.substitutions["stack_minimum"] = (20 + 2) * 8
env.substitutions["default_stack_size"] = 2**20 # 1MB
env.copy("context_arm64.cpp")
env.template("context_arm64_asm.S.in")

env.template("context.h.in")
env.template("stack.hpp.in")
env.template("scheduler.hpp.in")
Expand Down

0 comments on commit ce10452

Please sign in to comment.