Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ asm/seff_types.S: decls/seff_types.py decls/generate.py
output/seff.o: src/seff.c src/seff.h src/seff_types.h | output
$(CC) $(CFLAGS) -I./src -o output/seff.o -c src/seff.c

output/seff_asm.o: asm/seff.S asm/seff_types.S | output
$(CC) $(CFLAGS) -I./asm -o output/seff_asm.o -c asm/seff.S
output/seff_asm.o: asm/seff-${ARCH}.S asm/seff_types.S | output
$(CC) $(CFLAGS) -I./asm -o output/seff_asm.o -c asm/seff-${ARCH}.S

output/seff_mem.o: src/mem/seff_mem_${STACK_POLICY}.c src/mem/seff_mem.h src/seff_types.h | output
$(CC) $(CFLAGS) -I./src -o output/seff_mem.o -c src/mem/seff_mem_${STACK_POLICY}.c
Expand Down
2 changes: 2 additions & 0 deletions asm/dwarf.S
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,5 @@
#define DW_REG_r14 14
#define DW_REG_r15 15
#define DW_REG_rip 16

#define DW_REG_aarch64_r26 26
257 changes: 257 additions & 0 deletions asm/seff-aarch64.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
# Copyright (c) 2023 Huawei Technologies Co., Ltd.
# Copyright (c) 2024 Brian Campbell, University of Edinburgh
#
# libseff is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
# http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR
# FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
#
# Architecture-specific code for context-switching
# This file is for the Arm's AArch64 instruction set architecture
#

#include "dwarf.S"
#include "seff_types.S"

#ifdef STACK_POLICY_SEGMENTED
#error Segmented stacks not currently supported on AArch64
#endif

.global seff_exit
.global seff_yield
.global seff_resume
.global coroutine_prelude

.type seff_exit,%function
.type seff_yield,%function
.type seff_resume,%function
.type coroutine_prelude,%function

.global _seff_current_coroutine
.global _seff_system_stack
.global _seff_paused_coroutine_stack

.section .tbss

_seff_current_coroutine:
.zero 8
_seff_paused_coroutine_stack:
.zero 8
_seff_system_stack:
.zero 8

.macro swap_registers
# Saved registers
# TODO: ldp/stp?
ldr x9, [x0, seff_coroutine_t__resume_point + seff_cont_t__r19]
ldr x10, [x0, seff_coroutine_t__resume_point + seff_cont_t__r20]
ldr x11, [x0, seff_coroutine_t__resume_point + seff_cont_t__r21]
ldr x12, [x0, seff_coroutine_t__resume_point + seff_cont_t__r22]
ldr x13, [x0, seff_coroutine_t__resume_point + seff_cont_t__r23]
ldr x14, [x0, seff_coroutine_t__resume_point + seff_cont_t__r24]
ldr x15, [x0, seff_coroutine_t__resume_point + seff_cont_t__r25]
ldr x16, [x0, seff_coroutine_t__resume_point + seff_cont_t__r26]
ldr x17, [x0, seff_coroutine_t__resume_point + seff_cont_t__r27]
ldr x8, [x0, seff_coroutine_t__resume_point + seff_cont_t__r28]

str x19, [x0, seff_coroutine_t__resume_point + seff_cont_t__r19]
str x20, [x0, seff_coroutine_t__resume_point + seff_cont_t__r20]
str x21, [x0, seff_coroutine_t__resume_point + seff_cont_t__r21]
str x22, [x0, seff_coroutine_t__resume_point + seff_cont_t__r22]
str x23, [x0, seff_coroutine_t__resume_point + seff_cont_t__r23]
str x24, [x0, seff_coroutine_t__resume_point + seff_cont_t__r24]
str x25, [x0, seff_coroutine_t__resume_point + seff_cont_t__r25]
str x26, [x0, seff_coroutine_t__resume_point + seff_cont_t__r26]
str x27, [x0, seff_coroutine_t__resume_point + seff_cont_t__r27]
str x28, [x0, seff_coroutine_t__resume_point + seff_cont_t__r28]

mov x19, x9
mov x20, x10
mov x21, x11
mov x22, x12
mov x23, x13
mov x24, x14
mov x25, x15
mov x26, x16
mov x27, x17
mov x28, x8
.endm

.macro swap_stack
ldr x10, [x0, seff_coroutine_t__resume_point + seff_cont_t__rbp]
ldr x11, [x0, seff_coroutine_t__resume_point + seff_cont_t__rsp]

str x29, [x0, seff_coroutine_t__resume_point + seff_cont_t__rbp]
mov x29, sp
str x29, [x0, seff_coroutine_t__resume_point + seff_cont_t__rsp]

mov x29, x10
mov sp, x11
.endm

.text

# void* seff_yield(seff_coroutine_t* self, void* arg)
seff_yield:
.cfi_startproc
# self in x0
# arg1 in x1
# arg2 in x2

swap_registers

# We get to pummel x3-x15 so we use those for fast swaps

mrs x9, TPIDR_EL0

add x9, x9, :tprel_hi12:_seff_current_coroutine
add x9, x9, :tprel_lo12_nc:_seff_current_coroutine
# Keep x9 for later
ldr x4, [x9]

ldr x6, [x0, seff_coroutine_t__parent_coroutine]

# _seff_current_coroutine
str x6, [x9]

str x4, [x0, seff_coroutine_t__resume_point + seff_cont_t__current_coroutine]

# Save return pointer
mov x3, x30
ldr x30, [x0, seff_coroutine_t__resume_point + seff_cont_t__ip]
str x3, [x0, seff_coroutine_t__resume_point + seff_cont_t__ip]

swap_stack

mov x0, x1
mov x1, x2
ret
.cfi_endproc
.size seff_yield, . - seff_yield

# void* seff_resume(seff_coroutine_t* k, void* arg, effect_set handled)
seff_resume:
.cfi_startproc
# k in x0
# arg in x1
# handled in x2
str x2, [x0, seff_coroutine_t__handled_effects]

swap_registers

# We get to pummel x3-x15 so we use those for fast swaps

mrs x9, TPIDR_EL0

add x10, x9, :tprel_hi12:_seff_current_coroutine
add x10, x10, :tprel_lo12_nc:_seff_current_coroutine
ldr x4, [x10]

ldr x6, [x0, seff_coroutine_t__resume_point + seff_cont_t__current_coroutine]

str x6, [x10] /* _seff_current_coroutine */

str x4, [x0, seff_coroutine_t__parent_coroutine]

# Save return pointer
mov x3, x30
ldr x30, [x0, seff_coroutine_t__resume_point + seff_cont_t__ip]
str x3, [x0, seff_coroutine_t__resume_point + seff_cont_t__ip]

# At this point, the stack is aligned on a 16-byte boundary, so we use
# this as the system stack if possible. Note that we need to do this
# before clobbering x4
cbnz x4, seff_resume_after_store_system_stack
add x10, x9, :tprel_hi12:_seff_system_stack
add x10, x10, :tprel_lo12_nc:_seff_system_stack
mov x11, sp
str x11, [x10]
seff_resume_after_store_system_stack:

# Stack
swap_stack

mov x0, x1
ret
.cfi_endproc
.size seff_resume, . - seff_resume

# void coroutine_prelude(seff_coroutine_t *k, seff_start_fun_t *fn, void *arg);
# k in x26
# arg in x27
# fn in x28
coroutine_prelude:
.cfi_startproc
# needed or else gdb does not allow switching frames to a lower address in the backtrace
.cfi_signal_frame

# At this point we are already at a new stack frame, we need to recover the CFA from x26
.cfi_escape DW_CFA_def_cfa_expression, 2, DW_OP_breg(DW_REG_aarch64_r26), seff_coroutine_t__resume_point
# And then every other register from its offset to CFA
.cfi_offset x30, seff_cont_t__ip
.cfi_offset sp, seff_cont_t__rsp
.cfi_offset x29, seff_cont_t__rbp
.cfi_offset x19, seff_cont_t__r19
.cfi_offset x20, seff_cont_t__r20
.cfi_offset x21, seff_cont_t__r21
.cfi_offset x22, seff_cont_t__r22
.cfi_offset x23, seff_cont_t__r23
.cfi_offset x24, seff_cont_t__r24
.cfi_offset x25, seff_cont_t__r25
.cfi_offset x26, seff_cont_t__r26
.cfi_offset x27, seff_cont_t__r27
.cfi_offset x28, seff_cont_t__r28

mov x0, x27
# x26 is a callee-save register, so the debugger will continue to find the correct CFA

blr x28
# FALLTHROUGH TO SEFF_EXIT
# set the return value to (seff_result_t){ 0xFF...FF, %rax }
mov x2, x0
mov x0, x26
mov x1, #RETURN_EFFECT_ID
.cfi_endproc
.size coroutine_prelude, . - coroutine_prelude

# void seff_exit(seff_coroutine_t* k, void* result)
seff_exit:
.cfi_startproc
# k in x0
# eff_id in x1
# result in x2
mov x9, #seff_coroutine_state_t__FINISHED
str x9, [x0, seff_coroutine_t__state]

# TODO: it would be faster to avoid swapping, since we're never restarting this coroutine
swap_registers

ldr x9, [x0, seff_coroutine_t__parent_coroutine]
mrs x10, TPIDR_EL0
add x10, x10, :tprel_hi12:_seff_current_coroutine
add x10, x10, :tprel_lo12_nc:_seff_current_coroutine
str x9, [x10]

ldr x9, [x0, seff_coroutine_t__resume_point + seff_cont_t__ip]

ldr x29, [x0, seff_coroutine_t__resume_point + seff_cont_t__rbp]
ldr x10, [x0, seff_coroutine_t__resume_point + seff_cont_t__rsp]
mov sp, x10

#ifndef NDEBUG
# Cleaning up
str xzr, [x0, seff_coroutine_t__resume_point + seff_cont_t__ip]

str xzr, [x0, seff_coroutine_t__resume_point + seff_cont_t__rbp]
str xzr, [x0, seff_coroutine_t__resume_point + seff_cont_t__rsp]
#endif

mov x0, x1
mov x1, x2
br x9
.cfi_endproc
.size seff_exit, . - seff_exit
File renamed without changes.
39 changes: 32 additions & 7 deletions decls/seff_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
parser = argparse.ArgumentParser()

x86_64 = 'x86-64'
parser.add_argument('--arch', choices=[x86_64], default=x86_64)
aarch64 = 'aarch64'
parser.add_argument('--arch', choices=[x86_64, aarch64], default=x86_64)

segmented = 'segmented'
fixed = 'fixed'
Expand All @@ -38,6 +39,11 @@
if args.arch == x86_64:
arch = Architecture(64)
generate.arch = arch
Defn('SEFF_ARCH_X86_64')
elif args.arch == aarch64:
arch = Architecture(64)
generate.arch = arch
Defn('SEFF_ARCH_AARCH64')
else:
print(f"Fatal error: unsupported architecture {args.arch}")
exit()
Expand Down Expand Up @@ -73,14 +79,33 @@

Field('rsp', ptr(void)),
Field('rbp', ptr(void)),

Field('ip', ptr(void)),
Field('rbx', ptr(void)),
Field('r12', ptr(void)),
Field('r13', ptr(void)),
Field('r14', ptr(void)),
Field('r15', ptr(void)),
]
if args.arch == x86_64:
cont_fields.extend([
Field('rbx', ptr(void)),
Field('r12', ptr(void)),
Field('r13', ptr(void)),
Field('r14', ptr(void)),
Field('r15', ptr(void)),
])
elif args.arch == aarch64:
cont_fields.extend([
Field('r19', ptr(void)),
Field('r20', ptr(void)),
Field('r21', ptr(void)),
Field('r22', ptr(void)),
Field('r23', ptr(void)),
Field('r24', ptr(void)),
Field('r25', ptr(void)),
Field('r26', ptr(void)),
Field('r27', ptr(void)),
Field('r28', ptr(void)),
])
else:
print(f"Fatal error: unsupported architecture {args.arch}")
exit()

if stack_policy == segmented:
cont_fields.insert(0, Field('stack_top', ptr(void)))
cont = Struct('seff_cont_t', *cont_fields)
Expand Down
16 changes: 16 additions & 0 deletions src/seff.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ bool seff_coroutine_init_sized(
seff_coroutine_t *k, seff_start_fun_t *fn, void *arg, size_t frame_size) {
char *rsp;
// Overhead needed by coroutine_prelude (since they make a call)
// TODO: architecture dependent?
size_t overhead = 16;
seff_frame_ptr_t stack = init_stack_frame(frame_size + overhead, &rsp);
if (!stack) {
Expand All @@ -108,11 +109,26 @@ bool seff_coroutine_init_sized(
k->resume_point.stack_top = stack_top;
#endif
k->resume_point.current_coroutine = k;
#ifdef SEFF_ARCH_X86_64
k->resume_point.rbx = (void *)0xcacabbbb;
k->resume_point.r12 = (void *)0xcaca1212;
k->resume_point.r13 = (void *)k;
k->resume_point.r14 = (void *)arg;
k->resume_point.r15 = (void *)fn;
#elif defined(SEFF_ARCH_AARCH64)
k->resume_point.r19 = (void *)0xcaca1919;
k->resume_point.r20 = (void *)0xcaca2020;
k->resume_point.r21 = (void *)0xcaca2121;
k->resume_point.r22 = (void *)0xcaca2222;
k->resume_point.r23 = (void *)0xcaca2323;
k->resume_point.r24 = (void *)0xcaca2424;
k->resume_point.r25 = (void *)0xcaca2525;
k->resume_point.r26 = (void *)k;
k->resume_point.r27 = (void *)arg;
k->resume_point.r28 = (void *)fn;
#else
#error Architecture not supported in seff_coroutine_init_sized
#endif
k->state = PAUSED;

/*
Expand Down
9 changes: 9 additions & 0 deletions src/seff.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ E __attribute__((noreturn, no_split_stack)) void seff_exit(
E __attribute__((noreturn)) void seff_throw(effect_id eff_id, void *payload);

// TODO: this is architecture specific
#ifdef SEFF_ARCH_X86_64
#define MAKE_SYSCALL_WRAPPER(ret, fn, ...) \
ret __attribute__((no_split_stack)) fn##_syscall_wrapper(__VA_ARGS__); \
__asm__(#fn "_syscall_wrapper:" \
Expand All @@ -96,6 +97,14 @@ E __attribute__((noreturn)) void seff_throw(effect_id eff_id, void *payload);
"movq %fs:_seff_paused_coroutine_stack_top@TPOFF, %rcx;", "", \
"") "movq %rcx, %fs:0x70;" \
"retq;")
#elif defined(SEFF_ARCH_AARCH64)
#define MAKE_SYSCALL_WRAPPER(ret, fn, ...) \
ret __attribute__((no_split_stack)) fn##_syscall_wrapper(__VA_ARGS__); \
__asm__(#fn "_syscall_wrapper:" \
"b " #fn)
#else
#error Architecture not supported for MAKE_SYSCALL_WRAPPER
#endif

#define EFF_ID(name) __##name##_eff_id
#define EFF_PAYLOAD_T(name) __##name##_eff_payload
Expand Down
Loading